@astrosheep/keiyaku 4.0.0 → 4.0.2

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 (308) hide show
  1. package/README.md +133 -8
  2. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +2 -2
  3. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +4 -4
  4. package/build/integrations/marketplace/plugins/keiyaku/opencode.js +2 -2
  5. package/build/integrations/marketplace/plugins/keiyaku/package.json +2 -2
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +13 -5
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -32
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +134 -0
  9. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/agents/openai.yaml +4 -0
  10. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +41 -6
  11. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +262 -46
  12. package/build/src/akuma/abort.d.ts +2 -0
  13. package/build/src/akuma/abort.js +50 -0
  14. package/build/src/akuma/akuma.d.ts +50 -33
  15. package/build/src/akuma/akuma.js +175 -127
  16. package/build/src/akuma/archetype.d.ts +14 -5
  17. package/build/src/akuma/archetype.js +85 -39
  18. package/build/src/akuma/body.d.ts +3 -5
  19. package/build/src/akuma/body.js +490 -183
  20. package/build/src/akuma/coordinate.d.ts +9 -0
  21. package/build/src/akuma/coordinate.js +22 -0
  22. package/build/src/akuma/heart/facts.d.ts +88 -45
  23. package/build/src/akuma/heart/facts.js +19 -8
  24. package/build/src/akuma/heart/index.d.ts +64 -55
  25. package/build/src/akuma/heart/index.js +172 -252
  26. package/build/src/akuma/heart/rows.d.ts +38 -83
  27. package/build/src/akuma/heart/rows.js +117 -155
  28. package/build/src/akuma/heart/schema.d.ts +1 -1
  29. package/build/src/akuma/heart/schema.js +61 -22
  30. package/build/src/akuma/heart/soul.d.ts +8 -0
  31. package/build/src/akuma/heart/soul.js +136 -0
  32. package/build/src/akuma/heart/storage.d.ts +47 -0
  33. package/build/src/akuma/heart/storage.js +224 -0
  34. package/build/src/akuma/heart/tells.d.ts +12 -0
  35. package/build/src/akuma/heart/tells.js +79 -0
  36. package/build/src/akuma/heart/timeline.d.ts +15 -0
  37. package/build/src/akuma/heart/timeline.js +86 -0
  38. package/build/src/akuma/identity.d.ts +2 -2
  39. package/build/src/akuma/identity.js +9 -9
  40. package/build/src/akuma/index.d.ts +10 -3
  41. package/build/src/akuma/index.js +7 -1
  42. package/build/src/akuma/projection.d.ts +176 -0
  43. package/build/src/akuma/projection.js +256 -0
  44. package/build/src/akuma/provider-recipe.d.ts +24 -0
  45. package/build/src/akuma/provider-recipe.js +100 -0
  46. package/build/src/akuma/provider.d.ts +67 -13
  47. package/build/src/akuma/provider.js +172 -105
  48. package/build/src/akuma/providers/acp/core.d.ts +19 -0
  49. package/build/src/akuma/providers/acp/core.js +159 -0
  50. package/build/src/akuma/providers/acp/events.d.ts +20 -0
  51. package/build/src/akuma/providers/acp/events.js +73 -0
  52. package/build/src/akuma/providers/acp/index.d.ts +12 -0
  53. package/build/src/akuma/providers/acp/index.js +94 -0
  54. package/build/src/akuma/providers/{claude.d.ts → claude/events.d.ts} +9 -41
  55. package/build/src/akuma/providers/claude/events.js +238 -0
  56. package/build/src/akuma/providers/claude/index.d.ts +47 -0
  57. package/build/src/akuma/providers/claude/index.js +279 -0
  58. package/build/src/akuma/providers/claude/input.d.ts +13 -0
  59. package/build/src/akuma/providers/claude/input.js +109 -0
  60. package/build/src/akuma/providers/codex-app-server/events.d.ts +1 -1
  61. package/build/src/akuma/providers/codex-app-server/events.js +15 -12
  62. package/build/src/akuma/providers/codex-app-server/index.d.ts +15 -13
  63. package/build/src/akuma/providers/codex-app-server/index.js +77 -33
  64. package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
  65. package/build/src/akuma/providers/grok-build/index.js +70 -0
  66. package/build/src/akuma/providers/index.d.ts +5 -3
  67. package/build/src/akuma/providers/index.js +35 -56
  68. package/build/src/akuma/providers/opencode-sdk/events.d.ts +54 -0
  69. package/build/src/akuma/providers/opencode-sdk/events.js +235 -0
  70. package/build/src/akuma/providers/opencode-sdk/index.d.ts +33 -0
  71. package/build/src/akuma/providers/opencode-sdk/index.js +308 -0
  72. package/build/src/akuma/providers/opencode-sdk/session.d.ts +26 -0
  73. package/build/src/akuma/providers/opencode-sdk/session.js +63 -0
  74. package/build/src/akuma/providers/pi/events.d.ts +33 -0
  75. package/build/src/akuma/providers/pi/events.js +166 -0
  76. package/build/src/akuma/providers/pi/index.d.ts +11 -0
  77. package/build/src/akuma/providers/pi/index.js +191 -0
  78. package/build/src/akuma/publication.d.ts +3 -3
  79. package/build/src/akuma/publication.js +28 -40
  80. package/build/src/akuma/requests.d.ts +9 -6
  81. package/build/src/akuma/requests.js +95 -65
  82. package/build/src/alias/index.d.ts +4 -3
  83. package/build/src/alias/index.js +12 -13
  84. package/build/src/body/decode.js +7 -1
  85. package/build/src/body/region.d.ts +2 -0
  86. package/build/src/body/region.js +77 -7
  87. package/build/src/body/render.js +2 -1
  88. package/build/src/body/shape.js +7 -1
  89. package/build/src/body/verification.js +19 -4
  90. package/build/src/cli/accepted.d.ts +18 -12
  91. package/build/src/cli/accepted.js +73 -34
  92. package/build/src/cli/actor.js +3 -3
  93. package/build/src/cli/commands/akuma-invoke.d.ts +44 -19
  94. package/build/src/cli/commands/akuma-invoke.js +101 -52
  95. package/build/src/cli/commands/akuma.d.ts +27 -9
  96. package/build/src/cli/commands/akuma.js +151 -80
  97. package/build/src/cli/commands/contract.d.ts +155 -0
  98. package/build/src/cli/commands/contract.js +20 -0
  99. package/build/src/cli/commands/install.js +2 -0
  100. package/build/src/cli/commands/task-invoke.d.ts +19 -4
  101. package/build/src/cli/commands/task-invoke.js +65 -17
  102. package/build/src/cli/commands/task-query.d.ts +5 -0
  103. package/build/src/cli/commands/task-query.js +247 -0
  104. package/build/src/cli/commands/task.d.ts +3 -1
  105. package/build/src/cli/commands/task.js +52 -14
  106. package/build/src/cli/coordinates.d.ts +18 -0
  107. package/build/src/cli/coordinates.js +120 -0
  108. package/build/src/cli/draft.d.ts +8 -0
  109. package/build/src/cli/draft.js +96 -0
  110. package/build/src/cli/invoke.d.ts +9 -3
  111. package/build/src/cli/invoke.js +287 -108
  112. package/build/src/cli/main.js +54 -7
  113. package/build/src/cli/parse.d.ts +21 -117
  114. package/build/src/cli/parse.js +79 -84
  115. package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
  116. package/build/src/cli/render/akuma-tool-command.js +144 -0
  117. package/build/src/cli/render/akuma-tool.d.ts +4 -2
  118. package/build/src/cli/render/akuma-tool.js +35 -5
  119. package/build/src/cli/render/akuma.d.ts +3 -1
  120. package/build/src/cli/render/akuma.js +247 -212
  121. package/build/src/cli/render/audit.d.ts +3 -0
  122. package/build/src/cli/render/audit.js +104 -0
  123. package/build/src/cli/render/catalog.d.ts +2 -0
  124. package/build/src/cli/render/catalog.js +16 -0
  125. package/build/src/cli/render/contract.d.ts +3 -3
  126. package/build/src/cli/render/contract.js +200 -54
  127. package/build/src/cli/render/kanshi.js +272 -129
  128. package/build/src/cli/render/receipt.d.ts +19 -0
  129. package/build/src/cli/render/receipt.js +106 -0
  130. package/build/src/cli/render/refusal.d.ts +16 -2
  131. package/build/src/cli/render/refusal.js +88 -3
  132. package/build/src/cli/render/region.d.ts +2 -0
  133. package/build/src/cli/render/region.js +17 -0
  134. package/build/src/cli/render/task.d.ts +2 -1
  135. package/build/src/cli/render/task.js +223 -60
  136. package/build/src/cli/render/terminal.d.ts +20 -0
  137. package/build/src/cli/render/terminal.js +121 -0
  138. package/build/src/cli/render/text.js +11 -3
  139. package/build/src/cli/result.d.ts +126 -19
  140. package/build/src/cli/usage.d.ts +1 -0
  141. package/build/src/cli/usage.js +3 -0
  142. package/build/src/contract-worktree.d.ts +44 -0
  143. package/build/src/contract-worktree.js +251 -0
  144. package/build/src/coordination/durable-file.d.ts +5 -1
  145. package/build/src/coordination/durable-file.js +57 -10
  146. package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
  147. package/build/src/coordination/sqlite-transaction-lock.js +22 -5
  148. package/build/src/core/facts/codec.js +23 -4
  149. package/build/src/core/facts/eligibility.d.ts +1 -10
  150. package/build/src/core/facts/eligibility.js +0 -49
  151. package/build/src/core/facts/fold.js +1 -6
  152. package/build/src/core/facts/gate.d.ts +1 -0
  153. package/build/src/core/facts/gate.js +1 -0
  154. package/build/src/core/facts/observation.d.ts +3 -0
  155. package/build/src/core/facts/observation.js +12 -0
  156. package/build/src/core/facts/types.d.ts +10 -3
  157. package/build/src/core/subject.js +2 -2
  158. package/build/src/core/verbs/amend.d.ts +1 -1
  159. package/build/src/core/verbs/amend.js +3 -18
  160. package/build/src/core/verbs/bind.js +2 -16
  161. package/build/src/core/verbs/deliver.d.ts +1 -1
  162. package/build/src/core/verbs/deliver.js +14 -4
  163. package/build/src/core/verbs/placement.d.ts +1 -1
  164. package/build/src/core/verbs/placement.js +7 -9
  165. package/build/src/dispatch/index.d.ts +5 -3
  166. package/build/src/dispatch/index.js +30 -21
  167. package/build/src/duration.d.ts +10 -0
  168. package/build/src/duration.js +22 -0
  169. package/build/src/git/admission.d.ts +2 -2
  170. package/build/src/git/admission.js +33 -23
  171. package/build/src/git/hooks.d.ts +15 -0
  172. package/build/src/git/hooks.js +70 -18
  173. package/build/src/git/identity.d.ts +5 -1
  174. package/build/src/git/identity.js +23 -4
  175. package/build/src/git/integration.d.ts +48 -0
  176. package/build/src/git/integration.js +250 -0
  177. package/build/src/git/observe.d.ts +29 -15
  178. package/build/src/git/observe.js +185 -76
  179. package/build/src/git/read-observation.d.ts +41 -0
  180. package/build/src/git/read-observation.js +361 -0
  181. package/build/src/git/reconcile.d.ts +17 -5
  182. package/build/src/git/reconcile.js +305 -109
  183. package/build/src/git/repository.d.ts +41 -18
  184. package/build/src/git/repository.js +220 -114
  185. package/build/src/git/scratch.d.ts +17 -0
  186. package/build/src/git/scratch.js +73 -0
  187. package/build/src/git/target-placement.d.ts +92 -0
  188. package/build/src/git/target-placement.js +375 -0
  189. package/build/src/git/tender.d.ts +49 -0
  190. package/build/src/git/tender.js +63 -0
  191. package/build/src/git/terminal-seal.d.ts +24 -0
  192. package/build/src/git/terminal-seal.js +89 -0
  193. package/build/src/git/tree.d.ts +2 -2
  194. package/build/src/git/tree.js +4 -0
  195. package/build/src/git/workspace.d.ts +53 -0
  196. package/build/src/git/workspace.js +139 -0
  197. package/build/src/identity/selector.d.ts +6 -0
  198. package/build/src/identity/selector.js +19 -0
  199. package/build/src/index.d.ts +4 -2
  200. package/build/src/index.js +2 -1
  201. package/build/src/kanshi/index.d.ts +2 -2
  202. package/build/src/kanshi/index.js +1 -1
  203. package/build/src/kanshi/read.d.ts +7 -3
  204. package/build/src/kanshi/read.js +245 -45
  205. package/build/src/kanshi/report.d.ts +81 -6
  206. package/build/src/kanshi/select.d.ts +5 -0
  207. package/build/src/kanshi/select.js +33 -1
  208. package/build/src/library/address.d.ts +57 -0
  209. package/build/src/library/address.js +165 -0
  210. package/build/src/library/akuma-creation.d.ts +16 -7
  211. package/build/src/library/akuma-creation.js +96 -22
  212. package/build/src/library/audit.d.ts +18 -0
  213. package/build/src/library/audit.js +44 -0
  214. package/build/src/library/bind.d.ts +21 -0
  215. package/build/src/library/bind.js +56 -0
  216. package/build/src/library/catalog.d.ts +58 -0
  217. package/build/src/library/catalog.js +69 -0
  218. package/build/src/library/configuration.d.ts +6 -15
  219. package/build/src/library/configuration.js +14 -17
  220. package/build/src/library/contract.d.ts +23 -49
  221. package/build/src/library/contract.js +171 -185
  222. package/build/src/library/delivery.d.ts +24 -0
  223. package/build/src/library/delivery.js +21 -0
  224. package/build/src/library/fleet.d.ts +65 -0
  225. package/build/src/library/fleet.js +153 -0
  226. package/build/src/library/input.d.ts +3 -0
  227. package/build/src/library/input.js +19 -0
  228. package/build/src/library/keiyaku.d.ts +18 -3
  229. package/build/src/library/keiyaku.js +12 -1
  230. package/build/src/library/mutation.d.ts +39 -0
  231. package/build/src/library/mutation.js +37 -0
  232. package/build/src/library/reconcile.d.ts +29 -0
  233. package/build/src/library/reconcile.js +179 -0
  234. package/build/src/library/refusal.d.ts +21 -0
  235. package/build/src/library/refusal.js +29 -0
  236. package/build/src/library/region.d.ts +14 -1
  237. package/build/src/library/region.js +18 -4
  238. package/build/src/library/repo.d.ts +4 -13
  239. package/build/src/library/repo.js +14 -24
  240. package/build/src/protocol/attempt.d.ts +16 -3
  241. package/build/src/protocol/attempt.js +41 -10
  242. package/build/src/protocol/bind.d.ts +9 -2
  243. package/build/src/protocol/bind.js +48 -40
  244. package/build/src/protocol/intent.d.ts +57 -20
  245. package/build/src/protocol/intent.js +55 -79
  246. package/build/src/protocol/operations.d.ts +152 -43
  247. package/build/src/protocol/operations.js +482 -166
  248. package/build/src/protocol/outcome.d.ts +14 -3
  249. package/build/src/protocol/outcome.js +11 -3
  250. package/build/src/protocol/placement.d.ts +41 -0
  251. package/build/src/protocol/placement.js +147 -0
  252. package/build/src/protocol/read/documents.d.ts +2 -2
  253. package/build/src/protocol/read/documents.js +4 -4
  254. package/build/src/protocol/read/status.d.ts +18 -5
  255. package/build/src/protocol/read/status.js +73 -13
  256. package/build/src/protocol/run.d.ts +49 -7
  257. package/build/src/protocol/run.js +53 -25
  258. package/build/src/runtime/proc/line-rpc.d.ts +4 -8
  259. package/build/src/runtime/proc/line-rpc.js +22 -28
  260. package/build/src/runtime/proc/run.d.ts +23 -21
  261. package/build/src/runtime/proc/run.js +123 -89
  262. package/build/src/runtime/proc/stdio.d.ts +18 -0
  263. package/build/src/runtime/proc/stdio.js +58 -0
  264. package/build/src/settings.d.ts +7 -1
  265. package/build/src/settings.js +32 -17
  266. package/build/src/settlement/fence.d.ts +5 -0
  267. package/build/src/settlement/fence.js +14 -0
  268. package/build/src/settlement/holder.d.ts +35 -4
  269. package/build/src/settlement/holder.js +127 -28
  270. package/build/src/settlement/settle.d.ts +9 -1
  271. package/build/src/settlement/settle.js +74 -37
  272. package/build/src/task/board.d.ts +23 -5
  273. package/build/src/task/board.js +17 -10
  274. package/build/src/task/compose.d.ts +2 -2
  275. package/build/src/task/compose.js +18 -10
  276. package/build/src/task/context.d.ts +3 -3
  277. package/build/src/task/context.js +15 -20
  278. package/build/src/task/document.d.ts +2 -1
  279. package/build/src/task/document.js +15 -5
  280. package/build/src/task/index.d.ts +27 -15
  281. package/build/src/task/index.js +57 -35
  282. package/build/src/task/operations.d.ts +38 -13
  283. package/build/src/task/operations.js +80 -46
  284. package/build/src/task/query.d.ts +67 -0
  285. package/build/src/task/query.js +279 -0
  286. package/build/src/task/store.d.ts +5 -7
  287. package/build/src/task/store.js +43 -28
  288. package/build/src/verification/declaration.d.ts +1 -0
  289. package/build/src/verification/execution.d.ts +51 -0
  290. package/build/src/verification/execution.js +108 -0
  291. package/build/src/workspace-place.d.ts +41 -0
  292. package/build/src/workspace-place.js +386 -0
  293. package/build/src/world.d.ts +24 -0
  294. package/build/src/world.js +136 -0
  295. package/package.json +8 -4
  296. package/build/src/akuma/activity.d.ts +0 -66
  297. package/build/src/akuma/activity.js +0 -139
  298. package/build/src/akuma/providers/claude.js +0 -305
  299. package/build/src/context-root.d.ts +0 -4
  300. package/build/src/context-root.js +0 -15
  301. package/build/src/git/delivery.d.ts +0 -20
  302. package/build/src/git/delivery.js +0 -109
  303. package/build/src/git/verification.d.ts +0 -14
  304. package/build/src/git/verification.js +0 -56
  305. package/build/src/protocol/read/audit.d.ts +0 -25
  306. package/build/src/protocol/read/audit.js +0 -39
  307. package/build/src/verification/producer.d.ts +0 -23
  308. package/build/src/verification/producer.js +0 -54
@@ -1,18 +1,16 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { readdirSync } from "node:fs";
2
+ import { readdir } from "node:fs/promises";
3
3
  import { resolve } from "node:path";
4
- import { spawnAkumaBody } from "./body.js";
5
- import { HeldAkumaLeash, activitySlice, life, probeLeash, readCurrentTurn, readHeart, readLastAnsweredTurn, readTurns, readForkPoint, readSeal, readSoul, recordDeath, recordTell, requestPause, requestStop, } from "./heart/index.js";
4
+ import { CONTROL_RESPONSE_MS, spawnAkumaBody } from "./body.js";
5
+ import { HeldAkumaLeash, activitySlice, life, lifeAt, probeLeash, readHeart, readLastAnsweredTurn, readForkPoint, readKill, readSeal, readSoul, recordTell, requestPause, requestStop, } from "./heart/index.js";
6
6
  import { akuIdFromDirectoryName, akumaPaths, akumaRunRoot, parseAkuId, pathsForAkuId, archetypeName, } from "./identity.js";
7
- import { projectActivityHistory, selectActivitySnapshot, } from "./activity.js";
7
+ import { ordinarySelectedCount, ordinarySnapshotBudget, projectTurns, selectActivitySnapshot, selectHistory, selectSnapshot, } from "./projection.js";
8
8
  import { listArchetypes as readArchetypes, loadArchetype } from "./archetype.js";
9
9
  import { publishAkuma } from "./publication.js";
10
- import { providerNamed } from "./providers/index.js";
10
+ import { resolveProviderExecution } from "./providers/index.js";
11
11
  import { injectedBodyRequests, requestBodyCall } from "./requests.js";
12
- import { probeProcessTree, putDownProcessTree } from "../runtime/proc/run.js";
13
12
  import { settings as readSettings } from "../settings.js";
14
13
  const POLL_MS = 25;
15
- const KILL_GRACE_MS = 1_000;
16
14
  export class AkumaNotBornError extends Error {
17
15
  id;
18
16
  kind = "akuma-not-born";
@@ -27,7 +25,7 @@ function wait(milliseconds) {
27
25
  }
28
26
  async function takeLeashUntil(paths, deadline) {
29
27
  for (;;) {
30
- const leash = HeldAkumaLeash.try(paths);
28
+ const leash = await HeldAkumaLeash.try(paths);
31
29
  if (leash !== null)
32
30
  return leash;
33
31
  if (performance.now() >= deadline)
@@ -35,74 +33,77 @@ async function takeLeashUntil(paths, deadline) {
35
33
  await wait(POLL_MS);
36
34
  }
37
35
  }
38
- function recordTellBody(paths, body) {
36
+ async function recordTellBody(paths, akuma, body) {
39
37
  const id = randomUUID();
40
- const admitted = recordTell(paths, { id, body, recordedAt: new Date().toISOString() });
41
- return admitted === "dead" ? { kind: "dead" } : { kind: "recorded", id };
38
+ const admitted = await recordTell(paths, { kind: "tell", id, body, recordedAt: new Date().toISOString() });
39
+ if (admitted.kind === "not-born")
40
+ throw new AkumaNotBornError(akuma);
41
+ return { kind: "recorded", tellId: admitted.tell.id };
42
42
  }
43
- async function wakeTell(paths, akuma, id) {
44
- const soul = readSoul(paths);
45
- if (soul === null)
46
- throw new Error(`Akuma ${akuma} has no soul`);
43
+ async function wakeTell(paths, tellId) {
47
44
  try {
48
45
  await spawnAkumaBody({ paths });
49
- return { id, state: "recorded", wake: "spawned" };
46
+ return { admission: { tellId, fact: "recorded" }, wake: "spawned" };
50
47
  }
51
48
  catch (error) {
52
49
  return {
53
- id,
54
- state: "recorded",
50
+ admission: { tellId, fact: "recorded" },
55
51
  wake: { kind: "failed", diagnostic: error instanceof Error ? error.message : String(error) },
56
52
  };
57
53
  }
58
54
  }
59
- function collarProbe(snapshot) {
60
- if (snapshot.latestBody === null)
61
- return { kind: "gone", end: null };
62
- const probe = probeProcessTree(snapshot.latestBody.collar);
63
- if (probe.kind === "gone")
64
- return { kind: "gone", end: snapshot.latestBody.end ?? null };
65
- return probe;
66
- }
67
- function bornListRow(paths, expected, snapshot = readHeart(paths)) {
55
+ async function bornListRow(paths, expected, snapshot) {
56
+ snapshot ??= await readHeart(paths);
68
57
  if (snapshot.soul === null)
69
58
  throw new AkumaNotBornError(expected);
70
59
  if (snapshot.soul.id !== expected)
71
60
  throw new Error("Akuma soul does not match its coordinate");
72
- const collar = collarProbe(snapshot);
61
+ const currentLife = life({
62
+ leash: await probeLeash(paths),
63
+ body: snapshot.latestBody,
64
+ kill: snapshot.latestKill,
65
+ });
73
66
  return {
74
67
  id: snapshot.soul.id,
75
68
  archetype: snapshot.soul.archetype,
76
69
  ...(snapshot.soul.description === undefined ? {} : { description: snapshot.soul.description }),
77
- life: life(probeLeash(paths), collar, snapshot.death),
78
- collar,
70
+ life: currentLife,
71
+ lifeAt: lifeAt(currentLife, snapshot.latestBody, snapshot.latestKill, snapshot.soul.createdAt),
79
72
  confinement: snapshot.soul.confinement,
80
73
  pending: snapshot.pending.map((tell) => tell.id),
81
74
  };
82
75
  }
83
- function bornStatus(paths, expected) {
84
- const snapshot = readHeart(paths);
76
+ async function bornStatus(paths, expected, budget) {
77
+ const snapshot = await readHeart(paths);
85
78
  if (snapshot.soul === null)
86
79
  throw new AkumaNotBornError(expected);
87
- const current = bornListRow(paths, expected, snapshot);
88
- const latest = readCurrentTurn(paths);
80
+ const current = await bornListRow(paths, expected, snapshot);
81
+ const resumeUnsupported = current.life === "stranded"
82
+ && snapshot.latestSession?.provider === snapshot.soul.provider.name
83
+ && resolveProviderExecution(snapshot.soul.provider).adapter.resume === undefined;
84
+ const slice = await activitySlice(paths, { limit: Number.MAX_SAFE_INTEGER });
89
85
  return {
90
- ...current,
91
- ...(latest === null ? {} : { outcomeAt: latest.completedAt }),
92
- ...(latest?.outcome.kind === "answered"
93
- ? { answer: latest.outcome.answer, answerHistoryId: latest.outcome.historyId }
94
- : {}),
95
- ...(latest?.outcome.kind === "failed" ? { failure: latest.outcome.diagnostic } : {}),
96
- activity: (() => {
97
- const slice = activitySlice(paths, { limit: 5_000 });
98
- return selectActivitySnapshot(slice.rows, {
99
- pending: snapshot.pending,
100
- lowestRetained: slice.lowestRetained,
101
- highest: slice.highest,
102
- });
103
- })(),
86
+ id: current.id,
87
+ life: current.life,
88
+ ...(snapshot.soul.readonly === undefined ? {} : { readonly: snapshot.soul.readonly }),
89
+ ...(resumeUnsupported ? { strandedReason: "resume-unsupported" } : {}),
90
+ timeline: budget === undefined
91
+ ? selectActivitySnapshot(slice.rows)
92
+ : selectSnapshot(projectTurns(slice.rows), budget),
104
93
  };
105
94
  }
95
+ /** Package-internal action observation; it uses the same snapshot selector as status. */
96
+ export async function readActionFeedbackStatus(worldPath, id) {
97
+ return await bornStatus(pathsForAkuId(worldPath, id), id);
98
+ }
99
+ /** Package-internal budgeted observation; Fleet allocates, Akuma still selects. */
100
+ export async function readBudgetedStatus(worldPath, id, input) {
101
+ if (!Number.isSafeInteger(input.ordinaryBudget) || input.ordinaryBudget < 0) {
102
+ throw new TypeError("ordinary budget must be a nonnegative safe integer");
103
+ }
104
+ const status = await bornStatus(pathsForAkuId(worldPath, id), id, ordinarySnapshotBudget(input.ordinaryBudget));
105
+ return { status, ordinarySelected: ordinarySelectedCount(status.timeline) };
106
+ }
106
107
  function diagnostic(error) {
107
108
  return error instanceof Error ? error.message : String(error);
108
109
  }
@@ -116,10 +117,10 @@ export class AkumaHandle {
116
117
  get paths() {
117
118
  return pathsForAkuId(this.worldPath, this.id);
118
119
  }
119
- status() {
120
- return bornStatus(this.paths, this.id);
120
+ async status() {
121
+ return await bornStatus(this.paths, this.id);
121
122
  }
122
- history(input = {}) {
123
+ async history(input = {}) {
123
124
  if (input.before !== undefined && input.since !== undefined) {
124
125
  throw new TypeError("Akuma history before and since are mutually exclusive");
125
126
  }
@@ -132,13 +133,17 @@ export class AkumaHandle {
132
133
  if (!Number.isSafeInteger(limit) || limit <= 0 || limit > 5_000) {
133
134
  throw new TypeError("Akuma history limit must be a positive safe integer no greater than 5000");
134
135
  }
135
- const slice = activitySlice(this.paths, {
136
+ const slice = await activitySlice(this.paths, {
136
137
  ...(input.before === undefined ? {} : { before: input.before }),
137
138
  ...(input.since === undefined ? {} : { since: input.since }),
138
139
  limit: 5_000,
139
140
  });
140
- return projectActivityHistory(slice, readTurns(this.paths), {
141
- since: input.since !== undefined,
141
+ return selectHistory(projectTurns(slice.rows, {
142
+ lowestRetained: slice.lowestRetained,
143
+ highest: slice.highest,
144
+ }), {
145
+ ...(input.before === undefined ? {} : { before: input.before }),
146
+ ...(input.since === undefined ? {} : { since: input.since }),
142
147
  limit,
143
148
  });
144
149
  }
@@ -149,66 +154,73 @@ export class AkumaHandle {
149
154
  }
150
155
  const deadline = options.timeoutMs === undefined ? undefined : performance.now() + options.timeoutMs;
151
156
  for (;;) {
152
- const status = this.status();
157
+ const status = await this.status();
153
158
  if (predicate(status) || (deadline !== undefined && performance.now() >= deadline))
154
159
  return status;
155
160
  await wait(deadline === undefined ? POLL_MS : Math.min(POLL_MS, Math.max(0, deadline - performance.now())));
156
161
  }
157
162
  }
158
163
  async tell(body) {
159
- const recorded = recordTellBody(this.paths, body);
160
- if (recorded.kind === "dead")
161
- throw new Error(`Akuma ${this.id} is dead`);
162
- return await wakeTell(this.paths, this.id, recorded.id);
164
+ const recorded = await recordTellBody(this.paths, this.id, body);
165
+ return await wakeTell(this.paths, recorded.tellId);
163
166
  }
164
167
  async interrupt(body) {
165
- if (requestPause(this.paths, new Date().toISOString()) === "dead")
166
- return { kind: "dead" };
168
+ const request = await requestPause(this.paths, new Date().toISOString());
169
+ if (request.kind === "not-born") {
170
+ throw new AkumaNotBornError(this.id);
171
+ }
167
172
  let putDown = "was-idle";
168
- let leash = HeldAkumaLeash.try(this.paths);
173
+ let leash = await HeldAkumaLeash.try(this.paths);
169
174
  if (leash === null) {
170
- leash = await takeLeashUntil(this.paths, performance.now() + KILL_GRACE_MS);
175
+ leash = await takeLeashUntil(this.paths, performance.now() + CONTROL_RESPONSE_MS);
171
176
  putDown = "self-aborted";
172
177
  }
173
178
  if (leash === null) {
174
- const current = readHeart(this.paths).latestBody;
175
- if (current === null)
176
- return { kind: "unstoppable", evidence: "no-collar" };
177
- if (probeProcessTree(current.collar).kind === "unverifiable") {
178
- return { kind: "unstoppable", evidence: "collar-unverifiable" };
179
+ const body = (await readHeart(this.paths)).latestBody;
180
+ return { kind: "unavailable", evidence: body?.sequence === request.body.sequence && body.hung !== undefined
181
+ ? "hung"
182
+ : "unavailable" };
183
+ }
184
+ const settledBody = (await readHeart(this.paths)).latestBody;
185
+ if (settledBody?.sequence !== request.body.sequence || settledBody.end === undefined) {
186
+ try {
187
+ await leash.clearPause(this.paths);
179
188
  }
180
- const evidence = await putDownProcessTree(current.collar);
181
- if (evidence === "unavailable" || evidence === "alive-after-sigkill") {
182
- return { kind: "unstoppable", evidence };
189
+ finally {
190
+ leash.release();
183
191
  }
184
- leash = await takeLeashUntil(this.paths, performance.now() + KILL_GRACE_MS);
185
- if (leash === null)
186
- return { kind: "unstoppable", evidence: "leash-held-after-put-down" };
187
- putDown = "collar";
192
+ return { kind: "unavailable", evidence: "untidy" };
188
193
  }
194
+ if (request.body.end !== undefined || settledBody.end !== "put-down")
195
+ putDown = "was-idle";
189
196
  let recorded;
190
197
  try {
191
- leash.clearPause(this.paths);
192
- recorded = recordTellBody(this.paths, body);
198
+ const id = randomUUID();
199
+ const admitted = await leash.recordInterruptTell(this.paths, {
200
+ kind: "tell",
201
+ id,
202
+ body,
203
+ recordedAt: new Date().toISOString(),
204
+ });
205
+ if (admitted.kind === "not-born")
206
+ throw new AkumaNotBornError(this.id);
207
+ recorded = { kind: "recorded", tellId: admitted.tell.id };
193
208
  }
194
209
  finally {
195
210
  leash.release();
196
211
  }
197
- if (recorded.kind === "dead") {
198
- return { kind: "interrupted", putDown, tell: { kind: "refused-dead" } };
199
- }
200
- return { kind: "interrupted", putDown, tell: await wakeTell(this.paths, this.id, recorded.id) };
212
+ return { kind: "interrupted", putDown, tell: await wakeTell(this.paths, recorded.tellId) };
201
213
  }
202
214
  async fork(input) {
203
- const source = readSoul(this.paths);
215
+ const source = await readSoul(this.paths);
204
216
  if (source === null)
205
217
  throw new AkumaNotBornError(this.id);
206
218
  if (source.id !== this.id)
207
219
  throw new Error("Akuma soul does not match its coordinate");
208
- const adapter = providerNamed(source.provider);
220
+ const adapter = resolveProviderExecution(source.provider).adapter;
209
221
  if (adapter.fork === undefined)
210
222
  return { kind: "provider-cannot-fork", provider: source.provider.name };
211
- const point = readForkPoint(this.paths, input.at);
223
+ const point = await readForkPoint(this.paths, input.at);
212
224
  if (point === null)
213
225
  return { kind: "unknown-history", at: input.at };
214
226
  if (point.provider !== source.provider.name)
@@ -241,6 +253,7 @@ export class AkumaHandle {
241
253
  ...(source.description === undefined ? {} : { description: source.description }),
242
254
  provider: source.provider,
243
255
  options: source.options,
256
+ ...(source.readonly === undefined ? {} : { readonly: source.readonly }),
244
257
  cwd: source.cwd,
245
258
  origin: { kind: "fork", parent: this.id, at: input.at },
246
259
  confinement: source.confinement,
@@ -256,57 +269,77 @@ export class AkumaHandle {
256
269
  }
257
270
  async kill() {
258
271
  const at = new Date().toISOString();
259
- if (requestStop(this.paths, at) === "dead")
260
- return "already-dead";
261
- const graceDeadline = performance.now() + KILL_GRACE_MS;
262
- while (probeLeash(this.paths) === "held" && performance.now() < graceDeadline)
263
- await wait(POLL_MS);
264
- if (probeLeash(this.paths) === "held") {
265
- const current = readHeart(this.paths).latestBody;
266
- if (current === null)
272
+ const request = await requestStop(this.paths, at);
273
+ if (request.kind !== "requested")
274
+ return request.kind;
275
+ const target = request.body;
276
+ const graceDeadline = performance.now() + CONTROL_RESPONSE_MS;
277
+ const leash = await takeLeashUntil(this.paths, graceDeadline);
278
+ if (await readKill(this.paths, target.sequence) !== null) {
279
+ leash?.release();
280
+ return "killed";
281
+ }
282
+ if (leash === null) {
283
+ if (await readKill(this.paths, target.sequence) !== null)
284
+ return "killed";
285
+ const body = (await readHeart(this.paths)).latestBody;
286
+ return body?.sequence === target.sequence && body.hung !== undefined ? "hung" : "unavailable";
287
+ }
288
+ try {
289
+ const settledBody = (await readHeart(this.paths)).latestBody;
290
+ if (settledBody?.sequence !== target.sequence)
291
+ return await readKill(this.paths, target.sequence) === null ? "unavailable" : "killed";
292
+ if (settledBody.end !== "put-down") {
293
+ await leash.clearStop(this.paths);
294
+ return "untidy";
295
+ }
296
+ const settled = await leash.settleStop(this.paths, target.sequence);
297
+ if (settled === null)
267
298
  return "unavailable";
268
- const evidence = await putDownProcessTree(current.collar);
269
- if (evidence === "unavailable" || evidence === "alive-after-sigkill")
270
- return evidence;
299
+ return "killed";
300
+ }
301
+ finally {
302
+ leash.release();
271
303
  }
272
- const releaseDeadline = performance.now() + KILL_GRACE_MS;
273
- while (probeLeash(this.paths) === "held" && performance.now() < releaseDeadline)
274
- await wait(POLL_MS);
275
- if (probeLeash(this.paths) === "held")
276
- return "unavailable";
277
- return recordDeath(this.paths, { evidence: "killed", at }) === "already-dead" ? "already-dead" : "killed";
278
304
  }
279
- lastAnswer() {
280
- const turn = readLastAnsweredTurn(this.paths);
281
- return turn?.outcome.kind === "answered" ? turn.outcome.answer : "";
305
+ async lastAnswer() {
306
+ const turn = await readLastAnsweredTurn(this.paths);
307
+ return turn?.end?.outcome.kind === "answered"
308
+ ? { kind: "answer", answer: turn.end.outcome.answer }
309
+ : { kind: "no-answer" };
282
310
  }
283
311
  }
284
312
  export class Akuma {
285
313
  path;
286
- settings;
287
- constructor(path, settings) {
314
+ configuredSettings;
315
+ constructor(path, configuredSettings) {
288
316
  this.path = path;
289
- this.settings = settings;
317
+ this.configuredSettings = configuredSettings;
318
+ }
319
+ static of(root, settings) {
320
+ if (typeof root !== "string")
321
+ throw new TypeError("Akuma.of root must be a WorldRoot");
322
+ return new Akuma(root, settings);
290
323
  }
291
- static at(input) {
292
- const path = resolve(input.path);
293
- return new Akuma(path, input.settings ?? readSettings({ root: path }));
324
+ async settings() {
325
+ return this.configuredSettings ?? await readSettings({ root: this.path });
294
326
  }
295
327
  of(input) {
296
328
  return new AkumaHandle(parseAkuId(input.id).id, this.path);
297
329
  }
298
- listArchetypes() {
299
- return readArchetypes({ settings: this.settings });
330
+ async listArchetypes() {
331
+ return readArchetypes({ settings: await this.settings() });
300
332
  }
301
333
  async call(input) {
302
334
  const name = archetypeName(input.archetype);
303
- const archetype = loadArchetype({ name, settings: this.settings });
335
+ const archetype = await loadArchetype({ name, settings: await this.settings() });
304
336
  const provider = archetype.adapter;
305
337
  const cwd = resolve(input.cwd ?? this.path);
306
338
  const recipe = Object.freeze({
307
339
  ...(archetype.description === undefined ? {} : { description: archetype.description }),
308
340
  provider: archetype.provider,
309
341
  options: archetype.options,
342
+ ...(archetype.readonly === undefined ? {} : { readonly: archetype.readonly }),
310
343
  confinement: provider.confinement({ cwd, options: archetype.options }),
311
344
  });
312
345
  const requests = injectedBodyRequests();
@@ -333,6 +366,7 @@ export class Akuma {
333
366
  ...(archetype.description === undefined ? {} : { description: archetype.description }),
334
367
  provider: archetype.provider,
335
368
  options: archetype.options,
369
+ ...(archetype.readonly === undefined ? {} : { readonly: archetype.readonly }),
336
370
  cwd,
337
371
  origin: { kind: "direct" },
338
372
  confinement: recipe.confinement,
@@ -342,11 +376,18 @@ export class Akuma {
342
376
  });
343
377
  return new AkumaHandle(published.id, this.path);
344
378
  }
345
- list() {
379
+ async list(input = {}) {
380
+ if (typeof input !== "object" || input === null || Array.isArray(input)) {
381
+ throw new TypeError("Akuma list input must be an object");
382
+ }
383
+ const unknown = Object.keys(input).find((key) => key !== "archetype");
384
+ if (unknown !== undefined)
385
+ throw new TypeError(`Akuma list input has unknown field: ${unknown}`);
386
+ const selected = input.archetype === undefined ? undefined : archetypeName(input.archetype);
346
387
  const runRoot = akumaRunRoot(this.path);
347
388
  let names;
348
389
  try {
349
- names = readdirSync(runRoot, { withFileTypes: true })
390
+ names = (await readdir(runRoot, { withFileTypes: true }))
350
391
  .filter((entry) => entry.isDirectory())
351
392
  .map((entry) => entry.name)
352
393
  .sort();
@@ -356,24 +397,31 @@ export class Akuma {
356
397
  return { rows: [], searched: [runRoot] };
357
398
  throw error;
358
399
  }
359
- const rows = names.flatMap((name) => {
400
+ const rows = [];
401
+ for (const name of names) {
360
402
  try {
361
403
  const physical = akuIdFromDirectoryName(name);
404
+ if (selected !== undefined && physical.archetype !== selected)
405
+ continue;
362
406
  const paths = akumaPaths({ runRoot, archetype: physical.archetype, suffix: physical.suffix });
363
- const snapshot = readHeart(paths);
364
- if (snapshot.soul !== null)
365
- return [bornListRow(paths, physical.id, snapshot)];
366
- if (probeLeash(paths) === "held")
367
- return [{ id: physical.id, life: "unborn" }];
368
- const seal = readSeal(paths);
369
- return seal === null
370
- ? [{ id: physical.id, life: "unborn" }]
371
- : [{ id: physical.id, life: "stillborn", seal }];
407
+ const snapshot = await readHeart(paths);
408
+ if (snapshot.soul !== null) {
409
+ rows.push(await bornListRow(paths, physical.id, snapshot));
410
+ continue;
411
+ }
412
+ if (await probeLeash(paths) === "held") {
413
+ rows.push({ id: physical.id, life: "unborn" });
414
+ continue;
415
+ }
416
+ const seal = await readSeal(paths);
417
+ rows.push(seal === null
418
+ ? { id: physical.id, life: "unborn" }
419
+ : { id: physical.id, life: "stillborn", seal });
372
420
  }
373
421
  catch {
374
- return [];
422
+ continue;
375
423
  }
376
- });
424
+ }
377
425
  return {
378
426
  rows,
379
427
  searched: [runRoot],
@@ -1,6 +1,6 @@
1
1
  import type { Settings } from "../settings.js";
2
- import { type ProviderAdapter, type ProviderOptions } from "./provider.js";
3
- import type { ProviderExecution } from "./heart/index.js";
2
+ import type { ProviderAdapter } from "./provider.js";
3
+ import { type ProviderExecution, type ProviderOptions, type ReadonlyRestraint } from "./provider-recipe.js";
4
4
  type DecodedArchetype = Readonly<{
5
5
  name: string;
6
6
  path: string;
@@ -8,24 +8,33 @@ type DecodedArchetype = Readonly<{
8
8
  description?: string;
9
9
  options: ProviderOptions;
10
10
  }>;
11
+ export type ArchetypeCatalogRow = Readonly<{
12
+ name: string;
13
+ model?: string;
14
+ description?: string;
15
+ }>;
11
16
  type ArchetypeDefinition = DecodedArchetype & Readonly<{
12
17
  adapter: ProviderAdapter;
13
18
  }>;
14
19
  type AdmittedArchetype = Omit<ArchetypeDefinition, "provider"> & Readonly<{
15
20
  provider: ProviderExecution;
21
+ readonly?: ReadonlyRestraint;
16
22
  }>;
17
23
  export declare class AkumaArchetypeError extends Error {
18
24
  readonly archetype: string;
19
25
  readonly searched: readonly string[];
20
26
  readonly reason: string;
21
27
  readonly kind = "akuma-archetype";
22
- constructor(archetype: string, searched: readonly string[], reason: string);
28
+ constructor(archetype: string, searched: readonly string[], reason: string, guidance?: string);
23
29
  }
24
30
  export declare function listArchetypes(input: Readonly<{
25
31
  settings: Settings;
26
- }>): readonly string[];
32
+ }>): Promise<readonly string[]>;
33
+ export declare function listArchetypeDefinitions(input: Readonly<{
34
+ settings: Settings;
35
+ }>): Promise<readonly ArchetypeCatalogRow[]>;
27
36
  export declare function loadArchetype(input: Readonly<{
28
37
  name: string;
29
38
  settings: Settings;
30
- }>): AdmittedArchetype;
39
+ }>): Promise<AdmittedArchetype>;
31
40
  export {};