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.
- package/CHANGELOG.md +109 -0
- package/CONTRIBUTING.md +1 -1
- package/README.en.md +44 -8
- package/README.md +42 -8
- package/cordis.patch.yml +11 -1
- package/docs/README.md +10 -5
- package/docs/architecture/overview.md +13 -9
- package/docs/faq.md +45 -2
- package/docs/guide/hot-reload.md +189 -0
- package/docs/guide/install-upgrade-migration.md +11 -0
- package/docs/guide/quickstart.md +33 -1
- package/docs/guide/scenarios-and-philosophy.md +309 -0
- package/docs/operations/runbook.md +23 -0
- package/docs/operations/security.md +23 -0
- package/docs/reference/blockers.md +10 -2
- package/docs/reference/config.md +65 -2
- package/docs/reference/doctor.md +33 -0
- package/docs/reference/errors.md +50 -0
- package/docs/reference/events.md +45 -0
- package/docs/reference/operations.md +55 -0
- package/docs/reference/testing.md +61 -0
- package/docs/reference/tools.md +65 -23
- package/docs/zh/README.md +60 -0
- package/docs/zh/faq.md +81 -0
- package/docs/zh/guide/hot-reload.md +178 -0
- package/docs/zh/guide/install-upgrade-migration.md +57 -0
- package/docs/zh/guide/quickstart.md +96 -0
- package/docs/zh/guide/scenarios-and-philosophy.md +211 -0
- package/docs/zh/operations/security.md +42 -0
- package/docs/zh/reference/blockers.md +62 -0
- package/docs/zh/reference/config.md +113 -0
- package/docs/zh/reference/doctor.md +31 -0
- package/docs/zh/reference/errors.md +52 -0
- package/docs/zh/reference/events.md +46 -0
- package/docs/zh/reference/operations.md +50 -0
- package/docs/zh/reference/testing.md +60 -0
- package/docs/zh/reference/tools.md +75 -0
- package/index.js +261 -13
- package/lib/batch.js +578 -0
- package/lib/config.js +275 -9
- package/lib/doctor.js +171 -0
- package/lib/errors.js +111 -0
- package/lib/hmr.js +196 -0
- package/lib/leases.js +317 -0
- package/lib/legacy.js +413 -0
- package/lib/modeStore.js +28 -1
- package/lib/store.js +24 -1
- package/lib/tests.js +628 -0
- package/lib/tools.js +1566 -184
- package/lib/tower.js +986 -103
- package/lib/workspaceLock.js +117 -0
- package/lib/worktreeOwnership.js +166 -0
- package/package.json +4 -1
- package/reviewer.js +1 -0
- package/scripts/check-docs.mjs +135 -0
- package/scripts/enable-dev-hmr.mjs +347 -0
- package/skills/tower-review.md +4 -2
- package/skills/tower-worker-protocol.md +3 -1
- package/worker.js +4 -2
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
`tower_preflight` returns `{ok:false, blockers:[{code, detail}]}`. `tower_merge` and `tower_rebase`
|
|
4
4
|
return the same shape for operation failures. Codes are stable; the detail is human-facing.
|
|
5
5
|
|
|
6
|
-
## Gate blockers (
|
|
6
|
+
## Gate blockers (26)
|
|
7
7
|
|
|
8
8
|
| Code | Meaning / next action |
|
|
9
9
|
|---|---|
|
|
@@ -11,6 +11,7 @@ return the same shape for operation failures. Codes are stable; the detail is hu
|
|
|
11
11
|
| `mission-not-completed` | Mission is not `completed`; only a completed mission (awaiting review) merges. |
|
|
12
12
|
| `tasks-open` | Open tasks remain; the worker must finish or `task_drop` with a reason. |
|
|
13
13
|
| `blockers-present` | The mission has blockers; clear them after resolving. |
|
|
14
|
+
| `no-check-evidence` | `gates.requireChecks` is enabled and the completion report has no `checks`. Return the completed mission to `active`, re-run `tower_complete` with checks, then review again. |
|
|
14
15
|
| `branch-missing` | No worktree/branch yet: spawn a worker first. |
|
|
15
16
|
| `stale-base` | The branch does not contain the base tip: run `tower_rebase`. |
|
|
16
17
|
| `read-only-survey` | Survey mission changed files; survey missions must be read-only. |
|
|
@@ -24,16 +25,23 @@ return the same shape for operation failures. Codes are stable; the detail is hu
|
|
|
24
25
|
| `review-not-approved` | Latest clean review says `fix-then-merge` or `hold`; only `merge` approves. |
|
|
25
26
|
| `tip-moved` | The branch changed after review; review again (or use a clean rebase waiver). |
|
|
26
27
|
| `worker-busy` | A roster agent for this mission is running; wait or retire it. |
|
|
28
|
+
| `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. |
|
|
27
29
|
| `base-wrong-branch` | The main checkout is not on the recorded base branch. |
|
|
28
30
|
| `branch-owned-by-closed-missions` | The mission is already merged/abandoned; re-plan under a new title. |
|
|
31
|
+
| `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. |
|
|
32
|
+
| `tests-missing` | `gates.requireTests` is enabled and there is no passing discovery receipt for the reviewed tip; run `tower_test` or `tower_complete`. |
|
|
33
|
+
| `tests-failed` | The latest discovery receipt failed or did not meet minCount/required checks. Fix the tests and re-run. |
|
|
34
|
+
| `review-exemption-invalid` | The mission requests `reviewPolicy:"none"` but `gates.allowReviewExemption` is off (or the reason is missing). |
|
|
35
|
+
| `merge-intent-pending` | A merge intent was recorded before a crash/failure; run `tower_merge` to reconcile before another gate. |
|
|
29
36
|
|
|
30
|
-
## Merge failures (
|
|
37
|
+
## Merge failures (4)
|
|
31
38
|
|
|
32
39
|
| Code | Meaning / next action |
|
|
33
40
|
|---|---|
|
|
34
41
|
| `merge-conflict` | Real index conflict; the mission is `blocked`. Resolve, restore the mission to `active`/`completed`, retry. |
|
|
35
42
|
| `merge-hook-failed` | A hook/process failed before a commit existed; repository restored, mission stays `completed`. Retry; `timeout: true` means the git process timed out. Raise `timeoutMs` for slow hooks. |
|
|
36
43
|
| `merge-shape` | Git produced unexpected merge parents; inspect the repository, do not force. |
|
|
44
|
+
| `batch-invalid` | A batch id/member/receipt/check reference is invalid or close evidence is incomplete. |
|
|
37
45
|
|
|
38
46
|
A merge that already landed is **not** a blocker: `tower_merge` records it (`reconciled`,
|
|
39
47
|
`alreadyLanded`) or recovers it (`recoveredFromFailure`, `warnings`).
|
package/docs/reference/config.md
CHANGED
|
@@ -2,17 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
Every key is optional; defaults reproduce the shipped behavior. Unknown top-level keys are rejected.
|
|
4
4
|
`section` and `allowAgentControl` are legacy aliases for `mode.promptSection` and
|
|
5
|
-
`mode.allowAgentControl`.
|
|
5
|
+
`mode.allowAgentControl`. A legacy alias only fills a gap: when both forms are set, the canonical
|
|
6
|
+
`mode.*` key wins.
|
|
7
|
+
|
|
8
|
+
## Layers and precedence
|
|
9
|
+
|
|
10
|
+
Lowest precedence first:
|
|
11
|
+
|
|
12
|
+
1. code defaults (the table below),
|
|
13
|
+
2. profile config (the Cordis patch that mounts `dsh-tower` passes it to `apply()`),
|
|
14
|
+
3. repository config at `<git-common-dir>/dsh-tower/config.json` (usually `.git/dsh-tower/config.json`),
|
|
15
|
+
4. per-call tool arguments such as `worktreeRoot` and `timeoutMs`.
|
|
16
|
+
|
|
17
|
+
The repository layer is read every time a Tower tool opens a repository, so a repository can tune
|
|
18
|
+
review, merge, worktree and spawn policy without editing the profile. It uses the same JSON shape as
|
|
19
|
+
the profile config (the same groups and the legacy aliases) and is merged group by group: repo keys
|
|
20
|
+
win, profile keys survive when the repo does not set them. `tower_status` reports
|
|
21
|
+
`config.path` and `config.repoConfigPresent`.
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"review": { "maxRoundsPerReviewer": 3 },
|
|
26
|
+
"merge": { "timeoutMs": 1800000 },
|
|
27
|
+
"worktrees": { "root": "D:/tower-worktrees" },
|
|
28
|
+
"spawn": { "reviewerPreset": "tower-reviewer", "maxDepth": 2 }
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The `mode.*` group is session-scoped, not repository-scoped: it is accepted in the repository file
|
|
33
|
+
for schema compatibility but only the profile config controls the Tower-mode prompt and the
|
|
34
|
+
model-controlled toggle. A malformed file, a non-object value, unknown top-level keys, or a value that
|
|
35
|
+
violates the declared schema (for example `merge.timeoutMs` below 1000) fail with the stable
|
|
36
|
+
`config-invalid` / `config-unknown-key` tool error codes.
|
|
6
37
|
|
|
7
38
|
| Key | Default | Meaning |
|
|
8
39
|
|---|---|---|
|
|
9
40
|
| `section` | `''` | Legacy alias: replace the whole Tower-mode prompt text. Empty keeps the built-in reminder. |
|
|
10
41
|
| `allowAgentControl` | `false` (bundled patch: `true`) | Legacy alias: register `tower_control`. |
|
|
42
|
+
| `init.autoGitInit` | `false` (bundled patch: `true`) | `tower_init` may run `git init` + an empty initial commit when `repoRoot` is an absolute, existing directory that is not a repository. |
|
|
43
|
+
| `init.snapshotDirty` | `false` | `tower_init` may snapshot uncommitted **tracked** changes into a dangling commit used as the mission baseline (untracked files are not included; the commit is kept alive under `refs/tower/snapshot/*`). |
|
|
11
44
|
| `mode.promptSection` | `''` | Replacement prompt text (takes precedence over `section` when both set). |
|
|
12
45
|
| `mode.sectionAppend` | `''` | Extra text appended after the reminder (team conventions). |
|
|
13
46
|
| `mode.allowAgentControl` | `false` | Register `tower_control`; the model may enter/leave with a reason. |
|
|
14
47
|
| `mode.autoPauseGoal` | `true` | Pause an active goal on entry; the goal is never auto-resumed on exit. |
|
|
15
|
-
| `mode.
|
|
48
|
+
| `mode.requireResumeAuthorization` | `false` | Resuming a mission paused with `pauseCause:user` requires an `authorization` reference. |
|
|
49
|
+
| `mode.workspaceLock` | `false` (bundled patch: `true`) | Allow only one Tower session per repository (`tower.lock`); others get `workspace-busy`. |
|
|
50
|
+
| `mode.workspaceLockScope` | `all` | `all` locks every repo tool; `mutations` skips the workspace lock for read-only tools. |
|
|
51
|
+
| `mode.planModePolicy` | `clear` | Tower entry clears an active plan mode (or `refuse` until the plan is exited); a pre-step also clears a plan activated later. |
|
|
52
|
+
| `mode.workspaceStaleMs` | `300000` | A workspace lock older than this can be taken over. |
|
|
53
|
+
| `mode.heartbeatMs` | `10000` | Workspace-lock heartbeat interval. |
|
|
54
|
+
| `mode.denyTools` | goal/todo/team/workflow/subagent tools | Tools refused while the mode is active (12 defaults). |
|
|
16
55
|
| `mode.storePath` | `$DSH_HOME/tower-mode` | Directory for `modes.json`. |
|
|
17
56
|
| `mode.maxEntries` | `200` | Maximum persisted mode entries (1–2000). |
|
|
18
57
|
| `review.maxRoundsPerReviewer` | `5` | Review-round cap per reviewer per branch. |
|
|
@@ -25,6 +64,27 @@ Every key is optional; defaults reproduce the shipped behavior. Unknown top-leve
|
|
|
25
64
|
| `spawn.provider` | `''` | Subagent provider id; empty prefers `spawn`, then the first provider. |
|
|
26
65
|
| `spawn.workerModel` | `{}` | Optional `{provider, model, reasoningEffort, maxTokens}` for workers. |
|
|
27
66
|
| `spawn.reviewerModel` | `{}` | Optional model route for reviewers; independent review is stronger with a different model. |
|
|
67
|
+
| `spawn.maxLiveWorkers` | `4` | Maximum live worker entries per repository (idle `inactive`, failed, interrupted, missing, stale and retired entries do not count); exceeding it returns `worker-limit`. |
|
|
68
|
+
| `spawn.staleMs` | `15000` | Roster entries without catalog activity after this age are marked `stale` and block merge (`worker-stale`); 0 disables. |
|
|
69
|
+
| `spawn.maxWaitMs` | `90000` | Upper bound for `tower_spawn.waitMs` (Kimi-compatible 90s default). |
|
|
70
|
+
| `spawn.requireLease` | `''` | Optional lease name that must be held before a worker can spawn. |
|
|
71
|
+
| `send.maxPerMinute` | `120` | Per-repository `tower_send` rate limit (0 disables); exceeding it returns `rate-limited`. |
|
|
72
|
+
| `send.interruptDefault` | `false` (bundled patch: `true`) | Default for `tower_send.interrupt` (interrupt the running turn before delivering). |
|
|
73
|
+
| `tests.enabled` | `true` | Run declared test discovery when the worktree `package.json` configures it. |
|
|
74
|
+
| `tests.admission` | `complete` | `spawn` runs discovery before starting a worker, `complete` at `tower_complete`, `off` only on explicit `tower_test`. |
|
|
75
|
+
| `tests.timeoutMs` | `60000` | Per discovery command timeout. |
|
|
76
|
+
| `tests.maxBytes` | `16777216` (16 MiB) | Captured stdout cap per command. |
|
|
77
|
+
| `tests.autoChecks` | `true` | Attach an automatic `tests` check to the completion report. |
|
|
78
|
+
| `tests.allowPackageDiscovery` | `true` | Allow repo-controlled `tower.testDiscovery` commands (executes worktree code; see security). |
|
|
79
|
+
| `gates.requireChecks` | `false` | Require at least one `tower_complete.checks` entry before merge (`no-check-evidence`). |
|
|
80
|
+
| `gates.requireTests` | `false` | Require a passing discovery receipt for the reviewed tip (`tests-missing`). |
|
|
81
|
+
| `gates.allowReviewExemption` | `false` | Allow `reviewPolicy:"none"` + reason to skip review blockers; default off deliberately. |
|
|
82
|
+
| `docs.board` | `true` | Write `MISSIONS.md` after mutations. |
|
|
83
|
+
| `docs.boardLocation` | `common` | `common` = `<git-common-dir>/dsh-tower/MISSIONS.md`; `repo` = `<repoRoot>/MISSIONS.md`. |
|
|
84
|
+
| `leases.ttlMs` | `900000` | Default advisory lease lifetime; expiry never auto-releases. |
|
|
85
|
+
| `dev.hotReload` | `true` | Register `tower_reload`; `/tower reload` is disabled when off. It returns `reload-unavailable` when the profile has no HMR service. |
|
|
86
|
+
| `dev.reloadDelayMs` | `50` | Delay before a scheduled reload so the tool result is delivered first. |
|
|
87
|
+
| `dev.reloadRequiredIds` | four Tower loader ids | Entry ids passed to `reconcileProfile` as required. |
|
|
28
88
|
|
|
29
89
|
## Example
|
|
30
90
|
|
|
@@ -35,6 +95,7 @@ Every key is optional; defaults reproduce the shipped behavior. Unknown top-leve
|
|
|
35
95
|
mode:
|
|
36
96
|
allowAgentControl: true
|
|
37
97
|
sectionAppend: 'Team conventions: tests are mandatory.'
|
|
98
|
+
workspaceLock: true
|
|
38
99
|
review:
|
|
39
100
|
maxRoundsPerReviewer: 3
|
|
40
101
|
merge:
|
|
@@ -43,6 +104,8 @@ Every key is optional; defaults reproduce the shipped behavior. Unknown top-leve
|
|
|
43
104
|
reviewerModel:
|
|
44
105
|
provider: deepseek-account
|
|
45
106
|
model: deepseek-flash
|
|
107
|
+
dev:
|
|
108
|
+
hotReload: true
|
|
46
109
|
```
|
|
47
110
|
|
|
48
111
|
## Looking up the effective schema
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Doctor
|
|
2
|
+
|
|
3
|
+
`tower_doctor({repoRoot})` is read-only. It never takes the state lock, writes state, or changes Git.
|
|
4
|
+
It returns:
|
|
5
|
+
|
|
6
|
+
```json
|
|
7
|
+
{
|
|
8
|
+
"ok": true,
|
|
9
|
+
"checks": [
|
|
10
|
+
{ "id": "git", "status": "pass", "detail": "git version 2.55.0" },
|
|
11
|
+
{ "id": "state", "status": "pass", "detail": ".../state.json revision 7" }
|
|
12
|
+
],
|
|
13
|
+
"environmentContract": {
|
|
14
|
+
"platform": "win32",
|
|
15
|
+
"gitVersion": "git version 2.55.0",
|
|
16
|
+
"repoRoot": "D:/repo",
|
|
17
|
+
"commonDir": "D:/repo/.git",
|
|
18
|
+
"stateDir": "D:/repo/.git/dsh-tower"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Checks cover: git availability, repository identity, state schema/load, repo config presence,
|
|
24
|
+
worker/reviewer preset names, subagents and HMR services, workspace lock holder/staleness, live roster,
|
|
25
|
+
worktree existence/ownership/dirtiness, test-discovery policy, legacy snapshots, batches and leases.
|
|
26
|
+
Missions intentionally cleaned up by `tower_teardown` are skipped (the check notes the removed count)
|
|
27
|
+
instead of being reported as missing.
|
|
28
|
+
`warn` is advisory; `fail` means the repository needs attention before spawning/merging. A state-load
|
|
29
|
+
failure is reported as a failed check rather than thrown so doctor remains useful on a broken
|
|
30
|
+
repository.
|
|
31
|
+
|
|
32
|
+
The environment contract is informational; it is not an identity or authorization proof. `tower_init`
|
|
33
|
+
still requires the tower role, and `tower_spawn` still checks the live subagent catalog.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Tool error codes
|
|
2
|
+
|
|
3
|
+
Tool failures are thrown errors, not `{ok:false}` results (gate outcomes are the exception: see
|
|
4
|
+
[blockers.md](blockers.md)). Every thrown error carries a stable code as a message prefix:
|
|
5
|
+
|
|
6
|
+
```
|
|
7
|
+
[tower:mission-not-found] unknown mission "M9"
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Callers can match the prefix instead of the prose. Codes are reserved for the conditions below; a
|
|
11
|
+
message without a more specific match is reported as `tool-internal`.
|
|
12
|
+
|
|
13
|
+
| Code | Meaning | Typical trigger |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| `invalid-argument` | A tool argument is missing, malformed, or not allowed. | `missionId`/`id` omitted; unknown status; empty report; bad scope glob; `timeoutMs < 1000`; `status: "all"` on an update. |
|
|
16
|
+
| `repo-invalid` | `repoRoot` is missing, relative, or not inside a Git repository. | passing a path in a directory that is not a repo |
|
|
17
|
+
| `not-initialized` | Tower is not initialized for this repository. | a read tool before `tower_init` |
|
|
18
|
+
| `mission-not-found` | No mission with that id exists. | a stale or mistyped `M9` |
|
|
19
|
+
| `finding-not-found` | No finding with that id exists. | `tower_findings({id:"F99"})` |
|
|
20
|
+
| `invalid-transition` | The requested state transition is not allowed. | a blocked→merged attempt; a finding transition not in the graph; a reviewer mutating findings; completing a mission with open tasks, blockers, no commits, or unread inbox messages. |
|
|
21
|
+
| `state-locked` | Another Tower writer holds the state lock. | concurrent mutation after the lock timeout |
|
|
22
|
+
| `state-corrupt` | The Tower state file is unreadable or invalid. | hand-edited `state.json` |
|
|
23
|
+
| `config-invalid` | Tower configuration is invalid. | malformed repo `config.json`, a value that violates the schema |
|
|
24
|
+
| `config-unknown-key` | Tower configuration has an unknown top-level key. | a typo such as `allowAgentToggle` |
|
|
25
|
+
| `git-failed` | A git command failed for a reason other than the delegated cases. | a rejected merge command, invalid ref |
|
|
26
|
+
| `git-timeout` | A git command timed out or exceeded its output buffer. | slow pre-merge hook, huge diff |
|
|
27
|
+
| `spawn-unavailable` | The subagents service is unavailable. | a Host without `subagents` |
|
|
28
|
+
| `provider-missing` | No subagent provider is registered. | an empty provider list |
|
|
29
|
+
| `preset-missing` | The configured agent preset is not registered. | missing `tower-worker`/`tower-reviewer` preset rows, DSH not restarted |
|
|
30
|
+
| `reviewer-prerequisite` | The reviewer spawn prerequisite is not met. | reviewer spawned before the mission is `completed`, or before a worktree exists |
|
|
31
|
+
| `not-authorized` | The calling agent role may not perform this action. | a worker calling a tower-only tool or changing mission status/scope; a reviewer mutating findings |
|
|
32
|
+
| `workspace-busy` | Another Tower session owns this repository's workspace lock. | `mode.workspaceLock:true` and a second session calls a repo-scoped tool |
|
|
33
|
+
| `worker-limit` | The repository reached `spawn.maxLiveWorkers` live workers. | spawning a fifth worker with the default limit |
|
|
34
|
+
| `rate-limited` | The `tower_send` per-minute rate limit was reached. | `send.maxPerMinute` exceeded; retry later |
|
|
35
|
+
| `takeover-refused` | The mission still has a running worker. | `tower_spawn({takeover:true})` before `tower_interrupt` |
|
|
36
|
+
| `reload-unavailable` | The DSH HMR service is not available in this profile. | `tower_reload` / `/tower reload` on a profile without HMR |
|
|
37
|
+
| `reload-failed` | The HMR reload failed. | `reconcileProfile` threw; check the DSH log and restart |
|
|
38
|
+
| `tests-failed` | Declared test discovery failed or did not meet admission requirements. | nonzero command, malformed output, minCount/required shortfall |
|
|
39
|
+
| `tests-timeout` | Test discovery exceeded its time or output budget. | `tests.timeoutMs`, or stdout over `tests.maxBytes` |
|
|
40
|
+
| `lease-busy` | Another holder owns the requested advisory lease. | `tower_resource acquire` while `heavy-ci` is held |
|
|
41
|
+
| `lease-token` | The lease release token does not match the holder. | releasing with another session's token |
|
|
42
|
+
| `batch-invalid` | A batch request or its close evidence is invalid. | unknown member, duplicate id, unsafe receipt path, missing receipt hash |
|
|
43
|
+
| `legacy-invalid` | The legacy snapshot or mapping is invalid. | unknown schema, source inside the Tower state dir, mapping rewrite |
|
|
44
|
+
| `tool-internal` | An unexpected failure. | a bug; read the message and the activity log |
|
|
45
|
+
|
|
46
|
+
## Why thrown?
|
|
47
|
+
|
|
48
|
+
Returned `{ok:false}` shapes are reserved for expected policy outcomes that the tower decides on
|
|
49
|
+
(`tower_merge`/`tower_rebase` gate blockers and `tower_preflight`). Anything that prevents the tool
|
|
50
|
+
from producing a decision is thrown so the model does not mistake it for a normal negative result.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Tower events
|
|
2
|
+
|
|
3
|
+
Tower emits process-local Cordis events after successful tool calls (mutations and read-only tools), so
|
|
4
|
+
other plugins can observe a repository without polling. Events are **not** sent over the network and carry
|
|
5
|
+
no telemetry.
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
ctx.on('tower/merge', (payload) => {
|
|
9
|
+
// payload.tool, payload.repoRoot, payload.value (the tool's JSON result)
|
|
10
|
+
})
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
| Event | Emitted after |
|
|
14
|
+
|---|---|
|
|
15
|
+
| `tower/init` | `tower_init` created or re-anchored state |
|
|
16
|
+
| `tower/plan` | `tower_plan` created missions |
|
|
17
|
+
| `tower/mission` | `tower_mission` changed one mission |
|
|
18
|
+
| `tower/spawn` | `tower_spawn` recorded a worker/reviewer |
|
|
19
|
+
| `tower/complete` | `tower_complete` recorded a completion report |
|
|
20
|
+
| `tower/review` | `tower_review` recorded a verdict |
|
|
21
|
+
| `tower/merge` | `tower_merge` returned (including gate failures; inspect `value.ok`) |
|
|
22
|
+
| `tower/rebase` | `tower_rebase` returned |
|
|
23
|
+
| `tower/teardown` | `tower_teardown` removed worktrees |
|
|
24
|
+
| `tower/finding` | `tower_finding` created one finding |
|
|
25
|
+
| `tower/findings` | `tower_findings` read/listed/updated findings |
|
|
26
|
+
| `tower/send` | `tower_send` persisted a message |
|
|
27
|
+
| `tower/inbox` | `tower_inbox` acknowledged messages |
|
|
28
|
+
| `tower/interrupt` | `tower_interrupt` stopped a live agent |
|
|
29
|
+
| `tower/diff` | `tower_diff` read a mission diff |
|
|
30
|
+
| `tower/adopt` | `tower_adopt` reconciled the roster |
|
|
31
|
+
| `tower/roster` | `tower_roster` read the roster |
|
|
32
|
+
| `tower/status` | `tower_status` read the dashboard |
|
|
33
|
+
| `tower/preflight` | `tower_preflight` evaluated the gate |
|
|
34
|
+
| `tower/doctor` | `tower_doctor` completed its read-only checks |
|
|
35
|
+
| `tower/test` | `tower_test` ran discovery |
|
|
36
|
+
| `tower/batch` | `tower_batch` created, inspected or closed a batch |
|
|
37
|
+
| `tower/resource` | `tower_resource` acquired/released/inspected leases |
|
|
38
|
+
| `tower/import_legacy` | `tower_import_legacy` stored a legacy snapshot |
|
|
39
|
+
| `tower/legacy_map` | `tower_legacy_map` mapped or listed legacy ids |
|
|
40
|
+
|
|
41
|
+
`tower_mode`, `tower_control` and `tower_reload` do not emit Tower events. Payloads are JSON:
|
|
42
|
+
`{tool, repoRoot, value}`. Listener exceptions never affect the tool result.
|
|
43
|
+
|
|
44
|
+
For a durable audit trail use `<git-common-dir>/dsh-tower/activity.jsonl` and `MISSIONS.md` instead;
|
|
45
|
+
events are process-local and are not replayed.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Batches, leases and legacy import
|
|
2
|
+
|
|
3
|
+
## Evidence batches
|
|
4
|
+
|
|
5
|
+
`tower_batch` groups finite mission completion evidence.
|
|
6
|
+
|
|
7
|
+
- `create` freezes `missionIds`, `exclusions`, `requiredChecks` (default `["check"]`) and exact
|
|
8
|
+
relative `receiptPaths`. Members must be known missions and only paused legacy missions may be
|
|
9
|
+
excluded; membership is immutable after create.
|
|
10
|
+
- `status` summarizes members and pending/failed checks.
|
|
11
|
+
- `close` verifies every required check for completed, **merged**, or abandoned members (from
|
|
12
|
+
`completionReport.checks`, `testRuns`, or close-time `checks`), checks `treeTip` when provided, and
|
|
13
|
+
requires every frozen receipt path to be supplied in `receiptHashes`/`receipts` (or bound to a
|
|
14
|
+
passing check with `receiptHash`). Missing evidence returns `{ok:false, blockers}`; nothing is
|
|
15
|
+
deleted.
|
|
16
|
+
- `abandon` retires a stale open batch (`batchId`, optional `reason`) without touching mission state;
|
|
17
|
+
it is the escape hatch when the evidence window has passed (for example after merging before close).
|
|
18
|
+
|
|
19
|
+
A failed close is not a partial close: the batch stays `open` and can be retried after evidence is
|
|
20
|
+
fixed.
|
|
21
|
+
|
|
22
|
+
## Advisory leases
|
|
23
|
+
|
|
24
|
+
`tower_resource` manages per-repository leases in `<git-common-dir>/dsh-tower/leases.json`:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
tower_resource({action:"acquire", name:"heavy-ci", ttlMs:900000})
|
|
28
|
+
tower_resource({action:"status"})
|
|
29
|
+
tower_resource({action:"release", name:"heavy-ci", token:"<token from acquire>"})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- acquire is tower-only; the caller gets a token, pid, holder, created/expiry timestamps;
|
|
33
|
+
- the same token renews; another holder gets `[tower:lease-busy]`;
|
|
34
|
+
- release requires the token; an **expired** lease still requires the token and explicit `force:true`
|
|
35
|
+
(no silent takeover);
|
|
36
|
+
- `spawn.requireLease` makes a worker spawn fail unless that lease is held.
|
|
37
|
+
|
|
38
|
+
Leases coordinate local jobs and CI windows. They are **not** an OS CPU/memory hard cap: DSH has no
|
|
39
|
+
public Job Object quota API, so Tower cannot enforce per-process resource limits; use the live-worker
|
|
40
|
+
cap and your OS/CI scheduler for those.
|
|
41
|
+
|
|
42
|
+
## Legacy import and mapping
|
|
43
|
+
|
|
44
|
+
`tower_import_legacy({repoRoot,sourcePath})` accepts a Tower Codex `schemaVersion:1` state file or a
|
|
45
|
+
DSH legacy state. It:
|
|
46
|
+
|
|
47
|
+
- requires an absolute source path outside `<git-common-dir>/dsh-tower`;
|
|
48
|
+
- validates the schema (16 MiB cap), stores the raw payload byte-for-byte under
|
|
49
|
+
`<git-common-dir>/dsh-tower/legacy/<sha256>.json`, and records only a summary in
|
|
50
|
+
`state.legacySnapshots`;
|
|
51
|
+
- never activates, adopts, or resumes paused missions.
|
|
52
|
+
|
|
53
|
+
`tower_legacy_map` records an audit-only `sourceHash + oldId → newMissionId?` mapping. Mappings are
|
|
54
|
+
append-only; rewriting an existing mapping to another mission is rejected. Mapping does not change
|
|
55
|
+
mission state.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Testing, discovery and evidence
|
|
2
|
+
|
|
3
|
+
Tower 2.1 can execute a repository's declared test discovery and turn its result into durable
|
|
4
|
+
completion evidence. Discovery is **opt-in by configuration**: a worktree with no
|
|
5
|
+
`package.json.tower.testDiscovery` block behaves exactly as before.
|
|
6
|
+
|
|
7
|
+
## Configuration
|
|
8
|
+
|
|
9
|
+
`package.json` (Tower Codex-compatible):
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"tower": {
|
|
14
|
+
"testDiscovery": {
|
|
15
|
+
"version": 1,
|
|
16
|
+
"commands": [
|
|
17
|
+
{
|
|
18
|
+
"id": "unit",
|
|
19
|
+
"command": "node --test dist/tests/*.test.js",
|
|
20
|
+
"format": "node-tap",
|
|
21
|
+
"minCount": 1,
|
|
22
|
+
"required": ["smoke"]
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
| Field | Meaning |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `id` | Unique, `[A-Za-z0-9][A-Za-z0-9._-]{0,63}`; also used in diagnostic file names. |
|
|
33
|
+
| `command` | Shell command executed with the worktree as cwd (Windows `pwsh`, POSIX `bash`). |
|
|
34
|
+
| `format` | `node-tap` (TAP `ok N - name` / `not ok`) or `json-array` (JSON array of `{name, ok?}`). |
|
|
35
|
+
| `minCount` | Minimum discovered tests for this command (default 1). |
|
|
36
|
+
| `required` | Test names that must appear and pass. |
|
|
37
|
+
|
|
38
|
+
`tests.*` in the Tower config controls admission, timeout, output cap and whether package discovery
|
|
39
|
+
is allowed. `tests.admission` is `spawn` (before a worker starts; fail-closed, no child), `complete`
|
|
40
|
+
(at `tower_complete`; default), or `off` (explicit `tower_test` only).
|
|
41
|
+
|
|
42
|
+
## Receipts and gates
|
|
43
|
+
|
|
44
|
+
Each run stores a receipt under `<git-common-dir>/dsh-tower/test-runs/<mission>-<stamp>/` with
|
|
45
|
+
stdout/stderr files, SHA-256 hashes, exit codes, counts, required names, the worktree tip, and an
|
|
46
|
+
overall `ok`. `state.missions[].testRuns` keeps the most recent 50 receipts. The tool returns
|
|
47
|
+
`ok:false` with diagnostics on failure; `tower_complete` throws `[tower:tests-failed]` when automatic
|
|
48
|
+
discovery fails.
|
|
49
|
+
|
|
50
|
+
- `tower_test({repoRoot,missionId})` runs discovery on demand and records a receipt.
|
|
51
|
+
- `tower_complete` adds a `tests` check when `tests.autoChecks` is on.
|
|
52
|
+
- `gates.requireChecks` requires any completion check; `gates.requireTests` requires a passing receipt
|
|
53
|
+
for the reviewed tip (`tests-missing`).
|
|
54
|
+
|
|
55
|
+
## Trust boundary
|
|
56
|
+
|
|
57
|
+
Discovery commands are repository-controlled code. `tests.allowPackageDiscovery:false` disables the
|
|
58
|
+
package block; a CI or policy profile should set it when cloning untrusted repositories. The command
|
|
59
|
+
runs with the same OS permissions as DSH, in the mission worktree, with no network access added by
|
|
60
|
+
Tower. Output is capped at `tests.maxBytes` (16 MiB default) and each command at `tests.timeoutMs`
|
|
61
|
+
(60 s default); over-budget runs fail closed.
|
package/docs/reference/tools.md
CHANGED
|
@@ -1,33 +1,75 @@
|
|
|
1
1
|
# Tools reference
|
|
2
2
|
|
|
3
3
|
All tools take `repoRoot` (an absolute path inside the target Git repository) and return JSON.
|
|
4
|
-
The
|
|
5
|
-
`mode.allowAgentControl` is enabled (the bundled patch enables it)
|
|
4
|
+
The build exposes up to 28 tools: 19 core repository tools below (including `tower_interrupt`),
|
|
5
|
+
`tower_mode`, `tower_control` when `mode.allowAgentControl` is enabled (the bundled patch enables it),
|
|
6
|
+
`tower_reload` while `dev.hotReload` is on, and the 2.1 verification/ops tools `tower_doctor`,
|
|
7
|
+
`tower_test`, `tower_batch`, `tower_resource`, `tower_import_legacy`, `tower_legacy_map`.
|
|
8
|
+
|
|
9
|
+
`tower_mission` uses `id` (alias `missionId`); every other mission-scoped tool uses `missionId`
|
|
10
|
+
(alias `id`). Other input aliases: `task_done`/`taskDone`, `task_drop`/`taskDrop`,
|
|
11
|
+
`task_drop_reason`/`taskDropReason`, `clear_blockers`/`clearBlockers`,
|
|
12
|
+
`include_read`/`includeRead`, `dry_run`/`dryRun`, `timeoutMs`/`timeout_ms`,
|
|
13
|
+
`waitMs`/`wait_ms`, `mission_id`/`missionId` on findings, `agent_id`/`agentId` on interrupt,
|
|
14
|
+
`include_gate`/`includeGate` on status, `retire_missing`/`retireMissing` on adopt. Outputs use
|
|
15
|
+
canonical camelCase names.
|
|
16
|
+
|
|
17
|
+
## Roles
|
|
18
|
+
|
|
19
|
+
Roster roles are resolved from `exec.agent` + the roster. Mission-scoped tools (`tower_interrupt`,
|
|
20
|
+
`tower_init`, `tower_plan`, `tower_spawn`, `tower_merge`, `tower_rebase`, `tower_teardown`,
|
|
21
|
+
`tower_adopt`, `tower_reload`) are **tower only**. `tower_batch` create/close/abandon, `tower_resource`
|
|
22
|
+
acquire/release, `tower_import_legacy`, `tower_legacy_map` map and review-exemption planning are
|
|
23
|
+
tower-only; their read-only status actions are open to roster roles. A worker may call `tower_mission`
|
|
24
|
+
only for `task_done`/`task_drop`/`blocker`/`note`; status changes, scope widening, `clear_blockers` and
|
|
25
|
+
`completed` are tower-only (completion must go through `tower_complete`). A roster reviewer may read
|
|
26
|
+
findings but not mutate them. Violations throw `[tower:not-authorized]` or
|
|
27
|
+
`[tower:invalid-transition]`.
|
|
28
|
+
|
|
29
|
+
## Tools
|
|
6
30
|
|
|
7
31
|
| Tool | Parameters | Purpose / notes |
|
|
8
32
|
|---|---|---|
|
|
9
|
-
| `tower_init` | `base?` | Create
|
|
10
|
-
| `tower_plan` | `missions[]` (`title`, `scope[]`, `tasks[]?`, `deps[]?`, `kind?`, `context?`) | Create missions `M1..`; overlapping build scopes auto-add a dependency; rejects unknown deps and cycles. |
|
|
11
|
-
| `tower_mission` | `id
|
|
12
|
-
| `tower_status` |
|
|
13
|
-
| `tower_spawn` | `missionId
|
|
14
|
-
| `tower_roster` | — | Roster with live activity (`running`/`inactive`/`missing`/`unknown`) from the subagent catalog. Read-only. |
|
|
15
|
-
| `tower_adopt` |
|
|
16
|
-
| `tower_diff` | `missionId
|
|
17
|
-
| `tower_send` | `to`, `subject`, `body`, `scope?` | Durable message to a roster name, `tower`, or `all`; delivers live to a running agent. |
|
|
18
|
-
| `tower_inbox` | `
|
|
19
|
-
| `tower_complete` | `missionId
|
|
20
|
-
| `
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
23
|
-
| `
|
|
24
|
-
| `
|
|
25
|
-
| `
|
|
26
|
-
| `
|
|
33
|
+
| `tower_init` | `base?`, `autoGitInit?`, `snapshotDirty?`, `reanchor?` | Create `<git-common-dir>/dsh-tower/state.json`. `autoGitInit` runs `git init` + empty initial commit; `snapshotDirty` records a dangling snapshot commit of uncommitted tracked changes used as the mission baseline; `reanchor` changes base only when no non-terminal mission exists. Returns `dirty`, `snapshotCommit`, `reanchored`. |
|
|
34
|
+
| `tower_plan` | `missions[]` (`title`, `scope[]`, `tasks[]?`, `deps[]?`, `kind?`, `context?`, `references[]?` ≤20, `reviewPolicy?`, `reviewExemptionReason?`) | Create missions `M1..`; overlapping build scopes auto-add a dependency; rejects unknown deps and cycles. `reviewPolicy:"none"` requires a reason and `gates.allowReviewExemption`. |
|
|
35
|
+
| `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`. |
|
|
36
|
+
| `tower_status` | `missionId?`, `offset?`, `limit?`, `includeGate?`, `format?` | Dashboard by default. `missionId` returns full detail (tasks/notes/reviews/findings/completionReport). `offset`/`limit` page missions (default 20, max 100), `includeGate` adds gate digests, `format:"markdown"` returns the board. |
|
|
37
|
+
| `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. |
|
|
38
|
+
| `tower_roster` | — | Roster with live activity (`running`/`inactive`/`missing`/`unknown`) and `stale` flags from the subagent catalog. Read-only. |
|
|
39
|
+
| `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. |
|
|
40
|
+
| `tower_diff` | `missionId` (alias `id`), `maxBytes?` | Read-only merge-base diff: files, commits, capped patch. Safe for reviewers. |
|
|
41
|
+
| `tower_send` | `to`, `subject`, `body`, `scope?`, `interrupt?`, `consentRef?` | Durable message to a roster name, `tower`, or `all`; delivers live to a running agent. `interrupt:true` interrupts the running turn first (Kimi-style), then delivers; `consentRef` is recorded for audit. Rate-limited by `send.maxPerMinute`. |
|
|
42
|
+
| `tower_inbox` | `limit?`, `include_read?` | Read/ack messages addressed to the caller; unread messages block `tower_complete`. |
|
|
43
|
+
| `tower_complete` | `missionId` (alias `id`), `report`, `checks?` | Worker reports completion (mission becomes `completed`, awaiting review). Requires current owner, no open tasks/blockers, ≥1 commit, no unread inbox. `checks` records `{name, command?, exitCode?, evidence?}` evidence; `gates.requireChecks` can demand it. When configured, test discovery runs automatically and adds a `tests` check; failure throws `[tower:tests-failed]`. |
|
|
44
|
+
| `tower_interrupt` | `to?` (roster name), `agentId?`, `reason?` | Interrupt one running roster agent via `subagents.interrupt`, record `state:"interrupted"`. Idempotent (not running → `interrupted:false`). |
|
|
45
|
+
| `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`. |
|
|
46
|
+
| `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. |
|
|
47
|
+
| `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). |
|
|
48
|
+
| `tower_preflight` | `missionId` (alias `id`) | Read-only gate: returns `{ok, blockers[], branchTip, baseTip, changedFiles, review}`. |
|
|
49
|
+
| `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`. |
|
|
50
|
+
| `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. |
|
|
51
|
+
| `tower_teardown` | `force?`, `exclude?`, `dry_run?` (alias `dryRun`) | Remove eligible merged/abandoned worktrees and branches; running agents are always kept. |
|
|
52
|
+
| `tower_mode` | — | Report mode, last change, paused goal, denied tools, store path, plugin version, HMR availability, workspace-lock holder. |
|
|
27
53
|
| `tower_control` | `action` (`enter`/`exit`), `reason` | Model-initiated mode change; only when `mode.allowAgentControl` is true; reason is mandatory. |
|
|
54
|
+
| `tower_reload` | `repoRoot?` | Dev-only: ask DSH HMR to reconcile the profile and reload the Host plugin from disk. Registered while `dev.hotReload` is on; scheduled after the result (default 50 ms); fails with `reload-unavailable` without HMR. When `repoRoot` is supplied the caller must be the tower. |
|
|
55
|
+
| `tower_doctor` | — (takes `repoRoot`) | Read-only health contract: git, state schema, config, presets/subagents/HMR, workspace lock, roster, worktree realpath/ownership, test config, leases. Returns `{ok, checks[{id,status,detail}], environmentContract}`. Never writes. |
|
|
56
|
+
| `tower_test` | `missionId` (alias `id`) | Run the worktree's `package.json` `tower.testDiscovery` and record a receipt; `ok:false` on failure. Use `tower_complete` for automatic admission checks. |
|
|
57
|
+
| `tower_batch` | `action` (`create`/`status`/`close`/`abandon`), `missionIds?`, `exclusions?`, `requiredChecks?`, `receiptPaths?`, `batchId?`, `checks?`, `treeTip?`, `receiptHashes?`, `reason?` | Finite evidence batch. Create freezes members/checks/receipts; close verifies every required check and receipt hash; merged members are eligible; abandon retires a stale open batch without deleting missions. Membership is immutable. |
|
|
58
|
+
| `tower_resource` | `action` (`acquire`/`release`/`status`), `name?`, `holder?`, `token?`, `ttlMs?`, `force?` | Advisory per-repository lease in `<common>/dsh-tower/leases.json`. No OS CPU/memory hard cap; expired leases require explicit `force` and the correct token. |
|
|
59
|
+
| `tower_import_legacy` | `sourcePath` | Read-only import of a Tower Codex `schemaVersion:1` or DSH legacy state. Full payload goes under `<common>/dsh-tower/legacy/<sha256>.json`; state stores a summary only. Never activates/adopts/resumes paused missions. |
|
|
60
|
+
| `tower_legacy_map` | `action` (`map`/`status`), `sourceHash?`, `oldId?`, `newMissionId?` | Audit-only legacy-id mapping; mappings are append-only and never adopt a mission. |
|
|
61
|
+
|
|
62
|
+
## Workspace lock
|
|
63
|
+
|
|
64
|
+
With `mode.workspaceLock:true` (the bundled patch enables it), the first repo-scoped Tower tool call
|
|
65
|
+
from a Tower-mode session acquires `<git-common-dir>/dsh-tower/tower.lock`; another session gets
|
|
66
|
+
`[tower:workspace-busy]` until the holder runs `/tower off` or the lock exceeds
|
|
67
|
+
`mode.workspaceStaleMs`. `mode.workspaceLockScope:"mutations"` skips the lock for read-only tools.
|
|
68
|
+
Code default is off; the shipped patch is on for Kimi-compatible single-active-tower behavior.
|
|
28
69
|
|
|
29
70
|
## Failure results
|
|
30
71
|
|
|
31
|
-
Gate tools return `{ok:false, blockers:[{code, detail}]}
|
|
32
|
-
[blockers.md](blockers.md).
|
|
33
|
-
|
|
72
|
+
Gate tools return `{ok:false, blockers:[{code, detail}]}`; the code list is in
|
|
73
|
+
[blockers.md](blockers.md). Thrown tool errors carry a stable `[tower:<code>]` prefix
|
|
74
|
+
([errors.md](errors.md)). Successful mutations emit process-local events ([events.md](events.md)),
|
|
75
|
+
and, with `docs.board:true`, refresh `<git-common-dir>/dsh-tower/MISSIONS.md`.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# dsh-tower 中文文档
|
|
2
|
+
|
|
3
|
+
[English docs](../README.md) | **简体中文**
|
|
4
|
+
|
|
5
|
+
英文文档是权威来源;本页是中文翻译入口。英文文档位于 [docs/](../README.md),仓库主页见
|
|
6
|
+
[README.md](../../README.md)。
|
|
7
|
+
|
|
8
|
+
## 2.1 能力概览
|
|
9
|
+
|
|
10
|
+
- **只读健康检查**:[Doctor](reference/doctor.md)(`tower_doctor`)检查 git、state、配置、preset、
|
|
11
|
+
workspace 锁、roster、worktree 归属、测试策略与租约,不写任何状态。
|
|
12
|
+
- **测试发现与完成证据**:[测试、发现与证据](reference/testing.md)。仓库可在
|
|
13
|
+
`package.json.tower.testDiscovery` 声明发现命令;回执可自动附加到 `tower_complete`,
|
|
14
|
+
`gates.requireTests` 可要求针对被审查 tip 的通过回执。
|
|
15
|
+
- **证据批次、咨询式租约、旧版导入**:[批次、租约与旧版导入](reference/operations.md)
|
|
16
|
+
(`tower_batch`、`tower_resource`、`tower_import_legacy`、`tower_legacy_map`)。
|
|
17
|
+
- **workspace 锁与计划模式**:`mode.workspaceLock` 限制每个仓库同时只有一个 Tower 会话,
|
|
18
|
+
`mode.workspaceLockScope:"mutations"` 对只读工具跳过锁;`mode.planModePolicy` 控制进入 Tower
|
|
19
|
+
时如何处理活跃的 plan mode。
|
|
20
|
+
- **可观察性**:成功的工具调用发出进程内 [Tower 事件](reference/events.md);稳定
|
|
21
|
+
[工具错误码](reference/errors.md) 与 [blocker code](reference/blockers.md) 可被程序匹配。
|
|
22
|
+
- **工具面**:本构建最多 28 个工具(含可选的 `tower_control` 与 `tower_reload`);详见
|
|
23
|
+
[工具参考](reference/tools.md)。
|
|
24
|
+
|
|
25
|
+
## 选择阅读路径
|
|
26
|
+
|
|
27
|
+
| 你是 | 从这里开始 |
|
|
28
|
+
|---|---|
|
|
29
|
+
| 新用户 | [什么时候用 Tower](guide/scenarios-and-philosophy.md) → [快速开始](guide/quickstart.md) → [工具参考](reference/tools.md) → [第一个 mission 示例(英文)](../examples/first-mission.md) |
|
|
30
|
+
| 正在选择工作流 | [Tower 与 Agent Teams、Ralph、Workflow、普通并行子代理的区别](guide/scenarios-and-philosophy.md) |
|
|
31
|
+
| 运维 | [运维 runbook(英文)](../operations/runbook.md) → [blocker 与失败码](reference/blockers.md) → [错误码](reference/errors.md) → [事件](reference/events.md) → [Doctor](reference/doctor.md) → [测试](reference/testing.md) → [批次/租约/旧版](reference/operations.md) → [安全模型](operations/security.md) |
|
|
32
|
+
| 维护者 | [架构与状态机(英文)](../architecture/overview.md) → [配置参考](reference/config.md) → [热重载](guide/hot-reload.md) → [贡献指南](../../CONTRIBUTING.md) |
|
|
33
|
+
|
|
34
|
+
参考页是当前发行版的权威说明;CI 中的 `npm run docs:check` 会校验文档与实现一致(包括中文页)。
|
|
35
|
+
|
|
36
|
+
## 全部中文页面
|
|
37
|
+
|
|
38
|
+
- [快速开始](guide/quickstart.md)
|
|
39
|
+
- [什么时候用 Tower,与 Agent Teams / Ralph / Workflow / 并行子代理的区别](guide/scenarios-and-philosophy.md)
|
|
40
|
+
- [安装、升级与迁移](guide/install-upgrade-migration.md)
|
|
41
|
+
- [热重载(开发)](guide/hot-reload.md)
|
|
42
|
+
- [工具参考](reference/tools.md)
|
|
43
|
+
- [配置参考](reference/config.md)
|
|
44
|
+
- [blocker 与失败码](reference/blockers.md)
|
|
45
|
+
- [工具错误码](reference/errors.md)
|
|
46
|
+
- [Tower 事件](reference/events.md)
|
|
47
|
+
- [测试、发现与证据](reference/testing.md)
|
|
48
|
+
- [批次、租约与旧版导入](reference/operations.md)
|
|
49
|
+
- [Doctor](reference/doctor.md)
|
|
50
|
+
- [FAQ](faq.md)
|
|
51
|
+
- [安全模型](operations/security.md)
|
|
52
|
+
|
|
53
|
+
以下页面目前只有英文版:[架构与状态机](../architecture/overview.md)、
|
|
54
|
+
[运维 runbook](../operations/runbook.md)、[示例:第一个 mission](../examples/first-mission.md)。
|
|
55
|
+
|
|
56
|
+
## 语言 / Language
|
|
57
|
+
|
|
58
|
+
- [English docs](../README.md)
|
|
59
|
+
- **中文文档**(本页)
|
|
60
|
+
- [仓库主页 README(中文)](../../README.md) · [English README](../../README.en.md)
|