Multi-Agent Coordination
In-process, fork, ACP, Codex, Claude Code, and SDK backends behind one seam
Conclusion: This Is Not a Swarm Scheduler, but a Composition of Delegation Lifecycles
DeepSeek Harness builds multi-agent behavior from four pieces: a named SubagentProvider seam, one-shot SubagentRuns, cold-resumable continuable child Sessions with process-local Activation epochs, and model-visible delegation/control tools. This subagent subsystem has no single swarm, shared blackboard, voting layer, or task DAG. Collaboration emerges from parent-child Sessions, inboxes, durable descriptors, and optional providers.
This distinction matters. Seeing a subagent call does not tell you whether the child inherits history, remains conversational, is managed as a Job, or even runs in the same process. A provider promises only its declared capabilities. Unsupported outputSchema, depth limit, tool filter, or persona requests fail before startup instead of degrading silently. MULTIAGENT-SEAM
The base bundle registers the service, spawn/fork backends, control and listing tools, and binds spawn to continuable while fork remains one-shot. The Web bundle keeps the global registry/backends but moves model-visible tools into per-Session presets. “Multi-agent” is therefore both a runtime capability and a composition choice. MULTIAGENT-BASE-COMPOSITIONMULTIAGENT-WEB-PLANE
1. The Real Topology: Providers Create Nodes; the Manager Owns Continuable Conversations
Model tools (names are configurable)
subagent / subagent_fork
│
├─ foreground ─────────→ SubagentRuntime.start(provider)
│ └→ provider.start() → SubagentRun
├─ one-shot background → Jobs → provider.start() → SubagentRun
└─ continuable bg ─────→ ContinuationManager
├→ provider.prepareContinuable() (seed data only)
├→ Agent create / resume + inbox
└→ durable Session + Activation epoch
Global controls: send_message / interrupt_agent / list_agents
Child return path: report (continuable in-process children only)
SubagentProvider.start() owns pre-publication creation for a one-shot child. After it returns a run, the holder owns result observation and disposal. For a continuable child, the provider contributes only detached data describing whether to seed parent history; the continuation manager owns identity, composition, the Agent handle, messages, cold resume, ownership, and teardown. MULTIAGENT-SEAM
2. One Tool Definition Actually Selects Three Execution Routes
| Route | Trigger | Return commit point | Later control |
|---|---|---|---|
| Foreground one-shot | run_in_background:false | Return output after the child ends and the run is disposed | No continuable ID |
| Background one-shot | backgroundMode:one-shot plus explicit true | Return jobId after Job registration | job_output/job_kill |
| Background continuable | backgroundMode:continuable plus omitted or true | Return subagentId when the child inbox accepts the initial message | send_message/interrupt_agent |
backgroundMode chooses both the background mechanism and the default when the argument is omitted. Even when a provider supports continuation, an explicit foreground request uses the one-shot start() contract. A continuable start can return before any model request begins and before the initial prompt is claimed into a user/message event; acceptance itself is already recorded as an Inbox splice. MULTIAGENT-TOOL-ROUTESMULTIAGENT-CONTINUABLE-STARTMULTIAGENT-CONTINUATION-ACCEPTANCE-TESTMULTIAGENT-INBOX-SPLICE
“Background agent” is therefore not one state. One-shot background work is an ordinary Job; continuable background work is a conversation with a durable Session ID. Flattening both into running/done erases the most important control distinction.
3. Provider Matrix: One Seam, Six Different Isolation Boundaries
| Provider | Process/context | Parent conversation | Continuable | Start capabilities |
|---|---|---|---|---|
spawn | Same process, separate Agent/Session | None | Yes | Schema, depth, filter, and persona |
fork | Same process, separate Agent/Session | Completed-Turn prefix | Implemented | All four |
acp | External ACP process | None | No | None |
codex | Fresh app-server process per call | None | No | None |
claude-code | Official SDK/CLI subprocess | None | No | None |
dsh-sdk | Complete independent runtime process | None | No | None |
Spawn and fork are the backends that enter the local parent-child graph. External providers inherit no parent conversation; their only possible parent-derived context is the workspace cwd (ACP/SDK may instead use a configured cwd), and they return through the one-shot result seam. The ACP, Codex, Claude Code, and SDK packages are optional capabilities, not the default product surface: the Codex and Claude Code tool rows in the Standard/Code presets are explicitly disabled. MULTIAGENT-SPAWN-PROVIDERMULTIAGENT-FORK-PROVIDERMULTIAGENT-ACP-PROVIDERMULTIAGENT-SDK-PROVIDERMULTIAGENT-CODEX-PROVIDERMULTIAGENT-CLAUDE-PROVIDERMULTIAGENT-STANDARD-PRESETMULTIAGENT-CODE-PRESET
4. Spawn Versus Fork Differs in the Session Seed, Not in Whether the Child Is Independent
Spawn
Supplies no seed. The child starts with an empty conversation, so the delegated prompt must be self-contained.
Fork
Copies the balanced parent Session prefix from sequence zero through the last turn/end.
Open Turn excluded
The Turn currently invoking delegation is not closed and cannot be a valid child seed.
Independent thereafter
Both forms own a new Session ID, inbox, Turns, and output suffix.
Fork “inherits context” only in the sense of completed conversation history. It does not share current reasoning, a live inbox, or the same Session. A test forks while the parent's second Turn is hanging and verifies that the child seed contains only the first completed Turn. MULTIAGENT-SPAWN-PROVIDERMULTIAGENT-FORK-PROVIDERMULTIAGENT-FORK-OPEN-TURN-TEST
Both in-process forms join the exact preset generation the parent is currently running—the same plugin instances, tool registrations, and prompt sections—instead of resolving a possibly changed configuration again by preset name. MULTIAGENT-PRESET-INHERITANCE
5. Inheritance Matrix: Route, Workspace, and Capabilities Are Separate Dimensions
| Item | Rule | Durability |
|---|---|---|
| Provider / model / maxTokens | Default from parent; child request may override | Continuable descriptor stores provider/model, not maxTokens |
| Workspace / lineage | Inherit cwd; record direct parent, origin, depth, and a nonzero seedLength when present | Session header |
| Prompt / tools | Join parent's exact live preset, then layer child persona/filter | Preset ID and descriptor support reconstruction |
| Conversation | Only fork copies the completed-Turn prefix | The seed becomes the child's own log prefix |
| Sandbox / approval | Copy only the explicit Session sandbox override when sandbox policy is composed; pin approval to never when approval is composed | Only defined overrides become delegation-source events |
What does not inherit is equally important: spawn cannot see the parent transcript; fork cannot see the open Turn; one-shot approval grants do not flow down; the deployment sandbox default is not snapshotted; and a child's persona/tool filter remains in its own scope without mutating its parent or siblings. MULTIAGENT-CHILD-INHERITANCEMULTIAGENT-CHILD-COMPOSITIONMULTIAGENT-DELEGATED-POLICY
Inheritance here is not a shallow object copy. It is deliberately separated into Session seed, Agent options, preset scope, and durable policy events. That is much easier to audit than an ambiguous inheritContext=true.
6. Recursion Budget and Authority Narrow Monotonically Along the Lineage
The tool loader defaults maxDepth to 3; provider-managed is used for external providers the parent runtime cannot constrain. The lower-level depth reads the greater of the durable header and runtime option, then adds one for the child, so a resumed child cannot masquerade as depth zero. Direct apply without a cap remains uncapped, which means “3” is a tool-configuration default, not a service-wide law. MULTIAGENT-TOOL-CONFIGMULTIAGENT-DEPTH
send_message admits only the exact live direct parent; interrupt_agent may target a deeper descendant from an exact live ancestor. Identity is checked against live Agent objects and durable parent lineage, not merely a caller-supplied, guessable Session string. MULTIAGENT-CONTROL-TOOLSMULTIAGENT-COLD-RESUMEMULTIAGENT-INTERRUPT
This is not a role-based team. There is no leader/member table or sibling direct-message path. Current authority is tree-shaped and intentionally narrow; teams, shared queues, or arbitrary Agent routing would require a new explicit protocol, not reinterpretation of parentSession as a universal ACL.
7. The One-Shot Core Contract: Provider-Owned Before Publication, Run-Holder-Owned After
validate provider + capabilities + schema + descriptor
→ provider.start()
→ unpublished setup / rollback on failure
→ publish child or external run
→ emit subagent/start
→ await run.result ──────────→ emit subagent/end
→ map stopReason / preserve partial output
→ holder runs dispose() to quiescence
A provider-start rejection produces no run and no lifecycle edge. Once startup returns, Turn and transport failures belong to result. The in-process driver submits exactly one user prompt after child publication and waits for idle; the AbortSignal cancels the child, while dispose() is the idempotent release boundary. MULTIAGENT-RUNTIME-DISPATCHMULTIAGENT-ONE-SHOT-DRIVER
The result is read from the child-owned suffix after the seed/activation boundary. completed, aborted, error, max-tokens, and refusal are not collapsed to a boolean; cancelled or truncated work can still carry partial output. One-shot subagent/end follows result settlement and may precede holder disposal; a continuable epoch's end waits for the teardown outcome. A background Job treats only completed final text as successful output, maps other reasons to killed/failed, and always disposes after settlement. MULTIAGENT-ONE-SHOT-RESULTMULTIAGENT-LIFECYCLEMULTIAGENT-RUN-SETTLEMENT
8. “Final Answer” and “Structured Result” Use Separate Commit Protocols
The canonical ordinary-output rule selects the last non-empty assistant message. If none exists, it uses accumulated text deltas; if neither exists, output is empty. Selection is independent of stop reason, so an error or max-token ending can still retain diagnostically useful partial text. MULTIAGENT-ASSISTANT-OUTPUT
Only capable in-process providers install a real-schema structured_output tool, dedicated prompt, and monotonic guard in the child scope. A model call merely stages the value; capture commits only after the authoritative tools/result succeeds and, under Code Mode, after the outer invocation succeeds. A child that reports completed without a valid capture is reclassified as an error. MULTIAGENT-STRUCTURED-OUTPUTMULTIAGENT-ONE-SHOT-RESULT
This explains why external providers advertise zero capabilities: sharing a working directory does not let the parent runtime enforce their tool catalog, persona, recursion budget, or structured-result commit point.
9. A Continuable Durable Session Is Not the Same Object as a Process-Local Activation
| State | Derived from | Meaning |
|---|---|---|
running | The Agent runs, or a waking message is accepted but has not left the inbox | The current epoch cannot settle |
waiting | The Agent is idle but still owns undisposed child Activations | Descendant ownership pins the parent |
settled | The Agent is idle and has no owned children | Dispose the live handle; the durable Session may resume later |
An Activation is a residency epoch, not a durable Task. It holds the exact handle, weak ancestry, owned-child set, accepted message IDs, and one memoized disposal transaction. The child Session ID is stable; every cold-resumed residency gets a new lifecycle runId. MULTIAGENT-ACTIVATION-MODELMULTIAGENT-ACTIVATION-OWNERSHIPMULTIAGENT-LIFECYCLE
10. Inbox Acceptance Is the Authoritative Follow-up Commit; Cold Resume Does Not Reinvoke the Provider
send_message(childId)
├─ resident + running → enqueue in the same Agent inbox; wait behind current Turn
├─ resident + waiting → wake the same Agent
└─ no Activation → inspect durable Session
→ authorize exact direct parent
→ fold the child's own descriptor suffix
→ ctx.agents.resume()
→ enqueue in inbox
Delivery, release, and disposal for each child pass through the same ChildLock; the Agent inbox is the sole FIFO. The caller's AbortSignal owns only the work before acceptance. Once admitted, that send_message call cannot cancel the accepted Turn. MULTIAGENT-FOLLOWUP
Cold resume reconstructs provider/model, persona, and tool filter from the durable Session header and the descriptor in the child's own suffix, then calls agents.resume() directly. It does not dispatch the original provider. Provider unload blocks new starts but need not prevent an existing continuable child from resuming. The descriptor stores neither maxTokens nor outputSchema, so those activation-local constraints cannot be assumed on resume. MULTIAGENT-COLD-RESUMEMULTIAGENT-DESCRIPTOR
11. Four Return Channels Exist; Reporting and Completion Are Not Synonyms
| Channel | Sender | Ends child? | What the parent receives |
|---|---|---|---|
| Foreground result | Run holder | Yes, one-shot | Direct tool result |
| Background Job outcome | Job runtime | Yes, one-shot | Job state/notice |
report | Continuable child, explicitly | No | Relay in the direct parent's inbox |
| Settlement notice | Continuation manager | Sent after teardown | Stop reason plus available closing message |
send_message returns only the accepted messageId, not the child's answer. The child-scoped report can target only its direct parent, may use wakeup or quiet scheduling, and does not end the Turn or Activation. MULTIAGENT-CONTROL-TOOLSMULTIAGENT-REPORT-TOOLMULTIAGENT-REPORT-DELIVERY
Once a caller has received a child ID, Activation settlement independently attempts a runtime notice outside report. Even max-tokens, failure, cancellation, or a child that forgot to report can reach the parent. If the parent is no longer live, delivery is dropped without blocking teardown and the child Session remains the durable record. MULTIAGENT-SETTLEMENT-NOTICE
12. list_agents Is a Discovery Surface, Not a Task-Result Surface
The service merges the live Session store with optional persistence, identifies direct children/descendants through durable origin:subagent headers, then classifies mode and label through projections. Cold-read concurrency is fixed at four. A corrupt or temporarily unreadable child becomes its own corrupt/unavailable diagnostic instead of failing the whole listing. The scan does not consult the Activation manager or provider state. MULTIAGENT-LIST-SERVICEMULTIAGENT-LIST-CONCURRENCY
| Model status | Actual meaning | It is not |
|---|---|---|
running | A live Agent is being driven | A particular Job's running state |
idle | A live Agent is between Turns and may await descendants | Completed with a collectible result |
ready | Only a stored record remains; the direct parent can resume it | Terminal success |
The model tool filters out one-shot children because send_message cannot continue them; descendant traversal can still pass through those nodes in stable pre-order. Only depth-one entries accept follow-up, while deeper entries remain ancestor-interrupt candidates. MULTIAGENT-LIST-TOOL
13. Concurrency Means “Overlap Across Children, Linearize Per Child,” Not Global Scheduling
The provider contract explicitly permits starts for distinct children to overlap. The delegation tool declares itself concurrency-safe and its continuable guidance encourages independent delegations in one assistant message. One-shot background work additionally enters the Job registry's owner-capacity policy. MULTIAGENT-SEAMMULTIAGENT-TOOL-CONCURRENCYMULTIAGENT-JOB-CAPACITY
Follow-up, release, and disposal for one durable child queue behind its ChildLock. The accepted-ID set closes the microtask window where a message is synchronously inserted but Agent status has not yet become running, preventing settlement from beating already accepted work. The parent's owned-child set includes the descendant lifetime in the parent's settlement condition. MULTIAGENT-CHILD-LOCKMULTIAGENT-FOLLOWUPMULTIAGENT-ACTIVATION-OWNERSHIP
The subagent layer has no global worker pool, fair queue, priorities, quota allocation, or result reducer. It supplies correct concurrency boundaries; the model prompt, Job layer, or a higher-order workflow still decides how many children to start, when to start them, and how to synthesize their work.
14. Interrupt Stops One Current Turn; Drain Tears Down the Whole Activation Tree
| Operation | Immediate action | What survives | Completion wait |
|---|---|---|---|
| Foreground AbortSignal | Cancel the one-shot child/run | Already-produced partial output | Holder eventually disposes |
| Job kill | Abort the task-owned controller | Job identity until settlement | Producer settlement plus disposal |
interrupt_agent | cancel(..., keepInbox:true) | Activation, unclaimed messages, descendants | None; fire-and-return |
| Manager/scoped drain | Close admission synchronously; cancel top-down | Only durable Sessions | Release bottom-up and aggregate failures |
Interrupting an absent, completed, or one-shot ID is an accepted no-op; it is not a subtree kill. When local cancellation wins for an external one-shot provider, the result normalizes to aborted and the idempotent handle teardown waits for the managed process tree to exit. MULTIAGENT-INTERRUPTMULTIAGENT-OUTPROCESS-SETTLEMENT
Drain first closes admission, waits for admitted materializations to publish or roll back, then processes all roots in parallel. Within each tree it propagates cancellation top-down and releases handles child-first. Failure in one branch does not skip siblings; an aggregate reports after all settle. Final Session flush is best-effort: failure warns that resume may be missing or stale, but cannot pin ancestors forever. MULTIAGENT-DRAINMULTIAGENT-ACTIVATION-DISPOSAL
15. Durability Comes from the Session Descriptor, Not a Resident Agent or Task Queue
Session header
parentSession / origin=subagent / delegationDepth / seedLength / agentPreset
subagent/descriptor v2 (model-hidden, log-only)
one-shot: mode / provider / optional label
continuable: mode / provider / label / agentProvider / agentModel / persona / toolFilter
intentionally omitted: outputSchema / maxTokens / subagentDepth
Continuable creation appends a between-Turn descriptor after any fork prefix, then accepts the initial prompt. The descriptor is lossless-JSON snapshotted first; the current parser rejects unknown fields, while an unsupported version is not resumable. MULTIAGENT-DESCRIPTORMULTIAGENT-DESCRIPTOR-SEEDMULTIAGENT-DESCRIPTOR-FOLD
A fork seed can contain an ancestor descriptor. Cold resume therefore folds only the child-owned suffix after seedLength; the projection instead uses last-valid-descriptor wins so the child's own record overrides the ancestor identity in its seed. The two rules have the same goal but different fold boundaries. MULTIAGENT-DESCRIPTOR-PROJECTIONMULTIAGENT-COLD-RESUME
After process restart, the recoverable object is the child conversation and its declared composition—not the prior Activation, run handle, accepted set, or background Job. If final flush fails, the runtime still releases the graph, explicitly choosing “possibly stale resume” over “certainly deadlocked ancestor.” MULTIAGENT-FINAL-FLUSH
16. Codex Comparison: the DeepSeek Seam Sees One One-Shot Worker, While Codex May Orchestrate Subagents Internally
The repository's codex provider launches a new official codex app-server --stdio for every delegation and inherits only the parent Session cwd. It advertises zero start capabilities, has no prepareContinuable, shares no parent transcript/preset/tool scope, and returns no local Agent handle. DeepSeek Harness therefore wraps the entire Codex run as one one-shot child. Even if that Codex Turn uses its own subagents, the internal tree does not become addressable nodes in the DeepSeek continuation graph. MULTIAGENT-CODEX-PROVIDERMULTIAGENT-CODEX-RUN
Start
Run a fixed command and initialize JSON-RPC; do not publish before thread creation succeeds.
Isolate
thread/start requires ephemeral:true in the parent's workspace.
Execute
Accept only non-empty text blocks and start exactly one Turn.
Reclaim
Close the wire, end stdin, terminate, and await the entire managed process tree.
The wire returns only the last final_answer, falling back to the last unphased answer when no explicit final exists; commentary and reasoning are excluded. Context-window exhaustion becomes max-tokens, while other faults pass through shared out-of-process settlement as error with possible partial output. MULTIAGENT-CODEX-RUNMULTIAGENT-CODEX-WIRE
Command/file approvals choose only cancel or decline; permission requests receive an empty grant, user-input requests receive empty answers, and MCP elicitation is declined. The child never turns the absence of a human into implied consent. Protocol tests also verify the ephemeral thread, cross-thread/Turn filtering, commentary exclusion, and last-final selection. MULTIAGENT-CODEX-UNATTENDEDMULTIAGENT-CODEX-WIRE-TEST
Codex's Public Multi-Agent Contract Versus This Seam
| Dimension | DeepSeek Harness pinned source | Codex public documentation |
|---|---|---|
| Orchestration unit | Provider-bound child Session/run; continuable children have durable IDs | Subagent workflows and inspectable agent threads |
| Coordination owner | The model calls tools explicitly; direct parents own follow-up, while runtime separates report from settlement | Codex handles spawn, follow-up routing, wait, and close; the main thread consolidates results |
| Concurrency boundary | Distinct children may overlap; the subagent seam itself has no global concurrency cap | agents.max_concurrent_threads_per_session can cap concurrently open threads |
| Roles and configuration | Provider, preset, persona/filter, and Agent options compose | Built-in default/worker/explorer and project/personal TOML custom agents can override model, reasoning, sandbox, MCP, and skills |
| Permissions | When the corresponding services are composed, in-process children copy the explicit sandbox override and pin approval to never | Subagents inherit current sandbox/permission mode and live parent-Turn overrides; noninteractive runs fail when approval cannot surface |
The Codex column uses only OpenAI's public Subagents documentation, retrieved on 2026-08-13. DeepSeek is source-level at the pinned commit; this comparison makes no claim about undocumented implementation.
The adapter's strengths are crisp isolation, normalized failure, and reclaimable process trees. The tradeoff is that the DeepSeek parent receives only a one-shot final result and cannot see or directly steer Codex's internal agent threads. Exposing a Codex child as a node in DeepSeek's persistent message graph cannot be inferred from the codex provider name; it requires a backend with explicit durability and authority contracts.
17. Failure Layers: The Commit Point Determines Who Owns Cleanup
| Failure location | Externally visible result | Resource semantics |
|---|---|---|
| Provider/capability/schema validation | Immediate tool failure, no child ID | No provider work began |
| Unpublished create/handshake | Start rejects, no lifecycle edge | Provider/Agent factory rolls back partial resources |
| Post-publication model/transport | stopReason:error, possibly partial output | Holder must still dispose |
| One corrupt catalog child | Diagnostic row | Other children still list |
| Parent already gone | Settlement notice is dropped | Child Session retains the facts |
| Final flush/teardown failure | Warning or error lifecycle | Ownership is still released to avoid permanent waiting |
The service checks capabilities before provider dispatch, out-of-process helpers normalize post-publication transport rejection into a stable result, and listing contains read damage to a single row. MULTIAGENT-RUNTIME-DISPATCHMULTIAGENT-OUTPROCESS-SETTLEMENTMULTIAGENT-LIST-SERVICE
Each lifecycle listener's throw or rejection is contained. One-shot runs and each Activation epoch require paired start/end identity. The invariant companion also checks provider add/remove consistency, non-empty identities, no duplicate live run IDs, and matching provider/child/local fields between end and start. MULTIAGENT-LIFECYCLEMULTIAGENT-INVARIANTS
18. Two Composition Audit Findings at the Pinned Baseline
| Finding | Evidence | Impact |
|---|---|---|
| Fork-continuable claim conflicts with shipped presets | The provider comment says no shipped caller; base is indeed one-shot, but Standard, Code, and Cordis presets all configure continuable | Those presets enter the implemented prepareContinuable path and add the report prompt/tool to a fork child—the exact prefix-reuse condition the comment says must be avoided |
| Codex/Claude Code are optional packages, not default tools | Presets contain provider-bound tool rows but keep them disabled and do not load the corresponding provider plugins | “An adapter exists in the repository” must not be reported as “users can call it by default” |
The fork code does implement continuable seeding. Base configuration and its rationale agree with the source comment, while three agent presets carry the opposite value. Because the tool mounts successfully whenever the provider has prepareContinuable, this is not inert configuration. The project should standardize on one-shot, or update the design and prove that the report delta does not defeat the intended prefix/cache semantics. MULTIAGENT-FORK-PROVIDERMULTIAGENT-BASE-COMPOSITIONMULTIAGENT-STANDARD-PRESETMULTIAGENT-CODE-PRESETMULTIAGENT-CORDIS-PRESET
The Codex boundary needs the same precision: the provider package is complete, while the preset supplies only a disabled model-facing entry. MULTIAGENT-CODEX-PROVIDER
19. Guarantee Matrix and Final Assessment
| Form | Parent history | Continue after process restart | Later messages | Result channel |
|---|---|---|---|---|
| Spawn one-shot | None | No | No | Foreground result or Job |
| Fork one-shot | Completed-Turn prefix | No | No | Foreground result or Job |
| Spawn continuable | None | Yes, with Session persistence | Direct-parent FIFO | Report plus settlement notice |
| Fork continuable | Completed prefix captured once at creation | Technically supported; shipped configuration drifts | Direct-parent FIFO | Report plus settlement notice |
| ACP/Codex/Claude/SDK | None; at most the parent cwd (ACP/SDK may override) | No | No | One-shot result |
The mature part is not merely “it can delegate,” but its commit points: pre-publication failure exposes no ID, inbox acceptance transfers ownership, interrupt does not pretend to prove quiescence, Session and Activation remain distinct, and tree teardown does not skip siblings after one branch fails. The omissions are equally explicit: no global scheduler, shared team state, automatic result reducer, durable Job queue, or arbitrary inter-Agent message bus. Naming those as boundaries is more valuable than marketing composable primitives as a complete swarm.
This chapter traced production source, shipped configuration, and tests at pinned commit 47f943859bef60e4160492346772ded9b24f765a, then ran the 28 Vitest *.spec.ts files under packages/subagent (E2E files use a separate configuration): all 603 tests passed. The Codex comparison is separately bounded to OpenAI public documentation retrieved on 2026-08-13. The configuration drift is a cross-file static-audit finding and does not disappear because package tests pass.
My Learning Notes
Autosaved only in this browser. Nothing is uploaded or committed. Export Markdown whenever you want to keep a copy.