@astrosheep/keiyaku 2.9.9 → 2.9.11

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 (230) hide show
  1. package/README.md +93 -174
  2. package/build/.tsbuildinfo +1 -1
  3. package/build/agents/harness/control-types.js +18 -1
  4. package/build/agents/harness/index.js +2 -0
  5. package/build/agents/harness/outcome-error.js +81 -0
  6. package/build/agents/harness/projection.js +2 -1
  7. package/build/agents/harness/router.js +5 -1
  8. package/build/agents/providers/claude-agent-sdk/adapter.js +18 -4
  9. package/build/agents/providers/claude-agent-sdk/registration.js +11 -1
  10. package/build/agents/providers/claude-agent-sdk/session.js +19 -5
  11. package/build/agents/providers/codex-app-server/adapter.js +11 -6
  12. package/build/agents/providers/codex-app-server/events.js +67 -6
  13. package/build/agents/providers/codex-app-server/registration.js +11 -1
  14. package/build/agents/providers/opencode-sdk/adapter.js +8 -1
  15. package/build/agents/providers/opencode-sdk/events.js +24 -2
  16. package/build/agents/providers/opencode-sdk/registration.js +11 -1
  17. package/build/agents/providers/pi/checkpoint.js +9 -1
  18. package/build/agents/providers/pi/events.js +2 -0
  19. package/build/agents/providers/pi/registration.js +14 -1
  20. package/build/cli/commands/akuma/akuma/handler.js +1 -1
  21. package/build/cli/commands/akuma/akuma/meta.js +3 -3
  22. package/build/cli/commands/akuma/catalog.js +2 -2
  23. package/build/cli/commands/akuma/{view → show}/handler.js +5 -5
  24. package/build/cli/commands/akuma/{view → show}/meta.js +3 -3
  25. package/build/cli/commands/akuma.js +1 -1
  26. package/build/cli/commands/contract/amend/handler.js +5 -4
  27. package/build/cli/commands/contract/arc/handler.js +5 -4
  28. package/build/cli/commands/contract/audit/handler.js +2 -2
  29. package/build/cli/commands/contract/bind/handler.js +12 -3
  30. package/build/cli/commands/contract/bind/meta.js +45 -15
  31. package/build/cli/commands/contract/forfeit/handler.js +9 -5
  32. package/build/cli/commands/contract/log/handler.js +2 -2
  33. package/build/cli/commands/contract/petition/handler.js +34 -7
  34. package/build/cli/commands/contract/renew/handler.js +7 -7
  35. package/build/cli/commands/contract/renew/meta.js +3 -3
  36. package/build/cli/commands/metadata.js +10 -6
  37. package/build/cli/commands/projection/call/meta.js +1 -1
  38. package/build/cli/commands/projection/catalog.js +2 -0
  39. package/build/cli/commands/projection/history/handler.js +21 -0
  40. package/build/cli/commands/projection/history/meta.js +9 -0
  41. package/build/cli/commands/projection/shared.js +3 -4
  42. package/build/cli/commands/projection/status/handler.js +3 -3
  43. package/build/cli/commands/projection/wait/handler.js +20 -11
  44. package/build/cli/commands/task/add/handler.js +14 -5
  45. package/build/cli/commands/task/add/meta.js +2 -2
  46. package/build/cli/commands/task/catalog.js +4 -0
  47. package/build/cli/commands/task/done/handler.js +1 -4
  48. package/build/cli/commands/task/done/meta.js +1 -1
  49. package/build/cli/commands/task/drop/meta.js +1 -1
  50. package/build/cli/commands/task/hold/handler.js +3 -0
  51. package/build/cli/commands/task/hold/meta.js +8 -0
  52. package/build/cli/commands/task/log/handler.js +1 -1
  53. package/build/cli/commands/task/log/meta.js +2 -2
  54. package/build/cli/commands/task/resume/handler.js +3 -0
  55. package/build/cli/commands/task/resume/meta.js +8 -0
  56. package/build/cli/commands/task/shared.js +39 -14
  57. package/build/cli/commands/task/show/handler.js +1 -1
  58. package/build/cli/commands/task/show/meta.js +1 -1
  59. package/build/cli/commands/task/start/meta.js +1 -1
  60. package/build/cli/commands/task/stop/handler.js +1 -4
  61. package/build/cli/commands/task/stop/meta.js +1 -1
  62. package/build/cli/commands/task/update/handler.js +11 -3
  63. package/build/cli/commands/task/update/meta.js +3 -3
  64. package/build/cli/completion.js +3 -2
  65. package/build/cli/flags.js +51 -14
  66. package/build/cli/help.js +4 -1
  67. package/build/cli/index.js +40 -25
  68. package/build/cli/parse-flags.js +40 -7
  69. package/build/cli/parse-metadata.js +5 -2
  70. package/build/cli/parse-selectors.js +2 -3
  71. package/build/cli/parse.js +40 -6
  72. package/build/cli/projection-address.js +12 -10
  73. package/build/cli/render/amendment-warning.js +8 -0
  74. package/build/cli/render/arc.js +6 -2
  75. package/build/cli/render/audit.js +400 -81
  76. package/build/cli/render/kanshi.js +6 -1
  77. package/build/cli/render/lifecycle.js +56 -0
  78. package/build/cli/render/misc.js +24 -28
  79. package/build/cli/render/petition.js +5 -0
  80. package/build/cli/render/projection-activity.js +3 -2
  81. package/build/cli/render/projection-history.js +64 -0
  82. package/build/cli/render/shared.js +23 -9
  83. package/build/cli/render/status.js +9 -16
  84. package/build/cli/render/task.js +51 -26
  85. package/build/cli/render/terminal-failure.js +3 -1
  86. package/build/cli/render/wait.js +3 -5
  87. package/build/cli/subagent-guard.js +1 -1
  88. package/build/cli/types.js +1 -1
  89. package/build/config/env-keys.js +2 -0
  90. package/build/config/env.js +23 -0
  91. package/build/config/settings/schema.js +3 -1
  92. package/build/core/address-carrier.js +89 -0
  93. package/build/core/addressing.js +255 -196
  94. package/build/core/amend.js +115 -38
  95. package/build/core/amendment-criteria.js +17 -0
  96. package/build/core/amendment-warning.js +10 -0
  97. package/build/core/arc.js +184 -83
  98. package/build/core/audit/candidate.js +110 -9
  99. package/build/core/audit/coordinates.js +120 -65
  100. package/build/core/audit/evidence.js +19 -23
  101. package/build/core/audit/facade.js +34 -11
  102. package/build/core/audit/report.js +5 -5
  103. package/build/core/bind-reconciliation.js +390 -0
  104. package/build/core/bind-workspace.js +12 -20
  105. package/build/core/bind.js +242 -273
  106. package/build/core/call/call.js +1 -0
  107. package/build/core/call/context.js +46 -71
  108. package/build/core/call/prompt.js +6 -3
  109. package/build/core/context.js +49 -35
  110. package/build/core/contract-carrier-runtime.js +408 -0
  111. package/build/core/contract-carrier.js +270 -0
  112. package/build/core/contract-view.js +33 -27
  113. package/build/core/contract.js +5 -1
  114. package/build/core/derived-replay.js +207 -0
  115. package/build/core/draft.js +125 -57
  116. package/build/core/forfeit.js +113 -56
  117. package/build/core/identifier-slug.js +63 -13
  118. package/build/core/ids.js +4 -4
  119. package/build/core/lifecycle-history.js +35 -0
  120. package/build/core/lifecycle-recovery.js +117 -0
  121. package/build/core/lifecycle-runner.js +377 -0
  122. package/build/core/log.js +37 -11
  123. package/build/core/outcome-base.js +181 -0
  124. package/build/core/process-group.js +139 -0
  125. package/build/core/projection/generation/database.js +82 -7
  126. package/build/core/projection/generation/model.js +9 -36
  127. package/build/core/projection/generation/projection-generation-continuation.js +10 -22
  128. package/build/core/projection/generation/projection-generation-execution.js +6 -5
  129. package/build/core/projection/index.js +5 -4
  130. package/build/core/projection/projection-activity.js +27 -8
  131. package/build/core/projection/projection-alias.js +23 -10
  132. package/build/core/projection/projection-core.js +21 -7
  133. package/build/core/projection/projection-execution-observer.js +91 -39
  134. package/build/core/projection/projection-history.js +474 -0
  135. package/build/core/projection/projection-runner-lock.js +12 -0
  136. package/build/core/projection/projection-status-observation.js +365 -0
  137. package/build/core/projection/projection-status.js +21 -358
  138. package/build/core/projection/projection-terminal-failure.js +13 -8
  139. package/build/core/projection/projection-wait.js +7 -2
  140. package/build/core/projection/tell/launch-store.js +244 -0
  141. package/build/core/projection/tell/model.js +3 -3
  142. package/build/core/projection/tell/store.js +70 -118
  143. package/build/core/registry.js +22 -87
  144. package/build/core/renew-build.js +424 -0
  145. package/build/core/renew-plan.js +239 -0
  146. package/build/core/renew-rewrite.js +77 -0
  147. package/build/core/renew.js +295 -520
  148. package/build/core/repository-ledger/accepted-fold-read.js +19 -0
  149. package/build/core/repository-ledger/accepted-tail.js +116 -0
  150. package/build/core/repository-ledger/admission.js +38 -0
  151. package/build/core/repository-ledger/authoritative-transaction.js +1 -0
  152. package/build/core/repository-ledger/claim-evidence.js +147 -0
  153. package/build/core/repository-ledger/codec.js +297 -0
  154. package/build/core/repository-ledger/current-state-store.js +853 -0
  155. package/build/core/repository-ledger/fold-repository.js +375 -0
  156. package/build/core/repository-ledger/fold.js +248 -0
  157. package/build/core/repository-ledger/git-object-store.js +243 -0
  158. package/build/core/repository-ledger/history-read.js +15 -0
  159. package/build/core/repository-ledger/incremental-read.js +153 -0
  160. package/build/core/repository-ledger/index.js +15 -0
  161. package/build/core/repository-ledger/inventory-plan.js +75 -0
  162. package/build/core/repository-ledger/inventory.js +310 -0
  163. package/build/core/repository-ledger/publication-admission.js +125 -0
  164. package/build/core/repository-ledger/publication.js +353 -0
  165. package/build/core/repository-ledger/read-model.js +469 -0
  166. package/build/core/repository-ledger/transaction-membership.js +78 -0
  167. package/build/core/repository-ledger/traversal.js +404 -0
  168. package/build/core/repository-ledger/write-transaction.js +339 -0
  169. package/build/core/seal.js +168 -161
  170. package/build/core/settlement/claim-delivery.js +42 -215
  171. package/build/core/settlement/claim.js +235 -153
  172. package/build/core/settlement/index.js +4 -4
  173. package/build/core/settlement/petition-claim-gates.js +52 -33
  174. package/build/core/settlement/petition-forfeit.js +12 -5
  175. package/build/core/settlement/petition-head-guard.js +8 -5
  176. package/build/core/settlement/petition-preview.js +68 -56
  177. package/build/core/settlement/petition-window.js +50 -0
  178. package/build/core/settlement/petition.js +252 -131
  179. package/build/core/settlement/queue-read-model.js +72 -95
  180. package/build/core/settlement/queue-seat-allocation.js +35 -126
  181. package/build/core/settlement/queue.js +1 -1
  182. package/build/core/settlement/settlement.js +172 -80
  183. package/build/core/settlement/verdict.js +112 -66
  184. package/build/core/settlement/verification-coordination.js +305 -0
  185. package/build/core/settlement/verification-supervisor.js +275 -0
  186. package/build/core/settlement/verification.js +398 -31
  187. package/build/core/status/board.js +114 -119
  188. package/build/core/status/lifecycle.js +7 -80
  189. package/build/core/structured-query.js +23 -0
  190. package/build/core/target-ref.js +1 -1
  191. package/build/core/task/board.js +59 -24
  192. package/build/core/task/commands.js +181 -33
  193. package/build/core/task/coordinate.js +56 -0
  194. package/build/core/task/document.js +25 -9
  195. package/build/core/task/index.js +7 -4
  196. package/build/core/task/query.js +17 -27
  197. package/build/core/task/settlement-git.js +164 -179
  198. package/build/core/task/settlement-policy.js +15 -11
  199. package/build/core/task/source-board.js +31 -13
  200. package/build/core/task/task-bind-preparation.js +193 -0
  201. package/build/core/task/task-contract.js +102 -193
  202. package/build/core/task/task-file-transaction.js +171 -0
  203. package/build/core/task/task-git-runtime.js +76 -14
  204. package/build/core/task/task-git-store.js +68 -169
  205. package/build/core/task/task-store-repository.js +13 -6
  206. package/build/core/task/task-worktree.js +6 -33
  207. package/build/core/task/task.js +1 -1
  208. package/build/core/task/tree.js +3 -3
  209. package/build/core/task/validation.js +4 -3
  210. package/build/core/transcripts.js +93 -1
  211. package/build/core/worktree-bootstrap.js +44 -36
  212. package/build/core/worktree-path.js +210 -77
  213. package/build/flow-error.js +7 -7
  214. package/build/generated/version.js +2 -2
  215. package/build/git/core.js +76 -13
  216. package/build/git/refs.js +168 -46
  217. package/build/git/streaming-batch.js +73 -13
  218. package/package.json +1 -1
  219. package/skills/keiyaku/SKILL.md +1 -1
  220. package/skills/keiyaku-akuma/SKILL.md +3 -3
  221. package/skills/keiyaku-task/SKILL.md +4 -2
  222. package/skills/keiyaku-workflow/SKILL.md +88 -203
  223. package/build/core/entry.js +0 -305
  224. package/build/core/ledger-batch.js +0 -194
  225. package/build/core/ledger.js +0 -84
  226. package/build/core/projection/leash.js +0 -87
  227. package/build/core/ref-log.js +0 -119
  228. package/build/core/renew-session.js +0 -128
  229. package/build/core/status/ledger-batch.js +0 -1
  230. package/build/core/status/reconciliation.js +0 -137
@@ -30,9 +30,17 @@ export function createPiCheckpointController(session, options) {
30
30
  enqueue,
31
31
  control,
32
32
  setTurnStartedEmitter(emitter) { emitTurnStarted = emitter; },
33
+ beginTurn() {
34
+ const checkpoint = { fence: { kind: "ordinal", ordinal: submittedTurnOrdinal } };
35
+ options.onSyncCheckpoint?.(control, checkpoint);
36
+ },
37
+ modelInputVisible() {
38
+ // Pi's public event exposes an assistant start but no identity for the
39
+ // queued input accepted by that model call. Event order is not a receipt.
40
+ },
33
41
  completeTurn() {
34
42
  submittedTurnOrdinal += 1;
35
- const checkpoint = { fence: { kind: "ordinal", ordinal: submittedTurnOrdinal }, consumptionEvidence: true };
43
+ const checkpoint = { fence: { kind: "ordinal", ordinal: submittedTurnOrdinal } };
36
44
  if (options.onEvidence)
37
45
  emitProviderEvidence(options.onEvidence, { type: "checkpoint", provider: PI_PROVIDER, fence: checkpoint.fence, source: "notification" }, options.diagnostic());
38
46
  options.onSyncCheckpoint?.(control, checkpoint);
@@ -219,10 +219,12 @@ export function bindPiSessionEvents(session, builder, controller, state, settle)
219
219
  state.thoughtTurnOrdinal += 1;
220
220
  state.assistantMessageOrdinal = -1;
221
221
  state.activeAssistantMessageOrdinal = undefined;
222
+ controller.beginTurn();
222
223
  }
223
224
  if (event.type === "message_start") {
224
225
  const message = event.message;
225
226
  if (message?.role === "assistant") {
227
+ controller.modelInputVisible();
226
228
  state.assistantMessageOrdinal += 1;
227
229
  state.activeAssistantMessageOrdinal = state.assistantMessageOrdinal;
228
230
  }
@@ -109,7 +109,8 @@ export const piRegistration = {
109
109
  return loader ? { ...terms, loader } : terms;
110
110
  },
111
111
  nativePolicyOwnership: () => null,
112
- startLive: async ({ terms, signal, reviveTerms, onSyncCheckpoint, onSessionAdmission, onIngress }) => {
112
+ tellReceiptCapabilities: { seen: "unavailable", consumed: "unavailable" },
113
+ startLive: async ({ terms, signal, reviveTerms, onSyncCheckpoint, onSessionAdmission, onIngress, observer }) => {
113
114
  if (terms.provider !== PI_PROVIDER) {
114
115
  throw new Error(`startLive expected ${PI_PROVIDER}`);
115
116
  }
@@ -124,6 +125,12 @@ export const piRegistration = {
124
125
  sessionFile: session.sessionFile,
125
126
  appendSystemPromptOverride: piTerms.appendSystemPromptOverride,
126
127
  onSyncCheckpoint,
128
+ onTellReceipt: observer ? (receipt) => {
129
+ try {
130
+ observer.onTellReceipt(receipt);
131
+ }
132
+ catch { /* Receipt persistence cannot alter provider control. */ }
133
+ } : undefined,
127
134
  onEvidence: piTerms.onEvidence,
128
135
  onSessionAdmission,
129
136
  onIngress,
@@ -137,6 +144,12 @@ export const piRegistration = {
137
144
  signal,
138
145
  appendSystemPromptOverride: piTerms.appendSystemPromptOverride,
139
146
  onSyncCheckpoint,
147
+ onTellReceipt: observer ? (receipt) => {
148
+ try {
149
+ observer.onTellReceipt(receipt);
150
+ }
151
+ catch { /* Receipt persistence cannot alter provider control. */ }
152
+ } : undefined,
140
153
  onEvidence: piTerms.onEvidence,
141
154
  onSessionAdmission,
142
155
  onIngress,
@@ -1,4 +1,4 @@
1
1
  import { missingSubcommandError } from "../../../missing-subcommand.js";
2
2
  export const handler = async () => {
3
- throw missingSubcommandError("akuma", ["ls", "view"]);
3
+ throw missingSubcommandError("akuma", ["ls", "show"]);
4
4
  };
@@ -1,16 +1,16 @@
1
1
  export const meta = {
2
2
  command: "akuma",
3
3
  summary: "Inspect Akuma profiles",
4
- usage: ["keiyaku akuma ls|view"],
4
+ usage: ["keiyaku akuma ls|show"],
5
5
  stdin: { mode: "argument" },
6
6
  flags: [],
7
7
  purpose: "Inspect configured helper profiles.",
8
- subcommands: ["ls", "view"],
8
+ subcommands: ["ls", "show"],
9
9
  notes: [
10
10
  "Define user profiles in <KEIYAKU_HOME>/akuma/<name>.md.",
11
11
  "Define project profiles in .keiyaku/akuma/<name>.md.",
12
12
  "See README Configuration for the Markdown frontmatter format.",
13
13
  ],
14
- examples: ["keiyaku akuma ls", "keiyaku akuma view akuma-codex"],
14
+ examples: ["keiyaku akuma ls", "keiyaku akuma show akuma-codex"],
15
15
  completionRank: 6,
16
16
  };
@@ -1,8 +1,8 @@
1
1
  import { meta as akumaMeta } from "./akuma/meta.js";
2
2
  import { meta as lsMeta } from "./list/meta-ls.js";
3
- import { meta as viewMeta } from "./view/meta.js";
3
+ import { meta as showMeta } from "./show/meta.js";
4
4
  export const akumaCatalog = [
5
5
  { meta: akumaMeta, load: () => import("./akuma/handler.js") },
6
6
  { meta: lsMeta, load: () => import("./list/handler.js") },
7
- { meta: viewMeta, load: () => import("./view/handler.js") },
7
+ { meta: showMeta, load: () => import("./show/handler.js") },
8
8
  ];
@@ -7,15 +7,15 @@ import { isResponseArtifactId } from "../../../../core/response-artifact-id.js";
7
7
  import { textResponse } from "../../../render/shared.js";
8
8
  import { renderProjectionStatusSection } from "../../../render/status.js";
9
9
  import { projectDirectory } from "../../shared.js";
10
- import { renderAkumaShow, renderAkumaView } from "../../akuma.js";
10
+ import { composeAkumaDetail, renderAkumaShow } from "../../akuma.js";
11
11
  export const handler = async (_stdin, flags, _signal, positional) => {
12
12
  const [name] = positional;
13
13
  if (!name)
14
- throw new FlowError("EMPTY_PARAM", "akuma view requires an Akuma name");
14
+ throw new FlowError("EMPTY_PARAM", "akuma show requires an Akuma name");
15
15
  if (isResponseArtifactId(name)) {
16
- throw new FlowError("EMPTY_PARAM", `artifact ${name} is a response artifact; akuma view expects an Akuma profile name`);
16
+ throw new FlowError("EMPTY_PARAM", `artifact ${name} is a response artifact; akuma show expects an Akuma profile name`);
17
17
  }
18
- const cwd = await projectDirectory(flags, "akuma view");
18
+ const cwd = await projectDirectory(flags, "akuma show");
19
19
  const loaded = await loadKeiyakuSettings(cwd);
20
20
  assertSettingsKnobUsable(loaded, "agents");
21
21
  assertSettingsKnobUsable(loaded, "default");
@@ -23,5 +23,5 @@ export const handler = async (_stdin, flags, _signal, positional) => {
23
23
  const profile = renderAkumaShow(await loadAkumaCatalog(cwd), loaded.providerInstances, loaded.knobs, name).trimEnd();
24
24
  const projectionStatus = await readAkumaNonterminalProjectionStatus(cwd, Date.now(), name);
25
25
  const projections = renderProjectionStatusSection(projectionStatus).trimEnd();
26
- return textResponse(renderAkumaView(profile, projections));
26
+ return textResponse(composeAkumaDetail(profile, projections));
27
27
  };
@@ -1,7 +1,7 @@
1
1
  export const meta = {
2
- command: "akuma view",
3
- summary: "View one Akuma profile",
4
- usage: ["keiyaku akuma view NAME [-C|--cwd DIR] [--repo DIR]"],
2
+ command: "akuma show",
3
+ summary: "Show one Akuma profile",
4
+ usage: ["keiyaku akuma show NAME [-C|--cwd DIR] [--repo DIR]"],
5
5
  stdin: { mode: "argument" },
6
6
  flags: ["cwd", "repo"],
7
7
  purpose: "Read one configured helper profile and its current nonterminal projections.",
@@ -141,7 +141,7 @@ export function renderAkumaList(catalog, providerInstances, settings) {
141
141
  return lines.join("\n");
142
142
  }
143
143
  /** Compose profile inspection with an optional nonterminal projection section. */
144
- export function renderAkumaView(profile, projectionsSection) {
144
+ export function composeAkumaDetail(profile, projectionsSection) {
145
145
  return projectionsSection ? `${profile}
146
146
 
147
147
  ${projectionsSection}` : profile;
@@ -2,15 +2,16 @@ import { amendKeiyaku } from "../../../../core/amend.js";
2
2
  import { resolveExistingContractAddress } from "../../../../core/addressing.js";
3
3
  import { buildAmendInput } from "../../../../core/amend.js";
4
4
  import { buildAmendResponse } from "../../../render/arc.js";
5
- import { renderCoreResult } from "../../../render/shared.js";
5
+ import { renderLifecycleResult } from "../../../render/lifecycle.js";
6
6
  import { effectiveDirectory, repositoryDirectory } from "../../shared.js";
7
- export const handler = async (stdin, flags) => {
7
+ export const handler = async (stdin, flags, signal) => {
8
8
  const parsed = buildAmendInput(stdin, effectiveDirectory(flags), flags.contractId, flags.contractAddressSource, flags.appendScope);
9
9
  const cwd = await repositoryDirectory(flags, "amend");
10
10
  const address = await resolveExistingContractAddress(cwd, flags.contractId, flags.contractAddressSource, effectiveDirectory(flags));
11
- return renderCoreResult(amendKeiyaku({
11
+ return renderLifecycleResult(amendKeiyaku({
12
12
  ...parsed,
13
13
  cwd,
14
14
  address,
15
- }), buildAmendResponse);
15
+ signal,
16
+ }), buildAmendResponse, { cwd, address });
16
17
  };
@@ -1,15 +1,16 @@
1
1
  import { arcKeiyaku, buildArcInput } from "../../../../core/arc.js";
2
2
  import { resolveExistingContractAddress } from "../../../../core/addressing.js";
3
3
  import { buildArcResponse } from "../../../render/arc.js";
4
- import { renderCoreResult } from "../../../render/shared.js";
4
+ import { renderLifecycleResult } from "../../../render/lifecycle.js";
5
5
  import { effectiveDirectory, repositoryDirectory } from "../../shared.js";
6
- export const handler = async (stdin, flags) => {
6
+ export const handler = async (stdin, flags, signal) => {
7
7
  const parsed = buildArcInput(stdin, effectiveDirectory(flags), flags.appendScope, flags.contractId, flags.contractAddressSource);
8
8
  const cwd = await repositoryDirectory(flags, "arc");
9
9
  const address = await resolveExistingContractAddress(cwd, flags.contractId, flags.contractAddressSource, effectiveDirectory(flags));
10
- return renderCoreResult(arcKeiyaku({
10
+ return renderLifecycleResult(arcKeiyaku({
11
11
  ...parsed,
12
12
  cwd,
13
13
  address,
14
- }), buildArcResponse);
14
+ signal,
15
+ }), buildArcResponse, { cwd, address });
15
16
  };
@@ -2,12 +2,12 @@ import { auditContract } from "../../../../core/audit.js";
2
2
  import { resolveContractAddress, withResolvedAddress } from "../../../../core/addressing.js";
3
3
  import { buildAuditConstructionFailure, buildAuditResponse } from "../../../render/audit.js";
4
4
  import { effectiveDirectory, repositoryDirectory } from "../../shared.js";
5
- export const handler = async (_stdin, flags) => {
5
+ export const handler = async (_stdin, flags, signal) => {
6
6
  try {
7
7
  const cwd = await repositoryDirectory(flags, "audit");
8
8
  const address = await resolveContractAddress(cwd, flags.contractId, flags.contractAddressSource, effectiveDirectory(flags));
9
9
  return await withResolvedAddress(address, async () => {
10
- return buildAuditResponse(await auditContract({ cwd, address, diffBudgetBytes: flags.auditDiffBudgetBytes }), flags.json === true);
10
+ return buildAuditResponse(await auditContract({ cwd, address, diffBudgetBytes: flags.auditDiffBudgetBytes, signal }), flags.json === true);
11
11
  });
12
12
  }
13
13
  catch (error) {
@@ -1,10 +1,19 @@
1
- import { bindContract, previewBindContract } from "../../../../core/bind.js";
1
+ import { bindContract, previewBindContract, reconcileBindContract } from "../../../../core/bind.js";
2
2
  import { defaultActorClock } from "../../../../core/outcome-base.js";
3
3
  import { writeDraftArtifact } from "../../../draft-artifact.js";
4
- import { buildBindDraftResponse, buildBindPreviewResponse, buildBindResponse } from "../../../render/shared.js";
4
+ import { buildBindDraftResponse, buildBindOutcomeResponse, buildBindPreviewResponse } from "../../../render/shared.js";
5
5
  import { repositoryDirectory } from "../../shared.js";
6
6
  export const handler = async (stdin, flags, signal) => {
7
7
  const cwd = await repositoryDirectory(flags, "bind");
8
+ if (flags.contractId !== undefined) {
9
+ return buildBindOutcomeResponse(await reconcileBindContract({
10
+ cwd,
11
+ contractId: flags.contractId,
12
+ ...defaultActorClock(),
13
+ signal,
14
+ onProgress: (line) => { process.stdout.write(`${line}\n`); },
15
+ }), cwd);
16
+ }
8
17
  if (flags.dryRun) {
9
18
  const preview = await previewBindContract({
10
19
  cwd, draft: stdin, ...defaultActorClock(), workspace: "worktree",
@@ -26,5 +35,5 @@ export const handler = async (stdin, flags, signal) => {
26
35
  process.stdout.write(`${line}\n`);
27
36
  },
28
37
  });
29
- return buildBindResponse(result, cwd);
38
+ return buildBindOutcomeResponse(result, cwd);
30
39
  };
@@ -2,63 +2,93 @@ export const meta = {
2
2
  command: "bind",
3
3
  summary: "Create a contract ledger and workspace files",
4
4
  usage: [
5
+ "keiyaku @<full-contract-id> bind [-C|--cwd DIR] [--repo DIR]",
6
+ "keiyaku bind --contract <full-contract-id> [-C|--cwd DIR] [--repo DIR]",
5
7
  "keiyaku bind [-C|--cwd DIR] [--repo DIR] [--task ID]... [- < contract.md]",
6
- "keiyaku bind [-C|--cwd DIR] [--repo DIR] [--task ID]... --place NAME --objective TEXT --scope GLOB --checks CHECK [--dry-run]",
8
+ "keiyaku bind [-C|--cwd DIR] [--repo DIR] [--task ID]... --title TEXT --context TEXT --objective TEXT --design TEXT --scope GLOB --criteria CRITERION [--verification DECLARATION] [--dry-run]",
7
9
  ],
8
10
  stdin: { mode: "document", selector: { kind: "positional", index: 0, required: false, rejectBlank: false } },
9
- flags: ["cwd", "repo", "after", "exclusive", "draft-only", "place", "objective", "scope", "checks", "task", "dry-run"],
10
- // contract is parseable only so the mouth can reject it with bind-specific copy.
11
- parseFlags: ["cwd", "repo", "contract", "after", "exclusive", "draft-only", "place", "objective", "scope", "checks", "task", "dry-run"],
11
+ flags: ["cwd", "repo", "contract", "after", "exclusive", "draft-only", "title", "context", "objective", "design", "scope", "criteria", "verification", "task", "dry-run"],
12
+ // contract and place are parseable only so the mouth can reject them with bind-specific copy.
13
+ parseFlags: ["cwd", "repo", "contract", "after", "exclusive", "draft-only", "place", "title", "context", "objective", "design", "scope", "criteria", "verification", "task", "dry-run"],
12
14
  purpose: "Bind a Keiyaku from contract Markdown selected by literal -.",
13
15
  input: [
14
- "# <name>",
16
+ "# <title>",
17
+ "",
18
+ "## Context",
19
+ "<established facts and constraints>",
15
20
  "",
16
21
  "## Objective",
17
22
  "<what the commission should accomplish>",
18
23
  "",
24
+ "## Design",
25
+ "<settled blueprint>",
26
+ "",
19
27
  "## Scope",
20
28
  "~~~",
21
29
  "<pattern>",
22
30
  "<another-pattern>",
23
31
  "~~~",
24
32
  "",
25
- "## Checks",
26
- "- <verification>",
33
+ "## Criteria",
34
+ "- <declarative acceptance criterion>",
35
+ "",
36
+ "## Verification",
37
+ "- <executable declaration>",
27
38
  ],
28
39
  notes: [
29
- "bind creates a contract and does not accept @addr or --contract.",
40
+ "Bare bind creates a distinct contract. Addressed bind accepts only a full contract ID and replays its committed derived surfaces.",
30
41
  "Primary document form is literal - followed by Markdown on stdin (full document below).",
31
- "With --task, title and body supply name/objective defaults; literal - may send only the missing sections and any present section overrides the task default.",
32
- "Domain flags remain available as a full-document alternative; they cannot mix with Markdown selected by literal -.",
42
+ "With --task, task title and body supply title/objective defaults; literal - or domain flags may send only the missing sections and any present section overrides the task default.",
43
+ "Domain flags remain available as a partial-document alternative; they cannot mix with Markdown selected by literal -.",
44
+ "Verification is optional; omit it when the contract has no executable testimony declarations.",
33
45
  ],
34
46
  examples: [
35
47
  [
36
48
  "keiyaku bind - <<'KEIYAKU'",
37
- "# <name>",
49
+ "# <title>",
50
+ "",
51
+ "## Context",
52
+ "<established facts and constraints>",
38
53
  "",
39
54
  "## Objective",
40
55
  "<what the commission should accomplish>",
41
56
  "",
57
+ "## Design",
58
+ "<settled blueprint>",
59
+ "",
42
60
  "## Scope",
43
61
  "~~~",
44
62
  "<pattern>",
45
63
  "<another-pattern>",
46
64
  "~~~",
47
65
  "",
48
- "## Checks",
49
- "- <verification>",
66
+ "## Criteria",
67
+ "- <declarative acceptance criterion>",
68
+ "",
69
+ "## Verification",
70
+ "- <executable declaration>",
50
71
  "KEIYAKU",
51
72
  ].join("\n"),
52
73
  [
53
74
  "keiyaku bind --task fix-flaky-pump - <<'KEIYAKU'",
75
+ "## Context",
76
+ "<established facts and constraints>",
77
+ "",
78
+ "## Design",
79
+ "<settled blueprint>",
80
+ "",
54
81
  "## Scope",
55
82
  "~~~",
56
83
  "<pattern>",
57
84
  "<another-pattern>",
58
85
  "~~~",
59
86
  "",
60
- "## Checks",
61
- "- <verification>",
87
+ "## Criteria",
88
+ "- <declarative acceptance criterion>",
89
+ "",
90
+ "## Verification",
91
+ "- <executable declaration>",
62
92
  "KEIYAKU",
63
93
  ].join("\n"),
64
94
  ],
@@ -2,12 +2,16 @@ import { resolveExistingContractAddress, withResolvedAddress } from "../../../..
2
2
  import { defaultActorClock } from "../../../../core/outcome-base.js";
3
3
  import { forfeitContractCommand } from "../../../../core/forfeit.js";
4
4
  import { buildForfeitResponse } from "../../../render/shared.js";
5
+ import { buildLifecycleOutcomeResponse } from "../../../render/lifecycle.js";
6
+ import { isCompleteLifecycleOutcome } from "../../../../core/outcome-base.js";
5
7
  import { effectiveDirectory, repositoryDirectory } from "../../shared.js";
6
- export const handler = async (_stdin, flags) => {
8
+ export const handler = async (_stdin, flags, signal) => {
7
9
  const cwd = await repositoryDirectory(flags, "forfeit");
8
10
  const address = await resolveExistingContractAddress(cwd, flags.contractId, flags.contractAddressSource, effectiveDirectory(flags));
9
- return await withResolvedAddress(address, async () => buildForfeitResponse({
10
- ...await forfeitContractCommand({ cwd, contractId: address.binding.commissionId, ...defaultActorClock(), note: flags.reason }),
11
- address,
12
- }));
11
+ return await withResolvedAddress(address, async () => {
12
+ const result = await forfeitContractCommand({ cwd, contractId: address.binding.commissionId, ...defaultActorClock(), note: flags.reason, signal });
13
+ if (!isCompleteLifecycleOutcome(result))
14
+ return buildLifecycleOutcomeResponse(result, { cwd, address });
15
+ return buildForfeitResponse({ ...result, address, cleanup: result.cleanup });
16
+ });
13
17
  };
@@ -2,11 +2,11 @@ import { resolveExistingContractAddress, withResolvedAddress } from "../../../..
2
2
  import { readContractLog } from "../../../../core/log.js";
3
3
  import { buildLogResponse } from "../../../render/misc.js";
4
4
  import { effectiveDirectory, repositoryDirectory } from "../../shared.js";
5
- export const handler = async (_stdin, flags) => {
5
+ export const handler = async (_stdin, flags, signal) => {
6
6
  const cwd = await repositoryDirectory(flags, "log");
7
7
  const address = await resolveExistingContractAddress(cwd, flags.contractId, flags.contractAddressSource, effectiveDirectory(flags));
8
8
  return await withResolvedAddress(address, async () => {
9
- const result = await readContractLog({ cwd, contractId: address.binding.commissionId });
9
+ const result = await readContractLog({ cwd, contractId: address.binding.commissionId, signal });
10
10
  return buildLogResponse({ ...result, address });
11
11
  });
12
12
  };
@@ -1,9 +1,11 @@
1
1
  import { FlowError } from "../../../../flow-error.js";
2
2
  import { resolveExistingContractAddress, withResolvedAddress } from "../../../../core/addressing.js";
3
- import { buildPetitionClaimInput, petitionKeiyaku, previewPetition, } from "../../../../core/settlement/index.js";
3
+ import { buildPetitionClaimInput, petitionKeiyaku, previewPetition, reconcilePetitionRetry, } from "../../../../core/settlement/index.js";
4
4
  import { renewKeiyaku } from "../../../../core/renew.js";
5
- import { buildPetitionClaimResponse, buildPetitionPreviewResponse, renderPetitionRenewedConsequence, } from "../../../render/petition.js";
5
+ import { buildPetitionClaimResponse, buildPetitionPreviewResponse, renderPetitionRetryConsequence, renderPetitionRenewedConsequence, } from "../../../render/petition.js";
6
6
  import { writeCliOutput } from "../../../output-stream-error-policy.js";
7
+ import { buildLifecycleOutcomeResponse } from "../../../render/lifecycle.js";
8
+ import { isCompleteLifecycleOutcome } from "../../../../core/outcome-base.js";
7
9
  import { effectiveDirectory, repositoryDirectory } from "../../shared.js";
8
10
  export const handler = async (stdin, flags, signal) => {
9
11
  if (flags.json && !flags.dryRun) {
@@ -21,16 +23,41 @@ export const handler = async (stdin, flags, signal) => {
21
23
  cwd,
22
24
  contractId: address.binding.commissionId,
23
25
  oath: input.oath,
26
+ signal,
24
27
  }), flags.json === true);
25
28
  }
26
- const renewed = flags.renewBeforePetition
27
- ? await renewKeiyaku({ cwd, address, appendScope: flags.appendScope })
29
+ const retry = await reconcilePetitionRetry({
30
+ cwd,
31
+ contractId: address.binding.commissionId,
32
+ signal,
33
+ });
34
+ if (retry.status === "verdict") {
35
+ if (!isCompleteLifecycleOutcome(retry.verdict)) {
36
+ return buildLifecycleOutcomeResponse(retry.verdict, { cwd, address });
37
+ }
38
+ if (retry.result === "rejected") {
39
+ await writeCliOutput(process.stdout, `${renderPetitionRetryConsequence(retry.reason)}\n`);
40
+ }
41
+ }
42
+ const resumesApprovedClaim = retry.status === "approved-awaiting-claim"
43
+ || (retry.status === "verdict" && retry.result === "approved");
44
+ const renewed = flags.renewBeforePetition && !resumesApprovedClaim
45
+ ? await renewKeiyaku({ cwd, address, appendScope: flags.appendScope, signal })
28
46
  : undefined;
29
- if (renewed && !renewed.alreadyFresh) {
47
+ const alreadyFresh = renewed?.family === "refused-before-effects"
48
+ && renewed.failedInvariant.code === "NO_LIFECYCLE_CHANGE";
49
+ if (renewed && renewed.family !== "committed" && !alreadyFresh)
50
+ return buildLifecycleOutcomeResponse(renewed, { cwd, address });
51
+ if (renewed && renewed.family === "committed" && !isCompleteLifecycleOutcome(renewed))
52
+ return buildLifecycleOutcomeResponse(renewed, { cwd, address });
53
+ if (renewed && isCompleteLifecycleOutcome(renewed) && !renewed.alreadyFresh) {
30
54
  await writeCliOutput(process.stdout, `${renderPetitionRenewedConsequence(renewed)}\n`);
31
55
  }
32
56
  const input = buildPetitionClaimInput({ cwd, contractId: address.binding.commissionId, stdin, signal, appendScope: flags.appendScope });
33
- const petitionInput = renewed ? { ...input, appendScope: undefined } : input;
34
- return buildPetitionClaimResponse({ ...await petitionKeiyaku(petitionInput), address }, input);
57
+ const petitionInput = renewed && isCompleteLifecycleOutcome(renewed) ? { ...input, appendScope: undefined } : input;
58
+ const result = await petitionKeiyaku(petitionInput);
59
+ return isCompleteLifecycleOutcome(result) && "status" in result
60
+ ? buildPetitionClaimResponse({ ...result, address }, input)
61
+ : buildLifecycleOutcomeResponse(result, { cwd, address });
35
62
  });
36
63
  };
@@ -1,24 +1,24 @@
1
1
  import { resolveContractAddress, resolveExistingContractAddress } from "../../../../core/addressing.js";
2
2
  import { abortRenewKeiyaku, continueRenewKeiyaku, renewKeiyaku } from "../../../../core/renew.js";
3
3
  import { buildRenewAbortResponse, buildRenewResponse } from "../../../render/arc.js";
4
- import { renderCoreResult } from "../../../render/shared.js";
4
+ import { renderLifecycleResult } from "../../../render/lifecycle.js";
5
5
  import { effectiveDirectory, repositoryDirectory } from "../../shared.js";
6
- export const handler = async (_stdin, flags) => {
6
+ export const handler = async (_stdin, flags, signal) => {
7
7
  const cwd = await repositoryDirectory(flags, "renew");
8
8
  const resolveAddress = flags.renewContinue || flags.renewAbort
9
9
  ? resolveContractAddress
10
10
  : resolveExistingContractAddress;
11
11
  const address = await resolveAddress(cwd, flags.contractId, flags.contractAddressSource, effectiveDirectory(flags));
12
12
  if (flags.renewContinue) {
13
- return renderCoreResult(continueRenewKeiyaku({ cwd, address, appendScope: flags.appendScope }), buildRenewResponse);
13
+ return renderLifecycleResult(continueRenewKeiyaku({ cwd, address, appendScope: flags.appendScope, signal }), buildRenewResponse, { cwd, address });
14
14
  }
15
15
  if (flags.renewAbort) {
16
- return renderCoreResult(abortRenewKeiyaku({ cwd, address }), buildRenewAbortResponse);
16
+ return renderLifecycleResult(abortRenewKeiyaku({ cwd, address, signal }), buildRenewAbortResponse, { cwd, address });
17
17
  }
18
- return renderCoreResult(renewKeiyaku({
18
+ return renderLifecycleResult(renewKeiyaku({
19
19
  cwd,
20
20
  address,
21
21
  appendScope: flags.appendScope,
22
- resolveConflicts: flags.renewResolve,
23
- }), buildRenewResponse);
22
+ signal,
23
+ }), buildRenewResponse, { cwd, address });
24
24
  };
@@ -2,17 +2,17 @@ export const meta = {
2
2
  command: "renew",
3
3
  summary: "Rewrite delivery onto the current base",
4
4
  usage: [
5
- "keiyaku renew [-C|--cwd DIR] [--repo DIR] [--contract ADDR] [--append-scope PATTERN] [--resolve]",
5
+ "keiyaku renew [-C|--cwd DIR] [--repo DIR] [--contract ADDR] [--append-scope PATTERN]",
6
6
  "keiyaku @<id> renew --continue [--append-scope PATTERN]",
7
7
  "keiyaku @<id> renew --abort",
8
8
  ],
9
9
  stdin: { mode: "argument" },
10
- flags: ["cwd", "repo", "contract", "append-scope", "resolve", "continue", "abort"],
10
+ flags: ["cwd", "repo", "contract", "append-scope", "continue", "abort"],
11
11
  purpose: "Capture receipts, rewrite delivery onto the default branch, then seal the current a0 or open explicit arc and record the renewal.",
12
12
  notes: [
13
13
  "After an explicit arc closes, refuses loose commits until another arc is open.",
14
14
  "Refuses while an Akuma is in flight.",
15
- "Ordinary conflicts restore the delivery branch and worktree without ledger writes; --resolve opens an owned session for --continue or --abort.",
15
+ "Conflicts create derived scratch without changing the ledger, delivery branch, or worktree; resolve that scratch with --continue or discard it with --abort.",
16
16
  ],
17
17
  completionRank: 9,
18
18
  };
@@ -8,7 +8,7 @@ import { meta as killMeta } from "./projection/kill/meta.js";
8
8
  import { meta as logMeta } from "./contract/log/meta.js";
9
9
  import { meta as akumaMeta } from "./akuma/akuma/meta.js";
10
10
  import { meta as akumaLsMeta } from "./akuma/list/meta-ls.js";
11
- import { meta as akumaViewMeta } from "./akuma/view/meta.js";
11
+ import { meta as akumaShowMeta } from "./akuma/show/meta.js";
12
12
  import { meta as skillsMeta } from "./skills/skills/meta.js";
13
13
  import { meta as skillsInstallMeta } from "./skills/install/meta.js";
14
14
  import { meta as amendMeta } from "./contract/amend/meta.js";
@@ -19,6 +19,7 @@ import { meta as forfeitMeta } from "./contract/forfeit/meta.js";
19
19
  import { meta as guideMeta } from "./system/guide/meta.js";
20
20
  import { meta as completionMeta } from "./system/completion/meta.js";
21
21
  import { meta as statusMeta } from "./projection/status/meta.js";
22
+ import { meta as historyMeta } from "./projection/history/meta.js";
22
23
  import { meta as taskMeta } from "./task/task/meta.js";
23
24
  import { meta as taskAddMeta } from "./task/add/meta.js";
24
25
  import { meta as taskShowMeta } from "./task/show/meta.js";
@@ -26,6 +27,8 @@ import { meta as taskLsMeta } from "./task/ls/meta.js";
26
27
  import { meta as taskLogMeta } from "./task/log/meta.js";
27
28
  import { meta as taskStartMeta } from "./task/start/meta.js";
28
29
  import { meta as taskStopMeta } from "./task/stop/meta.js";
30
+ import { meta as taskHoldMeta } from "./task/hold/meta.js";
31
+ import { meta as taskResumeMeta } from "./task/resume/meta.js";
29
32
  import { meta as taskDoneMeta } from "./task/done/meta.js";
30
33
  import { meta as taskDropMeta } from "./task/drop/meta.js";
31
34
  import { meta as taskUpdateMeta } from "./task/update/meta.js";
@@ -33,16 +36,17 @@ import { meta as taskDoctorMeta } from "./task/doctor/meta.js";
33
36
  import { meta as dumpEnvMeta } from "./system/dump-env/meta.js";
34
37
  export const COMMAND_METADATA_ORDER = [
35
38
  "bind", "arc", "call", "revive", "wait", "tell", "kill", "log",
36
- "akuma", "akuma ls", "akuma view", "skills", "skills install", "amend", "audit",
37
- "renew", "petition", "forfeit", "guide", "completion", "status", "task",
38
- "task add", "task show", "task ls", "task log", "task start", "task stop", "task done",
39
+ "akuma", "akuma ls", "akuma show", "skills", "skills install", "amend", "audit",
40
+ "renew", "petition", "forfeit", "guide", "completion", "status", "history", "task",
41
+ "task add", "task show", "task ls", "task log", "task start", "task stop", "task hold", "task resume", "task done",
39
42
  "task drop", "task update", "task doctor", "dump-env",
40
43
  ];
41
44
  const COMMAND_METADATA = [
42
45
  bindMeta, arcMeta, callMeta, reviveMeta, waitMeta, tellMeta, killMeta, logMeta,
43
- akumaMeta, akumaLsMeta, akumaViewMeta, skillsMeta, skillsInstallMeta, amendMeta, auditMeta,
44
- renewMeta, petitionMeta, forfeitMeta, guideMeta, completionMeta, statusMeta,
46
+ akumaMeta, akumaLsMeta, akumaShowMeta, skillsMeta, skillsInstallMeta, amendMeta, auditMeta,
47
+ renewMeta, petitionMeta, forfeitMeta, guideMeta, completionMeta, statusMeta, historyMeta,
45
48
  taskMeta, taskAddMeta, taskShowMeta, taskLsMeta, taskLogMeta, taskStartMeta, taskStopMeta,
49
+ taskHoldMeta, taskResumeMeta,
46
50
  taskDoneMeta, taskDropMeta, taskUpdateMeta, taskDoctorMeta, dumpEnvMeta,
47
51
  ];
48
52
  export const CLI_COMMAND_METADATA = Object.fromEntries(COMMAND_METADATA.map((meta) => [meta.command, meta]));
@@ -1,7 +1,7 @@
1
1
  export const meta = {
2
2
  command: "call",
3
3
  summary: "Start an Akuma helper session",
4
- usage: ["keiyaku call NAME [--wait DURATION] <BODY|->"],
4
+ usage: ["keiyaku call NAME [-d|--detach] [--wait DURATION] <BODY|->"],
5
5
  stdin: {
6
6
  mode: "argument",
7
7
  selector: { kind: "positional", index: 0, required: true, rejectBlank: true },
@@ -4,6 +4,7 @@ import { meta as waitMeta } from "./wait/meta.js";
4
4
  import { meta as tellMeta } from "./tell/meta.js";
5
5
  import { meta as killMeta } from "./kill/meta.js";
6
6
  import { meta as statusMeta } from "./status/meta.js";
7
+ import { meta as historyMeta } from "./history/meta.js";
7
8
  export const projectionCatalog = [
8
9
  { meta: callMeta, load: () => import("./call/handler.js") },
9
10
  { meta: reviveMeta, load: () => import("./revive/handler.js") },
@@ -11,4 +12,5 @@ export const projectionCatalog = [
11
12
  { meta: tellMeta, load: () => import("./tell/handler.js") },
12
13
  { meta: killMeta, load: () => import("./kill/handler.js") },
13
14
  { meta: statusMeta, load: () => import("./status/handler.js") },
15
+ { meta: historyMeta, load: () => import("./history/handler.js") },
14
16
  ];
@@ -0,0 +1,21 @@
1
+ import { readProjectionHistoryAddress, readProjectionHistory, selectProjectionHistory, } from "../../../../core/projection/index.js";
2
+ import { FlowError } from "../../../../flow-error.js";
3
+ import { projectionHistoryJson, renderProjectionHistoryDetail, renderProjectionHistoryList } from "../../../render/projection-history.js";
4
+ import { textResponse } from "../../../render/shared.js";
5
+ import { projectDirectory } from "../../shared.js";
6
+ export const handler = async (_stdin, flags, _signal, positional) => {
7
+ const cwd = await projectDirectory(flags, "history");
8
+ const [address] = positional;
9
+ if (!address) {
10
+ const runs = selectProjectionHistory(await readProjectionHistory(cwd), {
11
+ filters: flags.taskFilters,
12
+ sort: flags.taskSort,
13
+ nowMs: Date.now(),
14
+ });
15
+ return textResponse(flags.json ? projectionHistoryJson(runs) : renderProjectionHistoryList(runs));
16
+ }
17
+ const detail = await readProjectionHistoryAddress(cwd, address);
18
+ if (!detail)
19
+ throw new FlowError("PROJECTION_HISTORY_NOT_FOUND", `history has no retained run for '${address}'`);
20
+ return textResponse(flags.json ? projectionHistoryJson(detail) : renderProjectionHistoryDetail(detail));
21
+ };