test: A4 compaction phase 4 — plan-level test hardening (plan #951, source #552) - #956
Conversation
…on rows Plan #951 (source #552, parent #947) test hardening: - sessionStore: RedisSessionStore.upsertEnvelope copy-forwards compactionPointer on a host flatten omit (durable, no volatility); sibling mm write does not disturb the carrier; read-back round-trips. Closes the gap where only the Memory store path was proven. - turnLoop: summarize_failed on the compact path fail-opens — the turn completes from the un-compacted projection and NO fold carries a fabricated compactionCheckpoint (never a next-turn prefer-checkpoint seed). Gates: typecheck clean; vitest 177 files / 3527 tests green; npm run build green (cloud workspace).
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
btipling
left a comment
There was a problem hiding this comment.
Adversarial review — PR #956
Verdict: PASS WITH NOTES
Repo: btipling/invincible
Scope: main ← plan/a4-compaction-p4-test-hardening (fdc62ca) · 2 files · test-only hardening (plan #951)
Lenses run: L1, L6 (skip: L2 product-security — test-only, no API/secret/runner reach; DI/cost gate ran: injected fakeClient, no PGlite/createDbConnection; L3 no UI/Wasm; L4 no CI/artifact; L5 no new runtime loop; L7 no config/host bind; L8 comments are load-bearing; L9 no UI)
AGENTS.md read: yes (tests-direct-with-vitest; no product-code / cap / docs in this phase)
Existing Phase-2/3 rows the PR body cites as already proving parent matrix 3/6/8 (route.test.ts 2a/2b/2e/2h, loop fail-open/reconstruct) are present on this head. Confused-deputy 2e is unbound-cp → legacy with no blob read; 2a is checkpoint-preferred seed with honesty + re-pair. This pass attacks the two new rows.
Findings
| Sev | Lens | Finding | Break scenario | Refutation attempt | Confidence |
|---|---|---|---|---|---|
| Minor | L1+L6 | RedisSessionStore.upsertEnvelope copy-forward row (lib/sessions/sessionStore.test.ts) locks host-omit + sibling mm + read-back, but not “intentional worker-authored value still wins” — the other half of the plan #951 / #949 copy-forward lock, which the Memory row immediately above does assert (t_cp_keep → omit keep → t_cp_new wins). Redis upsertEnvelope is a duplicated helper nest, not a shared function; wrap-order meta: { ...copyForward(input, existing), ...existing } keeps omit-copy-forward green and silently loses the next compaction’s pointer. |
1. Production Redis store. 2. Worker writes compactionPointer: t_cp_s_0001. 3. Host flatten omits the key (already asserted). 4. Next compact persist PUTs compactionPointer: t_cp_s_0002. 5. If Redis applies stored-meta last, envelope stays t_cp_s_0001. 6. Next turn prefer-checkpoint seeds the stale Blob. This test still passes. |
“Memory + copyForwardCompactionPointer unit already prove explicit-wins.” Those do not execute redisSessionStore.ts. This PR exists because Memory-only left a wrap-order hole on the store Production resolves. “Identical helper nest today.” Today, yes — the row does not lock it, so a Redis-only edit is free to invert precedence. |
high |
| Nit | L6 | New summarize_failed fail-open row (lib/workflows/turnLoop.test.ts) asserts ckFolds length 0. That is true if persist is never called with a fold at all ([].filter is empty). The wall_clock row on this file already does expect(foldCall).toBeDefined() before the undefined-checkpoint check. status === 'completed' is a proxy, not a fold lock. |
A future persist short-circuit that skips fold on fail-open complete still reports completed + ckFolds.length === 0. The “no fabricated checkpoint” claim is then unproven. |
“wiredDeps persist always runs on complete.” Today it does. The assertion still does not require a fold object, unlike the wall_clock sibling. | medium |
Residual risk
Prefix-clip / reconstruct fail-open paths already lock compactionCheckpoint undefined on those seeds; this new row covers summarize_failed + priorMessages (the test-only seed). Production compact omits priorMessages — compactedCheckpoint is a single writer, so the fold contract still holds, but this row does not re-prove reconstruct-path folds. Unbound compactionPointer + bound modelMessagesPointer composition is implied by 2e+2d, not a dedicated row. No live Redis/Workflows/Gateway in this review.
Merge guidance
- PASS WITH NOTES: safe to merge from this attack; the Minor is cheap and should land on this PR (Redis explicit-wins + read-back).
- Do not change any existing cap. Do not add product code. Phase 5 / #952 still owns living docs.
- Redis row: after host-omit / sibling mm, a later
upsertEnvelopewithcompactionPointer: t_cp_s_0002must win,modelMessagesPointermust copy-forward,readEnvelopemust round-trip the new id. - Fail-open row (optional Nit):
expect(persistSpy.mock.calls.some((c) => c[0].fold !== undefined)).toBe(true)before the no-checkpoint filter.
What was not attacked
Live Redis, prod Gateway, Workflows step isolate, DO runner, Wasm/DOM paint, npm run build in this workspace, Phase 5 docs, whether fakeClient JSON-round-trips the real node-redis adapter (pre-existing seam).
…istence Address PASS WITH NOTES on PR #956 (plan #951): - RedisSessionStore copy-forward row now locks worker-authored compactionPointer wins (t_cp_s_0002) and copy-forwards the sibling modelMessagesPointer; read-back round-trips both. Omit-only could not catch stored-meta-last wrap-order on the duplicated Redis nest. - summarize_failed fail-open asserts a persist fold actually ran before the no-compactionCheckpoint filter (vacuity lock). Focused: sessionStore + turnLoop 222 tests green. Refs #951. Refs #947.
Adversarial #956 follow-up 1 (landed on this PR)Posted the PASS WITH NOTES review (on
Focused: |
Plan
Implements plan #951 — HANDOFF-READY (source #552 A4 compaction engine, parent #947 phase 4). Test-only hardening: no product code, no caps changed, no Production mutate.
What shipped
Coverage map vs the parent testing matrix (Phases 1–3 already prove rows 2a–2h, confused-deputy, planted/stale, pin/clip, checkpoint writer, seam fail-closed). This PR closes the two composition-level gaps the plan locks:
lib/sessions/sessionStore.test.ts) —plan #951row:RedisSessionStore.upsertEnvelopecopy-forwardscompactionPointerfrom LWW existing when a host flatten omit arrives (durable, no volatility); a siblingmodelMessagesPointerwrite does not disturb the carrier; read-back round-trips. Closes the gap where only the Memory store path was proven — Redis is what Production resolves through.lib/workflows/turnLoop.test.ts) —plan #951row:summarize_failedon the compact path fail-opens; the turn completes from the un-compacted projection AND no fold anywhere in the run carries a fabricatedcompactionCheckpoint(a partial summary must never become the next turn's prefer-checkpoint seed).Testing matrix (plan #951 rows 5–8 + row 3 re-proof)
#949) + new Redis composition row[summaryRow, ...re-paired tail]Gates (required, run in this cloud workspace)
npm run typecheck— cleannpm test— 177 files / 3527 tests green (di-gate + drizzle-journal-gate pass)npm run build— green (pre-existing jose/Edge-Runtime warnings only)vitest run lib/sessions/sessionStore.test.ts lib/workflows/turnLoop.test.ts— 222 tests greennpm install+npm run fetch-harnesswere required in the fresh sandbox checkout (stalepublic/harness/harness.wasmcaused 13 local wasm-int failures; fresh artifact resolves all).Not in scope
Living docs (Phase 5 / #952), caps (none changed), Production mutate (none).
Closes #951 (phase acceptance pending adversarial review; no merge in this step).