[PR #3966] feat(evidence): add literal text query to retained Evidence summaries #5970

Open
opened 2026-10-31 01:10:49 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/3966
Author: @caioitalo1
Created: 10/15/2026
Status: 🔄 Open

Base: main ← Head: feat/evidence-text-query


📝 Commits (9)

  • 54b98db feat(evidence): add literal text query to retained Evidence summaries
  • 98df370 fix(evidence): fold query case per code point and bound traversal
  • 276d1e0 fix(evidence): map query offsets lazily and bound term scans
  • 1e370fa fix(evidence): fold symbol case variants and cap query length
  • 562e25f fix(evidence): fold capital sharp s and bound fold buffers
  • a0394d0 refactor(evidence): match query terms with Unicode simple case folding
  • ba37cc6 fix(evidence): build query match pointers only for the reported leaf
  • 387f2c2 fix(evidence): advertise the query code-point bound in the input schema
  • b651d82 perf(evidence): scan each leaf once for the first query term

📊 Changes

5 files changed (+415 additions, -4 deletions)

View changed files

📝 docs/mcp-contracts.md (+9 -1)
📝 src/contracts/sessionToolContracts.ts (+1 -1)
📝 src/contracts/toolInputReferences.test.ts (+21 -0)
📝 src/domain/evidenceRecordSummary.test.ts (+184 -1)
📝 src/domain/evidenceRecordSummary.ts (+200 -1)

📄 Description

Summary

Retained Evidence could only be selected by exact identifiers (evidence_id, operation, target_sha256, profile digest, procedure address). An analyst or agent looking for a string, symbol, or SQL fragment across a session's records had to export the complete bundle and search it outside REA. This adds a literal text query record filter to Evidence bundle summaries, so get_evidence_bundle (MCP, current session) and inspect-evidence-bundle (CLI, bundle file) return only matching records with a bounded snippet locating the hit.

Problem and expected behavior

Use case: "Which retained records mention LIKE and lower?" With detail: "summary" and filters.query, every whitespace-separated term must occur case-insensitively in some string value of the record's normalized_result or limitations. Each returned record carries query_match with the JSON Pointer path of the first leaf containing the first term, a snippet with up to 30 characters of context on each side, and match_start/match_length offsets into that snippet. Characters such as % and _ are matched literally.

Change and scope

The change is confined to the owning domain module src/domain/evidenceRecordSummary.ts: evidenceRecordFiltersSchema gains query, and summarizeEvidenceBundle applies it. Both adapters already parse filters through this schema and route through summarizeEvidenceBundle, so CLI and MCP gain the filter without adapter code. Payloads are read only when a query is selected; only the bounded snippet is copied into the summary.

Not included: fuzzy matching, relevance ranking, or an index. Matching is a linear scan over the selected records' string leaves.

Follow the contribution scope. This reads retained Evidence only and involves no target execution, injection, mutation, or protection recovery; a maintainer scope decision is not applicable unless maintainers judge otherwise.

Contract and boundary impact

  • Semantic owner and earliest changed stage: src/domain/evidenceRecordSummary.ts (record filters and summary schema).
  • Contribution scope fit and linked maintainer decision: read-only selection over existing Evidence; not applicable.
  • CLI and MCP/tool-catalog contract: additive optional filters.query; every summary record now includes query_match (null when no query is selected). Shared JsonValue typing rejects an optional field here, so the field is always present.
  • Provider, bridge, target-format, or platform compatibility: none.
  • Evidence, artifact, provenance, or reconstruction contract: records are unchanged; matches report a JSON Pointer path into the record.
  • Target selection, authority, upstream behavior, and cleanup details: not applicable.
  • Generated metadata, package, or installation impact: tool input schema gains query; npm run docs:check passed locally.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

  • Tests added or updated: src/domain/evidenceRecordSummary.test.ts covers AND-term selection, at most 1024 code points and 16 distinct terms, canonical key order, Unicode simple case folding (sigma, micro sign, long s, sharp s; dotless i distinct), literal regex syntax in terms, lone surrogates, whitespace trimming, terms spanning separate result strings and limitations, snippet path, ellipsis and offsets, literal %/_, per-code-point case folding (ΟΣ/Σ, İ), surrogate-safe snippet boundaries, and null without a query.
  • Base reproduction or other evidence: executed against the built CLI with a two-record bundle generated from dist/domain.
  • User-visible CLI/MCP output:
{"kind":"evidence-bundle-summary","filters":{"query":"like LOWER"},"total_retained_records":2,"matching_records":1,"records":[{"operation":"list_strings","query_match":{"path":"/normalized_result/strings/0","snippet":"…from notes where LOWER(title) LIKE :t0 ESCAPE '\\'","match_start":31,"match_length":4,"offset_units":"utf16-code-units"}}]}

(Abridged; unchanged record fields omitted.)

  • Remaining proof gaps: the MCP get_evidence_bundle path was not exercised through a live MCP client; it shares the parsed schema and summary function with the CLI path.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • npm run test:local -- src/domain/evidenceRecordSummary.test.ts — 8 passed; src/contracts/toolInputReferences.test.ts (advertised maxLength checked with Ajv against the runtime parser) and contract/catalog tests — 36 passed.
  • npm run check:fast — passed (typecheck and lint).
  • npm run docs:check — passed.
  • npm run build:cached — passed.
  • node scripts/rea.mjs inspect-evidence-bundle <query.json> --format json against the built CLI — 1 of 2 records matched, with the output shown above.
  • Ghidra/IDA adapter tests fail locally on Windows both with and without this change (native/windows/build/manifest.json missing); unrelated.

Compatibility, safety, and release

  • Breaking changes or migration steps: none intended; summary records gain an always-present query_match field (null by default).
  • Real Hopper/Ghidra, browser, or OS coverage: none needed; Windows 11 local run only.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: reads already-retained local Evidence only; snippets are bounded to roughly 60 characters plus the term.

Author readiness

Human owner: @caioitalo1

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/3966 **Author:** [@caioitalo1](https://github.com/caioitalo1) **Created:** 10/15/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feat/evidence-text-query` --- ### 📝 Commits (9) - [`54b98db`](https://github.com/morluto/rea/commit/54b98db75e2b43b59c6327b164eb6578fef7f0e6) feat(evidence): add literal text query to retained Evidence summaries - [`98df370`](https://github.com/morluto/rea/commit/98df3706a8394bd2ccea1ea8be0d11d6d4da837a) fix(evidence): fold query case per code point and bound traversal - [`276d1e0`](https://github.com/morluto/rea/commit/276d1e08acced0afb6a82c88a3c4e236e8276b44) fix(evidence): map query offsets lazily and bound term scans - [`1e370fa`](https://github.com/morluto/rea/commit/1e370fae8d438ce93673324b95cacac9903759ca) fix(evidence): fold symbol case variants and cap query length - [`562e25f`](https://github.com/morluto/rea/commit/562e25fb745a5ee3de8e996f065b01221c47cb79) fix(evidence): fold capital sharp s and bound fold buffers - [`a0394d0`](https://github.com/morluto/rea/commit/a0394d0077dd83d88e748cb6719e14f5de7df6de) refactor(evidence): match query terms with Unicode simple case folding - [`ba37cc6`](https://github.com/morluto/rea/commit/ba37cc6275c1b16f8c35bb78eeffe8e4dc2cc1f8) fix(evidence): build query match pointers only for the reported leaf - [`387f2c2`](https://github.com/morluto/rea/commit/387f2c25342b2d5f7cf28b1573178816af1a46dc) fix(evidence): advertise the query code-point bound in the input schema - [`b651d82`](https://github.com/morluto/rea/commit/b651d821de50179ab5e1a560e991ff36db387b1f) perf(evidence): scan each leaf once for the first query term ### 📊 Changes **5 files changed** (+415 additions, -4 deletions) <details> <summary>View changed files</summary> 📝 `docs/mcp-contracts.md` (+9 -1) 📝 `src/contracts/sessionToolContracts.ts` (+1 -1) 📝 `src/contracts/toolInputReferences.test.ts` (+21 -0) 📝 `src/domain/evidenceRecordSummary.test.ts` (+184 -1) 📝 `src/domain/evidenceRecordSummary.ts` (+200 -1) </details> ### 📄 Description ## Summary Retained Evidence could only be selected by exact identifiers (`evidence_id`, `operation`, `target_sha256`, profile digest, procedure address). An analyst or agent looking for a string, symbol, or SQL fragment across a session's records had to export the complete bundle and search it outside REA. This adds a literal text `query` record filter to Evidence bundle summaries, so `get_evidence_bundle` (MCP, current session) and `inspect-evidence-bundle` (CLI, bundle file) return only matching records with a bounded snippet locating the hit. ## Problem and expected behavior Use case: "Which retained records mention `LIKE` and `lower`?" With `detail: "summary"` and `filters.query`, every whitespace-separated term must occur case-insensitively in some string value of the record's `normalized_result` or `limitations`. Each returned record carries `query_match` with the JSON Pointer `path` of the first leaf containing the first term, a snippet with up to 30 characters of context on each side, and `match_start`/`match_length` offsets into that snippet. Characters such as `%` and `_` are matched literally. ## Change and scope The change is confined to the owning domain module `src/domain/evidenceRecordSummary.ts`: `evidenceRecordFiltersSchema` gains `query`, and `summarizeEvidenceBundle` applies it. Both adapters already parse `filters` through this schema and route through `summarizeEvidenceBundle`, so CLI and MCP gain the filter without adapter code. Payloads are read only when a query is selected; only the bounded snippet is copied into the summary. Not included: fuzzy matching, relevance ranking, or an index. Matching is a linear scan over the selected records' string leaves. Follow the [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope). This reads retained Evidence only and involves no target execution, injection, mutation, or protection recovery; a maintainer scope decision is not applicable unless maintainers judge otherwise. ## Contract and boundary impact - Semantic owner and earliest changed stage: `src/domain/evidenceRecordSummary.ts` (record filters and summary schema). - Contribution scope fit and linked maintainer decision: read-only selection over existing Evidence; not applicable. - CLI and MCP/tool-catalog contract: additive optional `filters.query`; every summary record now includes `query_match` (`null` when no query is selected). Shared `JsonValue` typing rejects an optional field here, so the field is always present. - Provider, bridge, target-format, or platform compatibility: none. - Evidence, artifact, provenance, or reconstruction contract: records are unchanged; matches report a JSON Pointer path into the record. - Target selection, authority, upstream behavior, and cleanup details: not applicable. - Generated metadata, package, or installation impact: tool input schema gains `query`; `npm run docs:check` passed locally. Expected effects: - [x] Read existing files or captured data. - [ ] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage - Tests added or updated: `src/domain/evidenceRecordSummary.test.ts` covers AND-term selection, at most 1024 code points and 16 distinct terms, canonical key order, Unicode simple case folding (sigma, micro sign, long s, sharp s; dotless i distinct), literal regex syntax in terms, lone surrogates, whitespace trimming, terms spanning separate result strings and limitations, snippet path, ellipsis and offsets, literal `%`/`_`, per-code-point case folding (`ΟΣ`/`Σ`, `İ`), surrogate-safe snippet boundaries, and `null` without a query. - Base reproduction or other evidence: executed against the built CLI with a two-record bundle generated from `dist/domain`. - User-visible CLI/MCP output: ```json {"kind":"evidence-bundle-summary","filters":{"query":"like LOWER"},"total_retained_records":2,"matching_records":1,"records":[{"operation":"list_strings","query_match":{"path":"/normalized_result/strings/0","snippet":"…from notes where LOWER(title) LIKE :t0 ESCAPE '\\'","match_start":31,"match_length":4,"offset_units":"utf16-code-units"}}]} ``` (Abridged; unchanged record fields omitted.) - Remaining proof gaps: the MCP `get_evidence_bundle` path was not exercised through a live MCP client; it shares the parsed schema and summary function with the CLI path. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - `npm run test:local -- src/domain/evidenceRecordSummary.test.ts` — 8 passed; `src/contracts/toolInputReferences.test.ts` (advertised `maxLength` checked with Ajv against the runtime parser) and contract/catalog tests — 36 passed. - `npm run check:fast` — passed (typecheck and lint). - `npm run docs:check` — passed. - `npm run build:cached` — passed. - `node scripts/rea.mjs inspect-evidence-bundle <query.json> --format json` against the built CLI — 1 of 2 records matched, with the output shown above. - Ghidra/IDA adapter tests fail locally on Windows both with and without this change (`native/windows/build/manifest.json` missing); unrelated. ## Compatibility, safety, and release - Breaking changes or migration steps: none intended; summary records gain an always-present `query_match` field (`null` by default). - Real Hopper/Ghidra, browser, or OS coverage: none needed; Windows 11 local run only. - Package or release metadata impact: none. - Security, privacy, process, or containment review: reads already-retained local Evidence only; snippets are bounded to roughly 60 characters plus the term. ## Author readiness Human owner: @caioitalo1 - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [ ] This PR addresses a concrete problem or an agreed enhancement. - [ ] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [ ] The PR has one focused outcome and the title follows `type(scope): outcome`. - [ ] Related issue is linked, or the reason for not linking one is stated above. - [ ] Tests cover changed observable behavior and meaningful failure paths. - [ ] Owning docs, contracts, and generated metadata are updated where needed. - [ ] User-visible CLI/MCP changes include representative output. - [ ] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#5970
No description provided.