Files
deepseek-harness/docs/capability-seams.md
Tianyi Cui 3672cd25b4 feat(subprocess): migrate lsp-local, subagent-acp, and the env scrubs onto the seam
Review direction (tianyicui, PR #660): in a stacked PR, change all other
process-running places to use the new service.

- lsp-local: LspConnection spawns through ctx.subprocess (piped protocol
  streams + a no-spill collected stderr tail); its private process-tree
  helpers (POSIX group signalling, Windows taskkill, liveness polling) are
  deleted in favor of the seam's handle verbs, and its buildChildEnv now
  rides scrubbedParentEnv (LSP children also stop inheriting stale DSH_*).
  The plugin injects 'subprocess'; compositions/tests mount
  dsh-subprocess-local.
- subagent-acp: the ACP child spawns through the seam (piped ndjson streams,
  inherited stderr); spawn failure surfaces through done-rejection into the
  same startup race; disposal is handle.dispose with the plugin's configured
  graces. dsh-subagent-subprocess is DELETED — its dispose ladder and scrub
  are the seam's, and the isolated-config-dir helper had no consumer.
- mcp-client, pty-local, sdk-helper: adopt scrubbedParentEnv as the one
  scrub definition (their spawns stay put by ownership: the MCP SDK and
  node-pty own those calls; the SDK wizard runs outside any composition).
- Coverage: per-file 100% over every touched src file, with each v8 ignore
  carrying a platform or contract reason; new suites cover stdio
  dispositions, the dispose ladder tiers, injected-win32 tree semantics,
  waitForExit, settled-kill/terminate no-ops, and spawn-failure disposal.
- Docs: consumer-migration Agent Note (en; zh follows in this PR), seam note
  updated in place, subprocess.md rewritten for the reshaped vocabulary
  (type-equiv re-registered), READMEs and SERVICE_ROLES updated, taskkill
  added to knip ignoreBinaries.
2026-07-26 15:27:59 +08:00

26 KiB

Capability Seams And Core Services

A service can be a core spine service, a swappable capability seam, or a bundle/composition point. The graph shows the package that owns the service declaration, known implementation packages, and packages that consume the service directly.

flowchart LR
  pkg_llm["llm"]
  svc_llm["ctx.llm<br/>LLM adapter registry"]
  pkg_llm_deepseek["llm-deepseek"]
  pkg_llm_pi_ai["llm-pi-ai"]
  pkg_llm_replay["llm-replay"]
  pkg_agent_loop["agent-loop"]
  pkg_compact_basic["compact-basic"]
  pkg_token_meter["token-meter"]
  svc_tokenMeter["ctx.tokenMeter<br/>Replay token measurement"]
  pkg_compact_tool_result_prune["compact-tool-result-prune"]
  svc_toolResultPrune["ctx.toolResultPrune<br/>Model-free tool-result pruning"]
  pkg_session["session"]
  svc_sessions["ctx.sessions<br/>In-memory session store"]
  pkg_agent["agent"]
  pkg_cli_demo["cli-demo"]
  pkg_session_persistence["session-persistence"]
  pkg_session_query["session-query"]
  pkg_session_query_sqlite["session-query-sqlite"]
  pkg_subagent_inprocess["subagent-inprocess"]
  pkg_invariants["invariants"]
  svc_invariants["ctx.invariants<br/>Package-owned invariant registry"]
  pkg_scope["scope"]
  svc_sessionPersistence["ctx.sessionPersistence<br/>Durable session persistence seam"]
  pkg_session_persistence_jsonl["session-persistence-jsonl"]
  pkg_session_persistence_sqlite["session-persistence-sqlite"]
  pkg_tool_bash["tool-bash"]
  pkg_hooks_claude["hooks-claude"]
  pkg_hooks_codex["hooks-codex"]
  pkg_storage["storage"]
  svc_storage["ctx.storage<br/>Non-session storage hub"]
  pkg_storage_json["storage-json"]
  pkg_storage_sqlite["storage-sqlite"]
  pkg_storage_domain["storage-domain"]
  svc_storageDomain["ctx.storageDomain<br/>Domain data facility"]
  pkg_workspace["workspace"]
  svc_workspace["ctx.workspace<br/>Workspace entity registry"]
  pkg_apiproxy["apiproxy"]
  svc_sessionQuery["ctx.sessionQuery<br/>Session reads, traces, filters, and search"]
  pkg_session_reference["session-reference"]
  pkg_tool_session_query["tool-session-query"]
  svc_sessionReferences["ctx.sessionReferences<br/>Cross-session snapshot preparation"]
  pkg_tui["tui"]
  pkg_session_title["session-title"]
  svc_sessionTitle["ctx.sessionTitle<br/>Log-backed session titles"]
  pkg_session_title_first_message_llm["session-title-first-message-llm"]
  pkg_session_title_all_messages_llm["session-title-all-messages-llm"]
  pkg_system_prompt["system-prompt"]
  svc_systemPrompt["ctx.systemPrompt<br/>System prompt assembly registry"]
  pkg_tools["tools"]
  pkg_tool_fs["tool-fs"]
  pkg_tool_pty["tool-pty"]
  pkg_tool_web["tool-web"]
  svc_tools["ctx.tools<br/>Tool registry and guarded execution pipeline"]
  pkg_tool_ask_user["tool-ask-user"]
  pkg_tool_cordis["tool-cordis"]
  pkg_tool_skill["tool-skill"]
  pkg_tool_subagent["tool-subagent"]
  pkg_tool_todo["tool-todo"]
  pkg_user_interaction["user-interaction"]
  svc_userInteraction["ctx.userInteraction<br/>Human question/answer seam"]
  pkg_plan_mode["plan-mode"]
  svc_planMode["ctx.planMode<br/>Plan collaboration state"]
  pkg_commands["commands"]
  svc_commands["ctx.commands<br/>Human command registry"]
  svc_tui["ctx.tui<br/>Mounted-terminal interaction service"]
  pkg_skill["skill"]
  svc_skills["ctx.skills<br/>Skill provider registry"]
  pkg_skill_local["skill-local"]
  svc_agents["ctx.agents<br/>Agent service"]
  pkg_acp["acp"]
  pkg_tui_demo["tui-demo"]
  svc_agentLoop["ctx.agentLoop<br/>Concrete loop driver"]
  pkg_agent_spine_demo["agent-spine-demo"]
  pkg_goal["goal"]
  svc_goals["ctx.goals<br/>Same-session goal domain"]
  pkg_subprocess["subprocess"]
  svc_subprocess["ctx.subprocess<br/>Subprocess seam"]
  pkg_subprocess_local["subprocess-local"]
  pkg_bash_local["bash-local"]
  pkg_bash_sandbox["bash-sandbox"]
  pkg_lsp_local["lsp-local"]
  pkg_subagent_acp["subagent-acp"]
  pkg_bash["bash"]
  svc_bash["ctx.bash<br/>Bash executor seam"]
  svc_bashEnv["ctx.bashEnv<br/>Managed bash environment registry"]
  pkg_pty["pty"]
  svc_pty["ctx.pty<br/>Persistent PTY session registry"]
  pkg_pty_local["pty-local"]
  pkg_sandbox["sandbox"]
  svc_sandbox["ctx.sandbox<br/>Process-sandbox seam"]
  pkg_sandbox_local["sandbox-local"]
  pkg_sandbox_policy["sandbox-policy"]
  svc_sandboxPolicy["ctx.sandboxPolicy<br/>Sandbox policy home"]
  pkg_fs_sandbox["fs-sandbox"]
  pkg_approval["approval"]
  svc_approval["ctx.approval<br/>Approval seam"]
  pkg_permission["permission"]
  svc_permission["ctx.permission<br/>Permission presets"]
  pkg_code_runtime["code-runtime"]
  svc_codeRuntime["ctx.codeRuntime<br/>Code-execution seam"]
  pkg_code_runtime_worker["code-runtime-worker"]
  pkg_fs["fs"]
  svc_fs["ctx.fs<br/>Filesystem provider seam"]
  pkg_fs_local["fs-local"]
  pkg_fs_policy["fs-policy"]
  pkg_compact["compact"]
  svc_compact["ctx.compact<br/>Compaction seam"]
  pkg_subagent["subagent"]
  svc_subagents["ctx.subagents<br/>Subagent provider registry"]
  pkg_subagent_spawn["subagent-spawn"]
  pkg_subagent_fork["subagent-fork"]
  pkg_tool_ralph["tool-ralph"]
  pkg_tasks["tasks"]
  svc_tasks["ctx.tasks<br/>Background task registry"]
  pkg_tasks_local["tasks-local"]
  pkg_tool_tasks["tool-tasks"]
  pkg_web["web"]
  svc_web["ctx.web<br/>Web access provider registry"]
  pkg_web_search_exa["web-search-exa"]
  pkg_web_search_perplexity["web-search-perplexity"]
  pkg_web_search_deepseek["web-search-deepseek"]
  pkg_web_fetch_local["web-fetch-local"]
  pkg_spill["spill"]
  svc_spillStore["ctx.spillStore<br/>Spill storage seam"]
  pkg_spill_local["spill-local"]
  pkg_spill_policy["spill-policy"]
  pkg_webserver["webserver"]
  svc_httpServer["ctx.httpServer<br/>HTTP route registration"]
  pkg_connection["connection"]
  pkg_modules["modules"]
  pkg_hmr["hmr"]
  svc_clientModuleHost["ctx.clientModuleHost<br/>Client plugin graph host"]
  pkg_workflow["workflow"]
  svc_workflows["ctx.workflows<br/>Workflow script engine"]
  pkg_workflow_workerthread["workflow-workerthread"]
  pkg_tool_workflow["tool-workflow"]
  pkg_acp --> svc_approval
  pkg_agent --> svc_agents
  pkg_agent_loop --> svc_agentLoop
  pkg_approval --> svc_approval
  pkg_bash --> svc_bash
  pkg_bash_local --> svc_bash
  pkg_bash_sandbox --> svc_bash
  pkg_code_runtime --> svc_codeRuntime
  pkg_code_runtime_worker --> svc_codeRuntime
  pkg_commands --> svc_commands
  pkg_compact --> svc_compact
  pkg_compact_basic --> svc_compact
  pkg_compact_tool_result_prune --> svc_toolResultPrune
  pkg_fs --> svc_fs
  pkg_fs_local --> svc_fs
  pkg_fs_sandbox --> svc_fs
  pkg_goal --> svc_goals
  pkg_invariants --> svc_invariants
  pkg_llm --> svc_llm
  pkg_llm_deepseek --> svc_llm
  pkg_llm_pi_ai --> svc_llm
  pkg_llm_replay --> svc_llm
  pkg_modules --> svc_clientModuleHost
  pkg_permission --> svc_permission
  pkg_plan_mode --> svc_planMode
  pkg_pty --> svc_pty
  pkg_pty_local --> svc_pty
  pkg_sandbox --> svc_sandbox
  pkg_sandbox_local --> svc_sandbox
  pkg_sandbox_policy --> svc_sandboxPolicy
  pkg_session --> svc_sessions
  pkg_session_persistence --> svc_sessionPersistence
  pkg_session_persistence_jsonl --> svc_sessionPersistence
  pkg_session_persistence_sqlite --> svc_sessionPersistence
  pkg_session_query --> svc_sessionQuery
  pkg_session_query_sqlite --> svc_sessionQuery
  pkg_session_reference --> svc_sessionReferences
  pkg_session_title --> svc_sessionTitle
  pkg_session_title_all_messages_llm --> svc_sessionTitle
  pkg_session_title_first_message_llm --> svc_sessionTitle
  pkg_skill --> svc_skills
  pkg_skill_local --> svc_skills
  pkg_spill --> svc_spillStore
  pkg_spill_local --> svc_spillStore
  pkg_storage --> svc_storage
  pkg_storage_domain --> svc_storageDomain
  pkg_storage_json --> svc_storage
  pkg_storage_sqlite --> svc_storage
  pkg_subagent --> svc_subagents
  pkg_subagent_acp --> svc_subagents
  pkg_subagent_fork --> svc_subagents
  pkg_subagent_spawn --> svc_subagents
  pkg_subprocess --> svc_subprocess
  pkg_subprocess_local --> svc_subprocess
  pkg_system_prompt --> svc_systemPrompt
  pkg_tasks --> svc_tasks
  pkg_tasks_local --> svc_tasks
  pkg_token_meter --> svc_tokenMeter
  pkg_tool_bash --> svc_bashEnv
  pkg_tools --> svc_tools
  pkg_tui --> svc_tui
  pkg_tui --> svc_userInteraction
  pkg_user_interaction --> svc_userInteraction
  pkg_web --> svc_web
  pkg_web_fetch_local --> svc_web
  pkg_web_search_deepseek --> svc_web
  pkg_web_search_exa --> svc_web
  pkg_web_search_perplexity --> svc_web
  pkg_webserver --> svc_httpServer
  pkg_workflow --> svc_workflows
  pkg_workflow_workerthread --> svc_workflows
  pkg_workspace --> svc_workspace
  svc_agentLoop --> pkg_agent_spine_demo
  svc_agents --> pkg_acp
  svc_agents --> pkg_agent_loop
  svc_agents --> pkg_cli_demo
  svc_agents --> pkg_subagent_inprocess
  svc_agents --> pkg_tui_demo
  svc_approval --> pkg_tool_bash
  svc_approval --> pkg_tools
  svc_bash --> pkg_hooks_claude
  svc_bash --> pkg_hooks_codex
  svc_bash --> pkg_tool_bash
  svc_clientModuleHost --> pkg_hmr
  svc_codeRuntime --> pkg_tools
  svc_commands --> pkg_tui
  svc_compact --> pkg_compact_basic
  svc_fs --> pkg_tool_fs
  svc_httpServer --> pkg_connection
  svc_httpServer --> pkg_hmr
  svc_httpServer --> pkg_modules
  svc_invariants --> pkg_agent
  svc_invariants --> pkg_agent_loop
  svc_invariants --> pkg_scope
  svc_invariants --> pkg_session
  svc_llm --> pkg_agent_loop
  svc_llm --> pkg_compact_basic
  svc_pty --> pkg_tool_pty
  svc_sandbox --> pkg_bash_sandbox
  svc_sandbox --> pkg_pty_local
  svc_sandboxPolicy --> pkg_bash_sandbox
  svc_sandboxPolicy --> pkg_fs_sandbox
  svc_sandboxPolicy --> pkg_pty_local
  svc_sessionPersistence --> pkg_agent_loop
  svc_sessionPersistence --> pkg_hooks_claude
  svc_sessionPersistence --> pkg_hooks_codex
  svc_sessionPersistence --> pkg_session_query
  svc_sessionPersistence --> pkg_session_query_sqlite
  svc_sessionPersistence --> pkg_tool_bash
  svc_sessionQuery --> pkg_session_reference
  svc_sessionQuery --> pkg_tool_session_query
  svc_sessionReferences --> pkg_tui
  svc_sessions --> pkg_agent
  svc_sessions --> pkg_agent_loop
  svc_sessions --> pkg_cli_demo
  svc_sessions --> pkg_invariants
  svc_sessions --> pkg_session_persistence
  svc_sessions --> pkg_session_query
  svc_sessions --> pkg_session_query_sqlite
  svc_sessions --> pkg_subagent_inprocess
  svc_skills --> pkg_tool_skill
  svc_spillStore --> pkg_spill_policy
  svc_storage --> pkg_storage_domain
  svc_storageDomain --> pkg_workspace
  svc_subagents --> pkg_tool_ralph
  svc_subagents --> pkg_tool_subagent
  svc_subprocess --> pkg_bash_local
  svc_subprocess --> pkg_bash_sandbox
  svc_subprocess --> pkg_lsp_local
  svc_subprocess --> pkg_subagent_acp
  svc_systemPrompt --> pkg_agent_loop
  svc_systemPrompt --> pkg_tool_fs
  svc_systemPrompt --> pkg_tool_pty
  svc_systemPrompt --> pkg_tool_web
  svc_systemPrompt --> pkg_tools
  svc_tasks --> pkg_tool_bash
  svc_tasks --> pkg_tool_pty
  svc_tasks --> pkg_tool_subagent
  svc_tasks --> pkg_tool_tasks
  svc_tokenMeter --> pkg_compact_basic
  svc_toolResultPrune --> pkg_compact_basic
  svc_tools --> pkg_agent_loop
  svc_tools --> pkg_tool_ask_user
  svc_tools --> pkg_tool_bash
  svc_tools --> pkg_tool_cordis
  svc_tools --> pkg_tool_fs
  svc_tools --> pkg_tool_pty
  svc_tools --> pkg_tool_skill
  svc_tools --> pkg_tool_subagent
  svc_tools --> pkg_tool_todo
  svc_tools --> pkg_tool_web
  svc_userInteraction --> pkg_tool_ask_user
  svc_userInteraction --> pkg_tui
  svc_web --> pkg_tool_web
  svc_workflows --> pkg_tool_ralph
  svc_workflows --> pkg_tool_workflow
  svc_workspace --> pkg_apiproxy
  svc_fs -. event gate .-> pkg_fs_policy
ctx key Role Owner Implementations Direct consumers Companion plugins Note
ctx.llm seam llm llm-deepseek, llm-pi-ai, llm-replay agent-loop, compact-basic - Adapters register provider implementations; the loop and compaction call the provider-neutral stream service.
ctx.tokenMeter core token-meter - compact-basic - Owns isolated per-session replay folds; pressure consumers share immutable revisioned measurements.
ctx.toolResultPrune core compact-tool-result-prune - compact-basic - Rewrites oversized current tool results through replayable single-node surface replacements before summary compaction.
ctx.sessions core session - agent-loop, agent, cli-demo, session-persistence, session-query, session-query-sqlite, subagent-inprocess, invariants - Owns append-only Session instances and emits the durable session event feed.
ctx.invariants core invariants - session, agent, scope, agent-loop - Companion subpaths register owner-local checks; the service owns selection, uniqueness, child fibers, and package-attributed failures.
ctx.sessionPersistence seam session-persistence session-persistence-jsonl, session-persistence-sqlite agent-loop, tool-bash, hooks-claude, hooks-codex, session-query, session-query-sqlite - Backends persist the same SessionEvent vocabulary; apps choose a backend at composition time.
ctx.storage seam storage storage-json, storage-sqlite storage-domain - Backends register side by side under names; data forms (domain first) mount on the hub and translate typed operations into opaque KV-unit primitives.
ctx.storageDomain core storage-domain - workspace - Waits for every configured backend, then publishes the domain form as one lifecycle-bound service for typed durable state.
ctx.workspace core workspace - apiproxy - Owns WorkspaceId-branded records over the domain facility; stable sessionIds accounts drive Host RPC and GUI projections.
ctx.sessionQuery seam session-query session-query-sqlite session-reference, tool-session-query - The interface supplies exact reads, filters, and traces; its concrete backend adds full-text reconciliation, ranking, snippets, and cursor generations, while the model consumer owns workspace authority and cursor-free rendering.
ctx.sessionReferences core session-reference - tui - Projects bounded current-surface conversation snapshots into durable untrusted message context; host adapters own mention syntax.
ctx.sessionTitle seam session-title session-title-first-message-llm, session-title-all-messages-llm - - Owns the deterministic fallback, latest-title fold, and sole optional asynchronous provider registration.
ctx.systemPrompt core system-prompt - agent-loop, tools, tool-fs, tool-pty, tool-web - Collects prompt sections and model-facing tool schemas for each step.
ctx.tools core tools - agent-loop, tool-ask-user, tool-bash, tool-cordis, tool-fs, tool-pty, tool-skill, tool-subagent, tool-todo, tool-web - Registers capabilities, owns Code Mode transport, and routes calls through pre-policy, monotonic guards, around dispatch, post-policy, and final-result observation.
ctx.userInteraction seam user-interaction tui tool-ask-user, tui - UI front doors provide the active human-answer provider; tool-ask-user pauses a tool call on the provider-neutral ask() promise.
ctx.planMode core plan-mode - - - Folds logged plan/mode state, flushes user selections at turn boundaries, renders deployment-owned guidance, registers /plan, and keeps the plan-exit schema stable across transitions.
ctx.commands core commands - tui - Plugins register direct human commands; TUI consumes the effective per-agent catalog without sending invocations to the model.
ctx.tui bundle tui - - - One TUI front door provides a FIFO overlay host; injected plugins receive caller-fiber ownership without access to pi-tui or terminal lifecycle state.
ctx.skills seam skill skill-local tool-skill - Merges provider skill catalogs; tool-skill renders the session-prefix catalog and loads complete skill bodies.
ctx.agents core agent - agent-loop, acp, cli-demo, subagent-inprocess, tui-demo - Owns live Agent handles, the create/resume factory seam, and process-local initiator propagation.
ctx.agentLoop bundle agent-loop - agent-spine-demo - The one concrete loop plugin; extension packages depend on dsh-agent events and services, not on this package.
ctx.goals core goal - - - Folds revisioned objective state from the session log and keeps live continuation activation process-local.
ctx.subprocess seam subprocess subprocess-local bash-local, bash-sandbox, lsp-local, subagent-acp - The bash executors, the LSP host, and the ACP subagent backend spawn their children through ctx.subprocess; the service owns tree lifetime, stdio dispositions (pipes, inherit, bounded spill-backed collection), and kill escalation.
ctx.bash seam bash bash-local, bash-sandbox tool-bash, hooks-claude, hooks-codex - The model-facing bash tools and hook bridges consume this seam; sandboxed or remote executors replace bash-local without touching them.
ctx.bashEnv core tool-bash - - - Plugins declare effect-scoped DSH_* facts; tool-bash collects one trusted snapshot per execution and the executor rebuilds the namespace.
ctx.pty seam pty pty-local tool-pty - The registry owns exact-Agent session identity and cleanup; backends own terminal mechanics, while tool-pty exposes the owner-scoped model surface.
ctx.sandbox seam sandbox sandbox-local bash-sandbox, pty-local - Consumers hand over the exact argv they are about to spawn; same-world backends wrap it under a per-call policy and report enforcement.
ctx.sandboxPolicy core sandbox-policy - bash-sandbox, fs-sandbox, pty-local - The one home for the deployment default mode + workspace root; only the sandboxed executor and provider read the service (the tool layers use the pure sandbox/mode fold it also exports). Both enforcing families read it so bash and fs cannot confine to different roots.
ctx.approval seam approval acp tools, tool-bash - One-shot permission decisions dispatched over the approval/request waterfall; answerers are listeners (the ACP bridge for its own agents), absence fails closed to unavailable.
ctx.permission core permission - - - User-facing preset table (workspace-write/danger-full-access) bundling the sandbox-mode and approval-policy knobs; a switch writes one permission/preset event through to both knob events.
ctx.codeRuntime seam code-runtime code-runtime-worker tools - Runs one model-written program against host-provided async bindings; backends differ by substrate and language (the tool registry consumes it for Code Mode).
ctx.fs seam fs fs-local, fs-sandbox tool-fs fs-policy tool-fs executes read/write/edit through ctx.fs; fs-sandbox fences mutations by the shared sandbox mode; fs-policy contributes observed-state checks through the fs/* event gate.
ctx.compact seam compact compact-basic compact-basic - The basic backend consumes post-step pressure and request-error recovery events; a model-facing compact tool remains deferred.
ctx.subagents seam subagent subagent-spawn, subagent-fork, subagent-acp tool-subagent, tool-ralph - Providers implement transports; tool-subagent exposes configured delegation while tool-ralph requires one fresh structured-output route.
ctx.tasks seam tasks tasks-local tool-bash, tool-pty, tool-subagent, tool-tasks - Producers (background bash, PTY sends, and subagent delegations) register running work; tool-tasks is the model-facing control surface that reads, lists, and kills it; tasks-local is the process-local registry.
ctx.web seam web web-search-exa, web-search-perplexity, web-search-deepseek, web-fetch-local tool-web - Search and fetch providers register into one ctx.web seam; tool-web owns the stable model-facing names.
ctx.spillStore seam spill spill-local spill-policy - The backend saves oversized tool text and returns a model-facing locator plus retrieval hint; spill-policy is the tools/post-execute consumer that decides when to spill.
ctx.httpServer core webserver - connection, modules, hmr - Plain node:http carrier: named-route registry, index transform taps, and the static dist fallback; web-transport plugins register their own routes.
ctx.clientModuleHost core modules - hmr - Composes the DSH_BOOT entry graph from an incremental dshClient scan, serves plugin bundles, and notifies rebuilt/graph-changed subscribers.
ctx.workflows seam workflow workflow-workerthread tool-workflow, tool-ralph - One engine per context (bash shape, no named-provider registry); the general workflow and fixed Ralph consumers start runs whose agent() calls fan out through ctx.subagents.

Maintenance mode: hybrid: services are discovered from Cordis declarations; interface/implementation/consumer roles are classified in scripts/gen-doc-graphs.ts with a completeness guard.