@astrosheep/keiyaku 4.5.8 → 4.5.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 (81) hide show
  1. package/README.md +1 -1
  2. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +2 -2
  3. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +15 -15
  4. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +17 -13
  5. package/build/src/akuma/akuma.d.ts +24 -4
  6. package/build/src/akuma/archetype.js +1 -1
  7. package/build/src/akuma/body.d.ts +2 -1
  8. package/build/src/akuma/body.js +7 -2
  9. package/build/src/akuma/call-request.js +1 -1
  10. package/build/src/akuma/heart/facts.d.ts +10 -0
  11. package/build/src/akuma/heart/facts.js +11 -0
  12. package/build/src/akuma/heart/index.d.ts +3 -2
  13. package/build/src/akuma/heart/index.js +4 -1
  14. package/build/src/akuma/projection.d.ts +63 -12
  15. package/build/src/akuma/projection.js +5 -11
  16. package/build/src/akuma/provider.js +8 -1
  17. package/build/src/akuma/providers/claude/events.d.ts +2 -2
  18. package/build/src/akuma/providers/claude/events.js +16 -3
  19. package/build/src/akuma/providers/codex-app-server/events.d.ts +2 -2
  20. package/build/src/akuma/providers/codex-app-server/events.js +25 -4
  21. package/build/src/akuma/providers/pi/index.js +55 -69
  22. package/build/src/akuma/request-lifecycle.d.ts +1 -1
  23. package/build/src/akuma/request-lifecycle.js +3 -1
  24. package/build/src/akuma/request-serve.d.ts +1 -1
  25. package/build/src/akuma/request-serve.js +4 -4
  26. package/build/src/akuma/turn-drive.js +8 -2
  27. package/build/src/body/amend.js +18 -19
  28. package/build/src/cli/commands/akuma.js +2 -2
  29. package/build/src/cli/commands/contract-invoke.js +27 -22
  30. package/build/src/cli/commands/contract.d.ts +7 -11
  31. package/build/src/cli/commands/contract.js +40 -15
  32. package/build/src/cli/commands/install.d.ts +1 -0
  33. package/build/src/cli/commands/install.js +2 -1
  34. package/build/src/cli/parse.js +23 -9
  35. package/build/src/cli/render/akuma-activity.d.ts +1 -1
  36. package/build/src/cli/render/akuma-activity.js +4 -3
  37. package/build/src/cli/render/akuma.js +1 -1
  38. package/build/src/cli/render/catalog.js +1 -1
  39. package/build/src/cli/render/contract.js +13 -0
  40. package/build/src/cli/render/kanshi-akuma.js +26 -5
  41. package/build/src/cli/render/kanshi.js +26 -3
  42. package/build/src/cli/render/terminal.d.ts +4 -1
  43. package/build/src/cli/render/terminal.js +12 -1
  44. package/build/src/cli/runtime.js +1 -1
  45. package/build/src/contract-guidance.js +3 -0
  46. package/build/src/git/nuke.js +3 -3
  47. package/build/src/git/process.js +7 -4
  48. package/build/src/git/read-observation.js +1 -1
  49. package/build/src/git/reconcile.d.ts +2 -1
  50. package/build/src/git/reconcile.js +6 -0
  51. package/build/src/git/ref-migration.d.ts +22 -0
  52. package/build/src/git/ref-migration.js +55 -0
  53. package/build/src/git/repository.d.ts +4 -4
  54. package/build/src/git/repository.js +8 -8
  55. package/build/src/library/audit.d.ts +13 -5
  56. package/build/src/library/audit.js +9 -21
  57. package/build/src/library/composition.d.ts +41 -27
  58. package/build/src/library/composition.js +3 -3
  59. package/build/src/library/contract-forwarding-reconciliation-result.d.ts +17 -11
  60. package/build/src/library/contract-forwarding-reconciliation-result.js +11 -2
  61. package/build/src/library/contract-forwarding-result.d.ts +1628 -3887
  62. package/build/src/library/contract-forwarding-result.js +1 -1
  63. package/build/src/library/contract-forwarding.d.ts +12 -13
  64. package/build/src/library/contract-forwarding.js +17 -28
  65. package/build/src/library/contract-handle.d.ts +3 -1
  66. package/build/src/library/contract-handle.js +23 -22
  67. package/build/src/library/contract-operations.d.ts +61 -893
  68. package/build/src/library/contract-operations.js +2 -3
  69. package/build/src/library/contract-types.d.ts +7 -3
  70. package/build/src/library/contract.d.ts +12 -4
  71. package/build/src/library/contract.js +21 -6
  72. package/build/src/library/fleet-result.d.ts +138 -12
  73. package/build/src/library/fleet-result.js +2 -0
  74. package/build/src/library/input.d.ts +1 -1
  75. package/build/src/library/input.js +7 -1
  76. package/build/src/library/keiyaku.d.ts +44 -27
  77. package/build/src/library/keiyaku.js +6 -1
  78. package/build/src/runtime/proc/run.d.ts +1 -0
  79. package/build/src/runtime/proc/run.js +25 -5
  80. package/build/src/runtime/proc/windows-launch.exe +0 -0
  81. package/package.json +1 -1
package/README.md CHANGED
@@ -142,7 +142,7 @@ Node ≥ 22.19. Product law lives in [`docs/`](docs/README.md).
142
142
 
143
143
  ## Source builds
144
144
 
145
- Building from source also builds the Windows launcher with Zig 0.14.1. Install
145
+ Building from source also builds the Windows launcher with Zig 0.14.1 or later. Install
146
146
  that system tool separately and make `zig` available on `PATH`, or set
147
147
  `KEIYAKU_ZIG` to the selected executable. `npm ci` alone is not sufficient for
148
148
  the Windows launcher: use `npm ci --ignore-scripts --prefer-offline` followed by
@@ -41,7 +41,7 @@ keiyaku -C <repo> tell <aku/...|@alias> (<prompt> | -)
41
41
  `-C` is the invocation and Akuma execution cwd. Add `--repo <path>` only when
42
42
  a Contract or Dispatch reader must use a different Git repository.
43
43
 
44
- Repeated `--allowed` values add actions to the Archetype defaults. Restriction
45
- comes from the Archetype base and, for nested calls, the direct parent Soul.
44
+ Repeated `--allowed` values add actions to the selected Akuma's defaults. A
45
+ nested call can use only actions permitted by its direct parent Soul.
46
46
 
47
47
  Use text by default; add `--json` when a script needs structured output.
@@ -6,7 +6,7 @@ description: Use when delegating work to, supervising, steering, inspecting, for
6
6
  # Keiyaku Akuma
7
7
 
8
8
  An Akuma is a durable callable worker. Its complete identity is
9
- `aku/<archetype>/<hex8>` — keep it; it is how you address the same worker
9
+ `aku/<akuma>/<hex8>` — keep it; it is how you address the same worker
10
10
  later. An Alias is a movable world-local selector usable wherever a direct id
11
11
  is accepted; the identity underneath never changes.
12
12
 
@@ -29,25 +29,25 @@ exclusive. Decide up front whether you will stay:
29
29
  Alias already points elsewhere, it moves to the born Akuma. The worker's
30
30
  execution cwd is exactly `-C <path>`, or your own cwd when `-C` is omitted.
31
31
 
32
- Repeated `--allowed` values add actions to the Archetype defaults. Restriction
33
- comes from the Archetype base and, for nested calls, the direct parent Soul.
32
+ Repeated `--allowed` values add actions to the selected Akuma's defaults. A
33
+ nested call can use only actions permitted by its direct parent Soul.
34
34
 
35
- ## Archetypes
35
+ ## Akuma Names
36
36
 
37
- An Archetype is a Markdown file at `~/.keiyaku/akuma/<name>.md`. Its
38
- frontmatter selects the provider and may declare `model`, `effort`,
39
- `readonly`, `network`, and `description`; the body is an optional system
40
- prompt, and an empty body keeps the harness default. Write a new one when no
41
- existing file grants the permissions and stance the work needs; a worker never
42
- outgrows its Archetype mid-life.
37
+ An Akuma name selects a Markdown file at `~/.keiyaku/akuma/<name>.md`; pass
38
+ the filename without `.md` as `<akuma-name>`. Its frontmatter selects the
39
+ provider and may declare `model`, `effort`, `readonly`, `network`, and
40
+ `description`; the body is an optional system prompt, and an empty body keeps
41
+ the harness default. If none grants the permissions and stance the work needs,
42
+ add a new Akuma name. A born Akuma keeps its selected defaults for its lifetime.
43
43
 
44
44
  ## Commission And Steer
45
45
 
46
- A call assembles a commission from independent inputs: the Archetype fixes
46
+ A call assembles a commission from independent inputs: the selected Akuma fixes
47
47
  capability stance for the identity's whole life; the `--contract` Dispatch
48
- associates standing terms; allowed actions set what the callee may do, always
49
- under the Archetype base and the parent Soul's ceiling; the prompt carries the
50
- question. None of these implies another — association is not a seat, forwarded
48
+ associates standing terms; allowed actions set what the callee may do, subject
49
+ to that Akuma's restrictions and the parent Soul's ceiling; the prompt carries
50
+ the question. None of these implies another — association is not a seat, forwarded
51
51
  actions are not a seat, and no combination mints a role.
52
52
 
53
53
  The prompt and every later tell genuinely direct the callee's work: they choose
@@ -67,7 +67,7 @@ not around it.
67
67
  ```bash
68
68
  keiyaku status # deep fleet observation
69
69
  keiyaku status <aku/...|@alias> # one worker's snapshot
70
- keiyaku ls aku/ # shallow catalog; also aku/<archetype>/ and "aku/*/*"
70
+ keiyaku ls aku/ # shallow catalog; also aku/<akuma>/ and "aku/*/*"
71
71
  keiyaku wait <selector>... [--any | --all] [--timeout <duration>]
72
72
  ```
73
73
 
@@ -266,25 +266,29 @@ Deliver when the worktree content is the candidate you intend to land:
266
266
  keiyaku deliver <contract> --include-dirty
267
267
  ```
268
268
 
269
- Use `--include-dirty` only when the complete current workspace is the intended
270
- candidate; otherwise commit the intended bytes first. Read the receipt for the
271
- candidate, gate/placement stop, and any physical-effect lag. A not-complete
272
- delivery is still a recorded `tendered` candidate.
273
-
274
- `deliver` freshly tenders the candidate and requests placement. A current audit
275
- attestation is reused only when its integration snapshot and Verification
276
- segment still match; changes to the worktree, target, policy, document,
277
- Verification, or snapshot-producing options make it stale.
269
+ Deliver when the work is ready to be judged, not when Git looks tidy. `git
270
+ commit` only shapes the candidate; skipping it is fine `deliver
271
+ --include-dirty` captures the complete non-ignored worktree. Deliver and review
272
+ answer different questions: deliver records the candidate and places and claims
273
+ by itself only when every placement obligation is current; a review gate is
274
+ satisfied only by review testimony over the current candidate, and a satisfied
275
+ review may itself be the invocation that places and claims. Reviewing before any
276
+ delivery is legal but records testimony only it creates no candidate and
277
+ authorizes nothing. A Contract without a review gate needs no review.
278
+
279
+ A current audit attestation is reused only when its integration snapshot and
280
+ Verification segment still match; changes to the worktree, target, policy,
281
+ document, Verification, or snapshot-producing options make it stale.
278
282
 
279
283
  ## Review Gates
280
284
 
281
285
  The Reviewer owns the answer. A gate review compares the full current candidate
282
286
  against every journaled Criterion — the floor that cannot be reduced — and
283
287
  testifies satisfied or unsatisfied over the current document identity and
284
- worktree; satisfied requests placement. A current defect, missing, failed, or
285
- stale required evidence, or terms too ambiguous or contradictory to judge all
286
- yield unsatisfied, with the summary naming what blocks. Advice beyond the terms
287
- belongs in the summary and never changes the verdict by itself.
288
+ worktree. A current defect, missing, failed, or stale required evidence, or
289
+ terms too ambiguous or contradictory to judge all yield unsatisfied, with the
290
+ summary naming what blocks. Advice beyond the terms belongs in the summary and
291
+ never changes the verdict by itself.
288
292
 
289
293
  ```bash
290
294
  keiyaku review <contract> --satisfied --summary "<conclusion>"
@@ -124,7 +124,7 @@ export declare const akumaStatusSchema: z.ZodObject<{
124
124
  pending: "pending";
125
125
  told: "told";
126
126
  }>;
127
- deliveries: z.ZodReadonly<z.ZodArray<z.ZodObject<{
127
+ deliveries: z.ZodReadonly<z.ZodArray<z.ZodPipe<z.ZodObject<{
128
128
  deliveredAt: z.ZodString;
129
129
  route: z.ZodEnum<{
130
130
  live: "live";
@@ -135,7 +135,17 @@ export declare const akumaStatusSchema: z.ZodObject<{
135
135
  required: "required";
136
136
  unavailable: "unavailable";
137
137
  }>>;
138
- }, z.core.$strict>>>;
138
+ }, z.core.$strict>, z.ZodTransform<Readonly<{
139
+ turnSequence: number;
140
+ route: "launch" | "live";
141
+ receipt?: "unavailable" | "required";
142
+ deliveredAt: string;
143
+ }>, {
144
+ deliveredAt: string;
145
+ route: "live" | "launch";
146
+ turnSequence: number;
147
+ receipt?: "required" | "unavailable" | undefined;
148
+ }>>>>;
139
149
  }, z.core.$strict>]>, z.ZodObject<{
140
150
  kind: z.ZodLiteral<"tool">;
141
151
  sequence: z.ZodNumber;
@@ -313,7 +323,7 @@ export declare const akumaStatusSchema: z.ZodObject<{
313
323
  pending: "pending";
314
324
  told: "told";
315
325
  }>;
316
- deliveries: z.ZodReadonly<z.ZodArray<z.ZodObject<{
326
+ deliveries: z.ZodReadonly<z.ZodArray<z.ZodPipe<z.ZodObject<{
317
327
  deliveredAt: z.ZodString;
318
328
  route: z.ZodEnum<{
319
329
  live: "live";
@@ -324,7 +334,17 @@ export declare const akumaStatusSchema: z.ZodObject<{
324
334
  required: "required";
325
335
  unavailable: "unavailable";
326
336
  }>>;
327
- }, z.core.$strict>>>;
337
+ }, z.core.$strict>, z.ZodTransform<Readonly<{
338
+ turnSequence: number;
339
+ route: "launch" | "live";
340
+ receipt?: "unavailable" | "required";
341
+ deliveredAt: string;
342
+ }>, {
343
+ deliveredAt: string;
344
+ route: "live" | "launch";
345
+ turnSequence: number;
346
+ receipt?: "required" | "unavailable" | undefined;
347
+ }>>>>;
328
348
  }, z.core.$strict>]>, z.ZodObject<{
329
349
  kind: z.ZodLiteral<"tool">;
330
350
  sequence: z.ZodNumber;
@@ -75,7 +75,7 @@ function archetypeReadonly(values) {
75
75
  function decodeArchetype(name, path, markdown) {
76
76
  const lines = markdown.split(/\r?\n/u);
77
77
  if (lines[0]?.trim() !== "---")
78
- throw new TypeError("Akuma configuration must begin with YAML frontmatter");
78
+ throw new TypeError("Akuma file must begin with YAML frontmatter");
79
79
  const closing = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
80
80
  if (closing < 0)
81
81
  throw new TypeError("Akuma frontmatter is not closed");
@@ -1,5 +1,5 @@
1
1
  import type { AkumaCallRequestChildLaunch } from "./call-request.js";
2
- import { type SessionFact, type Soul } from "./heart/index.js";
2
+ import { type SessionFact, type Soul, type TellRow } from "./heart/index.js";
3
3
  import { type AkumaPaths } from "./identity.js";
4
4
  import type { ProviderAdapter } from "./provider.js";
5
5
  import type { ErasedRequestCommand } from "./request-wire.js";
@@ -38,6 +38,7 @@ export type TellResult = Readonly<{
38
38
  tellId: string;
39
39
  fact: "recorded";
40
40
  }>;
41
+ row: TellRow;
41
42
  wake: TellWake;
42
43
  }>;
43
44
  export type TellWakeRuntime = Readonly<{
@@ -3,7 +3,7 @@ import { fileURLToPath } from "node:url";
3
3
  import { abortableDelay } from "./abort.js";
4
4
  import { BodySupervisor } from "./body-supervisor.js";
5
5
  import { driveTurn, turnRecipe } from "./turn-drive.js";
6
- import { HeldAkumaLeash, breakBody, endTurn, finishBodyIfIdle, heartExists, isHeartAbsent, readHeart, readNonterminalRequests, } from "./heart/index.js";
6
+ import { HeldAkumaLeash, breakBody, endTurn, finishBodyIfIdle, heartExists, isHeartAbsent, projectTell, readHeart, readTell, readNonterminalRequests, } from "./heart/index.js";
7
7
  import { worldRootForAkumaPaths } from "./identity.js";
8
8
  import { keiyakuSquarePath } from "../world.js";
9
9
  import { resolveProviderExecution } from "./providers/index.js";
@@ -367,8 +367,13 @@ async function wakePendingTells(paths, tellId, runtime) {
367
367
  }
368
368
  }
369
369
  export async function wakeRecordedTell(paths, tellId, runtime = DIRECT_TELL_WAKE) {
370
+ const wake = (await wakePendingTells(paths, tellId, runtime));
371
+ const tell = await readTell(paths, tellId);
372
+ if (tell === null)
373
+ throw new Error(`recorded Tell ${tellId} is missing from Heart`);
370
374
  return {
371
375
  admission: { tellId, fact: "recorded" },
372
- wake: (await wakePendingTells(paths, tellId, runtime)),
376
+ row: projectTell(tell),
377
+ wake,
373
378
  };
374
379
  }
@@ -40,7 +40,7 @@ const archetypeSchema = z.string().transform((value, context) => {
40
40
  return archetypeName(value);
41
41
  }
42
42
  catch {
43
- context.addIssue({ code: "custom", message: "expected archetype" });
43
+ context.addIssue({ code: "custom", message: "expected Akuma name" });
44
44
  return z.NEVER;
45
45
  }
46
46
  });
@@ -100,6 +100,16 @@ export type TellFact = Readonly<{
100
100
  state: "pending" | "told";
101
101
  deliveries: readonly TellDelivery[];
102
102
  }>;
103
+ export type TellRow = Readonly<{
104
+ kind: "tell";
105
+ sequence: number;
106
+ at: string;
107
+ tellId: string;
108
+ text: string;
109
+ state: "pending" | "told";
110
+ deliveries: readonly TellDelivery[];
111
+ }>;
112
+ export declare function projectTell(fact: TellFact): TellRow;
103
113
  export type TellDeliveryInput = Readonly<{
104
114
  tellId: string;
105
115
  turnSequence: number;
@@ -1,3 +1,14 @@
1
+ export function projectTell(fact) {
2
+ return {
3
+ kind: "tell",
4
+ sequence: fact.sequence,
5
+ at: fact.recordedAt,
6
+ tellId: fact.id,
7
+ text: fact.body,
8
+ state: fact.state,
9
+ deliveries: fact.deliveries,
10
+ };
11
+ }
1
12
  export function life(input) {
2
13
  if (input.body?.hung !== undefined)
3
14
  return "hung";
@@ -5,8 +5,8 @@ import type { ActivityFact } from "./rows.js";
5
5
  import { type ActivityFactSlice } from "./timeline.js";
6
6
  export { HeartAbsentError, HeldAkumaLeash, classifyHeartSchema, initializeHeart, isHeartAbsent, probeLeash, } from "./storage.js";
7
7
  export { admitRequest, isRequestInputConflict, readNonterminalRequests, readRequest, refuseRequest, reserveRequest, serveRequest, serveUpstreamRequest, voidRequest, } from "./request-authority.js";
8
- export { life, lifeAt } from "./facts.js";
9
- export type { AkumaLife, AkumaOrigin, BodyEnd, BodyFact, HeartSnapshot, ForkPoint, KillEvidence, KillFact, LeashProbe, PauseFact, RequestFact, RequestInput, RequestRecipe, SealFact, SessionFact, Soul, StopFact, TellFact, TellDelivery, TellDeliveryInput, TellReceiptInput, TurnEndFact, TurnFact, TurnOutcome, TurnStartFact, } from "./facts.js";
8
+ export { life, lifeAt, projectTell } from "./facts.js";
9
+ export type { AkumaLife, AkumaOrigin, BodyEnd, BodyFact, HeartSnapshot, ForkPoint, KillEvidence, KillFact, LeashProbe, PauseFact, RequestFact, RequestInput, RequestRecipe, SealFact, SessionFact, Soul, StopFact, TellFact, TellRow, TellDelivery, TellDeliveryInput, TellReceiptInput, TurnEndFact, TurnFact, TurnOutcome, TurnStartFact, } from "./facts.js";
10
10
  export type { ResumeCoordinate } from "../coordinate.js";
11
11
  export declare function readSoul(paths: AkumaPaths): Promise<Soul | null>;
12
12
  export declare function heartExists(paths: AkumaPaths): Promise<boolean>;
@@ -27,6 +27,7 @@ export declare function recordTell(paths: AkumaPaths, tell: Omit<TellFact, "sequ
27
27
  kind: "recorded";
28
28
  tell: TellFact;
29
29
  }>>;
30
+ export declare function readTell(paths: AkumaPaths, id: string): Promise<TellFact | null>;
30
31
  export declare function recordTellDeliveries(paths: AkumaPaths, inputs: readonly TellDeliveryInput[]): Promise<void>;
31
32
  export declare function recordTellReceipt(paths: AkumaPaths, input: TellReceiptInput): Promise<void>;
32
33
  export declare function readKill(paths: AkumaPaths, bodySequence: number): Promise<KillFact | null>;
@@ -6,7 +6,7 @@ import { isHeartAbsent, readSealFromLeash, readTransaction, transaction, withHea
6
6
  import { soulFact } from "./soul.js";
7
7
  export { HeartAbsentError, HeldAkumaLeash, classifyHeartSchema, initializeHeart, isHeartAbsent, probeLeash, } from "./storage.js";
8
8
  export { admitRequest, isRequestInputConflict, readNonterminalRequests, readRequest, refuseRequest, reserveRequest, serveRequest, serveUpstreamRequest, voidRequest, } from "./request-authority.js";
9
- export { life, lifeAt } from "./facts.js";
9
+ export { life, lifeAt, projectTell } from "./facts.js";
10
10
  const ACTIVITY_LIMIT = 5_000;
11
11
  export async function readSoul(paths) {
12
12
  try {
@@ -67,6 +67,9 @@ export async function recordTell(paths, tell) {
67
67
  return { kind: "recorded", tell: { sequence, ...tell, state: "pending", deliveries: [] } };
68
68
  }));
69
69
  }
70
+ export async function readTell(paths, id) {
71
+ return await withHeart(paths, (heart) => readTransaction(heart, () => tellFact(heart, id)));
72
+ }
70
73
  export async function recordTellDeliveries(paths, inputs) {
71
74
  await withHeart(paths, (heart) => transaction(heart, () => {
72
75
  for (const input of inputs) {
@@ -1,4 +1,5 @@
1
1
  import type { TimelineFact } from "./heart/index.js";
2
+ import { type TellRow } from "./heart/facts.js";
2
3
  import { z } from "zod";
3
4
  declare const turnRowSchema: z.ZodObject<{
4
5
  kind: z.ZodLiteral<"turn">;
@@ -22,7 +23,7 @@ declare const textRowSchema: (kind: "said" | "thought" | "note") => z.ZodObject<
22
23
  text: z.ZodString;
23
24
  truncated: z.ZodOptional<z.ZodLiteral<true>>;
24
25
  }, z.core.$strict>;
25
- declare const tellRowSchema: z.ZodObject<{
26
+ export declare const tellRowSchema: z.ZodObject<{
26
27
  kind: z.ZodLiteral<"tell">;
27
28
  sequence: z.ZodNumber;
28
29
  at: z.ZodString;
@@ -32,7 +33,7 @@ declare const tellRowSchema: z.ZodObject<{
32
33
  pending: "pending";
33
34
  told: "told";
34
35
  }>;
35
- deliveries: z.ZodReadonly<z.ZodArray<z.ZodObject<{
36
+ deliveries: z.ZodReadonly<z.ZodArray<z.ZodPipe<z.ZodObject<{
36
37
  deliveredAt: z.ZodString;
37
38
  route: z.ZodEnum<{
38
39
  live: "live";
@@ -43,7 +44,17 @@ declare const tellRowSchema: z.ZodObject<{
43
44
  required: "required";
44
45
  unavailable: "unavailable";
45
46
  }>>;
46
- }, z.core.$strict>>>;
47
+ }, z.core.$strict>, z.ZodTransform<Readonly<{
48
+ turnSequence: number;
49
+ route: "launch" | "live";
50
+ receipt?: "unavailable" | "required";
51
+ deliveredAt: string;
52
+ }>, {
53
+ deliveredAt: string;
54
+ route: "live" | "launch";
55
+ turnSequence: number;
56
+ receipt?: "required" | "unavailable" | undefined;
57
+ }>>>>;
47
58
  }, z.core.$strict>;
48
59
  declare const outcomeSchema: z.ZodUnion<readonly [z.ZodObject<{
49
60
  kind: z.ZodLiteral<"answered">;
@@ -253,7 +264,7 @@ declare const openSnapshotRowSchema: z.ZodUnion<readonly [z.ZodUnion<readonly [z
253
264
  pending: "pending";
254
265
  told: "told";
255
266
  }>;
256
- deliveries: z.ZodReadonly<z.ZodArray<z.ZodObject<{
267
+ deliveries: z.ZodReadonly<z.ZodArray<z.ZodPipe<z.ZodObject<{
257
268
  deliveredAt: z.ZodString;
258
269
  route: z.ZodEnum<{
259
270
  live: "live";
@@ -264,7 +275,17 @@ declare const openSnapshotRowSchema: z.ZodUnion<readonly [z.ZodUnion<readonly [z
264
275
  required: "required";
265
276
  unavailable: "unavailable";
266
277
  }>>;
267
- }, z.core.$strict>>>;
278
+ }, z.core.$strict>, z.ZodTransform<Readonly<{
279
+ turnSequence: number;
280
+ route: "launch" | "live";
281
+ receipt?: "unavailable" | "required";
282
+ deliveredAt: string;
283
+ }>, {
284
+ deliveredAt: string;
285
+ route: "live" | "launch";
286
+ turnSequence: number;
287
+ receipt?: "required" | "unavailable" | undefined;
288
+ }>>>>;
268
289
  }, z.core.$strict>]>, z.ZodObject<{
269
290
  kind: z.ZodLiteral<"tool">;
270
291
  sequence: z.ZodNumber;
@@ -402,7 +423,7 @@ declare const idleSnapshotRowSchema: z.ZodUnion<readonly [z.ZodUnion<readonly [z
402
423
  pending: "pending";
403
424
  told: "told";
404
425
  }>;
405
- deliveries: z.ZodReadonly<z.ZodArray<z.ZodObject<{
426
+ deliveries: z.ZodReadonly<z.ZodArray<z.ZodPipe<z.ZodObject<{
406
427
  deliveredAt: z.ZodString;
407
428
  route: z.ZodEnum<{
408
429
  live: "live";
@@ -413,7 +434,17 @@ declare const idleSnapshotRowSchema: z.ZodUnion<readonly [z.ZodUnion<readonly [z
413
434
  required: "required";
414
435
  unavailable: "unavailable";
415
436
  }>>;
416
- }, z.core.$strict>>>;
437
+ }, z.core.$strict>, z.ZodTransform<Readonly<{
438
+ turnSequence: number;
439
+ route: "launch" | "live";
440
+ receipt?: "unavailable" | "required";
441
+ deliveredAt: string;
442
+ }>, {
443
+ deliveredAt: string;
444
+ route: "live" | "launch";
445
+ turnSequence: number;
446
+ receipt?: "required" | "unavailable" | undefined;
447
+ }>>>>;
417
448
  }, z.core.$strict>]>, z.ZodObject<{
418
449
  kind: z.ZodLiteral<"tool">;
419
450
  sequence: z.ZodNumber;
@@ -578,7 +609,7 @@ export declare const activitySnapshotSchema: z.ZodUnion<readonly [z.ZodObject<{
578
609
  pending: "pending";
579
610
  told: "told";
580
611
  }>;
581
- deliveries: z.ZodReadonly<z.ZodArray<z.ZodObject<{
612
+ deliveries: z.ZodReadonly<z.ZodArray<z.ZodPipe<z.ZodObject<{
582
613
  deliveredAt: z.ZodString;
583
614
  route: z.ZodEnum<{
584
615
  live: "live";
@@ -589,7 +620,17 @@ export declare const activitySnapshotSchema: z.ZodUnion<readonly [z.ZodObject<{
589
620
  required: "required";
590
621
  unavailable: "unavailable";
591
622
  }>>;
592
- }, z.core.$strict>>>;
623
+ }, z.core.$strict>, z.ZodTransform<Readonly<{
624
+ turnSequence: number;
625
+ route: "launch" | "live";
626
+ receipt?: "unavailable" | "required";
627
+ deliveredAt: string;
628
+ }>, {
629
+ deliveredAt: string;
630
+ route: "live" | "launch";
631
+ turnSequence: number;
632
+ receipt?: "required" | "unavailable" | undefined;
633
+ }>>>>;
593
634
  }, z.core.$strict>]>, z.ZodObject<{
594
635
  kind: z.ZodLiteral<"tool">;
595
636
  sequence: z.ZodNumber;
@@ -767,7 +808,7 @@ export declare const activitySnapshotSchema: z.ZodUnion<readonly [z.ZodObject<{
767
808
  pending: "pending";
768
809
  told: "told";
769
810
  }>;
770
- deliveries: z.ZodReadonly<z.ZodArray<z.ZodObject<{
811
+ deliveries: z.ZodReadonly<z.ZodArray<z.ZodPipe<z.ZodObject<{
771
812
  deliveredAt: z.ZodString;
772
813
  route: z.ZodEnum<{
773
814
  live: "live";
@@ -778,7 +819,17 @@ export declare const activitySnapshotSchema: z.ZodUnion<readonly [z.ZodObject<{
778
819
  required: "required";
779
820
  unavailable: "unavailable";
780
821
  }>>;
781
- }, z.core.$strict>>>;
822
+ }, z.core.$strict>, z.ZodTransform<Readonly<{
823
+ turnSequence: number;
824
+ route: "launch" | "live";
825
+ receipt?: "unavailable" | "required";
826
+ deliveredAt: string;
827
+ }>, {
828
+ deliveredAt: string;
829
+ route: "live" | "launch";
830
+ turnSequence: number;
831
+ receipt?: "required" | "unavailable" | undefined;
832
+ }>>>>;
782
833
  }, z.core.$strict>]>, z.ZodObject<{
783
834
  kind: z.ZodLiteral<"tool">;
784
835
  sequence: z.ZodNumber;
@@ -844,7 +895,7 @@ type SaidRow = z.infer<ReturnType<typeof textRowSchema>>;
844
895
  type ThoughtRow = z.infer<ReturnType<typeof textRowSchema>>;
845
896
  type NoteRow = z.infer<ReturnType<typeof textRowSchema>>;
846
897
  type TurnNarrationRow = CallRow | SaidRow | ThoughtRow | NoteRow;
847
- export type TellRow = z.infer<typeof tellRowSchema>;
898
+ export type { TellRow } from "./heart/facts.js";
848
899
  export type OutcomeRow = z.infer<typeof outcomeRowSchema>;
849
900
  export type ActiveToolRow = z.infer<typeof activeToolRowSchema>;
850
901
  export type CompletedToolRow = z.infer<typeof completedToolRowSchema>;
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable max-lines -- Akuma owns one coherent activity projection and strict boundary schema. */
2
2
  import { decodeAgentEvent } from "./provider.js";
3
+ import { projectTell } from "./heart/facts.js";
3
4
  import { z } from "zod";
4
5
  const nonblankTextSchema = z.string().refine((value) => value.trim() !== "");
5
6
  const countSchema = z.number().int().nonnegative();
@@ -44,7 +45,8 @@ const tellDeliverySchema = z
44
45
  turnSequence: countSchema,
45
46
  receipt: z.enum(["unavailable", "required"]).optional(),
46
47
  })
47
- .strict();
48
+ .strict()
49
+ .transform(({ receipt, ...delivery }) => (receipt === undefined ? delivery : { ...delivery, receipt }));
48
50
  const turnRowSchema = z
49
51
  .object({
50
52
  kind: z.literal("turn"),
@@ -73,7 +75,7 @@ const textRowSchema = (kind) => z
73
75
  truncated: z.literal(true).optional(),
74
76
  })
75
77
  .strict();
76
- const tellRowSchema = z
78
+ export const tellRowSchema = z
77
79
  .object({
78
80
  kind: z.literal("tell"),
79
81
  sequence: countSchema,
@@ -397,15 +399,7 @@ export function projectTurns(facts, retained = {
397
399
  turn.rows.push(row);
398
400
  }
399
401
  else if (fact.kind === "tell") {
400
- state.tells.push({
401
- kind: "tell",
402
- sequence: fact.sequence,
403
- at: fact.recordedAt,
404
- tellId: fact.id,
405
- text: fact.body,
406
- state: fact.state,
407
- deliveries: fact.deliveries,
408
- });
402
+ state.tells.push(projectTell(fact));
409
403
  }
410
404
  else {
411
405
  projectActivityEvent(state, fact);
@@ -360,6 +360,7 @@ export function createProviderAttempt(parentSignal, establish) {
360
360
  const setupSettled = new Promise((resolve) => {
361
361
  setupComplete = resolve;
362
362
  });
363
+ let establishmentSettled = false;
363
364
  let retiring;
364
365
  const remember = (operation, reportFailure) => {
365
366
  const observed = operation.catch((error) => {
@@ -394,6 +395,8 @@ export function createProviderAttempt(parentSignal, establish) {
394
395
  return Promise.all(pending).then(() => undefined);
395
396
  };
396
397
  const own = (resource) => {
398
+ if (establishmentSettled)
399
+ throw new Error("cannot own a resource after provider establishment settles");
397
400
  if (ownedResources.has(resource))
398
401
  return;
399
402
  const owned = { resource };
@@ -422,7 +425,10 @@ export function createProviderAttempt(parentSignal, establish) {
422
425
  observeBackgroundRetirement(retire("forceDispose"));
423
426
  throw error;
424
427
  })
425
- .finally(() => parent.removeEventListener("abort", cancelFromParent));
428
+ .finally(() => {
429
+ establishmentSettled = true;
430
+ parent.removeEventListener("abort", cancelFromParent);
431
+ });
426
432
  void result.then(() => setupComplete(), () => setupComplete());
427
433
  const closed = (async () => {
428
434
  await setupSettled;
@@ -436,6 +442,7 @@ export function createProviderAttempt(parentSignal, establish) {
436
442
  if (cleanupFailures.length > 0)
437
443
  throw cleanupFailures[0];
438
444
  })();
445
+ void closed.catch(() => undefined);
439
446
  const control = async (operation) => {
440
447
  if (!controller.signal.aborted)
441
448
  controller.abort(new Error("provider attempt retired"));
@@ -28,8 +28,8 @@ export declare const CLAUDE_SYSTEM_DISPOSITIONS: {
28
28
  readonly elicitation_complete: "drop";
29
29
  readonly files_persisted: "note";
30
30
  readonly hook_progress: "drop";
31
- readonly hook_response: "drop";
32
- readonly hook_started: "note";
31
+ readonly hook_response: "hook-response";
32
+ readonly hook_started: "drop";
33
33
  readonly informational: "note";
34
34
  readonly init: "drop";
35
35
  readonly local_command_output: "drop";
@@ -21,8 +21,8 @@ export const CLAUDE_SYSTEM_DISPOSITIONS = {
21
21
  elicitation_complete: "drop",
22
22
  files_persisted: "note",
23
23
  hook_progress: "drop",
24
- hook_response: "drop",
25
- hook_started: "note",
24
+ hook_response: "hook-response",
25
+ hook_started: "drop",
26
26
  informational: "note",
27
27
  init: "drop",
28
28
  local_command_output: "drop",
@@ -89,7 +89,6 @@ const CLAUDE_SYSTEM_NOTES = {
89
89
  const failed = Array.isArray(message.failed) ? message.failed.length : 0;
90
90
  return failed === 0 ? `Persisted ${files} files` : `Persisted ${files} files; ${failed} failed`;
91
91
  },
92
- hook_started: (message) => `Hook ${nonblank(message.hook_name) ?? "unknown"} started`,
93
92
  informational: (message) => nonblank(message.content) ?? "Informational notice",
94
93
  mirror_error: (message) => `Transcript mirror warning: ${nonblank(message.error) ?? nonblank(message.message) ?? "unknown error"}`,
95
94
  model_refusal_fallback: () => "Model refusal; using fallback",
@@ -253,6 +252,14 @@ function toolResultEvents(message, events, state) {
253
252
  });
254
253
  }
255
254
  }
255
+ function hookResponseNote(value) {
256
+ const outcome = nonblank(value.outcome);
257
+ if (outcome !== "error" && outcome !== "cancelled")
258
+ return undefined;
259
+ const hook = nonblank(value.hook_name) ?? "unknown";
260
+ const exitCode = number(value.exit_code);
261
+ return `Hook ${hook} ${outcome}${exitCode === undefined ? "" : ` (exit ${exitCode})`}`;
262
+ }
256
263
  function emitSystemMessage(value, events) {
257
264
  const subtype = nonblank(value?.subtype) ?? "unknown";
258
265
  if (!Object.hasOwn(CLAUDE_SYSTEM_DISPOSITIONS, subtype)) {
@@ -262,6 +269,12 @@ function emitSystemMessage(value, events) {
262
269
  const systemDisposition = CLAUDE_SYSTEM_DISPOSITIONS[subtype];
263
270
  if (systemDisposition === "drop")
264
271
  return;
272
+ if (systemDisposition === "hook-response") {
273
+ const note = hookResponseNote(value);
274
+ if (note !== undefined)
275
+ events.emit(noteEvent(note));
276
+ return;
277
+ }
265
278
  if (systemDisposition === "control-progress" && value?.status !== "api_retry")
266
279
  return;
267
280
  const note = CLAUDE_SYSTEM_NOTES[subtype];
@@ -26,8 +26,8 @@ export declare const CODEX_NOTIFICATION_DISPOSITIONS: {
26
26
  readonly "fuzzyFileSearch/sessionCompleted": "drop";
27
27
  readonly "fuzzyFileSearch/sessionUpdated": "drop";
28
28
  readonly guardianWarning: "note";
29
- readonly "hook/completed": "drop";
30
- readonly "hook/started": "note";
29
+ readonly "hook/completed": "hook-completed";
30
+ readonly "hook/started": "drop";
31
31
  readonly "item/agentMessage/delta": "drop";
32
32
  readonly "item/autoApprovalReview/completed": "note";
33
33
  readonly "item/autoApprovalReview/started": "note";