fix(reflection): guard the derived session cache write against a concurrent delete's invalidation - #972
Conversation
rwmjhb
left a comment
There was a problem hiding this comment.
Reviewed head 551d825. The targeted tests, full suite, and repository CI pass. The generation snapshot/check is a conservative fail-safe around the derived-session cache publication and introduces no demonstrated HIGH/CRITICAL regression. Approving.
The new race test would be stronger if it proved the unfixed implementation fails under a production-reachable dispatch action and directly asserted the session-cache publication rather than allowing DB-backed repopulation to satisfy the result. Also note that the process-wide generation counter may suppress an unrelated session cache fill, which is correctness-safe but can cause extra reads.
|
Thanks for the update. After the recent merges, current head |
|
Rebased onto current master (post #952) as requested. Full suite green, dist rebuilt. |
551d825 to
e376345
Compare
rwmjhb
left a comment
There was a problem hiding this comment.
Reviewed head e376345 after the rebase. The generation guard is conservative, source/dist are aligned, CI and the orchestrator full suite pass, and I found no merge-blocking regression.
Non-blocking follow-up: strengthen the race regression with a direct positive control proving the derived-session cache publication path is exercised; the process-global generation may also cause avoidable cache misses across unrelated sessions.
|
Thanks for the update. After #934 merged, current head |
|
Rebased onto current master (post #934): package.json test-chain union was the only conflict. Typecheck, build (dist recommitted), manifest verifier, and the full suite are green. Mergeable again. |
e376345 to
67fa7e4
Compare
rwmjhb
left a comment
There was a problem hiding this comment.
Re-reviewed rebased head 67fa7e4. The rebase only unions the test registration, and the generation check still prevents a concurrent same-process delete from being followed by a stale derived-session cache publication. The focused race tests, full suite, and GitHub CI are green.
The synthetic dispatch used by the race test and the process-wide generation counter are reasonable follow-ups; the latter can cause an unrelated cache miss but remains fail-safe for correctness.
Approving.
|
PR #941 has now merged, and this branch currently has merge conflicts with the latest master. Please rebase onto current master, resolve the conflicts, and push the updated branch. We will re-review the new head after CI completes. |
|
Rebased onto current master (post #941); registration files re-unioned, typecheck and the full suite pass, dist rebuilt in-commit. |
67fa7e4 to
f44c5fe
Compare
rwmjhb
left a comment
There was a problem hiding this comment.
Re-reviewed rebased head f44c5fe. The conflict resolution preserves the generation guard and cache-invalidation race fix; targeted tests, the full suite, and GitHub CI are green.
The production-event positive control, broader DB-store/delete ordering, and process-wide generation granularity remain non-blocking follow-ups.
Approved.
|
PR #944 has now merged, and this branch currently has merge conflicts with the latest master. Please rebase onto current master, resolve the conflicts, and push the updated branch. We will re-review the new head after CI completes. |
f44c5fe to
3a3c061
Compare
rwmjhb
left a comment
There was a problem hiding this comment.
Re-reviewed rebased head 3a3c061. The conflict resolution preserves the previously approved generation guard; targeted tests, the full local suite, and all GitHub CI checks pass. The retriever dist changes are regenerated output for source behavior already present on the current base.
A production-event positive control for the synthetic non-boundary dispatch, broader delete-before-store ordering coverage, and process-wide generation granularity remain non-blocking follow-ups.
Approved.
|
Rebased onto master after #942's merge (registration-chain union only, no source conflicts). Full gates green: typecheck, fresh dist, manifest verifier, full suite. |
3a3c061 to
7fc420b
Compare
|
Rebased onto master after #955's merge (registration unions only). Full gates green. |
7fc420b to
0d27189
Compare
|
Rebased onto master after #960's merge (registration unions only). Full gates green. |
0d27189 to
3b231f5
Compare
…urrent delete's invalidation Squashed from the review-round history for a clean rebase onto current master.
|
Rebased onto master after #964's merge (registration unions only). Full gates green. |
3b231f5 to
d14984a
Compare
Problem
Two related gaps around
reflectionDerivedBySession, both from the trail #924 left open (its cross-process test coveredreflectionByAgentCacheand flagged the derived-by-session case as an unexplained discrepancy instead of claiming coverage).Same-process race: the
command:newreflection path caches its freshly generated derived slices after awaitingstoreReflectionToLanceDB. A delete landing during those awaits bumps the invalidation generation and clears the map, but the late cache write then resurrects derived lines whose rows the delete just removed, and they keep being injected for up to one cache TTL. The by-agent path already guards exactly this window (the TOCTOU check inloadAgentReflectionSlices); the derived write did not.The flagged discrepancy itself turns out to be a test-construction artifact, not an invalidation gap: the derived-focus injector is two caches in series (the session cache, then the independently clocked by-agent fallback inside
loadAgentReflectionSlices), so cross-process staleness is bounded from the last DB read, not from the derived cache's priming. A test that primes the two caches at different times and asserts one TTL from the derived priming measures the wrong clock, which reproduces exactly the inconsistency the earlier round saw.Change
index.ts: capture the invalidation generation before the reflection store awaits and skip thereflectionDerivedBySessionwrite when it moved (mirrors the existing guard inloadAgentReflectionSlices). The invalidation comment now names the two-caches-in-series fallback and the last-DB-read staleness bound.test/reflection-derived-cache-invalidation.test.mjs(new, registered in the package.json test chain and the CI manifest undercore-regression):runEmbeddedPiAgent) rather than seeded rows, so the assertion is single-clock and deterministicValidation
npm run buildclean,tsc --noEmitclean, fullnpm testchain green,core-regressionCI group green, CI manifest verifier green, dist rebuilt in the same commit./newexercised the changed path end to end (generation, mapped-row admission, reflection markdown write) with no new warnings or errors.