@astrosheep/keiyaku 2.9.11 → 2.9.13

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 (218) hide show
  1. package/README.md +79 -85
  2. package/build/.tsbuildinfo +1 -1
  3. package/build/agents/call-terms.js +1 -0
  4. package/build/agents/providers/claude-agent-sdk/adapter.js +17 -4
  5. package/build/cli/commands/akuma/akuma/handler.js +2 -1
  6. package/build/cli/commands/akuma/akuma/meta.js +4 -3
  7. package/build/cli/commands/akuma/catalog.js +2 -0
  8. package/build/cli/commands/akuma/list/handler.js +1 -1
  9. package/build/cli/commands/akuma/list/meta-list.js +12 -0
  10. package/build/cli/commands/akuma/list/meta-ls.js +2 -2
  11. package/build/cli/commands/akuma.js +5 -0
  12. package/build/cli/commands/contract/amend/meta.js +4 -3
  13. package/build/cli/commands/contract/arc/meta.js +2 -0
  14. package/build/cli/commands/contract/audit/handler.js +28 -2
  15. package/build/cli/commands/contract/audit/meta.js +4 -3
  16. package/build/cli/commands/contract/bind/meta.js +4 -4
  17. package/build/cli/commands/contract/petition/handler.js +2 -1
  18. package/build/cli/commands/contract/petition/meta.js +2 -2
  19. package/build/cli/commands/contract/renew/handler.js +44 -3
  20. package/build/cli/commands/contract/renew/meta.js +5 -4
  21. package/build/cli/commands/metadata.js +14 -10
  22. package/build/cli/commands/projection/call/handler.js +1 -1
  23. package/build/cli/commands/projection/call/meta.js +1 -1
  24. package/build/cli/commands/projection/catalog.js +2 -2
  25. package/build/cli/commands/projection/{revive → fork}/handler.js +10 -5
  26. package/build/cli/commands/projection/fork/meta.js +12 -0
  27. package/build/cli/commands/projection/history/handler.js +46 -2
  28. package/build/cli/commands/projection/history/meta.js +3 -3
  29. package/build/cli/commands/projection/kill/handler.js +4 -5
  30. package/build/cli/commands/projection/kill/meta.js +2 -2
  31. package/build/cli/commands/projection/status/handler.js +29 -13
  32. package/build/cli/commands/projection/status/meta.js +14 -3
  33. package/build/cli/commands/projection/tell/handler.js +8 -4
  34. package/build/cli/commands/projection/tell/meta.js +1 -1
  35. package/build/cli/commands/projection/wait/handler.js +45 -20
  36. package/build/cli/commands/projection/wait/meta.js +1 -1
  37. package/build/cli/commands/shared.js +2 -2
  38. package/build/cli/commands/system/catalog.js +2 -0
  39. package/build/cli/commands/task/add/handler.js +28 -12
  40. package/build/cli/commands/task/add/meta.js +18 -6
  41. package/build/cli/commands/task/catalog.js +4 -0
  42. package/build/cli/commands/task/compose/handler.js +18 -0
  43. package/build/cli/commands/task/compose/meta.js +10 -0
  44. package/build/cli/commands/task/doctor/handler.js +2 -3
  45. package/build/cli/commands/task/doctor/meta.js +2 -2
  46. package/build/cli/commands/task/done/meta.js +2 -2
  47. package/build/cli/commands/task/drop/handler.js +7 -2
  48. package/build/cli/commands/task/drop/meta.js +6 -3
  49. package/build/cli/commands/task/hold/meta.js +2 -2
  50. package/build/cli/commands/task/log/meta.js +2 -2
  51. package/build/cli/commands/task/ls/meta.js +2 -2
  52. package/build/cli/commands/task/note/handler.js +6 -0
  53. package/build/cli/commands/task/note/meta.js +11 -0
  54. package/build/cli/commands/task/resume/meta.js +2 -2
  55. package/build/cli/commands/task/shared.js +29 -15
  56. package/build/cli/commands/task/show/meta.js +2 -2
  57. package/build/cli/commands/task/start/meta.js +2 -2
  58. package/build/cli/commands/task/stop/meta.js +2 -2
  59. package/build/cli/commands/task/update/meta.js +3 -2
  60. package/build/cli/commands/verification/handler.js +43 -0
  61. package/build/cli/commands/verification/meta.js +13 -0
  62. package/build/cli/completion.js +16 -13
  63. package/build/cli/flags.js +48 -12
  64. package/build/cli/help.js +29 -30
  65. package/build/cli/index.js +14 -8
  66. package/build/cli/parse-flags.js +60 -21
  67. package/build/cli/parse-metadata.js +10 -4
  68. package/build/cli/parse-selectors.js +22 -4
  69. package/build/cli/parse.js +43 -30
  70. package/build/cli/projection-address.js +7 -7
  71. package/build/cli/render/arc.js +12 -3
  72. package/build/cli/render/audit.js +2 -2
  73. package/build/cli/render/call.js +4 -4
  74. package/build/cli/render/kanshi.js +122 -85
  75. package/build/cli/render/misc.js +2 -2
  76. package/build/cli/render/petition.js +16 -1
  77. package/build/cli/render/projection-history.js +17 -4
  78. package/build/cli/render/shared.js +5 -5
  79. package/build/cli/render/status-indicator.js +47 -0
  80. package/build/cli/render/status.js +106 -76
  81. package/build/cli/render/success-response.js +20 -5
  82. package/build/cli/render/task.js +33 -5
  83. package/build/cli/render/tell.js +10 -4
  84. package/build/cli/render/tool-command-normalization.js +137 -0
  85. package/build/cli/render/tool-presentation.js +2 -1
  86. package/build/cli/render/verification.js +23 -0
  87. package/build/cli/render/wait.js +101 -33
  88. package/build/cli/types.js +2 -1
  89. package/build/config/akuma-loader.js +21 -1
  90. package/build/config/settings/knobs.js +7 -1
  91. package/build/config/settings/schema.js +10 -5
  92. package/build/core/addressing.js +3 -3
  93. package/build/core/amend.js +102 -17
  94. package/build/core/arc.js +4 -4
  95. package/build/core/audit/candidate.js +10 -18
  96. package/build/core/audit/coordinates.js +12 -17
  97. package/build/core/audit/evidence.js +6 -4
  98. package/build/core/audit/facade.js +3 -3
  99. package/build/core/audit/report.js +1 -1
  100. package/build/core/bind-reconciliation.js +42 -23
  101. package/build/core/bind.js +182 -81
  102. package/build/core/call/call.js +6 -7
  103. package/build/core/call/context.js +46 -33
  104. package/build/core/call/execution.js +21 -6
  105. package/build/core/call/prompt.js +11 -42
  106. package/build/core/contract-carrier-runtime.js +209 -105
  107. package/build/core/contract-carrier.js +156 -73
  108. package/build/core/contract-view.js +43 -6
  109. package/build/core/contract.js +2 -1
  110. package/build/core/derived-replay.js +168 -35
  111. package/build/core/draft.js +60 -27
  112. package/build/core/forfeit.js +1 -1
  113. package/build/core/lifecycle-history.js +13 -0
  114. package/build/core/lifecycle-recovery.js +32 -27
  115. package/build/core/lifecycle-runner.js +14 -14
  116. package/build/core/log.js +1 -1
  117. package/build/core/outcome-base.js +2 -2
  118. package/build/core/projection/akuma-name.js +43 -0
  119. package/build/core/projection/generation/database.js +141 -79
  120. package/build/core/projection/generation/ledger.js +91 -0
  121. package/build/core/projection/generation/model.js +19 -14
  122. package/build/core/projection/generation/projection-generation-continuation.js +1 -1
  123. package/build/core/projection/generation/projection-generation-doorbell.js +88 -0
  124. package/build/core/projection/generation/projection-generation-execution.js +24 -0
  125. package/build/core/projection/generation/projection-generation-identity.js +4 -0
  126. package/build/core/projection/generation/projection-generation-launcher.js +72 -138
  127. package/build/core/projection/generation/projection-generation-process.js +16 -15
  128. package/build/core/projection/generation/projection-generation-runner.js +132 -76
  129. package/build/core/projection/generation/projection-generation-runtime.js +10 -61
  130. package/build/core/projection/generation/protocol.js +68 -0
  131. package/build/core/projection/generation/store.js +17 -7
  132. package/build/core/projection/generation/transitions.js +24 -14
  133. package/build/core/projection/index.js +5 -5
  134. package/build/core/projection/projection-core.js +6 -2
  135. package/build/core/projection/projection-execution-observer.js +1 -1
  136. package/build/core/projection/projection-history.js +8 -8
  137. package/build/core/projection/projection-kill.js +20 -10
  138. package/build/core/projection/projection-life-observer.js +8 -8
  139. package/build/core/projection/projection-mint.js +6 -8
  140. package/build/core/projection/projection-status-observation.js +77 -8
  141. package/build/core/projection/projection-status.js +151 -4
  142. package/build/core/projection/projection-wait.js +48 -29
  143. package/build/core/projection/projection-wake.js +28 -88
  144. package/build/core/projection/tell/launch-store.js +1 -1
  145. package/build/core/projection/tell/store.js +1 -1
  146. package/build/core/renew-build.js +204 -74
  147. package/build/core/renew-plan.js +34 -9
  148. package/build/core/renew-rewrite.js +56 -15
  149. package/build/core/renew.js +39 -35
  150. package/build/core/repository-ledger/accepted-fold-read.js +6 -3
  151. package/build/core/repository-ledger/claim-evidence.js +1 -1
  152. package/build/core/repository-ledger/codec.js +11 -5
  153. package/build/core/repository-ledger/current-state-store.js +464 -349
  154. package/build/core/repository-ledger/fold-repository.js +5 -6
  155. package/build/core/repository-ledger/identity.js +60 -0
  156. package/build/core/repository-ledger/inventory.js +3 -3
  157. package/build/core/repository-ledger/read-model.js +57 -9
  158. package/build/core/repository-ledger/write-transaction.js +24 -17
  159. package/build/core/run-control/connection-bound-close.js +41 -0
  160. package/build/core/run-control/detached-lease-bootstrap.js +208 -0
  161. package/build/core/run-control/detached-process.js +14 -0
  162. package/build/core/run-control/index.js +6 -0
  163. package/build/core/{process-group.js → run-control/process-tree.js} +1 -1
  164. package/build/core/run-control/runner-lease.js +172 -0
  165. package/build/core/run-control/sqlite-process-lifetime-lock.js +174 -0
  166. package/build/core/seal.js +44 -32
  167. package/build/core/settlement/claim-delivery.js +22 -9
  168. package/build/core/settlement/claim.js +8 -6
  169. package/build/core/settlement/petition-claim-gates.js +9 -8
  170. package/build/core/settlement/petition-head-guard.js +5 -6
  171. package/build/core/settlement/petition-preview.js +21 -5
  172. package/build/core/settlement/petition.js +51 -17
  173. package/build/core/settlement/settlement.js +20 -15
  174. package/build/core/settlement/verdict.js +2 -2
  175. package/build/core/settlement/verification.js +492 -364
  176. package/build/core/status/board.js +184 -75
  177. package/build/core/status/drift.js +8 -10
  178. package/build/core/task/board.js +1 -0
  179. package/build/core/task/commands.js +25 -0
  180. package/build/core/task/compose.js +328 -0
  181. package/build/core/task/document.js +102 -39
  182. package/build/core/task/index.js +4 -3
  183. package/build/core/task/settlement-git.js +70 -30
  184. package/build/core/task/settlement-policy.js +27 -14
  185. package/build/core/task/source-board.js +1 -0
  186. package/build/core/task/task-bind-preparation.js +59 -9
  187. package/build/core/task/task-contract.js +2 -2
  188. package/build/core/task/task-git-store.js +1 -0
  189. package/build/core/task/task-store-repository.js +2 -0
  190. package/build/core/task/task.js +2 -2
  191. package/build/core/transcripts.js +4 -4
  192. package/build/core/verification-declaration.js +95 -0
  193. package/build/core/worktree-bootstrap.js +1 -1
  194. package/build/core/worktree-path.js +7 -11
  195. package/build/flow-error.js +15 -2
  196. package/build/generated/version.js +2 -2
  197. package/build/git/branches.js +41 -70
  198. package/build/git/commits.js +92 -21
  199. package/build/git/core.js +9 -161
  200. package/build/git/diff/preview.js +4 -4
  201. package/build/git/diff/read.js +4 -4
  202. package/build/git/diff/structured.js +5 -5
  203. package/build/git/process.js +229 -0
  204. package/build/git/refs.js +30 -5
  205. package/build/git/staging.js +39 -115
  206. package/build/git/streaming-batch.js +9 -16
  207. package/build/git/worktree.js +104 -91
  208. package/build/index.js +7 -0
  209. package/package.json +2 -2
  210. package/skills/keiyaku-akuma/SKILL.md +27 -21
  211. package/skills/keiyaku-task/SKILL.md +61 -5
  212. package/skills/keiyaku-workflow/SKILL.md +81 -26
  213. package/build/cli/commands/projection/revive/meta.js +0 -12
  214. package/build/core/projection/projection-life-protocol.js +0 -115
  215. package/build/core/projection/projection-runner-lock.js +0 -382
  216. package/build/core/projection/tell/database.js +0 -127
  217. package/build/core/settlement/verification-coordination.js +0 -305
  218. package/build/core/settlement/verification-supervisor.js +0 -275
@@ -6,6 +6,7 @@ import { withContractCarrierSession } from "./contract-carrier.js";
6
6
  import { runLifecycle } from "./lifecycle-runner.js";
7
7
  import { committedLifecycleFacts, derivedCleanupFacts, isCompleteLifecycleOutcome, } from "./outcome-base.js";
8
8
  import { abortDetachedRenewChain, readDetachedRenewScratch, renewScratchName, } from "./renew-rewrite.js";
9
+ import { scopePathEvidence } from "./scope.js";
9
10
  import { persistResponseHistory } from "./transcripts.js";
10
11
  import { admitRenew, checkCancellation, prepareRenew, sameAdmission, scopeEntry } from "./renew-plan.js";
11
12
  async function persistRenewResponse(journal, facts, persist) {
@@ -46,6 +47,7 @@ async function executeRenew(input, continuation) {
46
47
  },
47
48
  signal: input.signal,
48
49
  ...(input.renewDeliveryProjector ? { renewDeliveryProjector: input.renewDeliveryProjector } : {}),
50
+ ...(input.transactionRunner ? { transactionRunner: input.transactionRunner } : {}),
49
51
  admit: (session, replay) => admitRenew(session, input, replay, continuation?.scratch),
50
52
  prepare: (admission) => prepareRenew(admission.business, input, continuation),
51
53
  revalidate: async ({ session, admission }) => {
@@ -79,7 +81,11 @@ async function executeRenew(input, continuation) {
79
81
  if (admission.business.acceptedReplay) {
80
82
  const accepted = admission.business.acceptedReplay;
81
83
  const replayed = await context.replayCommitted({ transactionObjectId: accepted.transactionObjectId });
82
- const sealed = { ...accepted.seal.data, scopeViolationEvidence: [], ledgerHead: accepted.sealObjectId };
84
+ const sealed = {
85
+ ...accepted.seal.data,
86
+ scopeViolationEvidence: await scopePathEvidence(admission.business.targetRoot, admission.business.model.effectiveScope, accepted.seal.data.scopeAudit.violations),
87
+ ledgerHead: accepted.sealObjectId,
88
+ };
83
89
  const value = {
84
90
  ...committedLifecycleFacts({ head: accepted.transactionObjectId, entryKind: "renew", contractId: input.contractId, carrier: replayed.carrier }),
85
91
  contractId: input.contractId,
@@ -95,13 +101,6 @@ async function executeRenew(input, continuation) {
95
101
  carrier: replayed.carrier,
96
102
  targetRoot: admission.business.targetRoot,
97
103
  };
98
- if (continuation) {
99
- await context.journal.run({
100
- effect: "renew-scratch-cleanup",
101
- idempotencyKey: `${input.contractId}:${accepted.transactionObjectId}:renew-scratch-cleanup`,
102
- run: async () => abortDetachedRenewChain({ cwd: input.cwd, scratchName: continuation.scratch.scratchName }),
103
- });
104
- }
105
104
  await persistRenewResponse(context.journal, value, input.persistResponse);
106
105
  return { kind: "committed", commit: replayed, entryKind: "renew", value };
107
106
  }
@@ -140,7 +139,7 @@ async function executeRenew(input, continuation) {
140
139
  if (!admission.business.amendment) {
141
140
  const transactionObjectId = admission.replay.state === "verb-committed"
142
141
  ? admission.replay.transaction.transactionObjectId
143
- : admission.ledgerHead;
142
+ : admission.replay.transactionObjectId;
144
143
  const replayed = await context.replayCommitted({ transactionObjectId });
145
144
  const accepted = replayed.transaction.entries.at(-1);
146
145
  if (!accepted)
@@ -166,7 +165,7 @@ async function executeRenew(input, continuation) {
166
165
  const published = await context.publishAuthoritative({
167
166
  verb: "renew",
168
167
  admittedLedgerHead: admission.ledgerHead,
169
- acceptedLifecycleTail: context.session.lifecycle.history.at(-1).objectId,
168
+ acceptedLifecycleTail: context.session.lifecycle.contractHead,
170
169
  entries: [admission.business.amendment],
171
170
  });
172
171
  if (published.status === "refused-before-effects")
@@ -203,15 +202,19 @@ async function executeRenew(input, continuation) {
203
202
  const published = await context.publishAuthoritative({
204
203
  verb: "renew",
205
204
  admittedLedgerHead: admission.ledgerHead,
206
- acceptedLifecycleTail: context.session.lifecycle.history.at(-1).objectId,
205
+ acceptedLifecycleTail: context.session.lifecycle.contractHead,
207
206
  entries,
207
+ target: {
208
+ ref: admission.business.targetRef,
209
+ expectedOid: prepared.entry.data.newBase,
210
+ },
208
211
  delivery: {
209
212
  ref: admission.business.deliveryRef,
210
213
  expectedOid: prepared.entry.data.oldHead,
211
214
  },
212
215
  });
213
216
  if (published.status === "refused-before-effects")
214
- return { kind: "refused-before-effects", authoritativeHead: admission.ledgerHead, refusal: { code: "CONCURRENT_MODIFICATION", message: "repository ledger or delivery ref changed before renew transaction" } };
217
+ return { kind: "refused-before-effects", authoritativeHead: admission.ledgerHead, refusal: { code: "CONCURRENT_MODIFICATION", message: "repository target, ledger, or delivery ref changed before renew transaction" } };
215
218
  if (published.status === "indeterminate")
216
219
  return { kind: "precommit-effects-only", authoritativeHead: admission.ledgerHead };
217
220
  const sealIndex = published.transaction.entries.findIndex((entry) => entry.kind === "seal");
@@ -239,13 +242,6 @@ async function executeRenew(input, continuation) {
239
242
  carrier: published.carrier,
240
243
  targetRoot: admission.business.targetRoot,
241
244
  };
242
- if (continuation) {
243
- await context.journal.run({
244
- effect: "renew-scratch-cleanup",
245
- idempotencyKey: `${input.contractId}:${published.head}:renew-scratch-cleanup`,
246
- run: async () => abortDetachedRenewChain({ cwd: input.cwd, scratchName: continuation.scratch.scratchName }),
247
- });
248
- }
249
245
  await persistRenewResponse(context.journal, value, input.persistResponse);
250
246
  return { kind: "committed", commit: published, entryKind: "renew", value };
251
247
  },
@@ -261,19 +257,7 @@ export async function renewContract(input) {
261
257
  }
262
258
  export async function continueRenewContract(input) {
263
259
  const scratchName = renewScratchName(input.contractId);
264
- let scratch;
265
- try {
266
- scratch = await readDetachedRenewScratch({ cwd: input.cwd, scratchName });
267
- }
268
- catch (error) {
269
- throw new FlowError("RENEW_SCRATCH_NOT_FOUND", `no renew conflict scratch is open for ${input.contractId}`, { cause: error });
270
- }
271
- return executeRenew(input, { scratch, resolution: input.resolution ?? { kind: "scratch-files" } });
272
- }
273
- export async function abortRenewContract(input) {
274
- checkCancellation(input.signal);
275
- return withContractCarrierSession({ cwd: input.cwd, contractId: input.contractId, mode: "observe-only", signal: input.signal }, async (session) => {
276
- const scratchName = renewScratchName(input.contractId);
260
+ for (let attempt = 0; attempt < 2; attempt += 1) {
277
261
  let scratch;
278
262
  try {
279
263
  scratch = await readDetachedRenewScratch({ cwd: input.cwd, scratchName });
@@ -281,17 +265,37 @@ export async function abortRenewContract(input) {
281
265
  catch (error) {
282
266
  throw new FlowError("RENEW_SCRATCH_NOT_FOUND", `no renew conflict scratch is open for ${input.contractId}`, { cause: error });
283
267
  }
268
+ const result = await executeRenew(input, { scratch, resolution: input.resolution ?? { kind: "scratch-files" } });
269
+ const code = result.family === "refused-before-effects" ? result.failedInvariant.code : null;
270
+ if (attempt === 0 && (code === "LIFECYCLE_COORDINATES_CHANGED"
271
+ || code === "LIFECYCLE_REPLAY_COORDINATES_CHANGED"
272
+ || code === "RENEW_COORDINATES_CHANGED"
273
+ || code === "CONCURRENT_MODIFICATION"))
274
+ continue;
275
+ if (isCompleteLifecycleOutcome(result)) {
276
+ await abortDetachedRenewChain({ cwd: input.cwd, scratchName: scratch.scratchName });
277
+ }
278
+ return result;
279
+ }
280
+ throw new FlowError("INTERNAL_STATE", "bounded renew continuation retry exhausted unexpectedly");
281
+ }
282
+ export async function abortRenewContract(input) {
283
+ checkCancellation(input.signal);
284
+ return withContractCarrierSession({ cwd: input.cwd, contractId: input.contractId, mode: "observe-only", signal: input.signal }, async (session) => {
285
+ const scratchName = renewScratchName(input.contractId);
284
286
  checkCancellation(input.signal);
285
287
  const cleanup = await abortDetachedRenewChain({ cwd: input.cwd, scratchName });
288
+ if (cleanup.status === "absent") {
289
+ throw new FlowError("RENEW_SCRATCH_NOT_FOUND", `no renew conflict scratch is open for ${input.contractId}`);
290
+ }
286
291
  return {
287
292
  ...derivedCleanupFacts({
288
293
  contractId: input.contractId,
289
- authoritativeHead: session.lifecycle.observedLedgerHead,
294
+ authoritativeHead: session.pins.repositoryLedgerHead,
290
295
  effect: "renew-conflict-scratch-cleanup",
291
- receipt: { status: cleanup.status, scratchName, oldHead: scratch.oldHead },
296
+ receipt: { status: cleanup.status, scratchName },
292
297
  }),
293
298
  contractId: input.contractId,
294
- oldHead: scratch.oldHead,
295
299
  scratchName,
296
300
  carrier: session.initialCarrier,
297
301
  };
@@ -1,15 +1,18 @@
1
1
  import { resolveLocalBranchHead } from "../../git/refs.js";
2
2
  import { foldRepositoryLedger } from "./fold-repository.js";
3
3
  import { REPOSITORY_LEDGER_REF } from "./codec.js";
4
+ import { repositoryLedgerHead } from "./identity.js";
4
5
  import { traverseRepositoryLedger } from "./traversal.js";
5
6
  export async function observeRepositoryLedgerHead(cwd) {
6
- return (await resolveLocalBranchHead(cwd, REPOSITORY_LEDGER_REF))?.head ?? null;
7
+ const head = (await resolveLocalBranchHead(cwd, REPOSITORY_LEDGER_REF))?.head;
8
+ return head === undefined ? null : repositoryLedgerHead(head);
7
9
  }
8
10
  /** The shared current-head typed traversal and fold used by full and targeted reads. */
9
11
  export async function readAcceptedRepositoryFold(cwd, options = {}) {
10
- const observedLedgerHead = await (options.observeHead ?? observeRepositoryLedgerHead)(cwd);
11
- if (observedLedgerHead === null)
12
+ const observed = await (options.observeHead ?? observeRepositoryLedgerHead)(cwd);
13
+ if (observed === null)
12
14
  return { observedLedgerHead: null, traversed: null, folded: null };
15
+ const observedLedgerHead = repositoryLedgerHead(observed);
13
16
  const traversed = await traverseRepositoryLedger(cwd, observedLedgerHead, options.signal, { historicalSemanticEvidence: false });
14
17
  return {
15
18
  observedLedgerHead,
@@ -119,7 +119,7 @@ export async function assertHonestClaimEvidence(cwd, evidence, readContext) {
119
119
  let merge;
120
120
  try {
121
121
  const coordinates = readContext?.coordinates ?? await deriveHostGitCoordinates(cwd);
122
- merge = readContext === undefined
122
+ merge = readContext?.reader === undefined
123
123
  ? await readCommitObject(cwd, coordinates, evidence.mergeCommit)
124
124
  : await readContext.reader.read(evidence.mergeCommit);
125
125
  }
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { verificationDeclarationSchema } from "../verification-declaration.js";
2
3
  export const REPOSITORY_LEDGER_REF = "refs/heads/keiyaku-ledger";
3
4
  export const REPOSITORY_DELIVERY_REF_PREFIX = "refs/heads/keiyaku/";
4
5
  export function repositoryDeliveryRef(contract) {
@@ -61,7 +62,7 @@ function buildLifecycleEntrySchema(format) {
61
62
  design: nonblank,
62
63
  scope: z.array(nonblank).min(1),
63
64
  criteria: z.array(nonblank),
64
- verification: z.array(nonblank),
65
+ verification: z.array(verificationDeclarationSchema),
65
66
  extensions: z.array(extension),
66
67
  base: oid,
67
68
  target: fullBranchRefSchema,
@@ -103,7 +104,7 @@ function buildLifecycleEntrySchema(format) {
103
104
  }
104
105
  });
105
106
  return z.discriminatedUnion("kind", [
106
- lifecycleEnvelope("bind", 2, bindData),
107
+ lifecycleEnvelope("bind", 3, bindData),
107
108
  lifecycleEnvelope("bootstrap", 1, bootstrapData),
108
109
  lifecycleEnvelope("arc", 1, z.object({
109
110
  arc: safePositiveInteger,
@@ -124,10 +125,15 @@ function buildLifecycleEntrySchema(format) {
124
125
  }).strict(),
125
126
  scopeAudit: z.object({ violations: z.array(nonblank) }).strict(),
126
127
  }).strict()),
127
- lifecycleEnvelope("amend", 1, z.object({
128
- amendment: nonblank,
128
+ lifecycleEnvelope("amend", 2, z.object({
129
+ amendment: z.string(),
129
130
  scopeDelta: z.object({ add: z.array(nonblank).min(1) }).strict().optional(),
130
- }).strict()),
131
+ verificationDelta: z.object({ replace: z.array(verificationDeclarationSchema) }).strict().optional(),
132
+ }).strict().superRefine((value, context) => {
133
+ if (!value.amendment.trim() && !value.scopeDelta && !value.verificationDelta) {
134
+ context.addIssue({ code: "custom", message: "amend requires prose, a scope delta, or a verification delta" });
135
+ }
136
+ })),
131
137
  lifecycleEnvelope("renew", 1, z.object({
132
138
  oldBase: oid,
133
139
  newBase: oid,