@astrosheep/keiyaku 4.1.0 → 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 (241) 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 +8 -5
  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.js +11 -5
  33. package/build/src/akuma/provider.js +105 -62
  34. package/build/src/akuma/providers/acp/config.js +5 -6
  35. package/build/src/akuma/providers/acp/core.js +17 -10
  36. package/build/src/akuma/providers/acp/events.js +38 -29
  37. package/build/src/akuma/providers/acp/index.js +13 -9
  38. package/build/src/akuma/providers/claude/events.js +8 -12
  39. package/build/src/akuma/providers/claude/index.d.ts +1 -0
  40. package/build/src/akuma/providers/claude/index.js +55 -26
  41. package/build/src/akuma/providers/claude/input.js +6 -2
  42. package/build/src/akuma/providers/codex-app-server/events.js +61 -36
  43. package/build/src/akuma/providers/codex-app-server/index.js +25 -13
  44. package/build/src/akuma/providers/grok-build/index.js +22 -25
  45. package/build/src/akuma/providers/index.js +2 -18
  46. package/build/src/akuma/providers/opencode-sdk/events.js +32 -18
  47. package/build/src/akuma/providers/opencode-sdk/index.js +26 -17
  48. package/build/src/akuma/providers/opencode-sdk/session.js +21 -5
  49. package/build/src/akuma/providers/pi/events.js +26 -19
  50. package/build/src/akuma/providers/pi/index.js +58 -40
  51. package/build/src/akuma/publication.js +9 -9
  52. package/build/src/akuma/request-serve.js +37 -40
  53. package/build/src/akuma/request-wire.d.ts +2 -2
  54. package/build/src/akuma/request-wire.js +75 -102
  55. package/build/src/akuma/requests.js +2 -2
  56. package/build/src/akuma-body.js +6 -5
  57. package/build/src/body/amend.d.ts +4 -1
  58. package/build/src/body/amend.js +14 -6
  59. package/build/src/body/decode.js +2 -4
  60. package/build/src/body/envelope.js +2 -4
  61. package/build/src/body/region.d.ts +1 -2
  62. package/build/src/body/region.js +2 -70
  63. package/build/src/body/render.js +17 -12
  64. package/build/src/body/shape.js +1 -7
  65. package/build/src/cli/accepted.d.ts +1 -1
  66. package/build/src/cli/accepted.js +8 -1
  67. package/build/src/cli/commands/akuma-invoke.js +18 -6
  68. package/build/src/cli/commands/akuma.js +10 -13
  69. package/build/src/cli/commands/amend.d.ts +2 -2
  70. package/build/src/cli/commands/amend.js +2 -4
  71. package/build/src/cli/commands/bind.d.ts +4 -4
  72. package/build/src/cli/commands/bind.js +16 -6
  73. package/build/src/cli/commands/contract.d.ts +97 -10
  74. package/build/src/cli/commands/contract.js +110 -16
  75. package/build/src/cli/commands/install.d.ts +1 -1
  76. package/build/src/cli/commands/install.js +23 -15
  77. package/build/src/cli/commands/task-invoke.js +187 -67
  78. package/build/src/cli/commands/task-query.js +48 -24
  79. package/build/src/cli/commands/task.js +150 -38
  80. package/build/src/cli/coordinates.js +2 -4
  81. package/build/src/cli/invoke.js +88 -44
  82. package/build/src/cli/main.js +4 -2
  83. package/build/src/cli/parse.d.ts +2 -89
  84. package/build/src/cli/parse.js +86 -78
  85. package/build/src/cli/render/akuma-tool-command.js +6 -7
  86. package/build/src/cli/render/akuma-tool.js +10 -8
  87. package/build/src/cli/render/akuma.js +125 -60
  88. package/build/src/cli/render/audit.js +5 -15
  89. package/build/src/cli/render/board.d.ts +1 -0
  90. package/build/src/cli/render/board.js +17 -0
  91. package/build/src/cli/render/catalog.js +81 -8
  92. package/build/src/cli/render/contract-observation.d.ts +10 -0
  93. package/build/src/cli/render/contract-observation.js +58 -0
  94. package/build/src/cli/render/contract.js +42 -61
  95. package/build/src/cli/render/kanshi.js +239 -215
  96. package/build/src/cli/render/receipt.js +2 -9
  97. package/build/src/cli/render/refusal.js +10 -15
  98. package/build/src/cli/render/region.js +22 -6
  99. package/build/src/cli/render/settings.js +4 -4
  100. package/build/src/cli/render/task.js +34 -14
  101. package/build/src/cli/render/terminal.js +16 -5
  102. package/build/src/cli/result.d.ts +3 -3
  103. package/build/src/cli/runtime.d.ts +6 -1
  104. package/build/src/cli/runtime.js +84 -63
  105. package/build/src/cli/selectors.js +2 -4
  106. package/build/src/cli/usage.js +6 -5
  107. package/build/src/contract-worktree.d.ts +1 -23
  108. package/build/src/contract-worktree.js +79 -155
  109. package/build/src/coordination/durable-file.js +7 -3
  110. package/build/src/coordination/sqlite-transaction-lock.js +29 -12
  111. package/build/src/core/facts/codec.js +7 -3
  112. package/build/src/core/facts/types.d.ts +1 -1
  113. package/build/src/core/subject.js +16 -9
  114. package/build/src/core/verbs/abandon.d.ts +1 -1
  115. package/build/src/core/verbs/abandon.js +1 -1
  116. package/build/src/core/verbs/amend.d.ts +1 -1
  117. package/build/src/core/verbs/amend.js +7 -7
  118. package/build/src/core/verbs/attestation.js +4 -1
  119. package/build/src/core/verbs/bind.d.ts +1 -1
  120. package/build/src/core/verbs/bind.js +1 -1
  121. package/build/src/core/verbs/placement.d.ts +1 -1
  122. package/build/src/core/verbs/placement.js +10 -8
  123. package/build/src/dispatch/index.js +8 -6
  124. package/build/src/duration.js +5 -1
  125. package/build/src/git/admission.js +5 -3
  126. package/build/src/git/hooks.d.ts +8 -0
  127. package/build/src/git/hooks.js +63 -14
  128. package/build/src/git/identity.js +1 -4
  129. package/build/src/git/integration.d.ts +2 -3
  130. package/build/src/git/integration.js +32 -39
  131. package/build/src/git/nuke.d.ts +1 -1
  132. package/build/src/git/nuke.js +110 -57
  133. package/build/src/git/observe.d.ts +13 -1
  134. package/build/src/git/observe.js +51 -44
  135. package/build/src/git/process.js +4 -2
  136. package/build/src/git/read-observation.js +10 -8
  137. package/build/src/git/reconcile.d.ts +14 -1
  138. package/build/src/git/reconcile.js +121 -69
  139. package/build/src/git/repository.d.ts +2 -0
  140. package/build/src/git/repository.js +13 -22
  141. package/build/src/git/target-placement.d.ts +9 -10
  142. package/build/src/git/target-placement.js +59 -62
  143. package/build/src/git/tender.js +13 -46
  144. package/build/src/git/terminal-seal.js +15 -12
  145. package/build/src/git/tree.js +5 -2
  146. package/build/src/git/workspace.d.ts +24 -2
  147. package/build/src/git/workspace.js +120 -16
  148. package/build/src/identity/coordinates.js +3 -1
  149. package/build/src/identity/selector.js +6 -3
  150. package/build/src/kanshi/fleet.d.ts +6 -0
  151. package/build/src/kanshi/fleet.js +27 -0
  152. package/build/src/kanshi/index.d.ts +1 -1
  153. package/build/src/kanshi/read.js +60 -48
  154. package/build/src/kanshi/report.d.ts +11 -23
  155. package/build/src/kanshi/select.js +25 -24
  156. package/build/src/library/address.d.ts +2 -1
  157. package/build/src/library/address.js +7 -8
  158. package/build/src/library/akuma-creation.js +20 -12
  159. package/build/src/library/audit.d.ts +0 -1
  160. package/build/src/library/audit.js +1 -2
  161. package/build/src/library/bind.d.ts +53 -5
  162. package/build/src/library/bind.js +98 -22
  163. package/build/src/library/catalog.d.ts +1 -0
  164. package/build/src/library/catalog.js +6 -3
  165. package/build/src/library/configuration.js +3 -1
  166. package/build/src/library/continuation.d.ts +15 -4
  167. package/build/src/library/continuation.js +24 -16
  168. package/build/src/library/contract.d.ts +33 -43
  169. package/build/src/library/contract.js +138 -140
  170. package/build/src/library/fleet.d.ts +1 -1
  171. package/build/src/library/fleet.js +19 -11
  172. package/build/src/library/input.d.ts +2 -0
  173. package/build/src/library/input.js +14 -0
  174. package/build/src/library/keiyaku.d.ts +8 -7
  175. package/build/src/library/keiyaku.js +3 -3
  176. package/build/src/library/nuke.js +14 -5
  177. package/build/src/library/reconcile.d.ts +9 -4
  178. package/build/src/library/reconcile.js +30 -24
  179. package/build/src/library/refusal.d.ts +13 -5
  180. package/build/src/library/refusal.js +7 -0
  181. package/build/src/library/region.d.ts +8 -7
  182. package/build/src/library/region.js +31 -11
  183. package/build/src/library/repo.js +2 -2
  184. package/build/src/markdown/lex.js +9 -2
  185. package/build/src/markdown/parse.js +11 -7
  186. package/build/src/markdown/query.js +4 -2
  187. package/build/src/protocol/amend.js +3 -1
  188. package/build/src/protocol/attempt.d.ts +7 -3
  189. package/build/src/protocol/attempt.js +9 -5
  190. package/build/src/protocol/audit.d.ts +1 -1
  191. package/build/src/protocol/audit.js +4 -14
  192. package/build/src/protocol/bind.d.ts +19 -6
  193. package/build/src/protocol/bind.js +28 -13
  194. package/build/src/protocol/completion.d.ts +0 -1
  195. package/build/src/protocol/completion.js +1 -3
  196. package/build/src/protocol/deliver.d.ts +1 -3
  197. package/build/src/protocol/deliver.js +15 -39
  198. package/build/src/protocol/intent.d.ts +1 -0
  199. package/build/src/protocol/intent.js +9 -7
  200. package/build/src/protocol/operations.d.ts +3 -7
  201. package/build/src/protocol/operations.js +5 -3
  202. package/build/src/protocol/placement.d.ts +0 -1
  203. package/build/src/protocol/placement.js +6 -6
  204. package/build/src/protocol/read/observation.d.ts +11 -0
  205. package/build/src/protocol/read/observation.js +37 -0
  206. package/build/src/protocol/read/status.d.ts +23 -12
  207. package/build/src/protocol/read/status.js +90 -72
  208. package/build/src/protocol/reconcile.d.ts +1 -0
  209. package/build/src/protocol/reconcile.js +2 -3
  210. package/build/src/protocol/reintegrate.js +1 -1
  211. package/build/src/protocol/review.d.ts +0 -1
  212. package/build/src/protocol/review.js +15 -22
  213. package/build/src/protocol/run.d.ts +1 -0
  214. package/build/src/protocol/run.js +4 -5
  215. package/build/src/runtime/proc/launch.d.ts +33 -0
  216. package/build/src/runtime/proc/launch.js +98 -0
  217. package/build/src/runtime/proc/line-rpc.js +9 -3
  218. package/build/src/runtime/proc/run.d.ts +12 -6
  219. package/build/src/runtime/proc/run.js +78 -21
  220. package/build/src/runtime/proc/stdio.js +7 -10
  221. package/build/src/settings.js +6 -2
  222. package/build/src/settlement/holder.js +13 -10
  223. package/build/src/settlement/settle.js +39 -6
  224. package/build/src/task/board.js +12 -6
  225. package/build/src/task/compose.js +85 -22
  226. package/build/src/task/context.js +21 -8
  227. package/build/src/task/document.js +46 -10
  228. package/build/src/task/identity.js +5 -2
  229. package/build/src/task/index.d.ts +0 -1
  230. package/build/src/task/index.js +119 -34
  231. package/build/src/task/input.js +29 -7
  232. package/build/src/task/mutation.js +61 -19
  233. package/build/src/task/operations.d.ts +6 -1
  234. package/build/src/task/operations.js +83 -29
  235. package/build/src/task/query.js +55 -26
  236. package/build/src/task/store.d.ts +3 -1
  237. package/build/src/task/store.js +81 -17
  238. package/build/src/verification/execution.js +14 -11
  239. package/build/src/workspace-place.js +19 -7
  240. package/build/src/world.js +16 -6
  241. package/package.json +8 -3
@@ -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 };
@@ -201,7 +203,10 @@ function applyAppend(body, operation, document) {
201
203
  if (index < 0)
202
204
  refusal(`unknown extension '${operation.target}'`);
203
205
  const extension = body.extensions[index];
204
- 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
+ };
205
210
  }
206
211
  function applyReplace(body, operation, document) {
207
212
  const target = contractSectionName(operation.target);
@@ -276,5 +281,8 @@ function apply(source, current) {
276
281
  }
277
282
  export function applyAmendDocument(source, current) {
278
283
  const result = apply(source, current);
279
- 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
+ };
280
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[];
@@ -39,68 +39,8 @@ function compileRegionPattern(pattern) {
39
39
  const canonical = directory ? [...segments.slice(0, -1), "**"] : segments;
40
40
  return { source, segments: canonical.map((segment) => compileSegment(segment, pattern)) };
41
41
  }
42
- export function assertCanonicalRegionPath(path) {
43
- if (path.length === 0 || /[\r\n\0]/u.test(path) || path.startsWith("/") || path.endsWith("/")) {
44
- refusal(`Region path '${path}' must be a canonical repository-relative path`);
45
- }
46
- if (path.split("/").some((segment) => segment.length === 0 || segment === "." || segment === "..")) {
47
- refusal(`Region path '${path}' must be a canonical repository-relative path`);
48
- }
49
- }
50
- function segmentMatchesPath(pattern, path) {
51
- const queue = [[0, 0]];
52
- const visited = new Set();
53
- let cursor = 0;
54
- while (cursor < queue.length) {
55
- const [patternIndex, pathIndex] = queue[cursor++];
56
- const key = `${patternIndex}:${pathIndex}`;
57
- if (visited.has(key))
58
- continue;
59
- visited.add(key);
60
- if (patternIndex === pattern.length && pathIndex === path.length)
61
- return true;
62
- const character = pattern[patternIndex];
63
- if (character === "*") {
64
- queue.push([patternIndex + 1, pathIndex]);
65
- if (pathIndex < path.length)
66
- queue.push([patternIndex, pathIndex + 1]);
67
- continue;
68
- }
69
- if (character === "?") {
70
- if (pathIndex < path.length)
71
- queue.push([patternIndex + 1, pathIndex + 1]);
72
- continue;
73
- }
74
- if (character !== undefined && character === path[pathIndex])
75
- queue.push([patternIndex + 1, pathIndex + 1]);
76
- }
77
- return false;
78
- }
79
- function patternMatchesPath(pattern, path) {
80
- const queue = [[0, 0]];
81
- const visited = new Set();
82
- let cursor = 0;
83
- while (cursor < queue.length) {
84
- const [patternIndex, pathIndex] = queue[cursor++];
85
- const key = `${patternIndex}:${pathIndex}`;
86
- if (visited.has(key))
87
- continue;
88
- visited.add(key);
89
- if (patternIndex === pattern.length && pathIndex === path.length)
90
- return true;
91
- const segment = pattern[patternIndex];
92
- if (segment?.kind === "deep") {
93
- queue.push([patternIndex + 1, pathIndex]);
94
- if (pathIndex < path.length)
95
- queue.push([patternIndex, pathIndex + 1]);
96
- continue;
97
- }
98
- if (segment === undefined || path[pathIndex] === undefined)
99
- continue;
100
- if (segmentMatchesPath(segment.characters, Array.from(path[pathIndex])))
101
- queue.push([patternIndex + 1, pathIndex + 1]);
102
- }
103
- return false;
42
+ export function assertRegionPattern(pattern) {
43
+ return compileRegionPattern(pattern).source;
104
44
  }
105
45
  function segmentTransition(characters, index) {
106
46
  const character = characters[index];
@@ -199,11 +139,3 @@ export function regionsOverlap(mine, theirs) {
199
139
  }
200
140
  return overlaps;
201
141
  }
202
- export function regionPatternsMatchPath(patterns, path) {
203
- assertCanonicalRegionPath(path);
204
- const pathSegments = path.split("/");
205
- return patterns
206
- .map((pattern) => compileRegionPattern(pattern))
207
- .filter((pattern) => patternMatchesPath(pattern.segments, pathSegments))
208
- .map((pattern) => pattern.source);
209
- }
@@ -38,7 +38,9 @@ function arcSection(arc) {
38
38
  ].join("\n\n");
39
39
  }
40
40
  export function renderContractBody(body, currentArc) {
41
- const criteria = body.criteria.map((criterion) => `### ${criterion.title}\n\n${content(criterion.body)}`).join("\n\n");
41
+ const criteria = body.criteria
42
+ .map((criterion) => `### ${criterion.title}\n\n${content(criterion.body)}`)
43
+ .join("\n\n");
42
44
  const verification = body.verification.map(verificationFence).join("\n\n");
43
45
  return [
44
46
  `# ${body.title}`,
@@ -50,25 +52,28 @@ export function renderContractBody(body, currentArc) {
50
52
  ...(verification.length === 0 ? [] : [section(CONTRACT_SECTIONS.verification.title, verification)]),
51
53
  ...body.extensions.map((extension) => section(extension.title, extension.content)),
52
54
  ...(currentArc === undefined ? [] : [arcSection(currentArc)]),
53
- ].join("\n\n").concat("\n");
55
+ ]
56
+ .join("\n\n")
57
+ .concat("\n");
54
58
  }
55
59
  function sections(document) {
56
- return indexedHeadings(indexDocument(document), { level: 2 })
57
- .filter((node) => node.type === "section");
60
+ return indexedHeadings(indexDocument(document), { level: 2 }).filter((node) => node.type === "section");
58
61
  }
59
62
  export function renderAmendedContractBody(currentSource, body, changedSections) {
60
63
  const current = parseToAST(currentSource);
61
64
  const renderedSource = renderContractBody(body);
62
65
  const rendered = parseToAST(renderedSource);
63
66
  const currentSections = sections(current);
64
- const preserved = new Map(currentSections.map((node) => [
65
- normalizeTitle(node.title),
66
- rawSlice(current, node.span),
67
- ]));
67
+ const preserved = new Map(currentSections.map((node) => [normalizeTitle(node.title), rawSlice(current, node.span)]));
68
68
  const first = currentSections[0];
69
69
  const prefix = first === undefined ? currentSource : currentSource.slice(0, first.span.start);
70
- return prefix + sections(rendered).map((node) => {
71
- const name = normalizeTitle(node.title);
72
- return changedSections.has(name) ? rawSlice(rendered, node.span) : preserved.get(name) ?? rawSlice(rendered, node.span);
73
- }).join("");
70
+ return (prefix +
71
+ sections(rendered)
72
+ .map((node) => {
73
+ const name = normalizeTitle(node.title);
74
+ return changedSections.has(name)
75
+ ? rawSlice(rendered, node.span)
76
+ : (preserved.get(name) ?? rawSlice(rendered, node.span));
77
+ })
78
+ .join(""));
74
79
  }
@@ -6,13 +6,7 @@ export const CONTRACT_SECTIONS = {
6
6
  criteria: { title: "Criteria", required: true },
7
7
  verification: { title: "Verification", required: false },
8
8
  };
9
- export const RESERVED_SECTIONS = new Set([
10
- "gates",
11
- "pipeline",
12
- "after",
13
- "arc",
14
- "fulfillment",
15
- ]);
9
+ export const RESERVED_SECTIONS = new Set(["gates", "pipeline", "after", "arc", "fulfillment"]);
16
10
  export function contractSectionName(title) {
17
11
  for (const name of Object.keys(CONTRACT_SECTIONS)) {
18
12
  if (CONTRACT_SECTIONS[name].title === title)
@@ -6,7 +6,7 @@ type MutationCallOptions = Readonly<{
6
6
  projectRefusal?: (refusal: unknown) => unknown;
7
7
  }>;
8
8
  export declare function acceptedBind(result: BindResult, coordinates: Readonly<{
9
- workspace: "worktree" | "here";
9
+ workspace: "worktree";
10
10
  target?: string;
11
11
  }>): AcceptedBindResult;
12
12
  export declare function acceptedAmend(result: AmendResult, coordinate: ContractId): AcceptedAmendResult;
@@ -27,6 +27,13 @@ function acceptedRegion(result) {
27
27
  return { overlapFailure: result.overlapFailure };
28
28
  return { overlaps: result.overlaps };
29
29
  }
30
+ function acceptedAmendRegion(result) {
31
+ if (result.overlapFailure !== undefined)
32
+ return { overlapFailure: result.overlapFailure };
33
+ if (result.overlaps !== undefined)
34
+ return { overlaps: result.overlaps };
35
+ return {};
36
+ }
30
37
  export function acceptedBind(result, coordinates) {
31
38
  return {
32
39
  ...acceptedEnvelope(result, undefined),
@@ -41,7 +48,7 @@ export function acceptedAmend(result, coordinate) {
41
48
  ...acceptedEnvelope(result, coordinate),
42
49
  verb: "amend",
43
50
  diff: result.documentDiff,
44
- ...acceptedRegion(result),
51
+ ...acceptedAmendRegion(result),
45
52
  };
46
53
  }
47
54
  export function acceptedDeliver(result, coordinate) {