@astrosheep/keiyaku 4.6.7 → 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 (165) hide show
  1. package/README.md +6 -2
  2. package/build/plugins/pi/keiyaku.ts +0 -5
  3. package/build/src/akuma/akuma-call.d.ts +2 -0
  4. package/build/src/akuma/akuma-call.js +8 -2
  5. package/build/src/akuma/akuma-instance.d.ts +12 -1
  6. package/build/src/akuma/akuma-instance.js +27 -7
  7. package/build/src/akuma/akuma-observe.js +2 -0
  8. package/build/src/akuma/akuma-owner.d.ts +3 -0
  9. package/build/src/akuma/akuma-owner.js +4 -0
  10. package/build/src/akuma/akuma.d.ts +35 -5
  11. package/build/src/akuma/akuma.js +8 -10
  12. package/build/src/akuma/archetype.d.ts +7 -15
  13. package/build/src/akuma/archetype.js +36 -35
  14. package/build/src/akuma/body.d.ts +5 -3
  15. package/build/src/akuma/body.js +29 -7
  16. package/build/src/akuma/call-request.d.ts +18 -10
  17. package/build/src/akuma/call-request.js +10 -3
  18. package/build/src/akuma/caller.d.ts +39 -0
  19. package/build/src/akuma/caller.js +36 -0
  20. package/build/src/akuma/dispatch-association.d.ts +0 -1
  21. package/build/src/akuma/dispatch-association.js +0 -3
  22. package/build/src/akuma/heart/facts.d.ts +16 -12
  23. package/build/src/akuma/heart/facts.js +8 -0
  24. package/build/src/akuma/heart/index.d.ts +2 -7
  25. package/build/src/akuma/heart/index.js +3 -17
  26. package/build/src/akuma/heart/rows.d.ts +3 -3
  27. package/build/src/akuma/heart/soul.d.ts +1 -1
  28. package/build/src/akuma/heart/soul.js +5 -24
  29. package/build/src/akuma/heart/storage.d.ts +5 -0
  30. package/build/src/akuma/heart/storage.js +7 -3
  31. package/build/src/akuma/identity.d.ts +0 -1
  32. package/build/src/akuma/identity.js +2 -5
  33. package/build/src/akuma/index.d.ts +5 -2
  34. package/build/src/akuma/index.js +1 -0
  35. package/build/src/akuma/nuke.js +6 -28
  36. package/build/src/akuma/projection.d.ts +0 -11
  37. package/build/src/akuma/provider-recipe.d.ts +7 -6
  38. package/build/src/akuma/provider-recipe.js +1 -1
  39. package/build/src/akuma/provider.d.ts +6 -10
  40. package/build/src/akuma/provider.js +6 -7
  41. package/build/src/akuma/providers/acp/events.js +5 -18
  42. package/build/src/akuma/providers/acp/index.js +2 -3
  43. package/build/src/akuma/providers/claude/events.js +35 -60
  44. package/build/src/akuma/providers/claude/index.d.ts +2 -2
  45. package/build/src/akuma/providers/claude/index.js +2 -3
  46. package/build/src/akuma/providers/codex-app-server/index.js +2 -2
  47. package/build/src/akuma/providers/decode.d.ts +25 -0
  48. package/build/src/akuma/providers/decode.js +44 -0
  49. package/build/src/akuma/providers/execution-environment.d.ts +2 -1
  50. package/build/src/akuma/providers/execution-environment.js +3 -0
  51. package/build/src/akuma/providers/grok-build/index.js +6 -22
  52. package/build/src/akuma/providers/index.js +2 -0
  53. package/build/src/akuma/providers/lifecycle.d.ts +9 -0
  54. package/build/src/akuma/providers/lifecycle.js +10 -0
  55. package/build/src/akuma/providers/opencode-sdk/events.js +1 -14
  56. package/build/src/akuma/providers/opencode-sdk/index.js +10 -17
  57. package/build/src/akuma/providers/opencode-sdk/session.js +1 -3
  58. package/build/src/akuma/providers/paseo/events.d.ts +25 -0
  59. package/build/src/akuma/providers/paseo/events.js +157 -0
  60. package/build/src/akuma/providers/paseo/index.d.ts +9 -0
  61. package/build/src/akuma/providers/paseo/index.js +353 -0
  62. package/build/src/akuma/providers/pi/events.js +5 -15
  63. package/build/src/akuma/publication.d.ts +2 -0
  64. package/build/src/akuma/publication.js +5 -0
  65. package/build/src/akuma/request-lifecycle.d.ts +3 -0
  66. package/build/src/akuma/request-lifecycle.js +25 -4
  67. package/build/src/akuma/requests.d.ts +3 -1
  68. package/build/src/akuma/requests.js +32 -0
  69. package/build/src/akuma/selection-observation.d.ts +72 -2
  70. package/build/src/akuma/selection-observation.js +0 -6
  71. package/build/src/akuma/turn-drive.js +2 -5
  72. package/build/src/cli/akuma-caller.d.ts +3 -0
  73. package/build/src/cli/akuma-caller.js +21 -0
  74. package/build/src/cli/commands/akuma-grammar.js +7 -12
  75. package/build/src/cli/commands/akuma.js +12 -4
  76. package/build/src/cli/commands/contract-grammar.d.ts +2 -1
  77. package/build/src/cli/commands/contract-grammar.js +13 -15
  78. package/build/src/cli/commands/contract-help.d.ts +2 -1
  79. package/build/src/cli/commands/contract-help.js +31 -1
  80. package/build/src/cli/commands/contract.js +24 -53
  81. package/build/src/cli/commands/task.js +18 -35
  82. package/build/src/cli/parse.d.ts +2 -2
  83. package/build/src/cli/render/catalog.d.ts +2 -5
  84. package/build/src/cli/render/contract-history.js +3 -6
  85. package/build/src/cli/render/contract.js +15 -50
  86. package/build/src/cli/render/receipt.js +3 -10
  87. package/build/src/cli/render/task.d.ts +4 -6
  88. package/build/src/cli/render/task.js +9 -26
  89. package/build/src/cli/runtime.d.ts +1 -1
  90. package/build/src/cli/runtime.js +11 -17
  91. package/build/src/cli/selectors.d.ts +3 -6
  92. package/build/src/cli/selectors.js +22 -53
  93. package/build/src/dispatch/index.d.ts +3 -3
  94. package/build/src/dispatch/index.js +1 -2
  95. package/build/src/git/observe.d.ts +6 -2
  96. package/build/src/git/observe.js +6 -2
  97. package/build/src/index.d.ts +6 -6
  98. package/build/src/index.js +2 -2
  99. package/build/src/kanshi/index.d.ts +1 -1
  100. package/build/src/kanshi/read.js +21 -6
  101. package/build/src/library/address.js +2 -4
  102. package/build/src/library/akuma-creation.d.ts +5 -1
  103. package/build/src/library/akuma-creation.js +27 -47
  104. package/build/src/library/akumas.d.ts +5 -4
  105. package/build/src/library/akumas.js +13 -9
  106. package/build/src/library/bind.d.ts +14 -14
  107. package/build/src/library/bind.js +11 -7
  108. package/build/src/library/contract-address.d.ts +9 -0
  109. package/build/src/library/contract-address.js +71 -0
  110. package/build/src/library/contract-composition.d.ts +4 -7
  111. package/build/src/library/contract-composition.js +6 -18
  112. package/build/src/library/contract-creation.d.ts +3 -5
  113. package/build/src/library/contract-creation.js +19 -17
  114. package/build/src/library/contract-execution.js +18 -23
  115. package/build/src/library/contract-outcomes.d.ts +2 -14
  116. package/build/src/library/contract-outcomes.js +2 -13
  117. package/build/src/library/contract-types.d.ts +36 -2
  118. package/build/src/library/delivery.d.ts +0 -2
  119. package/build/src/library/delivery.js +2 -5
  120. package/build/src/library/keiyaku.d.ts +0 -5
  121. package/build/src/library/keiyaku.js +6 -12
  122. package/build/src/library/outcome.d.ts +500 -499
  123. package/build/src/library/outcome.js +10 -0
  124. package/build/src/library/reconcile.js +8 -16
  125. package/build/src/library/refusal.d.ts +2 -2
  126. package/build/src/library/repo.d.ts +3 -2
  127. package/build/src/library/repo.js +10 -5
  128. package/build/src/library/selection.d.ts +4 -4
  129. package/build/src/library/selection.js +12 -12
  130. package/build/src/plugin/akuma-signals.d.ts +2 -0
  131. package/build/src/plugin/akuma-signals.js +4 -0
  132. package/build/src/plugin/public.d.ts +27 -2
  133. package/build/src/plugin/runtime.js +2 -2
  134. package/build/src/protocol/amend.js +3 -2
  135. package/build/src/protocol/attempt.js +3 -8
  136. package/build/src/protocol/bind.d.ts +2 -2
  137. package/build/src/protocol/bind.js +1 -1
  138. package/build/src/protocol/deliver.js +3 -3
  139. package/build/src/protocol/operations.d.ts +1 -3
  140. package/build/src/protocol/operations.js +0 -8
  141. package/build/src/protocol/outcome.d.ts +1 -2
  142. package/build/src/protocol/outcome.js +1 -13
  143. package/build/src/protocol/placement.js +3 -10
  144. package/build/src/protocol/read/status.js +31 -70
  145. package/build/src/protocol/reintegrate.js +3 -10
  146. package/build/src/protocol/review.js +3 -3
  147. package/build/src/protocol/run.d.ts +5 -1
  148. package/build/src/protocol/run.js +3 -3
  149. package/build/src/runtime/proc/windows-launch.exe +0 -0
  150. package/package.json +8 -4
  151. package/plugins/pi/keiyaku.ts +57 -0
  152. package/skills/keiyaku/SKILL.md +44 -0
  153. package/skills/keiyaku-akuma/SKILL.md +130 -0
  154. package/skills/keiyaku-akuma/references/automation.md +269 -0
  155. package/skills/keiyaku-babysit/SKILL.md +65 -0
  156. package/skills/keiyaku-bind/SKILL.md +216 -0
  157. package/skills/keiyaku-bind/agents/openai.yaml +4 -0
  158. package/skills/keiyaku-task/SKILL.md +104 -0
  159. package/skills/keiyaku-workflow/SKILL.md +129 -0
  160. package/build/src/cli/commands/amend.d.ts +0 -12
  161. package/build/src/cli/commands/amend.js +0 -10
  162. package/build/src/cli/commands/bind.d.ts +0 -11
  163. package/build/src/cli/commands/bind.js +0 -23
  164. package/build/src/dispatch/association.d.ts +0 -1
  165. package/build/src/dispatch/association.js +0 -1
@@ -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, {
@@ -1,7 +1,6 @@
1
1
  import { AkumaNotBornError, AkumaObservationError } from "../akuma/akuma-errors.js";
2
- import { AkumaArchetypeError } from "../akuma/archetype.js";
3
- import { AKUMA_REQUESTS_ENV } from "../akuma/provider.js";
4
- import { bodyRequestExecution, localExecutionContext } from "../akuma/requests.js";
2
+ import { executionForEnvironment } from "../akuma/requests.js";
3
+ import { AkumaArchetypeError } from "../index.js";
5
4
  import { AkumaAddressError, AkumaWorldScopeError } from "../library/address.js";
6
5
  import { encodeFailureWire, KeiyakuError } from "../library/outcome.js";
7
6
  import { isParsedAkumaCommand, runAkumaCommand } from "./commands/akuma.js";
@@ -28,11 +27,6 @@ function memoized(reader) {
28
27
  let value;
29
28
  return () => (value ??= reader());
30
29
  }
31
- function executionForEnvironment(environment) {
32
- return environment[AKUMA_REQUESTS_ENV] === undefined
33
- ? localExecutionContext()
34
- : bodyRequestExecution({ directory: environment[AKUMA_REQUESTS_ENV] });
35
- }
36
30
  function homeFromEnvironment(environment) {
37
31
  const mapped = environment.KEIYAKU_HOME?.trim();
38
32
  return mapped === undefined || mapped.length === 0 ? undefined : mapped;
@@ -175,16 +169,16 @@ export async function runCliCommand(invocation, input = {}) {
175
169
  const home = homeFromEnvironment(environment);
176
170
  const cancellation = cliCancellation(input.signal);
177
171
  let progress;
178
- const runtime = {
179
- environment,
180
- execution: executionForEnvironment(environment),
181
- ...(home === undefined ? {} : { home }),
182
- readStdin: memoized(input.readStdin ?? processStdin),
183
- signal: cancellation.signal,
184
- progress: () => (progress ??= writeExecutionProgress()),
185
- ...(input.actor === undefined ? {} : { actor: input.actor }),
186
- };
187
172
  try {
173
+ const runtime = {
174
+ environment,
175
+ execution: await executionForEnvironment(environment, cancellation.signal),
176
+ ...(home === undefined ? {} : { home }),
177
+ readStdin: memoized(input.readStdin ?? processStdin),
178
+ signal: cancellation.signal,
179
+ progress: () => (progress ??= writeExecutionProgress()),
180
+ ...(input.actor === undefined ? {} : { actor: input.actor }),
181
+ };
188
182
  if (command.command === "install")
189
183
  return await runInstall(command, environment);
190
184
  await admitBindInput(command, invocation, runtime, input.cwd ?? process.cwd());
@@ -1,14 +1,11 @@
1
1
  import { type ExecutionContext } from "../akuma/requests.js";
2
- import type { ContractBoard, ContractId, Keiyaku, Repo } from "../index.js";
3
- import type { KanshiReport } from "../kanshi/index.js";
2
+ import { Keiyaku, type ContractId, type Repo } from "../index.js";
4
3
  type SelectedContract = Readonly<{
5
4
  id: ContractId;
6
5
  contract: Keiyaku;
7
6
  }>;
8
7
  export declare function contractFromInput(repo: Repo, value: string, execution?: ExecutionContext): SelectedContract;
9
- export declare function resolveContextualContract(board: ContractBoard, selector: string | undefined, scope: string): ContractId;
10
- /** Resolve one explicit, short, or worktree-contextual selector to its Contract id. */
11
- export declare function resolveContractId(repo: Repo, selector: string | undefined, scope: string): Promise<ContractId>;
8
+ /** Adapt public Contract resolution evidence to the existing CLI usage diagnostics. */
9
+ export declare function resolveContractId(repo: Repo, selector: string | undefined, cwd: string): Promise<ContractId>;
12
10
  export declare function canonicalContractSelector(selector: string): ContractId;
13
- export declare function resolveKanshiContract(report: KanshiReport, selector: string): string;
14
11
  export {};
@@ -1,76 +1,45 @@
1
- import { resolve } from "node:path";
2
1
  import { localExecutionContext } from "../akuma/requests.js";
3
2
  import { identitySegments } from "../identity/coordinates.js";
3
+ import { Keiyaku } from "../index.js";
4
4
  import { composeContractLibrary } from "../library/contract-composition.js";
5
5
  import { createKeiyakuHandle } from "../library/keiyaku.js";
6
6
  import { CliUsageError } from "./parse.js";
7
- function selectorError(message) {
8
- throw new CliUsageError(message);
9
- }
10
- function activeManagedCandidates(rows) {
11
- return rows.flatMap((contract) => {
12
- if (contract.disposition !== "active" || contract.workspace !== "worktree" || contract.worktreePath === null)
13
- return [];
14
- return [{ id: contract.id, worktreePath: contract.worktreePath }];
15
- });
16
- }
17
7
  export function contractFromInput(repo, value, execution = localExecutionContext()) {
18
8
  try {
19
9
  const id = value;
20
10
  return { id, contract: composeContractLibrary(execution, createKeiyakuHandle).select({ repo, id }) };
21
11
  }
22
12
  catch (error) {
23
- selectorError(error instanceof Error ? error.message : String(error));
13
+ throw new CliUsageError(error instanceof Error ? error.message : String(error));
24
14
  }
25
15
  }
26
- function resolveShortContract(rows, selector) {
27
- if (selector.startsWith("@kei/"))
28
- selectorError(`redundant short contract selector: ${selector}`);
29
- const short = selector.slice(1);
30
- const candidates = activeManagedCandidates(rows).filter((candidate) => candidate.id.slice("kei/".length) === short);
31
- if (candidates.length === 0)
32
- selectorError(`unknown contract selector: ${selector}`);
33
- if (candidates.length !== 1)
34
- selectorError(`ambiguous contract selector: ${selector}`);
35
- return candidates[0].id;
36
- }
37
- function resolveOmittedContract(board, scope) {
38
- const candidates = activeManagedCandidates(board.rows).filter((candidate) => resolve(scope) === resolve(candidate.worktreePath));
39
- if (candidates.length === 0) {
40
- selectorError("an explicit full or @ contract selector is required outside a managed worktree");
16
+ /** Adapt public Contract resolution evidence to the existing CLI usage diagnostics. */
17
+ export async function resolveContractId(repo, selector, cwd) {
18
+ const result = await Keiyaku.with().resolve({ repo, ...(selector === undefined ? {} : { selector }), cwd });
19
+ if (result.kind === "resolved")
20
+ return result.id;
21
+ const refusal = result.refusal;
22
+ switch (refusal.kind) {
23
+ case "invalid-selector":
24
+ throw new CliUsageError(refusal.diagnostic);
25
+ case "redundant-short-selector":
26
+ throw new CliUsageError(`redundant short contract selector: ${refusal.selector}`);
27
+ case "unknown-short-selector":
28
+ throw new CliUsageError(`unknown contract selector: ${refusal.selector}`);
29
+ case "ambiguous-selector":
30
+ throw new CliUsageError("selector" in refusal
31
+ ? `ambiguous contract selector: ${refusal.selector}`
32
+ : "ambiguous managed worktree contract selector");
33
+ case "no-contextual-match":
34
+ throw new CliUsageError("an explicit full or @ contract selector is required outside a managed worktree");
41
35
  }
42
- if (candidates.length !== 1)
43
- selectorError("ambiguous managed worktree contract selector");
44
- return candidates[0].id;
45
- }
46
- export function resolveContextualContract(board, selector, scope) {
47
- if (selector === undefined)
48
- return resolveOmittedContract(board, scope);
49
- if (selector.startsWith("@"))
50
- return resolveShortContract(board.rows, selector);
51
- return selectorError(`contract selector must be kei/<contract-segment> or @<contract-segment>: ${selector}`);
52
- }
53
- /** Resolve one explicit, short, or worktree-contextual selector to its Contract id. */
54
- export async function resolveContractId(repo, selector, scope) {
55
- if (selector !== undefined && !selector.startsWith("@"))
56
- return contractFromInput(repo, selector).id;
57
- const { listKeiyaku } = await import("../library/contract-composition.js");
58
- return resolveContextualContract(await listKeiyaku({ repo }), selector, scope);
59
36
  }
60
37
  export function canonicalContractSelector(selector) {
61
38
  try {
62
39
  identitySegments({ family: "kei", value: selector });
63
40
  }
64
41
  catch {
65
- return selectorError(`contract selector must use kei/: ${selector}`);
42
+ throw new CliUsageError(`contract selector must use kei/: ${selector}`);
66
43
  }
67
44
  return selector;
68
45
  }
69
- export function resolveKanshiContract(report, selector) {
70
- if (report.contracts.kind !== "present") {
71
- return selectorError(`cannot select a contract while the Contract world is ${report.contracts.kind}`);
72
- }
73
- if (selector.startsWith("@"))
74
- return resolveShortContract(report.contracts.value.rows, selector);
75
- return canonicalContractSelector(selector);
76
- }