@astrosheep/keiyaku 4.5.17 → 4.5.19

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 (200) hide show
  1. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
  2. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +5 -2
  3. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +4 -2
  4. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-babysit/SKILL.md +3 -1
  5. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +3 -1
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +3 -2
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +13 -1
  8. package/build/src/akuma/akuma-handle.d.ts +18 -7
  9. package/build/src/akuma/akuma-handle.js +97 -120
  10. package/build/src/akuma/akuma-instance.d.ts +19 -4
  11. package/build/src/akuma/akuma-instance.js +102 -38
  12. package/build/src/akuma/akuma-observe.d.ts +2 -0
  13. package/build/src/akuma/akuma-observe.js +56 -29
  14. package/build/src/akuma/akuma-product.d.ts +12 -8
  15. package/build/src/akuma/akuma-product.js +66 -54
  16. package/build/src/akuma/akuma.d.ts +10 -23
  17. package/build/src/akuma/akuma.js +12 -72
  18. package/build/src/akuma/body.js +132 -108
  19. package/build/src/akuma/call-request.d.ts +2 -2
  20. package/build/src/akuma/call-request.js +2 -2
  21. package/build/src/akuma/control.d.ts +8 -0
  22. package/build/src/akuma/control.js +23 -0
  23. package/build/src/akuma/dispatch-association.d.ts +13 -0
  24. package/build/src/akuma/dispatch-association.js +20 -0
  25. package/build/src/akuma/fleet-execution.js +44 -25
  26. package/build/src/akuma/fleet-observation.js +1 -1
  27. package/build/src/akuma/fleet-request.js +9 -2
  28. package/build/src/akuma/heart/facts.d.ts +3 -0
  29. package/build/src/akuma/heart/facts.js +6 -0
  30. package/build/src/akuma/heart/index.d.ts +12 -17
  31. package/build/src/akuma/heart/index.js +93 -86
  32. package/build/src/akuma/heart/request-authority.js +19 -19
  33. package/build/src/akuma/heart/rows.d.ts +1 -0
  34. package/build/src/akuma/heart/rows.js +7 -0
  35. package/build/src/akuma/heart/schema.d.ts +1 -1
  36. package/build/src/akuma/heart/schema.js +23 -8
  37. package/build/src/akuma/heart/storage.d.ts +2 -4
  38. package/build/src/akuma/heart/storage.js +63 -63
  39. package/build/src/akuma/heart/tells.d.ts +11 -21
  40. package/build/src/akuma/heart/tells.js +89 -84
  41. package/build/src/akuma/heart/timeline.d.ts +7 -1
  42. package/build/src/akuma/heart/timeline.js +62 -53
  43. package/build/src/akuma/index.d.ts +5 -3
  44. package/build/src/akuma/index.js +1 -1
  45. package/build/src/akuma/nuke.js +8 -45
  46. package/build/src/akuma/providers/claude/events.d.ts +1 -1
  47. package/build/src/akuma/providers/claude/events.js +2 -1
  48. package/build/src/akuma/providers/codex-app-server/events.d.ts +2 -2
  49. package/build/src/akuma/providers/codex-app-server/events.js +6 -2
  50. package/build/src/akuma/providers/opencode-sdk/events.d.ts +1 -1
  51. package/build/src/akuma/providers/opencode-sdk/events.js +5 -1
  52. package/build/src/akuma/providers/pi/events.d.ts +4 -0
  53. package/build/src/akuma/providers/pi/events.js +8 -3
  54. package/build/src/akuma/publication.js +2 -11
  55. package/build/src/akuma/request-rendezvous.d.ts +1 -1
  56. package/build/src/akuma/request-rendezvous.js +9 -8
  57. package/build/src/akuma/schema.d.ts +4 -6
  58. package/build/src/akuma/schema.js +35 -31
  59. package/build/src/akuma-body.js +3 -2
  60. package/build/src/cli/accepted.d.ts +1 -2
  61. package/build/src/cli/accepted.js +18 -16
  62. package/build/src/cli/commands/akuma-invoke.d.ts +0 -2
  63. package/build/src/cli/commands/akuma-invoke.js +8 -25
  64. package/build/src/cli/commands/akuma.d.ts +2 -1
  65. package/build/src/cli/commands/akuma.js +6 -6
  66. package/build/src/cli/commands/contract-help.d.ts +2 -1
  67. package/build/src/cli/commands/contract-help.js +27 -13
  68. package/build/src/cli/commands/contract-invoke.js +15 -0
  69. package/build/src/cli/commands/contract.d.ts +1 -0
  70. package/build/src/cli/commands/contract.js +4 -3
  71. package/build/src/cli/commands/install.js +8 -7
  72. package/build/src/cli/commands/task.d.ts +2 -0
  73. package/build/src/cli/commands/task.js +9 -5
  74. package/build/src/cli/invoke.d.ts +0 -1
  75. package/build/src/cli/invoke.js +19 -5
  76. package/build/src/cli/parse.d.ts +3 -0
  77. package/build/src/cli/parse.js +26 -13
  78. package/build/src/cli/render/akuma-activity.js +4 -4
  79. package/build/src/cli/render/akuma.js +7 -9
  80. package/build/src/cli/render/audit.js +28 -24
  81. package/build/src/cli/render/board.js +7 -3
  82. package/build/src/cli/render/catalog.js +16 -23
  83. package/build/src/cli/render/contract-history.js +20 -21
  84. package/build/src/cli/render/contract-observation.d.ts +2 -0
  85. package/build/src/cli/render/contract-observation.js +30 -6
  86. package/build/src/cli/render/contract.js +39 -33
  87. package/build/src/cli/render/kanshi-akuma.js +5 -6
  88. package/build/src/cli/render/kanshi.js +56 -99
  89. package/build/src/cli/render/nuke.js +3 -3
  90. package/build/src/cli/render/receipt.d.ts +15 -5
  91. package/build/src/cli/render/receipt.js +54 -20
  92. package/build/src/cli/render/refusal.d.ts +1 -1
  93. package/build/src/cli/render/refusal.js +55 -45
  94. package/build/src/cli/render/region.js +8 -8
  95. package/build/src/cli/render/settings.js +13 -11
  96. package/build/src/cli/render/status-set.js +13 -8
  97. package/build/src/cli/render/task.d.ts +1 -0
  98. package/build/src/cli/render/task.js +15 -14
  99. package/build/src/cli/render/terminal.d.ts +3 -1
  100. package/build/src/cli/render/terminal.js +33 -21
  101. package/build/src/cli/render/value.d.ts +3 -0
  102. package/build/src/cli/render/value.js +24 -0
  103. package/build/src/cli/result.d.ts +11 -18
  104. package/build/src/cli/runtime.d.ts +0 -1
  105. package/build/src/cli/runtime.js +46 -31
  106. package/build/src/cli/usage.d.ts +15 -2
  107. package/build/src/cli/usage.js +59 -6
  108. package/build/src/contract-guidance.d.ts +1 -0
  109. package/build/src/contract-guidance.js +26 -2
  110. package/build/src/contract-worktree.js +2 -1
  111. package/build/src/core/facts/gate.d.ts +8 -1
  112. package/build/src/core/facts/gate.js +48 -6
  113. package/build/src/core/subject.d.ts +4 -3
  114. package/build/src/core/subject.js +6 -2
  115. package/build/src/dispatch/association.d.ts +1 -13
  116. package/build/src/dispatch/association.js +1 -20
  117. package/build/src/git/hooks.d.ts +1 -1
  118. package/build/src/git/hooks.js +10 -3
  119. package/build/src/git/integration.js +4 -4
  120. package/build/src/git/process.d.ts +2 -0
  121. package/build/src/git/process.js +106 -0
  122. package/build/src/git/read-observation.js +79 -56
  123. package/build/src/git/result-codec.js +4 -1
  124. package/build/src/git/scratch.js +1 -1
  125. package/build/src/git/target-placement.d.ts +15 -4
  126. package/build/src/git/target-placement.js +136 -84
  127. package/build/src/git/terminal-reconcile.js +16 -9
  128. package/build/src/git/workspace.d.ts +18 -3
  129. package/build/src/git/workspace.js +21 -4
  130. package/build/src/kanshi/read.js +3 -3
  131. package/build/src/library/address.js +2 -2
  132. package/build/src/library/akuma-creation.d.ts +6 -3
  133. package/build/src/library/akuma-creation.js +45 -23
  134. package/build/src/library/audit.js +11 -6
  135. package/build/src/library/catalog.js +2 -3
  136. package/build/src/library/composition.d.ts +1 -0
  137. package/build/src/library/continuation.d.ts +23 -31
  138. package/build/src/library/continuation.js +97 -99
  139. package/build/src/library/contract-bind.d.ts +2 -0
  140. package/build/src/library/contract-bind.js +31 -18
  141. package/build/src/library/contract-execution.d.ts +39 -0
  142. package/build/src/library/contract-execution.js +145 -0
  143. package/build/src/library/contract-forwarding.d.ts +9 -29
  144. package/build/src/library/contract-forwarding.js +14 -78
  145. package/build/src/library/contract-handle.js +38 -5
  146. package/build/src/library/contract-operations.d.ts +29 -0
  147. package/build/src/library/contract-operations.js +35 -2
  148. package/build/src/library/contract-types.d.ts +4 -0
  149. package/build/src/library/delivery.d.ts +2 -3
  150. package/build/src/library/delivery.js +3 -5
  151. package/build/src/library/execution-result.d.ts +243 -0
  152. package/build/src/library/execution-result.js +101 -0
  153. package/build/src/library/fleet.d.ts +3 -0
  154. package/build/src/library/fleet.js +6 -5
  155. package/build/src/library/keiyaku.d.ts +5 -4
  156. package/build/src/library/keiyaku.js +1 -0
  157. package/build/src/library/mutation.d.ts +121 -89
  158. package/build/src/library/mutation.js +109 -85
  159. package/build/src/library/reconcile.d.ts +7 -0
  160. package/build/src/library/reconcile.js +13 -0
  161. package/build/src/library/refusal.d.ts +6 -0
  162. package/build/src/library/refusal.js +40 -0
  163. package/build/src/plugin/runtime.d.ts +2 -2
  164. package/build/src/plugin/runtime.js +45 -23
  165. package/build/src/protocol/attempt.d.ts +3 -1
  166. package/build/src/protocol/attempt.js +13 -5
  167. package/build/src/protocol/audit.d.ts +8 -1
  168. package/build/src/protocol/audit.js +17 -8
  169. package/build/src/protocol/completion.d.ts +20 -16
  170. package/build/src/protocol/completion.js +162 -136
  171. package/build/src/protocol/deliver.d.ts +17 -15
  172. package/build/src/protocol/deliver.js +107 -52
  173. package/build/src/protocol/intent.d.ts +5 -2
  174. package/build/src/protocol/intent.js +9 -2
  175. package/build/src/protocol/operations.d.ts +4 -4
  176. package/build/src/protocol/operations.js +3 -1
  177. package/build/src/protocol/outcome.d.ts +9 -0
  178. package/build/src/protocol/placement.d.ts +3 -1
  179. package/build/src/protocol/placement.js +60 -29
  180. package/build/src/protocol/progress.d.ts +82 -0
  181. package/build/src/protocol/progress.js +142 -0
  182. package/build/src/protocol/read/status.d.ts +27 -3
  183. package/build/src/protocol/read/status.js +40 -9
  184. package/build/src/protocol/reintegrate.d.ts +2 -0
  185. package/build/src/protocol/reintegrate.js +1 -0
  186. package/build/src/protocol/result-codec.d.ts +2 -1
  187. package/build/src/protocol/result-codec.js +79 -49
  188. package/build/src/protocol/review.d.ts +11 -7
  189. package/build/src/protocol/review.js +17 -27
  190. package/build/src/protocol/run.d.ts +2 -0
  191. package/build/src/protocol/run.js +1 -0
  192. package/build/src/runtime/proc/windows-launch.exe +0 -0
  193. package/build/src/settings.js +15 -4
  194. package/build/src/verification/execution.d.ts +2 -2
  195. package/build/src/verification/execution.js +2 -2
  196. package/build/src/workspace-place.d.ts +4 -0
  197. package/build/src/workspace-place.js +15 -7
  198. package/build/src/world.d.ts +2 -2
  199. package/build/src/world.js +20 -51
  200. package/package.json +8 -6
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keiyaku",
3
- "version": "0.1.2+codex.20260826070830",
3
+ "version": "0.1.2+codex.20260905023250",
4
4
  "description": "Use the Keiyaku contract, task, and Akuma CLI.",
5
5
  "author": {
6
6
  "name": "Keiyaku"
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: keiyaku
3
- description: Use the Keiyaku v4 CLI for contract delivery, task coordination, and Akuma work.
3
+ description: >-
4
+ Keiyaku is a CLI that records plans, writes handoff terms for deliveries,
5
+ and calls delegates. Use this skill when you need to figure out which
6
+ Keiyaku skill or command to reach for.
4
7
  ---
5
8
 
6
9
  # Keiyaku
@@ -33,7 +36,7 @@ keiyaku -C <repo> review [<contract>|@<contract>] --satisfied
33
36
  ```
34
37
 
35
38
  ```bash
36
- keiyaku -C <cwd> call <akuma-name> [--contract <kei/...>] [--alias @name] [--readonly] [--allowed <product.action>]... [--schema <file>] [--wait <duration> | -d | --detach] [--json] (<prompt> | -)
39
+ keiyaku -C <cwd> call <akuma-name> [--contract <kei/...>] [--alias @name] [--allowed <product.action>]... [--schema <file>] [--wait <duration> | -d | --detach] [--json] (<prompt> | -)
37
40
  keiyaku -C <repo> wait <akuma-selector>... [--any | --all]
38
41
  keiyaku -C <repo> tell <aku/...|@alias> (<prompt> | -)
39
42
  ```
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: keiyaku-akuma
3
- description: Use when delegating work to, supervising, steering, inspecting, forking, or stopping a Keiyaku v4 Akuma.
3
+ description: >-
4
+ Calling an Akuma: delegating scouting, mechanical chores, or fanned-out
5
+ parallel work instead of doing it inline.
4
6
  ---
5
7
 
6
8
  # Keiyaku Akuma
@@ -13,7 +15,7 @@ is accepted; the identity underneath never changes.
13
15
  ## Start One
14
16
 
15
17
  ```bash
16
- keiyaku -C <cwd> call <akuma-name> [--alias @name] [--readonly] [--allowed <product.action>]... [--schema <file>] [--wait <duration> | -d | --detach] [--json] (<prompt> | -)
18
+ keiyaku -C <cwd> call <akuma-name> [--alias @name] [--allowed <product.action>]... [--schema <file>] [--wait <duration> | -d | --detach] [--json] (<prompt> | -)
17
19
  ```
18
20
 
19
21
  Give the worker's initial prompt as one argument (quote it when it contains
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: keiyaku-babysit
3
- description: Babysit a long-running multi-lane goal — a room of lanes that advance on their own, call for you on their schedule, and hold each other up while you are busy being productive.
3
+ description: >-
4
+ Entering babysit mode: supervising parallel work across multiple Akuma and
5
+ Contracts as they advance, instead of doing the work yourself.
4
6
  ---
5
7
 
6
8
  # Keiyaku Babysit
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: keiyaku-bind
3
- description: Author and bind one Keiyaku delivery Contract. Use when deciding whether a bounded delivery is ready for Contract terms, writing those terms for an implementer, binding an existing Task with `bind --task`, choosing bind inputs, or interpreting the bind receipt and worktree handoff.
3
+ description: >-
4
+ Binding a Keiyaku: writing down what a bounded piece of work must deliver and
5
+ how it will be judged, so it can be handed off.
4
6
  ---
5
7
 
6
8
  # Keiyaku Bind
@@ -1,8 +1,9 @@
1
1
  ---
2
2
  name: keiyaku-task
3
3
  description: >-
4
- Use when recording, decomposing, or tracking a complex task, typically
5
- involving three or more steps.
4
+ Organizing, tracking progress and status, or binding work of three or more
5
+ steps as a Keiyaku Task: what to do, in what order, what depends on what,
6
+ what is done and what is blocked.
6
7
  ---
7
8
 
8
9
  # Keiyaku Task
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: keiyaku-workflow
3
- description: Hold a Contract's fulfillment loop — the loop-holder's five decisions across the whole active loop, from a waiting or bound Contract to claimed or abandoned. Hold or delegate; shape the work into Contracts, Arcs, and Tasks; commission Deliverer and Reviewer seats; adjudicate deliver, review, and audit returns, amend or abandon; schedule landing. For the flagship or the single delegate holding a whole loop.
3
+ description: >-
4
+ The Keiyaku workflow: how work moves through Keiyaku from planning through
5
+ binding, commissioning, delivery, review, and landing, and what you decide
6
+ at each stage.
4
7
  ---
5
8
 
6
9
  # Holding a fulfillment loop
@@ -111,6 +114,15 @@ immutable commit without moving the branch or the real index — a
111
114
  prior git commit is optional shaping, never a prerequisite. Deliver
112
115
  never satisfies a review gate.
113
116
 
117
+ Conflict materialization projects an uncommitted merge; it does not resolve
118
+ its contents or record a delivery. After editing the final worktree bytes,
119
+ `deliver --include-dirty` can capture them even while the real index still
120
+ reports `UU`. No `git add` or commit is required, and capture preserves the
121
+ real index. The candidate includes the complete non-ignored worktree, not
122
+ just the Contract's Region or the conflict paths. Candidate capture and target
123
+ placement are separate: this authorization does not permit overwriting
124
+ blocking changes in the target checkout.
125
+
114
126
  Audit observes: prospective candidate, integration, Verification,
115
127
  diff, target. It records no candidate and satisfies no gate.
116
128
 
@@ -1,10 +1,15 @@
1
- import { type TellResult } from "./body.js";
2
- import { type KillEvidence } from "./heart/index.js";
3
- import { type AkuId } from "./identity.js";
1
+ import { type TellResult, type TellWakeRuntime } from "./body.js";
2
+ import { HeldAkumaLeash, type KillEvidence } from "./heart/index.js";
3
+ import { type AkuId, type AkumaPaths } from "./identity.js";
4
4
  import { type ActivityHistory, type ExactHistory } from "./projection.js";
5
5
  import type { AkumaCallExecution, AkumaStatus, ForkReceipt, InterruptReceipt } from "./akuma.js";
6
6
  import type { WorldRoot } from "../world.js";
7
7
  declare const CALL_EXECUTION: unique symbol;
8
+ export declare function settleAkumaKill(paths: AkumaPaths, signal?: AbortSignal, retainLeash?: boolean): Promise<Readonly<{
9
+ evidence: KillEvidence;
10
+ leash?: HeldAkumaLeash;
11
+ }>>;
12
+ export declare function killAkumaWithRecovery(paths: AkumaPaths, recover?: (paths: AkumaPaths) => Promise<void>, signal?: AbortSignal): Promise<KillEvidence>;
8
13
  export declare class AkumaHandle {
9
14
  readonly id: AkuId;
10
15
  private readonly worldPath;
@@ -23,13 +28,19 @@ export declare class AkumaHandle {
23
28
  wait(predicate?: (status: AkumaStatus) => boolean, options?: Readonly<{
24
29
  timeoutMs?: number;
25
30
  }>): Promise<AkumaStatus>;
26
- tell(body: string): Promise<TellResult>;
27
- interrupt(body: string): Promise<InterruptReceipt>;
28
- interruptSchema(body: string, schemaJson: string): Promise<TellResult>;
31
+ tell(body: string, tellId?: string, recordedAt?: string, runtime?: TellWakeRuntime, schemaJson?: string): Promise<TellResult>;
32
+ interrupt(body: string, options?: Readonly<{
33
+ tellId?: string;
34
+ schemaJson?: string;
35
+ signal?: AbortSignal;
36
+ runtime?: TellWakeRuntime;
37
+ }>): Promise<InterruptReceipt>;
29
38
  fork(input: Readonly<{
30
39
  at: string;
31
40
  }>): Promise<ForkReceipt>;
32
- kill(): Promise<KillEvidence>;
41
+ kill(options?: Readonly<{
42
+ signal?: AbortSignal;
43
+ }>): Promise<KillEvidence>;
33
44
  lastAnswer(): Promise<LastAnswer>;
34
45
  }
35
46
  /** Package-internal provenance retained only by the handle returned from call. */
@@ -1,73 +1,81 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { CONTROL_RESPONSE_MS, wakeRecordedTell } from "./body.js";
2
+ import { handoffPendingTells, wakeRecordedTell } from "./body.js";
3
3
  import { HeldAkumaLeash, activitySlice, readForkPoint, readHeart, readKill, readLastAnsweredTurn, readSoul, recordTell, requestPause, requestStop, } from "./heart/index.js";
4
+ import { acquireLeash } from "./control.js";
4
5
  import { parsePublicHistoryId, pathsForAkuId } from "./identity.js";
5
6
  import { projectTurns, selectHistory, selectExactHistory, } from "./projection.js";
6
7
  import { resolveProviderExecution } from "./providers/index.js";
7
8
  import { publishAkuma } from "./publication.js";
8
9
  import { spawnAkumaBody } from "./body.js";
9
10
  import { AkumaNotBornError } from "./akuma-errors.js";
10
- import { bornStatus } from "./akuma-observe.js";
11
+ import { bornStatus, defaultWaitComplete, readWaitComplete } from "./akuma-observe.js";
11
12
  const CALL_EXECUTION = Symbol("akuma-call-execution");
12
13
  const POLL_MS = 100;
13
14
  const wait = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
14
15
  function diagnostic(error) {
15
16
  return error instanceof Error ? error.message : String(error);
16
17
  }
17
- function defaultWaitComplete(status) {
18
- return (status.life !== "running" &&
19
- !status.timeline.entries.some((entry) => entry.kind === "row" && entry.row.kind === "tell" && entry.row.state === "pending"));
18
+ async function takeLeashUntilSignal(paths, bodySequence, signal, unbounded = false) {
19
+ const leash = await acquireLeash(paths, {
20
+ bodySequence,
21
+ ...(signal === undefined && unbounded ? { deadline: Number.POSITIVE_INFINITY } : {}),
22
+ ...(signal === undefined ? {} : { signal }),
23
+ });
24
+ if (leash !== null)
25
+ return leash;
26
+ const latestBody = (await readHeart(paths)).latestBody;
27
+ if (latestBody?.sequence === bodySequence && latestBody.hung !== undefined)
28
+ return { kind: "unavailable", evidence: "hung" };
29
+ if (latestBody?.sequence === bodySequence && latestBody.end !== undefined)
30
+ return { kind: "unavailable", evidence: "untidy" };
31
+ return { kind: "unavailable", evidence: "unavailable" };
20
32
  }
21
- async function takeLeashUntil(paths, deadline) {
22
- for (;;) {
23
- const leash = await HeldAkumaLeash.try(paths);
24
- if (leash !== null)
25
- return leash;
26
- if (performance.now() >= deadline)
27
- return null;
28
- await wait(Math.min(POLL_MS, Math.max(0, deadline - performance.now())));
33
+ export async function settleAkumaKill(paths, signal, retainLeash = false) {
34
+ const request = await requestStop(paths, new Date().toISOString(), signal);
35
+ if (request.kind !== "requested") {
36
+ if (!retainLeash)
37
+ return { evidence: request.kind };
38
+ const leash = await acquireLeash(paths, signal === undefined ? {} : { signal });
39
+ return leash === null ? { evidence: "unavailable" } : { evidence: request.kind, leash };
29
40
  }
30
- }
31
- async function recordTellBody(paths, akuma, body, id = randomUUID(), recordedAt = new Date().toISOString()) {
32
- const admitted = await recordTell(paths, { kind: "tell", id, body, recordedAt });
33
- if (admitted.kind === "not-born")
34
- throw new AkumaNotBornError(akuma);
35
- return { kind: "recorded", tellId: admitted.tell.id };
36
- }
37
- async function killAkumaWithRecovery(paths, recover = async () => { }) {
41
+ const target = request.body;
42
+ const waited = await takeLeashUntilSignal(paths, target.sequence, signal);
43
+ if ("kind" in waited) {
44
+ if ((await readKill(paths, target.sequence)) !== null)
45
+ return { evidence: "killed" };
46
+ return { evidence: waited.evidence };
47
+ }
48
+ const leash = waited;
49
+ let retain = false;
38
50
  try {
39
- const request = await requestStop(paths, new Date().toISOString());
40
- if (request.kind !== "requested")
41
- return request.kind;
42
- const target = request.body;
43
- const leash = await takeLeashUntil(paths, performance.now() + CONTROL_RESPONSE_MS);
44
- if ((await readKill(paths, target.sequence)) !== null) {
45
- leash?.release();
46
- return "killed";
51
+ if ((await readKill(paths, target.sequence)) !== null)
52
+ return { evidence: "killed" };
53
+ const settledBody = (await readHeart(paths)).latestBody;
54
+ if (settledBody?.sequence !== target.sequence) {
55
+ return { evidence: (await readKill(paths, target.sequence)) === null ? "unavailable" : "killed" };
47
56
  }
48
- if (leash === null) {
49
- if ((await readKill(paths, target.sequence)) !== null)
50
- return "killed";
51
- const body = (await readHeart(paths)).latestBody;
52
- return body?.sequence === target.sequence && body.hung !== undefined ? "hung" : "unavailable";
53
- }
54
- try {
55
- const settledBody = (await readHeart(paths)).latestBody;
56
- if (settledBody?.sequence !== target.sequence)
57
- return (await readKill(paths, target.sequence)) === null ? "unavailable" : "killed";
58
- if (settledBody.end !== "put-down") {
59
- await leash.clearStop(paths);
60
- return "untidy";
61
- }
62
- const settled = await leash.settleStop(paths, target.sequence);
63
- return settled === null ? "unavailable" : "killed";
57
+ if (settledBody.end !== "put-down") {
58
+ await leash.clearStop(paths);
59
+ return { evidence: "untidy" };
64
60
  }
65
- finally {
61
+ const settled = await leash.settleStop(paths, target.sequence);
62
+ if (settled === null)
63
+ return { evidence: "unavailable" };
64
+ retain = retainLeash;
65
+ return retainLeash ? { evidence: "killed", leash } : { evidence: "killed" };
66
+ }
67
+ finally {
68
+ if (!retain)
66
69
  leash.release();
67
- }
70
+ }
71
+ }
72
+ export async function killAkumaWithRecovery(paths, recover, signal) {
73
+ try {
74
+ return (await settleAkumaKill(paths, signal)).evidence;
68
75
  }
69
76
  finally {
70
- void recover(paths).catch(() => undefined);
77
+ if (recover !== undefined)
78
+ void recover(paths).catch(() => undefined);
71
79
  }
72
80
  }
73
81
  export class AkumaHandle {
@@ -129,108 +137,77 @@ export class AkumaHandle {
129
137
  }
130
138
  const deadline = options.timeoutMs === undefined ? undefined : performance.now() + options.timeoutMs;
131
139
  for (;;) {
132
- const status = await this.status();
133
- if (predicate(status) || (deadline !== undefined && performance.now() >= deadline))
134
- return status;
140
+ if (predicate !== defaultWaitComplete ||
141
+ (deadline !== undefined && performance.now() >= deadline) ||
142
+ (await readWaitComplete(this.worldPath, this.id))) {
143
+ const status = await this.status();
144
+ if (predicate(status) || (deadline !== undefined && performance.now() >= deadline))
145
+ return status;
146
+ }
135
147
  await wait(deadline === undefined ? POLL_MS : Math.min(POLL_MS, Math.max(0, deadline - performance.now())));
136
148
  }
137
149
  }
138
- async tell(body) {
139
- const recorded = await recordTellBody(this.paths, this.id, body);
140
- return await wakeRecordedTell(this.paths, recorded.tellId);
150
+ async tell(body, tellId = randomUUID(), recordedAt = new Date().toISOString(), runtime, schemaJson) {
151
+ const admitted = await recordTell(this.paths, {
152
+ kind: "tell",
153
+ id: tellId,
154
+ body,
155
+ recordedAt,
156
+ ...(schemaJson === undefined ? {} : { schemaJson }),
157
+ });
158
+ if (admitted.kind === "not-born")
159
+ throw new AkumaNotBornError(this.id);
160
+ return await wakeRecordedTell(this.paths, admitted.tell.id, runtime);
141
161
  }
142
- async interrupt(body) {
143
- const request = await requestPause(this.paths, new Date().toISOString());
162
+ async interrupt(body, options = {}) {
163
+ const request = await requestPause(this.paths, new Date().toISOString(), options.signal);
144
164
  if (request.kind === "not-born") {
145
165
  throw new AkumaNotBornError(this.id);
146
166
  }
147
167
  let putDown = "was-idle";
148
168
  let leash = await HeldAkumaLeash.try(this.paths);
149
169
  if (leash === null) {
150
- leash = await takeLeashUntil(this.paths, performance.now() + CONTROL_RESPONSE_MS);
170
+ const waited = await takeLeashUntilSignal(this.paths, request.body.sequence, options.signal, true);
171
+ if ("kind" in waited)
172
+ return waited;
173
+ leash = waited;
151
174
  putDown = "self-aborted";
152
175
  }
153
- if (leash === null) {
154
- const body = (await readHeart(this.paths)).latestBody;
155
- return {
156
- kind: "unavailable",
157
- evidence: body?.sequence === request.body.sequence && body.hung !== undefined ? "hung" : "unavailable",
158
- };
159
- }
160
- const settledBody = (await readHeart(this.paths)).latestBody;
161
- if (settledBody?.sequence === request.body.sequence && settledBody.hung !== undefined) {
162
- try {
163
- await leash.clearPause(this.paths);
164
- }
165
- finally {
166
- leash.release();
167
- }
168
- return { kind: "unavailable", evidence: "hung" };
169
- }
170
- if (settledBody?.sequence !== request.body.sequence || settledBody.end === undefined) {
171
- try {
172
- await leash.clearPause(this.paths);
173
- }
174
- finally {
175
- leash.release();
176
- }
177
- return { kind: "unavailable", evidence: "untidy" };
178
- }
179
- if (request.body.end !== undefined || settledBody.end !== "put-down")
180
- putDown = "was-idle";
181
176
  let recorded;
182
177
  try {
183
- const id = randomUUID();
184
- const admitted = await leash.recordInterruptTell(this.paths, {
185
- kind: "tell",
186
- id,
187
- body,
188
- recordedAt: new Date().toISOString(),
189
- });
190
- if (admitted.kind === "not-born")
191
- throw new AkumaNotBornError(this.id);
192
- recorded = { kind: "recorded", tellId: admitted.tell.id };
193
- }
194
- finally {
195
- leash.release();
196
- }
197
- return { kind: "interrupted", putDown, tell: await wakeRecordedTell(this.paths, recorded.tellId) };
198
- }
199
- async interruptSchema(body, schemaJson) {
200
- const request = await requestPause(this.paths, new Date().toISOString());
201
- if (request.kind === "not-born")
202
- throw new AkumaNotBornError(this.id);
203
- let tellId;
204
- let leash = await HeldAkumaLeash.try(this.paths);
205
- if (leash === null)
206
- leash = await takeLeashUntil(this.paths, performance.now() + CONTROL_RESPONSE_MS);
207
- if (leash === null)
208
- throw new Error("schema interrupt could not acquire Body leash");
209
- try {
178
+ options.signal?.throwIfAborted();
210
179
  const settledBody = (await readHeart(this.paths)).latestBody;
211
180
  if (settledBody?.sequence === request.body.sequence && settledBody.hung !== undefined) {
212
181
  await leash.clearPause(this.paths);
213
- throw new Error("schema interrupt found a hung Body");
182
+ return { kind: "unavailable", evidence: "hung" };
214
183
  }
215
184
  if (settledBody?.sequence !== request.body.sequence || settledBody.end === undefined) {
216
185
  await leash.clearPause(this.paths);
217
- throw new Error("schema interrupt could not prove Body settlement");
186
+ return { kind: "unavailable", evidence: "untidy" };
218
187
  }
188
+ if (request.body.end !== undefined || settledBody.end !== "put-down")
189
+ putDown = "was-idle";
190
+ options.signal?.throwIfAborted();
191
+ const id = randomUUID();
219
192
  const admitted = await leash.recordInterruptTell(this.paths, {
220
193
  kind: "tell",
221
- id: randomUUID(),
194
+ id: options.tellId ?? id,
222
195
  body,
223
196
  recordedAt: new Date().toISOString(),
224
- schemaJson,
197
+ ...(options.schemaJson === undefined ? {} : { schemaJson: options.schemaJson }),
225
198
  });
226
199
  if (admitted.kind === "not-born")
227
200
  throw new AkumaNotBornError(this.id);
228
- tellId = admitted.tell.id;
201
+ recorded = { kind: "recorded", tellId: admitted.tell.id };
229
202
  }
230
203
  finally {
231
204
  leash.release();
232
205
  }
233
- return await wakeRecordedTell(this.paths, tellId);
206
+ return {
207
+ kind: "interrupted",
208
+ putDown,
209
+ tell: await wakeRecordedTell(this.paths, recorded.tellId, options.runtime),
210
+ };
234
211
  }
235
212
  async fork(input) {
236
213
  const source = await readSoul(this.paths);
@@ -296,8 +273,8 @@ export class AkumaHandle {
296
273
  };
297
274
  }
298
275
  }
299
- async kill() {
300
- return await killAkumaWithRecovery(this.paths);
276
+ async kill(options = {}) {
277
+ return await killAkumaWithRecovery(this.paths, handoffPendingTells, options.signal);
301
278
  }
302
279
  async lastAnswer() {
303
280
  const turn = await readLastAnsweredTurn(this.paths);
@@ -1,9 +1,22 @@
1
1
  import type { AllowedAction } from "./allowed.js";
2
+ import type { AkumaStatus } from "./akuma.js";
3
+ import type { InterruptReceipt, KillEvidence } from "./akuma.js";
2
4
  import { type AkuId } from "./identity.js";
3
5
  import { type ActivityHistory } from "./projection.js";
4
6
  import type { Settings } from "../settings.js";
5
7
  import type { WorldRoot } from "../world.js";
6
- import type { Schema } from "./schema.js";
8
+ import { type Schema } from "./schema.js";
9
+ export type AkumaIdleOptions = Readonly<{
10
+ timeoutMs?: number;
11
+ }>;
12
+ export type AkumaHistoryOptions = Readonly<{
13
+ before?: number;
14
+ since?: number;
15
+ limit?: number;
16
+ }>;
17
+ export type AkumaSignalOptions = Readonly<{
18
+ signal?: AbortSignal;
19
+ }>;
7
20
  export type AkumaBirthInput = Readonly<{
8
21
  root: WorldRoot;
9
22
  cwd?: string;
@@ -25,7 +38,9 @@ export declare class Akuma {
25
38
  static select(root: WorldRoot, selector: string): Akuma;
26
39
  tell(text: string): Promise<string>;
27
40
  tell<T>(text: string, options: AkumaTellOptions<T>): Promise<T>;
28
- idle(): Promise<void>;
29
- history(): Promise<ActivityHistory>;
30
- kill(): Promise<void>;
41
+ status(): Promise<AkumaStatus>;
42
+ interrupt(text: string, options?: AkumaSignalOptions): Promise<InterruptReceipt>;
43
+ idle(options?: AkumaIdleOptions): Promise<void>;
44
+ history(options?: AkumaHistoryOptions): Promise<ActivityHistory>;
45
+ kill(options?: AkumaSignalOptions): Promise<KillEvidence>;
31
46
  }