diff --git a/scripts/e2e/lib/codex-npm-plugin-live/assertions.mjs b/scripts/e2e/lib/codex-npm-plugin-live/assertions.mjs index f54bdf052b79..7ab9868e4616 100644 --- a/scripts/e2e/lib/codex-npm-plugin-live/assertions.mjs +++ b/scripts/e2e/lib/codex-npm-plugin-live/assertions.mjs @@ -654,21 +654,20 @@ function assertFollowthroughTranscript({ transcriptEvents, progressMarker, compl ); return text === progressMarker || text === completeMarker ? [{ ...entry, args, text }] : []; }); - const expected = [ - { text: progressMarker, final: undefined }, - { text: completeMarker, final: true }, - ]; + const expected = [progressMarker, completeMarker]; if ( markerCalls.length !== expected.length || markerCalls.some( (call, index) => - call.text !== expected[index].text || + call.text !== expected[index] || call.args.action !== "send" || - call.args.final !== expected[index].final, + (index === 0 + ? call.args.final !== undefined + : call.args.final !== undefined && call.args.final !== true), ) ) { throw new Error( - `expected exact message final controls ${JSON.stringify(expected)}, got ${JSON.stringify(markerCalls.map((call) => ({ text: call.text, action: call.args.action, final: call.args.final })))}`, + `expected ordered message sends with an optional final completion marker ${JSON.stringify(expected)}, got ${JSON.stringify(markerCalls.map((call) => ({ text: call.text, action: call.args.action, final: call.args.final })))}`, ); } const [progressCall, completeCall] = markerCalls; diff --git a/test/scripts/codex-install-assertions.test.ts b/test/scripts/codex-install-assertions.test.ts index 866522f99dc7..d43fbd2d8648 100644 --- a/test/scripts/codex-install-assertions.test.ts +++ b/test/scripts/codex-install-assertions.test.ts @@ -880,9 +880,22 @@ describe("Codex install helpers", () => { expect(result.stderr).toContain("expected all workspace work to settle before completion"); }); + it("accepts a terminal completion message without the optional final marker", () => { + const root = makeTempDir(tempDirs, "openclaw-codex-npm-followthrough-legacy-completion-"); + const fixture = createCodexNpmPluginLiveFollowthroughFixture({ + root, + messageFinals: [undefined, undefined], + }); + + const result = runCodexNpmPluginLiveFollowthroughAssertions(fixture); + + expect(result.status).toBe(0); + expect(result.stderr).toBe(""); + }); + it.each([ ["explicit progress", [false, true]], - ["missing completion", [undefined, undefined]], + ["nonfinal completion", [undefined, false]], ] as const)("rejects %s Codex message final controls", (_label, messageFinals) => { const root = makeTempDir(tempDirs, "openclaw-codex-npm-followthrough-final-controls-"); const fixture = createCodexNpmPluginLiveFollowthroughFixture({ @@ -893,7 +906,9 @@ describe("Codex install helpers", () => { const result = runCodexNpmPluginLiveFollowthroughAssertions(fixture); expect(result.status).not.toBe(0); - expect(result.stderr).toContain("expected exact message final controls"); + expect(result.stderr).toContain( + "expected ordered message sends with an optional final completion marker", + ); }); it("accepts the explicit frozen-target JSON session and sidecar binding contract", () => {