@astrosheep/keiyaku 4.0.6 → 4.1.1

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 (251) hide show
  1. package/README.md +1 -1
  2. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -0
  3. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +3 -0
  4. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -6
  5. package/build/src/akuma/akuma.d.ts +17 -14
  6. package/build/src/akuma/akuma.js +122 -114
  7. package/build/src/akuma/allowed.d.ts +1 -0
  8. package/build/src/akuma/allowed.js +6 -0
  9. package/build/src/akuma/archetype.js +12 -2
  10. package/build/src/akuma/body-turn.js +27 -15
  11. package/build/src/akuma/body.d.ts +44 -3
  12. package/build/src/akuma/body.js +142 -33
  13. package/build/src/akuma/coordinate.js +17 -7
  14. package/build/src/akuma/heart/facts.js +1 -1
  15. package/build/src/akuma/heart/index.d.ts +1 -1
  16. package/build/src/akuma/heart/index.js +2 -4
  17. package/build/src/akuma/heart/request-authority.js +4 -4
  18. package/build/src/akuma/heart/request-rows.js +27 -16
  19. package/build/src/akuma/heart/rows.js +79 -41
  20. package/build/src/akuma/heart/soul.js +1 -1
  21. package/build/src/akuma/heart/storage.d.ts +1 -0
  22. package/build/src/akuma/heart/storage.js +76 -11
  23. package/build/src/akuma/heart/tells.js +35 -18
  24. package/build/src/akuma/heart/timeline.js +19 -11
  25. package/build/src/akuma/identity.d.ts +1 -0
  26. package/build/src/akuma/identity.js +1 -0
  27. package/build/src/akuma/index.d.ts +3 -3
  28. package/build/src/akuma/index.js +1 -1
  29. package/build/src/akuma/nuke.js +106 -14
  30. package/build/src/akuma/projection.d.ts +11 -9
  31. package/build/src/akuma/projection.js +110 -53
  32. package/build/src/akuma/provider-recipe.d.ts +2 -0
  33. package/build/src/akuma/provider-recipe.js +21 -5
  34. package/build/src/akuma/provider.js +105 -62
  35. package/build/src/akuma/providers/acp/config.d.ts +2 -0
  36. package/build/src/akuma/providers/acp/config.js +13 -6
  37. package/build/src/akuma/providers/acp/core.d.ts +5 -2
  38. package/build/src/akuma/providers/acp/core.js +45 -25
  39. package/build/src/akuma/providers/acp/events.js +38 -29
  40. package/build/src/akuma/providers/acp/index.js +18 -8
  41. package/build/src/akuma/providers/claude/events.js +8 -12
  42. package/build/src/akuma/providers/claude/index.d.ts +2 -1
  43. package/build/src/akuma/providers/claude/index.js +59 -26
  44. package/build/src/akuma/providers/claude/input.js +6 -2
  45. package/build/src/akuma/providers/codex-app-server/events.js +61 -36
  46. package/build/src/akuma/providers/codex-app-server/index.js +29 -14
  47. package/build/src/akuma/providers/grok-build/index.js +28 -17
  48. package/build/src/akuma/providers/index.js +3 -19
  49. package/build/src/akuma/providers/opencode-sdk/events.js +32 -18
  50. package/build/src/akuma/providers/opencode-sdk/index.js +29 -17
  51. package/build/src/akuma/providers/opencode-sdk/session.js +21 -5
  52. package/build/src/akuma/providers/pi/events.js +26 -19
  53. package/build/src/akuma/providers/pi/index.js +58 -38
  54. package/build/src/akuma/publication.js +9 -9
  55. package/build/src/akuma/request-serve.js +37 -40
  56. package/build/src/akuma/request-wire.d.ts +2 -2
  57. package/build/src/akuma/request-wire.js +75 -102
  58. package/build/src/akuma/requests.js +2 -2
  59. package/build/src/akuma-body.js +6 -5
  60. package/build/src/body/amend.d.ts +4 -1
  61. package/build/src/body/amend.js +14 -15
  62. package/build/src/body/decode.js +2 -4
  63. package/build/src/body/envelope.js +2 -4
  64. package/build/src/body/region.d.ts +1 -2
  65. package/build/src/body/region.js +4 -72
  66. package/build/src/body/render.js +17 -12
  67. package/build/src/body/shape.js +1 -7
  68. package/build/src/cli/accepted.d.ts +1 -1
  69. package/build/src/cli/accepted.js +10 -1
  70. package/build/src/cli/commands/akuma-invoke.js +18 -6
  71. package/build/src/cli/commands/akuma.js +10 -13
  72. package/build/src/cli/commands/amend.d.ts +2 -2
  73. package/build/src/cli/commands/amend.js +2 -4
  74. package/build/src/cli/commands/bind.d.ts +4 -4
  75. package/build/src/cli/commands/bind.js +16 -6
  76. package/build/src/cli/commands/contract.d.ts +99 -10
  77. package/build/src/cli/commands/contract.js +128 -24
  78. package/build/src/cli/commands/install.d.ts +1 -1
  79. package/build/src/cli/commands/install.js +23 -15
  80. package/build/src/cli/commands/task-invoke.d.ts +4 -1
  81. package/build/src/cli/commands/task-invoke.js +191 -68
  82. package/build/src/cli/commands/task-query.js +48 -24
  83. package/build/src/cli/commands/task.js +150 -30
  84. package/build/src/cli/coordinates.js +2 -4
  85. package/build/src/cli/invoke.js +88 -44
  86. package/build/src/cli/main.js +4 -2
  87. package/build/src/cli/parse.d.ts +2 -89
  88. package/build/src/cli/parse.js +87 -79
  89. package/build/src/cli/render/akuma-tool-command.js +6 -7
  90. package/build/src/cli/render/akuma-tool.js +10 -8
  91. package/build/src/cli/render/akuma.js +149 -53
  92. package/build/src/cli/render/audit.js +5 -15
  93. package/build/src/cli/render/board.d.ts +1 -0
  94. package/build/src/cli/render/board.js +17 -0
  95. package/build/src/cli/render/catalog.js +84 -7
  96. package/build/src/cli/render/contract-observation.d.ts +10 -0
  97. package/build/src/cli/render/contract-observation.js +58 -0
  98. package/build/src/cli/render/contract.js +57 -54
  99. package/build/src/cli/render/kanshi.js +281 -209
  100. package/build/src/cli/render/receipt.d.ts +1 -0
  101. package/build/src/cli/render/receipt.js +20 -23
  102. package/build/src/cli/render/refusal.js +16 -15
  103. package/build/src/cli/render/region.js +22 -6
  104. package/build/src/cli/render/settings.js +4 -4
  105. package/build/src/cli/render/task.js +93 -21
  106. package/build/src/cli/render/terminal.js +16 -5
  107. package/build/src/cli/result.d.ts +11 -4
  108. package/build/src/cli/runtime.d.ts +6 -1
  109. package/build/src/cli/runtime.js +84 -63
  110. package/build/src/cli/selectors.js +2 -4
  111. package/build/src/cli/usage.js +6 -5
  112. package/build/src/contract-worktree.d.ts +1 -25
  113. package/build/src/contract-worktree.js +87 -174
  114. package/build/src/coordination/durable-file.js +7 -3
  115. package/build/src/coordination/sqlite-transaction-lock.js +29 -12
  116. package/build/src/core/facts/codec.js +7 -3
  117. package/build/src/core/facts/types.d.ts +1 -1
  118. package/build/src/core/subject.js +16 -9
  119. package/build/src/core/verbs/abandon.d.ts +1 -1
  120. package/build/src/core/verbs/abandon.js +1 -1
  121. package/build/src/core/verbs/amend.d.ts +1 -1
  122. package/build/src/core/verbs/amend.js +7 -7
  123. package/build/src/core/verbs/attestation.js +4 -1
  124. package/build/src/core/verbs/bind.d.ts +1 -1
  125. package/build/src/core/verbs/bind.js +1 -1
  126. package/build/src/core/verbs/placement.d.ts +1 -1
  127. package/build/src/core/verbs/placement.js +10 -8
  128. package/build/src/dispatch/index.js +8 -6
  129. package/build/src/duration.js +5 -1
  130. package/build/src/git/admission.js +5 -3
  131. package/build/src/git/hooks.d.ts +8 -0
  132. package/build/src/git/hooks.js +63 -14
  133. package/build/src/git/identity.js +1 -4
  134. package/build/src/git/integration.d.ts +2 -3
  135. package/build/src/git/integration.js +32 -39
  136. package/build/src/git/nuke.d.ts +1 -1
  137. package/build/src/git/nuke.js +110 -62
  138. package/build/src/git/observe.d.ts +13 -1
  139. package/build/src/git/observe.js +51 -44
  140. package/build/src/git/process.js +4 -2
  141. package/build/src/git/read-observation.js +10 -8
  142. package/build/src/git/reconcile.d.ts +14 -3
  143. package/build/src/git/reconcile.js +123 -102
  144. package/build/src/git/repository.d.ts +2 -0
  145. package/build/src/git/repository.js +13 -22
  146. package/build/src/git/target-placement.d.ts +9 -10
  147. package/build/src/git/target-placement.js +59 -62
  148. package/build/src/git/tender.d.ts +13 -2
  149. package/build/src/git/tender.js +28 -22
  150. package/build/src/git/terminal-seal.js +15 -12
  151. package/build/src/git/tree.js +5 -2
  152. package/build/src/git/workspace.d.ts +24 -2
  153. package/build/src/git/workspace.js +120 -16
  154. package/build/src/identity/coordinates.js +3 -1
  155. package/build/src/identity/selector.js +6 -3
  156. package/build/src/kanshi/fleet.d.ts +6 -0
  157. package/build/src/kanshi/fleet.js +27 -0
  158. package/build/src/kanshi/index.d.ts +1 -1
  159. package/build/src/kanshi/read.js +77 -45
  160. package/build/src/kanshi/report.d.ts +13 -24
  161. package/build/src/kanshi/select.js +25 -24
  162. package/build/src/library/address.d.ts +2 -1
  163. package/build/src/library/address.js +7 -8
  164. package/build/src/library/akuma-creation.js +20 -12
  165. package/build/src/library/audit.d.ts +0 -1
  166. package/build/src/library/audit.js +1 -2
  167. package/build/src/library/bind.d.ts +53 -5
  168. package/build/src/library/bind.js +98 -22
  169. package/build/src/library/catalog.d.ts +1 -0
  170. package/build/src/library/catalog.js +6 -3
  171. package/build/src/library/configuration.js +3 -1
  172. package/build/src/library/continuation.d.ts +37 -0
  173. package/build/src/library/continuation.js +86 -0
  174. package/build/src/library/contract.d.ts +39 -45
  175. package/build/src/library/contract.js +141 -118
  176. package/build/src/library/delivery.d.ts +18 -13
  177. package/build/src/library/fleet.d.ts +1 -1
  178. package/build/src/library/fleet.js +19 -11
  179. package/build/src/library/input.d.ts +2 -0
  180. package/build/src/library/input.js +14 -0
  181. package/build/src/library/keiyaku.d.ts +8 -7
  182. package/build/src/library/keiyaku.js +3 -3
  183. package/build/src/library/mutation.js +11 -4
  184. package/build/src/library/nuke.js +14 -5
  185. package/build/src/library/reconcile.d.ts +9 -4
  186. package/build/src/library/reconcile.js +30 -24
  187. package/build/src/library/refusal.d.ts +13 -5
  188. package/build/src/library/refusal.js +7 -0
  189. package/build/src/library/region.d.ts +8 -7
  190. package/build/src/library/region.js +31 -11
  191. package/build/src/library/repo.js +2 -2
  192. package/build/src/markdown/lex.js +9 -2
  193. package/build/src/markdown/parse.js +11 -7
  194. package/build/src/markdown/query.js +4 -2
  195. package/build/src/protocol/amend.js +3 -1
  196. package/build/src/protocol/attempt.d.ts +7 -3
  197. package/build/src/protocol/attempt.js +9 -5
  198. package/build/src/protocol/audit.d.ts +1 -1
  199. package/build/src/protocol/audit.js +4 -14
  200. package/build/src/protocol/bind.d.ts +19 -6
  201. package/build/src/protocol/bind.js +28 -13
  202. package/build/src/protocol/completion.d.ts +0 -1
  203. package/build/src/protocol/completion.js +1 -3
  204. package/build/src/protocol/deliver.d.ts +12 -4
  205. package/build/src/protocol/deliver.js +60 -51
  206. package/build/src/protocol/intent.d.ts +1 -0
  207. package/build/src/protocol/intent.js +9 -7
  208. package/build/src/protocol/operations.d.ts +10 -9
  209. package/build/src/protocol/operations.js +5 -3
  210. package/build/src/protocol/placement.d.ts +0 -1
  211. package/build/src/protocol/placement.js +6 -6
  212. package/build/src/protocol/read/observation.d.ts +11 -0
  213. package/build/src/protocol/read/observation.js +37 -0
  214. package/build/src/protocol/read/status.d.ts +23 -12
  215. package/build/src/protocol/read/status.js +90 -72
  216. package/build/src/protocol/reconcile.d.ts +1 -0
  217. package/build/src/protocol/reconcile.js +2 -3
  218. package/build/src/protocol/reintegrate.js +1 -1
  219. package/build/src/protocol/review.d.ts +0 -1
  220. package/build/src/protocol/review.js +15 -22
  221. package/build/src/protocol/run.d.ts +1 -0
  222. package/build/src/protocol/run.js +4 -5
  223. package/build/src/runtime/proc/launch.d.ts +33 -0
  224. package/build/src/runtime/proc/launch.js +98 -0
  225. package/build/src/runtime/proc/line-rpc.js +9 -3
  226. package/build/src/runtime/proc/run.d.ts +12 -6
  227. package/build/src/runtime/proc/run.js +78 -21
  228. package/build/src/runtime/proc/stdio.js +7 -10
  229. package/build/src/settings.js +6 -2
  230. package/build/src/settlement/fence.d.ts +0 -2
  231. package/build/src/settlement/fence.js +0 -24
  232. package/build/src/settlement/holder.js +13 -10
  233. package/build/src/settlement/settle.js +39 -6
  234. package/build/src/task/board.d.ts +21 -2
  235. package/build/src/task/board.js +35 -16
  236. package/build/src/task/compose.js +85 -22
  237. package/build/src/task/context.js +21 -8
  238. package/build/src/task/document.js +46 -10
  239. package/build/src/task/identity.js +19 -6
  240. package/build/src/task/index.js +118 -27
  241. package/build/src/task/input.js +29 -7
  242. package/build/src/task/mutation.js +61 -19
  243. package/build/src/task/operations.d.ts +8 -2
  244. package/build/src/task/operations.js +97 -32
  245. package/build/src/task/query.js +57 -28
  246. package/build/src/task/store.d.ts +5 -1
  247. package/build/src/task/store.js +88 -95
  248. package/build/src/verification/execution.js +14 -11
  249. package/build/src/workspace-place.js +19 -7
  250. package/build/src/world.js +16 -6
  251. package/package.json +8 -3
@@ -2,11 +2,11 @@ import { access, mkdir, readFile, readdir, rm } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { abortableDelay } from "./abort.js";
4
4
  import { HeldAkumaLeash, admitRequest, readNonterminalRequests, readRequest, readSoul, refuseRequest, reserveRequest, serveRequest, serveUpstreamRequest, voidRequest, } from "./heart/index.js";
5
- import { pathsForAkuId, worldRootForAkumaPaths, } from "./identity.js";
5
+ import { pathsForAkuId, worldRootForAkumaPaths } from "./identity.js";
6
6
  import { BIRTH_TIMEOUT_MS, publishAkuma } from "./publication.js";
7
7
  import { atomicJson, canonicalAkuId, decodeClaim, decodeRecipe, receiptPath, } from "./request-wire.js";
8
8
  import { isTaskMutationAction } from "../task/mutation.js";
9
- const POLL_MS = 25;
9
+ const POLL_MS = 100;
10
10
  function diagnostic(error) {
11
11
  return error instanceof Error ? error.message : String(error);
12
12
  }
@@ -123,14 +123,10 @@ async function serveCall(input) {
123
123
  seed: {
124
124
  id: allocated.id,
125
125
  archetype: allocated.archetype,
126
- ...(request.recipe.description === undefined
127
- ? {}
128
- : { description: request.recipe.description }),
126
+ ...(request.recipe.description === undefined ? {} : { description: request.recipe.description }),
129
127
  provider: request.recipe.provider,
130
128
  options: request.recipe.options,
131
- ...(request.recipe.readonly === undefined
132
- ? {}
133
- : { readonly: request.recipe.readonly }),
129
+ ...(request.recipe.readonly === undefined ? {} : { readonly: request.recipe.readonly }),
134
130
  allowed: request.recipe.allowed,
135
131
  cwd: request.cwd ?? input.parent.cwd,
136
132
  origin: {
@@ -149,9 +145,10 @@ async function serveCall(input) {
149
145
  const current = await readRequest(input.paths, request.id);
150
146
  if (current === null)
151
147
  throw error;
152
- fact = current.state === "admitted" || current.state === "reserved"
153
- ? await voidRequest(input.paths, request.id, diagnostic(error))
154
- : current;
148
+ fact =
149
+ current.state === "admitted" || current.state === "reserved"
150
+ ? await voidRequest(input.paths, request.id, diagnostic(error))
151
+ : current;
155
152
  }
156
153
  await projectReceipt(input.directory, fact);
157
154
  }
@@ -228,14 +225,16 @@ async function executeDeliver(input, request) {
228
225
  });
229
226
  return {
230
227
  result: served.result,
231
- ...(served.deliveryFactId === undefined ? {} : {
232
- service: {
233
- action: request.action,
234
- repoRoot: request.repoRoot,
235
- contractId: request.contractId,
236
- deliveryFactId: served.deliveryFactId,
237
- },
238
- }),
228
+ ...(served.deliveryFactId === undefined
229
+ ? {}
230
+ : {
231
+ service: {
232
+ action: request.action,
233
+ repoRoot: request.repoRoot,
234
+ contractId: request.contractId,
235
+ deliveryFactId: served.deliveryFactId,
236
+ },
237
+ }),
239
238
  };
240
239
  }
241
240
  async function executeReview(input, request) {
@@ -251,14 +250,16 @@ async function executeReview(input, request) {
251
250
  });
252
251
  return {
253
252
  result: served.result,
254
- ...(served.reviewFactId === undefined ? {} : {
255
- service: {
256
- action: request.action,
257
- repoRoot: request.repoRoot,
258
- contractId: request.contractId,
259
- reviewFactId: served.reviewFactId,
260
- },
261
- }),
253
+ ...(served.reviewFactId === undefined
254
+ ? {}
255
+ : {
256
+ service: {
257
+ action: request.action,
258
+ repoRoot: request.repoRoot,
259
+ contractId: request.contractId,
260
+ reviewFactId: served.reviewFactId,
261
+ },
262
+ }),
262
263
  };
263
264
  }
264
265
  function pendingService(request) {
@@ -313,9 +314,10 @@ async function serveUpstream(input) {
313
314
  await projectReceipt(input.directory, fact);
314
315
  return;
315
316
  }
316
- fact = service === undefined
317
- ? await voidRequest(input.paths, request.id, "body completed without a durable Contract fact reference")
318
- : await serveUpstreamRequest(input.paths, request.id, service);
317
+ fact =
318
+ service === undefined
319
+ ? await voidRequest(input.paths, request.id, "body completed without a durable Contract fact reference")
320
+ : await serveUpstreamRequest(input.paths, request.id, service);
319
321
  await projectReceipt(input.directory, fact, outcome);
320
322
  }
321
323
  async function serve(input) {
@@ -325,9 +327,7 @@ async function serve(input) {
325
327
  }
326
328
  async function requestFiles(directory) {
327
329
  try {
328
- return (await readdir(directory))
329
- .filter((name) => name.endsWith(".request.json"))
330
- .sort();
330
+ return (await readdir(directory)).filter((name) => name.endsWith(".request.json")).sort();
331
331
  }
332
332
  catch (error) {
333
333
  if (error.code === "ENOENT")
@@ -421,9 +421,7 @@ export async function clearBodyRequestTransport(paths) {
421
421
  await rm(join(paths.directory, "requests"), { recursive: true, force: true });
422
422
  }
423
423
  function matchingRequestOrigin(soul, parent, id) {
424
- return soul.origin.kind === "request"
425
- && soul.origin.parent === parent
426
- && soul.origin.requestId === id;
424
+ return soul.origin.kind === "request" && soul.origin.parent === parent && soul.origin.requestId === id;
427
425
  }
428
426
  async function settleReservedSoul(paths, parent, request, soul) {
429
427
  await (matchingRequestOrigin(soul, parent.id, request.id)
@@ -435,7 +433,7 @@ async function settleReserved(paths, parent, request, now, signal) {
435
433
  const deadline = performance.now() + BIRTH_TIMEOUT_MS;
436
434
  for (;;) {
437
435
  signal?.throwIfAborted();
438
- if (!await access(childPaths.directory).then(() => true, () => false)) {
436
+ if (!(await access(childPaths.directory).then(() => true, () => false))) {
439
437
  await voidRequest(paths, request.id, "reserved child directory is absent");
440
438
  return true;
441
439
  }
@@ -466,7 +464,7 @@ async function settleReserved(paths, parent, request, now, signal) {
466
464
  }
467
465
  if (performance.now() >= deadline)
468
466
  return false;
469
- await abortableDelay(POLL_MS, signal);
467
+ await abortableDelay(Math.min(POLL_MS, Math.max(0, deadline - performance.now())), signal);
470
468
  }
471
469
  }
472
470
  export async function settleBodyRequests(paths, parent, now, signal) {
@@ -476,8 +474,7 @@ export async function settleBodyRequests(paths, parent, now, signal) {
476
474
  if (request.state === "admitted") {
477
475
  await voidRequest(paths, request.id, "body died before serving the request");
478
476
  }
479
- else if (request.state === "reserved"
480
- && !await settleReserved(paths, parent, request, now, signal))
477
+ else if (request.state === "reserved" && !(await settleReserved(paths, parent, request, now, signal)))
481
478
  pending = true;
482
479
  }
483
480
  return pending ? "pending" : "settled";
@@ -60,9 +60,9 @@ export type TaskRequestClaim = Readonly<{
60
60
  request: TaskMutationRequest;
61
61
  }>;
62
62
  export type RequestClaim = CallRequestClaim | WaitRequestClaim | TellRequestClaim | KillRequestClaim | DeliverRequestClaim | ReviewRequestClaim | TaskRequestClaim;
63
- export type StructuralRequestClaim = Omit<CallRequestClaim, "recipe"> & Readonly<{
63
+ export type StructuralRequestClaim = (Omit<CallRequestClaim, "recipe"> & Readonly<{
64
64
  recipe: unknown;
65
- }> | Exclude<RequestClaim, CallRequestClaim>;
65
+ }>) | Exclude<RequestClaim, CallRequestClaim>;
66
66
  export type UpstreamRequestFailure = Readonly<{
67
67
  kind: "akuma-not-born";
68
68
  id: AkuId;
@@ -3,7 +3,7 @@ import { rename, rm, writeFile } from "node:fs/promises";
3
3
  import { isAbsolute, join, resolve } from "node:path";
4
4
  import { decodeAllowedActions } from "./allowed.js";
5
5
  import { archetypeName, parseAkuId } from "./identity.js";
6
- import { decodeProviderOptions, decodeReadonlyRestraint, } from "./provider-recipe.js";
6
+ import { decodeProviderOptions, decodeReadonlyRestraint } from "./provider-recipe.js";
7
7
  import { decodeProviderExecution } from "./providers/index.js";
8
8
  import { decodeTaskMutationRequest, isTaskMutationAction, } from "../task/mutation.js";
9
9
  const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;
@@ -37,9 +37,7 @@ function canonicalTargets(value) {
37
37
  const ids = [];
38
38
  for (const item of value) {
39
39
  const id = canonicalAkuId(item);
40
- if (id === null
41
- || (ids.length > 0
42
- && Buffer.compare(Buffer.from(ids.at(-1)), Buffer.from(id)) >= 0))
40
+ if (id === null || (ids.length > 0 && Buffer.compare(Buffer.from(ids.at(-1)), Buffer.from(id)) >= 0))
43
41
  return null;
44
42
  ids.push(id);
45
43
  }
@@ -56,10 +54,9 @@ export function decodeRecipe(value) {
56
54
  ...(recipe.description === undefined ? [] : ["description"]),
57
55
  ...(recipe.readonly === undefined ? [] : ["readonly"]),
58
56
  ];
59
- if (!exactKeys(recipe, expected)
60
- || (recipe.description !== undefined
61
- && (typeof recipe.description !== "string"
62
- || recipe.description.trim().length === 0)))
57
+ if (!exactKeys(recipe, expected) ||
58
+ (recipe.description !== undefined &&
59
+ (typeof recipe.description !== "string" || recipe.description.trim().length === 0)))
63
60
  return null;
64
61
  try {
65
62
  const options = decodeProviderOptions(recipe.options);
@@ -82,17 +79,11 @@ function contractId(value) {
82
79
  return typeof value === "string" && /^kei\/[^/\s]+$/u.test(value) ? value : null;
83
80
  }
84
81
  function decodeCall(id, payload) {
85
- const expected = [
86
- "archetype",
87
- "body",
88
- "recipe",
89
- "world",
90
- ...(payload.cwd === undefined ? [] : ["cwd"]),
91
- ];
92
- if (!exactKeys(payload, expected)
93
- || typeof payload.body !== "string"
94
- || !absolute(payload.world)
95
- || (payload.cwd !== undefined && !absolute(payload.cwd)))
82
+ const expected = ["archetype", "body", "recipe", "world", ...(payload.cwd === undefined ? [] : ["cwd"])];
83
+ if (!exactKeys(payload, expected) ||
84
+ typeof payload.body !== "string" ||
85
+ !absolute(payload.world) ||
86
+ (payload.cwd !== undefined && !absolute(payload.cwd)))
96
87
  return null;
97
88
  try {
98
89
  archetypeName(payload.archetype);
@@ -112,42 +103,29 @@ function decodeCall(id, payload) {
112
103
  }
113
104
  function decodeWait(id, payload) {
114
105
  const targets = canonicalTargets(payload.targets);
115
- const expected = [
116
- "completion",
117
- "targets",
118
- ...(payload.timeoutMs === undefined ? [] : ["timeoutMs"]),
119
- ];
120
- if (!exactKeys(payload, expected)
121
- || targets === null
122
- || (payload.completion !== "any" && payload.completion !== "all")
123
- || (payload.timeoutMs !== undefined
124
- && (!Number.isSafeInteger(payload.timeoutMs)
125
- || payload.timeoutMs < 0)))
106
+ const expected = ["completion", "targets", ...(payload.timeoutMs === undefined ? [] : ["timeoutMs"])];
107
+ if (!exactKeys(payload, expected) ||
108
+ targets === null ||
109
+ (payload.completion !== "any" && payload.completion !== "all") ||
110
+ (payload.timeoutMs !== undefined && (!Number.isSafeInteger(payload.timeoutMs) || payload.timeoutMs < 0)))
126
111
  return null;
127
112
  return {
128
113
  id,
129
114
  action: "akuma.wait",
130
115
  targets,
131
116
  completion: payload.completion,
132
- ...(payload.timeoutMs === undefined
133
- ? {}
134
- : { timeoutMs: payload.timeoutMs }),
117
+ ...(payload.timeoutMs === undefined ? {} : { timeoutMs: payload.timeoutMs }),
135
118
  };
136
119
  }
137
120
  function decodeTell(id, payload) {
138
121
  const target = canonicalAkuId(payload.target);
139
- return exactKeys(payload, ["body", "target"])
140
- && target !== null
141
- && typeof payload.body === "string"
122
+ return exactKeys(payload, ["body", "target"]) && target !== null && typeof payload.body === "string"
142
123
  ? { id, action: "akuma.tell", target, body: payload.body }
143
124
  : null;
144
125
  }
145
126
  function decodeKill(id, payload) {
146
127
  const targets = canonicalTargets(payload.targets);
147
- return exactKeys(payload, ["targets"])
148
- && targets !== null
149
- ? { id, action: "akuma.kill", targets }
150
- : null;
128
+ return exactKeys(payload, ["targets"]) && targets !== null ? { id, action: "akuma.kill", targets } : null;
151
129
  }
152
130
  function decodeDeliver(id, payload) {
153
131
  const valid = exactKeys(payload, [
@@ -158,14 +136,12 @@ function decodeDeliver(id, payload) {
158
136
  ...(payload.message === undefined ? [] : ["message"]),
159
137
  ]);
160
138
  const selected = contractId(payload.contractId);
161
- return valid
162
- && selected !== null
163
- && absolute(payload.repoRoot)
164
- && typeof payload.includeDirty === "boolean"
165
- && typeof payload.materializeConflict === "boolean"
166
- && (payload.message === undefined
167
- || (typeof payload.message === "string"
168
- && payload.message.trim().length > 0))
139
+ return valid &&
140
+ selected !== null &&
141
+ absolute(payload.repoRoot) &&
142
+ typeof payload.includeDirty === "boolean" &&
143
+ typeof payload.materializeConflict === "boolean" &&
144
+ (payload.message === undefined || (typeof payload.message === "string" && payload.message.trim().length > 0))
169
145
  ? {
170
146
  id,
171
147
  action: "contract.deliver",
@@ -173,9 +149,7 @@ function decodeDeliver(id, payload) {
173
149
  contractId: selected,
174
150
  includeDirty: payload.includeDirty,
175
151
  materializeConflict: payload.materializeConflict,
176
- ...(payload.message === undefined
177
- ? {}
178
- : { message: payload.message }),
152
+ ...(payload.message === undefined ? {} : { message: payload.message }),
179
153
  }
180
154
  : null;
181
155
  }
@@ -187,29 +161,23 @@ function decodeReview(id, payload) {
187
161
  ...(payload.summary === undefined ? [] : ["summary"]),
188
162
  ]);
189
163
  const selected = contractId(payload.contractId);
190
- return valid
191
- && selected !== null
192
- && absolute(payload.repoRoot)
193
- && (payload.verdict === "satisfied" || payload.verdict === "unsatisfied")
194
- && (payload.summary === undefined
195
- || (typeof payload.summary === "string"
196
- && payload.summary.trim().length > 0))
164
+ return valid &&
165
+ selected !== null &&
166
+ absolute(payload.repoRoot) &&
167
+ (payload.verdict === "satisfied" || payload.verdict === "unsatisfied") &&
168
+ (payload.summary === undefined || (typeof payload.summary === "string" && payload.summary.trim().length > 0))
197
169
  ? {
198
170
  id,
199
171
  action: "contract.review",
200
172
  repoRoot: payload.repoRoot,
201
173
  contractId: selected,
202
174
  verdict: payload.verdict,
203
- ...(payload.summary === undefined
204
- ? {}
205
- : { summary: payload.summary }),
175
+ ...(payload.summary === undefined ? {} : { summary: payload.summary }),
206
176
  }
207
177
  : null;
208
178
  }
209
179
  function decodeTask(id, action, payload) {
210
- if (!isTaskMutationAction(action)
211
- || !exactKeys(payload, ["request", "world"])
212
- || !absolute(payload.world))
180
+ if (!isTaskMutationAction(action) || !exactKeys(payload, ["request", "world"]) || !absolute(payload.world))
213
181
  return null;
214
182
  try {
215
183
  return {
@@ -240,11 +208,11 @@ export function decodeClaim(bytes, fileId) {
240
208
  return null;
241
209
  }
242
210
  const value = object(decoded);
243
- if (value === null
244
- || !exactKeys(value, ["action", "id", "payload"])
245
- || value.id !== fileId
246
- || typeof value.id !== "string"
247
- || !UUID.test(value.id))
211
+ if (value === null ||
212
+ !exactKeys(value, ["action", "id", "payload"]) ||
213
+ value.id !== fileId ||
214
+ typeof value.id !== "string" ||
215
+ !UUID.test(value.id))
248
216
  return null;
249
217
  const payload = object(value.payload);
250
218
  if (payload === null || typeof value.action !== "string")
@@ -258,54 +226,59 @@ function outcome(value) {
258
226
  return { kind: input.kind, result: input.result };
259
227
  }
260
228
  const failure = object(input?.failure);
261
- if (input?.kind !== "failed"
262
- || !exactKeys(input, ["failure", "kind"])
263
- || failure === null)
229
+ if (input?.kind !== "failed" || !exactKeys(input, ["failure", "kind"]) || failure === null)
264
230
  return null;
265
231
  if (failure.kind === "akuma-not-born" && exactKeys(failure, ["id", "kind"])) {
266
232
  const id = canonicalAkuId(failure.id);
267
- return id === null
268
- ? null
269
- : { kind: input.kind, failure: { kind: failure.kind, id } };
233
+ return id === null ? null : { kind: input.kind, failure: { kind: failure.kind, id } };
270
234
  }
271
- return failure.kind === "failed" && exactKeys(failure, ["diagnostic", "kind"]) && typeof failure.diagnostic === "string"
272
- ? { kind: input.kind, failure: { kind: failure.kind, diagnostic: failure.diagnostic } } : null;
235
+ return failure.kind === "failed" &&
236
+ exactKeys(failure, ["diagnostic", "kind"]) &&
237
+ typeof failure.diagnostic === "string"
238
+ ? { kind: input.kind, failure: { kind: failure.kind, diagnostic: failure.diagnostic } }
239
+ : null;
273
240
  }
274
241
  function envelope(value, id, action) {
275
- if (value.state === "refused"
276
- && exactKeys(value, ["action", "diagnostic", "id", "state"])
277
- && typeof value.diagnostic === "string") {
242
+ if (value.state === "refused" &&
243
+ exactKeys(value, ["action", "diagnostic", "id", "state"]) &&
244
+ typeof value.diagnostic === "string") {
278
245
  return { id, action, state: value.state, diagnostic: value.diagnostic };
279
246
  }
280
- if (value.state === "voided"
281
- && exactKeys(value, ["action", "evidence", "id", "state"])
282
- && typeof value.evidence === "string") {
247
+ if (value.state === "voided" &&
248
+ exactKeys(value, ["action", "evidence", "id", "state"]) &&
249
+ typeof value.evidence === "string") {
283
250
  return { id, action, state: value.state, evidence: value.evidence };
284
251
  }
285
- if (action !== "akuma.call"
286
- && value.state === "served"
287
- && exactKeys(value, ["action", "id", "outcome", "state"])) {
252
+ if (action !== "akuma.call" && value.state === "served" && exactKeys(value, ["action", "id", "outcome", "state"])) {
288
253
  const decoded = outcome(value.outcome);
289
- return decoded === null
290
- ? null
291
- : { id, action, state: value.state, outcome: decoded };
254
+ return decoded === null ? null : { id, action, state: value.state, outcome: decoded };
292
255
  }
293
256
  return null;
294
257
  }
295
258
  function reference(value, action) {
296
259
  const input = object(value);
297
260
  const field = action === "contract.deliver" ? "deliveryFactId" : "reviewFactId";
298
- if (input === null
299
- || !exactKeys(input, ["contractId", field, "kind", "repoRoot"])
300
- || input.kind !== "accepted-reference"
301
- || !absolute(input.repoRoot)
302
- || contractId(input.contractId) === null
303
- || typeof input[field] !== "string"
304
- || input[field].trim().length === 0)
261
+ if (input === null ||
262
+ !exactKeys(input, ["contractId", field, "kind", "repoRoot"]) ||
263
+ input.kind !== "accepted-reference" ||
264
+ !absolute(input.repoRoot) ||
265
+ contractId(input.contractId) === null ||
266
+ typeof input[field] !== "string" ||
267
+ input[field].trim().length === 0)
305
268
  return null;
306
269
  return action === "contract.deliver"
307
- ? { kind: input.kind, repoRoot: input.repoRoot, contractId: input.contractId, deliveryFactId: input.deliveryFactId }
308
- : { kind: input.kind, repoRoot: input.repoRoot, contractId: input.contractId, reviewFactId: input.reviewFactId };
270
+ ? {
271
+ kind: input.kind,
272
+ repoRoot: input.repoRoot,
273
+ contractId: input.contractId,
274
+ deliveryFactId: input.deliveryFactId,
275
+ }
276
+ : {
277
+ kind: input.kind,
278
+ repoRoot: input.repoRoot,
279
+ contractId: input.contractId,
280
+ reviewFactId: input.reviewFactId,
281
+ };
309
282
  }
310
283
  function decodeCallReceipt(value, id) {
311
284
  if (value.state !== "served" || !exactKeys(value, ["action", "child", "id", "state"]))
@@ -327,10 +300,10 @@ function decodeTaskReceipt(value, id, action) {
327
300
  if (value.state !== "served" || !exactKeys(value, ["action", "id", "reference", "state"]))
328
301
  return null;
329
302
  const selected = object(value.reference);
330
- if (selected === null
331
- || !exactKeys(selected, ["action", "kind"])
332
- || selected.kind !== "served-reference"
333
- || selected.action !== action)
303
+ if (selected === null ||
304
+ !exactKeys(selected, ["action", "kind"]) ||
305
+ selected.kind !== "served-reference" ||
306
+ selected.action !== action)
334
307
  return null;
335
308
  return { id, action, state: value.state, reference: { kind: selected.kind, action } };
336
309
  }
@@ -4,7 +4,7 @@ import { abortableDelay } from "./abort.js";
4
4
  import { AKUMA_REQUESTS_ENV } from "./provider.js";
5
5
  import { absolute, atomicJson, decodeReceipt, receiptPath, requestPath, requestPayload, } from "./request-wire.js";
6
6
  import { isTaskMutationAction } from "../task/mutation.js";
7
- const POLL_MS = 25;
7
+ const POLL_MS = 100;
8
8
  export class AkumaBodyRequestError extends Error {
9
9
  outcome;
10
10
  diagnostic;
@@ -47,7 +47,7 @@ async function requestBody(input) {
47
47
  if (error.code !== "ENOENT")
48
48
  throw error;
49
49
  }
50
- if (!await access(input.directory).then(() => true, () => false)) {
50
+ if (!(await access(input.directory).then(() => true, () => false))) {
51
51
  throw new AkumaBodyRequestError("voided", "parent request channel closed before a receipt");
52
52
  }
53
53
  await abortableDelay(POLL_MS, input.signal);
@@ -1,8 +1,8 @@
1
- import { runAkumaBody } from "./akuma/body.js";
1
+ import { LEASH_HELD_EXIT, runAkumaBody } from "./akuma/body.js";
2
2
  import { worldRootForAkumaPaths } from "./akuma/identity.js";
3
- import { executeKillAkuma, executeTellAkuma, executeWaitAkuma, } from "./library/fleet.js";
4
- import { requireBranchesToBeUpToDateFrom, worktreeHooksFrom, } from "./library/configuration.js";
5
- import { executeForwardedDeliver, executeForwardedReview, } from "./library/contract.js";
3
+ import { executeKillAkuma, executeTellAkuma, executeWaitAkuma } from "./library/fleet.js";
4
+ import { requireBranchesToBeUpToDateFrom, worktreeHooksFrom } from "./library/configuration.js";
5
+ import { executeForwardedDeliver, executeForwardedReview } from "./library/contract.js";
6
6
  import { Repo } from "./library/repo.js";
7
7
  import { settings } from "./settings.js";
8
8
  import { executeTaskMutation } from "./task/mutation.js";
@@ -95,4 +95,5 @@ const configuration = {
95
95
  ...(mappedHome === undefined || mappedHome.length === 0 ? {} : { home: mappedHome }),
96
96
  ...(mappedGitPath === undefined ? {} : { gitPath: mappedGitPath }),
97
97
  };
98
- await runAkumaBody(launch, upstreamFor(launch, configuration));
98
+ if ((await runAkumaBody(launch, upstreamFor(launch, configuration))) === "held")
99
+ process.exitCode = LEASH_HELD_EXIT;
@@ -1,2 +1,5 @@
1
1
  import type { DecodedContractDocument } from "./types.js";
2
- export declare function applyAmendDocument(source: string, current: DecodedContractDocument): string;
2
+ export declare function applyAmendDocument(source: string, current: DecodedContractDocument): Readonly<{
3
+ document: string;
4
+ changedSections: ReadonlySet<string>;
5
+ }>;
@@ -1,6 +1,6 @@
1
1
  import { decodeVerificationDeclarations, VerificationDocumentError } from "./verification.js";
2
2
  import { parseToAST } from "../markdown/parse.js";
3
- import { directChildren, indexDocument, indexedHeadings, normalizeTitle, rawSlice, sectionContent } from "../markdown/query.js";
3
+ import { directChildren, indexDocument, indexedHeadings, normalizeTitle, rawSlice, sectionContent, } from "../markdown/query.js";
4
4
  import { decodeRegion, RegionDocumentError } from "./region.js";
5
5
  import { contractSectionName, RESERVED_SECTIONS } from "./shape.js";
6
6
  import { renderAmendedContractBody } from "./render.js";
@@ -11,8 +11,7 @@ function nonblank(document, node) {
11
11
  return rawSlice(document, node.span).trim().length > 0;
12
12
  }
13
13
  function sections(document) {
14
- return indexedHeadings(indexDocument(document), { level: 2 })
15
- .filter((node) => node.type === "section");
14
+ return indexedHeadings(indexDocument(document), { level: 2 }).filter((node) => node.type === "section");
16
15
  }
17
16
  function operationSections(document) {
18
17
  if (document.frontmatter !== undefined)
@@ -59,7 +58,10 @@ function criteria(document, section) {
59
58
  if (title.length === 0 || seen.has(key))
60
59
  refusal("criteria operation contains duplicate or empty titles");
61
60
  seen.add(key);
62
- const body = rawSlice(document, { start: heading.span.end, end: headings[index + 1]?.span.start ?? section.span.end });
61
+ const body = rawSlice(document, {
62
+ start: heading.span.end,
63
+ end: headings[index + 1]?.span.start ?? section.span.end,
64
+ });
63
65
  if (body.trim().length === 0)
64
66
  refusal(`criterion '${title}' operation body is empty`);
65
67
  return { title, body };
@@ -151,15 +153,6 @@ function applyRemove(body, operation, document) {
151
153
  body.extensionIndexes.delete(normalizeTitle(operation.target));
152
154
  }
153
155
  function applyUpdate(body, operation, document) {
154
- if (operation.target.startsWith("Criterion ")) {
155
- const title = operation.target.slice("Criterion ".length);
156
- const index = criterionIndex(body, title);
157
- if (index < 0)
158
- refusal(`unknown criterion '${title}'`);
159
- const criterion = body.criteria[index];
160
- body.criteria[index] = { ...criterion, body: prose(document, operation.section, "criterion") };
161
- return;
162
- }
163
156
  const index = extensionIndex(body, operation.target);
164
157
  if (index < 0)
165
158
  refusal(`unknown extension '${operation.target}'`);
@@ -210,7 +203,10 @@ function applyAppend(body, operation, document) {
210
203
  if (index < 0)
211
204
  refusal(`unknown extension '${operation.target}'`);
212
205
  const extension = body.extensions[index];
213
- body.extensions[index] = { ...extension, content: appendText(extension.content, prose(document, operation.section, "extension")) };
206
+ body.extensions[index] = {
207
+ ...extension,
208
+ content: appendText(extension.content, prose(document, operation.section, "extension")),
209
+ };
214
210
  }
215
211
  function applyReplace(body, operation, document) {
216
212
  const target = contractSectionName(operation.target);
@@ -285,5 +281,8 @@ function apply(source, current) {
285
281
  }
286
282
  export function applyAmendDocument(source, current) {
287
283
  const result = apply(source, current);
288
- return renderAmendedContractBody(current.document.bytes, result.body, result.changed);
284
+ return {
285
+ document: renderAmendedContractBody(current.document.bytes, result.body, result.changed),
286
+ changedSections: result.changed,
287
+ };
289
288
  }
@@ -1,6 +1,6 @@
1
1
  import { mintDocumentKey, mintDocumentSegmentKey } from "./keys.js";
2
2
  import { decodeDocumentEnvelope } from "./envelope.js";
3
- import { directChildren, normalizeTitle, rawSlice, sectionContent, } from "../markdown/query.js";
3
+ import { directChildren, normalizeTitle, rawSlice, sectionContent } from "../markdown/query.js";
4
4
  import { CONTRACT_SECTIONS, RESERVED_SECTIONS } from "./shape.js";
5
5
  import { decodeRegion, RegionDocumentError } from "./region.js";
6
6
  import { decodeVerificationDeclarations, VerificationDocumentError } from "./verification.js";
@@ -103,9 +103,7 @@ export function decodeContractDocument(source) {
103
103
  ...body,
104
104
  document: { bytes: source, key: mintDocumentKey(source) },
105
105
  segments,
106
- verificationSegment: verificationSection === undefined
107
- ? null
108
- : mintDocumentSegmentKey(document.source, verificationSection.span),
106
+ verificationSegment: verificationSection === undefined ? null : mintDocumentSegmentKey(document.source, verificationSection.span),
109
107
  };
110
108
  }
111
109
  export function verificationDefinition(document) {
@@ -7,15 +7,13 @@ function nonblankRaw(document, node) {
7
7
  return rawSlice(document, node.span).trim().length > 0;
8
8
  }
9
9
  function topLevelSections(document) {
10
- return indexedHeadings(indexDocument(document), { level: 2 })
11
- .filter((node) => node.type === "section");
10
+ return indexedHeadings(indexDocument(document), { level: 2 }).filter((node) => node.type === "section");
12
11
  }
13
12
  export function decodeDocumentEnvelope(source, kind) {
14
13
  const document = parseToAST(source);
15
14
  if (document.frontmatter !== undefined)
16
15
  refusal(`${kind} document may not contain frontmatter`);
17
- const titles = indexedHeadings(indexDocument(document), { level: 1 })
18
- .filter((node) => node.type === "section");
16
+ const titles = indexedHeadings(indexDocument(document), { level: 1 }).filter((node) => node.type === "section");
19
17
  if (titles.length !== 1)
20
18
  refusal(`${kind} document requires exactly one H1 title`);
21
19
  const title = titles[0];
@@ -2,7 +2,6 @@ import type { DocumentNode, SectionNode } from "../markdown/types.js";
2
2
  export declare class RegionDocumentError extends Error {
3
3
  constructor(message: string);
4
4
  }
5
- export declare function assertCanonicalRegionPath(path: string): void;
5
+ export declare function assertRegionPattern(pattern: string): string;
6
6
  export declare function decodeRegion(document: DocumentNode, section: SectionNode): readonly string[];
7
7
  export declare function regionsOverlap(mine: readonly string[], theirs: readonly string[]): readonly [string, string][];
8
- export declare function regionPatternsMatchPath(patterns: readonly string[], path: string): readonly string[];