DSHarness Systems Dissection Pinned baseline 47f943859b · 36 verified / 0 in progress / 36 chapters
中文
Orchestration·Chapter 24

Multi-Agent Coordination

In-process, fork, ACP, Codex, Claude Code, and SDK backends behind one seam

VerifiedUpstream 47f943859bScope: Analyze provider registries, spawn/fork, context inheritance, continuation activation, controls, reporting, and job integration.

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

Effective composition

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

RouteTriggerReturn commit pointLater control
Foreground one-shotrun_in_background:falseReturn output after the child ends and the run is disposedNo continuable ID
Background one-shotbackgroundMode:one-shot plus explicit trueReturn jobId after Job registrationjob_output/job_kill
Background continuablebackgroundMode:continuable plus omitted or trueReturn subagentId when the child inbox accepts the initial messagesend_message/interrupt_agent
Routing fact

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

ProviderProcess/contextParent conversationContinuableStart capabilities
spawnSame process, separate Agent/SessionNoneYesSchema, depth, filter, and persona
forkSame process, separate Agent/SessionCompleted-Turn prefixImplementedAll four
acpExternal ACP processNoneNoNone
codexFresh app-server process per callNoneNoNone
claude-codeOfficial SDK/CLI subprocessNoneNoNone
dsh-sdkComplete independent runtime processNoneNoNone

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

1

Spawn

Supplies no seed. The child starts with an empty conversation, so the delegated prompt must be self-contained.

2

Fork

Copies the balanced parent Session prefix from sequence zero through the last turn/end.

3

Open Turn excluded

The Turn currently invoking delegation is not closed and cannot be a valid child seed.

4

Independent thereafter

Both forms own a new Session ID, inbox, Turns, and output suffix.

Context semantics

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

ItemRuleDurability
Provider / model / maxTokensDefault from parent; child request may overrideContinuable descriptor stores provider/model, not maxTokens
Workspace / lineageInherit cwd; record direct parent, origin, depth, and a nonzero seedLength when presentSession header
Prompt / toolsJoin parent's exact live preset, then layer child persona/filterPreset ID and descriptor support reconstruction
ConversationOnly fork copies the completed-Turn prefixThe seed becomes the child's own log prefix
Sandbox / approvalCopy only the explicit Session sandbox override when sandbox policy is composed; pin approval to never when approval is composedOnly 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

Design assessment

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

Call authority

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
Commit point

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

Structured 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

StateDerived fromMeaning
runningThe Agent runs, or a waking message is accepted but has not left the inboxThe current epoch cannot settle
waitingThe Agent is idle but still owns undisposed child ActivationsDescendant ownership pins the parent
settledThe Agent is idle and has no owned childrenDispose 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

Provider-independent resume

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

ChannelSenderEnds child?What the parent receives
Foreground resultRun holderYes, one-shotDirect tool result
Background Job outcomeJob runtimeYes, one-shotJob state/notice
reportContinuable child, explicitlyNoRelay in the direct parent's inbox
Settlement noticeContinuation managerSent after teardownStop 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

Fallback notice

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 statusActual meaningIt is not
runningA live Agent is being drivenA particular Job's running state
idleA live Agent is between Turns and may await descendantsCompleted with a collectible result
readyOnly a stored record remains; the direct parent can resume itTerminal 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

What may overlap

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

What must serialize

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

OperationImmediate actionWhat survivesCompletion wait
Foreground AbortSignalCancel the one-shot child/runAlready-produced partial outputHolder eventually disposes
Job killAbort the task-owned controllerJob identity until settlementProducer settlement plus disposal
interrupt_agentcancel(..., keepInbox:true)Activation, unclaimed messages, descendantsNone; fire-and-return
Manager/scoped drainClose admission synchronously; cancel top-downOnly durable SessionsRelease 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

Tree quiescence

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

Preventing ancestor identity bleed

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

1

Start

Run a fixed command and initialize JSON-RPC; do not publish before thread creation succeeds.

2

Isolate

thread/start requires ephemeral:true in the parent's workspace.

3

Execute

Accept only non-empty text blocks and start exactly one Turn.

4

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

Unattended safety

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

DimensionDeepSeek Harness pinned sourceCodex public documentation
Orchestration unitProvider-bound child Session/run; continuable children have durable IDsSubagent workflows and inspectable agent threads
Coordination ownerThe model calls tools explicitly; direct parents own follow-up, while runtime separates report from settlementCodex handles spawn, follow-up routing, wait, and close; the main thread consolidates results
Concurrency boundaryDistinct children may overlap; the subagent seam itself has no global concurrency capagents.max_concurrent_threads_per_session can cap concurrently open threads
Roles and configurationProvider, preset, persona/filter, and Agent options composeBuilt-in default/worker/explorer and project/personal TOML custom agents can override model, reasoning, sandbox, MCP, and skills
PermissionsWhen the corresponding services are composed, in-process children copy the explicit sandbox override and pin approval to neverSubagents 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.

Comparison

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 locationExternally visible resultResource semantics
Provider/capability/schema validationImmediate tool failure, no child IDNo provider work began
Unpublished create/handshakeStart rejects, no lifecycle edgeProvider/Agent factory rolls back partial resources
Post-publication model/transportstopReason:error, possibly partial outputHolder must still dispose
One corrupt catalog childDiagnostic rowOther children still list
Parent already goneSettlement notice is droppedChild Session retains the facts
Final flush/teardown failureWarning or error lifecycleOwnership 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

Runtime invariants

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

FindingEvidenceImpact
Fork-continuable claim conflicts with shipped presetsThe provider comment says no shipped caller; base is indeed one-shot, but Standard, Code, and Cordis presets all configure continuableThose 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 toolsPresets 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”
Reproducible drift

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

FormParent historyContinue after process restartLater messagesResult channel
Spawn one-shotNoneNoNoForeground result or Job
Fork one-shotCompleted-Turn prefixNoNoForeground result or Job
Spawn continuableNoneYes, with Session persistenceDirect-parent FIFOReport plus settlement notice
Fork continuableCompleted prefix captured once at creationTechnically supported; shipped configuration driftsDirect-parent FIFOReport plus settlement notice
ACP/Codex/Claude/SDKNone; at most the parent cwd (ACP/SDK may override)NoNoOne-shot result
Final assessment

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.

Verification status

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.