dsh-tower 1.3.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/CONTRIBUTING.md +1 -1
  3. package/README.en.md +44 -8
  4. package/README.md +42 -8
  5. package/cordis.patch.yml +11 -1
  6. package/docs/README.md +10 -5
  7. package/docs/architecture/overview.md +13 -9
  8. package/docs/faq.md +45 -2
  9. package/docs/guide/hot-reload.md +189 -0
  10. package/docs/guide/install-upgrade-migration.md +11 -0
  11. package/docs/guide/quickstart.md +33 -1
  12. package/docs/guide/scenarios-and-philosophy.md +309 -0
  13. package/docs/operations/runbook.md +23 -0
  14. package/docs/operations/security.md +23 -0
  15. package/docs/reference/blockers.md +10 -2
  16. package/docs/reference/config.md +65 -2
  17. package/docs/reference/doctor.md +33 -0
  18. package/docs/reference/errors.md +50 -0
  19. package/docs/reference/events.md +45 -0
  20. package/docs/reference/operations.md +55 -0
  21. package/docs/reference/testing.md +61 -0
  22. package/docs/reference/tools.md +65 -23
  23. package/docs/zh/README.md +60 -0
  24. package/docs/zh/faq.md +81 -0
  25. package/docs/zh/guide/hot-reload.md +178 -0
  26. package/docs/zh/guide/install-upgrade-migration.md +57 -0
  27. package/docs/zh/guide/quickstart.md +96 -0
  28. package/docs/zh/guide/scenarios-and-philosophy.md +211 -0
  29. package/docs/zh/operations/security.md +42 -0
  30. package/docs/zh/reference/blockers.md +62 -0
  31. package/docs/zh/reference/config.md +113 -0
  32. package/docs/zh/reference/doctor.md +31 -0
  33. package/docs/zh/reference/errors.md +52 -0
  34. package/docs/zh/reference/events.md +46 -0
  35. package/docs/zh/reference/operations.md +50 -0
  36. package/docs/zh/reference/testing.md +60 -0
  37. package/docs/zh/reference/tools.md +75 -0
  38. package/index.js +261 -13
  39. package/lib/batch.js +578 -0
  40. package/lib/config.js +275 -9
  41. package/lib/doctor.js +171 -0
  42. package/lib/errors.js +111 -0
  43. package/lib/hmr.js +196 -0
  44. package/lib/leases.js +317 -0
  45. package/lib/legacy.js +413 -0
  46. package/lib/modeStore.js +28 -1
  47. package/lib/store.js +24 -1
  48. package/lib/tests.js +628 -0
  49. package/lib/tools.js +1566 -184
  50. package/lib/tower.js +986 -103
  51. package/lib/workspaceLock.js +117 -0
  52. package/lib/worktreeOwnership.js +166 -0
  53. package/package.json +4 -1
  54. package/reviewer.js +1 -0
  55. package/scripts/check-docs.mjs +135 -0
  56. package/scripts/enable-dev-hmr.mjs +347 -0
  57. package/skills/tower-review.md +4 -2
  58. package/skills/tower-worker-protocol.md +3 -1
  59. package/worker.js +4 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,114 @@
1
1
  # Changelog
2
2
 
3
+ > 自 2.0.0 起,每个版本按 **新增 / 变更 / 修复** 三类组织;更早的版本保留原始流水式记录。
4
+
5
+ ## 2.0.1(2026-10-18)
6
+
7
+ ### 新增
8
+
9
+ - **`tower_batch` 的 `abandon` 动作**:可带 `reason` 退掉过期的 open batch,不修改 mission 状态;
10
+ 用于"先 merge 后 close"或证据窗口已过的场景。
11
+
12
+ ### 修复
13
+
14
+ - **#3 `allowAgentControl` 被 schema 默认值遮蔽**:移除 `mode.allowAgentControl` 的 schema 默认值,
15
+ 在 legacy 别名解析后再应用默认;随包 patch 改用 canonical `mode.allowAgentControl: true`。
16
+ Cordis 校验后的配置现在能正确注册 `tower_control`。
17
+ - **#4 `tower_preflight` 未知 mission 产生非 lossless 输出**:`evaluateGate` 的 early return 与工具
18
+ 包装补齐 `branchTip/baseTip/changedFiles/review` 的 `null`/`[]` 形状。
19
+ - **#5 未知依赖被分类为 `tool-internal`**:`depends on unknown mission` 归入 `invalid-argument`。
20
+ - **#6 worker 可 spawn 到 merged/abandoned mission**:spawn 前拒绝终态 mission,不再 provision/
21
+ activation,不再改写已合并 mission 的 owner/generation。
22
+ - **#7 live `tests/live/ui-slots.cjs` 在新会话 dock 隐藏时误报**:先提交 host-handled `/tower`
23
+ 命令绑定会话,再断言 dock;`DSH_TEST_EXPECT_HINT=1` 才要求 dock 可见。
24
+ - **#8 `plan-mode.test.mjs` 写入真实 `$DSH_HOME`**:测试前设置临时 `DSH_HOME` 并在 after 清理;
25
+ 清理了历史 `session-plan-test` 残留。
26
+ - **#9 `tower_batch` close 拒绝 merged 成员/无法退掉 stale batch**:`merged` 与 completed 一样
27
+ 可 close(checks 仍从完成报告/testRuns/close-time checks 解析);新增 `abandon` 且 batch 状态
28
+ 可退,不会永久卡死。
29
+ - **#10 `tower_doctor` 在成功 teardown 后误报 worktree missing**:跳过带 `worktreeRemovedAt` 的
30
+ mission,并在检查详情中注明已移除数量。
31
+
32
+ ### 变更
33
+
34
+ - 离线套件增至 212 项(新增 issue 回归覆盖);`docs:check` 仍为 28 tools / 32 blockers /
35
+ 30 errors / 25 events。
36
+
37
+ ## 2.0.0(2026-10-18)
38
+
39
+ ### 新增
40
+
41
+ - **仓库级配置层**:`Tower.open()` 读取 `<git-common-dir>/dsh-tower/config.json`,优先级为
42
+ 代码默认 < profile 配置 < 仓库配置 < 工具参数;`review`/`merge`/`worktrees`/`spawn` 分组生效。
43
+ - **稳定工具错误码**:新增 `lib/errors.js`,工具失败统一 `[tower:<code>]` 前缀,覆盖 17 个 code;
44
+ 新增 `docs/reference/errors.md` 并由 `npm run docs:check` 校验。
45
+ - **finding 生命周期**:新增 `tower_findings`(列表/读取/状态流转/备注),状态为
46
+ `open → triaged → fixed` / `wontfix` 且可重新打开;只有 tower 或 worker 能改状态,reviewer 只读。
47
+ - **中文文档**:新增 `docs/zh/`(文档索引、quickstart、工具/配置/blocker/错误码参考),
48
+ 与英文参考页保持同一套工具名、blocker 与错误码。
49
+ - **测试与门禁**:新增仓库配置、finding 生命周期、工具别名/错误码/输出 schema、spawn mock
50
+ 与全流程 schema 校验用例;`docs:check` 同时校验中英文参考页、工具名、blocker 与错误码。
51
+ - **协议硬化**:`tower_interrupt`(停止 running agent)、`tower_send(interrupt:true)`;
52
+ `tower_init` 支持 `autoGitInit`/`snapshotDirty`/`reanchor`;worker 不能直接完成/放弃/扩界,
53
+ completed 必须经 `tower_complete`;单 mission 单活 worker + `takeover` 接管 + generation。
54
+ - **治理与可观测**:可选 `mode.workspaceLock` 仓库互斥;`spawn.maxLiveWorkers`、`send.maxPerMinute`
55
+ 与 roster stale 标记;`tower_status` 分页/单 mission 明细/gate digest/markdown;`MISSIONS.md`
56
+ 人类可读门板;`tower/*` 进程内事件;`tower_complete.checks` + `gates.requireChecks`。
57
+ - **热重载**:`/tower reload` 与 `tower_reload` 调用 DSH HMR `reconcileProfile`;新增
58
+ `npm run dev:hmr` 脚本把 linked 仓库加入 profile HMR watch root;`docs/guide/hot-reload.md`。
59
+ - **2.1 测试准入**:读取 worktree `package.json` 的 `tower.testDiscovery`(TAP/json-array),支持
60
+ `tests.admission:spawn|complete`、16 MiB/60s 预算、minCount/required;`tower_test` 与
61
+ `tower_complete` 自动生成 `tests` check;`gates.requireTests` / `tests-missing` / `tests-failed`。
62
+ - **2.1 批次与运营**:`tower_batch`(create/status/close,冻结成员、requiredChecks、receiptPaths)、
63
+ `tower_resource`(advisory lease,token/过期显式 force)、`tower_doctor`(只读健康契约)、
64
+ `tower_import_legacy` / `tower_legacy_map`(只读快照 + 审计映射)。
65
+ - **2.1 治理**:per-repo roster watchdog(`spawn.staleMs` 15s 标记 stale 并阻断合并)、
66
+ `spawn.maxWaitMs` 90s、`mode.workspaceLockScope`、plan/tower 互斥(默认清除 plan)、
67
+ `/tower base <branch>`、`docs.boardLocation`、delivery ack、merge intent 持久化。
68
+ - **2.1 UI**:ui-bundle 增加 12 个 tower tool 卡片、composer dock 最新摘要与 shell.overlay 瞬时状态条;
69
+ 纯会话派生,无 Host RPC/iframe。
70
+ - **2.1 文档**:`docs/reference/testing.md`、`operations.md`、`doctor.md` 与中文同步;工具面 28。
71
+
72
+ ### 变更
73
+
74
+ - **结构化输出 schema**:全部工具声明 output schema(spawn/status/diff/merge/review/preflight
75
+ 等核心工具含字段结构),并按 DSH 的输出校验规则保证可空字段可空。
76
+ - **命名统一(兼容别名)**:mission 级工具同时接受 `id` 与 `missionId`;`task_done`/`taskDone`、
77
+ `task_drop`/`taskDrop`、`clear_blockers`/`clearBlockers`、`include_read`/`includeRead`、
78
+ `dry_run`/`dryRun`、`timeoutMs`/`timeout_ms`、`waitMs`/`wait_ms` 等写法均可,并在参数 schema
79
+ 中显式声明;输出保持既有规范。
80
+ - **诊断信息**:`tower_status` 增加 `config.path`、`config.repoConfigPresent` 与
81
+ `findingsByStatus`;worker/reviewer preset 允许 `tower_findings`。
82
+ - **配置解析**:兼容别名只用于补缺——同时设置 `section` 与 `mode.promptSection` 时规范键优先;
83
+ 仓库配置增加 1 MiB 大小上限与 `__proto__`/`constructor`/`prototype` 等危险键拒绝。
84
+ - **配置默认值**:`mode.denyTools` 追加 workflow/ralph/subagent/subagent_fork/wait_agent/team_task_list
85
+ (Tower 模式与其它编排互斥);新增 `spawn.maxLiveWorkers:4`、`spawn.staleMs:15000`、
86
+ `spawn.maxWaitMs:90000`、`send.maxPerMinute:120`、`gates.requireChecks:false`、
87
+ `gates.requireTests:false`、`docs.board:true`、`leases.ttlMs:900000`、`dev.hotReload:true`;
88
+ 随包 patch 打开 `workspaceLock`/`interruptDefault`/`autoGitInit`。
89
+ - **briefing**:worker/reviewer 生成历史审查、上一轮 findings/decision、completion checks 与
90
+ related findings,长文本截断;reviewer 必须核对 completion checks。
91
+ - **输出/工具面**:`tower_status` 增加 total/offset/nextOffset/detail/markdown,并**默认只返回前 20 个 mission**(旧版返回全部;旧调用需要更多时用 `limit`/`offset`);`tower_adopt`
92
+ 支持 `retireMissing:false`;`tower_mode` 返回 pluginVersion/HMR/workspace lock;`tower_roster`
93
+ 增加 `stale`。工具总数最多 28(含 doctor/test/batch/resource/import/legacy_map 与可选的 control/reload)。
94
+ - **离线套件**:测试增至 206 项(含 2.1 discovery/batch/leases/legacy/doctor/UI/plan-mode/integration 用例)。
95
+ - 除 `tower_status` 默认分页与 `mode.denyTools` 默认扩充外,既有工具参数与输出保持兼容。
96
+
97
+ ### 修复
98
+
99
+ - **模式工具 schema 与返回值不一致**:`tower_mode`/`tower_control` 的 `lastChange`、`pausedGoal`、
100
+ `goalNote` 在正常路径返回 `null`,原 schema 会触发 DSH 强制输出校验失败;已改为可空并补回归测试。
101
+ - **错误码分类补全**:state 校验失败统一归为 `state-corrupt`;`tower_complete` 的未完成任务、
102
+ blocker、无提交、未读消息等前置条件归为 `invalid-transition`,不再落到 `tool-internal`。
103
+ - **findings 更新后的计数**:状态流转后返回的 `counts` 之前是旧值,现在按变更后重新统计。
104
+ - **findings 只读路径**:列表/读取不再获取写锁,与工具描述一致,长合并或 hook 期间也能读取。
105
+ - **mission id 规范化**:`tower_mission` 对首尾空白的 `id` 先 trim 再查找,不再误报
106
+ `mission-not-found`。
107
+ - **角色绕过**:worker 之前可经 `tower_mission` 直接 completed/abandoned/扩界或清 blocker,
108
+ 绕过 `tower_complete` 的未读/提交证据;现由服务端角色强制。
109
+ - **并发与接管**:同一 mission 不再允许出现第二个 live worker;stale/interrupted/failed 的
110
+ worker 可显式 takeover,running worker 必须先中断,否则 `takeover-refused`。
111
+
3
112
  ## 1.3.0 — 2026-10-18
4
113
 
5
114
  - **独立的只读 reviewer preset**:新增 `reviewer.js` / `tower-reviewer`,去掉 `write`/`edit`/`pwsh`/
package/CONTRIBUTING.md CHANGED
@@ -21,7 +21,7 @@ Requirements: Node.js 22+, Git. No package installation is needed for the offlin
21
21
 
22
22
  ## Pull request checklist
23
23
 
24
- 1. `npm test` passes locally (26 tests today, including protocol end-to-end against a real temporary Git repository) and `npm run docs:check` passes.
24
+ 1. `npm test` passes locally (206 tests today, including protocol end-to-end against a real temporary Git repository and mock spawn coverage) and `npm run docs:check` passes.
25
25
  2. New behavior has a test. Bug fixes should add a test that fails before the fix.
26
26
  3. No secrets, tokens, personal paths, session logs, or generated artifacts are added. `.gitignore` covers local acceptance output; do not force-add it.
27
27
  4. Keep the public API and state-file formats compatible; if a change is breaking, call it out in `CHANGELOG.md` and bump the version.
package/README.en.md CHANGED
@@ -18,6 +18,36 @@ The repository root **is** the DSH bundle: `package.json` declares `dsh.bundle.p
18
18
  - **Review-gated merges.** A reviewer bound to the current branch tip must submit a `clean` / `merge` verdict; the merge gate re-checks scope, staleness, task completion, review history, and worktree ownership before a `--no-ff` merge.
19
19
  - **Durable coordination.** Roster, inbox, findings, reviews, and mission state are persisted under `.git/dsh-tower/`, so a restart does not lose the plan.
20
20
  - **Safe by default.** While Tower mode is active, `create_goal`, `update_goal(resume)`, `todo_write`, the Team task board, and `spawn_teammate` are refused; a paused goal is never resumed automatically.
21
+ - **Traceable finding lifecycle.** `tower_findings` lists, reads, and moves findings through `open → triaged → fixed` / `wontfix` (and can reopen); only the tower or a worker may change state, while reviewers can only read.
22
+ - **Repository-level config.** Any repository can override review/merge/worktree/spawn policy in `<git-common-dir>/dsh-tower/config.json`; tool arguments override the repository layer, so no profile edit is needed per repository.
23
+ - **Stable error codes.** Tool failures carry a `[tower:<code>]` prefix (for example `mission-not-found`, `preset-missing`, `config-invalid`) so callers can branch deterministically.
24
+ - **Role enforcement and control.** Workers cannot complete/abandon a mission or widen its scope directly (completion goes through the `tower_complete` evidence gate); the tower can stop a runaway agent with `tower_interrupt`, and `tower_send(interrupt:true)` interrupts a running turn.
25
+ - **Workspace exclusivity and limits.** Optional `mode.workspaceLock` allows one Tower session per repository; `spawn.maxLiveWorkers`, `send.maxPerMinute` and roster stale flags bound concurrency and message bursts.
26
+ - **2.1 verification and operations.** `tower_test` runs the worktree's `tower.testDiscovery` (TAP/json-array, admission at spawn or complete), `tower_doctor` is a read-only health contract, `tower_batch` closes finite evidence batches, `tower_resource` manages advisory leases, and `tower_import_legacy`/`tower_legacy_map` import old snapshots and audit-map ids. Adds `worker-stale`, test gates, plan/Tower mutual exclusion, `workspaceLockScope`, `docs.boardLocation` and delivery acknowledgements.
27
+ - **Hot reload.** In a profile with DSH HMR, `/tower reload`, `tower_reload` and `npm run dev:hmr` apply linked plugin changes without a restart; `plugin_manager` install/update already applies live.
28
+ - **Evidence gate and events.** Workers can record `checks` in `tower_complete` and `gates.requireChecks` can require them; every mutation emits `tower/*` events and refreshes `MISSIONS.md`.
29
+
30
+ ## When to use Tower
31
+
32
+ Tower is a **delivery protocol for changes to a Git repository**, not the default answer for every multi-agent task. It fits when:
33
+
34
+ - a feature or refactor splits into 2–8 missions with clear scopes that can be reviewed independently;
35
+ - ordering matters (migrations, dependencies, branch freshness, scope reservations);
36
+ - the repository is sensitive or release-bound, and you need a reviewed commit, test evidence, and an auditable merge;
37
+ - work spans context compaction, restarts, or multiple days and must be recoverable from local state;
38
+ - "done" means tasks + tests + independent review, not just a confident message in chat.
39
+
40
+ It is a poor fit for one-file or one-line hotfixes, requirements still being discovered, open-ended research, many tiny independent tasks, interactive UI pairing, or cross-repository work. Rule of thumb: **if you would not open a PR for it, Tower is probably too heavy.**
41
+
42
+ How it differs (full guide: [When to use Tower](docs/guide/scenarios-and-philosophy.md)):
43
+
44
+ - **Ordinary parallel subagents**: cheap and flexible for read-only exploration or trying approaches; no worktree, review, or merge gate.
45
+ - **Agent Teams**: shared task board and peer collaboration for design, research, and cross-cutting decisions; integration is usually human, with no hard Git gate.
46
+ - **Ralph loop**: fresh agents retry one objective, good for iterative search/repair; no mission contract or merge review.
47
+ - **Workflow orchestration**: scripted high fan-out/pipelines for audits, batch analysis, and verification; no branch isolation or merge gate.
48
+ - **Tower**: a few missions + isolated writers + independent review + evidence + a merge gate, for "we have decided; land it safely".
49
+
50
+ Tower mode refuses Team/Workflow/Ralph/ordinary subagent tools and clears plan mode so two orchestration protocols do not drive one session. Compose by phase instead: use Workflow/Team to analyze and decide, then Tower to execute the repository change.
21
51
 
22
52
  ## Requirements
23
53
 
@@ -105,14 +135,16 @@ Image and file attachments are forwarded together with the instruction as one co
105
135
  maxDepth: 1
106
136
  ```
107
137
 
108
- - `mode.allowAgentControl` defaults to `false` in code; the bundled `cordis.patch.yml` enables it (`true`) so the model may enter/leave when the user intent or task state warrants it, always stating a reason.
109
- - Every key and default is in [docs/reference/config.md](docs/reference/config.md); unknown keys are rejected so typos cannot silently disable security-relevant settings.
138
+ - `mode.allowAgentControl` defaults to `false` in code; the bundled `cordis.patch.yml` enables it (`true`) so the model may enter/leave when the user intent or task state warrants it, always stating a reason. The bundled patch also enables `mode.workspaceLock` (single-active tower), `send.interruptDefault`, `init.autoGitInit`, and sets `spawn.staleMs` to 15s.
139
+ - `/tower base <branch>` records a session-level init base preference; `/tower on` clears an active plan mode (`mode.planModePolicy:"refuse"` instead refuses entry), keeping plan and Tower mutually exclusive.
140
+ - Repository-level config: put the same JSON shape in `<git-common-dir>/dsh-tower/config.json` (usually `.git/dsh-tower/config.json`) to override `review`/`merge`/`worktrees`/`spawn`. Precedence is code defaults < profile config < repository config < tool arguments. `mode.*` is session-scoped and only the profile layer controls it.
141
+ - Every key and default is in [docs/reference/config.md](docs/reference/config.md); unknown top-level keys are rejected so typos cannot silently disable security-relevant settings, while unknown keys inside a group are ignored. Tool error codes are in [docs/reference/errors.md](docs/reference/errors.md).
110
142
 
111
- ## Tools (18)
143
+ ## Tools (26 core)
112
144
 
113
- `tower_init` · `tower_plan` · `tower_mission` · `tower_status` · `tower_spawn` · `tower_roster` · `tower_adopt` · `tower_diff` · `tower_send` · `tower_inbox` · `tower_complete` · `tower_finding` · `tower_review` · `tower_preflight` · `tower_merge` · `tower_rebase` · `tower_teardown` · `tower_mode`
145
+ `tower_init` · `tower_plan` · `tower_mission` · `tower_status` · `tower_spawn` · `tower_roster` · `tower_adopt` · `tower_diff` · `tower_send` · `tower_inbox` · `tower_complete` · `tower_interrupt` · `tower_finding` · `tower_findings` · `tower_review` · `tower_preflight` · `tower_merge` · `tower_rebase` · `tower_teardown` · `tower_mode` · `tower_doctor` · `tower_test` · `tower_batch` · `tower_resource` · `tower_import_legacy` · `tower_legacy_map`
114
146
 
115
- `tower_control` exists only when `allowAgentControl: true` (the bundled patch enables it, so an installed build exposes 19 tools).
147
+ `tower_control` exists only when `allowAgentControl: true`; `tower_reload` is registered while `dev.hotReload` is on (default true) and returns `reload-unavailable` without an HMR service (so up to 28 tools). Mission-scoped tools also accept `id` as an alias for `missionId`; snake/camel spellings such as `task_done`/`taskDone` are both accepted.
116
148
 
117
149
  ## Safety and guardrails
118
150
 
@@ -122,7 +154,7 @@ Image and file attachments are forwarded together with the instruction as one co
122
154
  - **Worktree ownership.** Dirty worktrees, a running worker, or a branch owned by a closed mission block teardown/merge.
123
155
  - **Goal isolation.** Entering Tower mode pauses the active goal and records it; leaving does not resume it. Use `/tower off` and resume the goal yourself.
124
156
 
125
- 13 stable blocker codes (plus 6 additional gate guards and 6 merge/rebase failure codes) — the complete list with triggers and fixes is in [docs/reference/blockers.md](docs/reference/blockers.md).
157
+ 32 stable blocker/failure codes (including gate guards, `no-check-evidence`, `worker-stale`, test gates, and merge/rebase operation failures) — the complete list with triggers and fixes is in [docs/reference/blockers.md](docs/reference/blockers.md). Tool-level error codes are in [docs/reference/errors.md](docs/reference/errors.md); events are in [docs/reference/events.md](docs/reference/events.md).
126
158
 
127
159
  ## How it works
128
160
 
@@ -156,13 +188,17 @@ Workers use the bundled `tower-worker` preset (writable worktree surface); revie
156
188
  npm test # node --test tests/*.test.mjs
157
189
  ```
158
190
 
191
+ Hot-reload development: `npm run dev:hmr` adds this checkout to the current profile's HMR watch roots
192
+ (one DSH restart); afterwards `/tower reload` or the automatic watcher applies `lib/` edits. See
193
+ [docs/guide/hot-reload.md](docs/guide/hot-reload.md).
194
+
159
195
  The offline suite needs no DSH process and creates throwaway Git repositories in the OS temp directory. `tests/README.md` documents the isolated Web-runtime checks, model-driven acceptance, and the session-diagnostic scripts used while hardening the plugin.
160
196
 
161
197
  ## Documentation
162
198
 
163
199
  - [docs/README.md](docs/README.md) — documentation index (new user / operator / maintainer paths)
164
- - [Quick start](docs/guide/quickstart.md) · [Install, upgrade and migration](docs/guide/install-upgrade-migration.md)
165
- - [Tools reference](docs/reference/tools.md) · [Config reference](docs/reference/config.md) · [Blockers and failure codes](docs/reference/blockers.md)
200
+ - [Chinese docs](docs/zh/README.md) · [Quick start](docs/guide/quickstart.md) · [Install, upgrade and migration](docs/guide/install-upgrade-migration.md)
201
+ - [Tools reference](docs/reference/tools.md) · [Config reference](docs/reference/config.md) · [Blockers and failure codes](docs/reference/blockers.md) · [Error codes](docs/reference/errors.md) · [Events](docs/reference/events.md) · [Testing](docs/reference/testing.md) · [Batches/leases/legacy](docs/reference/operations.md) · [Doctor](docs/reference/doctor.md) · [Hot reload](docs/guide/hot-reload.md)
166
202
  - [Architecture and state machine](docs/architecture/overview.md) · [Operations runbook](docs/operations/runbook.md) · [Security model](docs/operations/security.md)
167
203
  - [FAQ](docs/faq.md) · [Examples](docs/examples/first-mission.md)
168
204
 
package/README.md CHANGED
@@ -18,6 +18,36 @@ Tower 模式与 mission/审查工作流的灵感来自 Moonshot AI 的 **Kimi Co
18
18
  - **审查门禁合并。** 审查者必须针对当前分支 tip 给出 `clean` / `merge` 结论;合并门禁重新校验 scope、分支新鲜度、任务完成度、审查记录与 worktree 归属,通过后才执行 `--no-ff` 合并。
19
19
  - **可恢复的协作状态。** roster、inbox、findings、reviews 与 mission 状态持久化在 `.git/dsh-tower/` 下,重启不会丢计划。
20
20
  - **默认安全。** Tower 模式开启期间拒绝 `create_goal`、`update_goal(resume)`、`todo_write`、Team 任务板与 `spawn_teammate`;被暂停的 goal 不会被自动恢复。
21
+ - **可追溯的 finding 生命周期。** `tower_findings` 列表、读取并按 `open → triaged → fixed` / `wontfix` 流转,也可重新打开;只有 tower 或 worker 能改状态,reviewer 只能读。
22
+ - **仓库级配置。** 每个仓库可用 `<git-common-dir>/dsh-tower/config.json` 覆盖 review/merge/worktree/spawn 策略,工具参数再覆盖仓库配置;无需为不同仓库改 profile。
23
+ - **稳定错误码。** 工具失败统一带 `[tower:<code>]` 前缀(如 `mission-not-found`、`preset-missing`、`config-invalid`),调用方可稳定分支处理。
24
+ - **角色强制与可控中断。** worker 不能直接完成/放弃 mission 或扩界(完成必须走 `tower_complete` 证据门),tower 可随时用 `tower_interrupt` 停止跑偏的 agent;`tower_send(interrupt:true)` 可中止运行中的 turn。
25
+ - **仓库互斥与限流。** 可选 `mode.workspaceLock` 让同一仓库只有一个 Tower 会话;`spawn.maxLiveWorkers`、`send.maxPerMinute`、roster stale 标记约束并发与消息风暴。
26
+ - **可热重载。** 在带 DSH HMR 的 profile 中,`/tower reload`、`tower_reload` 与 `npm run dev:hmr` 让 linked 插件代码改动无需重启即生效;`plugin_manager` 安装/更新本身即时生效。
27
+ - **测试证据门与事件。** worker 可在 `tower_complete` 记录 `checks`,`gates.requireChecks` 可强制;每次 mutation 后发射 `tower/*` 事件并刷新 `MISSIONS.md`。
28
+ - **2.1 验证与运营。** `tower_test` 执行 worktree 声明的 `tower.testDiscovery`(TAP/json-array,准入可设 spawn/complete),`tower_doctor` 只读健康契约,`tower_batch` 批次证据收口,`tower_resource` advisory lease,`tower_import_legacy` / `tower_legacy_map` 只读旧版导入与审计映射;新增 `worker-stale`、tests 门禁、plan/tower 互斥、`workspaceLockScope`、`docs.boardLocation` 与交付 ack。
29
+
30
+ ## 何时使用 Tower
31
+
32
+ Tower 是**面向 Git 仓库变更的交付协议**,不是所有多代理场景的默认答案。它适合:
33
+
34
+ - 一个特性/重构能拆成 2–8 个 scope 清晰、可独立审查的 mission;
35
+ - 有依赖顺序、需要分支新鲜度与 scope 约束的迁移;
36
+ - 敏感仓库、发布绑定变更,或需要"被审查 commit + 测试证据 + 可审计合并"的工作;
37
+ - 跨上下文压缩、重启、多天协作,需要从本地状态恢复的工作;
38
+ - 需要把"完成"定义成任务 + 测试 + 独立审查,而不是聊天里的一句"好了"。
39
+
40
+ 不适合:单文件/一行 hotfix、需求仍在探索、开放式研究、大量极小的独立任务、交互式 UI 配对、或跨仓库工作。判断标准:**如果你不会为它开 PR,Tower 很可能太重。**
41
+
42
+ 与其他模式的区别(详见[完整指南](docs/guide/scenarios-and-philosophy.md)):
43
+
44
+ - **普通并行子代理**:便宜、灵活,适合只读探索/试方案;没有 worktree、审查与合并门禁。
45
+ - **Agent Teams**:共享任务板与多人/多 agent 协作,适合设计、研究、横切决策;集成通常由人做,没有 Git 隔离的硬门禁。
46
+ - **Ralph 循环**:用新鲜 agent 对同一目标反复尝试,适合迭代搜索/修复;没有 mission 契约与合并审查。
47
+ - **Workflow 编排**:脚本化高扇出/流水线,适合批量分析、审计、验证;不做 Git 分支隔离与合并门禁。
48
+ - **Tower**:少量 mission + 隔离写入 + 独立审查 + 证据 + 合并门禁,适合"决定要做、需要安全落地"的仓库变更。
49
+
50
+ Tower 模式会拒绝 Team/Workflow/Ralph/普通 subagent 工具并清除 plan mode,避免两套编排协议同时驱动一个会话;请按阶段组合,例如先用 Workflow/Team 分析决策,再用 Tower 执行仓库变更。
21
51
 
22
52
  ## 环境要求
23
53
 
@@ -105,14 +135,16 @@ tower_teardown repoRoot=D:\work\repo
105
135
  maxDepth: 1
106
136
  ```
107
137
 
108
- - 代码中 `mode.allowAgentControl` 默认 `false`;随包 `cordis.patch.yml` 设为 `true`:模型可在用户意图/任务状态明确时自行进出,但必须给出理由;设为 `false` 时只有人类能切换。
109
- - 所有键与默认值见 [docs/reference/config.md](docs/reference/config.md);未知键会被拒绝(防止拼写错误静默失效)。
138
+ - 代码中 `mode.allowAgentControl` 默认 `false`;随包 `cordis.patch.yml` 设为 `true`:模型可在用户意图/任务状态明确时自行进出,但必须给出理由;设为 `false` 时只有人类能切换。随包 patch 还默认开启 `mode.workspaceLock`(单活塔)、`send.interruptDefault`、`init.autoGitInit`,并把 `spawn.staleMs` 设为 15s。
139
+ - `/tower base <branch>` 可设置会话级 init base 偏好;`/tower on` 会清除活跃 plan mode(`mode.planModePolicy:"refuse"` 则拒绝进入),保证 plan/tower 互斥。
140
+ - 仓库级配置:在 `<git-common-dir>/dsh-tower/config.json`(通常是 `.git/dsh-tower/config.json`)放入同样的 JSON 结构,可覆盖 `review`/`merge`/`worktrees`/`spawn`;优先级为代码默认 < profile < 仓库配置 < 工具参数。`mode.*` 属于会话级,只在 profile 生效。
141
+ - 所有键与默认值见 [docs/reference/config.md](docs/reference/config.md);未知顶层键会被拒绝(防止拼写错误静默失效),嵌套分组内的未知键会被忽略。工具错误码见 [docs/reference/errors.md](docs/reference/errors.md)。
110
142
 
111
- ## 工具(18 个)
143
+ ## 工具(26 个核心)
112
144
 
113
- `tower_init` · `tower_plan` · `tower_mission` · `tower_status` · `tower_spawn` · `tower_roster` · `tower_adopt` · `tower_diff` · `tower_send` · `tower_inbox` · `tower_complete` · `tower_finding` · `tower_review` · `tower_preflight` · `tower_merge` · `tower_rebase` · `tower_teardown` · `tower_mode`
145
+ `tower_init` · `tower_plan` · `tower_mission` · `tower_status` · `tower_spawn` · `tower_roster` · `tower_adopt` · `tower_diff` · `tower_send` · `tower_inbox` · `tower_complete` · `tower_interrupt` · `tower_finding` · `tower_findings` · `tower_review` · `tower_preflight` · `tower_merge` · `tower_rebase` · `tower_teardown` · `tower_mode` · `tower_doctor` · `tower_test` · `tower_batch` · `tower_resource` · `tower_import_legacy` · `tower_legacy_map`
114
146
 
115
- `tower_control` 仅在 `allowAgentControl: true` 时存在(随包 patch 默认开启,因此安装后共 19 个工具)。
147
+ `tower_control` 仅在 `allowAgentControl: true` 时注册;`tower_reload` 在 `dev.hotReload`(默认 true)时注册,无 HMR 服务调用会返回 `reload-unavailable`(因此最多 28 个工具)。mission 级工具同时接受 `id` 作为 `missionId` 的别名;`task_done`/`taskDone` 等 snake/camel 写法均可。
116
148
 
117
149
  ## 安全与约束
118
150
 
@@ -122,7 +154,7 @@ tower_teardown repoRoot=D:\work\repo
122
154
  - **worktree 归属。** 脏工作树、运行中的 worker、已关闭 mission 的分支都会阻止合并或 teardown。
123
155
  - **goal 隔离。** 进入 Tower 模式会暂停活跃 goal 并记录;退出不会自动恢复,需要你自行恢复。
124
156
 
125
- 13 个稳定 blocker code(另有 6 个 gate 守卫与 6 个 merge/rebase 操作失败码)——完整清单、触发条件与修复动作见 [docs/reference/blockers.md](docs/reference/blockers.md)。
157
+ 32 个稳定 blocker/failure code(含 gate 守卫、`no-check-evidence`、worker-stale、tests 门禁与 merge/rebase 操作失败码)——完整清单、触发条件与修复动作见 [docs/reference/blockers.md](docs/reference/blockers.md)。工具本身抛出的错误码见 [docs/reference/errors.md](docs/reference/errors.md),事件见 [docs/reference/events.md](docs/reference/events.md)。
126
158
 
127
159
  ## 工作原理
128
160
 
@@ -154,13 +186,15 @@ worker 与 reviewer 是使用内置 `tower-worker` preset 的普通 DSH 子代
154
186
  npm test # node --test tests/*.test.mjs
155
187
  ```
156
188
 
189
+ 热重载开发:`npm run dev:hmr` 把本仓库加入当前 profile 的 HMR watch root(需重启 DSH 一次),之后编辑 `lib/` 代码可用 `/tower reload` 或自动 watch 生效;详见 [docs/guide/hot-reload.md](docs/guide/hot-reload.md)。
190
+
157
191
  离线套件不需要 DSH 进程,只在系统临时目录创建一次性 Git 仓库。隔离 Web 运行时检查、模型驱动验收和会话诊断脚本见 `tests/README.md`。
158
192
 
159
193
  ## 文档
160
194
 
161
195
  - [docs/README.md](docs/README.md) — 文档索引(新用户 / 运维 / 维护者三条阅读路径)
162
- - [快速开始](docs/guide/quickstart.md) · [安装、升级与迁移](docs/guide/install-upgrade-migration.md)
163
- - [工具参考](docs/reference/tools.md) · [配置参考](docs/reference/config.md) · [blocker 与失败码](docs/reference/blockers.md)
196
+ - [中文文档](docs/zh/README.md) · [快速开始](docs/guide/quickstart.md) · [安装、升级与迁移](docs/guide/install-upgrade-migration.md)
197
+ - [工具参考](docs/reference/tools.md) · [配置参考](docs/reference/config.md) · [blocker 与失败码](docs/reference/blockers.md) · [错误码](docs/reference/errors.md) · [事件](docs/reference/events.md) · [测试准入](docs/reference/testing.md) · [批次/租约/旧版](docs/reference/operations.md) · [Doctor](docs/reference/doctor.md) · [热重载](docs/guide/hot-reload.md)
164
198
  - [架构与状态机](docs/architecture/overview.md) · [运维 runbook](docs/operations/runbook.md) · [安全模型](docs/operations/security.md)
165
199
  - [FAQ](docs/faq.md) · [示例](docs/examples/first-mission.md)
166
200
 
package/cordis.patch.yml CHANGED
@@ -2,7 +2,17 @@
2
2
  - id: tower
3
3
  name: 'dsh-tower'
4
4
  config:
5
- allowAgentControl: true
5
+ mode:
6
+ allowAgentControl: true
7
+ workspaceLock: true
8
+ workspaceLockScope: all
9
+ planModePolicy: clear
10
+ init:
11
+ autoGitInit: true
12
+ send:
13
+ interruptDefault: true
14
+ spawn:
15
+ staleMs: 15000
6
16
  - id: tower-skills
7
17
  name: 'dsh-tower/skills'
8
18
  - id: preset-tower-worker
package/docs/README.md CHANGED
@@ -1,13 +1,18 @@
1
1
  # dsh-tower documentation
2
2
 
3
+ English is the source of truth; a Chinese translation lives in [zh/README.md](zh/README.md).
4
+
3
5
  Choose a path:
4
6
 
5
7
  | You are | Start here |
6
8
  |---|---|
7
- | New user | [Quick start](guide/quickstart.md) → [Tools](reference/tools.md) → [Example](examples/first-mission.md) |
8
- | Operator | [Runbook](operations/runbook.md) → [Blockers](reference/blockers.md) → [Security](operations/security.md) |
9
- | Maintainer | [Architecture](architecture/overview.md) → [Config](reference/config.md) → [Contributing](../CONTRIBUTING.md) |
9
+ | New user | [When to use Tower](guide/scenarios-and-philosophy.md) → [Quick start](guide/quickstart.md) → [Tools](reference/tools.md) → [Example](examples/first-mission.md) |
10
+ | Choosing a workflow | [When to use Tower, and how it differs from Agent Teams, Ralph, Workflow and parallel subagents](guide/scenarios-and-philosophy.md) |
11
+ | Operator | [Runbook](operations/runbook.md) → [Blockers](reference/blockers.md) → [Error codes](reference/errors.md) → [Events](reference/events.md) → [Doctor](reference/doctor.md) → [Testing](reference/testing.md) → [Batches/leases/legacy](reference/operations.md) → [Security](operations/security.md) |
12
+ | Maintainer | [Architecture](architecture/overview.md) → [Config](reference/config.md) → [Hot reload](guide/hot-reload.md) → [Contributing](../CONTRIBUTING.md) |
10
13
 
11
- Reference pages are the source of truth for the current release; the [tools reference](reference/tools.md) and [blocker list](reference/blockers.md) are checked by `npm run docs:check` in CI.
14
+ Reference pages are the source of truth for the current release; the [tools reference](reference/tools.md),
15
+ [blocker list](reference/blockers.md) and [error codes](reference/errors.md) are checked against the
16
+ implementation by `npm run docs:check` in CI (including the Chinese pages).
12
17
 
13
- Other useful pages: [Install, upgrade and migration](guide/install-upgrade-migration.md), [FAQ](faq.md), [CHANGELOG](../CHANGELOG.md).
18
+ Other useful pages: [When to use Tower](guide/scenarios-and-philosophy.md), [Install, upgrade and migration](guide/install-upgrade-migration.md), [Hot reload](guide/hot-reload.md), [FAQ](faq.md), [CHANGELOG](../CHANGELOG.md).
@@ -4,16 +4,20 @@
4
4
 
5
5
  ```
6
6
  Host plugin (index.js)
7
- ├─ /tower command + Tower mode (guard, prompt section, tower_control)
8
- ├─ lib/tools.js -> 17 tools (+ tower_diff) registered on ctx.tools
9
- └─ lib/tower.js -> Tower domain: missions, gates, worktrees, roster, review, merge
10
- ├─ lib/git.js minimal git port (execFile, bounded output, timeout classification)
11
- ├─ lib/store.js repo-scoped lock + atomic JSON + activity.jsonl
12
- ├─ lib/config.js Config schema + runtime snapshot
13
- └─ lib/modeStore.js per-agent Tower mode persistence
7
+ ├─ /tower command + Tower mode (guard, prompt section, tower_mode/tower_control, /tower reload)
8
+ ├─ lib/tools.js -> 19 repository tools incl. tower_diff, tower_findings and tower_interrupt
9
+ │ (+ tower_reload while dev.hotReload is on; fails reload-unavailable without HMR)
10
+ └─ lib/tower.js -> Tower domain: missions, gates, worktrees, roster, review, findings, merge
11
+ ├─ lib/git.js minimal git port (execFile, bounded output, timeout classification)
12
+ ├─ lib/store.js repo-scoped lock + atomic JSON + activity.jsonl
13
+ ├─ lib/config.js Config schema + profile/repo layers + runtime snapshot
14
+ ├─ lib/errors.js stable tool error codes and classification
15
+ ├─ lib/workspaceLock.js optional one-Tower-session-per-repository advisory lock
16
+ ├─ lib/hmr.js optional DSH HMR bridge (tower_reload / /tower reload)
17
+ └─ lib/modeStore.js per-agent Tower mode persistence
14
18
  Subagents
15
- ├─ tower-worker (dsh-tower/worker) read/write/edit/pwsh + mission tools
16
- └─ tower-reviewer (dsh-tower/reviewer) read/glob/grep + tower_diff + review/finding
19
+ ├─ tower-worker (dsh-tower/worker) read/write/edit/pwsh + mission tools + findings
20
+ └─ tower-reviewer (dsh-tower/reviewer) read/glob/grep + tower_diff + review/finding (read-only)
17
21
  ```
18
22
 
19
23
  The main checkout is the control-tower repo; each mission has a branch `tower/<id>-<slug>` and a
package/docs/faq.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # FAQ
2
2
 
3
+ **When should I use Tower instead of Agent Teams, Ralph, Workflow, or ordinary subagents?**
4
+ Use Tower when the output is a reviewed, integrated change to one Git repository. Use ordinary
5
+ subagents for read-only exploration or quick independent subtasks, Agent Teams for cross-cutting human
6
+ collaboration, Ralph for repeated fresh attempts at one objective, and Workflow for programmatic
7
+ high-fan-out analysis. The full decision guide, scenarios, and comparison table are in
8
+ [When to use Tower](guide/scenarios-and-philosophy.md).
9
+
10
+ **Can I combine Tower with Team/Workflow/Ralph?**
11
+ Not concurrently in the same session: Tower mode refuses their tools and clears plan mode. Compose by
12
+ phase instead—use Workflow/Team to analyze and decide, then start Tower to execute and review the
13
+ repository change. See the [full guide](guide/scenarios-and-philosophy.md#4-how-tower-differs-from-other-dsh-workflow-patterns).
14
+
3
15
  **Why did `tower_preflight` fail with `no-review` right after the worker finished?**
4
16
  That is expected: a completed mission awaits review. Spawn a reviewer; after a clean review the gate
5
17
  turns green.
@@ -28,12 +40,43 @@ instead of rebasing.
28
40
  No. Reviewers use the read-only `tower-reviewer` preset (no write/edit/pwsh); a branch changed after the
29
41
  reviewer spawned is rejected. Reviewers file `tower_finding` for issues outside the mission.
30
42
 
43
+ **What is the difference between `tower_finding` and `tower_findings`?**
44
+ `tower_finding` creates one finding (`open`). `tower_findings` is the lifecycle tool: list/read, and
45
+ transition `open → triaged → fixed`/`wontfix` (reopen allowed). Only the tower or a worker may change the
46
+ status; a roster reviewer may list and read.
47
+
48
+ **How do I set config for one repository only?**
49
+ Create `<git-common-dir>/dsh-tower/config.json` (usually `.git/dsh-tower/config.json`) with the same
50
+ JSON groups as the profile config (`review`, `merge`, `worktrees`, `spawn`, and legacy aliases). The
51
+ repository layer wins over the profile; per-call tool arguments win over both. No restart is required
52
+ because the file is read when a Tower tool opens the repository.
53
+
31
54
  **Can workers use Tower tools to merge or spawn?**
32
55
  No. The worker preset contains mission/progress tools only; merge and spawn live in the parent tower.
33
56
 
57
+ **A worker is stuck or runaway. How do I stop it?**
58
+ Use `tower_interrupt({to:"worker-m1",reason:"..."})`; it calls the host subagent interrupt and records the
59
+ roster entry as `interrupted`. If you already interrupted it and want a new owner, spawn with
60
+ `takeover:true`. A still-running worker cannot be taken over (`takeover-refused`).
61
+
62
+ **Two sessions want to drive the same repository.**
63
+ Enable `mode.workspaceLock:true`: the first Tower session to call a repo-scoped tool owns
64
+ `<git-common-dir>/dsh-tower/tower.lock`; other sessions get `[tower:workspace-busy]` until the owner
65
+ runs `/tower off` or the lock is stale (`mode.workspaceStaleMs`).
66
+
67
+ **Can I reload the plugin without restarting DSH?**
68
+ Yes, in a profile with the DSH HMR service: `/tower reload` or the `tower_reload` tool reconciles the
69
+ profile and replaces the changed linked package. Run `npm run dev:hmr` once to add the repository to the
70
+ profile's HMR watch roots (then restart DSH once); see [hot reload](guide/hot-reload.md).
71
+ `plugin_manager` install/update already applies live.
72
+
73
+ **How do I make the completion evidence mandatory?**
74
+ Workers can pass `checks` to `tower_complete`; set `gates.requireChecks:true` to block merging when a
75
+ completed mission has no checks (`no-check-evidence`).
76
+
34
77
  **Where does Tower store state?**
35
- `<git-common-dir>/dsh-tower/state.json` and `activity.jsonl` in the target repo; mode state in
36
- `$DSH_HOME/tower-mode/modes.json`. Worktrees live next to the checkout in `.dsh-tower-worktrees/`.
78
+ `<git-common-dir>/dsh-tower/state.json`, `activity.jsonl` and the human-readable `MISSIONS.md`; mode state
79
+ in `$DSH_HOME/tower-mode/modes.json`. Worktrees live next to the checkout in `.dsh-tower-worktrees/`.
37
80
 
38
81
  **How do I change the review round cap or presets?**
39
82
  Use `review.maxRoundsPerReviewer` and `spawn.workerPreset`/`spawn.reviewerPreset`; see