@demlik/tea 0.15.0 → 0.17.0

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 (115) hide show
  1. package/README.md +30 -7
  2. package/dist/agent/index.d.ts +49 -37
  3. package/dist/agent/index.js +12 -8
  4. package/dist/chunk-4LPY67E4.js +18 -0
  5. package/dist/chunk-4LPY67E4.js.map +1 -0
  6. package/dist/chunk-4NTCPTNQ.js +64 -0
  7. package/dist/chunk-4NTCPTNQ.js.map +1 -0
  8. package/dist/{chunk-3B5X7SBB.js → chunk-4PXNZ5UY.js} +11 -9
  9. package/dist/chunk-4PXNZ5UY.js.map +1 -0
  10. package/dist/{chunk-AYS5N6WY.js → chunk-6XBEYZME.js} +62 -172
  11. package/dist/chunk-6XBEYZME.js.map +1 -0
  12. package/dist/chunk-C4U5D5HP.js +380 -0
  13. package/dist/chunk-C4U5D5HP.js.map +1 -0
  14. package/dist/{chunk-QPEVCJ5Q.js → chunk-DFUEAA6L.js} +13 -6
  15. package/dist/chunk-DFUEAA6L.js.map +1 -0
  16. package/dist/{chunk-22POWGFA.js → chunk-GWWCCSDH.js} +46 -20
  17. package/dist/chunk-GWWCCSDH.js.map +1 -0
  18. package/dist/chunk-K4ETBNKS.js +733 -0
  19. package/dist/chunk-K4ETBNKS.js.map +1 -0
  20. package/dist/chunk-KWNCM6XM.js +539 -0
  21. package/dist/chunk-KWNCM6XM.js.map +1 -0
  22. package/dist/{chunk-V46HSVCK.js → chunk-LYVOGOBC.js} +3 -3
  23. package/dist/{chunk-V46HSVCK.js.map → chunk-LYVOGOBC.js.map} +1 -1
  24. package/dist/{chunk-VTQI2NHP.js → chunk-OPH6Y4UT.js} +9 -8
  25. package/dist/chunk-OPH6Y4UT.js.map +1 -0
  26. package/dist/{chunk-Q5CQTBFA.js → chunk-OYR7ENKU.js} +20 -30
  27. package/dist/chunk-OYR7ENKU.js.map +1 -0
  28. package/dist/{chunk-MYXFNWAJ.js → chunk-QNGYQMZB.js} +4 -4
  29. package/dist/chunk-QNGYQMZB.js.map +1 -0
  30. package/dist/chunk-QWIPH4YH.js +98 -0
  31. package/dist/chunk-QWIPH4YH.js.map +1 -0
  32. package/dist/{chunk-TCLBCERH.js → chunk-XBZQT2TD.js} +238 -212
  33. package/dist/chunk-XBZQT2TD.js.map +1 -0
  34. package/dist/{core-DnzqWy6u.d.ts → core-rDbOaJTN.d.ts} +236 -140
  35. package/dist/do/index.d.ts +37 -33
  36. package/dist/do/index.js +21 -14
  37. package/dist/do/index.js.map +1 -1
  38. package/dist/{durable-effects-CWzA-o2B.d.ts → durable-effects-CNaw97Be.d.ts} +1 -1
  39. package/dist/effect/index.d.ts +151 -0
  40. package/dist/effect/index.js +98 -0
  41. package/dist/effect/index.js.map +1 -0
  42. package/dist/extension/index.d.ts +6 -7
  43. package/dist/extension/index.js +3 -2
  44. package/dist/extension/index.js.map +1 -1
  45. package/dist/flow/index.d.ts +68 -59
  46. package/dist/flow/index.js +32 -27
  47. package/dist/flow/index.js.map +1 -1
  48. package/dist/idempotency/index.d.ts +6 -7
  49. package/dist/idempotency/index.js +4 -2
  50. package/dist/{index-KXqTRJyb.d.ts → index-BOrsbdAf.d.ts} +19 -96
  51. package/dist/{index-DrIRb_Ch.d.ts → index-B_BxplWi.d.ts} +1 -1
  52. package/dist/index-CWmsXNdX.d.ts +207 -0
  53. package/dist/{index-C2DwkjlP.d.ts → index-Cberb5Rr.d.ts} +57 -45
  54. package/dist/{index-CSyMYDAB.d.ts → index-CcrKLtse.d.ts} +1 -1
  55. package/dist/{index-CuNO9m8i.d.ts → index-Cx0F2M34.d.ts} +14 -16
  56. package/dist/{index-HSYgG2Yt.d.ts → index-DaX_P35Q.d.ts} +247 -211
  57. package/dist/{index-CA_7I5g9.d.ts → index-q1PoukOZ.d.ts} +137 -246
  58. package/dist/index.d.ts +121 -385
  59. package/dist/index.js +2 -1
  60. package/dist/jev/index.d.ts +133 -97
  61. package/dist/jev/index.js +205 -161
  62. package/dist/jev/index.js.map +1 -1
  63. package/dist/{machine-DGlPWCWI.d.ts → machine-BcfCFMYF.d.ts} +171 -288
  64. package/dist/machine-viz/index.d.ts +5 -5
  65. package/dist/machine-viz/index.js +8 -4
  66. package/dist/machine-viz/index.js.map +1 -1
  67. package/dist/mem/index.d.ts +3 -4
  68. package/dist/mem/index.js +2 -1
  69. package/dist/mem/index.js.map +1 -1
  70. package/dist/node/index.d.ts +119 -78
  71. package/dist/node/index.js +52 -38
  72. package/dist/node/index.js.map +1 -1
  73. package/dist/paginate/index.d.ts +27 -22
  74. package/dist/paginate/index.js +6 -4
  75. package/dist/parity/index.d.ts +4 -5
  76. package/dist/parity/index.js +3 -2
  77. package/dist/parity/index.js.map +1 -1
  78. package/dist/pbt/index.d.ts +2 -2
  79. package/dist/pbt/index.js +2 -1
  80. package/dist/pbt/index.js.map +1 -1
  81. package/dist/persistence/index.d.ts +10 -12
  82. package/dist/persistence/index.js +5 -3
  83. package/dist/promise/index.d.ts +186 -0
  84. package/dist/promise/index.js +5 -0
  85. package/dist/promise/index.js.map +1 -0
  86. package/dist/{protocol-D8VbH-VH.d.ts → protocol-ClRZBhHQ.d.ts} +7 -8
  87. package/dist/react/index.d.ts +36 -17
  88. package/dist/react/index.js +27 -4
  89. package/dist/react/index.js.map +1 -1
  90. package/dist/resilience/index.d.ts +63 -456
  91. package/dist/resilience/index.js +37 -483
  92. package/dist/resilience/index.js.map +1 -1
  93. package/dist/{runtime-types-CMF13BBh.d.ts → runtime-types-B62Ucnxr.d.ts} +132 -389
  94. package/dist/testing/index.d.ts +33 -113
  95. package/dist/testing/index.js +39 -181
  96. package/dist/testing/index.js.map +1 -1
  97. package/dist/timing/index.d.ts +25 -22
  98. package/dist/timing/index.js +4 -3
  99. package/dist/timing/index.js.map +1 -1
  100. package/dist/{types-BseNPIhr.d.ts → types-DPm5YCDQ.d.ts} +2 -2
  101. package/dist/work-queue/index.d.ts +5 -6
  102. package/package.json +20 -7
  103. package/dist/chunk-22POWGFA.js.map +0 -1
  104. package/dist/chunk-3B5X7SBB.js.map +0 -1
  105. package/dist/chunk-66PY5WYF.js +0 -1816
  106. package/dist/chunk-66PY5WYF.js.map +0 -1
  107. package/dist/chunk-AYS5N6WY.js.map +0 -1
  108. package/dist/chunk-L3TND7LA.js +0 -97
  109. package/dist/chunk-L3TND7LA.js.map +0 -1
  110. package/dist/chunk-MYXFNWAJ.js.map +0 -1
  111. package/dist/chunk-Q5CQTBFA.js.map +0 -1
  112. package/dist/chunk-QPEVCJ5Q.js.map +0 -1
  113. package/dist/chunk-TCLBCERH.js.map +0 -1
  114. package/dist/chunk-VTQI2NHP.js.map +0 -1
  115. package/dist/index-ZCMhnVKN.d.ts +0 -272
@@ -1,4 +1,4 @@
1
- import { z } from 'zod';
1
+ import { StandardSchemaV1 } from '@standard-schema/spec';
2
2
 
3
3
  /**
4
4
  * @demlik/tea — pure-core leaf (ADR 0006).
@@ -9,40 +9,48 @@ import { z } from 'zod';
9
9
  * `Reducer`, `Transitions`, `Cmd`, `Sub`, `Port`, …).
10
10
  *
11
11
  * **Dependency direction (the actual decoupling):** this module imports
12
- * NOTHING from the runtime — no `better-result`, no `run`/host/`Store`. The
12
+ * NOTHING from the runtime — no `run`/host/`Store`. The
13
13
  * runtime (`run`, the host, interpret, `Store`, subscribe — all in
14
14
  * `../index.ts`) imports *from* here; never the reverse. The root door
15
15
  * re-exports this surface through `./index.ts`, and
16
16
  * `pure/import-graph.test.ts` is the regression fence asserting the pure
17
17
  * entrypoint's import graph never reaches `run`.
18
18
  *
19
- * The one external name it reaches for is zod's TYPE surface (`import type`),
20
- * erased at compile time — `Cmd.define` accepts zod schemas, and the parse
21
- * against them happens at the interpret edge in `../run.ts`, never here.
19
+ * The one external name it reaches for is the Standard Schema TYPE surface
20
+ * (`import type` from `@standard-schema/spec`), erased at compile time —
21
+ * `Cmd.define` accepts any Standard Schema (zod, Effect Schema through
22
+ * `Schema.toStandardSchemaV1`, …), and it imports no schema library.
22
23
  */
23
24
 
24
- type RequirementsOf<C> = C extends {
25
- readonly __r?: infer R;
26
- } ? R : unknown;
27
25
  /** The `E` union one Cmd can settle with; `unknown` for an untyped Cmd. */
28
26
  type ErrorsOf<C> = C extends {
29
27
  readonly __e?: infer E;
30
28
  } ? E : unknown;
31
- type UnionToIntersection<U> = (U extends unknown ? (u: U) => void : never) extends (u: infer I) => void ? I : never;
32
- type RequirementsBoxed<C> = C extends unknown ? [RequirementsOf<C>] : never;
33
- type KnownRequirements<B> = B extends [infer R] ? unknown extends R ? never : R : never;
34
29
  /**
35
- * The `ctx` a machine's whole Cmd union requires: every Cmd's `R`, intersected.
36
- * `run` types its `ctx` as `Ctx & RequiredCtx<C>`, so handing a machine whose
37
- * Cmds need `{ http }` to a `run` whose ctx lacks it is a compile error. A Cmd
38
- * that requires nothing — untyped, or `Cmd.define`d without `requirements` — leaves
39
- * the demand of its siblings intact (#56).
40
- *
41
- * This is the requirement. `provide` is what satisfies it: hand `run` a
42
- * `provide({ … })` graph in place of the object and the same `Ctx` is built once
43
- * at boot, in dependency order, and released in reverse when the run ends.
30
+ * The two builders the Promise engine hands a `Cmd.define`d handler on its
31
+ * ctx: `ok(value)` and `err({ _tag })`, with `err` typed to the def's declared
32
+ * tags.
44
33
  */
45
- type RequiredCtx<C> = UnionToIntersection<KnownRequirements<RequirementsBoxed<C>>>;
34
+ interface OutcomeHelpers<Ok, E> {
35
+ readonly ok: (value: Ok) => Outcome<Ok, never>;
36
+ readonly err: (error: E) => Outcome<never, E>;
37
+ }
38
+ /** The result a `Cmd.define`d handler returns: its value, or a declared failure. */
39
+ type Outcome<Ok, E> = {
40
+ readonly _tag: "Ok";
41
+ readonly value: Ok;
42
+ } | {
43
+ readonly _tag: "Err";
44
+ readonly error: E;
45
+ };
46
+ /**
47
+ * Build an {@link Outcome} outside a handler's helpers — in a test that calls a
48
+ * handler directly, or in an adapter converting another result type.
49
+ */
50
+ declare const Outcome: {
51
+ readonly ok: <Ok>(value: Ok) => Outcome<Ok, never>;
52
+ readonly err: <E>(error: E) => Outcome<never, E>;
53
+ };
46
54
  /** The shape every settled failure has (ADR 0011): a plain `_tag` record. */
47
55
  type Tagged = {
48
56
  readonly _tag: string;
@@ -57,9 +65,9 @@ type TaggedError<Tag extends string> = Tag extends string ? {
57
65
  readonly [detail: string]: unknown;
58
66
  } : never;
59
67
  /**
60
- * The kernel-minted failure: a handler returned a `_ok` value the Cmd's `ok`
68
+ * The kernel-minted failure: a handler returned an `Ok` value the Cmd's `ok`
61
69
  * schema rejects. Plain data, so it folds into Model like any settled error;
62
- * `issues` is zod's issue list flattened to `path` + `message` strings.
70
+ * `issues` is the schema's issue list flattened to `path` + `message` strings.
63
71
  */
64
72
  type MalformedResult = {
65
73
  readonly _tag: "malformed_result";
@@ -68,6 +76,51 @@ type MalformedResult = {
68
76
  readonly message: string;
69
77
  }>;
70
78
  };
79
+ /**
80
+ * A schema whose `validate` returned a Promise where the kernel needs an answer
81
+ * now — the `ok` check at the interpret edge, the `args` check in a reducer.
82
+ * A contract breach (ADR 0021 §5): it goes to the error sink.
83
+ */
84
+ declare class AsyncSchemaError extends Error {
85
+ /** What the schema was checking, e.g. `the "fetch" Cmd's ok schema`. */
86
+ readonly where: string;
87
+ readonly name = "AsyncSchemaError";
88
+ readonly _tag: "AsyncSchemaError";
89
+ constructor(
90
+ /** What the schema was checking, e.g. `the "fetch" Cmd's ok schema`. */
91
+ where: string);
92
+ }
93
+ /**
94
+ * A `Cmd.define`d handler failed outside its declared channel: its `Err` carried
95
+ * no `_tag`, or a tag the def does not declare. A contract breach (ADR 0011,
96
+ * 0021 §4): it goes to the error sink, never to `<name>_err`.
97
+ */
98
+ declare class UndeclaredFailureError extends Error {
99
+ readonly cmdType: string;
100
+ /** The `error` the handler's `Err` carried, verbatim. */
101
+ readonly failure: unknown;
102
+ /** The tags the def declares. */
103
+ readonly declared: readonly string[];
104
+ readonly name = "UndeclaredFailureError";
105
+ readonly _tag: "UndeclaredFailureError";
106
+ constructor(cmdType: string,
107
+ /** The `error` the handler's `Err` carried, verbatim. */
108
+ failure: unknown,
109
+ /** The tags the def declares. */
110
+ declared: readonly string[]);
111
+ }
112
+ /**
113
+ * A `Cmd.define`d handler returned something the engine cannot settle: any Msg
114
+ * (the engine mints the Cmd's `<name>_ok` / `<name>_err`, never the handler —
115
+ * ADR 0021), or any other value that is neither an {@link Outcome} nor nothing.
116
+ * Also thrown when such a handler dispatches its own `_ok` / `_err` Msg.
117
+ */
118
+ declare class OutcomeContractError extends Error {
119
+ readonly cmdType: string;
120
+ readonly name = "OutcomeContractError";
121
+ readonly _tag: "OutcomeContractError";
122
+ constructor(cmdType: string, detail: string);
123
+ }
71
124
  /**
72
125
  * The payload a constructor accepts: a plain record spread beside `type`. A
73
126
  * `type` key is refused at the type level — it would overwrite the discriminant.
@@ -75,16 +128,8 @@ type MalformedResult = {
75
128
  type CmdInput = {
76
129
  readonly type?: never;
77
130
  } & Record<string, unknown>;
78
- /**
79
- * Phantom carrier for a Cmd's `R`. `Cmd.requirements<{ http: Http }>()` is how a
80
- * declaration names the `Ctx` slice its handler reads — a type, not a value, so
81
- * nothing is constructed and nothing is checked at runtime.
82
- */
83
- type Requirements<R> = {
84
- readonly __r?: R;
85
- };
86
131
  /** The value `Cmd.define("fetch", …)` builds: `{ type: "fetch", ...input }`. */
87
- type CmdValue<Name extends string, Input extends CmdInput, E extends Tagged, R> = Cmd<Name, E | MalformedResult, R> & Readonly<Input>;
132
+ type CmdValue<Name extends string, Input extends CmdInput, Ok, E extends Tagged> = Cmd<Name, Ok, E | MalformedResult> & Readonly<Input>;
88
133
  type SettledOk<Name extends string, C, Ok> = {
89
134
  readonly type: `${Name}_ok`;
90
135
  readonly cmd: C;
@@ -104,37 +149,39 @@ type SettledErr<Name extends string, C, E extends Tagged> = {
104
149
  * the minted Msg builders and the declaration hung on it. `E` here is the
105
150
  * DECLARED tag union; the settled `_err` arm widens it by `MalformedResult`.
106
151
  *
107
- * `ok` / `err` take an optional `at` for minting OUTSIDE the runtime (a
108
- * `replay` log, a unit test); inside `run` the interpret edge stamps it from
109
- * the clock, so a handler never reads `Date.now()` itself.
152
+ * `ok` / `err` mint a settled Msg OUTSIDE the runtime (a `replay` log, a unit
153
+ * test) and take an optional `at`. A handler never calls them: it returns an
154
+ * {@link Outcome}, and inside `run` the interpret edge mints and stamps.
110
155
  */
111
- interface CmdDef<Name extends string, Input extends CmdInput, Ok, E extends Tagged, R> {
112
- (input: Input): CmdValue<Name, Input, E, R>;
156
+ interface CmdDef<Name extends string, Input extends CmdInput, Ok, E extends Tagged> {
157
+ (input: Input): CmdValue<Name, Input, Ok, E>;
113
158
  /** The `type` discriminant of every Cmd this builds. */
114
159
  readonly cmdType: Name;
115
160
  readonly okType: `${Name}_ok`;
116
161
  readonly errType: `${Name}_err`;
117
- readonly ok: (cmd: CmdValue<Name, Input, E, R>, value: Ok, at?: number) => SettledOk<Name, CmdValue<Name, Input, E, R>, Ok>;
118
- readonly err: (cmd: CmdValue<Name, Input, E, R>, error: E, at?: number) => SettledErr<Name, CmdValue<Name, Input, E, R>, E>;
162
+ readonly ok: (cmd: CmdValue<Name, Input, Ok, E>, value: Ok, at?: number) => SettledOk<Name, CmdValue<Name, Input, Ok, E>, Ok>;
163
+ readonly err: (cmd: CmdValue<Name, Input, Ok, E>, error: E, at?: number) => SettledErr<Name, CmdValue<Name, Input, Ok, E>, E>;
119
164
  readonly schema: {
120
- readonly input: z.ZodType<Input>;
121
- readonly ok: z.ZodType<Ok>;
165
+ readonly input: StandardSchemaV1<unknown, Input>;
166
+ readonly ok: StandardSchemaV1<unknown, Ok>;
122
167
  };
123
168
  /** The declared `_tag` list, verbatim. */
124
169
  readonly errTags: ReadonlyArray<E["_tag"]>;
125
170
  }
126
171
  /**
127
172
  * The declaration-erased view the runtime reads: which `type` a def builds,
128
- * which two Msg types it settles with, and the `ok` schema the edge parses
129
- * against. Every `CmdDef<…>` is one of these structurally.
173
+ * which two Msg types it settles with, the `ok` schema the edge parses against
174
+ * and the tags an `Err` may carry. Every `CmdDef<…>` is one of these
175
+ * structurally.
130
176
  */
131
177
  type AnyCmdDef = {
132
178
  readonly cmdType: string;
133
179
  readonly okType: string;
134
180
  readonly errType: string;
135
181
  readonly schema: {
136
- readonly ok: z.ZodType;
182
+ readonly ok: StandardSchemaV1;
137
183
  };
184
+ readonly errTags: ReadonlyArray<string>;
138
185
  };
139
186
  /** The Cmd value a def (or a union of defs) builds. */
140
187
  type CmdOf<D extends AnyCmdDef> = D extends ((input: never) => infer C extends Cmd) ? C : never;
@@ -143,17 +190,16 @@ type CmdOf<D extends AnyCmdDef> = D extends ((input: never) => infer C extends C
143
190
  * `value`, `<name>_err` carrying `error`. `defineMachine({ cmds })` folds this
144
191
  * into the machine's `M` so the user never spells the effect half of it.
145
192
  */
146
- type Settled<D extends AnyCmdDef> = D extends CmdDef<infer Name, infer Input, infer Ok, infer E, infer R> ? SettledOk<Name, CmdValue<Name, Input, E, R>, Ok> | SettledErr<Name, CmdValue<Name, Input, E, R>, E> : never;
193
+ type Settled<D extends AnyCmdDef> = D extends CmdDef<infer Name, infer Input, infer Ok, infer E> ? SettledOk<Name, CmdValue<Name, Input, Ok, E>, Ok> | SettledErr<Name, CmdValue<Name, Input, Ok, E>, E> : never;
147
194
  /** The `Ok` a def's handler must produce. */
148
- type OkOf<D extends AnyCmdDef> = D extends CmdDef<infer _Name, infer _Input, infer Ok, infer _E, infer _R> ? Ok : never;
195
+ type OkOf<D extends AnyCmdDef> = D extends CmdDef<infer _Name, infer _Input, infer Ok, infer _E> ? Ok : never;
149
196
  /** The DECLARED failure union a def's handler may settle with. */
150
- type ErrOf<D extends AnyCmdDef> = D extends CmdDef<infer _Name, infer _Input, infer _Ok, infer E, infer _R> ? E : never;
151
- declare function defineCmd<const Name extends string, Input extends CmdInput, Ok, const Tags extends readonly string[], R = unknown>(name: Name, spec: {
152
- readonly input: z.ZodType<Input>;
153
- readonly ok: z.ZodType<Ok>;
197
+ type ErrOf<D extends AnyCmdDef> = D extends CmdDef<infer _Name, infer _Input, infer _Ok, infer E> ? E : never;
198
+ declare function defineCmd<const Name extends string, Input extends CmdInput, Ok, const Tags extends readonly string[]>(name: Name, spec: {
199
+ readonly input: StandardSchemaV1<unknown, Input>;
200
+ readonly ok: StandardSchemaV1<unknown, Ok>;
154
201
  readonly err: Tags;
155
- readonly requirements?: Requirements<R>;
156
- }): CmdDef<Name, Input, Ok, TaggedError<Tags[number]>, R>;
202
+ }): CmdDef<Name, Input, Ok, TaggedError<Tags[number]>>;
157
203
  type SyncReturn<S, C extends Cmd> = readonly [S, readonly C[]] & {
158
204
  readonly then?: never;
159
205
  };
@@ -265,51 +311,50 @@ type ExhaustiveTransitions<S extends {
265
311
  /**
266
312
  * A tagged-union, one-shot effect — JSON-plain, hashable, replayable.
267
313
  *
268
- * `T` is the tag. `E` and `R` are Effect's Error and **Requirements** channels,
269
- * carried as phantom type parameters (ADR 0014): `E` is the `_tag` union this
270
- * Cmd can settle with, and `R` is the slice of `Ctx` its interpret handler
271
- * reads. `R` is a requirement, not a wiring — what SATISFIES it is the `ctx`
272
- * handed to `run`, built by hand or by a `provide` graph that acquires each
273
- * dependency once and releases it when the run ends.
274
- *
275
- * @see {@link RequiredCtx} — every Cmd's `R`, intersected: what `run` demands.
276
- * @see `provide` — the host-side graph that builds a `ctx` satisfying `R`.
314
+ * `T` is the tag. `Ok` and `E` are phantom type parameters (ADR 0014): `Ok` is
315
+ * the value this Cmd settles with, and `E` is the `_tag` union it can fail
316
+ * with. A Cmd carries no requirements (ADR 0020) — its handler gets its
317
+ * services from the plain `ctx` handed to `run`.
277
318
  */
278
- type Cmd<T extends string = string, E = unknown, R = unknown> = {
319
+ type Cmd<T extends string = string, Ok = unknown, E = unknown> = {
279
320
  readonly type: T;
321
+ /** Phantom — the value this Cmd settles with. Never assigned. */
322
+ readonly __ok?: Ok;
280
323
  /** Phantom — the `_tag` union this Cmd can settle with. Never assigned. */
281
324
  readonly __e?: E;
282
- /** Phantom — the `Ctx` slice this Cmd's handler needs. Never assigned. */
283
- readonly __r?: R;
284
325
  };
285
326
  declare const Cmd: {
286
327
  /**
287
- * Declare a typed Cmd constructor (ADR 0014). Returns the builder —
328
+ * Declare a typed Cmd constructor (ADR 0014, 0021). Returns the builder —
288
329
  * `fetch({ url })` yields `{ type: "fetch", url }` — carrying the minted Msg
289
- * builders `fetch.ok(cmd, value)` / `fetch.err(cmd, error)` and the
290
- * declaration the runtime edge parses against. `Settled<typeof fetch>` is
291
- * the two-arm Msg union it settles with; `defineMachine({ cmds: [fetch] })`
292
- * folds that union into the machine's `M`.
330
+ * builders `fetch.ok(cmd, value)` / `fetch.err(cmd, error)` (for replay
331
+ * logs and tests) and the declaration the runtime edge parses against.
332
+ * `Settled<typeof fetch>` is the two-arm Msg union it settles with;
333
+ * `defineMachine({ cmds: [fetch] })` folds that union into the machine's `M`.
293
334
  *
294
335
  * const fetch = Cmd.define("fetch", {
295
336
  * input: z.object({ url: z.string() }),
296
337
  * ok: z.object({ status: z.number(), body: z.string() }),
297
338
  * err: ["not_found", "timeout"],
298
- * requirements: Cmd.requirements<{ http: Http }>(),
299
339
  * });
300
340
  *
301
- * `err` is the `_tag` list the handler may settle with; the runtime adds
302
- * `malformed_result` for an `_ok` value the `ok` schema rejects. `requirements`
303
- * names the `Ctx` slice the handler reads — `run` refuses a ctx without it.
341
+ * `input` and `ok` take any Standard Schema whose `validate` is synchronous:
342
+ * zod directly, Effect Schema through `Schema.toStandardSchemaV1(...)`. `err`
343
+ * is the `_tag` list the handler may fail with; the runtime adds
344
+ * `malformed_result` for an `Ok` value the `ok` schema rejects.
345
+ *
346
+ * The handler returns an outcome and the engine mints the Msg:
347
+ *
348
+ * fetch: async (cmd, { ok, err }) =>
349
+ * res.status === 404 ? err({ _tag: "not_found" }) : ok(await res.json()),
350
+ *
351
+ * A throw or an undeclared tag goes to the error sink, never to `fetch_err`.
352
+ * The handler reads its services off the plain `ctx` handed to `run` (ADR
353
+ * 0020).
304
354
  *
305
355
  * A Cmd must not wait; see `DepKeyedSub` for anything that watches.
306
356
  */
307
357
  readonly define: typeof defineCmd;
308
- /**
309
- * Name a Cmd's `R` — the `Ctx` slice its handler reads. A phantom: nothing
310
- * is built, nothing is checked at runtime; the type is what `run` reads.
311
- */
312
- readonly requirements: <R>() => Requirements<R>;
313
358
  /**
314
359
  * The empty Cmd array. Typed `readonly never[]` so it's assignable to any
315
360
  * `readonly C[]` for any `C extends Cmd`. Use in `init` returns and
@@ -375,40 +420,40 @@ type SubId = string & {
375
420
  * Strengthens invariant 7 (identity is explicit).
376
421
  */
377
422
  declare function subId(s: string): SubId;
378
- type Sub<T extends string = string> = {
423
+ type Sub<T extends string = string, D = unknown> = {
379
424
  readonly id: SubId;
380
425
  readonly type: T;
426
+ readonly deps: D;
381
427
  };
382
428
  type Dispose = () => void | Promise<void>;
429
+ /** The `deps` a `timer` Sub declares: fire `msg` once, `ms` after it starts. */
430
+ type TimerDeps<M> = {
431
+ readonly ms: number;
432
+ readonly msg: M;
433
+ };
434
+ /** The built-in `timer` Sub, as its runner sees it. */
435
+ type TimerSub<M> = Sub<"timer", TimerDeps<M>>;
436
+ /** The Sub types every engine ships a runner for. */
437
+ type BuiltinSubType = "timer";
438
+ /** The built-in Subs a machine over `M` may declare without declaring them. */
439
+ type BuiltinSub<M> = TimerSub<M>;
440
+ /**
441
+ * The one `id` of a Sub: a structural hash of its `type` and its `deps`
442
+ * value. Same type and same deps → same id → the running Sub is left alone.
443
+ */
444
+ declare function subIdOf(type: string, deps: unknown): SubId;
383
445
  declare function structuralHash(deps: unknown): string;
384
- interface DepKeyedSub<S, M, Ctx = unknown> {
385
- /**
386
- * The slice of state this Sub depends on. `null` OR `undefined` ⇒ the Sub is
387
- * inactive in this state (the substrate disposes it if it was running) — see
388
- * `depsInactive`, so `(s) => s.optionalRunId` gates correctly. Otherwise the
389
- * Sub is active, keyed on `structuralHash(deps)`.
390
- *
391
- * Pure (invariant 2). Plain JSON-compatible data only (invariant 1) — the
392
- * structural hash walks it deterministically and THROWS on a `Date`, `Map`,
393
- * `Set`, `Error` or class instance rather than collapsing them all onto one
394
- * id. Project such a value first (`startedAt.toISOString()`).
395
- */
396
- readonly deps: (state: S) => unknown;
446
+ type DepKeyedSub<S, U extends Sub = Sub> = U extends Sub<infer T, infer D> ? {
447
+ readonly type: T;
397
448
  /**
398
- * Open the resource for the current `state` (whose `deps` the kernel just
399
- * found non-null). Receives `dispatch` to fire follow-up Msgs (a timer's
400
- * fire, an inbound frame) and the machine's `ctx` (the host's transport
401
- * factory, storage handles). Returns the `Dispose` the substrate runs on
402
- * teardown / re-arm. Same role as a `subscribe[type]` handler's returned
403
- * cleanup.
404
- *
405
- * `source` takes `state` (not the deps slice) so the slice type `D` never
406
- * escapes the entry — each battery's `.depKeyed` closes over its own typed
407
- * deps internally (cast-free existential: the entry that produced the deps
408
- * is the entry that consumes them).
449
+ * The slice of state this Sub depends on. `null` or `undefined` ⇒ off in
450
+ * this state (see `depsInactive`), so `(s) => s.optionalRunId` gates
451
+ * correctly. Pure (invariant 2). Plain JSON-compatible data only
452
+ * (invariant 1): the structural hash THROWS on a `Date`, `Map`, `Set`,
453
+ * `Error` or class instance rather than collapsing them onto one id.
409
454
  */
410
- readonly source: (state: S, dispatch: (msg: M) => void, ctx: Ctx) => Dispose;
411
- }
455
+ readonly deps: (state: S) => D | null | undefined;
456
+ } : never;
412
457
  interface Identity<S, M> {
413
458
  /** The identity THIS instance owns. Pure (invariant 2); plain value. */
414
459
  readonly ofState: (state: S) => unknown;
@@ -436,18 +481,33 @@ interface PortEmitter {
436
481
  emit<T>(port: Port<T>, value: T): void;
437
482
  }
438
483
  type NoCtx = Readonly<Record<never, never>>;
484
+ type HandlerCtx<Ctx> = (0 extends 1 & Ctx ? Ctx : [
485
+ Ctx
486
+ ] extends [void] ? unknown : Ctx) & PortEmitter;
439
487
  type Interpret<M extends {
440
488
  type: string;
441
489
  }, C extends Cmd, Ctx> = {
442
- [K in C["type"]]: (cmd: Extract<C, {
490
+ [K in C["type"]]: InterpretCell<M, Extract<C, {
443
491
  type: K;
444
- }>, ctx: Ctx & RequirementsOf<Extract<C, {
445
- type: K;
446
- }>> & PortEmitter, dispatch?: (msg: M) => void) => Promise<M | void>;
492
+ }>, Ctx>;
447
493
  };
494
+ /**
495
+ * One cell of {@link Interpret}: the outcome-returning form for a
496
+ * `Cmd.define`d Cmd, the Msg-returning form for a hand-written one. A Cmd is
497
+ * `Cmd.define`d exactly when its `E` phantom is declared (not `unknown`).
498
+ */
499
+ type InterpretCell<M extends {
500
+ type: string;
501
+ }, C extends Cmd, Ctx> = unknown extends ErrorsOf<C> ? (cmd: C, ctx: HandlerCtx<Ctx>, dispatch?: (msg: M) => void) => Promise<M | void> : (cmd: C, ctx: HandlerCtx<Ctx> & OutcomeHelpers<OkOfCmd<C>, DeclaredErrorsOf<C>>, dispatch?: (msg: M) => void) => Promise<Outcome<OkOfCmd<C>, DeclaredErrorsOf<C>> | void>;
502
+ /** The value a Cmd settles with; `unknown` for a hand-written Cmd. */
503
+ type OkOfCmd<C> = C extends {
504
+ readonly __ok?: infer Ok;
505
+ } ? Ok : unknown;
506
+ /** The failures a `Cmd.define`d Cmd's handler may return: its declared tags. */
507
+ type DeclaredErrorsOf<C> = Exclude<ErrorsOf<C>, MalformedResult>;
448
508
  type InterpretDetached<C extends Cmd, Allowed extends {
449
509
  type: string;
450
- }, Ctx> = (cmd: C, ctx: Ctx & PortEmitter, dispatch: (msg: Allowed) => void) => Promise<void>;
510
+ }, Ctx> = (cmd: C, ctx: HandlerCtx<Ctx>, dispatch: (msg: Allowed) => void) => Promise<void>;
451
511
  type Subscribe<M extends {
452
512
  type: string;
453
513
  }, U extends Sub, Ctx> = {
@@ -455,6 +515,54 @@ type Subscribe<M extends {
455
515
  type: K;
456
516
  }>, ctx: Ctx, dispatch: (msg: M) => void) => Dispose;
457
517
  };
518
+ /**
519
+ * The `interpret` option of an engine's `run`: optional for a machine that
520
+ * emits no Cmd, required — one handler per Cmd variant — for one that does.
521
+ */
522
+ type InterpretArg<M extends {
523
+ type: string;
524
+ }, C extends Cmd, Ctx> = [
525
+ C
526
+ ] extends [Cmd<never>] ? {
527
+ interpret?: Interpret<M, C, Ctx>;
528
+ } : {
529
+ interpret: Interpret<M, C, Ctx>;
530
+ };
531
+ /**
532
+ * The `subscribe` option of an engine's `run`: one runner per Sub type the
533
+ * machine declares, except the built-ins (`timer`) the engine already ships.
534
+ * Optional when every declared type is a built-in. An entry named after a
535
+ * built-in replaces it (#270 R2.1), which is how a test drives time.
536
+ */
537
+ type SubscribeArg<M extends {
538
+ type: string;
539
+ }, U extends Sub, Ctx> = [
540
+ Exclude<U["type"], BuiltinSubType>
541
+ ] extends [never] ? {
542
+ readonly subscribe?: Partial<Subscribe<M, Exclude<U, Sub<never>> | BuiltinSub<M>, Ctx>>;
543
+ } : {
544
+ readonly subscribe: Subscribe<M, Exclude<U, {
545
+ readonly type: BuiltinSubType;
546
+ }>, Ctx> & Partial<Subscribe<M, BuiltinSub<M>, Ctx>>;
547
+ };
548
+ /**
549
+ * The handlers an engine is handed beside a machine: the {@link InterpretArg}
550
+ * Cmd handlers and the {@link SubscribeArg} sub runners. A machine carries
551
+ * neither — it is data, and one machine file runs under any engine.
552
+ */
553
+ type RunHandlers<M extends {
554
+ type: string;
555
+ }, C extends Cmd, U extends Sub, Ctx> = InterpretArg<M, C, Ctx> & SubscribeArg<M, U, Ctx>;
556
+ /**
557
+ * A machine beside the handlers it runs under — what a wrapper, a battery's
558
+ * `toMachine` or an agent host hands around, and what an engine takes apart:
559
+ * `run(wired.machine, { ...wired, ctx })`.
560
+ */
561
+ type Wired<S, M extends {
562
+ type: string;
563
+ }, C extends Cmd, U extends Sub, Ctx> = {
564
+ readonly machine: Machine<S, M, C, U, Ctx>;
565
+ } & RunHandlers<M, C, U, Ctx>;
458
566
  type Machine<S, M extends {
459
567
  type: string;
460
568
  }, C extends Cmd, U extends Sub, Ctx> = {
@@ -487,24 +595,27 @@ type Machine<S, M extends {
487
595
  type: string;
488
596
  }] ? Transitions<S, M, C> : never);
489
597
  /**
490
- * Dep-keyed Subs. Each declares the state slice it depends on; the substrate
491
- * derives the id (`structuralHash(deps)`) and the gate (`deps` non-null) and
492
- * folds them into the SAME reconcile loop `subscriptions` feeds. The author
493
- * never writes `subId(...)` and never lists Subs in a central
494
- * `subscriptions(state)` aggregate — a per-Sub gate travels with the Sub, so
495
- * a new phase can't silently forget to arm it.
496
- *
497
- * The deps slice type is erased to `unknown` per entry — each Sub's slice
498
- * differs, but the slice type never crosses this field (the kernel only needs
499
- * to hash it and pass `state` back to that same entry's `source`).
598
+ * The machine's Subs, as data: each entry names a Sub `type` and the state
599
+ * slice it depends on (`deps`). The engine derives the id
600
+ * (`structuralHash({ type, deps })`) and the gate (`deps` non-null), starts
601
+ * the runner for `type` when an entry turns on, leaves it alone while the id
602
+ * holds, restarts it when the id changes, and stops it on `null` or `stop()`.
500
603
  *
501
- * Optional and independent of `subscriptions` / `subscribe`: a machine that
502
- * omits `subs` reconciles exactly as before.
604
+ * `U` is the machine's own Sub union (`types.sub`); the built-in `timer`
605
+ * (`{ type: "timer", deps: (s) => ({ ms, msg }) }`) is always available.
503
606
  *
504
607
  * Strengthens invariant 4 (lifecycle owned by the substrate) and invariant 7
505
608
  * (identity derived, not hand-authored).
506
609
  */
507
- subs?: ReadonlyArray<DepKeyedSub<S, M, Ctx>>;
610
+ readonly subs?: ReadonlyArray<DepKeyedSub<S, U | BuiltinSub<M>>>;
611
+ /**
612
+ * Phantom — never assigned, never read. `subs` reaches `U` only through a
613
+ * conditional type, which is no inference site, so this is the slot a caller
614
+ * like `run(machine, …)` infers the Sub union from (and so what types its
615
+ * `subscribe` runners). Same device as `Cmd`'s `__ok`. Tuple-wrapped so an
616
+ * empty union (`never`) is still a candidate rather than `undefined`.
617
+ */
618
+ readonly __sub?: readonly [U];
508
619
  /**
509
620
  * Instance-identity filter. Declares THIS instance's identity once; the
510
621
  * substrate drops any message addressed to a DIFFERENT identity before it
@@ -522,14 +633,6 @@ type Machine<S, M extends {
522
633
  * observable point, not per cell).
523
634
  */
524
635
  identity?: Identity<S, M>;
525
- /**
526
- * Manual Sub aggregate — the documented escape hatch, KEPT alongside `subs`.
527
- * The machine that needs cross-Sub logic the per-Sub `deps` fold can't
528
- * express lists Subs here; the substrate reconciles them via `subscribe`.
529
- * Both paths feed ONE reconcile pass.
530
- */
531
- subscriptions?: (state: S) => readonly U[];
532
- subscribe?: Subscribe<M, U, Ctx>;
533
636
  /**
534
637
  * The update form ("reducer" | "transitions"), stamped non-enumerably by
535
638
  * `defineMachine` at construction (see `UpdateForm` / `formOf`). Optional in
@@ -538,14 +641,7 @@ type Machine<S, M extends {
538
641
  * `detectUpdateForm` when the tag is absent. Never written by hand.
539
642
  */
540
643
  readonly __form?: UpdateForm;
541
- } & ([C] extends [Cmd<never>] ? {
542
- interpret?: Interpret<M, C, Ctx>;
543
- } : {
544
- interpret: Interpret<M, C, Ctx>;
545
- }) & ([U] extends [Sub<never>] ? unknown : {
546
- subscriptions: (state: S) => readonly U[];
547
- subscribe: Subscribe<M, U, Ctx>;
548
- });
644
+ };
549
645
  declare function foldUpdates<S, M extends {
550
646
  type: string;
551
647
  }, C extends Cmd>(machine: {
@@ -559,4 +655,4 @@ declare function foldMsgs<S, M extends {
559
655
  type: string;
560
656
  }, C extends Cmd, U extends Sub, Ctx>(machine: Machine<S, M, C, U, Ctx>, base: S, msgs: readonly M[]): S;
561
657
 
562
- export { type AnyCmdDef as A, applyCell as B, Cmd as C, type Dispose as D, type ErrOf as E, applyCellChecked as F, describeMachine as G, detectUpdateForm as H, type Interpret as I, foldMsgs as J, foldUpdates as K, formOf as L, type Machine as M, NoCellError as N, type OkOf as O, type Port as P, msgKeysOf as Q, type RequiredCtx as R, type Sub as S, type Transitions as T, type UpdateForm as U, structuralHash as V, subId as W, type CmdOf as a, type CmdDef as b, type SubId as c, type Reducer as d, type Settled as e, type RequirementsOf as f, type PortEmitter as g, type InterpretDetached as h, type NoCtx as i, type Tagged as j, type MalformedResult as k, type CmdValue as l, type Requirements as m, type TaggedError as n, type DepKeyedSub as o, type CmdInput as p, type ErrorsOf as q, type ExhaustiveTransitions as r, type Identity as s, type MachineShape as t, type SettledErr as u, type SettledOk as v, type Subscribe as w, type SyncReturn as x, acceptedTypes as y, acceptsOf as z };
658
+ export { applyCell as $, type AnyCmdDef as A, type BuiltinSubType as B, Cmd as C, type DeclaredErrorsOf as D, type ErrorsOf as E, type InterpretCell as F, type MachineShape as G, type HandlerCtx as H, type InterpretDetached as I, type NoCtx as J, OutcomeContractError as K, type OutcomeHelpers as L, type Machine as M, NoCellError as N, type OkOfCmd as O, type Port as P, type PortEmitter as Q, type RunHandlers as R, type Sub as S, type TimerDeps as T, type UpdateForm as U, type SubscribeArg as V, type Wired as W, type SyncReturn as X, UndeclaredFailureError as Y, acceptedTypes as Z, acceptsOf as _, type BuiltinSub as a, applyCellChecked as a0, describeMachine as a1, detectUpdateForm as a2, foldMsgs as a3, foldUpdates as a4, formOf as a5, msgKeysOf as a6, structuralHash as a7, subId as a8, subIdOf as a9, type CmdDef as b, type CmdOf as c, type Subscribe as d, type SettledOk as e, type SettledErr as f, type TaggedError as g, type Dispose as h, type Reducer as i, type Settled as j, type Transitions as k, Outcome as l, type SubId as m, type DepKeyedSub as n, type Interpret as o, type TimerSub as p, type MalformedResult as q, type Tagged as r, type OkOf as s, type ErrOf as t, type CmdValue as u, AsyncSchemaError as v, type CmdInput as w, type ExhaustiveTransitions as x, type Identity as y, type InterpretArg as z };