Skip to content

test(graph-rag): multi-snapshot query prototype and gate evidence (ADR 0020 Phase 2) - #296

Merged
kl3inIT merged 4 commits into
mainfrom
feat/msq-prototype-bench
Aug 5, 2026
Merged

test(graph-rag): multi-snapshot query prototype and gate evidence (ADR 0020 Phase 2)#296
kl3inIT merged 4 commits into
mainfrom
feat/msq-prototype-bench

Conversation

@kl3inIT

@kl3inIT kl3inIT commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Summary

ADR 0020 Phase 2 gate evidence (plan steps 1–3 of 2026-08-05-multi-snapshot-query-prototype). Implementation by Codex gpt-5.6-sol (high) under handoff; coordinator-reviewed with an amendment.

  • Shadow equivalence: PASS — compound AuthorizedMultiSnapshotQuery returns identical candidates/attribution to N per-space queries across 1/7/20 spaces, narrow/broad grants. Test-scope only (Testcontainers); zero runtime wiring.
  • Latency gate: FAIL, honestly retained — 20/72 scenarios exceed the predeclared p95 ≤ 500 ms; every multi-space scenario at the largest scale times out (>5 s). Coordinator amendment maps scales to production: the largest benchmark scale ≈ today's production corpus (8k vs 10k vectors), and identifies the cause — join-first distance computation defeats the HNSW index (no vector-adjacent ORDER BY … LIMIT). The store-fanned LATERAL variant the debate actually specified remains unmeasured and is the next evidence step.
  • Recall gate: not scored — deterministic recall@40 scorer + 15-question golden fixture land in evaluation/; scoring needs live observations (plan step 3 continuation).
  • Benchmark is opt-in (ORGMEMORY_RUN_MSQ_BENCHMARK=true), excluded from clean test.

Per ADR 0020, cutover stays blocked on this evidence; Phase 1 remains the standing architecture.

Verification

  • Opt-in benchmark harness run: PASS (8m06s, 72 scenarios, EXPLAIN captured; threshold failures retained as evidence).
  • ./gradlew --no-daemon clean test: PASS 9m05s. Focused PostgreSQL shadow test: PASS.
  • uv run --frozen pytest: 37 passed; ruff check: PASS.

skip-release: test-scope prototype and gate evidence only; no product behavior changes.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a retrieval-recall evaluation tool with configurable scoring, regression thresholds, validation, and JSON reports.
    • Added a Vietnamese retrieval golden dataset with 15 evaluation cases.
    • Added authorized multi-snapshot retrieval integration coverage across vector and graph queries.
  • Documentation

    • Documented retrieval-recall scoring, setup, execution, limitations, and review status.
    • Added a handoff report covering benchmark results, verification, and scoped exclusions.
  • Tests

    • Added coverage for recall cutoffs, deduplication, incomplete observations, regression detection, authorization, and performance thresholds.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This change adds a retrieval-recall evaluation CLI and golden dataset. It also adds an authorized multi-snapshot PostgreSQL query prototype, deterministic synthetic fixtures, integration tests, benchmarks, and a Phase 2 handoff.

Changes

Retrieval-recall evaluation

Layer / File(s) Summary
Dataset contracts and recall scoring
evaluation/fixtures/retrieval-recall-golden-v1.json, evaluation/src/orgmemory_eval/retrieval_recall.py
Defines strict dataset and observation schemas. Calculates cutoff recall, recall deltas, and tolerance-based pass/fail results.
CLI report generation
evaluation/src/orgmemory_eval/retrieval_recall.py, evaluation/pyproject.toml, evaluation/README.md
Adds the console script, JSON input workflow, report output, and execution documentation.
Scoring validation tests
evaluation/tests/test_retrieval_recall.py
Tests cutoff behavior, deduplication, passing scores, regression failures, and incomplete observations.

Authorized multi-snapshot query prototype

Layer / File(s) Summary
Synthetic multi-snapshot dataset
integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/MultiSnapshotSyntheticDataset.java
Creates deterministic graph, vector, publication, contribution, and authorization data at multiple scales.
Authorized query execution
integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQuery.java
Adds authorized compound and per-space SQL queries, validation, candidate merging, timing, and EXPLAIN handling.
Integration verification and benchmark reporting
integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQueryIntegrationTests.java, tmp/handoff-msq-prototype-done.md
Adds result-equivalence tests, gated benchmarks, percentile and EXPLAIN reporting, and Phase 2 handoff status.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant GoldenDataset
  participant ObservationSet
  participant score
  participant ReportFile
  CLI->>GoldenDataset: load golden JSON
  CLI->>ObservationSet: load observation JSON
  CLI->>score: validate and score inputs
  score-->>CLI: return recall report
  CLI->>ReportFile: write formatted JSON
Loading
sequenceDiagram
  participant IntegrationTests
  participant MultiSnapshotSyntheticDataset
  participant AuthorizedMultiSnapshotQuery
  participant PostgreSQL
  IntegrationTests->>MultiSnapshotSyntheticDataset: load deterministic fixture
  MultiSnapshotSyntheticDataset->>PostgreSQL: insert graph and vector projections
  IntegrationTests->>AuthorizedMultiSnapshotQuery: execute authorized query
  AuthorizedMultiSnapshotQuery->>PostgreSQL: run compound or per-space SQL
  PostgreSQL-->>AuthorizedMultiSnapshotQuery: return candidates and EXPLAIN data
  AuthorizedMultiSnapshotQuery-->>IntegrationTests: return merged results and timings
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the multi-snapshot query prototype and its gate evidence, which are the main changes in the pull request.
Description check ✅ Passed The description covers the summary, verification results, failures, scope, and cutover status, but omits the template's Documentation impact section.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/msq-prototype-bench

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Tegami

This repository uses Tegami to manage releases. When your changes affect published packages, add a changelog file under .tegami/ before merging.

Create a changelog → · Changelog format

Release preview

Package Bump Version
orgmemory minor 0.2.00.3.0

This PR does not add changelog files. Pending changelogs from other branches are included in the preview above.

Run pnpm run tegami locally to create a changelog interactively.

Managed by Tegami.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 16

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@evaluation/src/orgmemory_eval/retrieval_recall.py`:
- Around line 90-91: Enforce the report schema v1 contract in the retrieval
evaluation entry point by rejecting any top_k value other than 40 before
retrieval runs. Keep the existing recall@40 labels, fields, and gate aligned
with this fixed value, and add a test that explicitly passes a non-default top_k
and verifies it is rejected.

In
`@integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQuery.java`:
- Around line 340-347: The helper in AuthorizedMultiSnapshotQuery currently
infers the result shape from rows.getFirst(), misclassifying empty candidate
results and requiring unchecked casts. Split it into typed queryRows(...) and
queryExplain(...) methods, have each caller invoke the method matching its known
query shape, and preserve the existing result data and timing values without
runtime type inspection.
- Around line 406-419: Replace string concatenation in scopesJson with
Jackson-based JSON generation, serializing every SnapshotScope field and
authorized asset ID through the JSON writer so quotes, backslashes, and other
special characters are escaped correctly. Preserve the existing array/object
schema and output values consumed by jsonb_to_recordset, and use the existing
Jackson dependency rather than introducing a custom escaping implementation.
- Around line 225-236: Update ROW_ORDER so its spaceId, candidateId, and
contributionId tie-breakers compare UUIDs via toString(), matching PostgreSQL’s
unsigned-byte ordering and the existing SCORE_ORDER behavior. Leave the
globalRank ordering and comparator structure unchanged.
- Around line 56-95: Enforce ACL snapshot consistency in both
visible_entity_contributions and visible_relations by matching each
contribution’s acl_generation to scope.acl_generation, then update validateRows
to compare the row’s evidenceAclGeneration rather than the request-derived
value. Replace the substring-based projection checks in QUERY_BODY with exact
comma-delimited token matching for VECTOR and GRAPH, preserving the fail-closed
authorization behavior.
- Around line 328-334: Update the timeout setup in AuthorizedMultiSnapshotQuery
so the session-level statement_timeout is always restored before the pooled
connection is released. Wrap the timeout-scoped query work in a finally block
that resets the setting, or use SET LOCAL within an explicit transaction;
preserve the existing int-based timeout handling and do not change it solely for
the OpenGrep false positive.

In
`@integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQueryIntegrationTests.java`:
- Around line 176-191: The reported p95 is actually the maximum of five samples,
so align the metric naming and handoff with the implementation. In
AuthorizedMultiSnapshotQueryIntegrationTests, either increase REPETITIONS to
support a meaningful p95 or rename Statistics fields, report columns, and the
gate comparison from p95/p99 to observed maximum; in
tmp/handoff-msq-prototype-done.md lines 12-14, restate the outcome as “max of 5
samples <= 500 ms” if retaining the current sample count.
- Around line 296-340: Update the three String.format templates in the dataset,
scenario, and EXPLAIN report loops to end with the literal newline escape \n
instead of the platform-dependent %n. Keep the existing formatting and report
content unchanged so all generated sections consistently use LF line endings.
- Around line 143-159: Update the report-writing flow in the scenario loop so
markdown(datasets, results, explains) is written once after the completed
scenario pair or at the end of the spaceCount loop, rather than before and after
each inner measurement. Preserve the initial incremental evidence behavior while
removing the per-iteration full-document rewrite.
- Around line 205-207: Update the COLD-phase flow around discardPlans() and
AuthorizedMultiSnapshotQuery.query so DISCARD PLANS executes on the same JDBC
connection used for the measured query, or explicitly qualify the report’s COLD
claim to acknowledge plans may not be discarded for that session. Preserve the
existing WARM behavior and concurrent benchmark structure.
- Around line 408-438: Update ExplainHighlight.from and its number helper to
parse the EXPLAIN JSON with the existing Jackson JSON tree support, then read
the root object at [0].Plan for Node Type and the root-level Planning Time,
Execution Time, Shared Hit Blocks, and Shared Read Blocks values. Remove the
regex-based Matcher.find extraction and preserve the current fallback values
when fields are absent; the fixed literal-field Pattern.quote logic is not the
issue.
- Around line 245-248: Update the timeout check in the exception handler around
the visible SQLException condition to rely solely on SQLState "57014". Remove
the getMessage() access and locale-dependent text matching so null messages and
localized PostgreSQL errors are handled as statement timeouts without changing
the existing traversal or return behavior.
- Around line 99-104: Strengthen the shadow-equivalence test around the compound
and per-space query results by asserting both result sets are non-empty and
contain the expected candidate count derived from the fixture setup. Keep the
existing validateRows and recursive equivalence assertions, anchoring the
changes in the test method containing compound.rows() and perSpace.rows().
- Around line 34-52: Update the static postgres field in
AuthorizedMultiSnapshotQueryIntegrationTests to declare PostgreSQLContainer with
its generic parameter, preferably PostgreSQLContainer<?> (or the appropriate
self-type), while preserving the existing container initialization and fluent
builder typing.

In `@tmp/handoff-msq-prototype-done.md`:
- Line 47: Update the handoff note to mark JetBrains IDE inspection as an
outstanding gate, not a completed validation, while retaining the Gradle compile
and test results. Explicitly state that inspection must be run only on the
edited backend Java files before merge.
- Around line 1-4: Remove the handoff record from tmp/ and place it under the
existing multi-snapshot query increment directory at
docs/increments/active/2026-08-05-multi-snapshot-query-prototype/, or exclude
the tmp/ copy from version control; ensure no committed durable artifact remains
under tmp/.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 55adecdc-d509-463e-9653-4ff448f0b69e

📥 Commits

Reviewing files that changed from the base of the PR and between 2f9b32d and 0a4d18e.

⛔ Files ignored due to path filters (1)
  • docs/increments/active/2026-08-05-multi-snapshot-query-prototype/results.md is excluded by !docs/**
📒 Files selected for processing (9)
  • evaluation/README.md
  • evaluation/fixtures/retrieval-recall-golden-v1.json
  • evaluation/pyproject.toml
  • evaluation/src/orgmemory_eval/retrieval_recall.py
  • evaluation/tests/test_retrieval_recall.py
  • integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQuery.java
  • integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQueryIntegrationTests.java
  • integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/MultiSnapshotSyntheticDataset.java
  • tmp/handoff-msq-prototype-done.md
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: PostgreSQL GraphRAG
🧰 Additional context used
📓 Path-based instructions (2)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Treat the repository and runtime evidence as the engineering system of record; do not treat chat or Northstar as authoritative.
Before changing a domain, read its specification, test-coverage document, and applicable decision filenames.
Material decisions about domain boundaries, authorization, persistence, publication, concurrency, cache isolation, parity scope, or deployment require an independent architecture challenge and documented alternatives before implementation.
Do not use completed increment documents as the source for current behavior; use them only for history or archaeology.
Before using unfamiliar Spring Boot, Spring Modulith, Spring AI, Gradle, React, Vite, Tailwind, TypeScript, Next.js, or Fumadocs APIs, consult current official documentation, Context7, and the relevant verification skill.
Read docs/guidelines/agent-safety.md before retrieval, AI, MCP, permission, upload, graph, or export work; never commit secrets or customer data.
Keep ddl-auto=validate and pair every persisted-model change with a Flyway migration.
Use the testing harness; a terminating clean test is the JVM context gate, and bootRun is not verification.

Files:

  • evaluation/pyproject.toml
  • evaluation/README.md
  • evaluation/fixtures/retrieval-recall-golden-v1.json
  • tmp/handoff-msq-prototype-done.md
  • integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQuery.java
  • integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/MultiSnapshotSyntheticDataset.java
  • integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQueryIntegrationTests.java
  • evaluation/src/orgmemory_eval/retrieval_recall.py
  • evaluation/tests/test_retrieval_recall.py
**/*.java

📄 CodeRabbit inference engine (AGENTS.md)

Apply IDE inspection only to edited backend Java files.

Files:

  • integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQuery.java
  • integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/MultiSnapshotSyntheticDataset.java
  • integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQueryIntegrationTests.java
🪛 ast-grep (0.45.0)
integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQueryIntegrationTests.java

[warning] 433-434: Regular expression is compiled from a non-literal, possibly user-controlled value. A crafted regex (or input matched against one) can trigger catastrophic backtracking and hang the thread (ReDoS). Use a hardcoded literal pattern, wrap untrusted text with Pattern.quote(...), or validate/length-limit the input and enforce a matching timeout before passing it to Pattern.compile / String.matches / String.replaceAll / String.replaceFirst.
Context: Pattern.compile(String.format(
Locale.ROOT, NUMBER_FIELD.pattern(), Pattern.quote(field)))
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-java)

evaluation/src/orgmemory_eval/retrieval_recall.py

[info] 158-158: use jsonify instead of json.dumps for JSON output
Context: json.dumps(report, ensure_ascii=False, indent=2)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🪛 OpenGrep (1.26.0)
integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQuery.java

[ERROR] 332-332: SQL query built via string concatenation passed to Statement.execute*(). Use PreparedStatement with parameterized queries instead.

(coderabbit.sql-injection.java-statement-concat)

🔇 Additional comments (18)
evaluation/fixtures/retrieval-recall-golden-v1.json (1)

1-112: LGTM!

evaluation/pyproject.toml (1)

19-19: LGTM!

evaluation/README.md (1)

29-50: LGTM!

integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/MultiSnapshotSyntheticDataset.java (8)

17-33: LGTM!


35-140: LGTM!


142-172: LGTM!


174-290: LGTM!


292-317: LGTM!


323-348: LGTM!


350-387: LGTM!


389-440: LGTM!

integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQuery.java (5)

31-54: LGTM!


195-224: LGTM!


244-289: LGTM!


421-588: LGTM!


124-143: 🚀 Performance & Scalability

No change needed for the vector.embedding cast.

The baseline migration already creates a matching HNSW index for the expression ((embedding)::public.vector(1536)) with vector_cosine_ops, so the query side matches that indexed expression.

integrations/graph-rag-postgres/src/test/java/com/orgmemory/graphrag/postgres/AuthorizedMultiSnapshotQueryIntegrationTests.java (2)

58-82: LGTM!


255-272: LGTM!

Comment thread evaluation/src/orgmemory_eval/retrieval_recall.py
Comment thread tmp/handoff-msq-prototype-done.md
Comment thread tmp/handoff-msq-prototype-done.md
@kl3inIT
kl3inIT merged commit 475793d into main Aug 5, 2026
18 checks passed
kl3inIT added a commit that referenced this pull request Aug 5, 2026
fix(graph-rag): correct multi-snapshot gate evidence per PR #296 review
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant