@astrosheep/keiyaku 2.9.12 → 4.0.0

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