From 271531543816b9267e5c49328c9f78001fdb1893 Mon Sep 17 00:00:00 2001 From: Affaan Mustafa Date: Thu, 30 Apr 2026 11:53:29 -0400 Subject: [PATCH] fix: avoid loop-status index snapshot collision --- scripts/loop-status.js | 2 +- tests/scripts/loop-status.test.js | 37 +++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/scripts/loop-status.js b/scripts/loop-status.js index d6f32d5c..cb728da6 100644 --- a/scripts/loop-status.js +++ b/scripts/loop-status.js @@ -658,7 +658,7 @@ function writeStatusSnapshots(payload, writeDir) { const outputDir = path.resolve(writeDir); fs.mkdirSync(outputDir, { recursive: true }); - const usedNames = new Set(); + const usedNames = new Set(['index.json']); const sessions = payload.sessions.map(session => { const snapshotPath = getSnapshotPath(outputDir, session, usedNames); atomicWriteJson(snapshotPath, { diff --git a/tests/scripts/loop-status.test.js b/tests/scripts/loop-status.test.js index 76735978..a57330e4 100644 --- a/tests/scripts/loop-status.test.js +++ b/tests/scripts/loop-status.test.js @@ -594,6 +594,43 @@ function runTests() { } })) passed++; else failed++; + if (test('keeps index.json reserved when session id sanitizes to index', () => { + const homeDir = createTempHome(); + const snapshotDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-loop-status-index-collision-')); + + try { + writeTranscript(homeDir, '-Users-affoon-project-index-collision', 'index.jsonl', [ + assistantMessage('2026-04-30T09:55:00.000Z', 'index', 'Loop checkpoint.'), + ]); + + const result = run([ + '--home', + homeDir, + '--now', + NOW, + '--json', + '--write-dir', + snapshotDir, + ]); + + assert.strictEqual(result.code, 0, result.stderr); + + const indexPath = path.join(snapshotDir, 'index.json'); + const indexPayload = JSON.parse(fs.readFileSync(indexPath, 'utf8')); + assert.strictEqual(indexPayload.schemaVersion, 'ecc.loop-status.index.v1'); + assert.strictEqual(indexPayload.sessions.length, 1); + assert.strictEqual(indexPayload.sessions[0].sessionId, 'index'); + assert.notStrictEqual(indexPayload.sessions[0].snapshotPath, indexPath); + + const snapshotPayload = JSON.parse(fs.readFileSync(indexPayload.sessions[0].snapshotPath, 'utf8')); + assert.strictEqual(snapshotPayload.schemaVersion, 'ecc.loop-status.session.v1'); + assert.strictEqual(snapshotPayload.session.sessionId, 'index'); + } finally { + fs.rmSync(homeDir, { recursive: true, force: true }); + fs.rmSync(snapshotDir, { recursive: true, force: true }); + } + })) passed++; else failed++; + if (test('write-dir failures do not suppress normal stdout', () => { const homeDir = createTempHome();