@astrosheep/keiyaku 2.9.13 → 4.0.1

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 (730) hide show
  1. package/README.md +5 -132
  2. package/build/integrations/marketplace/.agents/plugins/marketplace.json +12 -0
  3. package/build/integrations/marketplace/.claude-plugin/marketplace.json +5 -0
  4. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +7 -0
  5. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +18 -0
  6. package/build/integrations/marketplace/plugins/keiyaku/opencode.js +16 -0
  7. package/build/integrations/marketplace/plugins/keiyaku/package.json +8 -0
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +42 -0
  9. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +53 -0
  10. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +94 -0
  11. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/agents/openai.yaml +4 -0
  12. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +97 -0
  13. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +189 -0
  14. package/build/src/akuma/akuma.d.ts +124 -0
  15. package/build/src/akuma/akuma.js +414 -0
  16. package/build/src/akuma/archetype.d.ts +39 -0
  17. package/build/src/akuma/archetype.js +207 -0
  18. package/build/src/akuma/body.d.ts +20 -0
  19. package/build/src/akuma/body.js +417 -0
  20. package/build/src/akuma/coordinate.d.ts +9 -0
  21. package/build/src/akuma/coordinate.js +22 -0
  22. package/build/src/akuma/heart/facts.d.ts +202 -0
  23. package/build/src/akuma/heart/facts.js +9 -0
  24. package/build/src/akuma/heart/index.d.ts +90 -0
  25. package/build/src/akuma/heart/index.js +240 -0
  26. package/build/src/akuma/heart/rows.d.ts +166 -0
  27. package/build/src/akuma/heart/rows.js +299 -0
  28. package/build/src/akuma/heart/schema.d.ts +5 -0
  29. package/build/src/akuma/heart/schema.js +160 -0
  30. package/build/src/akuma/heart/storage.d.ts +33 -0
  31. package/build/src/akuma/heart/storage.js +164 -0
  32. package/build/src/akuma/heart/tells.d.ts +12 -0
  33. package/build/src/akuma/heart/tells.js +79 -0
  34. package/build/src/akuma/heart/timeline.d.ts +15 -0
  35. package/build/src/akuma/heart/timeline.js +86 -0
  36. package/build/src/akuma/identity.d.ts +46 -0
  37. package/build/src/akuma/identity.js +89 -0
  38. package/build/src/akuma/index.d.ts +9 -0
  39. package/build/src/akuma/index.js +3 -0
  40. package/build/src/akuma/projection.d.ts +97 -0
  41. package/build/src/akuma/projection.js +145 -0
  42. package/build/src/akuma/provider.d.ts +169 -0
  43. package/build/src/akuma/provider.js +255 -0
  44. package/build/src/akuma/providers/claude/events.d.ts +52 -0
  45. package/build/src/akuma/providers/claude/events.js +185 -0
  46. package/build/src/akuma/providers/claude/index.d.ts +46 -0
  47. package/build/src/akuma/providers/claude/index.js +265 -0
  48. package/build/src/akuma/providers/claude/input.d.ts +13 -0
  49. package/build/src/akuma/providers/claude/input.js +109 -0
  50. package/build/src/akuma/providers/codex-app-server/events.d.ts +110 -0
  51. package/build/src/akuma/providers/codex-app-server/events.js +337 -0
  52. package/build/src/akuma/providers/codex-app-server/index.d.ts +29 -0
  53. package/build/src/akuma/providers/codex-app-server/index.js +213 -0
  54. package/build/src/akuma/providers/index.d.ts +4 -0
  55. package/build/src/akuma/providers/index.js +85 -0
  56. package/build/src/akuma/providers/opencode-sdk/events.d.ts +48 -0
  57. package/build/src/akuma/providers/opencode-sdk/events.js +116 -0
  58. package/build/src/akuma/providers/opencode-sdk/index.d.ts +32 -0
  59. package/build/src/akuma/providers/opencode-sdk/index.js +203 -0
  60. package/build/src/akuma/providers/opencode-sdk/session.d.ts +41 -0
  61. package/build/src/akuma/providers/opencode-sdk/session.js +62 -0
  62. package/build/src/akuma/providers/pi/events.d.ts +33 -0
  63. package/build/src/akuma/providers/pi/events.js +128 -0
  64. package/build/src/akuma/providers/pi/index.d.ts +11 -0
  65. package/build/src/akuma/providers/pi/index.js +162 -0
  66. package/build/src/akuma/publication.d.ts +10 -0
  67. package/build/src/akuma/publication.js +107 -0
  68. package/build/src/akuma/requests.d.ts +47 -0
  69. package/build/src/akuma/requests.js +391 -0
  70. package/build/src/alias/index.d.ts +18 -0
  71. package/build/src/alias/index.js +103 -0
  72. package/build/src/body/amend.d.ts +2 -0
  73. package/build/src/body/amend.js +289 -0
  74. package/build/src/body/arc.d.ts +2 -0
  75. package/build/src/body/arc.js +54 -0
  76. package/build/src/body/decode.d.ts +4 -0
  77. package/build/src/body/decode.js +146 -0
  78. package/build/src/body/keys.d.ts +4 -0
  79. package/build/src/body/keys.js +11 -0
  80. package/build/src/body/region.d.ts +6 -0
  81. package/build/src/body/region.js +139 -0
  82. package/build/src/body/render.d.ts +4 -0
  83. package/build/src/body/render.js +74 -0
  84. package/build/src/body/shape.d.ts +29 -0
  85. package/build/src/body/shape.js +22 -0
  86. package/build/src/body/types.d.ts +28 -0
  87. package/build/src/body/verification.d.ts +7 -0
  88. package/build/src/body/verification.js +40 -0
  89. package/build/src/cli/accepted.d.ts +18 -0
  90. package/build/src/cli/accepted.js +66 -0
  91. package/build/src/cli/actor.d.ts +8 -0
  92. package/build/src/cli/actor.js +11 -0
  93. package/build/src/cli/commands/akuma-invoke.d.ts +77 -0
  94. package/build/src/cli/commands/akuma-invoke.js +112 -0
  95. package/build/src/cli/commands/akuma.d.ts +50 -0
  96. package/build/src/cli/commands/akuma.js +262 -0
  97. package/build/src/cli/commands/amend.d.ts +13 -0
  98. package/build/src/cli/commands/amend.js +13 -0
  99. package/build/src/cli/commands/bind.d.ts +12 -0
  100. package/build/src/cli/commands/bind.js +17 -0
  101. package/build/src/cli/commands/contract.d.ts +142 -0
  102. package/build/src/cli/commands/contract.js +14 -0
  103. package/build/src/cli/commands/install.d.ts +25 -0
  104. package/build/src/cli/commands/install.js +105 -0
  105. package/build/src/cli/commands/task-invoke.d.ts +11 -0
  106. package/build/src/cli/commands/task-invoke.js +117 -0
  107. package/build/src/cli/commands/task.d.ts +16 -0
  108. package/build/src/cli/commands/task.js +144 -0
  109. package/build/src/cli/index.d.ts +2 -0
  110. package/build/src/cli/index.js +3 -0
  111. package/build/src/cli/invoke.d.ts +22 -0
  112. package/build/src/cli/invoke.js +463 -0
  113. package/build/src/cli/main.d.ts +1 -0
  114. package/build/src/cli/main.js +98 -0
  115. package/build/src/cli/parse.d.ts +107 -0
  116. package/build/src/cli/parse.js +348 -0
  117. package/build/src/cli/render/akuma-tool.d.ts +13 -0
  118. package/build/src/cli/render/akuma-tool.js +72 -0
  119. package/build/src/cli/render/akuma.d.ts +7 -0
  120. package/build/src/cli/render/akuma.js +194 -0
  121. package/build/src/cli/render/board.d.ts +2 -0
  122. package/build/src/cli/render/board.js +4 -0
  123. package/build/src/cli/render/catalog.d.ts +2 -0
  124. package/build/src/cli/render/catalog.js +16 -0
  125. package/build/src/cli/render/contract.d.ts +4 -0
  126. package/build/src/cli/render/contract.js +102 -0
  127. package/build/src/cli/render/kanshi.d.ts +3 -0
  128. package/build/src/cli/render/kanshi.js +252 -0
  129. package/build/src/cli/render/refusal.d.ts +2 -0
  130. package/build/src/cli/render/refusal.js +21 -0
  131. package/build/src/cli/render/settings.d.ts +3 -0
  132. package/build/src/cli/render/settings.js +30 -0
  133. package/build/src/cli/render/task.d.ts +6 -0
  134. package/build/src/cli/render/task.js +105 -0
  135. package/build/src/cli/render/terminal.d.ts +23 -0
  136. package/build/src/cli/render/terminal.js +151 -0
  137. package/build/src/cli/render/text.d.ts +3 -0
  138. package/build/src/cli/render/text.js +20 -0
  139. package/build/src/cli/result.d.ts +67 -0
  140. package/build/src/cli/selectors.d.ts +9 -0
  141. package/build/src/cli/selectors.js +66 -0
  142. package/build/src/cli/usage.d.ts +6 -0
  143. package/build/src/cli/usage.js +19 -0
  144. package/build/src/contract-worktree.d.ts +43 -0
  145. package/build/src/contract-worktree.js +213 -0
  146. package/build/src/coordination/durable-file.d.ts +4 -0
  147. package/build/src/coordination/durable-file.js +79 -0
  148. package/build/src/coordination/sqlite-transaction-lock.d.ts +14 -0
  149. package/build/src/coordination/sqlite-transaction-lock.js +119 -0
  150. package/build/src/core/decide.d.ts +45 -0
  151. package/build/src/core/facts/codec.d.ts +3 -0
  152. package/build/src/core/facts/codec.js +277 -0
  153. package/build/src/core/facts/eligibility.d.ts +7 -0
  154. package/build/src/core/facts/eligibility.js +26 -0
  155. package/build/src/core/facts/errors.d.ts +3 -0
  156. package/build/src/core/facts/errors.js +6 -0
  157. package/build/src/core/facts/fold.d.ts +2 -0
  158. package/build/src/core/facts/fold.js +97 -0
  159. package/build/src/core/facts/gate.d.ts +24 -0
  160. package/build/src/core/facts/gate.js +52 -0
  161. package/build/src/core/facts/observation.d.ts +15 -0
  162. package/build/src/core/facts/observation.js +35 -0
  163. package/build/src/core/facts/offer.d.ts +21 -0
  164. package/build/src/core/facts/types.d.ts +137 -0
  165. package/build/src/core/facts/types.js +66 -0
  166. package/build/src/core/subject.d.ts +21 -0
  167. package/build/src/core/subject.js +89 -0
  168. package/build/src/core/verbs/abandon.d.ts +13 -0
  169. package/build/src/core/verbs/abandon.js +17 -0
  170. package/build/src/core/verbs/amend.d.ts +14 -0
  171. package/build/src/core/verbs/amend.js +52 -0
  172. package/build/src/core/verbs/arc.d.ts +13 -0
  173. package/build/src/core/verbs/arc.js +25 -0
  174. package/build/src/core/verbs/attestation.d.ts +13 -0
  175. package/build/src/core/verbs/attestation.js +21 -0
  176. package/build/src/core/verbs/bind.d.ts +13 -0
  177. package/build/src/core/verbs/bind.js +26 -0
  178. package/build/src/core/verbs/deliver.d.ts +13 -0
  179. package/build/src/core/verbs/deliver.js +42 -0
  180. package/build/src/core/verbs/placement.d.ts +13 -0
  181. package/build/src/core/verbs/placement.js +37 -0
  182. package/build/src/dispatch/index.d.ts +33 -0
  183. package/build/src/dispatch/index.js +168 -0
  184. package/build/src/duration.d.ts +10 -0
  185. package/build/src/duration.js +22 -0
  186. package/build/src/git/admission.d.ts +18 -0
  187. package/build/src/git/admission.js +126 -0
  188. package/build/src/git/hooks.d.ts +49 -0
  189. package/build/src/git/hooks.js +310 -0
  190. package/build/src/git/identity.d.ts +17 -0
  191. package/build/src/git/identity.js +47 -0
  192. package/build/src/git/integration.d.ts +49 -0
  193. package/build/src/git/integration.js +214 -0
  194. package/build/src/git/observe.d.ts +50 -0
  195. package/build/src/git/observe.js +330 -0
  196. package/build/src/git/read-observation.d.ts +41 -0
  197. package/build/src/git/read-observation.js +361 -0
  198. package/build/src/git/reconcile.d.ts +59 -0
  199. package/build/src/git/reconcile.js +376 -0
  200. package/build/src/git/repository.d.ts +95 -0
  201. package/build/src/git/repository.js +490 -0
  202. package/build/src/git/scratch.d.ts +13 -0
  203. package/build/src/git/scratch.js +66 -0
  204. package/build/src/git/target-placement.d.ts +56 -0
  205. package/build/src/git/target-placement.js +255 -0
  206. package/build/src/git/tender.d.ts +48 -0
  207. package/build/src/git/tender.js +82 -0
  208. package/build/src/git/terminal-seal.d.ts +24 -0
  209. package/build/src/git/terminal-seal.js +87 -0
  210. package/build/src/git/tree.d.ts +34 -0
  211. package/build/src/git/tree.js +116 -0
  212. package/build/src/git/workspace.d.ts +21 -0
  213. package/build/src/git/workspace.js +104 -0
  214. package/build/src/identity/coordinates.d.ts +9 -0
  215. package/build/src/identity/coordinates.js +20 -0
  216. package/build/src/identity/normalize.d.ts +8 -0
  217. package/build/src/identity/normalize.js +45 -0
  218. package/build/src/identity/selector.d.ts +12 -0
  219. package/build/src/identity/selector.js +26 -0
  220. package/build/src/index.d.ts +6 -0
  221. package/build/src/index.js +3 -0
  222. package/build/src/kanshi/index.d.ts +5 -0
  223. package/build/src/kanshi/index.js +2 -0
  224. package/build/src/kanshi/read.d.ts +8 -0
  225. package/build/src/kanshi/read.js +209 -0
  226. package/build/src/kanshi/report.d.ts +60 -0
  227. package/build/src/kanshi/select.d.ts +8 -0
  228. package/build/src/kanshi/select.js +21 -0
  229. package/build/src/library/address.d.ts +48 -0
  230. package/build/src/library/address.js +134 -0
  231. package/build/src/library/akuma-creation.d.ts +83 -0
  232. package/build/src/library/akuma-creation.js +152 -0
  233. package/build/src/library/bind.d.ts +21 -0
  234. package/build/src/library/bind.js +56 -0
  235. package/build/src/library/catalog.d.ts +58 -0
  236. package/build/src/library/catalog.js +72 -0
  237. package/build/src/library/configuration.d.ts +17 -0
  238. package/build/src/library/configuration.js +97 -0
  239. package/build/src/library/contract.d.ts +120 -0
  240. package/build/src/library/contract.js +335 -0
  241. package/build/src/library/delivery.d.ts +23 -0
  242. package/build/src/library/delivery.js +21 -0
  243. package/build/src/library/fleet.d.ts +65 -0
  244. package/build/src/library/fleet.js +189 -0
  245. package/build/src/library/input.d.ts +16 -0
  246. package/build/src/library/input.js +101 -0
  247. package/build/src/library/keiyaku.d.ts +42 -0
  248. package/build/src/library/keiyaku.js +26 -0
  249. package/build/src/library/mutation.d.ts +38 -0
  250. package/build/src/library/mutation.js +39 -0
  251. package/build/src/library/refusal.d.ts +21 -0
  252. package/build/src/library/refusal.js +29 -0
  253. package/build/src/library/region.d.ts +18 -0
  254. package/build/src/library/region.js +30 -0
  255. package/build/src/library/repo.d.ts +36 -0
  256. package/build/src/library/repo.js +76 -0
  257. package/build/src/markdown/diff.d.ts +1 -0
  258. package/build/src/markdown/diff.js +4 -0
  259. package/build/src/markdown/lex.d.ts +3 -0
  260. package/build/src/markdown/lex.js +221 -0
  261. package/build/src/markdown/parse.d.ts +2 -0
  262. package/build/src/markdown/parse.js +221 -0
  263. package/build/src/markdown/query.d.ts +21 -0
  264. package/build/src/markdown/query.js +51 -0
  265. package/build/src/markdown/types.d.ts +118 -0
  266. package/build/src/markdown/types.js +6 -0
  267. package/build/src/protocol/attempt.d.ts +49 -0
  268. package/build/src/protocol/attempt.js +150 -0
  269. package/build/src/protocol/bind.d.ts +32 -0
  270. package/build/src/protocol/bind.js +70 -0
  271. package/build/src/protocol/intent.d.ts +76 -0
  272. package/build/src/protocol/intent.js +90 -0
  273. package/build/src/protocol/operations.d.ts +198 -0
  274. package/build/src/protocol/operations.js +485 -0
  275. package/build/src/protocol/outcome.d.ts +23 -0
  276. package/build/src/protocol/outcome.js +21 -0
  277. package/build/src/protocol/placement.d.ts +30 -0
  278. package/build/src/protocol/placement.js +114 -0
  279. package/build/src/protocol/read/audit.d.ts +31 -0
  280. package/build/src/protocol/read/audit.js +55 -0
  281. package/build/src/protocol/read/documents.d.ts +8 -0
  282. package/build/src/protocol/read/documents.js +16 -0
  283. package/build/src/protocol/read/status.d.ts +44 -0
  284. package/build/src/protocol/read/status.js +60 -0
  285. package/build/src/protocol/run.d.ts +81 -0
  286. package/build/src/protocol/run.js +64 -0
  287. package/build/src/runtime/proc/line-rpc.d.ts +38 -0
  288. package/build/src/runtime/proc/line-rpc.js +145 -0
  289. package/build/src/runtime/proc/run.d.ts +70 -0
  290. package/build/src/runtime/proc/run.js +226 -0
  291. package/build/src/settings.d.ts +51 -0
  292. package/build/src/settings.js +114 -0
  293. package/build/src/settlement/fence.d.ts +9 -0
  294. package/build/src/settlement/fence.js +23 -0
  295. package/build/src/settlement/holder.d.ts +36 -0
  296. package/build/src/settlement/holder.js +187 -0
  297. package/build/src/settlement/settle.d.ts +44 -0
  298. package/build/src/settlement/settle.js +165 -0
  299. package/build/src/task/board.d.ts +83 -0
  300. package/build/src/task/board.js +165 -0
  301. package/build/src/task/compose.d.ts +25 -0
  302. package/build/src/task/compose.js +232 -0
  303. package/build/src/task/context.d.ts +4 -0
  304. package/build/src/task/context.js +51 -0
  305. package/build/src/task/document.d.ts +24 -0
  306. package/build/src/task/document.js +118 -0
  307. package/build/src/task/identity.d.ts +12 -0
  308. package/build/src/task/identity.js +47 -0
  309. package/build/src/task/index.d.ts +90 -0
  310. package/build/src/task/index.js +182 -0
  311. package/build/src/task/operations.d.ts +134 -0
  312. package/build/src/task/operations.js +198 -0
  313. package/build/src/task/store.d.ts +20 -0
  314. package/build/src/task/store.js +114 -0
  315. package/build/src/verification/declaration.d.ts +23 -0
  316. package/build/src/verification/declaration.js +14 -0
  317. package/build/src/verification/execution.d.ts +49 -0
  318. package/build/src/verification/execution.js +104 -0
  319. package/build/src/world.d.ts +13 -0
  320. package/build/src/world.js +103 -0
  321. package/package.json +65 -44
  322. package/build/.tsbuildinfo +0 -1
  323. package/build/agents/call-terms.js +0 -32
  324. package/build/agents/harness/activity-values.js +0 -70
  325. package/build/agents/harness/control-types.js +0 -18
  326. package/build/agents/harness/event-channel.js +0 -213
  327. package/build/agents/harness/event-persistence.js +0 -220
  328. package/build/agents/harness/events.js +0 -48
  329. package/build/agents/harness/execution-handle.js +0 -172
  330. package/build/agents/harness/index.js +0 -11
  331. package/build/agents/harness/outcome-error.js +0 -81
  332. package/build/agents/harness/outcome.js +0 -220
  333. package/build/agents/harness/projection.js +0 -369
  334. package/build/agents/harness/provider-adapter.js +0 -58
  335. package/build/agents/harness/router.js +0 -30
  336. package/build/agents/harness/runtime.js +0 -85
  337. package/build/agents/harness/session.js +0 -15
  338. package/build/agents/launch-snapshot/model.js +0 -127
  339. package/build/agents/launch-snapshot/parse-helpers.js +0 -114
  340. package/build/agents/launch-snapshot/resolve.js +0 -46
  341. package/build/agents/opencode-sdk.js +0 -159
  342. package/build/agents/providers/claude-agent-sdk/adapter.js +0 -396
  343. package/build/agents/providers/claude-agent-sdk/events.js +0 -218
  344. package/build/agents/providers/claude-agent-sdk/registration.js +0 -225
  345. package/build/agents/providers/claude-agent-sdk/session-schema.js +0 -2
  346. package/build/agents/providers/claude-agent-sdk/session.js +0 -172
  347. package/build/agents/providers/codex-app-server/adapter.js +0 -387
  348. package/build/agents/providers/codex-app-server/events.js +0 -492
  349. package/build/agents/providers/codex-app-server/identity.js +0 -1
  350. package/build/agents/providers/codex-app-server/policy.js +0 -29
  351. package/build/agents/providers/codex-app-server/registration.js +0 -259
  352. package/build/agents/providers/codex-app-server/session-schema.js +0 -6
  353. package/build/agents/providers/codex-app-server/session.js +0 -273
  354. package/build/agents/providers/event-type-tail.js +0 -16
  355. package/build/agents/providers/opencode-sdk/adapter.js +0 -402
  356. package/build/agents/providers/opencode-sdk/events.js +0 -380
  357. package/build/agents/providers/opencode-sdk/registration.js +0 -146
  358. package/build/agents/providers/opencode-sdk/session-schema.js +0 -2
  359. package/build/agents/providers/opencode-sdk/session.js +0 -187
  360. package/build/agents/providers/pi/adapter.js +0 -285
  361. package/build/agents/providers/pi/checkpoint.js +0 -49
  362. package/build/agents/providers/pi/events.js +0 -285
  363. package/build/agents/providers/pi/registration.js +0 -160
  364. package/build/agents/providers/pi/session-schema.js +0 -6
  365. package/build/agents/providers/registration.js +0 -7
  366. package/build/agents/providers/registry.js +0 -76
  367. package/build/agents/selector.js +0 -120
  368. package/build/agents/session.js +0 -29
  369. package/build/agents/string-tail-buffer.js +0 -44
  370. package/build/agents/types.js +0 -30
  371. package/build/artifact-directories.js +0 -22
  372. package/build/cli/commands/akuma/akuma/handler.js +0 -5
  373. package/build/cli/commands/akuma/akuma/meta.js +0 -17
  374. package/build/cli/commands/akuma/catalog.js +0 -10
  375. package/build/cli/commands/akuma/list/handler.js +0 -15
  376. package/build/cli/commands/akuma/list/meta-list.js +0 -12
  377. package/build/cli/commands/akuma/list/meta-ls.js +0 -9
  378. package/build/cli/commands/akuma/show/handler.js +0 -27
  379. package/build/cli/commands/akuma/show/meta.js +0 -8
  380. package/build/cli/commands/akuma.js +0 -186
  381. package/build/cli/commands/contract/amend/handler.js +0 -17
  382. package/build/cli/commands/contract/amend/meta.js +0 -13
  383. package/build/cli/commands/contract/arc/handler.js +0 -16
  384. package/build/cli/commands/contract/arc/meta.js +0 -28
  385. package/build/cli/commands/contract/audit/handler.js +0 -42
  386. package/build/cli/commands/contract/audit/meta.js +0 -17
  387. package/build/cli/commands/contract/bind/handler.js +0 -39
  388. package/build/cli/commands/contract/bind/meta.js +0 -96
  389. package/build/cli/commands/contract/catalog.js +0 -18
  390. package/build/cli/commands/contract/forfeit/handler.js +0 -17
  391. package/build/cli/commands/contract/forfeit/meta.js +0 -12
  392. package/build/cli/commands/contract/log/handler.js +0 -12
  393. package/build/cli/commands/contract/log/meta.js +0 -12
  394. package/build/cli/commands/contract/petition/handler.js +0 -64
  395. package/build/cli/commands/contract/petition/meta.js +0 -23
  396. package/build/cli/commands/contract/renew/handler.js +0 -65
  397. package/build/cli/commands/contract/renew/meta.js +0 -19
  398. package/build/cli/commands/metadata.js +0 -68
  399. package/build/cli/commands/projection/call/handler.js +0 -43
  400. package/build/cli/commands/projection/call/meta.js +0 -12
  401. package/build/cli/commands/projection/catalog.js +0 -16
  402. package/build/cli/commands/projection/fork/handler.js +0 -61
  403. package/build/cli/commands/projection/fork/meta.js +0 -12
  404. package/build/cli/commands/projection/history/handler.js +0 -65
  405. package/build/cli/commands/projection/history/meta.js +0 -9
  406. package/build/cli/commands/projection/kill/handler.js +0 -20
  407. package/build/cli/commands/projection/kill/meta.js +0 -11
  408. package/build/cli/commands/projection/shared.js +0 -27
  409. package/build/cli/commands/projection/status/handler.js +0 -42
  410. package/build/cli/commands/projection/status/meta.js +0 -20
  411. package/build/cli/commands/projection/tell/handler.js +0 -32
  412. package/build/cli/commands/projection/tell/meta.js +0 -12
  413. package/build/cli/commands/projection/wait/handler.js +0 -80
  414. package/build/cli/commands/projection/wait/meta.js +0 -16
  415. package/build/cli/commands/registry.js +0 -48
  416. package/build/cli/commands/shared.js +0 -74
  417. package/build/cli/commands/skills/catalog.js +0 -6
  418. package/build/cli/commands/skills/install/handler.js +0 -7
  419. package/build/cli/commands/skills/install/meta.js +0 -9
  420. package/build/cli/commands/skills/skills/handler.js +0 -4
  421. package/build/cli/commands/skills/skills/meta.js +0 -10
  422. package/build/cli/commands/system/catalog.js +0 -10
  423. package/build/cli/commands/system/completion/handler.js +0 -10
  424. package/build/cli/commands/system/completion/meta.js +0 -9
  425. package/build/cli/commands/system/dump-env/handler.js +0 -3
  426. package/build/cli/commands/system/dump-env/meta.js +0 -10
  427. package/build/cli/commands/system/guide/handler.js +0 -4
  428. package/build/cli/commands/system/guide/meta.js +0 -9
  429. package/build/cli/commands/task/add/handler.js +0 -38
  430. package/build/cli/commands/task/add/meta.js +0 -31
  431. package/build/cli/commands/task/catalog.js +0 -32
  432. package/build/cli/commands/task/compose/handler.js +0 -18
  433. package/build/cli/commands/task/compose/meta.js +0 -10
  434. package/build/cli/commands/task/doctor/handler.js +0 -3
  435. package/build/cli/commands/task/doctor/meta.js +0 -8
  436. package/build/cli/commands/task/done/handler.js +0 -10
  437. package/build/cli/commands/task/done/meta.js +0 -8
  438. package/build/cli/commands/task/drop/handler.js +0 -8
  439. package/build/cli/commands/task/drop/meta.js +0 -11
  440. package/build/cli/commands/task/hold/handler.js +0 -3
  441. package/build/cli/commands/task/hold/meta.js +0 -8
  442. package/build/cli/commands/task/log/handler.js +0 -12
  443. package/build/cli/commands/task/log/meta.js +0 -8
  444. package/build/cli/commands/task/ls/handler.js +0 -17
  445. package/build/cli/commands/task/ls/meta.js +0 -8
  446. package/build/cli/commands/task/note/handler.js +0 -6
  447. package/build/cli/commands/task/note/meta.js +0 -11
  448. package/build/cli/commands/task/resume/handler.js +0 -3
  449. package/build/cli/commands/task/resume/meta.js +0 -8
  450. package/build/cli/commands/task/shared.js +0 -181
  451. package/build/cli/commands/task/show/handler.js +0 -13
  452. package/build/cli/commands/task/show/meta.js +0 -8
  453. package/build/cli/commands/task/start/handler.js +0 -3
  454. package/build/cli/commands/task/start/meta.js +0 -8
  455. package/build/cli/commands/task/stop/handler.js +0 -10
  456. package/build/cli/commands/task/stop/meta.js +0 -8
  457. package/build/cli/commands/task/task/handler.js +0 -5
  458. package/build/cli/commands/task/task/meta.js +0 -11
  459. package/build/cli/commands/task/update/handler.js +0 -21
  460. package/build/cli/commands/task/update/meta.js +0 -12
  461. package/build/cli/commands/verification/handler.js +0 -43
  462. package/build/cli/commands/verification/meta.js +0 -13
  463. package/build/cli/completion.js +0 -91
  464. package/build/cli/draft-artifact.js +0 -50
  465. package/build/cli/flags.js +0 -321
  466. package/build/cli/help.js +0 -99
  467. package/build/cli/index.js +0 -333
  468. package/build/cli/missing-subcommand.js +0 -7
  469. package/build/cli/output-stream-error-policy.js +0 -31
  470. package/build/cli/parse-flags.js +0 -301
  471. package/build/cli/parse-metadata.js +0 -132
  472. package/build/cli/parse-selectors.js +0 -83
  473. package/build/cli/parse.js +0 -250
  474. package/build/cli/projection-address.js +0 -105
  475. package/build/cli/render/address.js +0 -101
  476. package/build/cli/render/amendment-warning.js +0 -8
  477. package/build/cli/render/arc.js +0 -88
  478. package/build/cli/render/audit.js +0 -440
  479. package/build/cli/render/call.js +0 -70
  480. package/build/cli/render/compact-text.js +0 -3
  481. package/build/cli/render/errors.js +0 -101
  482. package/build/cli/render/format.js +0 -226
  483. package/build/cli/render/kanshi.js +0 -300
  484. package/build/cli/render/kill.js +0 -9
  485. package/build/cli/render/lifecycle.js +0 -56
  486. package/build/cli/render/line-width.js +0 -103
  487. package/build/cli/render/misc.js +0 -84
  488. package/build/cli/render/path-prefix-compaction.js +0 -131
  489. package/build/cli/render/petition.js +0 -85
  490. package/build/cli/render/projection-activity.js +0 -332
  491. package/build/cli/render/projection-history.js +0 -77
  492. package/build/cli/render/response-style.js +0 -27
  493. package/build/cli/render/shared.js +0 -232
  494. package/build/cli/render/skills.js +0 -10
  495. package/build/cli/render/status-indicator.js +0 -47
  496. package/build/cli/render/status.js +0 -243
  497. package/build/cli/render/success-response.js +0 -95
  498. package/build/cli/render/task.js +0 -175
  499. package/build/cli/render/tell.js +0 -11
  500. package/build/cli/render/terminal-failure.js +0 -65
  501. package/build/cli/render/tool-command-normalization.js +0 -137
  502. package/build/cli/render/tool-ledger-rollup.js +0 -74
  503. package/build/cli/render/tool-presentation.js +0 -98
  504. package/build/cli/render/types.js +0 -2
  505. package/build/cli/render/verification.js +0 -23
  506. package/build/cli/render/wait.js +0 -343
  507. package/build/cli/skills-install.js +0 -348
  508. package/build/cli/subagent-guard.js +0 -25
  509. package/build/cli/types.js +0 -2
  510. package/build/config/akuma-loader.js +0 -240
  511. package/build/config/env-keys.js +0 -57
  512. package/build/config/env.js +0 -304
  513. package/build/config/provider-policy-ownership.js +0 -10
  514. package/build/config/settings/disease.js +0 -33
  515. package/build/config/settings/knobs.js +0 -14
  516. package/build/config/settings/loader.js +0 -275
  517. package/build/config/settings/provider-instance-fields.js +0 -51
  518. package/build/config/settings/schema.js +0 -113
  519. package/build/core/address-carrier.js +0 -89
  520. package/build/core/addressing.js +0 -407
  521. package/build/core/amend.js +0 -321
  522. package/build/core/amendment-criteria.js +0 -17
  523. package/build/core/amendment-warning.js +0 -10
  524. package/build/core/arc.js +0 -293
  525. package/build/core/atomic-publish.js +0 -64
  526. package/build/core/audit/candidate.js +0 -141
  527. package/build/core/audit/coordinates.js +0 -230
  528. package/build/core/audit/evidence.js +0 -156
  529. package/build/core/audit/facade.js +0 -65
  530. package/build/core/audit/readiness.js +0 -4
  531. package/build/core/audit/report.js +0 -38
  532. package/build/core/audit.js +0 -1
  533. package/build/core/bind-reconciliation.js +0 -409
  534. package/build/core/bind-workspace.js +0 -115
  535. package/build/core/bind.js +0 -503
  536. package/build/core/call/call.js +0 -235
  537. package/build/core/call/context.js +0 -210
  538. package/build/core/call/execution.js +0 -255
  539. package/build/core/call/prompt.js +0 -27
  540. package/build/core/call/reference.js +0 -24
  541. package/build/core/call-persist.js +0 -76
  542. package/build/core/command-markdown.js +0 -45
  543. package/build/core/context.js +0 -104
  544. package/build/core/contract-carrier-runtime.js +0 -512
  545. package/build/core/contract-carrier.js +0 -353
  546. package/build/core/contract-view.js +0 -319
  547. package/build/core/contract.js +0 -19
  548. package/build/core/derived-replay.js +0 -340
  549. package/build/core/draft.js +0 -400
  550. package/build/core/execution-coordinate.js +0 -46
  551. package/build/core/execution-pact.js +0 -126
  552. package/build/core/forfeit.js +0 -132
  553. package/build/core/hints.js +0 -34
  554. package/build/core/identifier-slug.js +0 -116
  555. package/build/core/ids.js +0 -90
  556. package/build/core/lifecycle-history.js +0 -48
  557. package/build/core/lifecycle-recovery.js +0 -122
  558. package/build/core/lifecycle-runner.js +0 -377
  559. package/build/core/log.js +0 -50
  560. package/build/core/markdown/lex.js +0 -274
  561. package/build/core/markdown/parser.js +0 -260
  562. package/build/core/markdown/render.js +0 -68
  563. package/build/core/markdown/sections.js +0 -80
  564. package/build/core/markdown/titles.js +0 -9
  565. package/build/core/markdown/types.js +0 -6
  566. package/build/core/outcome-base.js +0 -185
  567. package/build/core/places.js +0 -175
  568. package/build/core/projection/akuma-name.js +0 -43
  569. package/build/core/projection/generation/database.js +0 -473
  570. package/build/core/projection/generation/identity.js +0 -84
  571. package/build/core/projection/generation/ledger.js +0 -91
  572. package/build/core/projection/generation/model.js +0 -261
  573. package/build/core/projection/generation/projection-generation-continuation.js +0 -84
  574. package/build/core/projection/generation/projection-generation-doorbell.js +0 -88
  575. package/build/core/projection/generation/projection-generation-execution.js +0 -241
  576. package/build/core/projection/generation/projection-generation-identity.js +0 -21
  577. package/build/core/projection/generation/projection-generation-launcher.js +0 -154
  578. package/build/core/projection/generation/projection-generation-process.js +0 -47
  579. package/build/core/projection/generation/projection-generation-runner.js +0 -489
  580. package/build/core/projection/generation/projection-generation-runtime.js +0 -46
  581. package/build/core/projection/generation/protocol.js +0 -68
  582. package/build/core/projection/generation/store.js +0 -108
  583. package/build/core/projection/generation/transitions.js +0 -463
  584. package/build/core/projection/heart.js +0 -9
  585. package/build/core/projection/index.js +0 -28
  586. package/build/core/projection/projection-activity.js +0 -273
  587. package/build/core/projection/projection-alias.js +0 -131
  588. package/build/core/projection/projection-coordinate.js +0 -61
  589. package/build/core/projection/projection-core.js +0 -127
  590. package/build/core/projection/projection-execution-observer.js +0 -270
  591. package/build/core/projection/projection-history.js +0 -474
  592. package/build/core/projection/projection-identity.js +0 -11
  593. package/build/core/projection/projection-kill.js +0 -112
  594. package/build/core/projection/projection-life-observer.js +0 -101
  595. package/build/core/projection/projection-mint.js +0 -170
  596. package/build/core/projection/projection-status-observation.js +0 -434
  597. package/build/core/projection/projection-status.js +0 -442
  598. package/build/core/projection/projection-terminal-failure.js +0 -111
  599. package/build/core/projection/projection-wait.js +0 -337
  600. package/build/core/projection/projection-wake.js +0 -298
  601. package/build/core/projection/tell/launch-store.js +0 -244
  602. package/build/core/projection/tell/model.js +0 -98
  603. package/build/core/projection/tell/store.js +0 -245
  604. package/build/core/provider-loader-ports.js +0 -4
  605. package/build/core/registry.js +0 -100
  606. package/build/core/renew-build.js +0 -554
  607. package/build/core/renew-plan.js +0 -264
  608. package/build/core/renew-rewrite.js +0 -118
  609. package/build/core/renew.js +0 -345
  610. package/build/core/repository-ledger/accepted-fold-read.js +0 -22
  611. package/build/core/repository-ledger/accepted-tail.js +0 -116
  612. package/build/core/repository-ledger/admission.js +0 -38
  613. package/build/core/repository-ledger/authoritative-transaction.js +0 -1
  614. package/build/core/repository-ledger/claim-evidence.js +0 -147
  615. package/build/core/repository-ledger/codec.js +0 -303
  616. package/build/core/repository-ledger/current-state-store.js +0 -968
  617. package/build/core/repository-ledger/fold-repository.js +0 -374
  618. package/build/core/repository-ledger/fold.js +0 -248
  619. package/build/core/repository-ledger/git-object-store.js +0 -243
  620. package/build/core/repository-ledger/history-read.js +0 -15
  621. package/build/core/repository-ledger/identity.js +0 -60
  622. package/build/core/repository-ledger/incremental-read.js +0 -153
  623. package/build/core/repository-ledger/index.js +0 -15
  624. package/build/core/repository-ledger/inventory-plan.js +0 -75
  625. package/build/core/repository-ledger/inventory.js +0 -310
  626. package/build/core/repository-ledger/publication-admission.js +0 -125
  627. package/build/core/repository-ledger/publication.js +0 -353
  628. package/build/core/repository-ledger/read-model.js +0 -517
  629. package/build/core/repository-ledger/transaction-membership.js +0 -78
  630. package/build/core/repository-ledger/traversal.js +0 -404
  631. package/build/core/repository-ledger/write-transaction.js +0 -346
  632. package/build/core/response-artifact-catalog-sqlite.js +0 -112
  633. package/build/core/response-artifact-catalog.js +0 -7
  634. package/build/core/response-artifact-id.js +0 -5
  635. package/build/core/run-control/connection-bound-close.js +0 -41
  636. package/build/core/run-control/detached-lease-bootstrap.js +0 -208
  637. package/build/core/run-control/detached-process.js +0 -14
  638. package/build/core/run-control/index.js +0 -6
  639. package/build/core/run-control/process-tree.js +0 -139
  640. package/build/core/run-control/runner-lease.js +0 -172
  641. package/build/core/run-control/sqlite-process-lifetime-lock.js +0 -174
  642. package/build/core/scope.js +0 -416
  643. package/build/core/seal.js +0 -364
  644. package/build/core/settlement/claim-delivery.js +0 -82
  645. package/build/core/settlement/claim.js +0 -258
  646. package/build/core/settlement/index.js +0 -19
  647. package/build/core/settlement/petition-claim-gates.js +0 -247
  648. package/build/core/settlement/petition-forfeit.js +0 -46
  649. package/build/core/settlement/petition-head-guard.js +0 -12
  650. package/build/core/settlement/petition-io.js +0 -1
  651. package/build/core/settlement/petition-preview.js +0 -125
  652. package/build/core/settlement/petition-window.js +0 -50
  653. package/build/core/settlement/petition.js +0 -315
  654. package/build/core/settlement/queue-read-model.js +0 -120
  655. package/build/core/settlement/queue-seat-allocation.js +0 -65
  656. package/build/core/settlement/queue.js +0 -6
  657. package/build/core/settlement/settlement.js +0 -385
  658. package/build/core/settlement/verdict.js +0 -126
  659. package/build/core/settlement/verification.js +0 -554
  660. package/build/core/status/board.js +0 -455
  661. package/build/core/status/drift.js +0 -113
  662. package/build/core/status/lifecycle.js +0 -11
  663. package/build/core/stored-agent-event.js +0 -129
  664. package/build/core/structured-query.js +0 -23
  665. package/build/core/target-ref.js +0 -10
  666. package/build/core/task/board.js +0 -248
  667. package/build/core/task/commands.js +0 -401
  668. package/build/core/task/compose.js +0 -328
  669. package/build/core/task/coordinate.js +0 -56
  670. package/build/core/task/document.js +0 -273
  671. package/build/core/task/index.js +0 -16
  672. package/build/core/task/model.js +0 -8
  673. package/build/core/task/query.js +0 -204
  674. package/build/core/task/settlement-git.js +0 -423
  675. package/build/core/task/settlement-policy.js +0 -137
  676. package/build/core/task/source-board.js +0 -104
  677. package/build/core/task/source-model.js +0 -1
  678. package/build/core/task/task-bind-preparation.js +0 -243
  679. package/build/core/task/task-contract.js +0 -371
  680. package/build/core/task/task-doctor.js +0 -14
  681. package/build/core/task/task-file-transaction.js +0 -171
  682. package/build/core/task/task-git-actor.js +0 -33
  683. package/build/core/task/task-git-runtime.js +0 -97
  684. package/build/core/task/task-git-store.js +0 -400
  685. package/build/core/task/task-repository.js +0 -1
  686. package/build/core/task/task-store-repository.js +0 -97
  687. package/build/core/task/task-store.js +0 -1
  688. package/build/core/task/task-worktree.js +0 -25
  689. package/build/core/task/task.js +0 -7
  690. package/build/core/task/tree.js +0 -37
  691. package/build/core/task/validation.js +0 -48
  692. package/build/core/transcripts.js +0 -485
  693. package/build/core/validation.js +0 -17
  694. package/build/core/verification-declaration.js +0 -95
  695. package/build/core/worktree-bootstrap.js +0 -195
  696. package/build/core/worktree-path.js +0 -371
  697. package/build/errno.js +0 -3
  698. package/build/flow-error.js +0 -191
  699. package/build/fs/durability.js +0 -27
  700. package/build/fs/path-coordinate.js +0 -16
  701. package/build/generated/version.js +0 -3
  702. package/build/git/branches.js +0 -84
  703. package/build/git/commits.js +0 -151
  704. package/build/git/core.js +0 -86
  705. package/build/git/diff/parsers.js +0 -181
  706. package/build/git/diff/pathspec.js +0 -3
  707. package/build/git/diff/preview.js +0 -38
  708. package/build/git/diff/read.js +0 -105
  709. package/build/git/diff/structured.js +0 -127
  710. package/build/git/diff/types.js +0 -1
  711. package/build/git/path-coordinate.js +0 -17
  712. package/build/git/process.js +0 -229
  713. package/build/git/refs.js +0 -250
  714. package/build/git/staging.js +0 -79
  715. package/build/git/streaming-batch.js +0 -354
  716. package/build/git/worktree.js +0 -175
  717. package/build/index.js +0 -67
  718. package/build/keiyaku-constants.js +0 -2
  719. package/build/keiyaku.js +0 -30
  720. package/build/telemetry/debug-log.js +0 -40
  721. package/build/telemetry/logger.js +0 -48
  722. package/skills/keiyaku/SKILL.md +0 -46
  723. package/skills/keiyaku-akuma/SKILL.md +0 -97
  724. package/skills/keiyaku-task/SKILL.md +0 -118
  725. package/skills/keiyaku-workflow/SKILL.md +0 -191
  726. /package/build/{agents/launch-snapshot → src/body}/types.js +0 -0
  727. /package/build/{agents/providers/claude-agent-sdk/terms.js → src/cli/result.js} +0 -0
  728. /package/build/{agents/providers/codex-app-server/terms.js → src/core/decide.js} +0 -0
  729. /package/build/{agents/providers/opencode-sdk/terms.js → src/core/facts/offer.js} +0 -0
  730. /package/build/{agents/providers/pi/terms.js → src/kanshi/report.js} +0 -0
@@ -1,968 +0,0 @@
1
- import * as fs from "node:fs/promises";
2
- import * as path from "node:path";
3
- import { createHash, randomUUID } from "node:crypto";
4
- import { DatabaseSync } from "node:sqlite";
5
- import { runGitProcess } from "../../git/core.js";
6
- import { acquireSqliteProcessLifetimeLock } from "../run-control/sqlite-process-lifetime-lock.js";
7
- import { applyFoldEntry } from "./fold.js";
8
- import { createLifecycleEntrySchema, evidenceObjectId, repositoryDeliveryRef } from "./codec.js";
9
- import { repositoryLedgerHead } from "./identity.js";
10
- export const REPOSITORY_CURRENT_STATE_VERSION = 4;
11
- export const REPOSITORY_CURRENT_STATE_PREFIX = "keiyaku-current-state-";
12
- export const REPOSITORY_CURRENT_STATE_SUFFIX = ".sqlite";
13
- const SNAPSHOT_READER_BUSY_MS = 5_000;
14
- const SNAPSHOT_WRITER_LOCK_FILE = "keiyaku-current-state-writer-coordination.sqlite";
15
- const SCHEMA = `
16
- CREATE TABLE snapshot_schema (
17
- singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
18
- version INTEGER NOT NULL CHECK (version = ${REPOSITORY_CURRENT_STATE_VERSION})
19
- ) STRICT;
20
- CREATE TABLE snapshot_pin (
21
- singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
22
- ledger_head TEXT,
23
- object_format TEXT CHECK (object_format IS NULL OR object_format IN ('sha1', 'sha256')),
24
- empty_tree TEXT
25
- ) STRICT;
26
- CREATE TABLE snapshot_contracts (
27
- contract TEXT PRIMARY KEY CHECK (length(contract) > 0),
28
- status TEXT NOT NULL CHECK (status IN ('healthy', 'diseased', 'isolated')),
29
- current_json TEXT CHECK (current_json IS NULL OR json_valid(current_json)),
30
- fold_json TEXT CHECK (fold_json IS NULL OR json_valid(fold_json)),
31
- diagnostics_json TEXT NOT NULL CHECK (json_valid(diagnostics_json))
32
- ) STRICT;
33
- CREATE TABLE snapshot_history (
34
- contract TEXT NOT NULL,
35
- position INTEGER NOT NULL CHECK (position >= 0),
36
- object_id TEXT NOT NULL,
37
- entry_json TEXT NOT NULL CHECK (json_valid(entry_json)),
38
- PRIMARY KEY(contract, position),
39
- UNIQUE(object_id)
40
- ) STRICT;
41
- CREATE TABLE snapshot_summaries (
42
- contract TEXT PRIMARY KEY,
43
- history_json TEXT NOT NULL CHECK (json_valid(history_json))
44
- ) STRICT;
45
- CREATE TABLE snapshot_repository (
46
- singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
47
- diagnostics_json TEXT NOT NULL CHECK (json_valid(diagnostics_json))
48
- ) STRICT;
49
- CREATE TABLE snapshot_topology (
50
- object_id TEXT PRIMARY KEY,
51
- node_json TEXT NOT NULL CHECK (json_valid(node_json))
52
- ) STRICT;
53
- CREATE TABLE snapshot_resources (
54
- kind TEXT NOT NULL CHECK (kind IN ('worktree', 'task')),
55
- resource_key TEXT NOT NULL,
56
- contract TEXT NOT NULL,
57
- PRIMARY KEY(kind, resource_key, contract)
58
- ) STRICT;
59
- CREATE TABLE snapshot_integrity (
60
- receipt_key TEXT PRIMARY KEY,
61
- digest TEXT NOT NULL CHECK (length(digest) = 64)
62
- ) STRICT;
63
- `;
64
- function digest(value) {
65
- return createHash("sha256").update(JSON.stringify(value)).digest("hex");
66
- }
67
- function exactRows(database, sql, ...params) {
68
- return database.prepare(sql).all(...params);
69
- }
70
- function pinDigest(pin) {
71
- return digest(["keiyaku-current-state-v4", REPOSITORY_CURRENT_STATE_VERSION, pin.head, pin.objectFormat, pin.emptyTree]);
72
- }
73
- function repositoryDigest(database) {
74
- return digest(["repository", exactRows(database, "SELECT singleton, diagnostics_json FROM snapshot_repository ORDER BY singleton")]);
75
- }
76
- function topologyDigest(database) {
77
- return digest(["topology", exactRows(database, "SELECT object_id, node_json FROM snapshot_topology ORDER BY object_id")]);
78
- }
79
- function resourcesDigest(database, contract) {
80
- return digest(["resources", contract ?? null, contract === undefined
81
- ? exactRows(database, "SELECT kind, resource_key, contract FROM snapshot_resources ORDER BY kind, resource_key, contract")
82
- : exactRows(database, "SELECT kind, resource_key, contract FROM snapshot_resources WHERE contract = ? ORDER BY kind, resource_key", contract)]);
83
- }
84
- function contractDigest(database, contract, summaryOnly) {
85
- const contractRows = summaryOnly
86
- ? exactRows(database, "SELECT contract, status, current_json, diagnostics_json FROM snapshot_contracts WHERE contract = ?", contract)
87
- : exactRows(database, "SELECT contract, status, current_json, fold_json, diagnostics_json FROM snapshot_contracts WHERE contract = ?", contract);
88
- const historyRows = summaryOnly
89
- ? exactRows(database, "SELECT contract, history_json FROM snapshot_summaries WHERE contract = ?", contract)
90
- : exactRows(database, "SELECT contract, position, object_id, entry_json FROM snapshot_history WHERE contract = ? ORDER BY position", contract);
91
- return digest([summaryOnly ? "contract-summary" : "contract-full", contract, contractRows, historyRows, resourcesDigest(database, contract)]);
92
- }
93
- function receipt(database, key) {
94
- return database.prepare("SELECT digest FROM snapshot_integrity WHERE receipt_key = ?").get(key)?.digest ?? null;
95
- }
96
- function assertReceipt(database, key, actual) {
97
- if (receipt(database, key) !== actual)
98
- throw new Error(`snapshot integrity receipt ${key} is missing or mismatched`);
99
- }
100
- function writeIntegrityReceipts(database) {
101
- database.exec("DELETE FROM snapshot_integrity");
102
- const insert = database.prepare("INSERT INTO snapshot_integrity(receipt_key, digest) VALUES (?, ?)");
103
- const pin = metadata(database);
104
- if (!pin)
105
- throw new Error("snapshot pin is missing while signing current state");
106
- insert.run("pin", pinDigest(pin));
107
- insert.run("repository", repositoryDigest(database));
108
- insert.run("topology", topologyDigest(database));
109
- insert.run("resources", resourcesDigest(database));
110
- const contracts = database.prepare("SELECT contract FROM snapshot_contracts ORDER BY contract").all().map((row) => row.contract);
111
- for (const contract of contracts) {
112
- insert.run(`contract:${contract}:full`, contractDigest(database, contract, false));
113
- insert.run(`contract:${contract}:summary`, contractDigest(database, contract, true));
114
- }
115
- insert.run("contracts", digest(["contracts", contracts.map((contract) => [contract, receipt(database, `contract:${contract}:full`), receipt(database, `contract:${contract}:summary`)])]));
116
- }
117
- function validatePinReceipt(database, pin) {
118
- assertReceipt(database, "pin", pinDigest(pin));
119
- }
120
- function validateContractReceipt(database, contract, summaryOnly) {
121
- assertReceipt(database, `contract:${contract}:${summaryOnly ? "summary" : "full"}`, contractDigest(database, contract, summaryOnly));
122
- }
123
- function validateRepositoryReceipts(database, contracts, summaryOnly, includeTopology) {
124
- assertReceipt(database, "repository", repositoryDigest(database));
125
- assertReceipt(database, "resources", resourcesDigest(database));
126
- for (const contract of contracts)
127
- validateContractReceipt(database, contract, summaryOnly);
128
- const signedContracts = contracts.map((contract) => [contract, receipt(database, `contract:${contract}:full`), receipt(database, `contract:${contract}:summary`)]);
129
- assertReceipt(database, "contracts", digest(["contracts", signedContracts]));
130
- if (includeTopology)
131
- assertReceipt(database, "topology", topologyDigest(database));
132
- }
133
- function snapshotFileName(head) {
134
- return `${REPOSITORY_CURRENT_STATE_PREFIX}${head ?? "empty"}${REPOSITORY_CURRENT_STATE_SUFFIX}`;
135
- }
136
- export async function repositoryCurrentStateSnapshotPath(cwd, head, signal) {
137
- // Addressing callers already pass the resolved primary worktree root. Reuse
138
- // that physical coordinate within this request instead of probing Git again.
139
- const localGitDirectory = path.join(cwd, ".git");
140
- try {
141
- if ((await fs.stat(localGitDirectory)).isDirectory()) {
142
- return path.join(await fs.realpath(localGitDirectory), snapshotFileName(head));
143
- }
144
- }
145
- catch {
146
- // A subdirectory or linked-worktree .git file still needs Git's common-dir witness.
147
- }
148
- const result = await runGitProcess(cwd, ["rev-parse", "--path-format=absolute", "--git-common-dir"], { signal });
149
- if (result.error?.name === "AbortError")
150
- throw result.error;
151
- const commonDir = result.stdout.trim();
152
- if (result.status !== 0 || result.error || !path.isAbsolute(commonDir)) {
153
- throw new Error(`cannot resolve repository common directory: ${result.stderr.trim() || result.error?.message || `exit ${String(result.status)}`}`);
154
- }
155
- return path.join(commonDir, snapshotFileName(head));
156
- }
157
- function classifySnapshotFailure(error) {
158
- const code = error.code;
159
- const message = error instanceof Error ? error.message.toLowerCase() : "";
160
- if (code === "ENOENT" || message.includes("no such file or directory"))
161
- return "missing";
162
- if (code === "ERR_SQLITE_BUSY" || code === "ERR_SQLITE_LOCKED" || message.includes("database is locked") || message.includes("database is busy"))
163
- return "transient";
164
- if (code === "ERR_SQLITE_CORRUPT" || code === "ERR_SQLITE_NOTADB" || message.includes("database disk image is malformed") || message.includes("file is not a database"))
165
- return "corrupt";
166
- return "validation-failure";
167
- }
168
- function isCantOpen(error) {
169
- const code = error.code;
170
- const message = error instanceof Error ? error.message.toLowerCase() : "";
171
- return code === "ERR_SQLITE_CANTOPEN" || message.includes("unable to open database file");
172
- }
173
- async function snapshotExists(databasePath) {
174
- try {
175
- await fs.lstat(databasePath);
176
- return true;
177
- }
178
- catch (error) {
179
- if (error.code === "ENOENT")
180
- return false;
181
- return undefined;
182
- }
183
- }
184
- async function openValidated(databasePath) {
185
- const existedBeforeOpen = await snapshotExists(databasePath);
186
- let database;
187
- try {
188
- database = new DatabaseSync(databasePath, { readOnly: true });
189
- database.exec(`PRAGMA busy_timeout = ${SNAPSHOT_READER_BUSY_MS}; PRAGMA query_only = ON`);
190
- const rows = database.prepare("SELECT version FROM snapshot_schema WHERE singleton = 1").all();
191
- if (rows.length !== 1 || rows[0]?.version !== REPOSITORY_CURRENT_STATE_VERSION) {
192
- database.close();
193
- return { kind: "validation-failure" };
194
- }
195
- return { kind: "opened", database };
196
- }
197
- catch (error) {
198
- try {
199
- database.close();
200
- }
201
- catch { /* open did not yield a usable connection */ }
202
- if (isCantOpen(error)) {
203
- const existsAfterFailure = await snapshotExists(databasePath);
204
- if (existedBeforeOpen === false || existsAfterFailure === false)
205
- return { kind: "missing", error };
206
- }
207
- return { kind: classifySnapshotFailure(error), error };
208
- }
209
- }
210
- async function readSnapshot(databasePath, read) {
211
- const opened = await openValidated(databasePath);
212
- if (opened.kind !== "opened")
213
- return opened;
214
- try {
215
- return { kind: "read", value: read(opened.database) };
216
- }
217
- catch (error) {
218
- return { kind: classifySnapshotFailure(error), error };
219
- }
220
- finally {
221
- try {
222
- opened.database.close();
223
- }
224
- catch { /* validation failure already has its outcome */ }
225
- }
226
- }
227
- export function currentStateWriterCoordination(databasePath) {
228
- const lockPath = path.join(path.dirname(databasePath), SNAPSHOT_WRITER_LOCK_FILE);
229
- return {
230
- path: lockPath,
231
- async acquire(signal) {
232
- const lease = await acquireSqliteProcessLifetimeLock({ path: lockPath, signal });
233
- return { release: () => lease.close() };
234
- },
235
- };
236
- }
237
- async function withSnapshotWriter(databasePath, signal, operation) {
238
- const lock = await currentStateWriterCoordination(databasePath).acquire(signal);
239
- try {
240
- return await operation();
241
- }
242
- finally {
243
- lock.release();
244
- }
245
- }
246
- function temporarySnapshotPath(databasePath) {
247
- return `${databasePath}.${process.pid}.${randomUUID()}.tmp`;
248
- }
249
- async function discardTemporarySnapshot(databasePath) {
250
- await fs.unlink(databasePath).catch((error) => {
251
- if (error.code !== "ENOENT")
252
- throw error;
253
- });
254
- }
255
- /** Writers alone publish or retire cache bytes; readers have no filesystem mutation path. */
256
- async function publishImmutableSnapshot(buildPath, databasePath) {
257
- if (await snapshotExists(databasePath))
258
- return false;
259
- await fs.rename(buildPath, databasePath);
260
- return true;
261
- }
262
- /**
263
- * A filename becomes published only after its complete signed contents validate.
264
- * This runs under writer coordination; readers merely report an unusable cache.
265
- */
266
- async function preparePublicationTarget(databasePath, expectedHead) {
267
- const snapshot = await readSnapshot(databasePath, (database) => {
268
- const pin = metadata(database);
269
- if (!pin || pin.head !== expectedHead)
270
- throw new Error("snapshot pin does not match its immutable filename");
271
- validatePinReceipt(database, pin);
272
- const rows = database.prepare(`
273
- SELECT contract, status, current_json AS currentJson, fold_json AS foldJson, diagnostics_json AS diagnosticsJson
274
- FROM snapshot_contracts ORDER BY contract
275
- `).all();
276
- const repository = database.prepare("SELECT diagnostics_json AS diagnosticsJson FROM snapshot_repository WHERE singleton = 1").get();
277
- if (!repository)
278
- throw new Error("snapshot repository row is missing");
279
- validateRepositoryReceipts(database, rows.map((row) => row.contract), false, true);
280
- parseDiagnostics(repository.diagnosticsJson);
281
- for (const row of rows) {
282
- parseDiagnostics(row.diagnosticsJson, row.contract);
283
- validateContractConsistency(database, row, pin);
284
- }
285
- });
286
- if (snapshot.kind === "read")
287
- return "published";
288
- if (snapshot.kind === "missing")
289
- return "missing";
290
- if (snapshot.kind === "transient")
291
- return "transient";
292
- await fs.unlink(databasePath).catch((error) => {
293
- if (error.code !== "ENOENT")
294
- throw error;
295
- });
296
- return "missing";
297
- }
298
- async function garbageCollectSnapshots(databasePath) {
299
- const directory = path.dirname(databasePath);
300
- const retained = path.basename(databasePath);
301
- let entries;
302
- try {
303
- entries = await fs.readdir(directory);
304
- }
305
- catch {
306
- return;
307
- }
308
- const cacheFile = /^keiyaku-current-state-(?:[0-9a-f]{40}|[0-9a-f]{64}|empty)\.sqlite(?:\..+\.tmp)?$/;
309
- await Promise.all(entries
310
- .filter((entry) => entry !== retained && cacheFile.test(entry))
311
- .map((entry) => fs.unlink(path.join(directory, entry)).catch(() => undefined)));
312
- }
313
- function parseJson(text) {
314
- return JSON.parse(text);
315
- }
316
- function parseDiagnostics(text, contract) {
317
- const value = JSON.parse(text);
318
- if (!Array.isArray(value) || value.some((item) => !isRecord(item)
319
- || typeof item.objectId !== "string" || typeof item.code !== "string" || typeof item.detail !== "string"
320
- || (contract !== undefined && item.contract !== contract))) {
321
- throw new Error("snapshot diagnostics are invalid or disagree with their owner");
322
- }
323
- return value;
324
- }
325
- function isRecord(value) {
326
- return typeof value === "object" && value !== null && !Array.isArray(value);
327
- }
328
- function assertClosedKeys(value, keys, label) {
329
- const actual = Object.keys(value).sort();
330
- const expected = [...keys].sort();
331
- if (actual.length !== expected.length || actual.some((key, index) => key !== expected[index])) {
332
- throw new Error(`${label} has an unknown or missing field`);
333
- }
334
- }
335
- function parseCurrent(text, contract) {
336
- const value = JSON.parse(text);
337
- if (!isRecord(value))
338
- throw new Error("snapshot current facts are not an object");
339
- assertClosedKeys(value, ["contractHead", "contract", "phase", "intent", "receiptSegments", "seal", "bootstrapReplay", "petition", "verdict", "pins", "effectiveScope", "causal", "resources"], "snapshot current facts");
340
- if (value.contract !== contract || typeof value.contractHead !== "string" || !isRecord(value.resources)) {
341
- throw new Error("snapshot current facts disagree with their row key");
342
- }
343
- return value;
344
- }
345
- function readHistory(database, contract, summaryOnly = false, objectFormat = "sha1") {
346
- if (summaryOnly) {
347
- const row = database.prepare("SELECT history_json AS historyJson FROM snapshot_summaries WHERE contract = ?").get(contract);
348
- if (!row)
349
- throw new Error("snapshot current summary is missing");
350
- const value = JSON.parse(row.historyJson);
351
- if (!Array.isArray(value) || value.some((item) => !isRecord(item) || typeof item.objectId !== "string" || !createLifecycleEntrySchema(objectFormat).safeParse(item.entry).success || item.entry.contract !== contract)) {
352
- throw new Error("snapshot current summary is invalid");
353
- }
354
- return value;
355
- }
356
- const rows = database.prepare("SELECT position, object_id AS objectId, entry_json AS entryJson FROM snapshot_history WHERE contract = ? ORDER BY position").all(contract);
357
- if (!summaryOnly && rows.some((row, index) => row.position !== index))
358
- throw new Error("snapshot lifecycle history positions are not contiguous");
359
- const history = rows.map((row) => {
360
- const parsed = createLifecycleEntrySchema(objectFormat).safeParse(JSON.parse(row.entryJson));
361
- if (!parsed.success || parsed.data.contract !== contract)
362
- throw new Error("snapshot lifecycle history row is invalid");
363
- return { objectId: row.objectId, entry: parsed.data };
364
- });
365
- return history;
366
- }
367
- function summaryHistory(history) {
368
- return history.filter(({ entry }, index) => entry.kind === "bind" || entry.kind === "petition" || index === history.length - 1)
369
- .filter((row, index, rows) => rows.findIndex((candidate) => candidate.objectId === row.objectId) === index);
370
- }
371
- function currentModel(database, contract, currentJson, summaryOnly = false, objectFormat = "sha1") {
372
- return { ...parseCurrent(currentJson, contract), history: readHistory(database, contract, summaryOnly, objectFormat) };
373
- }
374
- function validateContractConsistency(database, input, pin, summaryOnly = false) {
375
- if ((input.currentJson === null) !== (input.foldJson === null))
376
- throw new Error("snapshot current/fold presence disagrees");
377
- if (input.status !== "isolated" && input.currentJson === null)
378
- throw new Error("non-isolated snapshot row has no current facts");
379
- if (input.currentJson === null) {
380
- if (readHistory(database, input.contract).length !== 0)
381
- throw new Error("isolated snapshot row retains lifecycle history");
382
- return null;
383
- }
384
- if (!pin.objectFormat)
385
- throw new Error("snapshot contract row has no object format");
386
- const model = currentModel(database, input.contract, input.currentJson, summaryOnly, pin.objectFormat);
387
- const diagnosticRow = database.prepare("SELECT diagnostics_json AS diagnosticsJson FROM snapshot_contracts WHERE contract = ?").get(input.contract);
388
- const diagnostics = parseDiagnostics(diagnosticRow.diagnosticsJson, input.contract);
389
- if ((input.status === "healthy") !== (diagnostics.length === 0))
390
- throw new Error("snapshot status disagrees with diagnostics");
391
- if (summaryOnly)
392
- return model;
393
- const fold = JSON.parse(input.foldJson);
394
- if (!isRecord(fold) || fold.contract !== input.contract || !Array.isArray(fold.entryObjectIds))
395
- throw new Error("snapshot fold is invalid");
396
- const objectIds = model.history.map((row) => row.objectId);
397
- if (fold.entryObjectIds.length !== objectIds.length || fold.entryObjectIds.some((oid, index) => oid !== objectIds[index])) {
398
- throw new Error("snapshot fold and lifecycle history disagree");
399
- }
400
- if (model.contractHead !== objectIds.at(-1) || model.phase !== fold.phase || model.pins.base !== fold.bind?.data?.base) {
401
- throw new Error("snapshot current facts disagree with fold or pin");
402
- }
403
- const typedFold = fold;
404
- const expectedWorktree = typedFold.bind.data.workspace === "worktree"
405
- ? { place: typedFold.bind.data.place, state: typedFold.terminalObjectId === null ? "held" : "released" }
406
- : null;
407
- const expectedTasks = (typedFold.bind.data.taskIds ?? []).map((taskId) => ({ taskId, state: typedFold.terminal?.kind === "forfeit" ? "released" : "held" }));
408
- const petitionRow = [...model.history].reverse().find(({ entry }) => entry.kind === "petition");
409
- const verdictRow = [...model.history].reverse().find(({ entry }) => entry.kind === "verdict");
410
- const arcRow = [...model.history].reverse().find(({ entry }) => entry.kind === "arc");
411
- const expectedIntent = arcRow?.entry.kind === "arc"
412
- ? { arc: arcRow.entry.data.arc, openedBy: arcRow.objectId, title: arcRow.entry.data.title, objective: arcRow.entry.data.objective, brief: arcRow.entry.data.brief }
413
- : { arc: 0, openedBy: typedFold.entryObjectIds[0], title: typedFold.bind.data.title, objective: typedFold.bind.data.objective, brief: null };
414
- const expectedPetition = typedFold.terminalObjectId !== null || !typedFold.petition || !petitionRow || petitionRow.entry.kind !== "petition"
415
- ? { state: "none" }
416
- : {
417
- state: typedFold.phase === "approved" && typedFold.verdict ? "approved" : "awaiting-verdict",
418
- objectId: petitionRow.objectId,
419
- intent: typedFold.petition.data.intent,
420
- seat: typedFold.petition.data.seat,
421
- target: typedFold.petition.data.target,
422
- targetHead: typedFold.petition.data.intent === "claim" ? typedFold.petition.data.targetHead : null,
423
- ...(typedFold.phase === "approved" && typedFold.verdict && verdictRow ? { verdictObjectId: verdictRow.objectId, summary: typedFold.verdict.data.summary } : {}),
424
- };
425
- const expectedVerdict = verdictRow?.entry.kind === "verdict"
426
- ? { objectId: verdictRow.objectId, result: verdictRow.entry.data.result, summary: verdictRow.entry.data.summary }
427
- : null;
428
- if (model.pins.delivery !== typedFold.deliveryHead
429
- || model.pins.target.ref !== typedFold.target
430
- || model.pins.target.approvedHead !== (typedFold.approvedTargetSnapshot?.targetHead ?? null)
431
- || JSON.stringify(model.effectiveScope) !== JSON.stringify(typedFold.effectiveScope)
432
- || JSON.stringify(model.receiptSegments) !== JSON.stringify(typedFold.segments)
433
- || JSON.stringify(model.seal) !== JSON.stringify(typedFold.segments.at(-1)?.seal ?? null)
434
- || JSON.stringify(model.intent) !== JSON.stringify(expectedIntent)
435
- || JSON.stringify(model.petition) !== JSON.stringify(expectedPetition)
436
- || JSON.stringify(model.verdict) !== JSON.stringify(expectedVerdict)
437
- || JSON.stringify(model.causal.after) !== JSON.stringify(typedFold.bind.data.after ?? [])
438
- || model.resources.deliveryRef !== repositoryDeliveryRef(input.contract)
439
- || JSON.stringify(model.resources.worktree) !== JSON.stringify(expectedWorktree)
440
- || JSON.stringify(model.resources.tasks) !== JSON.stringify(expectedTasks)) {
441
- throw new Error("snapshot nested current facts disagree with the accepted fold");
442
- }
443
- const actualResources = database.prepare("SELECT kind, resource_key AS resourceKey FROM snapshot_resources WHERE contract = ? ORDER BY kind, resource_key").all(input.contract);
444
- const expectedResources = [
445
- ...(model.resources.worktree?.state === "held" ? [{ kind: "worktree", resourceKey: model.resources.worktree.place }] : []),
446
- ...model.resources.tasks.filter((task) => task.state === "held").map((task) => ({ kind: "task", resourceKey: task.taskId })),
447
- ].sort((left, right) => left.kind.localeCompare(right.kind) || left.resourceKey.localeCompare(right.resourceKey));
448
- if (JSON.stringify(actualResources) !== JSON.stringify(expectedResources))
449
- throw new Error("snapshot resource rows disagree with current facts");
450
- return model;
451
- }
452
- function metadata(database) {
453
- const rows = database.prepare("SELECT ledger_head AS head, object_format AS objectFormat, empty_tree AS emptyTree FROM snapshot_pin WHERE singleton = 1").all();
454
- return rows.length === 1 ? rows[0] : null;
455
- }
456
- function storedContract(database, contract) {
457
- const row = database.prepare(`
458
- SELECT contract, status, current_json AS currentJson, fold_json AS foldJson, diagnostics_json AS diagnosticsJson
459
- FROM snapshot_contracts WHERE contract = ?
460
- `).get(contract);
461
- if (!row)
462
- return null;
463
- const pin = metadata(database);
464
- if (!pin)
465
- throw new Error("snapshot pin is missing");
466
- return {
467
- contract: row.contract,
468
- status: row.status,
469
- model: validateContractConsistency(database, row, pin),
470
- diagnostics: parseDiagnostics(row.diagnosticsJson, contract),
471
- };
472
- }
473
- function atPin(model, _head) {
474
- return model;
475
- }
476
- export async function readPinnedCurrentContract(cwd, observedHead, contract, signal) {
477
- const databasePath = await repositoryCurrentStateSnapshotPath(cwd, observedHead, signal);
478
- const snapshot = await readSnapshot(databasePath, (database) => {
479
- const pin = metadata(database);
480
- if (!pin || pin.head !== observedHead)
481
- return null;
482
- validatePinReceipt(database, pin);
483
- const row = storedContract(database, contract);
484
- if (row)
485
- validateContractReceipt(database, contract, false);
486
- if (row?.status === "healthy" && row.model)
487
- return { status: "healthy", model: atPin(row.model, observedHead), diagnostics: [] };
488
- if (row?.status === "diseased" && row.model)
489
- return { status: "diseased", model: atPin(row.model, observedHead), diagnostics: row.diagnostics };
490
- if (row?.status === "isolated")
491
- return { status: "isolated", contract, diagnostics: row.diagnostics };
492
- assertReceipt(database, "repository", repositoryDigest(database));
493
- const repository = database.prepare("SELECT diagnostics_json AS diagnosticsJson FROM snapshot_repository WHERE singleton = 1").get();
494
- const unattributed = repository ? parseDiagnostics(repository.diagnosticsJson).filter((disease) => disease.contract === undefined) : [];
495
- return unattributed.length > 0
496
- ? { status: "indeterminate", contract, diagnostics: unattributed }
497
- : { status: "absent", contract, diagnostics: [] };
498
- });
499
- return snapshot.kind === "read" ? snapshot.value : null;
500
- }
501
- export async function readRepositoryCurrentStatePin(cwd, observedHead, signal) {
502
- const databasePath = await repositoryCurrentStateSnapshotPath(cwd, observedHead, signal);
503
- const snapshot = await readSnapshot(databasePath, (database) => {
504
- const pin = metadata(database);
505
- if (!pin)
506
- return undefined;
507
- validatePinReceipt(database, pin);
508
- return pin.head;
509
- });
510
- return snapshot.kind === "read" ? snapshot.value : undefined;
511
- }
512
- /**
513
- * The first commit parent is the only inexpensive candidate for a linear
514
- * incremental predecessor. It is not a current pointer: the caller still
515
- * validates the cache addressed by that exact OID before using it.
516
- */
517
- export async function readRepositoryCurrentStatePredecessor(cwd, observedHead, signal) {
518
- const result = await runGitProcess(cwd, ["show", "-s", "--format=%P", observedHead], { signal });
519
- if (result.error?.name === "AbortError")
520
- throw result.error;
521
- if (result.status !== 0 || result.error)
522
- return null;
523
- return result.stdout.trim().split(/\s+/)[0] || null;
524
- }
525
- export async function readRepositoryCurrentStateNodeIds(cwd, observedHead, signal) {
526
- const databasePath = await repositoryCurrentStateSnapshotPath(cwd, observedHead, signal);
527
- const snapshot = await readSnapshot(databasePath, (database) => {
528
- const pin = metadata(database);
529
- if (!pin || pin.head !== observedHead)
530
- return null;
531
- validatePinReceipt(database, pin);
532
- assertReceipt(database, "topology", topologyDigest(database));
533
- const rows = database.prepare("SELECT object_id AS objectId, node_json AS nodeJson FROM snapshot_topology").all();
534
- const ledgerParents = new Map();
535
- const entryIntroductions = new Map();
536
- for (const row of rows) {
537
- const node = JSON.parse(row.nodeJson);
538
- if (node.objectId !== row.objectId || !Array.isArray(node.ledgerParents) || node.ledgerParents.some((parent) => typeof parent !== "string"))
539
- throw new Error("snapshot topology row is invalid");
540
- ledgerParents.set(row.objectId, node.ledgerParents);
541
- if (node.type === "transaction") {
542
- if (!Array.isArray(node.entryObjectIds) || node.entryObjectIds.some((entry) => typeof entry !== "string"))
543
- throw new Error("snapshot transaction topology is invalid");
544
- for (const entry of node.entryObjectIds) {
545
- if (entryIntroductions.has(entry))
546
- throw new Error("snapshot topology repeats an entry introduction");
547
- entryIntroductions.set(entry, row.objectId);
548
- }
549
- }
550
- }
551
- return { ledgerParents, entryIntroductions };
552
- });
553
- return snapshot.kind === "read" ? snapshot.value : null;
554
- }
555
- /** Rehydrate the accepted typed topology for publication admission without Git history traversal. */
556
- export async function readPinnedAcceptedTraversal(cwd, observedHead, signal) {
557
- const databasePath = await repositoryCurrentStateSnapshotPath(cwd, observedHead, signal);
558
- const snapshot = await readSnapshot(databasePath, (database) => {
559
- const pin = metadata(database);
560
- if (!pin || pin.head !== observedHead || !pin.objectFormat || !pin.emptyTree)
561
- return null;
562
- validatePinReceipt(database, pin);
563
- assertReceipt(database, "repository", repositoryDigest(database));
564
- assertReceipt(database, "topology", topologyDigest(database));
565
- assertReceipt(database, "resources", resourcesDigest(database));
566
- const repository = database.prepare("SELECT diagnostics_json AS diagnosticsJson FROM snapshot_repository WHERE singleton = 1").get();
567
- const contractRows = database.prepare("SELECT contract, status, diagnostics_json AS diagnosticsJson FROM snapshot_contracts").all();
568
- validateRepositoryReceipts(database, contractRows.map((row) => row.contract).sort(), false, true);
569
- if (!repository || parseDiagnostics(repository.diagnosticsJson).length > 0 || contractRows.some((row) => row.status !== "healthy" || parseDiagnostics(row.diagnosticsJson, row.contract).length > 0))
570
- return null;
571
- const historyRows = database.prepare("SELECT object_id AS objectId, entry_json AS entryJson FROM snapshot_history").all();
572
- const entries = new Map(historyRows.map((row) => {
573
- const parsed = createLifecycleEntrySchema(pin.objectFormat).parse(JSON.parse(row.entryJson));
574
- return [row.objectId, parsed];
575
- }));
576
- const topologyRows = database.prepare("SELECT object_id AS objectId, node_json AS nodeJson FROM snapshot_topology ORDER BY rowid").all();
577
- const nodes = new Map();
578
- const order = [];
579
- for (const row of topologyRows) {
580
- const node = JSON.parse(row.nodeJson);
581
- if (node.objectId !== row.objectId || !Array.isArray(node.ledgerParents))
582
- return null;
583
- let typed;
584
- if (node.type === "lifecycle") {
585
- const entry = entries.get(row.objectId);
586
- if (!entry || node.ledgerParents.length > 1)
587
- return null;
588
- typed = { type: "lifecycle", objectId: row.objectId, entry, ledgerParents: node.ledgerParents, evidenceParent: evidenceObjectId(entry) };
589
- }
590
- else if (node.type === "transaction" && node.verb && node.contract && node.entryObjectIds && node.finalEntryObjectId) {
591
- typed = { type: "transaction", objectId: row.objectId, transaction: { v: 1, kind: "transaction", verb: node.verb, predecessor: node.ledgerParents.length === 0 ? "none" : "p1" }, ledgerParents: node.ledgerParents, entryObjectIds: node.entryObjectIds, contract: node.contract, finalEntryObjectId: node.finalEntryObjectId, evidenceParent: null };
592
- }
593
- else if (node.type === "join" && node.ledgerParents.length === 2) {
594
- typed = { type: "join", objectId: row.objectId, join: { v: 1, kind: "join", at: "1970-01-01T00:00:00.000Z", actor: "snapshot" }, ledgerParents: node.ledgerParents, evidenceParent: null };
595
- }
596
- else
597
- return null;
598
- nodes.set(row.objectId, typed);
599
- }
600
- const visited = new Set();
601
- const visit = (objectId) => {
602
- if (visited.has(objectId))
603
- return;
604
- visited.add(objectId);
605
- const node = nodes.get(objectId);
606
- if (!node)
607
- return;
608
- const dependencies = node.type === "transaction" ? [...node.ledgerParents, ...node.entryObjectIds] : [...node.ledgerParents];
609
- for (const dependency of dependencies)
610
- visit(dependency);
611
- order.push(objectId);
612
- };
613
- visit(observedHead);
614
- return { head: observedHead, coordinates: { objectFormat: pin.objectFormat, objectIdLength: pin.objectFormat === "sha1" ? 40 : 64, emptyTree: pin.emptyTree }, nodes, order, diseases: [] };
615
- });
616
- return snapshot.kind === "read" ? snapshot.value : null;
617
- }
618
- export async function readPinnedRepositoryLifecycle(cwd, observedHead, signal, options = {}) {
619
- const databasePath = await repositoryCurrentStateSnapshotPath(cwd, observedHead, signal);
620
- const snapshot = await readSnapshot(databasePath, (database) => {
621
- const pin = metadata(database);
622
- if (!pin || pin.head !== observedHead)
623
- return null;
624
- const rows = database.prepare(`
625
- SELECT contract, status, current_json AS currentJson, fold_json AS foldJson, diagnostics_json AS diagnosticsJson
626
- FROM snapshot_contracts ORDER BY contract
627
- `).all();
628
- const repository = database.prepare("SELECT diagnostics_json AS diagnosticsJson FROM snapshot_repository WHERE singleton = 1").get();
629
- if (!repository)
630
- throw new Error("snapshot repository row is missing");
631
- validatePinReceipt(database, pin);
632
- validateRepositoryReceipts(database, rows.map((row) => row.contract), options.summaryOnly === true, options.includeTopology !== false);
633
- return {
634
- observedLedgerHead: pin.head === null ? null : repositoryLedgerHead(pin.head),
635
- objectFormat: pin.objectFormat,
636
- emptyTree: pin.emptyTree,
637
- contracts: rows.flatMap((row) => {
638
- const model = validateContractConsistency(database, row, pin, options.summaryOnly);
639
- if (!model)
640
- return [];
641
- return [atPin(model, pin.head)];
642
- }),
643
- isolatedContracts: rows.filter((row) => row.status === "isolated").map((row) => row.contract),
644
- diagnostics: [
645
- ...parseDiagnostics(repository.diagnosticsJson),
646
- ...rows.flatMap((row) => parseDiagnostics(row.diagnosticsJson, row.contract)),
647
- ],
648
- topology: {
649
- head: pin.head,
650
- nodes: options.includeTopology === false
651
- ? []
652
- : database.prepare("SELECT node_json AS nodeJson FROM snapshot_topology ORDER BY rowid").all().map((row) => parseJson(row.nodeJson)),
653
- },
654
- };
655
- });
656
- return snapshot.kind === "read" ? snapshot.value : null;
657
- }
658
- export async function publishRepositoryCurrentState(cwd, read, options) {
659
- const databasePath = await repositoryCurrentStateSnapshotPath(cwd, read.observedLedgerHead, options.signal);
660
- await fs.mkdir(path.dirname(databasePath), { recursive: true });
661
- if (await options.confirmHead() !== read.observedLedgerHead)
662
- return false;
663
- return withSnapshotWriter(databasePath, options.signal, async () => {
664
- if (await options.confirmHead() !== read.observedLedgerHead)
665
- return false;
666
- const existing = await preparePublicationTarget(databasePath, read.observedLedgerHead);
667
- if (existing === "published")
668
- return true;
669
- if (existing === "transient")
670
- return false;
671
- const buildPath = temporarySnapshotPath(databasePath);
672
- let database;
673
- try {
674
- await fs.unlink(buildPath).catch((error) => {
675
- if (error.code !== "ENOENT")
676
- throw error;
677
- });
678
- database = new DatabaseSync(buildPath);
679
- database.exec("PRAGMA synchronous = FULL; PRAGMA journal_mode = DELETE; BEGIN IMMEDIATE");
680
- database.exec("DROP TABLE IF EXISTS snapshot_integrity; DROP TABLE IF EXISTS snapshot_resources; DROP TABLE IF EXISTS snapshot_topology; DROP TABLE IF EXISTS snapshot_summaries; DROP TABLE IF EXISTS snapshot_history; DROP TABLE IF EXISTS snapshot_contracts; DROP TABLE IF EXISTS snapshot_repository; DROP TABLE IF EXISTS snapshot_pin; DROP TABLE IF EXISTS snapshot_schema");
681
- database.exec(SCHEMA);
682
- database.prepare("INSERT INTO snapshot_schema(singleton, version) VALUES (1, ?)").run(REPOSITORY_CURRENT_STATE_VERSION);
683
- database.prepare("INSERT INTO snapshot_pin(singleton, ledger_head, object_format, empty_tree) VALUES (1, ?, ?, ?)").run(read.observedLedgerHead, read.objectFormat, read.emptyTree);
684
- const insert = database.prepare("INSERT INTO snapshot_contracts(contract, status, current_json, fold_json, diagnostics_json) VALUES (?, ?, ?, ?, ?)");
685
- const insertHistory = database.prepare("INSERT INTO snapshot_history(contract, position, object_id, entry_json) VALUES (?, ?, ?, ?)");
686
- const insertSummary = database.prepare("INSERT INTO snapshot_summaries(contract, history_json) VALUES (?, ?)");
687
- const isolated = new Set(read.isolatedContracts);
688
- const models = new Map(read.contracts.map((model) => [model.contract, model]));
689
- for (const contract of new Set([...models.keys(), ...isolated])) {
690
- const model = models.get(contract) ?? null;
691
- const diagnostics = read.diagnostics.filter((disease) => disease.contract === contract);
692
- const status = isolated.has(contract) ? "isolated" : diagnostics.length > 0 ? "diseased" : "healthy";
693
- const folded = options.fold.contracts.get(contract) ?? null;
694
- const current = model === null ? null : Object.fromEntries(Object.entries(model).filter(([key]) => key !== "history"));
695
- insert.run(contract, status, current === null ? null : JSON.stringify(current), folded === null ? null : JSON.stringify(folded), JSON.stringify(diagnostics));
696
- model?.history.forEach((row, position) => insertHistory.run(contract, position, row.objectId, JSON.stringify(row.entry)));
697
- if (model)
698
- insertSummary.run(contract, JSON.stringify(summaryHistory(model.history)));
699
- }
700
- database.prepare("INSERT INTO snapshot_repository(singleton, diagnostics_json) VALUES (1, ?)").run(JSON.stringify(read.diagnostics.filter((disease) => disease.contract === undefined)));
701
- const insertTopology = database.prepare("INSERT INTO snapshot_topology(object_id, node_json) VALUES (?, ?)");
702
- for (const node of read.topology.nodes)
703
- insertTopology.run(node.objectId, JSON.stringify(node));
704
- const insertResource = database.prepare("INSERT INTO snapshot_resources(kind, resource_key, contract) VALUES (?, ?, ?)");
705
- for (const model of read.contracts) {
706
- if (model.resources.worktree?.state === "held")
707
- insertResource.run("worktree", model.resources.worktree.place, model.contract);
708
- for (const task of model.resources.tasks)
709
- if (task.state === "held")
710
- insertResource.run("task", task.taskId, model.contract);
711
- }
712
- writeIntegrityReceipts(database);
713
- await options.beforeCommit?.();
714
- database.exec("COMMIT");
715
- database.close();
716
- // No reader can be holding this new name. An existing same-head file is
717
- // convergence, never a target for replacement.
718
- await publishImmutableSnapshot(buildPath, databasePath);
719
- await garbageCollectSnapshots(databasePath);
720
- return true;
721
- }
722
- catch (error) {
723
- try {
724
- database.exec("ROLLBACK");
725
- }
726
- catch { /* database may not have opened */ }
727
- try {
728
- database.close();
729
- }
730
- catch { /* database may not have opened */ }
731
- await discardTemporarySnapshot(buildPath);
732
- throw error;
733
- }
734
- });
735
- }
736
- export async function advanceRepositoryCurrentState(cwd, pinnedHead, observedHead, segment, options) {
737
- const pinnedDatabasePath = await repositoryCurrentStateSnapshotPath(cwd, pinnedHead, options.signal);
738
- const databasePath = await repositoryCurrentStateSnapshotPath(cwd, observedHead, options.signal);
739
- if (await options.confirmHead() !== observedHead)
740
- return false;
741
- return withSnapshotWriter(databasePath, options.signal, async () => {
742
- if (await options.confirmHead() !== observedHead)
743
- return false;
744
- const existing = await preparePublicationTarget(databasePath, observedHead);
745
- if (existing === "published")
746
- return true;
747
- if (existing === "transient")
748
- return false;
749
- const buildPath = temporarySnapshotPath(databasePath);
750
- let database;
751
- try {
752
- await fs.copyFile(pinnedDatabasePath, buildPath);
753
- database = new DatabaseSync(buildPath);
754
- database.exec("PRAGMA synchronous = FULL; BEGIN IMMEDIATE");
755
- const versions = database.prepare("SELECT version FROM snapshot_schema WHERE singleton = 1").all();
756
- if (versions.length !== 1 || versions[0]?.version !== REPOSITORY_CURRENT_STATE_VERSION) {
757
- database.exec("ROLLBACK");
758
- database.close();
759
- return false;
760
- }
761
- }
762
- catch {
763
- try {
764
- database.close();
765
- }
766
- catch { /* replacement recovery owns unusable bytes */ }
767
- return false;
768
- }
769
- try {
770
- const pin = metadata(database);
771
- if (!pin || pin.head !== pinnedHead) {
772
- database.exec("ROLLBACK");
773
- return false;
774
- }
775
- validatePinReceipt(database, pin);
776
- assertReceipt(database, "topology", topologyDigest(database));
777
- assertReceipt(database, "resources", resourcesDigest(database));
778
- for (const contract of new Set(segment.transactions.map((transaction) => transaction.entries[0]?.entry.contract).filter((contract) => contract !== undefined))) {
779
- if (database.prepare("SELECT 1 FROM snapshot_contracts WHERE contract = ?").get(contract))
780
- validateContractReceipt(database, contract, false);
781
- }
782
- const acceptedTopology = new Set(database.prepare("SELECT object_id AS objectId FROM snapshot_topology").all().map((row) => row.objectId));
783
- const pendingJoins = new Map(segment.joins.map((join) => [join.objectId, join]));
784
- const promoteReadyJoins = () => {
785
- let promoted;
786
- do {
787
- promoted = false;
788
- for (const join of pendingJoins.values()) {
789
- if (!join.parents.every((parent) => acceptedTopology.has(parent)))
790
- continue;
791
- database.prepare("INSERT INTO snapshot_topology(object_id, node_json) VALUES (?, ?)").run(join.objectId, JSON.stringify({
792
- objectId: join.objectId,
793
- type: "join",
794
- ledgerParents: join.parents,
795
- }));
796
- acceptedTopology.add(join.objectId);
797
- pendingJoins.delete(join.objectId);
798
- promoted = true;
799
- }
800
- } while (promoted);
801
- };
802
- for (const transaction of segment.transactions) {
803
- promoteReadyJoins();
804
- if ((transaction.predecessor !== null && !acceptedTopology.has(transaction.predecessor)) || transaction.entries.length === 0) {
805
- database.exec("ROLLBACK");
806
- return false;
807
- }
808
- if (transaction.entries.some((entry) => database.prepare("SELECT 1 FROM snapshot_history WHERE object_id = ?").get(entry.objectId) !== undefined)) {
809
- database.exec("ROLLBACK");
810
- return false;
811
- }
812
- const contract = transaction.entries[0].entry.contract;
813
- const row = database.prepare("SELECT status, current_json AS currentJson, fold_json AS foldJson, diagnostics_json AS diagnosticsJson FROM snapshot_contracts WHERE contract = ?").get(contract);
814
- let state = row?.foldJson ? parseJson(row.foldJson) : undefined;
815
- const priorModel = row?.currentJson ? currentModel(database, contract, row.currentJson) : null;
816
- const first = transaction.entries[0];
817
- if (first.entry.kind === "bind" && (state || row)) {
818
- const diagnostics = [...(row ? parseJson(row.diagnosticsJson) : []), {
819
- objectId: first.objectId,
820
- code: "same-contract-divergence",
821
- contract,
822
- detail: "incremental bind diverges from an already admitted contract",
823
- }];
824
- database.prepare("UPDATE snapshot_contracts SET status = 'isolated', current_json = NULL, fold_json = NULL, diagnostics_json = ? WHERE contract = ?").run(JSON.stringify(diagnostics), contract);
825
- }
826
- else {
827
- if (first.entry.kind !== "bind" && (!state || first.causalParent !== state.entryObjectIds.at(-1))) {
828
- database.exec("ROLLBACK");
829
- return false;
830
- }
831
- let staged = state === undefined ? undefined : structuredClone(state);
832
- let disease;
833
- const basePosition = staged?.entryObjectIds.length ?? 0;
834
- for (let index = 0; index < transaction.entries.length; index += 1) {
835
- const entry = transaction.entries[index];
836
- const applied = applyFoldEntry(staged, { objectId: entry.objectId, entry: entry.entry, position: basePosition + index });
837
- staged = applied.state;
838
- if (applied.disease) {
839
- disease = { ...applied.disease, transactionObjectId: transaction.objectId };
840
- break;
841
- }
842
- }
843
- if (disease || !staged) {
844
- const diagnostics = [...(row ? parseJson(row.diagnosticsJson) : []), ...(disease ? [disease] : [])];
845
- if (row)
846
- database.prepare("UPDATE snapshot_contracts SET status = 'diseased', diagnostics_json = ? WHERE contract = ?").run(JSON.stringify(diagnostics), contract);
847
- else
848
- database.prepare("INSERT INTO snapshot_contracts(contract, status, current_json, fold_json, diagnostics_json) VALUES (?, 'isolated', NULL, NULL, ?)").run(contract, JSON.stringify(diagnostics));
849
- }
850
- else {
851
- if (first.entry.kind === "bind" && (first.entry.data.after?.length ?? 0) > 0) {
852
- const unavailable = first.entry.data.after.filter((dependency) => {
853
- const prerequisite = database.prepare("SELECT status, fold_json AS foldJson FROM snapshot_contracts WHERE contract = ?").get(dependency);
854
- if (!prerequisite || prerequisite.status !== "healthy" || prerequisite.foldJson === null)
855
- return true;
856
- return false;
857
- });
858
- if (unavailable.length > 0) {
859
- const diagnostic = {
860
- objectId: first.objectId,
861
- code: "causal-prerequisite",
862
- contract,
863
- detail: `after prerequisites are not admitted healthy contracts: ${unavailable.join(", ")}`,
864
- };
865
- database.prepare(`
866
- INSERT INTO snapshot_contracts(contract, status, current_json, fold_json, diagnostics_json)
867
- VALUES (?, 'isolated', NULL, NULL, ?)
868
- ON CONFLICT(contract) DO UPDATE SET status = 'isolated', current_json = NULL, fold_json = NULL, diagnostics_json = excluded.diagnostics_json
869
- `).run(contract, JSON.stringify([diagnostic]));
870
- acceptedTopology.add(transaction.objectId);
871
- database.prepare("INSERT INTO snapshot_topology(object_id, node_json) VALUES (?, ?)").run(transaction.objectId, JSON.stringify({
872
- objectId: transaction.objectId,
873
- type: "transaction",
874
- ledgerParents: transaction.predecessor === null ? [] : [transaction.predecessor],
875
- verb: transaction.transaction.verb,
876
- contract,
877
- entryObjectIds: transaction.entries.map((entry) => entry.objectId),
878
- finalEntryObjectId: transaction.entries.at(-1).objectId,
879
- }));
880
- continue;
881
- }
882
- }
883
- const history = [...(priorModel?.history ?? []), ...transaction.entries.map((entry) => ({ objectId: entry.objectId, entry: entry.entry }))];
884
- const model = await options.materialize(staged, history);
885
- database.prepare(`
886
- INSERT INTO snapshot_contracts(contract, status, current_json, fold_json, diagnostics_json)
887
- VALUES (?, 'healthy', ?, ?, '[]')
888
- ON CONFLICT(contract) DO UPDATE SET status = 'healthy', current_json = excluded.current_json, fold_json = excluded.fold_json, diagnostics_json = '[]'
889
- `).run(contract, JSON.stringify(Object.fromEntries(Object.entries(model).filter(([key]) => key !== "history"))), JSON.stringify(staged));
890
- database.prepare("DELETE FROM snapshot_history WHERE contract = ?").run(contract);
891
- const insertHistory = database.prepare("INSERT INTO snapshot_history(contract, position, object_id, entry_json) VALUES (?, ?, ?, ?)");
892
- model.history.forEach((historyRow, position) => insertHistory.run(contract, position, historyRow.objectId, JSON.stringify(historyRow.entry)));
893
- database.prepare("INSERT INTO snapshot_summaries(contract, history_json) VALUES (?, ?) ON CONFLICT(contract) DO UPDATE SET history_json = excluded.history_json").run(contract, JSON.stringify(summaryHistory(model.history)));
894
- database.prepare("DELETE FROM snapshot_resources WHERE contract = ?").run(contract);
895
- const insertResource = database.prepare("INSERT INTO snapshot_resources(kind, resource_key, contract) VALUES (?, ?, ?)");
896
- if (model.resources.worktree?.state === "held")
897
- insertResource.run("worktree", model.resources.worktree.place, contract);
898
- for (const task of model.resources.tasks)
899
- if (task.state === "held")
900
- insertResource.run("task", task.taskId, contract);
901
- const collisions = [
902
- ...(model.resources.worktree?.state === "held" ? [{ kind: "worktree", key: model.resources.worktree.place }] : []),
903
- ...model.resources.tasks.filter((task) => task.state === "held").map((task) => ({ kind: "task", key: task.taskId })),
904
- ];
905
- for (const resource of collisions) {
906
- const owners = database.prepare("SELECT contract FROM snapshot_resources WHERE kind = ? AND resource_key = ?").all(resource.kind, resource.key);
907
- if (owners.length < 2)
908
- continue;
909
- for (const owner of owners) {
910
- const ownerRow = database.prepare("SELECT diagnostics_json AS diagnosticsJson FROM snapshot_contracts WHERE contract = ?").get(owner.contract);
911
- const diagnostic = {
912
- objectId: first.objectId,
913
- code: resource.kind === "worktree" ? "worktree-place-collision" : "task-ownership-collision",
914
- contract: owner.contract,
915
- detail: `${resource.kind} ${resource.key} is held by ${owners.map((candidate) => candidate.contract).sort().join(", ")}`,
916
- };
917
- database.prepare("UPDATE snapshot_contracts SET status = 'isolated', current_json = NULL, fold_json = NULL, diagnostics_json = ? WHERE contract = ?").run(JSON.stringify([...parseJson(ownerRow.diagnosticsJson), diagnostic]), owner.contract);
918
- }
919
- }
920
- }
921
- }
922
- const insertLifecycleTopology = database.prepare("INSERT OR IGNORE INTO snapshot_topology(object_id, node_json) VALUES (?, ?)");
923
- for (const entry of transaction.entries)
924
- insertLifecycleTopology.run(entry.objectId, JSON.stringify({
925
- objectId: entry.objectId,
926
- type: "lifecycle",
927
- ledgerParents: entry.causalParent === null ? [] : [entry.causalParent],
928
- }));
929
- database.prepare("INSERT INTO snapshot_topology(object_id, node_json) VALUES (?, ?)").run(transaction.objectId, JSON.stringify({
930
- objectId: transaction.objectId,
931
- type: "transaction",
932
- ledgerParents: transaction.predecessor === null ? [] : [transaction.predecessor],
933
- verb: transaction.transaction.verb,
934
- contract,
935
- entryObjectIds: transaction.entries.map((entry) => entry.objectId),
936
- finalEntryObjectId: transaction.entries.at(-1).objectId,
937
- }));
938
- acceptedTopology.add(transaction.objectId);
939
- }
940
- promoteReadyJoins();
941
- if (pendingJoins.size > 0 || !acceptedTopology.has(observedHead)) {
942
- database.exec("ROLLBACK");
943
- return false;
944
- }
945
- database.prepare("UPDATE snapshot_pin SET ledger_head = ? WHERE singleton = 1").run(observedHead);
946
- writeIntegrityReceipts(database);
947
- database.exec("COMMIT");
948
- database.close();
949
- await publishImmutableSnapshot(buildPath, databasePath);
950
- await garbageCollectSnapshots(databasePath);
951
- return true;
952
- }
953
- catch {
954
- try {
955
- database.exec("ROLLBACK");
956
- }
957
- catch { /* handled by recovery */ }
958
- return false;
959
- }
960
- finally {
961
- try {
962
- database.close();
963
- }
964
- catch { /* database may not have opened */ }
965
- await discardTemporarySnapshot(buildPath);
966
- }
967
- });
968
- }