@demlik/tea 0.16.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 (84) hide show
  1. package/dist/agent/index.d.ts +13 -13
  2. package/dist/agent/index.js +9 -9
  3. package/dist/{chunk-CIHSHLQX.js → chunk-4NTCPTNQ.js} +3 -3
  4. package/dist/{chunk-CIHSHLQX.js.map → chunk-4NTCPTNQ.js.map} +1 -1
  5. package/dist/{chunk-7MGXQZPW.js → chunk-4PXNZ5UY.js} +4 -4
  6. package/dist/{chunk-7MGXQZPW.js.map → chunk-4PXNZ5UY.js.map} +1 -1
  7. package/dist/{chunk-6NG4V5SB.js → chunk-6XBEYZME.js} +5 -5
  8. package/dist/{chunk-6NG4V5SB.js.map → chunk-6XBEYZME.js.map} +1 -1
  9. package/dist/{chunk-GOX2CYIM.js → chunk-C4U5D5HP.js} +3 -3
  10. package/dist/{chunk-GOX2CYIM.js.map → chunk-C4U5D5HP.js.map} +1 -1
  11. package/dist/{chunk-MVZS5FDM.js → chunk-DFUEAA6L.js} +3 -3
  12. package/dist/{chunk-MVZS5FDM.js.map → chunk-DFUEAA6L.js.map} +1 -1
  13. package/dist/{chunk-IVJP3GKJ.js → chunk-GWWCCSDH.js} +4 -4
  14. package/dist/{chunk-IVJP3GKJ.js.map → chunk-GWWCCSDH.js.map} +1 -1
  15. package/dist/{chunk-CH5KTOEZ.js → chunk-K4ETBNKS.js} +32 -9
  16. package/dist/chunk-K4ETBNKS.js.map +1 -0
  17. package/dist/{chunk-5XU6ZJO2.js → chunk-KWNCM6XM.js} +19 -13
  18. package/dist/chunk-KWNCM6XM.js.map +1 -0
  19. package/dist/{chunk-BCTEOVOU.js → chunk-LYVOGOBC.js} +3 -3
  20. package/dist/{chunk-BCTEOVOU.js.map → chunk-LYVOGOBC.js.map} +1 -1
  21. package/dist/{chunk-MYNLY3HP.js → chunk-OPH6Y4UT.js} +3 -3
  22. package/dist/{chunk-MYNLY3HP.js.map → chunk-OPH6Y4UT.js.map} +1 -1
  23. package/dist/{chunk-NSIAORRY.js → chunk-OYR7ENKU.js} +3 -3
  24. package/dist/{chunk-NSIAORRY.js.map → chunk-OYR7ENKU.js.map} +1 -1
  25. package/dist/{chunk-WT5PBPLB.js → chunk-QWIPH4YH.js} +4 -4
  26. package/dist/{chunk-WT5PBPLB.js.map → chunk-QWIPH4YH.js.map} +1 -1
  27. package/dist/{chunk-EHUDXAKC.js → chunk-XBZQT2TD.js} +7 -7
  28. package/dist/chunk-XBZQT2TD.js.map +1 -0
  29. package/dist/{core-BbgtiXdg.d.ts → core-rDbOaJTN.d.ts} +7 -3
  30. package/dist/do/index.d.ts +12 -12
  31. package/dist/do/index.js +10 -10
  32. package/dist/{durable-effects-7MTK_jnj.d.ts → durable-effects-CNaw97Be.d.ts} +1 -1
  33. package/dist/effect/index.d.ts +2 -2
  34. package/dist/effect/index.js +2 -2
  35. package/dist/extension/index.d.ts +3 -3
  36. package/dist/extension/index.js +2 -2
  37. package/dist/flow/index.d.ts +13 -13
  38. package/dist/flow/index.js +10 -10
  39. package/dist/idempotency/index.d.ts +3 -3
  40. package/dist/idempotency/index.js +3 -3
  41. package/dist/{index-Bz5Rh9Ga.d.ts → index-BOrsbdAf.d.ts} +4 -4
  42. package/dist/{index-DU6JpQ8G.d.ts → index-B_BxplWi.d.ts} +1 -1
  43. package/dist/{index-CjFDUBeq.d.ts → index-CWmsXNdX.d.ts} +1 -1
  44. package/dist/{index-_dOR3xqA.d.ts → index-Cberb5Rr.d.ts} +2 -2
  45. package/dist/{index-7vV8xmsD.d.ts → index-CcrKLtse.d.ts} +1 -1
  46. package/dist/{index-CkFYA9Y6.d.ts → index-Cx0F2M34.d.ts} +2 -2
  47. package/dist/{index-Xufl55W8.d.ts → index-DaX_P35Q.d.ts} +2 -2
  48. package/dist/{index-Cou86-GX.d.ts → index-q1PoukOZ.d.ts} +2 -2
  49. package/dist/index.d.ts +5 -5
  50. package/dist/index.js +2 -2
  51. package/dist/jev/index.d.ts +8 -8
  52. package/dist/jev/index.js +5 -5
  53. package/dist/{machine-BQzTV8On.d.ts → machine-BcfCFMYF.d.ts} +7 -7
  54. package/dist/machine-viz/index.d.ts +1 -1
  55. package/dist/machine-viz/index.js +2 -2
  56. package/dist/mem/index.d.ts +2 -2
  57. package/dist/mem/index.js +2 -2
  58. package/dist/node/index.d.ts +2 -2
  59. package/dist/node/index.js +2 -2
  60. package/dist/paginate/index.d.ts +4 -4
  61. package/dist/paginate/index.js +5 -5
  62. package/dist/parity/index.d.ts +3 -3
  63. package/dist/parity/index.js +3 -3
  64. package/dist/pbt/index.d.ts +1 -1
  65. package/dist/pbt/index.js +2 -2
  66. package/dist/persistence/index.d.ts +9 -10
  67. package/dist/persistence/index.js +4 -4
  68. package/dist/promise/index.d.ts +2 -2
  69. package/dist/promise/index.js +3 -3
  70. package/dist/react/index.d.ts +2 -2
  71. package/dist/resilience/index.d.ts +6 -6
  72. package/dist/resilience/index.js +5 -5
  73. package/dist/{runtime-types-CiVpC0HN.d.ts → runtime-types-B62Ucnxr.d.ts} +2 -2
  74. package/dist/testing/index.d.ts +22 -108
  75. package/dist/testing/index.js +27 -177
  76. package/dist/testing/index.js.map +1 -1
  77. package/dist/timing/index.d.ts +4 -4
  78. package/dist/timing/index.js +4 -4
  79. package/dist/{types-LxZxGYda.d.ts → types-DPm5YCDQ.d.ts} +1 -1
  80. package/dist/work-queue/index.d.ts +4 -4
  81. package/package.json +3 -3
  82. package/dist/chunk-5XU6ZJO2.js.map +0 -1
  83. package/dist/chunk-CH5KTOEZ.js.map +0 -1
  84. package/dist/chunk-EHUDXAKC.js.map +0 -1
@@ -1,8 +1,8 @@
1
- import { T as Trace } from '../index-DU6JpQ8G.js';
2
- export { B as BreadcrumbsOptions, a as Recorder, R as RecorderOptions, b as TraceAttachment, c as TraceBreadcrumb, d as breadcrumbsFromTrace, p as parseJSONL, r as recorder, t as traceAttachment } from '../index-DU6JpQ8G.js';
3
- export { c as SnapshotConfig, d as SnapshotFailedMsg, e as SnapshotKnob, f as SnapshotLoadCmd, g as SnapshotLoadFailedMsg, h as SnapshotLoadedMsg, b as SnapshotSavedMsg, a as SnapshotState, S as SnapshotWriteCmd, i as createSnapshot, s as snapshotLoadDef, j as snapshotWriteDef } from '../index-CjFDUBeq.js';
4
- import { C as Cmd, S as Sub, M as Machine } from '../core-BbgtiXdg.js';
5
- import '../runtime-types-CiVpC0HN.js';
1
+ import { T as Trace } from '../index-B_BxplWi.js';
2
+ export { B as BreadcrumbsOptions, a as Recorder, R as RecorderOptions, b as TraceAttachment, c as TraceBreadcrumb, d as breadcrumbsFromTrace, p as parseJSONL, r as recorder, t as traceAttachment } from '../index-B_BxplWi.js';
3
+ export { c as SnapshotConfig, d as SnapshotFailedMsg, e as SnapshotKnob, f as SnapshotLoadCmd, g as SnapshotLoadFailedMsg, h as SnapshotLoadedMsg, b as SnapshotSavedMsg, a as SnapshotState, S as SnapshotWriteCmd, i as createSnapshot, s as snapshotLoadDef, j as snapshotWriteDef } from '../index-CWmsXNdX.js';
4
+ import { C as Cmd, S as Sub, M as Machine } from '../core-rDbOaJTN.js';
5
+ import '../runtime-types-B62Ucnxr.js';
6
6
  import '@standard-schema/spec';
7
7
 
8
8
  /**
@@ -55,12 +55,11 @@ declare function replayTrace<S, M extends {
55
55
  /**
56
56
  * Order-insensitive structural deep-equality — the comparator the
57
57
  * record/replay lane owns, exposed so consumers (e.g. `@demlik/tea/parity`'s
58
- * `parityEqual`) reuse it rather than adding a fourth deep-compare. It is one
59
- * of three structural walkers in the package, divergent on purpose:
58
+ * `parityEqual`) reuse it rather than adding a third deep-compare. It is one
59
+ * of two structural walkers in the package, divergent on purpose:
60
60
  * this `deepEqual` returns a boolean verdict (order-insensitive, for
61
- * replay/parity equality), `devtools`'s `diffState` returns a change list (for
62
- * a human-readable diff view), and `testing`'s `__deepEqual` is the assertion
63
- * helpers' internal compare — same shape, three jobs, not one to collapse.
61
+ * replay/parity equality), and `devtools`'s `diffState` returns a change list
62
+ * (for a human-readable diff view) — same shape, two jobs, not one to collapse.
64
63
  * `true` iff `a` and `b` are structurally equal under {@link firstDivergence}'s
65
64
  * walk (object keys compared order-insensitively, arrays index-by-index).
66
65
  */
@@ -1,8 +1,8 @@
1
- export { breadcrumbsFromTrace, deepEqual, parseJSONL, recorder, replayTrace, traceAttachment } from '../chunk-BCTEOVOU.js';
2
- export { createSnapshot, snapshotLoadDef, snapshotWriteDef } from '../chunk-CIHSHLQX.js';
1
+ export { breadcrumbsFromTrace, deepEqual, parseJSONL, recorder, replayTrace, traceAttachment } from '../chunk-LYVOGOBC.js';
2
+ export { createSnapshot, snapshotLoadDef, snapshotWriteDef } from '../chunk-4NTCPTNQ.js';
3
3
  import '../chunk-4LPY67E4.js';
4
- import '../chunk-GOX2CYIM.js';
5
- import '../chunk-CH5KTOEZ.js';
4
+ import '../chunk-C4U5D5HP.js';
5
+ import '../chunk-K4ETBNKS.js';
6
6
  import '../chunk-HWVW4AXC.js';
7
7
  //# sourceMappingURL=index.js.map
8
8
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
- import { C as Cmd, S as Sub, M as Machine, R as RunHandlers } from '../core-BbgtiXdg.js';
2
- import { B as BootingRuntime, C as CtxArg, S as Store, O as OnError, a as Supervision, T as TelemetrySink } from '../runtime-types-CiVpC0HN.js';
1
+ import { C as Cmd, S as Sub, M as Machine, R as RunHandlers } from '../core-rDbOaJTN.js';
2
+ import { B as BootingRuntime, C as CtxArg, S as Store, O as OnError, a as Supervision, T as TelemetrySink } from '../runtime-types-B62Ucnxr.js';
3
3
  import '@standard-schema/spec';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
- export { driveToDone, run } from '../chunk-WT5PBPLB.js';
2
- import '../chunk-5XU6ZJO2.js';
3
- import '../chunk-CH5KTOEZ.js';
1
+ export { driveToDone, run } from '../chunk-QWIPH4YH.js';
2
+ import '../chunk-KWNCM6XM.js';
3
+ import '../chunk-K4ETBNKS.js';
4
4
  //# sourceMappingURL=index.js.map
5
5
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
- import { E as EngineRun, S as Store, b as BootedRunHandle } from '../runtime-types-CiVpC0HN.js';
2
- import { C as Cmd, S as Sub, R as RunHandlers, M as Machine } from '../core-BbgtiXdg.js';
1
+ import { E as EngineRun, S as Store, b as BootedRunHandle } from '../runtime-types-B62Ucnxr.js';
2
+ import { C as Cmd, S as Sub, R as RunHandlers, M as Machine } from '../core-rDbOaJTN.js';
3
3
  import '@standard-schema/spec';
4
4
 
5
5
  /**
@@ -1,12 +1,12 @@
1
- import { c as CmdOf, b as CmdDef, f as SettledErr, g as TaggedError, e as SettledOk, T as TimerDeps, C as Cmd } from '../core-BbgtiXdg.js';
1
+ import { c as CmdOf, b as CmdDef, f as SettledErr, g as TaggedError, e as SettledOk, T as TimerDeps, C as Cmd } from '../core-rDbOaJTN.js';
2
2
  import { M as MsgType } from '../protocol-ClRZBhHQ.js';
3
- import { a as DeadlineSub } from '../index-Xufl55W8.js';
4
- export { A as ArmTimer, g as CacheEntry, f as CacheEvictMsg, h as CacheEvictionDeps, C as CacheEvictionSub, D as DeadlineExceeded, i as DeadlineMsgType, j as DeadlineOpts, b as DeadlinesSub, T as TtlCache, k as cacheEvictMsg, l as cacheEvictionSub, m as cacheEvictionSubscribe, d as deadlineExceeded, n as deadlineMsgType, c as deadlineSub, o as deadlines, e as deadlinesSub, p as evictExpired, q as get, r as has, t as initCache, u as nextTimer, v as remove, w as set, x as setTimeoutArmTimer, s as subscribeDeadline, y as subscribeWith } from '../index-Xufl55W8.js';
5
- import { c as ResilientConfig, a as ResilientState, R as RunCmd, S as SucceedMsg, F as FailMsg, b as ResilientTimerMsg } from '../index-Cou86-GX.js';
6
- export { C as CacheConfig, d as CallBudget, e as CallPhase, f as CircuitConfig, g as CircuitPolicy, h as CircuitState, D as DEFAULT_RESILIENT_NAME, i as DeadlineExceededError, j as DeadlineNameOf, k as DefaultResilientName, l as RateLimitConfig, m as ResilientCallDeadlineConfig, n as ResilientDeadlineType, o as ResilientErrType, p as ResilientOkType, q as ResilientRunType, r as RunCmdDef, s as RunErr, t as SettleMsg, u as SettleOutcome, v as SettleResult, w as SlidingWindow, T as TokenBucket, x as canPass, y as createResilientCall, z as defaultCircuitPolicy, A as initBucket, B as initCircuit, E as initWindow, G as liftResilience, H as onFailure, I as onSuccess, J as record, K as refill, L as remaining, M as runCmdDef, N as tryConsume } from '../index-Cou86-GX.js';
3
+ import { a as DeadlineSub } from '../index-DaX_P35Q.js';
4
+ export { A as ArmTimer, g as CacheEntry, f as CacheEvictMsg, h as CacheEvictionDeps, C as CacheEvictionSub, D as DeadlineExceeded, i as DeadlineMsgType, j as DeadlineOpts, b as DeadlinesSub, T as TtlCache, k as cacheEvictMsg, l as cacheEvictionSub, m as cacheEvictionSubscribe, d as deadlineExceeded, n as deadlineMsgType, c as deadlineSub, o as deadlines, e as deadlinesSub, p as evictExpired, q as get, r as has, t as initCache, u as nextTimer, v as remove, w as set, x as setTimeoutArmTimer, s as subscribeDeadline, y as subscribeWith } from '../index-DaX_P35Q.js';
5
+ import { c as ResilientConfig, a as ResilientState, R as RunCmd, S as SucceedMsg, F as FailMsg, b as ResilientTimerMsg } from '../index-q1PoukOZ.js';
6
+ export { C as CacheConfig, d as CallBudget, e as CallPhase, f as CircuitConfig, g as CircuitPolicy, h as CircuitState, D as DEFAULT_RESILIENT_NAME, i as DeadlineExceededError, j as DeadlineNameOf, k as DefaultResilientName, l as RateLimitConfig, m as ResilientCallDeadlineConfig, n as ResilientDeadlineType, o as ResilientErrType, p as ResilientOkType, q as ResilientRunType, r as RunCmdDef, s as RunErr, t as SettleMsg, u as SettleOutcome, v as SettleResult, w as SlidingWindow, T as TokenBucket, x as canPass, y as createResilientCall, z as defaultCircuitPolicy, A as initBucket, B as initCircuit, E as initWindow, G as liftResilience, H as onFailure, I as onSuccess, J as record, K as refill, L as remaining, M as runCmdDef, N as tryConsume } from '../index-q1PoukOZ.js';
7
7
  import { Rng, RetryPolicy } from '../retry-backoff/index.js';
8
8
  import '@standard-schema/spec';
9
- import '../types-LxZxGYda.js';
9
+ import '../types-DPm5YCDQ.js';
10
10
 
11
11
  /**
12
12
  * A minted credential: the opaque `value` to send on the wire, and the absolute
@@ -1,10 +1,10 @@
1
- import { createResilientCall } from '../chunk-6NG4V5SB.js';
2
- export { DEFAULT_RESILIENT_NAME, canPass, createResilientCall, defaultCircuitPolicy, initBucket, initCircuit, initWindow, liftResilience, onFailure, onSuccess, record, refill, remaining, runCmdDef, tryConsume } from '../chunk-6NG4V5SB.js';
1
+ import { createResilientCall } from '../chunk-6XBEYZME.js';
2
+ export { DEFAULT_RESILIENT_NAME, canPass, createResilientCall, defaultCircuitPolicy, initBucket, initCircuit, initWindow, liftResilience, onFailure, onSuccess, record, refill, remaining, runCmdDef, tryConsume } from '../chunk-6XBEYZME.js';
3
3
  import { defaultRng, initRetry, recordFailure, shouldRetry, nextDelayMs } from '../chunk-VBDU4JL6.js';
4
4
  import { unchecked } from '../chunk-4LPY67E4.js';
5
- export { cacheEvictMsg, cacheEvictionSub, cacheEvictionSubscribe, deadlineExceeded, deadlineMsgType, deadlineSub, deadlines, deadlinesSub, evictExpired, get, has, initCache, nextTimer, remove, set, setTimeoutArmTimer, subscribeDeadline, subscribeWith } from '../chunk-IVJP3GKJ.js';
6
- import '../chunk-GOX2CYIM.js';
7
- import { Cmd, without } from '../chunk-CH5KTOEZ.js';
5
+ export { cacheEvictMsg, cacheEvictionSub, cacheEvictionSubscribe, deadlineExceeded, deadlineMsgType, deadlineSub, deadlines, deadlinesSub, evictExpired, get, has, initCache, nextTimer, remove, set, setTimeoutArmTimer, subscribeDeadline, subscribeWith } from '../chunk-GWWCCSDH.js';
6
+ import '../chunk-C4U5D5HP.js';
7
+ import { Cmd, without } from '../chunk-K4ETBNKS.js';
8
8
 
9
9
  // src/internal/resilience/token-refresh/index.ts
10
10
  function initTokenRefresh() {
@@ -1,4 +1,4 @@
1
- import { C as Cmd, S as Sub, M as Machine, R as RunHandlers, P as Port, N as NoCellError, i as Reducer, A as AnyCmdDef, j as Settled, c as CmdOf, k as Transitions, a as BuiltinSub, U as UpdateForm, l as Outcome, I as InterpretDetached, m as PortEmitter } from './core-BbgtiXdg.js';
1
+ import { C as Cmd, S as Sub, M as Machine, R as RunHandlers, P as Port, N as NoCellError, i as Reducer, A as AnyCmdDef, j as Settled, c as CmdOf, k as Transitions, a as BuiltinSub, U as UpdateForm, l as Outcome, I as InterpretDetached, H as HandlerCtx } from './core-rDbOaJTN.js';
2
2
 
3
3
  /**
4
4
  * @demlik/tea runtime interface surface + pure helpers — the public types,
@@ -683,7 +683,7 @@ declare function replay<S, M extends {
683
683
  };
684
684
  declare function wrapDetached<C extends Cmd, M extends {
685
685
  type: string;
686
- }, Allowed extends M, Ctx>(handler: InterpretDetached<C, Allowed, Ctx>): (cmd: C, ctx: Ctx & PortEmitter, dispatch?: (msg: M) => void) => Promise<void>;
686
+ }, Allowed extends M, Ctx>(handler: InterpretDetached<C, Allowed, Ctx>): (cmd: C, ctx: HandlerCtx<Ctx>, dispatch?: (msg: M) => void) => Promise<void>;
687
687
  /**
688
688
  * `applyCell`, with "no handler for this Msg" moved into the return type
689
689
  * instead of a throw.
@@ -1,112 +1,7 @@
1
- import { C as Cmd, S as Sub, M as Machine, a as BuiltinSub, p as Interpret } from '../core-BbgtiXdg.js';
2
- import { C as CtxArg, R as Runtime } from '../runtime-types-CiVpC0HN.js';
1
+ import { C as Cmd, S as Sub, M as Machine, a as BuiltinSub, o as Interpret } from '../core-rDbOaJTN.js';
2
+ import { C as CtxArg, R as Runtime } from '../runtime-types-B62Ucnxr.js';
3
3
  import '@standard-schema/spec';
4
4
 
5
- /**
6
- * The composed Model shape every `withX` wrapper produces: the base machine's
7
- * state nested under `base`, and the wrapper's own NAMED, serializable slice
8
- * under a single `$`-prefixed key. This helper does not care WHICH `$`-key the
9
- * wrapper uses — it discovers it structurally (the one non-`base` field).
10
- */
11
- type WrapperModel<S> = {
12
- readonly base: S;
13
- } & {
14
- readonly [K: `$${string}`]: unknown;
15
- };
16
- /** Options for the conformance replay. Mirrors `replay`'s second argument. */
17
- interface AssertWrapperFaithfulOpts<S, WM, BaseM, BaseCtx, WrapperCtx> {
18
- /** The Msg sequence to fold through BOTH machines. Use the base's Msgs. */
19
- readonly msgs: readonly BaseM[];
20
- /** Ctx for the WRAPPED machine (base ctx + wrapper ports). */
21
- readonly ctx: WrapperCtx;
22
- /** Ctx for the BARE base machine. Defaults to `ctx` when omitted. */
23
- readonly baseCtx?: BaseCtx;
24
- /** Optional pre-`init` snapshot of the COMPOSED Model (wrapped rehydrate). */
25
- readonly loaded?: WM | null;
26
- /**
27
- * Optional pre-`init` snapshot of the BARE base state. Supply when the
28
- * wrapped `loaded` is non-null so the base-equivalence check rehydrates the
29
- * base machine from the matching nested slice. Defaults to `loaded?.base`.
30
- */
31
- readonly baseLoaded?: S | null;
32
- /**
33
- * Opt-in relaxation for an INTERCEPTING wrapper (e.g. a retry wrapper).
34
- *
35
- * DEFAULT (`undefined` / `false`) — the OBSERVE-ONLY contract that a
36
- * deadline wrapper satisfies: every bare base Cmd must appear
37
- * UNCHANGED, in order, as a subsequence of the wrapped Cmd stream (properties
38
- * 1 and 3b). The wrapper may APPEND its own Cmds but may NOT alter, drop, or
39
- * retime a base Cmd. This is the strict default and it is NOT weakened.
40
- *
41
- * WHEN SET — for a wrapper whose whole job is to INTERCEPT a chosen base Cmd
42
- * (retag it into a wrapper-owned carrier so the concern — cache / breaker /
43
- * rate-limit / retry — can gate it), a target base Cmd LEGITIMATELY does not
44
- * appear raw at the top level of the wrapped stream. The contract is still
45
- * **retag-and-re-emit, never swallow** (rule 2): the Cmd must be RECORDED, not
46
- * vanished. So when a bare base Cmd is ABSENT from the top-level wrapped
47
- * subsequence, this option accepts it IFF, in that SAME transition window, it
48
- * is recorded by the wrapper as one of:
49
- *
50
- * - the inner payload of a `$x:*` "run" carrier Cmd (`carrierCmdType` +
51
- * `innerField`) — the retag path; OR
52
- * - any other `$x:*` divergence Cmd whose `recordsField` deep-equals the
53
- * base Cmd — the gate/defer path (e.g. a "fast-failed" or "deferred"
54
- * record Cmd that carries the base Cmd it diverged on).
55
- *
56
- * A target base Cmd that is NEITHER present raw NOR recorded by any `$x:*`
57
- * Cmd in its window is a SWALLOW betrayal and still fails the gate.
58
- *
59
- * Provide the field names the carrier uses so the gate can unwrap it
60
- * structurally without hard-coding any one wrapper's vocabulary.
61
- */
62
- readonly intercepting?: InterceptingOpt;
63
- }
64
- /**
65
- * Configures the intercepting relaxation (see
66
- * `AssertWrapperFaithfulOpts.intercepting`). All fields name the carrier /
67
- * divergence shape so the gate can structurally find a retagged base Cmd
68
- * inside a `$x:*` Cmd. The gate only EVER inspects `$x:*`-prefixed wrapped
69
- * Cmds for a recorded base Cmd — it never relaxes the check for a base Cmd
70
- * that appears under any non-wrapper Cmd type.
71
- */
72
- interface InterceptingOpt {
73
- /**
74
- * The `Cmd.type` of the wrapper's run-carrier (e.g. `"$resilience:run"`).
75
- * A bare base Cmd that is retagged appears as `carrier[innerField]`.
76
- */
77
- readonly carrierCmdType: string;
78
- /** The field on the carrier Cmd that holds the original base Cmd. */
79
- readonly innerField: string;
80
- /**
81
- * OPTIONAL field on ANY OTHER `$x:*` Cmd that records a base Cmd the wrapper
82
- * gated/deferred without running it (e.g. a fast-fail record). When present
83
- * on a `$x:*` Cmd and deep-equal to the missing base Cmd, it counts as a
84
- * recorded divergence. Omit when the wrapper only ever retags via the
85
- * carrier.
86
- */
87
- readonly recordsField?: string;
88
- }
89
- /**
90
- * Assert a `withX` wrapper is TEA-faithful. Replays the wrapped machine and the
91
- * bare base machine over the same Msgs and checks the four conformance
92
- * properties (see file header).
93
- *
94
- * @param base the bare base `Machine`.
95
- * @param makeWrapped a thunk that wraps `base` and returns the composed machine
96
- * (e.g. `() => withTimeout(wired, cfg).machine`, where `wired.machine` is
97
- * `base`). A thunk — not the wrapped value — so a wrapper that registers
98
- * process-scoped ports (`definePort`) is constructed inside the assertion's
99
- * control, and so the same betrayal-detector reads as
100
- * `assertWrapperFaithful(wired.machine, () => withX(wired, cfg).machine, ...)`
101
- * at every wrapper's test site.
102
- * @param opts the conformance replay options.
103
- */
104
- declare function assertWrapperFaithful<S, BaseM extends {
105
- type: string;
106
- }, BaseC extends Cmd, BaseU extends Sub, BaseCtx, WM extends WrapperModel<S>, WrapperM extends {
107
- type: string;
108
- }, WrapperC extends Cmd, WrapperU extends Sub, WrapperCtx>(base: Machine<S, BaseM, BaseC, BaseU, BaseCtx>, makeWrapped: () => Machine<WM, WrapperM, WrapperC, WrapperU, WrapperCtx>, opts: AssertWrapperFaithfulOpts<S, WM, BaseM, BaseCtx, WrapperCtx>): void;
109
-
110
5
  /**
111
6
  * Shared options shape for every test assertion below. Mirrors the
112
7
  * second argument of `replay(machine, opts)` — `msgs` is the sequence to
@@ -415,6 +310,25 @@ declare function drive<S, M extends {
415
310
  type: string;
416
311
  }, C extends Cmd, U extends Sub, Ctx>(machine: Machine<S, M, C, U, Ctx>, initial: S, msg: M, handlers: Interpret<M, C, Ctx>, ...[opts]: Record<never, never> extends DriveOptions<Ctx> ? [opts?: DriveOptions<Ctx>] : [opts: DriveOptions<Ctx>]): Promise<DriveResult<S, M, C>>;
417
312
 
313
+ /**
314
+ * Assert that replaying `opts.msgs` is a pure function of the Msg log: the
315
+ * final state and every emitted Cmd come out the same under two different
316
+ * global wall-clocks and RNG seeds.
317
+ *
318
+ * `init` and `update` never receive a clock, so a cell that reads
319
+ * `Date.now()` or `Math.random()` reaches for the global one, and a replay of
320
+ * the same log on another day or another host lands somewhere else. Two
321
+ * back-to-back replays under one clock would hide that; this helper stubs
322
+ * two distinct ambients and compares. Time belongs in the Msg (an `at`
323
+ * field), where it is identical across replays.
324
+ *
325
+ * Subs are not compared: they are derived from the final state, so a state
326
+ * that matches yields the same Subs.
327
+ */
328
+ declare function expectReplayDeterministic<S, M extends {
329
+ type: string;
330
+ }, C extends Cmd, U extends Sub, Ctx>(machine: Machine<S, M, C, U, Ctx>, opts: NoInfer<ReplayOpts<S, M, Ctx>>): void;
331
+
418
332
  /**
419
333
  * Construct an inert `Runtime<S, M>` value. Use at ctx sites that require
420
334
  * a Runtime reference but where the test never invokes `interpret` (so
@@ -474,4 +388,4 @@ declare function stateFactory<S extends {
474
388
  type: string;
475
389
  }>(defaults: StateFactoryDefaults<S>): StateFactoryAPI<S>;
476
390
 
477
- export { type AssertWrapperFaithfulOpts, type BoundMachine, DEFAULT_MAX_ROUNDS, type DriveCtxArg, DriveNoHandlerError, type DriveOptions, type DriveResult, DriveRoundsExceededError, type DriveTraceEntry, type InterceptingOpt, type ReplayOpts, type StateFactoryAPI, type StateFactoryDefaults, type WrapperModel, assertWrapperFaithful, bindMachine, drive, driveTraceOf, expectActiveSubs, expectCmdEmitted, expectCmdSequence, expectFinalState, noopRuntime, stateFactory, step };
391
+ export { type BoundMachine, DEFAULT_MAX_ROUNDS, type DriveCtxArg, DriveNoHandlerError, type DriveOptions, type DriveResult, DriveRoundsExceededError, type DriveTraceEntry, type ReplayOpts, type StateFactoryAPI, type StateFactoryDefaults, bindMachine, drive, driveTraceOf, expectActiveSubs, expectCmdEmitted, expectCmdSequence, expectFinalState, expectReplayDeterministic, noopRuntime, stateFactory, step };
@@ -1,181 +1,7 @@
1
- import '../chunk-GOX2CYIM.js';
2
- import { replay, cmdEdgeOver, Outcome, cmdEdge } from '../chunk-CH5KTOEZ.js';
1
+ import '../chunk-C4U5D5HP.js';
2
+ import { replay, cmdEdgeOver, Outcome, cmdEdge } from '../chunk-K4ETBNKS.js';
3
3
  import { expect, vi } from 'vitest';
4
4
 
5
- function assertWrapperFaithful(base, makeWrapped, opts) {
6
- const baseCtx = opts.baseCtx ?? opts.ctx;
7
- const wrappedMsgs = opts.msgs;
8
- const baseLoaded = opts.baseLoaded ?? (opts.loaded != null ? opts.loaded.base : null);
9
- const A0 = { now: 1e6, rng: 0.123 };
10
- const A1 = { now: 9876543, rng: 0.987 };
11
- const bare = underAmbient(
12
- A0,
13
- () => replay(base, { msgs: opts.msgs, ctx: baseCtx, loaded: baseLoaded })
14
- );
15
- const wrapped = underAmbient(A0, () => makeWrapped());
16
- const wrappedA = underAmbient(
17
- A0,
18
- () => replay(wrapped, {
19
- msgs: wrappedMsgs,
20
- ctx: opts.ctx,
21
- loaded: opts.loaded ?? null
22
- })
23
- );
24
- const wrappedB = underAmbient(
25
- A1,
26
- () => replay(makeWrapped(), {
27
- msgs: wrappedMsgs,
28
- ctx: opts.ctx,
29
- loaded: opts.loaded ?? null
30
- })
31
- );
32
- expect(wrappedA.state.base).toEqual(bare.state);
33
- expectCmdSubsequence(bare.cmds, wrappedA.cmds, void 0, opts.intercepting);
34
- const sliceKey = wrapperSliceKey(wrappedA.state);
35
- expect(
36
- sliceOf(wrappedB.state, sliceKey),
37
- `wrapper slice changed under a different ambient clock/RNG \u2192 update is reading Date.now()/Math.random(); time must enter only as Msg \`at\` data`
38
- ).toEqual(sliceOf(wrappedA.state, sliceKey));
39
- const wrapperFamily = `${sliceKey}:`;
40
- const wrapperCmdsA = wrappedA.cmds.filter(
41
- (c) => c.type.startsWith(wrapperFamily)
42
- );
43
- const wrapperCmdsB = wrappedB.cmds.filter(
44
- (c) => c.type.startsWith(wrapperFamily)
45
- );
46
- expect(
47
- wrapperCmdsB,
48
- `wrapper Cmds ("${wrapperFamily}*") changed under a different ambient clock/RNG \u2192 a wrapper Cmd PAYLOAD is reading Date.now()/Math.random(); wrapper Cmds must be a pure function of the Msg log, time entering only as Msg \`at\` data`
49
- ).toEqual(wrapperCmdsA);
50
- if (opts.msgs.length > 0) {
51
- expect(
52
- wrapperCmdsA.length,
53
- `expected at least one "${wrapperFamily}*" wrapper-decision Cmd in the replay log (found none across ${opts.msgs.length} transition(s)) \u2014 a wrapper whose decisions are invisible to the Msg/Cmd log has betrayed total visibility`
54
- ).toBeGreaterThan(0);
55
- }
56
- for (let i = 0; i < opts.msgs.length; i++) {
57
- const bareStep = stepCmds(
58
- () => underAmbient(
59
- A0,
60
- () => replay(base, {
61
- msgs: opts.msgs.slice(0, i),
62
- ctx: baseCtx,
63
- loaded: baseLoaded
64
- })
65
- ).cmds,
66
- () => underAmbient(
67
- A0,
68
- () => replay(base, {
69
- msgs: opts.msgs.slice(0, i + 1),
70
- ctx: baseCtx,
71
- loaded: baseLoaded
72
- })
73
- ).cmds
74
- );
75
- const wrappedStep = stepCmds(
76
- () => underAmbient(
77
- A0,
78
- () => replay(wrapped, {
79
- msgs: wrappedMsgs.slice(0, i),
80
- ctx: opts.ctx,
81
- loaded: opts.loaded ?? null
82
- })
83
- ).cmds,
84
- () => underAmbient(
85
- A0,
86
- () => replay(wrapped, {
87
- msgs: wrappedMsgs.slice(0, i + 1),
88
- ctx: opts.ctx,
89
- loaded: opts.loaded ?? null
90
- })
91
- ).cmds
92
- );
93
- expectCmdSubsequence(bareStep, wrappedStep, i, opts.intercepting);
94
- }
95
- const slice = sliceOf(wrappedA.state, sliceKey);
96
- expect(JSON.parse(JSON.stringify(slice))).toEqual(slice);
97
- }
98
- function underAmbient(ambient, fn) {
99
- const nowSpy = vi.spyOn(Date, "now").mockReturnValue(ambient.now);
100
- const rngSpy = vi.spyOn(Math, "random").mockReturnValue(ambient.rng);
101
- try {
102
- return fn();
103
- } finally {
104
- nowSpy.mockRestore();
105
- rngSpy.mockRestore();
106
- }
107
- }
108
- function sliceOf(model, sliceKey) {
109
- return model[sliceKey];
110
- }
111
- function stepCmds(prefixCmds, throughCmds) {
112
- const before = prefixCmds();
113
- const after = throughCmds();
114
- return after.slice(before.length);
115
- }
116
- function wrapperSliceKey(model) {
117
- const dollarKeys = Object.keys(model).filter((k) => k.startsWith("$"));
118
- if (dollarKeys.length !== 1) {
119
- throw new Error(
120
- `assertWrapperFaithful: expected exactly one "$"-prefixed wrapper slice on the composed Model, found ${dollarKeys.length} (${dollarKeys.join(", ") || "none"}). Every withX wrapper owns exactly one named slice (e.g. "$deadline").`
121
- );
122
- }
123
- return dollarKeys[0];
124
- }
125
- function expectCmdSubsequence(needle, haystack, step2, intercepting) {
126
- let i = 0;
127
- for (const cmd of haystack) {
128
- if (i >= needle.length) break;
129
- if (__deepEqual(needle[i], cmd)) {
130
- i++;
131
- continue;
132
- }
133
- if (intercepting !== void 0 && recordsBaseCmd(cmd, needle[i], intercepting)) {
134
- i++;
135
- }
136
- }
137
- const where = step2 === void 0 ? "the wrapped Cmd stream" : `the wrapped Cmd stream AT TRANSITION ${step2} (a base Cmd deferred to a later transition is an intra-window retiming betrayal)`;
138
- const swallowHint = intercepting === void 0 ? "a missing/rewritten/retimed base Cmd is a swallow betrayal" : `an intercepting wrapper must RETAG each target base Cmd into a "${intercepting.carrierCmdType}" carrier (inner field "${intercepting.innerField}") or record it on a "$*:" divergence Cmd \u2014 a base Cmd neither present raw NOR recorded by any "$*:" Cmd is a swallow betrayal`;
139
- expect(
140
- i,
141
- `expected every base Cmd to pass through unchanged (matched ${i} of ${needle.length} base Cmds as an ordered subsequence of ${where}) \u2014 ${swallowHint}`
142
- ).toBe(needle.length);
143
- }
144
- function recordsBaseCmd(cmd, baseCmd, opt) {
145
- if (!cmd.type.startsWith("$")) return false;
146
- const rec = cmd;
147
- if (cmd.type === opt.carrierCmdType && __deepEqual(rec[opt.innerField], baseCmd))
148
- return true;
149
- if (opt.recordsField !== void 0 && __deepEqual(rec[opt.recordsField], baseCmd))
150
- return true;
151
- return false;
152
- }
153
- function __deepEqual(a, b) {
154
- if (Object.is(a, b)) return true;
155
- if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) {
156
- return false;
157
- }
158
- const aIsArray = Array.isArray(a);
159
- if (aIsArray !== Array.isArray(b)) return false;
160
- if (aIsArray) {
161
- const bArr = b;
162
- if (a.length !== bArr.length) return false;
163
- for (let i = 0; i < a.length; i++) {
164
- if (!__deepEqual(a[i], bArr[i])) return false;
165
- }
166
- return true;
167
- }
168
- const aRec = a;
169
- const bRec = b;
170
- const aKeys = Object.keys(aRec);
171
- const bKeys = Object.keys(bRec);
172
- if (aKeys.length !== bKeys.length) return false;
173
- for (const key of aKeys) {
174
- if (!Object.hasOwn(bRec, key)) return false;
175
- if (!__deepEqual(aRec[key], bRec[key])) return false;
176
- }
177
- return true;
178
- }
179
5
  function expectFinalState(machine, opts, expected) {
180
6
  const { state } = replay(machine, opts);
181
7
  expect(state).toEqual(expected);
@@ -323,6 +149,30 @@ async function drive(machine, initial, msg, handlers, ...[opts]) {
323
149
  }
324
150
  return { state, trace };
325
151
  }
152
+ var AMBIENT_A = { now: 1e6, rng: 0.123 };
153
+ var AMBIENT_B = { now: 9876543, rng: 0.987 };
154
+ function expectReplayDeterministic(machine, opts) {
155
+ const a = underAmbient(AMBIENT_A, () => replay(machine, opts));
156
+ const b = underAmbient(AMBIENT_B, () => replay(machine, opts));
157
+ expect(
158
+ b.state,
159
+ "final state changed under a different clock/RNG: init or update reads Date.now()/Math.random(); time must enter as Msg data"
160
+ ).toEqual(a.state);
161
+ expect(
162
+ b.cmds,
163
+ "emitted Cmds changed under a different clock/RNG: a Cmd payload reads Date.now()/Math.random(); time must enter as Msg data"
164
+ ).toEqual(a.cmds);
165
+ }
166
+ function underAmbient(ambient, fn) {
167
+ const nowSpy = vi.spyOn(Date, "now").mockReturnValue(ambient.now);
168
+ const rngSpy = vi.spyOn(Math, "random").mockReturnValue(ambient.rng);
169
+ try {
170
+ return fn();
171
+ } finally {
172
+ nowSpy.mockRestore();
173
+ rngSpy.mockRestore();
174
+ }
175
+ }
326
176
 
327
177
  // src/testing/noop-runtime.ts
328
178
  function noopRuntime(opts) {
@@ -398,6 +248,6 @@ function stateFactory(defaults) {
398
248
  return api;
399
249
  }
400
250
 
401
- export { DEFAULT_MAX_ROUNDS, DriveNoHandlerError, DriveRoundsExceededError, assertWrapperFaithful, bindMachine, drive, driveTraceOf, expectActiveSubs, expectCmdEmitted, expectCmdSequence, expectFinalState, noopRuntime, stateFactory, step };
251
+ export { DEFAULT_MAX_ROUNDS, DriveNoHandlerError, DriveRoundsExceededError, bindMachine, drive, driveTraceOf, expectActiveSubs, expectCmdEmitted, expectCmdSequence, expectFinalState, expectReplayDeterministic, noopRuntime, stateFactory, step };
402
252
  //# sourceMappingURL=index.js.map
403
253
  //# sourceMappingURL=index.js.map