@astrosheep/keiyaku 4.0.3 → 4.0.5

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 (238) hide show
  1. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
  2. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
  3. package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
  4. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +4 -4
  5. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +1 -1
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +15 -1
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +3 -1
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +34 -13
  9. package/build/src/akuma/akuma.d.ts +34 -12
  10. package/build/src/akuma/akuma.js +118 -63
  11. package/build/src/akuma/allowed.d.ts +7 -0
  12. package/build/src/akuma/allowed.js +33 -0
  13. package/build/src/akuma/archetype.d.ts +7 -4
  14. package/build/src/akuma/archetype.js +15 -16
  15. package/build/src/akuma/body.d.ts +6 -1
  16. package/build/src/akuma/body.js +36 -27
  17. package/build/src/akuma/heart/facts.d.ts +82 -14
  18. package/build/src/akuma/heart/index.d.ts +5 -18
  19. package/build/src/akuma/heart/index.js +14 -84
  20. package/build/src/akuma/heart/request-authority.d.ts +12 -0
  21. package/build/src/akuma/heart/request-authority.js +119 -0
  22. package/build/src/akuma/heart/request-rows.d.ts +16 -0
  23. package/build/src/akuma/heart/request-rows.js +88 -0
  24. package/build/src/akuma/heart/rows.d.ts +1 -26
  25. package/build/src/akuma/heart/rows.js +0 -50
  26. package/build/src/akuma/heart/schema.d.ts +1 -1
  27. package/build/src/akuma/heart/schema.js +22 -10
  28. package/build/src/akuma/heart/soul.js +2 -36
  29. package/build/src/akuma/heart/storage.d.ts +1 -0
  30. package/build/src/akuma/heart/storage.js +15 -0
  31. package/build/src/akuma/heart/timeline.d.ts +1 -5
  32. package/build/src/akuma/heart/timeline.js +8 -17
  33. package/build/src/akuma/index.d.ts +5 -2
  34. package/build/src/akuma/index.js +1 -0
  35. package/build/src/akuma/projection.d.ts +17 -3
  36. package/build/src/akuma/projection.js +40 -3
  37. package/build/src/akuma/provider-recipe.js +1 -11
  38. package/build/src/akuma/provider.d.ts +2 -7
  39. package/build/src/akuma/provider.js +2 -1
  40. package/build/src/akuma/providers/acp/core.d.ts +3 -1
  41. package/build/src/akuma/providers/acp/core.js +10 -6
  42. package/build/src/akuma/providers/acp/events.d.ts +11 -3
  43. package/build/src/akuma/providers/acp/events.js +78 -4
  44. package/build/src/akuma/providers/acp/index.js +0 -1
  45. package/build/src/akuma/providers/claude/events.js +62 -3
  46. package/build/src/akuma/providers/claude/index.d.ts +0 -4
  47. package/build/src/akuma/providers/claude/index.js +7 -3
  48. package/build/src/akuma/providers/codex-app-server/events.js +1 -13
  49. package/build/src/akuma/providers/codex-app-server/index.d.ts +2 -27
  50. package/build/src/akuma/providers/codex-app-server/index.js +0 -2
  51. package/build/src/akuma/providers/grok-build/index.d.ts +2 -1
  52. package/build/src/akuma/providers/grok-build/index.js +72 -3
  53. package/build/src/akuma/providers/opencode-sdk/events.js +71 -6
  54. package/build/src/akuma/providers/opencode-sdk/index.d.ts +2 -28
  55. package/build/src/akuma/providers/opencode-sdk/index.js +8 -4
  56. package/build/src/akuma/providers/opencode-sdk/session.d.ts +1 -1
  57. package/build/src/akuma/providers/opencode-sdk/session.js +1 -1
  58. package/build/src/akuma/providers/pi/events.js +17 -3
  59. package/build/src/akuma/providers/pi/index.js +11 -4
  60. package/build/src/akuma/providers/unified-patch.d.ts +4 -0
  61. package/build/src/akuma/providers/unified-patch.js +14 -0
  62. package/build/src/akuma/publication.d.ts +1 -1
  63. package/build/src/akuma/publication.js +1 -1
  64. package/build/src/akuma/request-serve.d.ts +87 -0
  65. package/build/src/akuma/request-serve.js +484 -0
  66. package/build/src/akuma/request-wire.d.ts +124 -0
  67. package/build/src/akuma/request-wire.js +380 -0
  68. package/build/src/akuma/requests.d.ts +41 -41
  69. package/build/src/akuma/requests.js +75 -374
  70. package/build/src/akuma-body.d.ts +8 -0
  71. package/build/src/akuma-body.js +84 -0
  72. package/build/src/body/arc.js +4 -29
  73. package/build/src/body/decode.js +5 -39
  74. package/build/src/body/envelope.d.ts +7 -0
  75. package/build/src/body/envelope.js +37 -0
  76. package/build/src/cli/accepted.d.ts +4 -1
  77. package/build/src/cli/accepted.js +39 -9
  78. package/build/src/cli/commands/akuma-invoke.d.ts +8 -7
  79. package/build/src/cli/commands/akuma-invoke.js +18 -10
  80. package/build/src/cli/commands/akuma.d.ts +11 -2
  81. package/build/src/cli/commands/akuma.js +67 -28
  82. package/build/src/cli/commands/amend.d.ts +1 -1
  83. package/build/src/cli/commands/amend.js +1 -1
  84. package/build/src/cli/commands/contract.d.ts +8 -8
  85. package/build/src/cli/commands/contract.js +3 -3
  86. package/build/src/cli/commands/install.js +2 -2
  87. package/build/src/cli/commands/task-invoke.js +98 -9
  88. package/build/src/cli/commands/task-query.d.ts +1 -1
  89. package/build/src/cli/commands/task-query.js +11 -5
  90. package/build/src/cli/coordinates.d.ts +2 -0
  91. package/build/src/cli/coordinates.js +12 -5
  92. package/build/src/cli/invoke.d.ts +1 -0
  93. package/build/src/cli/invoke.js +116 -75
  94. package/build/src/cli/main.d.ts +2 -0
  95. package/build/src/cli/main.js +29 -4
  96. package/build/src/cli/parse.d.ts +3 -2
  97. package/build/src/cli/parse.js +25 -8
  98. package/build/src/cli/render/akuma.d.ts +2 -2
  99. package/build/src/cli/render/akuma.js +138 -24
  100. package/build/src/cli/render/audit.js +18 -8
  101. package/build/src/cli/render/contract.d.ts +2 -0
  102. package/build/src/cli/render/contract.js +243 -36
  103. package/build/src/cli/render/kanshi.js +64 -29
  104. package/build/src/cli/render/receipt.d.ts +2 -1
  105. package/build/src/cli/render/receipt.js +37 -2
  106. package/build/src/cli/render/terminal.d.ts +0 -2
  107. package/build/src/cli/render/terminal.js +0 -29
  108. package/build/src/cli/render/text.js +3 -1
  109. package/build/src/cli/result.d.ts +52 -9
  110. package/build/src/cli/selectors.d.ts +1 -0
  111. package/build/src/cli/selectors.js +9 -6
  112. package/build/src/contract-worktree.d.ts +1 -2
  113. package/build/src/contract-worktree.js +7 -9
  114. package/build/src/core/facts/codec.js +9 -0
  115. package/build/src/core/facts/fold.js +13 -1
  116. package/build/src/core/facts/types.d.ts +8 -1
  117. package/build/src/core/subject.js +4 -3
  118. package/build/src/core/verbs/placement.d.ts +9 -1
  119. package/build/src/core/verbs/placement.js +24 -6
  120. package/build/src/core/verbs/reintegrate.d.ts +13 -0
  121. package/build/src/core/verbs/reintegrate.js +24 -0
  122. package/build/src/dispatch/index.d.ts +1 -1
  123. package/build/src/dispatch/index.js +50 -39
  124. package/build/src/git/admission.d.ts +2 -1
  125. package/build/src/git/hooks.d.ts +0 -4
  126. package/build/src/git/hooks.js +0 -36
  127. package/build/src/git/integration.d.ts +7 -8
  128. package/build/src/git/integration.js +62 -9
  129. package/build/src/git/observe.d.ts +2 -1
  130. package/build/src/git/observe.js +6 -5
  131. package/build/src/git/process.d.ts +26 -0
  132. package/build/src/git/process.js +94 -0
  133. package/build/src/git/read-observation.d.ts +2 -1
  134. package/build/src/git/read-observation.js +3 -2
  135. package/build/src/git/reconcile.d.ts +8 -2
  136. package/build/src/git/reconcile.js +63 -14
  137. package/build/src/git/repository.d.ts +2 -29
  138. package/build/src/git/repository.js +4 -118
  139. package/build/src/git/scratch.d.ts +1 -1
  140. package/build/src/git/scratch.js +1 -1
  141. package/build/src/git/target-placement.d.ts +1 -1
  142. package/build/src/git/target-placement.js +9 -7
  143. package/build/src/git/tender.d.ts +20 -5
  144. package/build/src/git/tender.js +45 -13
  145. package/build/src/git/terminal-seal.d.ts +16 -2
  146. package/build/src/git/terminal-seal.js +15 -5
  147. package/build/src/git/workspace.d.ts +2 -1
  148. package/build/src/git/workspace.js +13 -5
  149. package/build/src/index.d.ts +1 -2
  150. package/build/src/index.js +1 -1
  151. package/build/src/kanshi/index.d.ts +1 -1
  152. package/build/src/kanshi/index.js +1 -1
  153. package/build/src/kanshi/read.d.ts +9 -1
  154. package/build/src/kanshi/read.js +91 -37
  155. package/build/src/kanshi/report.d.ts +1 -0
  156. package/build/src/library/address.d.ts +5 -14
  157. package/build/src/library/address.js +27 -23
  158. package/build/src/library/akuma-creation.d.ts +4 -2
  159. package/build/src/library/akuma-creation.js +43 -26
  160. package/build/src/library/audit.d.ts +2 -1
  161. package/build/src/library/audit.js +1 -1
  162. package/build/src/library/bind.d.ts +2 -1
  163. package/build/src/library/bind.js +4 -4
  164. package/build/src/library/catalog.d.ts +1 -2
  165. package/build/src/library/catalog.js +11 -6
  166. package/build/src/library/configuration.d.ts +5 -1
  167. package/build/src/library/configuration.js +71 -18
  168. package/build/src/library/contract.d.ts +70 -3
  169. package/build/src/library/contract.js +213 -27
  170. package/build/src/library/delivery.d.ts +1 -1
  171. package/build/src/library/fleet.d.ts +70 -12
  172. package/build/src/library/fleet.js +236 -56
  173. package/build/src/library/input.d.ts +0 -1
  174. package/build/src/library/input.js +1 -5
  175. package/build/src/library/keiyaku.d.ts +4 -4
  176. package/build/src/library/keiyaku.js +1 -2
  177. package/build/src/library/mutation.d.ts +2 -1
  178. package/build/src/library/reconcile.d.ts +2 -1
  179. package/build/src/library/reconcile.js +3 -1
  180. package/build/src/library/region.d.ts +1 -1
  181. package/build/src/library/repo.d.ts +3 -1
  182. package/build/src/library/repo.js +8 -4
  183. package/build/src/protocol/abandon.d.ts +9 -0
  184. package/build/src/protocol/abandon.js +15 -0
  185. package/build/src/protocol/amend.d.ts +16 -0
  186. package/build/src/protocol/amend.js +77 -0
  187. package/build/src/protocol/arc.d.ts +6 -0
  188. package/build/src/protocol/arc.js +12 -0
  189. package/build/src/protocol/attempt.d.ts +2 -1
  190. package/build/src/protocol/audit.d.ts +53 -0
  191. package/build/src/protocol/audit.js +140 -0
  192. package/build/src/protocol/bind.d.ts +2 -3
  193. package/build/src/protocol/bind.js +2 -16
  194. package/build/src/protocol/completion.d.ts +32 -0
  195. package/build/src/protocol/completion.js +130 -0
  196. package/build/src/protocol/deliver.d.ts +37 -0
  197. package/build/src/protocol/deliver.js +160 -0
  198. package/build/src/protocol/intent.d.ts +1 -1
  199. package/build/src/protocol/intent.js +1 -1
  200. package/build/src/protocol/operations.d.ts +65 -198
  201. package/build/src/protocol/operations.js +21 -634
  202. package/build/src/protocol/placement.d.ts +4 -13
  203. package/build/src/protocol/placement.js +3 -15
  204. package/build/src/protocol/read/status.d.ts +4 -2
  205. package/build/src/protocol/read/status.js +27 -15
  206. package/build/src/protocol/reconcile.d.ts +35 -0
  207. package/build/src/protocol/reconcile.js +41 -0
  208. package/build/src/protocol/reintegrate.d.ts +31 -0
  209. package/build/src/protocol/reintegrate.js +74 -0
  210. package/build/src/protocol/review.d.ts +33 -0
  211. package/build/src/protocol/review.js +148 -0
  212. package/build/src/protocol/run.d.ts +1 -1
  213. package/build/src/runtime/proc/run.d.ts +1 -0
  214. package/build/src/runtime/proc/run.js +9 -2
  215. package/build/src/settlement/fence.d.ts +1 -1
  216. package/build/src/settlement/holder.d.ts +1 -1
  217. package/build/src/settlement/settle.d.ts +2 -1
  218. package/build/src/settlement/settle.js +4 -1
  219. package/build/src/task/board.d.ts +18 -4
  220. package/build/src/task/board.js +73 -29
  221. package/build/src/task/compose.d.ts +1 -1
  222. package/build/src/task/compose.js +11 -4
  223. package/build/src/task/index.d.ts +4 -4
  224. package/build/src/task/index.js +8 -131
  225. package/build/src/task/input.d.ts +18 -0
  226. package/build/src/task/input.js +189 -0
  227. package/build/src/task/mutation.d.ts +39 -0
  228. package/build/src/task/mutation.js +85 -0
  229. package/build/src/task/operations.d.ts +4 -19
  230. package/build/src/task/operations.js +64 -18
  231. package/build/src/task/query.d.ts +9 -2
  232. package/build/src/task/query.js +32 -64
  233. package/build/src/task/store.js +0 -2
  234. package/build/src/verification/execution.d.ts +1 -1
  235. package/build/src/verification/execution.js +2 -1
  236. package/build/src/workspace-place.d.ts +1 -4
  237. package/build/src/workspace-place.js +0 -15
  238. package/package.json +5 -3
@@ -1,5 +1,5 @@
1
1
  import { toolRepr } from "./akuma-tool.js";
2
- import { displayColumns, renderBoundedTextBlock, safeText, truncateMiddleDisplayText } from "./terminal.js";
2
+ import { displayColumns, renderBoundedTextBlock, renderTextBlock, safeText, truncateMiddleDisplayText, } from "./terminal.js";
3
3
  const DEFAULT_CONTEXT = { columns: 80, color: false };
4
4
  const OPENING_STROKE = "─────";
5
5
  const TIME_WIDTH = 5;
@@ -7,16 +7,27 @@ const VERB_WIDTH = 6;
7
7
  function identity(id, alias) {
8
8
  return `${id}${alias === undefined ? "" : ` (${alias})`}`;
9
9
  }
10
- function associatedIdentity(id, alias, contractId) {
10
+ function associatedContractId(contract) {
11
+ return contract.kind === "associated" ? contract.contractId : undefined;
12
+ }
13
+ function associatedIdentity(id, alias, contract) {
14
+ const contractId = contract === undefined ? undefined : associatedContractId(contract);
11
15
  return `${identity(id, alias)}${contractId === undefined ? "" : ` [${contractId}]`}`;
12
16
  }
13
- function snapshotHeading(id, alias, contractId) {
17
+ function snapshotHeading(id, alias, contract) {
18
+ const contractId = contract === undefined ? undefined : associatedContractId(contract);
14
19
  return [
15
20
  OPENING_STROKE,
16
21
  identity(id, alias),
17
22
  ...(contractId === undefined ? [] : [`└─ ${contractId}`]),
18
23
  ];
19
24
  }
25
+ function contractFacts(contract) {
26
+ return contract.kind === "failed" ? [`! contract failed ${safeText(contract.diagnostic)}`] : [];
27
+ }
28
+ function unobservedText(id, diagnostic) {
29
+ return `! ${id} unobserved: ${safeText(diagnostic)}`;
30
+ }
20
31
  function lifeLabel(life) {
21
32
  if (life === "running")
22
33
  return "● running";
@@ -138,6 +149,59 @@ function groupedEntries(entries, context, history = false) {
138
149
  function groupedRows(rows, context, history = false) {
139
150
  return groupedEntries(rows.filter((row) => row.kind !== "turn").map((row) => ({ kind: "row", row })), context, history);
140
151
  }
152
+ function taskDispositionMark(disposition) {
153
+ if (disposition === "done")
154
+ return "✓";
155
+ if (disposition === "drop")
156
+ return "×";
157
+ if (disposition === "on_hold")
158
+ return "⧗";
159
+ if (disposition === "in_progress")
160
+ return "●";
161
+ return disposition === "blocked" ? "‖" : "○";
162
+ }
163
+ function taskScanLine(row, indent = "") {
164
+ return `${indent}${taskDispositionMark(row.disposition)} ${row.id} · P${row.priority} ${row.disposition}`;
165
+ }
166
+ function changeOp(op) {
167
+ return op === "add" ? "write" : op === "delete" ? "delete" : "edit";
168
+ }
169
+ function renderReportedChangeLines(snapshot, columns) {
170
+ const lines = [` changes ${snapshot.reportedChanges.length + snapshot.reportedChangesOmitted}`];
171
+ for (const change of snapshot.reportedChanges) {
172
+ const scan = ` ${changeOp(change.op)}`;
173
+ const path = safeText(change.path);
174
+ const stat = change.diffstat === undefined
175
+ ? ""
176
+ : ` — +${change.diffstat.added} -${change.diffstat.removed}`;
177
+ const inline = `${scan} ${path}${stat}`;
178
+ if (displayColumns(inline) <= columns)
179
+ lines.push(inline);
180
+ else
181
+ lines.push(`${scan}`, ...renderTextBlock(`${path}${stat}`, " ", columns));
182
+ }
183
+ if (snapshot.reportedChangesOmitted > 0) {
184
+ lines.push(` ⋮ ${snapshot.reportedChangesOmitted} earlier changes`);
185
+ }
186
+ return lines;
187
+ }
188
+ function renderTaskContextLines(created, columns) {
189
+ if (created === undefined)
190
+ return [];
191
+ if (created.kind === "failed")
192
+ return [`! tasks failed ${safeText(created.diagnostic)}`];
193
+ const lines = [` tasks ${created.rows.length}`];
194
+ for (const row of created.rows) {
195
+ const scan = ` ${taskScanLine(row)}`;
196
+ const title = safeText(row.title);
197
+ const inline = `${scan} — ${title}`;
198
+ if (displayColumns(inline) <= columns)
199
+ lines.push(inline);
200
+ else
201
+ lines.push(`${scan} —`, ...renderTextBlock(title, " ", columns));
202
+ }
203
+ return lines;
204
+ }
141
205
  function snapshotText(view, context, options = {}) {
142
206
  const snapshot = view.status.timeline;
143
207
  const activity = snapshot.kind === "idle" && snapshot.outcome !== undefined
@@ -148,22 +212,46 @@ function snapshotText(view, context, options = {}) {
148
212
  : groupedEntries(snapshot.entries, context);
149
213
  const facts = [
150
214
  ...(view.status.readonly?.enforcement === "none" ? [`! ${safeText(view.status.readonly.diagnostic)}`] : []),
215
+ ...contractFacts(view.contract),
151
216
  ...(options.facts ?? []),
152
217
  ];
153
218
  const footer = options.showLife === false ? [] : [` ${lifeLabel(view.status.life)}`];
154
- return [...snapshotHeading(view.status.id, options.alias, view.contractId), ...facts, ...activity, ...footer].join("\n");
219
+ return [
220
+ ...snapshotHeading(view.status.id, options.alias, view.contract),
221
+ ...facts,
222
+ ...activity,
223
+ ...footer,
224
+ ...renderReportedChangeLines(snapshot, context.columns),
225
+ ...renderTaskContextLines(view.createdTasks, context.columns),
226
+ ].join("\n");
227
+ }
228
+ function observationStageText(id, observation, context, options = {}) {
229
+ if (observation.kind === "unobserved")
230
+ return unobservedText(id, observation.diagnostic);
231
+ return snapshotText(observation, context, options);
232
+ }
233
+ function waitText(result, context) {
234
+ const alias = result.alias;
235
+ const blocks = [
236
+ ...result.result.observations.map((observation) => snapshotText(observation, context, { ...(alias === undefined ? {} : { alias }) })),
237
+ ...result.result.unobserved.map((member) => unobservedText(member.id, member.diagnostic)),
238
+ ];
239
+ return blocks.join("\n\n");
155
240
  }
156
241
  function historyText(command, result, context) {
157
242
  if (command.last)
158
243
  return result.mode === "last" ? result.answer : "no answer retained";
159
244
  if (result.mode !== "page")
160
245
  throw new Error("history result lacks page");
161
- const contractId = result.historyResult.contractId;
162
- return [...snapshotHeading(result.akuma, result.alias, contractId), ...groupedRows(result.history.rows, context, true)].join("\n");
246
+ return [...snapshotHeading(result.akuma, result.alias, result.historyResult.contract), ...groupedRows(result.history.rows, context, true)].join("\n");
163
247
  }
164
248
  function tellText(result, context) {
165
249
  const facts = typeof result.result.tell.wake === "string" ? [] : [`! error ${safeText(result.result.tell.wake.diagnostic)}`];
166
- return snapshotText(result.result.observation, context, { ...(result.alias === undefined ? {} : { alias: result.alias }), facts, showLife: false });
250
+ return observationStageText(result.result.akuma, result.result.observation, context, {
251
+ ...(result.alias === undefined ? {} : { alias: result.alias }),
252
+ facts,
253
+ showLife: false,
254
+ });
167
255
  }
168
256
  function dispatchLines(stage) {
169
257
  if (stage.kind === "none" || stage.kind === "dispatched")
@@ -195,8 +283,9 @@ export function akumaRawAnswer(result) {
195
283
  return undefined;
196
284
  return statusAnswer({ status: result.result.observation.status });
197
285
  }
198
- if (result.action === "wait" && result.result.statuses.length === 1)
199
- return statusAnswer(result.result.statuses[0]);
286
+ if (result.action === "wait" && result.result.observations.length === 1) {
287
+ return statusAnswer(result.result.observations[0]);
288
+ }
200
289
  return undefined;
201
290
  }
202
291
  function executionCwdLine(result) {
@@ -211,7 +300,9 @@ function callText(result, context) {
211
300
  facts.push(`alias failed ${result.result.alias.failure.kind} ${safeText(result.result.alias.failure.diagnostic)}`);
212
301
  const cwd = executionCwdLine(result.result);
213
302
  if (result.result.observation.kind === "detached") {
214
- const lines = [...snapshotHeading(result.result.akuma, alias, contractId), ...cwd, ...restraint, ...facts];
303
+ const lines = [...snapshotHeading(result.result.akuma, alias, contractId === undefined
304
+ ? { kind: "none" }
305
+ : { kind: "associated", contractId }), ...cwd, ...restraint, ...facts];
215
306
  if (!callFailed(result.result)) {
216
307
  const selector = result.result.alias.kind === "aliased" ? result.result.alias.alias.alias : result.result.akuma;
217
308
  lines.push(`$ keiyaku -C ${result.world} wait ${selector} --timeout 5m`);
@@ -219,9 +310,14 @@ function callText(result, context) {
219
310
  return lines.join("\n");
220
311
  }
221
312
  if (result.result.observation.kind === "failed") {
222
- return [...snapshotHeading(result.result.akuma, alias, contractId), ...cwd, ...restraint, ...facts, `! error ${safeText(result.result.observation.failure.diagnostic)}`].join("\n");
313
+ return [...snapshotHeading(result.result.akuma, alias, contractId === undefined
314
+ ? { kind: "none" }
315
+ : { kind: "associated", contractId }), ...cwd, ...restraint, ...facts, `! error ${safeText(result.result.observation.failure.diagnostic)}`].join("\n");
223
316
  }
224
- return snapshotText({ status: result.result.observation.status, ...(contractId === undefined ? {} : { contractId }) }, context, {
317
+ return snapshotText({
318
+ status: result.result.observation.status,
319
+ contract: contractId === undefined ? { kind: "none" } : { kind: "associated", contractId },
320
+ }, context, {
225
321
  ...(alias === undefined ? {} : { alias }),
226
322
  facts: [...cwd, ...facts],
227
323
  });
@@ -237,16 +333,26 @@ export function renderAkumaText(command, result, context = DEFAULT_CONTEXT) {
237
333
  switch (result.action) {
238
334
  case "call": return callText(result, context);
239
335
  case "status": return snapshotText(result.status, context, { ...(result.alias === undefined ? {} : { alias: result.alias }) });
240
- case "wait": return result.result.statuses.map((status) => snapshotText(status, context, { ...(result.alias === undefined ? {} : { alias: result.alias }) })).join("\n\n");
241
- case "tell": return result.mode === "ordinary" ? tellText(result, context) : snapshotText(result.result.observation, context, { ...(result.alias === undefined ? {} : { alias: result.alias }), showLife: false });
242
- case "history": return historyText(command, result, context);
336
+ case "wait":
337
+ return waitText(result, context);
338
+ case "tell":
339
+ return result.mode === "ordinary"
340
+ ? tellText(result, context)
341
+ : observationStageText(result.result.id, result.result.observation, context, {
342
+ ...(result.alias === undefined ? {} : { alias: result.alias }),
343
+ showLife: false,
344
+ });
345
+ case "history":
346
+ return historyText(command, result, context);
243
347
  case "fork": {
244
348
  if (result.receipt.kind !== "forked")
245
349
  return result.receipt.kind === "unknown-history" ? `${result.receipt.at} has no matching retained answered turn` : result.receipt.kind === "provider-cannot-fork" ? `${result.receipt.provider} cannot fork` : result.receipt.diagnostic;
246
350
  const contractId = result.receipt.dispatch.kind === "dispatched" ? result.receipt.dispatch.dispatch.contractId : undefined;
247
- return associatedIdentity(result.receipt.child, undefined, contractId);
351
+ return associatedIdentity(result.receipt.child, undefined, contractId === undefined
352
+ ? { kind: "none" }
353
+ : { kind: "associated", contractId });
248
354
  }
249
- case "kill": return result.result.results.map((member) => snapshotText(member.observation, context, { facts: [`kill ${member.evidence}`], ...(result.alias === undefined ? {} : { alias: result.alias }) })).join("\n\n");
355
+ case "kill": return result.result.results.map((member) => observationStageText(member.id, member.observation, context, { facts: [`kill ${member.evidence}`], ...(result.alias === undefined ? {} : { alias: result.alias }) })).join("\n\n");
250
356
  }
251
357
  }
252
358
  function callExitCode(result) {
@@ -277,13 +383,21 @@ export function akumaExitCode(result) {
277
383
  default: return 0;
278
384
  }
279
385
  }
280
- export function akumaJsonValue(command, result) {
281
- if (result.action === "call" || result.action === "fork" || result.action === "status" || result.action === "wait" || result.action === "tell" || result.action === "kill")
282
- return result.action === "status" ? result.status : result.action === "wait" ? result.result : result.action === "tell" ? result.result : result.action === "kill" ? result.result : result.action === "call" ? result.result : result.receipt;
283
- if (command.command !== "history")
284
- throw new Error("history result requires the history command");
386
+ export function akumaJsonValue(result) {
387
+ if (result.action === "call")
388
+ return result.result;
389
+ if (result.action === "fork")
390
+ return result.receipt;
391
+ if (result.action === "status")
392
+ return result.status;
393
+ if (result.action === "wait")
394
+ return result.result;
395
+ if (result.action === "tell")
396
+ return result.result;
397
+ if (result.action === "kill")
398
+ return result.result;
285
399
  return result.historyResult;
286
400
  }
287
- export function renderAkumaJson(command, result) {
288
- return JSON.stringify(akumaJsonValue(command, result));
401
+ export function renderAkumaJson(result) {
402
+ return JSON.stringify(akumaJsonValue(result));
289
403
  }
@@ -1,6 +1,6 @@
1
- import { cleanupLines, leakLines, outcomeLines, receiptPayload, receiptRow, stopLines, } from "./receipt.js";
1
+ import { cleanupLines, leakLines, receiptPayload, receiptRow, stopLines, titleLines, } from "./receipt.js";
2
2
  import { renderRefusalFacts } from "./refusal.js";
3
- import { gitShortStat, renderBoundedTextBlock, renderOpaqueBlock, } from "./terminal.js";
3
+ import { gitShortStat, renderOpaqueBlock, } from "./terminal.js";
4
4
  const CHILD = " ";
5
5
  function workspaceEvidence(workspace, columns) {
6
6
  return renderOpaqueBlock(`workspace ${workspace.kind} ${workspace.path}`, CHILD, columns);
@@ -46,11 +46,7 @@ function verificationLines(verification, columns, addressed) {
46
46
  { text: `${verification.passed} of ${verification.total}` },
47
47
  ], columns);
48
48
  if (verification.summary !== undefined) {
49
- lines.push(...renderBoundedTextBlock(verification.summary, {
50
- first: `${CHILD}summary `,
51
- continuation: CHILD,
52
- columns,
53
- }));
49
+ receiptPayload(lines, "summary", verification.summary);
54
50
  }
55
51
  return lines;
56
52
  }
@@ -91,14 +87,28 @@ function obligationLines(result, columns) {
91
87
  ...(result.leak === undefined ? [] : leakLines(result.leak, columns)),
92
88
  ];
93
89
  }
90
+ function recordLines(result, columns) {
91
+ if (result.facts.length === 0)
92
+ return [];
93
+ const rows = [];
94
+ for (const fact of result.facts) {
95
+ receiptRow(rows, " ", "journal", [
96
+ { text: fact.entry, opaque: true },
97
+ { text: `· ${fact.kind}` },
98
+ ], columns);
99
+ }
100
+ receiptRow(rows, " ", "head", [{ text: result.head, opaque: true }], columns);
101
+ return [" record", ...rows.map((line) => ` ${line}`)];
102
+ }
94
103
  export function renderAcceptedAudit(result, context) {
95
104
  const report = result.report;
96
105
  const columns = context?.columns ?? 80;
97
106
  return [
98
- ...outcomeLines("✓", result.verb, "accepted", result.contract, columns),
107
+ ...titleLines("✓", "audit", result.contract, columns),
99
108
  ...candidateLines(report, columns, result.contract),
100
109
  ...verificationLines(report.verification, columns, result.contract),
101
110
  ...targetLines(report.target, columns, result.contract),
102
111
  ...obligationLines(result, columns),
112
+ ...recordLines(result, columns),
103
113
  ].join("\n");
104
114
  }
@@ -1,4 +1,6 @@
1
+ import type { ContractHistory } from "../../index.js";
1
2
  import type { AcceptedResult, RetryResult } from "../result.js";
2
3
  import { type TextRenderContext } from "./terminal.js";
3
4
  export declare function renderAccepted(result: AcceptedResult, context?: TextRenderContext): string;
4
5
  export declare function renderRetry(result: RetryResult, context?: TextRenderContext): string;
6
+ export declare function renderContractHistory(history: ContractHistory): string;
@@ -1,5 +1,5 @@
1
1
  import { renderAcceptedAudit } from "./audit.js";
2
- import { appendHookPayload, cleanupLines, hookFailureSummary, leakLines, outcomeLines, receiptPayload, receiptRow, reuseLines, stopLines, } from "./receipt.js";
2
+ import { appendHookPayload, cleanupLines, hookFailureSummary, leakLines, outcomeLines, receiptPayload, receiptRow, reuseLines, stopLines, titleLines, } from "./receipt.js";
3
3
  import { gitShortStat, renderOpaqueBlock } from "./terminal.js";
4
4
  const HANG = " ";
5
5
  function isRecord(value) {
@@ -30,6 +30,13 @@ function effectRows(effect, columns) {
30
30
  { text: effect.path, opaque: true },
31
31
  ], columns);
32
32
  }
33
+ else if (effect.kind === "recovery-snapshot") {
34
+ receiptRow(lines, mark, "recovery-snapshot", [
35
+ { text: effect.action },
36
+ { text: effect.snapshot, opaque: true },
37
+ { text: effect.retention },
38
+ ], columns);
39
+ }
33
40
  else {
34
41
  receiptRow(lines, mark, "ref", [
35
42
  { text: effect.action },
@@ -104,7 +111,6 @@ function pushBlock(lines, block) {
104
111
  }
105
112
  function acceptedRecord(result, columns) {
106
113
  const record = [];
107
- receiptRow(record, " ", "head", [{ text: result.head, opaque: true }], columns);
108
114
  for (const fact of result.facts) {
109
115
  const contract = fact.contract === result.contract ? [] : [{ text: fact.contract, opaque: true }];
110
116
  receiptRow(record, " ", "journal", [
@@ -113,15 +119,10 @@ function acceptedRecord(result, columns) {
113
119
  { text: `· ${fact.kind}` },
114
120
  ], columns);
115
121
  }
116
- if (result.verb === "bind") {
117
- receiptRow(record, " ", "target", [{ text: result.target ?? "null", opaque: true }], columns);
118
- }
122
+ receiptRow(record, " ", "head", [{ text: result.head, opaque: true }], columns);
119
123
  if (result.verb === "deliver") {
120
124
  pushBlock(record, reuseLines(result.verificationReuse, columns));
121
125
  }
122
- if (result.verb === "amend") {
123
- receiptPayload(record, "diff", result.diff);
124
- }
125
126
  const changed = result.effects.filter(changedEffect);
126
127
  const unchanged = result.effects.filter((effect) => !changedEffect(effect));
127
128
  for (const effect of [...changed, ...unchanged])
@@ -146,22 +147,15 @@ function acceptedLagRows(result, columns) {
146
147
  }
147
148
  return obligations;
148
149
  }
149
- function acceptedObligations(result, columns) {
150
- const obligations = [];
151
- if (result.verb === "deliver" && result.verification !== undefined) {
152
- obligations.push(...stopLines("verification", result.verification, columns, result.contract));
153
- }
154
- if (result.placement !== undefined) {
155
- obligations.push(...stopLines("claim", result.placement, columns, result.contract));
156
- }
157
- if (result.verb === "deliver") {
158
- if (result.cleanup !== undefined)
159
- pushBlock(obligations, cleanupLines(result.cleanup, columns));
160
- if (result.leak !== undefined)
161
- pushBlock(obligations, leakLines(result.leak, columns));
162
- }
163
- obligations.push(...acceptedLagRows(result, columns));
164
- return obligations;
150
+ function indentRecord(lines) {
151
+ let payload = false;
152
+ return lines.map((line) => {
153
+ if (line.length === 0) {
154
+ payload = !payload;
155
+ return line;
156
+ }
157
+ return payload ? line : ` ${line}`;
158
+ });
165
159
  }
166
160
  function acceptedDeviations(result, columns) {
167
161
  const deviations = [];
@@ -178,32 +172,155 @@ function acceptedDeviations(result, columns) {
178
172
  }
179
173
  return deviations;
180
174
  }
181
- function renderAcceptedReceipt(result, context) {
182
- const columns = context?.columns ?? 80;
183
- const lines = outcomeLines("✓", result.verb, "accepted", result.contract, columns);
184
- if (result.verb === "deliver" || result.verb === "review") {
185
- lines.push(...acceptedObligations(result, columns));
175
+ function recordBlock(result, columns) {
176
+ const rows = [...acceptedRecord(result, columns), ...acceptedLagRows(result, columns)];
177
+ return [" record", ...indentRecord(rows)];
178
+ }
179
+ function verificationVerdictLine(verdict, columns) {
180
+ const lines = [];
181
+ receiptRow(lines, verdict === "satisfied" ? "✓" : "!", "verification", [
182
+ { text: verdict === "satisfied" ? "passed" : "failed" },
183
+ ], columns);
184
+ return lines;
185
+ }
186
+ function renderAcceptedBind(result, columns) {
187
+ const lines = titleLines("✓", "bound", result.contract, columns);
188
+ receiptRow(lines, " ", "workspace", [
189
+ { text: result.workspace === "worktree" ? "managed worktree" : "here" },
190
+ ], columns);
191
+ if (result.target === null)
192
+ receiptRow(lines, " ", "no target", [], columns);
193
+ else
194
+ receiptRow(lines, " ", "target", [{ text: result.target, opaque: true }], columns);
195
+ lines.push(...acceptedDeviations(result, columns), ...recordBlock(result, columns));
196
+ return lines.join("\n");
197
+ }
198
+ function renderAcceptedAmend(result, columns) {
199
+ const lines = titleLines("✓", "terms replaced", result.contract, columns);
200
+ receiptPayload(lines, " terms diff", result.diff);
201
+ lines.push(...acceptedDeviations(result, columns), ...recordBlock(result, columns));
202
+ return lines.join("\n");
203
+ }
204
+ function reintegrationLines(result, complete, columns) {
205
+ const reintegrated = result.facts.filter((fact) => fact.kind === "reintegrated");
206
+ if (reintegrated.length === 0)
207
+ return [];
208
+ const lines = [];
209
+ for (const fact of reintegrated) {
210
+ receiptRow(lines, " ", "re-integrated", [
211
+ { text: fact.data.predecessor, opaque: true },
212
+ { text: "->" },
213
+ { text: fact.data.snapshot, opaque: true },
214
+ ], columns);
186
215
  }
187
- else {
188
- lines.push(...acceptedLagRows(result, columns));
216
+ if (result.verificationVerdict !== undefined) {
217
+ receiptRow(lines, " ", "verification re-run", [
218
+ { text: "·" },
219
+ { text: result.verificationVerdict },
220
+ ], columns);
221
+ }
222
+ if (complete) {
223
+ receiptRow(lines, " ", "target", [
224
+ { text: "->" },
225
+ { text: reintegrated.at(-1).data.snapshot, opaque: true },
226
+ ], columns);
227
+ }
228
+ return lines;
229
+ }
230
+ function renderAcceptedDeliver(result, columns) {
231
+ const complete = result.facts.some((fact) => fact.kind === "claimed");
232
+ const title = complete ? "delivered" : "deliver — not complete";
233
+ const lines = titleLines("✓", title, result.contract, columns);
234
+ lines.push(...reintegrationLines(result, complete, columns));
235
+ if (!complete)
236
+ receiptRow(lines, " ", "candidate", [{ text: "kept" }], columns);
237
+ if (result.verification !== undefined) {
238
+ lines.push(...stopLines("verification", result.verification, columns, result.contract));
189
239
  }
190
- if (result.verb === "bind" || result.verb === "amend" || result.verb === "review") {
191
- lines.push(...acceptedDeviations(result, columns));
240
+ else if (result.verificationVerdict !== undefined) {
241
+ lines.push(...verificationVerdictLine(result.verificationVerdict, columns));
192
242
  }
193
- lines.push(...acceptedRecord(result, columns));
243
+ if (!complete && result.placement !== undefined) {
244
+ lines.push(...stopLines("completion", result.placement, columns, result.contract));
245
+ }
246
+ else if (!complete && (result.verification !== undefined || result.verificationVerdict === "unsatisfied")) {
247
+ receiptRow(lines, "·", "completion", [{ text: "not attempted" }], columns);
248
+ }
249
+ if (result.cleanup !== undefined)
250
+ pushBlock(lines, cleanupLines(result.cleanup, columns));
251
+ if (result.leak !== undefined)
252
+ pushBlock(lines, leakLines(result.leak, columns));
253
+ lines.push(...recordBlock(result, columns));
254
+ return lines.join("\n");
255
+ }
256
+ function renderAcceptedReview(result, columns) {
257
+ const complete = result.facts.some((fact) => fact.kind === "claimed");
258
+ const lines = titleLines("✓", `review ${result.verdict}`, result.contract, columns);
259
+ lines.push(...reintegrationLines(result, complete, columns));
260
+ receiptRow(lines, complete ? "✓" : "!", "contract", [
261
+ { text: complete ? "complete" : "not complete" },
262
+ ], columns);
263
+ if (result.placement !== undefined) {
264
+ lines.push(...stopLines("completion", result.placement, columns, result.contract));
265
+ }
266
+ if (result.verification !== undefined) {
267
+ lines.push(...stopLines("verification", result.verification, columns, result.contract));
268
+ }
269
+ if (result.cleanup !== undefined)
270
+ pushBlock(lines, cleanupLines(result.cleanup, columns));
271
+ if (result.leak !== undefined)
272
+ pushBlock(lines, leakLines(result.leak, columns));
273
+ lines.push(...acceptedDeviations(result, columns), ...recordBlock(result, columns));
274
+ return lines.join("\n");
275
+ }
276
+ function renderAcceptedArc(result, columns) {
277
+ const lines = titleLines("✓", "chapter recorded", result.contract, columns);
278
+ receiptRow(lines, " ", "chapter", [
279
+ { text: String(result.chapter.seq) },
280
+ { text: "·" },
281
+ { text: result.chapter.title },
282
+ ], columns);
283
+ lines.push(...recordBlock(result, columns));
284
+ return lines.join("\n");
285
+ }
286
+ function renderAcceptedAbandon(result, columns) {
287
+ const lines = titleLines("✓", "abandoned", result.contract, columns);
288
+ if (result.note !== undefined)
289
+ receiptRow(lines, " ", "note", [{ text: result.note }], columns);
290
+ for (const effect of result.effects) {
291
+ if (effect.kind === "worktree") {
292
+ receiptRow(lines, " ", "workspace", [
293
+ { text: effect.action },
294
+ { text: effect.path, opaque: true },
295
+ ], columns);
296
+ }
297
+ else if (effect.kind === "recovery-snapshot") {
298
+ receiptRow(lines, " ", "recovery snapshot", [
299
+ { text: effect.snapshot, opaque: true },
300
+ { text: `· ${effect.retention}` },
301
+ ], columns);
302
+ }
303
+ }
304
+ lines.push(...recordBlock(result, columns));
194
305
  return lines.join("\n");
195
306
  }
196
307
  export function renderAccepted(result, context) {
308
+ const columns = context?.columns ?? 80;
197
309
  switch (result.verb) {
198
310
  case "audit":
199
311
  return renderAcceptedAudit(result, context);
200
312
  case "bind":
313
+ return renderAcceptedBind(result, columns);
201
314
  case "amend":
202
- case "deliver":
315
+ return renderAcceptedAmend(result, columns);
203
316
  case "review":
317
+ return renderAcceptedReview(result, columns);
204
318
  case "arc":
319
+ return renderAcceptedArc(result, columns);
205
320
  case "abandon":
206
- return renderAcceptedReceipt(result, context);
321
+ return renderAcceptedAbandon(result, columns);
322
+ case "deliver":
323
+ return renderAcceptedDeliver(result, columns);
207
324
  }
208
325
  }
209
326
  export function renderRetry(result, context) {
@@ -213,3 +330,93 @@ export function renderRetry(result, context) {
213
330
  : [];
214
331
  return [...outcomeLines("?", result.verb, "retry", result.contract, columns), ...detail].join("\n");
215
332
  }
333
+ function journalCount(events, source) {
334
+ return events.filter((event) => event.source === source).length;
335
+ }
336
+ function journalHead(fact) {
337
+ return fact.actor === undefined
338
+ ? `${fact.at} ${fact.kind} · ${fact.entry}`
339
+ : `${fact.at} ${fact.kind} · ${fact.entry} · ${fact.actor}`;
340
+ }
341
+ function listFact(label, values) {
342
+ return values.length === 0 ? [` ${label} 0`] : [` ${label} ${values.join(" · ")}`];
343
+ }
344
+ function journalBody(fact) {
345
+ switch (fact.kind) {
346
+ case "bind": {
347
+ const { coordinates, terms } = fact.data;
348
+ return [
349
+ ` start ${coordinates.start}`,
350
+ ...(coordinates.target === undefined ? [] : [` target ${coordinates.target}`]),
351
+ ` workspace ${coordinates.workspace}`,
352
+ ` document ${terms.document.key}`,
353
+ ...listFact("gates", terms.gates),
354
+ ...listFact("after", terms.after),
355
+ ];
356
+ }
357
+ case "amend":
358
+ return [
359
+ ` document ${fact.data.document.key}`,
360
+ ...listFact("gates", fact.data.gates),
361
+ ...listFact("after", fact.data.after),
362
+ ];
363
+ case "bound":
364
+ return [];
365
+ case "deliver": {
366
+ const { tenderSnapshot, integration, method, policy } = fact.data;
367
+ return [
368
+ ` tender ${tenderSnapshot}`,
369
+ ` predecessor ${integration.predecessor}`,
370
+ ` snapshot ${integration.snapshot}`,
371
+ ` change ${integration.changeId}`,
372
+ ` method ${method}`,
373
+ ` require-branches-to-be-up-to-date ${String(policy.requireBranchesToBeUpToDate)}`,
374
+ ];
375
+ }
376
+ case "reintegrated":
377
+ return [
378
+ ` predecessor ${fact.data.predecessor}`,
379
+ ` snapshot ${fact.data.snapshot}`,
380
+ ];
381
+ case "attestation": {
382
+ const lines = [
383
+ ` gate ${fact.data.gate}`,
384
+ ` verdict ${fact.data.verdict}`,
385
+ ` subject ${fact.data.subject}`,
386
+ ];
387
+ if (fact.data.summary !== undefined)
388
+ receiptPayload(lines, "summary", fact.data.summary);
389
+ return lines;
390
+ }
391
+ case "claimed":
392
+ return [` delivery ${fact.data.delivery}`];
393
+ case "arc": {
394
+ const lines = [` sequence ${String(fact.data.seq)}`, ` title ${fact.data.title}`];
395
+ receiptPayload(lines, "objective", fact.data.objective);
396
+ receiptPayload(lines, "brief", fact.data.brief);
397
+ return lines;
398
+ }
399
+ case "abandoned": {
400
+ if (fact.data.note === undefined)
401
+ return [];
402
+ const lines = [];
403
+ receiptPayload(lines, "note", fact.data.note);
404
+ return lines;
405
+ }
406
+ }
407
+ }
408
+ function contractHistoryEventLines(event) {
409
+ if (event.source === "dispatch") {
410
+ return [`${event.dispatch.dispatchedAt} dispatch · ${event.dispatch.akuId}`];
411
+ }
412
+ return [journalHead(event.fact), ...journalBody(event.fact)];
413
+ }
414
+ export function renderContractHistory(history) {
415
+ const journals = journalCount(history.events, "journal");
416
+ const dispatches = journalCount(history.events, "dispatch");
417
+ return [
418
+ `history ${history.id} · ${journals} journal · ${dispatches} dispatch`,
419
+ "",
420
+ ...history.events.flatMap(contractHistoryEventLines),
421
+ ].join("\n");
422
+ }