@astrosheep/keiyaku 4.6.8 → 4.6.10

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 (253) hide show
  1. package/README.md +40 -14
  2. package/build/plugins/claude/.claude-plugin/plugin.json +1 -1
  3. package/build/plugins/claude/skills/keiyaku/SKILL.md +5 -6
  4. package/build/plugins/claude/skills/keiyaku-akuma/SKILL.md +1 -1
  5. package/build/plugins/claude/skills/keiyaku-akuma/references/automation.md +8 -8
  6. package/build/plugins/claude/skills/keiyaku-babysit/SKILL.md +1 -1
  7. package/build/plugins/claude/skills/keiyaku-bind/SKILL.md +9 -9
  8. package/build/plugins/claude/skills/keiyaku-debt/SKILL.md +91 -0
  9. package/build/plugins/claude/skills/keiyaku-workflow/SKILL.md +2 -2
  10. package/build/plugins/codex/.codex-plugin/plugin.json +1 -1
  11. package/build/plugins/codex/skills/keiyaku/SKILL.md +5 -6
  12. package/build/plugins/codex/skills/keiyaku-akuma/SKILL.md +1 -1
  13. package/build/plugins/codex/skills/keiyaku-akuma/references/automation.md +8 -8
  14. package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +1 -1
  15. package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +9 -9
  16. package/build/plugins/codex/skills/keiyaku-debt/SKILL.md +91 -0
  17. package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +2 -2
  18. package/build/plugins/opencode/index.js +1 -1
  19. package/build/plugins/opencode/skills/keiyaku/SKILL.md +5 -6
  20. package/build/plugins/opencode/skills/keiyaku-akuma/SKILL.md +1 -1
  21. package/build/plugins/opencode/skills/keiyaku-akuma/references/automation.md +8 -8
  22. package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +1 -1
  23. package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +9 -9
  24. package/build/plugins/opencode/skills/keiyaku-debt/SKILL.md +91 -0
  25. package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +2 -2
  26. package/build/skills/keiyaku/SKILL.md +5 -6
  27. package/build/skills/keiyaku-akuma/SKILL.md +1 -1
  28. package/build/skills/keiyaku-akuma/references/automation.md +8 -8
  29. package/build/skills/keiyaku-babysit/SKILL.md +1 -1
  30. package/build/skills/keiyaku-bind/SKILL.md +9 -9
  31. package/build/skills/keiyaku-debt/SKILL.md +91 -0
  32. package/build/skills/keiyaku-workflow/SKILL.md +2 -2
  33. package/build/src/akuma/akuma-instance.d.ts +2 -0
  34. package/build/src/akuma/akuma-instance.js +10 -0
  35. package/build/src/akuma/akuma-observe.d.ts +33 -8
  36. package/build/src/akuma/akuma-observe.js +88 -64
  37. package/build/src/akuma/akuma-owner.d.ts +11 -2
  38. package/build/src/akuma/akuma-owner.js +45 -35
  39. package/build/src/akuma/akuma-selection-execution.js +9 -1
  40. package/build/src/akuma/akuma-stream.d.ts +22 -0
  41. package/build/src/akuma/akuma-stream.js +116 -0
  42. package/build/src/akuma/akuma-wait.d.ts +1 -40
  43. package/build/src/akuma/akuma-wait.js +23 -84
  44. package/build/src/akuma/akuma.d.ts +17 -11
  45. package/build/src/akuma/akuma.js +2 -0
  46. package/build/src/akuma/allowed.d.ts +7 -12
  47. package/build/src/akuma/allowed.js +13 -4
  48. package/build/src/akuma/body-supervisor.d.ts +5 -5
  49. package/build/src/akuma/body-supervisor.js +22 -20
  50. package/build/src/akuma/body.js +28 -1
  51. package/build/src/akuma/call-request.d.ts +12 -22
  52. package/build/src/akuma/heart/activity-schema.d.ts +12 -0
  53. package/build/src/akuma/heart/activity-schema.js +6 -0
  54. package/build/src/akuma/heart/index.d.ts +59 -2
  55. package/build/src/akuma/heart/index.js +87 -8
  56. package/build/src/akuma/heart/rows.js +5 -3
  57. package/build/src/akuma/heart/soul.d.ts +9 -0
  58. package/build/src/akuma/heart/soul.js +29 -0
  59. package/build/src/akuma/heart/storage.d.ts +15 -0
  60. package/build/src/akuma/heart/storage.js +55 -0
  61. package/build/src/akuma/heart/timeline.d.ts +7 -0
  62. package/build/src/akuma/heart/timeline.js +10 -0
  63. package/build/src/akuma/index.d.ts +1 -0
  64. package/build/src/akuma/projection.d.ts +25 -0
  65. package/build/src/akuma/projection.js +24 -7
  66. package/build/src/akuma/provider-recipe.d.ts +11 -0
  67. package/build/src/akuma/provider-recipe.js +23 -0
  68. package/build/src/akuma/provider.d.ts +25 -0
  69. package/build/src/akuma/provider.js +99 -7
  70. package/build/src/akuma/providers/acp/events.js +25 -2
  71. package/build/src/akuma/providers/claude/events.js +76 -10
  72. package/build/src/akuma/providers/claude/index.js +2 -5
  73. package/build/src/akuma/providers/codex-app-server/events.js +17 -2
  74. package/build/src/akuma/providers/codex-app-server/index.js +15 -9
  75. package/build/src/akuma/providers/decode.d.ts +8 -0
  76. package/build/src/akuma/providers/decode.js +21 -0
  77. package/build/src/akuma/providers/grok-build/index.js +10 -26
  78. package/build/src/akuma/providers/opencode-sdk/event-stream.d.ts +3 -3
  79. package/build/src/akuma/providers/opencode-sdk/event-stream.js +2 -25
  80. package/build/src/akuma/providers/opencode-sdk/events.d.ts +7 -43
  81. package/build/src/akuma/providers/opencode-sdk/events.js +147 -284
  82. package/build/src/akuma/providers/opencode-sdk/index.js +267 -421
  83. package/build/src/akuma/providers/opencode-sdk/native-http.d.ts +9 -0
  84. package/build/src/akuma/providers/opencode-sdk/native-http.js +69 -0
  85. package/build/src/akuma/providers/opencode-sdk/session.d.ts +42 -36
  86. package/build/src/akuma/providers/opencode-sdk/session.js +75 -82
  87. package/build/src/akuma/providers/paseo/events.d.ts +8 -0
  88. package/build/src/akuma/providers/paseo/events.js +58 -11
  89. package/build/src/akuma/providers/paseo/index.js +11 -7
  90. package/build/src/akuma/providers/pi/events.d.ts +2 -0
  91. package/build/src/akuma/providers/pi/events.js +32 -24
  92. package/build/src/akuma/providers/pi/index.js +21 -35
  93. package/build/src/akuma/request-lifecycle.d.ts +1 -2
  94. package/build/src/akuma/request-lifecycle.js +2 -8
  95. package/build/src/akuma/request-rendezvous.js +38 -55
  96. package/build/src/akuma/request-serve.d.ts +1 -1
  97. package/build/src/akuma/request-serve.js +77 -113
  98. package/build/src/akuma/selection-observation.d.ts +57 -51
  99. package/build/src/akuma/selection-observation.js +3 -3
  100. package/build/src/akuma/turn-drive.d.ts +3 -0
  101. package/build/src/akuma/turn-drive.js +26 -5
  102. package/build/src/akuma-body.js +12 -22
  103. package/build/src/cli/akuma-caller.js +10 -0
  104. package/build/src/cli/commands/akuma-grammar.js +3 -4
  105. package/build/src/cli/commands/akuma.js +13 -51
  106. package/build/src/cli/commands/contract-grammar.d.ts +7 -6
  107. package/build/src/cli/commands/contract-grammar.js +27 -32
  108. package/build/src/cli/commands/contract-help.d.ts +16 -7
  109. package/build/src/cli/commands/contract-help.js +20 -11
  110. package/build/src/cli/commands/contract.js +11 -11
  111. package/build/src/cli/commands/debt-grammar.d.ts +19 -0
  112. package/build/src/cli/commands/debt-grammar.js +323 -0
  113. package/build/src/cli/commands/debt-query.d.ts +5 -0
  114. package/build/src/cli/commands/{task-query.js → debt-query.js} +9 -9
  115. package/build/src/cli/commands/{task.d.ts → debt.d.ts} +2 -2
  116. package/build/src/cli/commands/{task.js → debt.js} +83 -143
  117. package/build/src/cli/coordinates.d.ts +1 -1
  118. package/build/src/cli/coordinates.js +1 -1
  119. package/build/src/cli/parse.d.ts +4 -4
  120. package/build/src/cli/parse.js +17 -16
  121. package/build/src/cli/render/akuma-activity.d.ts +11 -83
  122. package/build/src/cli/render/akuma-activity.js +20 -382
  123. package/build/src/cli/render/catalog.d.ts +2 -2
  124. package/build/src/cli/render/catalog.js +5 -5
  125. package/build/src/cli/render/contract.js +2 -2
  126. package/build/src/cli/render/debt.d.ts +28 -0
  127. package/build/src/cli/render/{task.js → debt.js} +51 -112
  128. package/build/src/cli/render/kanshi.js +28 -28
  129. package/build/src/cli/render/marks.d.ts +5 -5
  130. package/build/src/cli/render/marks.js +4 -10
  131. package/build/src/cli/render/nuke.js +1 -1
  132. package/build/src/cli/runtime.js +3 -3
  133. package/build/src/cli/scan.d.ts +1 -1
  134. package/build/src/cli/usage.d.ts +1 -1
  135. package/build/src/cli/usage.js +4 -4
  136. package/build/src/contract-worktree.js +3 -3
  137. package/build/src/debt/board.d.ts +160 -0
  138. package/build/src/{task → debt}/board.js +89 -89
  139. package/build/src/debt/catalog.d.ts +11 -0
  140. package/build/src/debt/catalog.js +59 -0
  141. package/build/src/{task → debt}/context.d.ts +1 -1
  142. package/build/src/{task → debt}/context.js +1 -1
  143. package/build/src/{task → debt}/created-observation.d.ts +6 -10
  144. package/build/src/{task → debt}/created-observation.js +7 -7
  145. package/build/src/debt/document.d.ts +37 -0
  146. package/build/src/{task → debt}/document.js +37 -37
  147. package/build/src/debt/identity.d.ts +21 -0
  148. package/build/src/{task → debt}/identity.js +35 -35
  149. package/build/src/debt/index.d.ts +111 -0
  150. package/build/src/debt/index.js +203 -0
  151. package/build/src/{task → debt}/input.d.ts +8 -8
  152. package/build/src/{task → debt}/input.js +21 -21
  153. package/build/src/debt/lifecycle-operations.d.ts +6 -0
  154. package/build/src/{task → debt}/lifecycle-operations.js +27 -31
  155. package/build/src/debt/mutation-result.d.ts +981 -0
  156. package/build/src/debt/mutation-result.js +109 -0
  157. package/build/src/debt/mutation.d.ts +424 -0
  158. package/build/src/debt/mutation.js +223 -0
  159. package/build/src/debt/operation-types.d.ts +71 -0
  160. package/build/src/debt/operations.d.ts +28 -0
  161. package/build/src/{task → debt}/operations.js +59 -60
  162. package/build/src/debt/query.d.ts +76 -0
  163. package/build/src/{task → debt}/query.js +55 -55
  164. package/build/src/{task → debt}/store.d.ts +13 -13
  165. package/build/src/{task → debt}/store.js +58 -49
  166. package/build/src/debt/view.d.ts +4 -0
  167. package/build/src/debt/view.js +7 -0
  168. package/build/src/identity/coordinates.d.ts +1 -1
  169. package/build/src/index.d.ts +13 -13
  170. package/build/src/index.js +9 -9
  171. package/build/src/kanshi/index.d.ts +1 -1
  172. package/build/src/kanshi/read.js +33 -33
  173. package/build/src/kanshi/report.d.ts +7 -7
  174. package/build/src/kanshi/select.js +4 -4
  175. package/build/src/library/akumas.d.ts +2 -3
  176. package/build/src/library/bind.d.ts +3 -3
  177. package/build/src/library/bind.js +5 -5
  178. package/build/src/library/contract-creation.js +5 -5
  179. package/build/src/library/contract-execution.js +4 -4
  180. package/build/src/library/contract-types.d.ts +2 -2
  181. package/build/src/library/input.d.ts +2 -2
  182. package/build/src/library/input.js +5 -5
  183. package/build/src/library/invocation.js +2 -2
  184. package/build/src/library/nuke.js +3 -3
  185. package/build/src/library/outcome.d.ts +126 -126
  186. package/build/src/library/outcome.js +3 -3
  187. package/build/src/library/selection.d.ts +1 -4
  188. package/build/src/library/selection.js +11 -62
  189. package/build/src/plugin/public.d.ts +5 -0
  190. package/build/src/plugin/runtime.js +3 -1
  191. package/build/src/runtime/proc/windows-launch.exe +0 -0
  192. package/build/src/settlement/fence.d.ts +3 -3
  193. package/build/src/settlement/fence.js +4 -4
  194. package/build/src/settlement/holder.d.ts +16 -16
  195. package/build/src/settlement/holder.js +69 -63
  196. package/build/src/settlement/settle.d.ts +5 -5
  197. package/build/src/settlement/settle.js +53 -53
  198. package/package.json +12 -6
  199. package/plugins/paseo/plugin/index.server.ts +17 -0
  200. package/plugins/paseo/plugin/paseo-plugin.json +4 -0
  201. package/plugins/paseo/plugin/server/attach.ts +52 -0
  202. package/plugins/paseo/plugin/server/keiyaku.ts +44 -0
  203. package/plugins/paseo/plugin/server/message.ts +60 -0
  204. package/plugins/paseo/plugin/server/mirror.ts +193 -0
  205. package/plugins/paseo/plugin/server/model.ts +14 -0
  206. package/plugins/paseo/plugin/server/provider.ts +276 -0
  207. package/plugins/paseo/plugin/server/sdk-worker.ts +237 -0
  208. package/plugins/paseo/plugin/server/sdk.ts +289 -0
  209. package/plugins/paseo/plugin/server/stop.ts +26 -0
  210. package/plugins/paseo/plugin/server/transport.ts +35 -0
  211. package/plugins/paseo/plugin/shared/attach-rpc.ts +10 -0
  212. package/plugins/paseo/plugin/shared/refresh-rpc.ts +6 -0
  213. package/plugins/paseo/plugin/tsconfig.json +6 -0
  214. package/skills/keiyaku/SKILL.md +5 -6
  215. package/skills/keiyaku-akuma/SKILL.md +1 -1
  216. package/skills/keiyaku-akuma/references/automation.md +8 -8
  217. package/skills/keiyaku-babysit/SKILL.md +1 -1
  218. package/skills/keiyaku-bind/SKILL.md +9 -9
  219. package/skills/keiyaku-debt/SKILL.md +91 -0
  220. package/skills/keiyaku-workflow/SKILL.md +2 -2
  221. package/build/plugins/claude/skills/keiyaku-task/SKILL.md +0 -104
  222. package/build/plugins/codex/skills/keiyaku-task/SKILL.md +0 -104
  223. package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +0 -104
  224. package/build/skills/keiyaku-task/SKILL.md +0 -104
  225. package/build/src/cli/commands/task-grammar.d.ts +0 -19
  226. package/build/src/cli/commands/task-grammar.js +0 -384
  227. package/build/src/cli/commands/task-query.d.ts +0 -5
  228. package/build/src/cli/render/task.d.ts +0 -39
  229. package/build/src/task/board.d.ts +0 -168
  230. package/build/src/task/catalog.d.ts +0 -11
  231. package/build/src/task/catalog.js +0 -59
  232. package/build/src/task/compose-language.d.ts +0 -57
  233. package/build/src/task/compose-language.js +0 -364
  234. package/build/src/task/compose-parser.d.ts +0 -32
  235. package/build/src/task/compose-parser.js +0 -180
  236. package/build/src/task/compose.d.ts +0 -16
  237. package/build/src/task/compose.js +0 -189
  238. package/build/src/task/document.d.ts +0 -39
  239. package/build/src/task/identity.d.ts +0 -21
  240. package/build/src/task/index.d.ts +0 -138
  241. package/build/src/task/index.js +0 -269
  242. package/build/src/task/lifecycle-operations.d.ts +0 -6
  243. package/build/src/task/mutation-result.d.ts +0 -1726
  244. package/build/src/task/mutation-result.js +0 -198
  245. package/build/src/task/mutation.d.ts +0 -590
  246. package/build/src/task/mutation.js +0 -262
  247. package/build/src/task/operation-types.d.ts +0 -71
  248. package/build/src/task/operations.d.ts +0 -28
  249. package/build/src/task/query.d.ts +0 -76
  250. package/build/src/task/view.d.ts +0 -4
  251. package/build/src/task/view.js +0 -7
  252. package/skills/keiyaku-task/SKILL.md +0 -104
  253. /package/build/src/{task → debt}/operation-types.js +0 -0
@@ -33,7 +33,7 @@ to create parallel work.
33
33
 
34
34
  - Separate `kei`s have independently acceptable outcomes.
35
35
  - An Arc is a chapter of one `kei`; it is not separately accepted.
36
- - A Task stores decomposition or dependencies that outlive this conversation.
36
+ - A Debt records confirmed unresolved work and its dependencies.
37
37
 
38
38
  Use `after` only when one `kei` requires another to be accepted first. Ordinary
39
39
  overlap is not a dependency.
@@ -101,7 +101,7 @@ authority.
101
101
  | Role | Grant at birth | Return |
102
102
  | --- | --- | --- |
103
103
  | Holder | The actions the delegated loop will perform; include `contract.review` when this holder will review. Commission with the `kei`, current Arc when one exists, appointed worktree, and holder duties. | Acceptance or abandonment, with receipts. |
104
- | Deliverer | The ordinary baseline: every Task mutation, Contract audit and delivery, and Akuma management. `keiyaku -C <repo> call worker --alias @deliverer --contract <kei/...> --workdir <appointed-path> -` | The delivery receipt. |
104
+ | Deliverer | The ordinary baseline: every Debt mutation, Contract audit and delivery, and Akuma management. `keiyaku -C <repo> call worker --alias @deliverer --contract <kei/...> --workdir <appointed-path> -` | The delivery receipt. |
105
105
  | Reviewer | `--allowed contract.review`: `keiyaku -C <repo> call review-akuma --alias @reviewer --contract <kei/...> --workdir <appointed-path> --allowed contract.review -` | The verdict receipt. Without the grant, `not-allowed` refuses and no verdict is recorded. |
106
106
 
107
107
  An Archetype's explicit allowed set replaces the ordinary baseline; check
@@ -1,6 +1,7 @@
1
1
  import type { AkumaCaller } from "./caller.js";
2
2
  import type { Settings } from "../settings.js";
3
3
  import type { WorldRoot } from "../world.js";
4
+ import type { AkumaStreamSnapshot } from "./akuma-stream.js";
4
5
  import { type InterruptReceipt } from "./akuma-owner.js";
5
6
  import { type AkumaStatus } from "./akuma.js";
6
7
  import type { AllowedAction } from "./allowed.js";
@@ -66,5 +67,6 @@ export declare class Akuma {
66
67
  status(): Promise<AkumaStatus>;
67
68
  idle(options?: AkumaIdleOptions): Promise<AkumaIdleResult>;
68
69
  history(options?: AkumaHistoryOptions): Promise<ActivityHistory>;
70
+ stream(options?: AkumaSignalOptions): AsyncIterable<AkumaStreamSnapshot>;
69
71
  kill(options?: AkumaSignalOptions): Promise<KillEvidence>;
70
72
  }
@@ -151,6 +151,16 @@ export class Akuma {
151
151
  ...(options.limit === undefined ? {} : { limit: options.limit }),
152
152
  }));
153
153
  }
154
+ stream(options = {}) {
155
+ if (typeof options !== "object" || options === null || Array.isArray(options)) {
156
+ throw new TypeError("Akuma stream options must be an object");
157
+ }
158
+ const unknown = Object.keys(options).find((key) => key !== "signal");
159
+ if (unknown !== undefined)
160
+ throw new TypeError(`Akuma stream options has unknown field: ${unknown}`);
161
+ const signal = signalOption(options.signal);
162
+ return this.owner(true).stream(signal === undefined ? {} : { signal });
163
+ }
154
164
  async kill(options = {}) {
155
165
  if (typeof options !== "object" || options === null || Array.isArray(options)) {
156
166
  throw new TypeError("Akuma kill options must be an object");
@@ -1,5 +1,5 @@
1
1
  import { type AkuId, type AkumaPaths } from "./identity.js";
2
- import { selectHistory, selectSnapshot, type ActivityHistory, type ActivityRow, type ActivitySnapshot, type TurnLedger } from "./projection.js";
2
+ import { selectHistory, type ActivityHistory, type ActivityRow, type ActivitySnapshot } from "./projection.js";
3
3
  import type { WorldRoot } from "../world.js";
4
4
  import type { AkumaAlias } from "../identity/selector.js";
5
5
  import type { AkumaListRow, AkumaStatus, UnbornAkumaListRow } from "./akuma.js";
@@ -25,23 +25,47 @@ type StatusObservationInput = Readonly<{
25
25
  ordinaryBudget?: number;
26
26
  admittedTellId?: string;
27
27
  }>;
28
- type StatusProjection = Readonly<{
29
- ledger: TurnLedger;
30
- selected: ReturnType<typeof selectSnapshot>;
31
- }>;
32
28
  /** Private to a live wait: retain only this member's current frontier and last selection. */
33
29
  export declare function createLiveStatusReader(paths: AkumaPaths, expected: AkuId): {
34
30
  clear: () => void;
31
+ execution(signal?: AbortSignal): Promise<import("./heart/facts.js").AkumaLife>;
32
+ tellOutcome: (id: string, signal?: AbortSignal) => Promise<{
33
+ tell: Readonly<{
34
+ kind: "tell";
35
+ sequence: number;
36
+ id: string;
37
+ body: string;
38
+ initiator?: string;
39
+ schemaJson?: string;
40
+ recordedAt: string;
41
+ state: "pending" | "told";
42
+ deliveries: readonly import("./heart/facts.js").TellDelivery[];
43
+ binding?: import("./heart/facts.js").TellBinding;
44
+ }> | null;
45
+ end: Readonly<{
46
+ kind: "turn-end";
47
+ sequence: number;
48
+ turnSequence: number;
49
+ outcome: import("./heart/facts.js").TurnOutcome;
50
+ completedAt: string;
51
+ }> | undefined;
52
+ }>;
53
+ complete(signal?: AbortSignal): Promise<boolean>;
35
54
  read(input: StatusObservationInput, signal?: AbortSignal): Promise<LiveStatusObservation>;
36
55
  };
37
- /** Internal live companion for an observation loop; it is not a public result. */
38
- export declare function bornLiveStatus(paths: AkumaPaths, expected: AkuId, input: StatusObservationInput, signal?: AbortSignal, readProjection?: () => Promise<StatusProjection>): Promise<LiveStatusObservation>;
56
+ /** One-shot observations use the same reader and always release it. */
57
+ export declare function bornLiveStatus(paths: AkumaPaths, expected: AkuId, input: StatusObservationInput, signal?: AbortSignal): Promise<LiveStatusObservation>;
39
58
  export declare function bornStatus(paths: AkumaPaths, expected: AkuId, input: StatusObservationInput): Promise<BudgetedStatusObservation>;
40
59
  export declare function readLiveStatus(worldPath: WorldRoot, id: AkuId, input: StatusObservationInput, signal?: AbortSignal): Promise<LiveStatusObservation>;
60
+ export type ExecutionProgress = "settled" | "advancing" | "stopped";
61
+ /** Pending input is not execution. An owned launch can bridge the admission gap. */
62
+ export declare function executionProgress(life: AkumaStatus["life"], pending: boolean, wake?: "launching" | "settled" | "failed"): ExecutionProgress;
41
63
  export declare function defaultWaitComplete(status: AkumaStatus): boolean;
42
64
  /** Probe completion only; returned statuses still come from a full observation. */
43
- export declare function readWaitComplete(worldPath: WorldRoot, ids: readonly AkuId[], completion: "any" | "all", signal?: AbortSignal): Promise<boolean>;
65
+ export declare function readWaitComplete(worldPath: WorldRoot, ids: readonly AkuId[], completion: "any" | "all", signal?: AbortSignal, probe?: (id: AkuId) => Promise<boolean>): Promise<boolean>;
44
66
  export type WaitReason = "completed" | "deadline";
67
+ /** The one observation cadence public waiting and timeline streaming share. */
68
+ export declare const OBSERVATION_POLL_MS = 100;
45
69
  /**
46
70
  * The one deadline-aware observation loop for public Akuma waiting. It always
47
71
  * reads once before judging a passed deadline, so a zero-duration wait remains
@@ -49,6 +73,7 @@ export type WaitReason = "completed" | "deadline";
49
73
  */
50
74
  export declare function waitForObservation<T>(input: Readonly<{
51
75
  timeoutMs?: number;
76
+ pollMs?: number;
52
77
  signal?: AbortSignal;
53
78
  probe?(): Promise<boolean>;
54
79
  observe(): Promise<T>;
@@ -1,5 +1,5 @@
1
1
  import { projectAkumaBirth } from "./caller.js";
2
- import { readStatusFacts, createStatusFactReader, readLifeSnapshot, HeldAkumaLeash, isHeartAbsent, life, lifeAt, probeLeash, readHeart, readSeal, readSoul, } from "./heart/index.js";
2
+ import { createStatusFactReader, readLifeSnapshot, HeldAkumaLeash, isHeartAbsent, life, lifeAt, probeLeash, readHeart, readSeal, readSoul, } from "./heart/index.js";
3
3
  import { pathsForAkuId } from "./identity.js";
4
4
  import { ordinarySnapshotBudget, projectTurns, selectHistory, selectSnapshot, } from "./projection.js";
5
5
  import { resolveProviderExecution } from "./providers/index.js";
@@ -89,60 +89,75 @@ export function createLiveStatusReader(paths, expected) {
89
89
  };
90
90
  return {
91
91
  clear,
92
- async read(input, signal) {
92
+ async execution(signal) {
93
+ return (await bornObservation(paths, expected, () => reader.life(signal))).currentLife;
94
+ },
95
+ tellOutcome: reader.tellOutcome,
96
+ async complete(signal) {
93
97
  try {
94
- return await bornLiveStatus(paths, expected, input, signal, async () => {
95
- const facts = await reader.read(input, signal);
96
- const ledger = memo?.facts === facts ? memo.ledger : projectTurns(facts);
97
- const options = snapshotSelection(input);
98
- const selected = memo?.ledger === ledger &&
99
- memo.options.aperture === options.aperture &&
100
- memo.options.admittedTellId === options.admittedTellId &&
101
- memo.options.budget.tail === options.budget.tail &&
102
- memo.options.budget.voice === options.budget.voice
103
- ? memo.selected
104
- : selectSnapshot(ledger, options);
105
- memo = { facts, ledger, options, selected };
106
- return { ledger, selected };
107
- });
98
+ const observed = await bornObservation(paths, expected, () => reader.life(signal));
99
+ return complete(observed.currentLife, observed.snapshot.hasPendingTell);
108
100
  }
109
101
  catch (error) {
110
102
  clear();
111
103
  throw error;
112
104
  }
113
105
  },
114
- };
115
- }
116
- /** Internal live companion for an observation loop; it is not a public result. */
117
- export async function bornLiveStatus(paths, expected, input, signal, readProjection) {
118
- if (input.ordinaryBudget !== undefined && (!Number.isSafeInteger(input.ordinaryBudget) || input.ordinaryBudget < 0))
119
- throw new TypeError("ordinary budget must be a nonnegative safe integer");
120
- const { snapshot, soul, currentLife } = await bornObservation(paths, expected, () => readLifeSnapshot(paths, signal));
121
- const resumeUnsupported = currentLife === "stranded" &&
122
- snapshot.latestSession?.provider === soul.provider.name &&
123
- (await resolveProviderExecution(soul.provider)).adapter.resume === undefined;
124
- const { ledger, selected } = readProjection === undefined ? await readStatusProjection(paths, input, signal) : await readProjection();
125
- return {
126
- status: {
127
- id: soul.id,
128
- birth: projectAkumaBirth(soul),
129
- life: currentLife,
130
- cwd: soul.cwd,
131
- allowed: soul.allowed,
132
- ...(resumeUnsupported ? { strandedReason: "resume-unsupported" } : {}),
133
- timeline: selected.snapshot,
106
+ async read(input, signal) {
107
+ try {
108
+ if (input.ordinaryBudget !== undefined &&
109
+ (!Number.isSafeInteger(input.ordinaryBudget) || input.ordinaryBudget < 0))
110
+ throw new TypeError("ordinary budget must be a nonnegative safe integer");
111
+ const { snapshot, soul, currentLife } = await bornObservation(paths, expected, () => reader.life(signal));
112
+ const resumeUnsupported = currentLife === "stranded" &&
113
+ snapshot.latestSession?.provider === soul.provider.name &&
114
+ (await resolveProviderExecution(soul.provider)).adapter.resume === undefined;
115
+ const facts = await reader.read(input, signal);
116
+ const ledger = memo?.facts === facts ? memo.ledger : projectTurns(facts);
117
+ const options = snapshotSelection(input);
118
+ const selected = memo?.ledger === ledger &&
119
+ memo.options.aperture === options.aperture &&
120
+ memo.options.admittedTellId === options.admittedTellId &&
121
+ memo.options.budget.tail === options.budget.tail &&
122
+ memo.options.budget.voice === options.budget.voice
123
+ ? memo.selected
124
+ : selectSnapshot(ledger, options);
125
+ memo = { facts, ledger, options, selected };
126
+ return {
127
+ status: {
128
+ id: soul.id,
129
+ birth: projectAkumaBirth(soul),
130
+ life: currentLife,
131
+ cwd: soul.cwd,
132
+ // The execution adapter and its one current model are what this Akuma
133
+ // actually runs; a birth request the Soul still only seeded is not a
134
+ // claim that a native runtime ever used it.
135
+ provider: soul.provider.name,
136
+ ...(soul.options.model === undefined ? {} : { model: soul.options.model }),
137
+ allowed: soul.allowed,
138
+ ...(resumeUnsupported ? { strandedReason: "resume-unsupported" } : {}),
139
+ timeline: selected.snapshot,
140
+ },
141
+ ordinarySelected: selected.ordinaryCount,
142
+ rows: ledger.rows,
143
+ };
144
+ }
145
+ catch (error) {
146
+ clear();
147
+ throw error;
148
+ }
134
149
  },
135
- ordinarySelected: selected.ordinaryCount,
136
- rows: ledger.rows,
137
150
  };
138
151
  }
139
- async function readStatusProjection(paths, input, signal) {
140
- const facts = await readStatusFacts(paths, input, signal);
141
- const ledger = projectTurns(facts);
142
- return {
143
- ledger,
144
- selected: selectSnapshot(ledger, snapshotSelection(input)),
145
- };
152
+ /** One-shot observations use the same reader and always release it. */
153
+ export async function bornLiveStatus(paths, expected, input, signal) {
154
+ const reader = createLiveStatusReader(paths, expected);
155
+ try {
156
+ return await reader.read(input, signal);
157
+ }
158
+ finally {
159
+ reader.clear();
160
+ }
146
161
  }
147
162
  export async function bornStatus(paths, expected, input) {
148
163
  const { rows: _rows, ...status } = await bornLiveStatus(paths, expected, input);
@@ -151,21 +166,33 @@ export async function bornStatus(paths, expected, input) {
151
166
  export async function readLiveStatus(worldPath, id, input, signal) {
152
167
  return await bornLiveStatus(pathsForAkuId(worldPath, id), id, input, signal);
153
168
  }
169
+ /** Pending input is not execution. An owned launch can bridge the admission gap. */
170
+ export function executionProgress(life, pending, wake = "settled") {
171
+ if (wake === "launching" || life === "running")
172
+ return "advancing";
173
+ if (wake === "failed")
174
+ return "stopped";
175
+ if (life === "asleep")
176
+ return pending ? "advancing" : "settled";
177
+ return "stopped";
178
+ }
154
179
  function complete(life, pending) {
155
- return life !== "running" && !pending;
180
+ return executionProgress(life, pending) !== "advancing";
156
181
  }
157
182
  export function defaultWaitComplete(status) {
158
183
  return complete(status.life, status.timeline.entries.some((entry) => entry.kind === "row" && entry.row.kind === "tell" && entry.row.state === "pending"));
159
184
  }
160
185
  /** Probe completion only; returned statuses still come from a full observation. */
161
- export async function readWaitComplete(worldPath, ids, completion, signal) {
186
+ export async function readWaitComplete(worldPath, ids, completion, signal, probe) {
162
187
  let completed = 0;
163
188
  for (const id of ids) {
164
189
  signal?.throwIfAborted();
165
190
  try {
166
191
  const paths = pathsForAkuId(worldPath, id);
167
- const observed = await bornObservation(paths, id, () => readLifeSnapshot(paths, signal));
168
- if (complete(observed.currentLife, observed.snapshot.hasPendingTell)) {
192
+ const ready = probe === undefined
193
+ ? await bornObservation(paths, id, () => readLifeSnapshot(paths, signal)).then((observed) => complete(observed.currentLife, observed.snapshot.hasPendingTell))
194
+ : await probe(id);
195
+ if (ready) {
169
196
  if (completion === "any")
170
197
  return true;
171
198
  completed += 1;
@@ -178,7 +205,8 @@ export async function readWaitComplete(worldPath, ids, completion, signal) {
178
205
  }
179
206
  return ids.length > 0 && completed === ids.length;
180
207
  }
181
- const OBSERVATION_POLL_MS = 100;
208
+ /** The one observation cadence public waiting and timeline streaming share. */
209
+ export const OBSERVATION_POLL_MS = 100;
182
210
  /**
183
211
  * The one deadline-aware observation loop for public Akuma waiting. It always
184
212
  * reads once before judging a passed deadline, so a zero-duration wait remains
@@ -190,22 +218,18 @@ export async function waitForObservation(input) {
190
218
  input.signal?.throwIfAborted();
191
219
  const ready = input.probe === undefined || (await input.probe());
192
220
  input.signal?.throwIfAborted();
193
- if (!ready && (deadline === undefined || performance.now() < deadline)) {
194
- await abortableDelay(deadline === undefined
195
- ? OBSERVATION_POLL_MS
196
- : Math.min(OBSERVATION_POLL_MS, Math.max(0, deadline - performance.now())), input.signal);
197
- continue;
221
+ if (ready || (deadline !== undefined && performance.now() >= deadline)) {
222
+ const value = await input.observe();
223
+ input.signal?.throwIfAborted();
224
+ await input.onObserve?.(value);
225
+ if (input.complete(value))
226
+ return { reason: "completed", value };
227
+ if (deadline !== undefined && performance.now() >= deadline)
228
+ return { reason: "deadline", value };
198
229
  }
199
- const value = await input.observe();
200
- input.signal?.throwIfAborted();
201
- await input.onObserve?.(value);
202
- if (input.complete(value))
203
- return { reason: "completed", value };
204
- if (deadline !== undefined && performance.now() >= deadline)
205
- return { reason: "deadline", value };
206
230
  await abortableDelay(deadline === undefined
207
- ? OBSERVATION_POLL_MS
208
- : Math.min(OBSERVATION_POLL_MS, Math.max(0, deadline - performance.now())), input.signal);
231
+ ? (input.pollMs ?? OBSERVATION_POLL_MS)
232
+ : Math.min(input.pollMs ?? OBSERVATION_POLL_MS, Math.max(0, deadline - performance.now())), input.signal);
209
233
  }
210
234
  }
211
235
  export async function readAkumaBirthCwd(worldPath, id) {
@@ -1,6 +1,7 @@
1
1
  import { type AkumaCaller } from "./caller.js";
2
2
  import type { WorldRoot } from "../world.js";
3
3
  import { type OutcomeObserver, type LiveStatusObservation, type WaitReason } from "./akuma-observe.js";
4
+ import { type AkumaStreamSnapshot } from "./akuma-stream.js";
4
5
  import type { AkumaStatus } from "./akuma.js";
5
6
  import { type TellResult, type TellWakeRuntime } from "./body.js";
6
7
  import { type CallInitialTell, type CallInitialTellAdmission } from "./call-initial-tell.js";
@@ -64,7 +65,7 @@ export declare function killAkumaWithRecovery(paths: AkumaPaths, recover?: (path
64
65
  * The one lower native Akuma owner: standalone identity, plural selection and
65
66
  * the request service all consume these same single-target algorithms. It reads
66
67
  * only Heart, leash, provider and filesystem state; optional Alias, Dispatch,
67
- * Task and Contract associations are composed above this boundary.
68
+ * Debt and Contract associations are composed above this boundary.
68
69
  */
69
70
  export declare class AkumaOwner {
70
71
  readonly id: AkuId;
@@ -81,6 +82,14 @@ export declare class AkumaOwner {
81
82
  since?: number;
82
83
  limit?: number;
83
84
  }>): Promise<ActivityHistory | ExactHistory>;
85
+ /**
86
+ * Continuously observe that same retained timeline. Each emission is the whole
87
+ * latest bounded window through the existing history projection, and the
88
+ * operation observes until its caller stops pulling or aborts.
89
+ */
90
+ stream(options?: Readonly<{
91
+ signal?: AbortSignal;
92
+ }>): AsyncIterable<AkumaStreamSnapshot>;
84
93
  waitReceipt(predicate?: (status: AkumaStatus) => boolean, options?: Readonly<{
85
94
  timeoutMs?: number;
86
95
  signal?: AbortSignal;
@@ -122,12 +131,12 @@ export declare class AkumaOwner {
122
131
  timeoutMs?: number;
123
132
  signal?: AbortSignal;
124
133
  observe?: (observation: LiveStatusObservation) => void | Promise<void>;
134
+ wake?: () => "launching" | "settled" | "failed";
125
135
  }>): Promise<Readonly<{
126
136
  reason: WaitReason;
127
137
  outcome: TurnOutcome | null;
128
138
  completedAt: string | null;
129
139
  }>>;
130
- private boundTellOutcome;
131
140
  interrupt(body: string, options?: Readonly<{
132
141
  tellId?: string;
133
142
  schemaJson?: string;
@@ -1,12 +1,13 @@
1
1
  import { decodeAkumaCaller } from "./caller.js";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { AkumaNotBornError, AkumaProviderError } from "./akuma-errors.js";
4
- import { bornLiveStatus, bornStatus, defaultWaitComplete, observeOutcomeRows, observeStatusOutcome, waitForObservation, } from "./akuma-observe.js";
4
+ import { createLiveStatusReader, bornStatus, defaultWaitComplete, executionProgress, observeOutcomeRows, observeStatusOutcome, waitForObservation, } from "./akuma-observe.js";
5
5
  import { executeWaitAkuma } from "./akuma-wait.js";
6
+ import { createAkumaStream } from "./akuma-stream.js";
6
7
  import { handoffPendingTells, spawnAkumaBody, wakeRecordedTell, } from "./body.js";
7
8
  import { admitCallInitialTell } from "./call-initial-tell.js";
8
9
  import { acquireLeash } from "./control.js";
9
- import { HeldAkumaLeash, activitySlice, projectTell, readForkPoint, readHeart, readKill, readLastAnsweredTurn, readSoul, readTell, readTurn, recordTell, requestPause, requestStop, } from "./heart/index.js";
10
+ import { HeldAkumaLeash, activitySlice, projectTell, readForkPoint, readHeart, readKill, readLastAnsweredTurn, readSoul, readTell, recordTell, requestPause, requestStop, } from "./heart/index.js";
10
11
  import { parsePublicHistoryId, pathsForAkuId } from "./identity.js";
11
12
  import { projectTurns, selectExactHistory, selectHistory } from "./projection.js";
12
13
  import { resolveProviderExecution } from "./providers/index.js";
@@ -84,7 +85,7 @@ export async function killAkumaWithRecovery(paths, recover, signal) {
84
85
  * The one lower native Akuma owner: standalone identity, plural selection and
85
86
  * the request service all consume these same single-target algorithms. It reads
86
87
  * only Heart, leash, provider and filesystem state; optional Alias, Dispatch,
87
- * Task and Contract associations are composed above this boundary.
88
+ * Debt and Contract associations are composed above this boundary.
88
89
  */
89
90
  export class AkumaOwner {
90
91
  id;
@@ -146,6 +147,14 @@ export class AkumaOwner {
146
147
  await observeOutcomeRows(this.id, history.rows, this.outcomeObserved);
147
148
  return history;
148
149
  }
150
+ /**
151
+ * Continuously observe that same retained timeline. Each emission is the whole
152
+ * latest bounded window through the existing history projection, and the
153
+ * operation observes until its caller stops pulling or aborts.
154
+ */
155
+ stream(options = {}) {
156
+ return createAkumaStream(this.paths, this.id, options, this.outcomeObserved);
157
+ }
149
158
  async waitReceipt(predicate = defaultWaitComplete, options = {}) {
150
159
  if (options.timeoutMs !== undefined && (!Number.isFinite(options.timeoutMs) || options.timeoutMs < 0)) {
151
160
  throw new TypeError("Akuma wait timeoutMs must be a nonnegative finite millisecond duration");
@@ -224,38 +233,39 @@ export class AkumaOwner {
224
233
  }
225
234
  /** Observe the exact admitted Tell's bound Turn without substituting Akuma-wide idleness. */
226
235
  async tellOutcome(tellId, options = {}) {
227
- const waited = await waitForObservation({
228
- ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
229
- ...(options.signal === undefined ? {} : { signal: options.signal }),
230
- observe: async () => {
231
- const tell = await readTell(this.paths, tellId);
232
- if (tell === null)
233
- throw new AkumaProviderError(`recorded Tell ${tellId} is missing from Heart`);
234
- const outcome = await this.boundTellOutcome(tell);
235
- if (outcome.historyId !== undefined)
236
- await this.outcomeObserved?.(this.id, [outcome.historyId]);
237
- if (options.observe !== undefined) {
238
- await options.observe(await bornLiveStatus(this.paths, this.id, { aperture: "monitoring", admittedTellId: tellId }));
239
- }
240
- return { ...outcome, terminalWithoutTurn: tell.state === "told" && tell.binding === undefined };
241
- },
242
- complete: (observed) => observed.outcome !== null || observed.terminalWithoutTurn,
243
- });
244
- return {
245
- reason: waited.reason,
246
- outcome: waited.value.outcome,
247
- completedAt: waited.value.completedAt,
248
- };
249
- }
250
- async boundTellOutcome(tell) {
251
- if (tell.binding === undefined)
252
- return { outcome: null, completedAt: null };
253
- const end = (await readTurn(this.paths, tell.binding.turnSequence))?.end;
254
- return {
255
- outcome: end?.outcome ?? null,
256
- completedAt: end?.completedAt ?? null,
257
- ...(end === undefined ? {} : { historyId: `turn/${tell.binding.turnSequence}` }),
258
- };
236
+ const reader = createLiveStatusReader(this.paths, this.id);
237
+ try {
238
+ const waited = await waitForObservation({
239
+ ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
240
+ ...(options.signal === undefined ? {} : { signal: options.signal }),
241
+ observe: async () => {
242
+ const currentLife = await reader.execution(options.signal);
243
+ const progress = executionProgress(currentLife, true, options.wake?.());
244
+ const { tell, end } = await reader.tellOutcome(tellId, options.signal);
245
+ if (tell === null)
246
+ throw new AkumaProviderError(`recorded Tell ${tellId} is missing from Heart`);
247
+ if (end !== undefined)
248
+ await this.outcomeObserved?.(this.id, [`turn/${end.turnSequence}`]);
249
+ if (options.observe !== undefined) {
250
+ await options.observe(await reader.read({ aperture: "monitoring", admittedTellId: tellId }, options.signal));
251
+ }
252
+ return {
253
+ outcome: end?.outcome ?? null,
254
+ completedAt: end?.completedAt ?? null,
255
+ terminalWithoutTurn: (tell.state === "told" && tell.binding === undefined) || progress === "stopped",
256
+ };
257
+ },
258
+ complete: (observed) => observed.outcome !== null || observed.terminalWithoutTurn,
259
+ });
260
+ return {
261
+ reason: waited.reason,
262
+ outcome: waited.value.outcome,
263
+ completedAt: waited.value.completedAt,
264
+ };
265
+ }
266
+ finally {
267
+ reader.clear();
268
+ }
259
269
  }
260
270
  async interrupt(body, options = {}) {
261
271
  const admitted = await this.admitInterrupt(body, options);
@@ -68,9 +68,12 @@ export async function observeAdmittedAskAkuma(input) {
68
68
  const tell = input.receipt ?? (await owner.admittedReceipt(input.tellId));
69
69
  await input.onObserve?.admitted?.(tell, input.id);
70
70
  let settled;
71
+ let wakeError;
72
+ let wakeState = input.wake === undefined ? "settled" : "launching";
71
73
  void input.wake?.then((receipt) => {
72
74
  settled = receipt;
73
- }, () => undefined);
75
+ wakeState = receipt.wake.kind === "failed" ? "failed" : "settled";
76
+ }, (error) => { wakeError = { error }; wakeState = "failed"; });
74
77
  const admittedAt = Date.parse(tell.row.at);
75
78
  const observedAt = performance.timeOrigin + performance.now();
76
79
  const elapsed = input.startedAt === undefined
@@ -79,6 +82,11 @@ export async function observeAdmittedAskAkuma(input) {
79
82
  : 0
80
83
  : Math.max(0, performance.now() - input.startedAt);
81
84
  const observed = await owner.tellOutcome(input.tellId, {
85
+ wake: () => {
86
+ if (wakeError !== undefined)
87
+ throw wakeError.error;
88
+ return wakeState;
89
+ },
82
90
  ...(input.timeoutMs === undefined ? {} : { timeoutMs: Math.max(0, input.timeoutMs - elapsed) }),
83
91
  ...(input.signal === undefined ? {} : { signal: input.signal }),
84
92
  ...(input.onObserve?.observe === undefined ? {} : { observe: input.onObserve.observe }),
@@ -0,0 +1,22 @@
1
+ import { type OutcomeObserver } from "./akuma-observe.js";
2
+ import type { AkuId, AkumaPaths } from "./identity.js";
3
+ import { type ActivityHistory } from "./projection.js";
4
+ /** The complete bounded latest timeline window one stream emission carries; never a delta. */
5
+ export type AkumaStreamSnapshot = ActivityHistory;
6
+ /**
7
+ * The one continuous timeline observation as its caller sees it: pull-driven,
8
+ * so a slow consumer accumulates no queue.
9
+ *
10
+ * The observation runs behind this wrapper because a bare async generator
11
+ * cannot honour an end request while a pull is pending: `return()` would queue
12
+ * behind a pull that an idle timeline never settles, and the observation would
13
+ * hold its reader and its polling timer forever. The wrapper owns an internal
14
+ * controller instead, and the observation watches the caller's cancellation
15
+ * composed with it. `return` aborts that controller, which settles the pending
16
+ * poll and lets the loop release its reader in the same turn; because a
17
+ * composed signal keeps the reason of whichever source aborted first, an end
18
+ * request reads as completion while a caller's own abort keeps its own failure.
19
+ */
20
+ export declare function createAkumaStream(paths: AkumaPaths, id: AkuId, options?: Readonly<{
21
+ signal?: AbortSignal;
22
+ }>, observe?: OutcomeObserver): AsyncIterableIterator<AkumaStreamSnapshot>;