@astrosheep/keiyaku 4.6.4 → 4.6.7

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 (247) hide show
  1. package/README.md +7 -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/claude}/skills/keiyaku-akuma/SKILL.md +43 -8
  6. package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-bind/SKILL.md +7 -8
  7. package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-workflow/SKILL.md +3 -3
  8. package/build/{integrations/marketplace/plugins/keiyaku → plugins/codex}/.codex-plugin/plugin.json +1 -1
  9. package/build/plugins/codex/skills/keiyaku/SKILL.md +44 -0
  10. package/build/plugins/codex/skills/keiyaku-akuma/SKILL.md +130 -0
  11. package/build/plugins/codex/skills/keiyaku-akuma/references/automation.md +269 -0
  12. package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +65 -0
  13. package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +216 -0
  14. package/build/plugins/codex/skills/keiyaku-bind/agents/openai.yaml +4 -0
  15. package/build/plugins/codex/skills/keiyaku-task/SKILL.md +104 -0
  16. package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +129 -0
  17. package/build/plugins/opencode/package.json +6 -0
  18. package/build/plugins/opencode/skills/keiyaku/SKILL.md +44 -0
  19. package/build/plugins/opencode/skills/keiyaku-akuma/SKILL.md +130 -0
  20. package/build/plugins/opencode/skills/keiyaku-akuma/references/automation.md +269 -0
  21. package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +65 -0
  22. package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +216 -0
  23. package/build/plugins/opencode/skills/keiyaku-bind/agents/openai.yaml +4 -0
  24. package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +104 -0
  25. package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +129 -0
  26. package/build/skills/keiyaku/SKILL.md +44 -0
  27. package/build/skills/keiyaku-akuma/SKILL.md +130 -0
  28. package/build/skills/keiyaku-akuma/references/automation.md +269 -0
  29. package/build/skills/keiyaku-babysit/SKILL.md +65 -0
  30. package/build/skills/keiyaku-bind/SKILL.md +216 -0
  31. package/build/skills/keiyaku-bind/agents/openai.yaml +4 -0
  32. package/build/skills/keiyaku-task/SKILL.md +104 -0
  33. package/build/skills/keiyaku-workflow/SKILL.md +129 -0
  34. package/build/src/akuma/akuma-instance.js +7 -5
  35. package/build/src/akuma/akuma-observe.d.ts +22 -15
  36. package/build/src/akuma/akuma-observe.js +87 -16
  37. package/build/src/akuma/akuma-owner.d.ts +3 -2
  38. package/build/src/akuma/akuma-owner.js +28 -10
  39. package/build/src/akuma/akuma-selection-execution.d.ts +3 -1
  40. package/build/src/akuma/akuma-selection-execution.js +2 -1
  41. package/build/src/akuma/akuma-wait.d.ts +6 -4
  42. package/build/src/akuma/akuma-wait.js +78 -53
  43. package/build/src/akuma/akuma.d.ts +6 -4
  44. package/build/src/akuma/akuma.js +4 -0
  45. package/build/src/akuma/body.d.ts +1 -0
  46. package/build/src/akuma/body.js +12 -23
  47. package/build/src/akuma/call-initial-tell.d.ts +2 -2
  48. package/build/src/akuma/call-initial-tell.js +1 -1
  49. package/build/src/akuma/call-request.d.ts +2 -2
  50. package/build/src/akuma/heart/index.d.ts +7 -2
  51. package/build/src/akuma/heart/index.js +50 -5
  52. package/build/src/akuma/heart/tells.d.ts +33 -2
  53. package/build/src/akuma/heart/tells.js +24 -18
  54. package/build/src/akuma/heart/timeline.d.ts +23 -1
  55. package/build/src/akuma/heart/timeline.js +28 -21
  56. package/build/src/akuma/projection.d.ts +10 -10
  57. package/build/src/akuma/providers/pi/index.js +72 -39
  58. package/build/src/akuma/selection-observation.d.ts +20 -20
  59. package/build/src/akuma/selection-owner-port.d.ts +1 -1
  60. package/build/src/akuma/selection-owner-port.js +16 -5
  61. package/build/src/akuma/selection-request.d.ts +2 -0
  62. package/build/src/akuma/selection-request.js +2 -1
  63. package/build/src/akuma-body.js +5 -2
  64. package/build/src/alias/index.d.ts +0 -1
  65. package/build/src/alias/index.js +0 -4
  66. package/build/src/body/amend.d.ts +0 -4
  67. package/build/src/body/amend.js +0 -3
  68. package/build/src/body/region.d.ts +0 -1
  69. package/build/src/body/region.js +0 -3
  70. package/build/src/body/verification.d.ts +0 -1
  71. package/build/src/cli/commands/akuma-grammar.js +23 -66
  72. package/build/src/cli/commands/akuma.js +23 -42
  73. package/build/src/cli/commands/contract-grammar.d.ts +14 -1
  74. package/build/src/cli/commands/contract-grammar.js +54 -21
  75. package/build/src/cli/commands/contract-help.d.ts +9 -8
  76. package/build/src/cli/commands/contract-help.js +14 -7
  77. package/build/src/cli/commands/contract.js +57 -117
  78. package/build/src/cli/commands/install.d.ts +5 -5
  79. package/build/src/cli/commands/install.js +4 -7
  80. package/build/src/cli/commands/task-grammar.js +10 -66
  81. package/build/src/cli/commands/task.d.ts +0 -1
  82. package/build/src/cli/commands/task.js +34 -53
  83. package/build/src/cli/coordinates.d.ts +1 -2
  84. package/build/src/cli/coordinates.js +1 -4
  85. package/build/src/cli/parse.d.ts +2 -3
  86. package/build/src/cli/parse.js +24 -66
  87. package/build/src/cli/render/akuma.d.ts +3 -16
  88. package/build/src/cli/render/akuma.js +1 -13
  89. package/build/src/cli/render/audit.js +1 -1
  90. package/build/src/cli/render/contract.js +34 -32
  91. package/build/src/cli/render/kanshi-akuma.d.ts +8 -2
  92. package/build/src/cli/render/kanshi-akuma.js +14 -7
  93. package/build/src/cli/render/kanshi.d.ts +3 -1
  94. package/build/src/cli/render/kanshi.js +44 -32
  95. package/build/src/cli/render/receipt.js +6 -1
  96. package/build/src/cli/render/task.d.ts +1 -1
  97. package/build/src/cli/render/task.js +3 -27
  98. package/build/src/cli/render/terminal.d.ts +6 -2
  99. package/build/src/cli/render/terminal.js +8 -2
  100. package/build/src/cli/runtime.js +3 -16
  101. package/build/src/cli/scan.d.ts +26 -0
  102. package/build/src/cli/scan.js +82 -0
  103. package/build/src/cli/streams.d.ts +5 -0
  104. package/build/src/cli/streams.js +11 -0
  105. package/build/src/contract-worktree.js +38 -21
  106. package/build/src/core/facts/codec.d.ts +1 -2
  107. package/build/src/core/facts/codec.js +5 -11
  108. package/build/src/core/facts/types.d.ts +16 -2
  109. package/build/src/core/facts/types.js +15 -0
  110. package/build/src/core/verbs/abandon.js +3 -9
  111. package/build/src/core/verbs/amend.js +2 -9
  112. package/build/src/core/verbs/arc.js +6 -13
  113. package/build/src/core/verbs/attestation.js +2 -9
  114. package/build/src/core/verbs/bind.js +2 -9
  115. package/build/src/core/verbs/deliver.js +2 -9
  116. package/build/src/core/verbs/placement.d.ts +1 -1
  117. package/build/src/core/verbs/placement.js +2 -9
  118. package/build/src/core/verbs/reintegrate.d.ts +1 -1
  119. package/build/src/core/verbs/reintegrate.js +2 -9
  120. package/build/src/dispatch/index.d.ts +2 -2
  121. package/build/src/dispatch/index.js +33 -11
  122. package/build/src/git/hooks.d.ts +2 -4
  123. package/build/src/git/hooks.js +0 -12
  124. package/build/src/git/integration.d.ts +5 -3
  125. package/build/src/git/integration.js +36 -25
  126. package/build/src/git/nuke.js +4 -4
  127. package/build/src/git/observe.d.ts +4 -4
  128. package/build/src/git/observe.js +5 -5
  129. package/build/src/git/process.d.ts +1 -4
  130. package/build/src/git/process.js +1 -11
  131. package/build/src/git/read-observation.js +1 -1
  132. package/build/src/git/reconcile.d.ts +1 -1
  133. package/build/src/git/reconcile.js +15 -13
  134. package/build/src/git/repository.d.ts +2 -6
  135. package/build/src/git/repository.js +18 -31
  136. package/build/src/git/scratch.d.ts +6 -6
  137. package/build/src/git/scratch.js +110 -46
  138. package/build/src/git/target-placement.d.ts +5 -5
  139. package/build/src/git/target-placement.js +18 -33
  140. package/build/src/git/tender.d.ts +6 -2
  141. package/build/src/git/tender.js +19 -12
  142. package/build/src/git/terminal-reconcile.js +24 -13
  143. package/build/src/git/terminal-seal.d.ts +2 -5
  144. package/build/src/git/terminal-seal.js +5 -3
  145. package/build/src/git/workspace.d.ts +17 -13
  146. package/build/src/git/workspace.js +58 -41
  147. package/build/src/kanshi/index.d.ts +2 -2
  148. package/build/src/kanshi/index.js +1 -1
  149. package/build/src/kanshi/read.d.ts +8 -1
  150. package/build/src/kanshi/read.js +72 -7
  151. package/build/src/kanshi/report.d.ts +12 -0
  152. package/build/src/library/akuma-creation.d.ts +4 -4
  153. package/build/src/library/akuma-creation.js +21 -19
  154. package/build/src/library/bind.d.ts +1 -63
  155. package/build/src/library/bind.js +3 -9
  156. package/build/src/library/contract-creation.js +2 -30
  157. package/build/src/library/contract-execution.d.ts +0 -1
  158. package/build/src/library/contract-execution.js +9 -34
  159. package/build/src/library/contract-operations.d.ts +5 -1
  160. package/build/src/library/contract-operations.js +7 -3
  161. package/build/src/library/contract-types.d.ts +1 -1
  162. package/build/src/library/delivery.d.ts +91 -93
  163. package/build/src/library/delivery.js +2 -1
  164. package/build/src/library/input.d.ts +0 -2
  165. package/build/src/library/input.js +0 -4
  166. package/build/src/library/invocation.d.ts +0 -1
  167. package/build/src/library/invocation.js +3 -25
  168. package/build/src/library/outcome.d.ts +651 -602
  169. package/build/src/library/outcome.js +4 -4
  170. package/build/src/library/reconcile.d.ts +6 -0
  171. package/build/src/library/reconcile.js +31 -1
  172. package/build/src/library/repo.d.ts +0 -1
  173. package/build/src/library/selection.d.ts +1 -10
  174. package/build/src/library/selection.js +19 -17
  175. package/build/src/plugin/akuma-signals.d.ts +10 -11
  176. package/build/src/plugin/akuma-signals.js +36 -20
  177. package/build/src/plugin/public.d.ts +5 -0
  178. package/build/src/plugin/runtime.d.ts +1 -0
  179. package/build/src/plugin/runtime.js +34 -23
  180. package/build/src/protocol/abandon.d.ts +1 -1
  181. package/build/src/protocol/abandon.js +3 -10
  182. package/build/src/protocol/amend.js +2 -5
  183. package/build/src/protocol/arc.d.ts +1 -1
  184. package/build/src/protocol/arc.js +2 -9
  185. package/build/src/protocol/attempt.d.ts +3 -20
  186. package/build/src/protocol/attempt.js +6 -5
  187. package/build/src/protocol/audit.d.ts +1 -0
  188. package/build/src/protocol/audit.js +10 -11
  189. package/build/src/protocol/completion.d.ts +129 -55
  190. package/build/src/protocol/completion.js +62 -73
  191. package/build/src/protocol/deliver.d.ts +7 -5
  192. package/build/src/protocol/deliver.js +74 -44
  193. package/build/src/protocol/execution-observation.d.ts +2 -4
  194. package/build/src/protocol/execution-observation.js +3 -7
  195. package/build/src/protocol/intent.d.ts +1 -1
  196. package/build/src/protocol/intent.js +1 -0
  197. package/build/src/protocol/operations.d.ts +24 -12
  198. package/build/src/protocol/operations.js +36 -15
  199. package/build/src/protocol/placement.d.ts +2 -1
  200. package/build/src/protocol/placement.js +21 -5
  201. package/build/src/protocol/progress.d.ts +1 -1
  202. package/build/src/protocol/read/status.js +58 -41
  203. package/build/src/protocol/reintegrate.d.ts +1 -1
  204. package/build/src/protocol/reintegrate.js +10 -19
  205. package/build/src/protocol/review.d.ts +3 -28
  206. package/build/src/protocol/review.js +10 -37
  207. package/build/src/protocol/run.d.ts +19 -7
  208. package/build/src/protocol/run.js +19 -9
  209. package/build/src/runtime/proc/windows-launch.exe +0 -0
  210. package/build/src/settlement/holder.d.ts +2 -4
  211. package/build/src/settlement/holder.js +3 -6
  212. package/build/src/task/board.d.ts +6 -0
  213. package/build/src/task/board.js +30 -1
  214. package/build/src/task/catalog.js +1 -4
  215. package/build/src/task/compose.d.ts +0 -1
  216. package/build/src/task/compose.js +0 -1
  217. package/build/src/task/context.d.ts +0 -1
  218. package/build/src/task/context.js +0 -3
  219. package/build/src/task/created-observation.d.ts +5 -1
  220. package/build/src/task/created-observation.js +12 -5
  221. package/build/src/task/index.d.ts +1 -1
  222. package/build/src/task/index.js +7 -6
  223. package/build/src/task/input.d.ts +0 -6
  224. package/build/src/task/input.js +2 -14
  225. package/build/src/task/mutation.d.ts +3 -4
  226. package/build/src/task/mutation.js +11 -39
  227. package/build/src/task/operations.d.ts +2 -7
  228. package/build/src/task/operations.js +37 -49
  229. package/build/src/task/query.d.ts +0 -1
  230. package/build/src/task/query.js +1 -4
  231. package/build/src/task/store.d.ts +0 -2
  232. package/build/src/task/store.js +27 -11
  233. package/build/src/verification/declaration.js +3 -2
  234. package/build/src/verification/execution.d.ts +3 -2
  235. package/build/src/verification/execution.js +10 -6
  236. package/build/src/workspace-place.d.ts +0 -1
  237. package/build/src/workspace-place.js +0 -11
  238. package/package.json +13 -9
  239. package/build/integrations/marketplace/.claude-plugin/marketplace.json +0 -5
  240. package/build/integrations/marketplace/plugins/keiyaku/package.json +0 -17
  241. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku/SKILL.md +0 -0
  242. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-akuma/references/automation.md +0 -0
  243. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-babysit/SKILL.md +0 -0
  244. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-bind/agents/openai.yaml +0 -0
  245. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-task/SKILL.md +0 -0
  246. /package/build/{integrations/marketplace/plugins/keiyaku/opencode.js → plugins/opencode/index.js} +0 -0
  247. /package/build/{integrations → plugins}/pi/keiyaku.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  import { listArchetypeDefinitions } from "../../akuma/archetype.js";
2
2
  import { executionChannel } from "../../akuma/requests.js";
3
3
  import { Akumas, Keiyaku, KeiyakuError, nuke } from "../../index.js";
4
- import { kanshi, observeKanshi, selectKanshi, selectRegion } from "../../kanshi/index.js";
4
+ import { kanshi, kanshiCategory, observeKanshi, selectKanshi, selectRegion } from "../../kanshi/index.js";
5
5
  import { resolveNamedAddress } from "../../library/address.js";
6
6
  import { composeContractLibrary, observeKeiyaku } from "../../library/contract-composition.js";
7
7
  import { validateArcMarkdown, validateContractMarkdown } from "../../library/input.js";
@@ -14,14 +14,14 @@ import { BindDraftError, preserveBindDraft } from "../draft.js";
14
14
  import { snapshotText } from "../render/akuma-activity.js";
15
15
  import { renderAkumaCatalogue, renderArchetypeCatalogue, renderContractCatalogue, renderTaskCatalogue, } from "../render/catalog.js";
16
16
  import { renderAccepted, renderContractHistory, renderRetry } from "../render/contract.js";
17
- import { renderKanshiText } from "../render/kanshi.js";
17
+ import { renderKanshiCategoryText, renderKanshiText } from "../render/kanshi.js";
18
18
  import { nukeExitCode, renderNukeText } from "../render/nuke.js";
19
19
  import { reconcileHasFailure, renderReconcile } from "../render/reconcile.js";
20
20
  import { renderConflictMaterialized, renderRefusal } from "../render/refusal.js";
21
21
  import { renderRegionText } from "../render/region.js";
22
22
  import { renderSettingsText, settingsJsonValue } from "../render/settings.js";
23
23
  import { canonicalContractSelector, contractFromInput, resolveContractId, resolveKanshiContract, } from "../selectors.js";
24
- import { displayContext, writeJson, writeStdout } from "../streams.js";
24
+ import { displayContext, emit, writeJson, writeStdout } from "../streams.js";
25
25
  import { CliUsageError, isBlankInput } from "../usage.js";
26
26
  import { amendFromCommand } from "./amend.js";
27
27
  import { bindFromCommand } from "./bind.js";
@@ -120,11 +120,8 @@ function renderContractAnswer(answer, project, context) {
120
120
  }
121
121
  }
122
122
  async function finishContractAnswer(answer, output, project) {
123
- if (output === "json")
124
- writeJson(answer);
125
- else
126
- writeStdout(renderContractAnswer(answer, project, displayContext()));
127
- return contractExitCode(answer);
123
+ const text = () => renderContractAnswer(answer, project, displayContext());
124
+ return emit(output, answer, text, contractExitCode(answer));
128
125
  }
129
126
  async function selectedContract(repo, selector, scope) {
130
127
  const id = await resolveContractId(repo, selector, scope);
@@ -187,11 +184,8 @@ async function runBind(command, input, library) {
187
184
  if (answer.kind !== "refused")
188
185
  return await finishContractAnswer(answer, command.output);
189
186
  const draft = await bindDraftReceipt(coordinates.establishWorld, markdown);
190
- if (command.output === "json")
191
- writeJson(answer);
192
- else
193
- writeStdout(renderRefusal(refusedInvocation(answer), draft, displayContext()));
194
- return 1;
187
+ const text = () => renderRefusal(refusedInvocation(answer), draft, displayContext());
188
+ return emit(command.output, answer, text, 1);
195
189
  }
196
190
  catch (error) {
197
191
  if (error instanceof Error && "executionReceipt" in error)
@@ -247,6 +241,7 @@ async function runReview(command, runtime, seat) {
247
241
  answer = await seat.contract.review({
248
242
  verdict: command.verdict,
249
243
  ...(summary === undefined ? {} : { summary }),
244
+ ...(seat.actor === undefined ? {} : { actor: seat.actor }),
250
245
  ...(runtime.signal === undefined ? {} : { signal: runtime.signal }),
251
246
  }, { ...(driver === undefined ? {} : { observe: driver.observe }) });
252
247
  }
@@ -265,11 +260,8 @@ async function runArc(command, runtime, seat) {
265
260
  if (!(error instanceof TypeError) && !(error instanceof KeiyakuError && error.category === "invalid-input"))
266
261
  throw error;
267
262
  const refusal = { kind: "invalid-document", diagnostic: error.message };
268
- if (command.output === "json")
269
- writeJson({ kind: "refused", operation: "arc", contract: seat.id, refusal });
270
- else
271
- writeStdout(renderRefusal({ operation: "arc", contract: seat.id, refusal }, undefined, displayContext()));
272
- return 1;
263
+ const refused = { kind: "refused", operation: "arc", contract: seat.id, refusal };
264
+ return emit(command.output, refused, () => renderRefusal(refused, undefined, displayContext()), 1);
273
265
  }
274
266
  const answer = await seat.contract.arc({
275
267
  markdown,
@@ -325,11 +317,7 @@ function statusRefusal(operation, contract) {
325
317
  }
326
318
  async function runSettings(coordinates, home, output) {
327
319
  const value = await settingsAt(coordinates.world ?? undefined, home);
328
- if (output === "json")
329
- writeJson(settingsJsonValue(value));
330
- else
331
- writeStdout(renderSettingsText(value, displayContext().columns));
332
- return 0;
320
+ return emit(output, settingsJsonValue(value), () => renderSettingsText(value, displayContext().columns), 0);
333
321
  }
334
322
  async function runNuke(command, coordinates) {
335
323
  if (coordinates.world === null)
@@ -338,11 +326,7 @@ async function runNuke(command, coordinates) {
338
326
  world: coordinates.world,
339
327
  ...(command.confirm === undefined ? {} : { confirm: command.confirm }),
340
328
  });
341
- if (command.output === "json")
342
- writeJson(result);
343
- else
344
- writeStdout(renderNukeText(result));
345
- return nukeExitCode(result);
329
+ return emit(command.output, result, () => renderNukeText(result), nukeExitCode(result));
346
330
  }
347
331
  async function runLs(command, coordinates, home) {
348
332
  const query = command.query;
@@ -351,11 +335,7 @@ async function runLs(command, coordinates, home) {
351
335
  repo: requiredRepo(coordinates),
352
336
  ...(query.limit === undefined ? {} : { limit: query.limit }),
353
337
  });
354
- if (command.output === "json")
355
- writeJson(list);
356
- else
357
- writeStdout(renderContractCatalogue(list));
358
- return 0;
338
+ return emit(command.output, list, () => renderContractCatalogue(list), 0);
359
339
  }
360
340
  if (query.kind === "archetypes") {
361
341
  const list = await listArchetypeDefinitions({
@@ -363,11 +343,7 @@ async function runLs(command, coordinates, home) {
363
343
  ...(query.limit === undefined ? {} : { limit: query.limit }),
364
344
  ...(home === undefined ? {} : { home }),
365
345
  });
366
- if (command.output === "json")
367
- writeJson(list);
368
- else
369
- writeStdout(renderArchetypeCatalogue(list));
370
- return 0;
346
+ return emit(command.output, list, () => renderArchetypeCatalogue(list), 0);
371
347
  }
372
348
  if (coordinates.world === null)
373
349
  throw new CliUsageError("no Keiyaku world contains the invocation cwd");
@@ -379,21 +355,13 @@ async function runLs(command, coordinates, home) {
379
355
  });
380
356
  if (listed.kind !== "accepted")
381
357
  throw new Error("Task list did not return an accepted observation");
382
- if (command.output === "json")
383
- writeJson(listed);
384
- else
385
- writeStdout(renderTaskCatalogue(listed.value, query.namespace ?? []));
386
- return 0;
358
+ return emit(command.output, listed, () => renderTaskCatalogue(listed.value, query.namespace ?? []), 0);
387
359
  }
388
360
  const listed = await Akumas.of(coordinates.world).list({
389
361
  ...(query.archetype === undefined ? {} : { archetype: query.archetype }),
390
362
  ...(query.limit === undefined ? {} : { limit: query.limit }),
391
363
  });
392
- if (command.output === "json")
393
- writeJson(listed);
394
- else
395
- writeStdout(renderAkumaCatalogue(listed, query.archetype ?? null));
396
- return 0;
364
+ return emit(command.output, listed, () => renderAkumaCatalogue(listed, query.archetype ?? null), 0);
397
365
  }
398
366
  async function readAkumaStatus(akuma, alias, coordinates) {
399
367
  if (coordinates.world === null)
@@ -437,17 +405,10 @@ async function runStatusGuidance(command, coordinates) {
437
405
  const selected = await selectedContract(repo, command.contract, coordinates.cwd);
438
406
  const guidance = await selected.contract.guidance();
439
407
  if (guidance === null) {
440
- if (command.output === "json")
441
- writeJson(null);
442
- else
443
- writeStdout(renderRefusal(statusRefusal("status", selected.id), undefined, displayContext()));
444
- return 1;
408
+ const refusal = statusRefusal("status", selected.id);
409
+ return emit(command.output, null, () => renderRefusal(refusal, undefined, displayContext()), 1);
445
410
  }
446
- if (command.output === "json")
447
- writeJson(guidance);
448
- else
449
- writeStdout(guidance);
450
- return 0;
411
+ return emit(command.output, guidance, () => guidance, 0);
451
412
  }
452
413
  async function runStatusSelection(command, coordinates) {
453
414
  const selectors = command.selectors;
@@ -474,63 +435,43 @@ async function runStatusSelection(command, coordinates) {
474
435
  if (command.output === "text")
475
436
  blocks.push(resolved.project());
476
437
  }
477
- if (command.output === "json")
478
- writeJson(values);
479
- else
480
- writeStdout(blocks.join("\n\n"));
481
- return 0;
438
+ return emit(command.output, values, () => blocks.join("\n\n"), 0);
482
439
  }
483
- async function runStatus(command, coordinates) {
484
- if (command.guidance === true)
485
- return await runStatusGuidance(command, coordinates);
486
- if ("selectors" in command && command.selectors !== undefined)
487
- return await runStatusSelection({ ...command, selectors: command.selectors }, coordinates);
488
- if (command.akuma === true && command.contract !== undefined) {
489
- const resolved = await readAkumaStatus(command.contract, undefined, coordinates);
490
- if (command.output === "json")
491
- writeJson(resolved.value);
492
- else
493
- writeStdout(resolved.project());
494
- return 0;
495
- }
440
+ async function runStatusCategory(command, coordinates) {
441
+ if (command.category === "contract")
442
+ requiredRepo(coordinates);
443
+ const report = await kanshiCategory({
444
+ world: coordinates.world,
445
+ ...(coordinates.repo === undefined ? {} : { repo: coordinates.repo }),
446
+ category: command.category,
447
+ ...(command.limit === undefined ? {} : { limit: command.limit }),
448
+ });
449
+ return emit(command.output, report, () => renderKanshiCategoryText(report, displayContext()), 0);
450
+ }
451
+ async function runStatusIdentity(command, coordinates) {
496
452
  if (command.contract === undefined) {
497
453
  const report = await kanshi({
498
454
  world: coordinates.world,
499
455
  ...(coordinates.repo === undefined ? {} : { repo: coordinates.repo }),
500
456
  });
501
- if (command.output === "json")
502
- writeJson(report);
503
- else
504
- writeStdout(renderKanshiText(report, displayContext(), "world"));
505
- return 0;
457
+ return emit(command.output, report, () => renderKanshiText(report, displayContext(), "world"), 0);
506
458
  }
507
459
  if (command.contract.startsWith("@")) {
508
460
  const resolved = await namedStatus(command.contract, coordinates, await observeKanshi({
509
461
  world: coordinates.world,
510
462
  ...(coordinates.repo === undefined ? {} : { repo: coordinates.repo }),
511
463
  }));
512
- if (command.output === "json")
513
- writeJson(resolved.value);
514
- else
515
- writeStdout(resolved.project());
516
- return 0;
464
+ return emit(command.output, resolved.value, () => resolved.project(), 0);
517
465
  }
518
466
  if (command.contract.startsWith("kei/")) {
519
467
  const repo = requiredRepo(coordinates);
520
468
  const contract = canonicalContractSelector(command.contract);
521
469
  const report = await kanshi({ world: coordinates.world, repo, contract });
522
470
  if (report.contracts.kind === "present" && report.contracts.value.rows.length === 0) {
523
- if (command.output === "json")
524
- writeJson(statusRefusal("status", contract).refusal);
525
- else
526
- writeStdout(renderRefusal(statusRefusal("status", contract), undefined, displayContext()));
527
- return 1;
471
+ const refusal = statusRefusal("status", contract);
472
+ return emit(command.output, refusal.refusal, () => renderRefusal(refusal, undefined, displayContext()), 1);
528
473
  }
529
- if (command.output === "json")
530
- writeJson(report);
531
- else
532
- writeStdout(renderKanshiText(report, displayContext(), "contract"));
533
- return 0;
474
+ return emit(command.output, report, () => renderKanshiText(report, displayContext(), "contract"), 0);
534
475
  }
535
476
  const report = await kanshi({
536
477
  world: coordinates.world,
@@ -538,28 +479,31 @@ async function runStatus(command, coordinates) {
538
479
  });
539
480
  const contract = resolveKanshiContract(report, command.contract);
540
481
  const selected = selectKanshi({ report, contract });
541
- if (command.output === "json")
542
- writeJson(selected);
543
- else
544
- writeStdout(renderKanshiText(selected, displayContext(), "contract"));
545
- return 0;
482
+ return emit(command.output, selected, () => renderKanshiText(selected, displayContext(), "contract"), 0);
483
+ }
484
+ async function runStatus(command, coordinates) {
485
+ if (command.guidance === true)
486
+ return await runStatusGuidance(command, coordinates);
487
+ if (command.category !== undefined)
488
+ return await runStatusCategory(command, coordinates);
489
+ if ("selectors" in command && command.selectors !== undefined)
490
+ return await runStatusSelection({ ...command, selectors: command.selectors }, coordinates);
491
+ if (command.akuma === true && command.contract !== undefined) {
492
+ const resolved = await readAkumaStatus(command.contract, undefined, coordinates);
493
+ return emit(command.output, resolved.value, () => resolved.project(), 0);
494
+ }
495
+ return await runStatusIdentity(command, coordinates);
546
496
  }
547
497
  async function runRegion(command, coordinates) {
548
498
  const repo = requiredRepo(coordinates);
549
- const emit = (section) => {
550
- if (command.output === "json")
551
- writeJson(section);
552
- else
553
- writeStdout(renderRegionText(section));
554
- return 0;
555
- };
499
+ const emitSection = (section) => emit(command.output, section, () => renderRegionText(section), 0);
556
500
  if (command.paths !== undefined) {
557
501
  const report = await kanshi({ world: coordinates.world, repo, region: { kind: "path", patterns: command.paths } });
558
- return emit(report.region ?? { kind: "absent" });
502
+ return emitSection(report.region ?? { kind: "absent" });
559
503
  }
560
504
  const report = await kanshi({ world: coordinates.world, repo, region: { kind: "declarations" } });
561
505
  if (command.contract === undefined)
562
- return emit(report.region ?? { kind: "absent" });
506
+ return emitSection(report.region ?? { kind: "absent" });
563
507
  const contract = resolveKanshiContract(report, command.contract);
564
508
  const observed = await observeKeiyaku({ repo, id: contract });
565
509
  if (observed.kind === "missing" || observed.row.phase === "claimed" || observed.row.phase === "abandoned") {
@@ -574,8 +518,8 @@ async function runRegion(command, coordinates) {
574
518
  return 1;
575
519
  }
576
520
  if (report.region?.kind !== "present" || report.region.value.kind !== "declarations")
577
- return emit(report.region ?? { kind: "absent" });
578
- return emit({
521
+ return emitSection(report.region ?? { kind: "absent" });
522
+ return emitSection({
579
523
  kind: "present",
580
524
  value: selectRegion({
581
525
  declarations: report.region.value.declarations,
@@ -595,11 +539,7 @@ export async function runContractHistoryCommand(command, coordinates) {
595
539
  writeStdout(renderRefusal({ operation: "history", contract: selected.id, refusal }, undefined, displayContext()));
596
540
  return 1;
597
541
  }
598
- if (command.output === "json")
599
- writeJson(history);
600
- else
601
- writeStdout(renderContractHistory(history, { full: command.full }));
602
- return 0;
542
+ return emit(command.output, history, () => renderContractHistory(history, { full: command.full }), 0);
603
543
  }
604
544
  async function runReconcile(command, coordinates, execution, home) {
605
545
  const repo = requiredRepo(coordinates);
@@ -1,12 +1,12 @@
1
1
  import type { ProcessInput, ProcessOutcome } from "../../runtime/proc/run.js";
2
- export declare const HARNESS_NAMES: readonly ["codex", "claude", "opencode", "pi"];
3
- export type HarnessName = (typeof HARNESS_NAMES)[number];
2
+ declare const HARNESS_NAMES: readonly ["codex", "claude", "opencode", "pi"];
3
+ type HarnessName = (typeof HARNESS_NAMES)[number];
4
4
  export type ParsedInstallCommand = Readonly<{
5
5
  command: "install";
6
6
  harnesses: readonly HarnessName[];
7
7
  output: "text" | "json";
8
8
  }>;
9
- export type HarnessInstallResult = Readonly<{
9
+ type HarnessInstallResult = Readonly<{
10
10
  harness: HarnessName;
11
11
  status: "installed" | "failed";
12
12
  diagnostic?: string;
@@ -15,12 +15,12 @@ export type InstallInvocationResult = Readonly<{
15
15
  kind: "install";
16
16
  results: readonly HarnessInstallResult[];
17
17
  }>;
18
- export type InstallRunner = (input: ProcessInput) => Promise<ProcessOutcome>;
18
+ type InstallRunner = (input: ProcessInput) => Promise<ProcessOutcome>;
19
19
  export declare const INSTALL_USAGE = "install <codex|claude|opencode|pi>\ninstall --all";
20
20
  export declare const INSTALL_ROOT_PURPOSE = "Install the Keiyaku plugin into a supported coding harness.";
21
21
  export declare function parseInstallCommand(argv: readonly string[]): ParsedInstallCommand;
22
22
  export declare function renderInstallHelp(): string;
23
- export declare function installAssetsRoot(): string;
24
23
  export declare function installHarnesses(harnesses: readonly HarnessName[], environment: NodeJS.ProcessEnv, runner?: InstallRunner): Promise<InstallInvocationResult>;
25
24
  export declare function renderInstallText(result: InstallInvocationResult): string;
26
25
  export declare function installExitCode(result: InstallInvocationResult): number;
26
+ export {};
@@ -1,7 +1,7 @@
1
1
  import { dirname, resolve } from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import { CliUsageError, commandGuide, usageLine } from "../usage.js";
4
- export const HARNESS_NAMES = ["codex", "claude", "opencode", "pi"];
4
+ const HARNESS_NAMES = ["codex", "claude", "opencode", "pi"];
5
5
  export const INSTALL_USAGE = "install <codex|claude|opencode|pi>\ninstall --all";
6
6
  export const INSTALL_ROOT_PURPOSE = "Install the Keiyaku plugin into a supported coding harness.";
7
7
  function isHarness(value) {
@@ -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
  }
@@ -83,9 +83,6 @@ function diagnostic(argv, outcome) {
83
83
  const detail = outcome.stderr.trim() || outcome.stdout.trim();
84
84
  return `${argv[0]} exited ${outcome.code}${detail.length === 0 ? "" : `: ${detail}`}`;
85
85
  }
86
- export function installAssetsRoot() {
87
- return ASSET_ROOT;
88
- }
89
86
  export async function installHarnesses(harnesses, environment, runner) {
90
87
  const run = runner ?? (await import("../../runtime/proc/run.js")).runCrossPlatformProcess;
91
88
  const results = [];
@@ -1,4 +1,5 @@
1
- import { CliUsageError, isBlankInput, TASK_FAMILY_USAGE_GUIDE, unknownCommandGuide, } from "../usage.js";
1
+ import { CliUsageError, TASK_FAMILY_USAGE_GUIDE, unknownCommandGuide } from "../usage.js";
2
+ import { scanArgs } from "../scan.js";
2
3
  import { parseTaskNamespaceSelector } from "../../task/catalog.js";
3
4
  import { parseTaskId } from "../../task/identity.js";
4
5
  import { parseTaskQueryExpression, validateTaskLimit, validateTaskParent, } from "./task-query.js";
@@ -241,73 +242,16 @@ export function taskUsageGuide(action) {
241
242
  help: `keiyaku task ${action} --help`,
242
243
  };
243
244
  }
244
- function setFlag(flags, name, kind, value, fail) {
245
- if (flags[name] !== undefined && kind !== "repeat")
246
- fail(`duplicate option: --${name}`);
247
- if (kind === "boolean") {
248
- flags[name] = true;
249
- return;
250
- }
251
- if (value === undefined)
252
- fail(`--${name} requires a value`);
253
- if (isBlankInput(value))
254
- fail(`--${name} requires a nonblank value`);
255
- if (kind === "repeat") {
256
- const current = flags[name];
257
- flags[name] = [...(Array.isArray(current) ? current : []), value];
258
- }
259
- else
260
- flags[name] = value;
261
- }
262
- function scanTaskOption(input, fail) {
263
- const token = input.argv[input.index], name = token.slice(2), kind = input.spec.flags[name];
264
- if (kind === undefined)
265
- fail(`option ${token} is not valid for task ${input.action}`);
266
- const next = kind === "boolean" ? undefined : input.argv[input.index + 1];
267
- if (next === "-" && input.action === "update" && name === "body") {
268
- if (input.stdin !== undefined)
269
- fail("stdin marker '-' may appear only once");
270
- input.flags[name] = "";
271
- return { index: input.index + 1, stdin: name };
272
- }
273
- if (kind !== "boolean" && (next === undefined || next.startsWith("--") || next === "-"))
274
- fail(`--${name} requires a value`);
275
- setFlag(input.flags, name, kind, next, fail);
245
+ /** One scan spec per Task action: `-` reads the document, or `--body -` replaces an update body. */
246
+ function scanSpec(action, spec) {
276
247
  return {
277
- index: input.index + (kind === "boolean" ? 0 : 1),
278
- ...(input.stdin === undefined ? {} : { stdin: input.stdin }),
248
+ subject: `task ${action}`,
249
+ flags: spec.flags,
250
+ ...(spec.stdin === undefined ? {} : { stdin: spec.stdin }),
251
+ stdinRefusal: "stdin marker '-' is not valid here",
252
+ ...(action === "update" ? { stdinValue: "body" } : {}),
279
253
  };
280
254
  }
281
- function scanTaskArgv(action, argv, fail) {
282
- const spec = TASK_COMMAND_SPECS[action], positionals = [], flags = {};
283
- let stdin;
284
- let positionalOnly = false;
285
- for (let index = 1; index < argv.length; index += 1) {
286
- const token = argv[index];
287
- if (!positionalOnly && token === "--") {
288
- positionalOnly = true;
289
- continue;
290
- }
291
- if (!positionalOnly && token === "-") {
292
- if (spec.stdin === undefined)
293
- fail("stdin marker '-' is not valid here");
294
- if (stdin !== undefined)
295
- fail("stdin marker '-' may appear only once");
296
- stdin = spec.stdin;
297
- continue;
298
- }
299
- if (positionalOnly || !token.startsWith("--")) {
300
- if (isBlankInput(token))
301
- fail(`task ${action} requires a nonblank value`);
302
- positionals.push(token);
303
- continue;
304
- }
305
- const scanned = scanTaskOption({ action, spec, argv, index, flags, ...(stdin === undefined ? {} : { stdin }) }, fail);
306
- index = scanned.index;
307
- stdin = scanned.stdin;
308
- }
309
- return { positionals, flags, ...(stdin === undefined ? {} : { stdin }) };
310
- }
311
255
  function validateUpdate(scanned, fail) {
312
256
  const flags = scanned.flags;
313
257
  if (flags.body !== undefined && flags.append !== undefined)
@@ -419,7 +363,7 @@ export function parseTaskCommand(argv) {
419
363
  const fail = (message) => {
420
364
  throw new CliUsageError(message, taskUsageGuide(action));
421
365
  };
422
- const scanned = scanTaskArgv(action, argv, fail);
366
+ const scanned = scanArgs(argv, scanSpec(action, TASK_COMMAND_SPECS[action]), fail);
423
367
  validateTaskScan(action, scanned, fail);
424
368
  let where;
425
369
  if (action === "query" && typeof scanned.flags.where === "string") {
@@ -1,5 +1,4 @@
1
1
  import type { ParsedTaskCommand } from "./task-grammar.js";
2
2
  import type { CliRuntime } from "../runtime.js";
3
3
  import type { CliCoordinates } from "../coordinates.js";
4
- export { renderTaskHelp } from "./task-grammar.js";
5
4
  export declare function runTaskCommand(command: ParsedTaskCommand, coordinates: CliCoordinates, runtime: CliRuntime): Promise<number>;