dsh-tower 2.4.2 → 2.5.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.
Files changed (76) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/COMPATIBILITY.md +1 -0
  3. package/CONTRIBUTING.md +5 -3
  4. package/GLOSSARY.md +67 -0
  5. package/README.md +6 -0
  6. package/app/archive.js +16 -1
  7. package/app/board.js +16 -1
  8. package/app/gate.js +14 -0
  9. package/app/spawn-prechecks.js +18 -3
  10. package/cordis.patch.yml +21 -6
  11. package/docs/adr/0004-surface-budget.md +10 -4
  12. package/docs/adr/0005-component-surface.md +166 -0
  13. package/docs/guide/install-upgrade-migration.md +21 -0
  14. package/docs/guide/quickstart.md +71 -0
  15. package/docs/guide/release.md +60 -19
  16. package/docs/reference/component-surface.md +27 -15
  17. package/docs/reference/config.generated.md +4 -7
  18. package/docs/reference/config.md +7 -5
  19. package/docs/reference/doctor.md +11 -5
  20. package/docs/reference/surface-budget.md +29 -11
  21. package/docs/reference/tools.generated.md +1 -1
  22. package/docs/reference/tools.md +2 -2
  23. package/docs/zh/guide/install-upgrade-migration.md +1 -1
  24. package/docs/zh/reference/config.md +7 -5
  25. package/docs/zh/reference/doctor.md +7 -2
  26. package/docs/zh/reference/tools.md +3 -2
  27. package/domain/component-rules.js +216 -0
  28. package/domain/components.js +169 -49
  29. package/domain/config/schema.js +46 -23
  30. package/domain/gate.js +17 -2
  31. package/domain/scope.js +176 -5
  32. package/domain/surface.js +21 -7
  33. package/host/capability-archive.js +18 -0
  34. package/host/capability-board.js +18 -0
  35. package/host/capability-registry.js +4 -0
  36. package/host/doctor.js +50 -5
  37. package/host/presets.js +17 -0
  38. package/host/tool-registry.js +21 -4
  39. package/index.js +17 -6
  40. package/locale/archive/en.json +6 -0
  41. package/locale/archive/zh.json +6 -0
  42. package/locale/batch/en.json +1 -1
  43. package/locale/batch/zh.json +1 -1
  44. package/locale/board/en.json +6 -0
  45. package/locale/board/zh.json +6 -0
  46. package/locale/en.json +37 -22
  47. package/locale/hmr/en.json +2 -2
  48. package/locale/hmr/zh.json +1 -1
  49. package/locale/import/en.json +1 -1
  50. package/locale/import/zh.json +1 -1
  51. package/locale/leases/en.json +2 -2
  52. package/locale/leases/zh.json +2 -2
  53. package/locale/preset-reviewer/en.json +1 -1
  54. package/locale/preset-reviewer/zh.json +1 -1
  55. package/locale/preset-worker/en.json +1 -1
  56. package/locale/preset-worker/zh.json +1 -1
  57. package/locale/skills/en.json +1 -1
  58. package/locale/skills/zh.json +1 -1
  59. package/locale/tests/en.json +2 -2
  60. package/locale/tests/zh.json +2 -2
  61. package/locale/zh.json +36 -21
  62. package/package.json +11 -2
  63. package/scripts/check-components.mjs +582 -42
  64. package/scripts/component-surface.json +85 -27
  65. package/scripts/generate-capability-locale.mjs +3 -0
  66. package/scripts/mount-smoke/surface.mjs +2 -0
  67. package/scripts/pack-manifest.txt +9 -0
  68. package/scripts/release-notes.mjs +256 -0
  69. package/scripts/surface-baseline.json +32 -3
  70. package/scripts/surface-baseline.mjs +15 -5
  71. package/skills.js +4 -1
  72. package/tools/complete.js +3 -1
  73. package/tools/spawn.js +5 -5
  74. package/tools/test.js +7 -7
  75. package/ui-bundle/locale/en.json +1 -1
  76. package/ui-bundle/locale/zh.json +1 -1
@@ -378,7 +378,11 @@ async function ensureRepository(repoRootInput, autoGitInit) {
378
378
  }
379
379
  }
380
380
 
381
- const OPERATIONAL_TOOLS = new Map()
381
+ // #138: exported so `scripts/check-components.mjs` can import the route table
382
+ // instead of scraping this file. The table is empty since #122; an empty Map is
383
+ // the determined state, while a missing export or a failed import is a gate
384
+ // failure.
385
+ export const OPERATIONAL_TOOLS = new Map()
382
386
 
383
387
  function plainSchema(value) {
384
388
  return JSON.parse(JSON.stringify(value))
@@ -473,8 +477,11 @@ async function runMissionDiscovery(tower, mission) {
473
477
  return { configured: false, disabledBy: 'tower-tests', reason: disabledReason('tower-tests') }
474
478
  }
475
479
  const testsConfig = tower.config.tests ?? {}
476
- if (testsConfig.enabled === false || testsConfig.allowPackageDiscovery === false) {
477
- return { configured: false }
480
+ // #136: there is no second switch. The `tower-tests` row decided above; the
481
+ // only remaining reason to skip discovery is an explicit opt-out of repository
482
+ // package discovery.
483
+ if (testsConfig.allowPackageDiscovery === false) {
484
+ return { configured: false, error: 'test discovery is disabled by tests.allowPackageDiscovery:false' }
478
485
  }
479
486
  const worktreePath = mission?.worktree?.path
480
487
  if (!worktreePath) return { configured: false, error: 'mission has no worktree' }
@@ -565,6 +572,14 @@ export function registerCoreTowerTools(ctx, options = {}) {
565
572
  const baseDeps = options.deps ? assertPorts(options.deps) : (runtimeState.deps ?? createDefaultDeps())
566
573
  runtimeState.deps = {
567
574
  ...baseDeps,
575
+ // #140: the merge gate lives in the pure domain, which cannot read the
576
+ // component registry. Publish the two probes it needs on the port bag the
577
+ // store already receives, so `evaluateGate` can name a disabled row as the
578
+ // cause instead of guessing from config.
579
+ components: {
580
+ enabled: (id) => componentEnabled(id),
581
+ reason: (id) => disabledReason(id),
582
+ },
568
583
  events: {
569
584
  emit(name, payload) {
570
585
  try {
@@ -615,7 +630,9 @@ export function registerCoreTowerTools(ctx, options = {}) {
615
630
 
616
631
  registerStatusTool(ctx, { openTower, define, workspaceHook: runtimeState.workspaceHook, spawnBackoffView, observeActivity, componentReport })
617
632
 
618
- registerSpawnTool(ctx, { openTower, define, actorFor, requireTowerActor, enqueueSpawn, observeActivity, spawnBackoffState, recordSpawnThrottle, recordSpawnSuccess, runMissionDiscovery, textOf, inspectLeases })
633
+ // #131: the lease precondition needs the row state, and the app layer may not
634
+ // import the registry, so the probe travels with the other spawn deps.
635
+ registerSpawnTool(ctx, { openTower, define, actorFor, requireTowerActor, enqueueSpawn, observeActivity, spawnBackoffState, recordSpawnThrottle, recordSpawnSuccess, runMissionDiscovery, textOf, inspectLeases, leaseComponent: () => ({ enabled: componentEnabled('tower-leases'), reason: disabledReason('tower-leases') }) })
619
636
 
620
637
  registerRosterTool(ctx, { openTower, define })
621
638
 
package/index.js CHANGED
@@ -398,11 +398,15 @@ export function apply(ctx, rawConfig) {
398
398
  : () => {},
399
399
  )
400
400
 
401
- ctx.systemPrompt.section({
402
- name: 'tower:mode',
403
- order: 15000,
404
- text: (context) => (context && modeOn(agentKey(context.agent)) ? reminder : ''),
405
- })
401
+ // #139: same leak as the skills provider — the section belongs to the plugin
402
+ // lifetime, so registration goes through `ctx.effect`.
403
+ ctx.effect(() =>
404
+ ctx.systemPrompt.section({
405
+ name: 'tower:mode',
406
+ order: 15000,
407
+ text: (context) => (context && modeOn(agentKey(context.agent)) ? reminder : ''),
408
+ }),
409
+ )
406
410
 
407
411
  // Workspace-lock heartbeat; only sessions holding a lock do I/O.
408
412
  ctx.effect(() => {
@@ -583,7 +587,14 @@ export function apply(ctx, rawConfig) {
583
587
  }
584
588
  }
585
589
  const { active, message } = parsed
586
- if (active) await assertRuntimePreconditions(ctx, config)
590
+ // #142: preconditions guard the *transition* into Tower mode, not every
591
+ // `/tower` instruction. Re-validating on an already-active session meant a
592
+ // row disabled later in the session (tower-hmr ships off) blocked
593
+ // `/tower off` and ordinary forwarded text — the two commands a human
594
+ // needs precisely when something is broken. Spawn/plan/merge keep their own
595
+ // guards, so the capability checks still run before any real work.
596
+ const transition = active && !modeOn(key)
597
+ if (transition) await assertRuntimePreconditions(ctx, config)
587
598
  const outcome = active
588
599
  ? enterMode(ctx, key, agent, 'user', message || null)
589
600
  : await exitMode(key, 'user', message || null)
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "Mission archive",
4
+ "description": "Move finished missions and their linked records into the on-disk archive, so the live state file stops carrying their full history. When off: Finished missions stay in the live state file, so it keeps growing; merges and every other capability keep working, and nothing is deleted."
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "任务线归档",
4
+ "description": "把已结束的任务线及其关联记录移入磁盘归档,让当前状态文件不再承载它们的完整历史。关闭后:已结束的任务线继续留在当前状态文件中,文件会持续增大;合并与其他能力继续工作,且不会删除任何内容。"
5
+ }
6
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "Evidence batches",
4
- "description": "Group missions into finite evidence batches and close them against required checks and receipts. When off: tower_batch is not registered; missions, gates and merges are unaffected."
4
+ "description": "Collect a finite set of missions into a batch and close it only when every required check and evidence receipt is present. When off: Batch tools and their checks are unavailable; missions, merges and every other capability keep working."
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "证据批次",
4
- "description": "把 mission 归入有限证据批次,并按必需检查与回执关闭批次。关闭后:不再注册 tower_batch;mission、门禁与合并不受影响。"
4
+ "description": "把一组任务线收进一个批次,只有当所有必需检查与证据回执齐全时才允许关闭该批次(或结案)。关闭后:批次工具及其检查不可用;任务线、合并与其他能力继续工作。"
5
5
  }
6
6
  }
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "Mission board",
4
+ "description": "Write a plain-text board file (MISSIONS.md) beside the state so a person can read the mission list without calling a tool. When off: The board file is not written or refreshed, so an existing board goes stale; missions, merges and every other capability keep working."
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "任务线看板",
4
+ "description": "在状态文件旁写入纯文本看板文件(MISSIONS.md),让人无需调用工具就能阅读任务线列表。关闭后:不再写入或刷新看板文件,已有看板会过期;任务线、合并与其他能力继续工作。"
5
+ }
6
+ }
package/locale/en.json CHANGED
@@ -1,53 +1,68 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "Tower",
4
- "description": "Mission planning, isolated worktrees, worker/reviewer agents, and review-gated merges."
4
+ "description": "Plan and track missions, isolate each one in its own worktree, hand the work to worker and reviewer agents, and merge after review when review before merging is required. Off equals uninstalling Tower: no tools, presets or skills remain."
5
5
  },
6
6
  "components": {
7
7
  "tower": {
8
8
  "title": "Tower host",
9
- "summary": "Mission planning, worktree isolation, the mode guard, the health contract and the recovery escape.",
10
- "disables": "Turns off the mandatory host; this equals uninstalling Tower: no tools, presets or skills remain."
9
+ "summary": "The always-on core: mission planning and state, worktree isolation, Tower mode, the environment health check, and how to recover a stuck lock.",
10
+ "disables": "Off equals uninstalling Tower: no tools, presets or skills remain."
11
11
  },
12
12
  "tower-skills": {
13
13
  "title": "Tower skills",
14
- "summary": "Playbooks for worker/reviewer agents and recovery after a blocked merge.",
15
- "disables": "The three Tower skills leave the catalog; the worker/reviewer protocol sections and every mission tool keep working."
14
+ "summary": "Step-by-step playbooks for worker and reviewer agents, and a guide for getting unstuck when a merge is blocked.",
15
+ "disables": "The three Tower skills leave the catalog; the worker and reviewer protocol sections and every mission tool keep working."
16
16
  },
17
17
  "tower-batch": {
18
18
  "title": "Evidence batches",
19
- "summary": "Group missions into finite evidence batches and close them against required checks and receipts.",
20
- "disables": "tower_batch is not registered; missions, gates and merges are unaffected."
19
+ "summary": "Collect a finite set of missions into a batch and close it only when every required check and evidence receipt is present.",
20
+ "disables": "Batch tools and their checks are unavailable; missions, merges and every other capability keep working."
21
21
  },
22
22
  "tower-import": {
23
23
  "title": "Legacy import",
24
- "summary": "Import a Tower Codex legacy state file and audit its snapshot-to-mission mapping.",
25
- "disables": "tower_import_legacy and tower_legacy_map are not registered; new state is unaffected."
24
+ "summary": "Read a legacy Tower Codex state file (the earlier Tower state format) and show how each old snapshot maps to a mission.",
25
+ "disables": "The import tools are unavailable; current state and every other capability keep working."
26
26
  },
27
27
  "tower-leases": {
28
- "title": "Advisory leases",
29
- "summary": "Coordinate heavy per-repository work with advisory resource leases.",
30
- "disables": "tower_resource is not registered; nothing else depends on a lease."
28
+ "title": "Lease coordination",
29
+ "summary": "Coordination only: lets one agent claim a named piece of shared work (a lease) so two agents do not start the same job. A lease is a note other agents can read; it never blocks work by itself.",
30
+ "disables": "Lease tools are unavailable. A worker configured to require a lease cannot start: planning and entering Tower mode are refused with an explanation until that setting is cleared or this row is re-enabled. Everything else keeps working."
31
31
  },
32
32
  "tower-tests": {
33
- "title": "Test discovery",
34
- "summary": "Run the worktree's declared test discovery and record a receipt for the mission tip.",
35
- "disables": "tower_test is not registered and no receipt can be recorded; with gates.requireTests:true planning/mode entry is rejected with an explanation."
33
+ "title": "Test evidence",
34
+ "summary": "Run the project's declared test command in a mission's worktree and record the result as evidence for merging.",
35
+ "disables": "No test command can be run and no evidence can be recorded. If tests are already required before merging, planning and entering Tower mode are refused with an explanation, and merges stay blocked for the missing test evidence until that requirement is cleared; nothing else changes."
36
+ },
37
+ "tower-board": {
38
+ "title": "Mission board",
39
+ "summary": "Write a plain-text board file (MISSIONS.md) beside the state so a person can read the mission list without calling a tool.",
40
+ "disables": "The board file is not written or refreshed, so an existing board goes stale; missions, merges and every other capability keep working."
41
+ },
42
+ "tower-archive": {
43
+ "title": "Mission archive",
44
+ "summary": "Move finished missions and their linked records into the on-disk archive, so the live state file stops carrying their full history.",
45
+ "disables": "Finished missions stay in the live state file, so it keeps growing; merges and every other capability keep working, and nothing is deleted."
36
46
  },
37
47
  "tower-hmr": {
38
- "title": "Dev hot reload",
39
- "summary": "Register tower_reload and /tower reload for linked-profile development.",
40
- "disables": "tower_reload and /tower reload are unavailable; a non-HMR profile behaves exactly as before. Shipped off."
48
+ "title": "Development hot reload",
49
+ "summary": "Development-only: reloads Tower in a linked development setup after a code change, so you do not have to restart DSH.",
50
+ "disables": "Nothing reloads automatically; restart the development setup by hand instead. A normal installation is unaffected, because this is developer tooling that ships off on purpose."
41
51
  },
42
52
  "preset-tower-worker": {
43
53
  "title": "Tower Worker preset",
44
- "summary": "Declares the Tower Worker preset: the mission protocol plus the filesystem, shell and Tower tools a worker runs inside its assigned worktree.",
45
- "disables": "tower_spawn cannot start a worker without it."
54
+ "summary": "The mandatory Tower Worker preset: the mission protocol plus the filesystem, shell and Tower tools a worker uses inside its own worktree.",
55
+ "disables": "Tower cannot plan missions, enter Tower mode, or start a worker without it."
46
56
  },
47
57
  "preset-tower-reviewer": {
48
58
  "title": "Tower Reviewer preset",
49
- "summary": "Declares the Tower Reviewer preset: read-only independent review that inspects the mission diff, verifies scope and acceptance, and returns a verdict.",
50
- "disables": "The reviewer cannot be dispatched. Supported while review.requireReview is false; with the gate on planning/mode entry is locked with an explanatory error."
59
+ "summary": "The independent Tower Reviewer preset: a read-only reviewer agent that reads the mission diff, checks scope and acceptance, and returns a verdict. Usable while review before merging is optional; a precondition for merging once review before merging is required.",
60
+ "disables": "The reviewer cannot be started. That is supported while review before merging is optional; once review before merging is required, planning and entering Tower mode are refused with an explanation."
61
+ },
62
+ "tower-ui": {
63
+ "title": "Tower UI",
64
+ "summary": "Adds Tower cards for tool results, a compact status summary above the message box, and a short status strip, in the web client.",
65
+ "disables": "The web interface piece is not loaded: no Tower cards, status summary or status strip. The Tower host, missions, state and the board keep working."
51
66
  }
52
67
  }
53
68
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
- "title": "Dev hot reload",
4
- "description": "Register tower_reload and /tower reload for linked-profile development. When off: tower_reload and /tower reload are unavailable; a non-HMR profile behaves exactly as before. Shipped off."
3
+ "title": "Development hot reload",
4
+ "description": "Development-only: reloads Tower in a linked development setup after a code change, so you do not have to restart DSH. When off: Nothing reloads automatically; restart the development setup by hand instead. A normal installation is unaffected, because this is developer tooling that ships off on purpose."
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "开发热重载",
4
- "description": "为联动开发 profile 注册 tower_reload 与 /tower reload。关闭后:tower_reload 与 /tower reload 不可用;非 HMR profile 的行为与之前完全相同。随包默认关闭。"
4
+ "description": "仅限开发人员:改动代码后,在联动开发配置中重新加载 Tower,无需重启 DSH。关闭后:不会自动重新加载,需要在开发配置中手动重启。普通安装不受影响:它是开发人员专用工具,默认关闭是有意为之。"
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "Legacy import",
4
- "description": "Import a Tower Codex legacy state file and audit its snapshot-to-mission mapping. When off: tower_import_legacy and tower_legacy_map are not registered; new state is unaffected."
4
+ "description": "Read a legacy Tower Codex state file (the earlier Tower state format) and show how each old snapshot maps to a mission. When off: The import tools are unavailable; current state and every other capability keep working."
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "旧版导入",
4
- "description": "导入 Tower Codex 旧状态文件,并审计快照到 mission 的映射。关闭后:不再注册 tower_import_legacy 与 tower_legacy_map;新状态不受影响。"
4
+ "description": "读取旧版 Tower Codex 状态文件(Tower 早期的状态格式),并显示每个旧快照对应哪一条任务线。关闭后:导入工具不可用;当前状态与其他能力继续工作。"
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
- "title": "Advisory leases",
4
- "description": "Coordinate heavy per-repository work with advisory resource leases. When off: tower_resource is not registered; nothing else depends on a lease."
3
+ "title": "Lease coordination",
4
+ "description": "Coordination only: lets one agent claim a named piece of shared work (a lease) so two agents do not start the same job. A lease is a note other agents can read; it never blocks work by itself. When off: Lease tools are unavailable. A worker configured to require a lease cannot start: planning and entering Tower mode are refused with an explanation until that setting is cleared or this row is re-enabled. Everything else keeps working."
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
- "title": "咨询式租约",
4
- "description": "用咨询式资源租约协调每个仓库中的重型工作。关闭后:不再注册 tower_resource;其他能力不依赖租约。"
3
+ "title": "租约协调",
4
+ "description": "只做协调:让一个代理认领某一具体工作(称为租约),避免两个代理同时开工。租约只是给其他代理看的说明,本身不会阻塞任何工作。关闭后:租约工具不可用。若某个执行代理被配置为必须先持有租约,它将无法启动:规划或进入 Tower 模式会被拒绝并给出解释,直到清除该设置或重新启用这一项。其他工作照常进行。"
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "Tower Reviewer preset",
4
- "description": "Declares the Tower Reviewer preset: read-only independent review that inspects the mission diff, verifies scope and acceptance, and returns a verdict. When off: The reviewer cannot be dispatched. Supported while review.requireReview is false; with the gate on planning/mode entry is locked with an explanatory error."
4
+ "description": "The independent Tower Reviewer preset: a read-only reviewer agent that reads the mission diff, checks scope and acceptance, and returns a verdict. Usable while review before merging is optional; a precondition for merging once review before merging is required. When off: The reviewer cannot be started. That is supported while review before merging is optional; once review before merging is required, planning and entering Tower mode are refused with an explanation."
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "Tower Reviewer 预设",
4
- "description": "声明 Tower Reviewer 预设:只读独立审查,检视任务差异、核对范围与验收,并返回结论。关闭后:无法派发审查代理。review.requireReview 为 false 时允许关闭;强制审查开启时规划/进入模式会被锁定并给出解释。"
4
+ "description": "独立的 Tower Reviewer 审查代理预设:一个只读代理,阅读任务线差异、核对范围与验收,并给出结论。在合并前审查仍为可选时可以使用;一旦把合并前审查设为必须,它就是合并的前置条件。关闭后:无法启动审查代理。在合并前审查仍为可选时,允许关闭这一项;一旦要求合并前必须审查,规划或进入 Tower 模式会被拒绝并给出解释。"
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "Tower Worker preset",
4
- "description": "Declares the Tower Worker preset: the mission protocol plus the filesystem, shell and Tower tools a worker runs inside its assigned worktree. Mandatory dependency, not a switch: tower_spawn cannot start a worker without it."
4
+ "description": "The mandatory Tower Worker preset: the mission protocol plus the filesystem, shell and Tower tools a worker uses inside its own worktree. Mandatory dependency, not a switch: Tower cannot plan missions, enter Tower mode, or start a worker without it."
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "Tower Worker 预设",
4
- "description": "声明 Tower Worker 预设:任务协议,以及执行代理在其工作树内使用的文件系统、终端与 Tower 工具。强制依赖,不是开关:缺少它 tower_spawn 无法启动执行代理。"
4
+ "description": "必需的 Tower Worker 执行代理预设:任务线协议,以及执行代理在其独立工作树中使用的文件系统、终端与 Tower 工具。强制依赖,不是开关:缺少它,Tower 无法规划任务线、进入 Tower 模式或启动执行代理。"
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "Tower skills",
4
- "description": "Playbooks for worker/reviewer agents and recovery after a blocked merge. When off: The three Tower skills leave the catalog; the worker/reviewer protocol sections and every mission tool keep working."
4
+ "description": "Step-by-step playbooks for worker and reviewer agents, and a guide for getting unstuck when a merge is blocked. When off: The three Tower skills leave the catalog; the worker and reviewer protocol sections and every mission tool keep working."
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "Tower 技能包",
4
- "description": "执行与审查代理的操作手册,以及失败后的恢复指南。关闭后:三个 Tower 技能从目录中移除;执行/审查协议段落与所有 mission 工具继续工作。"
4
+ "description": "执行代理与审查代理的分步操作手册,以及合并受阻时如何脱困的指南。关闭后:三个 Tower 技能从目录中移除;执行代理与审查代理的协议段落与所有任务线工具继续工作。"
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
- "title": "Test discovery",
4
- "description": "Run the worktree's declared test discovery and record a receipt for the mission tip. When off: tower_test is not registered and no receipt can be recorded; with gates.requireTests:true planning/mode entry is rejected with an explanation."
3
+ "title": "Test evidence",
4
+ "description": "Run the project's declared test command in a mission's worktree and record the result as evidence for merging. When off: No test command can be run and no evidence can be recorded. If tests are already required before merging, planning and entering Tower mode are refused with an explanation, and merges stay blocked for the missing test evidence until that requirement is cleared; nothing else changes."
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
- "title": "测试发现",
4
- "description": "运行 worktree 声明的测试发现,并为 mission tip 记录回执。关闭后:不再注册 tower_test,也无法记录回执;若 gates.requireTests:true,规划/进入模式会以解释性错误拒绝。"
3
+ "title": "测试证据",
4
+ "description": "在任务线的工作树中运行项目声明的测试命令,并把结果记录为合并证据。关闭后:无法运行测试命令,也无法记录证据。若已把测试设为合并前必须通过,规划或进入 Tower 模式会被拒绝并给出解释,缺少测试证据的合并也会持续受阻,直到清除该要求;其他一切照常。"
5
5
  }
6
6
  }
package/locale/zh.json CHANGED
@@ -1,53 +1,68 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "Tower",
4
- "description": "多代理任务规划、隔离工作树与审查门禁合并。"
4
+ "description": "规划并跟踪任务线,让每条任务线在独立工作树中完成,交给执行代理与审查代理,并且在把合并前审查设为必须时,审查通过后再合并。关闭这一项等同于卸载 Tower:不再保留任何工具、预设或技能。"
5
5
  },
6
6
  "components": {
7
7
  "tower": {
8
8
  "title": "Tower 控制塔",
9
- "summary": "任务规划、隔离工作树、模式守卫、健康契约与恢复逃生口。",
10
- "disables": "关闭强制主组件等同于卸载 Tower:不再保留任何工具、preset 或技能。"
9
+ "summary": "常驻核心:任务线规划与状态、工作树隔离、Tower 模式、环境健康检查,以及卡住的锁如何恢复。",
10
+ "disables": "关闭这一项等同于卸载 Tower:不再保留任何工具、预设或技能。"
11
11
  },
12
12
  "tower-skills": {
13
13
  "title": "Tower 技能包",
14
- "summary": "执行与审查代理的操作手册,以及失败后的恢复指南。",
15
- "disables": "三个 Tower 技能从目录中移除;执行/审查协议段落与所有 mission 工具继续工作。"
14
+ "summary": "执行代理与审查代理的分步操作手册,以及合并受阻时如何脱困的指南。",
15
+ "disables": "三个 Tower 技能从目录中移除;执行代理与审查代理的协议段落与所有任务线工具继续工作。"
16
16
  },
17
17
  "tower-batch": {
18
18
  "title": "证据批次",
19
- "summary": "把 mission 归入有限证据批次,并按必需检查与回执关闭批次。",
20
- "disables": "不再注册 tower_batch;mission、门禁与合并不受影响。"
19
+ "summary": "把一组任务线收进一个批次,只有当所有必需检查与证据回执齐全时才允许关闭该批次(或结案)。",
20
+ "disables": "批次工具及其检查不可用;任务线、合并与其他能力继续工作。"
21
21
  },
22
22
  "tower-import": {
23
23
  "title": "旧版导入",
24
- "summary": "导入 Tower Codex 旧状态文件,并审计快照到 mission 的映射。",
25
- "disables": "不再注册 tower_import_legacy 与 tower_legacy_map;新状态不受影响。"
24
+ "summary": "读取旧版 Tower Codex 状态文件(Tower 早期的状态格式),并显示每个旧快照对应哪一条任务线。",
25
+ "disables": "导入工具不可用;当前状态与其他能力继续工作。"
26
26
  },
27
27
  "tower-leases": {
28
- "title": "咨询式租约",
29
- "summary": "用咨询式资源租约协调每个仓库中的重型工作。",
30
- "disables": "不再注册 tower_resource;其他能力不依赖租约。"
28
+ "title": "租约协调",
29
+ "summary": "只做协调:让一个代理认领某一具体工作(称为租约),避免两个代理同时开工。租约只是给其他代理看的说明,本身不会阻塞任何工作。",
30
+ "disables": "租约工具不可用。若某个执行代理被配置为必须先持有租约,它将无法启动:规划或进入 Tower 模式会被拒绝并给出解释,直到清除该设置或重新启用这一项。其他工作照常进行。"
31
31
  },
32
32
  "tower-tests": {
33
- "title": "测试发现",
34
- "summary": "运行 worktree 声明的测试发现,并为 mission tip 记录回执。",
35
- "disables": "不再注册 tower_test,也无法记录回执;若 gates.requireTests:true,规划/进入模式会以解释性错误拒绝。"
33
+ "title": "测试证据",
34
+ "summary": "在任务线的工作树中运行项目声明的测试命令,并把结果记录为合并证据。",
35
+ "disables": "无法运行测试命令,也无法记录证据。若已把测试设为合并前必须通过,规划或进入 Tower 模式会被拒绝并给出解释,缺少测试证据的合并也会持续受阻,直到清除该要求;其他一切照常。"
36
+ },
37
+ "tower-board": {
38
+ "title": "任务线看板",
39
+ "summary": "在状态文件旁写入纯文本看板文件(MISSIONS.md),让人无需调用工具就能阅读任务线列表。",
40
+ "disables": "不再写入或刷新看板文件,已有看板会过期;任务线、合并与其他能力继续工作。"
41
+ },
42
+ "tower-archive": {
43
+ "title": "任务线归档",
44
+ "summary": "把已结束的任务线及其关联记录移入磁盘归档,让当前状态文件不再承载它们的完整历史。",
45
+ "disables": "已结束的任务线继续留在当前状态文件中,文件会持续增大;合并与其他能力继续工作,且不会删除任何内容。"
36
46
  },
37
47
  "tower-hmr": {
38
48
  "title": "开发热重载",
39
- "summary": "为联动开发 profile 注册 tower_reload 与 /tower reload。",
40
- "disables": "tower_reload 与 /tower reload 不可用;非 HMR profile 的行为与之前完全相同。随包默认关闭。"
49
+ "summary": "仅限开发人员:改动代码后,在联动开发配置中重新加载 Tower,无需重启 DSH。",
50
+ "disables": "不会自动重新加载,需要在开发配置中手动重启。普通安装不受影响:它是开发人员专用工具,默认关闭是有意为之。"
41
51
  },
42
52
  "preset-tower-worker": {
43
53
  "title": "Tower Worker 预设",
44
- "summary": "声明 Tower Worker 预设:任务协议,以及执行代理在其工作树内使用的文件系统、终端与 Tower 工具。",
45
- "disables": "缺少它 tower_spawn 无法启动执行代理。"
54
+ "summary": "必需的 Tower Worker 执行代理预设:任务线协议,以及执行代理在其独立工作树中使用的文件系统、终端与 Tower 工具。",
55
+ "disables": "缺少它,Tower 无法规划任务线、进入 Tower 模式或启动执行代理。"
46
56
  },
47
57
  "preset-tower-reviewer": {
48
58
  "title": "Tower Reviewer 预设",
49
- "summary": "声明 Tower Reviewer 预设:只读独立审查,检视任务差异、核对范围与验收,并返回结论。",
50
- "disables": "无法派发审查代理。review.requireReview 为 false 时允许关闭;强制审查开启时规划/进入模式会被锁定并给出解释。"
59
+ "summary": "独立的 Tower Reviewer 审查代理预设:一个只读代理,阅读任务线差异、核对范围与验收,并给出结论。在合并前审查仍为可选时可以使用;一旦把合并前审查设为必须,它就是合并的前置条件。",
60
+ "disables": "无法启动审查代理。在合并前审查仍为可选时,允许关闭这一项;一旦要求合并前必须审查,规划或进入 Tower 模式会被拒绝并给出解释。"
61
+ },
62
+ "tower-ui": {
63
+ "title": "Tower 界面",
64
+ "summary": "在 Web 客户端中显示 Tower 工具结果卡片、输入框上方的简要状态摘要,以及简短的状态提示条。",
65
+ "disables": "界面插件不再加载,不再有 Tower 卡片、状态摘要或提示条。Tower 核心、任务线、状态与看板继续工作。"
51
66
  }
52
67
  }
53
68
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-tower",
3
- "version": "2.4.2",
3
+ "version": "2.5.0",
4
4
  "type": "module",
5
5
  "description": "DSH-native Tower: mission planning, worktree isolation, review-gated merges, and a human-owned Tower mode.",
6
6
  "license": "MIT",
@@ -35,6 +35,8 @@
35
35
  "./import": "./host/capability-import.js",
36
36
  "./leases": "./host/capability-leases.js",
37
37
  "./tests": "./host/capability-tests.js",
38
+ "./board": "./host/capability-board.js",
39
+ "./archive": "./host/capability-archive.js",
38
40
  "./hmr": "./host/capability-hmr.js",
39
41
  "./preset-worker": "./host/preset-worker.js",
40
42
  "./preset-reviewer": "./host/preset-reviewer.js",
@@ -43,6 +45,8 @@
43
45
  "./import/locale/*.json": "./locale/import/*.json",
44
46
  "./leases/locale/*.json": "./locale/leases/*.json",
45
47
  "./tests/locale/*.json": "./locale/tests/*.json",
48
+ "./board/locale/*.json": "./locale/board/*.json",
49
+ "./archive/locale/*.json": "./locale/archive/*.json",
46
50
  "./hmr/locale/*.json": "./locale/hmr/*.json",
47
51
  "./preset-worker/locale/*.json": "./locale/preset-worker/*.json",
48
52
  "./preset-reviewer/locale/*.json": "./locale/preset-reviewer/*.json",
@@ -74,6 +78,7 @@
74
78
  "CONTRIBUTING.md",
75
79
  "SECURITY.md",
76
80
  "PRINCIPLES.md",
81
+ "GLOSSARY.md",
77
82
  "docs/",
78
83
  "ui-bundle/",
79
84
  "ports/*.js"
@@ -85,12 +90,15 @@
85
90
  },
86
91
  "scripts": {
87
92
  "test": "node --test tests/*.test.mjs",
93
+ "test:property": "node --test tests/property/*.prop.mjs",
94
+ "test:property:long": "node --env-file=tests/property/tiers/long.env --test tests/property/*.prop.mjs",
88
95
  "test:watch": "node --test --watch tests/*.test.mjs",
89
96
  "test:coverage": "node --test --experimental-test-coverage tests/*.test.mjs",
90
97
  "test:live": "node tests/live/run.cjs",
91
98
  "smoke:mount": "node scripts/mount-smoke.mjs",
92
99
  "smoke:fixtures": "node scripts/mount-smoke/fixtures.mjs",
93
100
  "release:check": "node scripts/release-check.mjs",
101
+ "release:notes": "node scripts/release-notes.mjs",
94
102
  "audit:issues": "node scripts/issue-audit.mjs",
95
103
  "audit:regressions": "node scripts/regression-audit.mjs",
96
104
  "surface:check": "node scripts/surface-baseline.mjs",
@@ -118,7 +126,7 @@
118
126
  "types:coverage": "node scripts/types-coverage.mjs",
119
127
  "types:strict:check": "node scripts/types-strict.mjs",
120
128
  "types:strict:write": "node scripts/types-strict.mjs --write",
121
- "check": "npm test && npm run docs:check && npm run docs:check:philosophy && npm run docs:check:generated && npm run docs:check:generated:tools && npm run docs:check:generated:config && npm run docs:check:generated:events && npm run docs:check:generated:types && npm run docs:check:generated:components && npm run docs:check:generated:locale && npm run docs:check:components && npm run surface:check && npm run pack:check && npm run architecture:check && npm run types:coverage && npm run types:strict:check && npm run types:check && npm run domain:check",
129
+ "check": "npm test && npm run test:property && npm run docs:check && npm run docs:check:philosophy && npm run docs:check:generated && npm run docs:check:generated:tools && npm run docs:check:generated:config && npm run docs:check:generated:events && npm run docs:check:generated:types && npm run docs:check:generated:components && npm run docs:check:generated:locale && npm run docs:check:components && npm run surface:check && npm run pack:check && npm run architecture:check && npm run types:coverage && npm run types:strict:check && npm run types:check && npm run domain:check",
122
130
  "domain:metrics": "node scripts/domain-metrics.mjs",
123
131
  "domain:check": "node scripts/domain-metrics.mjs --check"
124
132
  },
@@ -128,6 +136,7 @@
128
136
  },
129
137
  "devDependencies": {
130
138
  "@types/node": "^22.20.5",
139
+ "fast-check": "^4.10.2",
131
140
  "typescript": "~5.9.3"
132
141
  }
133
142
  }