@demlik/tea 0.14.0 → 0.16.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 (116) hide show
  1. package/README.md +30 -7
  2. package/dist/agent/index.d.ts +49 -36
  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-5XU6ZJO2.js +533 -0
  7. package/dist/chunk-5XU6ZJO2.js.map +1 -0
  8. package/dist/{chunk-AQ6ZIMEA.js → chunk-6NG4V5SB.js} +89 -115
  9. package/dist/chunk-6NG4V5SB.js.map +1 -0
  10. package/dist/{chunk-HYDWG35Q.js → chunk-7MGXQZPW.js} +11 -9
  11. package/dist/chunk-7MGXQZPW.js.map +1 -0
  12. package/dist/{chunk-BLJ2JQSH.js → chunk-BCTEOVOU.js} +3 -3
  13. package/dist/{chunk-BLJ2JQSH.js.map → chunk-BCTEOVOU.js.map} +1 -1
  14. package/dist/chunk-CH5KTOEZ.js +710 -0
  15. package/dist/chunk-CH5KTOEZ.js.map +1 -0
  16. package/dist/chunk-CIHSHLQX.js +64 -0
  17. package/dist/chunk-CIHSHLQX.js.map +1 -0
  18. package/dist/{chunk-Z2L3LSNV.js → chunk-EHUDXAKC.js} +246 -210
  19. package/dist/chunk-EHUDXAKC.js.map +1 -0
  20. package/dist/chunk-GOX2CYIM.js +380 -0
  21. package/dist/chunk-GOX2CYIM.js.map +1 -0
  22. package/dist/chunk-IVJP3GKJ.js +104 -0
  23. package/dist/chunk-IVJP3GKJ.js.map +1 -0
  24. package/dist/{chunk-F7FMAWLA.js → chunk-MVZS5FDM.js} +13 -6
  25. package/dist/chunk-MVZS5FDM.js.map +1 -0
  26. package/dist/{chunk-LYLTKJWM.js → chunk-MYNLY3HP.js} +9 -8
  27. package/dist/chunk-MYNLY3HP.js.map +1 -0
  28. package/dist/{chunk-I5MQMJDW.js → chunk-NSIAORRY.js} +20 -30
  29. package/dist/chunk-NSIAORRY.js.map +1 -0
  30. package/dist/{chunk-MYXFNWAJ.js → chunk-QNGYQMZB.js} +4 -4
  31. package/dist/chunk-QNGYQMZB.js.map +1 -0
  32. package/dist/chunk-WT5PBPLB.js +98 -0
  33. package/dist/chunk-WT5PBPLB.js.map +1 -0
  34. package/dist/{core-CTzMJ82M.d.ts → core-BbgtiXdg.d.ts} +231 -139
  35. package/dist/do/index.d.ts +37 -32
  36. package/dist/do/index.js +21 -14
  37. package/dist/do/index.js.map +1 -1
  38. package/dist/{durable-effects-B0-qGQDy.d.ts → durable-effects-7MTK_jnj.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 -70
  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-DJWIER_3.d.ts → index-7vV8xmsD.d.ts} +1 -1
  51. package/dist/{index-NjrT3fL2.d.ts → index-Bz5Rh9Ga.d.ts} +19 -96
  52. package/dist/index-CjFDUBeq.d.ts +207 -0
  53. package/dist/{index-6A7dB8f6.d.ts → index-CkFYA9Y6.d.ts} +14 -16
  54. package/dist/{index-B5BZ-_cT.d.ts → index-Cou86-GX.d.ts} +189 -108
  55. package/dist/{index-TvRb1KVf.d.ts → index-DU6JpQ8G.d.ts} +1 -1
  56. package/dist/{index-q0hXFeZ0.d.ts → index-Xufl55W8.d.ts} +286 -215
  57. package/dist/{index-4vZzljCD.d.ts → index-_dOR3xqA.d.ts} +57 -45
  58. package/dist/index.d.ts +181 -385
  59. package/dist/index.js +2 -1
  60. package/dist/jev/index.d.ts +147 -99
  61. package/dist/jev/index.js +329 -233
  62. package/dist/jev/index.js.map +1 -1
  63. package/dist/{machine-CdIcN2Xm.d.ts → machine-BQzTV8On.d.ts} +171 -280
  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 -33
  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 +6 -7
  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-ClRZBhHQ.d.ts +53 -0
  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 -455
  91. package/dist/resilience/index.js +37 -483
  92. package/dist/resilience/index.js.map +1 -1
  93. package/dist/{runtime-types-LWDoi943.d.ts → runtime-types-CiVpC0HN.d.ts} +131 -388
  94. package/dist/testing/index.d.ts +165 -15
  95. package/dist/testing/index.js +104 -3
  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-DP3f5NIl.d.ts → types-LxZxGYda.d.ts} +2 -2
  101. package/dist/work-queue/index.d.ts +5 -6
  102. package/package.json +18 -5
  103. package/dist/chunk-AQ6ZIMEA.js.map +0 -1
  104. package/dist/chunk-F2US5BW6.js +0 -72
  105. package/dist/chunk-F2US5BW6.js.map +0 -1
  106. package/dist/chunk-F7FMAWLA.js.map +0 -1
  107. package/dist/chunk-HUKZQX6U.js +0 -97
  108. package/dist/chunk-HUKZQX6U.js.map +0 -1
  109. package/dist/chunk-HYDWG35Q.js.map +0 -1
  110. package/dist/chunk-I5MQMJDW.js.map +0 -1
  111. package/dist/chunk-LYLTKJWM.js.map +0 -1
  112. package/dist/chunk-MYXFNWAJ.js.map +0 -1
  113. package/dist/chunk-RQULHGYH.js +0 -1804
  114. package/dist/chunk-RQULHGYH.js.map +0 -1
  115. package/dist/chunk-Z2L3LSNV.js.map +0 -1
  116. package/dist/index-DMCeMPMJ.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,50 @@ 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
+ */
117
+ declare class OutcomeContractError extends Error {
118
+ readonly cmdType: string;
119
+ readonly name = "OutcomeContractError";
120
+ readonly _tag: "OutcomeContractError";
121
+ constructor(cmdType: string, detail: string);
122
+ }
71
123
  /**
72
124
  * The payload a constructor accepts: a plain record spread beside `type`. A
73
125
  * `type` key is refused at the type level — it would overwrite the discriminant.
@@ -75,16 +127,8 @@ type MalformedResult = {
75
127
  type CmdInput = {
76
128
  readonly type?: never;
77
129
  } & 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
130
  /** 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>;
131
+ type CmdValue<Name extends string, Input extends CmdInput, Ok, E extends Tagged> = Cmd<Name, Ok, E | MalformedResult> & Readonly<Input>;
88
132
  type SettledOk<Name extends string, C, Ok> = {
89
133
  readonly type: `${Name}_ok`;
90
134
  readonly cmd: C;
@@ -104,37 +148,39 @@ type SettledErr<Name extends string, C, E extends Tagged> = {
104
148
  * the minted Msg builders and the declaration hung on it. `E` here is the
105
149
  * DECLARED tag union; the settled `_err` arm widens it by `MalformedResult`.
106
150
  *
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.
151
+ * `ok` / `err` mint a settled Msg OUTSIDE the runtime (a `replay` log, a unit
152
+ * test) and take an optional `at`. A handler never calls them: it returns an
153
+ * {@link Outcome}, and inside `run` the interpret edge mints and stamps.
110
154
  */
111
- interface CmdDef<Name extends string, Input extends CmdInput, Ok, E extends Tagged, R> {
112
- (input: Input): CmdValue<Name, Input, E, R>;
155
+ interface CmdDef<Name extends string, Input extends CmdInput, Ok, E extends Tagged> {
156
+ (input: Input): CmdValue<Name, Input, Ok, E>;
113
157
  /** The `type` discriminant of every Cmd this builds. */
114
158
  readonly cmdType: Name;
115
159
  readonly okType: `${Name}_ok`;
116
160
  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>;
161
+ readonly ok: (cmd: CmdValue<Name, Input, Ok, E>, value: Ok, at?: number) => SettledOk<Name, CmdValue<Name, Input, Ok, E>, Ok>;
162
+ readonly err: (cmd: CmdValue<Name, Input, Ok, E>, error: E, at?: number) => SettledErr<Name, CmdValue<Name, Input, Ok, E>, E>;
119
163
  readonly schema: {
120
- readonly input: z.ZodType<Input>;
121
- readonly ok: z.ZodType<Ok>;
164
+ readonly input: StandardSchemaV1<unknown, Input>;
165
+ readonly ok: StandardSchemaV1<unknown, Ok>;
122
166
  };
123
167
  /** The declared `_tag` list, verbatim. */
124
168
  readonly errTags: ReadonlyArray<E["_tag"]>;
125
169
  }
126
170
  /**
127
171
  * 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.
172
+ * which two Msg types it settles with, the `ok` schema the edge parses against
173
+ * and the tags an `Err` may carry. Every `CmdDef<…>` is one of these
174
+ * structurally.
130
175
  */
131
176
  type AnyCmdDef = {
132
177
  readonly cmdType: string;
133
178
  readonly okType: string;
134
179
  readonly errType: string;
135
180
  readonly schema: {
136
- readonly ok: z.ZodType;
181
+ readonly ok: StandardSchemaV1;
137
182
  };
183
+ readonly errTags: ReadonlyArray<string>;
138
184
  };
139
185
  /** The Cmd value a def (or a union of defs) builds. */
140
186
  type CmdOf<D extends AnyCmdDef> = D extends ((input: never) => infer C extends Cmd) ? C : never;
@@ -143,17 +189,16 @@ type CmdOf<D extends AnyCmdDef> = D extends ((input: never) => infer C extends C
143
189
  * `value`, `<name>_err` carrying `error`. `defineMachine({ cmds })` folds this
144
190
  * into the machine's `M` so the user never spells the effect half of it.
145
191
  */
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;
192
+ 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
193
  /** 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;
194
+ type OkOf<D extends AnyCmdDef> = D extends CmdDef<infer _Name, infer _Input, infer Ok, infer _E> ? Ok : never;
149
195
  /** 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>;
196
+ type ErrOf<D extends AnyCmdDef> = D extends CmdDef<infer _Name, infer _Input, infer _Ok, infer E> ? E : never;
197
+ declare function defineCmd<const Name extends string, Input extends CmdInput, Ok, const Tags extends readonly string[]>(name: Name, spec: {
198
+ readonly input: StandardSchemaV1<unknown, Input>;
199
+ readonly ok: StandardSchemaV1<unknown, Ok>;
154
200
  readonly err: Tags;
155
- readonly requirements?: Requirements<R>;
156
- }): CmdDef<Name, Input, Ok, TaggedError<Tags[number]>, R>;
201
+ }): CmdDef<Name, Input, Ok, TaggedError<Tags[number]>>;
157
202
  type SyncReturn<S, C extends Cmd> = readonly [S, readonly C[]] & {
158
203
  readonly then?: never;
159
204
  };
@@ -265,51 +310,50 @@ type ExhaustiveTransitions<S extends {
265
310
  /**
266
311
  * A tagged-union, one-shot effect — JSON-plain, hashable, replayable.
267
312
  *
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`.
313
+ * `T` is the tag. `Ok` and `E` are phantom type parameters (ADR 0014): `Ok` is
314
+ * the value this Cmd settles with, and `E` is the `_tag` union it can fail
315
+ * with. A Cmd carries no requirements (ADR 0020) — its handler gets its
316
+ * services from the plain `ctx` handed to `run`.
277
317
  */
278
- type Cmd<T extends string = string, E = unknown, R = unknown> = {
318
+ type Cmd<T extends string = string, Ok = unknown, E = unknown> = {
279
319
  readonly type: T;
320
+ /** Phantom — the value this Cmd settles with. Never assigned. */
321
+ readonly __ok?: Ok;
280
322
  /** Phantom — the `_tag` union this Cmd can settle with. Never assigned. */
281
323
  readonly __e?: E;
282
- /** Phantom — the `Ctx` slice this Cmd's handler needs. Never assigned. */
283
- readonly __r?: R;
284
324
  };
285
325
  declare const Cmd: {
286
326
  /**
287
- * Declare a typed Cmd constructor (ADR 0014). Returns the builder —
327
+ * Declare a typed Cmd constructor (ADR 0014, 0021). Returns the builder —
288
328
  * `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`.
329
+ * builders `fetch.ok(cmd, value)` / `fetch.err(cmd, error)` (for replay
330
+ * logs and tests) and the declaration the runtime edge parses against.
331
+ * `Settled<typeof fetch>` is the two-arm Msg union it settles with;
332
+ * `defineMachine({ cmds: [fetch] })` folds that union into the machine's `M`.
293
333
  *
294
334
  * const fetch = Cmd.define("fetch", {
295
335
  * input: z.object({ url: z.string() }),
296
336
  * ok: z.object({ status: z.number(), body: z.string() }),
297
337
  * err: ["not_found", "timeout"],
298
- * requirements: Cmd.requirements<{ http: Http }>(),
299
338
  * });
300
339
  *
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.
340
+ * `input` and `ok` take any Standard Schema whose `validate` is synchronous:
341
+ * zod directly, Effect Schema through `Schema.toStandardSchemaV1(...)`. `err`
342
+ * is the `_tag` list the handler may fail with; the runtime adds
343
+ * `malformed_result` for an `Ok` value the `ok` schema rejects.
344
+ *
345
+ * The handler returns an outcome and the engine mints the Msg:
346
+ *
347
+ * fetch: async (cmd, { ok, err }) =>
348
+ * res.status === 404 ? err({ _tag: "not_found" }) : ok(await res.json()),
349
+ *
350
+ * A throw or an undeclared tag goes to the error sink, never to `fetch_err`.
351
+ * The handler reads its services off the plain `ctx` handed to `run` (ADR
352
+ * 0020).
304
353
  *
305
354
  * A Cmd must not wait; see `DepKeyedSub` for anything that watches.
306
355
  */
307
356
  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
357
  /**
314
358
  * The empty Cmd array. Typed `readonly never[]` so it's assignable to any
315
359
  * `readonly C[]` for any `C extends Cmd`. Use in `init` returns and
@@ -375,40 +419,40 @@ type SubId = string & {
375
419
  * Strengthens invariant 7 (identity is explicit).
376
420
  */
377
421
  declare function subId(s: string): SubId;
378
- type Sub<T extends string = string> = {
422
+ type Sub<T extends string = string, D = unknown> = {
379
423
  readonly id: SubId;
380
424
  readonly type: T;
425
+ readonly deps: D;
381
426
  };
382
427
  type Dispose = () => void | Promise<void>;
428
+ /** The `deps` a `timer` Sub declares: fire `msg` once, `ms` after it starts. */
429
+ type TimerDeps<M> = {
430
+ readonly ms: number;
431
+ readonly msg: M;
432
+ };
433
+ /** The built-in `timer` Sub, as its runner sees it. */
434
+ type TimerSub<M> = Sub<"timer", TimerDeps<M>>;
435
+ /** The Sub types every engine ships a runner for. */
436
+ type BuiltinSubType = "timer";
437
+ /** The built-in Subs a machine over `M` may declare without declaring them. */
438
+ type BuiltinSub<M> = TimerSub<M>;
439
+ /**
440
+ * The one `id` of a Sub: a structural hash of its `type` and its `deps`
441
+ * value. Same type and same deps → same id → the running Sub is left alone.
442
+ */
443
+ declare function subIdOf(type: string, deps: unknown): SubId;
383
444
  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;
445
+ type DepKeyedSub<S, U extends Sub = Sub> = U extends Sub<infer T, infer D> ? {
446
+ readonly type: T;
397
447
  /**
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).
448
+ * The slice of state this Sub depends on. `null` or `undefined` ⇒ off in
449
+ * this state (see `depsInactive`), so `(s) => s.optionalRunId` gates
450
+ * correctly. Pure (invariant 2). Plain JSON-compatible data only
451
+ * (invariant 1): the structural hash THROWS on a `Date`, `Map`, `Set`,
452
+ * `Error` or class instance rather than collapsing them onto one id.
409
453
  */
410
- readonly source: (state: S, dispatch: (msg: M) => void, ctx: Ctx) => Dispose;
411
- }
454
+ readonly deps: (state: S) => D | null | undefined;
455
+ } : never;
412
456
  interface Identity<S, M> {
413
457
  /** The identity THIS instance owns. Pure (invariant 2); plain value. */
414
458
  readonly ofState: (state: S) => unknown;
@@ -439,12 +483,24 @@ type NoCtx = Readonly<Record<never, never>>;
439
483
  type Interpret<M extends {
440
484
  type: string;
441
485
  }, C extends Cmd, Ctx> = {
442
- [K in C["type"]]: (cmd: Extract<C, {
486
+ [K in C["type"]]: InterpretCell<M, Extract<C, {
443
487
  type: K;
444
- }>, ctx: Ctx & RequirementsOf<Extract<C, {
445
- type: K;
446
- }>> & PortEmitter, dispatch?: (msg: M) => void) => Promise<M | void>;
488
+ }>, Ctx>;
447
489
  };
490
+ /**
491
+ * One cell of {@link Interpret}: the outcome-returning form for a
492
+ * `Cmd.define`d Cmd, the Msg-returning form for a hand-written one. A Cmd is
493
+ * `Cmd.define`d exactly when its `E` phantom is declared (not `unknown`).
494
+ */
495
+ type InterpretCell<M extends {
496
+ type: string;
497
+ }, C extends Cmd, Ctx> = unknown extends ErrorsOf<C> ? (cmd: C, ctx: Ctx & PortEmitter, dispatch?: (msg: M) => void) => Promise<M | void> : (cmd: C, ctx: Ctx & PortEmitter & OutcomeHelpers<OkOfCmd<C>, DeclaredErrorsOf<C>>, dispatch?: (msg: M) => void) => Promise<Outcome<OkOfCmd<C>, DeclaredErrorsOf<C>> | void>;
498
+ /** The value a Cmd settles with; `unknown` for a hand-written Cmd. */
499
+ type OkOfCmd<C> = C extends {
500
+ readonly __ok?: infer Ok;
501
+ } ? Ok : unknown;
502
+ /** The failures a `Cmd.define`d Cmd's handler may return: its declared tags. */
503
+ type DeclaredErrorsOf<C> = Exclude<ErrorsOf<C>, MalformedResult>;
448
504
  type InterpretDetached<C extends Cmd, Allowed extends {
449
505
  type: string;
450
506
  }, Ctx> = (cmd: C, ctx: Ctx & PortEmitter, dispatch: (msg: Allowed) => void) => Promise<void>;
@@ -455,6 +511,54 @@ type Subscribe<M extends {
455
511
  type: K;
456
512
  }>, ctx: Ctx, dispatch: (msg: M) => void) => Dispose;
457
513
  };
514
+ /**
515
+ * The `interpret` option of an engine's `run`: optional for a machine that
516
+ * emits no Cmd, required — one handler per Cmd variant — for one that does.
517
+ */
518
+ type InterpretArg<M extends {
519
+ type: string;
520
+ }, C extends Cmd, Ctx> = [
521
+ C
522
+ ] extends [Cmd<never>] ? {
523
+ interpret?: Interpret<M, C, Ctx>;
524
+ } : {
525
+ interpret: Interpret<M, C, Ctx>;
526
+ };
527
+ /**
528
+ * The `subscribe` option of an engine's `run`: one runner per Sub type the
529
+ * machine declares, except the built-ins (`timer`) the engine already ships.
530
+ * Optional when every declared type is a built-in. An entry named after a
531
+ * built-in replaces it (#270 R2.1), which is how a test drives time.
532
+ */
533
+ type SubscribeArg<M extends {
534
+ type: string;
535
+ }, U extends Sub, Ctx> = [
536
+ Exclude<U["type"], BuiltinSubType>
537
+ ] extends [never] ? {
538
+ readonly subscribe?: Partial<Subscribe<M, Exclude<U, Sub<never>> | BuiltinSub<M>, Ctx>>;
539
+ } : {
540
+ readonly subscribe: Subscribe<M, Exclude<U, {
541
+ readonly type: BuiltinSubType;
542
+ }>, Ctx> & Partial<Subscribe<M, BuiltinSub<M>, Ctx>>;
543
+ };
544
+ /**
545
+ * The handlers an engine is handed beside a machine: the {@link InterpretArg}
546
+ * Cmd handlers and the {@link SubscribeArg} sub runners. A machine carries
547
+ * neither — it is data, and one machine file runs under any engine.
548
+ */
549
+ type RunHandlers<M extends {
550
+ type: string;
551
+ }, C extends Cmd, U extends Sub, Ctx> = InterpretArg<M, C, Ctx> & SubscribeArg<M, U, Ctx>;
552
+ /**
553
+ * A machine beside the handlers it runs under — what a wrapper, a battery's
554
+ * `toMachine` or an agent host hands around, and what an engine takes apart:
555
+ * `run(wired.machine, { ...wired, ctx })`.
556
+ */
557
+ type Wired<S, M extends {
558
+ type: string;
559
+ }, C extends Cmd, U extends Sub, Ctx> = {
560
+ readonly machine: Machine<S, M, C, U, Ctx>;
561
+ } & RunHandlers<M, C, U, Ctx>;
458
562
  type Machine<S, M extends {
459
563
  type: string;
460
564
  }, C extends Cmd, U extends Sub, Ctx> = {
@@ -487,24 +591,27 @@ type Machine<S, M extends {
487
591
  type: string;
488
592
  }] ? Transitions<S, M, C> : never);
489
593
  /**
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`).
594
+ * The machine's Subs, as data: each entry names a Sub `type` and the state
595
+ * slice it depends on (`deps`). The engine derives the id
596
+ * (`structuralHash({ type, deps })`) and the gate (`deps` non-null), starts
597
+ * the runner for `type` when an entry turns on, leaves it alone while the id
598
+ * holds, restarts it when the id changes, and stops it on `null` or `stop()`.
500
599
  *
501
- * Optional and independent of `subscriptions` / `subscribe`: a machine that
502
- * omits `subs` reconciles exactly as before.
600
+ * `U` is the machine's own Sub union (`types.sub`); the built-in `timer`
601
+ * (`{ type: "timer", deps: (s) => ({ ms, msg }) }`) is always available.
503
602
  *
504
603
  * Strengthens invariant 4 (lifecycle owned by the substrate) and invariant 7
505
604
  * (identity derived, not hand-authored).
506
605
  */
507
- subs?: ReadonlyArray<DepKeyedSub<S, M, Ctx>>;
606
+ readonly subs?: ReadonlyArray<DepKeyedSub<S, U | BuiltinSub<M>>>;
607
+ /**
608
+ * Phantom — never assigned, never read. `subs` reaches `U` only through a
609
+ * conditional type, which is no inference site, so this is the slot a caller
610
+ * like `run(machine, …)` infers the Sub union from (and so what types its
611
+ * `subscribe` runners). Same device as `Cmd`'s `__ok`. Tuple-wrapped so an
612
+ * empty union (`never`) is still a candidate rather than `undefined`.
613
+ */
614
+ readonly __sub?: readonly [U];
508
615
  /**
509
616
  * Instance-identity filter. Declares THIS instance's identity once; the
510
617
  * substrate drops any message addressed to a DIFFERENT identity before it
@@ -522,14 +629,6 @@ type Machine<S, M extends {
522
629
  * observable point, not per cell).
523
630
  */
524
631
  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
632
  /**
534
633
  * The update form ("reducer" | "transitions"), stamped non-enumerably by
535
634
  * `defineMachine` at construction (see `UpdateForm` / `formOf`). Optional in
@@ -538,14 +637,7 @@ type Machine<S, M extends {
538
637
  * `detectUpdateForm` when the tag is absent. Never written by hand.
539
638
  */
540
639
  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
- });
640
+ };
549
641
  declare function foldUpdates<S, M extends {
550
642
  type: string;
551
643
  }, C extends Cmd>(machine: {
@@ -559,4 +651,4 @@ declare function foldMsgs<S, M extends {
559
651
  type: string;
560
652
  }, C extends Cmd, U extends Sub, Ctx>(machine: Machine<S, M, C, U, Ctx>, base: S, msgs: readonly M[]): S;
561
653
 
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 CmdValue as i, type Tagged as j, type NoCtx as k, type MalformedResult 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 };
654
+ export { applyCellChecked as $, type AnyCmdDef as A, type BuiltinSubType as B, Cmd as C, type DeclaredErrorsOf as D, type ErrorsOf as E, type InterpretArg as F, type InterpretCell as G, type MachineShape 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 SubscribeArg as Q, type RunHandlers as R, type Sub as S, type TimerDeps as T, type UpdateForm as U, type SyncReturn as V, type Wired as W, UndeclaredFailureError as X, acceptedTypes as Y, acceptsOf as Z, applyCell as _, type BuiltinSub as a, describeMachine as a0, detectUpdateForm as a1, foldMsgs as a2, foldUpdates as a3, formOf as a4, msgKeysOf as a5, structuralHash as a6, subId as a7, subIdOf as a8, 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 PortEmitter as m, type SubId as n, type DepKeyedSub as o, type Interpret as p, type TimerSub as q, type MalformedResult as r, type Tagged as s, type OkOf as t, type ErrOf as u, type CmdValue as v, AsyncSchemaError as w, type CmdInput as x, type ExhaustiveTransitions as y, type Identity as z };