Browse Source

test: adapt checkpoint epoch-limit test to not rely on fixed re-announcement bug

The test 'starts a new checkpoint cache epoch at the snapshot limit' was
previously driving 20 turns by repeatedly calling board.updateStatus on the
SAME taskID (child-1), alternating between 'completed' and 'error' states.
This trick only worked because of the exact bug we just fixed — under the
old code, the same job's reminder got endlessly re-treated as 'new'.

Now that the fix correctly prevents re-announcement of the same job, the
test's mechanism breaks: once child-1's first completion is reconciled
(correctly, on the very next request), board.updateStatus's existing guard
(refuses updates once a job is reconciled) freezes that job's board entry.

Adapted the test to register and complete 20 DISTINCT background jobs
(child-0 through child-19), one reaching a terminal state per turn, so the
board's rendered text is legitimately different each turn for a real reason
(a new job appearing), not by exploiting the old re-announcement bug.

The test structure and assertions remain otherwise unchanged:
- Still checks boardSnapshotIDs(request) reaches length 20 at turn 19 with
  ':0'..':19' suffixes
- Still checks epoch-rollover behavior afterward with 2 more distinct jobs
  (child-20, child-21) for the post-limit turns
- resultSummary naming adjusted per-job (result- tied to child-)
Major Hayden 2 weeks ago
parent
commit
855c335cff
2 changed files with 28 additions and 12 deletions
  1. 0 1
      bun.lock
  2. 28 11
      src/hooks/task-session-manager/index.test.ts

+ 0 - 1
bun.lock

@@ -1,6 +1,5 @@
 {
   "lockfileVersion": 1,
-  "configVersion": 0,
   "workspaces": {
     "": {
       "name": "oh-my-opencode-slim",

+ 28 - 11
src/hooks/task-session-manager/index.test.ts

@@ -767,12 +767,6 @@ describe('task-session-manager hook', () => {
 
   test('starts a new checkpoint cache epoch at the snapshot limit', async () => {
     const board = new BackgroundJobBoard();
-    board.registerLaunch({
-      taskID: 'child-1',
-      parentSessionID: 'parent-1',
-      agent: 'explorer',
-      description: 'map hooks',
-    });
     const { hook } = createHook({
       backgroundJobBoard: board,
       strategy: 'checkpoint-compatible',
@@ -780,9 +774,18 @@ describe('task-session-manager hook', () => {
 
     const history: string[] = ['root'];
     for (let turn = 0; turn < 20; turn += 1) {
+      // Register a distinct job for each turn
+      const taskID = `child-${turn}`;
+      board.registerLaunch({
+        taskID,
+        parentSessionID: 'parent-1',
+        agent: 'explorer',
+        description: `map hooks turn ${turn}`,
+      });
+      // Complete the job immediately
       board.updateStatus({
-        taskID: 'child-1',
-        state: turn % 2 === 0 ? 'completed' : 'error',
+        taskID,
+        state: 'completed',
         resultSummary: `result-${turn}`,
       });
       history.push(`turn-${turn}`);
@@ -797,8 +800,15 @@ describe('task-session-manager hook', () => {
     }
 
     history.push('epoch-2-turn-1');
+    // Register and complete first job in epoch 2
+    board.registerLaunch({
+      taskID: 'child-20',
+      parentSessionID: 'parent-1',
+      agent: 'explorer',
+      description: 'map hooks epoch 2 turn 1',
+    });
     board.updateStatus({
-      taskID: 'child-1',
+      taskID: 'child-20',
       state: 'completed',
       resultSummary: 'epoch-2-result-1',
     });
@@ -808,9 +818,16 @@ describe('task-session-manager hook', () => {
     expect(boardSnapshotIDs(epochStart)[0]).toEndWith(':20');
 
     history.push('epoch-2-turn-2');
+    // Register and complete second job in epoch 2
+    board.registerLaunch({
+      taskID: 'child-21',
+      parentSessionID: 'parent-1',
+      agent: 'explorer',
+      description: 'map hooks epoch 2 turn 2',
+    });
     board.updateStatus({
-      taskID: 'child-1',
-      state: 'error',
+      taskID: 'child-21',
+      state: 'completed',
       resultSummary: 'epoch-2-result-2',
     });
     const secondEpochRequest = createAnchoredMessages('parent-1', history);