Skip to content

fix(summarizer): set excludeTurns on ephemeral Codex thread/fork - #166

Merged
obra merged 1 commit into
obra:mainfrom
ada-sen:fix/158-summarizer-exclude-turns
Sep 9, 2026
Merged

obra merged 1 commit into
obra:mainfrom
ada-sen:fix/158-summarizer-exclude-turns

Conversation

@ada-sen

@ada-sen ada-sen commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Summary

thread/fork rejects the summarizer's ephemeral fork for any paginated (i.e. reasonably large) Codex thread on codex-cli 0.150+:

thread/fork failed: {"code":-32600,"message":"ephemeral paginated thread/fork requires `excludeTurns: true`"}

summarizeConversation() catches this and silently falls back to transcript-text summarization, so the Codex-native path stops being used for exactly the conversations it matters most for: the long ones. The only trace is a Codex summarizer unavailable, falling back to transcript text: ... log line — nothing surfaces as an error to the user.

Root cause

The ephemeral thread/fork request in summarizeConversation() didn't set excludeTurns: true. Newer codex-cli requires it for paginated (large) threads. The flag governs pagination of the fork response, not the fork's context — the forked thread still carries full session history with the flag set, so summaries produced after this change remain accurate.

Fix

Add excludeTurns: true to the ephemeral fork params in src/summarizer.ts:

         const fork = await send('thread/fork', {
           threadId: command.sessionId,
           ephemeral: true,
+          excludeTurns: true,
           sandbox: 'read-only',
           approvalPolicy: 'never',
           ...(command.model ? { model: command.model } : {}),
         });

dist/summarizer.js regenerated via npm run build and committed alongside src/summarizer.ts.

Test plan

  • Extended the existing thread/fork mock assertion in test/summarizer-options.test.ts to require excludeTurns === true, matching the existing ephemeral/sandbox checks
  • npx vitest run test/summarizer-options.test.ts — 29/29 pass
  • npm test (full suite) — 348/348 pass, 62 test files, no regressions
  • npm run build — clean

Fixes #158.

…a#158)

codex-cli 0.150 rejects an ephemeral thread/fork against a paginated
(i.e. reasonably large) thread with:

  thread/fork failed: {"code":-32600,"message":"ephemeral paginated
  thread/fork requires `excludeTurns: true`"}

summarizeConversation() catches this and silently falls back to
transcript-text summarization, so the Codex-native path stops being
used for exactly the conversations it matters most for: the long
ones. The only trace is a 'Codex summarizer unavailable, falling back
to transcript text' log line.

excludeTurns governs pagination of the fork response, not the fork's
context/semantics — the forked thread still carries full session
history with the flag set, so summaries after this change remain
accurate.

Fixes obra#158.

@obra obra left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified rather than taken on trust. Clean — merging.

The test genuinely catches the bug. Removed excludeTurns: true from src/summarizer.ts (i.e. reinstated the original defect) and the fork test went red on exactly the right assertion; restored, green again. That's the property that matters, and it isn't automatic — the assertion had to be added inside the fake server's thread/fork handler to see it.

dist and src agree, and a fresh npm run build produces no diff against the committed dist/summarizer.js, so the built artifact isn't carrying anything the source doesn't.

Full suite: 62 files, 348 tests, zero failures.

Why this is worth landing beyond the one flag

The failure mode is the interesting part: summarizeConversation() catches the -32600 and silently falls back to transcript-text summarization. So the Codex-native path quietly stopped being used for exactly the conversations it matters most for — the long ones — with the only trace a log line nobody reads. A degradation that announces itself as success is worse than a crash, and this repo has a few of those.

One thing to note for later, not blocking

The fix is right and the reasoning in the description is right (excludeTurns governs pagination of the fork response, not the fork's context). But nothing in the repo pins the codex-cli version this behaviour depends on, so if a future codex-cli changes the requirement again, the same silent fallback returns and the same log line is the only signal. Worth considering whether that fallback should be loud, or at least counted, rather than swallowed. Separate change.

Also worth knowing: this repo now has CI (landed today — build, typecheck, tests across Node 22 and 24, and it runs on fork PRs). Your future PRs here will get real checks. This one predates it and shows none; I ran the equivalent locally.

@obra
obra marked this pull request as ready for review September 9, 2026 19:15
@obra
obra merged commit 28f0933 into obra:main Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Codex summarizer: thread/fork 400s on large (paginated) threads — codex-cli 0.150 requires excludeTurns: true

2 participants