Draft v1
Fix post-compaction behavior so pi-readcache does not return diff/unchanged using pre-compaction trust evidence.
Current replay boundary can include pre-compaction trust history via firstKeptEntryId. This can yield post-compaction diff/unchanged responses that are hash-consistent but practically unhelpful for “fresh context after compaction” expectations.
Adopt a strict compaction barrier on the active branch path:
- Replay trust starts at
latestCompactionIndex + 1. - Ignore
firstKeptEntryIdfor trust reconstruction. - Pre-compaction trust is never used to establish post-compaction base.
This is branch-local and compaction-local:
- If multiple compactions exist, use the nearest ancestor compaction on current active path.
- If current leaf is before compaction (via
/tree), barrier is absent for that branch view.
-
First
readafter the latest active compaction for a file/scope:mode = fullorbaseline_fallback- never
unchanged/diffpurely from pre-compaction evidence.
-
Subsequent reads on same branch after post-compaction anchor:
- normal guarded trust logic applies (
unchanged,diff,unchanged_rangeas valid).
- normal guarded trust logic applies (
-
/treenavigation:- moving to a pre-compaction node removes that barrier from active path.
- moving to another branch uses that branch’s latest compaction barrier.
-
/readcache-refreshremains unchanged and still forces baseline for target scope.
- No pre-compaction trust may be used after active compaction barrier.
- Trust remains replay-derived, branch-local, and scope-aware.
- Guarded mode transitions remain unchanged.
- Fail-open fallback behavior remains intact.
- Tool contract (
read, params, output shape) remains unchanged.
Update findReplayStartIndex(branchEntries):
- current: prefers
firstKeptEntryId, fallbackcompaction+1 - target: always
compaction+1for latest compaction on active path
if (latestCompactionFound) {
return { startIndex: min(compactionIndex + 1, branchEntries.length), boundaryKey: `compaction:${id}` };
}
return { startIndex: 0, boundaryKey: "root" };- Keep boundary key stable for memo cache behavior.
- Keep trust transition engine untouched (anchor/derived guards still required).
No logic changes expected except behavior naturally follows updated boundary. Confirm replay window count is computed from new start index.
No algorithmic changes needed if replay boundary is fixed. Verify first post-compaction read resolves no base and returns baseline output.
No logic change required.
/readcache-status should reflect reduced replay window after compaction.
-
Replace/adjust old expectation:
- remove expectation that replay can start at
firstKeptEntryId. - assert latest-compaction boundary starts at
compaction+1.
- remove expectation that replay can start at
-
Keep existing guarded transition tests.
Add/adjust scenarios:
-
first_read_after_compaction_is_baseline_even_if_precompaction_anchor_exists- pre: full anchor + unchanged/diff before compaction
- compact
- post: first read must be
full/baseline_fallback
-
latest_compaction_wins_when_multiple_compactions_exist- create two compactions on active path
- verify replay starts after latest one
-
tree_navigation_pre_compaction_restores_precompaction_visibility- branch to node before compaction
- verify behavior follows that path’s boundary (may allow unchanged if valid there)
-
post_compaction_first_range_read_is_baseline_range- first range read after compaction cannot be
unchanged_rangefrom pre-compaction trust
- first range read after compaction cannot be
- non-anchor cannot bootstrap trust
- freshness selection (
seq) between range/full - refresh invalidation durability
Update sections:
- boundary selection: remove
firstKeptEntryIdtrust replay usage - formal state machine: add explicit compaction barrier rule
- test matrix: add “first post-compaction read is baseline” requirement
Update sections:
- replay boundary algorithm now strict
compaction+1 - edge cases and tests aligned to new policy
- remove references that imply
firstKeptEntryIdreplay trust path
-
Reduced token savings after compaction
- Expected tradeoff for stronger correctness/usability.
-
Existing tests tied to old boundary logic fail
- Update tests to new policy and preserve guarded transition tests.
-
Potential confusion with buildSessionContext using firstKept for LLM context
- Clarify: context reconstruction and readcache trust reconstruction now intentionally diverge by policy.
- Update replay boundary logic.
- Update failing tests first for strict boundary.
- Run targeted tests.
- Run full typecheck + test suite.
- Update spec + plan docs.
- Re-run full suite to ensure doc/code lockstep.
From repo root:
npm run typechecknpm test -- test/unit/replay.test.tsnpm test -- test/integration/compaction-boundary.test.tsnpm test -- test/integration/tree-navigation.test.tsnpm test -- test/integration/selective-range.test.tsnpm test -- test/integration/refresh-invalidation.test.tsnpm test -- test/integration/restart-resume.test.tsnpm test
- Replay boundary always starts at latest active
compaction+1. - Pre-compaction trust is not used post-compaction.
- First post-compaction read is baseline (
full/baseline_fallback) for requested scope. - Guarded trust-state transitions still pass all tests.
- Tree navigation behavior remains branch-correct.
- Docs (
IMPLEMENTATION_SPEC.md,IMPLEMENTATION_PLAN.md) match implemented policy exactly. - Full suite and typecheck pass.
Implement EVOLUTION_PLAN_2.md exactly: enforce strict compaction trust barrier (latest compaction + 1), update tests and docs accordingly, and stop only when the final acceptance matrix is fully green.