@paths.design/caws-cli 11.1.6 → 11.1.8

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 (190) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +55 -58
  3. package/dist/init/hook-packs/manifest-claude-code.d.ts +1 -1
  4. package/dist/init/hook-packs/manifest-claude-code.d.ts.map +1 -1
  5. package/dist/init/hook-packs/manifest-claude-code.js +317 -6
  6. package/dist/init/hook-packs/manifest-claude-code.js.map +1 -1
  7. package/dist/init/hook-packs/types.js +1 -1
  8. package/dist/init/hook-packs/types.js.map +1 -1
  9. package/dist/shell/binding/resolve-binding.d.ts.map +1 -1
  10. package/dist/shell/binding/resolve-binding.js +105 -1
  11. package/dist/shell/binding/resolve-binding.js.map +1 -1
  12. package/dist/shell/binding/types.d.ts +47 -3
  13. package/dist/shell/binding/types.d.ts.map +1 -1
  14. package/dist/shell/command-metadata.d.ts +93 -0
  15. package/dist/shell/command-metadata.d.ts.map +1 -0
  16. package/dist/shell/command-metadata.js +687 -0
  17. package/dist/shell/command-metadata.js.map +1 -0
  18. package/dist/shell/commands/agents.d.ts +48 -0
  19. package/dist/shell/commands/agents.d.ts.map +1 -0
  20. package/dist/shell/commands/agents.js +577 -0
  21. package/dist/shell/commands/agents.js.map +1 -0
  22. package/dist/shell/commands/claim.d.ts +16 -0
  23. package/dist/shell/commands/claim.d.ts.map +1 -1
  24. package/dist/shell/commands/claim.js +88 -30
  25. package/dist/shell/commands/claim.js.map +1 -1
  26. package/dist/shell/commands/events.d.ts +106 -0
  27. package/dist/shell/commands/events.d.ts.map +1 -0
  28. package/dist/shell/commands/events.js +510 -0
  29. package/dist/shell/commands/events.js.map +1 -0
  30. package/dist/shell/commands/gates.d.ts +2 -2
  31. package/dist/shell/commands/gates.d.ts.map +1 -1
  32. package/dist/shell/commands/gates.js +106 -25
  33. package/dist/shell/commands/gates.js.map +1 -1
  34. package/dist/shell/commands/init.d.ts.map +1 -1
  35. package/dist/shell/commands/init.js +26 -0
  36. package/dist/shell/commands/init.js.map +1 -1
  37. package/dist/shell/commands/prepush.d.ts +26 -0
  38. package/dist/shell/commands/prepush.d.ts.map +1 -0
  39. package/dist/shell/commands/prepush.js +373 -0
  40. package/dist/shell/commands/prepush.js.map +1 -0
  41. package/dist/shell/commands/scope.d.ts.map +1 -1
  42. package/dist/shell/commands/scope.js +31 -1
  43. package/dist/shell/commands/scope.js.map +1 -1
  44. package/dist/shell/commands/specs.d.ts +44 -3
  45. package/dist/shell/commands/specs.d.ts.map +1 -1
  46. package/dist/shell/commands/specs.js +411 -15
  47. package/dist/shell/commands/specs.js.map +1 -1
  48. package/dist/shell/commands/status.d.ts +12 -0
  49. package/dist/shell/commands/status.d.ts.map +1 -1
  50. package/dist/shell/commands/status.js +236 -21
  51. package/dist/shell/commands/status.js.map +1 -1
  52. package/dist/shell/commands/worktree.d.ts +9 -0
  53. package/dist/shell/commands/worktree.d.ts.map +1 -1
  54. package/dist/shell/commands/worktree.js +353 -1
  55. package/dist/shell/commands/worktree.js.map +1 -1
  56. package/dist/shell/gates/disposition.d.ts.map +1 -1
  57. package/dist/shell/gates/disposition.js +43 -2
  58. package/dist/shell/gates/disposition.js.map +1 -1
  59. package/dist/shell/index.d.ts +14 -6
  60. package/dist/shell/index.d.ts.map +1 -1
  61. package/dist/shell/index.js +32 -1
  62. package/dist/shell/index.js.map +1 -1
  63. package/dist/shell/legacy-command-map.js +832 -0
  64. package/dist/shell/push-range/classify-range.d.ts +99 -0
  65. package/dist/shell/push-range/classify-range.d.ts.map +1 -0
  66. package/dist/shell/push-range/classify-range.js +155 -0
  67. package/dist/shell/push-range/classify-range.js.map +1 -0
  68. package/dist/shell/push-range/scope-match.d.ts +13 -0
  69. package/dist/shell/push-range/scope-match.d.ts.map +1 -0
  70. package/dist/shell/push-range/scope-match.js +53 -0
  71. package/dist/shell/push-range/scope-match.js.map +1 -0
  72. package/dist/shell/register.d.ts.map +1 -1
  73. package/dist/shell/register.js +350 -165
  74. package/dist/shell/register.js.map +1 -1
  75. package/dist/shell/registered-command-groups.js +48 -0
  76. package/dist/shell/render/status.d.ts +7 -1
  77. package/dist/shell/render/status.d.ts.map +1 -1
  78. package/dist/shell/render/status.js +72 -0
  79. package/dist/shell/render/status.js.map +1 -1
  80. package/dist/shell/rules.d.ts +19 -0
  81. package/dist/shell/rules.d.ts.map +1 -1
  82. package/dist/shell/rules.js +27 -0
  83. package/dist/shell/rules.js.map +1 -1
  84. package/dist/shell/session/resolve-session.d.ts +29 -1
  85. package/dist/shell/session/resolve-session.d.ts.map +1 -1
  86. package/dist/shell/session/resolve-session.js +817 -11
  87. package/dist/shell/session/resolve-session.js.map +1 -1
  88. package/dist/shell/session/types.d.ts +127 -1
  89. package/dist/shell/session/types.d.ts.map +1 -1
  90. package/dist/shell/session/types.js +10 -4
  91. package/dist/shell/session/types.js.map +1 -1
  92. package/dist/store/agents-store.d.ts.map +1 -1
  93. package/dist/store/agents-store.js +9 -0
  94. package/dist/store/agents-store.js.map +1 -1
  95. package/dist/store/apply-patch.d.ts.map +1 -1
  96. package/dist/store/apply-patch.js +15 -0
  97. package/dist/store/apply-patch.js.map +1 -1
  98. package/dist/store/doctor-snapshot.d.ts.map +1 -1
  99. package/dist/store/doctor-snapshot.js +169 -3
  100. package/dist/store/doctor-snapshot.js.map +1 -1
  101. package/dist/store/events-migration.d.ts +207 -0
  102. package/dist/store/events-migration.d.ts.map +1 -0
  103. package/dist/store/events-migration.js +358 -0
  104. package/dist/store/events-migration.js.map +1 -0
  105. package/dist/store/events-store.d.ts +47 -1
  106. package/dist/store/events-store.d.ts.map +1 -1
  107. package/dist/store/events-store.js +278 -0
  108. package/dist/store/events-store.js.map +1 -1
  109. package/dist/store/git-autocommit.d.ts +46 -0
  110. package/dist/store/git-autocommit.d.ts.map +1 -0
  111. package/dist/store/git-autocommit.js +198 -0
  112. package/dist/store/git-autocommit.js.map +1 -0
  113. package/dist/store/git-sparse-checkout.d.ts +25 -0
  114. package/dist/store/git-sparse-checkout.d.ts.map +1 -0
  115. package/dist/store/git-sparse-checkout.js +101 -0
  116. package/dist/store/git-sparse-checkout.js.map +1 -0
  117. package/dist/store/index.d.ts +6 -1
  118. package/dist/store/index.d.ts.map +1 -1
  119. package/dist/store/index.js +16 -1
  120. package/dist/store/index.js.map +1 -1
  121. package/dist/store/leases-store.d.ts +89 -0
  122. package/dist/store/leases-store.d.ts.map +1 -0
  123. package/dist/store/leases-store.js +427 -0
  124. package/dist/store/leases-store.js.map +1 -0
  125. package/dist/store/lifecycle-transaction.d.ts.map +1 -1
  126. package/dist/store/lifecycle-transaction.js +34 -1
  127. package/dist/store/lifecycle-transaction.js.map +1 -1
  128. package/dist/store/rules.d.ts +74 -1
  129. package/dist/store/rules.d.ts.map +1 -1
  130. package/dist/store/rules.js +76 -0
  131. package/dist/store/rules.js.map +1 -1
  132. package/dist/store/specs-migration.d.ts +128 -0
  133. package/dist/store/specs-migration.d.ts.map +1 -0
  134. package/dist/store/specs-migration.js +481 -0
  135. package/dist/store/specs-migration.js.map +1 -0
  136. package/dist/store/specs-store.d.ts.map +1 -1
  137. package/dist/store/specs-store.js +14 -2
  138. package/dist/store/specs-store.js.map +1 -1
  139. package/dist/store/specs-writer.d.ts +130 -3
  140. package/dist/store/specs-writer.d.ts.map +1 -1
  141. package/dist/store/specs-writer.js +941 -102
  142. package/dist/store/specs-writer.js.map +1 -1
  143. package/dist/store/types.d.ts +31 -1
  144. package/dist/store/types.d.ts.map +1 -1
  145. package/dist/store/waivers-store.d.ts.map +1 -1
  146. package/dist/store/waivers-store.js +8 -1
  147. package/dist/store/waivers-store.js.map +1 -1
  148. package/dist/store/worktrees-migration.d.ts +141 -0
  149. package/dist/store/worktrees-migration.d.ts.map +1 -0
  150. package/dist/store/worktrees-migration.js +356 -0
  151. package/dist/store/worktrees-migration.js.map +1 -0
  152. package/dist/store/worktrees-writer.d.ts +28 -0
  153. package/dist/store/worktrees-writer.d.ts.map +1 -1
  154. package/dist/store/worktrees-writer.js +147 -13
  155. package/dist/store/worktrees-writer.js.map +1 -1
  156. package/package.json +5 -2
  157. package/templates/hook-packs/claude-code/CLAUDE.md +11 -5
  158. package/templates/hook-packs/claude-code/agent-heartbeat.sh +131 -0
  159. package/templates/hook-packs/claude-code/agent-register.sh +62 -0
  160. package/templates/hook-packs/claude-code/agent-stop.sh +51 -0
  161. package/templates/hook-packs/claude-code/audit.sh +1 -1
  162. package/templates/hook-packs/claude-code/block-dangerous.sh +1 -1
  163. package/templates/hook-packs/claude-code/classify_command.py +1 -1
  164. package/templates/hook-packs/claude-code/cwd-guard.sh +30 -0
  165. package/templates/hook-packs/claude-code/dispatch/post_tool_use.sh +15 -4
  166. package/templates/hook-packs/claude-code/dispatch/pre_tool_use.sh +19 -2
  167. package/templates/hook-packs/claude-code/dispatch/session_start.sh +6 -2
  168. package/templates/hook-packs/claude-code/dispatch/stop.sh +7 -2
  169. package/templates/hook-packs/claude-code/duplicate-export-check.sh +156 -0
  170. package/templates/hook-packs/claude-code/god-object-check.sh +102 -0
  171. package/templates/hook-packs/claude-code/guard-strikes.sh +1 -1
  172. package/templates/hook-packs/claude-code/lib/parse-input.sh +115 -1
  173. package/templates/hook-packs/claude-code/lib/run-handlers.sh +1 -1
  174. package/templates/hook-packs/claude-code/loc-delta-check.sh +91 -0
  175. package/templates/hook-packs/claude-code/naming-check.sh +128 -0
  176. package/templates/hook-packs/claude-code/plan-transcript-finalize.sh +59 -0
  177. package/templates/hook-packs/claude-code/plan-transcript-snapshot.sh +86 -0
  178. package/templates/hook-packs/claude-code/protected-paths.sh +59 -0
  179. package/templates/hook-packs/claude-code/quiet-merge.sh +68 -0
  180. package/templates/hook-packs/claude-code/reset-danger-latch.sh +1 -1
  181. package/templates/hook-packs/claude-code/reset-strikes.sh +1 -1
  182. package/templates/hook-packs/claude-code/runtime-paths.sh +1 -1
  183. package/templates/hook-packs/claude-code/scan-secrets.sh +98 -0
  184. package/templates/hook-packs/claude-code/scope-guard.sh +47 -65
  185. package/templates/hook-packs/claude-code/session-caws-status.sh +7 -1
  186. package/templates/hook-packs/claude-code/session-log.sh +1 -1
  187. package/templates/hook-packs/claude-code/session_log_renderer.py +956 -0
  188. package/templates/hook-packs/claude-code/shortcut-language-check.sh +147 -0
  189. package/templates/hook-packs/claude-code/worktree-guard.sh +130 -4
  190. package/templates/hook-packs/claude-code/worktree-write-guard.sh +133 -18
@@ -15,6 +15,7 @@
15
15
  // etc.) UNTOUCHED.
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.registerShellCommands = registerShellCommands;
18
+ const command_metadata_1 = require("./command-metadata");
18
19
  const index_1 = require("./index");
19
20
  function parseDataOption(raw) {
20
21
  if (typeof raw !== 'string' || raw.length === 0)
@@ -35,6 +36,102 @@ function parseDataOption(raw) {
35
36
  function isEvidenceKind(value) {
36
37
  return value === 'test' || value === 'gate' || value === 'ac';
37
38
  }
39
+ // ── Metadata-driven help wiring (CAWS-CLI-HELP-METADATA-AUTHORITY-001) ──────
40
+ // register.ts no longer authors `.description()` / `.option()` string literals
41
+ // for groups present in COMMAND_SURFACE_METADATA; it reads them from the typed
42
+ // metadata so the help text has a single, lock-tested source. The `.action()`
43
+ // handlers stay inline (they bind to the run*Command functions); only the
44
+ // help/option surface is metadata-driven.
45
+ /** Render an option's help string: prose, plus a derived "value list" when the
46
+ * option is enum-backed (allowedValues). The value list is the locked part —
47
+ * the lock test asserts it equals the kernel/schema enum. */
48
+ function renderOptionDescription(opt) {
49
+ if (opt.allowedValues && opt.allowedValues.length > 0) {
50
+ return `${opt.description}: ${opt.allowedValues.join(' | ')}`;
51
+ }
52
+ return opt.description;
53
+ }
54
+ /** Commander value collector for repeatable string options — accumulates each
55
+ * occurrence into an array, verbatim caller order, no normalization. Shared by
56
+ * every `collect: true` metadata option (claim --paths, prepush --ack, waiver
57
+ * create --gate). */
58
+ function collectOption(value, previous) {
59
+ return previous === undefined ? [value] : [...previous, value];
60
+ }
61
+ /** Apply one metadata option to a Commander command, choosing
62
+ * required/optional, supplying a collector for repeatable (`collect`) options,
63
+ * and passing a default value when declared. */
64
+ function applyOptionMeta(cmd, opt) {
65
+ const description = renderOptionDescription(opt);
66
+ if (opt.collect === true) {
67
+ // Repeatable option: Commander needs the collector fn. Whether to seed an
68
+ // initial [] is preserved from the prior hand-written behavior and encoded
69
+ // in metadata as defaultValue: [] (e.g. prepush --ack, waiver --gate seed
70
+ // so the value is always an array; claim --paths omits the seed so an
71
+ // unsupplied option stays `undefined`).
72
+ const seed = opt.defaultValue !== undefined ? opt.defaultValue : undefined;
73
+ if (opt.required === true) {
74
+ cmd.requiredOption(opt.flag, description, collectOption, seed ?? []);
75
+ }
76
+ else if (seed !== undefined) {
77
+ cmd.option(opt.flag, description, collectOption, seed);
78
+ }
79
+ else {
80
+ cmd.option(opt.flag, description, collectOption);
81
+ }
82
+ return;
83
+ }
84
+ if (opt.required === true) {
85
+ cmd.requiredOption(opt.flag, description);
86
+ return;
87
+ }
88
+ if (opt.defaultValue !== undefined) {
89
+ cmd.option(opt.flag, description, opt.defaultValue);
90
+ return;
91
+ }
92
+ cmd.option(opt.flag, description);
93
+ }
94
+ /** Construct the `.command()` name string with the metadata's positional
95
+ * argument suffix (`<name>` required, `[name]` optional), e.g. "create <id>". */
96
+ function leafCommandName(leaf) {
97
+ if (!leaf.argument)
98
+ return leaf.name;
99
+ const { name, required } = leaf.argument;
100
+ return required ? `${leaf.name} <${name}>` : `${leaf.name} [${name}]`;
101
+ }
102
+ /** Register a leaf subcommand from metadata: name(+arg), description, options.
103
+ * Returns the configured Command so the caller can attach `.action()`. */
104
+ function defineLeaf(group, leaf) {
105
+ const cmd = group.command(leafCommandName(leaf)).description(leaf.description);
106
+ for (const opt of leaf.options) {
107
+ applyOptionMeta(cmd, opt);
108
+ }
109
+ return cmd;
110
+ }
111
+ /** Apply the group-level description from metadata to a Commander group. */
112
+ function applyGroupMeta(group, meta) {
113
+ group.description(meta.description);
114
+ }
115
+ /** Register a FLAT top-level command from LeafCommandMeta (init/doctor/status/
116
+ * claim/prepush): name(+arg), description, options — all metadata-driven.
117
+ * Returns the configured Command so the caller can attach `.action()`. */
118
+ function defineFlat(program, leaf) {
119
+ const cmd = program.command(leafCommandName(leaf)).description(leaf.description);
120
+ for (const opt of leaf.options) {
121
+ applyOptionMeta(cmd, opt);
122
+ }
123
+ return cmd;
124
+ }
125
+ /** Look up a leaf's metadata within a group by subcommand name. Throws if the
126
+ * metadata is missing — a wiring bug should fail loudly at registration, not
127
+ * silently register a command with no help. */
128
+ function leafMeta(meta, name) {
129
+ const found = meta.subcommands.find((s) => s.name === name);
130
+ if (!found) {
131
+ throw new Error(`register.ts: no metadata for "${meta.name} ${name}" in COMMAND_SURFACE_METADATA`);
132
+ }
133
+ return found;
134
+ }
38
135
  function registerShellCommands(program, options = {}) {
39
136
  const exit = options.exit ?? ((code) => process.exit(code));
40
137
  // -------------------------------------------------------------------
@@ -46,22 +143,7 @@ function registerShellCommands(program, options = {}) {
46
143
  // Replaces the legacy `caws init` registration removed from
47
144
  // src/index.js as part of slice 7b.
48
145
  // -------------------------------------------------------------------
49
- program
50
- .command('init')
51
- .description('Bootstrap the canonical vNext .caws/ project state (idempotent; ' +
52
- 'refuses to overwrite legacy single-spec layout). With ' +
53
- '--agent-surface, also installs the corresponding hook pack.')
54
- .option('--data', 'Show structured data block on diagnostics')
55
- .option('--agent-surface <name>', 'Install a hook pack for an agent harness ' +
56
- '(claude-code | cursor | windsurf | none). When omitted, init ' +
57
- 'attempts filesystem detection and skips hook install when ' +
58
- 'ambiguous.')
59
- .option('--overwrite', 'For hook-pack install: replace drifted or unmanaged files at ' +
60
- 'managed pack paths. CAUTION: local edits to those files will ' +
61
- 'be lost.')
62
- .option('--adopt', 'For hook-pack install: leave drifted or unmanaged files in place ' +
63
- 'without enforcing pack contents. CAUTION: pack drift is no ' +
64
- 'longer tracked for those paths.')
146
+ defineFlat(program, command_metadata_1.INIT_COMMAND_META)
65
147
  .action((opts) => {
66
148
  // Commander hands back the raw string for agentSurface; the
67
149
  // runInitCommand validator rejects unknown values with exit 2.
@@ -84,10 +166,7 @@ function registerShellCommands(program, options = {}) {
84
166
  // -------------------------------------------------------------------
85
167
  // caws doctor
86
168
  // -------------------------------------------------------------------
87
- program
88
- .command('doctor')
89
- .description('Run drift detection against the current .caws/ state')
90
- .option('--data', 'Show structured data block on findings/diagnostics')
169
+ defineFlat(program, command_metadata_1.DOCTOR_COMMAND_META)
91
170
  .action((opts) => {
92
171
  const code = (0, index_1.runDoctorCommand)({
93
172
  showData: opts.data === true,
@@ -98,13 +177,9 @@ function registerShellCommands(program, options = {}) {
98
177
  // caws scope show <path> / caws scope check <path>
99
178
  // (replaces the legacy `scope` group entirely)
100
179
  // -------------------------------------------------------------------
101
- const scopeCmd = program
102
- .command('scope')
103
- .description('Evaluate file paths against the bound spec scope');
104
- scopeCmd
105
- .command('show <path>')
106
- .description('Explain the scope decision for <path>; always exits 0')
107
- .option('--data', 'Show structured data block')
180
+ const scopeCmd = program.command('scope');
181
+ applyGroupMeta(scopeCmd, command_metadata_1.SCOPE_COMMAND_META);
182
+ defineLeaf(scopeCmd, leafMeta(command_metadata_1.SCOPE_COMMAND_META, 'show'))
108
183
  .action((p, opts) => {
109
184
  const code = (0, index_1.runScopeCommand)({
110
185
  path: p,
@@ -113,10 +188,7 @@ function registerShellCommands(program, options = {}) {
113
188
  });
114
189
  exit(code);
115
190
  });
116
- scopeCmd
117
- .command('check <path>')
118
- .description('Enforce the scope decision for <path>; exits 0 on admit, 1 otherwise')
119
- .option('--data', 'Show structured data block')
191
+ defineLeaf(scopeCmd, leafMeta(command_metadata_1.SCOPE_COMMAND_META, 'check'))
120
192
  .action((p, opts) => {
121
193
  const code = (0, index_1.runScopeCommand)({
122
194
  path: p,
@@ -128,10 +200,7 @@ function registerShellCommands(program, options = {}) {
128
200
  // -------------------------------------------------------------------
129
201
  // caws status — read-only dashboard (replaces legacy status)
130
202
  // -------------------------------------------------------------------
131
- program
132
- .command('status')
133
- .description('Read-only dashboard: project, current context, claim, and doctor findings')
134
- .option('--data', 'Show structured data block on rendered diagnostics')
203
+ defineFlat(program, command_metadata_1.STATUS_COMMAND_META)
135
204
  .action((opts) => {
136
205
  const code = (0, index_1.runStatusCommand)({
137
206
  showData: opts.data === true,
@@ -139,19 +208,14 @@ function registerShellCommands(program, options = {}) {
139
208
  exit(code);
140
209
  });
141
210
  // -------------------------------------------------------------------
142
- // caws claim [--takeover]
211
+ // caws claim [--takeover] [--paths <path>...]
143
212
  // -------------------------------------------------------------------
144
- program
145
- .command('claim')
146
- .description('Surface ownership of the current worktree; with --takeover, ' +
147
- 'acquire ownership from a foreign session (writes prior_owners audit).')
148
- .option('--takeover', 'Forcibly take ownership of a foreign-owned worktree. Required when ' +
149
- 'the current owner is a different session.')
150
- .option('--data', 'Show structured data block on diagnostics')
213
+ defineFlat(program, command_metadata_1.CLAIM_COMMAND_META)
151
214
  .action((opts) => {
152
215
  const code = (0, index_1.runClaimCommand)({
153
216
  takeover: opts.takeover === true,
154
217
  showData: opts.data === true,
218
+ ...(opts.paths !== undefined ? { paths: opts.paths } : {}),
155
219
  });
156
220
  exit(code);
157
221
  });
@@ -159,20 +223,26 @@ function registerShellCommands(program, options = {}) {
159
223
  // caws gates run --spec <id> [--context <ctx>]
160
224
  // (replaces the legacy `gates` group and `quality-gates` alias)
161
225
  // -------------------------------------------------------------------
162
- const gatesCmd = program
163
- .command('gates')
164
- .description('Run quality gates against the current changes (policy-driven)');
165
- gatesCmd
166
- .command('run')
167
- .description('Invoke quality-gates subprocess and apply policy.gates[gate].mode ' +
168
- 'to decide block/warn/skip. Appends one gate_evaluated event per ' +
169
- 'policy-declared gate.')
170
- .requiredOption('--spec <id>', 'Spec id this gate run is about')
171
- .option('--context <ctx>', 'Subprocess context: cli | commit | ci', 'cli')
172
- .option('--data', 'Show structured data block on diagnostics')
226
+ const gatesCmd = program.command('gates');
227
+ applyGroupMeta(gatesCmd, command_metadata_1.GATES_COMMAND_META);
228
+ defineLeaf(gatesCmd, leafMeta(command_metadata_1.GATES_COMMAND_META, 'run'))
173
229
  .action((opts) => {
174
230
  const code = (0, index_1.runGatesRunCommand)({ specId: opts.spec }, {
175
- subprocessArgs: [`--context=${opts.context}`],
231
+ showData: opts.data === true,
232
+ });
233
+ exit(code);
234
+ });
235
+ // -------------------------------------------------------------------
236
+ // caws prepush — MULTI-AGENT-PUSH-RANGE-GUARD-001
237
+ // -------------------------------------------------------------------
238
+ defineFlat(program, command_metadata_1.PREPUSH_COMMAND_META)
239
+ .action((opts) => {
240
+ const code = (0, index_1.runPrepushCommand)({
241
+ remote: opts.remote,
242
+ branch: opts.branch,
243
+ ...(opts.base !== undefined ? { base: opts.base } : {}),
244
+ ...(opts.spec !== undefined ? { specId: opts.spec } : {}),
245
+ ack: opts.ack,
176
246
  showData: opts.data === true,
177
247
  });
178
248
  exit(code);
@@ -180,17 +250,9 @@ function registerShellCommands(program, options = {}) {
180
250
  // -------------------------------------------------------------------
181
251
  // caws evidence record
182
252
  // -------------------------------------------------------------------
183
- const evidenceCmd = program
184
- .command('evidence')
185
- .description('Record typed evidence events into .caws/events.jsonl');
186
- evidenceCmd
187
- .command('record')
188
- .description('Append a typed evidence event (test|gate|ac)')
189
- .requiredOption('--type <kind>', 'Evidence kind: test | gate | ac')
190
- .requiredOption('--spec <id>', 'Spec id this evidence is about')
191
- .requiredOption('--data <json>', 'Event payload as a JSON object string')
192
- .option('--actor-kind <kind>', 'Actor kind: agent | human | system | automation', 'agent')
193
- .option('--actor-id <id>', 'Override actor id (defaults to session id)')
253
+ const evidenceCmd = program.command('evidence');
254
+ applyGroupMeta(evidenceCmd, command_metadata_1.EVIDENCE_COMMAND_META);
255
+ defineLeaf(evidenceCmd, leafMeta(command_metadata_1.EVIDENCE_COMMAND_META, 'record'))
194
256
  .action((opts) => {
195
257
  // Parse --data here; pass already-typed shape to the command.
196
258
  let data;
@@ -219,25 +281,67 @@ function registerShellCommands(program, options = {}) {
219
281
  exit(code);
220
282
  });
221
283
  // -------------------------------------------------------------------
284
+ // caws events migrate / rotate / verify-archive
285
+ //
286
+ // v11.2 maintenance command surface for the event-log writer. See
287
+ // docs/architecture/caws-vnext-command-surface.md §6 invariant 14 and
288
+ // the Maintenance / control-plane subsection. Distinct semantics:
289
+ //
290
+ // - migrate: v10→v11 chain migration (planner-driven; refuses
291
+ // fully-unparseable, requires spec-scan).
292
+ // - rotate: lower-level maintenance rotation (admits fully-
293
+ // unparseable as evidence quarantine).
294
+ // - verify-archive: recompute archive sha256+line count vs the
295
+ // most recent chain_rotated event.
296
+ // -------------------------------------------------------------------
297
+ const eventsCmd = program.command('events');
298
+ applyGroupMeta(eventsCmd, command_metadata_1.EVENTS_COMMAND_META);
299
+ defineLeaf(eventsCmd, leafMeta(command_metadata_1.EVENTS_COMMAND_META, 'migrate'))
300
+ .action((opts) => {
301
+ if (opts.from !== 'v10') {
302
+ process.stderr.write(`caws events migrate: only --from v10 is supported in v11.2; got ${JSON.stringify(opts.from)}.\n`);
303
+ exit(1);
304
+ return;
305
+ }
306
+ const code = (0, index_1.runEventsMigrateCommand)({
307
+ from: 'v10',
308
+ ...(opts.apply === true ? { apply: true } : {}),
309
+ ...(opts.reason !== undefined ? { reason: opts.reason } : {}),
310
+ ...(opts.actorKind !== undefined
311
+ ? { actorKind: opts.actorKind }
312
+ : {}),
313
+ ...(opts.actorId !== undefined ? { actorId: opts.actorId } : {}),
314
+ ...(opts.allowPartialUpgrade === true ? { allowPartialUpgrade: true } : {}),
315
+ });
316
+ exit(code);
317
+ });
318
+ defineLeaf(eventsCmd, leafMeta(command_metadata_1.EVENTS_COMMAND_META, 'rotate'))
319
+ .action((opts) => {
320
+ const code = (0, index_1.runEventsRotateCommand)({
321
+ reason: opts.reason,
322
+ ...(opts.actorKind !== undefined
323
+ ? { actorKind: opts.actorKind }
324
+ : {}),
325
+ ...(opts.actorId !== undefined ? { actorId: opts.actorId } : {}),
326
+ ...(opts.allowClean === true ? { allowClean: true } : {}),
327
+ });
328
+ exit(code);
329
+ });
330
+ defineLeaf(eventsCmd, leafMeta(command_metadata_1.EVENTS_COMMAND_META, 'verify-archive'))
331
+ .action(() => {
332
+ const code = (0, index_1.runEventsVerifyArchiveCommand)({});
333
+ exit(code);
334
+ });
335
+ // -------------------------------------------------------------------
222
336
  // caws waiver create / list / show / revoke
223
337
  //
224
338
  // Singular `waiver` is the vNext authority surface. The legacy plural
225
339
  // `waivers` group is removed in src/index.js as part of slice 7a.4 —
226
340
  // no compatibility alias, no feature flag.
227
341
  // -------------------------------------------------------------------
228
- const waiverCmd = program
229
- .command('waiver')
230
- .description('Manage CAWS waivers (bounded exception records that suppress matching gate violations)');
231
- waiverCmd
232
- .command('create <id>')
233
- .description('Create a new active waiver. Validates against the kernel before writing.')
234
- .requiredOption('--title <title>', 'Short waiver title (≥5 chars)')
235
- .requiredOption('--gate <gate>', 'Gate id this waiver covers; repeat for multiple gates', collectMulti, [])
236
- .requiredOption('--reason <reason>', 'Justification for the waiver')
237
- .requiredOption('--approved-by <id>', 'Approver identity')
238
- .requiredOption('--expires-at <iso>', 'Expiry as an ISO-8601 datetime with timezone')
239
- .option('--spec <id>', 'Optional spec id this waiver is scoped to (omit for project-wide)')
240
- .option('--data', 'Show structured data block on diagnostics')
342
+ const waiverCmd = program.command('waiver');
343
+ applyGroupMeta(waiverCmd, command_metadata_1.WAIVER_COMMAND_META);
344
+ defineLeaf(waiverCmd, leafMeta(command_metadata_1.WAIVER_COMMAND_META, 'create'))
241
345
  .action((id, opts) => {
242
346
  const code = (0, index_1.runWaiverCreateCommand)({
243
347
  id,
@@ -251,12 +355,7 @@ function registerShellCommands(program, options = {}) {
251
355
  });
252
356
  exit(code);
253
357
  });
254
- waiverCmd
255
- .command('list')
256
- .description('List waivers. By default excludes revoked and expired records.')
257
- .option('--include-revoked', 'Include revoked waivers')
258
- .option('--include-expired', 'Include expired waivers')
259
- .option('--data', 'Show structured data block on diagnostics')
358
+ defineLeaf(waiverCmd, leafMeta(command_metadata_1.WAIVER_COMMAND_META, 'list'))
260
359
  .action((opts) => {
261
360
  const code = (0, index_1.runWaiverListCommand)({
262
361
  includeRevoked: opts.includeRevoked === true,
@@ -265,10 +364,7 @@ function registerShellCommands(program, options = {}) {
265
364
  });
266
365
  exit(code);
267
366
  });
268
- waiverCmd
269
- .command('show <id>')
270
- .description('Show a waiver, including its derived effectiveness at now.')
271
- .option('--data', 'Show structured data block on diagnostics')
367
+ defineLeaf(waiverCmd, leafMeta(command_metadata_1.WAIVER_COMMAND_META, 'show'))
272
368
  .action((id, opts) => {
273
369
  const code = (0, index_1.runWaiverShowCommand)({
274
370
  id,
@@ -276,12 +372,7 @@ function registerShellCommands(program, options = {}) {
276
372
  });
277
373
  exit(code);
278
374
  });
279
- waiverCmd
280
- .command('revoke <id>')
281
- .description('Revoke a waiver. Writes a revocation record; refuses double-revoke.')
282
- .option('--revoked-by <id>', 'Identity recorded in revocation.revoked_by')
283
- .option('--reason <reason>', 'Reason recorded in revocation.reason (recommended for audit)')
284
- .option('--data', 'Show structured data block on diagnostics')
375
+ defineLeaf(waiverCmd, leafMeta(command_metadata_1.WAIVER_COMMAND_META, 'revoke'))
285
376
  .action((id, opts) => {
286
377
  const code = (0, index_1.runWaiverRevokeCommand)({
287
378
  id,
@@ -299,31 +390,21 @@ function registerShellCommands(program, options = {}) {
299
390
  // Slice 4). The shell layer parses args + builds the actor envelope;
300
391
  // the writer owns YAML patching + event append.
301
392
  // -------------------------------------------------------------------
302
- const specsCmd = program
303
- .command('specs')
304
- .description('Manage CAWS spec lifecycle (create/list/show/close/archive)');
305
- specsCmd
306
- .command('create <id>')
307
- .description('Create a new spec in lifecycle_state: active.')
308
- .requiredOption('--title <title>', 'Short spec title')
309
- .requiredOption('--mode <mode>', 'Spec mode: feature | refactor | fix | doc | chore')
310
- .requiredOption('--risk-tier <n>', 'Risk tier: 1, 2, or 3')
311
- .option('--data', 'Show structured data block on diagnostics')
393
+ const specsCmd = program.command('specs');
394
+ applyGroupMeta(specsCmd, command_metadata_1.SPECS_COMMAND_META);
395
+ defineLeaf(specsCmd, leafMeta(command_metadata_1.SPECS_COMMAND_META, 'create'))
312
396
  .action((id, opts) => {
313
397
  const code = (0, index_1.runSpecsCreateCommand)({
314
398
  id,
315
- title: opts.title,
316
- mode: opts.mode,
317
- riskTier: opts.riskTier,
399
+ ...(opts.title !== undefined ? { title: opts.title } : {}),
400
+ ...(opts.mode !== undefined ? { mode: opts.mode } : {}),
401
+ ...(opts.riskTier !== undefined ? { riskTier: opts.riskTier } : {}),
402
+ ...(opts.type !== undefined ? { legacyType: opts.type } : {}),
318
403
  showData: opts.data === true,
319
404
  });
320
405
  exit(code);
321
406
  });
322
- specsCmd
323
- .command('list')
324
- .description('List specs. By default excludes archived specs.')
325
- .option('--archived', 'Include archived specs in the listing')
326
- .option('--data', 'Show structured data block on diagnostics')
407
+ defineLeaf(specsCmd, leafMeta(command_metadata_1.SPECS_COMMAND_META, 'list'))
327
408
  .action((opts) => {
328
409
  const code = (0, index_1.runSpecsListCommand)({
329
410
  includeArchived: opts.archived === true,
@@ -331,25 +412,42 @@ function registerShellCommands(program, options = {}) {
331
412
  });
332
413
  exit(code);
333
414
  });
334
- specsCmd
335
- .command('show <id>')
336
- .description('Show a spec by id (searches active and archived locations).')
337
- .option('--data', 'Show structured data block on diagnostics')
415
+ defineLeaf(specsCmd, leafMeta(command_metadata_1.SPECS_COMMAND_META, 'show'))
338
416
  .action((id, opts) => {
339
417
  const code = (0, index_1.runSpecsShowCommand)({
340
418
  id,
341
419
  showData: opts.data === true,
420
+ ...(opts.archived === true ? { archived: true } : {}),
421
+ });
422
+ exit(code);
423
+ });
424
+ defineLeaf(specsCmd, leafMeta(command_metadata_1.SPECS_COMMAND_META, 'recover'))
425
+ .action((id, opts) => {
426
+ const code = (0, index_1.runSpecsRecoverCommand)({
427
+ id,
428
+ showData: opts.data === true,
429
+ ...(typeof opts.out === 'string' && opts.out.length > 0 ? { outPath: opts.out } : {}),
430
+ });
431
+ exit(code);
432
+ });
433
+ defineLeaf(specsCmd, leafMeta(command_metadata_1.SPECS_COMMAND_META, 'retire-draft'))
434
+ .action((id, opts) => {
435
+ const code = (0, index_1.runSpecsRetireDraftCommand)({
436
+ id,
437
+ ...(opts.reason !== undefined ? { reason: opts.reason } : {}),
438
+ showData: opts.data === true,
342
439
  });
343
440
  exit(code);
344
441
  });
345
- specsCmd
346
- .command('close <id>')
347
- .description('Close an active spec. Non-destructive raw-byte YAML patch; appends spec_closed event.')
348
- .requiredOption('--resolution <r>', 'Resolution: completed | superseded | abandoned')
349
- .option('--reason <text>', 'Closure notes recorded on the spec YAML and the spec_closed event')
350
- .option('--merge-commit <sha>', 'Optional merge commit SHA (e.g., when closure follows a worktree merge)')
351
- .option('--superseded-by <id>', 'Spec id that supersedes this one (use with --resolution superseded)')
352
- .option('--data', 'Show structured data block on diagnostics')
442
+ defineLeaf(specsCmd, leafMeta(command_metadata_1.SPECS_COMMAND_META, 'activate'))
443
+ .action((id, opts) => {
444
+ const code = (0, index_1.runSpecsActivateCommand)({
445
+ id,
446
+ showData: opts.data === true,
447
+ });
448
+ exit(code);
449
+ });
450
+ defineLeaf(specsCmd, leafMeta(command_metadata_1.SPECS_COMMAND_META, 'close'))
353
451
  .action((id, opts) => {
354
452
  const code = (0, index_1.runSpecsCloseCommand)({
355
453
  id,
@@ -365,11 +463,7 @@ function registerShellCommands(program, options = {}) {
365
463
  });
366
464
  exit(code);
367
465
  });
368
- specsCmd
369
- .command('archive <id>')
370
- .description('Archive a closed spec. Moves the YAML file to .caws/specs/.archive/; appends spec_archived event.')
371
- .option('--reason <text>', 'Archive reason (advisory; spec_archived schema does not carry it)')
372
- .option('--data', 'Show structured data block on diagnostics')
466
+ defineLeaf(specsCmd, leafMeta(command_metadata_1.SPECS_COMMAND_META, 'archive'))
373
467
  .action((id, opts) => {
374
468
  const code = (0, index_1.runSpecsArchiveCommand)({
375
469
  id,
@@ -378,6 +472,28 @@ function registerShellCommands(program, options = {}) {
378
472
  });
379
473
  exit(code);
380
474
  });
475
+ defineLeaf(specsCmd, leafMeta(command_metadata_1.SPECS_COMMAND_META, 'prune-archive'))
476
+ .action((opts) => {
477
+ const code = (0, index_1.runSpecsPruneArchiveCommand)({
478
+ ...(opts.apply === true ? { apply: true } : {}),
479
+ showData: opts.data === true,
480
+ });
481
+ exit(code);
482
+ });
483
+ defineLeaf(specsCmd, leafMeta(command_metadata_1.SPECS_COMMAND_META, 'migrate'))
484
+ .action((opts) => {
485
+ const code = (0, index_1.runSpecsMigrateCommand)({
486
+ from: opts.from,
487
+ apply: opts.apply === true,
488
+ partial: opts.partial === true,
489
+ ...(opts.lifecycleMapping !== undefined
490
+ ? { lifecycleMappingPath: opts.lifecycleMapping }
491
+ : {}),
492
+ json: opts.json === true,
493
+ showData: opts.data === true,
494
+ });
495
+ exit(code);
496
+ });
381
497
  // -------------------------------------------------------------------
382
498
  // caws worktree (CLI-WORKTREE-001)
383
499
  //
@@ -386,16 +502,9 @@ function registerShellCommands(program, options = {}) {
386
502
  // substrate from Slice 4 + applyRegistryPatch + specs-writer.closeSpec
387
503
  // for auto-close on merge).
388
504
  // -------------------------------------------------------------------
389
- const worktreeCmd = program
390
- .command('worktree')
391
- .description('Manage CAWS worktrees (create/list/bind/destroy/merge). Worktrees are git worktrees bound to active specs.');
392
- worktreeCmd
393
- .command('create <name>')
394
- .description('Create a new git worktree under .caws/worktrees/<name> bound to an active spec.')
395
- .requiredOption('--spec <id>', 'Active spec id to bind the worktree to')
396
- .option('--base-branch <branch>', 'Base branch to start from (default: current branch)')
397
- .option('--branch <branch>', 'New branch name (default: worktree name)')
398
- .option('--data', 'Show structured data block on diagnostics')
505
+ const worktreeCmd = program.command('worktree');
506
+ applyGroupMeta(worktreeCmd, command_metadata_1.WORKTREE_COMMAND_META);
507
+ defineLeaf(worktreeCmd, leafMeta(command_metadata_1.WORKTREE_COMMAND_META, 'create'))
399
508
  .action((name, opts) => {
400
509
  const code = (0, index_1.runWorktreeCreateCommand)({
401
510
  name,
@@ -406,19 +515,12 @@ function registerShellCommands(program, options = {}) {
406
515
  });
407
516
  exit(code);
408
517
  });
409
- worktreeCmd
410
- .command('list')
411
- .description('List registered worktrees with branch, spec binding, and owner.')
412
- .option('--data', 'Show structured data block on diagnostics')
518
+ defineLeaf(worktreeCmd, leafMeta(command_metadata_1.WORKTREE_COMMAND_META, 'list'))
413
519
  .action((opts) => {
414
520
  const code = (0, index_1.runWorktreeListCommand)({ showData: opts.data === true });
415
521
  exit(code);
416
522
  });
417
- worktreeCmd
418
- .command('bind <name>')
419
- .description('Repair bidirectional binding between a worktree and a spec (one-sided → bound).')
420
- .requiredOption('--spec <id>', 'Spec id to bind the worktree to')
421
- .option('--data', 'Show structured data block on diagnostics')
523
+ defineLeaf(worktreeCmd, leafMeta(command_metadata_1.WORKTREE_COMMAND_META, 'bind'))
422
524
  .action((name, opts) => {
423
525
  const code = (0, index_1.runWorktreeBindCommand)({
424
526
  name,
@@ -427,11 +529,7 @@ function registerShellCommands(program, options = {}) {
427
529
  });
428
530
  exit(code);
429
531
  });
430
- worktreeCmd
431
- .command('destroy <name>')
432
- .description('Destroy a worktree. Non-forceful: refuses foreign ownership, dirty checkout, unmerged branch (use --abandon-unmerged to override branch check only).')
433
- .option('--abandon-unmerged', 'Destroy even when the branch is not merged into base. Still respects ownership and clean working tree.')
434
- .option('--data', 'Show structured data block on diagnostics')
532
+ defineLeaf(worktreeCmd, leafMeta(command_metadata_1.WORKTREE_COMMAND_META, 'destroy'))
435
533
  .action((name, opts) => {
436
534
  const code = (0, index_1.runWorktreeDestroyCommand)({
437
535
  name,
@@ -440,12 +538,7 @@ function registerShellCommands(program, options = {}) {
440
538
  });
441
539
  exit(code);
442
540
  });
443
- worktreeCmd
444
- .command('merge <name>')
445
- .description('Merge a worktree branch into its base. Auto-closes the bound spec via caws specs close.')
446
- .option('--dry-run', 'Validate prerequisites only; no git, no file writes, no events')
447
- .option('--message <text>', 'Custom merge commit message (default: merge(worktree): <name>)')
448
- .option('--data', 'Show structured data block on diagnostics')
541
+ defineLeaf(worktreeCmd, leafMeta(command_metadata_1.WORKTREE_COMMAND_META, 'merge'))
449
542
  .action((name, opts) => {
450
543
  const code = (0, index_1.runWorktreeMergeCommand)({
451
544
  name,
@@ -455,10 +548,102 @@ function registerShellCommands(program, options = {}) {
455
548
  });
456
549
  exit(code);
457
550
  });
458
- }
459
- /** Commander value collector for repeatable string options. */
460
- function collectMulti(value, prev) {
461
- prev.push(value);
462
- return prev;
551
+ defineLeaf(worktreeCmd, leafMeta(command_metadata_1.WORKTREE_COMMAND_META, 'migrate-registry'))
552
+ .action((opts) => {
553
+ const code = (0, index_1.runWorktreeMigrateRegistryCommand)({
554
+ ...(opts.dryRun === true ? { dryRun: true } : {}),
555
+ showData: opts.data === true,
556
+ });
557
+ exit(code);
558
+ });
559
+ defineLeaf(worktreeCmd, leafMeta(command_metadata_1.WORKTREE_COMMAND_META, 'repair-sparse'))
560
+ .action((name, opts) => {
561
+ const code = (0, index_1.runWorktreeRepairSparseCommand)({
562
+ name,
563
+ showData: opts.data === true,
564
+ });
565
+ exit(code);
566
+ });
567
+ // ─── caws agents (MULTI-AGENT-ACTIVITY-REGISTRY-001) ────────────────────
568
+ const agentsCmd = program.command('agents');
569
+ applyGroupMeta(agentsCmd, command_metadata_1.AGENTS_COMMAND_META);
570
+ defineLeaf(agentsCmd, leafMeta(command_metadata_1.AGENTS_COMMAND_META, 'register'))
571
+ .action((opts) => {
572
+ const code = (0, index_1.runAgentsRegisterCommand)({
573
+ ...(opts.sessionId !== undefined ? { sessionId: opts.sessionId } : {}),
574
+ ...(opts.platform !== undefined ? { platform: opts.platform } : {}),
575
+ ...(opts.reason !== undefined ? { reason: opts.reason } : {}),
576
+ json: opts.json === true,
577
+ includeActiveSummary: opts.includeActiveSummary === true,
578
+ showData: opts.data === true,
579
+ });
580
+ exit(code);
581
+ });
582
+ defineLeaf(agentsCmd, leafMeta(command_metadata_1.AGENTS_COMMAND_META, 'heartbeat'))
583
+ .action((opts) => {
584
+ const throttleMs = opts.throttle !== undefined ? Number(opts.throttle) : 0;
585
+ const code = (0, index_1.runAgentsHeartbeatCommand)({
586
+ ...(opts.sessionId !== undefined ? { sessionId: opts.sessionId } : {}),
587
+ ...(opts.platform !== undefined ? { platform: opts.platform } : {}),
588
+ ...(opts.reason !== undefined ? { reason: opts.reason } : {}),
589
+ throttleMs: Number.isFinite(throttleMs) && throttleMs > 0 ? throttleMs : 0,
590
+ json: opts.json === true,
591
+ includeActiveSummary: opts.includeActiveSummary === true,
592
+ showData: opts.data === true,
593
+ });
594
+ exit(code);
595
+ });
596
+ defineLeaf(agentsCmd, leafMeta(command_metadata_1.AGENTS_COMMAND_META, 'stop'))
597
+ .action((opts) => {
598
+ const code = (0, index_1.runAgentsStopCommand)({
599
+ ...(opts.sessionId !== undefined ? { sessionId: opts.sessionId } : {}),
600
+ ...(opts.platform !== undefined ? { platform: opts.platform } : {}),
601
+ json: opts.json === true,
602
+ showData: opts.data === true,
603
+ });
604
+ exit(code);
605
+ });
606
+ defineLeaf(agentsCmd, leafMeta(command_metadata_1.AGENTS_COMMAND_META, 'list'))
607
+ .action((opts) => {
608
+ const ttl = opts.staleTtlMs !== undefined ? Number(opts.staleTtlMs) : undefined;
609
+ const code = (0, index_1.runAgentsListCommand)({
610
+ includeStale: opts.includeStale === true,
611
+ includeStopped: opts.includeStopped === true,
612
+ activeOnly: opts.active === true,
613
+ ...(ttl !== undefined && Number.isFinite(ttl) ? { staleTtlMs: ttl } : {}),
614
+ json: opts.json === true,
615
+ showData: opts.data === true,
616
+ });
617
+ exit(code);
618
+ });
619
+ defineLeaf(agentsCmd, leafMeta(command_metadata_1.AGENTS_COMMAND_META, 'show'))
620
+ .action((id, opts) => {
621
+ const code = (0, index_1.runAgentsShowCommand)({
622
+ id,
623
+ json: opts.json === true,
624
+ showData: opts.data === true,
625
+ });
626
+ exit(code);
627
+ });
628
+ defineLeaf(agentsCmd, leafMeta(command_metadata_1.AGENTS_COMMAND_META, 'prune'))
629
+ .action((opts) => {
630
+ const status = opts.status === 'stopped' || opts.status === 'stale' ? opts.status : null;
631
+ const olderThanMs = Number(opts.olderThanMs);
632
+ if (status === null || !Number.isFinite(olderThanMs)) {
633
+ process.stderr.write('caws agents prune: --status must be stopped|stale and --older-than-ms must be a number.\n');
634
+ exit(1);
635
+ return;
636
+ }
637
+ const staleTtl = opts.staleTtlMs !== undefined ? Number(opts.staleTtlMs) : undefined;
638
+ const code = (0, index_1.runAgentsPruneCommand)({
639
+ status,
640
+ olderThanMs,
641
+ ...(staleTtl !== undefined && Number.isFinite(staleTtl) ? { staleTtlMs: staleTtl } : {}),
642
+ apply: opts.apply === true,
643
+ json: opts.json === true,
644
+ showData: opts.data === true,
645
+ });
646
+ exit(code);
647
+ });
463
648
  }
464
649
  //# sourceMappingURL=register.js.map