@astrosheep/keiyaku 4.5.7 → 4.5.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 (234) hide show
  1. package/README.md +10 -0
  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/opencode.js +3 -2
  5. package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +10 -9
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +22 -1
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-babysit/SKILL.md +35 -96
  9. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +28 -49
  10. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +21 -15
  11. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +148 -89
  12. package/build/src/akuma/abort.d.ts +2 -1
  13. package/build/src/akuma/abort.js +6 -23
  14. package/build/src/akuma/akuma-handle.js +4 -2
  15. package/build/src/akuma/akuma-observe.d.ts +2 -0
  16. package/build/src/akuma/akuma-observe.js +1 -0
  17. package/build/src/akuma/akuma-product.js +9 -7
  18. package/build/src/akuma/akuma.d.ts +372 -9
  19. package/build/src/akuma/akuma.js +31 -1
  20. package/build/src/akuma/allowed.d.ts +1 -1
  21. package/build/src/akuma/allowed.js +1 -0
  22. package/build/src/akuma/body.d.ts +6 -4
  23. package/build/src/akuma/body.js +5 -3
  24. package/build/src/akuma/call-request.d.ts +80 -0
  25. package/build/src/akuma/call-request.js +211 -0
  26. package/build/src/akuma/heart/facts.d.ts +6 -78
  27. package/build/src/akuma/heart/index.d.ts +1 -1
  28. package/build/src/akuma/heart/request-authority.d.ts +5 -4
  29. package/build/src/akuma/heart/request-authority.js +20 -34
  30. package/build/src/akuma/heart/request-rows.js +12 -23
  31. package/build/src/akuma/heart/schema.d.ts +1 -1
  32. package/build/src/akuma/heart/schema.js +5 -13
  33. package/build/src/akuma/index.d.ts +1 -1
  34. package/build/src/akuma/index.js +1 -1
  35. package/build/src/akuma/projection-read.d.ts +1 -0
  36. package/build/src/akuma/projection-read.js +8 -1
  37. package/build/src/akuma/projection.d.ts +856 -137
  38. package/build/src/akuma/projection.js +190 -0
  39. package/build/src/akuma/provider.d.ts +30 -3
  40. package/build/src/akuma/provider.js +104 -0
  41. package/build/src/akuma/providers/acp/core.d.ts +2 -2
  42. package/build/src/akuma/providers/acp/core.js +13 -6
  43. package/build/src/akuma/providers/acp/index.js +5 -4
  44. package/build/src/akuma/providers/claude/index.d.ts +3 -3
  45. package/build/src/akuma/providers/claude/index.js +16 -5
  46. package/build/src/akuma/providers/codex-app-server/events.js +1 -1
  47. package/build/src/akuma/providers/codex-app-server/index.js +18 -6
  48. package/build/src/akuma/providers/grok-build/index.js +5 -4
  49. package/build/src/akuma/providers/opencode-sdk/index.js +66 -25
  50. package/build/src/akuma/providers/opencode-sdk/session.d.ts +3 -2
  51. package/build/src/akuma/providers/opencode-sdk/session.js +28 -11
  52. package/build/src/akuma/providers/pi/index.js +42 -14
  53. package/build/src/akuma/request-lifecycle.d.ts +3 -9
  54. package/build/src/akuma/request-lifecycle.js +4 -4
  55. package/build/src/akuma/request-rendezvous.d.ts +26 -0
  56. package/build/src/akuma/request-rendezvous.js +100 -0
  57. package/build/src/akuma/request-serve.d.ts +5 -65
  58. package/build/src/akuma/request-serve.js +81 -208
  59. package/build/src/akuma/request-wire.d.ts +109 -115
  60. package/build/src/akuma/request-wire.js +63 -318
  61. package/build/src/akuma/requests.d.ts +19 -47
  62. package/build/src/akuma/requests.js +51 -107
  63. package/build/src/akuma/turn-drive.d.ts +5 -3
  64. package/build/src/akuma/turn-drive.js +32 -10
  65. package/build/src/akuma-body.d.ts +7 -2
  66. package/build/src/akuma-body.js +68 -46
  67. package/build/src/cli/accepted.d.ts +1 -1
  68. package/build/src/cli/accepted.js +2 -2
  69. package/build/src/cli/commands/akuma-invoke.d.ts +2 -0
  70. package/build/src/cli/commands/akuma-invoke.js +17 -9
  71. package/build/src/cli/commands/akuma.js +7 -7
  72. package/build/src/cli/commands/contract-invoke.d.ts +3 -2
  73. package/build/src/cli/commands/contract-invoke.js +26 -19
  74. package/build/src/cli/commands/contract.d.ts +13 -13
  75. package/build/src/cli/commands/contract.js +32 -17
  76. package/build/src/cli/commands/install.d.ts +1 -1
  77. package/build/src/cli/commands/install.js +1 -1
  78. package/build/src/cli/commands/task-invoke.d.ts +3 -0
  79. package/build/src/cli/commands/task-invoke.js +23 -140
  80. package/build/src/cli/commands/task.js +54 -20
  81. package/build/src/cli/invoke.js +39 -25
  82. package/build/src/cli/main.js +2 -1
  83. package/build/src/cli/parse.d.ts +2 -2
  84. package/build/src/cli/parse.js +37 -22
  85. package/build/src/cli/render/akuma-activity.d.ts +4 -1
  86. package/build/src/cli/render/akuma-activity.js +45 -30
  87. package/build/src/cli/render/akuma-tool.d.ts +5 -1
  88. package/build/src/cli/render/akuma.js +5 -9
  89. package/build/src/cli/render/audit.js +1 -1
  90. package/build/src/cli/render/catalog.js +80 -21
  91. package/build/src/cli/render/contract-observation.d.ts +2 -0
  92. package/build/src/cli/render/contract-observation.js +11 -0
  93. package/build/src/cli/render/contract.js +25 -65
  94. package/build/src/cli/render/kanshi-akuma.d.ts +8 -0
  95. package/build/src/cli/render/kanshi-akuma.js +111 -0
  96. package/build/src/cli/render/kanshi.js +108 -213
  97. package/build/src/cli/render/receipt.d.ts +1 -2
  98. package/build/src/cli/render/receipt.js +76 -26
  99. package/build/src/cli/render/refusal.js +2 -10
  100. package/build/src/cli/render/region.js +5 -2
  101. package/build/src/cli/render/settings.d.ts +1 -1
  102. package/build/src/cli/render/settings.js +27 -8
  103. package/build/src/cli/render/task.js +22 -5
  104. package/build/src/cli/render/terminal.d.ts +28 -0
  105. package/build/src/cli/render/terminal.js +65 -0
  106. package/build/src/cli/result.d.ts +3 -3
  107. package/build/src/cli/runtime.js +3 -1
  108. package/build/src/cli/selectors.d.ts +2 -1
  109. package/build/src/cli/selectors.js +4 -3
  110. package/build/src/cli/square-edge.js +120 -36
  111. package/build/src/cli/usage.js +2 -1
  112. package/build/src/contract-guidance.d.ts +5 -0
  113. package/build/src/contract-guidance.js +121 -0
  114. package/build/src/contract-worktree.d.ts +0 -1
  115. package/build/src/contract-worktree.js +32 -83
  116. package/build/src/coordination/sqlite-transaction-lock.d.ts +1 -0
  117. package/build/src/coordination/sqlite-transaction-lock.js +5 -0
  118. package/build/src/core/facts/codec.d.ts +2 -0
  119. package/build/src/core/facts/codec.js +4 -0
  120. package/build/src/core/verbs/placement.d.ts +6 -1
  121. package/build/src/core/verbs/placement.js +5 -3
  122. package/build/src/dispatch/index.d.ts +0 -2
  123. package/build/src/dispatch/index.js +54 -55
  124. package/build/src/git/admission.js +2 -2
  125. package/build/src/git/hooks.d.ts +9 -15
  126. package/build/src/git/hooks.js +23 -317
  127. package/build/src/git/nuke.d.ts +2 -1
  128. package/build/src/git/nuke.js +36 -18
  129. package/build/src/git/private-state-seat.d.ts +12 -0
  130. package/build/src/git/private-state-seat.js +39 -0
  131. package/build/src/git/process.d.ts +6 -0
  132. package/build/src/git/process.js +19 -7
  133. package/build/src/git/read-observation.js +29 -20
  134. package/build/src/git/reconcile.d.ts +11 -0
  135. package/build/src/git/reconcile.js +64 -11
  136. package/build/src/git/repository.d.ts +6 -2
  137. package/build/src/git/repository.js +8 -0
  138. package/build/src/git/target-placement.d.ts +1 -0
  139. package/build/src/git/target-placement.js +5 -0
  140. package/build/src/git/tender.d.ts +1 -0
  141. package/build/src/git/terminal-reconcile.d.ts +1 -1
  142. package/build/src/git/terminal-reconcile.js +22 -20
  143. package/build/src/git/workspace.d.ts +14 -0
  144. package/build/src/git/workspace.js +44 -0
  145. package/build/src/kanshi/index.d.ts +1 -1
  146. package/build/src/kanshi/read.js +16 -16
  147. package/build/src/kanshi/report.d.ts +2 -2
  148. package/build/src/library/address.d.ts +9 -3
  149. package/build/src/library/address.js +3 -2
  150. package/build/src/library/akuma-creation.d.ts +4 -3
  151. package/build/src/library/akuma-creation.js +19 -13
  152. package/build/src/library/audit.d.ts +1 -1
  153. package/build/src/library/audit.js +5 -3
  154. package/build/src/library/catalog.d.ts +3 -1
  155. package/build/src/library/catalog.js +20 -6
  156. package/build/src/library/composition.d.ts +371 -0
  157. package/build/src/library/composition.js +28 -0
  158. package/build/src/library/configuration.js +8 -2
  159. package/build/src/library/continuation.js +66 -30
  160. package/build/src/library/contract-bind.js +10 -2
  161. package/build/src/library/contract-forwarding-reconciliation-result.d.ts +96 -0
  162. package/build/src/library/contract-forwarding-reconciliation-result.js +83 -0
  163. package/build/src/library/contract-forwarding-result.d.ts +6723 -0
  164. package/build/src/library/contract-forwarding-result.js +521 -0
  165. package/build/src/library/contract-forwarding.d.ts +72 -0
  166. package/build/src/library/contract-forwarding.js +125 -0
  167. package/build/src/library/contract-handle.d.ts +36 -0
  168. package/build/src/library/contract-handle.js +313 -0
  169. package/build/src/library/contract-operations.d.ts +1044 -67
  170. package/build/src/library/contract-operations.js +190 -118
  171. package/build/src/library/contract.d.ts +11 -32
  172. package/build/src/library/contract.js +16 -289
  173. package/build/src/library/fleet-result.d.ts +1454 -0
  174. package/build/src/library/fleet-result.js +96 -0
  175. package/build/src/library/fleet.d.ts +112 -54
  176. package/build/src/library/fleet.js +211 -71
  177. package/build/src/library/input.d.ts +2 -0
  178. package/build/src/library/input.js +4 -0
  179. package/build/src/library/keiyaku.d.ts +371 -20
  180. package/build/src/library/keiyaku.js +8 -21
  181. package/build/src/library/mutation.d.ts +3 -3
  182. package/build/src/library/mutation.js +5 -9
  183. package/build/src/library/nuke.d.ts +1 -1
  184. package/build/src/library/nuke.js +4 -3
  185. package/build/src/library/reconcile.d.ts +4 -0
  186. package/build/src/library/reconcile.js +2 -0
  187. package/build/src/library/refusal.d.ts +0 -9
  188. package/build/src/library/refusal.js +0 -7
  189. package/build/src/protocol/amend.js +56 -50
  190. package/build/src/protocol/attempt.d.ts +2 -0
  191. package/build/src/protocol/attempt.js +8 -1
  192. package/build/src/protocol/completion.js +7 -0
  193. package/build/src/protocol/deliver.js +6 -2
  194. package/build/src/protocol/operations.d.ts +4 -1
  195. package/build/src/protocol/operations.js +5 -2
  196. package/build/src/protocol/placement.d.ts +1 -0
  197. package/build/src/protocol/placement.js +52 -38
  198. package/build/src/protocol/read/observation.d.ts +1 -4
  199. package/build/src/protocol/read/observation.js +2 -15
  200. package/build/src/protocol/reintegrate.js +62 -58
  201. package/build/src/protocol/review.js +5 -0
  202. package/build/src/protocol/run.js +17 -13
  203. package/build/src/runtime/proc/run.d.ts +8 -0
  204. package/build/src/runtime/proc/run.js +27 -0
  205. package/build/src/runtime/proc/termination.js +26 -22
  206. package/build/src/runtime/proc/windows-launch.exe +0 -0
  207. package/build/src/settlement/holder.d.ts +2 -1
  208. package/build/src/settlement/holder.js +15 -4
  209. package/build/src/settlement/settle.js +99 -33
  210. package/build/src/task/board.d.ts +68 -27
  211. package/build/src/task/board.js +31 -1
  212. package/build/src/task/catalog.d.ts +4 -0
  213. package/build/src/task/catalog.js +23 -0
  214. package/build/src/task/compose-language.js +33 -7
  215. package/build/src/task/compose-parser.d.ts +1 -1
  216. package/build/src/task/compose-parser.js +1 -1
  217. package/build/src/task/compose.js +2 -0
  218. package/build/src/task/index.d.ts +12 -4
  219. package/build/src/task/index.js +97 -16
  220. package/build/src/task/mutation-result.d.ts +923 -0
  221. package/build/src/task/mutation-result.js +140 -0
  222. package/build/src/task/mutation.d.ts +552 -28
  223. package/build/src/task/mutation.js +304 -97
  224. package/build/src/task/operations.d.ts +1 -4
  225. package/build/src/task/operations.js +0 -6
  226. package/build/src/task/public.d.ts +2 -0
  227. package/build/src/task/public.js +1 -0
  228. package/build/src/workspace-place.d.ts +7 -2
  229. package/build/src/workspace-place.js +34 -24
  230. package/build/src/world.d.ts +1 -0
  231. package/build/src/world.js +11 -0
  232. package/package.json +8 -6
  233. package/build/src/akuma/request-execution.d.ts +0 -8
  234. package/build/src/akuma/request-execution.js +0 -98
@@ -1,4 +1,5 @@
1
- import { DEFAULT_CONTEXT, akumaRawAnswer, associatedIdentity, historyText, mutationObservationStageText, snapshotHeading, snapshotText, tellText, waitText, } from "./akuma-activity.js";
1
+ import { parseAkumaStatus } from "../../akuma/akuma.js";
2
+ import { DEFAULT_CONTEXT, akumaRawAnswer, associatedIdentity, historyText, killResultText, mutationObservationStageText, snapshotHeading, snapshotText, tellText, waitText, } from "./akuma-activity.js";
2
3
  import { safeText } from "./terminal.js";
3
4
  export { akumaRawAnswer } from "./akuma-activity.js";
4
5
  function dispatchLines(stage) {
@@ -6,8 +7,6 @@ function dispatchLines(stage) {
6
7
  return [];
7
8
  if (stage.failure.kind === "conflict")
8
9
  return [`dispatch failed conflict ${stage.failure.current.contractId}`];
9
- if (stage.failure.kind === "contention")
10
- return ["dispatch failed contention"];
11
10
  return [`dispatch failed ${stage.failure.kind} ${safeText(stage.failure.diagnostic)}`];
12
11
  }
13
12
  function executionCwdLine(result) {
@@ -49,7 +48,7 @@ function callText(result, context) {
49
48
  ].join("\n");
50
49
  }
51
50
  return snapshotText({
52
- status: result.result.observation.status,
51
+ status: parseAkumaStatus(result.result.observation.status),
53
52
  contract: contractId === undefined ? { kind: "none" } : { kind: "associated", contractId },
54
53
  }, context, { ...(alias === undefined ? {} : { alias }), facts: [...cwd, ...facts] });
55
54
  }
@@ -70,7 +69,7 @@ export function renderAkumaText(command, result, context = DEFAULT_CONTEXT) {
70
69
  return waitText(result, context);
71
70
  case "tell":
72
71
  return result.mode === "ordinary"
73
- ? tellText(result, context)
72
+ ? tellText(result)
74
73
  : mutationObservationStageText(result.result.id, result.result.observation, context, {
75
74
  ...(result.alias === undefined ? {} : { alias: result.alias }),
76
75
  showLife: false,
@@ -89,10 +88,7 @@ export function renderAkumaText(command, result, context = DEFAULT_CONTEXT) {
89
88
  }
90
89
  case "kill":
91
90
  return result.result.results
92
- .map((member) => mutationObservationStageText(member.id, member.observation, context, {
93
- facts: [`kill ${member.evidence}`],
94
- ...(result.alias === undefined ? {} : { alias: result.alias }),
95
- }))
91
+ .map((member) => killResultText(member.id, member.evidence, result.alias))
96
92
  .join("\n\n");
97
93
  }
98
94
  }
@@ -39,7 +39,7 @@ function verificationLines(verification, columns, addressed) {
39
39
  return lines;
40
40
  }
41
41
  if (verification.kind === "stopped") {
42
- return stopLines("verification", verification.stop, columns, addressed);
42
+ return stopLines(verification.stop, columns, addressed);
43
43
  }
44
44
  receiptRow(lines, verification.kind === "satisfied" ? "✓" : "!", "verification", [{ text: verification.kind }, { text: `${verification.passed} of ${verification.total}` }], columns);
45
45
  if (verification.summary !== undefined) {
@@ -1,6 +1,6 @@
1
- import { abbreviateGitIds, afterWording, candidateFact, dependentWording, displayGitId, gateFact, gitIdsInRow, } from "./contract-observation.js";
1
+ import { abbreviateGitIds, afterWording, candidateFact, dependentWording, displayGitId, gateFact, gitIdsInRow, targetMovementFacts, } from "./contract-observation.js";
2
2
  import { safeText } from "./terminal.js";
3
- function targetLine(row) {
3
+ function targetLine(row, abbreviations) {
4
4
  if (row.target === null)
5
5
  return "no target";
6
6
  const target = row.target.startsWith("refs/heads/") ? row.target.slice("refs/heads/".length) : row.target;
@@ -9,11 +9,74 @@ function targetLine(row) {
9
9
  : row.targetLag.kind === "unknown"
10
10
  ? `commits behind ${target} unknown`
11
11
  : undefined;
12
- return [
13
- `target ${target}`,
14
- ...(lag === undefined ? [] : [lag]),
15
- ...(row.targetObservation?.drift === true ? ["target moved"] : []),
16
- ].join(" · ");
12
+ return [`target ${target}`, ...(lag === undefined ? [] : [lag]), ...targetMovementFacts(row, abbreviations)].join(" · ");
13
+ }
14
+ const CATALOG_VISIBLE_AKUMA = 10;
15
+ function akumaMark(life) {
16
+ if (life === "running")
17
+ return "●";
18
+ if (life === "asleep" || life === "unborn")
19
+ return "○";
20
+ if (life === "killed")
21
+ return "×";
22
+ if (life === "stillborn")
23
+ return "!";
24
+ return "?";
25
+ }
26
+ function akumaUpdatedAt(row) {
27
+ const lifeAt = "lifeAt" in row ? row.lifeAt : null;
28
+ const activityAt = "lastActivityAt" in row ? row.lastActivityAt : null;
29
+ if (lifeAt === null)
30
+ return activityAt;
31
+ if (activityAt === null)
32
+ return lifeAt;
33
+ return lifeAt > activityAt ? lifeAt : activityAt;
34
+ }
35
+ function relativeAge(source, observedAt) {
36
+ if (source === null)
37
+ return null;
38
+ const seconds = Math.floor((Date.parse(observedAt) - Date.parse(source)) / 1_000);
39
+ if (seconds < 0)
40
+ return "now";
41
+ if (seconds < 60)
42
+ return `${seconds}s`;
43
+ const minutes = Math.floor(seconds / 60);
44
+ if (minutes < 60)
45
+ return `${minutes}m`;
46
+ const hours = Math.floor(minutes / 60);
47
+ if (hours < 24)
48
+ return `${hours}h`;
49
+ return `${Math.floor(hours / 24)}d`;
50
+ }
51
+ function renderAkumaCatalog(catalog) {
52
+ const ordered = [...catalog.rows].sort((left, right) => {
53
+ const leftAt = akumaUpdatedAt(left);
54
+ const rightAt = akumaUpdatedAt(right);
55
+ if (leftAt === rightAt)
56
+ return 0;
57
+ if (leftAt === null)
58
+ return 1;
59
+ if (rightAt === null)
60
+ return -1;
61
+ return leftAt > rightAt ? -1 : 1;
62
+ });
63
+ const rows = ordered.slice(0, CATALOG_VISIBLE_AKUMA);
64
+ const lines = [
65
+ `akuma instances ${rows.length} of ${ordered.length} known`,
66
+ ...(catalog.archetype === null ? [] : [` scope ${safeText(catalog.archetype)}`]),
67
+ "",
68
+ ];
69
+ for (const row of rows) {
70
+ const lifeAt = "lifeAt" in row ? row.lifeAt : null;
71
+ const activityAt = "lastActivityAt" in row ? row.lastActivityAt : null;
72
+ const ages = [relativeAge(lifeAt, catalog.observedAt), relativeAge(activityAt, catalog.observedAt)].filter((age) => age !== null);
73
+ lines.push(`${akumaMark(row.life)} ${safeText(row.id)} · ${row.life}${ages.length === 0 ? "" : ` · ${ages.join(" · ")}`}`);
74
+ }
75
+ if (rows.length < ordered.length) {
76
+ const selector = catalog.archetype === null ? '"aku/*/*"' : `aku/${catalog.archetype}/`;
77
+ lines.push("", ` + ${ordered.length - rows.length} more akuma not shown`, ` keiyaku ls ${selector}`);
78
+ }
79
+ return lines.join("\n");
17
80
  }
18
81
  function catalogMark(row) {
19
82
  if (row.phase === "claimed")
@@ -58,7 +121,7 @@ function renderContractCatalog(catalog) {
58
121
  const blocks = rows.map((row) => {
59
122
  const lines = [
60
123
  `${catalogMark(row)} ${safeText(row.id)} · ${row.phase} · ${formatAge(row.phaseAt, catalog.observedAt)} · ${safeText(row.title ?? "title unavailable")}`,
61
- ` ${candidateFact(row.delivery)} · ${targetLine(row)}`,
124
+ ` ${candidateFact(row.delivery)} · ${targetLine(row, abbreviations)}`,
62
125
  ...row.after.map((edge) => ` ${afterWording(edge)}`),
63
126
  ...(row.dependents.length === 0 ? [] : [` dependents ${row.dependents.map(dependentWording).join(" · ")}`]),
64
127
  ...(row.gates.reports.length === 0 ? [] : [` ${row.gates.reports.map(gateFact).join(" ")}`]),
@@ -76,18 +139,14 @@ export function renderCatalogText(catalog) {
76
139
  if (catalog.kind === "contracts")
77
140
  return renderContractCatalog(catalog);
78
141
  if (catalog.kind === "archetypes") {
79
- return catalog.rows
80
- .flatMap((row) => [
81
- `${safeText(row.name)}${row.model === undefined ? "" : ` - ${safeText(row.model)}`}`,
82
- ...(row.description === undefined ? [] : [` ${safeText(row.description)}`]),
83
- ])
84
- .join("\n");
142
+ return [
143
+ `archetypes ${catalog.rows.length}`,
144
+ "",
145
+ ...catalog.rows.flatMap((row) => [
146
+ `${safeText(row.name)}${row.model === undefined ? "" : ` - ${safeText(row.model)}`}`,
147
+ ...(row.description === undefined ? [] : [` ${safeText(row.description)}`]),
148
+ ]),
149
+ ].join("\n");
85
150
  }
86
- return catalog.rows
87
- .map((row) => {
88
- if (!("lifeAt" in row))
89
- return `${safeText(row.id)} - ${row.life}`;
90
- return `${safeText(row.id)} - ${row.life} - runtime ${row.lifeAt ?? "-"} - last activity ${row.lastActivityAt ?? "-"}`;
91
- })
92
- .join("\n");
151
+ return renderAkumaCatalog(catalog);
93
152
  }
@@ -8,3 +8,5 @@ export declare function mergeSummary(observation: ContractWorkspaceObservation):
8
8
  export declare function abbreviateGitIds(ids: readonly string[]): ReadonlyMap<string, string>;
9
9
  export declare function gitIdsInRow(row: ContractRow): readonly string[];
10
10
  export declare function displayGitId(value: string, abbreviations: ReadonlyMap<string, string>): string;
11
+ /** Render the pinned delivery target and the same-epoch observed target head. */
12
+ export declare function targetMovementFacts(row: ContractRow, abbreviations: ReadonlyMap<string, string>): readonly string[];
@@ -56,3 +56,14 @@ export function gitIdsInRow(row) {
56
56
  export function displayGitId(value, abbreviations) {
57
57
  return abbreviations.get(value) ?? value;
58
58
  }
59
+ /** Render the pinned delivery target and the same-epoch observed target head. */
60
+ export function targetMovementFacts(row, abbreviations) {
61
+ if (row.target === null || row.targetObservation?.drift !== true)
62
+ return [];
63
+ if (row.delivery === null)
64
+ return ["target moved"];
65
+ return [
66
+ "target moved",
67
+ `${displayGitId(row.delivery.integration.snapshot, abbreviations)} -> ${row.targetObservation.head === null ? "null" : displayGitId(row.targetObservation.head, abbreviations)}`,
68
+ ];
69
+ }
@@ -1,5 +1,5 @@
1
1
  import { renderAcceptedAudit } from "./audit.js";
2
- import { appendHookPayload, cleanupLines, hookFailureSummary, leakLines, outcomeLines, receiptPayload, receiptRow, reuseLines, stopLines, stopSummary, titleLines, } 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) {
@@ -11,33 +11,6 @@ function retryLines(detail, indent, columns) {
11
11
  }
12
12
  return renderOpaqueBlock(detail.kind, indent, columns);
13
13
  }
14
- function changedEffect(effect) {
15
- return effect.action !== "unchanged";
16
- }
17
- function effectRows(effect, columns) {
18
- const mark = changedEffect(effect) ? "✓" : "·";
19
- const lines = [];
20
- if (effect.kind === "worktree") {
21
- receiptRow(lines, mark, "worktree", [{ text: effect.action }, { text: effect.path, opaque: true }], columns);
22
- }
23
- else if (effect.kind === "contract-file") {
24
- receiptRow(lines, mark, "contract-file", [{ text: effect.action }, { text: effect.path, opaque: true }], columns);
25
- }
26
- else if (effect.kind === "target-checkout") {
27
- receiptRow(lines, mark, "target-checkout", [{ text: effect.action }, { text: effect.target, opaque: true }, { text: effect.path, opaque: true }], columns);
28
- }
29
- else if (effect.kind === "recovery-snapshot") {
30
- receiptRow(lines, mark, "recovery-snapshot", [{ text: effect.action }, { text: effect.snapshot, opaque: true }, { text: effect.retention }], columns);
31
- }
32
- else {
33
- receiptRow(lines, mark, "ref", [
34
- { text: effect.action },
35
- { text: effect.name, opaque: true },
36
- { text: `${effect.before ?? "null"} -> ${effect.after ?? "null"}`, opaque: true },
37
- ], columns);
38
- }
39
- return lines;
40
- }
41
14
  function lagRows(lag, columns) {
42
15
  const lines = [];
43
16
  if (lag.kind === "worktree-retained") {
@@ -46,7 +19,7 @@ function lagRows(lag, columns) {
46
19
  else if (lag.kind === "worktree-follow-retained") {
47
20
  receiptRow(lines, "!", "lag", [
48
21
  {
49
- text: `${lag.kind} reason=${lag.reason} tender=${lag.tender} head=${lag.head} path=${lag.path}`,
22
+ text: `${lag.kind} reason=${lag.reason} tender=${lag.tender} head=${lag.head}${lag.paths === undefined || lag.paths.length === 0 ? "" : ` paths=${lag.paths.join(",")}`} path=${lag.path}`,
50
23
  opaque: true,
51
24
  },
52
25
  ], columns);
@@ -66,7 +39,7 @@ function lagRows(lag, columns) {
66
39
  else if (lag.kind === "worktree-hook-failed") {
67
40
  receiptRow(lines, "!", "lag", [
68
41
  {
69
- text: `worktree-hook-failed ${lag.phase} ${lag.path} command=${lag.command} ${hookFailureSummary(lag.failure)}`,
42
+ text: `worktree-hook-failed ${lag.phase} ${lag.path} command=${lag.command} name=${lag.name} ${hookFailureSummary(lag.failure)}`,
70
43
  opaque: true,
71
44
  },
72
45
  ], columns);
@@ -142,20 +115,11 @@ function acceptedRecord(result, columns) {
142
115
  : [...contract, { text: fact.entry, opaque: true }, { text: `· ${fact.kind}` }], columns);
143
116
  }
144
117
  receiptRow(record, " ", "head", [{ text: result.head, opaque: true }], columns);
118
+ if (result.recoverySnapshot !== undefined)
119
+ receiptRow(record, " ", "recovery snapshot", [{ text: result.recoverySnapshot, opaque: true }], columns);
145
120
  if (result.verb === "deliver") {
146
121
  pushBlock(record, reuseLines(result.verificationReuse, columns));
147
122
  }
148
- const changed = result.effects.filter(changedEffect);
149
- const unchanged = result.effects.filter((effect) => !changedEffect(effect));
150
- for (const effect of [...changed, ...unchanged])
151
- pushBlock(record, effectRows(effect, columns));
152
- for (const action of result.settlement.actions) {
153
- receiptRow(record, "·", "settle", [
154
- { text: action.kind },
155
- { text: action.action },
156
- { text: action.kind === "task" ? action.taskId : action.path, opaque: true },
157
- ], columns);
158
- }
159
123
  return record;
160
124
  }
161
125
  function acceptedLagRows(result, columns) {
@@ -164,7 +128,7 @@ function acceptedLagRows(result, columns) {
164
128
  for (const lag of result.lag)
165
129
  pushBlock(obligations, lagRows(lag, columns));
166
130
  }
167
- for (const lag of result.settlement.lags) {
131
+ for (const lag of result.settlementLags) {
168
132
  pushBlock(obligations, settlementLagRows(lag, columns));
169
133
  }
170
134
  return obligations;
@@ -210,7 +174,7 @@ function completionLines(result, columns) {
210
174
  ...(verification?.verdict === "satisfied" ? [{ text: `· verified (${verification.mode})` }] : []),
211
175
  ], columns);
212
176
  if (verification?.verdict === "unsatisfied") {
213
- receiptRow(lines, "!", "verification", [{ text: "unsatisfied" }, { text: `(${verification.mode})` }], columns);
177
+ receiptRow(lines, "!", "verification", [{ text: "unsatisfied" }, { text: `(${verification.mode})` }, { text: "· not required by Contract gates" }], columns);
214
178
  if (result.verificationSummary !== undefined) {
215
179
  receiptPayload(lines, " summary", result.verificationSummary);
216
180
  }
@@ -234,8 +198,10 @@ function continuationLines(result, columns) {
234
198
  receiptRow(lines, "✓", "continuation", [{ text: "complete" }, { text: contractId, opaque: true }], columns);
235
199
  }
236
200
  for (const { contractId, stop } of report.stopped) {
237
- const detail = "kind" in stop ? [{ text: stop.kind }] : stopSummary(stop, contractId);
238
- receiptRow(lines, "!", "continuation", [{ text: "blocked" }, { text: contractId, opaque: true }, { text: "·" }, ...detail], columns);
201
+ if ("kind" in stop)
202
+ receiptRow(lines, "!", contractId, [{ text: "· already terminal" }], columns);
203
+ else
204
+ lines.push(...stopLines(stop, columns, contractId, contractId));
239
205
  }
240
206
  return lines;
241
207
  }
@@ -259,15 +225,16 @@ function renderAcceptedDeliver(result, columns) {
259
225
  const complete = result.completion !== undefined;
260
226
  const title = complete ? "delivered" : "deliver — not complete";
261
227
  const lines = titleLines("✓", title, result.contract, columns);
262
- lines.push(...movementLines(result, columns), ...completionLines(result, columns), ...continuationLines(result, columns));
263
- if (!complete)
264
- receiptRow(lines, " ", "candidate", [{ text: "kept" }], columns);
228
+ lines.push(...movementLines(result, columns), ...completionLines(result, columns));
265
229
  if (result.verification !== undefined) {
266
- lines.push(...stopLines("verification", result.verification, columns, result.contract));
230
+ lines.push(...stopLines(result.verification, columns, result.contract));
267
231
  }
268
232
  if (!complete && result.placement !== undefined) {
269
- lines.push(...stopLines("completion", result.placement, columns, result.contract));
233
+ lines.push(...stopLines(result.placement, columns, result.contract));
270
234
  }
235
+ if (!complete)
236
+ receiptRow(lines, " ", "candidate", [{ text: "kept" }], columns);
237
+ lines.push(...continuationLines(result, columns));
271
238
  if (result.cleanup !== undefined)
272
239
  pushBlock(lines, cleanupLines(result.cleanup, columns));
273
240
  if (result.leak !== undefined)
@@ -278,15 +245,16 @@ function renderAcceptedDeliver(result, columns) {
278
245
  function renderAcceptedReview(result, columns) {
279
246
  const complete = result.completion !== undefined;
280
247
  const lines = titleLines("✓", `review ${result.verdict} — ${complete ? "complete" : "not complete"}`, result.contract, columns);
281
- lines.push(...movementLines(result, columns), ...completionLines(result, columns), ...continuationLines(result, columns));
282
- if (!complete)
283
- receiptRow(lines, " ", "candidate", [{ text: "kept" }], columns);
284
- if (result.placement !== undefined) {
285
- lines.push(...stopLines("completion", result.placement, columns, result.contract));
286
- }
248
+ lines.push(...movementLines(result, columns), ...completionLines(result, columns));
287
249
  if (result.verification !== undefined) {
288
- lines.push(...stopLines("verification", result.verification, columns, result.contract));
250
+ lines.push(...stopLines(result.verification, columns, result.contract));
289
251
  }
252
+ if (result.placement !== undefined) {
253
+ lines.push(...stopLines(result.placement, columns, result.contract));
254
+ }
255
+ if (!complete)
256
+ receiptRow(lines, " ", "candidate", [{ text: "kept" }], columns);
257
+ lines.push(...continuationLines(result, columns));
290
258
  if (result.cleanup !== undefined)
291
259
  pushBlock(lines, cleanupLines(result.cleanup, columns));
292
260
  if (result.leak !== undefined)
@@ -304,14 +272,6 @@ function renderAcceptedAbandon(result, columns) {
304
272
  const lines = titleLines("✓", "abandoned", result.contract, columns);
305
273
  if (result.note !== undefined)
306
274
  receiptRow(lines, " ", "note", [{ text: result.note }], columns);
307
- for (const effect of result.effects) {
308
- if (effect.kind === "worktree") {
309
- receiptRow(lines, " ", "workspace", [{ text: effect.action }, { text: effect.path, opaque: true }], columns);
310
- }
311
- else if (effect.kind === "recovery-snapshot") {
312
- receiptRow(lines, " ", "recovery snapshot", [{ text: effect.snapshot, opaque: true }, { text: `· ${effect.retention}` }], columns);
313
- }
314
- }
315
275
  lines.push(...recordBlock(result, columns));
316
276
  return lines.join("\n");
317
277
  }
@@ -0,0 +1,8 @@
1
+ import type { KanshiReport } from "../../kanshi/index.js";
2
+ import { type TextRenderContext } from "./terminal.js";
3
+ declare const NARROW_COLUMNS = 72;
4
+ declare function akumaMark(life: string): string;
5
+ declare function endpointFact(id: string, observed: string | undefined): string;
6
+ declare function renderAkuma(report: KanshiReport, context: TextRenderContext): readonly string[];
7
+ declare function formatAge(source: string | null | undefined, observedAt: string): string;
8
+ export { akumaMark, endpointFact, formatAge, NARROW_COLUMNS, renderAkuma };
@@ -0,0 +1,111 @@
1
+ import { visibleFleetRows } from "../../kanshi/fleet.js";
2
+ import { boundedActivity, entityLines, identityLine, plumbFacts, renderSectionBlock, safeText, tone, } from "./terminal.js";
3
+ const PLUMB = " │ ";
4
+ const NARROW_COLUMNS = 72;
5
+ function akumaMark(life) {
6
+ return life === "running"
7
+ ? "●"
8
+ : life === "stillborn"
9
+ ? "!"
10
+ : life === "asleep"
11
+ ? "○"
12
+ : life === "killed"
13
+ ? "×"
14
+ : "?";
15
+ }
16
+ function activitySnapshotLine(row) {
17
+ const snapshot = row.snapshot;
18
+ if (snapshot === undefined)
19
+ return undefined;
20
+ const latest = snapshot.entries.flatMap((entry) => (entry.kind === "row" ? [entry.row] : [])).at(-1);
21
+ if (latest === undefined) {
22
+ if (snapshot.kind !== "idle" || snapshot.outcome === undefined)
23
+ return undefined;
24
+ return snapshot.outcome.outcome.kind === "answered"
25
+ ? snapshot.outcome.outcome.answer
26
+ : snapshot.outcome.outcome.diagnostic;
27
+ }
28
+ if (latest.kind === "tool")
29
+ return latest.name;
30
+ return "text" in latest ? latest.text : "activity";
31
+ }
32
+ function akumaLabel(row) {
33
+ const aliases = row.aliases ?? [];
34
+ return aliases.length === 0 ? "" : `(${aliases.join(" ")})`;
35
+ }
36
+ function endpointFact(id, observed) {
37
+ return observed === "missing"
38
+ ? `-> ${id} (missing)`
39
+ : observed === "unavailable"
40
+ ? `-> ${id} (unavailable)`
41
+ : `-> ${id}`;
42
+ }
43
+ function renderAkuma(report, context) {
44
+ const section = report.akuma;
45
+ if (section.kind === "absent")
46
+ return ["AKUMA // absent", "", `${PLUMB}akuma absent`];
47
+ if (section.kind === "failed")
48
+ return ["AKUMA // unavailable", "", tone(`! ${safeText(section.failure.message)}`, "alert", context.color)];
49
+ const rows = visibleFleetRows(section.value.rows);
50
+ const rowLines = rows.map((row) => {
51
+ const lifeAt = "lifeAt" in row ? row.lifeAt : null;
52
+ const life = `${row.life} · ${formatAge(lifeAt, report.observedAt)}`;
53
+ const activity = "lastActivityAt" in row && row.lastActivityAt !== null
54
+ ? [`activity ${formatAge(row.lastActivityAt, report.observedAt)}`]
55
+ : [];
56
+ const key = row.life === "stranded" && "strandedReason" in row && row.strandedReason === "resume-unsupported"
57
+ ? [life, ...activity, "resume unsupported"]
58
+ : [life, ...activity];
59
+ const relation = row.contract === undefined ? ["unbound"] : [endpointFact(row.contract.id, row.contract.observed)];
60
+ const snapshot = activitySnapshotLine(row);
61
+ const aliases = akumaLabel(row);
62
+ if (context.columns > NARROW_COLUMNS) {
63
+ const lines = [
64
+ identityLine(akumaMark(row.life), row.id, `${aliases} · ${[...key, ...relation].join(" · ")}`.trim()),
65
+ ];
66
+ return snapshot === undefined
67
+ ? lines
68
+ : [...lines, ...plumbFacts([boundedActivity(snapshot, context.columns, PLUMB)], context.columns)];
69
+ }
70
+ const identity = aliases.length === 0 ? row.id : `${row.id} ${aliases}`;
71
+ const lines = entityLines({
72
+ mark: akumaMark(row.life),
73
+ identity,
74
+ state: key[0],
75
+ title: "",
76
+ facts: [...key.slice(1), ...relation],
77
+ context,
78
+ });
79
+ return snapshot === undefined
80
+ ? lines
81
+ : [...lines, ...plumbFacts([boundedActivity(snapshot, context.columns, PLUMB)], context.columns)];
82
+ });
83
+ const header = `AKUMA // ${rows.length} recent · ${section.value.rows.length} known`;
84
+ const rendered = renderSectionBlock({
85
+ name: "AKUMA",
86
+ unit: "akuma",
87
+ selector: "aku",
88
+ continuation: 'keiyaku ls "aku/*/*"',
89
+ rows: rowLines,
90
+ total: section.value.rows.length,
91
+ neutral: true,
92
+ });
93
+ return [header, ...rendered.slice(1)];
94
+ }
95
+ function formatAge(source, observedAt) {
96
+ if (source === null || source === undefined)
97
+ return "—";
98
+ const sourceMs = Date.parse(source);
99
+ const observedMs = Date.parse(observedAt);
100
+ if (sourceMs > observedMs)
101
+ return "now";
102
+ const seconds = Math.floor((observedMs - sourceMs) / 1_000);
103
+ if (seconds < 60)
104
+ return `${seconds}s`;
105
+ const minutes = Math.floor(seconds / 60);
106
+ if (minutes < 60)
107
+ return `${minutes}m`;
108
+ const hours = Math.floor(minutes / 60);
109
+ return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;
110
+ }
111
+ export { akumaMark, endpointFact, formatAge, NARROW_COLUMNS, renderAkuma };