Skip to content

Commit 592049e

Browse files
committed
test(session): pin verify facts in the fat handoff file
1 parent 91adeb5 commit 592049e

1 file changed

Lines changed: 23 additions & 7 deletions

File tree

‎src/session/compaction-verify.test.ts‎

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import os from "node:os";
44
import path from "node:path";
55
import { createPruningCompactor } from "./compactor.js";
66
import { condenseTurns } from "./summarizer.js";
7+
import { HANDOFF_LATEST_KEY } from "./compaction-handoff.js";
78
import {
89
createCompactionArchive,
910
wrapCompactorWithCompletenessGate,
@@ -47,6 +48,14 @@ function allText(turns: ConversationTurn[]): string {
4748
.join("\n");
4849
}
4950

51+
function handoffFileText(result: {
52+
blobs?: { key: string; bytes: Uint8Array }[];
53+
}): string {
54+
const blob = result.blobs?.find((b) => b.key === HANDOFF_LATEST_KEY);
55+
if (blob === undefined) return "";
56+
return new TextDecoder().decode(blob.bytes);
57+
}
58+
5059
// A dropped region with a standing goal, an exact path, a verification
5160
// command, and an unresolved failure.
5261
function droppedTurns(): ConversationTurn[] {
@@ -667,10 +676,12 @@ describe("pruning compactor verify pass", () => {
667676

668677
describe("continuation facts survive many folds", () => {
669678
test("verify signal holds after five lossy folds", async () => {
679+
let priorFile: string | undefined;
670680
const compactor = createPruningCompactor({
671681
keepRecentTurns: 2,
672682
summaryMaxChars: 4000,
673683
summarize: async () => "Work continues. Next: fix tests.",
684+
readPriorHandoff: async () => priorFile,
674685
});
675686
let turns: ConversationTurn[] = [
676687
...droppedTurns(),
@@ -683,17 +694,18 @@ describe("continuation facts survive many folds", () => {
683694
expect(result.record.reason).not.toBe(
684695
"verify failed — keeping prior context",
685696
);
697+
const file = handoffFileText(result);
698+
// The thin live spine does not carry next-action / blocker text; the
699+
// fat handoff file does. Verify repair writes those into the narrative
700+
// that the file persists, and later folds re-read it.
701+
expect(file).toContain("refresh assertion");
702+
priorFile = file;
686703
turns = [
687704
...result.output,
688705
textTurn("user", `follow-up ${fold}`),
689706
textTurn("assistant", `progress note ${fold}`),
690707
];
691708
}
692-
const text = allText(turns);
693-
// The initiating ask is anchored out of summarizedTurns, so "opaque tokens"
694-
// / "auth.ts" survive from that turn and do not prove the verify pass.
695-
// "refresh assertion" is only in dropped tool errors / next action.
696-
expect(text).toContain("refresh assertion");
697709
});
698710
});
699711

@@ -751,10 +763,12 @@ describe("completeness gate plus verify repair", () => {
751763

752764
test("two lossy folds through the gate keep facts via adopted handoffs", async () => {
753765
const archive = memoryArchive();
766+
let priorFile: string | undefined;
754767
const inner = createPruningCompactor({
755768
keepRecentTurns: 2,
756769
summaryMaxChars: 4000,
757770
summarize: async () => "Work continues. Next: fix tests.",
771+
readPriorHandoff: async () => priorFile,
758772
});
759773
const wrapped = wrapCompactorWithCompletenessGate(inner, archive);
760774
let turns: ConversationTurn[] = [
@@ -774,7 +788,9 @@ describe("completeness gate plus verify repair", () => {
774788
(occurrence) => occurrence.provenance === "compaction-handoff",
775789
);
776790
expect(handoffs.length).toBeGreaterThan(0);
777-
expect(allText(first.output)).toContain("refresh assertion");
791+
const firstFile = handoffFileText(first);
792+
expect(firstFile).toContain("refresh assertion");
793+
priorFile = firstFile;
778794

779795
const followUp = [
780796
textTurn("user", "follow-up after first fold"),
@@ -788,7 +804,7 @@ describe("completeness gate plus verify repair", () => {
788804
expect(second.record.reason).not.toBe(
789805
"verify failed — keeping prior context",
790806
);
791-
expect(allText(second.output)).toContain("refresh assertion");
807+
expect(handoffFileText(second)).toContain("refresh assertion");
792808
});
793809
});
794810

0 commit comments

Comments
 (0)