@astrosheep/keiyaku 4.6.6 → 4.6.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 (217) hide show
  1. package/README.md +11 -0
  2. package/build/{integrations/marketplace → plugins}/.agents/plugins/marketplace.json +1 -1
  3. package/build/plugins/.claude-plugin/marketplace.json +5 -0
  4. package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/.claude-plugin/plugin.json +1 -1
  5. package/build/{integrations/marketplace/plugins/keiyaku → plugins/codex}/.codex-plugin/plugin.json +1 -1
  6. package/build/plugins/codex/skills/keiyaku/SKILL.md +44 -0
  7. package/build/plugins/codex/skills/keiyaku-akuma/SKILL.md +130 -0
  8. package/build/plugins/codex/skills/keiyaku-akuma/references/automation.md +269 -0
  9. package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +65 -0
  10. package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +216 -0
  11. package/build/plugins/codex/skills/keiyaku-bind/agents/openai.yaml +4 -0
  12. package/build/plugins/codex/skills/keiyaku-task/SKILL.md +104 -0
  13. package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +129 -0
  14. package/build/plugins/opencode/package.json +6 -0
  15. package/build/plugins/opencode/skills/keiyaku/SKILL.md +44 -0
  16. package/build/plugins/opencode/skills/keiyaku-akuma/SKILL.md +130 -0
  17. package/build/plugins/opencode/skills/keiyaku-akuma/references/automation.md +269 -0
  18. package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +65 -0
  19. package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +216 -0
  20. package/build/plugins/opencode/skills/keiyaku-bind/agents/openai.yaml +4 -0
  21. package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +104 -0
  22. package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +129 -0
  23. package/build/{integrations → plugins}/pi/keiyaku.ts +0 -5
  24. package/build/skills/keiyaku/SKILL.md +44 -0
  25. package/build/skills/keiyaku-akuma/SKILL.md +130 -0
  26. package/build/skills/keiyaku-akuma/references/automation.md +269 -0
  27. package/build/skills/keiyaku-babysit/SKILL.md +65 -0
  28. package/build/skills/keiyaku-bind/SKILL.md +216 -0
  29. package/build/skills/keiyaku-bind/agents/openai.yaml +4 -0
  30. package/build/skills/keiyaku-task/SKILL.md +104 -0
  31. package/build/skills/keiyaku-workflow/SKILL.md +129 -0
  32. package/build/src/akuma/akuma-call.d.ts +2 -0
  33. package/build/src/akuma/akuma-call.js +8 -2
  34. package/build/src/akuma/akuma-instance.d.ts +12 -1
  35. package/build/src/akuma/akuma-instance.js +31 -9
  36. package/build/src/akuma/akuma-observe.d.ts +4 -0
  37. package/build/src/akuma/akuma-observe.js +14 -0
  38. package/build/src/akuma/akuma-owner.d.ts +6 -2
  39. package/build/src/akuma/akuma-owner.js +32 -10
  40. package/build/src/akuma/akuma-selection-execution.d.ts +3 -1
  41. package/build/src/akuma/akuma-selection-execution.js +2 -1
  42. package/build/src/akuma/akuma-wait.d.ts +2 -1
  43. package/build/src/akuma/akuma-wait.js +4 -1
  44. package/build/src/akuma/akuma.d.ts +35 -5
  45. package/build/src/akuma/akuma.js +8 -10
  46. package/build/src/akuma/archetype.d.ts +7 -15
  47. package/build/src/akuma/archetype.js +36 -35
  48. package/build/src/akuma/body.d.ts +6 -3
  49. package/build/src/akuma/body.js +41 -30
  50. package/build/src/akuma/call-request.d.ts +18 -10
  51. package/build/src/akuma/call-request.js +10 -3
  52. package/build/src/akuma/caller.d.ts +39 -0
  53. package/build/src/akuma/caller.js +36 -0
  54. package/build/src/akuma/dispatch-association.d.ts +0 -1
  55. package/build/src/akuma/dispatch-association.js +0 -3
  56. package/build/src/akuma/heart/facts.d.ts +16 -12
  57. package/build/src/akuma/heart/facts.js +8 -0
  58. package/build/src/akuma/heart/index.d.ts +2 -7
  59. package/build/src/akuma/heart/index.js +3 -17
  60. package/build/src/akuma/heart/rows.d.ts +3 -3
  61. package/build/src/akuma/heart/soul.d.ts +1 -1
  62. package/build/src/akuma/heart/soul.js +5 -24
  63. package/build/src/akuma/heart/storage.d.ts +5 -0
  64. package/build/src/akuma/heart/storage.js +7 -3
  65. package/build/src/akuma/identity.d.ts +0 -1
  66. package/build/src/akuma/identity.js +2 -5
  67. package/build/src/akuma/index.d.ts +5 -2
  68. package/build/src/akuma/index.js +1 -0
  69. package/build/src/akuma/nuke.js +6 -28
  70. package/build/src/akuma/projection.d.ts +0 -11
  71. package/build/src/akuma/provider-recipe.d.ts +7 -6
  72. package/build/src/akuma/provider-recipe.js +1 -1
  73. package/build/src/akuma/provider.d.ts +6 -10
  74. package/build/src/akuma/provider.js +6 -7
  75. package/build/src/akuma/providers/acp/events.js +5 -18
  76. package/build/src/akuma/providers/acp/index.js +2 -3
  77. package/build/src/akuma/providers/claude/events.js +35 -60
  78. package/build/src/akuma/providers/claude/index.d.ts +2 -2
  79. package/build/src/akuma/providers/claude/index.js +2 -3
  80. package/build/src/akuma/providers/codex-app-server/index.js +2 -2
  81. package/build/src/akuma/providers/decode.d.ts +25 -0
  82. package/build/src/akuma/providers/decode.js +44 -0
  83. package/build/src/akuma/providers/execution-environment.d.ts +2 -1
  84. package/build/src/akuma/providers/execution-environment.js +3 -0
  85. package/build/src/akuma/providers/grok-build/index.js +6 -22
  86. package/build/src/akuma/providers/index.js +2 -0
  87. package/build/src/akuma/providers/lifecycle.d.ts +9 -0
  88. package/build/src/akuma/providers/lifecycle.js +10 -0
  89. package/build/src/akuma/providers/opencode-sdk/events.js +1 -14
  90. package/build/src/akuma/providers/opencode-sdk/index.js +10 -17
  91. package/build/src/akuma/providers/opencode-sdk/session.js +1 -3
  92. package/build/src/akuma/providers/paseo/events.d.ts +25 -0
  93. package/build/src/akuma/providers/paseo/events.js +157 -0
  94. package/build/src/akuma/providers/paseo/index.d.ts +9 -0
  95. package/build/src/akuma/providers/paseo/index.js +353 -0
  96. package/build/src/akuma/providers/pi/events.js +5 -15
  97. package/build/src/akuma/publication.d.ts +2 -0
  98. package/build/src/akuma/publication.js +5 -0
  99. package/build/src/akuma/request-lifecycle.d.ts +3 -0
  100. package/build/src/akuma/request-lifecycle.js +25 -4
  101. package/build/src/akuma/requests.d.ts +3 -1
  102. package/build/src/akuma/requests.js +32 -0
  103. package/build/src/akuma/selection-observation.d.ts +72 -2
  104. package/build/src/akuma/selection-observation.js +0 -6
  105. package/build/src/akuma/selection-owner-port.d.ts +1 -1
  106. package/build/src/akuma/selection-owner-port.js +16 -5
  107. package/build/src/akuma/selection-request.d.ts +2 -0
  108. package/build/src/akuma/selection-request.js +2 -1
  109. package/build/src/akuma/turn-drive.js +2 -5
  110. package/build/src/akuma-body.js +4 -2
  111. package/build/src/cli/akuma-caller.d.ts +3 -0
  112. package/build/src/cli/akuma-caller.js +21 -0
  113. package/build/src/cli/commands/akuma-grammar.js +7 -12
  114. package/build/src/cli/commands/akuma.js +18 -16
  115. package/build/src/cli/commands/contract-grammar.d.ts +2 -1
  116. package/build/src/cli/commands/contract-grammar.js +13 -15
  117. package/build/src/cli/commands/contract-help.d.ts +2 -1
  118. package/build/src/cli/commands/contract-help.js +31 -1
  119. package/build/src/cli/commands/contract.js +24 -53
  120. package/build/src/cli/commands/install.js +3 -3
  121. package/build/src/cli/commands/task.js +18 -35
  122. package/build/src/cli/parse.d.ts +2 -2
  123. package/build/src/cli/render/catalog.d.ts +2 -5
  124. package/build/src/cli/render/contract-history.js +3 -6
  125. package/build/src/cli/render/contract.js +15 -50
  126. package/build/src/cli/render/receipt.js +3 -10
  127. package/build/src/cli/render/task.d.ts +4 -6
  128. package/build/src/cli/render/task.js +9 -26
  129. package/build/src/cli/runtime.d.ts +1 -1
  130. package/build/src/cli/runtime.js +11 -17
  131. package/build/src/cli/selectors.d.ts +3 -6
  132. package/build/src/cli/selectors.js +22 -53
  133. package/build/src/dispatch/index.d.ts +3 -3
  134. package/build/src/dispatch/index.js +1 -2
  135. package/build/src/git/observe.d.ts +6 -2
  136. package/build/src/git/observe.js +6 -2
  137. package/build/src/index.d.ts +6 -6
  138. package/build/src/index.js +2 -2
  139. package/build/src/kanshi/index.d.ts +1 -1
  140. package/build/src/kanshi/read.js +21 -6
  141. package/build/src/library/address.js +2 -4
  142. package/build/src/library/akuma-creation.d.ts +5 -1
  143. package/build/src/library/akuma-creation.js +33 -51
  144. package/build/src/library/akumas.d.ts +5 -4
  145. package/build/src/library/akumas.js +13 -9
  146. package/build/src/library/bind.d.ts +14 -14
  147. package/build/src/library/bind.js +11 -7
  148. package/build/src/library/contract-address.d.ts +9 -0
  149. package/build/src/library/contract-address.js +71 -0
  150. package/build/src/library/contract-composition.d.ts +4 -7
  151. package/build/src/library/contract-composition.js +6 -18
  152. package/build/src/library/contract-creation.d.ts +3 -5
  153. package/build/src/library/contract-creation.js +19 -17
  154. package/build/src/library/contract-execution.js +18 -23
  155. package/build/src/library/contract-outcomes.d.ts +2 -14
  156. package/build/src/library/contract-outcomes.js +2 -13
  157. package/build/src/library/contract-types.d.ts +36 -2
  158. package/build/src/library/delivery.d.ts +0 -2
  159. package/build/src/library/delivery.js +2 -5
  160. package/build/src/library/keiyaku.d.ts +0 -5
  161. package/build/src/library/keiyaku.js +6 -12
  162. package/build/src/library/outcome.d.ts +500 -499
  163. package/build/src/library/outcome.js +10 -0
  164. package/build/src/library/reconcile.js +8 -16
  165. package/build/src/library/refusal.d.ts +2 -2
  166. package/build/src/library/repo.d.ts +3 -2
  167. package/build/src/library/repo.js +10 -5
  168. package/build/src/library/selection.d.ts +4 -4
  169. package/build/src/library/selection.js +12 -9
  170. package/build/src/plugin/akuma-signals.d.ts +12 -11
  171. package/build/src/plugin/akuma-signals.js +40 -20
  172. package/build/src/plugin/public.d.ts +32 -2
  173. package/build/src/plugin/runtime.d.ts +1 -0
  174. package/build/src/plugin/runtime.js +35 -24
  175. package/build/src/protocol/amend.js +3 -2
  176. package/build/src/protocol/attempt.js +3 -8
  177. package/build/src/protocol/bind.d.ts +2 -2
  178. package/build/src/protocol/bind.js +1 -1
  179. package/build/src/protocol/deliver.js +3 -3
  180. package/build/src/protocol/operations.d.ts +1 -3
  181. package/build/src/protocol/operations.js +0 -8
  182. package/build/src/protocol/outcome.d.ts +1 -2
  183. package/build/src/protocol/outcome.js +1 -13
  184. package/build/src/protocol/placement.js +3 -10
  185. package/build/src/protocol/read/status.js +31 -70
  186. package/build/src/protocol/reintegrate.js +3 -10
  187. package/build/src/protocol/review.js +3 -3
  188. package/build/src/protocol/run.d.ts +5 -1
  189. package/build/src/protocol/run.js +3 -3
  190. package/build/src/runtime/proc/windows-launch.exe +0 -0
  191. package/package.json +12 -8
  192. package/plugins/pi/keiyaku.ts +57 -0
  193. package/skills/keiyaku/SKILL.md +44 -0
  194. package/skills/keiyaku-akuma/SKILL.md +130 -0
  195. package/skills/keiyaku-akuma/references/automation.md +269 -0
  196. package/skills/keiyaku-babysit/SKILL.md +65 -0
  197. package/skills/keiyaku-bind/SKILL.md +216 -0
  198. package/skills/keiyaku-bind/agents/openai.yaml +4 -0
  199. package/skills/keiyaku-task/SKILL.md +104 -0
  200. package/skills/keiyaku-workflow/SKILL.md +129 -0
  201. package/build/integrations/marketplace/.claude-plugin/marketplace.json +0 -5
  202. package/build/integrations/marketplace/plugins/keiyaku/package.json +0 -17
  203. package/build/src/cli/commands/amend.d.ts +0 -12
  204. package/build/src/cli/commands/amend.js +0 -10
  205. package/build/src/cli/commands/bind.d.ts +0 -11
  206. package/build/src/cli/commands/bind.js +0 -23
  207. package/build/src/dispatch/association.d.ts +0 -1
  208. package/build/src/dispatch/association.js +0 -1
  209. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku/SKILL.md +0 -0
  210. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-akuma/SKILL.md +0 -0
  211. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-akuma/references/automation.md +0 -0
  212. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-babysit/SKILL.md +0 -0
  213. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-bind/SKILL.md +0 -0
  214. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-bind/agents/openai.yaml +0 -0
  215. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-task/SKILL.md +0 -0
  216. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-workflow/SKILL.md +0 -0
  217. /package/build/{integrations/marketplace/plugins/keiyaku/opencode.js → plugins/opencode/index.js} +0 -0
@@ -1,7 +1,6 @@
1
- import { listArchetypeDefinitions } from "../../akuma/archetype.js";
2
1
  import { executionChannel } from "../../akuma/requests.js";
3
- import { Akumas, Keiyaku, KeiyakuError, nuke } from "../../index.js";
4
- import { kanshi, kanshiCategory, observeKanshi, selectKanshi, selectRegion } from "../../kanshi/index.js";
2
+ import { Akumas, Keiyaku, KeiyakuError, kanshiCategory, listArchetypeDefinitions, nuke } from "../../index.js";
3
+ import { kanshi, observeKanshi, selectRegion } from "../../kanshi/index.js";
5
4
  import { resolveNamedAddress } from "../../library/address.js";
6
5
  import { composeContractLibrary, observeKeiyaku } from "../../library/contract-composition.js";
7
6
  import { validateArcMarkdown, validateContractMarkdown } from "../../library/input.js";
@@ -20,11 +19,9 @@ import { reconcileHasFailure, renderReconcile } from "../render/reconcile.js";
20
19
  import { renderConflictMaterialized, renderRefusal } from "../render/refusal.js";
21
20
  import { renderRegionText } from "../render/region.js";
22
21
  import { renderSettingsText, settingsJsonValue } from "../render/settings.js";
23
- import { canonicalContractSelector, contractFromInput, resolveContractId, resolveKanshiContract, } from "../selectors.js";
24
- import { displayContext, emit, writeJson, writeStdout } from "../streams.js";
22
+ import { canonicalContractSelector, contractFromInput, resolveContractId } from "../selectors.js";
23
+ import { displayContext, emit, writeJson, writeStderr, writeStdout } from "../streams.js";
25
24
  import { CliUsageError, isBlankInput } from "../usage.js";
26
- import { amendFromCommand } from "./amend.js";
27
- import { bindFromCommand } from "./bind.js";
28
25
  function requiredRepo(coordinates) {
29
26
  if (coordinates.repo === undefined)
30
27
  throw new CliUsageError("this command requires a resolved Repo");
@@ -50,17 +47,6 @@ async function contractSettings(command, execution, world, home) {
50
47
  function draftWarning(error) {
51
48
  return { warning: `bind draft could not be preserved: ${error instanceof Error ? error.message : String(error)}` };
52
49
  }
53
- /** Preserve a refused bind draft at the invocation cwd; coordinates are not yet available. */
54
- async function bindDraftReceiptAtCwd(input, markdown) {
55
- try {
56
- return await preserveBindDraft(await resolveInvocationCwd(input), markdown);
57
- }
58
- catch (error) {
59
- if (error instanceof Error && "executionReceipt" in error)
60
- throw error;
61
- return draftWarning(error);
62
- }
63
- }
64
50
  /**
65
51
  * The one bind-document admission that runs before coordinate resolution, so a malformed document
66
52
  * refuses as a draft-bearing refusal instead of a later Repo/Git failure. Reads the memoized stdin.
@@ -76,7 +62,7 @@ export async function admitBindMarkdown(input) {
76
62
  throw error;
77
63
  if (!(error instanceof TypeError) && !(error instanceof KeiyakuError && error.category === "invalid-input"))
78
64
  throw error;
79
- throw new BindDraftError(error, await bindDraftReceiptAtCwd(input, input.markdown));
65
+ throw new BindDraftError(error, await bindDraftReceipt(() => resolveInvocationCwd(input), input.markdown));
80
66
  }
81
67
  }
82
68
  async function bindDraftReceipt(world, markdown) {
@@ -145,41 +131,32 @@ async function contractLibrary(command, execution, configuration, runtime) {
145
131
  return composeContractLibrary(execution, createKeiyakuHandle, {
146
132
  ...(configuration === undefined ? {} : { settings: configuration }),
147
133
  ...(actor === undefined ? {} : { actor }),
148
- },
149
- // The CLI owns this default: an omitted Markdown --target names the invocation branch.
150
- { kind: "current-branch" });
134
+ });
151
135
  }
152
136
  async function runBind(command, input, library) {
153
137
  const { coordinates, runtime } = input;
154
138
  const repo = requiredRepo(coordinates);
155
139
  const actor = actorFromEdge(command.actor, runtime.environment);
156
140
  if (command.forkOf !== undefined) {
157
- const answer = await bindFromCommand({
158
- command,
141
+ const answer = await library.bind({
159
142
  repo,
160
- library,
143
+ forkOf: contractFromInput(repo, command.forkOf).id,
144
+ ...(command.target === undefined ? {} : { target: command.target }),
161
145
  ...(actor === undefined ? {} : { actor }),
162
146
  });
163
147
  return await finishContractAnswer(answer, command.output);
164
148
  }
165
149
  const markdown = await runtime.readStdin();
166
- if (isBlankInput(markdown))
167
- throw new CliUsageError("bind requires a nonblank stdin document");
168
150
  try {
169
- validateContractMarkdown(markdown);
170
- }
171
- catch (error) {
172
- if (!(error instanceof TypeError) && !(error instanceof KeiyakuError && error.category === "invalid-input"))
173
- throw error;
174
- throw new BindDraftError(error, await bindDraftReceipt(coordinates.establishWorld, markdown));
175
- }
176
- try {
177
- const answer = await bindFromCommand({
178
- command,
151
+ const after = command.after?.map((id) => contractFromInput(repo, id).id);
152
+ const answer = await library.bind({
179
153
  repo,
180
- library,
181
154
  markdown,
155
+ ...(command.task === undefined ? {} : { task: command.task }),
156
+ ...(command.target === undefined ? {} : { target: command.target }),
182
157
  ...(actor === undefined ? {} : { actor }),
158
+ ...(after === undefined ? {} : { after }),
159
+ ...(command.gates === undefined ? {} : { gates: command.gates }),
183
160
  });
184
161
  if (answer.kind !== "refused")
185
162
  return await finishContractAnswer(answer, command.output);
@@ -203,13 +180,13 @@ async function runAmend(command, input, seat) {
203
180
  const markdown = command.stdin === true ? await runtime.readStdin() : undefined;
204
181
  if (markdown !== undefined && isBlankInput(markdown))
205
182
  throw new CliUsageError("amend requires a nonblank stdin document");
206
- const answer = await amendFromCommand({
207
- command,
208
- repo: requiredRepo(coordinates),
209
- contract: seat.contract,
183
+ const repo = requiredRepo(coordinates);
184
+ const after = command.clearAfter === true ? [] : command.after?.map((id) => contractFromInput(repo, id).id);
185
+ const answer = await seat.contract.amend({
210
186
  ...(markdown === undefined ? {} : { markdown }),
211
- ...(command.gates === undefined ? {} : { gates: command.gates }),
212
187
  ...(seat.actor === undefined ? {} : { actor: seat.actor }),
188
+ ...(after === undefined ? {} : { after }),
189
+ ...(command.gates === undefined ? {} : { gates: command.gates }),
213
190
  });
214
191
  return await finishContractAnswer(answer, command.output);
215
192
  }
@@ -366,7 +343,7 @@ async function runLs(command, coordinates, home) {
366
343
  async function readAkumaStatus(akuma, alias, coordinates) {
367
344
  if (coordinates.world === null)
368
345
  throw new CliUsageError("no Keiyaku world contains the Akuma selector");
369
- const status = await Akumas.of(coordinates.world).status({
346
+ const status = await Akumas.of(coordinates.world, { reportDiagnostic: writeStderr }).status({
370
347
  akuma,
371
348
  ...(coordinates.repo === undefined ? {} : { repo: coordinates.repo }),
372
349
  });
@@ -473,13 +450,7 @@ async function runStatusIdentity(command, coordinates) {
473
450
  }
474
451
  return emit(command.output, report, () => renderKanshiText(report, displayContext(), "contract"), 0);
475
452
  }
476
- const report = await kanshi({
477
- world: coordinates.world,
478
- ...(coordinates.repo === undefined ? {} : { repo: coordinates.repo }),
479
- });
480
- const contract = resolveKanshiContract(report, command.contract);
481
- const selected = selectKanshi({ report, contract });
482
- return emit(command.output, selected, () => renderKanshiText(selected, displayContext(), "contract"), 0);
453
+ throw new CliUsageError(`contract selector must use kei/: ${command.contract}`);
483
454
  }
484
455
  async function runStatus(command, coordinates) {
485
456
  if (command.guidance === true)
@@ -501,10 +472,10 @@ async function runRegion(command, coordinates) {
501
472
  const report = await kanshi({ world: coordinates.world, repo, region: { kind: "path", patterns: command.paths } });
502
473
  return emitSection(report.region ?? { kind: "absent" });
503
474
  }
475
+ const contract = command.contract === undefined ? undefined : await resolveContractId(repo, command.contract, coordinates.cwd);
504
476
  const report = await kanshi({ world: coordinates.world, repo, region: { kind: "declarations" } });
505
- if (command.contract === undefined)
477
+ if (contract === undefined)
506
478
  return emitSection(report.region ?? { kind: "absent" });
507
- const contract = resolveKanshiContract(report, command.contract);
508
479
  const observed = await observeKeiyaku({ repo, id: contract });
509
480
  if (observed.kind === "missing" || observed.row.phase === "claimed" || observed.row.phase === "abandoned") {
510
481
  const refusal = {
@@ -47,8 +47,8 @@ export function renderInstallHelp() {
47
47
  return `${INSTALL_ROOT_PURPOSE}\n\n${usageLine(INSTALL_USAGE)}\n\n--all continues past failures; any failure exits 1.`;
48
48
  }
49
49
  const INSTALL_TIMEOUT_MS = 5 * 60 * 1000;
50
- const ASSET_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../../../integrations/marketplace");
51
- const PLUGIN_ROOT = resolve(ASSET_ROOT, "plugins/keiyaku");
50
+ const ASSET_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../../../plugins");
51
+ const OPENCODE_PLUGIN_ROOT = resolve(ASSET_ROOT, "opencode");
52
52
  const PI_PACKAGE_SOURCE = "npm:@astrosheep/keiyaku";
53
53
  function recipes(harness) {
54
54
  switch (harness) {
@@ -64,7 +64,7 @@ function recipes(harness) {
64
64
  ["claude", "plugin", "update", "keiyaku@keiyaku", "--scope", "user"],
65
65
  ];
66
66
  case "opencode":
67
- return [["opencode", "plugin", PLUGIN_ROOT, "--global", "--force"]];
67
+ return [["opencode", "plugin", OPENCODE_PLUGIN_ROOT, "--global", "--force"]];
68
68
  case "pi":
69
69
  return [["pi", "install", PI_PACKAGE_SOURCE]];
70
70
  }
@@ -156,21 +156,15 @@ async function runRead(input) {
156
156
  });
157
157
  return emit(command.output, result, () => renderTaskList("ls", scope, result, displayContext()), taskExitCode(result));
158
158
  }
159
- case "ready": {
160
- const result = await tasks.ready({
161
- ...readScope(command, current),
162
- ...(value(command, "parent") === undefined ? {} : { parent: value(command, "parent") }),
163
- ...(limit(command) === undefined ? {} : { limit: limit(command) }),
164
- });
165
- return emit(command.output, result, () => renderTaskList("ready", scope, result, displayContext()), taskExitCode(result));
166
- }
159
+ case "ready":
167
160
  case "blocked": {
168
- const result = await tasks.blocked({
161
+ const action = command.action;
162
+ const result = await tasks[action]({
169
163
  ...readScope(command, current),
170
164
  ...(value(command, "parent") === undefined ? {} : { parent: value(command, "parent") }),
171
165
  ...(limit(command) === undefined ? {} : { limit: limit(command) }),
172
166
  });
173
- return emit(command.output, result, () => renderTaskList("blocked", scope, result, displayContext()), taskExitCode(result));
167
+ return emit(command.output, result, () => renderTaskList(action, scope, result, displayContext()), taskExitCode(result));
174
168
  }
175
169
  case "query": {
176
170
  const result = await tasks.query({
@@ -233,26 +227,18 @@ function missingWorld(command) {
233
227
  const result = missingTask(command.positionals[0]);
234
228
  return emit(output, result, () => renderTaskUpdate(result, displayContext()), taskExitCode(result));
235
229
  }
236
- if (command.action === "start" ||
237
- command.action === "stop" ||
238
- command.action === "hold" ||
239
- command.action === "resume") {
240
- if (command.positionals.length === 1) {
241
- const result = missingTask(command.positionals[0]);
242
- return emit(output, result, () => renderTaskMutation(command.action, result, displayContext()), taskExitCode(result));
243
- }
244
- const result = {
245
- items: command.positionals.map((id) => ({ id: id, outcome: missingTask(id) })),
246
- };
247
- return emit(output, result, () => renderTaskLifecycle(command.action, result, displayContext()), taskExitCode(result));
248
- }
249
- if (command.action === "done" || command.action === "drop") {
250
- const result = {
251
- items: command.positionals.map((id) => ({ id: id, outcome: missingTask(id) })),
252
- };
253
- return emit(output, result, () => renderTaskLifecycle(command.action, result, displayContext()), taskExitCode(result));
230
+ const singleLifecycle = ["start", "stop", "hold", "resume"].includes(command.action);
231
+ const batchLifecycle = ["done", "drop"].includes(command.action);
232
+ if (!singleLifecycle && !batchLifecycle)
233
+ throw new Error(`task action has no missing-world answer: ${command.action}`);
234
+ if (singleLifecycle && command.positionals.length === 1) {
235
+ const result = missingTask(command.positionals[0]);
236
+ return emit(output, result, () => renderTaskMutation(command.action, result, displayContext()), taskExitCode(result));
254
237
  }
255
- throw new Error(`task action has no missing-world answer: ${command.action}`);
238
+ const result = {
239
+ items: command.positionals.map((id) => ({ id: id, outcome: missingTask(id) })),
240
+ };
241
+ return emit(output, result, () => renderTaskLifecycle(command.action, result, displayContext()), taskExitCode(result));
256
242
  }
257
243
  /**
258
244
  * One compose execution outcome: JSON keeps the untouched native value, while an incomplete text
@@ -284,7 +270,7 @@ async function runBatchLifecycle(tasks, command, verb) {
284
270
  return emit(command.output, result, () => renderTaskLifecycle(verb, result, displayContext()), taskExitCode(result));
285
271
  }
286
272
  async function runMutation(input) {
287
- const { tasks, command, current, stdin, composeMarkdown, composeNamespace } = input;
273
+ const { tasks, command, current, stdin, composeNamespace } = input;
288
274
  if (isWorldObservationAction(command) || command.action === "tree")
289
275
  return await runRead(input);
290
276
  switch (command.action) {
@@ -326,7 +312,7 @@ async function runMutation(input) {
326
312
  }
327
313
  case "compose": {
328
314
  const result = await tasks.compose({
329
- markdown: composeMarkdown ?? stdin ?? "",
315
+ markdown: stdin ?? "",
330
316
  namespace: composeNamespace ?? current ?? [],
331
317
  ...(input.actor === undefined ? {} : { actor: input.actor }),
332
318
  ...(command.flags.plan === true ? { plan: true } : {}),
@@ -377,8 +363,7 @@ export async function runTaskCommand(command, coordinates, runtime) {
377
363
  if (stdinDiagnostic !== undefined && isBlankInput(stdin ?? ""))
378
364
  throw new CliUsageError(stdinDiagnostic);
379
365
  const planOnly = command.action === "compose" && command.flags.plan === true;
380
- const composeMarkdown = command.action === "compose" ? stdin : undefined;
381
- const composition = composeMarkdown === undefined ? undefined : taskCompositionNamespaceHeader(composeMarkdown);
366
+ const composition = command.action === "compose" && stdin !== undefined ? taskCompositionNamespaceHeader(stdin) : undefined;
382
367
  const explicitNamespace = command.action === "add"
383
368
  ? namespace(value(command, "namespace"))
384
369
  : command.action === "compose" && composition?.specified
@@ -414,12 +399,10 @@ export async function runTaskCommand(command, coordinates, runtime) {
414
399
  return await runMutation({
415
400
  tasks,
416
401
  command,
417
- runtime,
418
402
  context: coordinates.taskContext,
419
403
  ...(actor === undefined ? {} : { actor }),
420
404
  ...(current === undefined ? {} : { current }),
421
405
  ...(stdin === undefined ? {} : { stdin }),
422
- ...(composeMarkdown === undefined ? {} : { composeMarkdown }),
423
406
  ...(explicitNamespace === undefined ? {} : { composeNamespace: explicitNamespace }),
424
407
  });
425
408
  }
@@ -1,7 +1,7 @@
1
1
  import { type ParsedTaskCommand, type TaskAction } from "./commands/task-grammar.js";
2
2
  import { type AkumaAction, type ParsedAkumaCommand } from "./commands/akuma-grammar.js";
3
3
  import { type ParsedInstallCommand } from "./commands/install.js";
4
- import { type ParsedAbandon, type ParsedAmend, type ParsedArc, type ParsedAudit, type ParsedBind, type ParsedDeliver, type ParsedLs, type ParsedNuke, type ParsedReconcile, type ParsedRegion, type ParsedReview, type ParsedSettings, type ParsedStatus } from "./commands/contract-grammar.js";
4
+ import { type ParsedContractCommand } from "./commands/contract-grammar.js";
5
5
  import { type ContractCommand as Command } from "./commands/contract-help.js";
6
6
  import { type CliUsageGuide } from "./usage.js";
7
7
  export { CliUsageError } from "./usage.js";
@@ -10,7 +10,7 @@ export type { Command };
10
10
  export declare function renderRootHelp(columns?: number): string;
11
11
  export declare function usageGuideForCommand(command: ParsedCommand): CliUsageGuide;
12
12
  export declare function renderHelp(coordinate: CliHelpCoordinate, columns?: number): string;
13
- export type ParsedCommand = ParsedBind | ParsedAmend | ParsedDeliver | ParsedReview | ParsedArc | ParsedAbandon | ParsedStatus | ParsedLs | ParsedAudit | ParsedReconcile | ParsedNuke | ParsedSettings | ParsedRegion | ParsedInstallCommand | ParsedAkumaCommand | ParsedTaskCommand;
13
+ export type ParsedCommand = ParsedContractCommand | ParsedInstallCommand | ParsedAkumaCommand | ParsedTaskCommand;
14
14
  type CliHelpCoordinate = Readonly<{
15
15
  kind: "root";
16
16
  }> | Readonly<{
@@ -1,11 +1,8 @@
1
1
  import type { AkumaList } from "../../akuma/akuma.js";
2
- import type { ArchetypeCatalogRow } from "../../akuma/archetype.js";
2
+ import type { ArchetypeCatalog } from "../../index.js";
3
3
  import type { ContractList } from "../../library/contract-types.js";
4
4
  import type { TaskPage, TaskRow } from "../../task/index.js";
5
5
  export declare function renderAkumaCatalogue(list: AkumaList, archetype: string | null): string;
6
6
  export declare function renderContractCatalogue(list: ContractList): string;
7
- export declare function renderArchetypeCatalogue(list: Readonly<{
8
- rows: readonly ArchetypeCatalogRow[];
9
- hasMore: boolean;
10
- }>): string;
7
+ export declare function renderArchetypeCatalogue(list: ArchetypeCatalog): string;
11
8
  export declare function renderTaskCatalogue(list: TaskPage<TaskRow>, namespace: readonly string[]): string;
@@ -1,5 +1,5 @@
1
1
  import { parseAkuId } from "../../akuma/identity.js";
2
- import { lifecycleWord, shortGitId } from "./contract-observation.js";
2
+ import { gateDisplayName, lifecycleWord, shortGitId } from "./contract-observation.js";
3
3
  import { receiptPayload } from "./receipt.js";
4
4
  import { renderOpaqueBlock, DEFAULT_CLI_COLUMNS } from "./terminal.js";
5
5
  function journalCount(events, source) {
@@ -120,15 +120,12 @@ function eventAt(event) {
120
120
  function eventKind(event) {
121
121
  return event.source === "journal" ? event.fact.kind : "dispatch";
122
122
  }
123
- function gateNoun(gate) {
124
- return gate === "reviewed" ? "review" : gate === "verified" ? "verification" : gate;
125
- }
126
123
  function mark(verdict) {
127
124
  return verdict === "satisfied" ? "✓" : "×";
128
125
  }
129
126
  function bindLine(bind, dispatch) {
130
127
  const target = bind.data.coordinates.target?.replace(/^refs\/heads\//u, "") ?? "targetless";
131
- const gates = bind.data.terms.gates.map(gateNoun);
128
+ const gates = bind.data.terms.gates.map(gateDisplayName);
132
129
  const gateFact = gates.length === 0 ? "" : ` · ${gates.length === 1 ? "gate" : "gates"} ${gates.join(" · ")}`;
133
130
  let alias = "";
134
131
  if (dispatch?.source === "dispatch") {
@@ -190,7 +187,7 @@ function skeletonBeatLines(beat, history) {
190
187
  ];
191
188
  }
192
189
  case "attestation":
193
- return [`${clock(first)} ${mark(fact.data.verdict)} ${gateNoun(fact.data.gate)}${evidenceSuffix()}`];
190
+ return [`${clock(first)} ${mark(fact.data.verdict)} ${gateDisplayName(fact.data.gate)}${evidenceSuffix()}`];
194
191
  case "amend": {
195
192
  const changed = [fact.data.gates.length > 0 ? "gates" : "", fact.data.after.length > 0 ? "after" : ""]
196
193
  .filter((value) => value.length > 0)
@@ -40,26 +40,7 @@ function checkoutBehindRows(path, target, columns) {
40
40
  }
41
41
  function lagRows(lag, columns) {
42
42
  const lines = [];
43
- if (lag.kind === "worktree-retained") {
44
- receiptRow(lines, "!", "lag", [{ text: "worktree retained" }, { text: lag.path, opaque: true }], columns);
45
- }
46
- else if (lag.kind === "worktree-follow-retained") {
47
- receiptRow(lines, "!", "lag", [
48
- { text: "worktree follow retained" },
49
- { text: "·" },
50
- { text: lag.reason.replaceAll("-", " ") },
51
- { text: "·" },
52
- { text: lag.path, opaque: true },
53
- ], columns);
54
- }
55
- else if (lag.kind === "unsealed-bytes") {
56
- receiptRow(lines, "!", "lag", [{ text: "unsealed bytes" }, { text: lag.path, opaque: true }], columns);
57
- }
58
- else if (lag.kind === "target-checkout-retained") {
59
- pushBlock(lines, checkoutBehindRows(lag.path, lag.target, columns));
60
- receiptPayload(lines, "reason", lag.diagnostic);
61
- }
62
- else if (lag.kind === "worktree-hook-failed") {
43
+ if (lag.kind === "worktree-hook-failed") {
63
44
  receiptRow(lines, "!", "lag", [
64
45
  {
65
46
  text: `worktree-hook-failed ${lag.phase} ${lag.path} command ${lag.command} name ${lag.name} ${hookFailureSummary(lag.failure)}`,
@@ -153,24 +134,12 @@ function overlapRows(overlaps, color) {
153
134
  }
154
135
  return lines;
155
136
  }
156
- function pushBlock(lines, block) {
157
- if (block.length === 0)
158
- return;
159
- lines.push(...block);
160
- }
161
- function acceptedRecord(result, columns) {
162
- const record = [];
163
- const recoverySnapshot = effectRecoverySnapshot(result.effects);
164
- if (recoverySnapshot !== undefined)
165
- receiptRow(record, " ", "recovery snapshot", [{ text: recoverySnapshot, opaque: true }], columns);
166
- return record;
167
- }
168
137
  function acceptedLagRows(result, columns) {
169
138
  const obligations = [];
170
139
  // A checkout this invocation's own follow could not carry is loud; the same arm's reconciliation lag
171
140
  // is pre-existing residue and stays in the typed result only.
172
141
  for (const checkout of effectRetainedCheckouts(result.effects) ?? []) {
173
- pushBlock(obligations, checkoutBehindRows(checkout.path, checkout.target, columns));
142
+ obligations.push(...checkoutBehindRows(checkout.path, checkout.target, columns));
174
143
  }
175
144
  for (const { contract, lag } of effectLags(result.effects)) {
176
145
  if (lag.kind === "worktree-retained" ||
@@ -180,29 +149,34 @@ function acceptedLagRows(result, columns) {
180
149
  continue;
181
150
  if (contract !== result.contract)
182
151
  receiptRow(obligations, "!", "lag owner", [{ text: contract, opaque: true }], columns);
183
- pushBlock(obligations, lagRows(lag, columns));
152
+ obligations.push(...lagRows(lag, columns));
184
153
  }
185
154
  for (const { contract, lag } of effectSettlementLags(result.effects)) {
186
155
  if (contract !== result.contract)
187
156
  receiptRow(obligations, "!", "settlement owner", [{ text: contract, opaque: true }], columns);
188
- pushBlock(obligations, settlementLagRows(lag, columns));
157
+ obligations.push(...settlementLagRows(lag, columns));
189
158
  }
190
- pushBlock(obligations, executionCleanupLines(effectCleanup(result.effects), columns, result.contract));
191
- pushBlock(obligations, executionStopLines(effectExecutionStops(result.effects), columns));
159
+ obligations.push(...executionCleanupLines(effectCleanup(result.effects), columns, result.contract));
160
+ obligations.push(...executionStopLines(effectExecutionStops(result.effects), columns));
192
161
  return obligations;
193
162
  }
194
163
  function acceptedDeviations(result, columns, color) {
195
164
  const deviations = [];
196
165
  if (result.value.overlaps !== undefined)
197
- pushBlock(deviations, overlapRows(result.value.overlaps, color));
166
+ deviations.push(...overlapRows(result.value.overlaps, color));
198
167
  if (result.value.overlapFailure !== undefined) {
199
168
  receiptRow(deviations, "!", "overlap", [{ text: "unavailable" }], columns);
200
169
  receiptPayload(deviations, "reason", result.value.overlapFailure);
201
170
  }
202
171
  return deviations;
203
172
  }
173
+ /** Evidence handles stay in JSON and history; ordinary receipt text carries only outstanding obligations. */
204
174
  function recordBlock(result, columns) {
205
- const rows = [...acceptedRecord(result, columns), ...acceptedLagRows(result, columns)];
175
+ const rows = [];
176
+ const recoverySnapshot = effectRecoverySnapshot(result.effects);
177
+ if (recoverySnapshot !== undefined)
178
+ receiptRow(rows, " ", "recovery snapshot", [{ text: recoverySnapshot, opaque: true }], columns);
179
+ rows.push(...acceptedLagRows(result, columns));
206
180
  return rows;
207
181
  }
208
182
  /** A terminal command names the worktree it retired, or the retained worktree it failed to remove. */
@@ -279,15 +253,6 @@ function completedPlacementLines(result, columns) {
279
253
  receiptRow(lines, "✓", lifecycleWord("claimed"), [], columns);
280
254
  return lines;
281
255
  }
282
- /** Evidence handles stay in JSON and history; ordinary receipt text carries only outstanding obligations. */
283
- function obligationLines(result, columns) {
284
- const rows = [];
285
- const recoverySnapshot = effectRecoverySnapshot(result.effects);
286
- if (recoverySnapshot !== undefined)
287
- receiptRow(rows, " ", "recovery snapshot", [{ text: recoverySnapshot, opaque: true }], columns);
288
- rows.push(...acceptedLagRows(result, columns));
289
- return rows;
290
- }
291
256
  function movementLines(result, columns) {
292
257
  const count = result.facts.filter((fact) => fact.kind === "reintegrated").length;
293
258
  if (count === 0)
@@ -403,7 +368,7 @@ function renderAcceptedDeliver(result, columns) {
403
368
  lines.push(...stopLines(verification.stop, columns, result.contract));
404
369
  if (!complete && result.value.placement !== undefined)
405
370
  lines.push(...stopLines(result.value.placement, columns, result.contract));
406
- lines.push(...continuationLines(result, columns), ...(complete ? obligationLines(result, columns) : recordBlock(result, columns)), ...worktreeRetirementLines(result, columns), ...gatesAwaitLines(result.value.placement));
371
+ lines.push(...continuationLines(result, columns), ...recordBlock(result, columns), ...worktreeRetirementLines(result, columns), ...gatesAwaitLines(result.value.placement));
407
372
  return lines.join("\n");
408
373
  }
409
374
  function renderAcceptedReview(result, columns) {
@@ -416,7 +381,7 @@ function renderAcceptedReview(result, columns) {
416
381
  lines.push(...stopLines(result.value.placement, columns, result.contract));
417
382
  }
418
383
  lines.push(...continuationLines(result, columns));
419
- lines.push(...obligationLines(result, columns));
384
+ lines.push(...recordBlock(result, columns));
420
385
  lines.push(...worktreeRetirementLines(result, columns));
421
386
  lines.push(...gatesAwaitLines(result.value.placement));
422
387
  return lines.join("\n");
@@ -1,3 +1,4 @@
1
+ import { gateDisplayName } from "./contract-observation.js";
1
2
  import { renderRefusalFacts } from "./refusal.js";
2
3
  import { DEFAULT_CLI_COLUMNS, displayColumns, orderRefusalFacts, renderOpaqueBlock, safeText, quotedText, } from "./terminal.js";
3
4
  export function receiptRow(lines, mark, label, segments, columns) {
@@ -73,14 +74,6 @@ function prerequisiteRows(stop, columns) {
73
74
  }
74
75
  return lines;
75
76
  }
76
- /** Requirement names speak as plain event nouns; the "gate" class word never prints on a receipt. */
77
- function eventNoun(gate) {
78
- if (gate === "reviewed")
79
- return "review";
80
- if (gate === "verified")
81
- return "verification";
82
- return gate;
83
- }
84
77
  /** Only a recorded unsatisfied verdict alarms; missing and stale requirements fold into the await line. */
85
78
  function gateAlarmRows(stop, columns) {
86
79
  if (!("refusal" in stop) || stop.refusal?.kind !== "gates-unsatisfied")
@@ -90,7 +83,7 @@ function gateAlarmRows(stop, columns) {
90
83
  const { gate, current } = report;
91
84
  if (current.kind !== "attested")
92
85
  continue;
93
- receiptRow(lines, "!", eventNoun(gate), [{ text: `· ${current.verdict}` }, { text: `· at ${current.at}` }], columns);
86
+ receiptRow(lines, "!", gateDisplayName(gate), [{ text: `· ${current.verdict}` }, { text: `· at ${current.at}` }], columns);
94
87
  if (current.summary !== undefined)
95
88
  receiptPayload(lines, " summary", current.summary);
96
89
  }
@@ -106,7 +99,7 @@ export function gatesAwaitLines(placement) {
106
99
  return [];
107
100
  const events = placement.refusal.unmet
108
101
  .filter((report) => report.current.kind !== "attested")
109
- .map((report) => eventNoun(report.gate));
102
+ .map((report) => gateDisplayName(report.gate));
110
103
  if (events.length === 0)
111
104
  return [];
112
105
  return [`⧗ awaiting ${events.length > 3 ? `${events.length} gates` : events.join(", ")}`];
@@ -22,17 +22,15 @@ type TaskFailure = Extract<TaskMutationResult, {
22
22
  /** Task dispositions and relation states are snake_case facts; people read them as words. */
23
23
  export declare function dispositionText(word: string): string;
24
24
  export declare function taskFrameHead(view: string, scope: string): string;
25
- export declare function renderDoctor(report: TaskDoctorReport): string;
26
- /** One addressed show selection rendered directly from its native answer. */
27
- export declare function renderTaskShow(result: TaskShowResult, context?: TextRenderContext): string;
28
- /** One list read rendered from its native answer and the leaf's presentation-only scope. */
29
25
  export declare function renderTaskList(action: "ls" | "ready" | "blocked" | "query", scope: TaskListScope, result: TaskListOutcome, context?: TextRenderContext): string;
26
+ export declare function renderTaskShow(result: TaskShowResult, context?: TextRenderContext): string;
27
+ export declare function renderDoctor(report: TaskDoctorReport): string;
28
+ export declare function renderTaskUpdate(result: TaskUpdateResult, context?: TextRenderContext): string;
29
+ export declare function renderTaskCompose(result: TaskCompositionResult, context?: TextRenderContext): string;
30
30
  export declare function renderTaskTree(result: TaskDecompositionTree, context?: TextRenderContext): string;
31
31
  export declare function renderTaskContext(result: TaskContextResult, context?: TextRenderContext): string;
32
- export declare function renderTaskCompose(result: TaskCompositionResult, context?: TextRenderContext): string;
33
32
  /** One single-Task mutation answer; `verb` is the literal action the leaf invoked. */
34
33
  export declare function renderTaskMutation(verb: string, result: TaskMutationResult, context?: TextRenderContext): string;
35
- export declare function renderTaskUpdate(result: TaskUpdateResult, context?: TextRenderContext): string;
36
34
  /** One lifecycle answer: a single mutation or a plural batch, both native shapes. */
37
35
  export declare function renderTaskLifecycle(verb: string, result: TaskMutationResult | TaskBatchResult, context?: TextRenderContext): string;
38
36
  /** A native refusal the CLI edge raised for one action, through the shared refusal grammar. */
@@ -33,15 +33,8 @@ function stateEntity(task) {
33
33
  title: task.title,
34
34
  };
35
35
  }
36
- const TASK_REFUSAL_WORDS = {
37
- "task-missing": "task missing",
38
- "invalid-lifecycle-transition": "invalid lifecycle transition",
39
- "invalid-namespace-context": "invalid namespace context",
40
- "relation-owned-by-other": "relation owned by other",
41
- "invalid-composition": "invalid composition",
42
- };
43
36
  function projectRefusal(refusal) {
44
- const diagnostic = TASK_REFUSAL_WORDS[refusal.kind] ?? refusal.kind.replaceAll("-", " ");
37
+ const diagnostic = refusal.kind.replaceAll("-", " ");
45
38
  if (refusal.kind === "task-missing")
46
39
  return { diagnostic, facts: [`task ${refusal.taskId}`] };
47
40
  if (refusal.kind === "invalid-lifecycle-transition") {
@@ -110,7 +103,8 @@ function renderListRow(item, columns, omitDisposition) {
110
103
  }
111
104
  return lines;
112
105
  }
113
- function renderRows(action, scope, result, columns) {
106
+ export function renderTaskList(action, scope, result, context = DEFAULT_CONTEXT) {
107
+ const columns = context.columns;
114
108
  if (result.kind !== "accepted")
115
109
  return renderFailure(action, result, columns);
116
110
  const view = action === "ls" ? "tasks" : action;
@@ -162,7 +156,8 @@ function renderShowDetail(result, columns) {
162
156
  receiptPayload(lines, "body", task.body);
163
157
  return lines.join("\n");
164
158
  }
165
- function renderShow(result, columns) {
159
+ export function renderTaskShow(result, context = DEFAULT_CONTEXT) {
160
+ const columns = context.columns;
166
161
  if (Array.isArray(result))
167
162
  return result.map((detail) => renderShowDetail(detail, columns)).join("\n\n");
168
163
  if ("kind" in result)
@@ -214,7 +209,8 @@ function renderMutation(action, result, columns) {
214
209
  return renderFailure(action, result, columns);
215
210
  return renderAcceptedMutation(action, result.value, columns);
216
211
  }
217
- function renderUpdate(result, columns) {
212
+ export function renderTaskUpdate(result, context = DEFAULT_CONTEXT) {
213
+ const columns = context.columns;
218
214
  if (result.kind !== "accepted")
219
215
  return renderFailure("update", result, columns);
220
216
  return renderAcceptedMutation("update", result.value.task, columns, result.value.changedFields);
@@ -259,7 +255,8 @@ function renderPlan(result) {
259
255
  }
260
256
  return lines.join("\n");
261
257
  }
262
- function renderCompose(result, columns) {
258
+ export function renderTaskCompose(result, context = DEFAULT_CONTEXT) {
259
+ const columns = context.columns;
263
260
  if (result.kind === "incomplete")
264
261
  return "";
265
262
  if (result.kind === "planned")
@@ -272,14 +269,6 @@ function renderCompose(result, columns) {
272
269
  ...admissionLines(result.admissions),
273
270
  ].join("\n");
274
271
  }
275
- /** One addressed show selection rendered directly from its native answer. */
276
- export function renderTaskShow(result, context = DEFAULT_CONTEXT) {
277
- return renderShow(result, context.columns);
278
- }
279
- /** One list read rendered from its native answer and the leaf's presentation-only scope. */
280
- export function renderTaskList(action, scope, result, context = DEFAULT_CONTEXT) {
281
- return renderRows(action, scope, result, context.columns);
282
- }
283
272
  export function renderTaskTree(result, context = DEFAULT_CONTEXT) {
284
273
  return result.kind === "accepted"
285
274
  ? treeLines(result.value, context.columns).join("\n")
@@ -291,16 +280,10 @@ export function renderTaskContext(result, context = DEFAULT_CONTEXT) {
291
280
  const value = result.value.namespace.length === 0 ? "root" : result.value.namespace.join("/");
292
281
  return `context ${value} · ${result.value.source}`;
293
282
  }
294
- export function renderTaskCompose(result, context = DEFAULT_CONTEXT) {
295
- return renderCompose(result, context.columns);
296
- }
297
283
  /** One single-Task mutation answer; `verb` is the literal action the leaf invoked. */
298
284
  export function renderTaskMutation(verb, result, context = DEFAULT_CONTEXT) {
299
285
  return renderMutation(verb, result, context.columns);
300
286
  }
301
- export function renderTaskUpdate(result, context = DEFAULT_CONTEXT) {
302
- return renderUpdate(result, context.columns);
303
- }
304
287
  /** One lifecycle answer: a single mutation or a plural batch, both native shapes. */
305
288
  export function renderTaskLifecycle(verb, result, context = DEFAULT_CONTEXT) {
306
289
  return "items" in result ? renderBatch(verb, result, context.columns) : renderMutation(verb, result, context.columns);
@@ -1,5 +1,5 @@
1
1
  import { type LibraryExecution } from "../akuma/requests.js";
2
- import type { ActorId } from "../index.js";
2
+ import { type ActorId } from "../index.js";
3
3
  import type { ExecutionObserver } from "../protocol/execution-observation.js";
4
4
  import { type ParsedCommand, type ParsedInvocation } from "./parse.js";
5
5
  export type ParsedCommandInvocation = Extract<ParsedInvocation, {