@astrosheep/keiyaku 4.0.0 → 4.0.2

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 (308) hide show
  1. package/README.md +133 -8
  2. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +2 -2
  3. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +4 -4
  4. package/build/integrations/marketplace/plugins/keiyaku/opencode.js +2 -2
  5. package/build/integrations/marketplace/plugins/keiyaku/package.json +2 -2
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +13 -5
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -32
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +134 -0
  9. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/agents/openai.yaml +4 -0
  10. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +41 -6
  11. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +262 -46
  12. package/build/src/akuma/abort.d.ts +2 -0
  13. package/build/src/akuma/abort.js +50 -0
  14. package/build/src/akuma/akuma.d.ts +50 -33
  15. package/build/src/akuma/akuma.js +175 -127
  16. package/build/src/akuma/archetype.d.ts +14 -5
  17. package/build/src/akuma/archetype.js +85 -39
  18. package/build/src/akuma/body.d.ts +3 -5
  19. package/build/src/akuma/body.js +490 -183
  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 +88 -45
  23. package/build/src/akuma/heart/facts.js +19 -8
  24. package/build/src/akuma/heart/index.d.ts +64 -55
  25. package/build/src/akuma/heart/index.js +172 -252
  26. package/build/src/akuma/heart/rows.d.ts +38 -83
  27. package/build/src/akuma/heart/rows.js +117 -155
  28. package/build/src/akuma/heart/schema.d.ts +1 -1
  29. package/build/src/akuma/heart/schema.js +61 -22
  30. package/build/src/akuma/heart/soul.d.ts +8 -0
  31. package/build/src/akuma/heart/soul.js +136 -0
  32. package/build/src/akuma/heart/storage.d.ts +47 -0
  33. package/build/src/akuma/heart/storage.js +224 -0
  34. package/build/src/akuma/heart/tells.d.ts +12 -0
  35. package/build/src/akuma/heart/tells.js +79 -0
  36. package/build/src/akuma/heart/timeline.d.ts +15 -0
  37. package/build/src/akuma/heart/timeline.js +86 -0
  38. package/build/src/akuma/identity.d.ts +2 -2
  39. package/build/src/akuma/identity.js +9 -9
  40. package/build/src/akuma/index.d.ts +10 -3
  41. package/build/src/akuma/index.js +7 -1
  42. package/build/src/akuma/projection.d.ts +176 -0
  43. package/build/src/akuma/projection.js +256 -0
  44. package/build/src/akuma/provider-recipe.d.ts +24 -0
  45. package/build/src/akuma/provider-recipe.js +100 -0
  46. package/build/src/akuma/provider.d.ts +67 -13
  47. package/build/src/akuma/provider.js +172 -105
  48. package/build/src/akuma/providers/acp/core.d.ts +19 -0
  49. package/build/src/akuma/providers/acp/core.js +159 -0
  50. package/build/src/akuma/providers/acp/events.d.ts +20 -0
  51. package/build/src/akuma/providers/acp/events.js +73 -0
  52. package/build/src/akuma/providers/acp/index.d.ts +12 -0
  53. package/build/src/akuma/providers/acp/index.js +94 -0
  54. package/build/src/akuma/providers/{claude.d.ts → claude/events.d.ts} +9 -41
  55. package/build/src/akuma/providers/claude/events.js +238 -0
  56. package/build/src/akuma/providers/claude/index.d.ts +47 -0
  57. package/build/src/akuma/providers/claude/index.js +279 -0
  58. package/build/src/akuma/providers/claude/input.d.ts +13 -0
  59. package/build/src/akuma/providers/claude/input.js +109 -0
  60. package/build/src/akuma/providers/codex-app-server/events.d.ts +1 -1
  61. package/build/src/akuma/providers/codex-app-server/events.js +15 -12
  62. package/build/src/akuma/providers/codex-app-server/index.d.ts +15 -13
  63. package/build/src/akuma/providers/codex-app-server/index.js +77 -33
  64. package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
  65. package/build/src/akuma/providers/grok-build/index.js +70 -0
  66. package/build/src/akuma/providers/index.d.ts +5 -3
  67. package/build/src/akuma/providers/index.js +35 -56
  68. package/build/src/akuma/providers/opencode-sdk/events.d.ts +54 -0
  69. package/build/src/akuma/providers/opencode-sdk/events.js +235 -0
  70. package/build/src/akuma/providers/opencode-sdk/index.d.ts +33 -0
  71. package/build/src/akuma/providers/opencode-sdk/index.js +308 -0
  72. package/build/src/akuma/providers/opencode-sdk/session.d.ts +26 -0
  73. package/build/src/akuma/providers/opencode-sdk/session.js +63 -0
  74. package/build/src/akuma/providers/pi/events.d.ts +33 -0
  75. package/build/src/akuma/providers/pi/events.js +166 -0
  76. package/build/src/akuma/providers/pi/index.d.ts +11 -0
  77. package/build/src/akuma/providers/pi/index.js +191 -0
  78. package/build/src/akuma/publication.d.ts +3 -3
  79. package/build/src/akuma/publication.js +28 -40
  80. package/build/src/akuma/requests.d.ts +9 -6
  81. package/build/src/akuma/requests.js +95 -65
  82. package/build/src/alias/index.d.ts +4 -3
  83. package/build/src/alias/index.js +12 -13
  84. package/build/src/body/decode.js +7 -1
  85. package/build/src/body/region.d.ts +2 -0
  86. package/build/src/body/region.js +77 -7
  87. package/build/src/body/render.js +2 -1
  88. package/build/src/body/shape.js +7 -1
  89. package/build/src/body/verification.js +19 -4
  90. package/build/src/cli/accepted.d.ts +18 -12
  91. package/build/src/cli/accepted.js +73 -34
  92. package/build/src/cli/actor.js +3 -3
  93. package/build/src/cli/commands/akuma-invoke.d.ts +44 -19
  94. package/build/src/cli/commands/akuma-invoke.js +101 -52
  95. package/build/src/cli/commands/akuma.d.ts +27 -9
  96. package/build/src/cli/commands/akuma.js +151 -80
  97. package/build/src/cli/commands/contract.d.ts +155 -0
  98. package/build/src/cli/commands/contract.js +20 -0
  99. package/build/src/cli/commands/install.js +2 -0
  100. package/build/src/cli/commands/task-invoke.d.ts +19 -4
  101. package/build/src/cli/commands/task-invoke.js +65 -17
  102. package/build/src/cli/commands/task-query.d.ts +5 -0
  103. package/build/src/cli/commands/task-query.js +247 -0
  104. package/build/src/cli/commands/task.d.ts +3 -1
  105. package/build/src/cli/commands/task.js +52 -14
  106. package/build/src/cli/coordinates.d.ts +18 -0
  107. package/build/src/cli/coordinates.js +120 -0
  108. package/build/src/cli/draft.d.ts +8 -0
  109. package/build/src/cli/draft.js +96 -0
  110. package/build/src/cli/invoke.d.ts +9 -3
  111. package/build/src/cli/invoke.js +287 -108
  112. package/build/src/cli/main.js +54 -7
  113. package/build/src/cli/parse.d.ts +21 -117
  114. package/build/src/cli/parse.js +79 -84
  115. package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
  116. package/build/src/cli/render/akuma-tool-command.js +144 -0
  117. package/build/src/cli/render/akuma-tool.d.ts +4 -2
  118. package/build/src/cli/render/akuma-tool.js +35 -5
  119. package/build/src/cli/render/akuma.d.ts +3 -1
  120. package/build/src/cli/render/akuma.js +247 -212
  121. package/build/src/cli/render/audit.d.ts +3 -0
  122. package/build/src/cli/render/audit.js +104 -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 +3 -3
  126. package/build/src/cli/render/contract.js +200 -54
  127. package/build/src/cli/render/kanshi.js +272 -129
  128. package/build/src/cli/render/receipt.d.ts +19 -0
  129. package/build/src/cli/render/receipt.js +106 -0
  130. package/build/src/cli/render/refusal.d.ts +16 -2
  131. package/build/src/cli/render/refusal.js +88 -3
  132. package/build/src/cli/render/region.d.ts +2 -0
  133. package/build/src/cli/render/region.js +17 -0
  134. package/build/src/cli/render/task.d.ts +2 -1
  135. package/build/src/cli/render/task.js +223 -60
  136. package/build/src/cli/render/terminal.d.ts +20 -0
  137. package/build/src/cli/render/terminal.js +121 -0
  138. package/build/src/cli/render/text.js +11 -3
  139. package/build/src/cli/result.d.ts +126 -19
  140. package/build/src/cli/usage.d.ts +1 -0
  141. package/build/src/cli/usage.js +3 -0
  142. package/build/src/contract-worktree.d.ts +44 -0
  143. package/build/src/contract-worktree.js +251 -0
  144. package/build/src/coordination/durable-file.d.ts +5 -1
  145. package/build/src/coordination/durable-file.js +57 -10
  146. package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
  147. package/build/src/coordination/sqlite-transaction-lock.js +22 -5
  148. package/build/src/core/facts/codec.js +23 -4
  149. package/build/src/core/facts/eligibility.d.ts +1 -10
  150. package/build/src/core/facts/eligibility.js +0 -49
  151. package/build/src/core/facts/fold.js +1 -6
  152. package/build/src/core/facts/gate.d.ts +1 -0
  153. package/build/src/core/facts/gate.js +1 -0
  154. package/build/src/core/facts/observation.d.ts +3 -0
  155. package/build/src/core/facts/observation.js +12 -0
  156. package/build/src/core/facts/types.d.ts +10 -3
  157. package/build/src/core/subject.js +2 -2
  158. package/build/src/core/verbs/amend.d.ts +1 -1
  159. package/build/src/core/verbs/amend.js +3 -18
  160. package/build/src/core/verbs/bind.js +2 -16
  161. package/build/src/core/verbs/deliver.d.ts +1 -1
  162. package/build/src/core/verbs/deliver.js +14 -4
  163. package/build/src/core/verbs/placement.d.ts +1 -1
  164. package/build/src/core/verbs/placement.js +7 -9
  165. package/build/src/dispatch/index.d.ts +5 -3
  166. package/build/src/dispatch/index.js +30 -21
  167. package/build/src/duration.d.ts +10 -0
  168. package/build/src/duration.js +22 -0
  169. package/build/src/git/admission.d.ts +2 -2
  170. package/build/src/git/admission.js +33 -23
  171. package/build/src/git/hooks.d.ts +15 -0
  172. package/build/src/git/hooks.js +70 -18
  173. package/build/src/git/identity.d.ts +5 -1
  174. package/build/src/git/identity.js +23 -4
  175. package/build/src/git/integration.d.ts +48 -0
  176. package/build/src/git/integration.js +250 -0
  177. package/build/src/git/observe.d.ts +29 -15
  178. package/build/src/git/observe.js +185 -76
  179. package/build/src/git/read-observation.d.ts +41 -0
  180. package/build/src/git/read-observation.js +361 -0
  181. package/build/src/git/reconcile.d.ts +17 -5
  182. package/build/src/git/reconcile.js +305 -109
  183. package/build/src/git/repository.d.ts +41 -18
  184. package/build/src/git/repository.js +220 -114
  185. package/build/src/git/scratch.d.ts +17 -0
  186. package/build/src/git/scratch.js +73 -0
  187. package/build/src/git/target-placement.d.ts +92 -0
  188. package/build/src/git/target-placement.js +375 -0
  189. package/build/src/git/tender.d.ts +49 -0
  190. package/build/src/git/tender.js +63 -0
  191. package/build/src/git/terminal-seal.d.ts +24 -0
  192. package/build/src/git/terminal-seal.js +89 -0
  193. package/build/src/git/tree.d.ts +2 -2
  194. package/build/src/git/tree.js +4 -0
  195. package/build/src/git/workspace.d.ts +53 -0
  196. package/build/src/git/workspace.js +139 -0
  197. package/build/src/identity/selector.d.ts +6 -0
  198. package/build/src/identity/selector.js +19 -0
  199. package/build/src/index.d.ts +4 -2
  200. package/build/src/index.js +2 -1
  201. package/build/src/kanshi/index.d.ts +2 -2
  202. package/build/src/kanshi/index.js +1 -1
  203. package/build/src/kanshi/read.d.ts +7 -3
  204. package/build/src/kanshi/read.js +245 -45
  205. package/build/src/kanshi/report.d.ts +81 -6
  206. package/build/src/kanshi/select.d.ts +5 -0
  207. package/build/src/kanshi/select.js +33 -1
  208. package/build/src/library/address.d.ts +57 -0
  209. package/build/src/library/address.js +165 -0
  210. package/build/src/library/akuma-creation.d.ts +16 -7
  211. package/build/src/library/akuma-creation.js +96 -22
  212. package/build/src/library/audit.d.ts +18 -0
  213. package/build/src/library/audit.js +44 -0
  214. package/build/src/library/bind.d.ts +21 -0
  215. package/build/src/library/bind.js +56 -0
  216. package/build/src/library/catalog.d.ts +58 -0
  217. package/build/src/library/catalog.js +69 -0
  218. package/build/src/library/configuration.d.ts +6 -15
  219. package/build/src/library/configuration.js +14 -17
  220. package/build/src/library/contract.d.ts +23 -49
  221. package/build/src/library/contract.js +171 -185
  222. package/build/src/library/delivery.d.ts +24 -0
  223. package/build/src/library/delivery.js +21 -0
  224. package/build/src/library/fleet.d.ts +65 -0
  225. package/build/src/library/fleet.js +153 -0
  226. package/build/src/library/input.d.ts +3 -0
  227. package/build/src/library/input.js +19 -0
  228. package/build/src/library/keiyaku.d.ts +18 -3
  229. package/build/src/library/keiyaku.js +12 -1
  230. package/build/src/library/mutation.d.ts +39 -0
  231. package/build/src/library/mutation.js +37 -0
  232. package/build/src/library/reconcile.d.ts +29 -0
  233. package/build/src/library/reconcile.js +179 -0
  234. package/build/src/library/refusal.d.ts +21 -0
  235. package/build/src/library/refusal.js +29 -0
  236. package/build/src/library/region.d.ts +14 -1
  237. package/build/src/library/region.js +18 -4
  238. package/build/src/library/repo.d.ts +4 -13
  239. package/build/src/library/repo.js +14 -24
  240. package/build/src/protocol/attempt.d.ts +16 -3
  241. package/build/src/protocol/attempt.js +41 -10
  242. package/build/src/protocol/bind.d.ts +9 -2
  243. package/build/src/protocol/bind.js +48 -40
  244. package/build/src/protocol/intent.d.ts +57 -20
  245. package/build/src/protocol/intent.js +55 -79
  246. package/build/src/protocol/operations.d.ts +152 -43
  247. package/build/src/protocol/operations.js +482 -166
  248. package/build/src/protocol/outcome.d.ts +14 -3
  249. package/build/src/protocol/outcome.js +11 -3
  250. package/build/src/protocol/placement.d.ts +41 -0
  251. package/build/src/protocol/placement.js +147 -0
  252. package/build/src/protocol/read/documents.d.ts +2 -2
  253. package/build/src/protocol/read/documents.js +4 -4
  254. package/build/src/protocol/read/status.d.ts +18 -5
  255. package/build/src/protocol/read/status.js +73 -13
  256. package/build/src/protocol/run.d.ts +49 -7
  257. package/build/src/protocol/run.js +53 -25
  258. package/build/src/runtime/proc/line-rpc.d.ts +4 -8
  259. package/build/src/runtime/proc/line-rpc.js +22 -28
  260. package/build/src/runtime/proc/run.d.ts +23 -21
  261. package/build/src/runtime/proc/run.js +123 -89
  262. package/build/src/runtime/proc/stdio.d.ts +18 -0
  263. package/build/src/runtime/proc/stdio.js +58 -0
  264. package/build/src/settings.d.ts +7 -1
  265. package/build/src/settings.js +32 -17
  266. package/build/src/settlement/fence.d.ts +5 -0
  267. package/build/src/settlement/fence.js +14 -0
  268. package/build/src/settlement/holder.d.ts +35 -4
  269. package/build/src/settlement/holder.js +127 -28
  270. package/build/src/settlement/settle.d.ts +9 -1
  271. package/build/src/settlement/settle.js +74 -37
  272. package/build/src/task/board.d.ts +23 -5
  273. package/build/src/task/board.js +17 -10
  274. package/build/src/task/compose.d.ts +2 -2
  275. package/build/src/task/compose.js +18 -10
  276. package/build/src/task/context.d.ts +3 -3
  277. package/build/src/task/context.js +15 -20
  278. package/build/src/task/document.d.ts +2 -1
  279. package/build/src/task/document.js +15 -5
  280. package/build/src/task/index.d.ts +27 -15
  281. package/build/src/task/index.js +57 -35
  282. package/build/src/task/operations.d.ts +38 -13
  283. package/build/src/task/operations.js +80 -46
  284. package/build/src/task/query.d.ts +67 -0
  285. package/build/src/task/query.js +279 -0
  286. package/build/src/task/store.d.ts +5 -7
  287. package/build/src/task/store.js +43 -28
  288. package/build/src/verification/declaration.d.ts +1 -0
  289. package/build/src/verification/execution.d.ts +51 -0
  290. package/build/src/verification/execution.js +108 -0
  291. package/build/src/workspace-place.d.ts +41 -0
  292. package/build/src/workspace-place.js +386 -0
  293. package/build/src/world.d.ts +24 -0
  294. package/build/src/world.js +136 -0
  295. package/package.json +8 -4
  296. package/build/src/akuma/activity.d.ts +0 -66
  297. package/build/src/akuma/activity.js +0 -139
  298. package/build/src/akuma/providers/claude.js +0 -305
  299. package/build/src/context-root.d.ts +0 -4
  300. package/build/src/context-root.js +0 -15
  301. package/build/src/git/delivery.d.ts +0 -20
  302. package/build/src/git/delivery.js +0 -109
  303. package/build/src/git/verification.d.ts +0 -14
  304. package/build/src/git/verification.js +0 -56
  305. package/build/src/protocol/read/audit.d.ts +0 -25
  306. package/build/src/protocol/read/audit.js +0 -39
  307. package/build/src/verification/producer.d.ts +0 -23
  308. package/build/src/verification/producer.js +0 -54
@@ -1,126 +1,288 @@
1
- import { prepareDelivery, prepareReview, } from "../git/delivery.js";
2
- import { currentBranch, extendContractsForAdmission, observeGit, observeContract, observeContractsForAdmission, } from "../git/observe.js";
3
- import { reconcile, reconcileBatch, reconcileObservationFailure } from "../git/reconcile.js";
1
+ import { materializeIntegrationSnapshot, planIntegration, readDeliveryDiff, readDeliveryScope, worktreeChangeId, } from "../git/integration.js";
2
+ import { captureTender, dirtyTenderDelta, dirtyTenderRefusal, materializeTenderSnapshot, } from "../git/tender.js";
3
+ import { currentBranch, extendContractsForAdmissionAt, observeContractAt, observeContractWorld, observeContractsForAdmissionAt, } from "../git/observe.js";
4
+ import { reconcile, reconcileBatch, reconcileObservationFailure, } from "../git/reconcile.js";
4
5
  import { NoGitWorldError, repositoryAt } from "../git/repository.js";
5
- import { readDeliveryDiff } from "../git/verification.js";
6
+ import { withGitReadObservation } from "../git/read-observation.js";
6
7
  import { dependencyKeySet } from "../core/subject.js";
7
8
  import { AuthorityCorruptionError } from "../core/facts/errors.js";
8
- import { contractState, documentIsCurrent } from "../core/facts/observation.js";
9
+ import { activeContract, contractState, documentIsCurrent } from "../core/facts/observation.js";
9
10
  import { gate } from "../core/facts/types.js";
10
11
  import { decideAbandon } from "../core/verbs/abandon.js";
11
12
  import { decideAmend } from "../core/verbs/amend.js";
12
13
  import { decideArc } from "../core/verbs/arc.js";
13
14
  import { decideDeliver } from "../core/verbs/deliver.js";
14
15
  import { decideAttestation } from "../core/verbs/attestation.js";
15
- import { produceVerification } from "../verification/producer.js";
16
- import { admitIntent, admitPlacement, mintAttempts, verifyDelivery } from "./intent.js";
17
- import { auditReport, readAudit } from "./read/audit.js";
16
+ import { admitIntent, currentVerifiedAttestation, verifyDelivery, } from "./intent.js";
17
+ import { admitPlacement, } from "./placement.js";
18
+ import { adjudicateAuditTarget } from "../git/target-placement.js";
18
19
  import { readDocuments } from "./read/documents.js";
19
- import { readContractBoard, readContractObservation, } from "./read/status.js";
20
- import { admitDecidedOffer } from "./attempt.js";
20
+ import { readContractBoard, readContractObservationAt, } from "./read/status.js";
21
+ import { admitDecidedOffer, mintAttempts } from "./attempt.js";
22
+ import { appointmentFor, readManagedWorktreeAppointment, readPlaceRegister, } from "../workspace-place.js";
21
23
  export { bindOperation } from "./bind.js";
22
- import { accepted, admitted, complete } from "./outcome.js";
24
+ export { reconcileObservationFailure } from "../git/reconcile.js";
25
+ import { accepted, admitted, complete, } from "./outcome.js";
23
26
  const REVIEWED = gate("reviewed");
24
27
  function timestamp() { return new Date().toISOString(); }
25
28
  function mergeAdmissions(current, next) {
26
- return { ...next, facts: [...current.facts, ...next.facts] };
29
+ const effects = [...(current.physical?.effects ?? []), ...(next.physical?.effects ?? [])];
30
+ const lag = [...(current.physical?.lag ?? []), ...(next.physical?.lag ?? [])];
31
+ return {
32
+ ...next,
33
+ facts: [...current.facts, ...next.facts],
34
+ ...(effects.length === 0 && lag.length === 0 ? {} : { physical: { effects, lag } }),
35
+ };
27
36
  }
28
37
  function stepStop(result) {
29
38
  if (result.kind === "accepted")
30
39
  return undefined;
31
40
  return result.kind === "refused" ? { refusal: result.refusal } : { retry: result };
32
41
  }
42
+ function verificationStop(step) {
43
+ return "failure" in step ? step : stepStop(step);
44
+ }
45
+ function unpackVerificationOutcome(verification) {
46
+ const stop = verificationStop(verification.step);
47
+ const admission = !("failure" in verification.step) && verification.step.kind === "accepted"
48
+ ? verification.step
49
+ : undefined;
50
+ return {
51
+ ...(verification.cleanup === undefined ? {} : { cleanup: verification.cleanup }),
52
+ ...(verification.leak === undefined ? {} : { leak: verification.leak }),
53
+ ...(stop === undefined ? {} : { stop }),
54
+ ...(admission === undefined ? {} : { admission }),
55
+ ...(verification.counts === undefined ? {} : { counts: verification.counts }),
56
+ };
57
+ }
58
+ function placementStop(result) {
59
+ if (result.kind === "accepted")
60
+ return undefined;
61
+ if (result.kind === "placement-failed") {
62
+ return { failure: "target-placement-failed", diagnostic: result.diagnostic };
63
+ }
64
+ if (result.kind === "target-moved") {
65
+ const { contractId, target, expected, observed } = result;
66
+ return { failure: "target-moved", contractId, target, expected, observed };
67
+ }
68
+ return result.kind === "refused" ? { refusal: result.refusal } : { retry: result };
69
+ }
33
70
  export { NoGitWorldError };
34
- export function scopeOperation(input) { return repositoryAt(input.coordinate); }
35
- export function currentBranchOperation(input) {
36
- return currentBranch(input.scope);
71
+ export async function scopeOperation(input) {
72
+ return await repositoryAt(input.coordinate);
73
+ }
74
+ export async function currentBranchOperation(input) {
75
+ return await currentBranch(input.scope);
76
+ }
77
+ export async function contractsOperation(input) {
78
+ return withGitReadObservation(input.scope, input.channel, readContractBoard);
37
79
  }
38
- export function contractsOperation(input) { return readContractBoard(input.scope); }
39
- export function contractObservationOperation(input) {
40
- return readContractObservation(input.scope, input.contractId);
80
+ export async function contractObservationOperation(input) {
81
+ return await readContractObservationAt(input.scope, input.channel, input.contractId);
41
82
  }
42
- export function documentsOperation(input) { return readDocuments(input.scope); }
43
- export function stateOperation(input) {
44
- const state = observeContract(input.scope, input.contractId).state;
83
+ export async function documentsOperationAt(scope, channel) {
84
+ return withGitReadObservation(scope, channel, readDocuments);
85
+ }
86
+ export async function stateOperation(input) {
87
+ const state = (await observeContractAt(input.scope, input.channel, input.contractId)).state;
45
88
  if (state === null)
46
89
  throw new Error(`contract does not exist: ${input.contractId}`);
47
90
  return state;
48
91
  }
49
- export function readStateOperation(input) { return observeContract(input.scope, input.contractId).state; }
50
- export function deliveryOperation(input) {
51
- const state = observeContract(input.scope, input.contractId).state;
52
- if (state === null || state.delivery === null)
53
- return null;
92
+ export async function deliveryOperation(input) {
93
+ const state = (await observeContractAt(input.scope, input.channel, input.contractId)).state;
94
+ return state?.delivery?.data ?? null;
95
+ }
96
+ export async function deliveryDiffOperation(input) { return await readDeliveryDiff(input.scope, input.integrationPredecessor, input.integrationSnapshot); }
97
+ async function extendPrerequisiteClosureAt(channel, observation, seeds) {
98
+ let current = observation;
99
+ const visited = new Set();
100
+ let pending = [...seeds];
101
+ while (pending.length > 0) {
102
+ const batch = [...new Set(pending.filter((id) => !visited.has(id)))];
103
+ pending = [];
104
+ if (batch.length === 0)
105
+ break;
106
+ current = await extendContractsForAdmissionAt(channel, current, batch);
107
+ for (const id of batch) {
108
+ visited.add(id);
109
+ const state = contractState(current.decision, id);
110
+ if (state !== null)
111
+ pending.push(...state.terms.after);
112
+ }
113
+ }
114
+ return current;
115
+ }
116
+ export async function amendOperation(input) {
117
+ const attempts = mintAttempts({ entryCount: 1 });
118
+ let source = input.source;
119
+ for (let index = 0; index < attempts.length; index += 1) {
120
+ let observation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
121
+ const state = contractState(observation.decision, input.contractId);
122
+ if (source === undefined && state !== null)
123
+ source = state.terms;
124
+ const amendment = source === undefined || input.deriveAmendment === undefined
125
+ ? undefined
126
+ : { source, ...input.deriveAmendment(source) };
127
+ if (amendment !== undefined) {
128
+ observation = await extendPrerequisiteClosureAt(input.channel, observation, [...new Set([...(state?.terms.after ?? []), ...amendment.terms.after])]);
129
+ }
130
+ const preparation = amendment === undefined
131
+ ? undefined
132
+ : amendment.verification.kind === "prepared"
133
+ ? { kind: "prepared", data: amendment.terms }
134
+ : { kind: "refused", refusal: amendment.verification.refusal };
135
+ const decision = decideAmend({
136
+ input: {
137
+ contractId: input.contractId,
138
+ ...(input.actor === undefined ? {} : { actor: input.actor }),
139
+ at: timestamp(),
140
+ ...(amendment === undefined ? {} : { source: amendment.source }),
141
+ ...(preparation === undefined ? {} : { preparation }),
142
+ },
143
+ attempt: attempts[index],
144
+ observation: observation.decision,
145
+ });
146
+ if (decision.kind === "refused")
147
+ return decision;
148
+ const admission = await admitDecidedOffer({
149
+ channel: input.channel,
150
+ repository: input.scope,
151
+ decisionObservation: observation,
152
+ attempt: attempts[index],
153
+ offer: decision.offer,
154
+ primaryContract: input.contractId,
155
+ });
156
+ if (admission.kind === "accepted") {
157
+ if (amendment === undefined)
158
+ throw new Error("accepted amendment is missing its document derivation");
159
+ return admitted(admission, amendment);
160
+ }
161
+ if (admission.kind === "publication-failed")
162
+ return { kind: "retry", reason: admission };
163
+ if (admission.kind === "collision" && index + 1 === attempts.length)
164
+ return { kind: "retry", reason: admission };
165
+ }
166
+ return { kind: "retry", reason: { kind: "exhausted" } };
167
+ }
168
+ export async function prepareDelivery(repository, stage, input) {
169
+ const { contractId, coordinates } = stage;
170
+ if (coordinates.workspace === "here" && coordinates.target !== undefined) {
171
+ const branch = await currentBranch(repository);
172
+ if (branch !== coordinates.target) {
173
+ return { kind: "refused", refusal: { kind: "workspace-not-on-target", contractId, target: coordinates.target, branch } };
174
+ }
175
+ }
176
+ const appointed = coordinates.workspace === "worktree"
177
+ ? stage.appointment === undefined
178
+ ? appointmentFor(await readPlaceRegister(repository), contractId)
179
+ : { contract: contractId, place: stage.appointment.place }
180
+ : undefined;
181
+ const tender = await captureTender(repository, {
182
+ contractId,
183
+ coordinates,
184
+ ...(appointed === undefined ? {} : { place: appointed.place }),
185
+ });
186
+ if (tender.kind === "refused")
187
+ return tender;
188
+ if ((tender.data.dirty && input.includeDirty !== true) || tender.data.changes.submodules.length > 0) {
189
+ return { kind: "refused", refusal: await dirtyTenderRefusal(repository, contractId, tender.data) };
190
+ }
191
+ const tenderSnapshot = await materializeTenderSnapshot(repository, tender.data, {
192
+ contractId,
193
+ title: input.title,
194
+ ...(input.message === undefined ? {} : { message: input.message }),
195
+ });
196
+ const requireBranchesToBeUpToDate = input.requireBranchesToBeUpToDate ?? false;
197
+ const integration = await planIntegration(repository, { contractId, coordinates }, { ...tender.data, head: tenderSnapshot }, requireBranchesToBeUpToDate);
198
+ if (integration.kind === "refused")
199
+ return integration;
200
+ const integrationSnapshot = coordinates.target === undefined
201
+ ? tenderSnapshot
202
+ : await materializeIntegrationSnapshot(repository, integration.data.tree, integration.data.predecessor, {
203
+ contractId,
204
+ title: input.title,
205
+ ...(input.message === undefined ? {} : { message: input.message }),
206
+ });
54
207
  return {
55
- snapshotId: state.delivery.data.candidate,
56
- changeId: state.delivery.data.deliveryPatchId,
57
- expectedPredecessor: state.delivery.data.expectedPredecessor,
208
+ kind: "prepared",
209
+ data: {
210
+ tenderSnapshot,
211
+ integration: {
212
+ predecessor: integration.data.predecessor,
213
+ snapshot: integrationSnapshot,
214
+ changeId: await worktreeChangeId(repository, { contractId, coordinates }, tender.data),
215
+ },
216
+ method: "squash",
217
+ policy: { requireBranchesToBeUpToDate },
218
+ },
58
219
  };
59
220
  }
60
- function observePrerequisiteClosure(repository, contracts) {
61
- let observation = observeContractsForAdmission(repository, contracts);
62
- let frontier = contracts.slice(1);
63
- while (frontier.length > 0) {
64
- const next = new Set();
65
- for (const id of frontier) {
66
- const state = contractState(observation.decision, id);
67
- if (state === null)
68
- continue;
69
- for (const dependency of state.terms.after) {
70
- if (!observation.decision.has(dependency))
71
- next.add(dependency);
72
- }
73
- }
74
- frontier = [...next];
75
- observation = extendContractsForAdmission(repository, observation, frontier);
221
+ async function captureReviewableWorktree(repository, stage) {
222
+ const appointed = stage.coordinates.workspace === "worktree"
223
+ ? appointmentFor(await readPlaceRegister(repository), stage.contractId)
224
+ : undefined;
225
+ const tender = await captureTender(repository, {
226
+ ...stage,
227
+ ...(appointed === undefined ? {} : { place: appointed.place }),
228
+ });
229
+ if (tender.kind === "refused")
230
+ return tender;
231
+ if (tender.data.changes.submodules.length > 0) {
232
+ return { kind: "refused", refusal: await dirtyTenderRefusal(repository, stage.contractId, tender.data) };
76
233
  }
77
- return observation;
234
+ const workspace = await dirtyTenderDelta(repository, tender.data);
235
+ return {
236
+ kind: "prepared",
237
+ data: {
238
+ changeId: await worktreeChangeId(repository, stage, tender.data),
239
+ tender: tender.data,
240
+ ...(workspace === undefined ? {} : { workspace }),
241
+ },
242
+ };
78
243
  }
79
- export async function deliveryDiffOperation(input) { return readDeliveryDiff(input.scope, input.expectedPredecessor, input.snapshotId); }
80
- export function amendOperation(input) {
81
- const amendment = input.amendment;
82
- const preparation = amendment === undefined
83
- ? undefined
84
- : amendment.verification.kind === "prepared"
85
- ? { kind: "prepared", data: amendment.terms }
86
- : { kind: "refused", refusal: amendment.verification.refusal };
87
- const decisionInput = {
88
- contractId: input.contractId,
89
- ...(input.actor === undefined ? {} : { actor: input.actor }),
90
- at: timestamp(),
91
- ...(amendment === undefined ? {} : { source: amendment.source }),
92
- ...(preparation === undefined ? {} : { preparation }),
244
+ export async function prepareReview(repository, stage) {
245
+ const prepared = await captureReviewableWorktree(repository, stage);
246
+ if (prepared.kind === "refused")
247
+ return prepared;
248
+ return {
249
+ kind: "prepared",
250
+ data: {
251
+ changeId: prepared.data.changeId,
252
+ ...(prepared.data.workspace === undefined ? {} : { workspace: prepared.data.workspace }),
253
+ },
93
254
  };
94
- return complete(admitIntent(input.scope, decisionInput, decideAmend, {
95
- observedContracts: [input.contractId, ...(amendment?.terms.after ?? [])],
96
- observe: observePrerequisiteClosure,
97
- }), undefined);
98
255
  }
99
- function deliverAttempt(input, attempt) {
100
- const decisionObservation = observeContractsForAdmission(input.scope, [input.contractId]);
256
+ async function deliverAttempt(input, attempt) {
257
+ const decisionObservation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
101
258
  const state = contractState(decisionObservation.decision, input.contractId);
259
+ const derivation = state === null || input.deriveDocument === undefined
260
+ ? undefined
261
+ : input.deriveDocument(state);
102
262
  let preparation;
103
- if (state === null || input.derivation === undefined) {
263
+ if (state === null || derivation === undefined) {
104
264
  preparation = { kind: "unavailable" };
105
265
  }
106
- else if (input.derivation.verification.kind === "refused") {
266
+ else if (derivation.verification.kind === "refused") {
107
267
  preparation = {
108
268
  kind: "refused",
109
- document: input.derivation.document,
110
- refusal: input.derivation.verification.refusal,
269
+ document: derivation.document,
270
+ refusal: derivation.verification.refusal,
111
271
  };
112
272
  }
113
273
  else {
114
- const prepared = prepareDelivery(input.scope, {
274
+ const prepared = await prepareDelivery(input.scope, {
115
275
  contractId: state.id,
116
276
  coordinates: state.coordinates,
117
277
  }, {
118
- title: input.derivation.title,
278
+ title: derivation.title,
119
279
  ...(input.message === undefined ? {} : { message: input.message }),
280
+ requireBranchesToBeUpToDate: input.requireBranchesToBeUpToDate,
281
+ includeDirty: input.includeDirty,
120
282
  });
121
283
  preparation = prepared.kind === "refused"
122
- ? { kind: "refused", document: input.derivation.document, refusal: prepared.refusal }
123
- : { kind: "prepared", document: input.derivation.document, data: prepared.data };
284
+ ? { kind: "refused", document: derivation.document, refusal: prepared.refusal }
285
+ : { kind: "prepared", document: derivation.document, data: prepared.data };
124
286
  }
125
287
  const decisionInput = {
126
288
  contractId: input.contractId,
@@ -134,61 +296,73 @@ function deliverAttempt(input, attempt) {
134
296
  if (preparation.kind !== "prepared") {
135
297
  throw new Error("offered delivery is missing its mechanical preparation");
136
298
  }
137
- const admitted = admitDecidedOffer(input.scope, decisionObservation, attempt, decision.offer, input.contractId);
299
+ const admitted = await admitDecidedOffer({
300
+ channel: input.channel,
301
+ repository: input.scope,
302
+ decisionObservation,
303
+ attempt,
304
+ offer: decision.offer,
305
+ primaryContract: input.contractId,
306
+ });
138
307
  if (admitted.kind === "accepted") {
139
- return { ...admitted, value: {
140
- snapshotId: preparation.data.candidate,
141
- changeId: preparation.data.deliveryPatchId,
142
- expectedPredecessor: preparation.data.expectedPredecessor,
143
- } };
308
+ if (derivation === undefined)
309
+ throw new Error("accepted delivery is missing its document derivation");
310
+ return { ...admitted, value: { delivery: preparation.data, derivation } };
144
311
  }
145
312
  return admitted;
146
313
  }
147
314
  async function completeDelivery(input, first) {
148
- if (input.derivation === undefined) {
149
- throw new Error("accepted delivery is missing its document derivation");
150
- }
151
- const derivation = input.derivation;
315
+ const derivation = first.value.derivation;
152
316
  if (derivation.verification.kind !== "prepared") {
153
317
  throw new Error("accepted delivery is missing its Verification preparation");
154
318
  }
155
319
  let admission = first;
156
320
  let verificationValue;
321
+ let verificationReuse;
322
+ let cleanup;
157
323
  let leak;
158
- const verification = await verifyDelivery({
159
- repository: input.scope,
160
- contractId: input.contractId,
161
- ...(input.actor === undefined ? {} : { actor: input.actor }),
162
- at: timestamp(),
163
- state: first.state,
164
- environment: process.env,
165
- produce: produceVerification,
166
- ...(derivation.verification.data === null
167
- ? {}
168
- : { verification: derivation.verification.data }),
169
- });
170
- if (verification !== null) {
171
- leak = verification.leak;
172
- if ("failure" in verification.step)
173
- verificationValue = verification.step;
174
- else {
175
- verificationValue = stepStop(verification.step);
176
- if (verification.step.kind === "accepted")
177
- admission = mergeAdmissions(admission, verification.step);
324
+ const currentVerified = currentVerifiedAttestation(first.state);
325
+ if (currentVerified !== undefined) {
326
+ verificationReuse = currentVerified;
327
+ }
328
+ else {
329
+ const verification = await verifyDelivery({
330
+ channel: input.channel,
331
+ repository: input.scope,
332
+ contractId: input.contractId,
333
+ ...(input.actor === undefined ? {} : { actor: input.actor }),
334
+ at: timestamp(),
335
+ state: first.state,
336
+ snapshot: first.value.delivery.integration.snapshot,
337
+ environment: process.env,
338
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
339
+ ...(derivation.verification.data === null
340
+ ? {}
341
+ : { verification: derivation.verification.data }),
342
+ });
343
+ if (verification !== null) {
344
+ const unpacked = unpackVerificationOutcome(verification);
345
+ cleanup = unpacked.cleanup;
346
+ leak = unpacked.leak;
347
+ verificationValue = unpacked.stop;
348
+ if (unpacked.admission !== undefined)
349
+ admission = mergeAdmissions(admission, unpacked.admission);
178
350
  }
179
351
  }
180
- const placement = admitPlacement(input.scope, {
352
+ const placement = await admitPlacement(input.channel, input.scope, first.state.coordinates.target, {
181
353
  contractId: input.contractId,
182
354
  ...(input.actor === undefined ? {} : { actor: input.actor }),
183
355
  at: timestamp(),
184
356
  });
185
- const placementValue = stepStop(placement);
357
+ const placementValue = placementStop(placement);
186
358
  if (placement.kind === "accepted")
187
359
  admission = mergeAdmissions(admission, placement);
188
360
  return admitted(admission, {
189
- ...first.value,
361
+ ...first.value.delivery,
190
362
  ...(verificationValue === undefined ? {} : { verification: verificationValue }),
363
+ ...(verificationReuse === undefined ? {} : { verificationReuse }),
191
364
  ...(placementValue === undefined ? {} : { placement: placementValue }),
365
+ ...(cleanup === undefined ? {} : { cleanup }),
192
366
  ...(leak === undefined ? {} : { leak }),
193
367
  });
194
368
  }
@@ -196,7 +370,7 @@ export async function deliverOperation(input) {
196
370
  const attempts = mintAttempts({ entryCount: 2 });
197
371
  let first = null;
198
372
  for (let index = 0; index < attempts.length; index += 1) {
199
- const result = deliverAttempt(input, attempts[index]);
373
+ const result = await deliverAttempt(input, attempts[index]);
200
374
  if (result.kind === "accepted") {
201
375
  first = result;
202
376
  break;
@@ -212,30 +386,41 @@ export async function deliverOperation(input) {
212
386
  }
213
387
  if (first === null)
214
388
  return { kind: "retry", reason: { kind: "exhausted" } };
215
- return completeDelivery(input, first);
389
+ return await completeDelivery(input, first);
216
390
  }
217
- export function abandonOperation(input) {
218
- return complete(admitIntent(input.scope, {
391
+ export async function abandonOperation(input) {
392
+ return complete(await admitIntent(input.channel, input.scope, {
219
393
  contractId: input.contractId,
220
394
  ...(input.actor === undefined ? {} : { actor: input.actor }),
221
395
  at: timestamp(),
222
396
  ...(input.note === undefined ? {} : { note: input.note }),
223
- }, decideAbandon, input.decorateOffer === undefined ? {} : { decorateOffer: input.decorateOffer }), undefined);
397
+ }, decideAbandon, {
398
+ ...(input.decorateOffer === undefined ? {} : { decorateOffer: input.decorateOffer }),
399
+ ...(input.observationSelection === undefined ? {} : { observationSelection: input.observationSelection }),
400
+ }), undefined);
224
401
  }
225
- export function arcOperation(input) {
226
- return complete(admitIntent(input.scope, {
402
+ export async function arcOperation(input) {
403
+ return complete(await admitIntent(input.channel, input.scope, {
227
404
  contractId: input.contractId,
228
405
  ...(input.actor === undefined ? {} : { actor: input.actor }),
229
406
  at: timestamp(),
230
407
  data: input.chapter,
231
408
  }, decideArc), undefined);
232
409
  }
233
- function reviewAttempt(input, attempt) {
234
- const decisionObservation = observeContractsForAdmission(input.scope, [input.contractId]);
410
+ function reviewValue(value, placement) {
411
+ return {
412
+ ...(value.workspace === undefined ? {} : { workspace: value.workspace }),
413
+ ...(placement === undefined ? {} : { placement }),
414
+ };
415
+ }
416
+ async function reviewAttempt(input, attempt) {
417
+ const decisionObservation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
235
418
  const state = contractState(decisionObservation.decision, input.contractId);
236
419
  let preparation;
420
+ let workspace;
421
+ let tender;
237
422
  if (state !== null) {
238
- const prepared = prepareReview(input.scope, { contractId: state.id, coordinates: state.coordinates });
423
+ const prepared = await captureReviewableWorktree(input.scope, { contractId: state.id, coordinates: state.coordinates });
239
424
  preparation = prepared.kind === "refused"
240
425
  ? { kind: "refused", refusal: prepared.refusal }
241
426
  : {
@@ -244,12 +429,16 @@ function reviewAttempt(input, attempt) {
244
429
  gate: REVIEWED,
245
430
  subject: dependencyKeySet([
246
431
  { kind: "document", value: state.terms.document.key },
247
- { kind: "change", value: prepared.data },
432
+ { kind: "change", value: prepared.data.changeId },
248
433
  ]),
249
434
  verdict: input.verdict,
250
435
  ...(input.summary === undefined ? {} : { summary: input.summary }),
251
436
  },
252
437
  };
438
+ if (prepared.kind === "prepared") {
439
+ workspace = prepared.data.workspace;
440
+ tender = prepared.data.tender;
441
+ }
253
442
  }
254
443
  const decisionInput = {
255
444
  contractId: input.contractId,
@@ -260,17 +449,30 @@ function reviewAttempt(input, attempt) {
260
449
  const decision = decideAttestation({ input: decisionInput, attempt, observation: decisionObservation.decision });
261
450
  if (decision.kind === "refused")
262
451
  return { kind: "refused", refusal: decision.refusal };
263
- const admitted = admitDecidedOffer(input.scope, decisionObservation, attempt, decision.offer, input.contractId);
452
+ const admitted = await admitDecidedOffer({
453
+ channel: input.channel,
454
+ repository: input.scope,
455
+ decisionObservation,
456
+ attempt,
457
+ offer: decision.offer,
458
+ primaryContract: input.contractId,
459
+ });
264
460
  if (admitted.kind === "accepted")
265
- return { ...admitted, value: undefined };
461
+ return {
462
+ ...admitted,
463
+ value: {
464
+ ...(workspace === undefined ? {} : { workspace }),
465
+ ...(tender === undefined ? {} : { tender }),
466
+ },
467
+ };
266
468
  return admitted;
267
469
  }
268
- export function reviewOperation(input) {
470
+ export async function reviewOperation(input) {
269
471
  const git = input.scope;
270
- const attempts = mintAttempts({ entryCount: 2 });
472
+ const attempts = mintAttempts({ entryCount: 1 });
271
473
  let review = null;
272
474
  for (let index = 0; index < attempts.length; index += 1) {
273
- const result = reviewAttempt(input, attempts[index]);
475
+ const result = await reviewAttempt(input, attempts[index]);
274
476
  if (result.kind === "accepted" || result.kind === "refused") {
275
477
  review = result;
276
478
  break;
@@ -285,73 +487,178 @@ export function reviewOperation(input) {
285
487
  if (review.kind !== "accepted")
286
488
  return review;
287
489
  if (input.verdict !== "satisfied")
288
- return admitted(review, {});
289
- const placement = admitPlacement(git, {
490
+ return admitted(review, reviewValue(review.value));
491
+ const target = review.state.coordinates.target;
492
+ const tender = review.value.tender;
493
+ const placement = await admitPlacement(input.channel, git, target, {
290
494
  contractId: input.contractId,
291
495
  ...(input.actor === undefined ? {} : { actor: input.actor }),
292
496
  at: timestamp(),
497
+ }, tender === undefined || target === undefined ? undefined : async () => {
498
+ const integration = await planIntegration(git, {
499
+ contractId: input.contractId,
500
+ coordinates: review.state.coordinates,
501
+ }, tender, false);
502
+ if (integration.kind === "refused" && integration.refusal.kind !== "target-missing") {
503
+ return { kind: "refused", refusal: integration.refusal };
504
+ }
505
+ return undefined;
293
506
  });
294
- const placementStop = stepStop(placement);
507
+ const stopped = placementStop(placement);
295
508
  const admission = placement.kind === "accepted" ? mergeAdmissions(review, placement) : review;
296
- return admitted(admission, placementStop === undefined ? {} : { placement: placementStop });
509
+ return admitted(admission, reviewValue(review.value, stopped));
297
510
  }
298
- export async function auditOperation(input) {
299
- const git = input.scope;
300
- const initial = readAudit(git, input.contractId, REVIEWED);
301
- if (initial.state === null)
302
- return { kind: "refused", refusal: { kind: "contract-missing", contractId: input.contractId } };
303
- const derivation = input.derivation;
304
- if (derivation === undefined) {
305
- return { kind: "refused", refusal: { kind: "document-moved", contractId: input.contractId } };
306
- }
307
- if (!documentIsCurrent(initial.state, derivation.document)) {
308
- return { kind: "refused", refusal: { kind: "document-moved", contractId: input.contractId } };
309
- }
310
- if (derivation.verification.kind === "refused") {
311
- return { kind: "refused", refusal: derivation.verification.refusal };
312
- }
313
- if (initial.state.delivery === null || derivation.verification.data === null) {
314
- return accepted(initial.state, [], initial.report);
511
+ async function auditWorkspace(repository, state) {
512
+ if (state.coordinates.workspace === "here") {
513
+ return { kind: "ready", answer: { kind: "here", path: repository.effectiveCwd } };
315
514
  }
515
+ const appointed = await readManagedWorktreeAppointment(repository, state.id);
516
+ if (appointed.kind === "failed")
517
+ throw new Error(appointed.diagnostic);
518
+ if (appointed.kind === "unappointed")
519
+ return appointed;
520
+ return {
521
+ kind: "ready",
522
+ answer: { kind: "worktree", path: appointed.path },
523
+ appointment: appointed,
524
+ };
525
+ }
526
+ function auditDeliveryRelation(state, candidate) {
527
+ const recorded = state.delivery?.data.integration.changeId;
528
+ if (recorded === undefined)
529
+ return undefined;
530
+ return {
531
+ changeId: recorded,
532
+ relation: recorded === candidate.integration.changeId ? "identical" : "differs",
533
+ };
534
+ }
535
+ async function auditCandidateVerification(input, state, snapshot, definition) {
316
536
  const verification = await verifyDelivery({
317
- repository: git,
537
+ channel: input.channel,
538
+ repository: input.scope,
318
539
  contractId: input.contractId,
319
540
  ...(input.actor === undefined ? {} : { actor: input.actor }),
320
541
  at: timestamp(),
321
- state: initial.state,
542
+ state,
543
+ snapshot,
322
544
  environment: process.env,
323
- produce: produceVerification,
324
- verification: derivation.verification.data,
545
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
546
+ verification: definition,
325
547
  });
326
548
  if (verification === null) {
327
549
  throw new Error("audit verification preparation unexpectedly produced no attempt");
328
550
  }
329
- const attempt = "failure" in verification.step
330
- ? verification.step
331
- : verification.step.kind === "accepted"
332
- ? undefined
333
- : verification.step.kind === "refused"
334
- ? { refusal: verification.step.refusal }
335
- : { retry: verification.step };
336
- const report = !("failure" in verification.step) && verification.step.kind === "accepted"
337
- ? auditReport(verification.step.journal, REVIEWED)
338
- : initial.report;
551
+ return unpackVerificationOutcome(verification);
552
+ }
553
+ function auditVerificationAnswer(verified) {
554
+ if (verified === undefined)
555
+ return { kind: "not-run" };
556
+ if (verified.stop !== undefined)
557
+ return { kind: "stopped", stop: verified.stop };
558
+ if (verified.counts === undefined) {
559
+ throw new Error("terminal Verification is missing producer counts");
560
+ }
561
+ return {
562
+ kind: verified.counts.verdict,
563
+ passed: verified.counts.passed,
564
+ total: verified.counts.total,
565
+ ...(verified.counts.summary === undefined ? {} : { summary: verified.counts.summary }),
566
+ };
567
+ }
568
+ async function readyAuditCandidate(repository, candidate, workspace, showDiff) {
569
+ const predecessor = candidate.integration.predecessor;
570
+ const snapshot = candidate.integration.snapshot;
571
+ const scope = await readDeliveryScope(repository, predecessor, snapshot, showDiff);
572
+ const diff = showDiff ? await readDeliveryDiff(repository, predecessor, snapshot) : undefined;
573
+ return {
574
+ kind: "ready",
575
+ workspace,
576
+ identity: candidate,
577
+ scope,
578
+ ...(diff === undefined || diff === null ? {} : { diff }),
579
+ };
580
+ }
581
+ async function auditTargetAnswer(repository, state, candidate) {
582
+ const target = state.coordinates.target;
583
+ if (target === undefined)
584
+ return { kind: "not-observed" };
585
+ return await adjudicateAuditTarget(repository, {
586
+ contractId: state.id,
587
+ coordinates: { ...state.coordinates, target },
588
+ predecessor: candidate.integration.predecessor,
589
+ candidate: candidate.integration.snapshot,
590
+ });
591
+ }
592
+ export async function auditOperation(input) {
593
+ const observed = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
594
+ const state = activeContract(observed.decision, input.contractId);
595
+ if ("kind" in state)
596
+ return { kind: "refused", refusal: state };
597
+ const derivation = input.deriveDocument?.(state);
598
+ if (derivation === undefined || !documentIsCurrent(state, derivation.document)) {
599
+ return { kind: "refused", refusal: { kind: "document-moved", contractId: input.contractId } };
600
+ }
601
+ if (derivation.verification.kind === "refused") {
602
+ return { kind: "refused", refusal: derivation.verification.refusal };
603
+ }
604
+ const workspace = await auditWorkspace(input.scope, state);
605
+ if (workspace.kind === "unappointed") {
606
+ return accepted(state, [], {
607
+ candidate: { kind: "blocked", refusal: { kind: "worktree-missing", contractId: state.id } },
608
+ verification: { kind: "not-run" },
609
+ target: { kind: "not-observed" },
610
+ });
611
+ }
612
+ const prepared = await prepareDelivery(input.scope, {
613
+ contractId: state.id,
614
+ coordinates: state.coordinates,
615
+ ...(workspace.appointment === undefined ? {} : { appointment: workspace.appointment }),
616
+ }, {
617
+ title: derivation.title,
618
+ requireBranchesToBeUpToDate: input.requireBranchesToBeUpToDate ?? false,
619
+ includeDirty: input.includeDirty ?? false,
620
+ });
621
+ if (prepared.kind === "refused") {
622
+ return accepted(state, [], {
623
+ candidate: { kind: "blocked", refusal: prepared.refusal },
624
+ verification: { kind: "not-run" },
625
+ target: { kind: "not-observed" },
626
+ });
627
+ }
628
+ const verified = derivation.verification.data === null
629
+ ? undefined
630
+ : await auditCandidateVerification(input, state, prepared.data.integration.snapshot, derivation.verification.data);
631
+ const delivery = auditDeliveryRelation(state, prepared.data);
632
+ const verification = auditVerificationAnswer(verified);
339
633
  const value = {
340
- ...report,
341
- ...(attempt === undefined ? {} : { attempt }),
342
- ...(verification.leak === undefined ? {} : { leak: verification.leak }),
634
+ candidate: await readyAuditCandidate(input.scope, prepared.data, workspace.answer, input.showDiff === true),
635
+ verification,
636
+ target: verification.kind === "stopped"
637
+ ? { kind: "not-observed" }
638
+ : await auditTargetAnswer(input.scope, state, prepared.data),
639
+ ...(delivery === undefined ? {} : { delivery }),
343
640
  };
344
- return !("failure" in verification.step) && verification.step.kind === "accepted"
345
- ? admitted(verification.step, value)
346
- : accepted(initial.state, [], value);
641
+ const obligations = {
642
+ ...(verified?.cleanup === undefined ? {} : { cleanup: verified.cleanup }),
643
+ ...(verified?.leak === undefined ? {} : { leak: verified.leak }),
644
+ };
645
+ return verified?.admission === undefined
646
+ ? accepted(state, [], value, undefined, obligations)
647
+ : {
648
+ ...admitted(verified.admission, value),
649
+ ...obligations,
650
+ };
347
651
  }
348
652
  export async function reconcileOperation(input) {
349
653
  try {
350
654
  const observation = await reconcile({
351
655
  repository: input.scope,
656
+ channel: input.channel,
352
657
  contractId: input.contractId,
353
658
  hooks: input.hooks,
354
659
  retryHooks: input.retryHooks,
660
+ ...(input.retainTerminalWorktree === undefined ? {} : { retainTerminalWorktree: input.retainTerminalWorktree }),
661
+ ...(input.place === undefined ? {} : { place: input.place }),
355
662
  });
356
663
  return { state: observation.state, report: observation.result };
357
664
  }
@@ -361,10 +668,19 @@ export async function reconcileOperation(input) {
361
668
  return { state: null, report: reconcileObservationFailure(error) };
362
669
  }
363
670
  }
671
+ export async function worldContractStates(input) {
672
+ const observation = await withGitReadObservation(input.scope, input.channel, async (read) => await observeContractWorld(read));
673
+ return [...observation.contracts.values()].flatMap((value) => value.state === null ? [] : [value.state]);
674
+ }
364
675
  export async function reconcileAllOperation(input) {
365
676
  const git = input.scope;
366
- const observation = observeGit(git);
367
- const contracts = (await reconcileBatch(git, observation.contracts.keys(), input.hooks, input.retryHooks)).map((item) => ({
677
+ const observation = await withGitReadObservation(input.scope, input.channel, async (read) => await observeContractWorld(read));
678
+ const contracts = (await reconcileBatch(git, input.channel, observation.contracts.keys(), {
679
+ hooks: input.hooks,
680
+ retryHooks: input.retryHooks,
681
+ retainTerminalWorktree: input.retainTerminalWorktree ?? false,
682
+ ...(input.places === undefined ? {} : { places: input.places }),
683
+ })).map((item) => ({
368
684
  contractId: item.contract,
369
685
  state: item.state,
370
686
  report: item.result,