@astrosheep/keiyaku 4.0.3 → 4.0.5

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 (238) 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 +1 -1
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +15 -1
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +3 -1
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +34 -13
  9. package/build/src/akuma/akuma.d.ts +34 -12
  10. package/build/src/akuma/akuma.js +118 -63
  11. package/build/src/akuma/allowed.d.ts +7 -0
  12. package/build/src/akuma/allowed.js +33 -0
  13. package/build/src/akuma/archetype.d.ts +7 -4
  14. package/build/src/akuma/archetype.js +15 -16
  15. package/build/src/akuma/body.d.ts +6 -1
  16. package/build/src/akuma/body.js +36 -27
  17. package/build/src/akuma/heart/facts.d.ts +82 -14
  18. package/build/src/akuma/heart/index.d.ts +5 -18
  19. package/build/src/akuma/heart/index.js +14 -84
  20. package/build/src/akuma/heart/request-authority.d.ts +12 -0
  21. package/build/src/akuma/heart/request-authority.js +119 -0
  22. package/build/src/akuma/heart/request-rows.d.ts +16 -0
  23. package/build/src/akuma/heart/request-rows.js +88 -0
  24. package/build/src/akuma/heart/rows.d.ts +1 -26
  25. package/build/src/akuma/heart/rows.js +0 -50
  26. package/build/src/akuma/heart/schema.d.ts +1 -1
  27. package/build/src/akuma/heart/schema.js +22 -10
  28. package/build/src/akuma/heart/soul.js +2 -36
  29. package/build/src/akuma/heart/storage.d.ts +1 -0
  30. package/build/src/akuma/heart/storage.js +15 -0
  31. package/build/src/akuma/heart/timeline.d.ts +1 -5
  32. package/build/src/akuma/heart/timeline.js +8 -17
  33. package/build/src/akuma/index.d.ts +5 -2
  34. package/build/src/akuma/index.js +1 -0
  35. package/build/src/akuma/projection.d.ts +17 -3
  36. package/build/src/akuma/projection.js +40 -3
  37. package/build/src/akuma/provider-recipe.js +1 -11
  38. package/build/src/akuma/provider.d.ts +2 -7
  39. package/build/src/akuma/provider.js +2 -1
  40. package/build/src/akuma/providers/acp/core.d.ts +3 -1
  41. package/build/src/akuma/providers/acp/core.js +10 -6
  42. package/build/src/akuma/providers/acp/events.d.ts +11 -3
  43. package/build/src/akuma/providers/acp/events.js +78 -4
  44. package/build/src/akuma/providers/acp/index.js +0 -1
  45. package/build/src/akuma/providers/claude/events.js +62 -3
  46. package/build/src/akuma/providers/claude/index.d.ts +0 -4
  47. package/build/src/akuma/providers/claude/index.js +7 -3
  48. package/build/src/akuma/providers/codex-app-server/events.js +1 -13
  49. package/build/src/akuma/providers/codex-app-server/index.d.ts +2 -27
  50. package/build/src/akuma/providers/codex-app-server/index.js +0 -2
  51. package/build/src/akuma/providers/grok-build/index.d.ts +2 -1
  52. package/build/src/akuma/providers/grok-build/index.js +72 -3
  53. package/build/src/akuma/providers/opencode-sdk/events.js +71 -6
  54. package/build/src/akuma/providers/opencode-sdk/index.d.ts +2 -28
  55. package/build/src/akuma/providers/opencode-sdk/index.js +8 -4
  56. package/build/src/akuma/providers/opencode-sdk/session.d.ts +1 -1
  57. package/build/src/akuma/providers/opencode-sdk/session.js +1 -1
  58. package/build/src/akuma/providers/pi/events.js +17 -3
  59. package/build/src/akuma/providers/pi/index.js +11 -4
  60. package/build/src/akuma/providers/unified-patch.d.ts +4 -0
  61. package/build/src/akuma/providers/unified-patch.js +14 -0
  62. package/build/src/akuma/publication.d.ts +1 -1
  63. package/build/src/akuma/publication.js +1 -1
  64. package/build/src/akuma/request-serve.d.ts +87 -0
  65. package/build/src/akuma/request-serve.js +484 -0
  66. package/build/src/akuma/request-wire.d.ts +124 -0
  67. package/build/src/akuma/request-wire.js +380 -0
  68. package/build/src/akuma/requests.d.ts +41 -41
  69. package/build/src/akuma/requests.js +75 -374
  70. package/build/src/akuma-body.d.ts +8 -0
  71. package/build/src/akuma-body.js +84 -0
  72. package/build/src/body/arc.js +4 -29
  73. package/build/src/body/decode.js +5 -39
  74. package/build/src/body/envelope.d.ts +7 -0
  75. package/build/src/body/envelope.js +37 -0
  76. package/build/src/cli/accepted.d.ts +4 -1
  77. package/build/src/cli/accepted.js +39 -9
  78. package/build/src/cli/commands/akuma-invoke.d.ts +8 -7
  79. package/build/src/cli/commands/akuma-invoke.js +18 -10
  80. package/build/src/cli/commands/akuma.d.ts +11 -2
  81. package/build/src/cli/commands/akuma.js +67 -28
  82. package/build/src/cli/commands/amend.d.ts +1 -1
  83. package/build/src/cli/commands/amend.js +1 -1
  84. package/build/src/cli/commands/contract.d.ts +8 -8
  85. package/build/src/cli/commands/contract.js +3 -3
  86. package/build/src/cli/commands/install.js +2 -2
  87. package/build/src/cli/commands/task-invoke.js +98 -9
  88. package/build/src/cli/commands/task-query.d.ts +1 -1
  89. package/build/src/cli/commands/task-query.js +11 -5
  90. package/build/src/cli/coordinates.d.ts +2 -0
  91. package/build/src/cli/coordinates.js +12 -5
  92. package/build/src/cli/invoke.d.ts +1 -0
  93. package/build/src/cli/invoke.js +116 -75
  94. package/build/src/cli/main.d.ts +2 -0
  95. package/build/src/cli/main.js +29 -4
  96. package/build/src/cli/parse.d.ts +3 -2
  97. package/build/src/cli/parse.js +25 -8
  98. package/build/src/cli/render/akuma.d.ts +2 -2
  99. package/build/src/cli/render/akuma.js +138 -24
  100. package/build/src/cli/render/audit.js +18 -8
  101. package/build/src/cli/render/contract.d.ts +2 -0
  102. package/build/src/cli/render/contract.js +243 -36
  103. package/build/src/cli/render/kanshi.js +64 -29
  104. package/build/src/cli/render/receipt.d.ts +2 -1
  105. package/build/src/cli/render/receipt.js +37 -2
  106. package/build/src/cli/render/terminal.d.ts +0 -2
  107. package/build/src/cli/render/terminal.js +0 -29
  108. package/build/src/cli/render/text.js +3 -1
  109. package/build/src/cli/result.d.ts +52 -9
  110. package/build/src/cli/selectors.d.ts +1 -0
  111. package/build/src/cli/selectors.js +9 -6
  112. package/build/src/contract-worktree.d.ts +1 -2
  113. package/build/src/contract-worktree.js +7 -9
  114. package/build/src/core/facts/codec.js +9 -0
  115. package/build/src/core/facts/fold.js +13 -1
  116. package/build/src/core/facts/types.d.ts +8 -1
  117. package/build/src/core/subject.js +4 -3
  118. package/build/src/core/verbs/placement.d.ts +9 -1
  119. package/build/src/core/verbs/placement.js +24 -6
  120. package/build/src/core/verbs/reintegrate.d.ts +13 -0
  121. package/build/src/core/verbs/reintegrate.js +24 -0
  122. package/build/src/dispatch/index.d.ts +1 -1
  123. package/build/src/dispatch/index.js +50 -39
  124. package/build/src/git/admission.d.ts +2 -1
  125. package/build/src/git/hooks.d.ts +0 -4
  126. package/build/src/git/hooks.js +0 -36
  127. package/build/src/git/integration.d.ts +7 -8
  128. package/build/src/git/integration.js +62 -9
  129. package/build/src/git/observe.d.ts +2 -1
  130. package/build/src/git/observe.js +6 -5
  131. package/build/src/git/process.d.ts +26 -0
  132. package/build/src/git/process.js +94 -0
  133. package/build/src/git/read-observation.d.ts +2 -1
  134. package/build/src/git/read-observation.js +3 -2
  135. package/build/src/git/reconcile.d.ts +8 -2
  136. package/build/src/git/reconcile.js +63 -14
  137. package/build/src/git/repository.d.ts +2 -29
  138. package/build/src/git/repository.js +4 -118
  139. package/build/src/git/scratch.d.ts +1 -1
  140. package/build/src/git/scratch.js +1 -1
  141. package/build/src/git/target-placement.d.ts +1 -1
  142. package/build/src/git/target-placement.js +9 -7
  143. package/build/src/git/tender.d.ts +20 -5
  144. package/build/src/git/tender.js +45 -13
  145. package/build/src/git/terminal-seal.d.ts +16 -2
  146. package/build/src/git/terminal-seal.js +15 -5
  147. package/build/src/git/workspace.d.ts +2 -1
  148. package/build/src/git/workspace.js +13 -5
  149. package/build/src/index.d.ts +1 -2
  150. package/build/src/index.js +1 -1
  151. package/build/src/kanshi/index.d.ts +1 -1
  152. package/build/src/kanshi/index.js +1 -1
  153. package/build/src/kanshi/read.d.ts +9 -1
  154. package/build/src/kanshi/read.js +91 -37
  155. package/build/src/kanshi/report.d.ts +1 -0
  156. package/build/src/library/address.d.ts +5 -14
  157. package/build/src/library/address.js +27 -23
  158. package/build/src/library/akuma-creation.d.ts +4 -2
  159. package/build/src/library/akuma-creation.js +43 -26
  160. package/build/src/library/audit.d.ts +2 -1
  161. package/build/src/library/audit.js +1 -1
  162. package/build/src/library/bind.d.ts +2 -1
  163. package/build/src/library/bind.js +4 -4
  164. package/build/src/library/catalog.d.ts +1 -2
  165. package/build/src/library/catalog.js +11 -6
  166. package/build/src/library/configuration.d.ts +5 -1
  167. package/build/src/library/configuration.js +71 -18
  168. package/build/src/library/contract.d.ts +70 -3
  169. package/build/src/library/contract.js +213 -27
  170. package/build/src/library/delivery.d.ts +1 -1
  171. package/build/src/library/fleet.d.ts +70 -12
  172. package/build/src/library/fleet.js +236 -56
  173. package/build/src/library/input.d.ts +0 -1
  174. package/build/src/library/input.js +1 -5
  175. package/build/src/library/keiyaku.d.ts +4 -4
  176. package/build/src/library/keiyaku.js +1 -2
  177. package/build/src/library/mutation.d.ts +2 -1
  178. package/build/src/library/reconcile.d.ts +2 -1
  179. package/build/src/library/reconcile.js +3 -1
  180. package/build/src/library/region.d.ts +1 -1
  181. package/build/src/library/repo.d.ts +3 -1
  182. package/build/src/library/repo.js +8 -4
  183. package/build/src/protocol/abandon.d.ts +9 -0
  184. package/build/src/protocol/abandon.js +15 -0
  185. package/build/src/protocol/amend.d.ts +16 -0
  186. package/build/src/protocol/amend.js +77 -0
  187. package/build/src/protocol/arc.d.ts +6 -0
  188. package/build/src/protocol/arc.js +12 -0
  189. package/build/src/protocol/attempt.d.ts +2 -1
  190. package/build/src/protocol/audit.d.ts +53 -0
  191. package/build/src/protocol/audit.js +140 -0
  192. package/build/src/protocol/bind.d.ts +2 -3
  193. package/build/src/protocol/bind.js +2 -16
  194. package/build/src/protocol/completion.d.ts +32 -0
  195. package/build/src/protocol/completion.js +130 -0
  196. package/build/src/protocol/deliver.d.ts +37 -0
  197. package/build/src/protocol/deliver.js +160 -0
  198. package/build/src/protocol/intent.d.ts +1 -1
  199. package/build/src/protocol/intent.js +1 -1
  200. package/build/src/protocol/operations.d.ts +65 -198
  201. package/build/src/protocol/operations.js +21 -634
  202. package/build/src/protocol/placement.d.ts +4 -13
  203. package/build/src/protocol/placement.js +3 -15
  204. package/build/src/protocol/read/status.d.ts +4 -2
  205. package/build/src/protocol/read/status.js +27 -15
  206. package/build/src/protocol/reconcile.d.ts +35 -0
  207. package/build/src/protocol/reconcile.js +41 -0
  208. package/build/src/protocol/reintegrate.d.ts +31 -0
  209. package/build/src/protocol/reintegrate.js +74 -0
  210. package/build/src/protocol/review.d.ts +33 -0
  211. package/build/src/protocol/review.js +148 -0
  212. package/build/src/protocol/run.d.ts +1 -1
  213. package/build/src/runtime/proc/run.d.ts +1 -0
  214. package/build/src/runtime/proc/run.js +9 -2
  215. package/build/src/settlement/fence.d.ts +1 -1
  216. package/build/src/settlement/holder.d.ts +1 -1
  217. package/build/src/settlement/settle.d.ts +2 -1
  218. package/build/src/settlement/settle.js +4 -1
  219. package/build/src/task/board.d.ts +18 -4
  220. package/build/src/task/board.js +73 -29
  221. package/build/src/task/compose.d.ts +1 -1
  222. package/build/src/task/compose.js +11 -4
  223. package/build/src/task/index.d.ts +4 -4
  224. package/build/src/task/index.js +8 -131
  225. package/build/src/task/input.d.ts +18 -0
  226. package/build/src/task/input.js +189 -0
  227. package/build/src/task/mutation.d.ts +39 -0
  228. package/build/src/task/mutation.js +85 -0
  229. package/build/src/task/operations.d.ts +4 -19
  230. package/build/src/task/operations.js +64 -18
  231. package/build/src/task/query.d.ts +9 -2
  232. package/build/src/task/query.js +32 -64
  233. package/build/src/task/store.js +0 -2
  234. package/build/src/verification/execution.d.ts +1 -1
  235. package/build/src/verification/execution.js +2 -1
  236. package/build/src/workspace-place.d.ts +1 -4
  237. package/build/src/workspace-place.js +0 -15
  238. package/package.json +5 -3
@@ -1,6 +1,6 @@
1
1
  import { realpath, stat } from "node:fs/promises";
2
2
  import { moveAlias } from "../alias/index.js";
3
- import { Akuma, } from "../akuma/akuma.js";
3
+ import { Akuma, akumaCallExecution, callAkumaWithContext, } from "../akuma/akuma.js";
4
4
  import { AuthorityCorruptionError } from "../core/facts/errors.js";
5
5
  import { publishDispatch, readDispatch, } from "../dispatch/index.js";
6
6
  import { parseAkumaAlias } from "../identity/selector.js";
@@ -28,6 +28,17 @@ function settingsOption(value) {
28
28
  }
29
29
  return value;
30
30
  }
31
+ function homeOption(value) {
32
+ if (value === undefined)
33
+ return undefined;
34
+ return nonblank(value, "home");
35
+ }
36
+ function akumaWorld(path, home, settings) {
37
+ return Akuma.of(path, {
38
+ ...(home === undefined ? {} : { home }),
39
+ ...(settings === undefined ? {} : { settings }),
40
+ });
41
+ }
31
42
  function onlyKeys(values, allowed, label) {
32
43
  const accepted = new Set(allowed);
33
44
  for (const key of Object.keys(values)) {
@@ -132,31 +143,33 @@ async function resolveCallExecution(input) {
132
143
  source: "input",
133
144
  };
134
145
  }
135
- if (input.contract === undefined)
136
- return { cwd: input.path, source: "world" };
137
- const seat = seatForKeiyaku(input.contract);
138
- const state = await currentManagedContract(input.contract, seat.id);
139
- const appointment = await readManagedWorktreeAppointment(seat.scope, state.id);
140
- if (appointment.kind === "unappointed") {
141
- throw unavailableWorkspace(state.id, "is unappointed; use reconcile");
142
- }
143
- if (appointment.kind === "failed") {
144
- throw new Error(`${appointment.diagnostic}; use reconcile`);
146
+ if (input.contract !== undefined) {
147
+ const seat = seatForKeiyaku(input.contract);
148
+ const state = await currentManagedContract(input.contract, seat.id);
149
+ const appointment = await readManagedWorktreeAppointment(seat.scope, state.id);
150
+ if (appointment.kind === "unappointed") {
151
+ throw unavailableWorkspace(state.id, "is unappointed; use reconcile");
152
+ }
153
+ if (appointment.kind === "failed") {
154
+ throw new Error(`${appointment.diagnostic}; use reconcile`);
155
+ }
156
+ return {
157
+ cwd: await canonicalizeExistingDirectory(appointment.path, `Contract workspace is unavailable: ${appointment.path}`),
158
+ source: "contract-worktree",
159
+ };
145
160
  }
146
- return {
147
- cwd: await canonicalizeExistingDirectory(appointment.path, `Contract workspace is unavailable: ${appointment.path}`),
148
- source: "contract-worktree",
149
- };
161
+ return undefined;
150
162
  }
151
163
  export async function callKeiyaku(input) {
152
164
  const values = requireInput(input, "Keiyaku.call input");
153
- onlyKeys(values, ["path", "archetype", "body", "cwd", "mode", "timeoutMs", "settings", "contract", "alias"], "Keiyaku.call input");
165
+ onlyKeys(values, ["path", "archetype", "body", "cwd", "mode", "timeoutMs", "home", "settings", "contract", "alias", "allowed"], "Keiyaku.call input");
154
166
  const path = nonblank(values.path, "path");
155
167
  const archetype = nonblank(values.archetype, "archetype");
156
168
  const body = text(values.body, "body");
157
169
  const cwd = values.cwd === undefined ? undefined : nonblank(values.cwd, "cwd");
158
170
  const mode = callMode(values.mode);
159
171
  const timeoutMs = callTimeout(values.timeoutMs, mode);
172
+ const home = homeOption(values.home);
160
173
  const settings = settingsOption(values.settings);
161
174
  const alias = values.alias === undefined
162
175
  ? undefined
@@ -167,11 +180,19 @@ export async function callKeiyaku(input) {
167
180
  ...(cwd === undefined ? {} : { cwd }),
168
181
  ...(seat === undefined ? {} : { contract: values.contract }),
169
182
  });
170
- const handle = await Akuma.of(path, settings).call({
183
+ const world = akumaWorld(path, home, settings);
184
+ const call = {
171
185
  archetype,
172
186
  body,
173
- cwd: execution.cwd,
174
- });
187
+ ...(values.allowed === undefined ? {} : { allowed: values.allowed }),
188
+ ...(execution === undefined ? {} : { cwd: execution.cwd }),
189
+ };
190
+ const handle = execution === undefined
191
+ ? await world.call(call)
192
+ : await callAkumaWithContext(world, call, { cwdCanonical: true });
193
+ const completedExecution = execution ?? akumaCallExecution(handle);
194
+ if (completedExecution === undefined)
195
+ throw new Error("Akuma call is missing its birth execution");
175
196
  const readonly = (await handle.status()).readonly;
176
197
  const dispatch = seat === undefined
177
198
  ? { kind: "none" }
@@ -195,7 +216,7 @@ export async function callKeiyaku(input) {
195
216
  kind: "called",
196
217
  akuma: handle.id,
197
218
  ...(readonly === undefined ? {} : { readonly }),
198
- execution,
219
+ execution: completedExecution,
199
220
  dispatch,
200
221
  alias: aliasStage,
201
222
  observation,
@@ -203,19 +224,15 @@ export async function callKeiyaku(input) {
203
224
  }
204
225
  export async function forkKeiyaku(input) {
205
226
  const values = requireInput(input, "Keiyaku.fork input");
206
- onlyKeys(values, ["path", "akuma", "at", "settings", "repo"], "Keiyaku.fork input");
227
+ onlyKeys(values, ["path", "akuma", "at", "repo"], "Keiyaku.fork input");
207
228
  const path = nonblank(values.path, "path");
208
229
  const at = nonblank(values.at, "at");
209
- const settings = settingsOption(values.settings);
210
230
  const akuma = (await addressAkuma({
211
231
  path,
212
232
  akuma: nonblank(values.akuma, "akuma"),
213
- ...(settings === undefined ? {} : { settings }),
214
233
  })).id;
215
234
  const repository = values.repo === undefined ? undefined : scopeForRepo(values.repo);
216
- const receipt = await Akuma.of(path, settings)
217
- .of({ id: akuma })
218
- .fork({ at });
235
+ const receipt = await Akuma.of(path).of({ id: akuma }).fork({ at });
219
236
  if (receipt.kind !== "forked")
220
237
  return { ...receipt, parent: akuma };
221
238
  const dispatch = repository === undefined
@@ -1,5 +1,6 @@
1
1
  import type { ContractId } from "../core/facts/types.js";
2
- import { type AuditReport, type RepositoryScope } from "../protocol/operations.js";
2
+ import { type AuditReport } from "../protocol/audit.js";
3
+ import type { RepositoryScope } from "../protocol/operations.js";
3
4
  import { type WorktreeHooks } from "./configuration.js";
4
5
  import { type MutationResult } from "./mutation.js";
5
6
  export type AuditInput = Readonly<{
@@ -1,6 +1,6 @@
1
1
  import { decodeContractDocument } from "../body/decode.js";
2
2
  import { withGitDecodeChannel } from "../git/read-observation.js";
3
- import { auditOperation, } from "../protocol/operations.js";
3
+ import { auditOperation } from "../protocol/audit.js";
4
4
  import { worktreeHooksOption } from "./configuration.js";
5
5
  import { actorOption, documentDerivation, optionalBoolean, optionalSignal, requireInput, } from "./input.js";
6
6
  import { completeMutation } from "./mutation.js";
@@ -1,6 +1,7 @@
1
1
  import { type ActorId, type ContractId } from "../core/facts/types.js";
2
2
  import type { GitDecodeChannel } from "../git/read-observation.js";
3
- import { bindOperation, type IntentOutcome, type RepositoryScope } from "../protocol/operations.js";
3
+ import { bindOperation } from "../protocol/bind.js";
4
+ import type { IntentOutcome, RepositoryScope } from "../protocol/operations.js";
4
5
  import type { TaskId } from "../task/identity.js";
5
6
  import type { VerificationDeclarationPreparation } from "../verification/declaration.js";
6
7
  import type { KeiyakuRefusal } from "./refusal.js";
@@ -2,7 +2,7 @@ import { randomBytes } from "node:crypto";
2
2
  import { releaseContractWorktree, reserveContractWorktree, withContractWorktreeAppointment, } from "../contract-worktree.js";
3
3
  import { contractIdFromSegment } from "../core/facts/types.js";
4
4
  import { fitIdentityStem, normalizeIdentityStem } from "../identity/normalize.js";
5
- import { bindOperation } from "../protocol/operations.js";
5
+ import { bindOperation } from "../protocol/bind.js";
6
6
  import { claimTaskHolder } from "../settlement/holder.js";
7
7
  function candidateId(title, collision) {
8
8
  const stem = fitIdentityStem({ stem: normalizeIdentityStem({ source: title }) || "contract", maxBytes: 48 });
@@ -13,7 +13,6 @@ async function attempt(input, id) {
13
13
  return bindOperation({
14
14
  scope: input.scope,
15
15
  channel: input.channel,
16
- title: input.title,
17
16
  terms: input.terms,
18
17
  verification: input.verification,
19
18
  workspace: input.workspace,
@@ -26,6 +25,7 @@ async function attempt(input, id) {
26
25
  });
27
26
  }
28
27
  async function attemptCandidates(input) {
28
+ let result;
29
29
  for (let collision = 0; collision <= 3; collision += 1) {
30
30
  const id = candidateId(input.title, collision);
31
31
  let reserved = false;
@@ -40,7 +40,7 @@ async function attemptCandidates(input) {
40
40
  }
41
41
  reserved = true;
42
42
  }
43
- const result = await attempt(input, id);
43
+ result = await attempt(input, id);
44
44
  if (result.kind === "accepted")
45
45
  return result;
46
46
  if (reserved)
@@ -48,7 +48,7 @@ async function attemptCandidates(input) {
48
48
  if (result.kind !== "refused" || result.refusal.kind !== "contract-exists")
49
49
  return result;
50
50
  }
51
- throw new Error("contract identity collision attempts exhausted");
51
+ return result;
52
52
  }
53
53
  export async function admitBindWithAppointment(input) {
54
54
  const action = () => attemptCandidates(input);
@@ -1,6 +1,5 @@
1
1
  import { type AkumaList } from "../akuma/akuma.js";
2
2
  import { type ArchetypeCatalogRow } from "../akuma/archetype.js";
3
- import type { Settings } from "../settings.js";
4
3
  import type { TaskRow } from "../task/index.js";
5
4
  import { type ContractBoard } from "./contract.js";
6
5
  import { Repo } from "./repo.js";
@@ -29,7 +28,7 @@ export type CatalogInput = Readonly<{
29
28
  query: Extract<CatalogQuery, {
30
29
  kind: "archetypes";
31
30
  }>;
32
- settings: Settings;
31
+ home?: string;
33
32
  }> | Readonly<{
34
33
  query: Extract<CatalogQuery, {
35
34
  kind: "akuma";
@@ -4,10 +4,11 @@ import { observeTaskCatalogRows } from "../task/operations.js";
4
4
  import { listKeiyaku } from "./contract.js";
5
5
  import { requireInput } from "./input.js";
6
6
  import { Repo } from "./repo.js";
7
- function settingsValue(value) {
8
- if (typeof value !== "object" || value === null
9
- || typeof value.namespace !== "function") {
10
- throw new TypeError("settings must be a Settings");
7
+ function optionalHome(value) {
8
+ if (value === undefined)
9
+ return undefined;
10
+ if (typeof value !== "string" || value.trim().length === 0) {
11
+ throw new TypeError("home must be a nonblank string");
11
12
  }
12
13
  return value;
13
14
  }
@@ -40,7 +41,7 @@ export async function listCatalog(input) {
40
41
  const values = requireInput(input, "Keiyaku.ls input");
41
42
  const query = queryValue(values.query);
42
43
  const allowed = query.kind === "contracts" ? ["query", "repo"]
43
- : query.kind === "archetypes" ? ["query", "settings"] : ["query", "path"];
44
+ : query.kind === "archetypes" ? ["query", "home"] : ["query", "path"];
44
45
  for (const key of Object.keys(values)) {
45
46
  if (!allowed.includes(key))
46
47
  throw new TypeError(`Keiyaku.ls input has unknown field: ${key}`);
@@ -52,7 +53,11 @@ export async function listCatalog(input) {
52
53
  return { kind: "contracts", root: board.root, state: board.state, rows: board.rows };
53
54
  }
54
55
  if (query.kind === "archetypes") {
55
- return { kind: "archetypes", rows: await listArchetypeDefinitions({ settings: settingsValue(values.settings) }) };
56
+ const home = optionalHome(values.home);
57
+ return {
58
+ kind: "archetypes",
59
+ rows: await listArchetypeDefinitions(home === undefined ? {} : { home }),
60
+ };
56
61
  }
57
62
  const path = worldRoot(values.path);
58
63
  if (query.kind === "tasks") {
@@ -4,14 +4,18 @@ export type { HookCommand, WorktreeHooks } from "../git/hooks.js";
4
4
  export type Gate = string;
5
5
  export type GatesFromInput = Readonly<{
6
6
  settings: Settings;
7
- name?: string;
7
+ names?: readonly string[];
8
8
  }>;
9
9
  export type RequireBranchesToBeUpToDateFromInput = Readonly<{
10
10
  settings: Settings;
11
11
  }>;
12
+ export type WorktreeHooksFromInput = Readonly<{
13
+ settings: Settings;
14
+ }>;
12
15
  export { SettingsError };
13
16
  export declare function gatesFrom(input: GatesFromInput): readonly Gate[];
14
17
  export declare function requireBranchesToBeUpToDateFrom(input: RequireBranchesToBeUpToDateFromInput): boolean;
18
+ export declare function worktreeHooksFrom(input: WorktreeHooksFromInput): WorktreeHooks;
15
19
  export declare function normalizedWorktreeHooks(value: unknown): WorktreeHooks;
16
20
  export declare const EMPTY_WORKTREE_HOOKS: WorktreeHooks;
17
21
  export declare function worktreeHooksOption(value: unknown): WorktreeHooks;
@@ -9,31 +9,65 @@ function namespaceFailure(view) {
9
9
  throw new Error("settings namespace failure expected");
10
10
  throw new SettingsError(view.failures.map((failure) => `${failure.scope}: ${failure.diagnostic}`).join("; "));
11
11
  }
12
+ function bundleGates(name, value) {
13
+ if (!record(value))
14
+ throw new SettingsError(`gate bundle '${name}' must be an object`);
15
+ if (value.kind !== "bundle") {
16
+ throw new SettingsError(`gate bundle '${name}' has unsupported kind: ${String(value.kind)}`);
17
+ }
18
+ for (const field of Object.keys(value)) {
19
+ if (field !== "kind" && field !== "gates") {
20
+ throw new SettingsError(`gate bundle '${name}' has unknown field: ${field}`);
21
+ }
22
+ }
23
+ if (!Array.isArray(value.gates)) {
24
+ throw new SettingsError(`gate bundle '${name}'.gates must be an array`);
25
+ }
26
+ return value.gates.map((gate) => {
27
+ if (!gateWord(gate)) {
28
+ throw new SettingsError(`gate bundle '${name}' contains an invalid gate word`);
29
+ }
30
+ if (gate !== "reviewed" && gate !== "verified") {
31
+ throw new SettingsError(`gate bundle '${name}' contains a gate without a producer: ${gate}`);
32
+ }
33
+ return gate;
34
+ });
35
+ }
12
36
  export function gatesFrom(input) {
13
37
  if (!record(input))
14
38
  throw new TypeError("gatesFrom input must be an object");
15
- const name = input.name ?? "default";
16
- if (!gateWord(name))
17
- throw new SettingsError("gate set name must match ^[a-z][a-z0-9-]{0,63}$");
39
+ if (input.names !== undefined && !Array.isArray(input.names)) {
40
+ throw new TypeError("gatesFrom names must be an array");
41
+ }
42
+ const names = input.names ?? ["default"];
43
+ for (const name of names) {
44
+ if (!gateWord(name))
45
+ throw new SettingsError("gate bundle name must match ^[a-z][a-z0-9-]{0,63}$");
46
+ }
18
47
  const view = input.settings.namespace("gates");
19
48
  if (view.kind === "failed")
20
49
  namespaceFailure(view);
21
- const selected = view.entries.find((entry) => entry.name === name);
22
- if (selected === undefined) {
23
- if (input.name === undefined)
24
- return Object.freeze([]);
25
- throw new SettingsError(`unknown gate set: ${name}`);
50
+ const expanded = [];
51
+ const seen = new Set();
52
+ for (const name of names) {
53
+ const selected = view.entries.find((entry) => entry.name === name);
54
+ if (selected === undefined) {
55
+ if (input.names === undefined) {
56
+ if (!seen.has("reviewed"))
57
+ expanded.push("reviewed");
58
+ seen.add("reviewed");
59
+ continue;
60
+ }
61
+ throw new SettingsError(`unknown gate bundle: ${name}`);
62
+ }
63
+ for (const gate of bundleGates(name, selected.value)) {
64
+ if (seen.has(gate))
65
+ continue;
66
+ seen.add(gate);
67
+ expanded.push(gate);
68
+ }
26
69
  }
27
- if (!Array.isArray(selected.value))
28
- throw new SettingsError(`gate set '${name}' must be an array`);
29
- const values = selected.value.map((value) => {
30
- if (!gateWord(value))
31
- throw new SettingsError(`gate set '${name}' contains an invalid gate word`);
32
- return value;
33
- });
34
- if (new Set(values).size !== values.length)
35
- throw new SettingsError(`gate set '${name}' contains duplicate gates`);
36
- return Object.freeze(values);
70
+ return Object.freeze(expanded);
37
71
  }
38
72
  function command(value, coordinate, ErrorType) {
39
73
  if (!record(value))
@@ -76,6 +110,25 @@ export function requireBranchesToBeUpToDateFrom(input) {
76
110
  }
77
111
  return selected.value;
78
112
  }
113
+ export function worktreeHooksFrom(input) {
114
+ if (!record(input))
115
+ throw new TypeError("worktreeHooksFrom input must be an object");
116
+ const view = input.settings.namespace("worktree");
117
+ if (view.kind === "failed")
118
+ namespaceFailure(view);
119
+ for (const entry of view.entries) {
120
+ if (entry.name !== "create" && entry.name !== "destroy") {
121
+ throw new SettingsError(`worktree has unknown entry: ${entry.name}`);
122
+ }
123
+ }
124
+ const selected = (phase) => {
125
+ const entry = view.entries.find((item) => item.name === phase);
126
+ if (entry === undefined)
127
+ return Object.freeze([]);
128
+ return commands(entry.value, `worktree.${phase}`, SettingsError);
129
+ };
130
+ return Object.freeze({ create: selected("create"), destroy: selected("destroy") });
131
+ }
79
132
  export function normalizedWorktreeHooks(value) {
80
133
  if (!record(value))
81
134
  throw new TypeError("hooks must be an object");
@@ -3,20 +3,42 @@ import { type RegionObservation, type RegionOverlap } from "./region.js";
3
3
  import { type Gate, type WorktreeHooks } from "./configuration.js";
4
4
  import { type ChangeId, type ContractId, type ContractState, type JournalEntry, type SnapshotId } from "../core/facts/types.js";
5
5
  export { AuthorityCorruptionError } from "../core/facts/errors.js";
6
- import { type AuditReport, type ContractBoard, type ContractDisposition, type ContractGateCurrent, type ContractGateReport, type ContractObservation, type ContractPhase, type ContractRow, type FactKind, type PlacementStop, type ReconcileReport as ProtocolReconcileReport, type RepositoryScope, type ReviewValue, type VerificationReuse, type VerificationStop, type DeliveryPreparationRefusal } from "../protocol/operations.js";
6
+ import { type PlacementStop, type RepositoryScope, type VerificationStop, type DeliveryPreparationRefusal } from "../protocol/operations.js";
7
+ import type { ContractBoard, ContractDisposition, ContractGateCurrent, ContractGateReport, ContractObservation, ContractPhase, ContractRow } from "../protocol/read/status.js";
8
+ import type { AuditReport } from "../protocol/audit.js";
9
+ import { type DeliverValue, type VerificationReuse } from "../protocol/deliver.js";
10
+ import type { ReconcileReport as ProtocolReconcileReport } from "../protocol/reconcile.js";
11
+ import { type ReviewValue } from "../protocol/review.js";
12
+ import type { FactKind } from "../core/facts/types.js";
13
+ import { type Dispatch } from "../dispatch/index.js";
7
14
  import { type SettlementReport } from "../settlement/settle.js";
8
15
  import { type TaskId } from "../task/identity.js";
9
16
  import { Repo, type ReconcileInput } from "./repo.js";
10
17
  import { type AuditInput } from "./audit.js";
11
18
  import { Delivery } from "./delivery.js";
12
19
  import { type MutationResult } from "./mutation.js";
13
- export { KeiyakuRefused, KeiyakuRetry, type ContractAppointmentRefusal, type KeiyakuRefusal, type KeiyakuRetryReason, } from "./refusal.js";
20
+ import { KeiyakuRetry, type KeiyakuRefusal, type KeiyakuRetryReason } from "./refusal.js";
21
+ export { KeiyakuRefused, type ContractAppointmentRefusal, } from "./refusal.js";
22
+ export { KeiyakuRetry };
23
+ export type { KeiyakuRefusal, KeiyakuRetryReason };
14
24
  export { gatesFrom, requireBranchesToBeUpToDateFrom, SettingsError } from "./configuration.js";
15
25
  export type { Gate, GatesFromInput, HookCommand, RequireBranchesToBeUpToDateFromInput, WorktreeHooks } from "./configuration.js";
16
26
  export type { AuditReport, DeliveryPreparationRefusal, ChangeId, ContractId, ContractState, ContractBoard, ContractDisposition, ContractGateCurrent, ContractGateReport, ContractObservation, ContractPhase, ContractRow, FactKind, SnapshotId, };
17
27
  export type { TaskId };
18
28
  export type { RegionOverlap };
19
29
  export type Fact = JournalEntry;
30
+ export type ContractHistoryEvent = Readonly<{
31
+ source: "journal";
32
+ fact: Fact;
33
+ }> | Readonly<{
34
+ source: "dispatch";
35
+ dispatch: Dispatch;
36
+ }>;
37
+ export type ContractHistory = Readonly<{
38
+ id: ContractId;
39
+ state: SnapshotId;
40
+ events: readonly ContractHistoryEvent[];
41
+ }>;
20
42
  export type ActorId = string;
21
43
  export type AttestationVerdict = "satisfied" | "unsatisfied";
22
44
  export type Review = ReviewValue;
@@ -49,7 +71,7 @@ export type BindInput = Readonly<{
49
71
  hooks?: WorktreeHooks;
50
72
  }>;
51
73
  export type AmendInput = Readonly<{
52
- markdown: string;
74
+ markdown?: string;
53
75
  actor?: ActorId;
54
76
  after?: readonly ContractId[];
55
77
  gates?: readonly Gate[];
@@ -90,12 +112,57 @@ export type DeliverInput = ActorOptions & Readonly<{
90
112
  includeDirty?: boolean;
91
113
  signal?: AbortSignal;
92
114
  }>;
115
+ type ForwardedDeliveryReceipt = Readonly<{
116
+ kind: "accepted";
117
+ result: MutationResult<DeliverValue>;
118
+ }> | Readonly<{
119
+ kind: "refused";
120
+ refusal: KeiyakuRefusal;
121
+ }> | Readonly<{
122
+ kind: "retry";
123
+ reason: KeiyakuRetryReason;
124
+ }>;
125
+ type ForwardedReviewReceipt = Readonly<{
126
+ kind: "accepted";
127
+ result: MutationResult<ReviewValue>;
128
+ }> | Readonly<{
129
+ kind: "refused";
130
+ refusal: KeiyakuRefusal;
131
+ }> | Readonly<{
132
+ kind: "retry";
133
+ reason: KeiyakuRetryReason;
134
+ }>;
93
135
  export type { AuditInput };
136
+ export declare function executeForwardedDeliver(input: Readonly<{
137
+ repo: Repo;
138
+ contractId: string;
139
+ requester: string;
140
+ message?: string;
141
+ includeDirty: boolean;
142
+ requireBranchesToBeUpToDate: boolean;
143
+ hooks: WorktreeHooks;
144
+ signal?: AbortSignal;
145
+ }>): Promise<Readonly<{
146
+ result: ForwardedDeliveryReceipt;
147
+ deliveryFactId?: string;
148
+ }>>;
149
+ export declare function executeForwardedReview(input: Readonly<{
150
+ repo: Repo;
151
+ contractId: string;
152
+ requester: string;
153
+ verdict: AttestationVerdict;
154
+ summary?: string;
155
+ hooks: WorktreeHooks;
156
+ }>): Promise<Readonly<{
157
+ result: ForwardedReviewReceipt;
158
+ reviewFactId?: string;
159
+ }>>;
94
160
  export declare class KeiyakuHandle {
95
161
  private readonly id;
96
162
  private readonly scope;
97
163
  constructor(id: ContractId, scope: RepositoryScope);
98
164
  state(): Promise<ContractState>;
165
+ history(): Promise<ContractHistory>;
99
166
  guidance(): Promise<string>;
100
167
  delivery(): Promise<Delivery | null>;
101
168
  amend(input: AmendInput): Promise<AmendResult>;