@demlik/tea 0.5.1 → 0.7.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 (122) hide show
  1. package/dist/agent/index.d.ts +6 -5
  2. package/dist/agent/index.js +10 -10
  3. package/dist/authed-call/index.d.ts +2 -2
  4. package/dist/authed-call/index.js +7 -7
  5. package/dist/await-terminal/index.d.ts +3 -2
  6. package/dist/await-terminal/index.js +2 -2
  7. package/dist/batch-window/index.d.ts +4 -3
  8. package/dist/batch-window/index.js +3 -3
  9. package/dist/cache/index.d.ts +2 -2
  10. package/dist/cache/index.js +4 -4
  11. package/dist/chart/index.d.ts +934 -0
  12. package/dist/chart/index.js +244 -0
  13. package/dist/chart/index.js.map +1 -0
  14. package/dist/{chunk-2UGTDYOK.js → chunk-3JU6657S.js} +3 -3
  15. package/dist/{chunk-2UGTDYOK.js.map → chunk-3JU6657S.js.map} +1 -1
  16. package/dist/{chunk-AZ3NHUPD.js → chunk-4KTWLPL5.js} +3 -3
  17. package/dist/{chunk-AZ3NHUPD.js.map → chunk-4KTWLPL5.js.map} +1 -1
  18. package/dist/{chunk-ZH454CR5.js → chunk-5EHLEUTL.js} +24 -4
  19. package/dist/chunk-5EHLEUTL.js.map +1 -0
  20. package/dist/{chunk-WF46FABO.js → chunk-7SVIRMC6.js} +3 -3
  21. package/dist/{chunk-WF46FABO.js.map → chunk-7SVIRMC6.js.map} +1 -1
  22. package/dist/{chunk-XMHZ44QC.js → chunk-7V4EVLZA.js} +4 -4
  23. package/dist/{chunk-XMHZ44QC.js.map → chunk-7V4EVLZA.js.map} +1 -1
  24. package/dist/{chunk-IVHQCVFX.js → chunk-A56OR5RF.js} +3 -3
  25. package/dist/{chunk-IVHQCVFX.js.map → chunk-A56OR5RF.js.map} +1 -1
  26. package/dist/{chunk-O7ED34JH.js → chunk-B5VXOFMZ.js} +47 -15
  27. package/dist/chunk-B5VXOFMZ.js.map +1 -0
  28. package/dist/{chunk-EC6FO42Q.js → chunk-EUF7XOEE.js} +6 -6
  29. package/dist/{chunk-EC6FO42Q.js.map → chunk-EUF7XOEE.js.map} +1 -1
  30. package/dist/{chunk-XOAP3LOT.js → chunk-I5OV65MS.js} +3 -3
  31. package/dist/{chunk-XOAP3LOT.js.map → chunk-I5OV65MS.js.map} +1 -1
  32. package/dist/{chunk-ASX7PL2K.js → chunk-JGVL3WPL.js} +3 -3
  33. package/dist/{chunk-ASX7PL2K.js.map → chunk-JGVL3WPL.js.map} +1 -1
  34. package/dist/{chunk-S6Y3RNX4.js → chunk-JP5D6GSL.js} +4 -4
  35. package/dist/{chunk-S6Y3RNX4.js.map → chunk-JP5D6GSL.js.map} +1 -1
  36. package/dist/{chunk-ERYY5P6W.js → chunk-ND3DH6KM.js} +3 -3
  37. package/dist/{chunk-ERYY5P6W.js.map → chunk-ND3DH6KM.js.map} +1 -1
  38. package/dist/{chunk-A7USKARI.js → chunk-SUST46KO.js} +3 -3
  39. package/dist/{chunk-A7USKARI.js.map → chunk-SUST46KO.js.map} +1 -1
  40. package/dist/{chunk-2KBEIGYP.js → chunk-TP5UPGLY.js} +3 -3
  41. package/dist/{chunk-2KBEIGYP.js.map → chunk-TP5UPGLY.js.map} +1 -1
  42. package/dist/{chunk-66S2KEQQ.js → chunk-WLGO64WC.js} +4 -4
  43. package/dist/{chunk-66S2KEQQ.js.map → chunk-WLGO64WC.js.map} +1 -1
  44. package/dist/{chunk-UV7VCTNC.js → chunk-ZF6WDK2D.js} +7 -7
  45. package/dist/{chunk-UV7VCTNC.js.map → chunk-ZF6WDK2D.js.map} +1 -1
  46. package/dist/{core-JPHsMZVB.d.ts → core-Bjc0bS8j.d.ts} +37 -1
  47. package/dist/deadline/index.d.ts +2 -2
  48. package/dist/deadline/index.js +3 -3
  49. package/dist/do/index.d.ts +7 -6
  50. package/dist/do/index.js +10 -10
  51. package/dist/{durable-effects-MRnCBCxV.d.ts → durable-effects-D8SqU_if.d.ts} +1 -1
  52. package/dist/extension/index.d.ts +3 -2
  53. package/dist/extension/index.js +3 -3
  54. package/dist/extension/react.js +3 -3
  55. package/dist/extension/subs/index.d.ts +2 -2
  56. package/dist/fan-out/index.d.ts +3 -2
  57. package/dist/idempotent-intake/index.d.ts +3 -2
  58. package/dist/index.d.ts +5 -4
  59. package/dist/index.js +2 -2
  60. package/dist/llm-call/index.d.ts +2 -2
  61. package/dist/llm-call/index.js +7 -7
  62. package/dist/{machine-nGXCMyHn.d.ts → machine-0OmPvsy_.d.ts} +1 -1
  63. package/dist/machine-viz/index.d.ts +1 -1
  64. package/dist/machine-viz/index.js +2 -2
  65. package/dist/mem/index.d.ts +3 -2
  66. package/dist/monitored-run/index.d.ts +4 -3
  67. package/dist/monitored-run/index.js +5 -5
  68. package/dist/node/index.d.ts +3 -2
  69. package/dist/paginated-walk/index.d.ts +2 -2
  70. package/dist/paginated-walk/index.js +7 -7
  71. package/dist/parity/index.d.ts +31 -2
  72. package/dist/parity/index.js +3 -3
  73. package/dist/parity/index.js.map +1 -1
  74. package/dist/pbt/arbitraries/index.d.ts +1 -1
  75. package/dist/pbt/index.d.ts +1 -1
  76. package/dist/pbt/index.js +3 -3
  77. package/dist/pbt/runners/index.d.ts +1 -1
  78. package/dist/pbt/runners/index.js +3 -3
  79. package/dist/poller/index.d.ts +28 -7
  80. package/dist/poller/index.js +3 -3
  81. package/dist/poller/index.js.map +1 -1
  82. package/dist/prediction/index.d.ts +1 -1
  83. package/dist/prediction/index.js +2 -2
  84. package/dist/pure/index.d.ts +1 -1
  85. package/dist/pure/index.js +2 -2
  86. package/dist/react/index.d.ts +3 -2
  87. package/dist/react/index.js +2 -2
  88. package/dist/reconciler/index.d.ts +2 -2
  89. package/dist/reconciler/index.js +7 -7
  90. package/dist/recorder/index.d.ts +3 -2
  91. package/dist/resilient-call/index.d.ts +2 -2
  92. package/dist/resilient-call/index.js +6 -6
  93. package/dist/{runtime-types-BbBq4LWo.d.ts → runtime-types-Bxc637bp.d.ts} +53 -2
  94. package/dist/saga/index.d.ts +3 -2
  95. package/dist/snapshot/index.d.ts +1 -1
  96. package/dist/snapshot/index.js +3 -3
  97. package/dist/subs/index.d.ts +4 -3
  98. package/dist/subs/index.js +3 -3
  99. package/dist/testing/index.d.ts +3 -2
  100. package/dist/testing/index.js +2 -2
  101. package/dist/throttled-input/index.d.ts +2 -2
  102. package/dist/throttled-input/index.js +6 -6
  103. package/dist/token-refresh/index.d.ts +1 -1
  104. package/dist/token-refresh/index.js +3 -3
  105. package/dist/trace-replay/index.d.ts +3 -2
  106. package/dist/trace-replay/index.js +3 -3
  107. package/dist/{types-BMZ7IMrd.d.ts → types-D7u9DkH7.d.ts} +1 -1
  108. package/dist/with-deadline/index.d.ts +1 -1
  109. package/dist/with-deadline/index.js +2 -2
  110. package/dist/with-resilience/index.d.ts +2 -2
  111. package/dist/with-resilience/index.js +6 -6
  112. package/dist/with-telemetry/index.d.ts +1 -1
  113. package/dist/with-telemetry/index.js +2 -2
  114. package/dist/work-queue/adapter.d.ts +3 -2
  115. package/dist/work-queue/index.d.ts +3 -2
  116. package/dist/work-queue/ops.d.ts +3 -2
  117. package/dist/workflow/index.d.ts +6 -4
  118. package/dist/workflow/index.js +1 -1
  119. package/dist/workflow/index.js.map +1 -1
  120. package/package.json +8 -1
  121. package/dist/chunk-O7ED34JH.js.map +0 -1
  122. package/dist/chunk-ZH454CR5.js.map +0 -1
@@ -0,0 +1,244 @@
1
+ import { Cmd, NoCellError } from '../chunk-B5VXOFMZ.js';
2
+
3
+ // src/chart/compile.ts
4
+ var CellTargetError = class extends Error {
5
+ constructor(at, cell, returned, declared) {
6
+ super(
7
+ `@demlik/tea: cell "${cell}" at edge "${at}" returned state "${returned}", which is not among that edge's declared targets [${declared.map((t) => `"${t}"`).join(", ")}] \u2014 either the cell is wrong, or the edge's \`to\` is missing a target the code can reach (in which case add it, so the chart still draws the whole fan-out).`
8
+ );
9
+ this.at = at;
10
+ this.cell = cell;
11
+ this.returned = returned;
12
+ this.declared = declared;
13
+ }
14
+ at;
15
+ cell;
16
+ returned;
17
+ declared;
18
+ name = "CellTargetError";
19
+ _tag = "CellTargetError";
20
+ };
21
+ function cmdNames(ref) {
22
+ if (ref === void 0) return [];
23
+ return typeof ref === "string" ? [ref] : ref;
24
+ }
25
+ function flatten(c) {
26
+ const out = /* @__PURE__ */ new Map();
27
+ for (const group of Object.keys(c.states)) {
28
+ const members = c.states[group] ?? {};
29
+ for (const s of Object.keys(members)) {
30
+ const node = members[s];
31
+ if (node !== void 0) out.set(s, { node, group });
32
+ }
33
+ }
34
+ return out;
35
+ }
36
+ function scopeList(scope) {
37
+ return typeof scope === "string" ? [scope] : scope;
38
+ }
39
+ function rtParts(parts) {
40
+ const p = parts;
41
+ return {
42
+ assign: p.assign ?? {},
43
+ guards: p.guards ?? {},
44
+ cmds: p.cmds ?? {},
45
+ cells: p.cells ?? {}
46
+ };
47
+ }
48
+ function buildCell(spec, bare, at, p, parking) {
49
+ const edge = typeof spec === "string" ? { target: spec } : spec;
50
+ const cell = p.assign[at];
51
+ if (edge.cell !== void 0) {
52
+ const name = edge.cell;
53
+ const impl = p.cells[name];
54
+ if (impl === void 0) {
55
+ throw new Error(
56
+ `@demlik/tea: edge "${at}" names cell "${name}" with no implementation`
57
+ );
58
+ }
59
+ const hand = typeof impl === "function" ? impl : impl[at];
60
+ if (hand === void 0) {
61
+ throw new Error(
62
+ `@demlik/tea: cell "${name}" is written in the per-site form but has no entry for edge "${at}"`
63
+ );
64
+ }
65
+ const to = edge.to ?? [];
66
+ return (st, nsMsg) => {
67
+ const out = hand(st, { ...nsMsg, type: bare }, at);
68
+ if (!to.includes(out[0].type)) {
69
+ throw new CellTargetError(at, name, out[0].type, to);
70
+ }
71
+ return out;
72
+ };
73
+ }
74
+ return (st, nsMsg) => {
75
+ const msg = { ...nsMsg, type: bare };
76
+ let target;
77
+ let payloadFn;
78
+ let fired = true;
79
+ if (edge.resume !== void 0) {
80
+ target = st.was ?? edge.resume.fallback;
81
+ payloadFn = cell;
82
+ } else if (edge.when !== void 0) {
83
+ const guard = p.guards[edge.when];
84
+ fired = guard !== void 0 && guard(st, msg, at) === true;
85
+ const branch = cell;
86
+ target = fired ? edge.target : edge.otherwise;
87
+ payloadFn = fired ? branch.then : branch.else;
88
+ } else {
89
+ target = edge.target;
90
+ payloadFn = cell;
91
+ }
92
+ const data = payloadFn(st, msg);
93
+ const next = parking.has(target) ? { ...data, type: target, was: st.type } : { ...data, type: target };
94
+ const emitted = cmdNames(fired ? edge.cmd : edge.otherwiseCmd).map(
95
+ (n) => {
96
+ const build = p.cmds[n];
97
+ if (build === void 0) {
98
+ throw new Error(
99
+ `@demlik/tea: edge "${at}" names cmd "${n}" with no builder`
100
+ );
101
+ }
102
+ return { ...build(st, msg, at), type: n };
103
+ }
104
+ );
105
+ return [next, emitted];
106
+ };
107
+ }
108
+ function keyOf(c, e, ns) {
109
+ return ns === void 0 || c.events[e]?.foreign === true ? e : `${ns}.${e}`;
110
+ }
111
+ var NO_PARKING = /* @__PURE__ */ new Set();
112
+ function compile(chart, parts, ns) {
113
+ const c = chart;
114
+ const p = rtParts(parts);
115
+ const flat = flatten(c);
116
+ const events = Object.keys(c.events);
117
+ const parking = /* @__PURE__ */ new Set();
118
+ for (const [s, { node }] of flat) {
119
+ for (const spec of Object.values(node.on ?? {})) {
120
+ if (typeof spec === "object" && spec.resume !== void 0) parking.add(s);
121
+ }
122
+ }
123
+ const table = {};
124
+ for (const [s, { node, group }] of flat) {
125
+ const row = {};
126
+ const on = node.on ?? {};
127
+ for (const e of events) {
128
+ const key = keyOf(c, e, ns);
129
+ const spec = on[e];
130
+ if (spec === void 0) {
131
+ const scope = scopeList(c.events[e]?.scope ?? "edges");
132
+ const live = scope.includes("all") || scope.includes(group);
133
+ const refused = node.end === true || !live || (node.ignore ?? []).includes(e);
134
+ row[key] = refused ? (st) => [st, []] : () => {
135
+ throw new NoCellError(key, s);
136
+ };
137
+ continue;
138
+ }
139
+ row[key] = buildCell(spec, e, `${s}.${e}`, p, parking);
140
+ }
141
+ table[s] = row;
142
+ }
143
+ return table;
144
+ }
145
+ function compileReducer(chart, parts, ns) {
146
+ const c = chart;
147
+ const p = rtParts(parts);
148
+ const out = {};
149
+ for (const e of Object.keys(c.events)) {
150
+ const spec = c.on[e];
151
+ if (spec === void 0) {
152
+ throw new Error(`@demlik/tea: reducer chart declares no edge for "${e}"`);
153
+ }
154
+ out[keyOf(c, e, ns)] = buildCell(spec, e, e, p, NO_PARKING);
155
+ }
156
+ return out;
157
+ }
158
+ function reducerInitFrom(chart, boot) {
159
+ const type = chart.initial;
160
+ return (loaded) => [
161
+ loaded ?? { ...boot(), type },
162
+ Cmd.none
163
+ ];
164
+ }
165
+ function reducerMermaid(chart) {
166
+ const c = chart;
167
+ const lines = ["stateDiagram-v2", " direction TB", ` [*] --> ${c.initial}`];
168
+ for (const [e, spec] of Object.entries(c.on)) {
169
+ const edge = typeof spec === "string" ? { target: spec } : spec;
170
+ if (edge.cell !== void 0) {
171
+ for (const t of edge.to ?? []) {
172
+ lines.push(` any --> ${t} : ${e} / ${edge.cell}()`);
173
+ }
174
+ } else {
175
+ if (edge.target !== void 0)
176
+ lines.push(` any --> ${edge.target} : ${e}`);
177
+ if (edge.otherwise !== void 0) {
178
+ lines.push(` any --> ${edge.otherwise} : ${e} [!${edge.when ?? ""}]`);
179
+ }
180
+ }
181
+ }
182
+ return lines.join("\n");
183
+ }
184
+ function initialStateOf(chart) {
185
+ const flat = flatten(chart);
186
+ const marked = [...flat].filter(([, f]) => f.node.initial === true);
187
+ const only = marked[0];
188
+ if (marked.length !== 1 || only === void 0) {
189
+ throw new Error(
190
+ `@demlik/tea: chart must mark exactly one state \`initial: true\` (found ${marked.length})`
191
+ );
192
+ }
193
+ return only[0];
194
+ }
195
+ function initFrom(chart, boot) {
196
+ const type = initialStateOf(chart);
197
+ return (loaded) => [
198
+ // The one cast this helper needs: `{ ...InitialData, type: <the initial
199
+ // name> }` IS `Extract<S, { type: InitialState<C> }>`, but tsc cannot
200
+ // rebuild a union member from a spread plus a `string`-typed discriminant.
201
+ loaded ?? { ...boot(), type },
202
+ Cmd.none
203
+ ];
204
+ }
205
+ function chartMermaid(chart) {
206
+ const c = chart;
207
+ const lines = ["stateDiagram-v2", " direction TB"];
208
+ for (const [s, { node }] of flatten(c)) {
209
+ if (node.initial === true) lines.push(` [*] --> ${s}`);
210
+ for (const [e, spec] of Object.entries(node.on ?? {})) {
211
+ const edge = typeof spec === "string" ? { target: spec } : spec;
212
+ if (edge.cell !== void 0) {
213
+ for (const t of edge.to ?? []) {
214
+ lines.push(` ${s} --> ${t} : ${e} / ${edge.cell}()`);
215
+ }
216
+ } else if (edge.resume !== void 0) {
217
+ lines.push(` ${s} --> ${edge.resume.fallback} : ${e} (resume)`);
218
+ } else {
219
+ if (edge.target !== void 0)
220
+ lines.push(` ${s} --> ${edge.target} : ${e}`);
221
+ if (edge.otherwise !== void 0) {
222
+ lines.push(
223
+ ` ${s} --> ${edge.otherwise} : ${e} [!${edge.when ?? ""}]`
224
+ );
225
+ }
226
+ }
227
+ }
228
+ if (node.end === true) lines.push(` ${s} --> [*]`);
229
+ }
230
+ return lines.join("\n");
231
+ }
232
+
233
+ // src/chart/graph.ts
234
+ var ty = () => ({});
235
+ function defineChart(c) {
236
+ return c;
237
+ }
238
+ function defineReducerChart(c) {
239
+ return c;
240
+ }
241
+
242
+ export { CellTargetError, chartMermaid, compile, compileReducer, defineChart, defineReducerChart, initFrom, initialStateOf, reducerInitFrom, reducerMermaid, ty };
243
+ //# sourceMappingURL=index.js.map
244
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/chart/compile.ts","../../src/chart/graph.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// ═══════════════════════════════════════════════════════════════════════════\n// RUNTIME — the chart walk that emits a real `Transitions<S, M, C>`.\n// ═══════════════════════════════════════════════════════════════════════════\nimport { Cmd, NoCellError, type Reducer, type Transitions } from \"../pure/core\";\nimport type {\n Assigns,\n CellName,\n Cells,\n Chart,\n CmdOf,\n Cmds,\n GuardName,\n Guards,\n InitialData,\n InitialState,\n MsgIn,\n MsgOf,\n RAssigns,\n RCellName,\n RCells,\n RCmds,\n ReducerChart,\n RGuardName,\n RGuards,\n RStateOf,\n RUsedCmdName,\n StateOf,\n UsedCmdName,\n} from \"./graph\";\n\n/**\n * A cell returned a state OUTSIDE its edge's declared `to`.\n *\n * The escape hatch's bargain is that code may pick the target but only from the\n * set the chart admits — otherwise the drawing stops being a truthful picture\n * of the machine. For a SINGLE-site cell, and for the per-site form of a\n * multi-site one, the clamp is a compile error and this never fires. For the\n * function form of a MULTI-SITE cell it is the only enforcement there is: the\n * return of one rest signature over a union of tuples cannot be made to depend\n * on `at`, so the union of every site's `to` is the tightest static clamp\n * available and this closes the difference at the moment it is violated.\n *\n * It sits inside `buildCell`, so BOTH chart forms — the grid and the reducer —\n * get the same net from the same three lines.\n */\nexport class CellTargetError extends Error {\n override readonly name = \"CellTargetError\";\n readonly _tag = \"CellTargetError\" as const;\n constructor(\n public readonly at: string,\n public readonly cell: string,\n public readonly returned: string,\n public readonly declared: readonly string[],\n ) {\n super(\n `@demlik/tea: cell \"${cell}\" at edge \"${at}\" returned state ` +\n `\"${returned}\", which is not among that edge's declared targets ` +\n `[${declared.map((t) => `\"${t}\"`).join(\", \")}] — either the cell is ` +\n `wrong, or the edge's \\`to\\` is missing a target the code can reach ` +\n `(in which case add it, so the chart still draws the whole fan-out).`,\n );\n }\n}\n\n/** `undefined` → none; `\"x\"` → one; `[\"x\",\"y\"]` → both, in order. */\nfunction cmdNames(\n ref: string | readonly string[] | undefined,\n): readonly string[] {\n if (ref === undefined) return [];\n return typeof ref === \"string\" ? [ref] : ref;\n}\n\n// There is no `unhandled` policy any more. A pair is DECLARED (an edge), or\n// REFUSED — by the event's `scope`, or by this state's `ignore`, or by\n// `end: true` — and `Total<C>` refuses to compile on any third case. The\n// refusal is a self-loop with no cmds; the throw below is the safety net under\n// the compile-time refusal (`.decisions/0011`), reached only when the mapped\n// types were bypassed with a cast.\nexport type Parts<C, S extends { type: string }, M extends { type: string }> = {\n readonly assign: Assigns<C, S, M>;\n} & ([GuardName<C>] extends [never]\n ? { readonly guards?: undefined }\n : { readonly guards: Guards<C, S, M> }) &\n ([UsedCmdName<C>] extends [never]\n ? { readonly cmds?: undefined }\n : { readonly cmds: Cmds<C, S, M> }) &\n // the escape hatch's bag — demanded exactly when an edge names a cell.\n ([CellName<C>] extends [never]\n ? { readonly cells?: undefined }\n : { readonly cells: Cells<C, S, M> });\n\n// ── runtime views of the chart (the shapes the walk actually reads) ────────\ntype RtEdge =\n | string\n | {\n readonly target?: string;\n readonly when?: string;\n readonly otherwise?: string;\n readonly cmd?: string | readonly string[];\n readonly otherwiseCmd?: string | readonly string[];\n readonly resume?: { readonly fallback: string };\n readonly to?: readonly string[];\n readonly cell?: string;\n };\ntype RtNode = {\n readonly initial?: true;\n readonly on?: Record<string, RtEdge>;\n readonly ignore?: readonly string[];\n readonly end?: true;\n};\ntype RtChart = {\n readonly events: Record<\n string,\n { readonly scope: string | readonly string[]; readonly foreign?: true }\n >;\n readonly states: Record<string, Record<string, RtNode>>;\n};\ntype RtState = { readonly type: string; readonly was?: string };\ntype RtMsg = { readonly type: string };\ntype RtCell = (s: RtState, m: RtMsg) => readonly [RtState, readonly Cmd[]];\ntype RtCellFn = (\n s: RtState,\n m: RtMsg,\n at: string,\n) => readonly [RtState, readonly Cmd[]];\n/** Either form: one body for every site, or one body PER site keyed by `at`. */\ntype RtCellImpl = RtCellFn | Record<string, RtCellFn | undefined>;\ntype RtFn = (s: RtState, m: RtMsg) => object;\ntype RtAssign = RtFn | { readonly then: RtFn; readonly else: RtFn };\n\n/** State name → its node and its phase, flattened out of the grouped shape. */\ntype Flat = { readonly node: RtNode; readonly group: string };\n\nfunction flatten(c: RtChart): Map<string, Flat> {\n const out = new Map<string, Flat>();\n for (const group of Object.keys(c.states)) {\n const members = c.states[group] ?? {};\n for (const s of Object.keys(members)) {\n const node = members[s];\n if (node !== undefined) out.set(s, { node, group });\n }\n }\n return out;\n}\n\nfunction scopeList(scope: string | readonly string[]): readonly string[] {\n return typeof scope === \"string\" ? [scope] : scope;\n}\n\n/** The code parts, after the type layer has been erased. Shared by both forms. */\ntype RtParts = {\n readonly assign: Record<string, RtAssign | undefined>;\n readonly guards: Record<\n string,\n ((s: RtState, m: RtMsg, at: string) => boolean) | undefined\n >;\n readonly cmds: Record<\n string,\n ((s: RtState, m: RtMsg, at: string) => object) | undefined\n >;\n readonly cells: Record<string, RtCellImpl | undefined>;\n};\n\nfunction rtParts(parts: object): RtParts {\n const p = parts as Record<string, object | undefined>;\n return {\n assign: (p.assign ?? {}) as RtParts[\"assign\"],\n guards: (p.guards ?? {}) as RtParts[\"guards\"],\n cmds: (p.cmds ?? {}) as RtParts[\"cmds\"],\n cells: (p.cells ?? {}) as RtParts[\"cells\"],\n };\n}\n\n/**\n * ONE edge → one transition cell. This is the whole walk, and it is shared\n * verbatim by both chart forms: a `Transitions` cell and a `Reducer` cell\n * differ only in what `at` is (`\"state.event\"` vs `\"event\"`) and in whether a\n * parking set exists to inject `was` from — both parameters here, not branches.\n *\n * `bare` is the un-namespaced event name the author's parts are written\n * against; the compiled cell restores it before calling them.\n */\nfunction buildCell(\n spec: RtEdge,\n bare: string,\n at: string,\n p: RtParts,\n parking: ReadonlySet<string>,\n): RtCell {\n const edge = typeof spec === \"string\" ? { target: spec } : spec;\n const cell = p.assign[at];\n\n // ── THE ESCAPE HATCH ────────────────────────────────────────────────────\n // A `{ to, cell }` edge is the whole transition: the cell picks the target\n // from `to` and returns its own cmds, so there is no assign to call, no\n // guard to evaluate, no cmd list to rebuild and no `was` to inject (a cell\n // landing on a parking state supplies `was` itself — its return type demands\n // it). The other fields are compile errors beside `cell`, so this branch is\n // not silently skipping anything.\n if (edge.cell !== undefined) {\n const name = edge.cell;\n const impl = p.cells[name];\n if (impl === undefined) {\n throw new Error(\n `@demlik/tea: edge \"${at}\" names cell \"${name}\" with no implementation`,\n );\n }\n // the two forms: one body for every site, or one body per site. A\n // multi-site cell may be written either way (`Cells`/`RCells` offer both);\n // a single-site one is always the plain function.\n const hand = typeof impl === \"function\" ? impl : impl[at];\n if (hand === undefined) {\n throw new Error(\n `@demlik/tea: cell \"${name}\" is written in the per-site form but has no entry for edge \"${at}\"`,\n );\n }\n const to = edge.to ?? [];\n return (st, nsMsg) => {\n const out = hand(st, { ...nsMsg, type: bare }, at);\n // the runtime half of the `to` clamp — see `CellTargetError`.\n if (!to.includes(out[0].type)) {\n throw new CellTargetError(at, name, out[0].type, to);\n }\n return out;\n };\n }\n\n return (st, nsMsg) => {\n // strip the namespace so the author's parts see the bare event.\n const msg: RtMsg = { ...nsMsg, type: bare };\n\n let target: string;\n let payloadFn: RtFn;\n let fired = true;\n\n if (edge.resume !== undefined) {\n target = st.was ?? edge.resume.fallback;\n payloadFn = cell as RtFn;\n } else if (edge.when !== undefined) {\n const guard = p.guards[edge.when];\n fired = guard !== undefined && guard(st, msg, at) === true;\n const branch = cell as { then: RtFn; else: RtFn };\n target = fired ? (edge.target as string) : (edge.otherwise as string);\n payloadFn = fired ? branch.then : branch.else;\n } else {\n target = edge.target as string;\n payloadFn = cell as RtFn;\n }\n\n const data = payloadFn(st, msg);\n // `was` is INJECTED, never authored: entering a parking state records where\n // you came from. The type of `was` is `ResumeTargets<C, target>`, and\n // `st.type` is in that set by construction.\n const next: RtState = parking.has(target)\n ? { ...data, type: target, was: st.type }\n : { ...data, type: target };\n\n // 0..n Cmds, in declaration order. A guarded edge picks its arm's list —\n // `Cmd.when` lifted onto the edge, so which effects fire is visible in the\n // chart rather than buried in a cell body.\n const emitted = cmdNames(fired ? edge.cmd : edge.otherwiseCmd).map(\n (n): Cmd => {\n const build = p.cmds[n];\n if (build === undefined) {\n throw new Error(\n `@demlik/tea: edge \"${at}\" names cmd \"${n}\" with no builder`,\n );\n }\n return { ...build(st, msg, at), type: n };\n },\n );\n\n return [next, emitted];\n };\n}\n\n/** `undefined` → bare; a foreign event → bare; otherwise `${ns}.${event}`. */\nfunction keyOf(\n c: {\n readonly events: Record<string, { readonly foreign?: true } | undefined>;\n },\n e: string,\n ns: string | undefined,\n): string {\n return ns === undefined || c.events[e]?.foreign === true ? e : `${ns}.${e}`;\n}\n\nconst NO_PARKING: ReadonlySet<string> = new Set<string>();\n\n/**\n * Compile a chart + the code parts into a genuine `Transitions<S, M, C>`.\n *\n * `ns` is OPTIONAL and PER-EVENT. Omitted, nothing is decorated and the table\n * is keyed by the bare event names — a single-instance machine carries no\n * namespace and passes no dummy string. Given, the author's own events are\n * keyed `${ns}.${event}` (so N instances share one dispatch surface with\n * genuinely disjoint literal unions), while every event the chart marks\n * `foreign: true` keeps its BARE name: a library-minted Msg like\n * `deadline_exceeded` is the same event for every instance, and its name was\n * never the author's to rename.\n *\n * The returned type is `Transitions<S, MsgIn<C, NS>, K>` — literal keys, never\n * `string`. The parts are authored against the BARE msg union; the compiled\n * cell restores the bare event name before calling them.\n *\n * `S`/`M`/`K` DEFAULT to the chart's own derivations, so the common call is\n * `compile(chart, parts)` with no type arguments at all.\n */\nexport function compile<\n const C extends Chart<C>,\n S extends { type: string } = StateOf<C>,\n M extends { type: string } = MsgOf<C>,\n K extends Cmd = CmdOf<C>,\n const NS extends string | undefined = undefined,\n>(chart: C, parts: Parts<C, S, M>, ns?: NS): Transitions<S, MsgIn<C, NS>, K> {\n const c = chart as unknown as RtChart;\n const p = rtParts(parts);\n\n const flat = flatten(c);\n const events = Object.keys(c.events);\n const parking = new Set<string>();\n for (const [s, { node }] of flat) {\n for (const spec of Object.values(node.on ?? {})) {\n if (typeof spec === \"object\" && spec.resume !== undefined) parking.add(s);\n }\n }\n\n const table: Record<string, Record<string, RtCell>> = {};\n\n for (const [s, { node, group }] of flat) {\n const row: Record<string, RtCell> = {};\n const on = node.on ?? {};\n\n for (const e of events) {\n // the one runtime consequence of per-event namespacing.\n const key = keyOf(c, e, ns);\n const spec = on[e];\n\n if (spec === undefined) {\n // the mirror of `MissingAt<C, S>`: live-but-undecided is the only case\n // the type layer forbids, so it is the only case that throws.\n const scope = scopeList(c.events[e]?.scope ?? \"edges\");\n const live = scope.includes(\"all\") || scope.includes(group);\n const refused =\n node.end === true || !live || (node.ignore ?? []).includes(e);\n row[key] = refused\n ? (st) => [st, []]\n : () => {\n throw new NoCellError(key, s);\n };\n continue;\n }\n\n // the site tag, passed to guards/cmds/cells as their last argument — it is\n // what lets a multi-site helper discriminate (see `SiteArgs` in graph.ts).\n row[key] = buildCell(spec, e, `${s}.${e}`, p, parking);\n }\n table[s] = row;\n }\n\n // ── THE ONE CAST ────────────────────────────────────────────────────────\n // Inside the library, at the construction boundary. `Transitions` is a\n // mapped type over `S[\"type\"] × M[\"type\"]`; the walk builds the same keys\n // from the flattened chart × the per-event keys, but tsc cannot see that a\n // string-keyed record built in a loop is total over those unions.\n return table as unknown as Transitions<S, MsgIn<C, NS>, K>;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// REDUCER FORM — the same walk, one loop shallower.\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * The reducer form's parts bag. Structurally identical to `Parts`, over the\n * reducer chart's derivations — `assign` is total over the DECLARATIVE events\n * (a cell event owes none), and each of `guards`/`cmds`/`cells` is demanded\n * exactly when the chart names one.\n */\nexport type RParts<\n C,\n S extends { type: string },\n M extends { type: string },\n> = {\n readonly assign: RAssigns<C, S, M>;\n} & ([RGuardName<C>] extends [never]\n ? { readonly guards?: undefined }\n : { readonly guards: RGuards<C, S, M> }) &\n ([RUsedCmdName<C>] extends [never]\n ? { readonly cmds?: undefined }\n : { readonly cmds: RCmds<C, S, M> }) &\n ([RCellName<C>] extends [never]\n ? { readonly cells?: undefined }\n : { readonly cells: RCells<C, S, M> });\n\ntype RtReducerChart = {\n readonly events: Record<string, { readonly foreign?: true }>;\n readonly initial: string;\n readonly on: Record<string, RtEdge>;\n};\n\n/**\n * Compile a reducer-form chart into a genuine `Reducer<S, M, K>` — the flat,\n * msg-keyed `update` shape `defineMachine` already accepts (`src/pure/core.ts`).\n *\n * There is no `NoCellError` branch and no refusal branch here, and that is not\n * an omission: `on` is a TOTAL mapped type over the event alphabet, so an\n * undeclared event cannot exist to be missing. The safety the grid form buys\n * with `scope` + `ignore` + `Total<C>`, this form gets from the mapped type.\n *\n * `ns` behaves exactly as in `compile`: per-event, optional, and never applied\n * to an event the chart marks `foreign`.\n */\nexport function compileReducer<\n const C extends ReducerChart<C>,\n S extends { type: string } = RStateOf<C>,\n M extends { type: string } = MsgOf<C>,\n K extends Cmd = CmdOf<C>,\n const NS extends string | undefined = undefined,\n>(chart: C, parts: RParts<C, S, M>, ns?: NS): Reducer<S, MsgIn<C, NS>, K> {\n const c = chart as unknown as RtReducerChart;\n const p = rtParts(parts);\n const out: Record<string, RtCell> = {};\n\n for (const e of Object.keys(c.events)) {\n const spec = c.on[e];\n if (spec === undefined) {\n // unreachable through the typed door — `on` is total over `events`. The\n // safety net under the compile-time obligation, as `NoCellError` is\n // under `Total<C>`.\n throw new Error(`@demlik/tea: reducer chart declares no edge for \"${e}\"`);\n }\n // the site tag IS the event: one dimension, so `SiteArgs`'s `at` is the\n // bare name and a multi-site cell discriminates on it exactly as before.\n out[keyOf(c, e, ns)] = buildCell(spec, e, e, p, NO_PARKING);\n }\n\n // The same one cast, for the same reason: a string-keyed record built in a\n // loop is total over `M[\"type\"]`, and tsc cannot see it.\n return out as unknown as Reducer<S, MsgIn<C, NS>, K>;\n}\n\n/**\n * `init` for a reducer chart. The entry state is the chart's `initial` field —\n * one word, still never repeated by the author — and `boot()` supplies `ctx`,\n * which for this form IS the whole state minus its tag.\n */\nexport function reducerInitFrom<\n const C extends ReducerChart<C>,\n S extends { type: string } = RStateOf<C>,\n K extends Cmd = CmdOf<C>,\n>(\n chart: C,\n boot: () => Omit<RStateOf<C>, \"type\">,\n): (loaded: S | null) => readonly [S, readonly K[]] {\n const type: string = (chart as unknown as RtReducerChart).initial;\n return (loaded) => [\n loaded ?? ({ ...boot(), type } as unknown as S),\n Cmd.none,\n ];\n}\n\n/**\n * The reducer chart, drawn. There is no per-state routing to show, so the\n * honest picture is one `any` node — every edge is reachable from every state,\n * which is what having no phase dimension MEANS — plus each event's full\n * fan-out, cell edges included.\n */\nexport function reducerMermaid<const C extends ReducerChart<C>>(\n chart: C,\n): string {\n const c = chart as unknown as RtReducerChart;\n const lines = [\"stateDiagram-v2\", \" direction TB\", ` [*] --> ${c.initial}`];\n for (const [e, spec] of Object.entries(c.on)) {\n const edge = typeof spec === \"string\" ? { target: spec } : spec;\n if (edge.cell !== undefined) {\n for (const t of edge.to ?? []) {\n lines.push(` any --> ${t} : ${e} / ${edge.cell}()`);\n }\n } else {\n if (edge.target !== undefined)\n lines.push(` any --> ${edge.target} : ${e}`);\n if (edge.otherwise !== undefined) {\n lines.push(` any --> ${edge.otherwise} : ${e} [!${edge.when ?? \"\"}]`);\n }\n }\n }\n return lines.join(\"\\n\");\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// `init`, DERIVED FROM THE CHART\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * The name of the state marked `initial: true`. Throws unless EXACTLY one is\n * marked — the runtime half of what `InitialData`'s marker types say at the\n * type level.\n */\nexport function initialStateOf<const C extends Chart<C>>(\n chart: C,\n): InitialState<C> {\n const flat = flatten(chart as unknown as RtChart);\n const marked = [...flat].filter(([, f]) => f.node.initial === true);\n const only = marked[0];\n if (marked.length !== 1 || only === undefined) {\n throw new Error(\n `@demlik/tea: chart must mark exactly one state \\`initial: true\\` (found ${marked.length})`,\n );\n }\n // `Object.keys` yields `string`; the type-level answer is the same key.\n return only[0] as InitialState<C>;\n}\n\n/**\n * Build a `Machine[\"init\"]` from the chart's declared entry state plus a\n * `boot()` that supplies ONLY that state's data. The state NAME is never\n * repeated by the author — it comes from the same `initial: true` that\n * `machine-viz` reads to draw the `[*] -->` edge.\n *\n * Rehydrate is honoured verbatim: a non-null `loaded` is returned untouched\n * with NO cmds, which is exactly Invariant 2's contract.\n */\nexport function initFrom<\n const C extends Chart<C>,\n S extends { type: string },\n K extends Cmd,\n>(\n chart: C,\n boot: () => InitialData<C, S>,\n): (loaded: S | null) => readonly [S, readonly K[]] {\n const type: string = initialStateOf(chart);\n return (loaded) => [\n // The one cast this helper needs: `{ ...InitialData, type: <the initial\n // name> }` IS `Extract<S, { type: InitialState<C> }>`, but tsc cannot\n // rebuild a union member from a spread plus a `string`-typed discriminant.\n loaded ?? ({ ...boot(), type } as unknown as S),\n Cmd.none,\n ];\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// DRAWING THE CHART — every declared edge, including a cell edge's fan-out.\n//\n// `machine-viz`'s `toMermaid` works on a COMPILED machine and resolves a cell\n// by executing it against a sample, so it draws the ONE edge that sample takes\n// — true of a guarded edge before the escape hatch existed, and equally true\n// of a `{ to, cell }` edge now. The chart, though, still knows every possible\n// target, which is the whole point of declaring `to`. This reads the chart\n// directly and draws the full fan-out, no samples and no execution needed.\n// ═══════════════════════════════════════════════════════════════════════════\nexport function chartMermaid<const C extends Chart<C>>(chart: C): string {\n const c = chart as unknown as RtChart;\n const lines = [\"stateDiagram-v2\", \" direction TB\"];\n for (const [s, { node }] of flatten(c)) {\n if (node.initial === true) lines.push(` [*] --> ${s}`);\n for (const [e, spec] of Object.entries(node.on ?? {})) {\n const edge = typeof spec === \"string\" ? { target: spec } : spec;\n if (edge.cell !== undefined) {\n // one real edge per DECLARED target — the fan-out, labelled with the\n // cell that picks among them.\n for (const t of edge.to ?? []) {\n lines.push(` ${s} --> ${t} : ${e} / ${edge.cell}()`);\n }\n } else if (edge.resume !== undefined) {\n lines.push(` ${s} --> ${edge.resume.fallback} : ${e} (resume)`);\n } else {\n if (edge.target !== undefined)\n lines.push(` ${s} --> ${edge.target} : ${e}`);\n if (edge.otherwise !== undefined) {\n lines.push(\n ` ${s} --> ${edge.otherwise} : ${e} [!${edge.when ?? \"\"}]`,\n );\n }\n }\n }\n if (node.end === true) lines.push(` ${s} --> [*]`);\n }\n return lines.join(\"\\n\");\n}\n","// ═══════════════════════════════════════════════════════════════════════════\n// TYPE MACHINERY — everything in this file is erased at runtime.\n//\n// ONE CHART, ONE SITE PER FACT.\n//\n// The chart is a single value with four sections. Each fact is DECLARED in\n// exactly one of them and everything else is derived:\n//\n// ctx — the data every state carries. (1 site)\n// events — the event alphabet: name, payload, and SCOPE. (1 site)\n// cmds — the effect alphabet: name and payload. (1 site)\n// states — states grouped into named PHASES, each with its edges. (1 site)\n//\n// The Msg union, the State union, the Cmd union, the guard signatures, the cmd\n// builder signatures, the `was` field on parking states, the entry state and\n// the totality obligation are all DERIVED from that one value. Nothing in the\n// author's file names a state, an event or a cmd twice as a *declaration*; the\n// only repeats are *references* (an edge naming its target, an `assign` key\n// naming the edge it implements), which are the facts themselves.\n// ═══════════════════════════════════════════════════════════════════════════\nimport type { Cmd } from \"../pure/core\";\n\n// ── 0. the phantom-type carrier ────────────────────────────────────────────\n/**\n * A type smuggled through a value position. `ty<{ at: number }>()` is an empty\n * object at runtime whose TYPE remembers `{ at: number }` — which is what lets\n * an event declare its payload IN the chart instead of in a parallel type map\n * the author has to keep in step.\n */\nexport interface Ty<T> {\n readonly __ty: T;\n}\nexport const ty = <T>(): Ty<T> => ({}) as unknown as Ty<T>;\n\n/** `Ty<T>` → `T`; anything else (an absent `data`) → the neutral `unknown`. */\ntype Payload<X> = X extends Ty<infer T> ? T : unknown;\n\n// ── 1. section accessors ───────────────────────────────────────────────────\ntype EvMap<C> = C extends { readonly events: infer E } ? E : never;\ntype CmdMap<C> = C extends { readonly cmds: infer M }\n ? M\n : Record<never, never>;\ntype Groups<C> = C extends { readonly states: infer G } ? G : never;\ntype CtxOf<C> = C extends { readonly ctx: infer T } ? Payload<T> : unknown;\n\nexport type EventName<C> = Extract<keyof EvMap<C>, string>;\nexport type CmdName<C> = Extract<keyof CmdMap<C>, string>;\n/** The named phases — `keyof states`. A group name is declared by BEING a key. */\nexport type GroupName<C> = Extract<keyof Groups<C>, string>;\n\nexport type StateName<C> = Extract<\n { [G in keyof Groups<C>]: keyof Groups<C>[G] }[keyof Groups<C>],\n string\n>;\n\n/** The node for state `S`, found by scanning the groups. Groups partition. */\ntype NodeAt<C, S> = {\n [G in keyof Groups<C>]: S extends keyof Groups<C>[G]\n ? Groups<C>[G][S]\n : never;\n}[keyof Groups<C>];\n\n/** The phase `S` lives in. A union here means `S` was declared twice. */\nexport type GroupOf<C, S> = Extract<\n {\n [G in keyof Groups<C>]: S extends keyof Groups<C>[G] ? G : never;\n }[keyof Groups<C>],\n string\n>;\n\n// naked-parameter helpers: a conditional distributes only over a bare `X`.\ntype OnOf<X> = X extends { readonly on: infer O } ? O : Record<never, never>;\ntype IgnoreOf<X> = X extends { readonly ignore: readonly (infer I)[] }\n ? Extract<I, string>\n : never;\ntype DataOf<X> = X extends { readonly data: infer D } ? Payload<D> : unknown;\ntype IsEndOf<X> = X extends { readonly end: true } ? true : false;\ntype IsInitialOf<X> = X extends { readonly initial: true } ? true : false;\ntype IsForeignOf<X> = X extends { readonly foreign: true } ? true : false;\ntype ScopeOf<X> = X extends { readonly scope: infer S }\n ? S extends readonly string[]\n ? S[number]\n : S\n : never;\n\ntype On<C, S> = OnOf<NodeAt<C, S>>;\ntype IgnoredAt<C, S> = IgnoreOf<NodeAt<C, S>>;\n\n// ── 2. the edge shape ──────────────────────────────────────────────────────\n/** A cmd reference on an edge: one declared name, or an ORDERED list of them. */\nexport type CmdRef<N extends string> = N | readonly N[];\n\nexport type EdgeSpec<SN extends string, CN extends string> =\n | SN\n // ── THE ESCAPE HATCH ────────────────────────────────────────────────────\n // The author declares the SET of reachable targets; a hand-written cell\n // picks one at runtime and returns `[state, cmds]` itself. Everything the\n // chart is for is still declared here — `to` is the fan-out `machine-viz`\n // draws and the union the cell's return type is clamped to — and the one\n // thing the chart genuinely cannot know (WHICH of them, this time) is the\n // only thing left in code.\n | { readonly to: readonly SN[]; readonly cell: string }\n | { readonly target: SN; readonly cmd?: CmdRef<CN> }\n | {\n readonly target: SN;\n readonly when: string;\n readonly otherwise: SN;\n /** Fires only when the guard HOLDS. */\n readonly cmd?: CmdRef<CN>;\n /** Fires only when the guard FAILS — `Cmd.when` lifted onto the edge. */\n readonly otherwiseCmd?: CmdRef<CN>;\n }\n | { readonly resume: { readonly fallback: SN }; readonly cmd?: CmdRef<CN> };\n\n// ── 3. SCOPE — the answer to the |S| × |M| enumeration problem ─────────────\n//\n// The old design made every state list the events it deliberately drops. That\n// is correct and it scales as |S| × |M|: 30 states × 12 events is ~300 hand-\n// typed strings, which the author produces by pasting the tsc error back.\n//\n// The fact being written 300 times is really |M| facts, one per event: WHERE\n// DOES THIS EVENT MEAN ANYTHING? So it is declared once, on the event, as its\n// `scope` — a dial with three settings:\n//\n// \"edges\" — targeted. Live exactly where it is routed; everywhere else it\n// is not \"ignored\", it is simply not addressed to that state.\n// Obligation: none. Cost: one word.\n// <phase> — broadcast within a phase (or a list of phases). Every state in\n// that phase must handle it or `ignore` it BY NAME. Adding a\n// state to the phase turns that state red, naming the pair.\n// \"all\" — broadcast machine-wide. Every state must decide. This is the\n// old behaviour, still available, now opt-in per event.\n//\n// Totality is unchanged in form: a pair that is neither handled nor covered by\n// a decision fails to compile, naming the pair. What changed is that the\n// decision may be QUANTIFIED (one word, on the event) instead of ENUMERATED\n// (one string per cell). See `.decisions` note in the report: forcing a\n// per-pair reconsideration on every new event *requires* |S| × |M| author-owned\n// sites — that is the one thing the two goals genuinely trade against.\n\n/** The `scope` field AS DECLARED — before the list is flattened to its members. */\ntype ScopeDeclOf<X> = X extends { readonly scope: infer S } ? S : never;\ntype ScopeElems<S> = S extends readonly (infer T)[] ? T : S;\n\n/**\n * Is this event's `scope` something the AUTHOR wrote, or is it tsc's fallback?\n *\n * When some OTHER error in the chart literal (a typo'd target, say) defeats\n * inference of `C`, tsc falls back to the `Chart<C>` constraint, where `scope`\n * is the whole `\"edges\" | \"all\" | GroupName<C> | readonly (…)[]` universe. Left\n * alone that makes every event look live in every phase and buries the one real\n * diagnostic under a wall of spurious unhandled-pair demands.\n *\n * The fallback is recognised BY ITS SHAPE, not by what it happens to cover: it\n * is the one form that is a union MIXING a string with a list, which no literal\n * can produce. An author's scope is either a word (`\"all\"`) or a list\n * (`[\"edges\", \"p\"]`) — never both at once.\n *\n * The older test — \"a scope that spans the entire universe is no scope\" — was a\n * proxy for this, and it misfired on the genuinely authored `[\"edges\",\"all\",\"p\"]`:\n * the type layer read it as NO scope (so `MissingPairs<C>` was `never` and the\n * chart looked total) while `compile`'s `scopeList(…).includes(\"all\")` read it as\n * live everywhere and threw `NoCellError` on the first msg. Testing the shape\n * instead makes the two layers agree by construction.\n *\n * A `string`-typed (non-literal) scope is also not authorable as a decision, so\n * it keeps the old reading of \"no scope\".\n */\ntype IsAuthoredScope<X, S = ScopeDeclOf<X>> = [S] extends [string]\n ? [string] extends [S]\n ? false\n : true\n : [S] extends [readonly string[]]\n ? [string] extends [ScopeElems<S>]\n ? false\n : true\n : false;\n\n/** The event's declared scope, once it is established that it IS a declaration. */\ntype ScopeAt<C, E extends keyof EvMap<C>> = [\n IsAuthoredScope<EvMap<C>[E]>,\n] extends [true]\n ? ScopeOf<EvMap<C>[E]>\n : never;\n\n/** The events that are LIVE at `S` — i.e. that `S` owes a decision about. */\ntype LiveAt<C, S> = {\n [E in EventName<C>]: \"all\" extends ScopeAt<C, E>\n ? E\n : [GroupOf<C, S>] extends [ScopeAt<C, E>]\n ? E\n : never;\n}[EventName<C>];\n\n/** Pairs at `S` that are live, unhandled and unrefused. Empty = total. */\nexport type MissingAt<C, S> = [IsEndOf<NodeAt<C, S>>] extends [true]\n ? never\n : Exclude<LiveAt<C, S>, Extract<keyof On<C, S>, string> | IgnoredAt<C, S>>;\n\n/** Every unhandled pair in the whole chart — `never` when the chart is total. */\nexport type MissingPairs<C> = {\n [S in StateName<C>]: `${S}.${Extract<MissingAt<C, S>, string>}`;\n}[StateName<C>];\n\n// ── 4. the chart shape (F-bounded: every reference checked against itself) ──\nexport type Chart<C> = {\n /** Data EVERY state carries. Declared once; intersected into all of them. */\n readonly ctx?: Ty<object>;\n readonly events: {\n readonly [E in keyof EvMap<C>]: {\n readonly data?: Ty<object>;\n /**\n * \"This name is not mine.\" The Msg is minted by SOMEONE ELSE — a library\n * Sub (`@demlik/tea/deadline` dispatching `deadline_exceeded`), a host\n * bridge, another machine — so the author cannot rename it and the\n * compiler must not decorate it. A foreign event keeps its BARE name in\n * the emitted table under every namespace, which is what makes it the\n * same event across all N instances. Everything else — payload, `scope`,\n * totality, edges — is unchanged: it is a normal event that happens to\n * belong to someone else.\n */\n readonly foreign?: true;\n // written out rather than aliased: tsc prints the alias NAME in the\n // diagnostic, and the author needs to see the phase names themselves\n // (and get tsc's \"Did you mean …?\" against them).\n readonly scope:\n | \"edges\"\n | \"all\"\n | GroupName<C>\n | readonly (\"edges\" | \"all\" | GroupName<C>)[];\n };\n };\n readonly cmds?: { readonly [N in keyof CmdMap<C>]: Ty<object> };\n readonly states: {\n readonly [G in keyof Groups<C>]: {\n readonly [S in keyof Groups<C>[G]]: {\n /** Exactly one state in a machine-bearing chart marks itself the entry. */\n readonly initial?: true;\n /** Extra data only THIS state carries, on top of `ctx`. */\n readonly data?: Ty<object>;\n readonly on?: {\n readonly [E in EventName<C>]?: EdgeSpec<StateName<C>, CmdName<C>>;\n };\n /** Per-state exception: refuse a live event by name. */\n readonly ignore?: readonly EventName<C>[];\n readonly end?: true;\n };\n };\n };\n};\n\n// ── 5. the strictness layers that assignability alone does not buy ─────────\n//\n// Constraint checking is plain assignability — it does NOT run excess-property\n// checks — so `{ target, whn, otherwise }` structurally satisfies\n// `{ target: SN; cmd?: … }` and a typo'd `when` would silently drop the guard,\n// and a typo'd EVENT key in `on` would silently invent an edge for an event\n// that does not exist. These map the offending shape to a marker object naming\n// the offender, which the object-literal check then rejects.\ntype KnownEdgeField =\n | \"target\"\n | \"cmd\"\n | \"otherwiseCmd\"\n | \"when\"\n | \"otherwise\"\n | \"resume\"\n | \"to\"\n | \"cell\";\n\n/**\n * A cell edge OWNS its transition end to end — it picks the target and returns\n * its own cmds. So every declarative field that would also decide one of those\n * is illegal ALONGSIDE it, rather than silently ignored by the walk:\n *\n * `cmd`/`otherwiseCmd` — the cell already returns the cmd list (req. 4)\n * `when`/`otherwise` — the cell already chose (a guard would choose twice)\n * `target`/`resume` — same fact as `to`, said a second way\n *\n * The `assign` bypass (req. 6) is caught one level up: `Assigns` is keyed by\n * `EdgeKey` MINUS the cell edges, so writing `\"polling.poll_failed\"` in the\n * assign bag of a cell edge is an excess property, named by tsc.\n */\ntype CellFieldConflict =\n | \"target\"\n | \"cmd\"\n | \"otherwiseCmd\"\n | \"when\"\n | \"otherwise\"\n | \"resume\";\n\n/**\n * A resume edge OWNS its transition the same way a cell edge does: the target\n * is `st.was ?? fallback`, which is neither declared nor chosen by a guard. So\n * every field that would ALSO decide the target is illegal alongside it, rather\n * than accepted and then skipped by the walk — `buildCell` tests `edge.resume`\n * first, so a `when` beside it is a guard the author writes, maintains and\n * reads as load-bearing, and which is never once called.\n *\n * `cmd` is absent from this list deliberately: `EdgeSpec` admits `{ resume, cmd }`\n * and the walk fires it, so it is a real, working field on a resume edge.\n * `to`/`cell` are absent because `CellCheck` already names that conflict.\n */\ntype ResumeFieldConflict = \"target\" | \"when\" | \"otherwise\" | \"otherwiseCmd\";\n\ntype ResumeCheck<X> = X extends { readonly resume: unknown }\n ? [Extract<keyof X, ResumeFieldConflict>] extends [never]\n ? unknown\n : {\n readonly __resumeEdgeCannotAlsoDeclare: Extract<\n keyof X,\n ResumeFieldConflict\n >;\n }\n : unknown;\n\n/**\n * `when` and `otherwise` are ONE fact — \"this edge branches\" — written in two\n * halves, and half of it is not a decision, it is a hole.\n *\n * The two layers used to key the `{ then, else }` assign shape off different\n * halves: `Cell<C, X, …>` off `X extends { target; otherwise }`, `buildCell`\n * off `edge.when !== undefined`. Omit either field and they picked opposite\n * shapes — the chart compiled and then died with `payloadFn is not a function`\n * on the first message. Both layers now read `when`, and this makes the two\n * halves inseparable, so there is no shape left on which they could disagree.\n */\ntype GuardPairCheck<X> = X extends { readonly when: string }\n ? X extends { readonly otherwise: unknown }\n ? unknown\n : { readonly __whenNeedsAnOtherwiseTarget: true }\n : X extends { readonly otherwise: unknown }\n ? { readonly __otherwiseNeedsAWhenGuard: true }\n : unknown;\n\ntype CellCheck<X> = X extends { readonly cell: string }\n ? X extends { readonly to: readonly unknown[] }\n ? [Extract<keyof X, CellFieldConflict>] extends [never]\n ? unknown\n : {\n readonly __cellEdgeCannotAlsoDeclare: Extract<\n keyof X,\n CellFieldConflict\n >;\n }\n : { readonly __cellEdgeMustDeclareItsTargetsInTo: true }\n : X extends { readonly to: readonly unknown[] }\n ? { readonly __toWithoutACellToPickFromIt: true }\n : unknown;\n\ntype EdgeCheck<X> = X extends string\n ? unknown\n : [Exclude<keyof X, KnownEdgeField>] extends [never]\n ? CellCheck<X> &\n ResumeCheck<X> &\n GuardPairCheck<X> &\n // `otherwiseCmd` is meaningless without a guard to have an \"otherwise\":\n // it would sit on an unguarded edge and silently never fire.\n (X extends { readonly otherwiseCmd: unknown }\n ? X extends { readonly when: string }\n ? unknown\n : { readonly __otherwiseCmdWithoutAGuard: true }\n : unknown)\n : { readonly __edgeHasUnknownField: Exclude<keyof X, KnownEdgeField> };\n\n// ── unknown KEYS, at every level of the literal ────────────────────────────\n//\n// The same hole `KnownEdgeField` closes on an edge exists at the three levels\n// above it, and for the same reason: constraint checking is plain assignability\n// and `C` is inferred FROM the literal, so the literal's own typo is part of the\n// type it is checked against and excess-property checking has nothing to fire\n// on. `cxt: ty<…>()` was therefore a chart with no `ctx` — `CtxOf<C>` fell back\n// to `unknown`, `StateOf<C>` collapsed to bare `{ type }`, and every `assign`\n// builder was left owing nothing. The chart enforced LESS than a hand-written\n// table. Same shape for `foriegn` (the library event gets namespaced — exactly\n// what `foreign: true` exists to prevent), `dta`, `intial`, `evnets`.\n//\n// So: one rule per level, naming the offending key, the way the edge level does.\ntype KnownChartField = \"ctx\" | \"events\" | \"cmds\" | \"states\";\ntype KnownEventField = \"data\" | \"foreign\" | \"scope\";\ntype KnownNodeField = \"initial\" | \"data\" | \"on\" | \"ignore\" | \"end\";\n\ntype UnknownKeys<X, Known extends string> = Exclude<keyof X, Known>;\n\ntype EventCheck<X> = [UnknownKeys<X, KnownEventField>] extends [never]\n ? unknown\n : { readonly __eventHasUnknownField: UnknownKeys<X, KnownEventField> };\n\ntype NodeCheck<N> = [UnknownKeys<N, KnownNodeField>] extends [never]\n ? unknown\n : { readonly __stateNodeHasUnknownField: UnknownKeys<N, KnownNodeField> };\n\ntype StrictNode<C, N> = NodeCheck<N> & {\n readonly on?: {\n readonly [E in keyof OnOf<N>]: E extends EventName<C>\n ? EdgeCheck<OnOf<N>[E]>\n : { readonly __onDeclaresAnUndeclaredEvent: E };\n };\n};\n\n// ── the DEGENERACY guard ───────────────────────────────────────────────────\n//\n// Every derivation in this file is a union of LITERALS. One computed key whose\n// type is the bare `string` —\n//\n// const prefix = \"a\" as string;\n// states: { only: { [prefix]: { … } } }\n//\n// — gives `states.only` an index signature, `StateName<C>` becomes `string`, and\n// every check downstream of it silently stops checking: a bogus `target` is\n// accepted, `EdgeKey<C>` degenerates, and `compile(g, { assign: {} })` demands\n// no builders at all. The chart is not weakened, it is switched OFF, and nothing\n// says so. A LITERAL computed key (`const NAME = \"a\"`) and a spread of another\n// object both keep their literal types and are unaffected.\ntype IsDegenerate<N> = [string] extends [N] ? true : false;\n\ntype LiteralAlphabets<C> = ([IsDegenerate<StateName<C>>] extends [true]\n ? { readonly __stateNamesMustBeLiteralsNotAComputedStringKey: true }\n : unknown) &\n ([IsDegenerate<EventName<C>>] extends [true]\n ? { readonly __eventNamesMustBeLiteralsNotAComputedStringKey: true }\n : unknown) &\n ([IsDegenerate<CmdName<C>>] extends [true]\n ? { readonly __cmdNamesMustBeLiteralsNotAComputedStringKey: true }\n : unknown) &\n ([IsDegenerate<GroupName<C>>] extends [true]\n ? { readonly __phaseNamesMustBeLiteralsNotAComputedStringKey: true }\n : unknown);\n\nexport type Strict<C> = LiteralAlphabets<C> &\n ([UnknownKeys<C, KnownChartField>] extends [never]\n ? unknown\n : { readonly __chartHasUnknownField: UnknownKeys<C, KnownChartField> }) & {\n readonly events: {\n readonly [E in keyof EvMap<C>]: EventCheck<EvMap<C>[E]>;\n };\n readonly states: {\n readonly [G in keyof Groups<C>]: {\n readonly [S in keyof Groups<C>[G]]: StrictNode<C, Groups<C>[G][S]>;\n };\n };\n };\n\n// The diagnostic IS the property name: tsc reports the missing property\n// verbatim, so the author reads which pair and what the fixes are without\n// decoding a type. Value `never` so it cannot be silenced by writing the key.\ntype Demand<S extends string, E extends string> = E extends string\n ? `unhandled pair \"${S}.${E}\" — declare it in \\`on\\`, or list \"${E}\" in this state's \\`ignore\\`, or narrow the \\`scope\\` of event \"${E}\"`\n : never;\n\ntype IsUnion<T, U = T> = T extends unknown\n ? [U] extends [T]\n ? false\n : true\n : never;\n\nexport type Total<C> = {\n // A namespaced key IS `${ns}.${event}`, so a foreign name that already\n // contains a dot is indistinguishable from one. Banning the dot on foreign\n // names makes the collision unrepresentable for EVERY namespace at once,\n // rather than deferring it to a per-`compile` check that only fires for the\n // one namespace that happens to collide.\n readonly events: {\n readonly [E in keyof EvMap<C>]: [IsForeignOf<EvMap<C>[E]>] extends [true]\n ? E extends `${string}.${string}`\n ? { readonly __foreignEventNameCannotContainADot: E }\n : unknown\n : unknown;\n };\n readonly states: {\n readonly [G in keyof Groups<C>]: {\n readonly [S in keyof Groups<C>[G]]: ([MissingAt<C, S>] extends [never]\n ? unknown\n : {\n readonly [K in Demand<\n Extract<S, string>,\n Extract<MissingAt<C, S>, string>\n >]: never;\n }) &\n // An edge key IS `${state}.${event}` and `Assigns` splits it at the\n // FIRST dot, so a dotted state name re-partitions every key it appears\n // in: `\"a.b.X\"` reads as state `\"a\"`, event `\"b.X\"`. It already failed\n // closed, but with a diagnostic that named nothing (`Type '(s: any) =>\n // …' is not assignable to type 'never'`). Same ban, same reason and now\n // the same shape as `__foreignEventNameCannotContainADot`.\n (Extract<S, string> extends `${string}.${string}`\n ? { readonly __stateNameCannotContainADot: S }\n : unknown) &\n // `end: true` means \"accepts nothing\" — it cannot also accept something.\n ([Extract<keyof On<C, S>, string>] extends [never]\n ? unknown\n : [IsEndOf<Groups<C>[G][S]>] extends [true]\n ? { readonly __endStateCannotDeclareEdges: keyof On<C, S> }\n : unknown) &\n // a state may live in exactly one phase.\n ([IsUnion<GroupOf<C, S>>] extends [true]\n ? { readonly __stateDeclaredInTwoPhases: GroupOf<C, S> }\n : unknown) &\n // an `ignore` entry that refuses an event which is not live here\n // refuses nothing — the paste-the-error-back loop, caught.\n ([Exclude<IgnoredAt<C, S>, LiveAt<C, S>>] extends [never]\n ? unknown\n : {\n readonly __refusalRefusesNothing: Exclude<\n IgnoredAt<C, S>,\n LiveAt<C, S>\n >;\n });\n };\n };\n};\n\n/**\n * `const C` preserves the nested literals with no `as const` at the call site\n * (without it every edge value widens to `string` and every derivation below\n * collapses). `Strict` and `Total` sit on the PARAMETER, not on the constraint:\n * intersecting them into the constraint makes the typo'd-target diagnostic\n * collapse to an index-signature complaint about `string` and lose tsc's\n * \"Did you mean '\"review\"'?\" suggestion.\n */\nexport function defineChart<const C extends Chart<C>>(\n c: C & Strict<C> & Total<C>,\n): C {\n return c;\n}\n\n// ── 6. derivations off the chart ───────────────────────────────────────────\ntype EdgeAt<C, S, E> = E extends keyof On<C, S> ? On<C, S>[E] : never;\n\n/** The `State.Event` pairs that are ACTUALLY declared — not the cross product. */\nexport type EdgeKey<C> = {\n [S in StateName<C>]: `${S}.${Extract<keyof On<C, S>, string>}`;\n}[StateName<C>];\n\n/** The subset of `EdgeKey` whose transition is delegated to a cell. */\nexport type CellEdgeKey<C> = Extract<\n {\n [S in StateName<C>]: {\n [E in keyof On<C, S>]: On<C, S>[E] extends { readonly cell: string }\n ? `${S}.${Extract<E, string>}`\n : never;\n }[keyof On<C, S>];\n }[StateName<C>],\n string\n>;\n\n/** The state marked `initial: true` — the chart's entry, as data. */\nexport type InitialState<C> = Extract<\n {\n [S in StateName<C>]: [IsInitialOf<NodeAt<C, S>>] extends [true] ? S : never;\n }[StateName<C>],\n string\n>;\n\n// ── 7. the resume (\"hist\") derivation ──────────────────────────────────────\n/** States that carry a `resume` edge out of them — the parking states. */\nexport type ParkingState<C> = Extract<\n {\n [S in StateName<C>]: {\n [E in keyof On<C, S>]: On<C, S>[E] extends { readonly resume: unknown }\n ? S\n : never;\n }[keyof On<C, S>];\n }[StateName<C>],\n string\n>;\n\n/** The targets a CELL edge declares — the union its cell is clamped to. */\ntype ToOf<X> = X extends { readonly to: readonly (infer T)[] } ? T : never;\n\n/**\n * Every state an edge can land on. A guarded edge contributes both arms; a\n * cell edge contributes its whole declared `to` fan-out — which is precisely\n * why the escape hatch does not blind the derivations (`ResumeTargets`,\n * `chartMermaid`) that read the graph's shape.\n */\ntype TargetOf<X> = X extends string\n ? X\n : X extends { readonly to: readonly unknown[] }\n ? ToOf<X>\n : X extends { readonly target: infer T }\n ? T | (X extends { readonly otherwise: infer O } ? O : never)\n : never;\n\n/** States with an edge INTO `P` — i.e. the states you could be parked from. */\ntype ResumeSource<C, P> = {\n [S in StateName<C>]: {\n [E in keyof On<C, S>]: P extends TargetOf<On<C, S>[E]> ? S : never;\n }[keyof On<C, S>];\n}[StateName<C>];\n\n/** The `fallback` declared on `P`'s resume edge — Umut's `?? initial`. */\ntype FallbackOf<C, P> = {\n [E in keyof On<C, P>]: On<C, P>[E] extends {\n readonly resume: { readonly fallback: infer F };\n }\n ? F\n : never;\n}[keyof On<C, P>];\n\n/**\n * Where a resume edge out of parking state `P` can land: any state with an edge\n * into `P`, plus the declared fallback. `was ?? initial` lifted to a type — and\n * DERIVED, so adding a `BLOCKED` edge from a new state widens the legal `was`.\n */\nexport type ResumeTargets<C, P> = Extract<\n ResumeSource<C, P> | FallbackOf<C, P>,\n string\n>;\n\n// ── 8. the three unions, all derived from the one chart ────────────────────\n/**\n * `was` is INJECTED here, not authored: a parking state is one with a `resume`\n * edge, which the chart already says. Writing `blocked: Ctx & { was: … }` by\n * hand would be that same fact a second time.\n */\nexport type StateOf<C> = {\n [S in StateName<C>]: { readonly type: S } & CtxOf<C> &\n DataOf<NodeAt<C, S>> &\n (S extends ParkingState<C>\n ? { readonly was: ResumeTargets<C, S> }\n : unknown);\n}[StateName<C>];\n\nexport type MsgOf<C> = {\n [E in EventName<C>]: { readonly type: E } & DataOf<EvMap<C>[E]>;\n}[EventName<C>];\n\nexport type CmdOf<C> = [CmdName<C>] extends [never]\n ? Cmd<never>\n : {\n [N in CmdName<C>]: { readonly type: N } & Payload<CmdMap<C>[N]>;\n }[CmdName<C>];\n\n/** The events the chart declares FOREIGN — the names that are not ours to decorate. */\nexport type ForeignEvent<C> = Extract<\n {\n [E in EventName<C>]: [IsForeignOf<EvMap<C>[E]>] extends [true] ? E : never;\n }[EventName<C>],\n string\n>;\n\n/**\n * How the compiled table keys event `E`. Namespacing is PER-EVENT, not\n * per-machine: `NS` omitted (`undefined`) namespaces nothing, and a foreign\n * event keeps its bare name even under a namespace. Everything stays a literal.\n */\n// The foreign test comes FIRST, deliberately. `NS` is often an unresolved type\n// parameter (inside a `function make<const NS extends string>(ns: NS)` factory),\n// and a conditional on it stays deferred — which would leave even the foreign\n// key unresolved, so the library's own Msg would not be assignable to the\n// instance's Msg union inside the factory. Testing `E` first resolves the\n// foreign branch eagerly, whatever `NS` turns out to be.\ntype KeyOf<C, NS extends string | undefined, E extends string> =\n E extends ForeignEvent<C> ? E : NS extends string ? `${NS}.${E}` : E;\n\n/**\n * The Msg union AS THE COMPILED TABLE CONSUMES IT — the same derivation as\n * `MsgOf`, with the keys the namespace produces. Two namespaces give genuinely\n * disjoint literal unions for the author's OWN events, while the foreign events\n * are literally shared, because they are the same event.\n */\nexport type MsgIn<C, NS extends string | undefined = undefined> = {\n [E in EventName<C>]: { readonly type: KeyOf<C, NS, E> } & DataOf<EvMap<C>[E]>;\n}[EventName<C>];\n\n// ── 9. the parts the chart cannot own ──────────────────────────────────────\ntype Narrow<U, K> = Extract<U, { type: K }>;\ntype Data<S, K> = K extends string ? Omit<Narrow<S, K>, \"type\"> : never;\n\ntype UnionToIntersection<U> = (\n U extends unknown\n ? (x: U) => void\n : never\n) extends (x: infer I) => void\n ? I\n : never;\n\n/**\n * What an `assign` must return for a given target. `was` is stripped when the\n * target is a parking state: the compiler injects it from `state.type`, so the\n * author can neither forget it nor type it wrong.\n */\ntype Assigned<C, S, T> = T extends string\n ? T extends ParkingState<C>\n ? Omit<Data<S, T>, \"was\">\n : Data<S, T>\n : never;\n\n/**\n * What `boot()` must return: the initial state's payload, minus the `type` the\n * compiler stamps on. The two degenerate charts get a NAMED marker type rather\n * than a silent `never`, so the diagnostic says which rule was broken.\n */\nexport type InitialData<C, S extends { type: string }> = [\n InitialState<C>,\n] extends [never]\n ? { readonly __chartDeclaresNoInitialState: true }\n : [IsUnion<InitialState<C>>] extends [true]\n ? { readonly __chartDeclaresManyInitialStates: InitialState<C> }\n : Data<S, InitialState<C>>;\n\ntype Fn<S, M, From, Ev, R> = (state: Narrow<S, From>, msg: Narrow<M, Ev>) => R;\n\ntype Cell<C, X, S, M, From, Ev> = X extends { readonly resume: unknown }\n ? // a resume edge may land on ANY resume target → the payload must satisfy\n // all of them, hence the intersection (not the union).\n Fn<\n S,\n M,\n From,\n Ev,\n UnionToIntersection<Assigned<C, S, ResumeTargets<C, From>>>\n >\n : // THE SAME PREDICATE THE WALK USES. `buildCell` branches on\n // `edge.when !== undefined`; so does this. `GuardPairCheck` makes `when`\n // and `otherwise` inseparable, so on any chart that compiles the two arms\n // below are both present — but the SHAPE is decided by one field read by\n // both layers, not by two conditions that have to be kept in agreement.\n X extends { readonly when: string }\n ? {\n readonly then: Fn<\n S,\n M,\n From,\n Ev,\n Assigned<C, S, X extends { readonly target: infer T } ? T : never>\n >;\n readonly else: Fn<\n S,\n M,\n From,\n Ev,\n Assigned<C, S, X extends { readonly otherwise: infer O } ? O : never>\n >;\n }\n : X extends { readonly target: infer T }\n ? Fn<S, M, From, Ev, Assigned<C, S, T>>\n : X extends string\n ? Fn<S, M, From, Ev, Assigned<C, S, X>>\n : never;\n\n/**\n * The payload builders — one per DECLARATIVE edge. Cell edges are excluded:\n * a cell returns the whole next state itself, so an `assign` entry for one\n * would be dead code the walk never calls. Because this is a mapped type over\n * a closed key union, writing that entry anyway is an excess property and tsc\n * names it (req. 6 — the bypass is a compile error, not a surprise).\n */\nexport type Assigns<\n C,\n S extends { type: string },\n M extends { type: string },\n> = {\n [K in Exclude<\n EdgeKey<C>,\n CellEdgeKey<C>\n >]: K extends `${infer From}.${infer Ev}`\n ? Cell<C, EdgeAt<C, From, Ev>, S, M, From, Ev>\n : never;\n};\n\n// ── 10. guards / cmds, typed FROM THEIR USE SITES ──────────────────────────\nexport type GuardName<C> = Extract<\n {\n [S in StateName<C>]: {\n [E in keyof On<C, S>]: On<C, S>[E] extends { readonly when: infer W }\n ? W\n : never;\n }[keyof On<C, S>];\n }[StateName<C>],\n string\n>;\n\n/** Every cell named by a `{ to, cell }` edge — the escape hatch's alphabet. */\nexport type CellName<C> = Extract<\n {\n [S in StateName<C>]: {\n [E in keyof On<C, S>]: On<C, S>[E] extends { readonly cell: infer W }\n ? W\n : never;\n }[keyof On<C, S>];\n }[StateName<C>],\n string\n>;\n\n/** Flatten a `CmdRef` — one name, or every name in an ordered list. */\ntype Flatten<X> = X extends readonly string[] ? X[number] : X;\n\n/** Every cmd an edge can fire, across BOTH guard arms. */\ntype EdgeCmds<X> =\n | (X extends { readonly cmd: infer Q } ? Flatten<Q> : never)\n | (X extends { readonly otherwiseCmd: infer Q } ? Flatten<Q> : never);\n\n/** Every cmd name any edge in the chart actually FIRES declaratively. */\nexport type UsedCmdName<C> = Extract<\n {\n [S in StateName<C>]: {\n [E in keyof On<C, S>]: EdgeCmds<On<C, S>[E]>;\n }[keyof On<C, S>];\n }[StateName<C>],\n string\n>;\n\n/** What field `F` on an edge REFERENCES — a guard/cell name, or its cmd names. */\ntype Referenced<X, F extends \"when\" | \"cmd\" | \"cell\"> = F extends \"when\"\n ? X extends { readonly when: infer W }\n ? W\n : never\n : F extends \"cell\"\n ? X extends { readonly cell: infer W }\n ? W\n : never\n : EdgeCmds<X>;\n\n/**\n * Scan the chart for every edge that references `Name` through field `F`.\n * `[Name] extends [Referenced<…>]` rather than an equality check, because an\n * edge's cmd list references SEVERAL names at once.\n */\ntype SitesWhere<C, F extends \"when\" | \"cmd\" | \"cell\", Name> = {\n [S in StateName<C>]: {\n [E in keyof On<C, S>]: [Name] extends [Referenced<On<C, S>[E], F>]\n ? `${S}.${Extract<E, string>}`\n : never;\n }[keyof On<C, S>];\n}[StateName<C>];\n\n/**\n * `\"review.FAIL\"` → `[state: ReviewState, msg: FailMsg, at: \"review.FAIL\"]`.\n * Distributes over N sites, so a multi-site name yields a UNION OF TUPLES.\n *\n * The third element is the correlator. A union of tuples does not, on its own,\n * keep `state` and `msg` in step: narrowing `state.type` is a NESTED\n * discriminant, and TypeScript's dependent-parameter control-flow analysis\n * (TS 4.6, microsoft/TypeScript#47109) only re-narrows sibling parameters from\n * a discriminant that is a DIRECT, literal-typed element of the union. `at` is\n * exactly that: one `switch (at)` collapses the tuple union to a single member,\n * and `state` AND `msg` both narrow with it.\n *\n * For a single-site name `K` is not a union, so this is a lone tuple and the\n * author may keep writing `(s, m) => …`.\n */\ntype SiteArgs<K, S, M> = K extends `${infer From}.${infer Ev}`\n ? [state: Narrow<S, From>, msg: Narrow<M, Ev>, at: K]\n : never;\n\n/**\n * THE POINT. A guard's parameters come from the edges that REFERENCE it, not\n * from a standalone registry declaration — so `retriesRemaining`, used only at\n * `review.FAIL`, receives exactly `review`'s state and `FAIL`'s msg.\n */\nexport type Guards<\n C,\n S extends { type: string },\n M extends { type: string },\n> = {\n [N in GuardName<C>]: (\n ...args: SiteArgs<SitesWhere<C, \"when\", N>, S, M>\n ) => boolean;\n};\n\n/**\n * Same technique: a cmd's parameters come from the edges that REFERENCE it, and\n * the payload it owes is the one DECLARED in the chart's `cmds` section — the\n * single site where the effect alphabet lives. A cmd fired from two edges gets\n * the union of both sites' `[state, msg]` tuples.\n */\nexport type Cmds<C, S extends { type: string }, M extends { type: string }> = {\n // keyed by the cmds edges FIRE, not by every cmd declared. A cmd only ever\n // emitted from inside a cell needs no builder — the cell built the payload\n // when it built the cmd — but its name still belongs in the `cmds` section,\n // because that section is where the Cmd union comes from.\n [N in UsedCmdName<C>]: (\n ...args: SiteArgs<SitesWhere<C, \"cmd\", N>, S, M>\n ) => Payload<CmdMap<C>[N]>;\n};\n\n/**\n * THE ESCAPE HATCH's parts bag. Same shape and the same `SitesWhere`/`SiteArgs`\n * narrowing as `guards` and `cmds` — a cell used at one site gets exactly that\n * site's state and msg, a cell used at N sites gets the union of N tuples plus\n * the `at` correlator to discriminate on.\n *\n * What is different is the RETURN: a cell returns the transition itself,\n * `[nextState, cmds]`, clamped to the states the edge DECLARED in `to`. That\n * clamp is the whole bargain — code may decide, but only among the targets the\n * chart admits, so the chart stays a truthful drawing of the machine.\n */\nexport type Cells<C, S extends { type: string }, M extends { type: string }> = {\n [N in CellName<C>]: CellForm<C, SitesWhere<C, \"cell\", N>, S, M>;\n};\n\n/** The `to` union of every site `N` is used at, resolved to real State members. */\ntype CellTarget<C, Sites, S> = Sites extends `${infer From}.${infer Ev}`\n ? Narrow<S, ToOf<EdgeAt<C, From, Ev>>>\n : never;\n\ntype CellReturn<C, Sites, S> = readonly [\n CellTarget<C, Sites, S>,\n readonly CmdOf<C>[],\n];\n\n/**\n * THE MULTI-SITE RETURN, EXACTLY. One entry per use site, each a lone tuple of\n * parameters and each clamped to THAT site's `to` — so `a.X` returning a `c` is\n * rejected at `a.X` rather than waved through because some OTHER site admits a\n * `c`. The `at` element is still passed (the walk hands it over uniformly), and\n * is simply redundant here: the key already says which site this is.\n */\ntype CellBySite<C, Sites, S, M> = {\n readonly [K in Extract<Sites, string>]: (\n ...args: SiteArgs<K, S, M>\n ) => CellReturn<C, K, S>;\n};\n\n/**\n * A cell is written in ONE of two forms, and the choice is the precision dial.\n *\n * the FUNCTION form — one body, `switch (at)` inside. Parameters narrow per\n * site (the `SiteArgs` correlator); the RETURN does not, because the whole\n * thing is one rest signature over a union of tuples and TypeScript has no\n * dependent return type over that (5.7: a union of function types is\n * reduced back to exactly this shape, an intersection loses the parameter\n * correlation, and a generic on the site key correlates nothing and merely\n * rejects every body — all three measured, none of them work). The clamp is\n * therefore the union of every site's `to`.\n *\n * the PER-SITE form — one entry per site, each exact in both directions.\n *\n * The second is offered ONLY when the cell is genuinely multi-site: with one\n * site the function form is already exact in both directions, so its type stays\n * byte-for-byte what it was and the common case cannot regress.\n *\n * The looseness the function form keeps is closed at RUNTIME instead: the walk\n * checks the returned `type` against the edge's declared `to` and throws\n * `CellTargetError`. Worth less than a compile error, worth more than nothing —\n * and `to` is right there, so it costs one `includes`.\n */\ntype CellForm<C, Sites, S, M> =\n | ((...args: SiteArgs<Sites, S, M>) => CellReturn<C, Sites, S>)\n | ([IsUnion<Sites>] extends [true] ? CellBySite<C, Sites, S, M> : never);\n\n// ═══════════════════════════════════════════════════════════════════════════\n// 12. REDUCER FORM — the same chart, minus the state grouping.\n//\n// A `Transitions` chart answers |S| × |M| questions. A great many real machines\n// answer only |M| of them: the logic is keyed by the MESSAGE, and `state.type`\n// is a label the message handler writes rather than a dimension it dispatches\n// on. `examples/resilient-fetch.ts` is exactly that — four cells, six phases,\n// and not one of the four asks which phase it is in (except `deadline_exceeded`,\n// which asks INSIDE its body). Forcing it into a grid multiplies each of those\n// four facts by six.\n//\n// So: drop the dimension the machine does not have. Everything else — `ctx`,\n// `events` (with `foreign`), `cmds`, `EdgeSpec` (including `{ to, cell }`),\n// `Referenced`/`EdgeCmds`, `Cell`, `MsgIn`/`KeyOf` — is reused verbatim. What\n// this section adds is the three-line site notion (a site is an EVENT, not a\n// `state.event` pair) and the shapes that hang off it.\n//\n// ── `states`: KEPT, as a flat list ────────────────────────────────────────\n// It is still the chart's job to own every name. `states` stays because two\n// things need it and neither can be recovered from anywhere else:\n//\n// 1. `StateOf<C>` — the State type is DERIVED, as in the grid form, so\n// `type` is spelled once. Declaring the union separately in TypeScript\n// would be the one-site rule broken for no gain.\n// 2. the `to` clamp — `to: [\"succeded\"]` has to be a typo the compiler\n// catches, and it can only do that against a declared universe.\n//\n// What it is NOT is a record of nodes: a reducer cell receives the WHOLE `S`\n// un-narrowed (that is what `Reducer<S, M, C>` says), so per-state `data`,\n// per-state `on`, `end` and `ignore` are all unrepresentable here — which is\n// correct, not a limitation. `StateOf` therefore collapses from a union of\n// members to ONE object whose `type` is a union of literals. That is precisely\n// the original's `interface State { phase: Phase; … }`.\n//\n// ── `scope`/totality: `scope` GOES, totality STAYS (one dimension smaller) ─\n// `scope` answers \"at which states does this event mean anything?\". With no\n// state dimension the question has no content, so the field is gone rather\n// than accepted and ignored.\n//\n// Totality is NOT dropped. It changes quantifier: ∀(s,e) becomes ∀e, and it\n// needs no `Total<C>` analogue to enforce, because `on` is a REQUIRED mapped\n// type over `EventName<C>`. Declare an event and omit its edge and tsc says\n// \"Property 'fetch_err' is missing\". That is the same property `Reducer<S,M,C>`\n// itself enforces on a hand-written record, lifted into the chart — and it is\n// STRONGER per-event than the grid form, where `scope: \"edges\"` lets an event\n// be routed from nowhere at all.\n//\n// What is genuinely LOST, stated plainly: the per-state REFUSAL. A grid chart\n// can say \"in `done`, `poll_failed` is dropped\" and draw it. A reducer chart\n// cannot; that decision lives inside the cell body, exactly where the original\n// hand-written machine had it (`s.phase === \"waiting_retry\" ? … : [s, []]`).\n// This is a real reduction in what the drawing knows. It is the honest trade:\n// the grid form did not RECOVER that information from the original machine, it\n// MANUFACTURED it, at 18 edge declarations for 3 facts. A chart should not\n// charge for knowledge the machine does not have.\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** The declared state names — a flat tuple, not a grouped record of nodes. */\nexport type RStateName<C> = C extends { readonly states: readonly (infer S)[] }\n ? Extract<S, string>\n : never;\n\n/** The top-level edge bag. One edge per event; that IS the totality obligation. */\ntype ROn<C> = C extends { readonly on: infer O } ? O : never;\ntype REdgeAt<C, E> = E extends keyof ROn<C> ? ROn<C>[E] : never;\n\nexport type ReducerChart<C> = {\n /** Data EVERY state carries — and, here, the ONLY data any state carries. */\n readonly ctx?: Ty<object>;\n readonly states: readonly RStateName<C>[];\n /** The entry state, by name. One word where the grid form marks a node. */\n readonly initial: RStateName<C>;\n readonly events: {\n readonly [E in keyof EvMap<C>]: {\n readonly data?: Ty<object>;\n /** Same meaning as the grid form's: this name is not ours to decorate. */\n readonly foreign?: true;\n };\n };\n readonly cmds?: { readonly [N in keyof CmdMap<C>]: Ty<object> };\n /**\n * TOTAL, not partial. Every declared event owes an edge — the `?` the grid\n * form's per-state `on` carries is exactly what `Total<C>` had to police\n * there, and here the mapped type does it for free.\n */\n readonly on: {\n readonly [E in EventName<C>]: EdgeSpec<RStateName<C>, CmdName<C>>;\n };\n};\n\n/**\n * `resume` needs a phase dimension: `was` is derived from \"the states with an\n * edge INTO the parking state\", and here every edge is reachable from every\n * state, so the derivation degenerates to \"all of them\" and says nothing. It\n * is rejected by name rather than silently accepted and ignored by the walk.\n */\ntype RStrictEdge<X> = X extends { readonly resume: unknown }\n ? { readonly __resumeNeedsAPhaseDimension: true }\n : EdgeCheck<X>;\n\n/** The reducer form's key alphabet — `scope` has no meaning without phases. */\ntype KnownReducerChartField =\n | \"ctx\"\n | \"states\"\n | \"initial\"\n | \"events\"\n | \"cmds\"\n | \"on\";\ntype KnownReducerEventField = \"data\" | \"foreign\";\n\ntype REventCheck<X> = [UnknownKeys<X, KnownReducerEventField>] extends [never]\n ? unknown\n : {\n readonly __eventHasUnknownField: UnknownKeys<X, KnownReducerEventField>;\n };\n\nexport type StrictR<C> = ([IsDegenerate<RStateName<C>>] extends [true]\n ? { readonly __stateNamesMustBeLiteralsNotAComputedStringKey: true }\n : unknown) &\n ([IsDegenerate<EventName<C>>] extends [true]\n ? { readonly __eventNamesMustBeLiteralsNotAComputedStringKey: true }\n : unknown) &\n ([IsDegenerate<CmdName<C>>] extends [true]\n ? { readonly __cmdNamesMustBeLiteralsNotAComputedStringKey: true }\n : unknown) &\n // the same unknown-key rule as the grid form, over this form's alphabet — a\n // `cxt` typo here empties `RStateOf<C>` down to its bare tag exactly as it\n // emptied `StateOf<C>` there.\n ([UnknownKeys<C, KnownReducerChartField>] extends [never]\n ? unknown\n : {\n readonly __chartHasUnknownField: UnknownKeys<C, KnownReducerChartField>;\n }) & {\n readonly on: {\n readonly [E in keyof ROn<C>]: E extends EventName<C>\n ? RStrictEdge<ROn<C>[E]>\n : { readonly __onDeclaresAnUndeclaredEvent: E };\n };\n readonly events: {\n readonly [E in keyof EvMap<C>]: REventCheck<EvMap<C>[E]> &\n ([IsForeignOf<EvMap<C>[E]>] extends [true]\n ? E extends `${string}.${string}`\n ? { readonly __foreignEventNameCannotContainADot: E }\n : unknown\n : unknown);\n };\n };\n\n/** Same contract as `defineChart`, one dimension smaller. */\nexport function defineReducerChart<const C extends ReducerChart<C>>(\n c: C & StrictR<C>,\n): C {\n return c;\n}\n\n// ── 12b. derivations ───────────────────────────────────────────────────────\n/**\n * ONE object, not a union: every state carries `ctx` and nothing else, so the\n * only thing that varies is the tag. This is the original's\n * `interface State { phase: Phase; … }` with `phase` named `type`.\n */\nexport type RStateOf<C> = { readonly type: RStateName<C> } & CtxOf<C>;\n\n/** The events whose transition is delegated to a cell. */\nexport type RCellEvent<C> = Extract<\n {\n [E in EventName<C>]: ROn<C>[E & keyof ROn<C>] extends {\n readonly cell: string;\n }\n ? E\n : never;\n }[EventName<C>],\n string\n>;\n\ntype RNames<C, F extends \"when\" | \"cmd\" | \"cell\"> = Extract<\n { [E in keyof ROn<C>]: Referenced<ROn<C>[E], F> }[keyof ROn<C>],\n string\n>;\n\nexport type RGuardName<C> = RNames<C, \"when\">;\nexport type RCellName<C> = RNames<C, \"cell\">;\nexport type RUsedCmdName<C> = RNames<C, \"cmd\">;\n\n/**\n * A site is an EVENT. The grid form's `SitesWhere` scans `state × event`; with\n * one dimension the scan is the same shape with the outer loop removed.\n */\ntype RSitesWhere<C, F extends \"when\" | \"cmd\" | \"cell\", Name> = Extract<\n {\n [E in keyof ROn<C>]: [Name] extends [Referenced<ROn<C>[E], F>] ? E : never;\n }[keyof ROn<C>],\n string\n>;\n\n/**\n * The state is NOT narrowed — there is nothing to narrow it to. Everything\n * else is `SiteArgs` verbatim, including the `at` correlator that lets a\n * multi-site helper discriminate its msg with one `switch`.\n */\ntype RSiteArgs<K, S, M> = K extends string\n ? [state: S, msg: Narrow<M, K>, at: K]\n : never;\n\nexport type RGuards<C, S, M extends { type: string }> = {\n [N in RGuardName<C>]: (\n ...args: RSiteArgs<RSitesWhere<C, \"when\", N>, S, M>\n ) => boolean;\n};\n\nexport type RCmds<C, S, M extends { type: string }> = {\n [N in RUsedCmdName<C>]: (\n ...args: RSiteArgs<RSitesWhere<C, \"cmd\", N>, S, M>\n ) => Payload<CmdMap<C>[N & keyof CmdMap<C>]>;\n};\n\nexport type RCells<\n C,\n S extends { type: string },\n M extends { type: string },\n> = {\n [N in RCellName<C>]: RCellForm<C, RSitesWhere<C, \"cell\", N>, S, M>;\n};\n\n/** The `to` clamp, unchanged in spirit: the tag is restricted, `ctx` is not. */\ntype RCellTarget<C, Sites> = Sites extends string\n ? { readonly type: Extract<ToOf<REdgeAt<C, Sites>>, string> } & CtxOf<C>\n : never;\n\ntype RCellReturn<C, Sites> = readonly [\n RCellTarget<C, Sites>,\n readonly CmdOf<C>[],\n];\n\n/**\n * `CellForm`, with the phase dimension removed — the same two forms, offered on\n * the same condition, for the same reason. A site here is an EVENT, so the\n * per-site bag is keyed `\"X\" | \"Y\"` rather than `\"a.X\" | \"b.Y\"`; everything\n * else, including the runtime `CellTargetError` under the function form, is the\n * grid form's machinery reused verbatim (`buildCell` serves both).\n */\ntype RCellForm<C, Sites, S, M extends { type: string }> =\n | ((...args: RSiteArgs<Sites, S, M>) => RCellReturn<C, Sites>)\n | ([IsUnion<Sites>] extends [true]\n ? {\n readonly [K in Extract<Sites, string>]: (\n ...args: RSiteArgs<K, S, M>\n ) => RCellReturn<C, K>;\n }\n : never);\n\n/**\n * What an `assign` returns: `ctx`, for every target. The compiler stamps\n * `type` from the edge, so — as in the grid form — the author cannot forget it\n * and cannot get it wrong.\n */\ntype RAssigned<C> = CtxOf<C>;\ntype RFn<S, M extends { type: string }, E, R> = (\n state: S,\n msg: Narrow<M, E>,\n) => R;\n\n// `when`, for the same reason as the grid form's `Cell`: it is the field\n// `buildCell` — which serves BOTH forms — actually branches on.\ntype RCell<C, X, S, M extends { type: string }, E> = X extends {\n readonly when: string;\n}\n ? {\n readonly then: RFn<S, M, E, RAssigned<C>>;\n readonly else: RFn<S, M, E, RAssigned<C>>;\n }\n : RFn<S, M, E, RAssigned<C>>;\n\n/** One builder per DECLARATIVE event. Cell events own their whole transition. */\nexport type RAssigns<C, S, M extends { type: string }> = {\n [E in Exclude<EventName<C>, RCellEvent<C>>]: RCell<C, REdgeAt<C, E>, S, M, E>;\n};\n\n// ── 11. identity assertion helpers ─────────────────────────────────────────\nexport type Eq<A, B> =\n (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2\n ? true\n : false;\nexport type Assert<T extends true> = T;\n"]}
@@ -1,5 +1,5 @@
1
1
  import { dispatchIfPresent } from './chunk-ZJ5AOYBH.js';
2
- import { structuralHash, subId } from './chunk-O7ED34JH.js';
2
+ import { structuralHash, subId } from './chunk-B5VXOFMZ.js';
3
3
 
4
4
  // src/subs/define-listener.ts
5
5
  function defineListener(target) {
@@ -368,5 +368,5 @@ function fromTransport(opts) {
368
368
  }
369
369
 
370
370
  export { combineManagedResources, defineListener, defineManagedResource, fromBroadcastChannel, fromEventSource, fromEventTarget, fromInterval, fromPort, fromReconnectingWebSocket, fromTransport, fromWebSocket };
371
- //# sourceMappingURL=chunk-2UGTDYOK.js.map
372
- //# sourceMappingURL=chunk-2UGTDYOK.js.map
371
+ //# sourceMappingURL=chunk-3JU6657S.js.map
372
+ //# sourceMappingURL=chunk-3JU6657S.js.map