Merge master into worktree/semantic-session-checkpoints

This commit is contained in:
Tianyi Cui
2026-07-22 20:50:46 +08:00
611 changed files with 42224 additions and 1190 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
architecture.md: 40bffd4869a89cd6047bdb15d9b7f43a4fe60711
architecture.zh.md: eba79bcf0ed06883be2b808c8a7eec40807b37a2
architecture.md: d1a69f18f0ff043045a768f1972ea9687cbed21b
architecture.zh.md: 1a870b26a2866999f323bc3d91300d5b4792033d

View File

@@ -14,7 +14,7 @@ Harnesses are [Cordis](cordis-primer.md) contexts whose packages contribute serv
| ctx key | Package | Role |
|---|---|---|
| — | [`dsh-scope`](../packages/core/scope/README.md) | scoped-context registration primitive (library) |
| — | [`dsh-scope`](../packages/core/scope/README.md) | scoped-context registration and shared layer storage (library) |
| `ctx.sessions` | `dsh-session` | in-memory event-sourced sessions |
| `ctx.systemPrompt` | `dsh-system-prompt` | ordered prompt sections, tool schemas, and prompt variables |
| `ctx.tools` | `dsh-tools` | tool registry and [execution pipeline](tool-execution-pipeline.md) |
@@ -37,6 +37,7 @@ Harnesses are [Cordis](cordis-primer.md) contexts whose packages contribute serv
| `ctx.web` | [`web/`](../packages/web/README.md) | search/fetch provider registries |
| `ctx.compact`, `ctx.toolResultPrune` | [`compact/`](../packages/compact/README.md)/[`compact-tool-result-prune`](../packages/compact/compact-tool-result-prune/README.md) | summary compaction; optional model-free result pruning |
| `ctx.subagents` | [`subagent/`](../packages/subagent/README.md) | named delegation providers |
| `ctx.planMode` | [`plan/`](../packages/plan/README.md) | logged plan collaboration state |
| `ctx.tasks` | [`tasks/`](../packages/tasks/README.md) | background task registry + generic `task_*` control tools |
| `ctx.workflows` | [`workflow/`](../packages/workflow/README.md) | script-driven multi-agent orchestration |
| `ctx.goals` | [`goal/`](../packages/goal/README.md) | persisted same-session goals |
@@ -133,7 +134,7 @@ Session events are turn-enclosed. Reload closes an interrupted tail with a synth
### Agent Scope
Each agent owns a scoped `agent.ctx`; registrations shadow globals, filter dispatch, and unwind with awaited cleanup. `CreateAgentOptions.setup(agentCtx)` composes before publication. Typed resolvers derive carrier checks from merged `Events` and `scopeTarget` ([semantic gates](../.agents/notes/implemented/process/2026-07-14-typescript-program-backed-semantic-gates.md)). See [agent scope](../.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md) and [subagent composition](../.agents/notes/implemented/feature/2026-07-12-subagent-persona-tool-filter-and-depth.md). `AgentLoop` runs inside `ctx.agents.withInitiator()`; private orchestration derives `agent.session`, while turn, step, signal, cwd, and authority remain explicit ([decision](../.agents/notes/implemented/architecture/2026-07-15-agent-initiator-scope.md)).
Each agent owns a scoped `agent.ctx`; shared storage overlays global tool, prompt, and command entries while preserving domain views ([decision](../.agents/notes/implemented/architecture/2026-07-12-scoped-layers-store.md)). Scoped listeners filter dispatch, and every scoped contribution unwinds with awaited cleanup. `CreateAgentOptions.setup(agentCtx)` composes before publication. Typed resolvers derive carrier checks from merged `Events` and `scopeTarget` ([semantic gates](../.agents/notes/implemented/process/2026-07-14-typescript-program-backed-semantic-gates.md)). See [agent scope](../.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md) and [subagent composition](../.agents/notes/implemented/feature/2026-07-12-subagent-persona-tool-filter-and-depth.md). `AgentLoop` runs inside `ctx.agents.withInitiator()`; private orchestration derives `agent.session`, while turn, step, signal, cwd, and authority remain explicit ([decision](../.agents/notes/implemented/architecture/2026-07-15-agent-initiator-scope.md)).
## State

View File

@@ -14,7 +14,7 @@
| ctx 键 | 包 | 职责 |
|---|---|---|
| — | [`dsh-scope`](../packages/core/scope/README.md) | 作用域上下文注册原语(库) |
| — | [`dsh-scope`](../packages/core/scope/README.md) | 作用域上下文注册与共享层存储(库) |
| `ctx.sessions` | `dsh-session` | 内存中的事件溯源会话 |
| `ctx.systemPrompt` | `dsh-system-prompt` | 有序提示词片段、工具 schema 和提示词变量 |
| `ctx.tools` | `dsh-tools` | 工具注册表和[执行流水线](tool-execution-pipeline.md) |
@@ -37,6 +37,7 @@
| `ctx.web` | [`web/`](../packages/web/README.md) | 搜索与抓取提供方注册表 |
| `ctx.compact``ctx.toolResultPrune` | [`compact/`](../packages/compact/README.md)/[`compact-tool-result-prune`](../packages/compact/compact-tool-result-prune/README.md) | 摘要压缩compaction可选的无模型结果裁剪 |
| `ctx.subagents` | [`subagent/`](../packages/subagent/README.md) | 具名委托提供方 |
| `ctx.planMode` | [`plan/`](../packages/plan/README.md) | 落日志的 plan 协作状态 |
| `ctx.tasks` | [`tasks/`](../packages/tasks/README.md) | 后台任务注册表和通用 `task_*` 控制工具 |
| `ctx.workflows` | [`workflow/`](../packages/workflow/README.md) | 脚本驱动的多 agent 编排 |
| `ctx.goals` | [`goal/`](../packages/goal/README.md) | 持久化的同会话目标 |
@@ -133,7 +134,7 @@ forever:
### Agent 作用域
每个 agent 都拥有一个作用域化的 `agent.ctx`注册项会遮蔽全局项、过滤分派,并在撤销时等待清理完成。`CreateAgentOptions.setup(agentCtx)` 在发布前完成组合。类型化解析器从合并后的 `Events``scopeTarget` 推导载体检查([语义门禁](../.agents/notes/implemented/process/2026-07-14-typescript-program-backed-semantic-gates.md))。参见 [agent 作用域](../.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md)和 [subagent 组合](../.agents/notes/implemented/feature/2026-07-12-subagent-persona-tool-filter-and-depth.md)。`AgentLoop``ctx.agents.withInitiator()` 内运行;私有编排会派生 `agent.session`而轮次、步骤、信号、cwd 和权限仍保持显式([决策](../.agents/notes/implemented/architecture/2026-07-15-agent-initiator-scope.md))。
每个 agent 都拥有一个作用域化的 `agent.ctx`共享存储会在全局工具、提示词和命令条目之上叠加作用域条目,同时保留各领域视图([决策](../.agents/notes/implemented/architecture/2026-07-12-scoped-layers-store.md))。作用域监听器会过滤分派,每项作用域贡献都会在撤销时等待清理完成。`CreateAgentOptions.setup(agentCtx)` 在发布前完成组合。类型化解析器从合并后的 `Events``scopeTarget` 推导载体检查([语义门禁](../.agents/notes/implemented/process/2026-07-14-typescript-program-backed-semantic-gates.md))。参见 [agent 作用域](../.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md)和 [subagent 组合](../.agents/notes/implemented/feature/2026-07-12-subagent-persona-tool-filter-and-depth.md)。`AgentLoop``ctx.agents.withInitiator()` 内运行;私有编排会派生 `agent.session`而轮次、步骤、信号、cwd 和权限仍保持显式([决策](../.agents/notes/implemented/architecture/2026-07-15-agent-initiator-scope.md))。
## 状态

View File

@@ -54,6 +54,8 @@ flowchart LR
pkg_user_interaction["user-interaction"]
svc_userInteraction["ctx.userInteraction<br/>Human question/answer seam"]
pkg_tui["tui"]
pkg_plan_mode["plan-mode"]
svc_planMode["ctx.planMode<br/>Plan collaboration state"]
pkg_commands["commands"]
svc_commands["ctx.commands<br/>Human command registry"]
pkg_skill["skill"]
@@ -136,6 +138,7 @@ flowchart LR
pkg_llm_pi_ai --> svc_llm
pkg_llm_replay --> svc_llm
pkg_permission --> svc_permission
pkg_plan_mode --> svc_planMode
pkg_sandbox --> svc_sandbox
pkg_sandbox_local --> svc_sandbox
pkg_sandbox_policy --> svc_sandboxPolicy
@@ -192,6 +195,7 @@ flowchart LR
svc_llm --> pkg_agent_loop
svc_llm --> pkg_compact_basic
svc_permission --> pkg_acp
svc_planMode --> pkg_acp
svc_sandbox --> pkg_bash_sandbox
svc_sandboxPolicy --> pkg_bash_sandbox
svc_sandboxPolicy --> pkg_fs_sandbox
@@ -252,6 +256,7 @@ flowchart LR
| `ctx.systemPrompt` | `core` | [`system-prompt`](../packages/core/system-prompt) | - | [`agent-loop`](../packages/core/agent-loop), [`tools`](../packages/core/tools), [`tool-fs`](../packages/fs/tool-fs), [`tool-web`](../packages/web/tool-web) | - | Collects prompt sections and model-facing tool schemas for each step. |
| `ctx.tools` | `core` | [`tools`](../packages/core/tools) | - | [`agent-loop`](../packages/core/agent-loop), [`tool-ask-user`](../packages/ui/tool-ask-user), [`tool-bash`](../packages/bash/tool-bash), [`tool-cordis`](../packages/cordis/tool-cordis), [`tool-fs`](../packages/fs/tool-fs), [`tool-skill`](../packages/skill/tool-skill), [`tool-subagent`](../packages/subagent/tool-subagent), [`tool-todo`](../packages/todo/tool-todo), [`tool-web`](../packages/web/tool-web), [`acp`](../packages/ui/acp) | - | 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`](../packages/ui/user-interaction) | [`tui`](../packages/ui/tui), [`acp`](../packages/ui/acp) | [`tool-ask-user`](../packages/ui/tool-ask-user), [`tui`](../packages/ui/tui), [`acp`](../packages/ui/acp) | - | 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`](../packages/plan/plan-mode) | - | [`acp`](../packages/ui/acp) | - | 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`](../packages/ui/commands) | - | [`tui`](../packages/ui/tui), [`acp`](../packages/ui/acp) | - | Plugins register direct human commands; TUI and ACP consume the same effective per-agent catalog without sending invocations to the model. |
| `ctx.skills` | `seam` | [`skill`](../packages/skill/skill) | [`skill-local`](../packages/skill/skill-local) | [`tool-skill`](../packages/skill/tool-skill) | - | Merges provider skill catalogs; tool-skill renders the session-prefix catalog and loads complete skill bodies. |
| `ctx.agents` | `core` | [`agent`](../packages/core/agent) | - | [`agent-loop`](../packages/core/agent-loop), [`acp`](../packages/ui/acp), [`cli-demo`](../packages/examples/cli-demo), [`subagent-inprocess`](../packages/subagent/subagent-inprocess), [`tui-demo`](../packages/examples/tui-demo) | - | Owns live Agent handles, the create/resume factory seam, and process-local initiator propagation. |

View File

@@ -27,7 +27,7 @@ export interface AcpConfig {
Depends on: `Stream` (`@agentclientprotocol/sdk`)
Source: [`packages/ui/acp/src/index.ts:254`](../packages/ui/acp/src/index.ts)
Source: [`packages/ui/acp/src/index.ts:275`](../packages/ui/acp/src/index.ts)
## `@deepseek-ai/dsh-acp-demo`
@@ -786,6 +786,20 @@ Depends on: [`ApprovalPolicy`](core-data-structures/approval.md) · [`SandboxMod
Source: [`packages/ui/permission/src/index.ts:83`](../packages/ui/permission/src/index.ts)
## `@deepseek-ai/dsh-plan-mode`
Requires: `tools` · `systemPrompt`
```ts config-catalog
/** Deployment-owned plan guidance. */
export interface PlanModeConfig {
/** Guidance rendered as the `plan:policy` prompt section while plan mode is active. */
section: string
}
```
Source: [`packages/plan/plan-mode/src/index.ts:57`](../packages/plan/plan-mode/src/index.ts)
## `@deepseek-ai/dsh-repeat-tool-guard`
```ts config-catalog
@@ -1572,7 +1586,7 @@ export interface Config {
export type ApprovalPolicy = 'ask' | 'never'
```
Source: [`packages/ui/user-approval/src/index.ts:214`](../packages/ui/user-approval/src/index.ts)
Source: [`packages/ui/user-approval/src/index.ts:198`](../packages/ui/user-approval/src/index.ts)
## `@deepseek-ai/dsh-web`
@@ -1738,6 +1752,14 @@ Source: [`packages/context/workspace-context/src/config.ts:16`](../packages/cont
These load from a `cordis.yml` entry with no `config:` block; they declare no config surface.
- `@deepseek-ai/dsh-agent` ([`packages/core/agent/src/index.ts`](../packages/core/agent/src/index.ts))
- `@deepseek-ai/dsh-client-connection` ([`packages/client/connection/src/index.ts`](../packages/client/connection/src/index.ts))
- `@deepseek-ai/dsh-client-i18n` ([`packages/client/i18n/src/index.ts`](../packages/client/i18n/src/index.ts))
- `@deepseek-ai/dsh-client-runtime` ([`packages/client/runtime/src/index.ts`](../packages/client/runtime/src/index.ts))
- `@deepseek-ai/dsh-client-ui-conversation` ([`packages/client/ui-conversation/src/index.ts`](../packages/client/ui-conversation/src/index.ts))
- `@deepseek-ai/dsh-client-ui-layout` ([`packages/client/ui-layout/src/index.ts`](../packages/client/ui-layout/src/index.ts))
- `@deepseek-ai/dsh-client-ui-sidebar` ([`packages/client/ui-sidebar/src/index.ts`](../packages/client/ui-sidebar/src/index.ts))
- `@deepseek-ai/dsh-client-ui-theme` ([`packages/client/ui-theme/src/index.ts`](../packages/client/ui-theme/src/index.ts))
- `@deepseek-ai/dsh-client-ui-trajectory` ([`packages/client/ui-trajectory/src/index.ts`](../packages/client/ui-trajectory/src/index.ts))
- `@deepseek-ai/dsh-command-goal` — requires `commands` · `goals` ([`packages/goal/command-goal/src/index.ts`](../packages/goal/command-goal/src/index.ts))
- `@deepseek-ai/dsh-commands` ([`packages/ui/commands/src/index.ts`](../packages/ui/commands/src/index.ts))
- `@deepseek-ai/dsh-fs-policy` ([`packages/fs/fs-policy/src/index.ts`](../packages/fs/fs-policy/src/index.ts))
@@ -1775,8 +1797,15 @@ Imported as libraries by other packages; a `cordis.yml` cannot load them.
- `@deepseek-ai/dsh-agent-loop-testkit` ([`packages/support/agent-loop-testkit/src/index.ts`](../packages/support/agent-loop-testkit/src/index.ts))
- `@deepseek-ai/dsh-app-boot` ([`packages/ui/app-boot/src/index.ts`](../packages/ui/app-boot/src/index.ts))
- `@deepseek-ai/dsh-brand` ([`packages/util/brand/src/index.ts`](../packages/util/brand/src/index.ts))
- `@deepseek-ai/dsh-client-ui-primitives` ([`packages/client/ui-primitives/src/index.ts`](../packages/client/ui-primitives/src/index.ts))
- `@deepseek-ai/dsh-client-ui-slots` ([`packages/client/ui-slots/src/index.ts`](../packages/client/ui-slots/src/index.ts))
- `@deepseek-ai/dsh-client-web` ([`packages/client/web/src/index.ts`](../packages/client/web/src/index.ts))
- `@deepseek-ai/dsh-client-web-react` ([`packages/client/web-react/src/index.ts`](../packages/client/web-react/src/index.ts))
- `@deepseek-ai/dsh-helper` ([`packages/sdk/helper/src/index.ts`](../packages/sdk/helper/src/index.ts))
- `@deepseek-ai/dsh-hook-protocol` ([`packages/hooks/hook-protocol/src/index.ts`](../packages/hooks/hook-protocol/src/index.ts))
- `@deepseek-ai/dsh-host-apiproxy` ([`packages/host/apiproxy/src/index.ts`](../packages/host/apiproxy/src/index.ts))
- `@deepseek-ai/dsh-host-runtime` ([`packages/host/runtime/src/index.ts`](../packages/host/runtime/src/index.ts))
- `@deepseek-ai/dsh-host-webserver` ([`packages/host/webserver/src/index.ts`](../packages/host/webserver/src/index.ts))
- `@deepseek-ai/dsh-jsonrpc-demo` ([`packages/examples/jsonrpc-demo/src/index.ts`](../packages/examples/jsonrpc-demo/src/index.ts))
- `@deepseek-ai/dsh-loader-smoke` ([`packages/support/loader-smoke/src/index.ts`](../packages/support/loader-smoke/src/index.ts))
- `@deepseek-ai/dsh-paths` ([`packages/util/paths/src/index.ts`](../packages/util/paths/src/index.ts))

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
extension-cookbook.md: a1f6d2f0d27b2258ae06236721bbd80cbd3af80e
extension-cookbook.zh.md: f7729492b68bfef50d5e289581028d0c0c4164cf
extension-cookbook.md: 8873cac21960e2e2efe0e8c6c5868c3a8e7ee75c
extension-cookbook.zh.md: f34e9f2fa707be69b13ac408cc1ede1a86310fae

View File

@@ -87,7 +87,7 @@ export function apply(ctx: Context) {
## Runnable wirings
Four runnable leaves load their plugin trees from `cordis.yml`: [`examples/tui-agent`](../../examples/tui-agent) (DeepSeek coding tools through the full-screen TUI, `pnpm run demo:tui`), [`examples/headless-agent`](../../examples/headless-agent) (the coding capabilities behind a one-shot task and DSH-native output, `pnpm run demo:headless "task"`), [`examples/cordis-agent`](../../examples/cordis-agent) (self-inspection and dynamic plugin mounting through the TUI, `pnpm run demo:cordis`), and [`examples/acp-agent`](../../examples/acp-agent) (an ACP server over JSON-RPC stdio, `pnpm run demo:acp`). Interactive leaves load [`@deepseek-ai/dsh-tui-demo`](../../packages/examples/tui-demo), non-interactive leaves load [`@deepseek-ai/dsh-cli-demo`](../../packages/examples/cli-demo), the ACP leaf loads [`@deepseek-ai/dsh-acp-demo`](../../packages/examples/acp-demo), and all three app packages share [`@deepseek-ai/dsh-agent-spine-demo`](../../packages/examples/agent-spine-demo).
Runnable leaves load their plugin trees from `examples/*/cordis.yml`; the root `demo:*` scripts and those leaf directories are the authoritative inventory. Interactive leaves use [`@deepseek-ai/dsh-tui-demo`](../../packages/examples/tui-demo), non-interactive leaves use [`@deepseek-ai/dsh-cli-demo`](../../packages/examples/cli-demo), ACP leaves use [`@deepseek-ai/dsh-acp-demo`](../../packages/examples/acp-demo), and the app packages share [`@deepseek-ai/dsh-agent-spine-demo`](../../packages/examples/agent-spine-demo).
## The feature → mechanism map
@@ -113,7 +113,7 @@ Every product feature maps to a listener on a documented extension seam — the
| Monotonic terminal turn policy | return `{ action: 'stop' }` from serial `agent/turn-stop`, after continuation and steering have already been folded |
| Subprocess sandbox (landlock / sandbox-exec) | use a `ctx.sandbox` backend through `dsh-bash-sandbox`; use `tools/pre-execute` for capability-level denial |
| Permission system / AskUserQuestion | return `ask` from `tools/pre-execute` and answer through `ctx.approval`; register a separate model-facing ask tool for ordinary user questions |
| Plan mode | `tools/pre-execute` (deny writes) + a mode prompt section via `ctx.systemPrompt.section()` or `agent.inject()` (model-visible ⟺ logged: `agent/request` shapes call config only) |
| Plan mode | Shipped: [`@deepseek-ai/dsh-plan-mode`](../../packages/plan/plan-mode/README.md) — logged `plan/mode` state, the `plan:policy` guidance section, `/plan [message]`, and the user-reviewed `exit_plan_mode` exit; enforcement stays on the independent sandbox/approval axes |
| Sub-agent delegation | the `ctx.subagents` provider registry (`dsh-subagent-spawn`/`-fork`/`-acp`) + `dsh-tool-subagent` exposing one configured provider to the model |
| MCP | one plugin per server: discover tools → `ctx.tools.register()` |
| Skills | section + tool registration; `inject()` skill content on invocation |

View File

@@ -87,7 +87,7 @@ export function apply(ctx: Context) {
## 可运行的组装示例
四个可运行叶子从 `cordis.yml` 加载各自的插件树:[`examples/tui-agent`](../../examples/tui-agent)(通过全屏 TUI 运行的 DeepSeek coding 工具,`pnpm run demo:tui`)、[`examples/headless-agent`](../../examples/headless-agent)(通过单次任务和 DSH 原生输出运行的 coding 能力,`pnpm run demo:headless "task"`)、[`examples/cordis-agent`](../../examples/cordis-agent)(通过 TUI 进行自我检查和动态插件挂载,`pnpm run demo:cordis`)与 [`examples/acp-agent`](../../examples/acp-agent)(通过 JSON-RPC stdio 暴露的 ACP 服务器,`pnpm run demo:acp`。交互式叶子加载 [`@deepseek-ai/dsh-tui-demo`](../../packages/examples/tui-demo),非交互式叶子加载 [`@deepseek-ai/dsh-cli-demo`](../../packages/examples/cli-demo)ACP 叶子加载 [`@deepseek-ai/dsh-acp-demo`](../../packages/examples/acp-demo)三个 app 包都通过 [`@deepseek-ai/dsh-agent-spine-demo`](../../packages/examples/agent-spine-demo) 共享主干
可运行叶子从 `examples/*/cordis.yml` 加载各自的插件树;根目录的 `demo:*` 脚本和这些叶子目录是权威清单。交互式叶子使用 [`@deepseek-ai/dsh-tui-demo`](../../packages/examples/tui-demo),非交互式叶子使用 [`@deepseek-ai/dsh-cli-demo`](../../packages/examples/cli-demo)ACP 叶子使用 [`@deepseek-ai/dsh-acp-demo`](../../packages/examples/acp-demo)应用包共享 [`@deepseek-ai/dsh-agent-spine-demo`](../../packages/examples/agent-spine-demo)。
## 功能→机制映射
@@ -113,7 +113,7 @@ export function apply(ctx: Context) {
| 单调终端轮次策略 | 从串行 `agent/turn-stop` 返回 `{ action: 'stop' }`,此时 continuation 和 steering 已折叠完毕 |
| 子进程沙箱landlock / sandbox-exec | 通过 `dsh-bash-sandbox` 使用 `ctx.sandbox` 后端;能力级别的拒绝使用 `tools/pre-execute` |
| 权限系统 / AskUserQuestion | 从 `tools/pre-execute` 返回 `ask` 并通过 `ctx.approval` 应答;为普通用户提问注册一个独立的面向模型的 ask 工具 |
| Plan mode | `tools/pre-execute`(拒绝写操作)+ 通过 `ctx.systemPrompt.section()``agent.inject()` 注入模式提示词段model-visible ⟺ logged`agent/request` 仅塑形调用配置) |
| Plan mode | 已交付:[`@deepseek-ai/dsh-plan-mode`](../../packages/plan/plan-mode/README.md) — 落日志的 `plan/mode` 状态、`plan:policy` 引导段、`/plan [message]`,以及经用户评审的 `exit_plan_mode` 出口;强制约束留在独立的沙箱/审批轴上 |
| 子 agent 委派 | `ctx.subagents` 提供方注册表(`dsh-subagent-spawn`/`-fork`/`-acp`+ `dsh-tool-subagent` 向模型暴露一个已配置的提供方 |
| MCP | 每个服务器一个插件:发现工具 → `ctx.tools.register()` |
| Skill技能 | section + 工具注册;调用时通过 `inject()` 注入 skill 内容 |

View File

@@ -417,7 +417,7 @@ Ask composed answerers for one decision. Return an outcome to claim the request
Types: [ApprovalOutcome](../core-data-structures/approval.md) · [ApprovalRequest](../core-data-structures/approval.md) · [ApprovalService](../core-data-structures/approval.md) · [Scoped](../core-data-structures/scope.md)
Source: [`packages/ui/user-approval/src/index.ts:31`](../../packages/ui/user-approval/src/index.ts)
Source: [`packages/ui/user-approval/src/index.ts:30`](../../packages/ui/user-approval/src/index.ts)
## `commands/*`
@@ -435,7 +435,7 @@ A command was registered or unregistered. This is an unfiltered registry notific
'commands/change'(): void
```
Source: [`packages/ui/commands/src/index.ts:83`](../../packages/ui/commands/src/index.ts)
Source: [`packages/ui/commands/src/index.ts:103`](../../packages/ui/commands/src/index.ts)
## `fs/*`

View File

@@ -246,7 +246,7 @@ async request(req: ApprovalRequest): Promise<ApprovalOutcome>
Types: [ApprovalOutcome](../core-data-structures/approval.md) · [ApprovalRequest](../core-data-structures/approval.md)
Source: [`packages/ui/user-approval/src/index.ts:229`](../../packages/ui/user-approval/src/index.ts)
Source: [`packages/ui/user-approval/src/index.ts:213`](../../packages/ui/user-approval/src/index.ts)
## `ctx.bash` — `BashExecutor` (abstract seam)
@@ -379,7 +379,7 @@ async execute( agent: Agent, line: string, signal: AbortSignal, ): Promise<Comma
Types: [Agent](../core-data-structures/core.md) · [CommandDefinition](../core-data-structures/commands.md) · [CommandDescriptor](../core-data-structures/commands.md) · [CommandResult](../core-data-structures/commands.md)
Source: [`packages/ui/commands/src/index.ts:207`](../../packages/ui/commands/src/index.ts)
Source: [`packages/ui/commands/src/index.ts:227`](../../packages/ui/commands/src/index.ts)
## `ctx.compact` — `CompactService` (abstract seam)
@@ -733,6 +733,33 @@ Types: [Session](../core-data-structures/session.md) · [SessionEvent](../core-d
Source: [`packages/ui/permission/src/index.ts:97`](../../packages/ui/permission/src/index.ts)
## `ctx.planMode` — `PlanModeService`
`ctx.planMode`: owns logged plan state, boundary application and narration, the `plan:policy` section, the `/plan` command, and the stable exit tool. UIs observe committed flips through `session/event`; there is no live mirror.
```ts cordis-catalog
/**
* Read the logged plan state and any selected state awaiting a boundary.
*
* @param agent The agent to read.
* @returns Current logged state plus a pending selection, when present.
*/
get(agent: Agent): { active: boolean; pending?: boolean }
/**
* Select whether plan mode should be active from the next turn boundary.
* Repeated selection of the current or already-pending state is a no-op.
*
* @param agent The agent to switch.
* @param active Whether plan mode should be active.
*/
set(agent: Agent, active: boolean): void
```
Types: [Agent](../core-data-structures/core.md)
Source: [`packages/plan/plan-mode/src/index.ts:141`](../../packages/plan/plan-mode/src/index.ts)
## `ctx.sandbox` — `SandboxProvider` (abstract seam)
Abstract process-sandbox service. confine must return enforcing argv or fail closed at wrap or runner-execution time; silent unconfined passthrough is forbidden. Functional probes arbitrate multi-runner chains and may be skipped for a sole candidate, whose own refusal remains the fail-closed end.
@@ -1213,7 +1240,7 @@ async assemble(context: AssembleContext = {}): Promise<PromptAssembly>
Types: [AssembleContext](../core-data-structures/system-prompt.md) · [PromptSection](../core-data-structures/system-prompt.md) · [ToolProviderResult](../core-data-structures/system-prompt.md)
Source: [`packages/core/system-prompt/src/index.ts:213`](../../packages/core/system-prompt/src/index.ts)
Source: [`packages/core/system-prompt/src/index.ts:246`](../../packages/core/system-prompt/src/index.ts)
## `ctx.tasks` — `TaskService`
@@ -1456,7 +1483,7 @@ async execute(exec: ToolExecutionInput): Promise<ToolExecutionResult>
Types: [ScopeKey](../core-data-structures/scope.md) · [ToolDefinition](../core-data-structures/tools.md) · [ToolExecutionInput](../core-data-structures/tools.md) · [ToolExecutionMode](../core-data-structures/tools.md) · [ToolExecutionResult](../core-data-structures/tools.md) · [ToolGuard](../core-data-structures/tools.md) · [ToolRestriction](../core-data-structures/tools.md) · [ToolSchema](../core-data-structures/tools.md)
Source: [`packages/core/tools/src/index.ts:493`](../../packages/core/tools/src/index.ts)
Source: [`packages/core/tools/src/index.ts:524`](../../packages/core/tools/src/index.ts)
## `ctx.userInteraction` — `UserInteractionService`
@@ -1482,7 +1509,7 @@ async ask(request: AskUserQuestionRequest): Promise<AskUserQuestionAnswer>
Types: [AskUserQuestionAnswer](../core-data-structures/user-interaction.md) · [AskUserQuestionRequest](../core-data-structures/user-interaction.md) · [UserInteractionProvider](../core-data-structures/user-interaction.md)
Source: [`packages/ui/user-interaction/src/index.ts:82`](../../packages/ui/user-interaction/src/index.ts)
Source: [`packages/ui/user-interaction/src/index.ts:50`](../../packages/ui/user-interaction/src/index.ts)
## `ctx.web` — `WebService`

View File

@@ -235,6 +235,12 @@ interface GenerateOptions {
* it; replay uses it to keep concurrent parent and child cursors independent.
*/
sessionId?: Branded<'SessionId'>
/**
* Provider-neutral classification for an auxiliary model call. Adapters may
* map the purpose to model-hidden transport metadata. Ordinary conversation
* requests leave it unset.
*/
purpose?: 'compaction'
}
```
@@ -424,7 +430,7 @@ interface Agent {
}
```
`AgentStatus` is `'idle' | 'running' | 'disposed'`, and `SessionId` is branded. `running` describes the driver-wide drain interval, which can span turn close, its durability checkpoint, and consecutive queued turns; it does not prove a turn is still open. `AgentOptions` is merge-extensible and currently includes `provider?` and `model?`; dispatch requires both after `agent/request`. Persona belongs to `dsh-system-prompt`: an agent-scoped `deployment:persona` may shadow the global default.
`AgentStatus` is `'idle' | 'running' | 'disposed'`, and `SessionId` is branded. `running` describes the driver-wide drain interval, which can span turn close, its durability checkpoint, and consecutive queued turns; it does not prove a turn is still open. `AgentOptions` is merge-extensible: core declares `provider?` and `model?` (dispatch requires both after `agent/request`). Persona belongs to `dsh-system-prompt`: an agent-scoped `deployment:persona` may shadow the global default.
The cause is a TypeScript-enforced same-process input. An active holder copies its discriminant into the runtime-only `AbortSignal.reason`; it is retired before `turn/end` publication. `agentInterruptReasonOf(signal)` recognizes `user`, `parent`, and lifecycle-only `disposed` without consulting ambient initiator state. Durable `turn/end` retains the coarse `{ kind: 'aborted' }` outcome; request provenance would require a separate durable event rather than overloading the terminal result.

View File

@@ -1,8 +1,8 @@
# Scoped Registration
The [scope package](../../packages/core/scope) supplies the identity and carrier vocabulary that makes one registration context mean both per-agent visibility and shared lifetime ownership. It is a library primitive rather than a Cordis service; the [agent-scope runtime-design Agent Note](../../.agents/notes/implemented/architecture/2026-07-12-agent-scope-runtime-design.md#scope-routing-one-opaque-key-selects-one-layer) owns the implementation rationale, while the package [README](../../packages/core/scope/README.md) owns the callable API and filtering semantics.
The [scope package](../../packages/core/scope) supplies the identity, carrier, and scoped-layer vocabulary that makes one registration context mean both per-agent visibility and shared lifetime ownership. It is a library primitive rather than a Cordis service; the [agent-scope runtime-design Agent Note](../../.agents/notes/implemented/architecture/2026-07-12-agent-scope-runtime-design.md#scope-routing-one-opaque-key-selects-one-layer) owns the lifecycle rationale, the [shared-storage Agent Note](../../.agents/notes/implemented/architecture/2026-07-12-scoped-layers-store.md) owns the registry-layer decision, and the package [README](../../packages/core/scope/README.md) owns the callable API and filtering semantics.
Source: [`packages/core/scope/src/index.ts`](../../packages/core/scope/src/index.ts).
Sources: [`packages/core/scope/src/index.ts`](../../packages/core/scope/src/index.ts) and [`packages/core/scope/src/store.ts`](../../packages/core/scope/src/store.ts).
## Identity and dispatch carrier
@@ -39,3 +39,19 @@ interface Scope {
dispose(): Promise<void>
}
```
## Scoped registry layer
`ScopeLayer` represents one registry's complete contribution at the global or exact-scope level. A concrete layer may aggregate multiple named and anonymous tables; whole-layer emptiness lets `ScopedLayers` reclaim scoped state without discarding a sibling table.
```ts type-equiv
/** One scope's aggregate contribution to a registry. */
interface ScopeLayer {
/** Whether every table in this layer is empty. */
isEmpty(): boolean
}
```
`ScopedLayers<L>` owns the eager global layer and lazily created exact-scope layers. Reads do not create layers: `peek(undefined)` means no overlay, while `merge()` materializes insertion-ordered global named entries followed by scoped shadows. Registrations use one context for both visibility and Cordis effect ownership, collect one synchronous undo before optional notification, return Cordis's exact disposer, and reclaim a scoped layer only when its complete `ScopeLayer` is empty.
`NamedEntries<V>` supplies insertion-ordered lookup and live iteration with caller-owned duplicate errors. `AnonymousEntries<V>` gives every append a unique identity so equal values remain independent. Iteration stays live within one nonempty table generation; draining the table detaches existing iterators from later insertions. Both return idempotent exact-entry undos; the shared `EntryValues` implementation interface is not public.

View File

@@ -20,15 +20,17 @@ interface AskUserQuestionOption {
## Question item
`AskUserQuestionItem` is one question in a request. The model supplies a stable `id`, which is echoed back with the answer so batched questions remain routable.
`AskUserQuestionItem` is one question in a request. The caller supplies a stable `id`, which is echoed back with the answer so batched questions remain routable. Optional `detail` carries supporting text that providers render with the question but keep out of selectable option labels.
```ts type-equiv
/** One question in an ask_user_question request. */
/** One question in a user-interaction request. */
interface AskUserQuestionItem {
/** Stable model-provided question id, echoed in the answer. */
/** Stable caller-provided question id, echoed in the answer. */
id: string
/** The question to display. */
question: string
/** Optional supporting detail rendered with the question but kept out of option labels. */
detail?: string
/** Optional short heading/group label. */
header?: string
/** Optional choices the UI can render as a menu. */

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
development.md: f0db7fbcb4a9df98e83d6c1edd5610e5cc4dd517
development.zh.md: 62e16479a49d5548e1fbd773dabca5bd741a24fe
development.md: 10406cebae1bf83fff663903b1478c9acb8476a1
development.zh.md: 50051ffd631518b37c3ad96f5fd3830cf6893ec9

View File

@@ -35,13 +35,13 @@ pnpm run typecheck
That first typecheck runs the package/vendor build graph and the root no-emit `tsconfig.json` graph for examples, tests, and scripts. The root graph uses the same source `paths` map but relies on project references so vendored code is checked under its own tsconfig settings.
If you are preparing to push from a fresh clone or worktree, also build once:
If a relevant local check consumes built package output, build once first:
```sh
pnpm run build
```
`pnpm run hygiene` includes `publint`, which validates package entrypoints against the built `lib/*.js` files, and `verify-node-next-types`, which validates built declarations against a temporary NodeNext consumer. A fresh worktree has no bundled JS or declarations until `pnpm run build` runs.
`pnpm run hygiene` includes `publint`, which validates package entrypoints against the built `lib/*.js` files, and `verify-node-next-types`, which validates built declarations against a temporary NodeNext consumer. A fresh worktree has no bundled JS or declarations until `pnpm run build` runs; ordinary commits and pushes do not require that build unless their selected checks consume it.
## Environment variables
@@ -56,14 +56,14 @@ DEEPSEEK_BASE_URL=https://... # optional
## Git hooks
lefthook is configured in `lefthook.yml` as an early local checkpoint before review:
lefthook is configured in `lefthook.yml` as a fast local checkpoint:
- `pre-commit` runs staged-file ESLint fixes, `pnpm run typecheck`, and the vendor manifest guard.
- `pre-push` runs `pnpm run check:pre-push`, whose scheduler runs runtime-closure verification, unit tests, duplication detection, snapshot tests, build, module-graph freshness, and the member gates of `pnpm run hygiene` and `pnpm run doc-sync` concurrently.
- `pre-commit` runs staged-file ESLint fixes, checks the staged diff for whitespace errors, and runs the vendor manifest guard.
- `pre-push` runs only the incremental repository typecheck.
The vendor manifest guard checks that changes under `vendor/*/src` are staged with the matching `vendor/README.md` manifest update. See `vendor/README.md` before editing vendored code.
These hooks do not exactly mirror CI. Notably, `pre-push` runs unit tests without coverage, while CI runs `pnpm run test:coverage`; CI also runs built-bin smoke tests and exercises the compatibility matrix on Node 22.19, 24, and 26.
The hooks intentionally do not run tests, snapshots, documentation checks, builds, or hygiene. Contributors run the [checks relevant to the changed behavior](../AGENTS.md#run-relevant-checks-locally) once; CI owns exhaustive coverage, built-artifact smokes, and the Node 22.19, 24, and 26 compatibility matrix.
## CI gates

View File

@@ -35,13 +35,13 @@ pnpm run typecheck
首次类型检查会执行 package/vendor 的构建图,以及根目录下用于示例、测试和脚本的 no-emit `tsconfig.json` 项目图。根图使用同一份源码 `paths` 映射,但依赖 project references因此 vendor 代码在它自己的 tsconfig 设置下被检查。
如果准备从新克隆或新 worktree 推送,还需要构建一次:
如果相关的本地检查需要使用构建后的包产物,请先构建一次:
```sh
pnpm run build
```
`pnpm run hygiene` 包含 `publint`(用构建出的 `lib/*.js` 文件校验 package 入口点)和 `verify-node-next-types`(用一个临时的 NodeNext 消费方校验构建出的声明文件)。新 worktree 在 `pnpm run build` 运行之前没有打包的 JS 和声明文件。
`pnpm run hygiene` 包含 `publint`(用构建出的 `lib/*.js` 文件校验 package 入口点)和 `verify-node-next-types`(用一个临时的 NodeNext 消费方校验构建出的声明文件)。新 worktree 在 `pnpm run build` 运行之前没有打包的 JS 和声明文件;普通提交和推送无需构建,除非所选检查会使用这些产物
## 环境变量
@@ -56,14 +56,14 @@ DEEPSEEK_BASE_URL=https://... # optional
## Git 钩子
lefthook 在 `lefthook.yml` 中配置,作为评审前的本地早期检查点:
lefthook 在 `lefthook.yml` 中配置,作为快速的本地检查点:
- `pre-commit` 运行对暂存文件的 ESLint 修复`pnpm run typecheck` vendor manifest元数据清单守卫
- `pre-push` 运行 `pnpm run check:pre-push`,其调度器并发运行 runtime-closure 校验、单元测试、重复代码检查、快照测试、构建、module-graph 新鲜度,以及 `pnpm run hygiene``pnpm run doc-sync` 的各成员门禁
- `pre-commit` 运行对暂存文件的 ESLint 修复,检查暂存 diff 中的空白错误,并运行 vendor manifest元数据清单守卫
- `pre-push` 运行仓库增量类型检查
vendor manifest 守卫检查 `vendor/*/src` 下的改动是否连同对应的 `vendor/README.md` manifest 更新一起暂存。请在编辑 vendor 代码前先阅读 `vendor/README.md`
这些钩子并不与 CI 完全一致。特别是:`pre-push` 运行不带覆盖率的单元测试,而 CI 运行 `pnpm run test:coverage`CI 还会运行 built-bin 冒烟测试,并在 Node 22.19、24 和 26 上执行兼容性矩阵。
这些钩子有意不运行测试、快照、文档检查、构建或 `hygiene`。贡献者只运行一次[与改动行为相关的检查](../AGENTS.md#run-relevant-checks-locally)CI 负责全量覆盖率门禁、构建产物冒烟测试,以及 Node 22.19、24 和 26 兼容性矩阵。
## CI 门禁

View File

@@ -11,29 +11,29 @@ This matrix shows which packages dispatch each harness-owned event and which pac
| `agent/cancel-requested` | `emit` | [`packages/core/agent/src/types.ts:201`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-session`](../packages/goal/goal-session) |
| `agent/created` | `emit` | [`packages/core/agent/src/types.ts:163`](../packages/core/agent/src/types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
| `agent/disposed` | `emit` | [`packages/core/agent/src/types.ts:172`](../packages/core/agent/src/types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
| `agent/error` | `emit` | [`packages/core/agent/src/types.ts:346`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
| `agent/error` | `emit` | [`packages/core/agent/src/types.ts:346`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-session`](../packages/goal/goal-session), `runtime`, [`tui`](../packages/ui/tui) |
| `agent/post-step` | `serial` | [`packages/core/agent/src/types.ts:296`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`compact-basic`](../packages/compact/compact-basic), [`session-checkpoint-policy`](../packages/session-persistence/session-checkpoint-policy) |
| `agent/pre-step` | `serial` | [`packages/core/agent/src/types.ts:230`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`time-context`](../packages/context/time-context), [`user-approval`](../packages/ui/user-approval) |
| `agent/prompt-submit` | `waterfall` | [`packages/core/agent/src/types.ts:243`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`acp`](../packages/ui/acp), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard) |
| `agent/prompt-submit` | `waterfall` | [`packages/core/agent/src/types.ts:243`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`acp`](../packages/ui/acp), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`plan-mode`](../packages/plan/plan-mode), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard) |
| `agent/queued` | `emit` | [`packages/core/agent/src/types.ts:191`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-session`](../packages/goal/goal-session) |
| `agent/request` | `waterfall` | [`packages/core/agent/src/types.ts:257`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`agent`](../packages/core/agent) |
| `agent/request-error` | `waterfall` | [`packages/core/agent/src/types.ts:311`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compact-basic`](../packages/compact/compact-basic), [`llm-retry`](../packages/llm/llm-retry) |
| `agent/request-error` | `waterfall` | [`packages/core/agent/src/types.ts:311`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compact-basic`](../packages/compact/compact-basic), [`llm-retry`](../packages/llm/llm-retry), [`plan-mode`](../packages/plan/plan-mode) |
| `agent/session-prefix` | `waterfall` | [`packages/core/agent/src/types.ts:272`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`tool-skill`](../packages/skill/tool-skill), [`workspace-context`](../packages/context/workspace-context) |
| `agent/session-start` | `emit` | [`packages/core/agent/src/types.ts:214`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex) |
| `agent/status` | `emit` | [`packages/core/agent/src/types.ts:181`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`agent`](../packages/core/agent), [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
| `agent/status` | `emit` | [`packages/core/agent/src/types.ts:181`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`agent`](../packages/core/agent), [`goal-session`](../packages/goal/goal-session), `runtime`, [`tui`](../packages/ui/tui) |
| `agent/step-result` | `waterfall` | [`packages/core/agent/src/types.ts:284`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | - |
| `agent/turn-continuation` | `waterfall` | [`packages/core/agent/src/types.ts:322`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex) |
| `agent/turn-continuation` | `waterfall` | [`packages/core/agent/src/types.ts:322`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`plan-mode`](../packages/plan/plan-mode) |
| `agent/turn-stop` | `serial` | [`packages/core/agent/src/types.ts:333`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`subagent-inprocess`](../packages/subagent/subagent-inprocess), [`tool-goal`](../packages/goal/tool-goal) |
| `approval/request` | `waterfall` | [`packages/ui/user-approval/src/index.ts:31`](../packages/ui/user-approval/src/index.ts) | [`user-approval`](../packages/ui/user-approval) (`waterfall`) | [`acp`](../packages/ui/acp) |
| `commands/change` | `emit` | [`packages/ui/commands/src/index.ts:83`](../packages/ui/commands/src/index.ts) | [`commands`](../packages/ui/commands) (`events.dispatch`) | [`acp`](../packages/ui/acp), [`tui`](../packages/ui/tui) |
| `approval/request` | `waterfall` | [`packages/ui/user-approval/src/index.ts:30`](../packages/ui/user-approval/src/index.ts) | [`user-approval`](../packages/ui/user-approval) (`waterfall`) | [`acp`](../packages/ui/acp) |
| `commands/change` | `emit` | [`packages/ui/commands/src/index.ts:103`](../packages/ui/commands/src/index.ts) | [`commands`](../packages/ui/commands) (`events.dispatch`) | [`acp`](../packages/ui/acp), [`tui`](../packages/ui/tui) |
| `fs/edit-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:62`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
| `fs/observed` | `emit` | [`packages/fs/fs/src/index.ts:71`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`emit`) | [`fs-policy`](../packages/fs/fs-policy) |
| `fs/write-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:54`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
| `goal/changed` | `emit` | [`packages/goal/goal/src/types.ts:167`](../packages/goal/goal/src/types.ts) | [`goal`](../packages/goal/goal) (`emit`) | [`goal-session`](../packages/goal/goal-session) |
| `llm/stream` | `waterfall` | [`packages/llm/llm/src/index.ts:52`](../packages/llm/llm/src/index.ts) | [`llm`](../packages/llm/llm) (`waterfall`) | [`agent-loop`](../packages/core/agent-loop), [`llm`](../packages/llm/llm), [`llm-replay`](../packages/support/llm-replay), [`session-checkpoint-policy`](../packages/session-persistence/session-checkpoint-policy), [`session-title`](../packages/session-title/session-title) |
| `session/created` | `emit` | [`packages/core/session/src/index.ts:68`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`compact`](../packages/compact/compact), [`goal`](../packages/goal/goal), [`hook-protocol`](../packages/hooks/hook-protocol), [`jsonrpc`](../packages/ui/jsonrpc), [`llm-retry`](../packages/llm/llm-retry), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`user-approval`](../packages/ui/user-approval) |
| `session/disposed` | `emit` | [`packages/core/session/src/index.ts:78`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-title`](../packages/session-title/session-title) |
| `session/event` | `emit` | [`packages/core/session/src/index.ts:90`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`acp`](../packages/ui/acp), [`cli-demo`](../packages/examples/cli-demo), [`compact`](../packages/compact/compact), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`jsonrpc`](../packages/ui/jsonrpc), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-title`](../packages/session-title/session-title), [`token-meter`](../packages/llm/token-meter), [`tui`](../packages/ui/tui), [`user-approval`](../packages/ui/user-approval), [`workspace-context`](../packages/context/workspace-context) |
| `session/created` | `emit` | [`packages/core/session/src/index.ts:68`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`compact`](../packages/compact/compact), [`goal`](../packages/goal/goal), [`hook-protocol`](../packages/hooks/hook-protocol), [`jsonrpc`](../packages/ui/jsonrpc), [`llm-retry`](../packages/llm/llm-retry), `runtime`, [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`user-approval`](../packages/ui/user-approval) |
| `session/disposed` | `emit` | [`packages/core/session/src/index.ts:78`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), `runtime`, [`session-persistence`](../packages/session-persistence/session-persistence), [`session-title`](../packages/session-title/session-title) |
| `session/event` | `emit` | [`packages/core/session/src/index.ts:90`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`acp`](../packages/ui/acp), [`cli-demo`](../packages/examples/cli-demo), [`compact`](../packages/compact/compact), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`jsonrpc`](../packages/ui/jsonrpc), `runtime`, [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-title`](../packages/session-title/session-title), [`token-meter`](../packages/llm/token-meter), [`tui`](../packages/ui/tui), [`user-approval`](../packages/ui/user-approval), [`workspace-context`](../packages/context/workspace-context) |
| `session/flush` | `parallel` | [`packages/core/session/src/index.ts:100`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`session-persistence`](../packages/session-persistence/session-persistence) |
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:139`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`jsonrpc`](../packages/ui/jsonrpc), [`subagent`](../packages/subagent/subagent) |
| `subagent/provider-added` | `emit` | [`packages/subagent/subagent/src/index.ts:113`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
@@ -57,7 +57,9 @@ This matrix shows which packages dispatch each harness-owned event and which pac
| Event string | Dispatchers | Listeners |
| --- | --- | --- |
| `internal/dispatch` | - | [`compact`](../packages/compact/compact), [`fs`](../packages/fs/fs), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm-retry`](../packages/llm/llm-retry), [`permission`](../packages/ui/permission), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`time-context`](../packages/context/time-context), [`tool-todo`](../packages/todo/tool-todo), [`tools`](../packages/core/tools), [`user-approval`](../packages/ui/user-approval), [`workflow`](../packages/workflow/workflow) |
| `internal/dispatch` | - | [`compact`](../packages/compact/compact), [`fs`](../packages/fs/fs), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm-retry`](../packages/llm/llm-retry), [`permission`](../packages/ui/permission), [`plan-mode`](../packages/plan/plan-mode), `runtime`, [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`time-context`](../packages/context/time-context), [`tool-todo`](../packages/todo/tool-todo), [`tools`](../packages/core/tools), [`user-approval`](../packages/ui/user-approval), [`workflow`](../packages/workflow/workflow) |
| `internal/plugin` | - | `webserver` |
| `internal/status` | - | [`agent`](../packages/core/agent) |
| `slots/changed` | `runtime` (`emit`) | - |
Maintenance mode: generated: Cordis event declarations and producer/listener edges are resolved from the repository TypeScript Program.

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
README.md: bd5d8c08a4c474a13342b6b60800cfe0d31e110b
README.zh.md: a53ab8d9d6053b39def34505038504fefc80a3f9
README.md: c4ddf44ad2497b4ff371918356ab1ec0698c7049
README.zh.md: 4a31af4fdee4db2d0362cf9117a6eef4fea32393

View File

@@ -21,7 +21,7 @@ This repo's documentation is read by people and agents both inside and outside t
## The gate: verify-translation-pairing
`pnpm run verify-translation-pairing` (part of `doc-sync`, so CI and the pre-push hook run it) enforces the contract mechanically:
`pnpm run verify-translation-pairing` (part of `doc-sync`, which contributors run locally for documentation changes and CI runs exhaustively) enforces the contract mechanically:
1. Every file listed as `required` in [scripts/translation-pairing.manifest.json](../../scripts/translation-pairing.manifest.json) has a complete pair.
2. Every pair that exists at all — required or not — is complete and consistent: all three files present, each side's current blob hash equals the recorded one (editing either side without re-confirming the pair goes red), both sides carry the language switcher, and the structural signatures match in order — heading depths, verbatim code blocks (info string and content), table row and column counts, list kinds, ordered-list starts, item counts, and every link target apart from the switcher.

View File

@@ -21,7 +21,7 @@
## 门禁verify-translation-pairing
`pnpm run verify-translation-pairing``doc-sync`(文档同步门禁)的一环,因此 CI 和 pre-push 钩子都会运行)机械地强制执行这份契约:
`pnpm run verify-translation-pairing``doc-sync`(文档同步门禁)的一环,贡献者会针对文档变更在本地运行CI 则会完整运行)机械地强制执行这份契约:
1. [scripts/translation-pairing.manifest.json](../../scripts/translation-pairing.manifest.json) 中 `required` 列出的每个文件都有完整配对。
2. 任何已存在的配对——无论是否 required——都完整且一致三个文件齐全、每一侧的当前 blob hash 等于记录值(改了任一侧而没重新确认配对就变红)、双方都带语言切换行、结构签名按序一致——标题深度、逐字节一致的代码块(信息字符串与内容)、表格行列数、列表类型、有序列表起始编号、列表项数量,以及除切换行之外的每个链接目标。

View File

@@ -86,6 +86,9 @@ flowchart TD
subgraph group_todo["packages/todo"]
pkg_tool_todo["tool-todo"]
end
subgraph group_plan["packages/plan"]
pkg_plan_mode["plan-mode"]
end
subgraph group_cordis["packages/cordis"]
pkg_tool_cordis["tool-cordis"]
end
@@ -127,6 +130,20 @@ flowchart TD
pkg_user_approval["user-approval"]
pkg_user_interaction["user-interaction"]
end
subgraph group_client["packages/client"]
pkg_client_connection["client-connection"]
pkg_client_i18n["client-i18n"]
pkg_client_runtime["client-runtime"]
pkg_client_ui_conversation["client-ui-conversation"]
pkg_client_ui_layout["client-ui-layout"]
pkg_client_ui_primitives["client-ui-primitives"]
pkg_client_ui_sidebar["client-ui-sidebar"]
pkg_client_ui_slots["client-ui-slots"]
pkg_client_ui_theme["client-ui-theme"]
pkg_client_ui_trajectory["client-ui-trajectory"]
pkg_client_web["client-web"]
pkg_client_web_react["client-web-react"]
end
subgraph group_code_runtime["packages/code-runtime"]
pkg_code_runtime["code-runtime"]
pkg_code_runtime_worker["code-runtime-worker"]
@@ -145,6 +162,11 @@ flowchart TD
subgraph group_guard["packages/guard"]
pkg_repeat_tool_guard["repeat-tool-guard"]
end
subgraph group_host["packages/host"]
pkg_host_apiproxy["host-apiproxy"]
pkg_host_runtime["host-runtime"]
pkg_host_webserver["host-webserver"]
end
subgraph group_lsp["packages/lsp"]
pkg_lsp["lsp"]
pkg_lsp_local["lsp-local"]
@@ -183,8 +205,23 @@ flowchart TD
pkg_acp_snapshot --> pkg_invariants
pkg_loader_smoke --> pkg_invariants
pkg_app_boot --> pkg_invariants
pkg_client_connection --> pkg_invariants
pkg_client_i18n --> pkg_invariants
pkg_client_runtime --> pkg_invariants
pkg_client_ui_conversation --> pkg_invariants
pkg_client_ui_layout --> pkg_invariants
pkg_client_ui_primitives --> pkg_invariants
pkg_client_ui_sidebar --> pkg_invariants
pkg_client_ui_slots --> pkg_invariants
pkg_client_ui_theme --> pkg_invariants
pkg_client_ui_trajectory --> pkg_invariants
pkg_client_web --> pkg_invariants
pkg_client_web_react --> pkg_invariants
pkg_code_runtime --> pkg_invariants
pkg_jsonrpc_demo --> pkg_invariants
pkg_host_apiproxy --> pkg_invariants
pkg_host_runtime --> pkg_invariants
pkg_host_webserver --> pkg_invariants
pkg_llm --> pkg_brand
pkg_llm --> pkg_invariants
pkg_code_runtime_worker --> pkg_code_runtime
@@ -463,6 +500,13 @@ flowchart TD
pkg_tool_todo --> pkg_invariants
pkg_tool_todo --> pkg_session
pkg_tool_todo --> pkg_tools
pkg_plan_mode --> pkg_agent
pkg_plan_mode --> pkg_commands
pkg_plan_mode --> pkg_invariants
pkg_plan_mode --> pkg_session
pkg_plan_mode --> pkg_system_prompt
pkg_plan_mode --> pkg_tools
pkg_plan_mode --> pkg_user_interaction
pkg_tool_cordis --> pkg_invariants
pkg_tool_cordis --> pkg_scope
pkg_tool_cordis --> pkg_tools
@@ -485,21 +529,6 @@ flowchart TD
pkg_agent_loop_testkit --> pkg_session
pkg_agent_loop_testkit --> pkg_system_prompt
pkg_agent_loop_testkit --> pkg_tools
pkg_acp --> pkg_agent
pkg_acp --> pkg_bash
pkg_acp --> pkg_commands
pkg_acp --> pkg_invariants
pkg_acp --> pkg_llm
pkg_acp --> pkg_llm_retry
pkg_acp --> pkg_permission
pkg_acp --> pkg_sandbox
pkg_acp --> pkg_session
pkg_acp --> pkg_session_persistence
pkg_acp --> pkg_session_title
pkg_acp --> pkg_system_prompt
pkg_acp --> pkg_tools
pkg_acp --> pkg_user_approval
pkg_acp --> pkg_user_interaction
pkg_tool_ask_user --> pkg_agent
pkg_tool_ask_user --> pkg_invariants
pkg_tool_ask_user --> pkg_tools
@@ -561,6 +590,22 @@ flowchart TD
pkg_hooks_claude --> pkg_session_persistence
pkg_hooks_claude --> pkg_subagent
pkg_hooks_claude --> pkg_tools
pkg_acp --> pkg_agent
pkg_acp --> pkg_bash
pkg_acp --> pkg_commands
pkg_acp --> pkg_invariants
pkg_acp --> pkg_llm
pkg_acp --> pkg_llm_retry
pkg_acp --> pkg_permission
pkg_acp --> pkg_plan_mode
pkg_acp --> pkg_sandbox
pkg_acp --> pkg_session
pkg_acp --> pkg_session_persistence
pkg_acp --> pkg_session_title
pkg_acp --> pkg_system_prompt
pkg_acp --> pkg_tools
pkg_acp --> pkg_user_approval
pkg_acp --> pkg_user_interaction
pkg_jsonrpc --> pkg_agent
pkg_jsonrpc --> pkg_invariants
pkg_jsonrpc --> pkg_llm
@@ -676,8 +721,23 @@ flowchart TD
| [`acp-snapshot`](../packages/support/acp-snapshot) | `support` | [`invariants`](../packages/support/invariants) |
| [`loader-smoke`](../packages/support/loader-smoke) | `support` | [`invariants`](../packages/support/invariants) |
| [`app-boot`](../packages/ui/app-boot) | `ui` | [`invariants`](../packages/support/invariants) |
| [`client-connection`](../packages/client/connection) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-i18n`](../packages/client/i18n) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-runtime`](../packages/client/runtime) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-ui-conversation`](../packages/client/ui-conversation) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-ui-layout`](../packages/client/ui-layout) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-ui-primitives`](../packages/client/ui-primitives) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-ui-sidebar`](../packages/client/ui-sidebar) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-ui-slots`](../packages/client/ui-slots) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-ui-theme`](../packages/client/ui-theme) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-web`](../packages/client/web) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-web-react`](../packages/client/web-react) | `client` | [`invariants`](../packages/support/invariants) |
| [`code-runtime`](../packages/code-runtime/code-runtime) | `code-runtime` | [`invariants`](../packages/support/invariants) |
| [`jsonrpc-demo`](../packages/examples/jsonrpc-demo) | `examples` | [`invariants`](../packages/support/invariants) |
| [`host-apiproxy`](../packages/host/apiproxy) | `host` | [`invariants`](../packages/support/invariants) |
| [`host-runtime`](../packages/host/runtime) | `host` | [`invariants`](../packages/support/invariants) |
| [`host-webserver`](../packages/host/webserver) | `host` | [`invariants`](../packages/support/invariants) |
| [`llm`](../packages/llm/llm) | `llm` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants) |
| [`code-runtime-worker`](../packages/code-runtime/code-runtime-worker) | `code-runtime` | [`code-runtime`](../packages/code-runtime/code-runtime), [`invariants`](../packages/support/invariants) |
| [`helper`](../packages/sdk/helper) | `sdk` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants) |
@@ -745,11 +805,11 @@ flowchart TD
| [`spill-policy`](../packages/spill/spill-policy) | `spill` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`spill`](../packages/spill/spill), [`tools`](../packages/core/tools) |
| [`timeout-policy`](../packages/timeout/timeout-policy) | `timeout` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
| [`tool-todo`](../packages/todo/tool-todo) | `todo` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`tools`](../packages/core/tools) |
| [`plan-mode`](../packages/plan/plan-mode) | `plan` | [`agent`](../packages/core/agent), [`commands`](../packages/ui/commands), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-interaction`](../packages/ui/user-interaction) |
| [`tool-cordis`](../packages/cordis/tool-cordis) | `cordis` | [`invariants`](../packages/support/invariants), [`scope`](../packages/core/scope), [`tools`](../packages/core/tools) |
| [`hooks-codex`](../packages/hooks/hooks-codex) | `hooks` | [`agent`](../packages/core/agent), [`hook-protocol`](../packages/hooks/hook-protocol), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`tools`](../packages/core/tools) |
| [`session-checkpoint-policy`](../packages/session-persistence/session-checkpoint-policy) | `session-persistence` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`tools`](../packages/core/tools) |
| [`agent-loop-testkit`](../packages/support/agent-loop-testkit) | `support` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
| [`acp`](../packages/ui/acp) | `ui` | [`agent`](../packages/core/agent), [`bash`](../packages/bash/bash), [`commands`](../packages/ui/commands), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`llm-retry`](../packages/llm/llm-retry), [`permission`](../packages/ui/permission), [`sandbox`](../packages/sandbox/sandbox), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-title`](../packages/session-title/session-title), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-approval`](../packages/ui/user-approval), [`user-interaction`](../packages/ui/user-interaction) |
| [`tool-ask-user`](../packages/ui/tool-ask-user) | `ui` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools), [`user-interaction`](../packages/ui/user-interaction) |
| [`workspace-context`](../packages/context/workspace-context) | `context` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`paths`](../packages/util/paths), [`session`](../packages/core/session), [`tools`](../packages/core/tools) |
| [`repeat-tool-guard`](../packages/guard/repeat-tool-guard) | `guard` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |
@@ -761,6 +821,7 @@ flowchart TD
| [`subagent-inprocess`](../packages/subagent/subagent-inprocess) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
| [`tool-subagent`](../packages/subagent/tool-subagent) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
| [`hooks-claude`](../packages/hooks/hooks-claude) | `hooks` | [`agent`](../packages/core/agent), [`hook-protocol`](../packages/hooks/hook-protocol), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools) |
| [`acp`](../packages/ui/acp) | `ui` | [`agent`](../packages/core/agent), [`bash`](../packages/bash/bash), [`commands`](../packages/ui/commands), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`llm-retry`](../packages/llm/llm-retry), [`permission`](../packages/ui/permission), [`plan-mode`](../packages/plan/plan-mode), [`sandbox`](../packages/sandbox/sandbox), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-title`](../packages/session-title/session-title), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-approval`](../packages/ui/user-approval), [`user-interaction`](../packages/ui/user-interaction) |
| [`jsonrpc`](../packages/ui/jsonrpc) | `ui` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`llm-deepseek`](../packages/llm/llm-deepseek), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent) |
| [`tui`](../packages/ui/tui) | `ui` | [`agent`](../packages/core/agent), [`agent-loop`](../packages/core/agent-loop), [`commands`](../packages/ui/commands), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`llm-retry`](../packages/llm/llm-retry), [`session`](../packages/core/session), [`session-title`](../packages/session-title/session-title), [`system-prompt`](../packages/core/system-prompt), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools), [`user-interaction`](../packages/ui/user-interaction) |
| [`agent-spine-demo`](../packages/examples/agent-spine-demo) | `examples` | [`agent`](../packages/core/agent), [`agent-loop`](../packages/core/agent-loop), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`llm-retry`](../packages/llm/llm-retry), [`paths`](../packages/util/paths), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-title`](../packages/session-title/session-title), [`skill`](../packages/skill/skill), [`skill-local`](../packages/skill/skill-local), [`system-prompt`](../packages/core/system-prompt), [`tasks`](../packages/tasks/tasks), [`tool-bash`](../packages/bash/tool-bash), [`tool-goal`](../packages/goal/tool-goal), [`tool-skill`](../packages/skill/tool-skill), [`tool-tasks`](../packages/tasks/tool-tasks), [`tools`](../packages/core/tools), [`workspace-context`](../packages/context/workspace-context) |

View File

@@ -106,7 +106,7 @@ Sources: [`packages/core/session/src/types.ts:276`](../packages/core/session/src
Types: [CallId](core-data-structures/core.md)
Source: [`packages/ui/user-approval/src/index.ts:45`](../packages/ui/user-approval/src/index.ts)
Source: [`packages/ui/user-approval/src/index.ts:44`](../packages/ui/user-approval/src/index.ts)
#### `approval/decided` — log-only
@@ -122,7 +122,7 @@ Source: [`packages/ui/user-approval/src/index.ts:45`](../packages/ui/user-approv
}
```
Source: [`packages/ui/user-approval/src/index.ts:56`](../packages/ui/user-approval/src/index.ts)
Source: [`packages/ui/user-approval/src/index.ts:55`](../packages/ui/user-approval/src/index.ts)
#### `approval/policy` — log-only
@@ -138,7 +138,7 @@ Source: [`packages/ui/user-approval/src/index.ts:56`](../packages/ui/user-approv
'approval/policy': { policy: ApprovalPolicy }
```
Source: [`packages/ui/user-approval/src/index.ts:68`](../packages/ui/user-approval/src/index.ts)
Source: [`packages/ui/user-approval/src/index.ts:67`](../packages/ui/user-approval/src/index.ts)
### `assistant/*`
@@ -328,6 +328,21 @@ Source: [`packages/llm/llm-retry/src/index.ts:18`](../packages/llm/llm-retry/src
Source: [`packages/ui/permission/src/index.ts:36`](../packages/ui/permission/src/index.ts)
### `plan/*`
#### `plan/mode` — log-only
```ts persistence-catalog
/**
* Whether plan mode is in force from this point on: log-only, non-surface,
* whole-value replace. The last `plan/mode` wins; a log with none folds to
* inactive through {@link foldPlanMode}.
*/
'plan/mode': { active: boolean }
```
Source: [`packages/plan/plan-mode/src/index.ts:40`](../packages/plan/plan-mode/src/index.ts)
### `prompt/*`
#### `prompt/blocked` — log-only

View File

@@ -17,6 +17,7 @@ This table connects model-visible tool names to the plugin package and service s
| --- | --- | --- | --- | --- | --- |
| `@deepseek-ai/dsh-tool-ask-user` | `ask_user_question` | `ctx.tools`, `ctx.userInteraction` | `tool/call`, `tool/result after a UI/provider answers the question` | - | ask_user_question pauses the tool call until the active UI provider returns a human answer. |
| `@deepseek-ai/dsh-tools` | `run_code` | `ctx.tools`, `ctx.codeRuntime (execution time)`, `ctx.systemPrompt` | `tool/call`, `one tool/code-dispatch per bridged sub-call`, `tool/result` | - | Owned by the tool registry as a reserved transport outside filterable capability layers under `mode: code` / `mode: both` (see the Code Mode Agent Note). Under `code` it is the registry's only wire contribution; the other visible capabilities are declared in a generated TypeScript SDK section, and a program calls them through serialized bindings that re-enter the complete guarded tool pipeline and link each nested execution to this outer result. |
| `@deepseek-ai/dsh-plan-mode` | `exit_plan_mode` | `ctx.tools`, `ctx.systemPrompt`, `ctx.userInteraction (execution time, opportunistic)` | `tool/call`, `plan/mode inactive on an approved review`, `tool/result` | - | exit_plan_mode stays in the model-facing schema while planning is inactive so transitions add no tool-catalog churn on top of the plan-policy change. Its execute path rejects calls outside plan mode; in plan mode it presents the plan over the user-interaction seam (approve / keep planning with feedback), and approval logs plan mode inactive at the step boundary. |
| `@deepseek-ai/dsh-tool-bash` | `bash` | `ctx.tools`, `ctx.bash`, `ctx.tasks at call time for run_in_background` | `tool/call`, `tool/result` | - | The bash tool is the model-facing consumer of the bash executor seam. A `run_in_background` run registers with the generic `ctx.tasks` runtime and is collected/stopped through the `task_*` tools from `@deepseek-ai/dsh-tool-tasks`; the `enableRunInBackground` config (default true) removes the parameter entirely when disabled. |
| `@deepseek-ai/dsh-tool-cordis` | `cordis_inspect`, `cordis_mount`, `cordis_unmount` | `ctx.tools` | `tool/call`, `tool/result`, `live plugin-tree mutations (mount/unmount)` | - | Ships in examples/cordis-agent only (a deliberate opt-in — mounted code gets the real ctx, see .agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md). Plugins the model mounts may register ADDITIONAL model-visible tools at runtime; a full changed request header logs those tool-set changes. |
| `@deepseek-ai/dsh-tool-fs` | `edit`, `read`, `write` | `ctx.tools`, `ctx.fs`, `ctx.systemPrompt` | `tool/call`, `fs/write-intent or fs/edit-intent for mutations`, `fs/observed after successful file operations`, `tool/result` | - | The read-before-write/edit policy is added by `@deepseek-ai/dsh-fs-policy` (an `fs/*` event-gate plugin, no schema change); a deployment that loads these tools is expected to also load it. The tool schemas above are identical with or without the policy plugin. |
@@ -126,6 +127,31 @@ Source: [`packages/core/tools/src/code-mode.ts`](../packages/core/tools/src/code
Owned by the tool registry as a reserved transport outside filterable capability layers under `mode: code` / `mode: both` (see the Code Mode Agent Note). Under `code` it is the registry's only wire contribution; the other visible capabilities are declared in a generated TypeScript SDK section, and a program calls them through serialized bindings that re-enter the complete guarded tool pipeline and link each nested execution to this outer result.
## `@deepseek-ai/dsh-plan-mode`
### `exit_plan_mode`
Use only in plan mode. Present your plan for the user's review and, on approval, leave plan mode. Send the COMPLETE plan as markdown, starting with a # heading that names it. The user may approve (carry out the plan from your next step) or keep planning — their feedback comes back in the tool result; revise and present again.
```json
{
"type": "object",
"properties": {
"plan": {
"type": "string",
"description": "The complete plan, as markdown, starting with a # heading that names it."
}
},
"required": [
"plan"
]
}
```
Source: [`packages/plan/plan-mode/src/index.ts`](../packages/plan/plan-mode/src/index.ts)
exit_plan_mode stays in the model-facing schema while planning is inactive so transitions add no tool-catalog churn on top of the plan-policy change. Its execute path rejects calls outside plan mode; in plan mode it presents the plan over the user-interaction seam (approve / keep planning with feedback), and approval logs plan mode inactive at the step boundary.
## `@deepseek-ai/dsh-tool-bash`
### `bash`

107
docs/web-styling.md Normal file
View File

@@ -0,0 +1,107 @@
# Web GUI 样式规范
> **【token 体系已换代——§1 表格仅历史参考】** 本文的 `--bg-*`/`--text-*`/`--accent` token 族与其宿主包 `packages/client/web-ui` 已随插件化重构退役。现行 token 唯一来源=`packages/client/ui-theme/src/styles/` 的 `--dsw-*` 体系static 色阶+alias 语义层,暗色=`body[data-ds-dark-theme]` 覆写);组件对账基准=`missions/tasks/20260721-1520-web-plugin-rfc/style-spec.md`。**仍然有效**工程约束CSS Modules + clsx、无组件库、无 tailwind、组件禁 hardcode 色值)、字号成对写行高、间距 4 倍数、代码字体栈末位不放 monospace——这些已收编进 architecture.md §15。
> 状态:原「活文档」(随 `packages/client/web-ui` 演进)。视觉基线源自对 deepseekchat 前端仓的实测调研。框架决策与工程约束由 [web-styling-system RFC](../.agents/notes/implemented/process/2026-07-19-web-styling-system.md) 拍板,本文不重复论证。
## 1. 设计 token 表(权威定义)
所有 token 住 `packages/client/web-ui/src/style/global.css``:root` 亮色实值,`[data-theme='dark']` 块覆盖同名变量(未补全前列为占位)。组件 CSS 只引 token不出现字面量色值。
### 1.1 颜色(两层:注释里是 base 色板出处,变量名即语义别名)
| token | 亮色实值 | 暗色(占位) | 用途 |
| --- | --- | --- | --- |
| `--bg-base` | `#ffffff` | `#151517` | 页面底 |
| `--bg-layer` | `#ffffff` | `#232324` | 浮层/面板 |
| `--bg-sidebar` | `#f9fafb` | `#1b1b1c` | 侧边栏底 |
| `--text-primary` | `#0f1115` | `#f9fafb` | 正文 |
| `--text-secondary` | `#61666b` | `#cfd3d6` | 次要文字 |
| `--text-tertiary` | `#81858c` | `#adb2b8` | 辅助/说明 |
| `--border-l1` | `rgba(0,0,0,.04)` | `rgba(255,255,255,.06)` | 弱分隔(侧边栏右缘) |
| `--border-l2` | `rgba(0,0,0,.1)` | `rgba(255,255,255,.12)` | 常规边框 |
| `--hover-bg` | `rgba(38,49,72,.06)` | `rgba(255,255,255,.08)` | hover 态底 |
| `--active-bg` | `rgba(38,49,72,.1)` | `rgba(255,255,255,.14)` | 按压/激活态底 |
| `--accent` | `#3964fe` | `#5686fe` | 品牌蓝deepseek-500暗提亮一档 |
| `--accent-soft` | `#edf3fe` | `#28313f` | 淡品牌底(强调块) |
| `--accent-item` | `#e4edfd` | `#35363a` | 侧边栏选中条目底 |
| `--bubble-bg` | `#edf3fe` | `#2c2c2e` | 用户消息气泡底 |
| `--ok` / `--error` / `--warn` | `#22c55e` / `#ec1313` / `#f59e0b` | 同值 | 语义状态色 |
| `--text-on-solid` | `#ffffff` | 同值 | 实色底accent/error 徽标等)上的文字 |
| `--ok-soft` / `--error-soft` | `#e6faed` / `#fee2e2` | `#233c2c` / `#570c0c` | 语义状态软底徽章green-100/red-100暗为 900 档 |
| `--color-frame-mux` / `--color-frame-host` | `#8250df` / `#0969da` | 同值 | RPC 调试面板方向色(自有,非基线) |
| `--frame-mux-soft` / `--frame-host-soft` | `rgba(130,80,223,.1)` / `rgba(9,105,218,.1)` | 同色 `.24` | 方向色软底(徽章) |
| `--scroll-color` / `--scroll-color-hover` | `rgba(0,0,0,.08)` / `.15` | `rgba(255,255,255,.15)` / `.24` | 滚动条(`.scrollable` 专用) |
### 1.2 非颜色
| token | 值 | 说明 |
| --- | --- | --- |
| `--font-ui` | `Inter, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif` | 正文栈 |
| `--font-mono` | `Menlo, Monaco, Consolas, 'JetBrains Mono', 'Courier New', sans-serif` | 代码栈;**末位不放 monospace**(防 Windows 中文回退宋体) |
| `--fw-strong` | `600` | 粗体统一权重 |
| `--ease` | `cubic-bezier(.4,0,.2,1)` | 唯一缓动曲线 |
| `--dur` / `--dur-fast` / `--dur-slow` | `.2s` / `.1s` / `.3s` | 过渡三档 |
| `--radius-s` / `--radius-m` / `--radius-l` / `--radius-bubble` / `--radius-xl` | `8px` / `12px` / `16px` / `22px` / `24px` | 圆角语义档:小控件 / 列表条目与面板内块 / 浮层 / 气泡 / 输入卡片(基线 inputWrapper 同值);胶囊直接写 `999px` |
| `--shadow-panel` | `0 0 1px rgba(0,0,0,.2), 0 0 4px rgba(0,0,0,.02), 0 12px 32px rgba(0,0,0,.08)` | 浮层阴影(基线 lv3 |
| `--shadow-float` | `0 0 1px rgba(0,0,0,.24), 0 4px 12px rgba(0,0,0,.06), 0 16px 48px rgba(0,0,0,.16)` | 强浮动面板lv3 加强档,如 RPC 调试浮层) |
| `--shadow-card` | `0 4px 10px rgba(0,0,0,.02), 0 2px 4px rgba(0,0,0,.04)`;暗色 `none` | 输入卡片微阴影(基线:亮色同底靠边框+微影区分,暗色靠提亮底、阴影关闭) |
字号与间距**不 token 化**(基线仓同款决策):字号在组件里写 px 且**成对写行高**,常用对 16/24气泡、14/22UI 默认、12/18辅助间距用 4 的倍数。
## 2. 视觉基线(源自 deepseekchat
- 侧边栏:宽 `260px + 1px` 右边框(`--border-l1`);底色 `--bg-sidebar`
- 侧边栏条目:高 `40px`、圆角 `--radius-m`、字号 14pxhover 底 `--hover-bg` 或 sidebar 专属灰、**选中底 `--accent-item` 且不改文字色**。
- 侧边栏分组标题12px / weight 500 / `--text-tertiary` / sticky 顶部(底色同侧边栏遮滚动内容)。
- 会话列:`max-width: 840px` 居中,<1024px 降 712px。
- 消息流:**仅用户侧有气泡**——`--bubble-bg` 底、圆角 `--radius-bubble`、padding `10px 16px`、字号 16px/24px、`max-width: calc(100% - 88px)`**助手侧纯文档流无底色**。
- 消息操作条:默认 `opacity: 0`,父块 hover/focus-within 淡入(`--dur` + `--ease`)。
- 输入卡片与会话列同宽840px<1024px 降 712px)居中悬浮(距底留白带);圆角 `--radius-xl`、边框 `--border-l2`、底 `--bg-base`、阴影 `--shadow-card`;内部上下两段=textarea16px/24pxmin 2 行 max 14 行=336px镜像 div 自增高)+ 操作行(右下嵌 34px 主圆钮focus 无边框/阴影变化(基线同款)。
- 输入主按钮(拍板 2026-07-20 三连,视觉参照 Codex App32px 实心正圆图标钮(内联 SVG——空闲=`--accent` 底白↑箭头「发送」,运行中原地变 `--accent-soft` 底 accent ■「停止」(同色系不告警、不用红)。**运行中锁输入**(拍板 3取代早先 hover 菜单方案textarea disabled灰、草稿内容保留可见、无任何排队/插话菜单停止是唯一动作turn 结束解禁并 refocus。键盘 Enter=发送、Ctrl/Meta+Enter=换行(运行中键盘路径随锁失效)。
- 滚动条近隐形、hover 加深、`scrollbar-gutter: stable` 不占布局(统一走 `.scrollable`,见 §3-9
- RPC 四象限方向符(官方视觉词汇,空间隐喻:上=去 server、下=来自 server单线=unary、双线=SSE
| 符号 | 象限 | 徽章配色 |
| --- | --- | --- |
| `↑` | client-requestunary 出站) | `--accent` / `--accent-soft` |
| `↓` | server-responseunary 回包) | ok `--ok`/`--ok-soft`error `--error`/`--error-soft` |
| `⇟` | server-requestSSE 帧推送) | mux `--color-frame-mux`/`--frame-mux-soft`host `--color-frame-host`/`--frame-host-soft` |
| `⇞` | client-responseSSE 侧回应) | `--accent`/`--accent-soft` 降透明度 |
## 3. 样式编码规范review 对照打勾)
1. 颜色/圆角/动效/字体栈只引 §1 token组件 CSS 出现字面量色值即打回(渐变遮罩等特效除外,须注释说明)。
2. 组件 CSS 禁止出现 `[data-theme]` 选择器;暗色差异只在 global.css token 表做。确需按主题换非 token 值(渐变端点等),组件定义局部 CSS 变量、主题块只覆写变量(变量桥)。
3. 类名 camelCase状态类用单形容词`.active` `.show`),由 clsx 挂载:`clsx(styles.x, cond && styles.active, className)`
4. 对外组件必须透传 `className` 并合入根元素。
5. 禁用 `composes`;复用靠 token 与组件抽取。
6. `:global` 仅用于穿透第三方/跨包类名;禁止用它定义新全局类。
7. 交互过渡一律 `var(--dur*) var(--ease)`,只过渡 opacity / transform / 背景色 / 阴影;纯 hover 展示型元素包 `@media (hover: hover)`
8. hover/active 底色优先用透明度制 token叠任意海拔底色都成立不新造实色灰。
9. 滚动容器统一挂 global.css 的 `.scrollable` 工具类;组件内禁写 `::-webkit-scrollbar`
10. 媒体查询写在组件 css 尾部、贴着被覆盖规则;断点当前仅 1024px 一档(会话列降档),加第二档需先记入本文档。
11. 动态样式 JS 侧只写 CSS 变量(`style={{'--x': v}}`),规则留在 CSS禁止在 TSX 里拼接样式对象做主题/状态分支。
12. 文字灰阶只用 `--text-primary/secondary/tertiary` 三级,不新造灰色。
## 4. 文件组织
- `src/style/global.css` 固定分区顺序:① token 表(`:root` + `[data-theme='dark']`)② 全局基础box-sizing、body、button reset③ 全局工具类(`.scrollable` 等,总数保持个位数)。
- `*.module.css` 与组件同目录同名;一个组件一个 module 文件。
- 类型声明用现有 `css-modules.d.ts` 通配;组件数超 20 再评估引入 tcm 生成精确 `.css.d.ts`
- PostCSS 特性白名单:当前**零插件**(平铺 CSS + 原生嵌套按需);引入 nested/custom-media 需先记入本文档。
## 5. 演进规则与偏离记录
- **加新 token**:先进 §1 表含暗色占位列再在组件使用review 见到未入表的 `--` 新变量即打回(组件局部变量桥除外)。
- **偏离基线**:与 §2 任一常数不一致的实现,须在下方偏离表记一行(日期/项/理由)。
- **暗色表补全验收**`[data-theme='dark']` 覆盖 §1 全部占位列后,用 RPC 面板 + 侧边栏 + 会话流三个界面人工/截图核对一遍,无组件级主题选择器即达标。
| 日期 | 偏离项 | 理由 |
| --- | --- | --- |
| (空) | | |
## 6. 相关文档
- [web-styling-system RFC](../.agents/notes/implemented/process/2026-07-19-web-styling-system.md)(框架五条与工程约束的裁决记录)
- 客户端消费架构与分层协议:[Web 客户端架构 RFC](../.agents/notes/implemented/architecture/2026-07-19-gui-web-client-architecture.md)、[GUI 分层与 RPC 协议 RFC](../.agents/notes/implemented/architecture/2026-07-19-gui-layering-and-rpc-protocol.md)