Files
reliquary/docs/workpad/reports/2026-10-15-23-athanor-trunk-fork-provenance.md
T

19 KiB
Raw Blame History

Provenance: how the Athanor became "trunk and fork of itself"

Date: 2026-10-15 Author: researcher subagent, model id claude-opus-5-5 (from system prompt). Read-only research. Plugin files not changed. Session journal: 2026-10-15-21-grotto-work Question: The current docs say the Athanor reads the build plan and the code (the trunk), forks itself for complex blocks, and sends mechanical or distant blocks to fresh agents that read trunk notes (plugins/spire/agents/athanor.md:31-32, plugins/spire/skills/implementation/SKILL.md:45-49, references/spawning-claude-code.md:56-64). The user remembers a different intent. Which of these happened: (a) the user's model was recorded and later changed, (b) it was never written down, or (c) something else?


1. Answer

(c), and closest to (a). The user's idea was written down once, but only as Igor's one-line paraphrase in a journal entry. It was then reshaped in a single step by an Opus 5.5 subagent (the redesign report). That agent gave a harness reason for the change: "fork copies the caller." The claim had not been tested; it came from reading the schema and from the Igor skill's wording. Igor turned the reshaped version into a proposal in chat. The journal records the user as "fully agreed." Igor then wrote it into the goal, and an implementer agent wrote it into the plugin files. No verbatim user text exists in the repo for any of these steps.

Point by point:

  • Recorded? Partly. On 2026-10-05 at 21:20 the journal paraphrases the user's direction as "adept-like trunk implementer, forks per task, updated by orchestrator, may live a whole phase." That separates the trunk (an implementer) from the orchestrator that updates it. It does not record "the Athanor learns plans and design, not code" or "train ONE implementer early, then fork it per subsection." I found those two points nowhere before today's grotto journal (2026-10-15).
  • Changed by whom? By the redesign subagent (general-purpose, claude-opus-5-5, dispatched by Igor at 21:20, report back at 21:30). It made the Athanor the trunk, and said so as its own proposal.
  • Stated reasoning? "fork copies the caller, so the athanor itself must be the trunk." It also called the result "the closest match to the user's idea." It labelled the copies-the-caller claim "Verified in substance," based on the Igor skill's phrase "forking yourself" and on the schema having no fork-source parameter. It was not tested at runtime. In the later spawning reference the same row is marked "assumed."
  • Did the user approve? The journal (Igor-authored) says Igor proposed the restructure at 21:55, including "intake=trunk", and the user "fully agreed." The user's actual words are not stored. The 2026-10-05 session was remote (paths under /home/g4b/...), and no transcript exists in the local ~/.claude/projects folder.
  • Was the harness constraint real? Mostly yes, according to the current official docs. Claude Code documents no way to fork an agent other than the current conversation, and "A fork can't spawn further forks." So "fork the implementer the Athanor trained" cannot be expressed directly. The only remaining route is for the trained implementer to fork itself. That route has its own problems (§5).

2. Timeline with sources

When Who What Source
2026-09-14 (e054ffd) Spire MVP The Igor skill says: "Forking yourself is a last resort. The main valid use: synthesizing boot data from an expert's knowledge to brief a new expert. For actual work, dispatch a subagent or adept — don't fork yourself into doing the work." plugins/spire/skills/igor/SKILL.md:66 (blame: e054ffd2, unchanged since)
up to 2026-09-22 (2a27c10) — The Athanor is a decomposer and synthesizer. It loads superpowers SDD, fans out by model tier and reads its children's reports. It has no instruction to read the code it builds. git show 2a27c10:plugins/spire/agents/athanor.md, lines 23-43
2026-10-01 dirigent (user + agents) Settled rule: "longer implementation before review" does not mean one implementer. "Never carry an implementer from one block to the next." docs/workpad/reports/dirigent/2026-10-01-lean-process-report.md:45, :410-415
2026-10-05 21:20 user, paraphrased by Igor "trunk-and-forks idea (adept-like trunk implementer, forks per task, updated by orchestrator, may live a whole phase)" docs/workpad/journals/2026-10-05-21-athanor.md:17 (commit b0b3151)
2026-10-05 21:20–21:30 redesign subagent (claude-opus-5-5) Makes the Athanor the trunk because fork copies the caller. Proposes variants A, B and C. Calls B the closest match to the user's idea. docs/workpad/reports/2026-10-05-21-implementation-skill-redesign.md:16, :67-108
2026-10-05 21:30 Igor (journal) Summarises the report: "fork copies the caller → athanor itself must be the trunk; variant A … baseline, B … as trial". Igor flags the report's size and the superpowers drop, but not the trunk relocation. journal :19
2026-10-05 21:40 user, paraphrased by Igor "Igor must own the design direction it delegates, not relay agent output." journal :20
2026-10-05 21:55 Igor proposes; user agrees (as recorded by Igor) "Athanor phase turns: intake=trunk + trunk notes → foreground blocks, forks for complex trunk-area blocks, fresh for mechanical … User: fully agreed." journal :22
2026-10-05 22:00 Igor Writes the goal, which says: "intake (read build plan + touched code = the trunk …)" and "complex blocks in the trunk's area → fork of the Athanor". docs/workpad/goals/lean-athanor.md:30, :34 (commit b0b3151)
2026-10-05 22:12 implementer subagent (claude-opus-5-5) Writes the current text: "That reading is your trunk" and "a fork of yourself (it inherits your context and model)". commit e515207, athanor.md +66-67, SKILL.md +91
2026-10-05 22:18 fix pass after the reviewer's finding M5 Changes "inherits your context" to "inherits your model and, assumed, your context". Adds a row marking fork availability as unverified. commit 5909221; docs/workpad/reports/2026-10-05-22-lean-athanor-review.md:57
2026-10-05 22:55 Igor Opens goal 0.2.1: "Trunk and forks is tested, not assumed": a preflight plus a trial comparing trunk notes with forks. Still open. docs/workpad/goals/lean-athanor-0.2.1.md:12-14
2026-10-15 experiment in another project No fork type was offered, so the Athanor built 3 of 7 blocks inline "on a 1M-context Opus that had read the whole trunk". docs/workpad/reports/2026-10-15-22-spire-vs-superpowers-plan-and-build-experiment.md:364, :403
2026-10-15 user, paraphrased by Igor States the original intent (see §3.1). Provenance research dispatched. docs/workpad/journals/2026-10-15-21-grotto-work.md:43 (uncommitted)

The 0.2.2 release (7c1ed39) and the brainstorm file docs/workpad/brainstorm/2026-11-15-implementation_thoughts.md (committed in 8028411) do not touch trunk or forks. The brainstorm ends at "Step 4: Attack the Plan" and says nothing about how the builder delegates.


3. User-attributed statements

All of these are Igor's paraphrases in journals. None is a verbatim quote.

3.1 The user's model, as recorded

  • 2026-10-05 21:20 (journals/2026-10-05-21-athanor.md:17, commit b0b3151):

    "trunk-and-forks idea (adept-like trunk implementer, forks per task, updated by orchestrator, may live a whole phase); 5.5 fine to ~600k, both extremes (tiny implementers / keep-implementer) failed; skill must be lean and leave decision room"

    The trunk is called an implementer that is adept-like. Adepts are trained, persistent experts. An orchestrator updates it. That fits the user's account today: one trained implementer, separate from the Athanor. The entry says nothing about what the Athanor itself reads.

  • 2026-10-15 (journals/2026-10-15-21-grotto-work.md:43, working tree, not committed):

    "their original Athanor intent was different. The Athanor learns plans + design (not code), delegates on that basis and reads implementer reports. For a hard task it trains up ONE implementer early with background info, then forks THAT implementer per subsection."

3.2 The user's agreement to the changed model, as recorded

  • 2026-10-05 21:55 (journals/2026-10-05-21-athanor.md:22):

    "Igor proposed Athanor restructure (… Athanor phase turns: intake=trunk + trunk notes → foreground blocks, forks for complex trunk-area blocks, fresh for mechanical → gate → …). User: fully agreed."

    There is no record of the proposal text, so it is unknown whether "intake=trunk" was spelled out as "the Athanor reads the code itself" when the user agreed. In the same session the user did correct other agent-originated points: the superpowers drop at 21:50, and "own the design direction, not relay agent output" at 21:40. No correction of the trunk location is recorded.

  • dirigent, 2026-10-01: "longer implementation before review" does not mean one implementer, because Sonnet implementers ran out of context at 500k–750k (reports/dirigent/2026-10-01-lean-process-report.md:45). The user's model avoids this by forking the trained implementer rather than carrying it. Variant C in the redesign carries one resident implementer instead, which is the shape this rule rejects.

4. Agent-authored text that introduced the shape

  • Redesign report (claude-opus-5-5, reports/2026-10-05-21-implementation-skill-redesign.md):
    • :16: "Trunk and forks is feasible in Claude Code with one catch: fork copies the caller, so the athanor itself must be the trunk."
    • :71: defines the trunk as "an agent that has read the code relevant to the plan." The fork "can stay for a whole phase while its budget lasts."
    • :78: "A fork copies the caller, not an arbitrary child | Verified in substance. The Igor skill describes it as 'forking yourself', and no parameter names a fork source. | Consequence: only the agent that holds the trunk context can fork it."
    • :93 (variant B): "At intake the athanor reads the build plan and the code the plan names, roughly 100–250k tokens. It then forks itself per complex block … This is the closest match to the user's idea, and the athanor's intake read also makes it a better judge of handoff flags."
    • :94 (variant C): "Phase-resident implementer … requires SendMessage resumes, which hit the routing hazard … Not recommended as the default. It is the shape that reached about 960k in spacecraft."
    • It does not consider a fourth option: a trained implementer that forks itself per subsection while the Athanor stays plan-level.
  • Goal (written by Igor, goals/lean-athanor.md:30,34): "intake (read build plan + touched code = the trunk; write short trunk notes)" and "complex blocks in the trunk's area → fork of the Athanor". The goal header says the redesign report is "input, not law — corrected by this goal where they differ" (:4). On the trunk question the goal does not differ from the report.
  • Implementer (e515207) put the goal into the plugin files almost word for word. The reviewer (reports/2026-10-05-22-lean-athanor-review.md:32,57) only checked that the context inheritance was labelled as assumed. Neither checked the shape against the user's 21:20 idea, because the goal was the spec.

5. Is "fork the implementer the Athanor trained" expressible in the harness?

What the repo says

references/spawning-claude-code.md:

  • :62: fork copies the caller. Status: assumed.
  • :61: fork availability is unverified. It was not offered on 2026-10-05, and again not offered on 2026-10-15 (research/2026-10-15-11-spire-superpowers-coupling.md:171; experiment report :403).
  • :64: whether a fork can fork again is unknown.

What the official docs say

From code.claude.com/docs/en/sub-agents, fetched 2026-10-15:

  • "A fork is a subagent that inherits the entire conversation so far … a fork sees the same system prompt, tools, model, and message history as the main session." A table compares fork and non-fork subagents. The fork column reads "Same as main session" for system prompt, tools and model. The docs describe forking only "the current conversation." There is no parameter for forking another agent.
  • "A fork can't spawn further forks." This answers one of the unknowns at spawning-claude-code.md:64.
  • Fork mode is on by default in interactive sessions (v2.1.232+). It is off with -p and in the Agent SDK unless CLAUDE_CODE_FORK_SUBAGENT=1 is set. When fork mode is on, "Claude Code runs the subagents Claude spawns in the background, forks and non-fork subagents alike … Claude Code also removes the Agent tool's run_in_background parameter, so Claude can't ask for the foreground."
  • Depth: "a subagent can spawn subagents of its own, up to three layers below the main conversation."
  • Resume: SendMessage resumes a specific agent "with full conversation history" and "in the background". That continues the agent; it does not branch it.

The docs consistently say "main session" and "current conversation." They do not say whether a subagent such as the Athanor can fork itself at all. That makes the redesign's "Athanor forks itself" an assumption too.

What this means for each shape

Shape Expressible as documented? Notes
Athanor forks the implementer it trained No. There is no fork-source parameter, and forks copy the current conversation. This constraint is what pushed the redesign toward an Athanor trunk (report :16, :78).
Trained implementer forks itself per subsection (the implementer is the caller) Possibly. It needs the implementer to hold the Agent tool, fork mode on, subagent-level forking allowed (not documented), and enough depth: Igor (root) → Athanor (1) → implementer (2) → forks (3), which is at the 3-layer limit. Each fork's result returns to the implementer, not to the Athanor. The implementer becomes a sub-orchestrator. The Athanor then reads one report per subsection batch, not per subsection. Nobody has proposed or tested this.
Athanor resumes the trained implementer per subsection (SendMessage) Expressible, but it is a resume, not a fork. Context accumulates (variant C). A resume from a subagent goes to the background and the parent stalls (spawning-claude-code.md:41; docs: resumes run in background). This collides with dirigent's "never carry an implementer" rule.
Igor (root) trains the implementer and resumes it Same as the row above. Resumes are safe from the root, but they still accumulate rather than branch. Igor becomes the build orchestrator.
Training written to a file: the implementer writes trunk notes or a briefing, and fresh implementers read it Expressible today. This is variant A ("trunk notes"). The current docs already use it for mechanical blocks. The Athanor need not read code if a delegated implementer writes the notes; the redesign itself allows this ("The first block's implementer, or a short orientation agent, writes trunk.md", report :92).
Athanor reads the code and forks itself (current docs) Partly. Fork mode on means no foreground. Fork mode off means no fork. Whether a subagent can fork is undocumented. This conflicts with Spire's "foreground for sequential work" rule (spawning-claude-code.md:16) whenever forks are available. In practice the Athanor built blocks inline (experiment report :364, :403).

Did the constraint push the design? Yes, by the redesign's own account: "with one catch: fork copies the caller, so the athanor itself must be the trunk" (:16). The documented harness supports the premise that a fork copies the current conversation and nothing else. It does not support the conclusion that the Athanor is therefore the only possible trunk: the "implementer forks itself" row was never considered. The separate idea that the Athanor should not read code was never in tension with the harness. It was lost because the Athanor became the trunk, and the trunk is by definition the agent that has read the code.


6. Other observations

  • Inconsistency inside Spire: the Igor skill (igor/SKILL.md:66, since e054ffd) says not to "fork yourself into doing the work" and keeps forking for "synthesizing boot data … to brief a new expert." That use is close to the user's "train up an implementer." The redesign cited the same line as evidence that forks copy the caller (:78), then used it to justify the Athanor forking itself to do the work.
  • The open 0.2.1 checkbox "Trunk and forks is tested, not assumed" (goals/lean-athanor-0.2.1.md:12-14) compares only trunk notes against Athanor forks. Neither the user's shape nor "implementer forks itself" is among the arms.
  • What the evidence covered: dirigent's and spacecraft's evidence (fresh context per block; 960k with a carried implementer) is about carrying one implementer. None of the material tests forking a trained implementer, which keeps a stable trained base and branches it per subsection.

7. Options, without a verdict

  1. Leave the docs as they are and run the 0.2.1 trial as planned (trunk notes against Athanor forks).
  2. Add the user's shape as a trial arm: the Athanor reads plan and design only; one trained implementer per hard task forks itself per subsection. Preflight first: can a depth-2 subagent fork, is the depth limit enough, does fork mode remove foreground dispatch, where do fork results land.
  3. Keep the Athanor plan-level and make the training a file: a delegated implementer or orientation agent writes the trunk notes, and fresh implementers read them. This needs no new harness behaviour, but it replaces the user's in-context training with notes.
  4. Move build orchestration to the root: Igor trains the implementer and resumes it. This is resume, not fork, so context accumulates.
  5. Update spawning-claude-code.md with the documented facts either way: no fork of another agent; forks cannot fork; fork mode implies background-only; the fork-mode defaults and env var. Also answer the experiment report's request (:403) about what to do when forks are missing.

8. Gaps

  • There is no verbatim user text from the 2026-10-05 session. The transcript is not local, and the session was remote. Igor's 21:55 proposal text is not stored, so what exactly the user agreed to is unknown.
  • Igor's brief to the redesign agent is not stored. It is unknown whether the brief passed on "updated by orchestrator" or the separate-implementer reading.
  • Whether a subagent can fork itself is not settled by the docs, and nobody has run it.
  • Only one docs page was fetched (in two parts), plus one web search. The changelog was not checked against the claims about fork-mode version boundaries.

Sources: Claude Code docs — Subagents; search results also listed startdebugging.net: Subtask vs Fork vs Background Agent and labuladong: Fork Agent (not relied on).