Skip to content

Commit c9ecb62

Browse files
committed
fix(session): keep the evidence index fingerprint on a no-op
1 parent bbe2997 commit c9ecb62

2 files changed

Lines changed: 58 additions & 2 deletions

File tree

‎src/session/optimized-context-store.test.ts‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,57 @@ describe("createOptimizedContextStore checkpoint", () => {
874874
expect(new TextDecoder().decode(blob)).toContain('{"id":"appended"}');
875875
});
876876

877+
test("an append during a no-op commit is not remembered as already published", async () => {
878+
const dir = tempDir();
879+
const store = await createOptimizedContextStore(dir);
880+
const indexPath = path.join(dir, "evidence-archive", "index.jsonl");
881+
fs.mkdirSync(path.dirname(indexPath));
882+
fs.writeFileSync(indexPath, '{"id":"seed"}\n');
883+
await store.writeTurns([turn("seed")]);
884+
await store.writeMetadata(EMPTY_CHECKPOINT_METADATA);
885+
const first = await store.commit({ message: "seed evidence index" });
886+
887+
const evidenceDir = path.join(dir, "evidence-archive");
888+
let indexStats = 0;
889+
let appended = false;
890+
const original = fs.promises.lstat;
891+
fs.promises.lstat = (async (target: fs.PathLike, opts?: fs.StatOptions) => {
892+
if (typeof target === "string" && target === indexPath) indexStats += 1;
893+
// The drift check stats the index. The later directory stat is
894+
// rememberPublishedTree, which used to restat the index and store a
895+
// fingerprint the no-op never committed.
896+
if (
897+
typeof target === "string" &&
898+
target === evidenceDir &&
899+
indexStats >= 1 &&
900+
!appended
901+
) {
902+
appended = true;
903+
fs.appendFileSync(indexPath, '{"id":"during-noop"}\n');
904+
}
905+
return original.call(fs.promises, target, opts);
906+
}) as typeof fs.promises.lstat;
907+
let noopHash = "";
908+
try {
909+
const noop = await store.commit({ message: "no writes" });
910+
noopHash = noop.hash;
911+
} finally {
912+
fs.promises.lstat = original;
913+
}
914+
expect(appended).toBe(true);
915+
expect(noopHash).toBe(first.hash);
916+
917+
const third = await store.commit({ message: "publish append from no-op window" });
918+
expect(third.hash).not.toBe(first.hash);
919+
const { blob } = await git.readBlob({
920+
fs,
921+
dir,
922+
oid: third.hash,
923+
filepath: "evidence-archive/index.jsonl",
924+
});
925+
expect(new TextDecoder().decode(blob)).toContain('{"id":"during-noop"}');
926+
});
927+
877928
test("an unchanged evidence index is not re-read and a no-op does not walk tool-output", async () => {
878929
const dir = tempDir();
879930
const store = await createOptimizedContextStore(dir);

‎src/session/optimized-context-store.ts‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,8 +1664,13 @@ export async function createSessionStores(
16641664
toolOutputFingerprint = tool;
16651665
evidenceFingerprint = evidence;
16661666
blobDirsObserved = true;
1667-
publishedEvidenceIndex = await statEvidenceIndex();
1668-
evidenceIndexObserved = true;
1667+
// A no-op already compared the index and found it unchanged. Restatting
1668+
// here would store a fingerprint for bytes appended after that check and
1669+
// before this return, and the next commit would treat them as published.
1670+
if (refreshBlobs || !evidenceIndexObserved) {
1671+
publishedEvidenceIndex = await statEvidenceIndex();
1672+
evidenceIndexObserved = true;
1673+
}
16691674
}
16701675
const ownerToken = opts?.ownerId ?? globalThis.crypto.randomUUID();
16711676
const explicitOwnerId = opts?.ownerId;

0 commit comments

Comments
 (0)