Skip to content

fix(temporal): raise Glitter synthesis token cap and retry on truncation - #1995

Open
shepherdjerred wants to merge 2 commits into
mainfrom
fix/glitter-synthesis-truncation
Open

fix(temporal): raise Glitter synthesis token cap and retry on truncation#1995
shepherdjerred wants to merge 2 commits into
mainfrom
fix/glitter-synthesis-truncation

Conversation

@shepherdjerred

@shepherdjerred shepherdjerred commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Why

With the extraction fixes (#1982 repair-loop, #1988 sanitize) deployed, a pinned
Glitter generation clears all extraction cleanly (zero citation errors) and
now dies in synthesis with LengthFinishReasonError (finish_reason: length
→ unparseable structured output).

LLM traces (llm-archive) confirm the cause: gpt-5.6-sol synthesis runs
80–86k input tokens, 4.7–7.6k output, at reasoning_effort: "medium". Its
hidden reasoning tokens + output share the 15k max_completion_tokens cap,
and one attempt crossed it. The same pinned snapshot + code succeeded on
2026-07-29
, so this is sol model drift since the cache was populated.

What

  • Raise SYNTHESIS_MAX_OUTPUT_TOKENS 15k → 28k (comfortable headroom over the
    observed ~15k reasoning+output).
  • Retry a synthesis call once at a 40k ceiling on LengthFinishReasonError
    (imported from openai/core/error).
  • The preflight estimator and budget.authorizeUncachedCall use the 40k ceiling
    as the honest worst-case output bound.
  • Test: a synthesis call that truncates at 28k succeeds on the 40k retry and the
    run completes.

Probe note

This is deliberately a probe (per plan 2026-07-29_glitter-style-card-v2.md).
The traces also show glitter-style-synthesis-repair calls — synthesis output is
also failing finalizeStyleSynthesis (the exact 20-quote/30-sample/18-example
contract) and going into repair loops. If, after this fix, synthesis converges
within finalize validation, Phase 1 completes. If it still fails the exact-count
contract, that confirms a deeper sol re-tune is needed (contract counts can't be
sanitized by dropping, unlike extraction evidence).

Testing

  • typecheck + lint clean; 10/10 generate tests, glitter cache/workflow/budget +
    workflow-bundle smoke all pass.

🤖 Generated with Claude Code

A pinned Glitter generation now clears all extraction (the sanitize fix works)
but dies in synthesis with LengthFinishReasonError: gpt-5.6-sol runs at
reasoning_effort "medium", so its hidden reasoning tokens plus the large style
synthesis output crossed the 15k max_completion_tokens cap (LLM traces show
80-86k input / 4.7-7.6k output). The same snapshot+code passed on 2026-07-29, so
this is sol model drift since the cache was populated.

Raise SYNTHESIS_MAX_OUTPUT_TOKENS 15k->28k (headroom over the observed ~15k) and
retry a synthesis call once at a 40k ceiling on LengthFinishReasonError. The
preflight estimator and budget authorization use the 40k ceiling as the honest
worst case. Adds a test that a synthesis call truncating at 28k succeeds on the
40k retry and the run completes.

Probe: if synthesis then converges within finalizeStyleSynthesis, Phase 1
completes; the traces also show synthesis-repair loops (output failing the exact
20/30/18 contract), which would confirm a deeper sol re-tune is needed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WXxxmDmqcQas3cYqqE2nuU
@shepherdjerred
shepherdjerred marked this pull request as ready for review August 4, 2026 05:37

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2fe4566eca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +395 to +404
const completion = await (async () => {
try {
return await parseGlitterCompletion(callSite, params);
} catch (error: unknown) {
if (!(error instanceof LengthFinishReasonError)) {
throw error;
}
return await parseGlitterCompletion(callSite, {
...params,
max_completion_tokens: SYNTHESIS_TRUNCATION_RETRY_MAX_OUTPUT_TOKENS,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Account for the truncated attempt before retrying

When the 28k request ends with LengthFinishReasonError, that completed API request has already consumed billable input/reasoning/output tokens, but the catch immediately issues the 40k request without persisting or recording the first request's usage. If the retry succeeds, the artifact and GenerationBudget receive only the retry's usage; if it also fails, no spend receipt is created and the workflow's second activity attempt can pay for both calls again. The preflight estimate and authorization likewise reserve only one 40k call rather than the 28k call plus its retry, so the advertised hard run budget and reported actual spend can be exceeded precisely in the truncation scenario this change handles.

Useful? React with 👍 / 👎.

Comment on lines +269 to +274
- 2026-08-04 (truncation fix): `fix/glitter-synthesis-truncation` raises
`SYNTHESIS_MAX_OUTPUT_TOKENS` 15k→28k (comfortable headroom over the observed
~15k) and retries a synthesis call **once** at a 40k ceiling on
`LengthFinishReasonError` (imported from `openai/core/error`). The preflight
estimator + budget authorize now use the 40k ceiling as the honest worst case.
Test: a synthesis call that truncates at 28k succeeds on the 40k retry and the

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Add the required August session summary

This adds the 2026-08-04 implementation work to the plan, but the document still proceeds directly into the old ## Session Log — 2026-07-29 section and never records an August Done / Remaining / Caveats summary. Append the required 2026-08-04 session log so the unfinished probe and handoff state are captured in the repository's mandated format.

AGENTS.md reference: AGENTS.md:L125-L142

Useful? React with 👍 / 👎.

PR #1992 shipped @shepherdjerred/pr-fleet-web
(packages/pr-fleet-controller/packages/web) without adding it to
scripts/ci-test-manifest.json, so the `CI reporting manifest` test
(scripts/ci-reporting.test.ts) fails and `bun run verify` is red on main. Add the
workspace to the manifest and wire its `test:ci`/`test:report` scripts to the
shared runner (matching the sibling pr-fleet-controller). Its tests already pass
once the workspace is linked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WXxxmDmqcQas3cYqqE2nuU
@shepherdjerred

Copy link
Copy Markdown
Owner Author

Added a second commit (2dcdf1505) fixing an unrelated main breakage: PR #1992 shipped @shepherdjerred/pr-fleet-web without adding it to scripts/ci-test-manifest.json, so bun run verify (the CI reporting manifest test) is red on main and blocks every PR. This commit covers the workspace in the manifest and wires its test:ci/test:report scripts to the shared runner (matching pr-fleet-controller); its tests pass once linked. Needed here to get this PR's verify green.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2dcdf15053

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +402 to +405
return await parseGlitterCompletion(callSite, {
...params,
max_completion_tokens: SYNTHESIS_TRUNCATION_RETRY_MAX_OUTPUT_TOKENS,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include the retry ceiling in the artifact identity

When the 28k call truncates, this stores the 40k completion under a request hash that declares only maxCompletionTokens: 28_000. Consequently the reported artifact identity does not describe the request that produced it, and changing the retry ceiling later will continue reusing this stale artifact because the cache key will remain unchanged. Include the fallback policy/ceiling in the hashed request, or cache the retry as a distinct request.

Useful? React with 👍 / 👎.

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.

1 participant