[P1] Expose Tree-sitter query/capture APIs to Prolog #97
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
nsaspy/prolog-rlm#97
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Parent: #93
Depends on: #94, #95, #96
Goal
Expose Tree-sitter's structural query engine to Prolog so language adapters can be expressed mostly as declarative query packs plus Prolog normalization rules rather than hard-coded C tree walkers.
Required low-level query surface
Provide repository-convention predicates equivalent in semantics to:
Exact names/arity may differ. Support enough query metadata to report compile errors with byte/point information and error kind.
Query execution must preserve the owning language/tree lifetime rules established by #94.
Prolog-first language adapters
Keep language-specific extraction logic out of C.
Support query packs conceptually like:
The concrete on-disk convention may be refined, but the API must allow a language adapter to register named query purposes without modifying the foreign layer.
Example semantic shape:
Query provenance
A capture used to create KB facts must be attributable to:
Changing a query pack must not leave old extracted facts silently looking current.
Capture model
Represent capture names as safe atoms/strings and captured syntax nodes through the #96 node identity model.
Support multiple captures per match without losing match grouping. For example a function-definition match may capture both the definition node and the name node; a call match may capture caller context and callee expression.
Do not force callers to reconstruct grouping from a flattened capture stream if Tree-sitter exposes match boundaries.
Predicate/query safety
Tree-sitter query source is data consumed by Tree-sitter. It must never be converted into arbitrary Prolog callables or directives.
Language query packs are availability/extraction configuration, not execution authority.
Malformed query source returns a structured compile error; it must not crash the Prolog process.
Performance / bounded execution
Support bounded query execution over:
Avoid forcing a full materialized #96 CST merely to run a query when the native tree is available.
Acceptance criteria
Non-goals
Refs #93 #94 #95 #96
RAGE handoff from slice #96 (PR #342)
Where this loop begins
main(#342 merged 2026-09-02T19:26:52Z). Dependency gate is closed; the queue was re-read per the #334 hardening-lane contract at slice start. (Stale "not yet merged" blocker prose removed 2026-09-02 during #97 realization closeout.)~/git/worktrees/prolog-rlm-issue-97from currentmain(branchrage/97-query-capture-apis). Reuse-if-exists rule applies; never create a second worktree for a checked-out branch.~/.config/opencode/skills/rage/scripts/init-run.py 97 query-capture-apis --repo <checkout>. It records the immutable 40-char start SHA on branchrage/97-query-capture-apis; the run-log org file (rage/97-query-capture-apis.org) opens with the established* Run identityblock.research/README.md, human-gated). The loop begins at Analyze/research — not implementation. Research approval authorizes design only; design approval authorizes implementation.Contracts inherited from #94/#95/#96 that constrain this slice
rlm_project_syntaxgenerations), never raw pointers.rlm_project_grammar_packpattern); no pack grants execution/filesystem/network authority.*_execute -> Future -> sync await) for any native materialization; cancellation/deadline semantics like #96.Environmental intelligence from slice #96
make tree-sitter-ffiinsidenix develop(pkg-config tree-sitter); full grammar-bundle evidence vianix flake check path:. --no-update-lock-file --print-build-logs. The/usr/src/tree-sittersources inscripts/build-tree-sitter-test-grammars.share CI-only provisioning (Ubuntu dev packages).z-ai/glm-5.3-flash, repo varOPENROUTER_TEST_MODEL) is stochastic: #343 showed a one-offcore_minimal_depth_1verification-rejected answer that local replication cleared 6/6. Remedy for a red paid gate: confirm model pinning, replicate locally at exact head, re-run the job — never weaken the gate or claim fake-provider evidence.Suggested scope discipline (non-goals from #96 carry forward)
No universal semantic ontology (#98 owns normalization), no incremental reparsing (#99), no planner/product behavior, no second scheduler. Query packs: python definitions + javascript definitions/calls through one generic API as minimum grammar coverage.
Research approval recorded (ADADR control plane)
The research phase for this slice is approved; design work is authorized. Implementation remains blocked until the separate design-approval gate.
research/tree-sitter-query-capture.org— RLM-RESEARCH-012 "Tree-sitter query/capture APIs through the #94 FFI"prolog-rlm.research-approval.v1,#+approval_state: APPROVED4ab728553c65b574c440066f02aadbf9e9893225, blob1974058b0ad9b1ed0d1596a09810e5f2523eb837(binding machine-checked viagit rev-parse --verify)2026-09-02T20:26:54Z· validatormake research-approvalPASS (20 tracked files)rage/97-query-capture-apis, base156bfe9b2caffa1b967e77bee51263ee9e85fb50What the next slice consumer inherits
rlm_project_query-style sibling module (not insiderlm_project_syntax); the on-disk project KB persists under$PROJECT_ROOT/.kb/<kb tree>(operator-clarified epic intent, first recorded in this slice and on epic #93: https://github.com/lost-rob0t/prolog-rlm/issues/93#issuecomment-5515841794)..kbtree layout (path scheme, journal/snapshot cadence, backend-neutral facade API) — the design must answer it from existingpersist(File)precedent evidence or spawn bounded research first; the kill -9 restart fixture is its acceptance criterion.api.hsurface confirmed (26 query functions; 5 newer functions excluded); no native mid-scan query timeout → Prolog-driven step deadlines + match limit; predicates are host-evaluated → smallest slice rejects predicate-bearing packs structurally.rage/97-query-capture-notes.orgawaiting operator confirmation.Design approval recorded (ADADR control plane) — realization handed to a fresh slice
The approved design is recorded in
rage/97-query-capture-apis.org§Design phase onrage/97-query-capture-apis(design headbb729f427eb9e711964ca1474ec513c8d9ca6349at approval, base research commit4ab728553c65b574c440066f02aadbf9e9893225).2026-09-02T20:35:55Z; evidence recorded in the committed run log (#+design_approval_*block).rage/97-query-capture-realize-prompt.md(in-repo, same branch) — start evidence, approved-design summary, full TDD surface incl. the kill -9.kbrestart fixture, 0.20.x constraints, exact-head verification, PR/closing rules.State: research APPROVED → design APPROVED → implementation authorized (next slice).
Realization complete — merged via Forgejo PR nsaspy/prolog-rlm#294
Implemented within the approved design (RLM-RESEARCH-012: research APPROVED → design APPROVED → realization authorized; both gates recorded above).
Merged state
main, merge commit037ea1f149a8…, exact reviewed head6153b00a4cfd…(implementation commitc24e87c…; commits after it carry only the verifier evidence journal +.gitignore).rlm_direct,rlm_completion,rlm_plan, prompt compilation, SPEC, VERIFY, or any expert-tool abstraction.Evidence (machine-recorded at exact head
13efeac…via the worktree verifier;prolog-verify check= pass)rlm_tree_sitter_query+rlm_project_query+ fresh-processSIGKILLrestart fixture: 20/20.check_runtime,load_all(static load without optional FFI) pass.deterministic16/16 (quality 1.00),deep-experiment15/15; CLIdemo --jsonpass.make tree-sitter-ffiinnix developpass;nix flake check path:.4/4;git diff --checkclean.Acceptance criteria → named deterministic tests (all at merged head)
compile_metadata_and_match_grouping,next_capture_preserves_match_groupcompile_error_has_kind_and_byte_offset,malformed_pack_query_has_structured_locationcaptures_are_grouped_and_provenance_complete,next_capture_preserves_match_grouppython_and_javascript_use_the_same_generic_query_api+cprovenance test (python, javascript, c)rlm_project_querysuitepython_and_javascript_use_the_same_generic_query_apisubtree_and_byte_range_execution_are_bounded,cursor_ranges_and_close_are_structuredcaptures_are_grouped_and_provenance_complete(grammar ref, pack hash, parse generation, span, source SHA-256)replacing_a_pack_stales_old_extraction_and_changes_hash+ publication-fencing tests (new_parse_publication_fences_prior_records_stale,reused_parse_publication_fences_prior_extraction_stale, journaled fencing surviving restart)query_source_is_data_not_a_callable,predicate_bearing_packs_are_rejected_without_evaluation,wrong_grammar_and_callable_source_fail_closedzero_and_multiple_matches_remain_structured,malformed_pack_query_has_structured_location,wrong_grammar_and_callable_source_fail_closed,unicode_points_use_tree_sitter_byte_columns,replacing_a_pack_stales_old_extraction_and_changes_hash+ restart fixtureFollow-ups (not part of this issue): #98 semantic normalization and #99 freshness/invalidation consume the fenced
current/stalesubstrate; #96/#97 lock order and journal compatibility must be preserved there. Parent epic #93 stays open.Closing as completed: implementation merged to canonical
mainwith deterministic coverage of every acceptance criterion.