@astrosheep/keiyaku 2.9.3 → 2.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/build/.tsbuildinfo +1 -1
  2. package/build/agents/call-terms.js +14 -94
  3. package/build/agents/harness/activity-values.js +16 -0
  4. package/build/agents/harness/event-persistence.js +218 -0
  5. package/build/agents/harness/execution-handle.js +26 -222
  6. package/build/agents/harness/index.js +3 -1
  7. package/build/agents/harness/outcome.js +68 -5
  8. package/build/agents/harness/projection.js +179 -124
  9. package/build/agents/harness/provider-adapter.js +58 -0
  10. package/build/agents/harness/router.js +11 -187
  11. package/build/agents/harness/runtime.js +17 -4
  12. package/build/agents/harness/session.js +15 -0
  13. package/build/agents/launch-snapshot/model.js +15 -236
  14. package/build/agents/launch-snapshot/parse-helpers.js +114 -0
  15. package/build/agents/launch-snapshot/resolve.js +17 -43
  16. package/build/agents/opencode-sdk.js +45 -12
  17. package/build/agents/providers/claude-agent-sdk/adapter.js +6 -17
  18. package/build/agents/providers/claude-agent-sdk/registration.js +214 -0
  19. package/build/agents/providers/claude-agent-sdk/session-schema.js +2 -0
  20. package/build/agents/providers/codex-app-server/adapter.js +82 -53
  21. package/build/agents/providers/codex-app-server/events.js +90 -11
  22. package/build/agents/providers/codex-app-server/identity.js +1 -0
  23. package/build/agents/providers/codex-app-server/policy.js +29 -0
  24. package/build/agents/providers/codex-app-server/registration.js +248 -0
  25. package/build/agents/providers/codex-app-server/session-schema.js +6 -0
  26. package/build/agents/providers/codex-app-server/session.js +23 -17
  27. package/build/agents/providers/codex-app-server/terms.js +1 -0
  28. package/build/agents/providers/opencode-sdk/adapter.js +94 -50
  29. package/build/agents/providers/opencode-sdk/events.js +8 -4
  30. package/build/agents/providers/opencode-sdk/registration.js +135 -0
  31. package/build/agents/providers/opencode-sdk/session-schema.js +2 -0
  32. package/build/agents/providers/opencode-sdk/session.js +21 -14
  33. package/build/agents/providers/opencode-sdk/terms.js +1 -0
  34. package/build/agents/providers/pi/adapter.js +36 -30
  35. package/build/agents/providers/pi/events.js +4 -3
  36. package/build/agents/providers/pi/registration.js +145 -0
  37. package/build/agents/providers/pi/session-schema.js +6 -0
  38. package/build/agents/providers/pi/terms.js +1 -0
  39. package/build/agents/providers/registration.js +7 -0
  40. package/build/agents/providers/registry.js +76 -0
  41. package/build/agents/selector.js +2 -29
  42. package/build/agents/types.js +10 -0
  43. package/build/artifact-directories.js +22 -0
  44. package/build/cli/commands/akuma/akuma/handler.js +1 -1
  45. package/build/cli/commands/akuma/akuma/meta.js +1 -1
  46. package/build/cli/commands/akuma/list/meta-ls.js +1 -1
  47. package/build/cli/commands/akuma/view/handler.js +5 -4
  48. package/build/cli/commands/akuma/view/meta.js +1 -1
  49. package/build/cli/commands/akuma.js +6 -0
  50. package/build/cli/commands/contract/amend/handler.js +8 -2
  51. package/build/cli/commands/contract/amend/meta.js +4 -4
  52. package/build/cli/commands/contract/arc/handler.js +8 -2
  53. package/build/cli/commands/contract/arc/meta.js +4 -4
  54. package/build/cli/commands/contract/audit/handler.js +16 -0
  55. package/build/cli/commands/contract/audit/meta.js +16 -0
  56. package/build/cli/commands/contract/bind/handler.js +4 -3
  57. package/build/cli/commands/contract/bind/meta.js +44 -8
  58. package/build/cli/commands/contract/catalog.js +2 -0
  59. package/build/cli/commands/contract/forfeit/handler.js +4 -4
  60. package/build/cli/commands/contract/forfeit/meta.js +1 -1
  61. package/build/cli/commands/contract/log/handler.js +3 -3
  62. package/build/cli/commands/contract/log/meta.js +1 -1
  63. package/build/cli/commands/contract/petition/handler.js +5 -8
  64. package/build/cli/commands/contract/petition/meta.js +6 -6
  65. package/build/cli/commands/contract/renew/handler.js +20 -6
  66. package/build/cli/commands/contract/renew/meta.js +6 -5
  67. package/build/cli/commands/metadata.js +59 -0
  68. package/build/cli/commands/projection/call/handler.js +6 -5
  69. package/build/cli/commands/projection/call/meta.js +4 -1
  70. package/build/cli/commands/projection/kill/handler.js +16 -32
  71. package/build/cli/commands/projection/kill/meta.js +1 -1
  72. package/build/cli/commands/projection/revive/meta.js +4 -1
  73. package/build/cli/commands/projection/shared.js +28 -0
  74. package/build/cli/commands/projection/status/handler.js +1 -1
  75. package/build/cli/commands/projection/status/meta.js +1 -1
  76. package/build/cli/commands/projection/tell/handler.js +14 -30
  77. package/build/cli/commands/projection/tell/meta.js +4 -1
  78. package/build/cli/commands/projection/wait/handler.js +45 -22
  79. package/build/cli/commands/projection/wait/meta.js +8 -3
  80. package/build/cli/commands/registry.js +2 -54
  81. package/build/cli/commands/shared.js +10 -7
  82. package/build/cli/commands/skills/install/handler.js +2 -5
  83. package/build/cli/commands/skills/install/meta.js +1 -1
  84. package/build/cli/commands/skills/skills/handler.js +1 -1
  85. package/build/cli/commands/skills/skills/meta.js +1 -1
  86. package/build/cli/commands/system/completion/meta.js +1 -1
  87. package/build/cli/commands/system/dump-env/meta.js +1 -1
  88. package/build/cli/commands/system/guide/meta.js +1 -1
  89. package/build/cli/commands/task/add/handler.js +7 -15
  90. package/build/cli/commands/task/add/meta.js +4 -1
  91. package/build/cli/commands/task/catalog.js +2 -2
  92. package/build/cli/commands/task/doctor/meta.js +1 -1
  93. package/build/cli/commands/task/done/handler.js +4 -8
  94. package/build/cli/commands/task/done/meta.js +1 -1
  95. package/build/cli/commands/task/drop/handler.js +3 -6
  96. package/build/cli/commands/task/drop/meta.js +1 -1
  97. package/build/cli/commands/task/ls/handler.js +12 -8
  98. package/build/cli/commands/task/ls/meta.js +3 -3
  99. package/build/cli/commands/task/shared.js +14 -4
  100. package/build/cli/commands/task/{view → show}/handler.js +7 -8
  101. package/build/cli/commands/task/show/meta.js +8 -0
  102. package/build/cli/commands/task/start/handler.js +3 -6
  103. package/build/cli/commands/task/start/meta.js +1 -1
  104. package/build/cli/commands/task/stop/handler.js +4 -8
  105. package/build/cli/commands/task/stop/meta.js +1 -1
  106. package/build/cli/commands/task/task/handler.js +1 -1
  107. package/build/cli/commands/task/task/meta.js +1 -1
  108. package/build/cli/commands/task/update/handler.js +6 -11
  109. package/build/cli/commands/task/update/meta.js +4 -1
  110. package/build/cli/completion.js +1 -1
  111. package/build/cli/flags.js +37 -6
  112. package/build/cli/help.js +7 -14
  113. package/build/cli/index.js +112 -154
  114. package/build/cli/missing-subcommand.js +7 -0
  115. package/build/cli/output-stream-error-policy.js +19 -5
  116. package/build/cli/parse-flags.js +33 -7
  117. package/build/cli/parse-metadata.js +3 -9
  118. package/build/cli/parse-selectors.js +2 -1
  119. package/build/cli/parse.js +35 -5
  120. package/build/cli/projection-address.js +12 -12
  121. package/build/cli/render/address.js +41 -37
  122. package/build/cli/render/arc.js +24 -12
  123. package/build/cli/render/audit.js +121 -0
  124. package/build/cli/render/call.js +11 -5
  125. package/build/cli/render/errors.js +36 -1
  126. package/build/cli/render/format.js +4 -0
  127. package/build/cli/render/kanshi.js +6 -12
  128. package/build/cli/render/kill.js +9 -0
  129. package/build/cli/render/misc.js +58 -13
  130. package/build/cli/render/petition.js +20 -15
  131. package/build/cli/render/projection-activity.js +15 -6
  132. package/build/cli/render/shared.js +60 -21
  133. package/build/cli/render/skills.js +10 -0
  134. package/build/cli/render/status.js +56 -23
  135. package/build/cli/render/success-response.js +78 -0
  136. package/build/cli/render/task.js +66 -57
  137. package/build/cli/render/tell.js +5 -0
  138. package/build/cli/render/terminal-failure.js +63 -0
  139. package/build/cli/render/types.js +1 -0
  140. package/build/cli/render/wait.js +68 -38
  141. package/build/cli/types.js +1 -1
  142. package/build/config/akuma-loader.js +0 -5
  143. package/build/config/env-keys.js +3 -1
  144. package/build/config/env.js +3 -0
  145. package/build/config/provider-policy-ownership.js +3 -32
  146. package/build/config/settings/disease.js +8 -1
  147. package/build/config/settings/loader.js +11 -3
  148. package/build/config/settings/provider-instance-fields.js +51 -0
  149. package/build/config/settings/schema.js +6 -176
  150. package/build/core/addressing.js +66 -16
  151. package/build/core/amend.js +61 -18
  152. package/build/core/arc.js +33 -73
  153. package/build/core/audit.js +650 -0
  154. package/build/core/bind.js +82 -35
  155. package/build/core/call/call.js +15 -9
  156. package/build/core/call/context.js +6 -51
  157. package/build/core/call/execution.js +22 -22
  158. package/build/core/call/prompt.js +14 -1
  159. package/build/core/command-markdown.js +45 -0
  160. package/build/core/context.js +13 -7
  161. package/build/core/contract-view.js +22 -6
  162. package/build/core/draft.js +139 -19
  163. package/build/core/entry.js +3 -4
  164. package/build/core/forfeit.js +5 -2
  165. package/build/core/hints.js +1 -75
  166. package/build/core/identifier-slug.js +66 -0
  167. package/build/core/ids.js +25 -11
  168. package/build/core/ledger.js +20 -68
  169. package/build/core/markdown/lex.js +2 -1
  170. package/build/core/markdown/parser.js +0 -68
  171. package/build/core/markdown/render.js +68 -0
  172. package/build/core/markdown/sections.js +2 -1
  173. package/build/core/outcome-base.js +4 -0
  174. package/build/core/projection/generation/database.js +41 -52
  175. package/build/core/projection/generation/model.js +63 -2
  176. package/build/core/{projection-generation-continuation.js → projection/generation/projection-generation-continuation.js} +3 -3
  177. package/build/core/{projection-generation-execution.js → projection/generation/projection-generation-execution.js} +36 -53
  178. package/build/core/{projection-generation-identity.js → projection/generation/projection-generation-identity.js} +2 -2
  179. package/build/core/{projection-generation-launcher.js → projection/generation/projection-generation-launcher.js} +9 -7
  180. package/build/core/{projection-generation-process.js → projection/generation/projection-generation-process.js} +2 -1
  181. package/build/core/{projection-generation-runner.js → projection/generation/projection-generation-runner.js} +19 -3
  182. package/build/core/projection/generation/store.js +3 -3
  183. package/build/core/projection/generation/transitions.js +19 -3
  184. package/build/core/projection/index.js +27 -0
  185. package/build/core/{projection-activity.js → projection/projection-activity.js} +12 -0
  186. package/build/core/{projection-alias.js → projection/projection-alias.js} +13 -13
  187. package/build/core/projection/projection-coordinate.js +61 -0
  188. package/build/core/{projection-core.js → projection/projection-core.js} +9 -9
  189. package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js} +37 -78
  190. package/build/core/{projection-identity.js → projection/projection-identity.js} +1 -1
  191. package/build/core/{projection-kill.js → projection/projection-kill.js} +1 -1
  192. package/build/core/{projection-life-observer.js → projection/projection-life-observer.js} +16 -2
  193. package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
  194. package/build/core/{projection-status.js → projection/projection-status.js} +163 -45
  195. package/build/core/projection/projection-terminal-failure.js +106 -0
  196. package/build/core/projection/projection-wait.js +275 -0
  197. package/build/core/projection/projection-wake.js +227 -0
  198. package/build/core/provider-loader-ports.js +4 -0
  199. package/build/core/ref-log.js +65 -40
  200. package/build/core/registry.js +63 -10
  201. package/build/core/renew-session.js +128 -0
  202. package/build/core/renew.js +448 -102
  203. package/build/core/scope.js +272 -68
  204. package/build/core/seal.js +165 -40
  205. package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +8 -8
  206. package/build/core/{claim.js → settlement/claim.js} +32 -8
  207. package/build/core/settlement/index.js +19 -0
  208. package/build/core/{petition-claim-gates.js → settlement/petition-claim-gates.js} +24 -49
  209. package/build/core/{petition-forfeit.js → settlement/petition-forfeit.js} +2 -2
  210. package/build/core/{petition-head-guard.js → settlement/petition-head-guard.js} +2 -2
  211. package/build/core/settlement/petition-io.js +1 -0
  212. package/build/core/{petition-preview.js → settlement/petition-preview.js} +2 -2
  213. package/build/core/{petition.js → settlement/petition.js} +21 -12
  214. package/build/core/settlement/queue-read-model.js +143 -0
  215. package/build/core/settlement/queue-seat-allocation.js +156 -0
  216. package/build/core/settlement/queue.js +6 -0
  217. package/build/core/settlement/settlement.js +288 -0
  218. package/build/core/{verdict.js → settlement/verdict.js} +9 -37
  219. package/build/core/settlement/verification.js +59 -0
  220. package/build/core/status/board.js +62 -41
  221. package/build/core/status/ledger-batch.js +158 -0
  222. package/build/core/status/reconciliation.js +10 -4
  223. package/build/core/stored-agent-event.js +6 -2
  224. package/build/core/task/board.js +41 -4
  225. package/build/core/task/commands.js +45 -28
  226. package/build/core/task/document.js +5 -0
  227. package/build/core/task/index.js +12 -0
  228. package/build/core/task/model.js +8 -1
  229. package/build/core/task/query.js +172 -0
  230. package/build/core/task/settlement-git.js +265 -74
  231. package/build/core/task/settlement-policy.js +67 -29
  232. package/build/core/task/source-board.js +1 -0
  233. package/build/core/task/task-contract.js +444 -0
  234. package/build/core/{task-doctor.js → task/task-doctor.js} +1 -1
  235. package/build/core/{task-git-actor.js → task/task-git-actor.js} +5 -10
  236. package/build/core/{task-git-runtime.js → task/task-git-runtime.js} +3 -3
  237. package/build/core/{task-git-store.js → task/task-git-store.js} +90 -19
  238. package/build/core/task/task-repository.js +1 -0
  239. package/build/core/{task-store-repository.js → task/task-store-repository.js} +6 -4
  240. package/build/core/task/task-store.js +1 -0
  241. package/build/core/{task-worktree.js → task/task-worktree.js} +2 -1
  242. package/build/core/task/task.js +7 -0
  243. package/build/core/task/tree.js +37 -0
  244. package/build/core/task/validation.js +5 -2
  245. package/build/core/transcripts.js +15 -3
  246. package/build/core/worktree-path.js +43 -28
  247. package/build/flow-error.js +83 -39
  248. package/build/fs/path-coordinate.js +16 -0
  249. package/build/generated/version.js +3 -2
  250. package/build/git/branches.js +2 -1
  251. package/build/git/core.js +106 -2
  252. package/build/git/diff/parsers.js +23 -13
  253. package/build/git/diff/structured.js +127 -0
  254. package/build/git/path-coordinate.js +17 -0
  255. package/build/git/refs.js +57 -0
  256. package/build/git/streaming-batch.js +301 -0
  257. package/build/git/worktree.js +65 -0
  258. package/build/index.js +9 -9
  259. package/build/keiyaku.js +2 -36
  260. package/build/telemetry/logger.js +4 -2
  261. package/package.json +4 -10
  262. package/skills/keiyaku/SKILL.md +5 -4
  263. package/skills/keiyaku-akuma/SKILL.md +25 -11
  264. package/skills/keiyaku-task/SKILL.md +17 -8
  265. package/skills/keiyaku-workflow/SKILL.md +58 -9
  266. package/build/agents/providers/codex-sdk.js +0 -329
  267. package/build/cli/commands/task/view/meta.js +0 -8
  268. package/build/core/command-io.js +0 -174
  269. package/build/core/path-coordinate.js +0 -27
  270. package/build/core/petition-claim.js +0 -117
  271. package/build/core/petition-run.js +0 -83
  272. package/build/core/projection-coordinate.js +0 -63
  273. package/build/core/projection-wait.js +0 -165
  274. package/build/core/projection-wake.js +0 -136
  275. package/build/core/queue.js +0 -343
  276. package/build/core/task-contract.js +0 -237
  277. package/build/core/task.js +0 -4
  278. /package/build/{core/task-repository.js → agents/launch-snapshot/types.js} +0 -0
  279. /package/build/{core/task-store.js → agents/providers/claude-agent-sdk/terms.js} +0 -0
  280. /package/build/core/{projection-generation-runtime.js → projection/generation/projection-generation-runtime.js} +0 -0
  281. /package/build/core/{projection-life-protocol.js → projection/projection-life-protocol.js} +0 -0
  282. /package/build/core/{projection-runner-lock.js → projection/projection-runner-lock.js} +0 -0
@@ -1,13 +1,13 @@
1
1
  import * as fs from "node:fs/promises";
2
2
  import * as path from "node:path";
3
- import { FlowError } from "../flow-error.js";
4
- import { syncDirectory } from "../fs/durability.js";
5
- import { createGit, errorContainsAnyPattern, MISSING_HEAD_PATTERNS, wrapGitError } from "../git/core.js";
6
- import { readLedger } from "./ledger.js";
7
- import { shortCommitHash } from "../git/commits.js";
8
- import { commissionTarget, latestBase } from "./status/drift.js";
9
- import { settleTaskBoardForLanding } from "./task-contract.js";
10
- import { stableRepoRoot } from "./worktree-path.js";
3
+ import { FlowError } from "../../flow-error.js";
4
+ import { syncDirectory } from "../../fs/durability.js";
5
+ import { createGit, errorContainsAnyPattern, MISSING_HEAD_PATTERNS, wrapGitError } from "../../git/core.js";
6
+ import { readLedger } from "../ledger.js";
7
+ import { shortCommitHash } from "../../git/commits.js";
8
+ import { commissionTarget, latestBase } from "../status/drift.js";
9
+ import { settleTaskBoardForLanding } from "../task/index.js";
10
+ import { stableRepoRoot } from "../worktree-path.js";
11
11
  const CLAIM_RECEIPTS_FILE = "claim-receipts.jsonl";
12
12
  async function appendClaimReceipt(cwd, receipt, restoreIfMissing = "") {
13
13
  const receiptPath = path.join(await stableRepoRoot(cwd), ".keiyaku", CLAIM_RECEIPTS_FILE);
@@ -1,10 +1,11 @@
1
- import { FlowError } from "../flow-error.js";
2
- import { activeLedgerRef, appendWithRetry, readLedger } from "./ledger.js";
1
+ import { FlowError } from "../../flow-error.js";
2
+ import { assertCleanTrackedWorkingTree } from "../../git/worktree.js";
3
+ import { activeLedgerRef, appendWithRetry, readLedger } from "../ledger.js";
3
4
  import { assertClaimQueueHead, readQueueReadModel } from "./queue.js";
4
- import { releaseScope } from "./registry.js";
5
- import { deriveContractState } from "./status/lifecycle.js";
6
- import { commissionTarget, latestBase } from "./status/drift.js";
7
- import { cleanupContractWorkspace, findContractWorktreePath, stableRepoRoot } from "./worktree-path.js";
5
+ import { releaseScope } from "../registry.js";
6
+ import { deriveContractState } from "../status/lifecycle.js";
7
+ import { commissionTarget, latestBase } from "../status/drift.js";
8
+ import { cleanupContractWorkspace, findContractWorktreePath, stableRepoRoot } from "../worktree-path.js";
8
9
  import { defaultMergeDelivery, relativeDisplayPath, resolveCommit, resolveCommitOrNull, } from "./claim-delivery.js";
9
10
  async function cleanupClaim(cwd, contractId, actor, at) {
10
11
  const stableRoot = await stableRepoRoot(cwd);
@@ -14,16 +15,37 @@ async function cleanupClaim(cwd, contractId, actor, at) {
14
15
  function findClaim(entries) {
15
16
  return entries.find((entry) => entry.kind === "claim");
16
17
  }
18
+ /** Verdict belonging to the open petition window (after last petition, before claim). */
19
+ function latestCurrentPetitionVerdict(entries) {
20
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
21
+ const entry = entries[index];
22
+ if (entry.kind === "verdict")
23
+ return entry;
24
+ if (entry.kind === "petition")
25
+ return undefined;
26
+ }
27
+ return undefined;
28
+ }
29
+ /**
30
+ * Delivery requires an approved verdict for the current petition.
31
+ * Already-claimed cleanup retry remains legal without re-proving judgment.
32
+ */
17
33
  function assertClaimableFromLedger(contractId, ledger) {
18
34
  if (!ledger) {
19
35
  throw new FlowError("INTERNAL_STATE", `contract ${contractId} not found`);
20
36
  }
21
37
  const state = deriveContractState(ledger.entries);
22
38
  const claim = findClaim(ledger.entries);
23
- if (state.state === "petitioned")
24
- return claim;
39
+ // Already-claimed cleanup retry: legal head even if a prior crash left debris.
25
40
  if (claim && state.state === "claimed")
26
41
  return claim;
42
+ if (state.state === "petitioned") {
43
+ const verdict = latestCurrentPetitionVerdict(ledger.entries);
44
+ if (verdict?.data.result !== "approved") {
45
+ throw new FlowError("INTERNAL_STATE", `contract ${contractId} cannot claim without approved verdict for current petition`);
46
+ }
47
+ return claim;
48
+ }
27
49
  if (state.state === "forfeited") {
28
50
  throw new FlowError("INTERNAL_STATE", `contract ${contractId} forfeited`);
29
51
  }
@@ -95,6 +117,8 @@ export async function previewClaimContract(input) {
95
117
  }
96
118
  export async function claimContract(input) {
97
119
  const at = new Date(input.nowMs).toISOString();
120
+ const deliveryWorktree = await findContractWorktreePath(input.cwd, input.contractId);
121
+ await assertCleanTrackedWorkingTree(deliveryWorktree ?? input.cwd);
98
122
  const existing = await readLedger(input.cwd, input.contractId);
99
123
  const existingClaim = assertClaimableFromLedger(input.contractId, existing);
100
124
  const existingState = existing ? deriveContractState(existing.entries) : undefined;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Public surface for the settlement package.
3
+ * Only symbols required by current external consumers are re-exported.
4
+ * Package-internal modules must import each other directly, not through this file.
5
+ *
6
+ * Orchestrator owns: gates → petition → pure verdict → claim delivery / reject publish.
7
+ * Foundations (queue, claim-delivery) may be depended on downward by stage modules.
8
+ * Stage modules (petition, verdict, claim) do not import one another.
9
+ */
10
+ export { claimKeiyaku, petitionKeiyaku, } from "./settlement.js";
11
+ export { buildPetitionClaimInput, petitionContract, loadPetitionPreflightContext, assertPetitionFresh, assertPetitionArcReady, assertPetitionable, } from "./petition.js";
12
+ export { previewPetition, PETITION_PREVIEW_GATE_NAMES, } from "./petition-preview.js";
13
+ export { verdictContract, } from "./verdict.js";
14
+ export { claimContract, previewClaimContract, } from "./claim.js";
15
+ export { defaultMergeDelivery, relativeDisplayPath, resolveCommit, resolveCommitOrNull, } from "./claim-delivery.js";
16
+ export { allocateSettlementSeat, assertClaimQueueHead, deriveQueueReadModel, queueMembership, readQueueReadModel, seatAllocatorRef, } from "./queue.js";
17
+ export { buildClaimGatePipeline, createAgentReviewGate, createOathGate, } from "./petition-claim-gates.js";
18
+ export { assertHeadUnchanged } from "./petition-head-guard.js";
19
+ export { forfeitKeiyaku } from "./petition-forfeit.js";
@@ -1,21 +1,20 @@
1
- import { spawn } from "node:child_process";
2
- import { getConfig } from "../config/env.js";
3
- import { assertSettingsKnobUsable } from "../config/settings/disease.js";
4
- import { resolveReviewerAgentName } from "../config/settings/knobs.js";
5
- import { loadKeiyakuSettings } from "../config/settings/loader.js";
6
- import { loadAkumaCatalog } from "../config/akuma-loader.js";
7
- import { formatAvailableAgentNames } from "../agents/selector.js";
8
- import { getDiffStats } from "../git/diff/preview.js";
9
- import { readDiff } from "../git/diff/read.js";
10
- import { getCurrentBranch } from "../git/branches.js";
11
- import { getLatestCommitHash } from "../git/staging.js";
12
- import { DIFF_PREVIEW_TEXT_MAX_CHARS } from "../keiyaku.js";
13
- import { FlowError } from "../flow-error.js";
14
- import { persistResponseHistory } from "./transcripts.js";
15
- import { logInfo } from "../telemetry/logger.js";
16
- import { execSubagent } from "./call/call.js";
17
- import { readContractLog } from "./log.js";
18
- import { buildVerificationFailureHints } from "./hints.js";
1
+ import { getConfig } from "../../config/env.js";
2
+ import { assertSettingsKnobUsable } from "../../config/settings/disease.js";
3
+ import { resolveReviewerAgentName } from "../../config/settings/knobs.js";
4
+ import { loadKeiyakuSettings } from "../../config/settings/loader.js";
5
+ import { loadAkumaCatalog } from "../../config/akuma-loader.js";
6
+ import { formatAvailableAgentNames } from "../../agents/selector.js";
7
+ import { getDiffStats } from "../../git/diff/preview.js";
8
+ import { readDiff } from "../../git/diff/read.js";
9
+ import { getCurrentBranch } from "../../git/branches.js";
10
+ import { getLatestCommitHash } from "../../git/staging.js";
11
+ import { DIFF_PREVIEW_TEXT_MAX_CHARS } from "../../keiyaku.js";
12
+ import { FlowError } from "../../flow-error.js";
13
+ import { persistResponseHistory } from "../transcripts.js";
14
+ import { logInfo } from "../../telemetry/logger.js";
15
+ import { execSubagent } from "../call/call.js";
16
+ import { readContractLog } from "../log.js";
17
+ import { runVerificationCommand } from "./verification.js";
19
18
  const CLAIM_VERIFICATION_OUTPUT_MAX_CHARS = 1200;
20
19
  const REVIEW_PASS_TOKEN = "PASS";
21
20
  const REVIEW_REJECTION_MESSAGE = "CLAIM rejected by independent reviewer.";
@@ -49,31 +48,6 @@ function buildReviewAttemptBlock(reviewNumber) {
49
48
  "Focus on whether the previous concerns have been addressed.",
50
49
  ];
51
50
  }
52
- async function runCommand(options) {
53
- return await new Promise((resolve, reject) => {
54
- const child = spawn(options.command, options.args, {
55
- cwd: options.cwd,
56
- stdio: ["ignore", "pipe", "pipe"],
57
- env: getConfig().runtimeEnv,
58
- });
59
- let stdout = "";
60
- let stderr = "";
61
- child.stdout.on("data", (chunk) => {
62
- stdout += String(chunk);
63
- });
64
- child.stderr.on("data", (chunk) => {
65
- stderr += String(chunk);
66
- });
67
- child.on("error", reject);
68
- child.on("close", (code) => {
69
- resolve({
70
- code: typeof code === "number" ? code : -1,
71
- stdout,
72
- stderr,
73
- });
74
- });
75
- });
76
- }
77
51
  function clipCommandOutput(value, maxChars = CLAIM_VERIFICATION_OUTPUT_MAX_CHARS) {
78
52
  const trimmed = value.trim();
79
53
  if (!trimmed)
@@ -129,17 +103,18 @@ export function createCommandVerificationGate() {
129
103
  async evaluate({ cwd, verificationCommands }) {
130
104
  for (const verification of verificationCommands) {
131
105
  logInfo(`[CLAIM] Running verification: ${verification.label}`, { cwd, section: "script", progressOnly: true });
132
- const result = await runCommand({
133
- cwd,
134
- command: verification.command,
135
- args: verification.args,
136
- });
106
+ const result = await runVerificationCommand(cwd, verification);
137
107
  if (result.code !== 0) {
138
108
  return {
139
109
  pass: false,
140
110
  code: "CLOSE_QUALITY_GATE_FAILED",
141
111
  message: `CLAIM blocked: verification failed at '${verification.label}' (exit ${result.code}).`,
142
- hints: buildVerificationFailureHints(verification.label, clipCommandOutput(result.stdout), clipCommandOutput(result.stderr)),
112
+ facts: {
113
+ kind: "verification_failure",
114
+ label: verification.label,
115
+ stdout: clipCommandOutput(result.stdout.tail),
116
+ stderr: clipCommandOutput(result.stderr.tail),
117
+ },
143
118
  };
144
119
  }
145
120
  }
@@ -1,5 +1,5 @@
1
- import { forfeitContract } from "./forfeit.js";
2
- import { readContractLog } from "./log.js";
1
+ import { forfeitContract } from "../forfeit.js";
2
+ import { readContractLog } from "../log.js";
3
3
  function maxArc(entries) {
4
4
  return entries.filter((entry) => entry.kind === "arc").length;
5
5
  }
@@ -1,5 +1,5 @@
1
- import { FlowError } from "../flow-error.js";
2
- import { getLatestCommitHash } from "../git/staging.js";
1
+ import { FlowError } from "../../flow-error.js";
2
+ import { getLatestCommitHash } from "../../git/staging.js";
3
3
  const CONCURRENT_MODIFICATION_CODE = "CONCURRENT_MODIFICATION";
4
4
  export async function assertHeadUnchanged(cwd, expectedHead, operation) {
5
5
  const currentHead = await getLatestCommitHash(cwd);
@@ -0,0 +1 @@
1
+ export {};
@@ -1,6 +1,6 @@
1
1
  import { createOathGate } from "./petition-claim-gates.js";
2
2
  import { assertPetitionArcReady, assertPetitionFresh, assertPetitionable, loadPetitionPreflightContext, } from "./petition.js";
3
- import { petitionSealSource, previewSeal } from "./seal.js";
3
+ import { petitionSealSource, previewSeal } from "../seal.js";
4
4
  export const PETITION_PREVIEW_GATE_NAMES = [
5
5
  "contract",
6
6
  "freshness",
@@ -55,7 +55,7 @@ export async function previewPetition(input) {
55
55
  let seal;
56
56
  if (freshness.result === "pass" && arc.result === "pass" && state.result === "pass") {
57
57
  try {
58
- const sealPreview = await previewSeal(context.deliveryCwd, context.ledger.entries, "HEAD", input.waivePaths);
58
+ const sealPreview = await previewSeal(context.deliveryCwd, context.ledger.entries, "HEAD");
59
59
  seal = { name: "seal", result: "pass", detail: sealPathDetail(sealPreview.paths) };
60
60
  }
61
61
  catch (error) {
@@ -1,12 +1,13 @@
1
- import { FlowError } from "../flow-error.js";
2
- import { createGit, errorContainsAnyPattern, MISSING_HEAD_PATTERNS, wrapGitError } from "../git/core.js";
3
- import { parseCommandMarkdown } from "./command-io.js";
4
- import { activeLedgerRef, appendWithRetry, readLedger } from "./ledger.js";
1
+ import { FlowError } from "../../flow-error.js";
2
+ import { createGit, errorContainsAnyPattern, MISSING_HEAD_PATTERNS, wrapGitError } from "../../git/core.js";
3
+ import { parseCommandMarkdown } from "../command-markdown.js";
4
+ import { activeLedgerRef, appendWithRetry, readLedger } from "../ledger.js";
5
5
  import { allocateSettlementSeat, queueMembership, readQueueReadModel } from "./queue.js";
6
- import { findOpenArc, getMaxArc, receiptsAfterFence, sealCurrentArc } from "./seal.js";
7
- import { deriveContractState } from "./status/lifecycle.js";
8
- import { commissionTarget, latestBase } from "./status/drift.js";
9
- import { findContractWorktreePath } from "./worktree-path.js";
6
+ import { appendScopeTerms, findOpenArc, getMaxArc, receiptsAfterFence, sealCurrentArc } from "../seal.js";
7
+ import { deriveContractState } from "../status/lifecycle.js";
8
+ import { commissionTarget, latestBase } from "../status/drift.js";
9
+ import { findContractWorktreePath } from "../worktree-path.js";
10
+ import { assertCleanTrackedWorkingTree } from "../../git/worktree.js";
10
11
  async function resolveCommit(cwd, ref) {
11
12
  const git = createGit(cwd);
12
13
  try {
@@ -47,7 +48,7 @@ export async function assertPetitionFresh(cwd, contractId, entries, base) {
47
48
  throw new FlowError("INTERNAL_STATE", `contract ${contractId} commission target ${target.ref} does not resolve`);
48
49
  }
49
50
  if (base !== head) {
50
- throw new FlowError("INTERNAL_STATE", `contract ${contractId} must renew onto ${target.branch} before petition`, { hints: [`keiyaku @${contractId} renew — renews delivery before petition`] });
51
+ throw new FlowError("INTERNAL_STATE", `contract ${contractId} must renew onto ${target.branch} before petition`, { facts: { kind: "needs_renew", contractId } });
51
52
  }
52
53
  }
53
54
  export async function assertPetitionArcReady(deliveryCwd, contractId, entries) {
@@ -55,7 +56,7 @@ export async function assertPetitionArcReady(deliveryCwd, contractId, entries) {
55
56
  return;
56
57
  const loose = await receiptsAfterFence(deliveryCwd, entries);
57
58
  if (loose.length > 0) {
58
- throw new FlowError("NO_OPEN_ARC", `${loose.length} commits after fence have no arc to receipt them`, { hints: [`keiyaku @${contractId} arc — opens a new arc to receipt them, then petition`] });
59
+ throw new FlowError("NO_OPEN_ARC", `${loose.length} commits after fence have no arc to receipt them`, { facts: { kind: "loose_commits", contractId, nextVerb: "petition" } });
59
60
  }
60
61
  }
61
62
  export function assertPetitionable(contractId, entries) {
@@ -68,16 +69,24 @@ export function assertPetitionable(contractId, entries) {
68
69
  export async function petitionContract(input) {
69
70
  const at = new Date(input.nowMs).toISOString();
70
71
  const { ledger, deliveryCwd, base, target } = await loadPetitionPreflightContext(input.cwd, input.contractId);
72
+ await assertCleanTrackedWorkingTree(deliveryCwd);
71
73
  await assertPetitionFresh(input.cwd, input.contractId, ledger.entries, base);
72
74
  await assertPetitionArcReady(deliveryCwd, input.contractId, ledger.entries);
73
75
  assertPetitionable(input.contractId, ledger.entries);
76
+ await appendScopeTerms({
77
+ cwd: input.cwd,
78
+ renderCwd: deliveryCwd,
79
+ contractId: input.contractId,
80
+ patterns: input.intent === "claim" ? input.appendScope : undefined,
81
+ actor: input.actor,
82
+ nowMs: input.nowMs,
83
+ });
74
84
  const sealed = await sealCurrentArc({
75
85
  cwd: deliveryCwd,
76
86
  renderCwd: deliveryCwd,
77
87
  contractId: input.contractId,
78
88
  sealedBy: "petition",
79
89
  nowMs: input.nowMs,
80
- waivePaths: input.intent === "claim" ? input.waivePaths : undefined,
81
90
  });
82
91
  const allocated = await allocateSettlementSeat(input.cwd, {
83
92
  target: target.ref,
@@ -146,6 +155,6 @@ export function buildPetitionClaimInput(input) {
146
155
  plea: `Settle contract ${input.contractId} through the petition pipeline.`,
147
156
  oath,
148
157
  signal: input.signal,
149
- waivePaths: input.waivePaths,
158
+ appendScope: input.appendScope,
150
159
  };
151
160
  }
@@ -0,0 +1,143 @@
1
+ import { listContractIds, readLedger } from "../ledger.js";
2
+ import { deriveContractState } from "../status/lifecycle.js";
3
+ import { commissionTarget } from "../status/drift.js";
4
+ export function isCurrentPetitionData(data) {
5
+ return "target" in data && "seat" in data;
6
+ }
7
+ function latestPetition(entries) {
8
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
9
+ const entry = entries[index];
10
+ if (entry.kind === "petition")
11
+ return entry;
12
+ }
13
+ return undefined;
14
+ }
15
+ export function deriveQueueReadModel(ledgers) {
16
+ const seatsByContract = new Map();
17
+ const diagnosticsByContract = new Map();
18
+ const orderedByTarget = new Map();
19
+ for (const ledger of ledgers) {
20
+ if (deriveContractState(ledger.entries).state !== "petitioned")
21
+ continue;
22
+ const petition = latestPetition(ledger.entries);
23
+ if (!petition)
24
+ continue;
25
+ const derived = commissionTarget(ledger.entries);
26
+ if (!derived)
27
+ continue;
28
+ const diagnostics = [];
29
+ let seat;
30
+ if (isCurrentPetitionData(petition.data)) {
31
+ seat = {
32
+ contract: ledger.contractId,
33
+ target: petition.data.target,
34
+ seat: petition.data.seat,
35
+ legacy: false,
36
+ };
37
+ if (petition.data.target !== derived.ref) {
38
+ diagnostics.push({
39
+ kind: "target-mismatch",
40
+ petitioned: petition.data.target,
41
+ derived: derived.ref,
42
+ });
43
+ }
44
+ const bucket = orderedByTarget.get(petition.data.target) ?? [];
45
+ bucket.push(seat);
46
+ orderedByTarget.set(petition.data.target, bucket);
47
+ }
48
+ else {
49
+ seat = {
50
+ contract: ledger.contractId,
51
+ target: derived.ref,
52
+ seat: null,
53
+ legacy: true,
54
+ };
55
+ diagnostics.push({ kind: "legacy-petition" });
56
+ }
57
+ seatsByContract.set(ledger.contractId, seat);
58
+ diagnosticsByContract.set(ledger.contractId, diagnostics);
59
+ }
60
+ for (const [target, seats] of orderedByTarget) {
61
+ const bySeat = new Map();
62
+ for (const seat of seats) {
63
+ if (seat.seat === null)
64
+ continue;
65
+ const group = bySeat.get(seat.seat) ?? [];
66
+ group.push(seat);
67
+ bySeat.set(seat.seat, group);
68
+ }
69
+ for (const [seatNumber, group] of bySeat) {
70
+ if (group.length < 2)
71
+ continue;
72
+ const sorted = [...group].sort((a, b) => a.contract.localeCompare(b.contract));
73
+ for (const member of sorted) {
74
+ const others = sorted.filter((other) => other.contract !== member.contract);
75
+ const existing = diagnosticsByContract.get(member.contract) ?? [];
76
+ for (const other of others) {
77
+ existing.push({ kind: "duplicate-seat", seat: seatNumber, with: other.contract });
78
+ }
79
+ diagnosticsByContract.set(member.contract, existing);
80
+ }
81
+ }
82
+ seats.sort((a, b) => {
83
+ const seatA = a.seat ?? Number.POSITIVE_INFINITY;
84
+ const seatB = b.seat ?? Number.POSITIVE_INFINITY;
85
+ if (seatA !== seatB)
86
+ return seatA - seatB;
87
+ return a.contract.localeCompare(b.contract);
88
+ });
89
+ orderedByTarget.set(target, seats);
90
+ }
91
+ const targetQueues = [...orderedByTarget.entries()]
92
+ .sort(([a], [b]) => a.localeCompare(b))
93
+ .map(([target, ordered]) => ({ target, ordered }));
94
+ return {
95
+ targetQueues,
96
+ seatsByContract,
97
+ diagnosticsByContract,
98
+ };
99
+ }
100
+ export async function readQueueReadModel(cwd) {
101
+ const contractIds = await listContractIds(cwd);
102
+ const ledgers = [];
103
+ for (const id of contractIds) {
104
+ const ledger = await readLedger(cwd, id);
105
+ if (ledger)
106
+ ledgers.push(ledger);
107
+ }
108
+ return deriveQueueReadModel(ledgers);
109
+ }
110
+ export function queueMembership(model, contractId) {
111
+ const seat = model.seatsByContract.get(contractId);
112
+ if (!seat)
113
+ return undefined;
114
+ const diagnostics = model.diagnosticsByContract.get(contractId) ?? [];
115
+ if (seat.legacy) {
116
+ return {
117
+ seat,
118
+ position: null,
119
+ queueLength: 0,
120
+ queueHead: null,
121
+ diagnostics,
122
+ };
123
+ }
124
+ const targetQueue = model.targetQueues.find((queue) => queue.target === seat.target);
125
+ if (!targetQueue) {
126
+ return {
127
+ seat,
128
+ position: null,
129
+ queueLength: 0,
130
+ queueHead: null,
131
+ diagnostics,
132
+ };
133
+ }
134
+ const index = targetQueue.ordered.findIndex((entry) => entry.contract === contractId);
135
+ const position = index < 0 ? null : index + 1;
136
+ return {
137
+ seat,
138
+ position,
139
+ queueLength: targetQueue.ordered.length,
140
+ queueHead: targetQueue.ordered[0]?.contract ?? null,
141
+ diagnostics,
142
+ };
143
+ }
@@ -0,0 +1,156 @@
1
+ import { createHash } from "node:crypto";
2
+ import { FlowError } from "../../flow-error.js";
3
+ import { listContractIds, readLedger } from "../ledger.js";
4
+ import { casUpdateRefLog, createRefLogCommit, listRefLogCommits, readRefLogCommitMessage, resolveRefLogHead, } from "../ref-log.js";
5
+ import { isCurrentPetitionData, queueMembership, } from "./queue-read-model.js";
6
+ const ISO_UTC_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/;
7
+ function isPositiveSafeInteger(value) {
8
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
9
+ }
10
+ export function assertClaimQueueHead(model, contractId) {
11
+ const membership = queueMembership(model, contractId);
12
+ if (!membership) {
13
+ throw new FlowError("INTERNAL_STATE", `contract ${contractId} is not queue head; position=not queued`);
14
+ }
15
+ if (membership.seat.legacy) {
16
+ throw new FlowError("QUEUE_LEGACY_PETITION", `contract ${contractId} petitioned before seat law took effect; reject its petition and petition again`);
17
+ }
18
+ const mismatch = membership.diagnostics.find((diagnostic) => diagnostic.kind === "target-mismatch");
19
+ if (mismatch && mismatch.kind === "target-mismatch") {
20
+ throw new FlowError("QUEUE_TARGET_MISMATCH", `contract ${contractId} petition target ${mismatch.petitioned} disagrees with derived target ${mismatch.derived}; reject its petition and petition again`);
21
+ }
22
+ if (membership.position !== 1) {
23
+ throw new FlowError("INTERNAL_STATE", `contract ${contractId} is not queue head; position=${membership.position ?? "not queued"}`);
24
+ }
25
+ return membership;
26
+ }
27
+ export function seatAllocatorRef(target) {
28
+ const digest = createHash("sha256").update(target, "utf8").digest("hex");
29
+ return `refs/keiyaku/seat/${digest}`;
30
+ }
31
+ function parseSeatAllocatorMessage(message, expectedTarget) {
32
+ const normalized = message.replace(/\r\n/g, "\n");
33
+ const separatorIndex = normalized.indexOf("\n\n");
34
+ if (separatorIndex < 0)
35
+ throw new Error("missing blank line");
36
+ const subject = normalized.slice(0, separatorIndex).trim();
37
+ const body = normalized.slice(separatorIndex + 2).trim();
38
+ const parsed = JSON.parse(body);
39
+ const keys = Object.keys(parsed).sort();
40
+ if (keys.join(",") !== "actor,at,seat,target,v")
41
+ throw new Error("unexpected fields");
42
+ if (parsed.v !== 1)
43
+ throw new Error("bad version");
44
+ if (typeof parsed.target !== "string" || parsed.target !== expectedTarget)
45
+ throw new Error("target mismatch");
46
+ if (!isPositiveSafeInteger(parsed.seat))
47
+ throw new Error("bad seat");
48
+ if (typeof parsed.at !== "string" || !ISO_UTC_RE.test(parsed.at))
49
+ throw new Error("bad at");
50
+ if (typeof parsed.actor !== "string" || parsed.actor.trim().length === 0)
51
+ throw new Error("bad actor");
52
+ if (subject !== `keiyaku seat: ${parsed.seat}`)
53
+ throw new Error("bad subject");
54
+ return {
55
+ v: 1,
56
+ target: parsed.target,
57
+ seat: parsed.seat,
58
+ at: parsed.at,
59
+ actor: parsed.actor,
60
+ };
61
+ }
62
+ async function parseAllocatorChain(cwd, head, expectedTarget) {
63
+ // Intentional degrade: any rev-list or parse failure treats the chain as corrupt.
64
+ let commits;
65
+ try {
66
+ commits = await listRefLogCommits(cwd, head);
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ if (commits.length === 0)
72
+ return null;
73
+ const entries = [];
74
+ let previousSeat = 0;
75
+ for (const commit of commits) {
76
+ try {
77
+ const entry = parseSeatAllocatorMessage(await readRefLogCommitMessage(cwd, commit), expectedTarget);
78
+ if (entry.seat <= previousSeat)
79
+ return null;
80
+ previousSeat = entry.seat;
81
+ entries.push(entry);
82
+ }
83
+ catch {
84
+ return null;
85
+ }
86
+ }
87
+ return { entries, lastSeat: previousSeat };
88
+ }
89
+ async function ledgerSeatFloor(cwd, target) {
90
+ const contractIds = await listContractIds(cwd);
91
+ let maxSeat = 0;
92
+ for (const id of contractIds) {
93
+ const ledger = await readLedger(cwd, id);
94
+ if (!ledger)
95
+ continue;
96
+ for (const entry of ledger.entries) {
97
+ if (entry.kind !== "petition")
98
+ continue;
99
+ if (!isCurrentPetitionData(entry.data))
100
+ continue;
101
+ if (entry.data.target !== target)
102
+ continue;
103
+ if (entry.data.seat > maxSeat)
104
+ maxSeat = entry.data.seat;
105
+ }
106
+ }
107
+ return maxSeat;
108
+ }
109
+ export async function allocateSettlementSeat(cwd, input) {
110
+ const ref = seatAllocatorRef(input.target);
111
+ const maxRetries = 3;
112
+ for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
113
+ // Raw observed-head read: any object id, not commit-only.
114
+ // Non-commit heads are returned so parseAllocatorChain can classify them as corrupt.
115
+ const observedHead = await resolveRefLogHead(cwd, ref, { peel: "object" });
116
+ const floor = await ledgerSeatFloor(cwd, input.target);
117
+ const parsed = observedHead ? await parseAllocatorChain(cwd, observedHead, input.target) : null;
118
+ const healthy = parsed !== null && parsed.lastSeat >= floor;
119
+ let seat;
120
+ let parent;
121
+ let expectedOld;
122
+ if (healthy && parsed) {
123
+ seat = parsed.lastSeat + 1;
124
+ parent = observedHead;
125
+ expectedOld = observedHead;
126
+ }
127
+ else {
128
+ // Missing, parse failure, target mismatch, non-monotonic, or stale-behind-ledger:
129
+ // mint a detached no-parent root at floor+1. Leave the bad chain for Git GC.
130
+ seat = floor + 1;
131
+ parent = null;
132
+ expectedOld = observedHead;
133
+ }
134
+ if (!isPositiveSafeInteger(seat)) {
135
+ throw new FlowError("INTERNAL_STATE", `settlement seats exhausted for ${input.target}`);
136
+ }
137
+ const entry = {
138
+ v: 1,
139
+ target: input.target,
140
+ seat,
141
+ at: input.at,
142
+ actor: input.actor,
143
+ };
144
+ const newHead = await createRefLogCommit(cwd, {
145
+ subject: `keiyaku seat: ${entry.seat}`,
146
+ body: JSON.stringify(entry, null, 2),
147
+ parentHead: parent,
148
+ errorLabel: `seat ${entry.seat}`,
149
+ });
150
+ // Intentional degrade: CAS failure returns false; bounded retry re-reads head.
151
+ const casOk = await casUpdateRefLog(cwd, ref, newHead, expectedOld);
152
+ if (casOk)
153
+ return { head: newHead, seat };
154
+ }
155
+ throw new FlowError("INTERNAL_STATE", `failed to allocate settlement seat for ${input.target}`);
156
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Settlement queue surface: read-model derivation/query and seat allocation/assertion.
3
+ * Implementation lives in sibling files; this module preserves the historical import path.
4
+ */
5
+ export { deriveQueueReadModel, queueMembership, readQueueReadModel, } from "./queue-read-model.js";
6
+ export { allocateSettlementSeat, assertClaimQueueHead, seatAllocatorRef, } from "./queue-seat-allocation.js";