dsh-tower 2.5.0 → 2.6.0
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.
- package/CHANGELOG.md +32 -0
- package/COMPATIBILITY.md +1 -0
- package/CONTRIBUTING.md +1 -1
- package/GLOSSARY.md +6 -0
- package/PRINCIPLES.md +15 -7
- package/README.en.md +16 -15
- package/README.md +12 -10
- package/app/review.js +7 -0
- package/app/spawn-prechecks.js +12 -2
- package/app/tower.js +5 -5
- package/client.js +321 -0
- package/cordis.patch.yml +5 -3
- package/docs/adr/0005-component-surface.md +58 -13
- package/docs/architecture/overview.md +12 -6
- package/docs/examples/first-mission.md +3 -2
- package/docs/faq.md +9 -7
- package/docs/guide/install-upgrade-migration.md +32 -7
- package/docs/guide/quickstart.md +20 -10
- package/docs/guide/scenarios-and-philosophy.md +35 -28
- package/docs/operations/security.md +11 -10
- package/docs/reference/blockers.md +12 -7
- package/docs/reference/component-surface.md +14 -7
- package/docs/reference/config.generated.md +3 -2
- package/docs/reference/config.md +29 -3
- package/docs/reference/errors.generated.md +1 -0
- package/docs/reference/errors.md +2 -1
- package/docs/reference/surface-budget.md +20 -3
- package/docs/reference/testing.md +1 -1
- package/docs/reference/tools.generated.md +5 -5
- package/docs/reference/tools.md +3 -3
- package/docs/zh/faq.md +7 -5
- package/docs/zh/guide/install-upgrade-migration.md +25 -6
- package/docs/zh/guide/quickstart.md +17 -10
- package/docs/zh/guide/scenarios-and-philosophy.md +23 -15
- package/docs/zh/operations/security.md +9 -8
- package/docs/zh/reference/blockers.md +11 -7
- package/docs/zh/reference/config.md +21 -3
- package/docs/zh/reference/errors.md +2 -1
- package/docs/zh/reference/testing.md +2 -2
- package/docs/zh/reference/tools.md +3 -3
- package/domain/components.js +12 -4
- package/domain/config/schema.js +40 -5
- package/domain/contracts/outputs.js +2 -0
- package/domain/contracts/tool-inputs/missions.js +1 -1
- package/domain/errors.js +6 -0
- package/domain/gate.js +6 -3
- package/domain/integration/review.js +203 -9
- package/host/config.js +40 -3
- package/host/doctor.js +18 -7
- package/host/presets.js +9 -8
- package/host/tool-registry.js +9 -1
- package/package.json +7 -1
- package/scripts/check-components.mjs +120 -6
- package/scripts/check-pack.mjs +3 -0
- package/scripts/component-surface.json +16 -10
- package/scripts/pack-manifest.txt +1 -0
- package/scripts/surface-baseline.json +8 -1
- package/scripts/types-coverage.mjs +7 -0
- package/tools/preflight.js +1 -1
- package/tools/review.js +1 -1
- package/tools/spawn.js +2 -2
- package/tools/status.js +8 -1
- package/types/index.d.ts +10 -0
|
@@ -10,8 +10,8 @@ a better fit.
|
|
|
10
10
|
|
|
11
11
|
If you only remember one sentence: **use Tower when the output is an integrated repository change that
|
|
12
12
|
must land through a controlled merge; use the other patterns when the output is exploration, repeated
|
|
13
|
-
attempts, or programmatic fan-out.**
|
|
14
|
-
independent reviewer
|
|
13
|
+
attempts, or programmatic fan-out.** Set the review policy to `required` when the change also needs
|
|
14
|
+
an independent reviewer; the default policy is `optional`.
|
|
15
15
|
|
|
16
16
|
## 1. The design philosophy
|
|
17
17
|
|
|
@@ -45,11 +45,13 @@ When review is enabled, a reviewer also inspects a specific branch tip and the g
|
|
|
45
45
|
binding. Separation of duties is the point when review is on: the agent that wrote the code is not the
|
|
46
46
|
agent that approves it, and neither is the agent that merges.
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
mission must carry a clean, merge-approved review from a
|
|
50
|
-
to
|
|
51
|
-
remains available as a per-mission exemption when the
|
|
52
|
-
|
|
48
|
+
The review policy is one tri-state control: `off`, `optional` (the default) or `required`. `required`
|
|
49
|
+
enforces independent review (a complete mission must carry a clean, merge-approved review from a
|
|
50
|
+
reviewer bound to the branch tip). Choose it for sensitive repositories; `reviewPolicy:"none"` + a
|
|
51
|
+
reason + `gates.allowReviewExemption:true` remains available as a per-mission exemption when the
|
|
52
|
+
policy is required. `optional` records reviews but never blocks a merge, and `off` is a supported
|
|
53
|
+
mode that removes the review tool. The policy is configuration, not a component row: there is one
|
|
54
|
+
control on the plugin page, not three mutually exclusive rows.
|
|
53
55
|
|
|
54
56
|
### 1.5 Evidence over assertion
|
|
55
57
|
|
|
@@ -184,7 +186,7 @@ integration, and what "done" means.**
|
|
|
184
186
|
| Isolation | Git worktree + branch per mission; one writer per mission | Shared workspace; coordination by task ownership | Fresh child per round; no built-in branch/merge contract | Per-step child; no Git isolation | Child sessions; may share workspace |
|
|
185
187
|
| Durable state | Git metadata + JSON state + activity + board | Team task board + sessions | Minimal; each round starts fresh | Run record/results; not a merge ledger | Session/subagent records |
|
|
186
188
|
| Integration authority | Tower only, after preflight/gate (plus review when enabled) | Humans/teammates merge or edit manually | Usually the parent/worker applies results | Script applies results | Parent applies results |
|
|
187
|
-
| Review / gate | Optional independent review (
|
|
189
|
+
| Review / gate | Optional independent review (one `review.mode` control: off/optional/required) + preflight/merge gate | Review is a collaboration convention, not a hard gate | No built-in review gate | No built-in review gate | No built-in review gate |
|
|
188
190
|
| Parallelism | Multiple missions, disjoint scopes, serialized merges | Many teammates, shared board | Sequential rounds (or external fan-out) | High fan-out, script-controlled | High fan-out |
|
|
189
191
|
| Human role | Owns the mode; can inspect evidence and release | Collaborator/coordinator | Author of the repeated objective | Author of the orchestration script | Delegator |
|
|
190
192
|
| Best for | Feature delivery, migrations, release-bound changes | Design, research, cross-cutting collaboration | Iterative search/repair with fresh context | Large audits, batch analysis, deterministic pipelines | Quick exploration or independent subtasks |
|
|
@@ -195,8 +197,8 @@ integration, and what "done" means.**
|
|
|
195
197
|
Ordinary `subagent`/`subagent_fork` calls are cheap and flexible. They are the right tool for "read
|
|
196
198
|
these five files in parallel" or "try three approaches". They do not provide a write scope, a
|
|
197
199
|
dedicated worktree, a durable mission, independent review, or a merge gate. Tower wraps the same
|
|
198
|
-
subagent primitive in those contracts; it also costs more per child. (Review is optional:
|
|
199
|
-
`
|
|
200
|
+
subagent primitive in those contracts; it also costs more per child. (Review is optional: set the
|
|
201
|
+
policy to `required` when you need the reviewer role to gate a merge.)
|
|
200
202
|
|
|
201
203
|
Choose subagents when the work is read-mostly, short-lived, or you will integrate the result
|
|
202
204
|
yourself. Choose Tower when the result must land on a branch under a controlled merge; enable review
|
|
@@ -245,14 +247,19 @@ Tower entry clears an active plan (or refuses entry under `mode.planModePolicy:"
|
|
|
245
247
|
Tower session cannot use the goal/todo/team/workflow tools. Plan first, then execute; do not expect
|
|
246
248
|
Tower to discover the plan for you.
|
|
247
249
|
|
|
248
|
-
### 4.6
|
|
250
|
+
### 4.6 The review policy is one tri-state control
|
|
249
251
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
+
The review policy is one control — `off`, `optional` (the default) or `required` — in the plugin-page
|
|
253
|
+
`dsh-tower` configuration section, mirrored by `review.mode` in config. It is not a component row and
|
|
254
|
+
not three mutually exclusive rows. `optional` means a completed mission can merge without a reviewer
|
|
255
|
+
for low-risk repositories, scratch work, or human-supervised sessions. `required` enforces the
|
|
252
256
|
independent review gate; the gate then re-checks `no-review`, `not-clean`, `review-hold`,
|
|
253
|
-
`review-not-approved`, `tip-moved`, and `review-mission-mismatch`. `
|
|
254
|
-
|
|
255
|
-
`reviewPolicy:"none"` + a reason and
|
|
257
|
+
`review-not-approved`, `tip-moved`, and `review-mission-mismatch`. `off` is a supported mode that
|
|
258
|
+
does not register `tower_review`; `optional` records verdicts but never blocks a merge. For one
|
|
259
|
+
mission only, with the policy `required`, set `reviewPolicy:"none"` + a reason and
|
|
260
|
+
`gates.allowReviewExemption:true`. The deprecated one-release boolean alias maps `true` → `required`
|
|
261
|
+
and `false` → `optional`; see
|
|
262
|
+
[install, upgrade and migration](install-upgrade-migration.md).
|
|
256
263
|
|
|
257
264
|
### 4.7 Concrete examples by workflow
|
|
258
265
|
|
|
@@ -309,8 +316,8 @@ A team wants "organization invitations": token model, email delivery, accept/dec
|
|
|
309
316
|
`src/ui/invites/**`; make the API depend on tokens and email.
|
|
310
317
|
2. Spawn workers for the independent missions; the API waits for its deps.
|
|
311
318
|
3. Each worker commits on its branch, completes with checks.
|
|
312
|
-
4. With `review.
|
|
313
|
-
|
|
319
|
+
4. With `review.mode:required`, spawn reviewers and require a clean+merge verdict; otherwise review
|
|
320
|
+
is optional or off.
|
|
314
321
|
5. `tower_preflight` and `tower_merge` each mission; resolve scope/base/review blockers.
|
|
315
322
|
6. `tower_teardown`; `MISSIONS.md` is the human-readable record.
|
|
316
323
|
|
|
@@ -344,9 +351,9 @@ Tower missions from those findings.
|
|
|
344
351
|
### Scenario E: sensitive release
|
|
345
352
|
|
|
346
353
|
A library release with external consumers. Plan missions for the change, migration guide, and
|
|
347
|
-
release notes;
|
|
348
|
-
|
|
349
|
-
|
|
354
|
+
release notes; set `review.mode:required` if the release requires independent review, require tests,
|
|
355
|
+
and use `tower_batch` to close the release evidence only when all required checks are present; merge
|
|
356
|
+
and tag outside Tower as your release process requires.
|
|
350
357
|
|
|
351
358
|
## 6. Choosing in practice: a short decision path
|
|
352
359
|
|
|
@@ -354,9 +361,9 @@ merge and tag outside Tower as your release process requires.
|
|
|
354
361
|
2. **Would you open a PR for it?** No → Tower is too heavy; use a normal agent.
|
|
355
362
|
3. **Do the slices have stable scopes and a known definition of done?** No → plan/explore first; then
|
|
356
363
|
return to Tower.
|
|
357
|
-
4. **Do you need a merge gate?** Repository changes with integration risk → Tower.
|
|
358
|
-
`
|
|
359
|
-
|
|
364
|
+
4. **Do you need a merge gate?** Repository changes with integration risk → Tower. Set the review
|
|
365
|
+
policy to `required` if you also need independent review. If neither isolation nor evidence is
|
|
366
|
+
needed, plain subagents may be enough.
|
|
360
367
|
5. **Do you need many parallel analyses or repeated fresh attempts?** Use Workflow/Ralph for that
|
|
361
368
|
phase; encode the resulting changes as Tower missions.
|
|
362
369
|
6. **Do you need cross-cutting human collaboration?** Use Agent Teams to decide; execute the decided
|
|
@@ -368,9 +375,9 @@ merge and tag outside Tower as your release process requires.
|
|
|
368
375
|
round, gate, merge. Keep missions meaningful (roughly a PR-sized slice), not one task per function.
|
|
369
376
|
- **Merges serialize**: overlapping scopes auto-add dependencies; independent missions still merge
|
|
370
377
|
one at a time onto the base. Do not expect linear speedup for merge-heavy work.
|
|
371
|
-
- **Review is not free when
|
|
372
|
-
`review.
|
|
373
|
-
are opt-in and require a reason.
|
|
378
|
+
- **Review is not free when required**: each mission then needs a reviewer and a clean verdict.
|
|
379
|
+
`review.mode:optional` (the default) makes review non-blocking, and `off` removes the review tool;
|
|
380
|
+
when the policy is `required`, exemptions are opt-in and require a reason.
|
|
374
381
|
- **Too-fine missions** increase coordination and merge cost. **Too-coarse missions** lose the benefit
|
|
375
382
|
of parallel review and make scope conflicts likely.
|
|
376
383
|
- **Tower is not a sandbox**: it is a coordination protocol. Host permissions, repository hooks, and
|
|
@@ -385,7 +392,7 @@ merge and tag outside Tower as your release process requires.
|
|
|
385
392
|
- [ ] The work produces a repository change that deserves a PR-style review.
|
|
386
393
|
- [ ] I can name 2–8 missions with non-overlapping scopes and a rough dependency order.
|
|
387
394
|
- [ ] Each mission has a testable definition of done (tasks, checks/tests, optional review).
|
|
388
|
-
- [ ] If this change needs independent review,
|
|
395
|
+
- [ ] If this change needs independent review, the review policy is `required` (default is `optional`).
|
|
389
396
|
- [ ] I know which missions can run in parallel and which must wait.
|
|
390
397
|
- [ ] I accept the merge-gate overhead (and review overhead if enabled) and will inspect
|
|
391
398
|
`MISSIONS.md`/the branch.
|
|
@@ -4,15 +4,16 @@ Tower's guarantees are **coordination guarantees**, not a sandbox. Understand wh
|
|
|
4
4
|
|
|
5
5
|
## Enforced by the plugin
|
|
6
6
|
|
|
7
|
-
- **Review binding (when
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
- **Review binding (when required).** `tower_review` records the branch tip it inspected; with
|
|
8
|
+
`review.mode:required`, the gate rejects a moved tip (`tip-moved`) unless a clean conflict-free
|
|
9
|
+
rebase waived it. A reviewer that modifies the branch after spawning is rejected
|
|
10
10
|
(`reviewer must not modify the mission branch`).
|
|
11
|
-
- **Review is optional by default, enforceable by
|
|
12
|
-
default
|
|
13
|
-
`reviewPolicy:"none"` + reason is the narrower exemption when the
|
|
14
|
-
off
|
|
15
|
-
repositories.
|
|
11
|
+
- **Review is optional by default, enforceable by the tri-state policy.** `review.mode` is `off`,
|
|
12
|
+
`optional` (the default) or `required`. Set it to `required` to enforce the independent-review gate.
|
|
13
|
+
Mission-level `reviewPolicy:"none"` + reason is the narrower exemption when the policy is required.
|
|
14
|
+
With `off`, review is intentionally unavailable; with `optional`, separation of duties is not
|
|
15
|
+
enforced by the plugin, so use it only for trusted or human-supervised repositories. The policy is
|
|
16
|
+
one control on the plugin page, not a component row.
|
|
16
17
|
- **Role enforcement.** The caller is resolved against the roster. Worker mission updates are limited to
|
|
17
18
|
task/blocker/note; `completed`, `abandoned`, scope widening and blocker clearing are tower-only, and
|
|
18
19
|
completion (with its unread-inbox/commit gates) must go through `tower_complete`. Tower-only tools reject
|
|
@@ -84,8 +85,8 @@ intent behind that entry. What it does provide:
|
|
|
84
85
|
It does **not** defend against: a model that legitimately passes every gate while acting on malicious
|
|
85
86
|
instructions; repository hooks or test commands the repository itself declares; or filesystem/shell
|
|
86
87
|
access outside the worktree by a worker that ignores its instructions. For a higher-assurance team,
|
|
87
|
-
set `mode.allowAgentControl:false`, keep `review.
|
|
88
|
-
Tower work, and run the host under OS-level isolation.
|
|
88
|
+
set `mode.allowAgentControl:false`, keep the review policy at `review.mode:required`, review the
|
|
89
|
+
repository before Tower work, and run the host under OS-level isolation.
|
|
89
90
|
|
|
90
91
|
## Not enforced by the plugin (deployment concerns)
|
|
91
92
|
|
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
return the same shape for operation failures. Codes are stable; the detail is human-facing. The
|
|
5
5
|
tables below define 32 stable blocker/failure codes.
|
|
6
6
|
|
|
7
|
+
The review blockers below (`no-review`, `review-mission-mismatch`, `not-clean`, `review-hold`,
|
|
8
|
+
`review-not-approved`, `tip-moved`, `review-exemption-invalid`) exist only when `review.mode` is
|
|
9
|
+
`required`. With `off` or `optional` no review blocker is produced; `off` additionally removes
|
|
10
|
+
`tower_review` and refuses reviewer spawn.
|
|
11
|
+
|
|
7
12
|
## Gate blockers (26)
|
|
8
13
|
|
|
9
14
|
| Code | Meaning / next action |
|
|
@@ -19,12 +24,12 @@ tables below define 32 stable blocker/failure codes.
|
|
|
19
24
|
| `out-of-scope` | Changed files outside the mission scope; widen scope deliberately or revert. On a case-sensitive checkout a case-only mismatch is still rejected and the detail names the scope entry it would match if case were folded. |
|
|
20
25
|
| `base-dirty` | The main checkout has uncommitted changes the merge would overwrite. |
|
|
21
26
|
| `deps-unmerged` | A dependency mission is not satisfied: a build dependency must be `merged`/`abandoned`, while a survey dependency is satisfied at `completed` (archived entries included). |
|
|
22
|
-
| `no-review` | `review.
|
|
23
|
-
| `review-mission-mismatch` | `review.
|
|
24
|
-
| `not-clean` | `review.
|
|
25
|
-
| `review-hold` | `review.
|
|
26
|
-
| `review-not-approved` | `review.
|
|
27
|
-
| `tip-moved` | `review.
|
|
27
|
+
| `no-review` | `review.mode:required` and no review exists on the branch: spawn a reviewer (or disable the review gate). |
|
|
28
|
+
| `review-mission-mismatch` | `review.mode:required` and the latest review belongs to another mission. |
|
|
29
|
+
| `not-clean` | `review.mode:required` and latest review is `p1-Nitems`/`p2-Nitems`; another round is required. Verdicts from later routes of the same round are appended to it instead of flipping the mission again. |
|
|
30
|
+
| `review-hold` | `review.mode:required` and latest review recommends hold; a later clean review must supersede it. |
|
|
31
|
+
| `review-not-approved` | `review.mode:required` and latest clean review says `fix-then-merge` or `hold`; only `merge` approves. |
|
|
32
|
+
| `tip-moved` | `review.mode:required` and the branch changed after review; review again (or use a clean rebase waiver). |
|
|
28
33
|
| `worker-busy` | A roster agent for this mission is running; wait or retire it. |
|
|
29
34
|
| `worker-status-unknown` | The parent catalog is unavailable, so a live roster agent cannot be proven stopped; retry after the catalog recovers or adopt it. |
|
|
30
35
|
| `base-wrong-branch` | The main checkout is not on the recorded base branch. |
|
|
@@ -32,7 +37,7 @@ tables below define 32 stable blocker/failure codes.
|
|
|
32
37
|
| `worker-stale` | A roster worker for this mission has no catalog activity beyond `spawn.staleMs`; adopt it (or interrupt it only if it is actually running) before merge. |
|
|
33
38
|
| `tests-missing` | `gates.requireTests` is enabled and there is no passing discovery receipt for the current branch tip; run `tower_test` or `tower_complete`. |
|
|
34
39
|
| `tests-failed` | The latest discovery receipt failed or did not meet minCount/required checks. Fix the tests and re-run. |
|
|
35
|
-
| `review-exemption-invalid` | `review.
|
|
40
|
+
| `review-exemption-invalid` | `review.mode:required` and the mission requests `reviewPolicy:"none"` while `gates.allowReviewExemption` is off (or the reason is missing). |
|
|
36
41
|
| `merge-intent-pending` | A merge intent was recorded before a crash/failure; run `tower_merge` to reconcile before another gate. |
|
|
37
42
|
|
|
38
43
|
## Merge failures (4)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Generated by `npm run docs:generate:components` from `scripts/component-surface.json` and
|
|
4
4
|
> `scripts/surface-baseline.json`. Do not edit by hand.
|
|
5
5
|
|
|
6
|
-
Decision: [ADR 0005](../adr/0005-component-surface.md) · decision date: 2026-
|
|
6
|
+
Decision: [ADR 0005](../adr/0005-component-surface.md) · decision date: 2026-11-01 · baseline 2026-10-23 · visible components: 11 (`tower`, `tower-skills`, `tower-batch`, `tower-import`, `tower-leases`, `tower-tests`, `tower-board`, `tower-archive`, `tower-hmr`, `preset-tower-reviewer`, `tower-ui`)
|
|
7
7
|
|
|
8
8
|
The component axis answers one question for every config key: may a user turn it
|
|
9
9
|
off, and if so, must that switch be a component? Four classes cover every key, so
|
|
@@ -14,7 +14,7 @@ off, and if so, must that switch be a component? Four classes cover every key, s
|
|
|
14
14
|
| `core` | Removing it breaks the Tower contract. It is never a switch. |
|
|
15
15
|
| `optional-component` | A capability whose off state leaves the rest of Tower intact. It must be a user-visible switch with a documented fallback. |
|
|
16
16
|
| `optional-config` | A tuning knob, not a capability. It stays in the config form and never hides a component. |
|
|
17
|
-
| `forbidden-to-disable` | The host, the health contract, the recovery escape
|
|
17
|
+
| `forbidden-to-disable` | The host, the health contract, the recovery escape and the merge gates. No group, row or boolean key may turn it off. |
|
|
18
18
|
|
|
19
19
|
## Components
|
|
20
20
|
|
|
@@ -35,13 +35,18 @@ row is a section of its parent and is not independently switchable.
|
|
|
35
35
|
| `tower-archive` | visible | row | Terminal missions are not moved out of state.json, so the hot state keeps growing and status/doctor keep loading their full history. Merges, gates and every other capability keep working; nothing is deleted. afterDays/maxMissions keep their tuning meaning. |
|
|
36
36
|
| `tower-hmr` | visible | row | Development-only tooling: tower_reload and /tower reload are unavailable, so a linked-profile reload has to be triggered outside Tower. A normal profile behaves exactly as before; the row ships disabled on purpose. |
|
|
37
37
|
| `preset-tower-worker` | internal | row | Declared by dsh-tower/preset-worker: tower_spawn fails without the worker preset. A mandatory dependency, never a switch. |
|
|
38
|
-
| `preset-tower-reviewer` | visible | row | Declared by dsh-tower/preset-reviewer: the reviewer cannot be dispatched. Supported while review.
|
|
38
|
+
| `preset-tower-reviewer` | visible | row | Declared by dsh-tower/preset-reviewer: the reviewer cannot be dispatched. Supported while review.mode is off or optional (merge is unaffected; off does not use the preset at all); with review.mode required, planning/mode entry is locked with an explanatory error. |
|
|
39
39
|
| `tower-ui` | visible | row | The Tower web UI plugin does not load in this profile: no Tower tool cards, composer-dock summary or status strip. Host tools, missions, state and the MISSIONS.md board are unaffected. |
|
|
40
40
|
|
|
41
41
|
## Forbidden to disable
|
|
42
42
|
|
|
43
|
-
The host, the health contract, the recovery escape
|
|
44
|
-
|
|
43
|
+
The host, the health contract, the recovery escape and the merge gates are
|
|
44
|
+
configuration or code, never switches. The review gate in `required` mode is
|
|
45
|
+
also non-disableable: a completed mission still needs the review evidence bound
|
|
46
|
+
to the branch tip, and the exemption path stays explicit. The policy itself is
|
|
47
|
+
not a never-switch — `review.mode` is the one tri-state control on the
|
|
48
|
+
plugin-page config form (`off`, `optional` or `required`) — and only the gate it
|
|
49
|
+
turns on in `required` mode is non-disableable. `npm run
|
|
45
50
|
docs:check:components` derives the live disablers from `host/tool-registry.js`
|
|
46
51
|
and `cordis.patch.yml`; a disabler that is not recorded here fails the gate.
|
|
47
52
|
|
|
@@ -50,7 +55,7 @@ and `cordis.patch.yml`; a disabler that is not recorded here fails the gate.
|
|
|
50
55
|
| the Tower host | Without the host the plugin registers nothing; there is no off state that leaves the rest working, and no config boolean may remove it. The visible `tower` anchor is the all-off boundary, and the host section nested under it may never become its own switch. | none | none may exist |
|
|
51
56
|
| tower_doctor (read-only health contract) | Diagnosis must always exist so a failure message can point at it. #122 removed exposeDoctor and the exposeOperational master switch; the tool is registered for every configuration. | none | none may exist |
|
|
52
57
|
| tower_recover (stale state-lock escape) | The escape hatch must exist whenever the lock it repairs can be left behind. #122 removed exposeRecovery and the exposeOperational master switch; the tool is registered for every configuration. | none | none may exist |
|
|
53
|
-
| the review
|
|
58
|
+
| the review gate in required mode | The policy is one tri-state configuration control on the plugin-page form, not a component row: review.mode is off, optional (default) or required, and off is a documented mode that removes tower_review and makes the merge gate ignore review. What no group, row or boolean key may switch off is the gate once the mode is required: a completed mission still needs a clean review bound to the branch tip, and the exemption path stays explicit. review.requireReview is a deprecated one-release alias, not a switch. The reviewer preset row remains a capability the policy may leave unused, never a way to weaken required mode. | none | none may exist |
|
|
54
59
|
| the merge gates | gates.* decides delivery; a component may not bypass it. | none | none may exist |
|
|
55
60
|
|
|
56
61
|
## Gateable tools
|
|
@@ -92,7 +97,8 @@ All keys from `domain/config/schema.js`, classified on the component axis.
|
|
|
92
97
|
| `mode.storePath` | `optional-config` | Custom mode-store location; no capability is removed. |
|
|
93
98
|
| `mode.maxEntries` | `optional-config` | Bounds the persisted mode store. |
|
|
94
99
|
| `mode.lockTimeoutMs` | `optional-config` | Bounded wait for the cross-process mode lock. |
|
|
95
|
-
| `review.
|
|
100
|
+
| `review.mode` | `core` | The review policy: off, optional (default) or required, selected by one tri-state control on the plugin-page configuration form. It is configuration, not a component row and not three mutually exclusive rows. off intentionally removes tower_review, refuses reviewer spawn and makes the merge gate ignore review; optional never blocks a merge; required makes a clean tip-bound review a merge blocker. The reviewer preset row stays a capability the mode may leave unused. |
|
|
101
|
+
| `review.requireReview` | `core` | Deprecated one-release boolean alias for review.mode (true -> required, false -> optional; default optional). It is policy configuration and a deprecated alias, not a switch a row may own; false never overrides an explicit mode. Kept so 2.5 configurations keep working; remove after the 2.6 alias window. |
|
|
96
102
|
| `review.maxRoundsPerReviewer` | `forbidden-to-disable` | Caps review rounds; part of the review contract. |
|
|
97
103
|
| `merge.timeoutMs` | `optional-config` | Default merge timeout; a per-call value wins. |
|
|
98
104
|
| `merge.maxBufferBytes` | `optional-config` | Captured merge output buffer. |
|
|
@@ -135,6 +141,7 @@ hides a capability cannot use the tuning class without that record.
|
|
|
135
141
|
|
|
136
142
|
| Key |
|
|
137
143
|
|---|
|
|
144
|
+
| `review.mode` |
|
|
138
145
|
| `spawn.requireLease` |
|
|
139
146
|
| `tests.admission` |
|
|
140
147
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Config reference (generated)
|
|
2
2
|
|
|
3
3
|
> Generated by `npm run docs:generate:config` from `domain/config/schema.js`. Values are defaults before repo config.
|
|
4
|
-
> Surface: config keys:
|
|
4
|
+
> Surface: config keys: 54 · sections: 14 · tools: 29 · baseline 2026-10-23. Generated from `scripts/surface-baseline.json`; do not edit by hand.
|
|
5
5
|
|
|
6
6
|
| Key | Default | Description |
|
|
7
7
|
|---|---|---|
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
| `mode.storePath` | `` | Directory for modes.json; defaults to $DSH_HOME/tower-mode. |
|
|
26
26
|
| `mode.maxEntries` | `200` | Maximum persisted mode entries. |
|
|
27
27
|
| `mode.lockTimeoutMs` | `5000` | How long saveModes waits for the cross-process modes.lock before giving up. |
|
|
28
|
-
| `review.
|
|
28
|
+
| `review.mode` | `"optional"` | Review policy. off = review is intentionally unavailable (recording a review is refused, reviewer spawn is refused, and the merge gate ignores review; a profile-level off also does not register tower_review); optional = review is available but never blocks a merge (default); required = a clean review bound to the branch tip is a merge blocker. |
|
|
29
|
+
| `review.requireReview` | `false` | Deprecated alias for review.mode (true -> required, false -> optional); prefer review.mode. true next to a non-required mode is rejected; false never overrides an explicit mode (off, optional or required). The Plugins-page control shows the alias when it is the only key and always writes review.mode with review.requireReview:false. |
|
|
29
30
|
| `review.maxRoundsPerReviewer` | `5` | Review-round cap per reviewer per mission branch. |
|
|
30
31
|
| `merge.timeoutMs` | `900000` | Default tower_merge timeout, including pre-merge hooks. |
|
|
31
32
|
| `merge.maxBufferBytes` | `67108864` | Captured merge output buffer. |
|
package/docs/reference/config.md
CHANGED
|
@@ -27,13 +27,38 @@ win, profile keys survive when the repo does not set them. `tower_status` report
|
|
|
27
27
|
|
|
28
28
|
```json
|
|
29
29
|
{
|
|
30
|
-
"review": { "
|
|
30
|
+
"review": { "mode": "required", "maxRoundsPerReviewer": 3 },
|
|
31
31
|
"merge": { "timeoutMs": 1800000 },
|
|
32
32
|
"worktrees": { "root": "D:/tower-worktrees" },
|
|
33
33
|
"spawn": { "reviewerPreset": "tower-reviewer", "maxDepth": 2 }
|
|
34
34
|
}
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
`review.mode` is the review policy: `off`, `optional` or `required`. `review.requireReview` is a
|
|
38
|
+
deprecated alias kept for one release (`true` → `required`, `false` → `optional`); prefer
|
|
39
|
+
`review.mode`. When both are set in the same layer, `requireReview:true` next to any mode other than
|
|
40
|
+
`required` is a contradiction and is rejected with `config-invalid` naming both keys.
|
|
41
|
+
`requireReview:false` never contradicts an explicit mode: `off`, `optional` and `required` all stay
|
|
42
|
+
accepted and the mode wins (`required` still enforces the gate; the resolved alias is mirrored back as
|
|
43
|
+
`true` only for that mode). A repository layer is resolved on its own: it may relax review, but a
|
|
44
|
+
profile with `review.mode:off` never registered `tower_review`, so a repository cannot raise its own
|
|
45
|
+
mode.
|
|
46
|
+
|
|
47
|
+
The Plugins-page control shows the policy exactly as the runtime resolves it: `review.mode` decides
|
|
48
|
+
when present, and a profile that still sets only `review.requireReview` displays Required (`true`) or
|
|
49
|
+
Optional (`false`). Saving a choice always writes `review.mode` and sets `review.requireReview` to
|
|
50
|
+
`false` in the same profile patch, so the alias can never contradict the selected mode.
|
|
51
|
+
|
|
52
|
+
The same three choices are available on the Plugins page, in the `dsh-tower` configuration
|
|
53
|
+
section: **Off**, **Optional** (the default) and **Required**, each with a one-line description of
|
|
54
|
+
its effect. That control writes the profile config through the Host settings form, so the accepted
|
|
55
|
+
value is reflected on the page without a manual file edit.
|
|
56
|
+
|
|
57
|
+
One live change cannot rebuild the mounted tool surface: a profile that started with review off did
|
|
58
|
+
not register `tower_review`. Switching to Optional or Required through the page immediately changes
|
|
59
|
+
the merge gate, but the review tool itself appears only after a restart (or a profile reload); the
|
|
60
|
+
control states that after such a save.
|
|
61
|
+
|
|
37
62
|
The `mode.*` group is session-scoped, not repository-scoped: it is accepted in the repository file
|
|
38
63
|
for schema compatibility but only the profile config controls the Tower-mode prompt and the
|
|
39
64
|
model-controlled toggle. A malformed file, a non-object value, unknown top-level keys, or a value that
|
|
@@ -61,7 +86,8 @@ violates the declared schema (for example `merge.timeoutMs` below 1000) fail wit
|
|
|
61
86
|
| `mode.denyTools` | goal/todo/team/workflow/subagent tools | Tools refused while the mode is active (12 defaults). |
|
|
62
87
|
| `mode.storePath` | `$DSH_HOME/tower-mode` | Directory for `modes.json`. |
|
|
63
88
|
| `mode.maxEntries` | `200` | Maximum persisted mode entries (1–2000). |
|
|
64
|
-
| `review.
|
|
89
|
+
| `review.mode` | `optional` | Review policy. `off` = review is intentionally unavailable: recording a review is refused, `tower_spawn` refuses the reviewer role, the merge gate ignores review, and a profile-level `off` does not register `tower_review` (a repository-level `off` refuses the submission instead); `optional` = review is available but never blocks a merge (default); `required` = a clean review bound to the branch tip is a merge blocker (`no-review`/`not-clean`/`review-hold`/`review-not-approved`/`tip-moved`/`review-mission-mismatch`). |
|
|
90
|
+
| `review.requireReview` | `false` | Deprecated alias for `review.mode`: `true` → `required`, `false` → `optional`. Prefer `review.mode`. `true` next to a non-`required` `review.mode` is rejected with `config-invalid` naming both keys; `false` is accepted next to any explicit `review.mode` (`off`/`optional`/`required`) and never overrides it. The Plugins-page control shows the alias when it is the only key and always writes `review.mode` with `review.requireReview:false`. |
|
|
65
91
|
| `review.maxRoundsPerReviewer` | `5` | Review-round cap per reviewer per branch. |
|
|
66
92
|
| `merge.timeoutMs` | `900000` (15 min) | Default `tower_merge` timeout, including hooks. A per-call `timeoutMs` wins. |
|
|
67
93
|
| `merge.maxBufferBytes` | `67108864` (64 MB) | Merge output buffer. |
|
|
@@ -86,7 +112,7 @@ violates the declared schema (for example `merge.timeoutMs` below 1000) fail wit
|
|
|
86
112
|
| `tests.allowPackageDiscovery` | `true` | Allow repo-controlled `tower.testDiscovery` commands (executes worktree code; see security). |
|
|
87
113
|
| `gates.requireChecks` | `false` | Require at least one `tower_complete.checks` entry before merge (`no-check-evidence`). |
|
|
88
114
|
| `gates.requireTests` | `false` | Require a passing discovery receipt for the current mission branch tip (`tests-missing`); independent of the review gate. With the `tower-tests` component row off, planning/mode entry refuse this combination with an explanation. |
|
|
89
|
-
| `gates.allowReviewExemption` | `false` | With `review.
|
|
115
|
+
| `gates.allowReviewExemption` | `false` | With `review.mode:required`, allow `reviewPolicy:"none"` + a non-empty reason to skip review blockers. Off deliberately; irrelevant when `review.mode` is `off` or `optional` (no review blocker is produced). |
|
|
90
116
|
| `gates.maxReportBytes` | `32768` (32 KiB) | Hard cap in UTF-8 bytes for `tower_complete.report`. A larger report is rejected with `invalid-argument` and an actionable `nextAction` (file the full text in the mission worktree and reference its path); it is never truncated. Existing larger reports still load. |
|
|
91
117
|
| `docs.boardLocation` | `common` | `common` = `<git-common-dir>/dsh-tower/MISSIONS.md`; `repo` = `<repoRoot>/MISSIONS.md`. Whether the board is written at all is the `tower-board` component row (#133); `docs.board` was removed and is rejected as an unknown key. |
|
|
92
118
|
| `archive.afterDays` | `30` | Age trigger: a terminal mission untouched for at least this many days is archived on the next mutation (`0` archives immediately). Archival itself is the `tower-archive` component row (#135); `archive.enabled` was removed and is rejected as an unknown key. |
|
|
@@ -29,6 +29,7 @@ single recovery step appended to the message as ` — next: …` (with ` (retrya
|
|
|
29
29
|
| `provider-cooldown` | The provider is throttled; spawn is in a short cooldown. | yes | wait for the cooldown to expire, then retry |
|
|
30
30
|
| `preset-missing` | The configured agent preset is not registered. | no | install the tower-worker and tower-reviewer agent presets and restart DSH |
|
|
31
31
|
| `reviewer-prerequisite` | The reviewer spawn prerequisite is not met. | no | complete the mission first, then spawn the reviewer |
|
|
32
|
+
| `review-disabled` | Review is disabled by `review.mode:off`; no reviewer, verdict, or review blocker exists in this configuration. | no | set review.mode to optional or required in the Tower config, then retry |
|
|
32
33
|
| `not-authorized` | The calling agent role may not perform this action. | no | call the tool as the tower, or as the worker/reviewer it is assigned to |
|
|
33
34
|
| `workspace-busy` | Another Tower session owns this repository workspace lock. | yes | run /tower off in the other session or wait for its lock to become stale |
|
|
34
35
|
| `worker-limit` | The repository reached spawn.maxLiveWorkers live workers. | no | wait for a live worker to finish or raise spawn.maxLiveWorkers |
|
package/docs/reference/errors.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Tool failures are thrown errors, not `{ok:false}` results (gate outcomes are the exception: see
|
|
4
4
|
[blockers.md](blockers.md)). Every thrown error carries a stable code as a message prefix. This
|
|
5
|
-
release defines
|
|
5
|
+
release defines 36 tool error codes.
|
|
6
6
|
|
|
7
7
|
Every `TowerToolError` carries `retryable` (boolean), `nextAction` (string or `null`) and `details`
|
|
8
8
|
(structured context or `null`) for programmatic callers. The model-visible surface is the message:
|
|
@@ -43,6 +43,7 @@ plain `Error` without a structured code is reported as `tool-internal`.
|
|
|
43
43
|
| `provider-cooldown` | The provider is throttled; spawn is in a short cooldown. | yes | wait for the cooldown to expire, then retry | repeated retryable provider failures; wait for `blockedUntil` |
|
|
44
44
|
| `preset-missing` | The configured agent preset is not registered. | no | install the tower-worker and tower-reviewer agent presets and restart DSH | missing `tower-worker`/`tower-reviewer` preset rows, DSH not restarted |
|
|
45
45
|
| `reviewer-prerequisite` | The reviewer spawn prerequisite is not met. | no | complete the mission first, then spawn the reviewer | reviewer spawned before the mission is `completed`, or before a worktree exists |
|
|
46
|
+
| `review-disabled` | Review is disabled by `review.mode:off`; no reviewer, verdict, or review blocker exists in this configuration. | no | set review.mode to optional or required in the Tower config, then retry | `tower_spawn` with `role:"reviewer"`, or a review submission, while `review.mode` is `off` |
|
|
46
47
|
| `not-authorized` | The calling agent role may not perform this action. | no | call the tool as the tower, or as the worker/reviewer it is assigned to | a worker calling a tower-only tool or changing mission status/scope; a reviewer mutating findings |
|
|
47
48
|
| `workspace-busy` | Another Tower session owns this repository workspace lock. | yes | run /tower off in the other session or wait for its lock to become stale | `mode.workspaceLock:true` and a second session calls a repo-scoped tool |
|
|
48
49
|
| `worker-limit` | The repository reached spawn.maxLiveWorkers live workers. | no | wait for a live worker to finish or raise spawn.maxLiveWorkers | spawning a fifth worker with the default limit |
|
|
@@ -65,8 +65,24 @@ config-key count is two-way: a later increase **or** decrease needs its own
|
|
|
65
65
|
decision naming an ADR, unlike sections and tools. The same wave makes the gate
|
|
66
66
|
import `OPERATIONAL_TOOLS` instead of scraping it, discover every shipped
|
|
67
67
|
`cordis.patch.yml` in both directions, review the non-boolean behaviour knobs
|
|
68
|
-
(`spawn.requireLease`, `tests.admission`), and refuse a row
|
|
69
|
-
component's `allowedOverrides`.
|
|
68
|
+
(`spawn.requireLease`, `tests.admission`, and now `review.mode`), and refuse a row
|
|
69
|
+
config outside its component's `allowedOverrides`.
|
|
70
|
+
|
|
71
|
+
#M39 grew the config surface by exactly one, 53 → 54: `review.mode`
|
|
72
|
+
(`off`/`optional`/`required`) is the review policy, and the deprecated
|
|
73
|
+
`review.requireReview` boolean stays accepted for one release as a normalized
|
|
74
|
+
alias. It is not a fifth component row: `preset-tower-reviewer` remains a
|
|
75
|
+
capability row and `review.mode:off` simply leaves it unused (no `tower_review`,
|
|
76
|
+
no reviewer spawn, no review blockers). The dated decision records both the new
|
|
77
|
+
key and why the old boolean was not removed in the same release.
|
|
78
|
+
|
|
79
|
+
#M42 reclassifies the deprecated alias from `forbidden-to-disable` to `core` in
|
|
80
|
+
the component surface: it is policy configuration and a compatibility alias, not
|
|
81
|
+
a capability a row may switch. The policy is one tri-state control on the
|
|
82
|
+
plugin-page form, not a row and not one row per mode; the review gate in
|
|
83
|
+
`required` mode, its tip-bound evidence and the exemption path remain
|
|
84
|
+
non-disableable. The component and config-key counts do not move (11 visible
|
|
85
|
+
components, 54 keys).
|
|
70
86
|
|
|
71
87
|
## Config keys
|
|
72
88
|
|
|
@@ -92,7 +108,8 @@ component's `allowedOverrides`.
|
|
|
92
108
|
| `mode.storePath` | niche | Custom mode-store location added for one deployment workflow. Removal note: derive the path from `$DSH_HOME` in the next minor; no in-tree caller sets this key. |
|
|
93
109
|
| `mode.maxEntries` | tuning | Bounds the persisted mode store. |
|
|
94
110
|
| `mode.lockTimeoutMs` | tuning | Bounded wait for the cross-process mode lock. |
|
|
95
|
-
| `review.
|
|
111
|
+
| `review.mode` | core | The review policy itself (`off`/`optional`/`required`); it replaces the deprecated boolean as the single gate switch. |
|
|
112
|
+
| `review.requireReview` | core | Deprecated alias for `review.mode` (`true` → `required`, `false` → `optional`); retained for one release. |
|
|
96
113
|
| `review.maxRoundsPerReviewer` | core | Caps review rounds; changes the review lifecycle. |
|
|
97
114
|
| `merge.timeoutMs` | tuning | Default merge timeout; a per-call value wins. |
|
|
98
115
|
| `merge.maxBufferBytes` | tuning | Captured merge output buffer. |
|
|
@@ -51,7 +51,7 @@ discovery fails.
|
|
|
51
51
|
- `tower_complete` adds a `tests` check when `tests.autoChecks` is on.
|
|
52
52
|
- `gates.requireChecks` requires any completion check; `gates.requireTests` requires a passing receipt
|
|
53
53
|
for the current mission branch tip (`tests-missing`). Review is independent of this gate: with
|
|
54
|
-
`review.
|
|
54
|
+
`review.mode:optional` (the default) or `off`, the tests gate still checks the branch tip.
|
|
55
55
|
|
|
56
56
|
## Trust boundary
|
|
57
57
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Tools overview (generated)
|
|
2
2
|
|
|
3
3
|
> Generated by `npm run docs:generate:tools` from the registered tool definitions. Do not edit by hand.
|
|
4
|
-
> Surface: config keys:
|
|
4
|
+
> Surface: config keys: 54 · sections: 14 · tools: 29 · baseline 2026-10-23. Generated from `scripts/surface-baseline.json`; do not edit by hand.
|
|
5
5
|
|
|
6
6
|
| Tool | Description |
|
|
7
7
|
|---|---|
|
|
@@ -22,15 +22,15 @@
|
|
|
22
22
|
| `tower_mission` | Update one mission: lifecycle status, decision note, blocker, clear blockers, mark a task done, drop a task with a reason, or widen the scope (tower only). "merged" is never set here; only a future tower_merge records it. Merged and abandoned are terminal. |
|
|
23
23
|
| `tower_mode` | Report whether Tower mode is active for the calling agent, who changed it last, whether the model may toggle it, any goal paused on entry, the workspace lock, HMR availability and the plugin version. |
|
|
24
24
|
| `tower_plan` | Plan one or more missions in an initialized repository. Each mission has a printable-Unicode title (NFC-normalized, at most 120 characters), relative scope globs, optional task checklist, optional mission-id dependencies, and kind build|survey. Assigns M1.. ids and auto-adds a dependency when build scopes overlap (serializes merges); rejects dependency cycles. |
|
|
25
|
-
| `tower_preflight` | Read-only merge gate for one mission: returns ok plus stable blocker codes (branch-missing, deps-unmerged, read-only-survey, stale-base, out-of-scope, base-dirty, branch-owned-by-closed-missions, and mission/worker guards). Review blockers (no-review, review-hold, not-clean, review-not-approved, tip-moved, review-mission-mismatch) apply only when review.
|
|
25
|
+
| `tower_preflight` | Read-only merge gate for one mission: returns ok plus stable blocker codes (branch-missing, deps-unmerged, read-only-survey, stale-base, out-of-scope, base-dirty, branch-owned-by-closed-missions, and mission/worker guards). Review blockers (no-review, review-hold, not-clean, review-not-approved, tip-moved, review-mission-mismatch) apply only when review.mode is required; review.mode off and optional skip them. Never changes anything. |
|
|
26
26
|
| `tower_rebase` | Rebase a mission branch onto the current base tip inside its own worktree. Refuses while its worker is running or the worktree is dirty. A clean conflict-free rebase waives re-review for the old review; a conflict is aborted and the mission is marked blocked. If the branch is already contained in the base, it returns alreadyMerged and leaves the branch untouched so tower_merge can record the landed merge. |
|
|
27
27
|
| `tower_recover` | Read-only recovery diagnostics and an explicit stale-state-lock repair. status reports the state lock owner with its age, heartbeat age and staleness; clear-stale-lock requires confirm:"CLEAR_STALE_LOCK" and only moves a lock whose PID is provably dead to a backup file. force:true additionally clears a live-but-silent PID (a recycled PID) and still renames the record to a .recovered-<ts> backup. It never resets Tower state or worktrees. |
|
|
28
28
|
| `tower_reload` | Dev-only: ask DSH HMR to reconcile this profile and reload the Tower Host plugin from disk. Registered only while the tower-hmr component is on (the row is shipped off). The reload is scheduled a few milliseconds after this call returns (so the result reaches the model first). Use after editing the plugin source in a linked profile; plugin_manager install/update already triggers reconciliation by itself. Fails with reload-unavailable when the HMR service is absent. |
|
|
29
29
|
| `tower_resource` | Advisory resource leases per repository (coordination only; no OS CPU/memory hard cap). acquire/release require a token and are tower-only; status is read-only. Expired leases are never taken over silently. |
|
|
30
|
-
| `tower_review` | Submit an independent review verdict bound to the current branch tip: a completed mission starts a review round, and while the mission is active a later route may still record a verdict for that same reviewed tip, appending to the same round without changing the status (a moved tip is rejected with an explanation). status is "clean", "p1-Nitems", or "p2-Nitems"; merge is "merge", "fix-then-merge", or "hold" (only clean + merge is later approval). Non-clean returns the mission to active. Reviewers are capped at 5 rounds per branch; a tower-submitted review is break-glass and requires breakGlassReason. |
|
|
30
|
+
| `tower_review` | Submit an independent review verdict bound to the current branch tip: a completed mission starts a review round, and while the mission is active a later route may still record a verdict for that same reviewed tip, appending to the same round without changing the status (a moved tip is rejected with an explanation). status is "clean", "p1-Nitems", or "p2-Nitems"; merge is "merge", "fix-then-merge", or "hold" (only clean + merge is later approval). Non-clean returns the mission to active. Reviewers are capped at 5 rounds per branch; a tower-submitted review is break-glass and requires breakGlassReason. The tool is not registered when review.mode is off. |
|
|
31
31
|
| `tower_roster` | List tower roster agents with authoritative live activity from the subagent catalog (running/inactive/missing/unknown). Read-only; never resumes children. Use before completion or merge decisions. |
|
|
32
32
|
| `tower_send` | Send a durable inbox message to a tower participant: a roster agent name, "tower", or "all" (broadcast). The message is persisted first; when the recipient is a currently running roster agent the tower also steers it into that child's current turn. Returns delivery results. |
|
|
33
|
-
| `tower_spawn` | Spawn a worker or reviewer for a mission. Workers use the tower-worker preset; reviewers require a completed mission and use the read-only tower-reviewer preset. Provisions (or reuses) the mission git worktree and branch, generates a self-contained briefing, and starts a background subagent in that worktree. The child final report is delivered back to this session; tower_roster shows authoritative activity. Records the agent in the roster; reviewer spawns record the branch tip so a reviewer that modifies the branch cannot submit a review. Returns immediately unless wait=true. |
|
|
34
|
-
| `tower_status` | Read the Tower dashboard for a repository: state path, base branch, revision, mission status counts, paged mission summaries (scope/deps/tasks/worktree/owner), roster size, findings, archive count, config path and the activity tail. Also reports the repo-scoped git lock holder (`gitLock: {held,pid,phase,heldMs}`) so a merge holding the mutex is visible. Pass missionId for one full mission (tasks, notes, reviews, findings, completion report; archived missions are loaded from their year file); offset/limit page the mission list (default 20, max 100); includeGate adds preflight gate digests for the page; includeArchived appends compact archived summaries after the active page; format:"markdown" returns the human-readable mission board (active missions plus an archived count). Read-only. |
|
|
33
|
+
| `tower_spawn` | Spawn a worker or reviewer for a mission. Workers use the tower-worker preset; reviewers require a completed mission and use the read-only tower-reviewer preset, and the reviewer role is refused when review.mode is off. Provisions (or reuses) the mission git worktree and branch, generates a self-contained briefing, and starts a background subagent in that worktree. The child final report is delivered back to this session; tower_roster shows authoritative activity. Records the agent in the roster; reviewer spawns record the branch tip so a reviewer that modifies the branch cannot submit a review. Returns immediately unless wait=true. |
|
|
34
|
+
| `tower_status` | Read the Tower dashboard for a repository: state path, base branch, revision, mission status counts, paged mission summaries (scope/deps/tasks/worktree/owner), roster size, findings, archive count, config path and the activity tail. Also reports the repo-scoped git lock holder (`gitLock: {held,pid,phase,heldMs}`) so a merge holding the mutex is visible, and the resolved review policy (`review: {mode, available, required, detail}`; mode off means review is intentionally unavailable). Pass missionId for one full mission (tasks, notes, reviews, findings, completion report; archived missions are loaded from their year file); offset/limit page the mission list (default 20, max 100); includeGate adds preflight gate digests for the page; includeArchived appends compact archived summaries after the active page; format:"markdown" returns the human-readable mission board (active missions plus an archived count). Read-only. |
|
|
35
35
|
| `tower_teardown` | Tear down eligible mission worktrees after their missions are merged or abandoned. A worktree whose roster agent is running is always kept (force cannot override); dirty worktrees need force; exclude keeps named missions. dry_run previews the remove/keep decisions without changing anything. Terminal missions whose worktree is gone and whose configured archive policy is due (archive.afterDays / archive.maxMissions) are moved to <git-common-dir>/dsh-tower/archive/ so state.json stops rewriting them; nothing is deleted. |
|
|
36
36
|
| `tower_test` | Run the mission worktree's declared tower.testDiscovery (package.json) and record the receipt. Returns ok:false with diagnostics when discovery fails; does not change mission status. Use tower_complete for automatic admission checks. |
|
package/docs/reference/tools.md
CHANGED
|
@@ -38,7 +38,7 @@ findings but not mutate them. Violations throw `[tower:not-authorized]` or
|
|
|
38
38
|
| `tower_plan` | `missions[]` (`title` — printable Unicode, NFC-normalized, ≤120 characters, `scope[]`, `tasks[]?`, `deps[]?`, `kind?`, `context?`, `references[]?` ≤20, `reviewPolicy?`, `reviewExemptionReason?`) | Create missions `M1..`; overlapping build scopes auto-add a dependency; rejects unknown deps and cycles. Mission ids stay ASCII (`M1`, `M2`); invisible characters and over-long titles are rejected with `invalid-argument`. `reviewPolicy:"none"` requires a non-empty reason; when the review gate is on, preflight also requires `gates.allowReviewExemption`. |
|
|
39
39
|
| `tower_mission` | `id` (alias `missionId`), `status?`, `task_done?`, `task_drop?`+`task_drop_reason?`, `blocker?`, `clear_blockers?`, `note?`, `scope?`, `pause_cause?`, `authorization?` | Update one mission. Worker-safe fields are task/blocker/note; `merged` cannot be set here. Paused missions record `pause_cause` (user/failure/resource/dependency); resuming a user-paused mission honors `mode.requireResumeAuthorization`. |
|
|
40
40
|
\|\ `tower_status`\ \|\ `missionId\?`,\ `offset\?`,\ `limit\?`,\ `includeGate\?`,\ `includeArchived\?`,\ `format\?`\ \|\ Dashboard\ by\ default\.\ Paged\ missions\ carry\ `reportBytes`\ only;\ `missionId`\ returns\ full\ detail\ \(tasks/notes/reviews/findings/completionReport\ body\),\ and\ an\ archived\ mission\ is\ loaded\ from\ its\ year\ file\.\ `offset`/`limit`\ page\ active\ missions\ \(default\ 20,\ max\ 100\),\ `includeGate`\ adds\ gate\ digests,\ `includeArchived`\ appends\ compact\ archived\ summaries\ \(flagged\ `archived:true`,\ no\ report\ body\)\ after\ the\ active\ page,\ and\ `format:"markdown"`\ returns\ the\ board\ \(active\ rows\ plus\ an\ archived\ count\)\.\ Includes\ `mode`\ with\ `lastChange`\ and\ recent\ `history`\ when\ the\ host\ mode\ hook\ is\ available\.\ `archive`\ reports\ `\{count,\ years,\ unreadable,\ message}`;\ a\ corrupt\ archive\ degrades\ to\ `unreadable:true`\ instead\ of\ failing\ the\ dashboard\.\ Also\ returns\ `gitLock`\ \(`\{held,\ pid,\ phase,\ heldMs}`\)\ for\ the\ repo-scoped\ git\ mutex,\ and\ `\{held:\ false}`\ when\ it\ is\ free\.\ \|
|
|
41
|
-
| `tower_spawn` | `missionId` (alias `id`), `role` (`worker`/`reviewer`), `name?`, `instructions?`, `worktreeRoot?`, `wait?`, `waitMs?`, `takeover?`, `includeDirtyBase?` | Provision/reuse the worktree and start a subagent. Worker uses `tower-worker`; reviewer requires a `completed` mission and uses the read-only `tower-reviewer`. `takeover:true` replaces a live worker entry that is no longer running (increments ownerGeneration). Only one live worker per mission; `spawn.maxLiveWorkers` caps the repository. |
|
|
41
|
+
| `tower_spawn` | `missionId` (alias `id`), `role` (`worker`/`reviewer`), `name?`, `instructions?`, `worktreeRoot?`, `wait?`, `waitMs?`, `takeover?`, `includeDirtyBase?` | Provision/reuse the worktree and start a subagent. Worker uses `tower-worker`; reviewer requires a `completed` mission and uses the read-only `tower-reviewer`; with `review.mode:off` the reviewer role is refused with `[tower:review-disabled]`. `takeover:true` replaces a live worker entry that is no longer running (increments ownerGeneration). Only one live worker per mission; `spawn.maxLiveWorkers` caps the repository. |
|
|
42
42
|
| `tower_roster` | — | Roster with live activity (`running`/`inactive`/`missing`/`unknown`) and `stale` flags from the subagent catalog. Read-only. |
|
|
43
43
|
| `tower_adopt` | `retireMissing?` | Reconcile roster entries with the durable subagent catalog. Provably gone agents are retired (default) or marked `missing` (`retireMissing:false`) so they can be inspected/taken over. |
|
|
44
44
|
| `tower_diff` | `missionId` (alias `id`), `maxBytes?` | Read-only merge-base diff: files, commits, capped patch. Safe for reviewers. |
|
|
@@ -48,8 +48,8 @@ findings but not mutate them. Violations throw `[tower:not-authorized]` or
|
|
|
48
48
|
| `tower_interrupt` | `to?` (roster name), `agentId?`, `reason?` | Interrupt one running roster agent via `subagents.interrupt`, record `state:"interrupted"`. Idempotent (not running → `interrupted:false`). |
|
|
49
49
|
| `tower_finding` | `type`, `title`, `summary`, `details`, `suggested_fix`, `severity?`, `missionId?`, `location?` | Record an out-of-scope issue; reviewers use this instead of editing. Finds start as `open`. |
|
|
50
50
|
| `tower_findings` | `id?`, `status?`, `note?`, filters (`type?`, `severity?`, `missionId?`, `open?`, `limit?`) | Lifecycle tool: list/read/transition. Statuses `open → triaged → fixed`/`wontfix`, reopen allowed. Only the tower or a worker may mutate; a reviewer can list/read. |
|
|
51
|
-
| `tower_review` | `missionId` (alias `id`), `status` (`clean`/`p1-Nitems`/`p2-Nitems`), `merge` (`merge`/`fix-then-merge`/`hold`), `findings`, `decision`, `checks?`, `breakGlassReason?` | Reviewer verdict bound to the current tip. Reviewer must be the assigned reviewer (or tower break-glass). A later route may record a verdict for the same reviewed tip while the mission is active: it appends to that round (`appended:true`) without changing the status; a verdict for a moved tip is rejected with an explanation. |
|
|
52
|
-
| `tower_preflight` | `missionId` (alias `id`) | Read-only gate: returns `{ok, blockers[], branchTip, baseTip, changedFiles, review}`. |
|
|
51
|
+
| `tower_review` | `missionId` (alias `id`), `status` (`clean`/`p1-Nitems`/`p2-Nitems`), `merge` (`merge`/`fix-then-merge`/`hold`), `findings`, `decision`, `checks?`, `breakGlassReason?` | Reviewer verdict bound to the current tip. Reviewer must be the assigned reviewer (or tower break-glass). Not registered when `review.mode:off`; a repository-level `off` refuses the submission with `[tower:review-disabled]`. A later route may record a verdict for the same reviewed tip while the mission is active: it appends to that round (`appended:true`) without changing the status; a verdict for a moved tip is rejected with an explanation. |
|
|
52
|
+
| `tower_preflight` | `missionId` (alias `id`) | Read-only gate: returns `{ok, blockers[], branchTip, baseTip, changedFiles, review}`. Review blockers appear only with `review.mode:required`; `off`/`optional` skip them. |
|
|
53
53
|
| `tower_merge` | `missionId` (alias `id`), `timeoutMs?` (alias `timeout_ms`) | Merge after a green gate. Records already-landed merges (`reconciled`), recovers a failed call whose commit exists (`recoveredFromFailure`), and separates `merge-hook-failed` from `merge-conflict`. |
|
|
54
54
|
| `tower_rebase` | `missionId` (alias `id`) | Rebase the branch onto the base in its worktree. Refuses while the worker runs or the worktree is dirty. Already-contained branches return `alreadyMerged` untouched. |
|
|
55
55
|
| `tower_teardown` | `force?`, `exclude?`, `dry_run?` (alias `dryRun`) | Remove eligible merged/abandoned worktrees and branches; running agents are always kept. The final pass applies the `archive` policy while the `tower-archive` component row is mounted: terminal missions whose worktree is gone are moved to `<git-common-dir>/dsh-tower/archive/` once `archive.afterDays`/`archive.maxMissions` says so, and `archived` lists their ids. Nothing is deleted; `archive.afterDays:0` archives a just-torn-down mission immediately. |
|
package/docs/zh/faq.md
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
分析与决策,再启动 Tower 执行(可选审查)仓库变更。详见[完整指南](guide/scenarios-and-philosophy.md#4-tower-与其他-dsh-工作流模式的区别)。
|
|
13
13
|
|
|
14
14
|
**为什么 worker 刚完成,`tower_preflight` 就因 `no-review` 失败?**
|
|
15
|
-
|
|
16
|
-
reviewer;干净审查后门禁就会变绿。默认 `review.
|
|
15
|
+
只有在审查策略为 `required`(`review.mode:required`)时才会如此:已完成的 mission 在等待独立审查。
|
|
16
|
+
spawn 一个 reviewer;干净审查后门禁就会变绿。默认 `review.mode:optional` 时审查可选,不会产生
|
|
17
17
|
`no-review` blocker。
|
|
18
18
|
|
|
19
19
|
**需要轮询 worker 吗?**
|
|
@@ -35,9 +35,11 @@ reviewer;干净审查后门禁就会变绿。默认 `review.requireReview:fals
|
|
|
35
35
|
正确:分支已经包含在基线中。此时调用 `tower_merge` 记录已落地的合并,而不是 rebase。
|
|
36
36
|
|
|
37
37
|
**可以要求强制独立审查吗?**
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
做更窄的豁免。`
|
|
38
|
+
可以。把审查策略设为 `required` —— 插件页上的一个三态控件,或在 profile/仓库配置中写
|
|
39
|
+
`review.mode:required`(默认 `optional`)。策略为 `required` 时,可用 mission 级
|
|
40
|
+
`reviewPolicy:"none"` + 理由 + `gates.allowReviewExemption:true` 做更窄的豁免。`optional` 模式下
|
|
41
|
+
`tower_review` 同样可用并记录结论。旧布尔开关是已弃用、保留一个版本的别名;映射关系见
|
|
42
|
+
[安装、升级与迁移](guide/install-upgrade-migration.md)。
|
|
41
43
|
|
|
42
44
|
**reviewer 能修改文件吗?**
|
|
43
45
|
不能。reviewer 使用只读的 `tower-reviewer` preset(没有 write/edit/pwsh);reviewer spawn 之后分支
|