@demlik/tea 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +30 -7
  2. package/dist/agent/index.d.ts +49 -37
  3. package/dist/agent/index.js +12 -8
  4. package/dist/chunk-4LPY67E4.js +18 -0
  5. package/dist/chunk-4LPY67E4.js.map +1 -0
  6. package/dist/chunk-4NTCPTNQ.js +64 -0
  7. package/dist/chunk-4NTCPTNQ.js.map +1 -0
  8. package/dist/{chunk-3B5X7SBB.js → chunk-4PXNZ5UY.js} +11 -9
  9. package/dist/chunk-4PXNZ5UY.js.map +1 -0
  10. package/dist/{chunk-AYS5N6WY.js → chunk-6XBEYZME.js} +62 -172
  11. package/dist/chunk-6XBEYZME.js.map +1 -0
  12. package/dist/chunk-C4U5D5HP.js +380 -0
  13. package/dist/chunk-C4U5D5HP.js.map +1 -0
  14. package/dist/{chunk-QPEVCJ5Q.js → chunk-DFUEAA6L.js} +13 -6
  15. package/dist/chunk-DFUEAA6L.js.map +1 -0
  16. package/dist/{chunk-22POWGFA.js → chunk-GWWCCSDH.js} +46 -20
  17. package/dist/chunk-GWWCCSDH.js.map +1 -0
  18. package/dist/chunk-K4ETBNKS.js +733 -0
  19. package/dist/chunk-K4ETBNKS.js.map +1 -0
  20. package/dist/chunk-KWNCM6XM.js +539 -0
  21. package/dist/chunk-KWNCM6XM.js.map +1 -0
  22. package/dist/{chunk-V46HSVCK.js → chunk-LYVOGOBC.js} +3 -3
  23. package/dist/{chunk-V46HSVCK.js.map → chunk-LYVOGOBC.js.map} +1 -1
  24. package/dist/{chunk-VTQI2NHP.js → chunk-OPH6Y4UT.js} +9 -8
  25. package/dist/chunk-OPH6Y4UT.js.map +1 -0
  26. package/dist/{chunk-Q5CQTBFA.js → chunk-OYR7ENKU.js} +20 -30
  27. package/dist/chunk-OYR7ENKU.js.map +1 -0
  28. package/dist/{chunk-MYXFNWAJ.js → chunk-QNGYQMZB.js} +4 -4
  29. package/dist/chunk-QNGYQMZB.js.map +1 -0
  30. package/dist/chunk-QWIPH4YH.js +98 -0
  31. package/dist/chunk-QWIPH4YH.js.map +1 -0
  32. package/dist/{chunk-TCLBCERH.js → chunk-XBZQT2TD.js} +238 -212
  33. package/dist/chunk-XBZQT2TD.js.map +1 -0
  34. package/dist/{core-DnzqWy6u.d.ts → core-rDbOaJTN.d.ts} +236 -140
  35. package/dist/do/index.d.ts +37 -33
  36. package/dist/do/index.js +21 -14
  37. package/dist/do/index.js.map +1 -1
  38. package/dist/{durable-effects-CWzA-o2B.d.ts → durable-effects-CNaw97Be.d.ts} +1 -1
  39. package/dist/effect/index.d.ts +151 -0
  40. package/dist/effect/index.js +98 -0
  41. package/dist/effect/index.js.map +1 -0
  42. package/dist/extension/index.d.ts +6 -7
  43. package/dist/extension/index.js +3 -2
  44. package/dist/extension/index.js.map +1 -1
  45. package/dist/flow/index.d.ts +68 -59
  46. package/dist/flow/index.js +32 -27
  47. package/dist/flow/index.js.map +1 -1
  48. package/dist/idempotency/index.d.ts +6 -7
  49. package/dist/idempotency/index.js +4 -2
  50. package/dist/{index-KXqTRJyb.d.ts → index-BOrsbdAf.d.ts} +19 -96
  51. package/dist/{index-DrIRb_Ch.d.ts → index-B_BxplWi.d.ts} +1 -1
  52. package/dist/index-CWmsXNdX.d.ts +207 -0
  53. package/dist/{index-C2DwkjlP.d.ts → index-Cberb5Rr.d.ts} +57 -45
  54. package/dist/{index-CSyMYDAB.d.ts → index-CcrKLtse.d.ts} +1 -1
  55. package/dist/{index-CuNO9m8i.d.ts → index-Cx0F2M34.d.ts} +14 -16
  56. package/dist/{index-HSYgG2Yt.d.ts → index-DaX_P35Q.d.ts} +247 -211
  57. package/dist/{index-CA_7I5g9.d.ts → index-q1PoukOZ.d.ts} +137 -246
  58. package/dist/index.d.ts +121 -385
  59. package/dist/index.js +2 -1
  60. package/dist/jev/index.d.ts +133 -97
  61. package/dist/jev/index.js +205 -161
  62. package/dist/jev/index.js.map +1 -1
  63. package/dist/{machine-DGlPWCWI.d.ts → machine-BcfCFMYF.d.ts} +171 -288
  64. package/dist/machine-viz/index.d.ts +5 -5
  65. package/dist/machine-viz/index.js +8 -4
  66. package/dist/machine-viz/index.js.map +1 -1
  67. package/dist/mem/index.d.ts +3 -4
  68. package/dist/mem/index.js +2 -1
  69. package/dist/mem/index.js.map +1 -1
  70. package/dist/node/index.d.ts +119 -78
  71. package/dist/node/index.js +52 -38
  72. package/dist/node/index.js.map +1 -1
  73. package/dist/paginate/index.d.ts +27 -22
  74. package/dist/paginate/index.js +6 -4
  75. package/dist/parity/index.d.ts +4 -5
  76. package/dist/parity/index.js +3 -2
  77. package/dist/parity/index.js.map +1 -1
  78. package/dist/pbt/index.d.ts +2 -2
  79. package/dist/pbt/index.js +2 -1
  80. package/dist/pbt/index.js.map +1 -1
  81. package/dist/persistence/index.d.ts +10 -12
  82. package/dist/persistence/index.js +5 -3
  83. package/dist/promise/index.d.ts +186 -0
  84. package/dist/promise/index.js +5 -0
  85. package/dist/promise/index.js.map +1 -0
  86. package/dist/{protocol-D8VbH-VH.d.ts → protocol-ClRZBhHQ.d.ts} +7 -8
  87. package/dist/react/index.d.ts +36 -17
  88. package/dist/react/index.js +27 -4
  89. package/dist/react/index.js.map +1 -1
  90. package/dist/resilience/index.d.ts +63 -456
  91. package/dist/resilience/index.js +37 -483
  92. package/dist/resilience/index.js.map +1 -1
  93. package/dist/{runtime-types-CMF13BBh.d.ts → runtime-types-B62Ucnxr.d.ts} +132 -389
  94. package/dist/testing/index.d.ts +33 -113
  95. package/dist/testing/index.js +39 -181
  96. package/dist/testing/index.js.map +1 -1
  97. package/dist/timing/index.d.ts +25 -22
  98. package/dist/timing/index.js +4 -3
  99. package/dist/timing/index.js.map +1 -1
  100. package/dist/{types-BseNPIhr.d.ts → types-DPm5YCDQ.d.ts} +2 -2
  101. package/dist/work-queue/index.d.ts +5 -6
  102. package/package.json +20 -7
  103. package/dist/chunk-22POWGFA.js.map +0 -1
  104. package/dist/chunk-3B5X7SBB.js.map +0 -1
  105. package/dist/chunk-66PY5WYF.js +0 -1816
  106. package/dist/chunk-66PY5WYF.js.map +0 -1
  107. package/dist/chunk-AYS5N6WY.js.map +0 -1
  108. package/dist/chunk-L3TND7LA.js +0 -97
  109. package/dist/chunk-L3TND7LA.js.map +0 -1
  110. package/dist/chunk-MYXFNWAJ.js.map +0 -1
  111. package/dist/chunk-Q5CQTBFA.js.map +0 -1
  112. package/dist/chunk-QPEVCJ5Q.js.map +0 -1
  113. package/dist/chunk-TCLBCERH.js.map +0 -1
  114. package/dist/chunk-VTQI2NHP.js.map +0 -1
  115. package/dist/index-ZCMhnVKN.d.ts +0 -272
@@ -1,10 +1,9 @@
1
1
  import { I as IdempotencyStore } from '../index-Bc40JWVl.js';
2
2
  export { a as IdempotencyEntry, e as evictExpired, i as initStore, r as recall, b as remember, s as seen } from '../index-Bc40JWVl.js';
3
- import { a as CmdOf, b as CmdDef } from '../core-DnzqWy6u.js';
4
- import { Q as QueueItem } from '../index-CSyMYDAB.js';
5
- import 'zod';
6
- import '../runtime-types-CMF13BBh.js';
7
- import 'better-result';
3
+ import { c as CmdOf, b as CmdDef } from '../core-rDbOaJTN.js';
4
+ import { Q as QueueItem } from '../index-CcrKLtse.js';
5
+ import '@standard-schema/spec';
6
+ import '../runtime-types-B62Ucnxr.js';
8
7
 
9
8
  /**
10
9
  * A cached intake entry: either a key whose work is still in flight
@@ -69,7 +68,7 @@ declare function intakeProcessDef<P>(): CmdDef<"intake:process", {
69
68
  readonly itemId: string;
70
69
  /** The original payload, for the worker to process. */
71
70
  readonly payload: P;
72
- }, void, never, unknown>;
71
+ }, undefined, never>;
73
72
  type IntakeProcessCmd<P> = CmdOf<ReturnType<typeof intakeProcessDef<P>>>;
74
73
  /**
75
74
  * A duplicate of an already-completed key arrived — replay the cached result
@@ -80,7 +79,7 @@ declare function intakeReplayDef<R>(): CmdDef<"intake:replay", {
80
79
  readonly key: string;
81
80
  /** The result the ORIGINAL request produced, recalled from the cache. */
82
81
  readonly result: R;
83
- }, void, never, unknown>;
82
+ }, undefined, never>;
84
83
  type IntakeReplayCmd<R> = CmdOf<ReturnType<typeof intakeReplayDef<R>>>;
85
84
  /** The Cmd union the intake verbs emit. */
86
85
  type IntakeCmd<P, R> = IntakeProcessCmd<P> | IntakeReplayCmd<R>;
@@ -1,6 +1,8 @@
1
- export { createIntake, intakeProcessDef, intakeReplayDef } from '../chunk-VTQI2NHP.js';
1
+ export { createIntake, intakeProcessDef, intakeReplayDef } from '../chunk-OPH6Y4UT.js';
2
2
  export { evictExpired, initStore, recall, remember, seen } from '../chunk-PR6TB3BL.js';
3
3
  import '../chunk-TXN2KFHF.js';
4
- import '../chunk-66PY5WYF.js';
4
+ import '../chunk-4LPY67E4.js';
5
+ import '../chunk-C4U5D5HP.js';
6
+ import '../chunk-K4ETBNKS.js';
5
7
  //# sourceMappingURL=index.js.map
6
8
  //# sourceMappingURL=index.js.map
@@ -1,89 +1,7 @@
1
- import { I as Interpret, C as Cmd } from './core-DnzqWy6u.js';
2
- import { S as SnapshotWriteCmd, a as SnapshotState, b as SnapshotStore, c as SnapshotSavedMsg, d as SnapshotFailedMsg, e as SnapshotLoadedMsg, f as SnapshotLoadFailedMsg, g as SnapshotLoadCmd } from './index-ZCMhnVKN.js';
3
- import { D as DeadlineExceeded, a as DeadlineSub } from './index-HSYgG2Yt.js';
4
- import { Q as QueueItem } from './index-CSyMYDAB.js';
5
-
6
- /**
7
- * internal/flow/monitored-run — a long-running operation that is BOTH staged and
8
- * watched: an ordered stage pipeline whose POSITION survives eviction, wrapped
9
- * by a no-progress safety deadline and (optionally) a periodic durable
10
- * checkpoint.
11
- *
12
- * This is the merge of two field-guide concerns the audit-agent machine
13
- * hand-wired together (`seed/audit-agent-machine`): the OUTER pipeline position
14
- * (`RunStage` — planning → testing → summarizing → reporting, replayed on cold
15
- * wake by re-emitting the one outstanding effect) and the no-progress safety
16
- * alarm (`subs.ts`, keyed on `progressSeq` so every progress event retires the
17
- * old alarm and arms a fresh one). `monitored-run` lifts both into one config-
18
- * driven knob with the uniform L2 contract `resilient-call` established:
19
- * `init()`, the verbs (`start` / `advance` / `progress` / `onDeadline` /
20
- * `boot`), `subs(state)`, and `handlers(ports)`.
21
- *
22
- * - It is **staged, optionally**. Omit `stages` and the run is single-shot:
23
- * `start` enters `running`, `advance` finishes it to `done`. Provide
24
- * `stages` and it becomes an ordered pipeline — each `advance` retires the
25
- * current stage and claims the next, finishing to `done` only when the last
26
- * stage is retired. The pipeline POSITION lives in the Model (a
27
- * `work-queue` of stage items), so an eviction mid-pipeline resumes at the
28
- * same stage via `boot` — the audit machine's "pipeline position survives
29
- * eviction" property, generalized.
30
- * - It is **watched**. While `running`, a no-progress deadline is armed at
31
- * `lastProgressAt + deadlineMs` and keyed on `progressSeq`. Every
32
- * `progress` / `advance` bumps the seq, so the substrate retires the old
33
- * alarm and arms a new one — a self-rearming watchdog. If the alarm fires
34
- * (`onDeadline`) the run goes `failed` with a deadline reason. Omit
35
- * `deadlineMs` → no watchdog (the `stale` phase is never reachable).
36
- * - It **checkpoints, optionally**. Provide `snapshotEvery` and every
37
- * progress unit is accounted to a `../snapshot` slice; once the cadence is
38
- * reached a checkpoint Cmd is emitted (interpreted by the spliced snapshot
39
- * `handlers`), so a crashed run restarts from the last durable checkpoint
40
- * rather than from zero. Omit it → no checkpointing.
41
- *
42
- * ## Why the run lifecycle is INLINE (run-tracker not extracted)
43
- *
44
- * The phase union (`idle` / `running` / `stale` / `done` / `failed` / `cancelled`, a
45
- * discriminated union carrying only each phase's own data) and its bookkeeping
46
- * (`runId`, `startedAt`, `lastProgressAt`, `progressSeq`) live directly on this
47
- * slice rather than behind a `run-tracker` sub-knob.
48
- * Extraction earns its keep when two independent axes vary; here the lifecycle
49
- * has exactly one anchoring axis (this run), so a separate module would be a
50
- * premature seam. The two genuinely independent axes — the safety DEADLINE and
51
- * the periodic SNAPSHOT — ARE extracted (`../deadline`, `../snapshot`), and the
52
- * stage list is a `../work-queue` slice (`QueueItem<Stage>[]`) whose every
53
- * status flip is DELEGATED to the blessed `../work-queue/ops` (`enqueueOp` /
54
- * `claimNextOp` / `markDoneOp`) — never re-rolled here. The lifecycle is the
55
- * glue between them.
56
- *
57
- * ## The two non-negotiables (canon)
58
- *
59
- * - **Durable** — the slice is plain data (the stage queue is a
60
- * JSON-serializable `QueueItem<Stage>[]`, the snapshot slice is plain
61
- * numbers), so it survives DO eviction / reload.
62
- * - **Replayable** — every transition is a pure verb returning new state +
63
- * Cmds; nothing here reads the clock or RNG. Time arrives as an `at` / `atMs`
64
- * parameter; the only clock read is `Date.now()` inside the snapshot
65
- * `handlers` port (the effect boundary), exactly as `../snapshot` stamps it.
66
- *
67
- * ## Typical wiring
68
- *
69
- * const run = createMonitoredRun<MyStage, MyState>({
70
- * stages: ["plan", "test", "report"],
71
- * deadlineMs: 10 * 60_000,
72
- * snapshotEvery: 25,
73
- * });
74
- *
75
- * init: (loaded) => loaded ? [loaded, []] : [{ run: run.init() }, []],
76
- * update: {
77
- * begin: (s, m) => lift(s, run.start(s.run, m.runId, m.at)),
78
- * advance: (s, m) => lift(s, run.advance(s.run, checkpoint(s), m.result, m.at)),
79
- * progress: (s, m) => lift(s, run.progress(s.run, checkpoint(s), m.at)),
80
- * run_deadline: (s, m) => lift(s, run.onDeadline(s.run, m)),
81
- * boot: (s, m) => lift(s, run.boot(s.run, m.at)),
82
- * },
83
- * subscriptions: (s) => run.subs(s.run),
84
- * subscribe: { deadline: subscribeDeadline },
85
- * interpret: run.handlers({ store: r2 }),
86
- */
1
+ import { b as CmdDef, T as TimerDeps, C as Cmd } from './core-rDbOaJTN.js';
2
+ import { S as SnapshotWriteCmd, a as SnapshotState, b as SnapshotSavedMsg } from './index-CWmsXNdX.js';
3
+ import { D as DeadlineExceeded, a as DeadlineSub } from './index-DaX_P35Q.js';
4
+ import { Q as QueueItem } from './index-CcrKLtse.js';
87
5
 
88
6
  /**
89
7
  * The monitored-run knob. EVERY field is optional:
@@ -263,11 +181,6 @@ type StageResult = {
263
181
  type MonitoredRunCmd<V> = SnapshotWriteCmd<V>;
264
182
  /** The deadline Msg the safety alarm dispatches when the watchdog fires. */
265
183
  type MonitoredRunTimerMsg = DeadlineExceeded;
266
- /** Ports the consumer supplies to `handlers` — just the checkpoint store. */
267
- interface MonitoredRunPorts<V> {
268
- /** Where periodic checkpoints are written (R2 / KV / DO sub-key / Map). */
269
- readonly store: SnapshotStore<V>;
270
- }
271
184
  /**
272
185
  * Build a monitored-run knob from `config`. `Stage` is the consumer's stage
273
186
  * identifier type; `V` is the consumer's checkpoint value type (what
@@ -275,9 +188,19 @@ interface MonitoredRunPorts<V> {
275
188
  *
276
189
  * No `rng` parameter: unlike `resilient-call`, nothing here jitters — the only
277
190
  * external inputs are time (an `at` / `atMs` parameter) and the consumer's
278
- * stage outcomes. The clock is read only inside the snapshot `handlers` port.
191
+ * stage outcomes.
279
192
  */
280
193
  declare function createMonitoredRun<Stage, V = unknown>(config?: MonitoredRunConfig<Stage>): {
194
+ /** The `snapshot_write` Cmd def — list it in `cmds` when checkpointing. */
195
+ checkpoint: CmdDef<"snapshot_write", {
196
+ readonly key: string;
197
+ readonly seq: number;
198
+ readonly at: number;
199
+ readonly payload: V;
200
+ }, undefined, {
201
+ readonly [detail: string]: unknown;
202
+ readonly _tag: "snapshot_write_failed";
203
+ }>;
281
204
  init: () => MonitoredRunState<Stage>;
282
205
  start: (s: MonitoredRunState<Stage>, runId: string, at: number) => readonly [MonitoredRunState<Stage>, readonly MonitoredRunCmd<V>[]];
283
206
  progress: (s: MonitoredRunState<Stage>, payload: V, at: number) => readonly [MonitoredRunState<Stage>, readonly MonitoredRunCmd<V>[]];
@@ -286,9 +209,9 @@ declare function createMonitoredRun<Stage, V = unknown>(config?: MonitoredRunCon
286
209
  advance: (s: MonitoredRunState<Stage>, payload: V, result: StageResult, at: number) => readonly [MonitoredRunState<Stage>, readonly MonitoredRunCmd<V>[]];
287
210
  onDeadline: (s: MonitoredRunState<Stage>, msg: MonitoredRunTimerMsg) => readonly [MonitoredRunState<Stage>, readonly MonitoredRunCmd<V>[]];
288
211
  boot: (s: MonitoredRunState<Stage>, at: number) => readonly [MonitoredRunState<Stage>, readonly MonitoredRunCmd<V>[]];
289
- confirmSnapshot: (s: MonitoredRunState<Stage>, msg: SnapshotSavedMsg) => MonitoredRunState<Stage>;
290
- subs: (s: MonitoredRunState<Stage>) => readonly DeadlineSub[];
291
- handlers: (ports: MonitoredRunPorts<V>) => Interpret<SnapshotSavedMsg | SnapshotFailedMsg | SnapshotLoadedMsg<V> | SnapshotLoadFailedMsg, SnapshotWriteCmd<V> | SnapshotLoadCmd, unknown>;
212
+ confirmSnapshot: (s: MonitoredRunState<Stage>, msg: SnapshotSavedMsg<V>) => MonitoredRunState<Stage>;
213
+ deadlines: (s: MonitoredRunState<Stage>) => readonly DeadlineSub[];
214
+ timer: (s: MonitoredRunState<Stage>) => TimerDeps<MonitoredRunTimerMsg> | null;
292
215
  };
293
216
  /**
294
217
  * Lift a knob result `[slice, cmds]` into a host `[State, cmds]` where the
@@ -300,4 +223,4 @@ declare function liftRun<S extends {
300
223
  run: MonitoredRunState<Stage>;
301
224
  }, Stage, C extends Cmd>(state: S, [slice, cmds]: readonly [MonitoredRunState<Stage>, readonly C[]]): readonly [S, readonly C[]];
302
225
 
303
- export { type EndedRun as E, type MonitoredRunCmd as M, type RunFailure as R, type StageResult as S, type MonitoredRunState as a, type MonitoredRunConfig as b, type MonitoredRunPorts as c, type MonitoredRunTimerMsg as d, createMonitoredRun as e, liftRun as l };
226
+ export { type EndedRun as E, type MonitoredRunCmd as M, type RunFailure as R, type StageResult as S, type MonitoredRunState as a, type MonitoredRunConfig as b, type MonitoredRunTimerMsg as c, createMonitoredRun as d, liftRun as l };
@@ -1,4 +1,4 @@
1
- import { B as BootingRuntime } from './runtime-types-CMF13BBh.js';
1
+ import { B as BootingRuntime } from './runtime-types-B62Ucnxr.js';
2
2
 
3
3
  /**
4
4
  * A recorded run, sufficient to reproduce it via `../trace-replay`.
@@ -0,0 +1,207 @@
1
+ import { c as CmdOf, b as CmdDef, e as SettledOk, f as SettledErr, g as TaggedError, C as Cmd } from './core-rDbOaJTN.js';
2
+
3
+ /**
4
+ * The snapshot knob.
5
+ *
6
+ * `every` is the cadence: a checkpoint is written once `every` units of
7
+ * progress have accumulated since the last one (see `record`). It is the
8
+ * `snapshotEvery` field `monitored-run` threads through to this module.
9
+ *
10
+ * `key` is the store key the checkpoint is written under. A single machine
11
+ * keeps a single rolling checkpoint, so the key is fixed at config time rather
12
+ * than passed per write — the latest checkpoint overwrites the previous one
13
+ * (R2/KV are last-write-wins on a key). Defaults to `"@@snapshot"`, mirroring
14
+ * `doStore`'s `@@state` default-key convention.
15
+ */
16
+ interface SnapshotConfig {
17
+ /**
18
+ * Write a checkpoint once this many progress units have accumulated since the
19
+ * last write. `every: 1` checkpoints on every `record`; a value `<= 0` is
20
+ * treated as `1` (every progress unit triggers a write) — a non-positive
21
+ * cadence has no other sensible meaning, and clamping keeps `record` from
22
+ * never checkpointing on a misconfigured `0`.
23
+ */
24
+ readonly every: number;
25
+ /** Store key the rolling checkpoint is written under. Defaults to `"@@snapshot"`. */
26
+ readonly key?: string;
27
+ }
28
+ /**
29
+ * The snapshot bookkeeping slice. Plain data — JSON-serializable so it rides
30
+ * inside the consumer's `Store<S>` blob and survives DO eviction / reload (the
31
+ * "durable" non-negotiable). It carries NO payload: the thing being
32
+ * checkpointed lives elsewhere in the machine's state; this slice only tracks
33
+ * *when* to checkpoint and *what has been acknowledged durable*.
34
+ *
35
+ * - `sinceLast` — progress units accumulated since the last checkpoint
36
+ * DECISION (reset to 0 the moment `record` decides to write, not when the
37
+ * write lands). The cadence counter.
38
+ * - `seq` — monotonic checkpoint sequence. Bumped each time a write is
39
+ * emitted, so the write Cmd and its later acknowledgement can be matched
40
+ * even if several are in flight. The "version" of the latest emitted
41
+ * checkpoint.
42
+ * - `lastSavedSeq` — the highest `seq` whose write the host has confirmed
43
+ * durable (via `confirm`). `null` until the first confirmed write. The gap
44
+ * `seq - lastSavedSeq` is the "writes emitted but not yet acknowledged"
45
+ * depth — observable for backpressure / health.
46
+ * - `lastSavedAt` — the `at` of the most recent confirmed write (epoch ms),
47
+ * `null` until the first. Carried for observability, never compared inside
48
+ * a verb (time is injected, never read here).
49
+ */
50
+ interface SnapshotState {
51
+ readonly sinceLast: number;
52
+ readonly seq: number;
53
+ readonly lastSavedSeq: number | null;
54
+ readonly lastSavedAt: number | null;
55
+ }
56
+ /**
57
+ * The checkpoint-write Cmd a `record` / `force` decision emits. Plain data
58
+ * (invariant 1 — Cmds are data, not closures): it carries the `payload` to
59
+ * write, the `key` to write it under, the `seq` it represents, and the `at` it
60
+ * was decided.
61
+ *
62
+ * `payload` is `V` — the consumer's serializable checkpoint value (the run
63
+ * state, the cursor, whatever the machine wants restartable). The verb takes it
64
+ * as an argument so the snapshot slice never has to hold a copy of the
65
+ * machine's domain state.
66
+ *
67
+ * `Cmd.define`d (ADR 0014, 0021), minted per `V` by a factory the way
68
+ * `workflowActivityDef<A>()` is, since the payload type is the knob's own
69
+ * parameter. The handler you write puts the payload in your store and returns
70
+ * `ok(undefined)`, or `err({ _tag: "snapshot_write_failed", … })`; the engine
71
+ * mints `snapshot_write_ok` / `snapshot_write_err`.
72
+ */
73
+ declare function snapshotWriteDef<V>(): CmdDef<"snapshot_write", {
74
+ readonly key: string;
75
+ readonly seq: number;
76
+ readonly at: number;
77
+ readonly payload: V;
78
+ }, undefined, {
79
+ readonly [detail: string]: unknown;
80
+ readonly _tag: "snapshot_write_failed";
81
+ }>;
82
+ type SnapshotWriteCmd<V> = CmdOf<ReturnType<typeof snapshotWriteDef<V>>>;
83
+ /**
84
+ * The checkpoint-READ Cmd a `requestLoad` decision emits — the recovery half of
85
+ * the module. Plain data (invariant 1): it carries only the `key` to read. The
86
+ * handler you write reads the store and returns `ok(payload)` — `null` when
87
+ * the store has no checkpoint under `key` — or
88
+ * `err({ _tag: "snapshot_load_failed", … })`.
89
+ *
90
+ * Distinct from `snapshot_write`: a write carries a payload OUT to the store; a
91
+ * load asks the store to hand a payload BACK. The consumer dispatches the
92
+ * triggering Msg once on resume (a `boot` Msg, never `init`'s rehydrate branch —
93
+ * invariant 2), folds the recovered payload into its run slice, then continues.
94
+ */
95
+ declare function snapshotLoadDef<V>(): CmdDef<"snapshot_load", {
96
+ readonly key: string;
97
+ }, V | null, {
98
+ readonly [detail: string]: unknown;
99
+ readonly _tag: "snapshot_load_failed";
100
+ }>;
101
+ type SnapshotLoadCmd<V = unknown> = CmdOf<ReturnType<typeof snapshotLoadDef<V>>>;
102
+ /**
103
+ * The Msg the engine mints when a write lands. Fold it through
104
+ * `confirm(state, msg)` to advance `lastSavedSeq` / `lastSavedAt`. It carries
105
+ * the write Cmd, so `msg.cmd.seq` matches the emitting decision and a late
106
+ * acknowledgement of an older write can never regress a newer confirmed one.
107
+ */
108
+ type SnapshotSavedMsg<V = unknown> = SettledOk<"snapshot_write", SnapshotWriteCmd<V>, undefined>;
109
+ /**
110
+ * The Msg the engine mints when a write fails. Errors are data (never
111
+ * swallowed): the consumer's reducer decides whether a failed checkpoint is
112
+ * fatal, retryable (compose `@demlik/tea/retry-backoff`), or merely logged.
113
+ * `msg.cmd.seq` identifies which checkpoint failed.
114
+ */
115
+ type SnapshotFailedMsg<V = unknown> = SettledErr<"snapshot_write", SnapshotWriteCmd<V>, TaggedError<"snapshot_write_failed">>;
116
+ /**
117
+ * The Msg the engine mints when a read resolves. `value` is the recovered
118
+ * checkpoint, or `null` when the store has no checkpoint under `key` (fresh
119
+ * boot — never checkpointed, or a wiped store). `null` is NOT an error — "no
120
+ * checkpoint yet" is a normal first-run state, distinct from "the read failed"
121
+ * (`snapshot_load_err`).
122
+ */
123
+ type SnapshotLoadedMsg<V> = SettledOk<"snapshot_load", SnapshotLoadCmd<V>, V | null>;
124
+ /**
125
+ * The Msg the engine mints when a read fails. Errors are data: a failed
126
+ * recovery read is a visible signal the consumer's reducer decides on
127
+ * (fatal-abort, retry, or boot-fresh-and-log). Kept apart from a `null` load
128
+ * so "the store has no checkpoint" can never masquerade as "the read failed".
129
+ */
130
+ type SnapshotLoadFailedMsg<V = unknown> = SettledErr<"snapshot_load", SnapshotLoadCmd<V>, TaggedError<"snapshot_load_failed">>;
131
+ /**
132
+ * The bundle `createSnapshot` returns: plain functions plus the two Cmd defs to
133
+ * list in `cmds`. There are no subs: a checkpoint is driven by progress (a
134
+ * `record` call from the consumer's reducer), not by a timer.
135
+ */
136
+ interface SnapshotKnob<V> {
137
+ /** The `snapshot_write` Cmd def — list it in the machine's `cmds`. */
138
+ readonly write: ReturnType<typeof snapshotWriteDef<V>>;
139
+ /** The `snapshot_load` Cmd def — list it in the machine's `cmds`. */
140
+ readonly load: ReturnType<typeof snapshotLoadDef<V>>;
141
+ /** The initial slice — zero progress, no checkpoint emitted or confirmed yet. */
142
+ init(): SnapshotState;
143
+ /**
144
+ * Account one unit of progress. PURE. Increments `sinceLast`; once the
145
+ * accumulated count reaches the configured cadence, DECIDES to checkpoint:
146
+ * resets `sinceLast` to 0, bumps `seq`, and emits a single `snapshot_write`
147
+ * Cmd carrying `payload` + `key` + the new `seq` + `at`. Below the cadence it
148
+ * returns the bumped slice and NO Cmd.
149
+ *
150
+ * `payload` is the checkpoint value to persist (the consumer's domain state);
151
+ * `at` is the caller-stamped time the progress occurred (epoch ms) — injected,
152
+ * never read from the clock here.
153
+ */
154
+ record(state: SnapshotState, payload: V, at: number): readonly [SnapshotState, readonly SnapshotWriteCmd<V>[]];
155
+ /**
156
+ * Force a checkpoint regardless of the cadence counter. PURE. Always bumps
157
+ * `seq`, resets `sinceLast`, and emits the write Cmd. Use on a phase boundary
158
+ * the cadence would otherwise miss — e.g. "the run just finished, checkpoint
159
+ * the terminal state now" — so the last durable checkpoint is the final state,
160
+ * not whatever the modulo happened to land on.
161
+ */
162
+ force(state: SnapshotState, payload: V, at: number): readonly [SnapshotState, readonly SnapshotWriteCmd<V>[]];
163
+ /**
164
+ * Record a confirmed durable write. PURE. Advances `lastSavedSeq` /
165
+ * `lastSavedAt` to the acknowledged write's `seq` / `at`, but only forward:
166
+ * an out-of-order acknowledgement of an OLDER `seq` (a slow write landing
167
+ * after a newer one) is ignored, so the confirmed watermark is monotonic.
168
+ * Fold the `snapshot_write_ok` Msg here.
169
+ *
170
+ * Returns the reducer-cell shape `readonly [SnapshotState, readonly Cmd[]]`
171
+ * (with `Cmd.none` — an ack emits nothing) for uniformity with every sibling
172
+ * knob, so it drops straight into a `snapshot_write_ok` cell.
173
+ */
174
+ confirm(state: SnapshotState, msg: SnapshotSavedMsg<V>): readonly [SnapshotState, readonly Cmd[]];
175
+ /**
176
+ * Resume after a reload. PURE. Resets `sinceLast` to 0 because any
177
+ * un-checkpointed progress accumulated before the crash is moot — recovery
178
+ * resumes from the last DURABLE checkpoint, so the cadence counter starts
179
+ * fresh from there. `seq` / `lastSavedSeq` / `lastSavedAt` are preserved
180
+ * (they describe what is durable, which a reload does not change). Call from
181
+ * a `boot` Msg the host dispatches once after `run(...)`, never from `init`'s
182
+ * rehydrate branch (invariant 2).
183
+ *
184
+ * Returns the reducer-cell shape `readonly [SnapshotState, readonly Cmd[]]`
185
+ * (with `Cmd.none` — a resume emits nothing) so it drops straight into a
186
+ * `snapshot_load_ok` cell.
187
+ */
188
+ boot(state: SnapshotState): readonly [SnapshotState, readonly Cmd[]];
189
+ /**
190
+ * Ask the store for the durable checkpoint. PURE. Emits a single
191
+ * `snapshot_load` Cmd carrying the configured `key`; returns the slice
192
+ * UNCHANGED (a read decides nothing about the cadence bookkeeping — only the
193
+ * later `snapshot_load_ok` fold, via `boot`, touches the slice). This is the
194
+ * entry point of the recovery loop: the consumer dispatches a `boot` Msg once
195
+ * after `run(...)` and folds `requestLoad` there.
196
+ */
197
+ requestLoad(state: SnapshotState): readonly [SnapshotState, readonly SnapshotLoadCmd<V>[]];
198
+ }
199
+ /**
200
+ * Create a snapshot knob from a `SnapshotConfig`. The returned bundle is spliced
201
+ * into a consumer machine: `init()` seeds the slice, `record` / `force` are
202
+ * folded in reducer cells, `confirm` / `boot` handle the acknowledgement +
203
+ * resume Msgs, and `write` / `load` are the Cmd defs whose handlers you write.
204
+ */
205
+ declare function createSnapshot<V>(config: SnapshotConfig): SnapshotKnob<V>;
206
+
207
+ export { type SnapshotWriteCmd as S, type SnapshotState as a, type SnapshotSavedMsg as b, type SnapshotConfig as c, type SnapshotFailedMsg as d, type SnapshotKnob as e, type SnapshotLoadCmd as f, type SnapshotLoadFailedMsg as g, type SnapshotLoadedMsg as h, createSnapshot as i, snapshotWriteDef as j, snapshotLoadDef as s };
@@ -1,6 +1,5 @@
1
- import { C as Cmd } from './core-DnzqWy6u.js';
2
- import { S as SubscribeHandler } from './types-BseNPIhr.js';
3
- import { D as DeadlineExceeded, a as DeadlineSub } from './index-HSYgG2Yt.js';
1
+ import { C as Cmd, T as TimerDeps, d as Subscribe } from './core-rDbOaJTN.js';
2
+ import { D as DeadlineExceeded, a as DeadlineSub, b as DeadlinesSub } from './index-DaX_P35Q.js';
4
3
 
5
4
  /**
6
5
  * internal/flow/batch-window — coalesce a stream of items into size- or
@@ -8,14 +7,13 @@ import { D as DeadlineExceeded, a as DeadlineSub } from './index-HSYgG2Yt.js';
8
7
  *
9
8
  * What this module actually DELEGATES to, vs. what it merely RE-EXPORTS:
10
9
  *
11
- * - `../deadline` — REAL delegation (the only one). The window timer IS a
12
- * `deadline` Sub: `subsFor` returns `deadlineSub` keyed on the window's
13
- * identity, the subscribe cell is `subscribeDeadline` verbatim, and the
14
- * expiry Msg is `deadlineExceeded`. Nothing about the timer is redrawn here.
15
- * "Fire at an absolute instant, even across a rehydrate" is exactly
16
- * `deadline`'s absolute-target lifecycle: a late subscribe (post-`Store`
17
- * rehydrate) recomputes the remaining delay from the current clock and still
18
- * fires at the correct moment.
10
+ * - `../deadline` — REAL delegation (the only one). The window timer's Msg
11
+ * is `deadlineExceeded`, keyed on the window's identity. `timerFor` arms it
12
+ * through the engine's built-in `timer` Sub: `maxMs` counted from the
13
+ * transition that opened the window, so a machine needs no runner. The
14
+ * absolute-instant form is still here too — `subsFor` lists the same
15
+ * deadline for `deadlinesSub` + `subscribeDeadline`, which re-arms for the
16
+ * REMAINING time after a `Store` rehydrate rather than a fresh `maxMs`.
19
17
  * - `../work-queue` — TYPE re-export only, NOT a sink this module calls. A
20
18
  * flush emits a Cmd; the CONSUMER's interpret handler is what enqueues onto a
21
19
  * `createQueue(store)`. This module never touches queue status — it has no
@@ -48,10 +46,10 @@ import { D as DeadlineExceeded, a as DeadlineSub } from './index-HSYgG2Yt.js';
48
46
  * // Model: { batch: BatchWindow<LogLine>, ... }
49
47
  * // init: (loaded) => [loaded ?? { batch: bw.init(), ... }, []]
50
48
  * // update cells:
51
- * // LogArrived: (s, m) => mapBatch(s, bw.add(s.batch, m.line, m.at))
52
- * // WindowFired: (s, m) => mapBatch(s, bw.onWindow(s.batch, m.atMs))
53
- * // subscriptions: (s) => bw.subs(s.batch)
54
- * // subscribe: { ...bw.handlers() }
49
+ * // LogArrived: (s, m) => mapBatch(s, bw.add(s.batch, m.line, m.at))
50
+ * // deadline_exceeded: (s, m) => mapBatch(s, bw.onWindow(s.batch, m.atMs))
51
+ * // subs: [{ type: "timer", deps: (s: Model) => bw.timer(s.batch) }]
52
+ * // at run: run(machine, { interpret }) // `timer` is built in
55
53
  *
56
54
  * where `mapBatch(s, [batch, cmds]) => [{ ...s, batch }, cmds]` lifts the slice
57
55
  * transition into the consumer's Model. The `FlushBatch` Cmd's interpret handler
@@ -118,26 +116,26 @@ interface BatchWindow<I> {
118
116
  /** The starting slice: closed window, empty buffer. */
119
117
  declare function initBatchWindow<I>(): BatchWindow<I>;
120
118
  /**
121
- * The Sub a batch window's open timer produces: it IS `../deadline`'s
119
+ * The deadline a batch window's open timer lists: it IS `../deadline`'s
122
120
  * `DeadlineSub`, not a re-tagged copy. `atMs` is the absolute flush-by instant
123
121
  * (`openedAt + maxMs`). Aliasing the deadline type (rather than redeclaring an
124
122
  * identical shape) is what lets `subsFor` return `deadlineSub(...)` with no
125
123
  * cast — the value's static type already satisfies this name. Consumers running
126
- * several windows route each one by the Sub's `id`, not by a distinct type.
124
+ * several windows route each one by the deadline's `id`, not by a distinct type.
127
125
  */
128
126
  type BatchWindowSub = DeadlineSub;
129
127
  /** The Msg a closed-by-time window dispatches. Alias of `deadline`'s Msg. */
130
128
  type BatchWindowExpired = DeadlineExceeded;
131
129
  /**
132
130
  * Construct the window-expired Msg for the window identified by `id`, flushing
133
- * by `atMs`. Re-exported alias of `deadlineExceeded` so the subscribe cell and
131
+ * by `atMs`. Re-exported alias of `deadlineExceeded` so the runner and
134
132
  * the consumer's reducer share one constructor rather than two literals that
135
133
  * can drift. The consumer handles it in a reducer cell by calling `onWindow`.
136
134
  */
137
135
  declare function batchWindowExpired(id: string, atMs: number): BatchWindowExpired;
138
136
  /**
139
137
  * The bound knob returned by `createBatchWindow`. `init` + the two pure verbs +
140
- * `subs` + `handlers`, all closing over one `BatchWindowConfig`. The verbs
138
+ * `timer` + `subs`, all closing over one `BatchWindowConfig`. The verbs
141
139
  * return `readonly [BatchWindow<I>, readonly C[]]`: the next slice and the Cmds
142
140
  * to emit (one `flush` Cmd when a window closes, none otherwise).
143
141
  */
@@ -154,18 +152,16 @@ interface BatchWindowKnob<I, C extends Cmd> {
154
152
  */
155
153
  onWindow(state: BatchWindow<I>, at: number): readonly [BatchWindow<I>, readonly C[]];
156
154
  /**
157
- * The window timer Sub, armed only while a window is open. See `subsFor`.
158
- * `id` keys the deadline so several windows on one machine route distinctly.
155
+ * The built-in `timer` Sub's deps while a window is open, `null` while it is
156
+ * closed. See `timerFor`. `id` keys the Msg so several windows on one
157
+ * machine route distinctly.
159
158
  */
160
- subs(state: BatchWindow<I>, id?: string): readonly BatchWindowSub[];
159
+ timer(state: BatchWindow<I>, id?: string): TimerDeps<BatchWindowExpired> | null;
161
160
  /**
162
- * The `subscribe` cells this knob splices into `machine.subscribe`. One cell,
163
- * keyed `"deadline"`, delegating to `../deadline`'s subscribe handler. Spread
164
- * into the consumer's subscribe map: `subscribe: { ...bw.handlers() }`.
161
+ * The window timer as an absolute deadline, listed only while a window is
162
+ * open — for `deadlinesSub` + `subscribeBatchWindow`. See `subsFor`.
165
163
  */
166
- handlers(): {
167
- deadline: SubscribeHandler<BatchWindowSub, BatchWindowExpired, unknown>;
168
- };
164
+ subs(state: BatchWindow<I>, id?: string): readonly BatchWindowSub[];
169
165
  }
170
166
  /**
171
167
  * Buffer `item` and decide whether the size trigger fires. PURE.
@@ -215,18 +211,18 @@ declare function addItem<I, C extends Cmd>(config: BatchWindowConfig<I, C>, stat
215
211
  */
216
212
  declare function onWindow<I, C extends Cmd>(config: BatchWindowConfig<I, C>, state: BatchWindow<I>, _at: number): readonly [BatchWindow<I>, readonly C[]];
217
213
  /**
218
- * The window timer Sub, derived from the slice. PURE.
214
+ * The window timer deadline, derived from the slice. PURE.
219
215
  *
220
- * Returns the single `deadline` Sub targeting `openedAt + maxMs` while a window
221
- * is open (buffer non-empty), or `[]` while it is closed. The substrate's
222
- * reconcile pass arms the timer when the array gains the Sub and disarms it
223
- * (clearing the pending `setTimeout`) when the array loses it — so a size-flush
224
- * that empties the buffer auto-cancels the now-irrelevant time trigger on the
225
- * next transition.
216
+ * Returns the single deadline targeting `openedAt + maxMs` while a window is
217
+ * open (buffer non-empty), or `[]` while it is closed. Fed through
218
+ * `deadlinesSub`, the engine arms the timer when the list gains the deadline
219
+ * and disarms it (clearing the pending `setTimeout`) when the list loses it —
220
+ * so a size-flush that empties the buffer auto-cancels the now-irrelevant time
221
+ * trigger on the next transition.
226
222
  *
227
223
  * `id` defaults to `"batch-window"`; pass a distinct id per window when a
228
- * machine runs several so the dispatched `BatchWindowExpired` Msg (and its
229
- * reconcile identity) routes to the right one.
224
+ * machine runs several so the dispatched `BatchWindowExpired` Msg routes to the
225
+ * right one.
230
226
  *
231
227
  * @param config the knob (maxMs)
232
228
  * @param state the current slice
@@ -235,22 +231,38 @@ declare function onWindow<I, C extends Cmd>(config: BatchWindowConfig<I, C>, sta
235
231
  */
236
232
  declare function subsFor<I, C extends Cmd>(config: BatchWindowConfig<I, C>, state: BatchWindow<I>, id?: string): readonly BatchWindowSub[];
237
233
  /**
238
- * The `subscribe["deadline"]` cell for a batch window's timer — the exact
239
- * `../deadline` handler. Arms a one-shot timer for `max(0, atMs - now)` and
240
- * dispatches `batchWindowExpired(...)`; returns a cleanup that clears it. The
241
- * consumer assigns it via the knob's `handlers()`.
234
+ * The built-in `timer` Sub's deps for a batch window. PURE.
235
+ *
236
+ * While a window is open it counts `maxMs` down from the transition that
237
+ * opened it — the deps are fixed for the window's life (`openedAt` never moves
238
+ * while items append), so the engine starts the countdown exactly once — and
239
+ * fires `batchWindowExpired(id, openedAt + maxMs)`. A closed window is `null`,
240
+ * so a size-flush that empties the buffer cancels the countdown on the next
241
+ * transition.
242
+ *
243
+ * Relative by construction: a process that rehydrates an open window counts a
244
+ * fresh `maxMs`. Reach for `subsFor` + `subscribeBatchWindow` when the flush
245
+ * must land at the original absolute instant.
246
+ */
247
+ declare function timerFor<I, C extends Cmd>(config: BatchWindowConfig<I, C>, state: BatchWindow<I>, id?: string): TimerDeps<BatchWindowExpired> | null;
248
+ /**
249
+ * The `deadline` runner for a batch window's absolute timer — the exact
250
+ * `../deadline` runner. Arms a one-shot timer per listed deadline for
251
+ * `max(0, atMs - now)` and dispatches `batchWindowExpired(...)`; returns a
252
+ * cleanup that clears them. Hand it to `run` as `subscribe.deadline` when the
253
+ * machine declares `deadlinesSub((s) => bw.subs(s.batch))`.
242
254
  */
243
- declare const subscribeBatchWindow: SubscribeHandler<BatchWindowSub, BatchWindowExpired, unknown>;
255
+ declare const subscribeBatchWindow: Subscribe<BatchWindowExpired, DeadlinesSub, unknown>["deadline"];
244
256
  /**
245
257
  * Build a batch window knob from a config. Combinator form (the default L2
246
258
  * ergonomic): hand it the config, splice the ~4 returned hooks into your
247
259
  * machine. The pure verbs (`add` / `onWindow`) close over the config so the
248
- * consumer's reducer cells stay a uniform `(state, ...args)` shape; `subs` /
249
- * `handlers` pre-wire the window timer.
260
+ * consumer's reducer cells stay a uniform `(state, ...args)` shape; `timer`
261
+ * arms the window timer.
250
262
  *
251
263
  * @typeParam I the item type buffered into each batch
252
264
  * @typeParam C the Cmd type `config.flush` returns
253
265
  */
254
266
  declare function createBatchWindow<I, C extends Cmd>(config: BatchWindowConfig<I, C>): BatchWindowKnob<I, C>;
255
267
 
256
- export { type BatchWindow as B, type BatchWindowSub as a, type BatchWindowExpired as b, type BatchWindowConfig as c, type BatchWindowKnob as d, addItem as e, batchWindowExpired as f, createBatchWindow as g, subscribeBatchWindow as h, initBatchWindow as i, onWindow as o, subsFor as s };
268
+ export { type BatchWindow as B, type BatchWindowSub as a, type BatchWindowExpired as b, type BatchWindowConfig as c, type BatchWindowKnob as d, addItem as e, batchWindowExpired as f, createBatchWindow as g, subscribeBatchWindow as h, initBatchWindow as i, onWindow as o, subsFor as s, timerFor as t };
@@ -1,4 +1,4 @@
1
- import { S as Store } from './runtime-types-CMF13BBh.js';
1
+ import { S as Store } from './runtime-types-B62Ucnxr.js';
2
2
 
3
3
  /**
4
4
  * internal/work-queue — substrate-agnostic work-queue lifecycle on `Store<S>`.