@astrosheep/keiyaku 4.5.7 → 4.5.9

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 (244) hide show
  1. package/README.md +10 -0
  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/opencode.js +3 -2
  5. package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +12 -11
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +33 -12
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-babysit/SKILL.md +35 -96
  9. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +28 -49
  10. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +21 -15
  11. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +148 -89
  12. package/build/src/akuma/abort.d.ts +2 -1
  13. package/build/src/akuma/abort.js +6 -23
  14. package/build/src/akuma/akuma-handle.js +4 -2
  15. package/build/src/akuma/akuma-observe.d.ts +2 -0
  16. package/build/src/akuma/akuma-observe.js +1 -0
  17. package/build/src/akuma/akuma-product.js +9 -7
  18. package/build/src/akuma/akuma.d.ts +392 -9
  19. package/build/src/akuma/akuma.js +31 -1
  20. package/build/src/akuma/allowed.d.ts +1 -1
  21. package/build/src/akuma/allowed.js +1 -0
  22. package/build/src/akuma/archetype.js +1 -1
  23. package/build/src/akuma/body.d.ts +8 -5
  24. package/build/src/akuma/body.js +12 -5
  25. package/build/src/akuma/call-request.d.ts +80 -0
  26. package/build/src/akuma/call-request.js +211 -0
  27. package/build/src/akuma/heart/facts.d.ts +16 -78
  28. package/build/src/akuma/heart/facts.js +11 -0
  29. package/build/src/akuma/heart/index.d.ts +3 -2
  30. package/build/src/akuma/heart/index.js +4 -1
  31. package/build/src/akuma/heart/request-authority.d.ts +5 -4
  32. package/build/src/akuma/heart/request-authority.js +20 -34
  33. package/build/src/akuma/heart/request-rows.js +12 -23
  34. package/build/src/akuma/heart/schema.d.ts +1 -1
  35. package/build/src/akuma/heart/schema.js +5 -13
  36. package/build/src/akuma/index.d.ts +1 -1
  37. package/build/src/akuma/index.js +1 -1
  38. package/build/src/akuma/projection-read.d.ts +1 -0
  39. package/build/src/akuma/projection-read.js +8 -1
  40. package/build/src/akuma/projection.d.ts +907 -137
  41. package/build/src/akuma/projection.js +193 -9
  42. package/build/src/akuma/provider.d.ts +30 -3
  43. package/build/src/akuma/provider.js +111 -0
  44. package/build/src/akuma/providers/acp/core.d.ts +2 -2
  45. package/build/src/akuma/providers/acp/core.js +13 -6
  46. package/build/src/akuma/providers/acp/index.js +5 -4
  47. package/build/src/akuma/providers/claude/events.d.ts +2 -2
  48. package/build/src/akuma/providers/claude/events.js +16 -3
  49. package/build/src/akuma/providers/claude/index.d.ts +3 -3
  50. package/build/src/akuma/providers/claude/index.js +16 -5
  51. package/build/src/akuma/providers/codex-app-server/events.d.ts +2 -2
  52. package/build/src/akuma/providers/codex-app-server/events.js +25 -4
  53. package/build/src/akuma/providers/codex-app-server/index.js +18 -6
  54. package/build/src/akuma/providers/grok-build/index.js +5 -4
  55. package/build/src/akuma/providers/opencode-sdk/index.js +66 -25
  56. package/build/src/akuma/providers/opencode-sdk/session.d.ts +3 -2
  57. package/build/src/akuma/providers/opencode-sdk/session.js +28 -11
  58. package/build/src/akuma/providers/pi/index.js +72 -58
  59. package/build/src/akuma/request-lifecycle.d.ts +4 -10
  60. package/build/src/akuma/request-lifecycle.js +7 -5
  61. package/build/src/akuma/request-rendezvous.d.ts +26 -0
  62. package/build/src/akuma/request-rendezvous.js +100 -0
  63. package/build/src/akuma/request-serve.d.ts +6 -66
  64. package/build/src/akuma/request-serve.js +83 -210
  65. package/build/src/akuma/request-wire.d.ts +109 -115
  66. package/build/src/akuma/request-wire.js +63 -318
  67. package/build/src/akuma/requests.d.ts +19 -47
  68. package/build/src/akuma/requests.js +51 -107
  69. package/build/src/akuma/turn-drive.d.ts +5 -3
  70. package/build/src/akuma/turn-drive.js +39 -11
  71. package/build/src/akuma-body.d.ts +7 -2
  72. package/build/src/akuma-body.js +68 -46
  73. package/build/src/body/amend.js +18 -19
  74. package/build/src/cli/accepted.d.ts +1 -1
  75. package/build/src/cli/accepted.js +2 -2
  76. package/build/src/cli/commands/akuma-invoke.d.ts +2 -0
  77. package/build/src/cli/commands/akuma-invoke.js +17 -9
  78. package/build/src/cli/commands/akuma.js +8 -8
  79. package/build/src/cli/commands/contract-invoke.d.ts +3 -2
  80. package/build/src/cli/commands/contract-invoke.js +42 -30
  81. package/build/src/cli/commands/contract.d.ts +16 -20
  82. package/build/src/cli/commands/contract.js +58 -25
  83. package/build/src/cli/commands/install.d.ts +2 -1
  84. package/build/src/cli/commands/install.js +3 -2
  85. package/build/src/cli/commands/task-invoke.d.ts +3 -0
  86. package/build/src/cli/commands/task-invoke.js +23 -140
  87. package/build/src/cli/commands/task.js +54 -20
  88. package/build/src/cli/invoke.js +39 -25
  89. package/build/src/cli/main.js +2 -1
  90. package/build/src/cli/parse.d.ts +2 -2
  91. package/build/src/cli/parse.js +56 -27
  92. package/build/src/cli/render/akuma-activity.d.ts +3 -0
  93. package/build/src/cli/render/akuma-activity.js +45 -29
  94. package/build/src/cli/render/akuma-tool.d.ts +5 -1
  95. package/build/src/cli/render/akuma.js +4 -8
  96. package/build/src/cli/render/audit.js +1 -1
  97. package/build/src/cli/render/catalog.js +80 -21
  98. package/build/src/cli/render/contract-observation.d.ts +2 -0
  99. package/build/src/cli/render/contract-observation.js +11 -0
  100. package/build/src/cli/render/contract.js +35 -62
  101. package/build/src/cli/render/kanshi-akuma.d.ts +8 -0
  102. package/build/src/cli/render/kanshi-akuma.js +132 -0
  103. package/build/src/cli/render/kanshi.js +131 -213
  104. package/build/src/cli/render/receipt.d.ts +1 -2
  105. package/build/src/cli/render/receipt.js +76 -26
  106. package/build/src/cli/render/refusal.js +2 -10
  107. package/build/src/cli/render/region.js +5 -2
  108. package/build/src/cli/render/settings.d.ts +1 -1
  109. package/build/src/cli/render/settings.js +27 -8
  110. package/build/src/cli/render/task.js +22 -5
  111. package/build/src/cli/render/terminal.d.ts +32 -1
  112. package/build/src/cli/render/terminal.js +77 -1
  113. package/build/src/cli/result.d.ts +3 -3
  114. package/build/src/cli/runtime.js +4 -2
  115. package/build/src/cli/selectors.d.ts +2 -1
  116. package/build/src/cli/selectors.js +4 -3
  117. package/build/src/cli/square-edge.js +120 -36
  118. package/build/src/cli/usage.js +2 -1
  119. package/build/src/contract-guidance.d.ts +5 -0
  120. package/build/src/contract-guidance.js +121 -0
  121. package/build/src/contract-worktree.d.ts +0 -1
  122. package/build/src/contract-worktree.js +32 -83
  123. package/build/src/coordination/sqlite-transaction-lock.d.ts +1 -0
  124. package/build/src/coordination/sqlite-transaction-lock.js +5 -0
  125. package/build/src/core/facts/codec.d.ts +2 -0
  126. package/build/src/core/facts/codec.js +4 -0
  127. package/build/src/core/verbs/placement.d.ts +6 -1
  128. package/build/src/core/verbs/placement.js +5 -3
  129. package/build/src/dispatch/index.d.ts +0 -2
  130. package/build/src/dispatch/index.js +54 -55
  131. package/build/src/git/admission.js +2 -2
  132. package/build/src/git/hooks.d.ts +9 -15
  133. package/build/src/git/hooks.js +23 -317
  134. package/build/src/git/nuke.d.ts +2 -1
  135. package/build/src/git/nuke.js +39 -21
  136. package/build/src/git/private-state-seat.d.ts +12 -0
  137. package/build/src/git/private-state-seat.js +39 -0
  138. package/build/src/git/process.d.ts +6 -0
  139. package/build/src/git/process.js +26 -11
  140. package/build/src/git/read-observation.js +29 -20
  141. package/build/src/git/reconcile.d.ts +13 -1
  142. package/build/src/git/reconcile.js +70 -11
  143. package/build/src/git/ref-migration.d.ts +22 -0
  144. package/build/src/git/ref-migration.js +55 -0
  145. package/build/src/git/repository.d.ts +10 -6
  146. package/build/src/git/repository.js +16 -8
  147. package/build/src/git/target-placement.d.ts +1 -0
  148. package/build/src/git/target-placement.js +5 -0
  149. package/build/src/git/tender.d.ts +1 -0
  150. package/build/src/git/terminal-reconcile.d.ts +1 -1
  151. package/build/src/git/terminal-reconcile.js +22 -20
  152. package/build/src/git/workspace.d.ts +14 -0
  153. package/build/src/git/workspace.js +44 -0
  154. package/build/src/kanshi/index.d.ts +1 -1
  155. package/build/src/kanshi/read.js +16 -16
  156. package/build/src/kanshi/report.d.ts +2 -2
  157. package/build/src/library/address.d.ts +9 -3
  158. package/build/src/library/address.js +3 -2
  159. package/build/src/library/akuma-creation.d.ts +4 -3
  160. package/build/src/library/akuma-creation.js +19 -13
  161. package/build/src/library/audit.d.ts +14 -6
  162. package/build/src/library/audit.js +13 -23
  163. package/build/src/library/catalog.d.ts +3 -1
  164. package/build/src/library/catalog.js +20 -6
  165. package/build/src/library/composition.d.ts +385 -0
  166. package/build/src/library/composition.js +28 -0
  167. package/build/src/library/configuration.js +8 -2
  168. package/build/src/library/continuation.js +66 -30
  169. package/build/src/library/contract-bind.js +10 -2
  170. package/build/src/library/contract-forwarding-reconciliation-result.d.ts +102 -0
  171. package/build/src/library/contract-forwarding-reconciliation-result.js +92 -0
  172. package/build/src/library/contract-forwarding-result.d.ts +4464 -0
  173. package/build/src/library/contract-forwarding-result.js +521 -0
  174. package/build/src/library/contract-forwarding.d.ts +71 -0
  175. package/build/src/library/contract-forwarding.js +114 -0
  176. package/build/src/library/contract-handle.d.ts +38 -0
  177. package/build/src/library/contract-handle.js +314 -0
  178. package/build/src/library/contract-operations.d.ts +214 -69
  179. package/build/src/library/contract-operations.js +189 -118
  180. package/build/src/library/contract-types.d.ts +7 -3
  181. package/build/src/library/contract.d.ts +21 -34
  182. package/build/src/library/contract.js +29 -287
  183. package/build/src/library/fleet-result.d.ts +1580 -0
  184. package/build/src/library/fleet-result.js +98 -0
  185. package/build/src/library/fleet.d.ts +112 -54
  186. package/build/src/library/fleet.js +211 -71
  187. package/build/src/library/input.d.ts +3 -1
  188. package/build/src/library/input.js +11 -1
  189. package/build/src/library/keiyaku.d.ts +388 -20
  190. package/build/src/library/keiyaku.js +13 -21
  191. package/build/src/library/mutation.d.ts +3 -3
  192. package/build/src/library/mutation.js +5 -9
  193. package/build/src/library/nuke.d.ts +1 -1
  194. package/build/src/library/nuke.js +4 -3
  195. package/build/src/library/reconcile.d.ts +4 -0
  196. package/build/src/library/reconcile.js +2 -0
  197. package/build/src/library/refusal.d.ts +0 -9
  198. package/build/src/library/refusal.js +0 -7
  199. package/build/src/protocol/amend.js +56 -50
  200. package/build/src/protocol/attempt.d.ts +2 -0
  201. package/build/src/protocol/attempt.js +8 -1
  202. package/build/src/protocol/completion.js +7 -0
  203. package/build/src/protocol/deliver.js +6 -2
  204. package/build/src/protocol/operations.d.ts +4 -1
  205. package/build/src/protocol/operations.js +5 -2
  206. package/build/src/protocol/placement.d.ts +1 -0
  207. package/build/src/protocol/placement.js +52 -38
  208. package/build/src/protocol/read/observation.d.ts +1 -4
  209. package/build/src/protocol/read/observation.js +2 -15
  210. package/build/src/protocol/reintegrate.js +62 -58
  211. package/build/src/protocol/review.js +5 -0
  212. package/build/src/protocol/run.js +17 -13
  213. package/build/src/runtime/proc/run.d.ts +9 -0
  214. package/build/src/runtime/proc/run.js +51 -4
  215. package/build/src/runtime/proc/termination.js +26 -22
  216. package/build/src/runtime/proc/windows-launch.exe +0 -0
  217. package/build/src/settlement/holder.d.ts +2 -1
  218. package/build/src/settlement/holder.js +15 -4
  219. package/build/src/settlement/settle.js +99 -33
  220. package/build/src/task/board.d.ts +68 -27
  221. package/build/src/task/board.js +31 -1
  222. package/build/src/task/catalog.d.ts +4 -0
  223. package/build/src/task/catalog.js +23 -0
  224. package/build/src/task/compose-language.js +33 -7
  225. package/build/src/task/compose-parser.d.ts +1 -1
  226. package/build/src/task/compose-parser.js +1 -1
  227. package/build/src/task/compose.js +2 -0
  228. package/build/src/task/index.d.ts +12 -4
  229. package/build/src/task/index.js +97 -16
  230. package/build/src/task/mutation-result.d.ts +923 -0
  231. package/build/src/task/mutation-result.js +140 -0
  232. package/build/src/task/mutation.d.ts +552 -28
  233. package/build/src/task/mutation.js +304 -97
  234. package/build/src/task/operations.d.ts +1 -4
  235. package/build/src/task/operations.js +0 -6
  236. package/build/src/task/public.d.ts +2 -0
  237. package/build/src/task/public.js +1 -0
  238. package/build/src/workspace-place.d.ts +7 -2
  239. package/build/src/workspace-place.js +34 -24
  240. package/build/src/world.d.ts +1 -0
  241. package/build/src/world.js +11 -0
  242. package/package.json +8 -6
  243. package/build/src/akuma/request-execution.d.ts +0 -8
  244. package/build/src/akuma/request-execution.js +0 -98
@@ -1,4 +1,5 @@
1
1
  import { extendContractsForAdmissionAt, observeContractsForAdmissionAt } from "../git/observe.js";
2
+ import { withPrivateStatePublicationSeat } from "../git/private-state-seat.js";
2
3
  import { contractState } from "../core/facts/observation.js";
3
4
  import { decideAmend } from "../core/verbs/amend.js";
4
5
  import { admitDecidedOffer, mintAttempts } from "./attempt.js";
@@ -24,56 +25,61 @@ async function extendPrerequisiteClosureAt(channel, observation, seeds) {
24
25
  return current;
25
26
  }
26
27
  export async function amendOperation(input) {
27
- const attempts = mintAttempts({ entryCount: 1 });
28
28
  let source = input.source;
29
- for (let index = 0; index < attempts.length; index += 1) {
30
- let observation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
31
- const state = contractState(observation.decision, input.contractId);
32
- if (source === undefined && state !== null)
33
- source = state.terms;
34
- const amendment = source === undefined || input.deriveAmendment === undefined
35
- ? undefined
36
- : { source, ...input.deriveAmendment(source) };
37
- if (amendment !== undefined) {
38
- observation = await extendPrerequisiteClosureAt(input.channel, observation, [
39
- ...new Set([...(state?.terms.after ?? []), ...amendment.terms.after]),
40
- ]);
41
- }
42
- const preparation = amendment === undefined
43
- ? undefined
44
- : amendment.verification.kind === "prepared"
45
- ? { kind: "prepared", data: amendment.terms }
46
- : { kind: "refused", refusal: amendment.verification.refusal };
47
- const decision = decideAmend({
48
- input: {
49
- contractId: input.contractId,
50
- ...(input.actor === undefined ? {} : { actor: input.actor }),
51
- at: timestamp(),
52
- ...(amendment === undefined ? {} : { source: amendment.source }),
53
- ...(preparation === undefined ? {} : { preparation }),
54
- },
55
- attempt: attempts[index],
56
- observation: observation.decision,
57
- });
58
- if (decision.kind === "refused")
59
- return decision;
60
- const admission = await admitDecidedOffer({
61
- channel: input.channel,
62
- repository: input.scope,
63
- decisionObservation: observation,
64
- attempt: attempts[index],
65
- offer: decision.offer,
66
- primaryContract: input.contractId,
67
- });
68
- if (admission.kind === "accepted") {
69
- if (amendment === undefined)
70
- throw new Error("accepted amendment is missing its document derivation");
71
- return admitted(admission, amendment);
72
- }
73
- if (admission.kind === "publication-failed")
74
- return { kind: "retry", reason: admission };
75
- if (admission.kind === "collision" && index + 1 === attempts.length)
76
- return { kind: "retry", reason: admission };
29
+ if (source === undefined) {
30
+ const initial = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
31
+ source = contractState(initial.decision, input.contractId)?.terms;
77
32
  }
78
- return { kind: "retry", reason: { kind: "exhausted" } };
33
+ return await withPrivateStatePublicationSeat(input.scope, async (seat) => {
34
+ const attempts = mintAttempts({ entryCount: 1 });
35
+ for (let index = 0; index < attempts.length; index += 1) {
36
+ let observation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
37
+ const state = contractState(observation.decision, input.contractId);
38
+ const amendment = source === undefined || input.deriveAmendment === undefined
39
+ ? undefined
40
+ : { source, ...input.deriveAmendment(source) };
41
+ if (amendment !== undefined) {
42
+ observation = await extendPrerequisiteClosureAt(input.channel, observation, [
43
+ ...new Set([...(state?.terms.after ?? []), ...amendment.terms.after]),
44
+ ]);
45
+ }
46
+ const preparation = amendment === undefined
47
+ ? undefined
48
+ : amendment.verification.kind === "prepared"
49
+ ? { kind: "prepared", data: amendment.terms }
50
+ : { kind: "refused", refusal: amendment.verification.refusal };
51
+ const decision = decideAmend({
52
+ input: {
53
+ contractId: input.contractId,
54
+ ...(input.actor === undefined ? {} : { actor: input.actor }),
55
+ at: timestamp(),
56
+ ...(amendment === undefined ? {} : { source: amendment.source }),
57
+ ...(preparation === undefined ? {} : { preparation }),
58
+ },
59
+ attempt: attempts[index],
60
+ observation: observation.decision,
61
+ });
62
+ if (decision.kind === "refused")
63
+ return decision;
64
+ const admission = await admitDecidedOffer({
65
+ channel: input.channel,
66
+ repository: input.scope,
67
+ seat,
68
+ decisionObservation: observation,
69
+ attempt: attempts[index],
70
+ offer: decision.offer,
71
+ primaryContract: input.contractId,
72
+ });
73
+ if (admission.kind === "accepted") {
74
+ if (amendment === undefined)
75
+ throw new Error("accepted amendment is missing its document derivation");
76
+ return admitted(admission, amendment);
77
+ }
78
+ if (admission.kind === "publication-failed")
79
+ return { kind: "retry", reason: admission };
80
+ if (admission.kind === "collision" && index + 1 === attempts.length)
81
+ return { kind: "retry", reason: admission };
82
+ }
83
+ return { kind: "retry", reason: { kind: "exhausted" } };
84
+ });
79
85
  }
@@ -1,5 +1,6 @@
1
1
  import { type PublicationFailed } from "../git/admission.js";
2
2
  import { type GitDecisionObservation } from "../git/observe.js";
3
+ import { type PrivateStatePublicationSeat } from "../git/private-state-seat.js";
3
4
  import type { GitDecodeChannel } from "../git/read-observation.js";
4
5
  import { type GitRefAssertion } from "../git/repository.js";
5
6
  import type { GitRepository } from "../git/process.js";
@@ -41,6 +42,7 @@ export type DecidedOfferResult<Refusal = never> = AcceptedAdmission | AttemptTer
41
42
  export declare function admitDecidedOffer<Refusal = never>(input: Readonly<{
42
43
  channel: GitDecodeChannel;
43
44
  repository: GitRepository;
45
+ seat: PrivateStatePublicationSeat;
44
46
  decisionObservation: GitDecisionObservation;
45
47
  attempt: AttemptContext;
46
48
  offer: Offer;
@@ -2,6 +2,7 @@ import { randomBytes } from "node:crypto";
2
2
  import { encodeEntry } from "../core/facts/codec.js";
3
3
  import { admit } from "../git/admission.js";
4
4
  import { observeContractsForAdmissionAt } from "../git/observe.js";
5
+ import { confirmPrivateStatePublication } from "../git/private-state-seat.js";
5
6
  import { GIT_REF, readRefs } from "../git/repository.js";
6
7
  import { foldJournal } from "../core/facts/fold.js";
7
8
  import { AuthorityCorruptionError } from "../core/facts/errors.js";
@@ -103,6 +104,7 @@ export async function admitDecidedOffer(input) {
103
104
  }
104
105
  const admission = await admit(repository, offer, decisionObservation.admission, assertions);
105
106
  if (admission.kind === "accepted") {
107
+ confirmPrivateStatePublication(input.seat);
106
108
  return {
107
109
  kind: "accepted",
108
110
  facts: offerEntries(offer),
@@ -118,9 +120,14 @@ export async function admitDecidedOffer(input) {
118
120
  const recovered = await observeContractsForAdmissionAt(repository, channel, offer.facts.map((append) => append.contractId));
119
121
  const classification = classifyUnknownAttempt({ contracts: recovered.journals }, offer);
120
122
  if (classification.kind === "accepted")
121
- return recoveredAcceptance({ contracts: recovered.journals }, offer, primaryContract);
123
+ return confirmRecoveredAcceptance(input.seat, { contracts: recovered.journals }, offer, primaryContract);
122
124
  return classification.kind === "collision" ? { kind: "collision" } : { kind: "redecide" };
123
125
  }
126
+ function confirmRecoveredAcceptance(seat, observation, offer, primaryContract) {
127
+ const recovered = recoveredAcceptance(observation, offer, primaryContract);
128
+ confirmPrivateStatePublication(seat);
129
+ return recovered;
130
+ }
124
131
  /** Classify an unknown atomic-publication outcome using only a captured Git observation. */
125
132
  export function classifyUnknownAttempt(observation, offer) {
126
133
  let exact = 0;
@@ -135,6 +135,9 @@ export async function completeCandidate(input) {
135
135
  if (placement.kind !== "target-moved" || input.target === undefined) {
136
136
  return { admission, evidence: mergeEvidence(evidence, { placement: requiredPlacementStop(placement) }) };
137
137
  }
138
+ if (placement.observedTreeEqualsCandidate) {
139
+ return { admission, evidence: mergeEvidence(evidence, { placement: requiredPlacementStop(placement) }) };
140
+ }
138
141
  let integratedAt;
139
142
  for (let attempts = 1; attempts <= MAX_REINTEGRATION_CYCLES; attempts += 1) {
140
143
  const reintegrated = await reintegrateOperation({
@@ -161,6 +164,9 @@ export async function completeCandidate(input) {
161
164
  if (placement.kind !== "target-moved") {
162
165
  return { admission, evidence: mergeEvidence(evidence, { placement: requiredPlacementStop(placement) }) };
163
166
  }
167
+ if (placement.observedTreeEqualsCandidate) {
168
+ return { admission, evidence: mergeEvidence(evidence, { placement: requiredPlacementStop(placement) }) };
169
+ }
164
170
  if (attempts === MAX_REINTEGRATION_CYCLES) {
165
171
  return {
166
172
  admission,
@@ -172,6 +178,7 @@ export async function completeCandidate(input) {
172
178
  integratedAt: integratedAt,
173
179
  observed: placement.observed,
174
180
  attempts,
181
+ observedTreeEqualsCandidate: placement.observedTreeEqualsCandidate,
175
182
  },
176
183
  }),
177
184
  };
@@ -2,6 +2,7 @@ import { materializeIntegrationSnapshot, materializeJudgedConflict, planIntegrat
2
2
  import { captureTender, dirtyTenderRefusal, materializeTenderSnapshot, prepareDeliveryCommitMetadata, } from "../git/tender.js";
3
3
  import { worktreePath } from "../git/workspace.js";
4
4
  import { observeContractsForAdmissionAt } from "../git/observe.js";
5
+ import { withPrivateStatePublicationSeat } from "../git/private-state-seat.js";
5
6
  import { contractState } from "../core/facts/observation.js";
6
7
  import { decideDeliver } from "../core/verbs/deliver.js";
7
8
  import { admitDecidedOffer, mintAttempts } from "./attempt.js";
@@ -11,7 +12,7 @@ import { appointmentFor, readPlaceRegister } from "../workspace-place.js";
11
12
  import { timestamp } from "./operations.js";
12
13
  const DELIVER_CONFLICT_RECOVERY = Object.freeze({
13
14
  materialize: "deliver --materialize-conflict",
14
- continue: "deliver",
15
+ continue: "deliver --include-dirty",
15
16
  });
16
17
  export async function prepareDelivery(repository, stage, input) {
17
18
  const { contractId, coordinates } = stage;
@@ -25,7 +26,6 @@ export async function prepareDelivery(repository, stage, input) {
25
26
  coordinates,
26
27
  ...(appointed === undefined ? {} : { place: appointed.place }),
27
28
  captureMergeState: true,
28
- rejectUnmerged: true,
29
29
  });
30
30
  if (tender.kind === "refused")
31
31
  return tender;
@@ -64,6 +64,9 @@ export async function prepareDelivery(repository, stage, input) {
64
64
  };
65
65
  }
66
66
  async function deliverAttempt(input, attempt) {
67
+ return await withPrivateStatePublicationSeat(input.scope, async (seat) => await deliverAttemptInPrivateStateSeat(input, attempt, seat));
68
+ }
69
+ async function deliverAttemptInPrivateStateSeat(input, attempt, seat) {
67
70
  const decisionObservation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
68
71
  const state = contractState(decisionObservation.decision, input.contractId);
69
72
  const derivation = state === null ? undefined : input.deriveDocument(state);
@@ -117,6 +120,7 @@ async function deliverAttempt(input, attempt) {
117
120
  const admission = await admitDecidedOffer({
118
121
  channel: input.channel,
119
122
  repository: input.scope,
123
+ seat,
120
124
  decisionObservation,
121
125
  attempt,
122
126
  offer: decision.offer,
@@ -41,7 +41,7 @@ export type DeliverConflictRefusal = Readonly<{
41
41
  conflictPaths: readonly string[];
42
42
  recovery: Readonly<{
43
43
  materialize: "deliver --materialize-conflict";
44
- continue: "deliver";
44
+ continue: "deliver --include-dirty";
45
45
  }>;
46
46
  }>;
47
47
  export type DeliveryPreparationRefusal = Readonly<{
@@ -82,6 +82,7 @@ export type PlacementStop = StepStop<PlacementRefusal | TargetPlacementRefusal |
82
82
  target: string;
83
83
  expected: SnapshotId;
84
84
  observed: SnapshotId | null;
85
+ observedTreeEqualsCandidate: boolean;
85
86
  }> | Readonly<{
86
87
  failure: "target-moved";
87
88
  contractId: ContractId;
@@ -89,6 +90,7 @@ export type PlacementStop = StepStop<PlacementRefusal | TargetPlacementRefusal |
89
90
  integratedAt: SnapshotId;
90
91
  observed: SnapshotId | null;
91
92
  attempts: number;
93
+ observedTreeEqualsCandidate: boolean;
92
94
  }> | Readonly<{
93
95
  failure: "target-placement-failed";
94
96
  diagnostic: string;
@@ -117,6 +119,7 @@ export declare function unpackVerificationOutcome(verification: VerificationResu
117
119
  }>;
118
120
  export declare function placementStop(result: PlacementProtocolResult<IntegrationPreparationRefusal>): PlacementStop | undefined;
119
121
  export type RepositoryScope = GitRepository;
122
+ export declare function withScopeAbortSignal(scope: RepositoryScope, signal: AbortSignal | undefined): RepositoryScope;
120
123
  export declare function scopeOperation(input: Readonly<{
121
124
  coordinate: string;
122
125
  gitPath?: string;
@@ -39,11 +39,14 @@ export function placementStop(result) {
39
39
  if (result.kind === "placement-failed")
40
40
  return { failure: "target-placement-failed", diagnostic: result.diagnostic };
41
41
  if (result.kind === "target-moved") {
42
- const { contractId, target, expected, observed } = result;
43
- return { failure: "target-moved", contractId, target, expected, observed };
42
+ const { contractId, target, expected, observed, observedTreeEqualsCandidate } = result;
43
+ return { failure: "target-moved", contractId, target, expected, observed, observedTreeEqualsCandidate };
44
44
  }
45
45
  return result.kind === "refused" ? { refusal: result.refusal } : { retry: result };
46
46
  }
47
+ export function withScopeAbortSignal(scope, signal) {
48
+ return signal === undefined ? scope : { ...scope, signal };
49
+ }
47
50
  export async function scopeOperation(input) {
48
51
  return await repositoryAt(input.coordinate, input.gitPath);
49
52
  }
@@ -16,6 +16,7 @@ export type TargetMovedStop = Readonly<{
16
16
  target: string;
17
17
  expected: SnapshotId;
18
18
  observed: SnapshotId | null;
19
+ observedTreeEqualsCandidate: boolean;
19
20
  }>;
20
21
  export type PlacementProtocolResult<ExtraRefusal = never> = (AcceptedAdmission & Readonly<{
21
22
  physical?: ReconcileResult;
@@ -3,9 +3,10 @@ import { AuthorityCorruptionError } from "../core/facts/errors.js";
3
3
  import { contractState } from "../core/facts/observation.js";
4
4
  import { decidePlacement } from "../core/verbs/placement.js";
5
5
  import { observeGitForAdmissionAt } from "../git/observe.js";
6
+ import { withPrivateStatePublicationSeat } from "../git/private-state-seat.js";
6
7
  import { reconcileEffectFailure } from "../git/reconcile.js";
7
8
  import { GitPlumbingError } from "../git/process.js";
8
- import { acquireTargetPlacementFence, followTargetPlacement, prepareTargetPlacement, observeTargetHead, } from "../git/target-placement.js";
9
+ import { acquireTargetPlacementFence, followTargetPlacement, prepareTargetPlacement, observeTargetHead, observedTreeEqualsCandidate, } from "../git/target-placement.js";
9
10
  import { admitDecidedOffer, mintAttempts } from "./attempt.js";
10
11
  import { prepareProtocolAttempt, runProtocol } from "./run.js";
11
12
  function placementFailure(error) {
@@ -21,45 +22,58 @@ function expectedPlacementFailure(error) {
21
22
  return { kind: "placement-failed", diagnostic: expectedOperationalDiagnostic(error) };
22
23
  }
23
24
  async function runFencedPlacement(repository, input, protocol) {
24
- for (let index = 0; index < protocol.attempts.length; index += 1) {
25
- const prepared = await prepareProtocolAttempt(protocol, protocol.attempts[index]);
26
- if (prepared.kind === "refused")
27
- return prepared;
28
- const state = contractState(prepared.observation.decision, input.contractId);
29
- if (state === null)
30
- throw new Error("placement offer has no contract state");
31
- if (prepared.offer.target === undefined)
32
- throw new Error("targeted placement offer is missing its target movement");
33
- const observed = await observeTargetHead(repository, prepared.offer.target.target);
34
- if (observed !== prepared.offer.target.expectedOid) {
35
- return {
36
- kind: "target-moved",
37
- contractId: input.contractId,
38
- target: prepared.offer.target.target,
39
- expected: prepared.offer.target.expectedOid,
40
- observed,
41
- };
42
- }
43
- const physical = await prepareTargetPlacement(repository, state, prepared.offer.target);
44
- if (physical.kind === "refused")
45
- return physical;
46
- const result = await admitDecidedOffer({
47
- channel: protocol.channel,
48
- repository,
49
- decisionObservation: prepared.observation,
50
- attempt: prepared.attempt,
51
- offer: prepared.offer,
52
- primaryContract: input.contractId,
53
- });
54
- if (result.kind === "accepted") {
55
- return { ...result, physical: await followTargetPlacement(repository, physical.placement) };
25
+ let preparedPhysical;
26
+ const result = await withPrivateStatePublicationSeat(repository, async (seat) => {
27
+ for (let index = 0; index < protocol.attempts.length; index += 1) {
28
+ const prepared = await prepareProtocolAttempt(protocol, protocol.attempts[index]);
29
+ if (prepared.kind === "refused")
30
+ return prepared;
31
+ const state = contractState(prepared.observation.decision, input.contractId);
32
+ if (state === null)
33
+ throw new Error("placement offer has no contract state");
34
+ if (prepared.offer.target === undefined)
35
+ throw new Error("targeted placement offer is missing its target movement");
36
+ const observed = await observeTargetHead(repository, prepared.offer.target.target);
37
+ if (observed !== prepared.offer.target.expectedOid) {
38
+ const treeEquals = await observedTreeEqualsCandidate(repository, observed, prepared.offer.target.newOid);
39
+ return {
40
+ kind: "target-moved",
41
+ contractId: input.contractId,
42
+ target: prepared.offer.target.target,
43
+ expected: prepared.offer.target.expectedOid,
44
+ observed,
45
+ observedTreeEqualsCandidate: treeEquals,
46
+ };
47
+ }
48
+ const physical = await prepareTargetPlacement(repository, state, prepared.offer.target);
49
+ if (physical.kind === "refused")
50
+ return physical;
51
+ const result = await admitDecidedOffer({
52
+ channel: protocol.channel,
53
+ repository,
54
+ seat,
55
+ decisionObservation: prepared.observation,
56
+ attempt: prepared.attempt,
57
+ offer: prepared.offer,
58
+ primaryContract: input.contractId,
59
+ });
60
+ if (result.kind === "accepted") {
61
+ preparedPhysical = physical.placement;
62
+ return result;
63
+ }
64
+ if (result.kind === "publication-failed")
65
+ return result;
66
+ if (result.kind === "collision" && index + 1 === protocol.attempts.length)
67
+ return result;
56
68
  }
57
- if (result.kind === "publication-failed")
58
- return result;
59
- if (result.kind === "collision" && index + 1 === protocol.attempts.length)
60
- return result;
69
+ return { kind: "exhausted" };
70
+ });
71
+ if (result.kind !== "accepted")
72
+ return result;
73
+ if (preparedPhysical === undefined) {
74
+ throw new Error("accepted placement has no prepared target checkout");
61
75
  }
62
- return { kind: "exhausted" };
76
+ return { ...result, physical: await followTargetPlacement(repository, preparedPhysical) };
63
77
  }
64
78
  /** Hold the existing target-placement fence for one owner callback. */
65
79
  export async function runUnderTargetPlacementFence(repository, target, run, onReleaseFailure) {
@@ -1,11 +1,8 @@
1
1
  import type { GitRepository } from "../../git/process.js";
2
2
  import type { ContractRow } from "./status.js";
3
3
  export type CurrentPhysicalIssue = Readonly<{
4
- kind: "hook-failure";
5
- diagnostic: string;
6
- }> | Readonly<{
7
4
  kind: "target-checkout-retained";
8
5
  target: string;
9
6
  }>;
10
- /** Selected-only pure projection of durable hook failure or retained target checkout. */
7
+ /** Selected-only pure projection of retained target checkout state. */
11
8
  export declare function observeCurrentPhysicalIssue(repository: GitRepository, row: ContractRow): Promise<CurrentPhysicalIssue | undefined>;
@@ -1,20 +1,7 @@
1
- import { observeWorktreeHookMarker } from "../../git/hooks.js";
2
- import { registeredWorktrees, worktreeGitDirectory } from "../../git/repository.js";
1
+ import { registeredWorktrees } from "../../git/repository.js";
3
2
  import { observeTargetCheckoutShape } from "../../git/target-placement.js";
4
- function appointedWorkspacePath(row) {
5
- const observation = row.workspaceObservation;
6
- if (observation.kind !== "clean" && observation.kind !== "dirty")
7
- return null;
8
- return observation.location.kind === "worktree" ? observation.location.path : null;
9
- }
10
- /** Selected-only pure projection of durable hook failure or retained target checkout. */
3
+ /** Selected-only pure projection of retained target checkout state. */
11
4
  export async function observeCurrentPhysicalIssue(repository, row) {
12
- const workspacePath = appointedWorkspacePath(row);
13
- if (workspacePath !== null) {
14
- const marker = await observeWorktreeHookMarker(await worktreeGitDirectory(repository, workspacePath));
15
- if (marker.kind === "failed")
16
- return { kind: "hook-failure", diagnostic: marker.diagnostic };
17
- }
18
5
  const target = row.target;
19
6
  const delivery = row.delivery;
20
7
  if (row.phase !== "claimed" || target === null || delivery === null)
@@ -2,72 +2,76 @@ import { contractState } from "../core/facts/observation.js";
2
2
  import { decideReintegrate } from "../core/verbs/reintegrate.js";
3
3
  import { materializeReintegrationSnapshot, persistedTender, planIntegration, } from "../git/integration.js";
4
4
  import { observeContractsForAdmissionAt } from "../git/observe.js";
5
+ import { withPrivateStatePublicationSeat } from "../git/private-state-seat.js";
5
6
  import { admitDecidedOffer, mintAttempts } from "./attempt.js";
6
7
  import { timestamp } from "./operations.js";
7
8
  import { runUnderTargetPlacementFence } from "./placement.js";
8
9
  async function runReintegration(input) {
9
- const attempts = mintAttempts({ entryCount: 1 });
10
- for (let index = 0; index < attempts.length; index += 1) {
11
- const attempt = attempts[index];
12
- const observation = await observeContractsForAdmissionAt(input.repository, input.channel, [input.contractId]);
13
- const state = contractState(observation.decision, input.contractId);
14
- let preparation;
15
- let assertions = [];
16
- if (state === null || state.delivery === null || state.currentIntegration === null) {
17
- preparation = {
18
- kind: "refused",
19
- refusal: {
20
- kind: state === null ? "contract-missing" : "delivery-missing",
21
- contractId: input.contractId,
22
- },
23
- };
24
- }
25
- else {
26
- const planned = await planIntegration(input.repository, { contractId: input.contractId, coordinates: state.coordinates }, await persistedTender(input.repository, state.delivery.data.tenderSnapshot), state.delivery.data.policy.requireBranchesToBeUpToDate);
27
- if (planned.kind === "refused") {
28
- preparation = planned;
29
- }
30
- else {
31
- const snapshot = await materializeReintegrationSnapshot(input.repository, planned.data.tree, planned.data.predecessor, state.delivery.data.integration.snapshot);
10
+ return await withPrivateStatePublicationSeat(input.repository, async (seat) => {
11
+ const attempts = mintAttempts({ entryCount: 1 });
12
+ for (let index = 0; index < attempts.length; index += 1) {
13
+ const attempt = attempts[index];
14
+ const observation = await observeContractsForAdmissionAt(input.repository, input.channel, [input.contractId]);
15
+ const state = contractState(observation.decision, input.contractId);
16
+ let preparation;
17
+ let assertions = [];
18
+ if (state === null || state.delivery === null || state.currentIntegration === null) {
32
19
  preparation = {
33
- kind: "prepared",
34
- data: { predecessor: planned.data.predecessor, snapshot },
20
+ kind: "refused",
21
+ refusal: {
22
+ kind: state === null ? "contract-missing" : "delivery-missing",
23
+ contractId: input.contractId,
24
+ },
35
25
  };
36
- assertions = [{ ref: input.target, oid: planned.data.predecessor }];
37
26
  }
27
+ else {
28
+ const planned = await planIntegration(input.repository, { contractId: input.contractId, coordinates: state.coordinates }, await persistedTender(input.repository, state.delivery.data.tenderSnapshot), state.delivery.data.policy.requireBranchesToBeUpToDate);
29
+ if (planned.kind === "refused") {
30
+ preparation = planned;
31
+ }
32
+ else {
33
+ const snapshot = await materializeReintegrationSnapshot(input.repository, planned.data.tree, planned.data.predecessor, state.delivery.data.integration.snapshot);
34
+ preparation = {
35
+ kind: "prepared",
36
+ data: { predecessor: planned.data.predecessor, snapshot },
37
+ };
38
+ assertions = [{ ref: input.target, oid: planned.data.predecessor }];
39
+ }
40
+ }
41
+ const decision = decideReintegrate({
42
+ input: {
43
+ contractId: input.contractId,
44
+ ...(input.actor === undefined ? {} : { actor: input.actor }),
45
+ at: timestamp(),
46
+ preparation,
47
+ },
48
+ attempt,
49
+ observation: observation.decision,
50
+ });
51
+ if (decision.kind === "refused")
52
+ return { kind: "refused", refusal: decision.refusal };
53
+ const result = await admitDecidedOffer({
54
+ channel: input.channel,
55
+ repository: input.repository,
56
+ seat,
57
+ decisionObservation: observation,
58
+ attempt,
59
+ offer: decision.offer,
60
+ primaryContract: input.contractId,
61
+ assertions,
62
+ });
63
+ if (result.kind === "accepted") {
64
+ if (preparation.kind !== "prepared")
65
+ throw new Error("accepted reintegration has no preparation");
66
+ return { ...result, value: preparation.data };
67
+ }
68
+ if (result.kind === "publication-failed")
69
+ return { kind: "retry", reason: result };
70
+ if (result.kind === "collision" && index + 1 === attempts.length)
71
+ return { kind: "retry", reason: result };
38
72
  }
39
- const decision = decideReintegrate({
40
- input: {
41
- contractId: input.contractId,
42
- ...(input.actor === undefined ? {} : { actor: input.actor }),
43
- at: timestamp(),
44
- preparation,
45
- },
46
- attempt,
47
- observation: observation.decision,
48
- });
49
- if (decision.kind === "refused")
50
- return { kind: "refused", refusal: decision.refusal };
51
- const result = await admitDecidedOffer({
52
- channel: input.channel,
53
- repository: input.repository,
54
- decisionObservation: observation,
55
- attempt,
56
- offer: decision.offer,
57
- primaryContract: input.contractId,
58
- assertions,
59
- });
60
- if (result.kind === "accepted") {
61
- if (preparation.kind !== "prepared")
62
- throw new Error("accepted reintegration has no preparation");
63
- return { ...result, value: preparation.data };
64
- }
65
- if (result.kind === "publication-failed")
66
- return { kind: "retry", reason: result };
67
- if (result.kind === "collision" && index + 1 === attempts.length)
68
- return { kind: "retry", reason: result };
69
- }
70
- return { kind: "retry", reason: { kind: "exhausted" } };
73
+ return { kind: "retry", reason: { kind: "exhausted" } };
74
+ });
71
75
  }
72
76
  export async function reintegrateOperation(input) {
73
77
  return await runUnderTargetPlacementFence(input.repository, input.target, async () => await runReintegration(input));
@@ -1,6 +1,7 @@
1
1
  import { worktreeChangeId } from "../git/integration.js";
2
2
  import { captureTender, dirtyTenderDelta, dirtyTenderRefusal, } from "../git/tender.js";
3
3
  import { observeContractsForAdmissionAt } from "../git/observe.js";
4
+ import { withPrivateStatePublicationSeat } from "../git/private-state-seat.js";
4
5
  import { dependencyKeySet } from "../core/subject.js";
5
6
  import { contractState } from "../core/facts/observation.js";
6
7
  import { gate } from "../core/facts/types.js";
@@ -53,6 +54,9 @@ function reviewValue(value, completion = {}) {
53
54
  };
54
55
  }
55
56
  async function reviewAttempt(input, attempt) {
57
+ return await withPrivateStatePublicationSeat(input.scope, async (seat) => await reviewAttemptInPrivateStateSeat(input, attempt, seat));
58
+ }
59
+ async function reviewAttemptInPrivateStateSeat(input, attempt, seat) {
56
60
  const decisionObservation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
57
61
  const state = contractState(decisionObservation.decision, input.contractId);
58
62
  let preparation;
@@ -98,6 +102,7 @@ async function reviewAttempt(input, attempt) {
98
102
  const admission = await admitDecidedOffer({
99
103
  channel: input.channel,
100
104
  repository: input.scope,
105
+ seat,
101
106
  decisionObservation,
102
107
  attempt,
103
108
  offer: decision.offer,