@astrosheep/keiyaku 2.9.11 → 2.9.13

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 (218) hide show
  1. package/README.md +79 -85
  2. package/build/.tsbuildinfo +1 -1
  3. package/build/agents/call-terms.js +1 -0
  4. package/build/agents/providers/claude-agent-sdk/adapter.js +17 -4
  5. package/build/cli/commands/akuma/akuma/handler.js +2 -1
  6. package/build/cli/commands/akuma/akuma/meta.js +4 -3
  7. package/build/cli/commands/akuma/catalog.js +2 -0
  8. package/build/cli/commands/akuma/list/handler.js +1 -1
  9. package/build/cli/commands/akuma/list/meta-list.js +12 -0
  10. package/build/cli/commands/akuma/list/meta-ls.js +2 -2
  11. package/build/cli/commands/akuma.js +5 -0
  12. package/build/cli/commands/contract/amend/meta.js +4 -3
  13. package/build/cli/commands/contract/arc/meta.js +2 -0
  14. package/build/cli/commands/contract/audit/handler.js +28 -2
  15. package/build/cli/commands/contract/audit/meta.js +4 -3
  16. package/build/cli/commands/contract/bind/meta.js +4 -4
  17. package/build/cli/commands/contract/petition/handler.js +2 -1
  18. package/build/cli/commands/contract/petition/meta.js +2 -2
  19. package/build/cli/commands/contract/renew/handler.js +44 -3
  20. package/build/cli/commands/contract/renew/meta.js +5 -4
  21. package/build/cli/commands/metadata.js +14 -10
  22. package/build/cli/commands/projection/call/handler.js +1 -1
  23. package/build/cli/commands/projection/call/meta.js +1 -1
  24. package/build/cli/commands/projection/catalog.js +2 -2
  25. package/build/cli/commands/projection/{revive → fork}/handler.js +10 -5
  26. package/build/cli/commands/projection/fork/meta.js +12 -0
  27. package/build/cli/commands/projection/history/handler.js +46 -2
  28. package/build/cli/commands/projection/history/meta.js +3 -3
  29. package/build/cli/commands/projection/kill/handler.js +4 -5
  30. package/build/cli/commands/projection/kill/meta.js +2 -2
  31. package/build/cli/commands/projection/status/handler.js +29 -13
  32. package/build/cli/commands/projection/status/meta.js +14 -3
  33. package/build/cli/commands/projection/tell/handler.js +8 -4
  34. package/build/cli/commands/projection/tell/meta.js +1 -1
  35. package/build/cli/commands/projection/wait/handler.js +45 -20
  36. package/build/cli/commands/projection/wait/meta.js +1 -1
  37. package/build/cli/commands/shared.js +2 -2
  38. package/build/cli/commands/system/catalog.js +2 -0
  39. package/build/cli/commands/task/add/handler.js +28 -12
  40. package/build/cli/commands/task/add/meta.js +18 -6
  41. package/build/cli/commands/task/catalog.js +4 -0
  42. package/build/cli/commands/task/compose/handler.js +18 -0
  43. package/build/cli/commands/task/compose/meta.js +10 -0
  44. package/build/cli/commands/task/doctor/handler.js +2 -3
  45. package/build/cli/commands/task/doctor/meta.js +2 -2
  46. package/build/cli/commands/task/done/meta.js +2 -2
  47. package/build/cli/commands/task/drop/handler.js +7 -2
  48. package/build/cli/commands/task/drop/meta.js +6 -3
  49. package/build/cli/commands/task/hold/meta.js +2 -2
  50. package/build/cli/commands/task/log/meta.js +2 -2
  51. package/build/cli/commands/task/ls/meta.js +2 -2
  52. package/build/cli/commands/task/note/handler.js +6 -0
  53. package/build/cli/commands/task/note/meta.js +11 -0
  54. package/build/cli/commands/task/resume/meta.js +2 -2
  55. package/build/cli/commands/task/shared.js +29 -15
  56. package/build/cli/commands/task/show/meta.js +2 -2
  57. package/build/cli/commands/task/start/meta.js +2 -2
  58. package/build/cli/commands/task/stop/meta.js +2 -2
  59. package/build/cli/commands/task/update/meta.js +3 -2
  60. package/build/cli/commands/verification/handler.js +43 -0
  61. package/build/cli/commands/verification/meta.js +13 -0
  62. package/build/cli/completion.js +16 -13
  63. package/build/cli/flags.js +48 -12
  64. package/build/cli/help.js +29 -30
  65. package/build/cli/index.js +14 -8
  66. package/build/cli/parse-flags.js +60 -21
  67. package/build/cli/parse-metadata.js +10 -4
  68. package/build/cli/parse-selectors.js +22 -4
  69. package/build/cli/parse.js +43 -30
  70. package/build/cli/projection-address.js +7 -7
  71. package/build/cli/render/arc.js +12 -3
  72. package/build/cli/render/audit.js +2 -2
  73. package/build/cli/render/call.js +4 -4
  74. package/build/cli/render/kanshi.js +122 -85
  75. package/build/cli/render/misc.js +2 -2
  76. package/build/cli/render/petition.js +16 -1
  77. package/build/cli/render/projection-history.js +17 -4
  78. package/build/cli/render/shared.js +5 -5
  79. package/build/cli/render/status-indicator.js +47 -0
  80. package/build/cli/render/status.js +106 -76
  81. package/build/cli/render/success-response.js +20 -5
  82. package/build/cli/render/task.js +33 -5
  83. package/build/cli/render/tell.js +10 -4
  84. package/build/cli/render/tool-command-normalization.js +137 -0
  85. package/build/cli/render/tool-presentation.js +2 -1
  86. package/build/cli/render/verification.js +23 -0
  87. package/build/cli/render/wait.js +101 -33
  88. package/build/cli/types.js +2 -1
  89. package/build/config/akuma-loader.js +21 -1
  90. package/build/config/settings/knobs.js +7 -1
  91. package/build/config/settings/schema.js +10 -5
  92. package/build/core/addressing.js +3 -3
  93. package/build/core/amend.js +102 -17
  94. package/build/core/arc.js +4 -4
  95. package/build/core/audit/candidate.js +10 -18
  96. package/build/core/audit/coordinates.js +12 -17
  97. package/build/core/audit/evidence.js +6 -4
  98. package/build/core/audit/facade.js +3 -3
  99. package/build/core/audit/report.js +1 -1
  100. package/build/core/bind-reconciliation.js +42 -23
  101. package/build/core/bind.js +182 -81
  102. package/build/core/call/call.js +6 -7
  103. package/build/core/call/context.js +46 -33
  104. package/build/core/call/execution.js +21 -6
  105. package/build/core/call/prompt.js +11 -42
  106. package/build/core/contract-carrier-runtime.js +209 -105
  107. package/build/core/contract-carrier.js +156 -73
  108. package/build/core/contract-view.js +43 -6
  109. package/build/core/contract.js +2 -1
  110. package/build/core/derived-replay.js +168 -35
  111. package/build/core/draft.js +60 -27
  112. package/build/core/forfeit.js +1 -1
  113. package/build/core/lifecycle-history.js +13 -0
  114. package/build/core/lifecycle-recovery.js +32 -27
  115. package/build/core/lifecycle-runner.js +14 -14
  116. package/build/core/log.js +1 -1
  117. package/build/core/outcome-base.js +2 -2
  118. package/build/core/projection/akuma-name.js +43 -0
  119. package/build/core/projection/generation/database.js +141 -79
  120. package/build/core/projection/generation/ledger.js +91 -0
  121. package/build/core/projection/generation/model.js +19 -14
  122. package/build/core/projection/generation/projection-generation-continuation.js +1 -1
  123. package/build/core/projection/generation/projection-generation-doorbell.js +88 -0
  124. package/build/core/projection/generation/projection-generation-execution.js +24 -0
  125. package/build/core/projection/generation/projection-generation-identity.js +4 -0
  126. package/build/core/projection/generation/projection-generation-launcher.js +72 -138
  127. package/build/core/projection/generation/projection-generation-process.js +16 -15
  128. package/build/core/projection/generation/projection-generation-runner.js +132 -76
  129. package/build/core/projection/generation/projection-generation-runtime.js +10 -61
  130. package/build/core/projection/generation/protocol.js +68 -0
  131. package/build/core/projection/generation/store.js +17 -7
  132. package/build/core/projection/generation/transitions.js +24 -14
  133. package/build/core/projection/index.js +5 -5
  134. package/build/core/projection/projection-core.js +6 -2
  135. package/build/core/projection/projection-execution-observer.js +1 -1
  136. package/build/core/projection/projection-history.js +8 -8
  137. package/build/core/projection/projection-kill.js +20 -10
  138. package/build/core/projection/projection-life-observer.js +8 -8
  139. package/build/core/projection/projection-mint.js +6 -8
  140. package/build/core/projection/projection-status-observation.js +77 -8
  141. package/build/core/projection/projection-status.js +151 -4
  142. package/build/core/projection/projection-wait.js +48 -29
  143. package/build/core/projection/projection-wake.js +28 -88
  144. package/build/core/projection/tell/launch-store.js +1 -1
  145. package/build/core/projection/tell/store.js +1 -1
  146. package/build/core/renew-build.js +204 -74
  147. package/build/core/renew-plan.js +34 -9
  148. package/build/core/renew-rewrite.js +56 -15
  149. package/build/core/renew.js +39 -35
  150. package/build/core/repository-ledger/accepted-fold-read.js +6 -3
  151. package/build/core/repository-ledger/claim-evidence.js +1 -1
  152. package/build/core/repository-ledger/codec.js +11 -5
  153. package/build/core/repository-ledger/current-state-store.js +464 -349
  154. package/build/core/repository-ledger/fold-repository.js +5 -6
  155. package/build/core/repository-ledger/identity.js +60 -0
  156. package/build/core/repository-ledger/inventory.js +3 -3
  157. package/build/core/repository-ledger/read-model.js +57 -9
  158. package/build/core/repository-ledger/write-transaction.js +24 -17
  159. package/build/core/run-control/connection-bound-close.js +41 -0
  160. package/build/core/run-control/detached-lease-bootstrap.js +208 -0
  161. package/build/core/run-control/detached-process.js +14 -0
  162. package/build/core/run-control/index.js +6 -0
  163. package/build/core/{process-group.js → run-control/process-tree.js} +1 -1
  164. package/build/core/run-control/runner-lease.js +172 -0
  165. package/build/core/run-control/sqlite-process-lifetime-lock.js +174 -0
  166. package/build/core/seal.js +44 -32
  167. package/build/core/settlement/claim-delivery.js +22 -9
  168. package/build/core/settlement/claim.js +8 -6
  169. package/build/core/settlement/petition-claim-gates.js +9 -8
  170. package/build/core/settlement/petition-head-guard.js +5 -6
  171. package/build/core/settlement/petition-preview.js +21 -5
  172. package/build/core/settlement/petition.js +51 -17
  173. package/build/core/settlement/settlement.js +20 -15
  174. package/build/core/settlement/verdict.js +2 -2
  175. package/build/core/settlement/verification.js +492 -364
  176. package/build/core/status/board.js +184 -75
  177. package/build/core/status/drift.js +8 -10
  178. package/build/core/task/board.js +1 -0
  179. package/build/core/task/commands.js +25 -0
  180. package/build/core/task/compose.js +328 -0
  181. package/build/core/task/document.js +102 -39
  182. package/build/core/task/index.js +4 -3
  183. package/build/core/task/settlement-git.js +70 -30
  184. package/build/core/task/settlement-policy.js +27 -14
  185. package/build/core/task/source-board.js +1 -0
  186. package/build/core/task/task-bind-preparation.js +59 -9
  187. package/build/core/task/task-contract.js +2 -2
  188. package/build/core/task/task-git-store.js +1 -0
  189. package/build/core/task/task-store-repository.js +2 -0
  190. package/build/core/task/task.js +2 -2
  191. package/build/core/transcripts.js +4 -4
  192. package/build/core/verification-declaration.js +95 -0
  193. package/build/core/worktree-bootstrap.js +1 -1
  194. package/build/core/worktree-path.js +7 -11
  195. package/build/flow-error.js +15 -2
  196. package/build/generated/version.js +2 -2
  197. package/build/git/branches.js +41 -70
  198. package/build/git/commits.js +92 -21
  199. package/build/git/core.js +9 -161
  200. package/build/git/diff/preview.js +4 -4
  201. package/build/git/diff/read.js +4 -4
  202. package/build/git/diff/structured.js +5 -5
  203. package/build/git/process.js +229 -0
  204. package/build/git/refs.js +30 -5
  205. package/build/git/staging.js +39 -115
  206. package/build/git/streaming-batch.js +9 -16
  207. package/build/git/worktree.js +104 -91
  208. package/build/index.js +7 -0
  209. package/package.json +2 -2
  210. package/skills/keiyaku-akuma/SKILL.md +27 -21
  211. package/skills/keiyaku-task/SKILL.md +61 -5
  212. package/skills/keiyaku-workflow/SKILL.md +81 -26
  213. package/build/cli/commands/projection/revive/meta.js +0 -12
  214. package/build/core/projection/projection-life-protocol.js +0 -115
  215. package/build/core/projection/projection-runner-lock.js +0 -382
  216. package/build/core/projection/tell/database.js +0 -127
  217. package/build/core/settlement/verification-coordination.js +0 -305
  218. package/build/core/settlement/verification-supervisor.js +0 -275
@@ -11,7 +11,7 @@ export function parseFlagName(raw) {
11
11
  }
12
12
  export function assertAllowedFlag(command, name) {
13
13
  if (!allowedFlagsForParse(command).includes(name)) {
14
- throw new FlowError("EMPTY_PARAM", `option --${name} is not valid for ${command}`);
14
+ throw new FlowError("UNKNOWN_OPTION", `option --${name} is not valid for ${command}`);
15
15
  }
16
16
  }
17
17
  export function assignFlag(flags, name, value) {
@@ -65,43 +65,40 @@ export function assignFlag(flags, name, value) {
65
65
  return;
66
66
  case "place":
67
67
  if (flags.bindPlace !== undefined) {
68
- throw new FlowError("EMPTY_PARAM", "option --place may only be specified once");
68
+ throw new FlowError("INVALID_USAGE", "option --place may only be specified once");
69
69
  }
70
70
  flags.bindPlace = String(value);
71
71
  return;
72
72
  case "objective":
73
73
  if (flags.bindObjective !== undefined) {
74
- throw new FlowError("EMPTY_PARAM", "option --objective may only be specified once");
74
+ throw new FlowError("INVALID_USAGE", "option --objective may only be specified once");
75
75
  }
76
76
  flags.bindObjective = String(value);
77
77
  return;
78
78
  case "context":
79
79
  if (flags.bindContext !== undefined) {
80
- throw new FlowError("EMPTY_PARAM", "option --context may only be specified once");
80
+ throw new FlowError("INVALID_USAGE", "option --context may only be specified once");
81
81
  }
82
82
  flags.bindContext = String(value);
83
83
  return;
84
84
  case "design":
85
85
  if (flags.bindDesign !== undefined) {
86
- throw new FlowError("EMPTY_PARAM", "option --design may only be specified once");
86
+ throw new FlowError("INVALID_USAGE", "option --design may only be specified once");
87
87
  }
88
88
  flags.bindDesign = String(value);
89
89
  return;
90
90
  case "scope":
91
- if (flags.bindScope !== undefined) {
92
- throw new FlowError("EMPTY_PARAM", "option --scope may only be specified once");
93
- }
94
- flags.bindScope = String(value);
91
+ flags.bindScope = [...(flags.bindScope ?? []), String(value)];
95
92
  return;
96
93
  case "criteria":
97
94
  if (flags.bindCriteria !== undefined) {
98
- throw new FlowError("EMPTY_PARAM", "option --criteria may only be specified once");
95
+ throw new FlowError("INVALID_USAGE", "option --criteria may only be specified once");
99
96
  }
100
97
  flags.bindCriteria = String(value);
101
98
  return;
102
99
  case "verification":
103
100
  if (flags.bindVerification !== undefined) {
104
- throw new FlowError("EMPTY_PARAM", "option --verification may only be specified once");
101
+ throw new FlowError("INVALID_USAGE", "option --verification may only be specified once");
105
102
  }
106
103
  flags.bindVerification = String(value);
107
104
  return;
@@ -120,12 +117,18 @@ export function assignFlag(flags, name, value) {
120
117
  case "dry-run":
121
118
  flags.dryRun = Boolean(value);
122
119
  return;
120
+ case "check":
121
+ flags.check = Boolean(value);
122
+ return;
123
123
  case "append-scope":
124
124
  flags.appendScope = [...(flags.appendScope ?? []), String(value)];
125
125
  return;
126
126
  case "renew":
127
127
  flags.renewBeforePetition = Boolean(value);
128
128
  return;
129
+ case "audit":
130
+ flags.renewAudit = Boolean(value);
131
+ return;
129
132
  case "continue":
130
133
  flags.renewContinue = Boolean(value);
131
134
  return;
@@ -152,7 +155,7 @@ export function assignFlag(flags, name, value) {
152
155
  return;
153
156
  case "target":
154
157
  if (flags.target !== undefined) {
155
- throw new FlowError("EMPTY_PARAM", "option --target may only be specified once");
158
+ throw new FlowError("INVALID_USAGE", "option --target may only be specified once");
156
159
  }
157
160
  flags.target = String(value);
158
161
  return;
@@ -162,11 +165,14 @@ export function assignFlag(flags, name, value) {
162
165
  case "diff-budget": {
163
166
  const parsed = Number(String(value));
164
167
  if (!Number.isSafeInteger(parsed) || parsed < 0) {
165
- throw new FlowError("EMPTY_PARAM", "option --diff-budget requires a non-negative safe integer byte count");
168
+ throw new FlowError("INVALID_USAGE", "option --diff-budget requires a non-negative safe integer byte count");
166
169
  }
167
170
  flags.auditDiffBudgetBytes = parsed;
168
171
  return;
169
172
  }
173
+ case "skip-diff-body":
174
+ flags.auditSkipDiffBody = Boolean(value);
175
+ return;
170
176
  case "done":
171
177
  flags.done = Boolean(value);
172
178
  return;
@@ -175,17 +181,44 @@ export function assignFlag(flags, name, value) {
175
181
  return;
176
182
  case "sort":
177
183
  if (flags.taskSort !== undefined) {
178
- throw new FlowError("EMPTY_PARAM", "option --sort may only be specified once");
184
+ throw new FlowError("INVALID_USAGE", "option --sort may only be specified once");
179
185
  }
180
186
  flags.taskSort = String(value);
181
187
  return;
188
+ case "limit": {
189
+ const parsed = Number(String(value));
190
+ if (!Number.isSafeInteger(parsed) || parsed < 1) {
191
+ throw new FlowError("INVALID_USAGE", "option --limit requires a positive safe integer entry count");
192
+ }
193
+ flags.historyLimit = parsed;
194
+ return;
195
+ }
196
+ case "offset": {
197
+ const parsed = Number(String(value));
198
+ if (!Number.isSafeInteger(parsed) || parsed < 0) {
199
+ throw new FlowError("INVALID_USAGE", "option --offset requires a non-negative safe integer entry count");
200
+ }
201
+ flags.historyOffset = parsed;
202
+ return;
203
+ }
204
+ case "entry": {
205
+ const parsed = Number(String(value));
206
+ if (!Number.isSafeInteger(parsed) || parsed < 0) {
207
+ throw new FlowError("INVALID_USAGE", "option --entry requires a non-negative safe integer retained entry index");
208
+ }
209
+ flags.historyEntry = parsed;
210
+ return;
211
+ }
212
+ case "raw":
213
+ flags.historyRaw = Boolean(value);
214
+ return;
182
215
  case "pri": {
183
216
  const raw = String(value);
184
217
  if (!/^[0-3]$/.test(raw)) {
185
- throw new FlowError("EMPTY_PARAM", "task priority must be an integer from 0 through 3");
218
+ throw new FlowError("INVALID_USAGE", "task priority must be an integer from 0 through 3");
186
219
  }
187
220
  if (flags.taskPri !== undefined) {
188
- throw new FlowError("EMPTY_PARAM", "option --pri may only be specified once");
221
+ throw new FlowError("INVALID_USAGE", "option --pri may only be specified once");
189
222
  }
190
223
  flags.taskPri = Number(raw);
191
224
  return;
@@ -213,7 +246,7 @@ export function assignFlag(flags, name, value) {
213
246
  return;
214
247
  case "parent":
215
248
  if (flags.taskParent !== undefined) {
216
- throw new FlowError("EMPTY_PARAM", "option --parent may only be specified once");
249
+ throw new FlowError("INVALID_USAGE", "option --parent may only be specified once");
217
250
  }
218
251
  flags.taskParent = String(value);
219
252
  return;
@@ -222,24 +255,30 @@ export function assignFlag(flags, name, value) {
222
255
  return;
223
256
  case "title":
224
257
  if (flags.taskTitle !== undefined) {
225
- throw new FlowError("EMPTY_PARAM", "option --title may only be specified once");
258
+ throw new FlowError("INVALID_USAGE", "option --title may only be specified once");
226
259
  }
227
260
  flags.taskTitle = String(value);
228
261
  return;
229
262
  case "body":
230
263
  if (flags.taskBody !== undefined) {
231
- throw new FlowError("EMPTY_PARAM", "option --body may only be specified once");
264
+ throw new FlowError("INVALID_USAGE", "option --body may only be specified once");
232
265
  }
233
266
  flags.taskBody = String(value);
234
267
  return;
235
268
  case "append":
236
269
  if (flags.taskAppend !== undefined) {
237
- throw new FlowError("EMPTY_PARAM", "option --append may only be specified once");
270
+ throw new FlowError("INVALID_USAGE", "option --append may only be specified once");
238
271
  }
239
272
  flags.taskAppend = String(value);
240
273
  return;
274
+ case "note":
275
+ if (flags.taskNote !== undefined) {
276
+ throw new FlowError("INVALID_USAGE", "option --note may only be specified once");
277
+ }
278
+ flags.taskNote = String(value);
279
+ return;
241
280
  default:
242
- throw new FlowError("EMPTY_PARAM", `unknown option: --${name}`);
281
+ throw new FlowError("UNKNOWN_OPTION", `unknown option: --${name}`);
243
282
  }
244
283
  }
245
284
  export function readValueFlag(name, token, eq, tokens, index) {
@@ -45,13 +45,13 @@ export function isPetitionDryRunInvocation(tokens) {
45
45
  export function parseWaitTimeout(value) {
46
46
  const matched = /^(?<amount>[1-9][0-9]*)(?<unit>[smh])$/.exec(value);
47
47
  if (!matched?.groups) {
48
- throw new FlowError("EMPTY_PARAM", "wait timeout must use <positive integer><s|m|h>, for example 45s, 5m, or 2h (maximum 24h)");
48
+ throw new FlowError("INVALID_USAGE", "wait timeout must use <positive integer><s|m|h>, for example 45s, 5m, or 2h (maximum 24h)");
49
49
  }
50
50
  const amount = Number(matched.groups.amount);
51
51
  const multiplier = matched.groups.unit === "s" ? 1_000 : matched.groups.unit === "m" ? 60_000 : 3_600_000;
52
52
  const timeoutMs = amount * multiplier;
53
53
  if (!Number.isSafeInteger(timeoutMs) || timeoutMs > 24 * 3_600_000) {
54
- throw new FlowError("EMPTY_PARAM", "wait timeout must use <positive integer><s|m|h>, for example 45s, 5m, or 2h (maximum 24h)");
54
+ throw new FlowError("INVALID_USAGE", "wait timeout must use <positive integer><s|m|h>, for example 45s, 5m, or 2h (maximum 24h)");
55
55
  }
56
56
  return timeoutMs;
57
57
  }
@@ -68,7 +68,7 @@ export function commandPositionalRange(command) {
68
68
  if (command === "tell") {
69
69
  return { min: 2, max: 2, label: "<PROJECTION> <BODY|->" };
70
70
  }
71
- if (command === "revive") {
71
+ if (command === "fork") {
72
72
  return { min: 1, max: 2, label: "<ARTIFACT> [BODY|-]" };
73
73
  }
74
74
  if (command === "wait") {
@@ -84,11 +84,17 @@ export function commandPositionalRange(command) {
84
84
  return { min: 0, max: 1, label: "[projection|alias|rsp]" };
85
85
  }
86
86
  if (command === "task add") {
87
- return { min: 1, max: 1, label: "<BODY|->" };
87
+ return { min: 1, max: 1, label: "<TITLE|->" };
88
+ }
89
+ if (command === "task compose") {
90
+ return { min: 0, max: 0 };
88
91
  }
89
92
  if (command === "task show" || command === "task log" || command === "task start" || command === "task hold" || command === "task resume" || command === "task drop") {
90
93
  return { min: 1, max: 1, label: "<ID>" };
91
94
  }
95
+ if (command === "task note") {
96
+ return { min: 2, max: 2, label: "<ID> <TEXT|->" };
97
+ }
92
98
  if (command === "task update") {
93
99
  return { min: 1, max: 1, label: "<ID>" };
94
100
  }
@@ -14,6 +14,21 @@ const COMMISSION_SELECTOR_COMMANDS = new Set([
14
14
  "petition",
15
15
  "forfeit",
16
16
  "audit",
17
+ "status",
18
+ "task add",
19
+ "task compose",
20
+ "task show",
21
+ "task ls",
22
+ "task log",
23
+ "task start",
24
+ "task stop",
25
+ "task hold",
26
+ "task resume",
27
+ "task done",
28
+ "task note",
29
+ "task drop",
30
+ "task update",
31
+ "task doctor",
17
32
  ]);
18
33
  function formatSelectorList(items) {
19
34
  if (items.length <= 1) {
@@ -26,13 +41,13 @@ function formatSelectorList(items) {
26
41
  }
27
42
  export function applyCommissionSelector(command, flags, atTokens, contractFlagRaws) {
28
43
  if (atTokens.length > 0 && contractFlagRaws.length > 0) {
29
- throw new FlowError("EMPTY_PARAM", `commission address supplied twice: ${atTokens[0]} and --contract ${contractFlagRaws[0]}; use exactly one form`);
44
+ throw new FlowError("INVALID_USAGE", `commission address supplied twice: ${atTokens[0]} and --contract ${contractFlagRaws[0]}; use exactly one form`);
30
45
  }
31
46
  if (atTokens.length > 1) {
32
- throw new FlowError("EMPTY_PARAM", `${command} accepts one commission address; got ${formatSelectorList(atTokens)}`);
47
+ throw new FlowError("INVALID_USAGE", `${command} accepts one commission address; got ${formatSelectorList(atTokens)}`);
33
48
  }
34
49
  if (contractFlagRaws.length > 1) {
35
- throw new FlowError("EMPTY_PARAM", `${command} accepts one commission address; got ${formatSelectorList(contractFlagRaws.map((raw) => `--contract ${raw}`))}`);
50
+ throw new FlowError("INVALID_USAGE", `${command} accepts one commission address; got ${formatSelectorList(contractFlagRaws.map((raw) => `--contract ${raw}`))}`);
36
51
  }
37
52
  if (atTokens.length === 1) {
38
53
  flags.contractId = normalizeContractAddress(atTokens[0]);
@@ -46,9 +61,12 @@ export function assertCommissionSelectorAllowed(command, flags) {
46
61
  if (flags.contractId === undefined || COMMISSION_SELECTOR_COMMANDS.has(command)) {
47
62
  return;
48
63
  }
49
- throw new FlowError("EMPTY_PARAM", `contract address @${flags.contractId} is not valid for ${command}`);
64
+ throw new FlowError("INVALID_USAGE", `contract address @${flags.contractId} is not valid for ${command}`);
50
65
  }
51
66
  export function assertProjectionSelectorPresent(command, flags, atTokens, contractFlagRaws, restLength, payloadLength) {
67
+ if (command === "status" && flags.contractId !== undefined && restLength + payloadLength > 0) {
68
+ throw new FlowError("INVALID_USAGE", `status accepts either one projection id or one commission selector; ${flags.contractAddressSource === "at-address" ? atTokens[0] ?? `@${flags.contractId}` : `--contract ${contractFlagRaws[0] ?? flags.contractId}`} cannot be combined with a projection id`);
69
+ }
52
70
  if ((command !== "wait" && command !== "tell") || flags.contractId === undefined) {
53
71
  return;
54
72
  }
@@ -4,10 +4,13 @@ import { isResponseArtifactId } from "../core/response-artifact-id.js";
4
4
  import { isCommissionId } from "../core/ids.js";
5
5
  import { HELP_FLAGS } from "./flags.js";
6
6
  import { getCommandMetadata } from "./commands/metadata.js";
7
+ import { AKUMA_SUBCOMMANDS } from "./types.js";
7
8
  import { assertAllowedFlag, assignFlag, BOOLEAN_FLAGS, CONTROL_FLAGS, parseFlagName, readValueFlag, SHORT_FLAG_ALIASES, VALUE_FLAGS, } from "./parse-flags.js";
8
9
  import { commandPositionalRange, isCallCommand, resolveCommand, splitAtLiteralBoundary, TASK_SUBCOMMANDS, } from "./parse-metadata.js";
9
10
  import { applyCommissionSelector, assertCommissionSelectorAllowed, assertProjectionSelectorPresent, } from "./parse-selectors.js";
10
11
  import { WAIT_SET_SELECTION_ERROR } from "./commands/projection/wait/meta.js";
12
+ import { TASK_ADD_INPUT_SHAPE_ERROR } from "./commands/task/add/meta.js";
13
+ import { TASK_UPDATE_EXPLICIT_CHANGE_ERROR } from "./commands/task/update/meta.js";
11
14
  export { commandPositionalRange, isCallCommand, isPetitionDryRunInvocation, normalizeContractAddress, parseWaitTimeout, } from "./parse-metadata.js";
12
15
  export function parseCliArgs(tokens) {
13
16
  const { head, payload } = splitAtLiteralBoundary(tokens);
@@ -31,7 +34,7 @@ export function parseCliArgs(tokens) {
31
34
  const short = token.slice(1);
32
35
  const name = SHORT_FLAG_ALIASES[short];
33
36
  if (!name) {
34
- throw new FlowError("EMPTY_PARAM", `unknown option: ${token}`);
37
+ throw new FlowError("UNKNOWN_OPTION", `unknown option: ${token}`);
35
38
  }
36
39
  seenFlagNames.add(name);
37
40
  if (VALUE_FLAGS.has(name)) {
@@ -52,7 +55,7 @@ export function parseCliArgs(tokens) {
52
55
  assignFlag(flags, name, true);
53
56
  continue;
54
57
  }
55
- throw new FlowError("EMPTY_PARAM", `unknown option: ${token}`);
58
+ throw new FlowError("UNKNOWN_OPTION", `unknown option: ${token}`);
56
59
  }
57
60
  if (!token.startsWith("--")) {
58
61
  free.push(token);
@@ -61,9 +64,17 @@ export function parseCliArgs(tokens) {
61
64
  const eq = token.indexOf("=");
62
65
  const name = parseFlagName(eq === -1 ? token : token.slice(0, eq));
63
66
  if (!CONTROL_FLAGS.has(name)) {
64
- throw new FlowError("EMPTY_PARAM", `unknown option: --${name}`);
67
+ throw new FlowError("UNKNOWN_OPTION", `unknown option: --${name}`);
65
68
  }
66
69
  seenFlagNames.add(name);
70
+ // `--akuma` is a status-only collection selector. Elsewhere it remains
71
+ // the existing value-taking launch option.
72
+ if (name === "akuma" && head.includes("status")) {
73
+ if (eq !== -1)
74
+ throw new FlowError("INVALID_USAGE", "option --akuma does not accept a value for status");
75
+ flags.akumaRoster = true;
76
+ continue;
77
+ }
67
78
  if (VALUE_FLAGS.has(name)) {
68
79
  const { value, nextIndex } = readValueFlag(name, token, eq, head, index);
69
80
  index = nextIndex;
@@ -77,7 +88,7 @@ export function parseCliArgs(tokens) {
77
88
  }
78
89
  if (BOOLEAN_FLAGS.has(name)) {
79
90
  if (eq !== -1) {
80
- throw new FlowError("EMPTY_PARAM", `option --${name} does not accept a value`);
91
+ throw new FlowError("INVALID_USAGE", `option --${name} does not accept a value`);
81
92
  }
82
93
  assignFlag(flags, name, true);
83
94
  }
@@ -103,7 +114,7 @@ export function parseCliArgs(tokens) {
103
114
  };
104
115
  }
105
116
  if (command === "akuma") {
106
- throw new FlowError("EMPTY_PARAM", "akuma requires subcommand: ls or show");
117
+ throw new FlowError("EMPTY_PARAM", `akuma requires subcommand: ${AKUMA_SUBCOMMANDS.slice(0, -1).join(", ")} or ${AKUMA_SUBCOMMANDS.at(-1)}`);
107
118
  }
108
119
  if (command === "skills") {
109
120
  throw new FlowError("EMPTY_PARAM", "skills requires subcommand: install");
@@ -113,9 +124,9 @@ export function parseCliArgs(tokens) {
113
124
  }
114
125
  if (seenFlagNames.has("place")) {
115
126
  if (command === "bind") {
116
- throw new FlowError("EMPTY_PARAM", "bind no longer accepts --place; use --title <text>");
127
+ throw new FlowError("UNKNOWN_OPTION", "bind no longer accepts --place; use --title <text>");
117
128
  }
118
- throw new FlowError("EMPTY_PARAM", "unknown option --place; use @addr or --contract <addr>");
129
+ throw new FlowError("UNKNOWN_OPTION", "unknown option --place; use @addr or --contract <addr>");
119
130
  }
120
131
  for (const name of seenFlagNames) {
121
132
  assertAllowedFlag(command, name);
@@ -125,48 +136,48 @@ export function parseCliArgs(tokens) {
125
136
  delete flags.taskTitle;
126
137
  }
127
138
  if (command === "call" && flags.detach && flags.timeoutMs !== undefined) {
128
- throw new FlowError("EMPTY_PARAM", "call cannot combine --detach and --wait");
139
+ throw new FlowError("INVALID_USAGE", "call cannot combine --detach and --wait");
129
140
  }
130
141
  if (command === "task ls" && flags.all && flags.done) {
131
- throw new FlowError("EMPTY_PARAM", "task ls cannot combine --all and --done");
142
+ throw new FlowError("INVALID_USAGE", "task ls cannot combine --all and --done");
132
143
  }
133
144
  if (command === "wait" && flags.any && flags.all) {
134
- throw new FlowError("EMPTY_PARAM", WAIT_SET_SELECTION_ERROR);
145
+ throw new FlowError("INVALID_USAGE", WAIT_SET_SELECTION_ERROR);
135
146
  }
136
147
  if (command === "task update" && flags.taskParent !== undefined && flags.taskNoParent) {
137
- throw new FlowError("EMPTY_PARAM", "task update cannot combine --parent and --no-parent");
148
+ throw new FlowError("INVALID_USAGE", "task update cannot combine --parent and --no-parent");
138
149
  }
139
150
  if (command === "task update" && flags.taskBody !== undefined && flags.taskAppend !== undefined) {
140
- throw new FlowError("EMPTY_PARAM", "task update cannot combine --body and --append");
151
+ throw new FlowError("INVALID_USAGE", "task update cannot combine --body and --append");
141
152
  }
142
153
  if (command === "task update" && flags.taskTitle === undefined && flags.taskBody === undefined && flags.taskAppend === undefined
143
154
  && flags.taskPri === undefined && flags.taskNeeds === undefined && flags.taskDropNeeds === undefined
144
155
  && flags.taskParent === undefined && !flags.taskNoParent && flags.taskFrom === undefined
145
156
  && flags.taskSupersedes === undefined && flags.taskDropSupersedes === undefined
146
157
  && flags.taskRelatesTo === undefined && flags.taskDropRelatesTo === undefined) {
147
- throw new FlowError("EMPTY_PARAM", "task update requires at least one change");
158
+ throw new FlowError("INVALID_USAGE", TASK_UPDATE_EXPLICIT_CHANGE_ERROR);
148
159
  }
149
160
  if (command === "petition" && flags.json && !flags.dryRun) {
150
- throw new FlowError("EMPTY_PARAM", "petition --json requires --dry-run");
151
- }
152
- if (command === "petition" && flags.dryRun && (flags.appendScope?.length ?? 0) > 0) {
153
- throw new FlowError("EMPTY_PARAM", "petition --dry-run does not accept --append-scope");
161
+ throw new FlowError("INVALID_USAGE", "petition --json requires --dry-run");
154
162
  }
155
163
  if (command === "renew") {
156
164
  const recoveryModes = [flags.renewContinue, flags.renewAbort].filter(Boolean).length;
157
165
  if (recoveryModes > 1) {
158
- throw new FlowError("EMPTY_PARAM", "renew accepts only one of --continue or --abort");
166
+ throw new FlowError("INVALID_USAGE", "renew accepts only one of --continue or --abort");
159
167
  }
160
168
  if (flags.renewAbort && (flags.appendScope?.length ?? 0) > 0) {
161
- throw new FlowError("EMPTY_PARAM", "renew --abort does not accept --append-scope");
169
+ throw new FlowError("INVALID_USAGE", "renew --abort does not accept --append-scope");
162
170
  }
163
171
  }
164
172
  assertCommissionSelectorAllowed(command, flags);
165
173
  assertProjectionSelectorPresent(command, flags, atTokens, contractFlagRaws, rest.length, payload.length);
166
174
  const positional = [...rest, ...payload];
175
+ if (command === "amend" && flags.appendScope && positional.length > 0 && positional[0] !== "-") {
176
+ throw new FlowError("INVALID_USAGE", "amend accepts Markdown only through literal '-' and --append-scope never reads unselected stdin");
177
+ }
167
178
  if (command === "bind" && flags.contractId !== undefined) {
168
179
  if (!isCommissionId(flags.contractId)) {
169
- throw new FlowError("EMPTY_PARAM", `bind replay requires a full canonical contract id; got ${flags.contractId}`);
180
+ throw new FlowError("UNKNOWN_ADDRESS", `bind replay requires a full canonical contract id; got ${flags.contractId}`);
170
181
  }
171
182
  const hasReplayInput = positional.length > 0
172
183
  || flags.bindTaskIds !== undefined
@@ -182,7 +193,7 @@ export function parseCliArgs(tokens) {
182
193
  || flags.bindCriteria !== undefined
183
194
  || flags.bindVerification !== undefined;
184
195
  if (hasReplayInput) {
185
- throw new FlowError("EMPTY_PARAM", "addressed bind is replay-only and accepts no draft or creation input");
196
+ throw new FlowError("INVALID_USAGE", "addressed bind is replay-only and accepts no draft or creation input");
186
197
  }
187
198
  }
188
199
  if (command === "wait") {
@@ -190,13 +201,13 @@ export function parseCliArgs(tokens) {
190
201
  throw new FlowError("EMPTY_PARAM", "wait requires <projection-address>");
191
202
  }
192
203
  if (positional.length > 1 && !flags.any && !flags.all) {
193
- throw new FlowError("EMPTY_PARAM", WAIT_SET_SELECTION_ERROR);
204
+ throw new FlowError("INVALID_USAGE", WAIT_SET_SELECTION_ERROR);
194
205
  }
195
206
  }
196
207
  if (isCallCommand(command)) {
197
208
  if (flags.akuma) {
198
209
  if (positional.length > 1) {
199
- throw new FlowError("EMPTY_PARAM", `${command} accepts at most one <BODY|-> when --akuma is used`);
210
+ throw new FlowError("INVALID_USAGE", `${command} accepts at most one <BODY|-> when --akuma is used`);
200
211
  }
201
212
  }
202
213
  else {
@@ -205,16 +216,16 @@ export function parseCliArgs(tokens) {
205
216
  throw new FlowError("EMPTY_PARAM", `${command} requires an agent name; use \`keiyaku ${command} NAME <BODY|->\``);
206
217
  }
207
218
  if (isResponseArtifactId(name)) {
208
- throw new FlowError("EMPTY_PARAM", `artifact ${name} is a response artifact; call expects an Akuma profile name`);
219
+ throw new FlowError("UNKNOWN_ADDRESS", `artifact ${name} is a response artifact; call expects an Akuma profile name`);
209
220
  }
210
221
  const parsedName = agentNameSchema.safeParse(name);
211
222
  if (!parsedName.success) {
212
- throw new FlowError("EMPTY_PARAM", `${command} requires a valid agent name before <BODY|->`);
223
+ throw new FlowError("UNKNOWN_ADDRESS", `${command} requires a valid agent name before <BODY|->`);
213
224
  }
214
225
  flags.akuma = parsedName.data;
215
226
  positional.shift();
216
227
  if (positional.length > 1) {
217
- throw new FlowError("EMPTY_PARAM", `${command} accepts at most one <BODY|-> after the agent name`);
228
+ throw new FlowError("INVALID_USAGE", `${command} accepts at most one <BODY|-> after the agent name`);
218
229
  }
219
230
  }
220
231
  }
@@ -228,10 +239,12 @@ export function parseCliArgs(tokens) {
228
239
  && positional.length === stdin.selector.index + 1
229
240
  && positional[stdin.selector.index] === "-";
230
241
  if (positional.length > positionalRange.max && !documentStdinSelector) {
231
- const message = stdin.mode === "document"
232
- ? `${command} reads Markdown only through literal '-'; file path arguments are not supported`
233
- : `${command} does not accept positional arguments`;
234
- throw new FlowError("EMPTY_PARAM", message);
242
+ const message = command === "task add"
243
+ ? TASK_ADD_INPUT_SHAPE_ERROR
244
+ : stdin.mode === "document"
245
+ ? `${command} reads Markdown only through literal '-'; file path arguments are not supported`
246
+ : `${command} does not accept positional arguments`;
247
+ throw new FlowError("INVALID_USAGE", message);
235
248
  }
236
249
  return { command, flags, positional };
237
250
  }
@@ -56,7 +56,7 @@ export async function resolveProjectionAddress(input) {
56
56
  });
57
57
  }
58
58
  if (isResponseArtifactId(input.address)) {
59
- throw new AddressResolutionError("EMPTY_PARAM", `artifact ${input.address} is a response artifact; ${input.verb} expects a projection id or alias`, { ...attempt, actual: "artifact" });
59
+ throw new AddressResolutionError("UNKNOWN_ADDRESS", `artifact ${input.address} is a response artifact; ${input.verb} expects a projection id or alias`, { ...attempt, actual: "artifact" });
60
60
  }
61
61
  const suffix = input.scope
62
62
  ? `within ${input.scope.spelling.asTyped}`
@@ -65,22 +65,22 @@ export async function resolveProjectionAddress(input) {
65
65
  let alias;
66
66
  if (input.address.includes("/")) {
67
67
  if (!isProjectionId(input.address))
68
- throw new AddressResolutionError("EMPTY_PARAM", `projection ${input.address} has no match ${suffix}`, attempt);
68
+ throw new AddressResolutionError("UNKNOWN_ADDRESS", `projection ${input.address} has no match ${suffix}`, attempt);
69
69
  id = input.address;
70
70
  }
71
71
  else {
72
72
  if (!isProjectionAlias(input.address))
73
- throw new AddressResolutionError("EMPTY_PARAM", `projection alias ${input.address} has no match ${suffix}`, attempt);
73
+ throw new AddressResolutionError("UNKNOWN_ADDRESS", `projection alias ${input.address} has no match ${suffix}`, attempt);
74
74
  const target = await readProjectionAliasAtRoot(projectionAliasRootAtCoordinate(coordinate), input.address);
75
75
  if (!target)
76
- throw new AddressResolutionError("EMPTY_PARAM", `projection alias ${input.address} has no match ${suffix}`, attempt);
76
+ throw new AddressResolutionError("UNKNOWN_ADDRESS", `projection alias ${input.address} has no match ${suffix}`, attempt);
77
77
  id = target;
78
78
  alias = input.address;
79
79
  }
80
80
  const directory = projectionDirAtCoordinate(coordinate, id);
81
81
  if (!isRealDirectory(directory)) {
82
82
  const subject = alias ? `projection alias ${alias} points to missing projection ${id}` : `projection ${id}`;
83
- throw new AddressResolutionError("EMPTY_PARAM", `${subject} has no match ${suffix}`, attempt);
83
+ throw new AddressResolutionError("UNKNOWN_ADDRESS", `${subject} has no match ${suffix}`, attempt);
84
84
  }
85
85
  // Historical projection storage has no current identity to resolve. Tell
86
86
  // still reaches its typed no-mutation refusal instead of exposing storage
@@ -94,12 +94,12 @@ export async function resolveProjectionAddress(input) {
94
94
  catch (error) {
95
95
  if (error instanceof Error && /ENOENT|no such file/i.test(error.message)) {
96
96
  const subject = alias ? `projection alias ${alias} points to missing projection ${id}` : `projection ${id}`;
97
- throw new AddressResolutionError("EMPTY_PARAM", `${subject} has no match ${suffix}`, attempt);
97
+ throw new AddressResolutionError("UNKNOWN_ADDRESS", `${subject} has no match ${suffix}`, attempt);
98
98
  }
99
99
  throw error;
100
100
  }
101
101
  if (input.scope && (identity.binding.kind !== "commission" || identity.binding.commissionId !== input.scope.binding.commissionId)) {
102
- throw new AddressResolutionError("EMPTY_PARAM", `projection ${id} has no match ${suffix}`, attempt);
102
+ throw new AddressResolutionError("UNKNOWN_ADDRESS", `projection ${id} has no match ${suffix}`, attempt);
103
103
  }
104
104
  return { id, directory, ...(alias ? { alias } : {}) };
105
105
  }
@@ -15,12 +15,19 @@ function sealLines(result) {
15
15
  `fence ${result.sealed.oldFence.slice(0, 7)}▸${result.sealed.newFence.slice(0, 7)}`,
16
16
  ];
17
17
  }
18
+ function scopeWarnings(sealed) {
19
+ const violations = sealed?.scopeAudit.violations ?? [];
20
+ return violations.length === 0 ? [] : [`Scope warning: ${violations.join(", ")}`];
21
+ }
18
22
  export function buildArcResponse(result) {
19
23
  const { status: _status, address: _address, ...resultData } = result;
20
24
  const diff = renderSealDiffSection(result.sealed, "working tree untouched");
21
25
  const payload = { ...resultData, diff };
22
26
  const summarySection = buildSection(CONTENT_SECTION_TITLE, sealLines(result));
23
- const warningSection = buildSection(WARNING_SECTION_TITLE, formatWarnings(result.meta?.warnings ?? []));
27
+ const warningSection = buildSection(WARNING_SECTION_TITLE, [
28
+ ...scopeWarnings(result.sealed),
29
+ ...formatWarnings(result.meta?.warnings ?? []),
30
+ ]);
24
31
  const hintsSection = buildSection(HINTS_SECTION_TITLE, formatHints(result.meta?.hints ?? [], { maxItems: HINTS_LIST_MAX_ITEMS }));
25
32
  const infoSection = buildSection(INFO_SECTION_TITLE, [
26
33
  ...formatMaybe("Title", result.title),
@@ -46,7 +53,10 @@ export function buildRenewResponse(result) {
46
53
  ...formatMaybe("Ledger Head", result.ledgerHead, INFO_COMMIT_MAX_CHARS),
47
54
  ...formatList("Seal", sealLines(result)),
48
55
  ]);
49
- const warningSection = buildSection(WARNING_SECTION_TITLE, formatWarnings(result.meta?.warnings ?? []));
56
+ const warningSection = buildSection(WARNING_SECTION_TITLE, [
57
+ ...scopeWarnings(result.sealed),
58
+ ...formatWarnings(result.meta?.warnings ?? []),
59
+ ]);
50
60
  return prependAddressReceipt({
51
61
  text: assembleResponse(`${RESPONSE_MARKERS.arc} Renewed`, appendPersistenceSummary(result.summary, result.responsePath), [buildSection(CONTENT_SECTION_TITLE, diff), infoSection, warningSection].filter((section) => section !== null)),
52
62
  payload: buildPayload(payload, result.responsePath),
@@ -55,7 +65,6 @@ export function buildRenewResponse(result) {
55
65
  export function buildRenewAbortResponse(result) {
56
66
  const payload = {
57
67
  contractId: result.contractId,
58
- oldHead: result.oldHead,
59
68
  scratchName: result.scratchName,
60
69
  summary: result.summary,
61
70
  };
@@ -120,7 +120,7 @@ function renderChanges(report) {
120
120
  `${report.diff.stat.filesChanged} files · +${report.diff.stat.insertions} -${report.diff.stat.deletions}`,
121
121
  ];
122
122
  if (outside.length > 0) {
123
- lines.push("", "Outside declared write set", "");
123
+ lines.push("", "Scope warning · Outside declared write set", "");
124
124
  for (const file of outside) {
125
125
  lines.push(...renderFileBlock(file, report), "");
126
126
  }
@@ -231,7 +231,7 @@ function renderVerificationResults(report) {
231
231
  }
232
232
  const labels = report.verification.results.map((result) => result.label);
233
233
  const width = Math.max(8, ...labels.map((label) => label.length));
234
- const lines = [];
234
+ const lines = [` run ${report.verification.runId}`];
235
235
  const groups = ["contract", "repository-gate"];
236
236
  for (const source of groups) {
237
237
  const results = report.verification.results.filter((result) => result.source === source);
@@ -9,9 +9,9 @@ export function renderAdoptedLaunchReceipt(address, projectionId, alias, previou
9
9
  ...(alias ? { projectionAlias: alias } : {}),
10
10
  ...(akumaName ? { akumaName } : {}),
11
11
  }),
12
- ...(alias ? [`alias ${alias} ${projectionId}`] : []),
12
+ `${projectionId}${alias ? ` (${alias})` : ""} launched.`,
13
13
  ...(alias && previousAliasTarget ? [`(moved from ${previousAliasTarget}, still running)`] : []),
14
- ...projectionRejoinHintLines(alias ?? projectionId),
14
+ ...projectionRejoinHintLines(projectionId),
15
15
  ].join("\n");
16
16
  }
17
17
  export function buildCallResponse(result, input) {
@@ -24,8 +24,8 @@ export function buildCallResponse(result, input) {
24
24
  text: input.addressPlacement === "stdout"
25
25
  ? renderAdoptedLaunchReceipt(result.address, result.projection.id, result.projection.alias, result.projection.previousAliasTarget, result.agent ?? input.agent)
26
26
  : [
27
- ...(result.projection.alias ? [`alias ${result.projection.alias} ${result.projection.id}`] : []),
28
- ...projectionRejoinHintLines(result.projection.alias ?? result.projection.id),
27
+ `${result.projection.id}${result.projection.alias ? ` (${result.projection.alias})` : ""} launched.`,
28
+ ...projectionRejoinHintLines(result.projection.id),
29
29
  ].join("\n"),
30
30
  payload: buildPayload(payload),
31
31
  };