Files
deepseek-harness/docs/rfc/README.md
Tianyi Cui 7cc7b9cf7f feat(subagent): enrich subagent/start + subagent/end lifecycle events (observe-only)
A hooks bridge translating SubagentStart/SubagentStop needs to know WHICH kind of
subagent ran and WHAT it produced — Claude Code's hooks carry subagent_type and the
child's final message. Enrich the existing lifecycle emits to match, observe-only:

- agentType: an optional caller-supplied subagent-kind label (CC's subagent_type),
  added to SubagentStartRequest and carried VERBATIM onto both subagent/start
  (SubagentRunInfo) and subagent/end (SubagentRunEndInfo). The seam never interprets
  it. dsh-tool-subagent threads it from a new optional Config.agentType, so a
  deployment exposing multiple subagent kinds (one tool load per kind) labels each.
- lastAssistantMessage: the child's final output (SubagentResult.output), added to
  SubagentRunEndInfo on the settle path so an observer sees what the subagent
  produced without holding the run. Absent on the reject path (no result produced).

Strictly observe-only: both events stay plain emits (subagent/end fires from a
detached .then and awaits no listener). A control-flow subagent/end (awaited
waterfall returning a decision) would need the emit→waterfall reshape, awaiting
listeners before settling, and a provider resume capability — deferred to the
background/steering redesign (FIXME(subagent-continuation) anchors it). RFC:
implemented/feature/2026-06-30-subagent-observe-enrich.md.
2026-06-30 21:29:08 +08:00

15 KiB

RFCs

One kind of design doc lives here. An RFC records a decision or proposal that shapes this codebase — the why and what we gave up, the parts code and docs can't carry. (Earlier this split into separate "ADR" and "RFC" trees; they were unified, since most ADRs were simply implemented RFCs.)

Layout and naming

Every RFC has two axes, both encoded in its path{lifecycle}/{class}/yyyy-mm-dd-topic-title.md:

  • Lifecycle (the top-level folder) is the RFC's status, and an RFC moves between folders as that status changes:
    • proposed/ — proposals reviewed before implementation; not yet built (or only partly).
    • implemented/ — the decision shipped. The file records what was decided and what was rejected, and is kept current with what actually shipped: when the code later moves a file, renames a package, or changes a key/default, the RFC is updated in the same change to match (facts only — paths, names, structure — not the decision itself). See implemented/AGENTS.md.
    • rejected/ — the proposal was considered and declined. Kept for the record so the rejection isn't re-litigated.
  • Class (the nested folder) is the kind of decision — see Classification below.

The date in the filename is when the topic was first proposed (per git history). Cross-references between RFCs use relative markdown links ([topic](../../implemented/architecture/2026-…-….md)) — never bare prose or numbers — so they are mechanically checkable and survive moves between folders.

Classification

Each RFC is filed under exactly one class — the kind of decision it records. The class is encoded in the path (the folder is the label, so a file's location declares its class) and the set is closed: scripts/verify-rfc-classification.ts rejects any folder outside the set and asserts this index lists every RFC under the heading matching its path. Adding a new class means amending that gate and this section, not just dropping a new folder. See the classification RFC for why the taxonomy is path-encoded and gated.

Class What it covers
feature A new user- or model-facing capability.
bug-fix Corrects a defect or closes a gap a postmortem surfaced.
simplification Removes code, behavior, or surface area without adding a capability.
architecture A structural decision about the shipped source — how packages relate, what the runtime vocabulary is.
process Tooling, policy, or workflow around the code — gates, the package manager, vendoring — not runtime behavior.
testing Test infrastructure and strategy.

The architecture / process line: architecture is about the source we ship; process is the surrounding tooling and workflow. (refactor is deliberately absent — it overlaps simplification, whose discriminator, "does observable behavior change?", already covers it.)

When to write one

Write an RFC when a decision is durable (it shapes the codebase beyond a single function or package), contested (there was a real alternative a reasonable engineer might have chosen), and surprising (a future reader would otherwise ask "why on earth is it done this way?"). A proposal for substantial future work starts in proposed/; a decision already made starts in implemented/. Pick the class folder that matches the decision (see Classification).

Do NOT write one for a mechanical or local choice (a variable name, a one-file refactor), for anything already enforced and explained by a gate or a convention in AGENTS.md, or for a still-provisional decision tagged TODO(...) in the code — record those as TODOs and promote to an RFC only once they settle. An RFC is never edited into a different decision: supersede it with a new one and cross-link. (Editing an implemented/ RFC to track where its already-made decision now lives — a moved file, a renamed package — is not a different decision and is required, not forbidden; see implemented/AGENTS.md.)

Proposed

Feature

Title First proposed
Agent Client Protocol (ACP) support for external editors 2026-06-14
Multiplex concurrent ACP sessions over one connection 2026-06-14
Optional Code Mode — model writes TypeScript against an SDK of all tools 2026-06-15
Compaction as a capability seam (abstract contract + basic backend) 2026-06-18
Pre-tool input rewrite — a consistent design 2026-06-30

Simplification

Title First proposed
Unify the agent id and the session id 2026-06-20
Stop mirroring durable boundaries as agent events 2026-06-20

Architecture

Title First proposed
Runtime schemas for the event vocabulary (Zod vs the merge-extensible-map pattern) 2026-06-16
Extract a generic long-running tool runtime 2026-06-20

Process

Title First proposed
Architectural conformance — dependency rules and the adapter kit 2026-06-11
API extractor reports 2026-06-11
Supply chain checks and vendor drift verification 2026-06-11
Discover package inventories instead of maintaining static lists 2026-06-20

Testing

Title First proposed
Mutation testing as the coverage counterweight 2026-06-11
Deterministic tests, the replay invariant fixture, and race stress 2026-06-11

Implemented

Feature

Title First proposed
Rich ACP bash rendering — the terminal card (_meta) and command classification 2026-06-18
Subagent capability seam 2026-06-21
ACP subagent backend (out-of-process delegation) 2026-06-22
The todo_write tool — model task list as event-sourced session state 2026-06-29
Interception seams — the typed-Decision surface a hook programs against 2026-06-30
Subagent lifecycle enrichment — agentType + lastAssistantMessage (observe-only) 2026-06-30

Simplification

Title First proposed
Drop the mutable session summary 2026-06-19
Drop unconsumed assembled LLM convenience surfaces 2026-06-20
Drop the unconsumed llm/adapter-change event 2026-06-20
Prune dead methods from the persistence seam 2026-06-20
Keep one public stop primitive 2026-06-20
Fold trace-only session facts into load-bearing events 2026-06-20

Architecture

Title First proposed
Microkernel: extension via Cordis event taxonomy, one concrete loop 2026-06-11
Event-sourced sessions with derived message history 2026-06-11
Provider-neutral content-block vocabulary owned by dsh-llm 2026-06-11
Custom typed tool-schema DSL instead of schemastery 2026-06-11
Tool schemas are part of the system-prompt assembly 2026-06-11
Runtime arg validation at the model boundary 2026-06-11
Dev-mode invariants over compile-time deep-readonly 2026-06-11
Structured error taxonomy 2026-06-11
Capability seams — interface / implementation / consumer split 2026-06-13
Two LLM adapters as a design-verification twin 2026-06-13
Session persistence as an abstract service over SessionEvent 2026-06-14
Every session event is enclosed in a turn 2026-06-15
Shared persistence write coordinator 2026-06-18
Agent lifecycle and ownership seams 2026-06-18
Session surface — a linked list over the event log for LLM message derivation 2026-06-18
Reorganize packages into a modular hierarchy 2026-06-20
Branded IDs everywhere they belong 2026-06-20
Extract example apps into packages 2026-06-20
Event-domain semantics — session is the fact log, agent is the live surface 2026-06-30
stdin + extra env on the bash seam — a trusted-plugin surface 2026-06-30

Process

Title First proposed
Vendor Cordis as source, not npm dependencies 2026-06-11
Mechanical quality gates over prose guidelines 2026-06-11
tsdown for JS bundling instead of dumble 2026-06-11
Doc-sync enforcement 2026-06-11
pnpm as the package manager instead of Yarn 4 2026-06-16
TSC-first build and one tsconfig 2026-06-17
Markdown cross-link validity linting 2026-06-18
Core-data-structures catalog and the ts type-equiv drift gate 2026-06-20
Generated cordis events + services catalog 2026-06-20
Classify RFCs by kind via path-encoded subdirectories 2026-06-20

Testing

Title First proposed
Property-based testing for protocol-shaped code 2026-06-11
ACP snapshot tests — record-once / replay-deterministic 2026-06-19
Real-API e2e in CI against the external DeepSeek API 2026-06-19
Use session.jsonl as the only snapshot session-log artifact 2026-06-20
Per-session snapshot replay for nested agents 2026-06-22
Persist the seed boundary so fork-child replay routes correctly 2026-06-22
Record fork and mixed spawn+fork snapshot scenarios 2026-06-22

Rejected

Simplification

Title First proposed
Persist assembled assistant messages, not stream chunks 2026-06-20
Drop ACP session/load until resume has a product shape 2026-06-20
Drop ACP terminal _meta rendering 2026-06-20
Drop bash full-output spill files 2026-06-20
Drop durable step boundary events 2026-06-20
Drop unused session lineage metadata 2026-06-20
Fold the persistence interface into dsh-session 2026-06-20
Collapse tool-owned UI presentation 2026-06-20
Retire mid-turn steering 2026-06-20
Return the ACP bridge to one live session per connection 2026-06-20
Truncate interrupted final turns on load 2026-06-20

Architecture

Title First proposed
Deep-readonly public surfaces 2026-06-11
Make the shared example base providerless 2026-06-20