@astrosheep/keiyaku 4.6.4 → 4.6.6

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 (191) hide show
  1. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +43 -8
  2. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +7 -8
  3. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -3
  4. package/build/src/akuma/akuma-observe.d.ts +18 -15
  5. package/build/src/akuma/akuma-observe.js +75 -16
  6. package/build/src/akuma/akuma-wait.d.ts +4 -3
  7. package/build/src/akuma/akuma-wait.js +75 -53
  8. package/build/src/akuma/akuma.d.ts +6 -4
  9. package/build/src/akuma/akuma.js +4 -0
  10. package/build/src/akuma/call-initial-tell.d.ts +2 -2
  11. package/build/src/akuma/call-initial-tell.js +1 -1
  12. package/build/src/akuma/call-request.d.ts +2 -2
  13. package/build/src/akuma/heart/index.d.ts +7 -2
  14. package/build/src/akuma/heart/index.js +50 -5
  15. package/build/src/akuma/heart/tells.d.ts +33 -2
  16. package/build/src/akuma/heart/tells.js +24 -18
  17. package/build/src/akuma/heart/timeline.d.ts +23 -1
  18. package/build/src/akuma/heart/timeline.js +28 -21
  19. package/build/src/akuma/projection.d.ts +10 -10
  20. package/build/src/akuma/providers/pi/index.js +72 -39
  21. package/build/src/akuma/selection-observation.d.ts +20 -20
  22. package/build/src/akuma-body.js +1 -0
  23. package/build/src/alias/index.d.ts +0 -1
  24. package/build/src/alias/index.js +0 -4
  25. package/build/src/body/amend.d.ts +0 -4
  26. package/build/src/body/amend.js +0 -3
  27. package/build/src/body/region.d.ts +0 -1
  28. package/build/src/body/region.js +0 -3
  29. package/build/src/body/verification.d.ts +0 -1
  30. package/build/src/cli/commands/akuma-grammar.js +23 -66
  31. package/build/src/cli/commands/akuma.js +17 -30
  32. package/build/src/cli/commands/contract-grammar.d.ts +14 -1
  33. package/build/src/cli/commands/contract-grammar.js +54 -21
  34. package/build/src/cli/commands/contract-help.d.ts +9 -8
  35. package/build/src/cli/commands/contract-help.js +14 -7
  36. package/build/src/cli/commands/contract.js +57 -117
  37. package/build/src/cli/commands/install.d.ts +5 -5
  38. package/build/src/cli/commands/install.js +1 -4
  39. package/build/src/cli/commands/task-grammar.js +10 -66
  40. package/build/src/cli/commands/task.d.ts +0 -1
  41. package/build/src/cli/commands/task.js +34 -53
  42. package/build/src/cli/coordinates.d.ts +1 -2
  43. package/build/src/cli/coordinates.js +1 -4
  44. package/build/src/cli/parse.d.ts +2 -3
  45. package/build/src/cli/parse.js +24 -66
  46. package/build/src/cli/render/akuma.d.ts +3 -16
  47. package/build/src/cli/render/akuma.js +1 -13
  48. package/build/src/cli/render/audit.js +1 -1
  49. package/build/src/cli/render/contract.js +34 -32
  50. package/build/src/cli/render/kanshi-akuma.d.ts +8 -2
  51. package/build/src/cli/render/kanshi-akuma.js +14 -7
  52. package/build/src/cli/render/kanshi.d.ts +3 -1
  53. package/build/src/cli/render/kanshi.js +44 -32
  54. package/build/src/cli/render/receipt.js +6 -1
  55. package/build/src/cli/render/task.d.ts +1 -1
  56. package/build/src/cli/render/task.js +3 -27
  57. package/build/src/cli/render/terminal.d.ts +6 -2
  58. package/build/src/cli/render/terminal.js +8 -2
  59. package/build/src/cli/runtime.js +3 -16
  60. package/build/src/cli/scan.d.ts +26 -0
  61. package/build/src/cli/scan.js +82 -0
  62. package/build/src/cli/streams.d.ts +5 -0
  63. package/build/src/cli/streams.js +11 -0
  64. package/build/src/contract-worktree.js +38 -21
  65. package/build/src/core/facts/codec.d.ts +1 -2
  66. package/build/src/core/facts/codec.js +5 -11
  67. package/build/src/core/facts/types.d.ts +16 -2
  68. package/build/src/core/facts/types.js +15 -0
  69. package/build/src/core/verbs/abandon.js +3 -9
  70. package/build/src/core/verbs/amend.js +2 -9
  71. package/build/src/core/verbs/arc.js +6 -13
  72. package/build/src/core/verbs/attestation.js +2 -9
  73. package/build/src/core/verbs/bind.js +2 -9
  74. package/build/src/core/verbs/deliver.js +2 -9
  75. package/build/src/core/verbs/placement.d.ts +1 -1
  76. package/build/src/core/verbs/placement.js +2 -9
  77. package/build/src/core/verbs/reintegrate.d.ts +1 -1
  78. package/build/src/core/verbs/reintegrate.js +2 -9
  79. package/build/src/dispatch/index.d.ts +2 -2
  80. package/build/src/dispatch/index.js +33 -11
  81. package/build/src/git/hooks.d.ts +2 -4
  82. package/build/src/git/hooks.js +0 -12
  83. package/build/src/git/integration.d.ts +5 -3
  84. package/build/src/git/integration.js +36 -25
  85. package/build/src/git/nuke.js +4 -4
  86. package/build/src/git/observe.d.ts +4 -4
  87. package/build/src/git/observe.js +5 -5
  88. package/build/src/git/process.d.ts +1 -4
  89. package/build/src/git/process.js +1 -11
  90. package/build/src/git/read-observation.js +1 -1
  91. package/build/src/git/reconcile.d.ts +1 -1
  92. package/build/src/git/reconcile.js +15 -13
  93. package/build/src/git/repository.d.ts +2 -6
  94. package/build/src/git/repository.js +18 -31
  95. package/build/src/git/scratch.d.ts +6 -6
  96. package/build/src/git/scratch.js +110 -46
  97. package/build/src/git/target-placement.d.ts +5 -5
  98. package/build/src/git/target-placement.js +18 -33
  99. package/build/src/git/tender.d.ts +6 -2
  100. package/build/src/git/tender.js +19 -12
  101. package/build/src/git/terminal-reconcile.js +24 -13
  102. package/build/src/git/terminal-seal.d.ts +2 -5
  103. package/build/src/git/terminal-seal.js +5 -3
  104. package/build/src/git/workspace.d.ts +17 -13
  105. package/build/src/git/workspace.js +58 -41
  106. package/build/src/kanshi/index.d.ts +2 -2
  107. package/build/src/kanshi/index.js +1 -1
  108. package/build/src/kanshi/read.d.ts +8 -1
  109. package/build/src/kanshi/read.js +72 -7
  110. package/build/src/kanshi/report.d.ts +12 -0
  111. package/build/src/library/akuma-creation.d.ts +4 -4
  112. package/build/src/library/bind.d.ts +1 -63
  113. package/build/src/library/bind.js +3 -9
  114. package/build/src/library/contract-creation.js +2 -30
  115. package/build/src/library/contract-execution.d.ts +0 -1
  116. package/build/src/library/contract-execution.js +9 -34
  117. package/build/src/library/contract-operations.d.ts +5 -1
  118. package/build/src/library/contract-operations.js +7 -3
  119. package/build/src/library/contract-types.d.ts +1 -1
  120. package/build/src/library/delivery.d.ts +91 -93
  121. package/build/src/library/delivery.js +2 -1
  122. package/build/src/library/input.d.ts +0 -2
  123. package/build/src/library/input.js +0 -4
  124. package/build/src/library/invocation.d.ts +0 -1
  125. package/build/src/library/invocation.js +3 -25
  126. package/build/src/library/outcome.d.ts +651 -602
  127. package/build/src/library/outcome.js +4 -4
  128. package/build/src/library/reconcile.d.ts +6 -0
  129. package/build/src/library/reconcile.js +31 -1
  130. package/build/src/library/repo.d.ts +0 -1
  131. package/build/src/library/selection.d.ts +1 -10
  132. package/build/src/library/selection.js +14 -15
  133. package/build/src/protocol/abandon.d.ts +1 -1
  134. package/build/src/protocol/abandon.js +3 -10
  135. package/build/src/protocol/amend.js +2 -5
  136. package/build/src/protocol/arc.d.ts +1 -1
  137. package/build/src/protocol/arc.js +2 -9
  138. package/build/src/protocol/attempt.d.ts +3 -20
  139. package/build/src/protocol/attempt.js +6 -5
  140. package/build/src/protocol/audit.d.ts +1 -0
  141. package/build/src/protocol/audit.js +10 -11
  142. package/build/src/protocol/completion.d.ts +129 -55
  143. package/build/src/protocol/completion.js +62 -73
  144. package/build/src/protocol/deliver.d.ts +7 -5
  145. package/build/src/protocol/deliver.js +74 -44
  146. package/build/src/protocol/execution-observation.d.ts +2 -4
  147. package/build/src/protocol/execution-observation.js +3 -7
  148. package/build/src/protocol/intent.d.ts +1 -1
  149. package/build/src/protocol/intent.js +1 -0
  150. package/build/src/protocol/operations.d.ts +24 -12
  151. package/build/src/protocol/operations.js +36 -15
  152. package/build/src/protocol/placement.d.ts +2 -1
  153. package/build/src/protocol/placement.js +21 -5
  154. package/build/src/protocol/progress.d.ts +1 -1
  155. package/build/src/protocol/read/status.js +58 -41
  156. package/build/src/protocol/reintegrate.d.ts +1 -1
  157. package/build/src/protocol/reintegrate.js +10 -19
  158. package/build/src/protocol/review.d.ts +3 -28
  159. package/build/src/protocol/review.js +10 -37
  160. package/build/src/protocol/run.d.ts +19 -7
  161. package/build/src/protocol/run.js +19 -9
  162. package/build/src/runtime/proc/windows-launch.exe +0 -0
  163. package/build/src/settlement/holder.d.ts +2 -4
  164. package/build/src/settlement/holder.js +3 -6
  165. package/build/src/task/board.d.ts +6 -0
  166. package/build/src/task/board.js +30 -1
  167. package/build/src/task/catalog.js +1 -4
  168. package/build/src/task/compose.d.ts +0 -1
  169. package/build/src/task/compose.js +0 -1
  170. package/build/src/task/context.d.ts +0 -1
  171. package/build/src/task/context.js +0 -3
  172. package/build/src/task/created-observation.d.ts +5 -1
  173. package/build/src/task/created-observation.js +12 -5
  174. package/build/src/task/index.d.ts +1 -1
  175. package/build/src/task/index.js +7 -6
  176. package/build/src/task/input.d.ts +0 -6
  177. package/build/src/task/input.js +2 -14
  178. package/build/src/task/mutation.d.ts +3 -4
  179. package/build/src/task/mutation.js +11 -39
  180. package/build/src/task/operations.d.ts +2 -7
  181. package/build/src/task/operations.js +37 -49
  182. package/build/src/task/query.d.ts +0 -1
  183. package/build/src/task/query.js +1 -4
  184. package/build/src/task/store.d.ts +0 -2
  185. package/build/src/task/store.js +27 -11
  186. package/build/src/verification/declaration.js +3 -2
  187. package/build/src/verification/execution.d.ts +3 -2
  188. package/build/src/verification/execution.js +10 -6
  189. package/build/src/workspace-place.d.ts +0 -1
  190. package/build/src/workspace-place.js +0 -11
  191. package/package.json +7 -3
@@ -16,6 +16,12 @@ shorter, world-local name.
16
16
 
17
17
  ## Call a new Akuma
18
18
 
19
+ ```bash
20
+ keiyaku call worker "Summarize the recent changes in src/cli"
21
+ keiyaku call worker --alias @reviewer --wait 10m - < brief.md
22
+ keiyaku call worker
23
+ ```
24
+
19
25
  The prompt is optional for prompt-free birth. Otherwise it is the new Akuma's
20
26
  first prompt: give it as one argument, or use `-` to read stdin, never both.
21
27
  Calls are detached by default: they return the new identity after birth without
@@ -34,34 +40,57 @@ capabilities, not merely for parallelism.
34
40
  `--contract` only records the association. It does not tell the Akuma the
35
41
  Contract or worktree. Put them in the prompt explicitly:
36
42
 
37
- ```text
38
- Contract: <kei/...>
39
- Worktree: <exact path>
40
- This Arc: <what to do>
43
+ ```bash
44
+ keiyaku call worker --contract kei/add-rate-limit-a1b2 --workdir /path/to/worktree - <<'EOF'
45
+ Contract: kei/add-rate-limit-a1b2
46
+ Worktree: /path/to/worktree
47
+ This Arc: implement the limiter and its tests
48
+ EOF
41
49
  ```
42
50
 
43
51
  `--contract` does not choose a worktree. Use `--workdir <path>` when needed.
44
52
 
45
53
  ## Tell or ask an existing Akuma
46
54
 
55
+ ```bash
56
+ keiyaku tell @reviewer "The candidate moved; re-examine the worktree"
57
+ keiyaku tell @reviewer --interrupt - < new-priority.md
58
+ keiyaku ask @reviewer --wait 10m "What is your verdict?"
59
+ keiyaku ask @reviewer --schema verdict.schema.json - < question.md
60
+ ```
61
+
47
62
  `tell` admits the next instruction and returns its admission receipt; it does
48
63
  not await an answer. `ask` admits a Tell and observes that exact answer,
49
64
  unbounded unless `--wait` limits observation. Both require a prompt and accept
50
65
  `--interrupt` to put down current work before admitting the new Tell. Schema
51
66
  belongs only to `ask`; `tell --schema` and `tell --wait` refuse and point to
52
67
  `ask`. A deadline never withdraws an admitted Tell. Read `tell --help` and
53
- `ask --help` for invocation syntax.
68
+ `ask --help` for the complete flag grammar.
54
69
 
55
70
  ## Observe work
56
71
 
72
+ ```bash
73
+ keiyaku wait @deliverer @reviewer
74
+ keiyaku wait --all --timeout 30m @deliverer @reviewer
75
+ ```
76
+
57
77
  Use `wait` for one or more existing Akumas. The default is `--any`; use
58
78
  `--all` for every selected Akuma. `--timeout` limits observation and does not
59
79
  stop workers. A completed Akuma already counts, so repeating a wait can return
60
- immediately. See `wait --help` for syntax. Unlike `ask`, `wait` observes
61
- existing Akuma-wide work, not the answer to a newly admitted Tell.
80
+ immediately. See `wait --help` for the complete grammar. Unlike `ask`, `wait`
81
+ observes existing Akuma-wide work, not the answer to a newly admitted Tell.
62
82
 
63
83
  ## Inspect and retrieve results
64
84
 
85
+ ```bash
86
+ keiyaku status
87
+ keiyaku status @reviewer
88
+ keiyaku ls aku/
89
+ keiyaku ls "aku/*/*"
90
+ keiyaku history @reviewer --last
91
+ keiyaku history @reviewer --id turn/3
92
+ ```
93
+
65
94
  `status` shows the roster or one Akuma's workdir and effective actions.
66
95
  `ls aku/` shows callable names; `ls "aku/*/*"` shows born workers.
67
96
  `history --last` reads the latest complete answer; `history --id` reads an
@@ -70,10 +99,16 @@ move; see `history --help` for paging.
70
99
 
71
100
  ## Stop and branch
72
101
 
102
+ ```bash
103
+ keiyaku kill @reviewer
104
+ keiyaku fork @reviewer --at turn/3
105
+ ```
106
+
73
107
  `kill` stops current work without admitting a Tell, deleting the Akuma, or
74
108
  removing its history. `fork` creates a new Akuma from one exact retained
75
109
  answered history point; the source is unchanged, and providers that cannot
76
- fork report that refusal. See the `kill --help` and `fork --help` syntax.
110
+ fork report that refusal. See `kill --help` and `fork --help` for the
111
+ complete grammar.
77
112
 
78
113
  ## JavaScript automation
79
114
 
@@ -154,14 +154,13 @@ fence containing commands runnable as written. Use separate fences when checks
154
154
  need different timeouts or results. Use an explicit timeout for bounded
155
155
  commands; `5m` is the normal baseline.
156
156
 
157
- Verification runs against the exact integration snapshot in a clean disposable
158
- worktree for that attempt. It does not run in the author's worktree or the
159
- target checkout. If the Contract declares Verification, `deliver` runs it when
160
- no current `verified` attestation exists and otherwise reuses the current
161
- attestation. A newly run unsatisfied result stops that delivery. `audit` runs
162
- Verification for a prospective candidate. `--gates reviewed` requires review
163
- evidence; it does not select or suppress Verification. Selected gates are
164
- checked at placement.
157
+ Verification runs only when the Contract selects the `verified` gate, against
158
+ the exact integration snapshot in a clean disposable worktree for that attempt.
159
+ `deliver` reuses current satisfied evidence or runs the declarations; unsatisfied
160
+ results and runtime stops prevent placement. `audit` runs declarations for a
161
+ prospective candidate. Without `verified`, no verb runs Verification and the
162
+ section is inert document text. `reviewed` independently requires review
163
+ evidence. Selected gates are checked at placement.
165
164
 
166
165
  For an existing Task with real scheduling or dependency value:
167
166
 
@@ -72,9 +72,9 @@ Each act changes a different part of the world:
72
72
  audit; when it matters, merge the target branch (main when selected) in the
73
73
  worktree and resolve conflicts there before auditing.
74
74
  - **Audit:** Previews the candidate and target without tendering or claiming.
75
- Declared Verification can record a `verified` attestation for the captured
76
- subject; current evidence is reused. No declaration or a stopped run records
77
- no new verdict.
75
+ With `verified` selected, Verification runs for the captured subject and can
76
+ record an attestation. Without that gate, the section is inert text and no
77
+ verb runs Verification. A stopped run records no new verdict.
78
78
  - **Deliver:** Captures a tender and integration against the observed target;
79
79
  journal gains a delivered candidate. Ready prerequisites and gates trigger
80
80
  placement and claim in this invocation; otherwise the candidate waits.
@@ -1,5 +1,5 @@
1
1
  import { type AkuId, type AkumaPaths } from "./identity.js";
2
- import { selectHistory, type ActivityHistory, type ActivityRow, type ActivitySnapshot } from "./projection.js";
2
+ import { selectHistory, selectSnapshot, type ActivityHistory, type ActivityRow, type ActivitySnapshot, type TurnLedger } 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";
@@ -16,24 +16,27 @@ type BudgetedStatusObservation = Readonly<{
16
16
  export type LiveStatusObservation = BudgetedStatusObservation & Readonly<{
17
17
  rows: readonly ActivityRow[];
18
18
  }>;
19
- /** Internal live companion for an observation loop; it is not a public result. */
20
- export declare function bornLiveStatus(paths: AkumaPaths, expected: AkuId, input: Readonly<{
21
- aperture: "monitoring" | "receipt";
22
- ordinaryBudget?: number;
23
- admittedTellId?: string;
24
- }>): Promise<LiveStatusObservation>;
25
- export declare function bornStatus(paths: AkumaPaths, expected: AkuId, input: Readonly<{
26
- aperture: "monitoring" | "receipt";
27
- ordinaryBudget?: number;
28
- admittedTellId?: string;
29
- }>): Promise<BudgetedStatusObservation>;
30
- export declare function readLiveStatus(worldPath: WorldRoot, id: AkuId, input: Readonly<{
19
+ type StatusObservationInput = Readonly<{
31
20
  aperture: "monitoring" | "receipt";
32
21
  ordinaryBudget?: number;
33
22
  admittedTellId?: string;
34
- }>): Promise<LiveStatusObservation>;
23
+ }>;
24
+ type StatusProjection = Readonly<{
25
+ ledger: TurnLedger;
26
+ selected: ReturnType<typeof selectSnapshot>;
27
+ }>;
28
+ /** Private to a live wait: retain only this member's current frontier and last selection. */
29
+ export declare function createLiveStatusReader(paths: AkumaPaths, expected: AkuId): {
30
+ clear: () => void;
31
+ read(input: StatusObservationInput, signal?: AbortSignal): Promise<LiveStatusObservation>;
32
+ };
33
+ /** Internal live companion for an observation loop; it is not a public result. */
34
+ export declare function bornLiveStatus(paths: AkumaPaths, expected: AkuId, input: StatusObservationInput, signal?: AbortSignal, readProjection?: () => Promise<StatusProjection>): Promise<LiveStatusObservation>;
35
+ export declare function bornStatus(paths: AkumaPaths, expected: AkuId, input: StatusObservationInput): Promise<BudgetedStatusObservation>;
36
+ export declare function readLiveStatus(worldPath: WorldRoot, id: AkuId, input: StatusObservationInput, signal?: AbortSignal): Promise<LiveStatusObservation>;
35
37
  export declare function defaultWaitComplete(status: AkumaStatus): boolean;
36
- export declare function readWaitComplete(worldPath: WorldRoot, id: AkuId): Promise<boolean>;
38
+ /** Probe completion only; returned statuses still come from a full observation. */
39
+ export declare function readWaitComplete(worldPath: WorldRoot, ids: readonly AkuId[], completion: "any" | "all", signal?: AbortSignal): Promise<boolean>;
37
40
  export type WaitReason = "completed" | "deadline";
38
41
  /**
39
42
  * The one deadline-aware observation loop for public Akuma waiting. It always
@@ -1,4 +1,4 @@
1
- import { readStatusFacts, readLifeSnapshot, HeldAkumaLeash, isHeartAbsent, life, lifeAt, probeLeash, readHeart, readSeal, readSoul, } from "./heart/index.js";
1
+ import { readStatusFacts, createStatusFactReader, readLifeSnapshot, HeldAkumaLeash, isHeartAbsent, life, lifeAt, probeLeash, readHeart, readSeal, readSoul, } from "./heart/index.js";
2
2
  import { pathsForAkuId } from "./identity.js";
3
3
  import { ordinarySnapshotBudget, projectTurns, selectHistory, selectSnapshot, } from "./projection.js";
4
4
  import { resolveProviderExecution } from "./providers/index.js";
@@ -59,21 +59,56 @@ async function bornObservation(paths, expected, read, snapshot) {
59
59
  claim?.release();
60
60
  }
61
61
  }
62
+ function snapshotSelection(input) {
63
+ return {
64
+ aperture: input.aperture,
65
+ budget: ordinarySnapshotBudget(input.ordinaryBudget),
66
+ ...(input.admittedTellId === undefined ? {} : { admittedTellId: input.admittedTellId }),
67
+ };
68
+ }
69
+ /** Private to a live wait: retain only this member's current frontier and last selection. */
70
+ export function createLiveStatusReader(paths, expected) {
71
+ const reader = createStatusFactReader(paths);
72
+ let memo;
73
+ const clear = () => {
74
+ reader.clear();
75
+ memo = undefined;
76
+ };
77
+ return {
78
+ clear,
79
+ async read(input, signal) {
80
+ try {
81
+ return await bornLiveStatus(paths, expected, input, signal, async () => {
82
+ const facts = await reader.read(input, signal);
83
+ const ledger = memo?.facts === facts ? memo.ledger : projectTurns(facts);
84
+ const options = snapshotSelection(input);
85
+ const selected = memo?.ledger === ledger &&
86
+ memo.options.aperture === options.aperture &&
87
+ memo.options.admittedTellId === options.admittedTellId &&
88
+ memo.options.budget.tail === options.budget.tail &&
89
+ memo.options.budget.voice === options.budget.voice
90
+ ? memo.selected
91
+ : selectSnapshot(ledger, options);
92
+ memo = { facts, ledger, options, selected };
93
+ return { ledger, selected };
94
+ });
95
+ }
96
+ catch (error) {
97
+ clear();
98
+ throw error;
99
+ }
100
+ },
101
+ };
102
+ }
62
103
  /** Internal live companion for an observation loop; it is not a public result. */
63
- export async function bornLiveStatus(paths, expected, input) {
104
+ export async function bornLiveStatus(paths, expected, input, signal, readProjection) {
64
105
  if (input.ordinaryBudget !== undefined && (!Number.isSafeInteger(input.ordinaryBudget) || input.ordinaryBudget < 0))
65
106
  throw new TypeError("ordinary budget must be a nonnegative safe integer");
66
- const { snapshot, soul, currentLife } = await bornObservation(paths, expected, () => readLifeSnapshot(paths));
107
+ const { snapshot, soul, currentLife } = await bornObservation(paths, expected, () => readLifeSnapshot(paths, signal));
67
108
  const resumeUnsupported = currentLife === "stranded" &&
68
109
  snapshot.latestSession?.provider === soul.provider.name &&
69
110
  (await resolveProviderExecution(soul.provider)).adapter.resume === undefined;
70
- const facts = await readStatusFacts(paths, input);
71
- const ledger = projectTurns(facts);
72
- const selected = selectSnapshot(ledger, {
73
- aperture: input.aperture,
74
- budget: ordinarySnapshotBudget(input.ordinaryBudget),
75
- ...(input.admittedTellId === undefined ? {} : { admittedTellId: input.admittedTellId }),
76
- });
111
+ const { ledger, selected } = readProjection === undefined ? await readStatusProjection(paths, input, signal) : await readProjection();
77
112
  return {
78
113
  status: {
79
114
  id: soul.id,
@@ -87,12 +122,20 @@ export async function bornLiveStatus(paths, expected, input) {
87
122
  rows: ledger.rows,
88
123
  };
89
124
  }
125
+ async function readStatusProjection(paths, input, signal) {
126
+ const facts = await readStatusFacts(paths, input, signal);
127
+ const ledger = projectTurns(facts);
128
+ return {
129
+ ledger,
130
+ selected: selectSnapshot(ledger, snapshotSelection(input)),
131
+ };
132
+ }
90
133
  export async function bornStatus(paths, expected, input) {
91
134
  const { rows: _rows, ...status } = await bornLiveStatus(paths, expected, input);
92
135
  return status;
93
136
  }
94
- export async function readLiveStatus(worldPath, id, input) {
95
- return await bornLiveStatus(pathsForAkuId(worldPath, id), id, input);
137
+ export async function readLiveStatus(worldPath, id, input, signal) {
138
+ return await bornLiveStatus(pathsForAkuId(worldPath, id), id, input, signal);
96
139
  }
97
140
  function complete(life, pending) {
98
141
  return life !== "running" && !pending;
@@ -100,10 +143,26 @@ function complete(life, pending) {
100
143
  export function defaultWaitComplete(status) {
101
144
  return complete(status.life, status.timeline.entries.some((entry) => entry.kind === "row" && entry.row.kind === "tell" && entry.row.state === "pending"));
102
145
  }
103
- export async function readWaitComplete(worldPath, id) {
104
- const paths = pathsForAkuId(worldPath, id);
105
- const observed = await bornObservation(paths, id, () => readLifeSnapshot(paths));
106
- return complete(observed.currentLife, observed.snapshot.hasPendingTell);
146
+ /** Probe completion only; returned statuses still come from a full observation. */
147
+ export async function readWaitComplete(worldPath, ids, completion, signal) {
148
+ let completed = 0;
149
+ for (const id of ids) {
150
+ signal?.throwIfAborted();
151
+ try {
152
+ const paths = pathsForAkuId(worldPath, id);
153
+ const observed = await bornObservation(paths, id, () => readLifeSnapshot(paths, signal));
154
+ if (complete(observed.currentLife, observed.snapshot.hasPendingTell)) {
155
+ if (completion === "any")
156
+ return true;
157
+ completed += 1;
158
+ }
159
+ }
160
+ catch (error) {
161
+ if (ids.length === 1 || error instanceof AkumaNotBornError)
162
+ throw error;
163
+ }
164
+ }
165
+ return ids.length > 0 && completed === ids.length;
107
166
  }
108
167
  const OBSERVATION_POLL_MS = 100;
109
168
  /**
@@ -53,9 +53,10 @@ export type NativeWaitResult = Readonly<{
53
53
  * The one lower set-observation owner for Akuma wait completion. It serves the
54
54
  * standalone one-ID association-free face and the plural any/all face with one
55
55
  * ordered round algorithm, one shared ordinary-detail budget, transient
56
- * unreadable peers, and an honest final deadline edge. The default completion
57
- * probe is used only without live row callbacks and never with a custom
58
- * predicate; a live viewer always observes rounds.
56
+ * unreadable peers, and an honest final deadline edge. A silent observation —
57
+ * no live row callback and no custom judge — decides which running rounds to
58
+ * skip with the owner's lightweight completion probe over the selected set; a
59
+ * live viewer or a custom judge always observes full rounds.
59
60
  */
60
61
  export declare function executeWaitAkuma(input: WaitExecutionInput): Promise<NativeWaitResult>;
61
62
  export {};
@@ -1,10 +1,22 @@
1
1
  import { AkumaNotBornError } from "./akuma-errors.js";
2
- import { defaultWaitComplete, readLiveStatus, readWaitComplete, waitForObservation, } from "./akuma-observe.js";
2
+ import { createLiveStatusReader, defaultWaitComplete, readLiveStatus, readWaitComplete, waitForObservation, } from "./akuma-observe.js";
3
+ import { pathsForAkuId } from "./identity.js";
3
4
  const SHARED_ORDINARY_BUDGET = 30;
4
- async function observeWaitRound(path, ids, signal) {
5
+ async function observeWaitRound(path, ids, signal, readers) {
6
+ const read = async (id, ordinaryBudget) => {
7
+ const options = { aperture: "monitoring", ...(ordinaryBudget === undefined ? {} : { ordinaryBudget }) };
8
+ if (readers === undefined)
9
+ return await readLiveStatus(path, id, options, signal);
10
+ let reader = readers.get(id);
11
+ if (reader === undefined) {
12
+ reader = createLiveStatusReader(pathsForAkuId(path, id), id);
13
+ readers.set(id, reader);
14
+ }
15
+ return await reader.read(options, signal);
16
+ };
5
17
  signal?.throwIfAborted();
6
18
  if (ids.length <= 1) {
7
- const observations = await Promise.all(ids.map(async (id) => await readLiveStatus(path, id, { aperture: "monitoring" })));
19
+ const observations = await Promise.all(ids.map(async (id) => await read(id)));
8
20
  return { observations, unobserved: [] };
9
21
  }
10
22
  let remaining = SHARED_ORDINARY_BUDGET;
@@ -13,11 +25,13 @@ async function observeWaitRound(path, ids, signal) {
13
25
  for (const id of ids) {
14
26
  signal?.throwIfAborted();
15
27
  try {
16
- const observed = await readLiveStatus(path, id, { aperture: "monitoring", ordinaryBudget: remaining });
28
+ const observed = await read(id, remaining);
17
29
  observations.push(observed);
18
30
  remaining -= observed.ordinarySelected;
19
31
  }
20
32
  catch (error) {
33
+ readers?.get(id)?.clear();
34
+ readers?.delete(id);
21
35
  if (error instanceof AkumaNotBornError)
22
36
  throw error;
23
37
  unobserved.push({ id, diagnostic: diagnostic(error) });
@@ -54,59 +68,67 @@ function selectionOrderedIds(ids, order) {
54
68
  * The one lower set-observation owner for Akuma wait completion. It serves the
55
69
  * standalone one-ID association-free face and the plural any/all face with one
56
70
  * ordered round algorithm, one shared ordinary-detail budget, transient
57
- * unreadable peers, and an honest final deadline edge. The default completion
58
- * probe is used only without live row callbacks and never with a custom
59
- * predicate; a live viewer always observes rounds.
71
+ * unreadable peers, and an honest final deadline edge. A silent observation —
72
+ * no live row callback and no custom judge — decides which running rounds to
73
+ * skip with the owner's lightweight completion probe over the selected set; a
74
+ * live viewer or a custom judge always observes full rounds.
60
75
  */
61
76
  export async function executeWaitAkuma(input) {
62
- // Identity facts are read once per observed Akuma, not once per 100ms round.
63
- const facts = new Map();
64
- if (input.onSelected !== undefined) {
65
- for (const id of input.ids) {
66
- input.signal?.throwIfAborted();
67
- const known = input.identity === undefined ? undefined : await input.identity(id);
68
- facts.set(id, known ?? { contract: { kind: "none" } });
69
- }
70
- const ordered = input.selectionOrder === undefined ? input.ids : selectionOrderedIds(input.ids, input.selectionOrder);
71
- input.onSelected(ordered.map((id) => ({ id, ...facts.get(id) })));
72
- }
73
- const observeRound = async (round) => {
74
- if (input.observe === undefined)
75
- return;
76
- const observed = [];
77
- for (const observation of round.observations) {
78
- input.signal?.throwIfAborted();
79
- const { status, rows } = observation;
80
- let known = facts.get(status.id);
81
- if (known === undefined && input.identity !== undefined) {
82
- known = await input.identity(status.id);
83
- facts.set(status.id, known);
84
- }
85
- if (known === undefined) {
86
- observed.push({ status, rows, contract: { kind: "none" } });
87
- continue;
77
+ const readers = input.observe === undefined ? undefined : new Map();
78
+ try {
79
+ // Identity facts are read once per observed Akuma, not once per 100ms round.
80
+ const facts = new Map();
81
+ if (input.onSelected !== undefined) {
82
+ for (const id of input.ids) {
83
+ input.signal?.throwIfAborted();
84
+ const known = input.identity === undefined ? undefined : await input.identity(id);
85
+ facts.set(id, known ?? { contract: { kind: "none" } });
88
86
  }
89
- observed.push({ status, rows, ...known });
87
+ const ordered = input.selectionOrder === undefined ? input.ids : selectionOrderedIds(input.ids, input.selectionOrder);
88
+ input.onSelected(ordered.map((id) => ({ id, ...facts.get(id) })));
90
89
  }
91
- input.observe(observed);
92
- };
93
- const live = input.observe !== undefined;
94
- const waited = await waitForObservation({
95
- ...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }),
96
- ...(input.signal === undefined ? {} : { signal: input.signal }),
97
- ...(input.predicate === undefined && !live && input.ids.length === 1
98
- ? { probe: async () => await readWaitComplete(input.path, input.ids[0]) }
99
- : {}),
100
- observe: async () => await observeWaitRound(input.path, input.ids, input.signal),
101
- complete: (round) => roundComplete(round, input.completion, input.predicate),
102
- onObserve: async (round) => await observeRound(round),
103
- });
104
- return {
105
- mode: input.completion,
106
- reason: waited.reason,
107
- observations: waited.value.observations.map((observation) => observation.status),
108
- unobserved: waited.value.unobserved,
109
- };
90
+ const observeRound = async (round) => {
91
+ if (input.observe === undefined)
92
+ return;
93
+ const observed = [];
94
+ for (const observation of round.observations) {
95
+ input.signal?.throwIfAborted();
96
+ const { status, rows } = observation;
97
+ let known = facts.get(status.id);
98
+ if (known === undefined && input.identity !== undefined) {
99
+ known = await input.identity(status.id);
100
+ facts.set(status.id, known);
101
+ }
102
+ if (known === undefined) {
103
+ observed.push({ status, rows, contract: { kind: "none" } });
104
+ continue;
105
+ }
106
+ observed.push({ status, rows, ...known });
107
+ }
108
+ input.observe(structuredClone(observed));
109
+ };
110
+ const waited = await waitForObservation({
111
+ ...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }),
112
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
113
+ ...(input.predicate === undefined && input.observe === undefined
114
+ ? { probe: async () => await readWaitComplete(input.path, input.ids, input.completion, input.signal) }
115
+ : {}),
116
+ observe: async () => await observeWaitRound(input.path, input.ids, input.signal, readers),
117
+ complete: (round) => roundComplete(round, input.completion, input.predicate),
118
+ onObserve: async (round) => await observeRound(round),
119
+ });
120
+ return {
121
+ mode: input.completion,
122
+ reason: waited.reason,
123
+ observations: waited.value.observations.map((observation) => observation.status),
124
+ unobserved: waited.value.unobserved,
125
+ };
126
+ }
127
+ finally {
128
+ for (const reader of readers?.values() ?? [])
129
+ reader.clear();
130
+ readers?.clear();
131
+ }
110
132
  }
111
133
  function diagnostic(error) {
112
134
  return error instanceof Error ? error.message : String(error);
@@ -156,8 +156,8 @@ export declare const akumaStatusSchema: z.ZodObject<{
156
156
  }>;
157
157
  turnSequence: z.ZodNumber;
158
158
  receipt: z.ZodOptional<z.ZodEnum<{
159
- required: "required";
160
159
  unavailable: "unavailable";
160
+ required: "required";
161
161
  }>>;
162
162
  }, z.core.$strict>, z.ZodTransform<Readonly<{
163
163
  turnSequence: number;
@@ -168,7 +168,7 @@ export declare const akumaStatusSchema: z.ZodObject<{
168
168
  deliveredAt: string;
169
169
  route: "live" | "launch";
170
170
  turnSequence: number;
171
- receipt?: "required" | "unavailable" | undefined;
171
+ receipt?: "unavailable" | "required" | undefined;
172
172
  }>>>>;
173
173
  }, z.core.$strict>]>, z.ZodObject<{
174
174
  kind: z.ZodLiteral<"tool">;
@@ -363,8 +363,8 @@ export declare const akumaStatusSchema: z.ZodObject<{
363
363
  }>;
364
364
  turnSequence: z.ZodNumber;
365
365
  receipt: z.ZodOptional<z.ZodEnum<{
366
- required: "required";
367
366
  unavailable: "unavailable";
367
+ required: "required";
368
368
  }>>;
369
369
  }, z.core.$strict>, z.ZodTransform<Readonly<{
370
370
  turnSequence: number;
@@ -375,7 +375,7 @@ export declare const akumaStatusSchema: z.ZodObject<{
375
375
  deliveredAt: string;
376
376
  route: "live" | "launch";
377
377
  turnSequence: number;
378
- receipt?: "required" | "unavailable" | undefined;
378
+ receipt?: "unavailable" | "required" | undefined;
379
379
  }>>>>;
380
380
  }, z.core.$strict>]>, z.ZodObject<{
381
381
  kind: z.ZodLiteral<"tool">;
@@ -450,6 +450,8 @@ export declare function listAkumaArchetypes(path: WorldRoot, input?: Readonly<{
450
450
  * observed extent. World Alias context is attached by the upper composition.
451
451
  */
452
452
  export declare function readAkumaRoster(path: WorldRoot, input?: AkumaListInput): Promise<AkumaList>;
453
+ /** Internal recent observation with an aperture already validated by the composition. */
454
+ export declare function observeAkumaRoster(path: WorldRoot, limit: number, selected?: string): Promise<AkumaList>;
453
455
  /** The complete native roster for callers whose semantics require a frozen set. */
454
456
  export declare function readAkumaCompleteRoster(path: WorldRoot, input?: Readonly<{
455
457
  archetype?: string;
@@ -118,6 +118,10 @@ function rosterArchetype(input, allowLimit) {
118
118
  export async function readAkumaRoster(path, input = {}) {
119
119
  const selected = rosterArchetype(input, true);
120
120
  const limit = boundedListLimit(input.limit);
121
+ return observeAkumaRoster(path, limit, selected);
122
+ }
123
+ /** Internal recent observation with an aperture already validated by the composition. */
124
+ export async function observeAkumaRoster(path, limit, selected) {
121
125
  const observedAt = new Date().toISOString();
122
126
  const known = await knownAkuma(path, selected);
123
127
  const candidatesWithBounds = await boundedMap(known.rows, async (row) => ({
@@ -78,8 +78,8 @@ export declare const tellResultSchema: z.ZodObject<{
78
78
  }>;
79
79
  turnSequence: z.ZodNumber;
80
80
  receipt: z.ZodOptional<z.ZodEnum<{
81
- required: "required";
82
81
  unavailable: "unavailable";
82
+ required: "required";
83
83
  }>>;
84
84
  }, z.core.$strict>, z.ZodTransform<Readonly<{
85
85
  turnSequence: number;
@@ -90,7 +90,7 @@ export declare const tellResultSchema: z.ZodObject<{
90
90
  deliveredAt: string;
91
91
  route: "live" | "launch";
92
92
  turnSequence: number;
93
- receipt?: "required" | "unavailable" | undefined;
93
+ receipt?: "unavailable" | "required" | undefined;
94
94
  }>>>>;
95
95
  }, z.core.$strict>;
96
96
  wake: z.ZodUnion<readonly [z.ZodObject<{
@@ -37,7 +37,7 @@ export async function admitCallInitialTell(input) {
37
37
  const birth = await waitForObservation({
38
38
  timeoutMs: BIRTH_TIMEOUT_MS,
39
39
  ...(input.signal === undefined ? {} : { signal: input.signal }),
40
- probe: async () => await readWaitComplete(input.world, input.id),
40
+ probe: async () => await readWaitComplete(input.world, [input.id], "all", input.signal),
41
41
  observe: async () => (await bornStatus(paths, input.id, { aperture: "receipt" })).status,
42
42
  complete: defaultWaitComplete,
43
43
  });
@@ -206,8 +206,8 @@ declare const liveResultSchema: z.ZodObject<{
206
206
  }>;
207
207
  turnSequence: z.ZodNumber;
208
208
  receipt: z.ZodOptional<z.ZodEnum<{
209
- required: "required";
210
209
  unavailable: "unavailable";
210
+ required: "required";
211
211
  }>>;
212
212
  }, z.core.$strict>, z.ZodTransform<Readonly<{
213
213
  turnSequence: number;
@@ -218,7 +218,7 @@ declare const liveResultSchema: z.ZodObject<{
218
218
  deliveredAt: string;
219
219
  route: "live" | "launch";
220
220
  turnSequence: number;
221
- receipt?: "required" | "unavailable" | undefined;
221
+ receipt?: "unavailable" | "required" | undefined;
222
222
  }>>>>;
223
223
  }, z.core.$strict>;
224
224
  wake: z.ZodUnion<readonly [z.ZodObject<{
@@ -23,12 +23,17 @@ export type ActivitySlice = ActivityFactSlice;
23
23
  export type { ActivityFact };
24
24
  export type { TimelineFact } from "./timeline.js";
25
25
  export declare function activitySlice(paths: AkumaPaths): Promise<ActivitySlice>;
26
- export declare function readStatusFacts(paths: AkumaPaths, input: StatusFactInput): Promise<ActivitySlice["rows"]>;
26
+ export declare function readStatusFacts(paths: AkumaPaths, input: StatusFactInput, signal?: AbortSignal): Promise<ActivitySlice["rows"]>;
27
+ /** One live observation's successful raw input and decoded frontier, never a connection. */
28
+ export declare function createStatusFactReader(paths: AkumaPaths): {
29
+ clear(): void;
30
+ read(input: StatusFactInput, signal?: AbortSignal): Promise<ActivitySlice["rows"]>;
31
+ };
27
32
  type LifeSnapshot = Pick<HeartSnapshot, "soul" | "latestBody" | "latestSession" | "latestKill"> & Readonly<{
28
33
  hasPendingTell: boolean;
29
34
  }>;
30
35
  /** Lifecycle probes do not load narration, Tell bodies, or delivery histories. */
31
- export declare function readLifeSnapshot(paths: AkumaPaths): Promise<LifeSnapshot>;
36
+ export declare function readLifeSnapshot(paths: AkumaPaths, signal?: AbortSignal): Promise<LifeSnapshot>;
32
37
  export declare function recordTell(paths: AkumaPaths, tell: Omit<TellFact, "sequence" | "state" | "deliveries" | "binding">, options?: Readonly<{
33
38
  interrupt?: boolean;
34
39
  }>): Promise<Readonly<{