From edfa411684ef9e73f74e3c3025f6989c6271fb76 Mon Sep 17 00:00:00 2001 From: Gujiassh Date: Thu, 12 Mar 2026 19:58:57 +0900 Subject: [PATCH] fix(session-manager): match todo filenames exactly Stop sibling session IDs from colliding in stable JSON storage by requiring an exact todo filename match instead of a substring filter. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus --- src/tools/session-manager/storage.test.ts | 20 ++++++++++++++++++++ src/tools/session-manager/storage.ts | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/tools/session-manager/storage.test.ts b/src/tools/session-manager/storage.test.ts index 447362719..f4e3c1cb0 100644 --- a/src/tools/session-manager/storage.test.ts +++ b/src/tools/session-manager/storage.test.ts @@ -168,6 +168,26 @@ describe("session-manager storage", () => { expect(todos).toEqual([]) }) + test("readSessionTodos only reads the exact session todo file", async () => { + // given + writeFileSync( + join(TEST_TODO_DIR, "ses_1.json"), + JSON.stringify([{ id: "todo_exact", content: "Exact match", status: "pending" }]), + ) + writeFileSync( + join(TEST_TODO_DIR, "ses_10.json"), + JSON.stringify([{ id: "todo_collision", content: "Wrong session", status: "completed" }]), + ) + + // when + const todos = await readSessionTodos("ses_1") + + // then + expect(todos).toHaveLength(1) + expect(todos[0].id).toBe("todo_exact") + expect(todos[0].content).toBe("Exact match") + }) + test("getSessionInfo returns null for non-existent session", async () => { // when const info = await getSessionInfo("ses_nonexistent") diff --git a/src/tools/session-manager/storage.ts b/src/tools/session-manager/storage.ts index 59fda3ffc..2455cd29e 100644 --- a/src/tools/session-manager/storage.ts +++ b/src/tools/session-manager/storage.ts @@ -277,7 +277,7 @@ export async function readSessionTodos(sessionID: string): Promise { try { const allFiles = await readdir(TODO_DIR) - const todoFiles = allFiles.filter((f) => f.includes(sessionID) && f.endsWith(".json")) + const todoFiles = allFiles.filter((f) => f === `${sessionID}.json`) for (const file of todoFiles) { try {