Address four findings from the first Codex review round:
- Contain subagent/start|end listener throws (emitContainedStart/End): a
thrown lifecycle listener could escape SubagentService.start() before the
caller received the live run to dispose it (a leaked child), and a thrown
subagent/end listener could surface as an unhandled rejection on the detached
result-settle hook. Both emits now log-and-contain, mirroring the agent
registry's agent/created|disposed containment.
- Make the model-facing tool name configurable (Config.toolName, default
subagent). The docs say to load dsh-tool-subagent once per provider to expose
multiple transports, but the hardcoded name made the second load throw a
duplicate-tool-name error; a distinct toolName per load is now required and
documented.
- Reach the per-file 100% coverage gate: tests for the subagent/end error
branch, lifecycle-listener containment, every stopReasonError arm + the
merge-extensible default, the multi-provider toolName path, agentOptions
forwarding, and the direct-apply schema-bypass fallbacks.
- Document the seam vocabulary in docs/core-data-structures/subagent.md with
verbatim type-equiv blocks + manifest entries, and link it from core.md (a
brand-new core/seam type the doc-sync gate cannot detect on its own).
Introduce the `packages/subagent/` group and the abstract subagent seam — an
agent delegating to a child agent — as a named-provider registry (`ctx.subagents`),
unlike the single-implementation bash seam, so multiple transports (in-process,
ACP, future A2A) coexist. This first PR lands the interface, a scripted test
backend, and the model-facing tool, validated through the real cordis load path.
- dsh-subagent: SubagentService registry + SubagentProvider/SubagentRun
vocabulary + subagent/start|end events. Start-time capabilities (outputSchema,
depthLimit, toolFilter) are checked pre-start and rejected loud; runtime
capabilities (sendMessage, resume) are optional methods on SubagentRun.
- dsh-subagent-mock (support): scripted provider for keyless, deterministic
tests through the real Loader/export path.
- dsh-tool-subagent: the model-facing `subagent` tool, config-bound to one
provider; synchronous collect with try/finally dispose, signal->cancel
bridging, and non-completed-stop-reason -> isError mapping.
- Proposed RFC documenting the seam, the fork-vs-spawn-as-separate-backends
decision, own-session isolation, synchronous-collect scope, and the deferral
of background/poll/spill to a future unification with bash.
- Wire the new group into tsconfigs, build refs, package hierarchy docs, the
module graph, and the cordis catalog.
RFC: docs/rfc/proposed/feature/2026-06-21-subagent-capability-seam.md