@astrosheep/keiyaku 4.0.1 → 4.0.2

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 (245) hide show
  1. package/README.md +137 -5
  2. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
  3. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
  4. package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
  5. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -3
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -35
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +98 -58
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +152 -53
  9. package/build/src/akuma/abort.d.ts +2 -0
  10. package/build/src/akuma/abort.js +50 -0
  11. package/build/src/akuma/akuma.d.ts +23 -14
  12. package/build/src/akuma/akuma.js +120 -104
  13. package/build/src/akuma/archetype.d.ts +7 -6
  14. package/build/src/akuma/archetype.js +68 -41
  15. package/build/src/akuma/body.d.ts +3 -5
  16. package/build/src/akuma/body.js +408 -213
  17. package/build/src/akuma/heart/facts.d.ts +25 -34
  18. package/build/src/akuma/heart/facts.js +18 -7
  19. package/build/src/akuma/heart/index.d.ts +39 -42
  20. package/build/src/akuma/heart/index.js +134 -93
  21. package/build/src/akuma/heart/rows.d.ts +9 -31
  22. package/build/src/akuma/heart/rows.js +26 -44
  23. package/build/src/akuma/heart/schema.d.ts +1 -1
  24. package/build/src/akuma/heart/schema.js +7 -15
  25. package/build/src/akuma/heart/soul.d.ts +8 -0
  26. package/build/src/akuma/heart/soul.js +136 -0
  27. package/build/src/akuma/heart/storage.d.ts +28 -14
  28. package/build/src/akuma/heart/storage.js +86 -26
  29. package/build/src/akuma/identity.d.ts +2 -2
  30. package/build/src/akuma/identity.js +9 -9
  31. package/build/src/akuma/index.d.ts +6 -1
  32. package/build/src/akuma/index.js +6 -0
  33. package/build/src/akuma/projection.d.ts +117 -38
  34. package/build/src/akuma/projection.js +208 -97
  35. package/build/src/akuma/provider-recipe.d.ts +24 -0
  36. package/build/src/akuma/provider-recipe.js +100 -0
  37. package/build/src/akuma/provider.d.ts +12 -4
  38. package/build/src/akuma/provider.js +117 -70
  39. package/build/src/akuma/providers/acp/core.d.ts +19 -0
  40. package/build/src/akuma/providers/acp/core.js +159 -0
  41. package/build/src/akuma/providers/acp/events.d.ts +20 -0
  42. package/build/src/akuma/providers/acp/events.js +73 -0
  43. package/build/src/akuma/providers/acp/index.d.ts +12 -0
  44. package/build/src/akuma/providers/acp/index.js +94 -0
  45. package/build/src/akuma/providers/claude/events.js +66 -13
  46. package/build/src/akuma/providers/claude/index.d.ts +2 -1
  47. package/build/src/akuma/providers/claude/index.js +35 -21
  48. package/build/src/akuma/providers/codex-app-server/events.js +4 -1
  49. package/build/src/akuma/providers/codex-app-server/index.d.ts +3 -3
  50. package/build/src/akuma/providers/codex-app-server/index.js +24 -31
  51. package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
  52. package/build/src/akuma/providers/grok-build/index.js +70 -0
  53. package/build/src/akuma/providers/index.d.ts +5 -3
  54. package/build/src/akuma/providers/index.js +24 -59
  55. package/build/src/akuma/providers/opencode-sdk/events.d.ts +40 -34
  56. package/build/src/akuma/providers/opencode-sdk/events.js +220 -101
  57. package/build/src/akuma/providers/opencode-sdk/index.d.ts +3 -2
  58. package/build/src/akuma/providers/opencode-sdk/index.js +233 -128
  59. package/build/src/akuma/providers/opencode-sdk/session.d.ts +11 -26
  60. package/build/src/akuma/providers/opencode-sdk/session.js +10 -9
  61. package/build/src/akuma/providers/pi/events.js +49 -11
  62. package/build/src/akuma/providers/pi/index.d.ts +1 -1
  63. package/build/src/akuma/providers/pi/index.js +50 -21
  64. package/build/src/akuma/publication.d.ts +3 -3
  65. package/build/src/akuma/publication.js +28 -40
  66. package/build/src/akuma/requests.d.ts +9 -7
  67. package/build/src/akuma/requests.js +92 -65
  68. package/build/src/alias/index.d.ts +2 -2
  69. package/build/src/alias/index.js +10 -10
  70. package/build/src/body/decode.js +7 -1
  71. package/build/src/body/region.d.ts +2 -0
  72. package/build/src/body/region.js +77 -7
  73. package/build/src/cli/accepted.d.ts +17 -13
  74. package/build/src/cli/accepted.js +72 -34
  75. package/build/src/cli/actor.js +3 -3
  76. package/build/src/cli/commands/akuma-invoke.d.ts +4 -3
  77. package/build/src/cli/commands/akuma-invoke.js +14 -9
  78. package/build/src/cli/commands/akuma.d.ts +13 -3
  79. package/build/src/cli/commands/akuma.js +67 -34
  80. package/build/src/cli/commands/contract.d.ts +18 -5
  81. package/build/src/cli/commands/contract.js +9 -3
  82. package/build/src/cli/commands/task-invoke.d.ts +17 -4
  83. package/build/src/cli/commands/task-invoke.js +43 -20
  84. package/build/src/cli/commands/task-query.d.ts +5 -0
  85. package/build/src/cli/commands/task-query.js +247 -0
  86. package/build/src/cli/commands/task.d.ts +3 -1
  87. package/build/src/cli/commands/task.js +51 -13
  88. package/build/src/cli/coordinates.d.ts +18 -0
  89. package/build/src/cli/coordinates.js +120 -0
  90. package/build/src/cli/draft.d.ts +8 -0
  91. package/build/src/cli/draft.js +96 -0
  92. package/build/src/cli/invoke.d.ts +4 -3
  93. package/build/src/cli/invoke.js +160 -179
  94. package/build/src/cli/main.js +34 -6
  95. package/build/src/cli/parse.d.ts +9 -2
  96. package/build/src/cli/parse.js +29 -7
  97. package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
  98. package/build/src/cli/render/akuma-tool-command.js +144 -0
  99. package/build/src/cli/render/akuma-tool.d.ts +2 -2
  100. package/build/src/cli/render/akuma-tool.js +30 -4
  101. package/build/src/cli/render/akuma.d.ts +1 -0
  102. package/build/src/cli/render/akuma.js +211 -116
  103. package/build/src/cli/render/audit.d.ts +3 -0
  104. package/build/src/cli/render/audit.js +104 -0
  105. package/build/src/cli/render/contract.d.ts +3 -3
  106. package/build/src/cli/render/contract.js +192 -79
  107. package/build/src/cli/render/kanshi.js +263 -168
  108. package/build/src/cli/render/receipt.d.ts +19 -0
  109. package/build/src/cli/render/receipt.js +106 -0
  110. package/build/src/cli/render/refusal.d.ts +16 -2
  111. package/build/src/cli/render/refusal.js +88 -20
  112. package/build/src/cli/render/region.d.ts +2 -0
  113. package/build/src/cli/render/region.js +17 -0
  114. package/build/src/cli/render/task.d.ts +2 -1
  115. package/build/src/cli/render/task.js +223 -60
  116. package/build/src/cli/render/terminal.d.ts +7 -0
  117. package/build/src/cli/render/terminal.js +46 -0
  118. package/build/src/cli/render/text.js +6 -3
  119. package/build/src/cli/result.d.ts +115 -20
  120. package/build/src/cli/usage.d.ts +1 -0
  121. package/build/src/cli/usage.js +3 -0
  122. package/build/src/contract-worktree.d.ts +6 -5
  123. package/build/src/contract-worktree.js +95 -57
  124. package/build/src/coordination/durable-file.d.ts +4 -3
  125. package/build/src/coordination/durable-file.js +29 -25
  126. package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
  127. package/build/src/coordination/sqlite-transaction-lock.js +22 -5
  128. package/build/src/core/facts/fold.js +1 -6
  129. package/build/src/core/facts/gate.d.ts +1 -0
  130. package/build/src/core/facts/gate.js +1 -0
  131. package/build/src/core/verbs/amend.d.ts +1 -1
  132. package/build/src/core/verbs/amend.js +0 -11
  133. package/build/src/core/verbs/deliver.d.ts +1 -1
  134. package/build/src/core/verbs/deliver.js +1 -7
  135. package/build/src/core/verbs/placement.d.ts +1 -1
  136. package/build/src/core/verbs/placement.js +4 -1
  137. package/build/src/dispatch/index.d.ts +2 -2
  138. package/build/src/dispatch/index.js +17 -17
  139. package/build/src/git/admission.d.ts +1 -1
  140. package/build/src/git/admission.js +11 -11
  141. package/build/src/git/hooks.js +13 -13
  142. package/build/src/git/integration.d.ts +14 -15
  143. package/build/src/git/integration.js +80 -44
  144. package/build/src/git/observe.d.ts +5 -3
  145. package/build/src/git/observe.js +18 -12
  146. package/build/src/git/read-observation.js +9 -9
  147. package/build/src/git/reconcile.d.ts +2 -0
  148. package/build/src/git/reconcile.js +138 -95
  149. package/build/src/git/repository.d.ts +27 -19
  150. package/build/src/git/repository.js +155 -83
  151. package/build/src/git/scratch.d.ts +7 -3
  152. package/build/src/git/scratch.js +44 -37
  153. package/build/src/git/target-placement.d.ts +40 -4
  154. package/build/src/git/target-placement.js +221 -101
  155. package/build/src/git/tender.d.ts +6 -5
  156. package/build/src/git/tender.js +24 -43
  157. package/build/src/git/terminal-seal.d.ts +1 -1
  158. package/build/src/git/terminal-seal.js +7 -5
  159. package/build/src/git/workspace.d.ts +36 -4
  160. package/build/src/git/workspace.js +53 -18
  161. package/build/src/identity/selector.js +1 -1
  162. package/build/src/index.d.ts +3 -3
  163. package/build/src/index.js +1 -1
  164. package/build/src/kanshi/index.d.ts +2 -2
  165. package/build/src/kanshi/index.js +1 -1
  166. package/build/src/kanshi/read.d.ts +2 -1
  167. package/build/src/kanshi/read.js +118 -27
  168. package/build/src/kanshi/report.d.ts +50 -0
  169. package/build/src/kanshi/select.d.ts +5 -0
  170. package/build/src/kanshi/select.js +32 -0
  171. package/build/src/library/address.d.ts +12 -3
  172. package/build/src/library/address.js +77 -46
  173. package/build/src/library/akuma-creation.d.ts +6 -1
  174. package/build/src/library/akuma-creation.js +86 -13
  175. package/build/src/library/audit.d.ts +18 -0
  176. package/build/src/library/audit.js +44 -0
  177. package/build/src/library/bind.js +4 -4
  178. package/build/src/library/catalog.d.ts +1 -1
  179. package/build/src/library/catalog.js +5 -8
  180. package/build/src/library/contract.d.ts +5 -6
  181. package/build/src/library/contract.js +11 -35
  182. package/build/src/library/delivery.d.ts +2 -1
  183. package/build/src/library/fleet.d.ts +2 -2
  184. package/build/src/library/fleet.js +35 -71
  185. package/build/src/library/keiyaku.d.ts +3 -2
  186. package/build/src/library/keiyaku.js +1 -0
  187. package/build/src/library/mutation.d.ts +7 -6
  188. package/build/src/library/mutation.js +23 -25
  189. package/build/src/library/reconcile.d.ts +29 -0
  190. package/build/src/library/reconcile.js +179 -0
  191. package/build/src/library/region.d.ts +12 -0
  192. package/build/src/library/region.js +15 -1
  193. package/build/src/library/repo.d.ts +4 -16
  194. package/build/src/library/repo.js +13 -38
  195. package/build/src/protocol/attempt.js +6 -6
  196. package/build/src/protocol/bind.js +4 -4
  197. package/build/src/protocol/intent.d.ts +15 -2
  198. package/build/src/protocol/intent.js +21 -6
  199. package/build/src/protocol/operations.d.ts +73 -22
  200. package/build/src/protocol/operations.js +292 -88
  201. package/build/src/protocol/outcome.d.ts +9 -3
  202. package/build/src/protocol/outcome.js +3 -1
  203. package/build/src/protocol/placement.d.ts +15 -4
  204. package/build/src/protocol/placement.js +58 -25
  205. package/build/src/protocol/read/status.d.ts +8 -1
  206. package/build/src/protocol/read/status.js +61 -14
  207. package/build/src/runtime/proc/line-rpc.d.ts +3 -8
  208. package/build/src/runtime/proc/line-rpc.js +16 -43
  209. package/build/src/runtime/proc/run.d.ts +15 -29
  210. package/build/src/runtime/proc/run.js +113 -105
  211. package/build/src/runtime/proc/stdio.d.ts +18 -0
  212. package/build/src/runtime/proc/stdio.js +58 -0
  213. package/build/src/settings.d.ts +2 -2
  214. package/build/src/settings.js +8 -8
  215. package/build/src/settlement/fence.d.ts +0 -4
  216. package/build/src/settlement/fence.js +0 -9
  217. package/build/src/settlement/holder.d.ts +11 -1
  218. package/build/src/settlement/holder.js +25 -0
  219. package/build/src/settlement/settle.d.ts +1 -1
  220. package/build/src/settlement/settle.js +52 -89
  221. package/build/src/task/board.d.ts +3 -3
  222. package/build/src/task/board.js +6 -9
  223. package/build/src/task/compose.d.ts +1 -1
  224. package/build/src/task/compose.js +18 -10
  225. package/build/src/task/context.d.ts +3 -3
  226. package/build/src/task/context.js +14 -14
  227. package/build/src/task/document.d.ts +2 -1
  228. package/build/src/task/document.js +15 -5
  229. package/build/src/task/index.d.ts +19 -7
  230. package/build/src/task/index.js +42 -23
  231. package/build/src/task/operations.d.ts +15 -9
  232. package/build/src/task/operations.js +78 -48
  233. package/build/src/task/query.d.ts +67 -0
  234. package/build/src/task/query.js +279 -0
  235. package/build/src/task/store.d.ts +2 -2
  236. package/build/src/task/store.js +40 -25
  237. package/build/src/verification/execution.d.ts +4 -2
  238. package/build/src/verification/execution.js +9 -5
  239. package/build/src/workspace-place.d.ts +41 -0
  240. package/build/src/workspace-place.js +386 -0
  241. package/build/src/world.d.ts +13 -2
  242. package/build/src/world.js +81 -48
  243. package/package.json +3 -2
  244. package/build/src/protocol/read/audit.d.ts +0 -31
  245. package/build/src/protocol/read/audit.js +0 -55
@@ -1,140 +1,172 @@
1
1
  import { toolRepr } from "./akuma-tool.js";
2
- import { displayColumns, renderBoundedTextBlock, renderVoiceRuler, safeText, truncateMiddleDisplayText } from "./terminal.js";
3
- const GUTTER_MS = 60_000;
4
- const LABEL_WIDTH = 6;
2
+ import { displayColumns, renderBoundedTextBlock, safeText, truncateMiddleDisplayText } from "./terminal.js";
5
3
  const DEFAULT_CONTEXT = { columns: 80, color: false };
6
- function identity(id, alias) { return `${id}${alias === undefined ? "" : ` (${alias})`}`; }
7
- function ruler(left, columns, scope = "") {
8
- if (scope !== "")
9
- return renderVoiceRuler(left, scope, columns).trimEnd();
10
- const width = Math.max(20, Math.min(80, columns));
11
- return `${left} ${"─".repeat(Math.max(1, width - displayColumns(left) - 1))}`;
4
+ const OPENING_STROKE = "─────";
5
+ const TIME_WIDTH = 5;
6
+ const VERB_WIDTH = 6;
7
+ function identity(id, alias) {
8
+ return `${id}${alias === undefined ? "" : ` (${alias})`}`;
9
+ }
10
+ function associatedIdentity(id, alias, contractId) {
11
+ return `${identity(id, alias)}${contractId === undefined ? "" : ` [${contractId}]`}`;
12
+ }
13
+ function snapshotHeading(id, alias, contractId) {
14
+ return [
15
+ OPENING_STROKE,
16
+ identity(id, alias),
17
+ ...(contractId === undefined ? [] : [`└─ ${contractId}`]),
18
+ ];
19
+ }
20
+ function lifeLabel(life) {
21
+ if (life === "running")
22
+ return "● running";
23
+ if (life === "asleep")
24
+ return "○ asleep";
25
+ if (life === "killed")
26
+ return "× killed";
27
+ return `? ${life}`;
12
28
  }
13
29
  function clock(at) {
14
- if (at === undefined)
15
- return "";
16
30
  const date = new Date(at);
17
- return Number.isFinite(date.getTime()) ? `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}` : "";
18
- }
19
- function label(value) { return `${value}${" ".repeat(Math.max(0, LABEL_WIDTH - displayColumns(value)))}`; }
20
- function renderSpineRow(item, context, profile, lastAt) {
21
- const stamp = item.at === undefined ? undefined : Date.parse(item.at);
22
- const printTime = stamp !== undefined && Number.isFinite(stamp) && (lastAt === undefined || stamp - lastAt >= GUTTER_MS);
23
- const nextLastAt = printTime ? stamp : lastAt;
24
- const gutter = `${printTime ? clock(item.at) : ""}`.padStart(5, " ");
25
- const spine = item.spine === "turn" ? "┌│" : item.spine === "frontier" ? "┌⧖" : item.spine === "pending" ? " ⧗" : item.spine === "ok" ? " ✓" : item.spine === "error" ? " !" : " │";
26
- const quote = item.quoted === true ? "“" : "";
27
- const first = `${gutter}${spine} ${label(item.label)} ${quote}`;
28
- if (item.indivisible === true)
29
- return { lines: [`${first}${safeText(item.text)}`.trimEnd()], lastAt: nextLastAt };
30
- if (item.overflow === "middle-ellipsis") {
31
- const suffix = item.suffix ?? "";
32
- const budget = Math.max(1, context.columns - displayColumns(first) - displayColumns(suffix));
33
- return { lines: [`${first}${truncateMiddleDisplayText(item.text, budget)}${suffix}`.trimEnd()], lastAt: nextLastAt };
34
- }
35
- const continuation = `${"".padStart(gutter.length)} │ ${"".padEnd(LABEL_WIDTH + 1, " ")}`;
36
- const lines = renderBoundedTextBlock(item.text, { first, continuation, columns: context.columns, lines: profile === "history" ? Number.MAX_SAFE_INTEGER : (item.snapshotLines ?? 2), ...(item.truncated === true ? { truncated: true } : {}) });
37
- return { lines: item.quoted === true ? lines.map((line, index) => index === lines.length - 1 ? `${line}”` : line) : lines, lastAt: nextLastAt };
31
+ return Number.isFinite(date.getTime()) ? `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}` : "unknown";
38
32
  }
39
- function renderSpine(items, context, profile = "snapshot") {
40
- let lastAt;
41
- const lines = [];
42
- for (const item of items) {
43
- if (item.kind === "gap") {
44
- if (item.count > 1)
45
- lines.push(` ⋮ +${item.count}`);
46
- continue;
47
- }
48
- const rendered = renderSpineRow(item, context, profile, lastAt);
49
- lastAt = rendered.lastAt;
50
- lines.push(...rendered.lines);
51
- }
52
- return lines;
53
- }
54
- function activityLabel(row) {
33
+ function label(row) {
55
34
  if (row.kind === "said")
56
35
  return "say";
57
36
  if (row.kind === "thought")
58
37
  return "think";
59
38
  if (row.kind === "note")
60
39
  return "note";
61
- if (row.kind === "call" || row.kind === "turn")
40
+ if (row.kind === "call")
62
41
  return "call";
63
42
  if (row.kind === "tell")
64
43
  return "tell";
65
44
  if (row.kind === "outcome")
66
45
  return row.outcome.kind === "answered" ? "say" : "error";
46
+ if (row.kind === "turn")
47
+ return "call";
67
48
  return toolRepr(row).label;
68
49
  }
69
- function rowSpine(row, firstTurn, frontier) {
50
+ function mark(row) {
70
51
  if (row.kind === "outcome")
71
- return row.outcome.kind === "answered" ? "ok" : "error";
52
+ return row.outcome.kind === "answered" ? "✓" : "!";
72
53
  if (row.kind === "tell" && row.state === "pending")
73
- return "pending";
74
- if (frontier || (row.kind === "tool" && row.state === "running"))
75
- return "frontier";
76
- return firstTurn ? "turn" : "normal";
54
+ return "⧗";
55
+ if (row.kind === "tool") {
56
+ if (row.state === "active")
57
+ return "⧖";
58
+ if (row.state === "unsettled")
59
+ return "?";
60
+ return row.state.status === "ok" ? "✓" : "!";
61
+ }
62
+ return "·";
77
63
  }
78
64
  function rowText(row) {
79
- if (row.kind === "said" || row.kind === "thought")
80
- return { text: row.text, quoted: true, snapshotLines: row.kind === "said" ? 3 : 2 };
81
- if (row.kind === "note")
82
- return { text: row.text, snapshotLines: 2 };
83
- if (row.kind === "call")
84
- return { text: row.text, quoted: true, snapshotLines: 1 };
85
- if (row.kind === "turn")
86
- return { text: "", snapshotLines: 1 };
87
- if (row.kind === "tell")
88
- return { text: row.text, quoted: true, snapshotLines: 1 };
65
+ if (row.kind === "said" || row.kind === "thought" || row.kind === "note" || row.kind === "call" || row.kind === "tell") {
66
+ return { text: row.text, lines: row.kind === "said" || row.kind === "thought" ? 2 : row.kind === "tell" || row.kind === "call" ? 1 : 2 };
67
+ }
89
68
  if (row.kind === "outcome")
90
69
  return row.outcome.kind === "answered"
91
- ? { text: row.outcome.answer, quoted: true, snapshotLines: 3 }
92
- : { text: row.outcome.diagnostic, snapshotLines: 2 };
70
+ ? { text: row.outcome.answer, lines: 3 }
71
+ : { text: row.outcome.diagnostic, lines: 2 };
72
+ if (row.kind === "turn")
73
+ return { text: "", lines: 1 };
93
74
  const repr = toolRepr(row);
94
- return { text: repr.text, ...(repr.overflow === undefined ? {} : { overflow: repr.overflow }), ...(repr.suffix === undefined ? {} : { suffix: repr.suffix }), snapshotLines: 2 };
75
+ return { text: repr.text, lines: 2, ...(repr.overflow === "middle-ellipsis" ? { middle: true } : {}), ...(repr.suffix === undefined ? {} : { suffix: repr.suffix }) };
95
76
  }
96
- function rowItem(row, firstTurn, frontier) {
97
- const truncated = "truncated" in row && row.truncated === true ? { truncated: true } : {};
98
- return { kind: "row", at: row.at, label: activityLabel(row), spine: rowSpine(row, firstTurn, frontier), ...rowText(row), ...truncated };
77
+ function eventPrefix(glyph, verb, time) {
78
+ const gutter = time === undefined ? " ".repeat(TIME_WIDTH) : time.padEnd(TIME_WIDTH);
79
+ return `${gutter} ${glyph} ${verb.padEnd(VERB_WIDTH)} `;
99
80
  }
100
- function snapshotItems(entries) {
101
- const seen = new Set();
102
- return entries.flatMap((entry) => {
103
- if (entry.kind === "gap")
104
- return [entry];
105
- const row = entry.row;
106
- if (row.kind === "turn")
107
- return [];
108
- const first = "turnSequence" in row && !seen.has(row.turnSequence);
109
- if ("turnSequence" in row)
110
- seen.add(row.turnSequence);
111
- return [rowItem(row, first, false)];
81
+ function continuationPrefix() {
82
+ return eventPrefix("│", "");
83
+ }
84
+ function quotedBody(row) {
85
+ return row.kind === "said" || row.kind === "thought" || row.kind === "tell"
86
+ || (row.kind === "outcome" && row.outcome.kind === "answered");
87
+ }
88
+ function quoteLines(lines, prefix) {
89
+ const prefixWidth = prefix.length;
90
+ return lines.map((line) => {
91
+ const body = line.slice(prefixWidth);
92
+ if (body.length === 0)
93
+ return line;
94
+ return `${line.slice(0, prefixWidth)}“${body}”`;
112
95
  });
113
96
  }
97
+ function renderMiddleEllipsis(first, text, suffix, columns) {
98
+ const prefixWidth = displayColumns(first);
99
+ const remaining = columns - prefixWidth;
100
+ const suffixWidth = displayColumns(suffix);
101
+ const withSuffix = remaining - suffixWidth;
102
+ // `$ ` + one head char + ellipsis + tail; cue and ellipsis alone are not a subject.
103
+ const showSuffix = suffix.length > 0 && withSuffix >= 6;
104
+ return `${first}${truncateMiddleDisplayText(text, Math.max(0, showSuffix ? withSuffix : remaining))}${showSuffix ? suffix : ""}`;
105
+ }
106
+ function renderRow(row, context, history, first) {
107
+ const value = rowText(row);
108
+ const quoted = quotedBody(row);
109
+ const quoteWidth = quoted ? 2 : 0;
110
+ if (value.middle === true) {
111
+ return [renderMiddleEllipsis(first, value.text, value.suffix ?? "", context.columns - quoteWidth)];
112
+ }
113
+ const lines = renderBoundedTextBlock(value.text, {
114
+ first,
115
+ continuation: continuationPrefix(),
116
+ columns: context.columns - quoteWidth,
117
+ lines: history ? Number.MAX_SAFE_INTEGER : value.lines,
118
+ ...("truncated" in row && row.truncated === true ? { truncated: true } : {}),
119
+ });
120
+ return quoted ? quoteLines(lines, first) : lines;
121
+ }
122
+ function groupedEntries(entries, context, history = false) {
123
+ const lines = [];
124
+ let previousClock;
125
+ for (const entry of entries) {
126
+ if (entry.kind === "gap") {
127
+ lines.push(`${" ".repeat(TIME_WIDTH)} ⋮ ${entry.count} omitted`);
128
+ continue;
129
+ }
130
+ const row = entry.row;
131
+ const at = clock(row.at);
132
+ const changed = previousClock === undefined || at !== previousClock;
133
+ lines.push(...renderRow(row, context, history, eventPrefix(mark(row), label(row), changed ? at : undefined)));
134
+ previousClock = at;
135
+ }
136
+ return lines;
137
+ }
138
+ function groupedRows(rows, context, history = false) {
139
+ return groupedEntries(rows.filter((row) => row.kind !== "turn").map((row) => ({ kind: "row", row })), context, history);
140
+ }
114
141
  function snapshotText(view, context, options = {}) {
115
- const status = view.status;
116
- const items = [...snapshotItems(status.timeline.entries), ...(options.tail ?? [])];
117
- return [ruler(identity(status.id, options.alias), context.columns, options.contractId ?? view.contractId), ...(options.facts ?? []), ...renderSpine(items, context)].filter(Boolean).join("\n");
142
+ const snapshot = view.status.timeline;
143
+ const activity = snapshot.kind === "idle" && snapshot.outcome !== undefined
144
+ ? groupedRows([
145
+ ...snapshot.entries.filter((entry) => entry.kind === "row").map((entry) => entry.row),
146
+ snapshot.outcome,
147
+ ].sort((left, right) => left.sequence - right.sequence), context)
148
+ : groupedEntries(snapshot.entries, context);
149
+ const facts = [
150
+ ...(view.status.readonly?.enforcement === "none" ? [`! ${safeText(view.status.readonly.diagnostic)}`] : []),
151
+ ...(options.facts ?? []),
152
+ ];
153
+ const footer = options.showLife === false ? [] : [` ${lifeLabel(view.status.life)}`];
154
+ return [...snapshotHeading(view.status.id, options.alias, view.contractId), ...facts, ...activity, ...footer].join("\n");
118
155
  }
119
156
  function historyText(command, result, context) {
120
157
  if (command.last)
121
158
  return result.mode === "last" ? result.answer : "no answer retained";
122
159
  if (result.mode !== "page")
123
160
  throw new Error("history result lacks page");
124
- const history = result.history;
125
- const rows = history.rows.map((row) => rowItem(row, false, false));
126
161
  const contractId = result.historyResult.contractId;
127
- const scope = contractId === undefined ? "history" : `history · ${contractId}`;
128
- return [ruler(identity(result.akuma, result.alias), context.columns, scope), ...renderSpine(rows, context, "history")].join("\n");
162
+ return [...snapshotHeading(result.akuma, result.alias, contractId), ...groupedRows(result.history.rows, context, true)].join("\n");
129
163
  }
130
164
  function tellText(result, context) {
131
165
  const facts = typeof result.result.tell.wake === "string" ? [] : [`! error ${safeText(result.result.tell.wake.diagnostic)}`];
132
- return snapshotText(result.result.observation, context, { ...(result.alias === undefined ? {} : { alias: result.alias }), facts });
166
+ return snapshotText(result.result.observation, context, { ...(result.alias === undefined ? {} : { alias: result.alias }), facts, showLife: false });
133
167
  }
134
168
  function dispatchLines(stage) {
135
- if (stage.kind === "none")
136
- return [];
137
- if (stage.kind === "dispatched")
169
+ if (stage.kind === "none" || stage.kind === "dispatched")
138
170
  return [];
139
171
  if (stage.failure.kind === "conflict")
140
172
  return [`dispatch failed conflict ${stage.failure.current.contractId}`];
@@ -142,47 +174,108 @@ function dispatchLines(stage) {
142
174
  return ["dispatch failed contention"];
143
175
  return [`dispatch failed ${stage.failure.kind} ${safeText(stage.failure.diagnostic)}`];
144
176
  }
177
+ function callFailed(result) {
178
+ return result.dispatch.kind === "failed"
179
+ || result.alias.kind === "failed"
180
+ || result.readonly?.enforcement === "none";
181
+ }
182
+ function statusAnswer(view) {
183
+ if (view.status.life !== "asleep")
184
+ return undefined;
185
+ if (view.status.readonly?.enforcement === "none")
186
+ return undefined;
187
+ const timeline = view.status.timeline;
188
+ if (timeline.kind !== "idle" || timeline.outcome?.outcome.kind !== "answered")
189
+ return undefined;
190
+ return timeline.outcome.outcome.answer;
191
+ }
192
+ export function akumaRawAnswer(result) {
193
+ if (result.action === "call") {
194
+ if (callFailed(result.result) || result.result.observation.kind !== "observed")
195
+ return undefined;
196
+ return statusAnswer({ status: result.result.observation.status });
197
+ }
198
+ if (result.action === "wait" && result.result.statuses.length === 1)
199
+ return statusAnswer(result.result.statuses[0]);
200
+ return undefined;
201
+ }
202
+ function executionCwdLine(result) {
203
+ return result.execution.source === "contract-worktree" ? [`cwd ${result.execution.cwd}`] : [];
204
+ }
145
205
  function callText(result, context) {
146
206
  const alias = result.result.alias.kind === "aliased" ? result.result.alias.alias.alias : undefined;
147
- const facts = [...dispatchLines(result.result.dispatch)];
148
207
  const contractId = result.result.dispatch.kind === "dispatched" ? result.result.dispatch.dispatch.contractId : undefined;
149
- const head = contractId === undefined ? identity(result.result.akuma, alias) : ruler(identity(result.result.akuma, alias), context.columns, contractId);
208
+ const facts = [...dispatchLines(result.result.dispatch)];
209
+ const restraint = result.result.readonly?.enforcement === "none" ? [`! ${safeText(result.result.readonly.diagnostic)}`] : [];
150
210
  if (result.result.alias.kind === "failed")
151
211
  facts.push(`alias failed ${result.result.alias.failure.kind} ${safeText(result.result.alias.failure.diagnostic)}`);
152
- if (result.result.observation.kind === "detached")
153
- return [head, ...facts].join("\n");
154
- if (result.result.observation.kind === "failed")
155
- return [head, ...facts, `! error ${safeText(result.result.observation.failure.diagnostic)}`].join("\n");
156
- return snapshotText({ status: result.result.observation.status, ...(contractId === undefined ? {} : { contractId }) }, context, { ...(alias === undefined ? {} : { alias }), facts });
212
+ const cwd = executionCwdLine(result.result);
213
+ if (result.result.observation.kind === "detached") {
214
+ const lines = [...snapshotHeading(result.result.akuma, alias, contractId), ...cwd, ...restraint, ...facts];
215
+ if (!callFailed(result.result)) {
216
+ const selector = result.result.alias.kind === "aliased" ? result.result.alias.alias.alias : result.result.akuma;
217
+ lines.push(`$ keiyaku -C ${result.world} wait ${selector} --timeout 5m`);
218
+ }
219
+ return lines.join("\n");
220
+ }
221
+ 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");
223
+ }
224
+ return snapshotText({ status: result.result.observation.status, ...(contractId === undefined ? {} : { contractId }) }, context, {
225
+ ...(alias === undefined ? {} : { alias }),
226
+ facts: [...cwd, ...facts],
227
+ });
157
228
  }
158
229
  export function renderAkumaText(command, result, context = DEFAULT_CONTEXT) {
230
+ const answer = akumaRawAnswer(result);
231
+ if (answer !== undefined) {
232
+ if (result.action !== "call")
233
+ return answer;
234
+ const cwd = executionCwdLine(result.result);
235
+ return cwd.length === 0 ? answer : `${cwd.join("\n")}\n${answer}`;
236
+ }
159
237
  switch (result.action) {
160
238
  case "call": return callText(result, context);
161
239
  case "status": return snapshotText(result.status, context, { ...(result.alias === undefined ? {} : { alias: result.alias }) });
162
240
  case "wait": return result.result.statuses.map((status) => snapshotText(status, context, { ...(result.alias === undefined ? {} : { alias: result.alias }) })).join("\n\n");
163
- case "tell": return result.mode === "ordinary" ? tellText(result, context) : snapshotText(result.result.observation, context, { ...(result.alias === undefined ? {} : { alias: result.alias }) });
241
+ case "tell": return result.mode === "ordinary" ? tellText(result, context) : snapshotText(result.result.observation, context, { ...(result.alias === undefined ? {} : { alias: result.alias }), showLife: false });
164
242
  case "history": return historyText(command, result, context);
165
243
  case "fork": {
166
244
  if (result.receipt.kind !== "forked")
167
- 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.kind === "fork-failed" ? result.receipt.diagnostic : result.receipt.diagnostic;
245
+ 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;
168
246
  const contractId = result.receipt.dispatch.kind === "dispatched" ? result.receipt.dispatch.dispatch.contractId : undefined;
169
- return contractId === undefined ? result.receipt.child : ruler(result.receipt.child, context.columns, contractId);
247
+ return associatedIdentity(result.receipt.child, undefined, contractId);
170
248
  }
171
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");
172
250
  }
173
251
  }
174
- export function akumaExitCode(result) {
175
- if (result.action === "call" && (result.result.dispatch.kind === "failed" || result.result.alias.kind === "failed" || result.result.observation.kind === "failed"))
176
- return 2;
177
- if (result.action === "kill" && result.result.results.some((member) => member.evidence === "unavailable" || member.evidence === "alive-after-sigkill"))
178
- return 1;
179
- if (result.action === "tell" && result.mode === "ordinary" && typeof result.result.tell.wake !== "string")
252
+ function callExitCode(result) {
253
+ if (result.result.dispatch.kind === "failed" || result.result.alias.kind === "failed" || result.result.observation.kind === "failed")
180
254
  return 2;
181
- if (result.action === "tell" && result.mode === "interrupt" && result.result.receipt.kind !== "interrupted")
182
- return 1;
183
- if (result.action === "fork" && result.receipt.kind !== "forked")
184
- return result.receipt.kind === "upstream-forked" ? 2 : 1;
185
- return 0;
255
+ if (result.result.observation.kind !== "observed")
256
+ return 0;
257
+ const timeline = result.result.observation.status.timeline;
258
+ return timeline.kind === "idle" && timeline.outcome?.outcome.kind === "failed" ? 2 : 0;
259
+ }
260
+ function killExitCode(result) {
261
+ return result.result.results.some((member) => member.evidence === "unavailable" || member.evidence === "hung" || member.evidence === "untidy") ? 1 : 0;
262
+ }
263
+ function tellExitCode(result) {
264
+ if (result.mode === "ordinary")
265
+ return typeof result.result.tell.wake === "string" ? 0 : 2;
266
+ return result.result.receipt.kind === "interrupted" ? 0 : 1;
267
+ }
268
+ function forkExitCode(result) {
269
+ return result.receipt.kind === "forked" ? 0 : result.receipt.kind === "upstream-forked" ? 2 : 1;
270
+ }
271
+ export function akumaExitCode(result) {
272
+ switch (result.action) {
273
+ case "call": return callExitCode(result);
274
+ case "kill": return killExitCode(result);
275
+ case "tell": return tellExitCode(result);
276
+ case "fork": return forkExitCode(result);
277
+ default: return 0;
278
+ }
186
279
  }
187
280
  export function akumaJsonValue(command, result) {
188
281
  if (result.action === "call" || result.action === "fork" || result.action === "status" || result.action === "wait" || result.action === "tell" || result.action === "kill")
@@ -191,4 +284,6 @@ export function akumaJsonValue(command, result) {
191
284
  throw new Error("history result requires the history command");
192
285
  return result.historyResult;
193
286
  }
194
- export function renderAkumaJson(command, result) { return JSON.stringify(akumaJsonValue(command, result)); }
287
+ export function renderAkumaJson(command, result) {
288
+ return JSON.stringify(akumaJsonValue(command, result));
289
+ }
@@ -0,0 +1,3 @@
1
+ import type { AcceptedAuditResult } from "../result.js";
2
+ import { type TextRenderContext } from "./terminal.js";
3
+ export declare function renderAcceptedAudit(result: AcceptedAuditResult, context?: TextRenderContext): string;
@@ -0,0 +1,104 @@
1
+ import { cleanupLines, leakLines, outcomeLines, receiptPayload, receiptRow, stopLines, } from "./receipt.js";
2
+ import { renderRefusalFacts } from "./refusal.js";
3
+ import { gitShortStat, renderBoundedTextBlock, renderOpaqueBlock, } from "./terminal.js";
4
+ const CHILD = " ";
5
+ function workspaceEvidence(workspace, columns) {
6
+ return renderOpaqueBlock(`workspace ${workspace.kind} ${workspace.path}`, CHILD, columns);
7
+ }
8
+ function candidateLines(report, columns, addressed) {
9
+ const candidate = report.candidate;
10
+ const lines = [];
11
+ if (candidate.kind === "blocked") {
12
+ receiptRow(lines, "!", "candidate", [{ text: "blocked" }], columns);
13
+ lines.push(...renderRefusalFacts(candidate.refusal, CHILD, columns, addressed));
14
+ return lines;
15
+ }
16
+ const identity = candidate.identity;
17
+ receiptRow(lines, "✓", "candidate", [{ text: "ready" }], columns);
18
+ lines.push(...renderOpaqueBlock(`tender=${identity.tenderSnapshot}`, CHILD, columns));
19
+ lines.push(...renderOpaqueBlock(`integration=${identity.integration.snapshot}`, CHILD, columns));
20
+ lines.push(...renderOpaqueBlock(`change=${identity.integration.changeId}`, CHILD, columns));
21
+ lines.push(...workspaceEvidence(candidate.workspace, columns));
22
+ lines.push(...renderOpaqueBlock(gitShortStat(candidate.scope), CHILD, columns));
23
+ if (candidate.scope.paths !== undefined) {
24
+ for (const path of candidate.scope.paths) {
25
+ lines.push(...renderOpaqueBlock(path, CHILD, columns));
26
+ }
27
+ }
28
+ if (report.delivery !== undefined) {
29
+ lines.push(...renderOpaqueBlock(`delivery change=${report.delivery.changeId} ${report.delivery.relation}`, CHILD, columns));
30
+ }
31
+ if (candidate.diff !== undefined)
32
+ receiptPayload(lines, "diff", candidate.diff);
33
+ return lines;
34
+ }
35
+ function verificationLines(verification, columns, addressed) {
36
+ const lines = [];
37
+ if (verification.kind === "not-run") {
38
+ receiptRow(lines, "·", "verification", [{ text: "not-run" }], columns);
39
+ return lines;
40
+ }
41
+ if (verification.kind === "stopped") {
42
+ return stopLines("verification", verification.stop, columns, addressed);
43
+ }
44
+ receiptRow(lines, verification.kind === "satisfied" ? "✓" : "!", "verification", [
45
+ { text: verification.kind },
46
+ { text: `${verification.passed} of ${verification.total}` },
47
+ ], columns);
48
+ if (verification.summary !== undefined) {
49
+ lines.push(...renderBoundedTextBlock(verification.summary, {
50
+ first: `${CHILD}summary `,
51
+ continuation: CHILD,
52
+ columns,
53
+ }));
54
+ }
55
+ return lines;
56
+ }
57
+ function targetLines(target, columns, addressed) {
58
+ const lines = [];
59
+ if (target.kind === "not-observed") {
60
+ receiptRow(lines, "·", "target", [{ text: "not-observed" }], columns);
61
+ return lines;
62
+ }
63
+ if (target.kind === "placeable") {
64
+ receiptRow(lines, "✓", "target", [
65
+ { text: "placeable" },
66
+ { text: target.ref, opaque: true },
67
+ { text: target.head, opaque: true },
68
+ ], columns);
69
+ return lines;
70
+ }
71
+ if (target.kind === "moved") {
72
+ receiptRow(lines, "!", "target", [
73
+ { text: "moved" },
74
+ { text: target.ref, opaque: true },
75
+ { text: `${target.expected} -> ${target.observed}`, opaque: true },
76
+ ], columns);
77
+ return lines;
78
+ }
79
+ if (target.kind === "failed") {
80
+ receiptRow(lines, "!", "target", [{ text: "failed" }], columns);
81
+ receiptPayload(lines, "diagnostic", target.diagnostic);
82
+ return lines;
83
+ }
84
+ receiptRow(lines, "!", "target", [{ text: "refused" }], columns);
85
+ lines.push(...renderRefusalFacts(target.refusal, CHILD, columns, addressed));
86
+ return lines;
87
+ }
88
+ function obligationLines(result, columns) {
89
+ return [
90
+ ...(result.cleanup === undefined ? [] : cleanupLines(result.cleanup, columns)),
91
+ ...(result.leak === undefined ? [] : leakLines(result.leak, columns)),
92
+ ];
93
+ }
94
+ export function renderAcceptedAudit(result, context) {
95
+ const report = result.report;
96
+ const columns = context?.columns ?? 80;
97
+ return [
98
+ ...outcomeLines("✓", result.verb, "accepted", result.contract, columns),
99
+ ...candidateLines(report, columns, result.contract),
100
+ ...verificationLines(report.verification, columns, result.contract),
101
+ ...targetLines(report.target, columns, result.contract),
102
+ ...obligationLines(result, columns),
103
+ ].join("\n");
104
+ }
@@ -1,4 +1,4 @@
1
1
  import type { AcceptedResult, RetryResult } from "../result.js";
2
- export declare function obligationLines(value: Pick<AcceptedResult, "verification" | "placement" | "cleanup" | "leak">): readonly string[];
3
- export declare function renderAccepted(result: AcceptedResult): string;
4
- export declare function renderRetry(result: RetryResult): string;
2
+ import { type TextRenderContext } from "./terminal.js";
3
+ export declare function renderAccepted(result: AcceptedResult, context?: TextRenderContext): string;
4
+ export declare function renderRetry(result: RetryResult, context?: TextRenderContext): string;