@playfast/reform-proof 1.2.1 → 1.3.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 (69) hide show
  1. package/dist/assert.d.ts +15 -0
  2. package/dist/assert.d.ts.map +1 -0
  3. package/dist/assert.js +39 -0
  4. package/dist/assert.js.map +1 -0
  5. package/dist/engine.d.ts +16 -0
  6. package/dist/engine.d.ts.map +1 -0
  7. package/dist/engine.js +119 -0
  8. package/dist/engine.js.map +1 -0
  9. package/dist/engineMounted.d.ts +18 -0
  10. package/dist/engineMounted.d.ts.map +1 -0
  11. package/dist/engineMounted.js +96 -0
  12. package/dist/engineMounted.js.map +1 -0
  13. package/dist/engineMounts.d.ts +13 -0
  14. package/dist/engineMounts.d.ts.map +1 -0
  15. package/dist/engineMounts.js +116 -0
  16. package/dist/engineMounts.js.map +1 -0
  17. package/dist/engineRender.d.ts +10 -0
  18. package/dist/engineRender.d.ts.map +1 -0
  19. package/dist/engineRender.js +64 -0
  20. package/dist/engineRender.js.map +1 -0
  21. package/dist/engineSink.d.ts +66 -0
  22. package/dist/engineSink.d.ts.map +1 -0
  23. package/dist/engineSink.js +72 -0
  24. package/dist/engineSink.js.map +1 -0
  25. package/dist/engineTree.d.ts +63 -0
  26. package/dist/engineTree.d.ts.map +1 -0
  27. package/dist/engineTree.js +137 -0
  28. package/dist/engineTree.js.map +1 -0
  29. package/dist/engineTreeDriver.d.ts +5 -0
  30. package/dist/engineTreeDriver.d.ts.map +1 -0
  31. package/dist/engineTreeDriver.js +187 -0
  32. package/dist/engineTreeDriver.js.map +1 -0
  33. package/dist/engineTreeFacade.d.ts +5 -0
  34. package/dist/engineTreeFacade.d.ts.map +1 -0
  35. package/dist/engineTreeFacade.js +105 -0
  36. package/dist/engineTreeFacade.js.map +1 -0
  37. package/dist/engineTreeTypes.d.ts +80 -0
  38. package/dist/engineTreeTypes.d.ts.map +1 -0
  39. package/dist/engineTreeTypes.js +11 -0
  40. package/dist/engineTreeTypes.js.map +1 -0
  41. package/dist/errors.d.ts +39 -0
  42. package/dist/errors.d.ts.map +1 -0
  43. package/dist/errors.js +30 -0
  44. package/dist/errors.js.map +1 -0
  45. package/dist/facade.d.ts +54 -0
  46. package/dist/facade.d.ts.map +1 -0
  47. package/dist/facade.js +2 -0
  48. package/dist/facade.js.map +1 -0
  49. package/dist/fingerprint.d.ts +2 -0
  50. package/dist/fingerprint.d.ts.map +1 -0
  51. package/dist/fingerprint.js +55 -0
  52. package/dist/fingerprint.js.map +1 -0
  53. package/dist/index.d.ts +88 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +73 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/product.d.ts +56 -0
  58. package/dist/product.d.ts.map +1 -0
  59. package/dist/product.js +35 -0
  60. package/dist/product.js.map +1 -0
  61. package/dist/proofCase.d.ts +24 -0
  62. package/dist/proofCase.d.ts.map +1 -0
  63. package/dist/proofCase.js +2 -0
  64. package/dist/proofCase.js.map +1 -0
  65. package/dist/runner.d.ts +15 -0
  66. package/dist/runner.d.ts.map +1 -0
  67. package/dist/runner.js +13 -0
  68. package/dist/runner.js.map +1 -0
  69. package/package.json +17 -5
@@ -0,0 +1,105 @@
1
+ import { Array as Arr, Effect, Option, TestClock } from 'effect';
2
+ import { AssertionFailed, NoTestClock, UnknownAction, UnknownSlot } from './errors.js';
3
+ import { matchProps } from './assert.js';
4
+ import {} from '@playfast/reform';
5
+ import { keyed, uiNameOf, } from './engineSink.js';
6
+ import { makeTreeDriver } from './engineTreeDriver.js';
7
+ export function makeRuntimeTreeFacade(runtime, root, rootProps, sink, dispatched) {
8
+ const driver = makeTreeDriver(runtime, root, rootProps, sink);
9
+ const currentRoot = () => driver.render().root;
10
+ // The nested-Feature twin of the mounted facade's `advance`: same virtual clock
11
+ // off the same runtime, settled through this driver instead.
12
+ const advance = (duration) => Option.match(runtime.readOption(TestClock.TestClock), {
13
+ onNone: () => Effect.dieMessage(new NoTestClock().message),
14
+ onSome: (clock) => clock.adjust(duration).pipe(Effect.flatMap(() => driver.settle)),
15
+ });
16
+ // `peek` is the non-dying half of `resolve`: None once the node has left the
17
+ // tree, so an action that removed its own node can still report a result.
18
+ const nodeFacade = (resolve, peek) => ({
19
+ props: Effect.sync(() => resolve().props),
20
+ expectProps: (partial) => Effect.sync(() => {
21
+ const mismatch = matchProps({
22
+ actual: resolve().props,
23
+ expected: partial,
24
+ });
25
+ if (mismatch !== undefined) {
26
+ return Effect.runSync(Effect.dieMessage(new AssertionFailed({ detail: mismatch }).message));
27
+ }
28
+ }),
29
+ actions: keyed((event) => (payload) => Effect.gen(function* () {
30
+ const node = resolve();
31
+ const trigger = node.events[event];
32
+ if (trigger === undefined) {
33
+ return yield* Effect.dieMessage(new UnknownAction({
34
+ composition: uiNameOf(node.comp),
35
+ action: event,
36
+ rendered: 1,
37
+ }).message);
38
+ }
39
+ dispatched.add(event);
40
+ trigger(payload);
41
+ yield* driver.settle;
42
+ // A self-removing action leaves nothing to re-read; report what the
43
+ // node last rendered instead of dying on the vanished child.
44
+ return Option.match(peek(), {
45
+ onNone: () => node.props,
46
+ onSome: (settled) => settled.props,
47
+ });
48
+ })),
49
+ slots: keyed((slotName) => slotFacade(resolve, slotName)),
50
+ frame: driver.settle,
51
+ advance,
52
+ });
53
+ const slotFacade = (resolveParent, slotName) => {
54
+ const children = () => {
55
+ const parent = resolveParent();
56
+ const resolved = parent.slots[slotName];
57
+ if (resolved === undefined) {
58
+ return Effect.runSync(Effect.dieMessage(new UnknownSlot({ parent: uiNameOf(parent.comp), slot: slotName }).message));
59
+ }
60
+ return resolved;
61
+ };
62
+ const peekAt = (index) => Option.fromNullable(children()[index]);
63
+ const peekByKey = (key) => Arr.findFirst(children(), (candidate) => Option.contains(candidate.key, key));
64
+ const childAt = (index) => nodeFacade(() => children()[index] ?? missingChild(index), () => peekAt(index));
65
+ const childByKey = (key) => nodeFacade(() => Option.getOrElse(peekByKey(key), () => missingKey(key)), () => peekByKey(key));
66
+ const missingChild = (index) => {
67
+ const parent = resolveParent();
68
+ return Effect.runSync(Effect.dieMessage(new UnknownSlot({
69
+ parent: uiNameOf(parent.comp),
70
+ slot: `${slotName}[${index}]`,
71
+ }).message));
72
+ };
73
+ const missingKey = (key) => {
74
+ const parent = resolveParent();
75
+ return Effect.runSync(Effect.dieMessage(new UnknownSlot({
76
+ parent: uiNameOf(parent.comp),
77
+ slot: `${slotName}[key=${key}]`,
78
+ }).message));
79
+ };
80
+ const first = childAt(0);
81
+ return {
82
+ first: Effect.sync(() => childAt(0)),
83
+ at: (index) => Effect.sync(() => childAt(index)),
84
+ all: Effect.sync(() => children().map((_child, index) => childAt(index))),
85
+ byKey: (key) => Effect.sync(() => {
86
+ const child = Arr.findFirst(children(), (candidate) => Option.contains(candidate.key, key));
87
+ return Option.isNone(child) ? missingKey(key) : childByKey(key);
88
+ }),
89
+ where: (predicate) => Effect.sync(() => children().flatMap((child, index) => (predicate(child.props) ? [childAt(index)] : []))),
90
+ count: Effect.sync(() => children().length),
91
+ props: first.props,
92
+ expectProps: first.expectProps,
93
+ actions: first.actions,
94
+ slots: first.slots,
95
+ frame: driver.settle,
96
+ advance,
97
+ };
98
+ };
99
+ return {
100
+ facade: nodeFacade(currentRoot, () => Option.some(currentRoot())),
101
+ settle: driver.settle,
102
+ dispose: driver.dispose,
103
+ };
104
+ }
105
+ //# sourceMappingURL=engineTreeFacade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engineTreeFacade.js","sourceRoot":"","sources":["../src/engineTreeFacade.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import { type Effect, type Option } from 'effect';
2
+ import type { FeatureLoadFailed, SlotFill, Trigger, UiContract } from '@playfast/reform';
3
+ import type { AnyComposition, AnyFeatureBinding } from '@playfast/reform/internal';
4
+ import { type HostRuntime, type MountedFacade, type MountedFacadeHandleErasure } from './engineSink.js';
5
+ export type FeatureMountState = {
6
+ readonly _tag: 'Loading';
7
+ } | {
8
+ readonly _tag: 'Live';
9
+ readonly runtime: HostRuntime;
10
+ } | {
11
+ readonly _tag: 'Failed';
12
+ readonly error: FeatureLoadFailed;
13
+ };
14
+ export interface TreeFeatureMount {
15
+ readonly id: string;
16
+ readonly binding: AnyFeatureBinding;
17
+ readonly parent: HostRuntime;
18
+ readonly depth: number;
19
+ readonly props: unknown;
20
+ attempt: number;
21
+ state: FeatureMountState;
22
+ dispose: () => void;
23
+ }
24
+ export interface TreeNode {
25
+ readonly path: string;
26
+ readonly depth: number;
27
+ readonly key: Option.Option<string>;
28
+ readonly comp: AnyComposition;
29
+ readonly props: unknown;
30
+ readonly events: Record<string, Trigger<unknown>>;
31
+ readonly slots: Readonly<Record<string, ReadonlyArray<TreeNode>>>;
32
+ }
33
+ export interface TreeRenderState {
34
+ readonly root: TreeNode;
35
+ readonly fingerprint: string;
36
+ }
37
+ export interface RuntimeTreeFacade<C extends UiContract> {
38
+ readonly facade: MountedFacade<C>;
39
+ readonly settle: Effect.Effect<void, never, never>;
40
+ dispose(): void;
41
+ }
42
+ export interface RuntimeTreeFacadeErasure extends MountedFacadeHandleErasure {
43
+ dispose(): void;
44
+ }
45
+ export interface TreeDriver {
46
+ readonly render: () => TreeRenderState;
47
+ readonly settle: Effect.Effect<void, never, never>;
48
+ readonly dispose: () => void;
49
+ }
50
+ export interface MountIdentityInput {
51
+ readonly parent: HostRuntime;
52
+ readonly parentPath: string;
53
+ readonly slotName: string;
54
+ readonly key: string;
55
+ readonly binding: AnyFeatureBinding;
56
+ }
57
+ export interface FeatureRecordInput {
58
+ readonly id: string;
59
+ readonly parent: HostRuntime;
60
+ readonly binding: AnyFeatureBinding;
61
+ readonly depth: number;
62
+ readonly props: unknown;
63
+ }
64
+ export interface RenderCompositionInput {
65
+ readonly runtime: HostRuntime;
66
+ readonly comp: AnyComposition;
67
+ readonly props: unknown;
68
+ readonly key: Option.Option<string>;
69
+ readonly path: string;
70
+ readonly depth: number;
71
+ readonly seen: Set<string>;
72
+ readonly mountMissing: boolean;
73
+ }
74
+ export declare const encodeIdentityPart: (part: string) => string;
75
+ export declare const fillEntries: (slotName: string, fill: SlotFill<unknown>) => ReadonlyArray<{
76
+ readonly key: string;
77
+ readonly props: unknown;
78
+ }>;
79
+ export declare const treeFingerprint: (node: TreeNode) => unknown;
80
+ //# sourceMappingURL=engineTreeTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engineTreeTypes.d.ts","sourceRoot":"","sources":["../src/engineTreeTypes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { Match, Record as Rec } from 'effect';
2
+ import { uiNameOf, } from './engineSink.js';
3
+ export const encodeIdentityPart = (part) => `${part.length}:${part}`;
4
+ export const fillEntries = (slotName, fill) => Match.value(fill).pipe(Match.when({ _tag: 'Each' }, (each) => each.items), Match.when({ _tag: 'One' }, (oneFill) => [{ key: `${slotName}.0`, props: oneFill.props }]), Match.when({ _tag: 'Absent' }, () => []), Match.exhaustive);
5
+ export const treeFingerprint = (node) => [
6
+ uiNameOf(node.comp),
7
+ node.key,
8
+ node.props,
9
+ Rec.map(node.slots, (children) => children.map(treeFingerprint)),
10
+ ];
11
+ //# sourceMappingURL=engineTreeTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engineTreeTypes.js","sourceRoot":"","sources":["../src/engineTreeTypes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,EAAe,MAAM,IAAI,GAAG,EAAE,MAAM,QAAQ,CAAA;AAGvE,OAAO,EAIL,QAAQ,GACT,MAAM,cAAc,CAAA;AA4ErB,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,CAAA;AAEpF,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,QAAgB,EAChB,IAAuB,EAC2C,EAAE,CACpE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CACpB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAClD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,QAAQ,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,EAC1F,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EACxC,KAAK,CAAC,UAAU,CACjB,CAAA;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAc,EAAW,EAAE,CAAC;IAC1D,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;IACnB,IAAI,CAAC,GAAG;IACR,IAAI,CAAC,KAAK;IACV,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;CACjE,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { type Cause } from 'effect';
2
+ type TaggedErrorClass<Tag extends string, A extends Record<string, unknown>> = new (args: A) => Cause.YieldableError & {
3
+ readonly _tag: Tag;
4
+ } & Readonly<A>;
5
+ declare const AssertionFailedBase: TaggedErrorClass<'reform-proof/AssertionFailed', {
6
+ readonly detail: string;
7
+ }>;
8
+ export declare class AssertionFailed extends AssertionFailedBase {
9
+ get message(): string;
10
+ }
11
+ declare const UnknownActionBase: TaggedErrorClass<'reform-proof/UnknownAction', {
12
+ readonly composition: string;
13
+ readonly action: string;
14
+ readonly rendered: number;
15
+ }>;
16
+ export declare class UnknownAction extends UnknownActionBase {
17
+ get message(): string;
18
+ }
19
+ declare const UnknownSlotBase: TaggedErrorClass<'reform-proof/UnknownSlot', {
20
+ readonly parent: string;
21
+ readonly slot: string;
22
+ }>;
23
+ export declare class UnknownSlot extends UnknownSlotBase {
24
+ get message(): string;
25
+ }
26
+ /** The `Data.TaggedError(tag)` shape for a payload-free error: a `void` argument. */
27
+ type TaggedErrorClassVoid<Tag extends string> = new (args: void) => Cause.YieldableError & {
28
+ readonly _tag: Tag;
29
+ };
30
+ declare const NoTestClockBase: TaggedErrorClassVoid<'reform-proof/NoTestClock'>;
31
+ /**
32
+ * `app.advance(...)` ran against a scene whose runtime still holds the real clock,
33
+ * so there is no product time to move.
34
+ */
35
+ export declare class NoTestClock extends NoTestClockBase {
36
+ get message(): string;
37
+ }
38
+ export {};
39
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAQ,MAAM,QAAQ,CAAA;AAEzC,KAAK,gBAAgB,CAAC,GAAG,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,KAC7E,IAAI,EAAE,CAAC,KACJ,KAAK,CAAC,cAAc,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAA;CAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;AAEhE,QAAA,MAAM,mBAAmB,EAAE,gBAAgB,CACzC,8BAA8B,EAC9B;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CACoD,CAAA;AAEjF,qBAAa,eAAgB,SAAQ,mBAAmB;IACtD,IAAa,OAAO,IAAI,MAAM,CAE7B;CACF;AAED,QAAA,MAAM,iBAAiB,EAAE,gBAAgB,CACvC,4BAA4B,EAC5B;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAKpF,CAAA;AAEF,qBAAa,aAAc,SAAQ,iBAAiB;IAClD,IAAa,OAAO,IAAI,MAAM,CAE7B;CACF;AAED,QAAA,MAAM,eAAe,EAAE,gBAAgB,CACrC,0BAA0B,EAC1B;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CACgD,CAAA;AAEpG,qBAAa,WAAY,SAAQ,eAAe;IAC9C,IAAa,OAAO,IAAI,MAAM,CAE7B;CACF;AAED,qFAAqF;AACrF,KAAK,oBAAoB,CAAC,GAAG,SAAS,MAAM,IAAI,KAC9C,IAAI,EAAE,IAAI,KACP,KAAK,CAAC,cAAc,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAA;CAAE,CAAA;AAElD,QAAA,MAAM,eAAe,EAAE,oBAAoB,CAAC,0BAA0B,CAErE,CAAA;AAED;;;GAGG;AACH,qBAAa,WAAY,SAAQ,eAAe;IAC9C,IAAa,OAAO,IAAI,MAAM,CAE7B;CACF"}
package/dist/errors.js ADDED
@@ -0,0 +1,30 @@
1
+ import { Data } from 'effect';
2
+ const AssertionFailedBase = (Data.TaggedError('reform-proof/AssertionFailed'));
3
+ export class AssertionFailed extends AssertionFailedBase {
4
+ get message() {
5
+ return `reform-proof: assertion failed — ${this.detail}`;
6
+ }
7
+ }
8
+ const UnknownActionBase = (Data.TaggedError('reform-proof/UnknownAction'));
9
+ export class UnknownAction extends UnknownActionBase {
10
+ get message() {
11
+ return `reform-proof: '${this.composition}' has no action '${this.action}' (rendered ${this.rendered} instance(s))`;
12
+ }
13
+ }
14
+ const UnknownSlotBase = (Data.TaggedError('reform-proof/UnknownSlot'));
15
+ export class UnknownSlot extends UnknownSlotBase {
16
+ get message() {
17
+ return `reform-proof: '${this.parent}' has no slot '${this.slot}'`;
18
+ }
19
+ }
20
+ const NoTestClockBase = Data.TaggedError('reform-proof/NoTestClock');
21
+ /**
22
+ * `app.advance(...)` ran against a scene whose runtime still holds the real clock,
23
+ * so there is no product time to move.
24
+ */
25
+ export class NoTestClock extends NoTestClockBase {
26
+ get message() {
27
+ return "reform-proof: app.advance(...) needs a virtual clock — wrap the scene's layers with `Proof.withTestClock(...)`. Without it the scene's procedures sleep on the real clock and only elapse in real time.";
28
+ }
29
+ }
30
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,IAAI,EAAE,MAAM,QAAQ,CAAA;AAMzC,MAAM,mBAAmB,GAGrB,CAAA,IAAI,CAAC,WAAW,CAAC,8BAA8B,CAA8B,CAAA,CAAA;AAEjF,MAAM,OAAO,eAAgB,SAAQ,mBAAmB;IACtD,IAAa,OAAO;QAClB,OAAO,oCAAoC,IAAI,CAAC,MAAM,EAAE,CAAA;IAC1D,CAAC;CACF;AAED,MAAM,iBAAiB,GAGnB,CAAA,IAAI,CAAC,WAAW,CAAC,4BAA4B,CAI/C,CAAA,CAAA;AAEF,MAAM,OAAO,aAAc,SAAQ,iBAAiB;IAClD,IAAa,OAAO;QAClB,OAAO,kBAAkB,IAAI,CAAC,WAAW,oBAAoB,IAAI,CAAC,MAAM,eAAe,IAAI,CAAC,QAAQ,eAAe,CAAA;IACrH,CAAC;CACF;AAED,MAAM,eAAe,GAGjB,CAAA,IAAI,CAAC,WAAW,CAAC,0BAA0B,CAAqD,CAAA,CAAA;AAEpG,MAAM,OAAO,WAAY,SAAQ,eAAe;IAC9C,IAAa,OAAO;QAClB,OAAO,kBAAkB,IAAI,CAAC,MAAM,kBAAkB,IAAI,CAAC,IAAI,GAAG,CAAA;IACpE,CAAC;CACF;AAOD,MAAM,eAAe,GAAqD,IAAI,CAAC,WAAW,CACxF,0BAA0B,CAC3B,CAAA;AAED;;;GAGG;AACH,MAAM,OAAO,WAAY,SAAQ,eAAe;IAC9C,IAAa,OAAO;QAClB,OAAO,yMAAyM,CAAA;IAClN,CAAC;CACF"}
@@ -0,0 +1,54 @@
1
+ import type { Duration, Effect } from 'effect';
2
+ import type { SlotContract as ReformSlotContract, Trigger, UiContract } from '@playfast/reform';
3
+ export type EventsOf<C extends UiContract> = C extends {
4
+ readonly events: infer E extends NonNullable<UiContract['events']>;
5
+ } ? E : Readonly<Record<PropertyKey, never>>;
6
+ export type EventNamesOf<C extends UiContract> = C extends {
7
+ readonly events: NonNullable<UiContract['events']>;
8
+ } ? keyof EventsOf<C> : never;
9
+ export type SlotsOf<C extends UiContract> = C extends {
10
+ readonly slots: infer S extends NonNullable<UiContract['slots']>;
11
+ } ? S : Readonly<Record<PropertyKey, never>>;
12
+ export type PayloadOf<T> = T extends Trigger<infer P> ? P : never;
13
+ export type ContractOf<Comp> = Comp extends {
14
+ readonly Contract: infer C extends UiContract;
15
+ } ? C : never;
16
+ export type ContractOfSlot<S> = ReformSlotContract<S>;
17
+ export type ActionsOf<C extends UiContract, R = never> = C extends {
18
+ readonly events: NonNullable<UiContract['events']>;
19
+ } ? {
20
+ readonly [K in keyof EventsOf<C>]: (payload: PayloadOf<EventsOf<C>[K]>) => Effect.Effect<C['props'], never, R>;
21
+ } : Readonly<Record<PropertyKey, never>>;
22
+ export type SlotFacadesOf<C extends UiContract, R = never> = C extends {
23
+ readonly slots: NonNullable<UiContract['slots']>;
24
+ } ? {
25
+ readonly [K in keyof SlotsOf<C>]: SlotFacade<ContractOfSlot<SlotsOf<C>[K]>, R>;
26
+ } : Readonly<Record<PropertyKey, never>>;
27
+ export type Action<R = never> = (payload: unknown) => Effect.Effect<unknown, never, R>;
28
+ export interface Facade<C extends UiContract, R = never> {
29
+ readonly props: Effect.Effect<C['props'], never, R>;
30
+ readonly expectProps: (partial: Partial<C['props']>) => Effect.Effect<void, never, R>;
31
+ readonly actions: ActionsOf<C, R>;
32
+ readonly slots: SlotFacadesOf<C, R>;
33
+ readonly frame: Effect.Effect<void, never, R>;
34
+ /**
35
+ * Elapse `duration` of the scene's product time, then settle. Every timer the
36
+ * scene's procedures hold — `Effect.sleep`, `Schedule`, `Clock` reads — moves by
37
+ * exactly this much and no real time passes, so a 1500ms poll interval is observed
38
+ * in microseconds and never races the runner.
39
+ *
40
+ * Requires the scene's layers to be wrapped in `Proof.withTestClock(...)`. Against
41
+ * the real clock there is no virtual time to move, so the proof dies with
42
+ * `NoTestClock` instead of silently doing nothing.
43
+ */
44
+ readonly advance: (duration: Duration.DurationInput) => Effect.Effect<void, never, R>;
45
+ }
46
+ export interface SlotFacade<C extends UiContract, R = never> extends Facade<C, R> {
47
+ readonly first: Effect.Effect<Facade<C, R>, never, R>;
48
+ readonly at: (index: number) => Effect.Effect<Facade<C, R>, never, R>;
49
+ readonly all: Effect.Effect<ReadonlyArray<Facade<C, R>>, never, R>;
50
+ readonly byKey: (key: string) => Effect.Effect<Facade<C, R>, never, R>;
51
+ readonly where: (predicate: (props: C['props']) => boolean) => Effect.Effect<ReadonlyArray<Facade<C, R>>, never, R>;
52
+ readonly count: Effect.Effect<number, never, R>;
53
+ }
54
+ //# sourceMappingURL=facade.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facade.d.ts","sourceRoot":"","sources":["../src/facade.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC9C,OAAO,KAAK,EACV,YAAY,IAAI,kBAAkB,EAClC,OAAO,EACP,UAAU,EACX,MAAM,kBAAkB,CAAA;AAEzB,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,UAAU,IAAI,CAAC,SAAS;IACrD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAA;CACnE,GACG,CAAC,GACD,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAA;AACxC,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,UAAU,IAAI,CAAC,SAAS;IACzD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAA;CACnD,GACG,MAAM,QAAQ,CAAC,CAAC,CAAC,GACjB,KAAK,CAAA;AACT,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,UAAU,IAAI,CAAC,SAAS;IACpD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAA;CACjE,GACG,CAAC,GACD,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAA;AACxC,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;AACjE,MAAM,MAAM,UAAU,CAAC,IAAI,IAAI,IAAI,SAAS;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,SAAS,UAAU,CAAA;CAC9C,GACG,CAAC,GACD,KAAK,CAAA;AACT,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,CAAA;AAErD,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,SAAS;IACjE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAA;CACnD,GACG;IACE,QAAQ,EAAE,CAAC,IAAI,MAAM,QAAQ,CAAC,CAAC,CAAC,GAAG,CACjC,OAAO,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;CACzC,GACD,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAA;AACxC,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,SAAS;IACrE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAA;CACjD,GACG;IACE,QAAQ,EAAE,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;CAC/E,GACD,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAA;AAExC,MAAM,MAAM,MAAM,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;AAEtF,MAAM,WAAW,MAAM,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,GAAG,KAAK;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IACnD,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IACrF,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IAC7C;;;;;;;;;OASG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,aAAa,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;CACtF;AAED,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,GAAG,KAAK,CAAE,SAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IAC/E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IACrD,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IACrE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IAClE,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IACtE,QAAQ,CAAC,KAAK,EAAE,CACd,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,OAAO,KACtC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IACzD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;CAChD"}
package/dist/facade.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=facade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facade.js","sourceRoot":"","sources":["../src/facade.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export declare const formatFingerprint: (fingerprintInput: unknown) => string;
2
+ //# sourceMappingURL=fingerprint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAuEA,eAAO,MAAM,iBAAiB,GAAI,kBAAkB,OAAO,KAAG,MACX,CAAA"}
@@ -0,0 +1,55 @@
1
+ import * as Option from 'effect/Option';
2
+ const readPropertyOption = Option.liftThrowable((target, key) => Reflect.get(target, key));
3
+ const readProperty = (target, key) => Option.getOrElse(readPropertyOption(target, key), () => '[Property read threw]');
4
+ const propertyKeyFingerprint = (key) => typeof key === 'symbol'
5
+ ? `symbol:${String(key.description)}`
6
+ : typeof key === 'number'
7
+ ? `number-key:${String(key)}`
8
+ : `key:${key.length}:${key}`;
9
+ const valueFingerprint = (candidate, seen) => {
10
+ if (typeof candidate === 'bigint') {
11
+ return `bigint:${String(candidate)}`;
12
+ }
13
+ if (typeof candidate === 'boolean') {
14
+ return candidate ? 'boolean:true' : 'boolean:false';
15
+ }
16
+ if (typeof candidate === 'function') {
17
+ return `function:${String(candidate)}`;
18
+ }
19
+ if (typeof candidate === 'number') {
20
+ return `number:${String(candidate)}`;
21
+ }
22
+ if (typeof candidate === 'string') {
23
+ return `string:${candidate.length}:${candidate}`;
24
+ }
25
+ if (typeof candidate === 'symbol') {
26
+ return `symbol:${String(candidate.description)}`;
27
+ }
28
+ if (typeof candidate === 'undefined') {
29
+ return 'undefined';
30
+ }
31
+ if (candidate === null) {
32
+ return 'null';
33
+ }
34
+ if (seen.has(candidate)) {
35
+ return '[Circular]';
36
+ }
37
+ seen.add(candidate);
38
+ if (Array.isArray(candidate)) {
39
+ return `[${candidate.map((arrayEntry) => valueFingerprint(arrayEntry, seen)).join(',')}]`;
40
+ }
41
+ if (candidate instanceof Date) {
42
+ return `date:${String(candidate.getTime())}`;
43
+ }
44
+ if (candidate instanceof Map) {
45
+ return `map:[${Array.from(candidate, ([mapKey, mapEntry]) => `${valueFingerprint(mapKey, seen)}=>${valueFingerprint(mapEntry, seen)}`).join(',')}]`;
46
+ }
47
+ if (candidate instanceof Set) {
48
+ return `set:[${Array.from(candidate, (setEntry) => valueFingerprint(setEntry, seen)).join(',')}]`;
49
+ }
50
+ return `{${Reflect.ownKeys(candidate)
51
+ .map((key) => `${propertyKeyFingerprint(key)}:${valueFingerprint(readProperty(candidate, key), seen)}`)
52
+ .join(',')}}`;
53
+ };
54
+ export const formatFingerprint = (fingerprintInput) => valueFingerprint(fingerprintInput, new WeakSet());
55
+ //# sourceMappingURL=fingerprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import { Effect, Layer, type TestServices } from 'effect';
2
+ import { ProofRunner, type ProofRunnerApi, proofRunnerLayer, withProofRunner } from './runner.js';
3
+ import type { ContractOf, Facade, SlotsOf } from './facade.js';
4
+ import type { AnyRequirementClass, ProductClass, ProductComposition, RequirementClass } from './product.js';
5
+ import type { ProofCapture, ProofGenerator, SuiteResult } from './proofCase.js';
6
+ import type { Scene, SlotComposition as ReformSlotComposition, UiContract } from '@playfast/reform';
7
+ import type { AnyScene, CapturedRender } from '@playfast/reform/internal';
8
+ export { ProofRunner, proofRunnerLayer, withProofRunner };
9
+ export type { ProofRunnerApi };
10
+ export { makeFacade, makeProofFacade, makeRuntimeHandleFacade, makeRuntimeTreeFacade, makeSink, proofLayer, } from './engine.js';
11
+ export type { MountedFacade, MountedSlotFacade, MountedSlotFacadesOf, RuntimeTreeFacade, Sink, } from './engine.js';
12
+ export { Product, ProductRequirement } from './product.js';
13
+ export type { AnyRequirementClass, ProductClass, ProductComposition, ProductManifest, RequirementCapture, RequirementClass, RequirementManifest, } from './product.js';
14
+ export { expect, matchProps } from './assert.js';
15
+ export type { Action, ActionsOf, ContractOf, EventsOf, Facade, SlotFacade, SlotFacadesOf, } from './facade.js';
16
+ export type { ProofCapture, ProofCase, ProofResult, SuiteResult } from './proofCase.js';
17
+ export interface Proof {
18
+ readonly requirement: AnyRequirementClass;
19
+ readonly scene: AnyScene;
20
+ readonly capture: <Result>(visit: ProofCapture<Result>) => Result;
21
+ }
22
+ export interface ProofSuite {
23
+ readonly kind: 'ProofSuite';
24
+ readonly product: ProductClass;
25
+ readonly proofs: ReadonlyArray<Proof>;
26
+ }
27
+ declare const implement: <Comp extends ProductComposition>(requirement: RequirementClass<Comp, string>, scene: Scene<ContractOf<NoInfer<Comp>>, NoInfer<Comp>["States"]>, body: (app: Facade<ContractOf<Comp>, never>) => ProofGenerator) => Proof;
28
+ type SlotsHolding<C extends UiContract, Target extends ProductComposition> = C extends {
29
+ readonly slots: NonNullable<UiContract['slots']>;
30
+ } ? {
31
+ [K in keyof SlotsOf<C>]: [ReformSlotComposition<SlotsOf<C>[K]>] extends [Target] ? K : never;
32
+ }[keyof SlotsOf<C>] : never;
33
+ type SceneHolding<Comp extends ProductComposition, C extends UiContract, S extends ReadonlyArray<unknown>> = [SlotsHolding<C, Comp>] extends [never] ? never : Scene<C, S>;
34
+ declare const implementVia: <Comp extends ProductComposition, C extends UiContract, S extends ReadonlyArray<unknown>>(requirement: RequirementClass<Comp, string>, scene: SceneHolding<NoInfer<Comp>, C, S>, body: (app: Facade<C, never>) => ProofGenerator) => Proof;
35
+ interface MakeSuiteConfig {
36
+ readonly proofs: ReadonlyArray<Proof>;
37
+ }
38
+ declare const suite: (product: ProductClass, config: MakeSuiteConfig) => ProofSuite;
39
+ export declare const isProofSuite: (candidate: unknown) => candidate is ProofSuite;
40
+ declare const run: (proofSuite: ProofSuite) => Promise<SuiteResult>;
41
+ declare const runEffect: (proofSuite: ProofSuite) => Effect.Effect<SuiteResult, never, never>;
42
+ export interface StepFrame {
43
+ readonly index: number;
44
+ readonly captures: ReadonlyArray<CapturedRender>;
45
+ }
46
+ export interface DriveResult {
47
+ readonly requirement: string;
48
+ readonly frames: ReadonlyArray<StepFrame>;
49
+ readonly ok: boolean;
50
+ readonly error: string | undefined;
51
+ }
52
+ export interface ProofDriver {
53
+ readonly requirement: string;
54
+ readonly run: () => Promise<DriveResult>;
55
+ }
56
+ declare const driver: (proofSuite: ProofSuite) => ReadonlyArray<ProofDriver>;
57
+ /**
58
+ * Wrap a scene's layers in a virtual clock, so every `Effect.sleep`, `Schedule` and
59
+ * `Clock` read its procedures make elapses only when the proof says so via
60
+ * `app.advance(...)`:
61
+ *
62
+ * ```ts
63
+ * const MyScene = scene(MyComposition, { provide: [Proof.withTestClock(App)] })
64
+ * ```
65
+ *
66
+ * It has to WRAP the scene's layers, never sit beside them in `provide`. The engine
67
+ * forks its loop while its layer is being built, and a forked fiber inherits the
68
+ * clock in scope at that moment — so a clock merged as a sibling reaches the proof
69
+ * body but not the procedures whose timers it is meant to control. That mis-wiring
70
+ * is silent (`app.advance(...)` finds a clock, adjusts it, and no product timer
71
+ * moves), which is why the clock is exposed as this combinator, not a bare layer.
72
+ *
73
+ * Opt-in per scene rather than on by default: a scene without it keeps the real
74
+ * clock, so proofs that observe product timers by waiting stay correct. Once a scene
75
+ * has it, a product timer NEVER fires on its own — an unadvanced proof sees the
76
+ * pre-timer state, which is the point.
77
+ */
78
+ declare const withTestClock: <ROut, E, RIn>(layer: Layer.Layer<ROut, E, RIn>) => Layer.Layer<ROut | TestServices.TestServices, E, RIn>;
79
+ export declare const Proof: {
80
+ readonly implement: typeof implement;
81
+ readonly implementVia: typeof implementVia;
82
+ readonly suite: typeof suite;
83
+ readonly run: typeof run;
84
+ readonly runEffect: typeof runEffect;
85
+ readonly driver: typeof driver;
86
+ readonly withTestClock: typeof withTestClock;
87
+ };
88
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,73 @@
1
+ import { Effect, Layer, TestContext } from 'effect';
2
+ import { ProofRunner, proofRunnerLayer, withProofRunner } from './runner.js';
3
+ import { isRecord } from './assert.js';
4
+ export { ProofRunner, proofRunnerLayer, withProofRunner };
5
+ export { makeFacade, makeProofFacade, makeRuntimeHandleFacade, makeRuntimeTreeFacade, makeSink, proofLayer, } from './engine.js';
6
+ export { Product, ProductRequirement } from './product.js';
7
+ export { expect, matchProps } from './assert.js';
8
+ const implement = (requirement, scene, body) => scene.capture((exactScene) => {
9
+ const proofCase = {
10
+ requirement,
11
+ scene: exactScene,
12
+ placement: 'Root',
13
+ body,
14
+ };
15
+ return {
16
+ requirement,
17
+ scene: exactScene,
18
+ capture: (visit) => visit(proofCase),
19
+ };
20
+ });
21
+ const implementVia = (requirement, scene, body) => scene.capture((exactScene) => {
22
+ const proofCase = {
23
+ requirement,
24
+ scene: exactScene,
25
+ placement: 'Slot',
26
+ body,
27
+ };
28
+ return {
29
+ requirement,
30
+ scene: exactScene,
31
+ capture: (visit) => visit(proofCase),
32
+ };
33
+ });
34
+ const suite = (product, config) => ({
35
+ kind: 'ProofSuite',
36
+ product,
37
+ proofs: config.proofs,
38
+ });
39
+ export const isProofSuite = (candidate) => isRecord(candidate) && candidate['kind'] === 'ProofSuite' && Array.isArray(candidate['proofs']);
40
+ const run = (proofSuite) => Effect.runPromise(runEffect(proofSuite));
41
+ const runEffect = (proofSuite) => ProofRunner.pipe(Effect.flatMap((runner) => Effect.forEach(proofSuite.proofs, (proof) => runner.executeProofEffect(proof))), Effect.map((reports) => ({
42
+ product: proofSuite.product.manifest.name,
43
+ results: reports,
44
+ ok: reports.every((report) => report.ok),
45
+ })), Effect.provide(proofRunnerLayer));
46
+ const driver = (proofSuite) => proofSuite.proofs.map((proof) => ({
47
+ requirement: proof.requirement.manifest.statement,
48
+ run: () => withProofRunner((runner) => runner.driveProof(proof)),
49
+ }));
50
+ /**
51
+ * Wrap a scene's layers in a virtual clock, so every `Effect.sleep`, `Schedule` and
52
+ * `Clock` read its procedures make elapses only when the proof says so via
53
+ * `app.advance(...)`:
54
+ *
55
+ * ```ts
56
+ * const MyScene = scene(MyComposition, { provide: [Proof.withTestClock(App)] })
57
+ * ```
58
+ *
59
+ * It has to WRAP the scene's layers, never sit beside them in `provide`. The engine
60
+ * forks its loop while its layer is being built, and a forked fiber inherits the
61
+ * clock in scope at that moment — so a clock merged as a sibling reaches the proof
62
+ * body but not the procedures whose timers it is meant to control. That mis-wiring
63
+ * is silent (`app.advance(...)` finds a clock, adjusts it, and no product timer
64
+ * moves), which is why the clock is exposed as this combinator, not a bare layer.
65
+ *
66
+ * Opt-in per scene rather than on by default: a scene without it keeps the real
67
+ * clock, so proofs that observe product timers by waiting stay correct. Once a scene
68
+ * has it, a product timer NEVER fires on its own — an unadvanced proof sees the
69
+ * pre-timer state, which is the point.
70
+ */
71
+ const withTestClock = (layer) => layer.pipe(Layer.provideMerge(TestContext.TestContext));
72
+ export const Proof = { implement, implementVia, suite, run, runEffect, driver, withTestClock };
73
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}