@astrosheep/keiyaku 4.5.7 → 4.5.8

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 (234) hide show
  1. package/README.md +10 -0
  2. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
  3. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
  4. package/build/integrations/marketplace/plugins/keiyaku/opencode.js +3 -2
  5. package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +10 -9
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +22 -1
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-babysit/SKILL.md +35 -96
  9. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +28 -49
  10. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +21 -15
  11. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +148 -89
  12. package/build/src/akuma/abort.d.ts +2 -1
  13. package/build/src/akuma/abort.js +6 -23
  14. package/build/src/akuma/akuma-handle.js +4 -2
  15. package/build/src/akuma/akuma-observe.d.ts +2 -0
  16. package/build/src/akuma/akuma-observe.js +1 -0
  17. package/build/src/akuma/akuma-product.js +9 -7
  18. package/build/src/akuma/akuma.d.ts +372 -9
  19. package/build/src/akuma/akuma.js +31 -1
  20. package/build/src/akuma/allowed.d.ts +1 -1
  21. package/build/src/akuma/allowed.js +1 -0
  22. package/build/src/akuma/body.d.ts +6 -4
  23. package/build/src/akuma/body.js +5 -3
  24. package/build/src/akuma/call-request.d.ts +80 -0
  25. package/build/src/akuma/call-request.js +211 -0
  26. package/build/src/akuma/heart/facts.d.ts +6 -78
  27. package/build/src/akuma/heart/index.d.ts +1 -1
  28. package/build/src/akuma/heart/request-authority.d.ts +5 -4
  29. package/build/src/akuma/heart/request-authority.js +20 -34
  30. package/build/src/akuma/heart/request-rows.js +12 -23
  31. package/build/src/akuma/heart/schema.d.ts +1 -1
  32. package/build/src/akuma/heart/schema.js +5 -13
  33. package/build/src/akuma/index.d.ts +1 -1
  34. package/build/src/akuma/index.js +1 -1
  35. package/build/src/akuma/projection-read.d.ts +1 -0
  36. package/build/src/akuma/projection-read.js +8 -1
  37. package/build/src/akuma/projection.d.ts +856 -137
  38. package/build/src/akuma/projection.js +190 -0
  39. package/build/src/akuma/provider.d.ts +30 -3
  40. package/build/src/akuma/provider.js +104 -0
  41. package/build/src/akuma/providers/acp/core.d.ts +2 -2
  42. package/build/src/akuma/providers/acp/core.js +13 -6
  43. package/build/src/akuma/providers/acp/index.js +5 -4
  44. package/build/src/akuma/providers/claude/index.d.ts +3 -3
  45. package/build/src/akuma/providers/claude/index.js +16 -5
  46. package/build/src/akuma/providers/codex-app-server/events.js +1 -1
  47. package/build/src/akuma/providers/codex-app-server/index.js +18 -6
  48. package/build/src/akuma/providers/grok-build/index.js +5 -4
  49. package/build/src/akuma/providers/opencode-sdk/index.js +66 -25
  50. package/build/src/akuma/providers/opencode-sdk/session.d.ts +3 -2
  51. package/build/src/akuma/providers/opencode-sdk/session.js +28 -11
  52. package/build/src/akuma/providers/pi/index.js +42 -14
  53. package/build/src/akuma/request-lifecycle.d.ts +3 -9
  54. package/build/src/akuma/request-lifecycle.js +4 -4
  55. package/build/src/akuma/request-rendezvous.d.ts +26 -0
  56. package/build/src/akuma/request-rendezvous.js +100 -0
  57. package/build/src/akuma/request-serve.d.ts +5 -65
  58. package/build/src/akuma/request-serve.js +81 -208
  59. package/build/src/akuma/request-wire.d.ts +109 -115
  60. package/build/src/akuma/request-wire.js +63 -318
  61. package/build/src/akuma/requests.d.ts +19 -47
  62. package/build/src/akuma/requests.js +51 -107
  63. package/build/src/akuma/turn-drive.d.ts +5 -3
  64. package/build/src/akuma/turn-drive.js +32 -10
  65. package/build/src/akuma-body.d.ts +7 -2
  66. package/build/src/akuma-body.js +68 -46
  67. package/build/src/cli/accepted.d.ts +1 -1
  68. package/build/src/cli/accepted.js +2 -2
  69. package/build/src/cli/commands/akuma-invoke.d.ts +2 -0
  70. package/build/src/cli/commands/akuma-invoke.js +17 -9
  71. package/build/src/cli/commands/akuma.js +7 -7
  72. package/build/src/cli/commands/contract-invoke.d.ts +3 -2
  73. package/build/src/cli/commands/contract-invoke.js +26 -19
  74. package/build/src/cli/commands/contract.d.ts +13 -13
  75. package/build/src/cli/commands/contract.js +32 -17
  76. package/build/src/cli/commands/install.d.ts +1 -1
  77. package/build/src/cli/commands/install.js +1 -1
  78. package/build/src/cli/commands/task-invoke.d.ts +3 -0
  79. package/build/src/cli/commands/task-invoke.js +23 -140
  80. package/build/src/cli/commands/task.js +54 -20
  81. package/build/src/cli/invoke.js +39 -25
  82. package/build/src/cli/main.js +2 -1
  83. package/build/src/cli/parse.d.ts +2 -2
  84. package/build/src/cli/parse.js +37 -22
  85. package/build/src/cli/render/akuma-activity.d.ts +4 -1
  86. package/build/src/cli/render/akuma-activity.js +45 -30
  87. package/build/src/cli/render/akuma-tool.d.ts +5 -1
  88. package/build/src/cli/render/akuma.js +5 -9
  89. package/build/src/cli/render/audit.js +1 -1
  90. package/build/src/cli/render/catalog.js +80 -21
  91. package/build/src/cli/render/contract-observation.d.ts +2 -0
  92. package/build/src/cli/render/contract-observation.js +11 -0
  93. package/build/src/cli/render/contract.js +25 -65
  94. package/build/src/cli/render/kanshi-akuma.d.ts +8 -0
  95. package/build/src/cli/render/kanshi-akuma.js +111 -0
  96. package/build/src/cli/render/kanshi.js +108 -213
  97. package/build/src/cli/render/receipt.d.ts +1 -2
  98. package/build/src/cli/render/receipt.js +76 -26
  99. package/build/src/cli/render/refusal.js +2 -10
  100. package/build/src/cli/render/region.js +5 -2
  101. package/build/src/cli/render/settings.d.ts +1 -1
  102. package/build/src/cli/render/settings.js +27 -8
  103. package/build/src/cli/render/task.js +22 -5
  104. package/build/src/cli/render/terminal.d.ts +28 -0
  105. package/build/src/cli/render/terminal.js +65 -0
  106. package/build/src/cli/result.d.ts +3 -3
  107. package/build/src/cli/runtime.js +3 -1
  108. package/build/src/cli/selectors.d.ts +2 -1
  109. package/build/src/cli/selectors.js +4 -3
  110. package/build/src/cli/square-edge.js +120 -36
  111. package/build/src/cli/usage.js +2 -1
  112. package/build/src/contract-guidance.d.ts +5 -0
  113. package/build/src/contract-guidance.js +121 -0
  114. package/build/src/contract-worktree.d.ts +0 -1
  115. package/build/src/contract-worktree.js +32 -83
  116. package/build/src/coordination/sqlite-transaction-lock.d.ts +1 -0
  117. package/build/src/coordination/sqlite-transaction-lock.js +5 -0
  118. package/build/src/core/facts/codec.d.ts +2 -0
  119. package/build/src/core/facts/codec.js +4 -0
  120. package/build/src/core/verbs/placement.d.ts +6 -1
  121. package/build/src/core/verbs/placement.js +5 -3
  122. package/build/src/dispatch/index.d.ts +0 -2
  123. package/build/src/dispatch/index.js +54 -55
  124. package/build/src/git/admission.js +2 -2
  125. package/build/src/git/hooks.d.ts +9 -15
  126. package/build/src/git/hooks.js +23 -317
  127. package/build/src/git/nuke.d.ts +2 -1
  128. package/build/src/git/nuke.js +36 -18
  129. package/build/src/git/private-state-seat.d.ts +12 -0
  130. package/build/src/git/private-state-seat.js +39 -0
  131. package/build/src/git/process.d.ts +6 -0
  132. package/build/src/git/process.js +19 -7
  133. package/build/src/git/read-observation.js +29 -20
  134. package/build/src/git/reconcile.d.ts +11 -0
  135. package/build/src/git/reconcile.js +64 -11
  136. package/build/src/git/repository.d.ts +6 -2
  137. package/build/src/git/repository.js +8 -0
  138. package/build/src/git/target-placement.d.ts +1 -0
  139. package/build/src/git/target-placement.js +5 -0
  140. package/build/src/git/tender.d.ts +1 -0
  141. package/build/src/git/terminal-reconcile.d.ts +1 -1
  142. package/build/src/git/terminal-reconcile.js +22 -20
  143. package/build/src/git/workspace.d.ts +14 -0
  144. package/build/src/git/workspace.js +44 -0
  145. package/build/src/kanshi/index.d.ts +1 -1
  146. package/build/src/kanshi/read.js +16 -16
  147. package/build/src/kanshi/report.d.ts +2 -2
  148. package/build/src/library/address.d.ts +9 -3
  149. package/build/src/library/address.js +3 -2
  150. package/build/src/library/akuma-creation.d.ts +4 -3
  151. package/build/src/library/akuma-creation.js +19 -13
  152. package/build/src/library/audit.d.ts +1 -1
  153. package/build/src/library/audit.js +5 -3
  154. package/build/src/library/catalog.d.ts +3 -1
  155. package/build/src/library/catalog.js +20 -6
  156. package/build/src/library/composition.d.ts +371 -0
  157. package/build/src/library/composition.js +28 -0
  158. package/build/src/library/configuration.js +8 -2
  159. package/build/src/library/continuation.js +66 -30
  160. package/build/src/library/contract-bind.js +10 -2
  161. package/build/src/library/contract-forwarding-reconciliation-result.d.ts +96 -0
  162. package/build/src/library/contract-forwarding-reconciliation-result.js +83 -0
  163. package/build/src/library/contract-forwarding-result.d.ts +6723 -0
  164. package/build/src/library/contract-forwarding-result.js +521 -0
  165. package/build/src/library/contract-forwarding.d.ts +72 -0
  166. package/build/src/library/contract-forwarding.js +125 -0
  167. package/build/src/library/contract-handle.d.ts +36 -0
  168. package/build/src/library/contract-handle.js +313 -0
  169. package/build/src/library/contract-operations.d.ts +1044 -67
  170. package/build/src/library/contract-operations.js +190 -118
  171. package/build/src/library/contract.d.ts +11 -32
  172. package/build/src/library/contract.js +16 -289
  173. package/build/src/library/fleet-result.d.ts +1454 -0
  174. package/build/src/library/fleet-result.js +96 -0
  175. package/build/src/library/fleet.d.ts +112 -54
  176. package/build/src/library/fleet.js +211 -71
  177. package/build/src/library/input.d.ts +2 -0
  178. package/build/src/library/input.js +4 -0
  179. package/build/src/library/keiyaku.d.ts +371 -20
  180. package/build/src/library/keiyaku.js +8 -21
  181. package/build/src/library/mutation.d.ts +3 -3
  182. package/build/src/library/mutation.js +5 -9
  183. package/build/src/library/nuke.d.ts +1 -1
  184. package/build/src/library/nuke.js +4 -3
  185. package/build/src/library/reconcile.d.ts +4 -0
  186. package/build/src/library/reconcile.js +2 -0
  187. package/build/src/library/refusal.d.ts +0 -9
  188. package/build/src/library/refusal.js +0 -7
  189. package/build/src/protocol/amend.js +56 -50
  190. package/build/src/protocol/attempt.d.ts +2 -0
  191. package/build/src/protocol/attempt.js +8 -1
  192. package/build/src/protocol/completion.js +7 -0
  193. package/build/src/protocol/deliver.js +6 -2
  194. package/build/src/protocol/operations.d.ts +4 -1
  195. package/build/src/protocol/operations.js +5 -2
  196. package/build/src/protocol/placement.d.ts +1 -0
  197. package/build/src/protocol/placement.js +52 -38
  198. package/build/src/protocol/read/observation.d.ts +1 -4
  199. package/build/src/protocol/read/observation.js +2 -15
  200. package/build/src/protocol/reintegrate.js +62 -58
  201. package/build/src/protocol/review.js +5 -0
  202. package/build/src/protocol/run.js +17 -13
  203. package/build/src/runtime/proc/run.d.ts +8 -0
  204. package/build/src/runtime/proc/run.js +27 -0
  205. package/build/src/runtime/proc/termination.js +26 -22
  206. package/build/src/runtime/proc/windows-launch.exe +0 -0
  207. package/build/src/settlement/holder.d.ts +2 -1
  208. package/build/src/settlement/holder.js +15 -4
  209. package/build/src/settlement/settle.js +99 -33
  210. package/build/src/task/board.d.ts +68 -27
  211. package/build/src/task/board.js +31 -1
  212. package/build/src/task/catalog.d.ts +4 -0
  213. package/build/src/task/catalog.js +23 -0
  214. package/build/src/task/compose-language.js +33 -7
  215. package/build/src/task/compose-parser.d.ts +1 -1
  216. package/build/src/task/compose-parser.js +1 -1
  217. package/build/src/task/compose.js +2 -0
  218. package/build/src/task/index.d.ts +12 -4
  219. package/build/src/task/index.js +97 -16
  220. package/build/src/task/mutation-result.d.ts +923 -0
  221. package/build/src/task/mutation-result.js +140 -0
  222. package/build/src/task/mutation.d.ts +552 -28
  223. package/build/src/task/mutation.js +304 -97
  224. package/build/src/task/operations.d.ts +1 -4
  225. package/build/src/task/operations.js +0 -6
  226. package/build/src/task/public.d.ts +2 -0
  227. package/build/src/task/public.js +1 -0
  228. package/build/src/workspace-place.d.ts +7 -2
  229. package/build/src/workspace-place.js +34 -24
  230. package/build/src/world.d.ts +1 -0
  231. package/build/src/world.js +11 -0
  232. package/package.json +8 -6
  233. package/build/src/akuma/request-execution.d.ts +0 -8
  234. package/build/src/akuma/request-execution.js +0 -98
@@ -1,7 +1,8 @@
1
1
  import { type ResumeCoordinate, type Soul, type TellFact } from "./heart/index.js";
2
2
  import type { AkumaPaths } from "./identity.js";
3
3
  import { type ProviderAdapter, type TurnResult } from "./provider.js";
4
- import { type RequestChildLaunch, type UpstreamExecutionPort } from "./request-serve.js";
4
+ import type { AkumaCallRequestChildLaunch } from "./call-request.js";
5
+ import type { ErasedRequestCommand } from "./request-wire.js";
5
6
  import { BodySupervisor } from "./body-supervisor.js";
6
7
  import type { OwnedProcess } from "../runtime/proc/run.js";
7
8
  export declare function turnRecipe(paths: AkumaPaths, soul: Soul): Promise<Readonly<{
@@ -25,8 +26,9 @@ export type DriveTurnInput = Readonly<{
25
26
  call?: string;
26
27
  launchTells: readonly TellFact[];
27
28
  supervisor: BodySupervisor;
28
- runtimeSpawn(launch: RequestChildLaunch): Promise<OwnedProcess | void>;
29
- upstream?: UpstreamExecutionPort;
29
+ runtimeSpawn(launch: AkumaCallRequestChildLaunch): Promise<OwnedProcess | void>;
30
+ upstream?: unknown;
31
+ commands: Readonly<Record<string, ErasedRequestCommand>>;
30
32
  now(): string;
31
33
  }>;
32
34
  export declare function driveTurn(input: DriveTurnInput): Promise<(DrivenTurn & Readonly<{
@@ -1,6 +1,7 @@
1
1
  import { abortableDelay } from "./abort.js";
2
+ /* eslint-disable max-lines-per-function -- Turn setup and consumption each preserve one ordered lifecycle transaction. */
2
3
  import { appendActivity, beginTurn, breakBody, heartExists, readHeart, recordSession, recordTellDeliveries, recordTellReceipt, } from "./heart/index.js";
3
- import { encodeAgentEvent } from "./provider.js";
4
+ import { encodeAgentEvent, } from "./provider.js";
4
5
  import { BodyRequestPump } from "./request-serve.js";
5
6
  import { CONTROL_RESPONSE_MS } from "./body-supervisor.js";
6
7
  function serializeEffects() {
@@ -79,6 +80,7 @@ async function startTurnDrive(input) {
79
80
  now: input.now,
80
81
  spawn: input.runtimeSpawn,
81
82
  ...(input.upstream === undefined ? {} : { upstream: input.upstream }),
83
+ commands: input.commands,
82
84
  signal: input.supervisor.signal,
83
85
  });
84
86
  const driveController = new AbortController();
@@ -101,14 +103,14 @@ async function startTurnDrive(input) {
101
103
  signal: driveController.signal,
102
104
  requests: { dir: requests.directory },
103
105
  };
104
- const setup = session === undefined
106
+ const attempt = session === undefined
105
107
  ? input.adapter.start({ ...driveInput, session: { kind: "fresh" } })
106
108
  : input.adapter.resume({ ...driveInput, session: { kind: "resume", coordinate: session } });
107
109
  try {
108
- const selected = await Promise.race([setup, requests.failure]);
110
+ const selected = await Promise.race([attempt.result, requests.failure]);
109
111
  if (input.supervisor.signal.aborted) {
110
112
  try {
111
- const retirement = await retireProviderCustody(input, turn.sequence, selected);
113
+ const retirement = await retireProviderCustody(input, turn.sequence, attempt);
112
114
  await requests.close();
113
115
  if (retirement.kind === "hung")
114
116
  return retirement;
@@ -129,6 +131,7 @@ async function startTurnDrive(input) {
129
131
  void selected.completion.then(() => requests.stopAdmission(), () => undefined);
130
132
  return {
131
133
  turnSequence: turn.sequence,
134
+ attempt,
132
135
  drive: selected,
133
136
  requests,
134
137
  cwd,
@@ -138,21 +141,39 @@ async function startTurnDrive(input) {
138
141
  };
139
142
  }
140
143
  catch (error) {
144
+ const retirement = await retireProviderCustody(input, turn.sequence, attempt);
145
+ if (retirement.kind === "hung") {
146
+ try {
147
+ await requests.close();
148
+ }
149
+ finally {
150
+ input.supervisor.signal.removeEventListener("abort", cancelDrive);
151
+ }
152
+ return retirement;
153
+ }
141
154
  return await failedTurnSetup(input, turn.sequence, requests, cancelDrive, error);
142
155
  }
143
156
  }
144
- async function retireProviderCustody(input, turnSequence, drive) {
157
+ async function retireProviderCustody(input, turnSequence, attempt) {
145
158
  const dispose = async (operation) => await Promise.race([
146
- operation().then(() => ({ kind: "retired" }), (error) => ({ kind: "held", error })),
159
+ operation().then(async () => {
160
+ try {
161
+ await attempt.closed;
162
+ return { kind: "retired" };
163
+ }
164
+ catch (error) {
165
+ return { kind: "held", error };
166
+ }
167
+ }, (error) => ({ kind: "held", error })),
147
168
  abortableDelay(CONTROL_RESPONSE_MS).then(() => ({
148
169
  kind: "held",
149
170
  error: new Error(`provider custody remained live after ${CONTROL_RESPONSE_MS}ms`),
150
171
  })),
151
172
  ]);
152
- let outcome = await dispose(drive.abort);
173
+ let outcome = await dispose(attempt.abort);
153
174
  if (outcome.kind === "retired")
154
175
  return outcome;
155
- outcome = await dispose(drive.forceDispose);
176
+ outcome = await dispose(attempt.forceDispose);
156
177
  if (outcome.kind === "retired")
157
178
  return outcome;
158
179
  if (await heartExists(input.paths)) {
@@ -226,7 +247,7 @@ async function submitPendingLiveTells(writers, pending, attempted, tellLive) {
226
247
  }
227
248
  async function stopActiveDrive(input, active) {
228
249
  try {
229
- const retirement = await retireProviderCustody(input, active.turnSequence, active.drive);
250
+ const retirement = await retireProviderCustody(input, active.turnSequence, active.attempt);
230
251
  await active.requests.close();
231
252
  return retirement;
232
253
  }
@@ -308,6 +329,7 @@ async function consumeTurnDrive(input, active) {
308
329
  pending = iterator.next();
309
330
  }
310
331
  const result = await drive.completion;
332
+ await active.attempt.closed;
311
333
  if (tellPump !== null)
312
334
  await tellPump;
313
335
  await writeWitness.drain();
@@ -320,7 +342,7 @@ async function consumeTurnDrive(input, active) {
320
342
  const retirement = await stopActiveDrive(input, active);
321
343
  return retirement.kind === "hung" ? retirement : { kind: "stopped" };
322
344
  }
323
- const retirement = await retireProviderCustody(input, turnSequence, drive);
345
+ const retirement = await retireProviderCustody(input, turnSequence, active.attempt);
324
346
  try {
325
347
  await requests.close();
326
348
  }
@@ -1,8 +1,13 @@
1
1
  import { type BodyLaunch } from "./akuma/body.js";
2
- import type { UpstreamExecutionPort } from "./akuma/request-serve.js";
2
+ import { type WorldRoot } from "./world.js";
3
+ import { type FleetRequestPort } from "./library/fleet.js";
4
+ import { type ContractRequestPort } from "./library/contract-operations.js";
5
+ import { type TaskMutationRequestPort } from "./task/mutation.js";
3
6
  type BodyProcessConfiguration = Readonly<{
4
7
  home?: string;
5
8
  gitPath?: string;
6
9
  }>;
7
- export declare function upstreamFor(launch: BodyLaunch, processConfiguration: BodyProcessConfiguration): UpstreamExecutionPort;
10
+ export declare function upstreamFor(launch: BodyLaunch, processConfiguration: BodyProcessConfiguration): Promise<FleetRequestPort & ContractRequestPort & TaskMutationRequestPort & Readonly<{
11
+ launchWorld(): WorldRoot;
12
+ }>>;
8
13
  export {};
@@ -1,47 +1,45 @@
1
1
  import { LEASH_HELD_EXIT, runAkumaBody } from "./akuma/body.js";
2
+ import { akumaCallRequestCommands } from "./akuma/call-request.js";
2
3
  import { worldRootForAkumaPaths } from "./akuma/identity.js";
4
+ import { World } from "./world.js";
3
5
  import { executeKillAkuma, executeTellAkuma, executeWaitAkuma } from "./library/fleet.js";
6
+ import { fleetRequestCommands } from "./library/fleet.js";
4
7
  import { requireBranchesToBeUpToDateFrom, worktreeHooksFrom } from "./library/configuration.js";
5
- import { executeForwardedDeliver, executeForwardedReview } from "./library/contract.js";
8
+ import { contractRequestCommands, executeForwardedAudit, executeForwardedDeliver, executeForwardedReview, } from "./library/contract-operations.js";
6
9
  import { Repo } from "./library/repo.js";
7
10
  import { settings } from "./settings.js";
8
- import { executeTaskMutation } from "./task/mutation.js";
9
- export function upstreamFor(launch, processConfiguration) {
10
- const path = worldRootForAkumaPaths(launch.paths);
11
+ import { executeTaskMutation, taskMutationRequestCommands } from "./task/mutation.js";
12
+ async function contractDependencies(repoRoot, processConfiguration) {
13
+ const repo = await Repo.at({
14
+ path: repoRoot,
15
+ ...(processConfiguration.gitPath === undefined ? {} : { gitPath: processConfiguration.gitPath }),
16
+ });
17
+ if (repo.root !== repoRoot)
18
+ throw new TypeError("forwarded Contract repoRoot must equal the canonical primary worktree");
19
+ const world = await World.prove(repo.root);
20
+ const configuration = await settings({
21
+ root: world,
22
+ ...(processConfiguration.home === undefined ? {} : { home: processConfiguration.home }),
23
+ });
24
+ return [repo, configuration];
25
+ }
26
+ function contractUpstream(processConfiguration) {
11
27
  return {
12
- wait: async (input) => await executeWaitAkuma({
13
- path,
14
- ids: input.targets,
15
- completion: input.completion,
16
- ...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }),
17
- signal: input.signal,
18
- }),
19
- tell: async (input) => await executeTellAkuma({
20
- path,
21
- id: input.target,
22
- body: input.body,
23
- tellId: input.tellId,
24
- recordedAt: input.recordedAt,
25
- signal: input.signal,
26
- }),
27
- kill: async (input) => {
28
- const result = await executeKillAkuma({ path, ids: input.targets, signal: input.signal });
29
- return {
30
- result,
31
- service: result.results.map(({ id, evidence }) => ({ id, evidence })),
32
- };
28
+ audit: async (input) => {
29
+ const [repo, configuration] = await contractDependencies(input.repoRoot, processConfiguration);
30
+ return await executeForwardedAudit({
31
+ repo,
32
+ contractId: input.contractId,
33
+ requester: input.requester,
34
+ includeDirty: input.includeDirty,
35
+ showDiff: input.showDiff,
36
+ requireBranchesToBeUpToDate: requireBranchesToBeUpToDateFrom({ settings: configuration }),
37
+ hooks: worktreeHooksFrom({ settings: configuration }),
38
+ signal: input.signal,
39
+ });
33
40
  },
34
41
  deliver: async (input) => {
35
- const [repo, configuration] = await Promise.all([
36
- Repo.at({
37
- path: input.repoRoot,
38
- ...(processConfiguration.gitPath === undefined ? {} : { gitPath: processConfiguration.gitPath }),
39
- }),
40
- settings({
41
- root: input.repoRoot,
42
- ...(processConfiguration.home === undefined ? {} : { home: processConfiguration.home }),
43
- }),
44
- ]);
42
+ const [repo, configuration] = await contractDependencies(input.repoRoot, processConfiguration);
45
43
  return await executeForwardedDeliver({
46
44
  repo,
47
45
  contractId: input.contractId,
@@ -55,16 +53,7 @@ export function upstreamFor(launch, processConfiguration) {
55
53
  });
56
54
  },
57
55
  review: async (input) => {
58
- const [repo, configuration] = await Promise.all([
59
- Repo.at({
60
- path: input.repoRoot,
61
- ...(processConfiguration.gitPath === undefined ? {} : { gitPath: processConfiguration.gitPath }),
62
- }),
63
- settings({
64
- root: input.repoRoot,
65
- ...(processConfiguration.home === undefined ? {} : { home: processConfiguration.home }),
66
- }),
67
- ]);
56
+ const [repo, configuration] = await contractDependencies(input.repoRoot, processConfiguration);
68
57
  return await executeForwardedReview({
69
58
  repo,
70
59
  contractId: input.contractId,
@@ -74,6 +63,32 @@ export function upstreamFor(launch, processConfiguration) {
74
63
  hooks: worktreeHooksFrom({ settings: configuration }),
75
64
  });
76
65
  },
66
+ };
67
+ }
68
+ export async function upstreamFor(launch, processConfiguration) {
69
+ const world = await World.prove(worldRootForAkumaPaths(launch.paths));
70
+ return {
71
+ launchWorld: () => world,
72
+ ...contractUpstream(processConfiguration),
73
+ wait: async (input) => await executeWaitAkuma({
74
+ path: world,
75
+ ids: input.targets,
76
+ completion: input.completion,
77
+ ...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }),
78
+ signal: input.signal,
79
+ }),
80
+ tell: async (input) => await executeTellAkuma({
81
+ path: world,
82
+ id: input.target,
83
+ body: input.body,
84
+ tellId: input.tellId,
85
+ recordedAt: input.recordedAt,
86
+ signal: input.signal,
87
+ }),
88
+ kill: async (input) => {
89
+ const result = await executeKillAkuma({ path: world, ids: input.targets, signal: input.signal });
90
+ return result;
91
+ },
77
92
  task: async (input) => await executeTaskMutation({
78
93
  world: input.world,
79
94
  request: input.request,
@@ -95,5 +110,12 @@ const configuration = {
95
110
  ...(mappedHome === undefined || mappedHome.length === 0 ? {} : { home: mappedHome }),
96
111
  ...(mappedGitPath === undefined ? {} : { gitPath: mappedGitPath }),
97
112
  };
98
- if ((await runAkumaBody(launch, upstreamFor(launch, configuration))) === "held")
113
+ const upstream = await upstreamFor(launch, configuration);
114
+ const commands = {
115
+ ...akumaCallRequestCommands(),
116
+ ...fleetRequestCommands(),
117
+ ...contractRequestCommands(),
118
+ ...taskMutationRequestCommands(),
119
+ };
120
+ if ((await runAkumaBody(launch, upstream, commands)) === "held")
99
121
  process.exitCode = LEASH_HELD_EXIT;
@@ -1,6 +1,6 @@
1
1
  import { type AmendResult, type AuditReport, type BindResult, type ContractId, type Delivery, type MutationResult, type Review } from "../index.js";
2
2
  import type { AcceptedAbandonResult, AcceptedAmendResult, AcceptedArcResult, AcceptedAuditResult, AcceptedBindResult, AcceptedDeliverResult, AcceptedResult, AcceptedReviewResult, InvocationResult } from "./result.js";
3
- type MutationObservation = Pick<MutationResult<unknown>, "facts" | "head" | "effects" | "lags" | "settlement">;
3
+ type MutationObservation = Pick<MutationResult<unknown>, "facts" | "head" | "lags" | "settlementLags" | "recoverySnapshot">;
4
4
  type MutationCallOptions = Readonly<{
5
5
  coordinate?: ContractId;
6
6
  projectRefusal?: (refusal: unknown) => unknown;
@@ -17,8 +17,8 @@ function acceptedEnvelope(result, coordinate) {
17
17
  contract,
18
18
  head: result.head,
19
19
  facts: acceptedFacts(result),
20
- effects: result.effects,
21
- settlement: result.settlement,
20
+ settlementLags: result.settlementLags,
21
+ ...(result.recoverySnapshot === undefined ? {} : { recoverySnapshot: result.recoverySnapshot }),
22
22
  ...(result.lags.length === 0 || firstLag === undefined ? {} : { lag: [firstLag, ...result.lags.slice(1)] }),
23
23
  };
24
24
  }
@@ -4,6 +4,7 @@ import type { Settings } from "../../settings.js";
4
4
  import type { WorldRoot } from "../../world.js";
5
5
  import type { InvokedAkumaCommand } from "./akuma.js";
6
6
  import { finishCall } from "../../library/akuma-creation.js";
7
+ import { type ExecutionContext } from "../../akuma/requests.js";
7
8
  export type AkumaInvocationResult = Readonly<{
8
9
  kind: "akuma";
9
10
  action: "call";
@@ -83,6 +84,7 @@ type InvokeInput = Readonly<{
83
84
  environment: NodeJS.ProcessEnv;
84
85
  readStdin(): Promise<string>;
85
86
  finishCall?: typeof finishCall;
87
+ execution?: ExecutionContext;
86
88
  }>;
87
89
  export declare function invokeAkuma(command: InvokedAkumaCommand, input: InvokeInput): Promise<AkumaInvocationResult>;
88
90
  export declare function invokeAkumaStatus(path: WorldRoot, akuma: string, alias?: string, repo?: Repo): Promise<AkumaInvocationResult>;
@@ -1,6 +1,14 @@
1
1
  import { Keiyaku, } from "../../index.js";
2
2
  import { beginCall, finishCall } from "../../library/akuma-creation.js";
3
+ import { killAkuma, tellAkuma, waitAkuma } from "../../library/fleet.js";
4
+ import { localExecutionContext } from "../../akuma/requests.js";
3
5
  import { recognizeAndListen } from "../square-edge.js";
6
+ function withRollbackDiagnostic(primary, rollback) {
7
+ const primaryText = primary instanceof Error ? primary.message : String(primary);
8
+ const rollbackText = rollback instanceof Error ? rollback.message : String(rollback);
9
+ const error = new Error(`${primaryText}; ${rollbackText}`, { cause: primary });
10
+ return error;
11
+ }
4
12
  function inputAlias(selector) {
5
13
  return selector.startsWith("@") ? selector : undefined;
6
14
  }
@@ -12,13 +20,13 @@ async function invokeWait(command, input) {
12
20
  return {
13
21
  kind: "akuma",
14
22
  action: "wait",
15
- result: await Keiyaku.wait({
23
+ result: await waitAkuma({
16
24
  path: input.path,
17
25
  akuma: command.akuma,
18
26
  ...(input.repo === undefined ? {} : { repo: input.repo }),
19
27
  ...(command.completion === undefined ? {} : { completion: command.completion }),
20
28
  ...(command.timeoutMs === undefined ? {} : { timeoutMs: command.timeoutMs }),
21
- }),
29
+ }, input.execution ?? localExecutionContext()),
22
30
  ...(alias === undefined ? {} : { alias }),
23
31
  };
24
32
  }
@@ -41,12 +49,12 @@ async function invokeTell(command, input) {
41
49
  ...(alias === undefined ? {} : { alias }),
42
50
  };
43
51
  }
44
- const result = await Keiyaku.tell({
52
+ const result = await tellAkuma({
45
53
  path: input.path,
46
54
  akuma: command.akuma,
47
55
  body,
48
56
  ...(input.repo === undefined ? {} : { repo: input.repo }),
49
- });
57
+ }, input.execution ?? localExecutionContext());
50
58
  const alias = inputAlias(command.akuma);
51
59
  return { kind: "akuma", action: "tell", mode: "ordinary", result, body, ...(alias === undefined ? {} : { alias }) };
52
60
  }
@@ -93,11 +101,11 @@ async function invokeKill(command, input) {
93
101
  return {
94
102
  kind: "akuma",
95
103
  action: "kill",
96
- result: await Keiyaku.kill({
104
+ result: await killAkuma({
97
105
  path: input.path,
98
106
  akuma: command.akuma,
99
107
  ...(input.repo === undefined ? {} : { repo: input.repo }),
100
- }),
108
+ }, input.execution ?? localExecutionContext()),
101
109
  ...(alias === undefined ? {} : { alias }),
102
110
  };
103
111
  }
@@ -118,7 +126,7 @@ export async function invokeAkuma(command, input) {
118
126
  ...(input.contract === undefined ? {} : { contract: input.contract }),
119
127
  ...(command.alias === undefined ? {} : { alias: command.alias }),
120
128
  ...(command.allowed === undefined ? {} : { allowed: command.allowed }),
121
- });
129
+ }, input.execution ?? localExecutionContext());
122
130
  const listener = born.born.kind === "born"
123
131
  ? await recognizeAndListen(input.path, input.environment, born.born.allocated)
124
132
  : undefined;
@@ -131,8 +139,8 @@ export async function invokeAkuma(command, input) {
131
139
  try {
132
140
  await listener.rollback();
133
141
  }
134
- catch {
135
- /* preserve launch failure */
142
+ catch (rollbackError) {
143
+ throw withRollbackDiagnostic(error, rollbackError);
136
144
  }
137
145
  }
138
146
  throw error;
@@ -17,7 +17,7 @@ const AKUMA_COMMAND_SPECS = {
17
17
  allowed: "repeatable",
18
18
  json: "boolean",
19
19
  },
20
- usage: "call <akuma-name> [--contract <kei/...>] [--alias @name] [--readonly] [--allowed <product.action>]... [--wait <duration> | -d | --detach] (<prompt> | -)",
20
+ usage: "call <akuma-name> [--contract <kei/...>] [--alias @name] [--readonly] [--allowed <product.action>]... [--wait <duration> | -d | --detach] [--json] (<prompt> | -)",
21
21
  purpose: "Birth an Akuma from <akuma-name> with one prompt.",
22
22
  details: [
23
23
  "Give <prompt> as one argument, or use - to read stdin.",
@@ -33,14 +33,14 @@ const AKUMA_COMMAND_SPECS = {
33
33
  arity: "one-or-more",
34
34
  stdin: false,
35
35
  flags: { any: "boolean", all: "boolean", timeout: "value", json: "boolean" },
36
- usage: "wait <akuma-selector>... [--any | --all] [--timeout <duration>]",
36
+ usage: "wait <akuma-selector>... [--any | --all] [--timeout <duration>] [--json]",
37
37
  purpose: "Wait for one Akuma or an explicitly selected Akuma set.",
38
38
  },
39
39
  tell: {
40
40
  arity: 1,
41
41
  stdin: true,
42
42
  flags: { interrupt: "boolean", json: "boolean" },
43
- usage: "tell <aku/...|@alias> [--interrupt] (<prompt> | -)",
43
+ usage: "tell <aku/...|@alias> [--interrupt] [--json] (<prompt> | -)",
44
44
  purpose: "Send one prompt to an existing Akuma and wake it.",
45
45
  details: [
46
46
  "Give <prompt> as one argument, or use - to read stdin.",
@@ -51,21 +51,21 @@ const AKUMA_COMMAND_SPECS = {
51
51
  arity: 1,
52
52
  stdin: false,
53
53
  flags: { id: "value", before: "value", since: "value", limit: "value", last: "boolean", json: "boolean" },
54
- usage: "history <aku/...|@alias|kei/...> [--id <historyId> | --before <index> | --since <index>] [--limit <count>] [--last]",
54
+ usage: "history <aku/...|@alias> [--id <historyId> | --before <index> | --since <index>] [--limit <count>] [--last] [--json]\nhistory <kei/...> [--json]",
55
55
  purpose: "Read Akuma execution history or one complete Contract journal and Dispatch timeline.",
56
56
  },
57
57
  fork: {
58
58
  arity: 1,
59
59
  stdin: false,
60
60
  flags: { at: "value", json: "boolean" },
61
- usage: "fork <aku/...> --at <historyId>",
61
+ usage: "fork <aku/...|@alias> --at <historyId> [--json]",
62
62
  purpose: "Fork one Akuma at a retained answered history point.",
63
63
  },
64
64
  kill: {
65
65
  arity: "one-or-more",
66
66
  stdin: false,
67
67
  flags: { json: "boolean" },
68
- usage: "kill <akuma-selector>...",
68
+ usage: "kill <akuma-selector>... [--json]",
69
69
  purpose: "Put down the current Body of an Akuma selector snapshot.",
70
70
  },
71
71
  };
@@ -76,7 +76,7 @@ export function isParsedAkumaCommand(command) {
76
76
  return isAkumaAction(command.command) && !("contract" in command && command.command === "history");
77
77
  }
78
78
  export function renderAkumaRootRows() {
79
- return Object.values(AKUMA_COMMAND_SPECS).flatMap((spec) => [` ${spec.usage}`, ` ${spec.purpose}`]);
79
+ return Object.entries(AKUMA_COMMAND_SPECS).map(([action, spec]) => ` keiyaku ${action} ${spec.purpose}`);
80
80
  }
81
81
  export function renderAkumaHelp(action) {
82
82
  const spec = AKUMA_COMMAND_SPECS[action];
@@ -4,6 +4,7 @@ import type { WorktreeHooks } from "../../library/configuration.js";
4
4
  import type { Repo } from "../../library/repo.js";
5
5
  import type { Settings } from "../../settings.js";
6
6
  import type { WorldRoot } from "../../world.js";
7
+ import type { ExecutionContext } from "../../akuma/requests.js";
7
8
  type ContractMutation = Extract<ParsedCommand, {
8
9
  command: "bind" | "amend" | "deliver" | "review" | "arc" | "abandon" | "audit";
9
10
  }>;
@@ -17,9 +18,9 @@ export type ContractMutationInput = Readonly<{
17
18
  edge: InvocationEdge;
18
19
  scope: string;
19
20
  configuration?: Settings;
20
- hooks: WorktreeHooks;
21
+ hooks?: WorktreeHooks;
21
22
  establishWorld: () => Promise<WorldRoot>;
22
- forwarded?: true;
23
+ execution: ExecutionContext;
23
24
  }>;
24
25
  export declare function invokeContractMutation(input: ContractMutationInput): Promise<InvocationResult>;
25
26
  export {};
@@ -26,13 +26,13 @@ async function selectedGitPolicy(value) {
26
26
  const { requireBranchesToBeUpToDateFrom, SettingsError } = await import("../../library/configuration.js");
27
27
  return consumeSettings(() => requireBranchesToBeUpToDateFrom({ settings: value }), SettingsError);
28
28
  }
29
- async function selectContract(repo, selector, scope) {
29
+ async function selectContract(repo, selector, scope, execution) {
30
30
  const { contractFromInput, resolveContextualContract } = await import("../selectors.js");
31
31
  if (selector !== undefined && !selector.startsWith("@"))
32
- return contractFromInput(repo, selector);
32
+ return contractFromInput(repo, selector, execution);
33
33
  const { Keiyaku } = await import("../../library/keiyaku.js");
34
34
  const id = resolveContextualContract(await Keiyaku.list({ repo }), selector, scope);
35
- return contractFromInput(repo, id);
35
+ return contractFromInput(repo, id, execution);
36
36
  }
37
37
  async function bindDraftReceipt(establishWorld, markdown) {
38
38
  const { preserveBindDraft } = await import("../draft.js");
@@ -51,7 +51,12 @@ async function invokeBind(input) {
51
51
  const { bindFromCommand } = await import("./bind.js");
52
52
  const { acceptedBind, resultFromMutationCall } = await import("../accepted.js");
53
53
  if (parsed.forkOf !== undefined) {
54
- return resultFromMutationCall("bind", () => bindFromCommand({ command: parsed, repo, ...(actor === undefined ? {} : { actor }), hooks }), (accepted) => {
54
+ return resultFromMutationCall("bind", () => bindFromCommand({
55
+ command: parsed,
56
+ repo,
57
+ ...(actor === undefined ? {} : { actor }),
58
+ ...(hooks === undefined ? {} : { hooks }),
59
+ }), (accepted) => {
55
60
  const bound = accepted.facts.find((fact) => fact.kind === "bind");
56
61
  if (bound === undefined || bound.kind !== "bind")
57
62
  throw new Error("accepted bind is missing its bind fact");
@@ -69,7 +74,7 @@ async function invokeBind(input) {
69
74
  markdown,
70
75
  gates,
71
76
  ...(actor === undefined ? {} : { actor }),
72
- hooks,
77
+ ...(hooks === undefined ? {} : { hooks }),
73
78
  }), (accepted) => {
74
79
  const bound = accepted.facts.find((fact) => fact.kind === "bind");
75
80
  if (bound === undefined || bound.kind !== "bind")
@@ -95,10 +100,10 @@ function deliverRefusal(refusal) {
95
100
  return { ...refusal, option: { flag: "--include-dirty", available: submodules.length === 0 } };
96
101
  }
97
102
  async function existingSeat(input, parsed) {
98
- const { repo, edge, scope, hooks } = input;
99
- const { id, contract } = await selectContract(repo, parsed.contract, scope);
103
+ const { repo, edge, scope, hooks, execution } = input;
104
+ const { id, contract } = await selectContract(repo, parsed.contract, scope, execution);
100
105
  const actor = actorFromEdge(parsed.actor, edge.environment);
101
- return { contract, id, ...(actor === undefined ? {} : { actor }), hooks };
106
+ return { contract, id, ...(actor === undefined ? {} : { actor }), ...(hooks === undefined ? {} : { hooks }) };
102
107
  }
103
108
  async function invokeDeliver(parsed, seat, requireBranchesToBeUpToDate) {
104
109
  const { acceptedDeliver } = await import("../accepted.js");
@@ -109,7 +114,7 @@ async function invokeDeliver(parsed, seat, requireBranchesToBeUpToDate) {
109
114
  requireBranchesToBeUpToDate,
110
115
  includeDirty: parsed.includeDirty,
111
116
  materializeConflict: parsed.materializeConflict,
112
- hooks: seat.hooks,
117
+ ...(seat.hooks === undefined ? {} : { hooks: seat.hooks }),
113
118
  });
114
119
  if (!("facts" in delivered))
115
120
  return delivered;
@@ -132,11 +137,11 @@ async function invokeReview(parsed, seat, readStdin) {
132
137
  verdict: parsed.verdict,
133
138
  ...(seat.actor === undefined ? {} : { actor: seat.actor }),
134
139
  ...(summary === undefined ? {} : { summary }),
135
- hooks: seat.hooks,
140
+ ...(seat.hooks === undefined ? {} : { hooks: seat.hooks }),
136
141
  }), (result) => acceptedReview(result, seat.id), { coordinate: seat.id });
137
142
  }
138
143
  export async function invokeContractMutation(input) {
139
- const { parsed, repo, edge, configuration, hooks, forwarded } = input;
144
+ const { parsed, repo, edge, configuration, hooks } = input;
140
145
  if (parsed.command === "bind")
141
146
  return invokeBind(input);
142
147
  const seat = await existingSeat(input, parsed);
@@ -156,37 +161,39 @@ export async function invokeContractMutation(input) {
156
161
  ...(markdown === undefined ? {} : { markdown }),
157
162
  gates,
158
163
  ...(actor === undefined ? {} : { actor }),
159
- hooks,
164
+ ...(hooks === undefined ? {} : { hooks }),
160
165
  }), (result) => acceptedAmend(result, id), { coordinate: id });
161
166
  }
162
167
  case "deliver":
163
- return invokeDeliver(parsed, seat, forwarded === true ? false : await selectedGitPolicy(configuration));
168
+ return invokeDeliver(parsed, seat, configuration === undefined ? false : await selectedGitPolicy(configuration));
164
169
  case "review":
165
170
  return invokeReview(parsed, seat, edge.readStdin);
166
171
  case "arc": {
167
172
  const markdown = await edge.readStdin();
168
173
  const { acceptedArc, resultFromMutationCall } = await import("../accepted.js");
169
- return resultFromMutationCall("arc", () => contract.arc({ markdown, ...(actor === undefined ? {} : { actor }), hooks }), (result) => acceptedArc(result, id), { coordinate: id });
174
+ return resultFromMutationCall("arc", () => contract.arc({
175
+ markdown,
176
+ ...(actor === undefined ? {} : { actor }),
177
+ ...(hooks === undefined ? {} : { hooks }),
178
+ }), (result) => acceptedArc(result, id), { coordinate: id });
170
179
  }
171
180
  case "abandon": {
172
181
  const { acceptedAbandon, resultFromMutationCall } = await import("../accepted.js");
173
182
  return resultFromMutationCall("abandon", () => contract.abandon({
174
183
  ...(actor === undefined ? {} : { actor }),
175
184
  ...(parsed.note === undefined ? {} : { note: parsed.note }),
176
- hooks,
185
+ ...(hooks === undefined ? {} : { hooks }),
177
186
  }), (result) => acceptedAbandon(result, id), { coordinate: id });
178
187
  }
179
188
  case "audit": {
180
- if (configuration === undefined)
181
- throw new Error("audit invocation requires Settings");
182
- const requireBranchesToBeUpToDate = await selectedGitPolicy(configuration);
189
+ const requireBranchesToBeUpToDate = configuration === undefined ? false : await selectedGitPolicy(configuration);
183
190
  const { acceptedAudit, resultFromMutationCall } = await import("../accepted.js");
184
191
  return resultFromMutationCall("audit", () => contract.audit({
185
192
  ...(actor === undefined ? {} : { actor }),
186
193
  includeDirty: parsed.includeDirty,
187
194
  showDiff: parsed.showDiff,
188
195
  requireBranchesToBeUpToDate,
189
- hooks,
196
+ ...(hooks === undefined ? {} : { hooks }),
190
197
  }), (result) => acceptedAudit(result, id), { coordinate: id });
191
198
  }
192
199
  }