Repository navigation
fix: send the Agent SDK's initialize request to every relaunched stream-json child - #330
Merged
Merged
Conversation
…am-json child The Agent SDK sends initialize once per query. It carries the appended system prompt, the hook callback ids, the SDK MCP servers, and the other init settings. The stdin relay forwarded it to the first child only, so a move that resumed the session with --resume relaunched Claude Code without those settings. The relay now keeps the latest line of each control request in REPLAYED_REQUESTS for the life of the session and sends those lines to every relaunched child ahead of the resume prompt and the queued input. The --session-id replay keeps the other lines the killed child received. Closes #322
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…ume prompt A REPLAYED_REQUESTS line that arrives while no child is attached now updates the saved state instead of the queue, so the relaunched child receives it before the resume prompt and the turn runs under the latest model, permission mode, and thinking budget.
Owner
Author
|
Adversarial review (OpenCode on MiMo v2.6 Pro, because the Codex review plugin is not installed on the host) returned three findings:
|
anaclumos
added a commit
that referenced
this pull request
Oct 6, 2026
Carry #330 into the restructured architecture page: the harness-session paragraph names the setup requests the supervisor sends each relaunched process before the first prompt.
This was referenced Oct 6, 2026
anaclumos
added a commit
that referenced
this pull request
Oct 6, 2026
Closes #311. The docs site now carries its flows and structures as diagrams, tables, step lists, and file trees, and its long paragraphs are split into short sections. ## What changed - **Mermaid diagrams.** A fenced `mermaid` block in MDX renders as a diagram, client side, with the `mermaid` package (12.1.0), in the `neutral` theme in light mode and the `dark` theme in dark mode. A diagram that fails to parse falls back to its source in a code block. - **Fumadocs components.** `Steps`, `Files`, and `Tabs` are registered for MDX. - **Pages.** `index`, `architecture`, `switching`, `credentials`, `state-directory`, `hub`, `codex`, `pi`, `quickstart`, `configuration`, and `distribution` get 44 diagrams in total, plus tables for enumerations (fields, kinds, cases, conditions to outcomes), `###` subsections that split the long paragraphs, a `Files` tree of the state directory, and `Steps` for the setup procedures. ## Decisions - **Every claim stays.** The docs rule is to preserve every claim when rewriting, so a sentence was deleted only when a diagram, a table, or another sentence on the same page states all of its content. Each page was checked sentence by sentence against its version on main. The pages are therefore not much shorter in characters; the gain is that no paragraph runs past about four sentences and each flow has a picture. - **A local remark plugin instead of `remarkMdxMermaid`.** `fumadocs-core` ships `remarkMdxMermaid`, but in the processed Markdown that `llms-full.txt`, each page's `content.md`, and the **Copy Markdown** button serve, its `<Mermaid>` element carries the diagram in a `chart` attribute with every double quote escaped as `"`, which no Markdown viewer renders as a diagram. `docs/lib/remark-mermaid.ts` emits the same element and sets `_stringify.text` to the original fenced `mermaid` block, so the exported Markdown carries each diagram's source unchanged. `_stringify.node` would not work: the Fumadocs stringifier keeps the JSX handler after it swaps the node, so each diagram exports as `<></>`. - **Pages left as they are.** `commands`, `platforms`, `statusline`, `troubleshooting`, `limitations`, `terms`, `switching-profile`, and `status-only-pools` are already tables, lists, or short prose. - **Changes from main carried over.** The sentence changes of #321 (`configuration`, `switching`), #324 and #330 (`architecture`), #328 (`pi`, `quickstart`), #331 (`switching`), and #334 (`configuration`, `hub`) are restated in the restructured text. For #328, the `init` diagram on `quickstart` also names the PATH line on a second `init`. For #331, the new **Banked resets** section keeps every sentence, is split into subsections, and gets a diagram of the spend decision and one of the claim. For #334, the buffered usage quota text is a **Buffered usage quota** section on `configuration` and a subsection under the `api-call` requests on `hub`, with its sentences split into a list. - **Stale claims found during the review** were filed separately as #327 and fixed in #328, not here, because this change restates the pages without changing what they claim. ## Verification - Every diagram of every changed page renders with mermaid 12.1.0 in a headless browser in both themes, with no parse failure and a natural width of at most about 950px against the 825px column, and each rendering was looked at for legibility and overlap. - The processed Markdown keeps all 44 diagrams as fenced `mermaid` blocks with no empty fragment: `llms-full.txt` holds 44, and the `content.md` routes of `architecture`, `quickstart`, `credentials`, and `switching` hold 10, 1, 7, and 7, read from a local dev server. - A scripted check confirms that every `##` heading and every link of the old pages is still present and that every cross-page and in-page anchor resolves. - No page has an em dash, an en dash, or a curly quote. - The Vercel Preview deployment of the head commit is the build and content check. The project names no end-to-end target, and the diff changes only the docs app.
This was referenced Oct 16, 2026
anaclumos
added a commit
that referenced
this pull request
Oct 16, 2026
…launched child (#449) Closes #447. Author model: claudeAgent/claude-fable-5-1 ## Problem T3 Code 0.1.0 registers its `t3-code` MCP server through the Agent SDK's runtime control request `mcp_set_servers` over stdin (pingdotgg/t3code#17898, merged 2026-10-10), not through `--mcp-config`: every launch of a T3 session, T3's own and the supervisor's moves alike, carries the same argv with no MCP flag, and the child's environment holds no MCP variable. The stdin relay kept only `initialize`, `set_model`, `set_permission_mode`, and `set_max_thinking_tokens` for the life of a session and replayed those to each relaunched child, so a move dropped the MCP request. The moved child came up with no `t3-code` server, `ToolSearch` listed only the servers from settings, and every T3 tool was gone until T3 Code stopped and relaunched the session itself. On 2026-10-16 the T3 Code Captain relaunched seven threads by hand for this, several for the second or third time that day. ## Change - `src/entries/supervisor.ts`: `mcp_set_servers` joins `REPLAYED_REQUESTS`, so `StdinRelay` keeps the latest one and `attach` sends it to every relaunched child with the other setup requests, ahead of the resume prompt. - `docs/content/docs/architecture.mdx`: the two sentences that list the replayed setup requests name the MCP servers the harness registers at runtime. ## Decisions - The replayed set is `initialize` plus the SDK's session-state setters, and every other control request gets no replay because a repeat could run it twice (#330). `mcp_set_servers` is a setter: Claude Code replaces a named server only when its config differs from the one it holds, so a replay to a child that already has the server is a no-op, and a fresh child registers the same servers the harness last set. That makes it idempotent in the same sense as `set_model`, so it belongs in the set rather than in the error-reply path. - No code comment marks the addition; the docs carry the explanation, as the surrounding list does. - Nothing changes for the codex and muse supervisors: both spawn with an inherited stdin and have no relay, so this request shape never reaches them. - Found alongside and filed separately as #448, not changed here: on a `--resume` move, a non-setup control request the killed child never answered gets neither a replay nor the moved-request error reply, where the `--session-id` path answers it. ## Verification A development host runs no check command, so CI carries the typecheck. Hermetic run under a throwaway `HOME` and `TOKENMAXXING_HOME` with a stub `claude` that records its argv and stdin per launch, creates the session transcript, and writes a respawn marker after its first `user` line. The harness fed `initialize`, an `mcp_set_servers` request for one http server, `set_model`, a `user` line, then another `user` line after the move. - On `main` (`0e3fc40`): the relaunched `--resume` child received `initialize`, `set_model`, the resume prompt, and the later `user` line. No `mcp_set_servers`. - On this branch: the relaunched child received `initialize`, `mcp_set_servers`, `set_model`, the resume prompt, and the later `user` line. Not run: a live T3 Code session through a real move, because that spends pooled quota; the first live moves after the release are the check, read from the moved child's tool list. ## After the merge CI publishes the next version to npm; hosts pick it up through the self-update tick within a day, or by hand with the pinned `bun add -g` the release rules name, followed by a restart of the hub service. ## Review - Round 1 on base `37574c82` and head `8f996d54`: Muse Wonder Full (`muse/muse-wonder-full-1.0`, high) answered a quota 429 (usage window reset 10:20Z) with no report; its replacement in the same round, GPT Astra (`codex/gpt-6-astra`, medium), reviewed the prospective merge and approved with no findings, noting that its review was static and that Claude Code's handling of a replayed request id was not independently verified (the hermetic stub run above covers the relay side only).
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #322.
Problem
The Agent SDK sends its
initializecontrol request once per query. The request carriesappendSystemPrompt, the hook callback ids, the SDK MCP servers,agents, and the other init settings. The supervisor's stdin relay forwarded each harness line to the live child once, so after a move that resumed with--resume, the relaunched child never receivedinitialize. A T3 Code thread lost its appended runtime instructions after its first move, and an SDK consumer lost its hooks and in-process MCP servers.Change
StdinRelaykeeps the latest line of each control request inREPLAYED_REQUESTS(initialize,set_model,set_permission_mode,set_max_thinking_tokens) for the life of the session, andattachsends those lines to every child ahead of the resume prompt and the queued input. A first launch has none, so it is unchanged.--session-idreplay from fix: replay a stream-json session's lost lines on a move before its first transcript row #324 keeps the other lines the killed child received (userlines), and still answers every other control request with an errorcontrol_response. Setters now go before the replayeduserlines instead of in arrival order, so a replayed first turn runs under the latest model and permission mode.AGENTS.md,DESIGN.md, anddocs/content/docs/architecture.mdxdescribe the relaunch.Decisions
initializeis safe for the SDK. In@anthropic-ai/claude-agent-sdk0.3.276,Query.readMessagesfiles acontrol_responsewith no pending request in a boundedunmatchedControlResponsesmap, andhookCallbackslives on theQueryobject for the life of the query, so the hook callback ids in the replayed request still resolve. This answers the issue's open question about hook callback ids.Verification
Hermetic run under a throwaway
HOMEandTOKENMAXXING_HOME, with a stubclaudethat records its stdin and writes a respawn marker after the firstuserline:--resumemove, onmain: the relaunched child receives only the resume prompt and later input. On this branch:initialize,set_model, the resume prompt, then later input.--session-idmove (no transcript) with anmcp_callrequest before it: the relaunched child receivesinitialize,set_model, the replayeduserline, then later input, and stdout carries the errorcontrol_responsefor themcp_call.Not run: a live T3 Code session through a real move, because that spends pooled quota.