From dfb4e324d239b0f6ce7538f806e7d65d656cdce6 Mon Sep 17 00:00:00 2001 From: now-ing <956750945@qq.com> Date: Fri, 4 Sep 2026 11:59:11 +0800 Subject: [PATCH] test(codex-plugin): accept both convergences of the Stop/SessionEnd marker race (#4668) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The race test asserted state.ovSessionId === null after running a Stop worker and a session-end worker concurrently, but the system has two legal outcomes. auto-capture clears end markers older than its own start (resume semantics), so when the SessionEnd parent writes its marker just before the Stop hook starts — the exit race this test spawns — the session-end worker finds no marker under the lock and exits superseded, leaving the Stop worker's live session for the SessionStart sweep's idle-TTL pass instead of an inline commit. Assert the real invariants instead: exactly-once sends, cursor consistency, only the derived cx-* session may stay live, and no stale end marker survives either convergence. Co-authored-by: mac --- .../scripts/session-end.test.mjs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/examples/codex-memory-plugin/scripts/session-end.test.mjs b/examples/codex-memory-plugin/scripts/session-end.test.mjs index 8e3623c14..ba18976a3 100644 --- a/examples/codex-memory-plugin/scripts/session-end.test.mjs +++ b/examples/codex-memory-plugin/scripts/session-end.test.mjs @@ -419,7 +419,21 @@ test("a concurrent Stop worker and session-end worker never double-send a turn", assert.equal(sentMessages(calls).length, 6, "each transcript turn must be sent exactly once"); const state = await readState(stateDir, "s8"); assert.equal(state.capturedTurnCount, 6); - assert.equal(state.ovSessionId, null); + // The two hooks race over the end marker. auto-capture clears markers + // older than its own start (resume semantics), so when the SessionEnd + // parent writes its marker just before the Stop hook starts — the exit + // race this test spawns — the marker is gone by the time the session-end + // worker takes the lock and it exits as superseded. The system then + // settles on the Stop worker's terminal state: the live session stays + // uncommitted for the SessionStart sweep's idle-TTL pass instead of being + // committed inline. Both convergences are correct as long as no turn is + // double-sent and no stale marker survives, so accept either one. + if (state.ovSessionId !== null) { + assert.equal(state.ovSessionId, "cx-s8", + "only the derived cx-s8 session may remain live"); + } + assert.equal(await endedMarkerExists(stateDir, "s8"), false, + "a converged run must not leave a stale end marker"); } finally { await rm(stateDir, { recursive: true, force: true }); }