@astrosheep/keiyaku 4.0.1 → 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 (245) hide show
  1. package/README.md +137 -5
  2. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
  3. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
  4. package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
  5. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -3
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -35
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +98 -58
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +152 -53
  9. package/build/src/akuma/abort.d.ts +2 -0
  10. package/build/src/akuma/abort.js +50 -0
  11. package/build/src/akuma/akuma.d.ts +23 -14
  12. package/build/src/akuma/akuma.js +120 -104
  13. package/build/src/akuma/archetype.d.ts +7 -6
  14. package/build/src/akuma/archetype.js +68 -41
  15. package/build/src/akuma/body.d.ts +3 -5
  16. package/build/src/akuma/body.js +408 -213
  17. package/build/src/akuma/heart/facts.d.ts +25 -34
  18. package/build/src/akuma/heart/facts.js +18 -7
  19. package/build/src/akuma/heart/index.d.ts +39 -42
  20. package/build/src/akuma/heart/index.js +134 -93
  21. package/build/src/akuma/heart/rows.d.ts +9 -31
  22. package/build/src/akuma/heart/rows.js +26 -44
  23. package/build/src/akuma/heart/schema.d.ts +1 -1
  24. package/build/src/akuma/heart/schema.js +7 -15
  25. package/build/src/akuma/heart/soul.d.ts +8 -0
  26. package/build/src/akuma/heart/soul.js +136 -0
  27. package/build/src/akuma/heart/storage.d.ts +28 -14
  28. package/build/src/akuma/heart/storage.js +86 -26
  29. package/build/src/akuma/identity.d.ts +2 -2
  30. package/build/src/akuma/identity.js +9 -9
  31. package/build/src/akuma/index.d.ts +6 -1
  32. package/build/src/akuma/index.js +6 -0
  33. package/build/src/akuma/projection.d.ts +117 -38
  34. package/build/src/akuma/projection.js +208 -97
  35. package/build/src/akuma/provider-recipe.d.ts +24 -0
  36. package/build/src/akuma/provider-recipe.js +100 -0
  37. package/build/src/akuma/provider.d.ts +12 -4
  38. package/build/src/akuma/provider.js +117 -70
  39. package/build/src/akuma/providers/acp/core.d.ts +19 -0
  40. package/build/src/akuma/providers/acp/core.js +159 -0
  41. package/build/src/akuma/providers/acp/events.d.ts +20 -0
  42. package/build/src/akuma/providers/acp/events.js +73 -0
  43. package/build/src/akuma/providers/acp/index.d.ts +12 -0
  44. package/build/src/akuma/providers/acp/index.js +94 -0
  45. package/build/src/akuma/providers/claude/events.js +66 -13
  46. package/build/src/akuma/providers/claude/index.d.ts +2 -1
  47. package/build/src/akuma/providers/claude/index.js +35 -21
  48. package/build/src/akuma/providers/codex-app-server/events.js +4 -1
  49. package/build/src/akuma/providers/codex-app-server/index.d.ts +3 -3
  50. package/build/src/akuma/providers/codex-app-server/index.js +24 -31
  51. package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
  52. package/build/src/akuma/providers/grok-build/index.js +70 -0
  53. package/build/src/akuma/providers/index.d.ts +5 -3
  54. package/build/src/akuma/providers/index.js +24 -59
  55. package/build/src/akuma/providers/opencode-sdk/events.d.ts +40 -34
  56. package/build/src/akuma/providers/opencode-sdk/events.js +220 -101
  57. package/build/src/akuma/providers/opencode-sdk/index.d.ts +3 -2
  58. package/build/src/akuma/providers/opencode-sdk/index.js +233 -128
  59. package/build/src/akuma/providers/opencode-sdk/session.d.ts +11 -26
  60. package/build/src/akuma/providers/opencode-sdk/session.js +10 -9
  61. package/build/src/akuma/providers/pi/events.js +49 -11
  62. package/build/src/akuma/providers/pi/index.d.ts +1 -1
  63. package/build/src/akuma/providers/pi/index.js +50 -21
  64. package/build/src/akuma/publication.d.ts +3 -3
  65. package/build/src/akuma/publication.js +28 -40
  66. package/build/src/akuma/requests.d.ts +9 -7
  67. package/build/src/akuma/requests.js +92 -65
  68. package/build/src/alias/index.d.ts +2 -2
  69. package/build/src/alias/index.js +10 -10
  70. package/build/src/body/decode.js +7 -1
  71. package/build/src/body/region.d.ts +2 -0
  72. package/build/src/body/region.js +77 -7
  73. package/build/src/cli/accepted.d.ts +17 -13
  74. package/build/src/cli/accepted.js +72 -34
  75. package/build/src/cli/actor.js +3 -3
  76. package/build/src/cli/commands/akuma-invoke.d.ts +4 -3
  77. package/build/src/cli/commands/akuma-invoke.js +14 -9
  78. package/build/src/cli/commands/akuma.d.ts +13 -3
  79. package/build/src/cli/commands/akuma.js +67 -34
  80. package/build/src/cli/commands/contract.d.ts +18 -5
  81. package/build/src/cli/commands/contract.js +9 -3
  82. package/build/src/cli/commands/task-invoke.d.ts +17 -4
  83. package/build/src/cli/commands/task-invoke.js +43 -20
  84. package/build/src/cli/commands/task-query.d.ts +5 -0
  85. package/build/src/cli/commands/task-query.js +247 -0
  86. package/build/src/cli/commands/task.d.ts +3 -1
  87. package/build/src/cli/commands/task.js +51 -13
  88. package/build/src/cli/coordinates.d.ts +18 -0
  89. package/build/src/cli/coordinates.js +120 -0
  90. package/build/src/cli/draft.d.ts +8 -0
  91. package/build/src/cli/draft.js +96 -0
  92. package/build/src/cli/invoke.d.ts +4 -3
  93. package/build/src/cli/invoke.js +160 -179
  94. package/build/src/cli/main.js +34 -6
  95. package/build/src/cli/parse.d.ts +9 -2
  96. package/build/src/cli/parse.js +29 -7
  97. package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
  98. package/build/src/cli/render/akuma-tool-command.js +144 -0
  99. package/build/src/cli/render/akuma-tool.d.ts +2 -2
  100. package/build/src/cli/render/akuma-tool.js +30 -4
  101. package/build/src/cli/render/akuma.d.ts +1 -0
  102. package/build/src/cli/render/akuma.js +211 -116
  103. package/build/src/cli/render/audit.d.ts +3 -0
  104. package/build/src/cli/render/audit.js +104 -0
  105. package/build/src/cli/render/contract.d.ts +3 -3
  106. package/build/src/cli/render/contract.js +192 -79
  107. package/build/src/cli/render/kanshi.js +263 -168
  108. package/build/src/cli/render/receipt.d.ts +19 -0
  109. package/build/src/cli/render/receipt.js +106 -0
  110. package/build/src/cli/render/refusal.d.ts +16 -2
  111. package/build/src/cli/render/refusal.js +88 -20
  112. package/build/src/cli/render/region.d.ts +2 -0
  113. package/build/src/cli/render/region.js +17 -0
  114. package/build/src/cli/render/task.d.ts +2 -1
  115. package/build/src/cli/render/task.js +223 -60
  116. package/build/src/cli/render/terminal.d.ts +7 -0
  117. package/build/src/cli/render/terminal.js +46 -0
  118. package/build/src/cli/render/text.js +6 -3
  119. package/build/src/cli/result.d.ts +115 -20
  120. package/build/src/cli/usage.d.ts +1 -0
  121. package/build/src/cli/usage.js +3 -0
  122. package/build/src/contract-worktree.d.ts +6 -5
  123. package/build/src/contract-worktree.js +95 -57
  124. package/build/src/coordination/durable-file.d.ts +4 -3
  125. package/build/src/coordination/durable-file.js +29 -25
  126. package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
  127. package/build/src/coordination/sqlite-transaction-lock.js +22 -5
  128. package/build/src/core/facts/fold.js +1 -6
  129. package/build/src/core/facts/gate.d.ts +1 -0
  130. package/build/src/core/facts/gate.js +1 -0
  131. package/build/src/core/verbs/amend.d.ts +1 -1
  132. package/build/src/core/verbs/amend.js +0 -11
  133. package/build/src/core/verbs/deliver.d.ts +1 -1
  134. package/build/src/core/verbs/deliver.js +1 -7
  135. package/build/src/core/verbs/placement.d.ts +1 -1
  136. package/build/src/core/verbs/placement.js +4 -1
  137. package/build/src/dispatch/index.d.ts +2 -2
  138. package/build/src/dispatch/index.js +17 -17
  139. package/build/src/git/admission.d.ts +1 -1
  140. package/build/src/git/admission.js +11 -11
  141. package/build/src/git/hooks.js +13 -13
  142. package/build/src/git/integration.d.ts +14 -15
  143. package/build/src/git/integration.js +80 -44
  144. package/build/src/git/observe.d.ts +5 -3
  145. package/build/src/git/observe.js +18 -12
  146. package/build/src/git/read-observation.js +9 -9
  147. package/build/src/git/reconcile.d.ts +2 -0
  148. package/build/src/git/reconcile.js +138 -95
  149. package/build/src/git/repository.d.ts +27 -19
  150. package/build/src/git/repository.js +155 -83
  151. package/build/src/git/scratch.d.ts +7 -3
  152. package/build/src/git/scratch.js +44 -37
  153. package/build/src/git/target-placement.d.ts +40 -4
  154. package/build/src/git/target-placement.js +221 -101
  155. package/build/src/git/tender.d.ts +6 -5
  156. package/build/src/git/tender.js +24 -43
  157. package/build/src/git/terminal-seal.d.ts +1 -1
  158. package/build/src/git/terminal-seal.js +7 -5
  159. package/build/src/git/workspace.d.ts +36 -4
  160. package/build/src/git/workspace.js +53 -18
  161. package/build/src/identity/selector.js +1 -1
  162. package/build/src/index.d.ts +3 -3
  163. package/build/src/index.js +1 -1
  164. package/build/src/kanshi/index.d.ts +2 -2
  165. package/build/src/kanshi/index.js +1 -1
  166. package/build/src/kanshi/read.d.ts +2 -1
  167. package/build/src/kanshi/read.js +118 -27
  168. package/build/src/kanshi/report.d.ts +50 -0
  169. package/build/src/kanshi/select.d.ts +5 -0
  170. package/build/src/kanshi/select.js +32 -0
  171. package/build/src/library/address.d.ts +12 -3
  172. package/build/src/library/address.js +77 -46
  173. package/build/src/library/akuma-creation.d.ts +6 -1
  174. package/build/src/library/akuma-creation.js +86 -13
  175. package/build/src/library/audit.d.ts +18 -0
  176. package/build/src/library/audit.js +44 -0
  177. package/build/src/library/bind.js +4 -4
  178. package/build/src/library/catalog.d.ts +1 -1
  179. package/build/src/library/catalog.js +5 -8
  180. package/build/src/library/contract.d.ts +5 -6
  181. package/build/src/library/contract.js +11 -35
  182. package/build/src/library/delivery.d.ts +2 -1
  183. package/build/src/library/fleet.d.ts +2 -2
  184. package/build/src/library/fleet.js +35 -71
  185. package/build/src/library/keiyaku.d.ts +3 -2
  186. package/build/src/library/keiyaku.js +1 -0
  187. package/build/src/library/mutation.d.ts +7 -6
  188. package/build/src/library/mutation.js +23 -25
  189. package/build/src/library/reconcile.d.ts +29 -0
  190. package/build/src/library/reconcile.js +179 -0
  191. package/build/src/library/region.d.ts +12 -0
  192. package/build/src/library/region.js +15 -1
  193. package/build/src/library/repo.d.ts +4 -16
  194. package/build/src/library/repo.js +13 -38
  195. package/build/src/protocol/attempt.js +6 -6
  196. package/build/src/protocol/bind.js +4 -4
  197. package/build/src/protocol/intent.d.ts +15 -2
  198. package/build/src/protocol/intent.js +21 -6
  199. package/build/src/protocol/operations.d.ts +73 -22
  200. package/build/src/protocol/operations.js +292 -88
  201. package/build/src/protocol/outcome.d.ts +9 -3
  202. package/build/src/protocol/outcome.js +3 -1
  203. package/build/src/protocol/placement.d.ts +15 -4
  204. package/build/src/protocol/placement.js +58 -25
  205. package/build/src/protocol/read/status.d.ts +8 -1
  206. package/build/src/protocol/read/status.js +61 -14
  207. package/build/src/runtime/proc/line-rpc.d.ts +3 -8
  208. package/build/src/runtime/proc/line-rpc.js +16 -43
  209. package/build/src/runtime/proc/run.d.ts +15 -29
  210. package/build/src/runtime/proc/run.js +113 -105
  211. package/build/src/runtime/proc/stdio.d.ts +18 -0
  212. package/build/src/runtime/proc/stdio.js +58 -0
  213. package/build/src/settings.d.ts +2 -2
  214. package/build/src/settings.js +8 -8
  215. package/build/src/settlement/fence.d.ts +0 -4
  216. package/build/src/settlement/fence.js +0 -9
  217. package/build/src/settlement/holder.d.ts +11 -1
  218. package/build/src/settlement/holder.js +25 -0
  219. package/build/src/settlement/settle.d.ts +1 -1
  220. package/build/src/settlement/settle.js +52 -89
  221. package/build/src/task/board.d.ts +3 -3
  222. package/build/src/task/board.js +6 -9
  223. package/build/src/task/compose.d.ts +1 -1
  224. package/build/src/task/compose.js +18 -10
  225. package/build/src/task/context.d.ts +3 -3
  226. package/build/src/task/context.js +14 -14
  227. package/build/src/task/document.d.ts +2 -1
  228. package/build/src/task/document.js +15 -5
  229. package/build/src/task/index.d.ts +19 -7
  230. package/build/src/task/index.js +42 -23
  231. package/build/src/task/operations.d.ts +15 -9
  232. package/build/src/task/operations.js +78 -48
  233. package/build/src/task/query.d.ts +67 -0
  234. package/build/src/task/query.js +279 -0
  235. package/build/src/task/store.d.ts +2 -2
  236. package/build/src/task/store.js +40 -25
  237. package/build/src/verification/execution.d.ts +4 -2
  238. package/build/src/verification/execution.js +9 -5
  239. package/build/src/workspace-place.d.ts +41 -0
  240. package/build/src/workspace-place.js +386 -0
  241. package/build/src/world.d.ts +13 -2
  242. package/build/src/world.js +81 -48
  243. package/package.json +3 -2
  244. package/build/src/protocol/read/audit.d.ts +0 -31
  245. package/build/src/protocol/read/audit.js +0 -55
@@ -1,4 +1,4 @@
1
- import { materializeIntegrationSnapshot, planIntegration, prepareReviewIntegration, readDeliveryDiff, } from "../git/integration.js";
1
+ import { materializeIntegrationSnapshot, planIntegration, readDeliveryDiff, readDeliveryScope, worktreeChangeId, } from "../git/integration.js";
2
2
  import { captureTender, dirtyTenderDelta, dirtyTenderRefusal, materializeTenderSnapshot, } from "../git/tender.js";
3
3
  import { currentBranch, extendContractsForAdmissionAt, observeContractAt, observeContractWorld, observeContractsForAdmissionAt, } from "../git/observe.js";
4
4
  import { reconcile, reconcileBatch, reconcileObservationFailure, } from "../git/reconcile.js";
@@ -6,20 +6,22 @@ import { NoGitWorldError, repositoryAt } from "../git/repository.js";
6
6
  import { withGitReadObservation } from "../git/read-observation.js";
7
7
  import { dependencyKeySet } from "../core/subject.js";
8
8
  import { AuthorityCorruptionError } from "../core/facts/errors.js";
9
- import { contractState, documentIsCurrent } from "../core/facts/observation.js";
9
+ import { activeContract, contractState, documentIsCurrent } from "../core/facts/observation.js";
10
10
  import { gate } from "../core/facts/types.js";
11
11
  import { decideAbandon } from "../core/verbs/abandon.js";
12
12
  import { decideAmend } from "../core/verbs/amend.js";
13
13
  import { decideArc } from "../core/verbs/arc.js";
14
14
  import { decideDeliver } from "../core/verbs/deliver.js";
15
15
  import { decideAttestation } from "../core/verbs/attestation.js";
16
- import { admitIntent, verifyDelivery, } from "./intent.js";
17
- import { admitPlacement } from "./placement.js";
18
- import { auditReport, readAuditAt } 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";
19
19
  import { readDocuments } from "./read/documents.js";
20
20
  import { readContractBoard, readContractObservationAt, } from "./read/status.js";
21
21
  import { admitDecidedOffer, mintAttempts } from "./attempt.js";
22
+ import { appointmentFor, readManagedWorktreeAppointment, readPlaceRegister, } from "../workspace-place.js";
22
23
  export { bindOperation } from "./bind.js";
24
+ export { reconcileObservationFailure } from "../git/reconcile.js";
23
25
  import { accepted, admitted, complete, } from "./outcome.js";
24
26
  const REVIEWED = gate("reviewed");
25
27
  function timestamp() { return new Date().toISOString(); }
@@ -40,6 +42,19 @@ function stepStop(result) {
40
42
  function verificationStop(step) {
41
43
  return "failure" in step ? step : stepStop(step);
42
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
+ }
43
58
  function placementStop(result) {
44
59
  if (result.kind === "accepted")
45
60
  return undefined;
@@ -53,15 +68,17 @@ function placementStop(result) {
53
68
  return result.kind === "refused" ? { refusal: result.refusal } : { retry: result };
54
69
  }
55
70
  export { NoGitWorldError };
56
- export function scopeOperation(input) { return repositoryAt(input.coordinate); }
57
- export function currentBranchOperation(input) {
58
- 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);
59
76
  }
60
77
  export async function contractsOperation(input) {
61
78
  return withGitReadObservation(input.scope, input.channel, readContractBoard);
62
79
  }
63
- export function contractObservationOperation(input) {
64
- return readContractObservationAt(input.scope, input.channel, input.contractId);
80
+ export async function contractObservationOperation(input) {
81
+ return await readContractObservationAt(input.scope, input.channel, input.contractId);
65
82
  }
66
83
  export async function documentsOperationAt(scope, channel) {
67
84
  return withGitReadObservation(scope, channel, readDocuments);
@@ -76,7 +93,26 @@ export async function deliveryOperation(input) {
76
93
  const state = (await observeContractAt(input.scope, input.channel, input.contractId)).state;
77
94
  return state?.delivery?.data ?? null;
78
95
  }
79
- export async function deliveryDiffOperation(input) { return readDeliveryDiff(input.scope, input.integrationPredecessor, input.integrationSnapshot); }
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
+ }
80
116
  export async function amendOperation(input) {
81
117
  const attempts = mintAttempts({ entryCount: 1 });
82
118
  let source = input.source;
@@ -89,7 +125,7 @@ export async function amendOperation(input) {
89
125
  ? undefined
90
126
  : { source, ...input.deriveAmendment(source) };
91
127
  if (amendment !== undefined) {
92
- observation = await extendContractsForAdmissionAt(input.channel, observation, [...new Set([...(state?.terms.after ?? []), ...amendment.terms.after])]);
128
+ observation = await extendPrerequisiteClosureAt(input.channel, observation, [...new Set([...(state?.terms.after ?? []), ...amendment.terms.after])]);
93
129
  }
94
130
  const preparation = amendment === undefined
95
131
  ? undefined
@@ -129,32 +165,41 @@ export async function amendOperation(input) {
129
165
  }
130
166
  return { kind: "retry", reason: { kind: "exhausted" } };
131
167
  }
132
- export function prepareDelivery(repository, stage, input) {
168
+ export async function prepareDelivery(repository, stage, input) {
133
169
  const { contractId, coordinates } = stage;
134
170
  if (coordinates.workspace === "here" && coordinates.target !== undefined) {
135
- const branch = currentBranch(repository);
171
+ const branch = await currentBranch(repository);
136
172
  if (branch !== coordinates.target) {
137
173
  return { kind: "refused", refusal: { kind: "workspace-not-on-target", contractId, target: coordinates.target, branch } };
138
174
  }
139
175
  }
140
- const tender = captureTender(repository, stage);
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
+ });
141
186
  if (tender.kind === "refused")
142
187
  return tender;
143
188
  if ((tender.data.dirty && input.includeDirty !== true) || tender.data.changes.submodules.length > 0) {
144
- return { kind: "refused", refusal: dirtyTenderRefusal(repository, contractId, tender.data) };
189
+ return { kind: "refused", refusal: await dirtyTenderRefusal(repository, contractId, tender.data) };
145
190
  }
146
- const tenderSnapshot = materializeTenderSnapshot(repository, tender.data, {
191
+ const tenderSnapshot = await materializeTenderSnapshot(repository, tender.data, {
147
192
  contractId,
148
193
  title: input.title,
149
194
  ...(input.message === undefined ? {} : { message: input.message }),
150
195
  });
151
196
  const requireBranchesToBeUpToDate = input.requireBranchesToBeUpToDate ?? false;
152
- const integration = planIntegration(repository, stage, { ...tender.data, head: tenderSnapshot }, requireBranchesToBeUpToDate);
197
+ const integration = await planIntegration(repository, { contractId, coordinates }, { ...tender.data, head: tenderSnapshot }, requireBranchesToBeUpToDate);
153
198
  if (integration.kind === "refused")
154
199
  return integration;
155
200
  const integrationSnapshot = coordinates.target === undefined
156
201
  ? tenderSnapshot
157
- : materializeIntegrationSnapshot(repository, integration.data.tree, integration.data.predecessor, {
202
+ : await materializeIntegrationSnapshot(repository, integration.data.tree, integration.data.predecessor, {
158
203
  contractId,
159
204
  title: input.title,
160
205
  ...(input.message === undefined ? {} : { message: input.message }),
@@ -163,28 +208,54 @@ export function prepareDelivery(repository, stage, input) {
163
208
  kind: "prepared",
164
209
  data: {
165
210
  tenderSnapshot,
166
- integration: { predecessor: integration.data.predecessor, snapshot: integrationSnapshot, changeId: integration.data.changeId },
211
+ integration: {
212
+ predecessor: integration.data.predecessor,
213
+ snapshot: integrationSnapshot,
214
+ changeId: await worktreeChangeId(repository, { contractId, coordinates }, tender.data),
215
+ },
167
216
  method: "squash",
168
217
  policy: { requireBranchesToBeUpToDate },
169
218
  },
170
219
  };
171
220
  }
172
- export function prepareReview(repository, stage) {
173
- const tender = captureTender(repository, stage);
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
+ });
174
229
  if (tender.kind === "refused")
175
230
  return tender;
176
231
  if (tender.data.changes.submodules.length > 0) {
177
- return { kind: "refused", refusal: dirtyTenderRefusal(repository, stage.contractId, tender.data) };
232
+ return { kind: "refused", refusal: await dirtyTenderRefusal(repository, stage.contractId, tender.data) };
178
233
  }
179
- const workspace = dirtyTenderDelta(repository, tender.data);
180
- return prepareReviewIntegration(repository, stage, tender.data, workspace);
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
+ };
243
+ }
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
+ },
254
+ };
181
255
  }
182
256
  async function deliverAttempt(input, attempt) {
183
- let decisionObservation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
257
+ const decisionObservation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
184
258
  const state = contractState(decisionObservation.decision, input.contractId);
185
- if (state !== null) {
186
- decisionObservation = await extendContractsForAdmissionAt(input.channel, decisionObservation, state.terms.after);
187
- }
188
259
  const derivation = state === null || input.deriveDocument === undefined
189
260
  ? undefined
190
261
  : input.deriveDocument(state);
@@ -200,7 +271,7 @@ async function deliverAttempt(input, attempt) {
200
271
  };
201
272
  }
202
273
  else {
203
- const prepared = prepareDelivery(input.scope, {
274
+ const prepared = await prepareDelivery(input.scope, {
204
275
  contractId: state.id,
205
276
  coordinates: state.coordinates,
206
277
  }, {
@@ -247,27 +318,35 @@ async function completeDelivery(input, first) {
247
318
  }
248
319
  let admission = first;
249
320
  let verificationValue;
321
+ let verificationReuse;
250
322
  let cleanup;
251
323
  let leak;
252
- const verification = await verifyDelivery({
253
- channel: input.channel,
254
- repository: input.scope,
255
- contractId: input.contractId,
256
- ...(input.actor === undefined ? {} : { actor: input.actor }),
257
- at: timestamp(),
258
- state: first.state,
259
- environment: process.env,
260
- ...(input.signal === undefined ? {} : { signal: input.signal }),
261
- ...(derivation.verification.data === null
262
- ? {}
263
- : { verification: derivation.verification.data }),
264
- });
265
- if (verification !== null) {
266
- cleanup = verification.cleanup;
267
- leak = verification.leak;
268
- verificationValue = verificationStop(verification.step);
269
- if (!("failure" in verification.step) && verification.step.kind === "accepted") {
270
- 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);
271
350
  }
272
351
  }
273
352
  const placement = await admitPlacement(input.channel, input.scope, first.state.coordinates.target, {
@@ -281,6 +360,7 @@ async function completeDelivery(input, first) {
281
360
  return admitted(admission, {
282
361
  ...first.value.delivery,
283
362
  ...(verificationValue === undefined ? {} : { verification: verificationValue }),
363
+ ...(verificationReuse === undefined ? {} : { verificationReuse }),
284
364
  ...(placementValue === undefined ? {} : { placement: placementValue }),
285
365
  ...(cleanup === undefined ? {} : { cleanup }),
286
366
  ...(leak === undefined ? {} : { leak }),
@@ -306,7 +386,7 @@ export async function deliverOperation(input) {
306
386
  }
307
387
  if (first === null)
308
388
  return { kind: "retry", reason: { kind: "exhausted" } };
309
- return completeDelivery(input, first);
389
+ return await completeDelivery(input, first);
310
390
  }
311
391
  export async function abandonOperation(input) {
312
392
  return complete(await admitIntent(input.channel, input.scope, {
@@ -327,16 +407,20 @@ export async function arcOperation(input) {
327
407
  data: input.chapter,
328
408
  }, decideArc), undefined);
329
409
  }
330
- function reviewAttempt(input, attempt) {
331
- return reviewAttemptObserved(input, attempt);
410
+ function reviewValue(value, placement) {
411
+ return {
412
+ ...(value.workspace === undefined ? {} : { workspace: value.workspace }),
413
+ ...(placement === undefined ? {} : { placement }),
414
+ };
332
415
  }
333
- async function reviewAttemptObserved(input, attempt) {
416
+ async function reviewAttempt(input, attempt) {
334
417
  const decisionObservation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
335
418
  const state = contractState(decisionObservation.decision, input.contractId);
336
419
  let preparation;
337
420
  let workspace;
421
+ let tender;
338
422
  if (state !== null) {
339
- const prepared = prepareReview(input.scope, { contractId: state.id, coordinates: state.coordinates });
423
+ const prepared = await captureReviewableWorktree(input.scope, { contractId: state.id, coordinates: state.coordinates });
340
424
  preparation = prepared.kind === "refused"
341
425
  ? { kind: "refused", refusal: prepared.refusal }
342
426
  : {
@@ -351,8 +435,10 @@ async function reviewAttemptObserved(input, attempt) {
351
435
  ...(input.summary === undefined ? {} : { summary: input.summary }),
352
436
  },
353
437
  };
354
- if (prepared.kind === "prepared")
438
+ if (prepared.kind === "prepared") {
355
439
  workspace = prepared.data.workspace;
440
+ tender = prepared.data.tender;
441
+ }
356
442
  }
357
443
  const decisionInput = {
358
444
  contractId: input.contractId,
@@ -374,7 +460,10 @@ async function reviewAttemptObserved(input, attempt) {
374
460
  if (admitted.kind === "accepted")
375
461
  return {
376
462
  ...admitted,
377
- value: workspace === undefined ? {} : { workspace },
463
+ value: {
464
+ ...(workspace === undefined ? {} : { workspace }),
465
+ ...(tender === undefined ? {} : { tender }),
466
+ },
378
467
  };
379
468
  return admitted;
380
469
  }
@@ -398,58 +487,167 @@ export async function reviewOperation(input) {
398
487
  if (review.kind !== "accepted")
399
488
  return review;
400
489
  if (input.verdict !== "satisfied")
401
- return admitted(review, review.value);
402
- const placement = await admitPlacement(input.channel, git, review.state.coordinates.target, {
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, {
403
494
  contractId: input.contractId,
404
495
  ...(input.actor === undefined ? {} : { actor: input.actor }),
405
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;
406
506
  });
407
507
  const stopped = placementStop(placement);
408
508
  const admission = placement.kind === "accepted" ? mergeAdmissions(review, placement) : review;
409
- return admitted(admission, { ...review.value, ...(stopped === undefined ? {} : { placement: stopped }) });
509
+ return admitted(admission, reviewValue(review.value, stopped));
410
510
  }
411
- export async function auditOperation(input) {
412
- const git = input.scope;
413
- const initial = await readAuditAt(git, input.channel, input.contractId, REVIEWED);
414
- if (initial.state === null)
415
- return { kind: "refused", refusal: { kind: "contract-missing", contractId: input.contractId } };
416
- const derivation = input.deriveDocument?.(initial.state);
417
- if (derivation === undefined || !documentIsCurrent(initial.state, derivation.document)) {
418
- return { kind: "refused", refusal: { kind: "document-moved", contractId: input.contractId } };
419
- }
420
- if (derivation.verification.kind === "refused") {
421
- return { kind: "refused", refusal: derivation.verification.refusal };
422
- }
423
- if (initial.state.delivery === null || derivation.verification.data === null) {
424
- 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 } };
425
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) {
426
536
  const verification = await verifyDelivery({
427
537
  channel: input.channel,
428
- repository: git,
538
+ repository: input.scope,
429
539
  contractId: input.contractId,
430
540
  ...(input.actor === undefined ? {} : { actor: input.actor }),
431
541
  at: timestamp(),
432
- state: initial.state,
542
+ state,
543
+ snapshot,
433
544
  environment: process.env,
434
545
  ...(input.signal === undefined ? {} : { signal: input.signal }),
435
- verification: derivation.verification.data,
546
+ verification: definition,
436
547
  });
437
548
  if (verification === null) {
438
549
  throw new Error("audit verification preparation unexpectedly produced no attempt");
439
550
  }
440
- const attempt = verificationStop(verification.step);
441
- const report = !("failure" in verification.step) && verification.step.kind === "accepted"
442
- ? auditReport(verification.step.journal, REVIEWED, initial.state, initial.report.targetObservation)
443
- : 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);
444
633
  const value = {
445
- ...report,
446
- ...(attempt === undefined ? {} : { attempt }),
447
- ...(verification.cleanup === undefined ? {} : { cleanup: verification.cleanup }),
448
- ...(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 }),
640
+ };
641
+ const obligations = {
642
+ ...(verified?.cleanup === undefined ? {} : { cleanup: verified.cleanup }),
643
+ ...(verified?.leak === undefined ? {} : { leak: verified.leak }),
449
644
  };
450
- return !("failure" in verification.step) && verification.step.kind === "accepted"
451
- ? admitted(verification.step, value)
452
- : accepted(initial.state, [], value);
645
+ return verified?.admission === undefined
646
+ ? accepted(state, [], value, undefined, obligations)
647
+ : {
648
+ ...admitted(verified.admission, value),
649
+ ...obligations,
650
+ };
453
651
  }
454
652
  export async function reconcileOperation(input) {
455
653
  try {
@@ -460,6 +658,7 @@ export async function reconcileOperation(input) {
460
658
  hooks: input.hooks,
461
659
  retryHooks: input.retryHooks,
462
660
  ...(input.retainTerminalWorktree === undefined ? {} : { retainTerminalWorktree: input.retainTerminalWorktree }),
661
+ ...(input.place === undefined ? {} : { place: input.place }),
463
662
  });
464
663
  return { state: observation.state, report: observation.result };
465
664
  }
@@ -469,13 +668,18 @@ export async function reconcileOperation(input) {
469
668
  return { state: null, report: reconcileObservationFailure(error) };
470
669
  }
471
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
+ }
472
675
  export async function reconcileAllOperation(input) {
473
676
  const git = input.scope;
474
- const observation = await withGitReadObservation(input.scope, input.channel, (read) => observeContractWorld(read));
677
+ const observation = await withGitReadObservation(input.scope, input.channel, async (read) => await observeContractWorld(read));
475
678
  const contracts = (await reconcileBatch(git, input.channel, observation.contracts.keys(), {
476
679
  hooks: input.hooks,
477
680
  retryHooks: input.retryHooks,
478
681
  retainTerminalWorktree: input.retainTerminalWorktree ?? false,
682
+ ...(input.places === undefined ? {} : { places: input.places }),
479
683
  })).map((item) => ({
480
684
  contractId: item.contract,
481
685
  state: item.state,
@@ -1,23 +1,29 @@
1
1
  import type { ContractHead, ContractState, JournalEntry } from "../core/facts/types.js";
2
+ import type { WorktreeLeak } from "../git/scratch.js";
3
+ import type { ReconcileResult } from "../git/reconcile.js";
2
4
  import type { AcceptedAdmission } from "./attempt.js";
5
+ import type { VerificationCleanupFailure } from "./intent.js";
3
6
  import type { ProtocolResult, ProtocolTerminal } from "./run.js";
4
- import type { ReconcileResult } from "../git/reconcile.js";
5
7
  export type AcceptedProtocolStep = AcceptedAdmission & Readonly<{
6
8
  physical?: ReconcileResult;
7
9
  }>;
10
+ export type AcceptedObligations = Readonly<{
11
+ cleanup?: VerificationCleanupFailure;
12
+ leak?: WorktreeLeak;
13
+ }>;
8
14
  export type IntentOutcome<Value, Refusal = never> = Readonly<{
9
15
  kind: "accepted";
10
16
  facts: readonly JournalEntry[];
11
17
  head: ContractHead;
12
18
  value: Value;
13
19
  physical?: ReconcileResult;
14
- }> | Readonly<{
20
+ } & AcceptedObligations> | Readonly<{
15
21
  kind: "refused";
16
22
  refusal: Refusal;
17
23
  }> | Readonly<{
18
24
  kind: "retry";
19
25
  reason: ProtocolTerminal;
20
26
  }>;
21
- export declare function accepted<Value, Refusal = never>(state: ContractState, facts: readonly JournalEntry[], value: Value, physical?: ReconcileResult): IntentOutcome<Value, Refusal>;
27
+ export declare function accepted<Value, Refusal = never>(state: ContractState, facts: readonly JournalEntry[], value: Value, physical?: ReconcileResult, obligations?: AcceptedObligations): IntentOutcome<Value, Refusal>;
22
28
  export declare function admitted<Value, Refusal = never>(admission: AcceptedProtocolStep, value: Value): IntentOutcome<Value, Refusal>;
23
29
  export declare function complete<Value, Refusal>(result: ProtocolResult<Refusal>, value: Value): IntentOutcome<Value, Refusal>;
@@ -1,4 +1,4 @@
1
- export function accepted(state, facts, value, physical) {
1
+ export function accepted(state, facts, value, physical, obligations) {
2
2
  if (state.head === null)
3
3
  throw new Error("accepted contract is missing its journal head");
4
4
  return {
@@ -7,6 +7,8 @@ export function accepted(state, facts, value, physical) {
7
7
  head: state.head,
8
8
  value,
9
9
  ...(physical === undefined ? {} : { physical }),
10
+ ...(obligations?.cleanup === undefined ? {} : { cleanup: obligations.cleanup }),
11
+ ...(obligations?.leak === undefined ? {} : { leak: obligations.leak }),
10
12
  };
11
13
  }
12
14
  export function admitted(admission, value) {