@astrosheep/keiyaku 4.0.4 → 4.0.6

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 (233) hide show
  1. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
  2. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
  3. package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
  4. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +4 -4
  5. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +15 -7
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +5 -3
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +24 -4
  8. package/build/src/akuma/akuma.d.ts +2 -1
  9. package/build/src/akuma/akuma.js +27 -9
  10. package/build/src/akuma/allowed.d.ts +1 -1
  11. package/build/src/akuma/allowed.js +3 -10
  12. package/build/src/akuma/archetype.d.ts +3 -1
  13. package/build/src/akuma/archetype.js +11 -6
  14. package/build/src/akuma/body-turn.d.ts +64 -0
  15. package/build/src/akuma/body-turn.js +449 -0
  16. package/build/src/akuma/body.d.ts +4 -5
  17. package/build/src/akuma/body.js +9 -414
  18. package/build/src/akuma/heart/facts.d.ts +37 -9
  19. package/build/src/akuma/heart/facts.js +3 -1
  20. package/build/src/akuma/heart/index.d.ts +4 -13
  21. package/build/src/akuma/heart/index.js +14 -135
  22. package/build/src/akuma/heart/request-authority.d.ts +12 -0
  23. package/build/src/akuma/heart/request-authority.js +119 -0
  24. package/build/src/akuma/heart/request-rows.d.ts +16 -0
  25. package/build/src/akuma/heart/request-rows.js +88 -0
  26. package/build/src/akuma/heart/rows.d.ts +1 -28
  27. package/build/src/akuma/heart/rows.js +4 -138
  28. package/build/src/akuma/heart/schema.d.ts +1 -1
  29. package/build/src/akuma/heart/schema.js +11 -3
  30. package/build/src/akuma/heart/soul.js +0 -36
  31. package/build/src/akuma/heart/timeline.d.ts +1 -0
  32. package/build/src/akuma/heart/timeline.js +19 -0
  33. package/build/src/akuma/index.d.ts +1 -1
  34. package/build/src/akuma/nuke.d.ts +2 -0
  35. package/build/src/akuma/nuke.js +152 -0
  36. package/build/src/akuma/provider-recipe.js +1 -11
  37. package/build/src/akuma/provider.d.ts +4 -7
  38. package/build/src/akuma/providers/acp/config.d.ts +8 -0
  39. package/build/src/akuma/providers/acp/config.js +37 -0
  40. package/build/src/akuma/providers/acp/core.js +12 -2
  41. package/build/src/akuma/providers/acp/index.d.ts +1 -8
  42. package/build/src/akuma/providers/acp/index.js +2 -38
  43. package/build/src/akuma/providers/claude/index.d.ts +0 -4
  44. package/build/src/akuma/providers/claude/index.js +12 -3
  45. package/build/src/akuma/providers/codex-app-server/index.d.ts +2 -27
  46. package/build/src/akuma/providers/codex-app-server/index.js +5 -2
  47. package/build/src/akuma/providers/grok-build/index.js +1 -2
  48. package/build/src/akuma/providers/index.d.ts +3 -2
  49. package/build/src/akuma/providers/index.js +36 -36
  50. package/build/src/akuma/providers/opencode-sdk/index.d.ts +2 -28
  51. package/build/src/akuma/providers/opencode-sdk/index.js +14 -4
  52. package/build/src/akuma/providers/opencode-sdk/session.d.ts +2 -2
  53. package/build/src/akuma/providers/opencode-sdk/session.js +2 -2
  54. package/build/src/akuma/providers/pi/index.d.ts +1 -1
  55. package/build/src/akuma/providers/pi/index.js +29 -6
  56. package/build/src/akuma/request-serve.d.ts +88 -0
  57. package/build/src/akuma/request-serve.js +484 -0
  58. package/build/src/akuma/request-wire.d.ts +125 -0
  59. package/build/src/akuma/request-wire.js +383 -0
  60. package/build/src/akuma/requests.d.ts +28 -94
  61. package/build/src/akuma/requests.js +52 -562
  62. package/build/src/akuma-body.d.ts +7 -0
  63. package/build/src/akuma-body.js +69 -2
  64. package/build/src/alias/index.d.ts +1 -0
  65. package/build/src/alias/index.js +34 -1
  66. package/build/src/body/arc.js +4 -29
  67. package/build/src/body/decode.js +5 -39
  68. package/build/src/body/envelope.d.ts +7 -0
  69. package/build/src/body/envelope.js +37 -0
  70. package/build/src/cli/accepted.js +21 -9
  71. package/build/src/cli/commands/akuma-invoke.js +1 -0
  72. package/build/src/cli/commands/akuma.d.ts +1 -0
  73. package/build/src/cli/commands/akuma.js +13 -10
  74. package/build/src/cli/commands/contract.d.ts +28 -17
  75. package/build/src/cli/commands/contract.js +23 -17
  76. package/build/src/cli/commands/install.d.ts +2 -2
  77. package/build/src/cli/commands/install.js +6 -6
  78. package/build/src/cli/commands/nuke.d.ts +10 -0
  79. package/build/src/cli/commands/nuke.js +20 -0
  80. package/build/src/cli/commands/task-invoke.d.ts +15 -0
  81. package/build/src/cli/commands/task-invoke.js +144 -24
  82. package/build/src/cli/commands/task-query.d.ts +2 -2
  83. package/build/src/cli/commands/task-query.js +1 -2
  84. package/build/src/cli/commands/task.js +22 -22
  85. package/build/src/cli/coordinates.d.ts +6 -2
  86. package/build/src/cli/coordinates.js +12 -56
  87. package/build/src/cli/invoke.d.ts +5 -4
  88. package/build/src/cli/invoke.js +112 -58
  89. package/build/src/cli/main.d.ts +0 -2
  90. package/build/src/cli/main.js +4 -140
  91. package/build/src/cli/parse.d.ts +17 -4
  92. package/build/src/cli/parse.js +93 -15
  93. package/build/src/cli/render/akuma.js +111 -53
  94. package/build/src/cli/render/audit.js +2 -6
  95. package/build/src/cli/render/contract.js +61 -20
  96. package/build/src/cli/render/kanshi.js +15 -5
  97. package/build/src/cli/render/nuke.d.ts +3 -0
  98. package/build/src/cli/render/nuke.js +8 -0
  99. package/build/src/cli/render/receipt.js +28 -1
  100. package/build/src/cli/render/refusal.d.ts +2 -1
  101. package/build/src/cli/render/refusal.js +31 -0
  102. package/build/src/cli/render/terminal.d.ts +0 -2
  103. package/build/src/cli/render/terminal.js +0 -29
  104. package/build/src/cli/render/text.js +6 -1
  105. package/build/src/cli/result.d.ts +36 -9
  106. package/build/src/cli/runtime.d.ts +2 -0
  107. package/build/src/cli/runtime.js +140 -0
  108. package/build/src/cli/usage.d.ts +0 -2
  109. package/build/src/cli/usage.js +0 -4
  110. package/build/src/contract-worktree.d.ts +29 -14
  111. package/build/src/contract-worktree.js +131 -70
  112. package/build/src/core/facts/codec.js +9 -0
  113. package/build/src/core/facts/fold.js +13 -1
  114. package/build/src/core/facts/types.d.ts +8 -1
  115. package/build/src/core/subject.js +4 -3
  116. package/build/src/core/verbs/placement.d.ts +9 -1
  117. package/build/src/core/verbs/placement.js +24 -6
  118. package/build/src/core/verbs/reintegrate.d.ts +13 -0
  119. package/build/src/core/verbs/reintegrate.js +24 -0
  120. package/build/src/dispatch/index.d.ts +1 -1
  121. package/build/src/git/admission.d.ts +2 -1
  122. package/build/src/git/hooks.d.ts +2 -0
  123. package/build/src/git/hooks.js +34 -1
  124. package/build/src/git/integration.d.ts +9 -2
  125. package/build/src/git/integration.js +92 -1
  126. package/build/src/git/nuke.d.ts +2 -0
  127. package/build/src/git/nuke.js +97 -0
  128. package/build/src/git/observe.d.ts +2 -1
  129. package/build/src/git/observe.js +6 -5
  130. package/build/src/git/process.d.ts +28 -0
  131. package/build/src/git/process.js +94 -0
  132. package/build/src/git/read-observation.d.ts +2 -1
  133. package/build/src/git/read-observation.js +3 -2
  134. package/build/src/git/reconcile.d.ts +4 -1
  135. package/build/src/git/reconcile.js +42 -8
  136. package/build/src/git/repository.d.ts +2 -29
  137. package/build/src/git/repository.js +7 -118
  138. package/build/src/git/scratch.d.ts +1 -1
  139. package/build/src/git/scratch.js +1 -1
  140. package/build/src/git/target-placement.d.ts +3 -2
  141. package/build/src/git/target-placement.js +15 -14
  142. package/build/src/git/tender.d.ts +2 -1
  143. package/build/src/git/tender.js +4 -3
  144. package/build/src/git/terminal-seal.d.ts +2 -2
  145. package/build/src/git/terminal-seal.js +3 -6
  146. package/build/src/git/workspace.d.ts +4 -1
  147. package/build/src/git/workspace.js +1 -1
  148. package/build/src/index.d.ts +1 -2
  149. package/build/src/index.js +1 -1
  150. package/build/src/kanshi/read.js +5 -1
  151. package/build/src/library/address.js +7 -1
  152. package/build/src/library/akuma-creation.d.ts +1 -0
  153. package/build/src/library/akuma-creation.js +8 -1
  154. package/build/src/library/audit.d.ts +3 -1
  155. package/build/src/library/audit.js +2 -1
  156. package/build/src/library/bind.d.ts +2 -1
  157. package/build/src/library/bind.js +1 -1
  158. package/build/src/library/configuration.d.ts +1 -1
  159. package/build/src/library/configuration.js +52 -18
  160. package/build/src/library/contract.d.ts +59 -4
  161. package/build/src/library/contract.js +195 -34
  162. package/build/src/library/delivery.d.ts +4 -2
  163. package/build/src/library/fleet.d.ts +27 -7
  164. package/build/src/library/fleet.js +79 -39
  165. package/build/src/library/input.d.ts +0 -1
  166. package/build/src/library/input.js +0 -5
  167. package/build/src/library/keiyaku.d.ts +6 -2
  168. package/build/src/library/keiyaku.js +2 -0
  169. package/build/src/library/mutation.d.ts +3 -1
  170. package/build/src/library/mutation.js +3 -0
  171. package/build/src/library/nuke.d.ts +14 -0
  172. package/build/src/library/nuke.js +54 -0
  173. package/build/src/library/reconcile.d.ts +2 -1
  174. package/build/src/library/reconcile.js +8 -3
  175. package/build/src/library/refusal.d.ts +10 -1
  176. package/build/src/library/region.d.ts +1 -1
  177. package/build/src/library/repo.d.ts +4 -1
  178. package/build/src/library/repo.js +10 -4
  179. package/build/src/protocol/abandon.d.ts +9 -0
  180. package/build/src/protocol/abandon.js +15 -0
  181. package/build/src/protocol/amend.d.ts +16 -0
  182. package/build/src/protocol/amend.js +77 -0
  183. package/build/src/protocol/arc.d.ts +6 -0
  184. package/build/src/protocol/arc.js +12 -0
  185. package/build/src/protocol/attempt.d.ts +2 -1
  186. package/build/src/protocol/audit.d.ts +53 -0
  187. package/build/src/protocol/audit.js +147 -0
  188. package/build/src/protocol/bind.d.ts +1 -1
  189. package/build/src/protocol/completion.d.ts +42 -0
  190. package/build/src/protocol/completion.js +183 -0
  191. package/build/src/protocol/deliver.d.ts +49 -0
  192. package/build/src/protocol/deliver.js +261 -0
  193. package/build/src/protocol/intent.d.ts +2 -1
  194. package/build/src/protocol/intent.js +8 -2
  195. package/build/src/protocol/operations.d.ts +93 -202
  196. package/build/src/protocol/operations.js +23 -642
  197. package/build/src/protocol/placement.d.ts +12 -13
  198. package/build/src/protocol/placement.js +8 -19
  199. package/build/src/protocol/read/status.d.ts +17 -5
  200. package/build/src/protocol/read/status.js +57 -13
  201. package/build/src/protocol/reconcile.d.ts +35 -0
  202. package/build/src/protocol/reconcile.js +41 -0
  203. package/build/src/protocol/reintegrate.d.ts +31 -0
  204. package/build/src/protocol/reintegrate.js +74 -0
  205. package/build/src/protocol/review.d.ts +34 -0
  206. package/build/src/protocol/review.js +156 -0
  207. package/build/src/protocol/run.d.ts +1 -1
  208. package/build/src/runtime/proc/run.js +9 -5
  209. package/build/src/settlement/fence.d.ts +3 -1
  210. package/build/src/settlement/fence.js +24 -0
  211. package/build/src/settlement/holder.d.ts +1 -1
  212. package/build/src/settlement/settle.d.ts +1 -1
  213. package/build/src/settlement/settle.js +1 -2
  214. package/build/src/task/board.d.ts +0 -1
  215. package/build/src/task/board.js +0 -3
  216. package/build/src/task/compose.d.ts +2 -2
  217. package/build/src/task/compose.js +13 -11
  218. package/build/src/task/context.d.ts +14 -2
  219. package/build/src/task/context.js +30 -7
  220. package/build/src/task/index.d.ts +7 -6
  221. package/build/src/task/index.js +17 -145
  222. package/build/src/task/input.d.ts +18 -0
  223. package/build/src/task/input.js +189 -0
  224. package/build/src/task/mutation.d.ts +44 -0
  225. package/build/src/task/mutation.js +93 -0
  226. package/build/src/task/operations.d.ts +14 -6
  227. package/build/src/task/operations.js +57 -57
  228. package/build/src/task/store.d.ts +1 -0
  229. package/build/src/task/store.js +91 -3
  230. package/build/src/verification/execution.d.ts +1 -1
  231. package/build/src/workspace-place.d.ts +3 -4
  232. package/build/src/workspace-place.js +26 -15
  233. package/package.json +3 -3
@@ -9,12 +9,23 @@ import { scopeForRepo } from "./repo.js";
9
9
  function source(path) {
10
10
  return Akuma.of(path);
11
11
  }
12
- async function contractFor(repo, id) {
13
- const dispatch = repo === undefined ? null : await readDispatch(scopeForRepo(repo), id);
14
- return dispatch?.contractId;
12
+ function observationDiagnostic(error) {
13
+ return error instanceof Error ? error.message : String(error);
14
+ }
15
+ const NO_DISPATCH = { kind: "none" };
16
+ async function dispatchAssociation(repo, id) {
17
+ if (repo === undefined)
18
+ return NO_DISPATCH;
19
+ try {
20
+ const dispatch = await readDispatch(scopeForRepo(repo), id);
21
+ return dispatch === null ? NO_DISPATCH : { kind: "associated", contractId: dispatch.contractId };
22
+ }
23
+ catch (error) {
24
+ return { kind: "failed", diagnostic: observationDiagnostic(error) };
25
+ }
15
26
  }
16
27
  function createdTaskDiagnostic(error) {
17
- return error instanceof Error ? error.message : String(error);
28
+ return observationDiagnostic(error);
18
29
  }
19
30
  async function createdTasksFor(path, statuses) {
20
31
  let board;
@@ -30,16 +41,23 @@ async function createdTasksFor(path, statuses) {
30
41
  async function observeAkuma(status, path, repo) {
31
42
  return (await observeAkumaSet([status], path, repo))[0];
32
43
  }
44
+ async function observeAkumaStage(path, id, repo) {
45
+ try {
46
+ return { kind: "observed", ...await observeAkuma(await source(path).of({ id }).status(), path, repo) };
47
+ }
48
+ catch (error) {
49
+ if (error instanceof AkumaNotBornError)
50
+ throw error;
51
+ return { kind: "unobserved", diagnostic: observationDiagnostic(error) };
52
+ }
53
+ }
33
54
  async function observeAkumaSet(statuses, path, repo) {
34
55
  const created = await createdTasksFor(path, statuses);
35
- return await Promise.all(statuses.map(async (status, index) => {
36
- const contractId = await contractFor(repo, status.id);
37
- return {
38
- status,
39
- createdTasks: created[index],
40
- ...(contractId === undefined ? {} : { contractId }),
41
- };
42
- }));
56
+ return await Promise.all(statuses.map(async (status, index) => ({
57
+ status,
58
+ contract: await dispatchAssociation(repo, status.id),
59
+ createdTasks: created[index],
60
+ })));
43
61
  }
44
62
  function timeout(value) {
45
63
  if (value === undefined)
@@ -69,31 +87,45 @@ function delay(milliseconds, signal) {
69
87
  });
70
88
  }
71
89
  const SHARED_ORDINARY_BUDGET = 30;
72
- async function observeWaitStatuses(path, ids, signal) {
90
+ async function observeWaitRound(path, ids, signal) {
73
91
  signal?.throwIfAborted();
74
92
  if (ids.length <= 1) {
75
- return await Promise.all(ids.map(async (id) => await source(path).of({ id }).status()));
93
+ return {
94
+ statuses: await Promise.all(ids.map(async (id) => await source(path).of({ id }).status())),
95
+ unobserved: [],
96
+ };
76
97
  }
77
98
  let remaining = SHARED_ORDINARY_BUDGET;
78
99
  const statuses = [];
100
+ const unobserved = [];
79
101
  for (const id of ids) {
80
102
  signal?.throwIfAborted();
81
- const observed = await readBudgetedStatus(path, id, { ordinaryBudget: remaining });
82
- statuses.push(observed.status);
83
- remaining -= observed.ordinarySelected;
103
+ try {
104
+ const observed = await readBudgetedStatus(path, id, { ordinaryBudget: remaining });
105
+ statuses.push(observed.status);
106
+ remaining -= observed.ordinarySelected;
107
+ }
108
+ catch (error) {
109
+ if (error instanceof AkumaNotBornError)
110
+ throw error;
111
+ unobserved.push({ id, diagnostic: observationDiagnostic(error) });
112
+ }
84
113
  }
85
- return statuses;
114
+ return { statuses, unobserved };
86
115
  }
87
116
  export async function executeWaitAkuma(input) {
88
117
  const deadline = input.timeoutMs === undefined ? undefined : performance.now() + input.timeoutMs;
89
118
  for (;;) {
90
- const statuses = await observeWaitStatuses(input.path, input.ids, input.signal);
91
- const settled = statuses.map((status) => status.life !== "running");
92
- if ((input.completion === "any" ? settled.some(Boolean) : settled.every(Boolean))
119
+ const round = await observeWaitRound(input.path, input.ids, input.signal);
120
+ const settled = round.statuses.map((status) => status.life !== "running");
121
+ const completed = round.statuses.length > 0
122
+ && (input.completion === "any" ? settled.some(Boolean) : settled.every(Boolean));
123
+ if (completed
93
124
  || (deadline !== undefined && performance.now() >= deadline)) {
94
125
  return {
95
126
  completion: input.completion,
96
- observations: await observeAkumaSet(statuses, input.path, input.repo),
127
+ observations: await observeAkumaSet(round.statuses, input.path, input.repo),
128
+ unobserved: round.unobserved,
97
129
  };
98
130
  }
99
131
  await delay(deadline === undefined ? 25 : Math.min(25, Math.max(0, deadline - performance.now())), input.signal);
@@ -109,7 +141,7 @@ export async function executeTellAkuma(input) {
109
141
  return {
110
142
  akuma: input.id,
111
143
  tell,
112
- observation: await observeAkuma(await handle.status(), input.path, input.repo),
144
+ observation: await observeAkumaStage(input.path, input.id, input.repo),
113
145
  };
114
146
  }
115
147
  export async function executeKillAkuma(input) {
@@ -117,10 +149,12 @@ export async function executeKillAkuma(input) {
117
149
  const handles = input.ids.map((id) => source(input.path).of({ id }));
118
150
  const evidence = await Promise.all(handles.map(async (handle) => await handle.kill()));
119
151
  input.signal?.throwIfAborted();
120
- const statuses = await Promise.all(input.ids.map(async (id) => await source(input.path).of({ id }).status()));
121
- const observations = await observeAkumaSet(statuses, input.path, input.repo);
122
152
  return {
123
- results: input.ids.map((id, index) => ({ id, evidence: evidence[index], observation: observations[index] })),
153
+ results: await Promise.all(input.ids.map(async (id, index) => ({
154
+ id,
155
+ evidence: evidence[index],
156
+ observation: await observeAkumaStage(input.path, id, input.repo),
157
+ }))),
124
158
  };
125
159
  }
126
160
  function upstreamResult(outcome) {
@@ -130,22 +164,29 @@ function upstreamResult(outcome) {
130
164
  throw new AkumaNotBornError(outcome.failure.id);
131
165
  throw new Error(outcome.failure.diagnostic);
132
166
  }
133
- async function attachContract(repo, observation) {
134
- if (repo === undefined || observation.contractId !== undefined)
167
+ function needsDispatchAttach(association) {
168
+ return association.kind === "none";
169
+ }
170
+ async function attachObservationContract(repo, observation) {
171
+ if (repo === undefined || !needsDispatchAttach(observation.contract))
172
+ return observation;
173
+ return { ...observation, contract: await dispatchAssociation(repo, observation.status.id) };
174
+ }
175
+ async function attachObservationStage(repo, observation) {
176
+ if (repo === undefined || observation.kind !== "observed")
135
177
  return observation;
136
- const contractId = await contractFor(repo, observation.status.id);
137
- return contractId === undefined ? observation : { ...observation, contractId };
178
+ return { ...observation, ...(await attachObservationContract(repo, observation)) };
138
179
  }
139
180
  async function attachWaitContracts(repo, result) {
140
181
  return repo === undefined
141
182
  ? result
142
183
  : {
143
184
  ...result,
144
- observations: await Promise.all(result.observations.map((observation) => attachContract(repo, observation))),
185
+ observations: await Promise.all(result.observations.map((observation) => attachObservationContract(repo, observation))),
145
186
  };
146
187
  }
147
188
  async function attachTellContract(repo, result) {
148
- return repo === undefined ? result : { ...result, observation: await attachContract(repo, result.observation) };
189
+ return repo === undefined ? result : { ...result, observation: await attachObservationStage(repo, result.observation) };
149
190
  }
150
191
  async function attachKillContracts(repo, result) {
151
192
  return repo === undefined
@@ -154,7 +195,7 @@ async function attachKillContracts(repo, result) {
154
195
  ...result,
155
196
  results: await Promise.all(result.results.map(async (entry) => ({
156
197
  ...entry,
157
- observation: await attachContract(repo, entry.observation),
198
+ observation: await attachObservationStage(repo, entry.observation),
158
199
  }))),
159
200
  };
160
201
  }
@@ -262,7 +303,7 @@ export async function interruptAkuma(input) {
262
303
  const addressed = await addressAkuma(directAddress(values));
263
304
  const handle = source(addressed.path).of({ id: addressed.id });
264
305
  const receipt = await handle.interrupt(values.body);
265
- const observation = await observeAkuma(await handle.status(), addressed.path, values.repo);
306
+ const observation = await observeAkumaStage(addressed.path, addressed.id, values.repo);
266
307
  return { id: addressed.id, receipt, observation };
267
308
  }
268
309
  export async function historyAkuma(input) {
@@ -276,18 +317,17 @@ export async function historyAkuma(input) {
276
317
  throw new TypeError("last must be a boolean");
277
318
  const addressed = await addressAkuma(directAddress(values));
278
319
  const handle = source(addressed.path).of({ id: addressed.id });
320
+ const contract = await dispatchAssociation(values.repo, addressed.id);
279
321
  if (values.last === true) {
280
322
  const answer = await handle.lastAnswer();
281
- const contractId = await contractFor(values.repo, addressed.id);
282
323
  return answer.kind === "answer"
283
- ? { kind: "last", id: addressed.id, answer: answer.answer, ...(contractId === undefined ? {} : { contractId }) }
284
- : { kind: "no-answer", id: addressed.id, ...(contractId === undefined ? {} : { contractId }) };
324
+ ? { kind: "last", id: addressed.id, answer: answer.answer, contract }
325
+ : { kind: "no-answer", id: addressed.id, contract };
285
326
  }
286
327
  const history = await handle.history({
287
328
  ...(values.before === undefined ? {} : { before: values.before }),
288
329
  ...(values.since === undefined ? {} : { since: values.since }),
289
330
  ...(values.limit === undefined ? {} : { limit: values.limit }),
290
331
  });
291
- const contractId = await contractFor(values.repo, addressed.id);
292
- return { kind: "history", id: addressed.id, history, ...(contractId === undefined ? {} : { contractId }) };
332
+ return { kind: "history", id: addressed.id, history, contract };
293
333
  }
@@ -6,7 +6,6 @@ export declare function actorOption(actor: unknown): Readonly<{
6
6
  }>;
7
7
  export declare function requireMarkdown(value: unknown, label?: string): string;
8
8
  export declare function requireInput(value: unknown, label: string): Record<string, unknown>;
9
- export declare function rejectUnknownFields(values: Record<string, unknown>, allowed: readonly string[], label: string): void;
10
9
  export declare function optionalNonblank(value: unknown, label: string): string | undefined;
11
10
  export declare function optionalBoolean(value: unknown, label: string): boolean | undefined;
12
11
  export declare function optionalSignal(value: unknown): AbortSignal | undefined;
@@ -22,11 +22,6 @@ export function requireInput(value, label) {
22
22
  throw new TypeError(`${label} must be an object`);
23
23
  return value;
24
24
  }
25
- export function rejectUnknownFields(values, allowed, label) {
26
- for (const key of Object.keys(values))
27
- if (!allowed.includes(key))
28
- throw new TypeError(`${label} has unknown field: ${key}`);
29
- }
30
25
  export function optionalNonblank(value, label) {
31
26
  if (value === undefined)
32
27
  return undefined;
@@ -2,12 +2,13 @@ import { KeiyakuHandle, bindKeiyaku, keiyakuOf, listKeiyaku, observeKeiyaku, typ
2
2
  import { callKeiyaku, forkKeiyaku } from "./akuma-creation.js";
3
3
  import { historyAkuma, interruptAkuma, killAkuma, statusAkuma, tellAkuma, waitAkuma } from "./fleet.js";
4
4
  import { listCatalog } from "./catalog.js";
5
+ import { nukeKeiyaku } from "./nuke.js";
5
6
  export { AuthorityCorruptionError } from "../core/facts/errors.js";
6
7
  export { Delivery, KeiyakuRefused, KeiyakuRetry, } from "./contract.js";
7
8
  export { NoGitWorldError, Repo } from "./repo.js";
8
9
  export { gatesFrom, requireBranchesToBeUpToDateFrom, SettingsError, worktreeHooksFrom, } from "./configuration.js";
9
10
  export { AkumaWorldScopeError } from "./address.js";
10
- export type { AbandonInput, ActorId, AmendInput, AmendResult, ArcInput, AttestationVerdict, AuditInput, AuditReport, DeliveryPreparationRefusal, BindInput, BindResult, ContractBoard, ContractDisposition, ContractGateCurrent, ContractGateReport, ContractHistory, ContractHistoryEvent, ContractListInput, ContractObservation, ContractObservationInput, ContractPhase, ContractRow, DeliverInput, Fact, FactKind, KeiyakuOfInput, KeiyakuRefusal, KeiyakuRetryReason, Lag, MutationResult, PlacementStop, ReconcileReport, Review, ReviewInput, TaskId, TopologyEffect, VerificationReuse, VerificationStop, } from "./contract.js";
11
+ export type { AbandonInput, ActorId, AmendInput, AmendResult, ArcInput, AttestationVerdict, AuditInput, AuditReport, DeliveryPreparationRefusal, BindInput, BindResult, ContractBoard, ContractDisposition, ContractGateCurrent, ContractGateReport, ContractHistory, ContractHistoryEvent, ContractListInput, ContractObservation, ContractObservationInput, ContractPhase, ContractRow, DeliverInput, Fact, IntegrationConflictMaterialized, FactKind, KeiyakuOfInput, KeiyakuRefusal, KeiyakuRetryReason, Lag, MutationResult, PlacementStop, ReconcileReport, Review, ReviewInput, TaskId, TopologyEffect, VerificationReuse, VerificationStop, } from "./contract.js";
11
12
  export type { ContractId, ContractState, ChangeId, SnapshotId, } from "../core/facts/types.js";
12
13
  export type { Gate, GatesFromInput, HookCommand, RequireBranchesToBeUpToDateFromInput, WorktreeHooks, } from "./configuration.js";
13
14
  export type { RegionOverlap } from "./region.js";
@@ -21,8 +22,10 @@ export type { AkumaGlob } from "../identity/selector.js";
21
22
  export type { AkuId } from "../akuma/identity.js";
22
23
  export type { AllowedAction, AllowedActions } from "../akuma/allowed.js";
23
24
  export type { Catalog, CatalogInput, CatalogQuery } from "./catalog.js";
25
+ export type { NukeInput, NukeResult, } from "./nuke.js";
26
+ export type { NukeConfirmationRefusal, NukeConfirmationRequiredRefusal } from "./refusal.js";
24
27
  export type { AkumaAddressInput, AkumaSetAddressInput, AkumaWorldScopeRefusal, DirectAkumaSelector, SetAkumaSelector, } from "./address.js";
25
- export type { AkumaHistoryInput, AkumaHistoryResult, AkumaInterruptInput, AkumaInterruptResult, AkumaKillResult, AkumaObservation, AkumaTellInput, CreatedTaskObservation, AkumaTellResult, AkumaWaitInput, AkumaWaitResult, } from "./fleet.js";
28
+ export type { AkumaHistoryInput, AkumaHistoryResult, AkumaInterruptInput, AkumaInterruptResult, AkumaKillResult, AkumaObservation, AkumaObservationStage, AkumaTellInput, AkumaUnobserved, CreatedTaskObservation, DispatchAssociation, AkumaTellResult, AkumaWaitInput, AkumaWaitResult, } from "./fleet.js";
26
29
  export type Keiyaku = KeiyakuType;
27
30
  export declare const Keiyaku: Readonly<{
28
31
  prototype: KeiyakuHandle;
@@ -34,6 +37,7 @@ export declare const Keiyaku: Readonly<{
34
37
  interrupt: typeof interruptAkuma;
35
38
  kill: typeof killAkuma;
36
39
  ls: typeof listCatalog;
40
+ nuke: typeof nukeKeiyaku;
37
41
  list: typeof listKeiyaku;
38
42
  observe: typeof observeKeiyaku;
39
43
  of: typeof keiyakuOf;
@@ -2,6 +2,7 @@ import { KeiyakuHandle, bindKeiyaku, keiyakuOf, listKeiyaku, observeKeiyaku, } f
2
2
  import { callKeiyaku, forkKeiyaku } from "./akuma-creation.js";
3
3
  import { historyAkuma, interruptAkuma, killAkuma, statusAkuma, tellAkuma, waitAkuma, } from "./fleet.js";
4
4
  import { listCatalog } from "./catalog.js";
5
+ import { nukeKeiyaku } from "./nuke.js";
5
6
  export { AuthorityCorruptionError } from "../core/facts/errors.js";
6
7
  export { Delivery, KeiyakuRefused, KeiyakuRetry, } from "./contract.js";
7
8
  export { NoGitWorldError, Repo } from "./repo.js";
@@ -17,6 +18,7 @@ export const Keiyaku = Object.freeze({
17
18
  interrupt: interruptAkuma,
18
19
  kill: killAkuma,
19
20
  ls: listCatalog,
21
+ nuke: nukeKeiyaku,
20
22
  list: listKeiyaku,
21
23
  observe: observeKeiyaku,
22
24
  of: keiyakuOf,
@@ -1,6 +1,7 @@
1
1
  import type { ContractHead, ContractId, JournalEntry } from "../core/facts/types.js";
2
2
  import type { GitDecodeChannel } from "../git/read-observation.js";
3
- import type { ReconcileReport, RepositoryScope } from "../protocol/operations.js";
3
+ import type { ReconcileReport } from "../protocol/reconcile.js";
4
+ import type { RepositoryScope } from "../protocol/operations.js";
4
5
  import type { IntentOutcome } from "../protocol/operations.js";
5
6
  import type { AcceptedObligations } from "../protocol/outcome.js";
6
7
  import { type SettlementReport } from "../settlement/settle.js";
@@ -30,6 +31,7 @@ type Completion<Value, PublicValue> = Readonly<{
30
31
  value: (result: Value) => PublicValue;
31
32
  hooks: WorktreeHooks;
32
33
  }>;
34
+ export declare function completionInput<Value, PublicValue>(scope: RepositoryScope, channel: GitDecodeChannel, contractId: ContractId, value: (result: Value) => PublicValue, hooks: WorktreeHooks): Omit<Completion<Value, PublicValue>, "accepted">;
33
35
  export declare function completeMutation<Value, PublicValue>(input: Completion<Value, PublicValue>): Promise<MutationResult<PublicValue>>;
34
36
  export declare function completeHolderMutation<Value, PublicValue, Refusal>(input: Readonly<{
35
37
  completion: Omit<Completion<Value, PublicValue>, "accepted">;
@@ -1,5 +1,8 @@
1
1
  import { deferredTaskHolderSettlement } from "../settlement/settle.js";
2
2
  import { completeReconcile } from "./reconcile.js";
3
+ export function completionInput(scope, channel, contractId, value, hooks) {
4
+ return { scope, channel, contractId, value, hooks };
5
+ }
3
6
  export async function completeMutation(input) {
4
7
  const { scope, channel, contractId, accepted, value, hooks } = input;
5
8
  const report = await completeReconcile({ scope, channel, contractId, hooks, retryHooks: false });
@@ -0,0 +1,14 @@
1
+ import type { WorldRoot } from "../world.js";
2
+ export type NukeInput = Readonly<{
3
+ world: WorldRoot;
4
+ confirm?: string;
5
+ }>;
6
+ export type NukeResult = Readonly<{
7
+ kind: "success";
8
+ world: WorldRoot;
9
+ }> | Readonly<{
10
+ kind: "failed";
11
+ world: WorldRoot;
12
+ diagnostic: string;
13
+ }>;
14
+ export declare function nukeKeiyaku(input: NukeInput): Promise<NukeResult>;
@@ -0,0 +1,54 @@
1
+ import { stopAkuma } from "../akuma/nuke.js";
2
+ import { nukeGit } from "../git/nuke.js";
3
+ import { nukeTask } from "../task/operations.js";
4
+ import { KeiyakuRefused } from "./refusal.js";
5
+ import { requireInput, requireMarkdown } from "./input.js";
6
+ function diagnostic(error) {
7
+ return error instanceof Error ? error.message : String(error);
8
+ }
9
+ function nukeInput(input) {
10
+ const value = requireInput(input, "nuke input");
11
+ const world = requireMarkdown(value.world, "world");
12
+ const confirm = value.confirm === undefined ? undefined : requireMarkdown(value.confirm, "confirm");
13
+ return { world, ...(confirm === undefined ? {} : { confirm }) };
14
+ }
15
+ export async function nukeKeiyaku(input) {
16
+ const value = nukeInput(input);
17
+ if (value.confirm === undefined) {
18
+ throw new KeiyakuRefused({ kind: "nuke-confirmation-required", world: value.world });
19
+ }
20
+ if (value.confirm !== value.world) {
21
+ throw new KeiyakuRefused({
22
+ kind: "nuke-confirmation-mismatch",
23
+ world: value.world,
24
+ confirmation: value.confirm,
25
+ });
26
+ }
27
+ try {
28
+ const deleteAkuma = await stopAkuma(value.world);
29
+ let failed = false;
30
+ let firstDiagnostic;
31
+ const attempt = async (owner) => {
32
+ try {
33
+ await owner;
34
+ }
35
+ catch (error) {
36
+ if (!failed) {
37
+ failed = true;
38
+ firstDiagnostic = error;
39
+ }
40
+ }
41
+ };
42
+ await Promise.all([
43
+ attempt(deleteAkuma()),
44
+ attempt(nukeGit(value.world)),
45
+ attempt(nukeTask(value.world)),
46
+ ]);
47
+ if (failed)
48
+ throw firstDiagnostic;
49
+ return { kind: "success", world: value.world };
50
+ }
51
+ catch (error) {
52
+ return { kind: "failed", world: value.world, diagnostic: diagnostic(error) };
53
+ }
54
+ }
@@ -1,6 +1,7 @@
1
1
  import type { ContractId } from "../core/facts/types.js";
2
2
  import type { GitDecodeChannel } from "../git/read-observation.js";
3
- import { type ReconcileReport, type RepositoryScope } from "../protocol/operations.js";
3
+ import { type ReconcileReport } from "../protocol/reconcile.js";
4
+ import { type RepositoryScope } from "../protocol/operations.js";
4
5
  import { type SettlementReport } from "../settlement/settle.js";
5
6
  import type { WorktreeHooks } from "./configuration.js";
6
7
  import { type ContractFileEffect, type ContractFileLag } from "../contract-worktree.js";
@@ -1,5 +1,7 @@
1
1
  import { AuthorityCorruptionError } from "../core/facts/errors.js";
2
- import { reconcileAllOperation, reconcileObservationFailure, reconcileOperation, stateOperation, worldContractStates, } from "../protocol/operations.js";
2
+ import { reconcileAllOperation, reconcileOperation, worldContractStates, } from "../protocol/reconcile.js";
3
+ import { reconcileObservationFailure } from "../git/reconcile.js";
4
+ import { stateOperation } from "../protocol/operations.js";
3
5
  import { settle, settleAll } from "../settlement/settle.js";
4
6
  import { projectContractWorktree, } from "../contract-worktree.js";
5
7
  import { appointManagedWorktrees, placeRegisterPath, releaseManagedWorktrees, } from "../workspace-place.js";
@@ -11,6 +13,9 @@ function registerLag(scope, error) {
11
13
  diagnostic: error instanceof Error ? error.message : String(error),
12
14
  };
13
15
  }
16
+ function hereConflict(diagnostic) {
17
+ throw new AuthorityCorruptionError(diagnostic);
18
+ }
14
19
  function emptySettlement() {
15
20
  return { actions: [], lags: [] };
16
21
  }
@@ -89,7 +94,7 @@ export async function completeReconcile(input) {
89
94
  retainTerminalWorktree: true,
90
95
  ...appointed,
91
96
  });
92
- const projection = await projectContractWorktree(input.scope, retained.state, appointment.register);
97
+ const projection = await projectContractWorktree(input.scope, retained.state, appointment.register, hereConflict);
93
98
  const settlement = await settle({
94
99
  repository: input.scope,
95
100
  channel: input.channel,
@@ -164,7 +169,7 @@ export async function completeRepoReconcile(input) {
164
169
  if (releaseEligible(contract.state, report, places.has(contract.contractId))) {
165
170
  released.push(contract.contractId);
166
171
  }
167
- const projection = await projectContractWorktree(input.scope, contract.state, appointed);
172
+ const projection = await projectContractWorktree(input.scope, contract.state, appointed, hereConflict);
168
173
  contracts.push({
169
174
  contractId: contract.contractId,
170
175
  report: {
@@ -6,7 +6,16 @@ export type ContractAppointmentRefusal = Readonly<{
6
6
  path: string;
7
7
  contract?: ContractId;
8
8
  }>;
9
- export type KeiyakuRefusal = IntentRefusal | ContractAppointmentRefusal;
9
+ export type NukeConfirmationRefusal = Readonly<{
10
+ kind: "nuke-confirmation-mismatch";
11
+ world: string;
12
+ confirmation: string;
13
+ }>;
14
+ export type NukeConfirmationRequiredRefusal = Readonly<{
15
+ kind: "nuke-confirmation-required";
16
+ world: string;
17
+ }>;
18
+ export type KeiyakuRefusal = IntentRefusal | ContractAppointmentRefusal | NukeConfirmationRefusal | NukeConfirmationRequiredRefusal;
10
19
  export type KeiyakuRetryReason = IntentRetry;
11
20
  export declare class KeiyakuRefused extends Error {
12
21
  readonly refusal: KeiyakuRefusal;
@@ -1,7 +1,7 @@
1
1
  import type { ContractId } from "../core/facts/types.js";
2
2
  import type { GitDecodeChannel } from "../git/read-observation.js";
3
3
  import { type RepositoryScope } from "../protocol/operations.js";
4
- import type { ContractDocumentProjection } from "../protocol/operations.js";
4
+ import type { ContractDocumentProjection } from "../protocol/read/documents.js";
5
5
  export type RegionOverlap = Readonly<{
6
6
  contract: ContractId;
7
7
  patterns: readonly Readonly<{
@@ -1,10 +1,12 @@
1
- import { NoGitWorldError, type RepositoryScope } from "../protocol/operations.js";
1
+ import { type RepositoryScope } from "../protocol/operations.js";
2
+ import { NoGitWorldError } from "../git/repository.js";
2
3
  import { type WorktreeHooks } from "./configuration.js";
3
4
  import { type RepoContractReconcileReport, type RepoReconcileReport } from "./reconcile.js";
4
5
  export { NoGitWorldError };
5
6
  export type { RepoContractReconcileReport, RepoReconcileReport };
6
7
  export type RepoAtInput = Readonly<{
7
8
  path?: string;
9
+ gitPath?: string;
8
10
  }>;
9
11
  export type ReconcileInput = Readonly<{
10
12
  hooks?: WorktreeHooks;
@@ -16,6 +18,7 @@ export declare function reconcileInput(input: ReconcileInput | undefined): Reado
16
18
  }>;
17
19
  export declare class Repo {
18
20
  readonly root: string;
21
+ readonly cwd: string;
19
22
  private constructor();
20
23
  static at(input?: RepoAtInput): Promise<Repo>;
21
24
  currentBranch(): Promise<string | null>;
@@ -1,12 +1,16 @@
1
- import { currentBranchOperation, NoGitWorldError, scopeOperation, } from "../protocol/operations.js";
1
+ import { currentBranchOperation, scopeOperation, } from "../protocol/operations.js";
2
+ import { NoGitWorldError } from "../git/repository.js";
2
3
  import { optionalNonblank, requireInput } from "./input.js";
3
4
  import { worktreeHooksOption } from "./configuration.js";
4
5
  import { withGitDecodeChannel } from "../git/read-observation.js";
5
6
  import { completeRepoReconcile, } from "./reconcile.js";
6
7
  export { NoGitWorldError };
7
8
  const REPO_SCOPES = new WeakMap();
8
- async function resolvePinnedScope(path) {
9
- return await scopeOperation({ coordinate: path === undefined ? process.cwd() : path });
9
+ async function resolvePinnedScope(path, gitPath) {
10
+ return await scopeOperation({
11
+ coordinate: path === undefined ? process.cwd() : path,
12
+ ...(gitPath === undefined ? {} : { gitPath }),
13
+ });
10
14
  }
11
15
  export function reconcileInput(input) {
12
16
  const values = input === undefined ? undefined : requireInput(input, "reconcile input");
@@ -20,13 +24,15 @@ export function reconcileInput(input) {
20
24
  }
21
25
  export class Repo {
22
26
  root;
27
+ cwd;
23
28
  constructor(scope) {
24
29
  this.root = scope.primaryWorktree;
30
+ this.cwd = scope.invocationWorktree;
25
31
  REPO_SCOPES.set(this, scope);
26
32
  }
27
33
  static async at(input) {
28
34
  const values = input === undefined ? undefined : requireInput(input, "Repo.at input");
29
- return new Repo(await resolvePinnedScope(optionalNonblank(values?.path, "repository path")));
35
+ return new Repo(await resolvePinnedScope(optionalNonblank(values?.path, "repository path"), optionalNonblank(values?.gitPath, "Git executable path")));
30
36
  }
31
37
  async currentBranch() {
32
38
  return await currentBranchOperation({ scope: scopeForRepo(this) });
@@ -0,0 +1,9 @@
1
+ import { type AbandonRefusal } from "../core/verbs/abandon.js";
2
+ import type { GitTreeSelection } from "../git/read-observation.js";
3
+ import type { CompanionDecorator } from "./run.js";
4
+ import type { IntentOutcome, MutationOperationInput } from "./operations.js";
5
+ export declare function abandonOperation(input: MutationOperationInput & Readonly<{
6
+ note?: string;
7
+ decorateOffer?: CompanionDecorator;
8
+ observationSelection?: GitTreeSelection;
9
+ }>): Promise<IntentOutcome<void, AbandonRefusal>>;
@@ -0,0 +1,15 @@
1
+ import { decideAbandon } from "../core/verbs/abandon.js";
2
+ import { admitIntent } from "./intent.js";
3
+ import { complete } from "./outcome.js";
4
+ import { timestamp } from "./operations.js";
5
+ export async function abandonOperation(input) {
6
+ return complete(await admitIntent(input.channel, input.scope, {
7
+ contractId: input.contractId,
8
+ ...(input.actor === undefined ? {} : { actor: input.actor }),
9
+ at: timestamp(),
10
+ ...(input.note === undefined ? {} : { note: input.note }),
11
+ }, decideAbandon, {
12
+ ...(input.decorateOffer === undefined ? {} : { decorateOffer: input.decorateOffer }),
13
+ ...(input.observationSelection === undefined ? {} : { observationSelection: input.observationSelection }),
14
+ }), undefined);
15
+ }
@@ -0,0 +1,16 @@
1
+ import type { AmendData, ContractTerms } from "../core/facts/types.js";
2
+ import { type AmendRefusal } from "../core/verbs/amend.js";
3
+ import type { VerificationDeclarationPreparation, VerificationDeclarationRefusal } from "../verification/declaration.js";
4
+ import type { MutationOperationInput, IntentOutcome } from "./operations.js";
5
+ type AmendOperationInput = MutationOperationInput & Readonly<{
6
+ source?: ContractTerms;
7
+ deriveAmendment?: (source: ContractTerms) => Readonly<{
8
+ terms: AmendData;
9
+ verification: VerificationDeclarationPreparation;
10
+ }>;
11
+ }>;
12
+ type Amendment = Readonly<{
13
+ source: ContractTerms;
14
+ }> & ReturnType<NonNullable<AmendOperationInput["deriveAmendment"]>>;
15
+ export declare function amendOperation(input: AmendOperationInput): Promise<IntentOutcome<Amendment, AmendRefusal | VerificationDeclarationRefusal>>;
16
+ export {};
@@ -0,0 +1,77 @@
1
+ import { extendContractsForAdmissionAt, observeContractsForAdmissionAt } from "../git/observe.js";
2
+ import { contractState } from "../core/facts/observation.js";
3
+ import { decideAmend } from "../core/verbs/amend.js";
4
+ import { admitDecidedOffer, mintAttempts } from "./attempt.js";
5
+ import { admitted } from "./outcome.js";
6
+ import { timestamp } from "./operations.js";
7
+ async function extendPrerequisiteClosureAt(channel, observation, seeds) {
8
+ let current = observation;
9
+ const visited = new Set();
10
+ let pending = [...seeds];
11
+ while (pending.length > 0) {
12
+ const batch = [...new Set(pending.filter((id) => !visited.has(id)))];
13
+ pending = [];
14
+ if (batch.length === 0)
15
+ break;
16
+ current = await extendContractsForAdmissionAt(channel, current, batch);
17
+ for (const id of batch) {
18
+ visited.add(id);
19
+ const state = contractState(current.decision, id);
20
+ if (state !== null)
21
+ pending.push(...state.terms.after);
22
+ }
23
+ }
24
+ return current;
25
+ }
26
+ export async function amendOperation(input) {
27
+ const attempts = mintAttempts({ entryCount: 1 });
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, [...new Set([...(state?.terms.after ?? []), ...amendment.terms.after])]);
39
+ }
40
+ const preparation = amendment === undefined
41
+ ? undefined
42
+ : amendment.verification.kind === "prepared"
43
+ ? { kind: "prepared", data: amendment.terms }
44
+ : { kind: "refused", refusal: amendment.verification.refusal };
45
+ const decision = decideAmend({
46
+ input: {
47
+ contractId: input.contractId,
48
+ ...(input.actor === undefined ? {} : { actor: input.actor }),
49
+ at: timestamp(),
50
+ ...(amendment === undefined ? {} : { source: amendment.source }),
51
+ ...(preparation === undefined ? {} : { preparation }),
52
+ },
53
+ attempt: attempts[index],
54
+ observation: observation.decision,
55
+ });
56
+ if (decision.kind === "refused")
57
+ return decision;
58
+ const admission = await admitDecidedOffer({
59
+ channel: input.channel,
60
+ repository: input.scope,
61
+ decisionObservation: observation,
62
+ attempt: attempts[index],
63
+ offer: decision.offer,
64
+ primaryContract: input.contractId,
65
+ });
66
+ if (admission.kind === "accepted") {
67
+ if (amendment === undefined)
68
+ throw new Error("accepted amendment is missing its document derivation");
69
+ return admitted(admission, amendment);
70
+ }
71
+ if (admission.kind === "publication-failed")
72
+ return { kind: "retry", reason: admission };
73
+ if (admission.kind === "collision" && index + 1 === attempts.length)
74
+ return { kind: "retry", reason: admission };
75
+ }
76
+ return { kind: "retry", reason: { kind: "exhausted" } };
77
+ }