@directive-run/core 1.6.1 → 1.8.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.
- package/dist/{chunk-HJ3CDQGB.cjs → chunk-2OS4RCLV.cjs} +3 -3
- package/dist/{chunk-HJ3CDQGB.cjs.map → chunk-2OS4RCLV.cjs.map} +1 -1
- package/dist/chunk-FCOZCTLY.js +16 -0
- package/dist/{chunk-2PLP22ZU.js.map → chunk-FCOZCTLY.js.map} +1 -1
- package/dist/{chunk-BWBPR34Z.cjs → chunk-WIZHZF4G.cjs} +2 -2
- package/dist/{chunk-BWBPR34Z.cjs.map → chunk-WIZHZF4G.cjs.map} +1 -1
- package/dist/{chunk-JFUK5NIO.js → chunk-ZE2RY5KP.js} +2 -2
- package/dist/{chunk-JFUK5NIO.js.map → chunk-ZE2RY5KP.js.map} +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +246 -1
- package/dist/index.d.ts +246 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +1 -1
- package/dist/internals.js +1 -1
- package/dist/system-DEMPYZHI.cjs +2 -0
- package/dist/{system-WNO6PRHB.cjs.map → system-DEMPYZHI.cjs.map} +1 -1
- package/dist/system-R4JL6U4S.js +2 -0
- package/dist/{system-K6OITF5B.js.map → system-R4JL6U4S.js.map} +1 -1
- package/dist/testing.cjs +1 -1
- package/dist/testing.js +1 -1
- package/dist/worker.cjs +1 -1
- package/dist/worker.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-2PLP22ZU.js +0 -16
- package/dist/system-K6OITF5B.js +0 -2
- package/dist/system-WNO6PRHB.cjs +0 -2
package/dist/index.d.cts
CHANGED
|
@@ -403,6 +403,251 @@ declare function framesFromSnapshots(snapshots: unknown): ReplayFrame[];
|
|
|
403
403
|
*/
|
|
404
404
|
declare function replayUnder<F = Record<string, unknown>>(options: ReplayUnderOptions<F>): PredicateBacktestReport;
|
|
405
405
|
|
|
406
|
+
/**
|
|
407
|
+
* Parameter sweep over a predicate template — the grid-search counterpart
|
|
408
|
+
* to `replayUnder`.
|
|
409
|
+
*
|
|
410
|
+
* `replayUnder` diffs ONE proposed predicate against the original.
|
|
411
|
+
* `sweepUnder` takes a **template** with one or more `{ $hole: "name" }`
|
|
412
|
+
* markers and a set of candidate values, then replays the history once
|
|
413
|
+
* per (cartesian-product) combination. The result is a response curve
|
|
414
|
+
* over the parameter space plus the argmax under a user-supplied
|
|
415
|
+
* objective — turning rule-tuning from guess-and-check into a one-call
|
|
416
|
+
* optimization against recorded traffic.
|
|
417
|
+
*
|
|
418
|
+
* Pure module — imports only the predicate runtime and replay engine.
|
|
419
|
+
* No engine / store / tracking dependency.
|
|
420
|
+
*/
|
|
421
|
+
|
|
422
|
+
/** A placeholder inside a predicate template — substituted from `sweep` values. */
|
|
423
|
+
interface SweepHole {
|
|
424
|
+
readonly $hole: string;
|
|
425
|
+
}
|
|
426
|
+
interface SweepUnderOptions<F = Record<string, unknown>> {
|
|
427
|
+
/** Recorded fact-state frames, in chronological order. */
|
|
428
|
+
frames: readonly ReplayFrame<F>[];
|
|
429
|
+
/** The constraint's current `when` predicate (baseline). */
|
|
430
|
+
original: FactPredicate<F>;
|
|
431
|
+
/**
|
|
432
|
+
* Predicate template containing one or more `{ $hole: "name" }` markers.
|
|
433
|
+
* Each marker is substituted by the corresponding value from `sweep` on
|
|
434
|
+
* every point in the curve.
|
|
435
|
+
*
|
|
436
|
+
* @example
|
|
437
|
+
* ```ts
|
|
438
|
+
* { cartTotal: { $gte: { $hole: "threshold" } } }
|
|
439
|
+
* ```
|
|
440
|
+
*/
|
|
441
|
+
template: unknown;
|
|
442
|
+
/**
|
|
443
|
+
* Map of hole name → candidate values. Multiple holes produce the
|
|
444
|
+
* cartesian product (grid search).
|
|
445
|
+
*
|
|
446
|
+
* @example
|
|
447
|
+
* ```ts
|
|
448
|
+
* { threshold: [25, 50, 100, 200] }
|
|
449
|
+
* { riskScore: [0.5, 0.7, 0.9], minAge: [13, 18, 21] } // 3*3 = 9 points
|
|
450
|
+
* ```
|
|
451
|
+
*/
|
|
452
|
+
sweep: Readonly<Record<string, readonly unknown[]>>;
|
|
453
|
+
/**
|
|
454
|
+
* Score function for ranking. Higher is better. Default:
|
|
455
|
+
* `(report) => report.proposed.matched` (maximize matched frames).
|
|
456
|
+
*/
|
|
457
|
+
objective?: (report: PredicateBacktestReport) => number;
|
|
458
|
+
/** Optional fact key to additionally report distinct-entity counts. */
|
|
459
|
+
entityKey?: string;
|
|
460
|
+
/**
|
|
461
|
+
* Diff frames sampled per replay (default 0 — count-only for speed).
|
|
462
|
+
* Set higher to inspect specific frames in the report.
|
|
463
|
+
*/
|
|
464
|
+
maxSamples?: number;
|
|
465
|
+
}
|
|
466
|
+
/** One point on the sweep curve — one candidate value tuple. */
|
|
467
|
+
interface SweepPoint {
|
|
468
|
+
/** Hole name → value used at this point. */
|
|
469
|
+
values: Readonly<Record<string, unknown>>;
|
|
470
|
+
/** Full backtest report against this candidate. */
|
|
471
|
+
report: PredicateBacktestReport;
|
|
472
|
+
/** Computed objective score (higher is better). */
|
|
473
|
+
score: number;
|
|
474
|
+
}
|
|
475
|
+
interface SweepReport {
|
|
476
|
+
/** All points, in sweep order (cartesian-product traversal of sweep keys). */
|
|
477
|
+
points: readonly SweepPoint[];
|
|
478
|
+
/** Index of the highest-scoring point in `points`. */
|
|
479
|
+
bestIndex: number;
|
|
480
|
+
/** Convenience accessor: `points[bestIndex]`. */
|
|
481
|
+
best: SweepPoint;
|
|
482
|
+
/** The original predicate replayed against itself — score baseline for comparison. */
|
|
483
|
+
baseline: SweepPoint;
|
|
484
|
+
}
|
|
485
|
+
/** Hard cap on points evaluated in a single sweep — protects against runaway grids. */
|
|
486
|
+
declare const MAX_SWEEP_POINTS = 10000;
|
|
487
|
+
/**
|
|
488
|
+
* Sweep a predicate template's hole(s) across candidate values and replay
|
|
489
|
+
* the recorded history through each one. Returns the full response curve
|
|
490
|
+
* plus the argmax under a user-supplied objective.
|
|
491
|
+
*
|
|
492
|
+
* The mechanism is a tight loop over `replayUnder`: walk the cartesian
|
|
493
|
+
* product of sweep values, substitute each combination into the template,
|
|
494
|
+
* and run a backtest. Same caveats as `replayUnder` apply (no cascade
|
|
495
|
+
* modeling, survivorship bias) — see {@link replayUnder} docs.
|
|
496
|
+
*
|
|
497
|
+
* @example
|
|
498
|
+
* ```ts
|
|
499
|
+
* const report = sweepUnder({
|
|
500
|
+
* frames: recordedSessions,
|
|
501
|
+
* original: { cartTotal: { $gte: 100 } },
|
|
502
|
+
* template: { cartTotal: { $gte: { $hole: "threshold" } } },
|
|
503
|
+
* sweep: { threshold: [25, 50, 100, 200] },
|
|
504
|
+
* });
|
|
505
|
+
*
|
|
506
|
+
* report.best.values; // { threshold: 25 } (assuming higher matched is better)
|
|
507
|
+
* report.best.report.proposed.matched; // 9210
|
|
508
|
+
* report.baseline.score; // 4217 — the original spec's matched count
|
|
509
|
+
* report.points.length; // 4
|
|
510
|
+
* ```
|
|
511
|
+
*
|
|
512
|
+
* Multi-hole sweeps grid-search:
|
|
513
|
+
*
|
|
514
|
+
* ```ts
|
|
515
|
+
* sweepUnder({
|
|
516
|
+
* frames,
|
|
517
|
+
* original,
|
|
518
|
+
* template: {
|
|
519
|
+
* risk: { $gte: { $hole: "minRisk" } },
|
|
520
|
+
* age: { $gte: { $hole: "minAge" } },
|
|
521
|
+
* },
|
|
522
|
+
* sweep: { minRisk: [0.5, 0.7, 0.9], minAge: [13, 18, 21] },
|
|
523
|
+
* });
|
|
524
|
+
* // → 9 points (3 × 3)
|
|
525
|
+
* ```
|
|
526
|
+
*/
|
|
527
|
+
declare function sweepUnder<F = Record<string, unknown>>(options: SweepUnderOptions<F>): SweepReport;
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Structural diff between two snapshots of a system's constraint `whenSpec`
|
|
531
|
+
* map. The "git diff for business rules" — operates on the predicate AST
|
|
532
|
+
* instead of source-text lines.
|
|
533
|
+
*
|
|
534
|
+
* A predicate is a tree of leaf clauses (`{ fact: operator(value) }`) and
|
|
535
|
+
* combinators (`$all` / `$any` / `$not`). `diffRules` flattens both trees
|
|
536
|
+
* into path-keyed leaf lists and compares: missing path → added/removed,
|
|
537
|
+
* same path with different operand → changed (with relaxed/tightened
|
|
538
|
+
* classification for numeric thresholds).
|
|
539
|
+
*
|
|
540
|
+
* Pure module — imports only utils. No engine / store / predicate-runtime
|
|
541
|
+
* dependency: predicates are walked as plain JSON.
|
|
542
|
+
*/
|
|
543
|
+
/** A leaf clause extracted from a predicate tree, keyed by its dotted path. */
|
|
544
|
+
interface LeafClause {
|
|
545
|
+
/** Dotted path through the predicate. E.g. `phase`, `$all[0].elapsed`, `$not.paused`. */
|
|
546
|
+
path: string;
|
|
547
|
+
/** Operator name. `$eq` is implied for bare-value equality. */
|
|
548
|
+
op: string;
|
|
549
|
+
/** Operand. */
|
|
550
|
+
value: unknown;
|
|
551
|
+
}
|
|
552
|
+
/** Kind of change observed for a single clause. */
|
|
553
|
+
type ChangeKind = "added" | "removed" | "changed" | "relaxed" | "tightened";
|
|
554
|
+
/** A single change between two predicates at a specific path. */
|
|
555
|
+
interface Change {
|
|
556
|
+
path: string;
|
|
557
|
+
kind: ChangeKind;
|
|
558
|
+
before?: {
|
|
559
|
+
op: string;
|
|
560
|
+
value: unknown;
|
|
561
|
+
};
|
|
562
|
+
after?: {
|
|
563
|
+
op: string;
|
|
564
|
+
value: unknown;
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
/** Status of a single constraint across the two snapshots. */
|
|
568
|
+
type ConstraintStatus = "added" | "removed" | "changed" | "unchanged";
|
|
569
|
+
interface ConstraintDiff {
|
|
570
|
+
id: string;
|
|
571
|
+
status: ConstraintStatus;
|
|
572
|
+
/** Empty for `unchanged`. For `added` / `removed`, every leaf is listed once. */
|
|
573
|
+
changes: Change[];
|
|
574
|
+
}
|
|
575
|
+
interface RulesDiffReport {
|
|
576
|
+
constraints: ConstraintDiff[];
|
|
577
|
+
summary: {
|
|
578
|
+
added: number;
|
|
579
|
+
removed: number;
|
|
580
|
+
changed: number;
|
|
581
|
+
unchanged: number;
|
|
582
|
+
totalClauseChanges: number;
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
interface DiffRulesOptions {
|
|
586
|
+
before: RulesMapInput;
|
|
587
|
+
after: RulesMapInput;
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Accepted shapes for the `before` / `after` predicate maps:
|
|
591
|
+
* - A plain map `{ [constraintId]: whenSpec }`
|
|
592
|
+
* - The `system.inspect().constraints` array form `Array<{ id, whenSpec? }>`
|
|
593
|
+
* - Either wrapped as `{ constraints: <one-of-the-above> }`
|
|
594
|
+
*
|
|
595
|
+
* Anything else throws at `toRulesMap` so a bad input fails loud.
|
|
596
|
+
*/
|
|
597
|
+
type RulesMapInput = unknown;
|
|
598
|
+
/**
|
|
599
|
+
* Coerce supported input shapes into a flat `Record<constraintId, whenSpec>`.
|
|
600
|
+
* Constraints without a `whenSpec` (function-form `when`) are dropped with
|
|
601
|
+
* an undefined entry so callers can distinguish them from absent constraints
|
|
602
|
+
* if they care; the diff treats `undefined` as "no data" and skips clause
|
|
603
|
+
* walking.
|
|
604
|
+
*/
|
|
605
|
+
declare function toRulesMap(raw: RulesMapInput): Record<string, unknown>;
|
|
606
|
+
/**
|
|
607
|
+
* Walk a predicate tree and emit every leaf clause with its dotted path.
|
|
608
|
+
* Combinators (`$all` / `$any` / `$not`) become indexed path segments.
|
|
609
|
+
* Bare-value equality (`{ phase: "red" }`) emits as `op: "$eq"`.
|
|
610
|
+
*
|
|
611
|
+
* Array-form predicates (`[{ fact, op, value }, ...]`) are also accepted —
|
|
612
|
+
* each clause's `fact` becomes the path, the operator is `op`, and the
|
|
613
|
+
* value is `value`.
|
|
614
|
+
*
|
|
615
|
+
* **What gets dropped:** non-object combinator children (e.g. `$not: "red"`
|
|
616
|
+
* with a string operand instead of a predicate object), function-form
|
|
617
|
+
* predicates (the engine accepts a function for `when`; this walker only
|
|
618
|
+
* sees data), and bare primitive predicates (a top-level `true` or `"x"`).
|
|
619
|
+
* The walker is a tree visitor — anything not shaped like a predicate node
|
|
620
|
+
* is silently skipped, never thrown on.
|
|
621
|
+
*/
|
|
622
|
+
declare function flattenPredicate(spec: unknown, pathPrefix?: string, out?: LeafClause[]): LeafClause[];
|
|
623
|
+
/**
|
|
624
|
+
* Diff two snapshots of a system's constraint whenSpec map.
|
|
625
|
+
*
|
|
626
|
+
* @example
|
|
627
|
+
* ```ts
|
|
628
|
+
* const report = diffRules({
|
|
629
|
+
* before: { blockCheckout: { cartTotal: { $gte: 100 } } },
|
|
630
|
+
* after: { blockCheckout: { cartTotal: { $gte: 50 } } },
|
|
631
|
+
* });
|
|
632
|
+
*
|
|
633
|
+
* report.constraints[0].status; // "changed"
|
|
634
|
+
* report.constraints[0].changes[0].kind; // "relaxed"
|
|
635
|
+
* report.summary.totalClauseChanges; // 1
|
|
636
|
+
* ```
|
|
637
|
+
*
|
|
638
|
+
* The input shape is forgiving — either a flat `{ id: whenSpec }` map, the
|
|
639
|
+
* `system.inspect().constraints` array form, or either wrapped as
|
|
640
|
+
* `{ constraints: ... }`. Constraints whose `when` is a function (no
|
|
641
|
+
* `whenSpec`) are tracked as added/removed but cannot be clause-diffed
|
|
642
|
+
* (the function form is opaque).
|
|
643
|
+
*/
|
|
644
|
+
declare function diffRules(options: DiffRulesOptions): RulesDiffReport;
|
|
645
|
+
/**
|
|
646
|
+
* Diff two predicate trees and return the list of leaf-level changes.
|
|
647
|
+
* Exported for reuse beyond the full per-constraint report.
|
|
648
|
+
*/
|
|
649
|
+
declare function diffClauses(before: unknown, after: unknown): Change[];
|
|
650
|
+
|
|
406
651
|
/** Brand symbol for branded types */
|
|
407
652
|
declare const Brand: unique symbol;
|
|
408
653
|
/** Branded type - adds a unique brand to a base type */
|
|
@@ -1663,4 +1908,4 @@ declare const Backoff: {
|
|
|
1663
1908
|
readonly Exponential: "exponential";
|
|
1664
1909
|
};
|
|
1665
1910
|
|
|
1666
|
-
export { Backoff, type Branded, type ChainableSchemaType, ClauseResult, CreateSystemOptionsNamed, CreateSystemOptionsSingle, CrossModuleDeps, DefinitionMeta, ErrorBoundaryConfig, type ExtendedSchemaType, FactPredicate, FactTemplate, Facts, MAX_REPLAY_FRAMES, type ModuleConfig, type ModuleConfigWithDeps, ModuleDef, ModuleHooks, ModuleSchema, ModulesMap, NamespacedSystem, PatchSpec, Plugin, type PredicateBacktestReport, type ReplayDiffSample, type ReplayFrame, type ReplayUnderOptions, Requirement, RequirementSet, type RequirementTypeStatus, RequirementWithId, SchemaType, type SignalClock, SingleModuleSystem, type TimerFactOpts, type TimerFactState, TraceOption, applyPatch, completeTimer, createModule, createModuleFactory, createRequirementStatusPlugin, createStatusHook, createSystem, createSystemWithStatus, defaultClock, elapsedMs, evaluateKeySelector, evaluatePredicate, evaluatePredicateExplained, evaluateTemplate, extractDeps, extractTemplateKeys, forType, framesFromHistory, framesFromSnapshots, generateRequirementId, initialTimerState, isPredicate, isRequirementType, isTemplate, memoizePredicate, pauseTimer, realClock, registerRepeat, remainingMs, replayUnder, req, resetTimer, resumeTimer, startTimer, t, tickTimer, timerOps, toReplayFrames, validatePredicate, virtualClock };
|
|
1911
|
+
export { Backoff, type Branded, type ChainableSchemaType, type Change, type ChangeKind, ClauseResult, type ConstraintDiff, type ConstraintStatus, CreateSystemOptionsNamed, CreateSystemOptionsSingle, CrossModuleDeps, DefinitionMeta, type DiffRulesOptions, ErrorBoundaryConfig, type ExtendedSchemaType, FactPredicate, FactTemplate, Facts, type LeafClause, MAX_REPLAY_FRAMES, MAX_SWEEP_POINTS, type ModuleConfig, type ModuleConfigWithDeps, ModuleDef, ModuleHooks, ModuleSchema, ModulesMap, NamespacedSystem, PatchSpec, Plugin, type PredicateBacktestReport, type ReplayDiffSample, type ReplayFrame, type ReplayUnderOptions, Requirement, RequirementSet, type RequirementTypeStatus, RequirementWithId, type RulesDiffReport, type RulesMapInput, SchemaType, type SignalClock, SingleModuleSystem, type SweepHole, type SweepPoint, type SweepReport, type SweepUnderOptions, type TimerFactOpts, type TimerFactState, TraceOption, applyPatch, completeTimer, createModule, createModuleFactory, createRequirementStatusPlugin, createStatusHook, createSystem, createSystemWithStatus, defaultClock, diffClauses, diffRules, elapsedMs, evaluateKeySelector, evaluatePredicate, evaluatePredicateExplained, evaluateTemplate, extractDeps, extractTemplateKeys, flattenPredicate, forType, framesFromHistory, framesFromSnapshots, generateRequirementId, initialTimerState, isPredicate, isRequirementType, isTemplate, memoizePredicate, pauseTimer, realClock, registerRepeat, remainingMs, replayUnder, req, resetTimer, resumeTimer, startTimer, sweepUnder, t, tickTimer, timerOps, toReplayFrames, toRulesMap, validatePredicate, virtualClock };
|
package/dist/index.d.ts
CHANGED
|
@@ -403,6 +403,251 @@ declare function framesFromSnapshots(snapshots: unknown): ReplayFrame[];
|
|
|
403
403
|
*/
|
|
404
404
|
declare function replayUnder<F = Record<string, unknown>>(options: ReplayUnderOptions<F>): PredicateBacktestReport;
|
|
405
405
|
|
|
406
|
+
/**
|
|
407
|
+
* Parameter sweep over a predicate template — the grid-search counterpart
|
|
408
|
+
* to `replayUnder`.
|
|
409
|
+
*
|
|
410
|
+
* `replayUnder` diffs ONE proposed predicate against the original.
|
|
411
|
+
* `sweepUnder` takes a **template** with one or more `{ $hole: "name" }`
|
|
412
|
+
* markers and a set of candidate values, then replays the history once
|
|
413
|
+
* per (cartesian-product) combination. The result is a response curve
|
|
414
|
+
* over the parameter space plus the argmax under a user-supplied
|
|
415
|
+
* objective — turning rule-tuning from guess-and-check into a one-call
|
|
416
|
+
* optimization against recorded traffic.
|
|
417
|
+
*
|
|
418
|
+
* Pure module — imports only the predicate runtime and replay engine.
|
|
419
|
+
* No engine / store / tracking dependency.
|
|
420
|
+
*/
|
|
421
|
+
|
|
422
|
+
/** A placeholder inside a predicate template — substituted from `sweep` values. */
|
|
423
|
+
interface SweepHole {
|
|
424
|
+
readonly $hole: string;
|
|
425
|
+
}
|
|
426
|
+
interface SweepUnderOptions<F = Record<string, unknown>> {
|
|
427
|
+
/** Recorded fact-state frames, in chronological order. */
|
|
428
|
+
frames: readonly ReplayFrame<F>[];
|
|
429
|
+
/** The constraint's current `when` predicate (baseline). */
|
|
430
|
+
original: FactPredicate<F>;
|
|
431
|
+
/**
|
|
432
|
+
* Predicate template containing one or more `{ $hole: "name" }` markers.
|
|
433
|
+
* Each marker is substituted by the corresponding value from `sweep` on
|
|
434
|
+
* every point in the curve.
|
|
435
|
+
*
|
|
436
|
+
* @example
|
|
437
|
+
* ```ts
|
|
438
|
+
* { cartTotal: { $gte: { $hole: "threshold" } } }
|
|
439
|
+
* ```
|
|
440
|
+
*/
|
|
441
|
+
template: unknown;
|
|
442
|
+
/**
|
|
443
|
+
* Map of hole name → candidate values. Multiple holes produce the
|
|
444
|
+
* cartesian product (grid search).
|
|
445
|
+
*
|
|
446
|
+
* @example
|
|
447
|
+
* ```ts
|
|
448
|
+
* { threshold: [25, 50, 100, 200] }
|
|
449
|
+
* { riskScore: [0.5, 0.7, 0.9], minAge: [13, 18, 21] } // 3*3 = 9 points
|
|
450
|
+
* ```
|
|
451
|
+
*/
|
|
452
|
+
sweep: Readonly<Record<string, readonly unknown[]>>;
|
|
453
|
+
/**
|
|
454
|
+
* Score function for ranking. Higher is better. Default:
|
|
455
|
+
* `(report) => report.proposed.matched` (maximize matched frames).
|
|
456
|
+
*/
|
|
457
|
+
objective?: (report: PredicateBacktestReport) => number;
|
|
458
|
+
/** Optional fact key to additionally report distinct-entity counts. */
|
|
459
|
+
entityKey?: string;
|
|
460
|
+
/**
|
|
461
|
+
* Diff frames sampled per replay (default 0 — count-only for speed).
|
|
462
|
+
* Set higher to inspect specific frames in the report.
|
|
463
|
+
*/
|
|
464
|
+
maxSamples?: number;
|
|
465
|
+
}
|
|
466
|
+
/** One point on the sweep curve — one candidate value tuple. */
|
|
467
|
+
interface SweepPoint {
|
|
468
|
+
/** Hole name → value used at this point. */
|
|
469
|
+
values: Readonly<Record<string, unknown>>;
|
|
470
|
+
/** Full backtest report against this candidate. */
|
|
471
|
+
report: PredicateBacktestReport;
|
|
472
|
+
/** Computed objective score (higher is better). */
|
|
473
|
+
score: number;
|
|
474
|
+
}
|
|
475
|
+
interface SweepReport {
|
|
476
|
+
/** All points, in sweep order (cartesian-product traversal of sweep keys). */
|
|
477
|
+
points: readonly SweepPoint[];
|
|
478
|
+
/** Index of the highest-scoring point in `points`. */
|
|
479
|
+
bestIndex: number;
|
|
480
|
+
/** Convenience accessor: `points[bestIndex]`. */
|
|
481
|
+
best: SweepPoint;
|
|
482
|
+
/** The original predicate replayed against itself — score baseline for comparison. */
|
|
483
|
+
baseline: SweepPoint;
|
|
484
|
+
}
|
|
485
|
+
/** Hard cap on points evaluated in a single sweep — protects against runaway grids. */
|
|
486
|
+
declare const MAX_SWEEP_POINTS = 10000;
|
|
487
|
+
/**
|
|
488
|
+
* Sweep a predicate template's hole(s) across candidate values and replay
|
|
489
|
+
* the recorded history through each one. Returns the full response curve
|
|
490
|
+
* plus the argmax under a user-supplied objective.
|
|
491
|
+
*
|
|
492
|
+
* The mechanism is a tight loop over `replayUnder`: walk the cartesian
|
|
493
|
+
* product of sweep values, substitute each combination into the template,
|
|
494
|
+
* and run a backtest. Same caveats as `replayUnder` apply (no cascade
|
|
495
|
+
* modeling, survivorship bias) — see {@link replayUnder} docs.
|
|
496
|
+
*
|
|
497
|
+
* @example
|
|
498
|
+
* ```ts
|
|
499
|
+
* const report = sweepUnder({
|
|
500
|
+
* frames: recordedSessions,
|
|
501
|
+
* original: { cartTotal: { $gte: 100 } },
|
|
502
|
+
* template: { cartTotal: { $gte: { $hole: "threshold" } } },
|
|
503
|
+
* sweep: { threshold: [25, 50, 100, 200] },
|
|
504
|
+
* });
|
|
505
|
+
*
|
|
506
|
+
* report.best.values; // { threshold: 25 } (assuming higher matched is better)
|
|
507
|
+
* report.best.report.proposed.matched; // 9210
|
|
508
|
+
* report.baseline.score; // 4217 — the original spec's matched count
|
|
509
|
+
* report.points.length; // 4
|
|
510
|
+
* ```
|
|
511
|
+
*
|
|
512
|
+
* Multi-hole sweeps grid-search:
|
|
513
|
+
*
|
|
514
|
+
* ```ts
|
|
515
|
+
* sweepUnder({
|
|
516
|
+
* frames,
|
|
517
|
+
* original,
|
|
518
|
+
* template: {
|
|
519
|
+
* risk: { $gte: { $hole: "minRisk" } },
|
|
520
|
+
* age: { $gte: { $hole: "minAge" } },
|
|
521
|
+
* },
|
|
522
|
+
* sweep: { minRisk: [0.5, 0.7, 0.9], minAge: [13, 18, 21] },
|
|
523
|
+
* });
|
|
524
|
+
* // → 9 points (3 × 3)
|
|
525
|
+
* ```
|
|
526
|
+
*/
|
|
527
|
+
declare function sweepUnder<F = Record<string, unknown>>(options: SweepUnderOptions<F>): SweepReport;
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Structural diff between two snapshots of a system's constraint `whenSpec`
|
|
531
|
+
* map. The "git diff for business rules" — operates on the predicate AST
|
|
532
|
+
* instead of source-text lines.
|
|
533
|
+
*
|
|
534
|
+
* A predicate is a tree of leaf clauses (`{ fact: operator(value) }`) and
|
|
535
|
+
* combinators (`$all` / `$any` / `$not`). `diffRules` flattens both trees
|
|
536
|
+
* into path-keyed leaf lists and compares: missing path → added/removed,
|
|
537
|
+
* same path with different operand → changed (with relaxed/tightened
|
|
538
|
+
* classification for numeric thresholds).
|
|
539
|
+
*
|
|
540
|
+
* Pure module — imports only utils. No engine / store / predicate-runtime
|
|
541
|
+
* dependency: predicates are walked as plain JSON.
|
|
542
|
+
*/
|
|
543
|
+
/** A leaf clause extracted from a predicate tree, keyed by its dotted path. */
|
|
544
|
+
interface LeafClause {
|
|
545
|
+
/** Dotted path through the predicate. E.g. `phase`, `$all[0].elapsed`, `$not.paused`. */
|
|
546
|
+
path: string;
|
|
547
|
+
/** Operator name. `$eq` is implied for bare-value equality. */
|
|
548
|
+
op: string;
|
|
549
|
+
/** Operand. */
|
|
550
|
+
value: unknown;
|
|
551
|
+
}
|
|
552
|
+
/** Kind of change observed for a single clause. */
|
|
553
|
+
type ChangeKind = "added" | "removed" | "changed" | "relaxed" | "tightened";
|
|
554
|
+
/** A single change between two predicates at a specific path. */
|
|
555
|
+
interface Change {
|
|
556
|
+
path: string;
|
|
557
|
+
kind: ChangeKind;
|
|
558
|
+
before?: {
|
|
559
|
+
op: string;
|
|
560
|
+
value: unknown;
|
|
561
|
+
};
|
|
562
|
+
after?: {
|
|
563
|
+
op: string;
|
|
564
|
+
value: unknown;
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
/** Status of a single constraint across the two snapshots. */
|
|
568
|
+
type ConstraintStatus = "added" | "removed" | "changed" | "unchanged";
|
|
569
|
+
interface ConstraintDiff {
|
|
570
|
+
id: string;
|
|
571
|
+
status: ConstraintStatus;
|
|
572
|
+
/** Empty for `unchanged`. For `added` / `removed`, every leaf is listed once. */
|
|
573
|
+
changes: Change[];
|
|
574
|
+
}
|
|
575
|
+
interface RulesDiffReport {
|
|
576
|
+
constraints: ConstraintDiff[];
|
|
577
|
+
summary: {
|
|
578
|
+
added: number;
|
|
579
|
+
removed: number;
|
|
580
|
+
changed: number;
|
|
581
|
+
unchanged: number;
|
|
582
|
+
totalClauseChanges: number;
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
interface DiffRulesOptions {
|
|
586
|
+
before: RulesMapInput;
|
|
587
|
+
after: RulesMapInput;
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Accepted shapes for the `before` / `after` predicate maps:
|
|
591
|
+
* - A plain map `{ [constraintId]: whenSpec }`
|
|
592
|
+
* - The `system.inspect().constraints` array form `Array<{ id, whenSpec? }>`
|
|
593
|
+
* - Either wrapped as `{ constraints: <one-of-the-above> }`
|
|
594
|
+
*
|
|
595
|
+
* Anything else throws at `toRulesMap` so a bad input fails loud.
|
|
596
|
+
*/
|
|
597
|
+
type RulesMapInput = unknown;
|
|
598
|
+
/**
|
|
599
|
+
* Coerce supported input shapes into a flat `Record<constraintId, whenSpec>`.
|
|
600
|
+
* Constraints without a `whenSpec` (function-form `when`) are dropped with
|
|
601
|
+
* an undefined entry so callers can distinguish them from absent constraints
|
|
602
|
+
* if they care; the diff treats `undefined` as "no data" and skips clause
|
|
603
|
+
* walking.
|
|
604
|
+
*/
|
|
605
|
+
declare function toRulesMap(raw: RulesMapInput): Record<string, unknown>;
|
|
606
|
+
/**
|
|
607
|
+
* Walk a predicate tree and emit every leaf clause with its dotted path.
|
|
608
|
+
* Combinators (`$all` / `$any` / `$not`) become indexed path segments.
|
|
609
|
+
* Bare-value equality (`{ phase: "red" }`) emits as `op: "$eq"`.
|
|
610
|
+
*
|
|
611
|
+
* Array-form predicates (`[{ fact, op, value }, ...]`) are also accepted —
|
|
612
|
+
* each clause's `fact` becomes the path, the operator is `op`, and the
|
|
613
|
+
* value is `value`.
|
|
614
|
+
*
|
|
615
|
+
* **What gets dropped:** non-object combinator children (e.g. `$not: "red"`
|
|
616
|
+
* with a string operand instead of a predicate object), function-form
|
|
617
|
+
* predicates (the engine accepts a function for `when`; this walker only
|
|
618
|
+
* sees data), and bare primitive predicates (a top-level `true` or `"x"`).
|
|
619
|
+
* The walker is a tree visitor — anything not shaped like a predicate node
|
|
620
|
+
* is silently skipped, never thrown on.
|
|
621
|
+
*/
|
|
622
|
+
declare function flattenPredicate(spec: unknown, pathPrefix?: string, out?: LeafClause[]): LeafClause[];
|
|
623
|
+
/**
|
|
624
|
+
* Diff two snapshots of a system's constraint whenSpec map.
|
|
625
|
+
*
|
|
626
|
+
* @example
|
|
627
|
+
* ```ts
|
|
628
|
+
* const report = diffRules({
|
|
629
|
+
* before: { blockCheckout: { cartTotal: { $gte: 100 } } },
|
|
630
|
+
* after: { blockCheckout: { cartTotal: { $gte: 50 } } },
|
|
631
|
+
* });
|
|
632
|
+
*
|
|
633
|
+
* report.constraints[0].status; // "changed"
|
|
634
|
+
* report.constraints[0].changes[0].kind; // "relaxed"
|
|
635
|
+
* report.summary.totalClauseChanges; // 1
|
|
636
|
+
* ```
|
|
637
|
+
*
|
|
638
|
+
* The input shape is forgiving — either a flat `{ id: whenSpec }` map, the
|
|
639
|
+
* `system.inspect().constraints` array form, or either wrapped as
|
|
640
|
+
* `{ constraints: ... }`. Constraints whose `when` is a function (no
|
|
641
|
+
* `whenSpec`) are tracked as added/removed but cannot be clause-diffed
|
|
642
|
+
* (the function form is opaque).
|
|
643
|
+
*/
|
|
644
|
+
declare function diffRules(options: DiffRulesOptions): RulesDiffReport;
|
|
645
|
+
/**
|
|
646
|
+
* Diff two predicate trees and return the list of leaf-level changes.
|
|
647
|
+
* Exported for reuse beyond the full per-constraint report.
|
|
648
|
+
*/
|
|
649
|
+
declare function diffClauses(before: unknown, after: unknown): Change[];
|
|
650
|
+
|
|
406
651
|
/** Brand symbol for branded types */
|
|
407
652
|
declare const Brand: unique symbol;
|
|
408
653
|
/** Branded type - adds a unique brand to a base type */
|
|
@@ -1663,4 +1908,4 @@ declare const Backoff: {
|
|
|
1663
1908
|
readonly Exponential: "exponential";
|
|
1664
1909
|
};
|
|
1665
1910
|
|
|
1666
|
-
export { Backoff, type Branded, type ChainableSchemaType, ClauseResult, CreateSystemOptionsNamed, CreateSystemOptionsSingle, CrossModuleDeps, DefinitionMeta, ErrorBoundaryConfig, type ExtendedSchemaType, FactPredicate, FactTemplate, Facts, MAX_REPLAY_FRAMES, type ModuleConfig, type ModuleConfigWithDeps, ModuleDef, ModuleHooks, ModuleSchema, ModulesMap, NamespacedSystem, PatchSpec, Plugin, type PredicateBacktestReport, type ReplayDiffSample, type ReplayFrame, type ReplayUnderOptions, Requirement, RequirementSet, type RequirementTypeStatus, RequirementWithId, SchemaType, type SignalClock, SingleModuleSystem, type TimerFactOpts, type TimerFactState, TraceOption, applyPatch, completeTimer, createModule, createModuleFactory, createRequirementStatusPlugin, createStatusHook, createSystem, createSystemWithStatus, defaultClock, elapsedMs, evaluateKeySelector, evaluatePredicate, evaluatePredicateExplained, evaluateTemplate, extractDeps, extractTemplateKeys, forType, framesFromHistory, framesFromSnapshots, generateRequirementId, initialTimerState, isPredicate, isRequirementType, isTemplate, memoizePredicate, pauseTimer, realClock, registerRepeat, remainingMs, replayUnder, req, resetTimer, resumeTimer, startTimer, t, tickTimer, timerOps, toReplayFrames, validatePredicate, virtualClock };
|
|
1911
|
+
export { Backoff, type Branded, type ChainableSchemaType, type Change, type ChangeKind, ClauseResult, type ConstraintDiff, type ConstraintStatus, CreateSystemOptionsNamed, CreateSystemOptionsSingle, CrossModuleDeps, DefinitionMeta, type DiffRulesOptions, ErrorBoundaryConfig, type ExtendedSchemaType, FactPredicate, FactTemplate, Facts, type LeafClause, MAX_REPLAY_FRAMES, MAX_SWEEP_POINTS, type ModuleConfig, type ModuleConfigWithDeps, ModuleDef, ModuleHooks, ModuleSchema, ModulesMap, NamespacedSystem, PatchSpec, Plugin, type PredicateBacktestReport, type ReplayDiffSample, type ReplayFrame, type ReplayUnderOptions, Requirement, RequirementSet, type RequirementTypeStatus, RequirementWithId, type RulesDiffReport, type RulesMapInput, SchemaType, type SignalClock, SingleModuleSystem, type SweepHole, type SweepPoint, type SweepReport, type SweepUnderOptions, type TimerFactOpts, type TimerFactState, TraceOption, applyPatch, completeTimer, createModule, createModuleFactory, createRequirementStatusPlugin, createStatusHook, createSystem, createSystemWithStatus, defaultClock, diffClauses, diffRules, elapsedMs, evaluateKeySelector, evaluatePredicate, evaluatePredicateExplained, evaluateTemplate, extractDeps, extractTemplateKeys, flattenPredicate, forType, framesFromHistory, framesFromSnapshots, generateRequirementId, initialTimerState, isPredicate, isRequirementType, isTemplate, memoizePredicate, pauseTimer, realClock, registerRepeat, remainingMs, replayUnder, req, resetTimer, resumeTimer, startTimer, sweepUnder, t, tickTimer, timerOps, toReplayFrames, toRulesMap, validatePredicate, virtualClock };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {a as a$1}from'./chunk-2PLP22ZU.js';export{a as createSystem}from'./chunk-2PLP22ZU.js';import {g,h,f as f$1,c as c$1,d,a as a$2,b}from'./chunk-JFUK5NIO.js';export{p as DirectiveError,C as RequirementSet,n as applyPatch,m as evaluateKeySelector,g as evaluatePredicate,h as evaluatePredicateExplained,k as evaluateTemplate,j as extractDeps,l as extractTemplateKeys,B as forType,y as generateRequirementId,v as isNamespacedSystem,c as isPredicate,A as isRequirementType,u as isSingleModuleSystem,e as isTemplate,i as memoizePredicate,z as req,s as typedConstraint,t as typedResolver,f as validatePredicate}from'./chunk-JFUK5NIO.js';import {a,l}from'./chunk-TZHC4E6S.js';export{j as diffSnapshots,k as isSignedSnapshot,h as isSnapshotExpired,f as shallowEqual,l as signSnapshot,i as validateSnapshot,m as verifySnapshotSignature}from'./chunk-T6IJUWYR.js';var f=1e6;function I(e,t){try{f$1(e);}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(`[Directive] replayUnder: the ${t} predicate is invalid \u2014 ${i}`)}if(!c$1(e)){let r=e===null||typeof e!="object"?`${typeof e} \u2014 ${JSON.stringify(e)}`:JSON.stringify(e).slice(0,80);throw new Error(`[Directive] replayUnder: the ${t} predicate is not a valid FactPredicate (got ${r})`)}let n;if(d(e,{operator(r,i){n===void 0&&i.startsWith("$")&&!a$2.has(i)&&(n=i);},strayOperatorKey(r){n===void 0&&!a$2.has(r)&&!b.has(r)&&(n=r);}}),n!==void 0)throw new Error(`[Directive] replayUnder: the ${t} predicate uses an unknown operator "${n}" \u2014 known operators: ${[...a$2].join(", ")}`)}function N(e){if(e&&typeof e=="object"&&!Array.isArray(e)&&Array.isArray(e.snapshots))return W(e);let t=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.frames)?e.frames:null;if(!t)throw new Error("[Directive] toReplayFrames: history must be a JSON array of frames, an object with a `frames` array, or a history export with a `snapshots` array");if(t.length>f)throw new Error(`[Directive] toReplayFrames: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${f}) \u2014 split or down-sample the history`);return t.map((n,r)=>{if(n&&typeof n=="object"&&"facts"in n){let i=n,o={id:i.id??`#${r}`,facts:i.facts??{}};return typeof i.timestamp=="number"&&(o.timestamp=i.timestamp),o}return {id:`#${r}`,facts:n??{}}})}function W(e){let t=typeof e=="string"?JSON.parse(e):e;if(Array.isArray(t))return O(t);if(!t||typeof t!="object")throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");let n=t;if(n.version!==void 0&&n.version!==1)throw new Error(`[Directive] framesFromHistory: unsupported history export version ${JSON.stringify(n.version)} \u2014 expected 1`);if(!Array.isArray(n.snapshots))throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");return O(n.snapshots)}function O(e){if(!Array.isArray(e))throw new Error("[Directive] framesFromSnapshots: expected an array of fact-state snapshots");if(e.length>f)throw new Error(`[Directive] framesFromSnapshots: history has ${e.length} snapshots, exceeds the MAX_REPLAY_FRAMES limit (${f}) \u2014 split or down-sample the history`);for(let t=0;t<e.length;t++){let n=e[t];if(!n||typeof n!="object"||!("facts"in n))throw new Error(`[Directive] framesFromSnapshots: snapshot at index ${t} is not a { facts, ... } object`)}return N(e)}function we(e){let{frames:t,original:n,proposed:r,entityKey:i}=e,o=e.maxSamples??20,a=o>0?o:0;if(t.length>f)throw new Error(`[Directive] replayUnder: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${f}) \u2014 split or down-sample the history`);I(n,"original"),I(r,"proposed");let p=0,s=0,u=0,l=0,d=0,m=[],y=[],h=i?new Set:void 0,x=i?new Set:void 0,g$1;for(let k of t){let T=k.facts,R=g(n,T,g$1),E=g(r,T,g$1);R&&(p++,h?.add(T[i])),E&&(s++,x?.add(T[i])),R===E?d++:!R&&E?(u++,m.length<a&&m.push(U(k,n,r,g$1))):(l++,y.length<a&&y.push(U(k,n,r,g$1))),g$1=T;}let C={framesEvaluated:t.length,original:{matched:p},proposed:{matched:s},delta:s-p,newMatchCount:u,lostMatchCount:l,unchanged:d,newMatches:m,lostMatches:y};return h&&x&&(C.original.matchedEntities=h.size,C.proposed.matchedEntities=x.size),C}function U(e,t,n,r){let i=e.facts,o={frameId:e.id,facts:i,originalExplain:h(t,i,r),proposedExplain:h(n,i,r)};return e.timestamp!==void 0&&(o.timestamp=e.timestamp),o}function D(e=[],t,n,r,i,o,a){return {_type:void 0,_validators:e,_typeName:t,_default:n,_transform:r,_description:i,_refinements:o,_meta:a,validate(p){return D([...e,p],t,n,r,i,o,a)}}}function c(e,t,n,r,i,o,a){return {...D(e,t,n,r,i,o,a),default(s){return c(e,t,s,r,i,o,a)},transform(s){return c([],t,void 0,l=>{let d=r?r(l):l;return s(d)},i,void 0,a)},brand(){return c(e,`Branded<${t}>`,n,r,i,o,a)},describe(s){return c(e,t,n,r,s,o,a)},refine(s,u){let l=[...o??[],{predicate:s,message:u}];return c([...e,s],t,n,r,i,l,a)},nullable(){return c([s=>s===null||e.every(u=>u(s))],`${t} | null`,n,r,i,void 0,a)},optional(){return c([s=>s===void 0||e.every(u=>u(s))],`${t} | undefined`,n,r,i,void 0,a)},meta(s){return c(e,t,n,r,i,o,s)}}}var xe=((...e)=>{if(e.length===0)return c([],"union");let t=e.map(n=>n._typeName??"unknown");return c([n=>e.some(r=>r._validators.every(i=>i(n)))],t.join(" | "))}),Ce={string(){let e=(t,n,r,i,o,a)=>({...c(t,"string",n,r,i,o,a),minLength(s){return e([...t,u=>u.length>=s],n,r,i,o,a)},maxLength(s){return e([...t,u=>u.length<=s],n,r,i,o,a)},pattern(s){return e([...t,u=>s.test(u)],n,r,i,o,a)},default(s){return e(t,s,r,i,o,a)},describe(s){return e(t,n,r,s,o,a)},refine(s,u){let l=[...o??[],{predicate:s,message:u}];return e([...t,s],n,r,i,l,a)},meta(s){return e(t,n,r,i,o,s)}});return e([t=>typeof t=="string"])},number(){let e=(t,n,r,i,o,a)=>({...c(t,"number",n,r,i,o,a),min(s){return e([...t,u=>u>=s],n,r,i,o,a)},max(s){return e([...t,u=>u<=s],n,r,i,o,a)},default(s){return e(t,s,r,i,o,a)},describe(s){return e(t,n,r,s,o,a)},refine(s,u){let l=[...o??[],{predicate:s,message:u}];return e([...t,s],n,r,i,l,a)},meta(s){return e(t,n,r,i,o,s)}});return e([t=>typeof t=="number"])},boolean(){return c([e=>typeof e=="boolean"],"boolean")},array(){let e=(t,n,r,i,o,a)=>{let p=c(t,"array",r,void 0,i,void 0,a),s=o??{value:-1};return {...p,get _lastFailedIndex(){return s.value},set _lastFailedIndex(l){s.value=l;},of(l){let d={value:-1};return e([...t,m=>{for(let y=0;y<m.length;y++)if(!l._validators.every(h=>h(m[y])))return d.value=y,false;return true}],l,r,i,d,a)},nonEmpty(){return e([...t,l=>l.length>0],n,r,i,s,a)},maxLength(l){return e([...t,d=>d.length<=l],n,r,i,s,a)},minLength(l){return e([...t,d=>d.length>=l],n,r,i,s,a)},default(l){return e(t,n,l,i,s,a)},describe(l){return e(t,n,r,l,s,a)},meta(l){return e(t,n,r,i,s,l)}}};return e([t=>Array.isArray(t)])},object(){let e=(t,n,r,i)=>({...c(t,"object",n,void 0,r,void 0,i),shape(a){return e([...t,p=>{for(let[s,u]of Object.entries(a)){let l=p[s],d=u;if(d&&!d._validators.every(m=>m(l)))return false}return true}],n,r,i)},nonNull(){return e([...t,a=>a!=null],n,r,i)},hasKeys(...a){return e([...t,p=>a.every(s=>s in p)],n,r,i)},default(a){return e(t,a,r,i)},describe(a){return e(t,n,a,i)},meta(a){return e(t,n,r,a)}});return e([t=>typeof t=="object"&&t!==null&&!Array.isArray(t)])},enum(...e){a&&e.length===0&&console.warn("[Directive] t.enum() called with no values - this will reject all strings");let t=new Set(e);return c([n=>typeof n=="string"&&t.has(n)],`enum(${e.join("|")})`)},literal(e){return c([t=>t===e],`literal(${String(e)})`)},nullable(e){let t=e._typeName??"unknown";return D([n=>n===null?true:e._validators.every(r=>r(n))],`${t} | null`)},optional(e){let t=e._typeName??"unknown";return D([n=>n===void 0?true:e._validators.every(r=>r(n))],`${t} | undefined`)},union:xe,record(e){let t=e._typeName??"unknown";return c([n=>typeof n!="object"||n===null||Array.isArray(n)?false:Object.values(n).every(r=>e._validators.every(i=>i(r)))],`Record<string, ${t}>`)},tuple(...e){a&&e.length===0&&console.warn("[Directive] t.tuple() called with no types - this will only accept empty arrays");let t=e.map(n=>n._typeName??"unknown");return c([n=>!Array.isArray(n)||n.length!==e.length?false:e.every((r,i)=>r._validators.every(o=>o(n[i])))],`[${t.join(", ")}]`)},date(){return c([e=>e instanceof Date&&!Number.isNaN(e.getTime())],"Date")},uuid(){let e=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;return c([t=>typeof t=="string"&&e.test(t)],"uuid")},email(){let e=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;return c([t=>typeof t=="string"&&e.test(t)],"email")},url(){return c([e=>{if(typeof e!="string")return false;try{return new URL(e),!0}catch{return false}}],"url")},bigint(){return c([e=>typeof e=="bigint"],"bigint")},any(){return c([],"any")},unknown(){return c([],"unknown")}};function ke(e){if(!e||typeof e!="string"){console.warn("[Directive] Module ID must be a non-empty string");return}/^(__[a-z][a-z0-9_-]*|[a-z][a-z0-9-]*)$/i.test(e)||console.warn(`[Directive] Module ID "${e}" should follow kebab-case convention (e.g., "my-module")`);}function K(e,t,n,r,i){for(let o of e)t.has(o)||console.warn(`[Directive] ${n} "${o}" not declared in ${r}`);for(let o of t)e.has(o)||console.warn(`[Directive] ${r}["${o}"] ${i}`);}function Re(e,t){e.length===0&&console.warn("[Directive] history.snapshotEvents is an empty array \u2014 no events will create history snapshots. Omit history.snapshotEvents entirely to snapshot all events, or list specific events.");let n=new Set(Object.keys(t));for(let r of e)n.has(r)||console.warn(`[Directive] history.snapshotEvents entry "${r}" not declared in schema.events. Available events: ${[...n].join(", ")||"(none)"}`);}function Ee(e,t){let n=new Set(Object.keys(t));for(let[r,i]of Object.entries(e)){let o=i;typeof o.requirement=="string"&&!n.has(o.requirement)&&console.warn(`[Directive] Resolver "${r}" references unknown requirement type "${o.requirement}". Available types: ${[...n].join(", ")||"(none)"}`);}}function Ae(e,t){let n=t.schema?.facts??{},r=Object.keys(n);if(r.length===0)return;let i=new Set(["self","prev","current"]),o="crossModuleDeps"in t&&t.crossModuleDeps?Object.keys(t.crossModuleDeps):[];for(let a of o)i.add(a);for(let a of r)if(i.has(a))throw new Error(`[Directive] module '${e}': fact key '${a}' conflicts with a reserved namespace pivot or evaluation alias (self / prev / current / a crossModuleDep namespace). Three fixes:
|
|
1
|
+
import {a as a$1}from'./chunk-FCOZCTLY.js';export{a as createSystem}from'./chunk-FCOZCTLY.js';import {h,i,g,d as d$1,e,a as a$2,b,c}from'./chunk-ZE2RY5KP.js';export{q as DirectiveError,D as RequirementSet,o as applyPatch,n as evaluateKeySelector,h as evaluatePredicate,i as evaluatePredicateExplained,l as evaluateTemplate,k as extractDeps,m as extractTemplateKeys,C as forType,z as generateRequirementId,w as isNamespacedSystem,d as isPredicate,B as isRequirementType,v as isSingleModuleSystem,f as isTemplate,j as memoizePredicate,A as req,t as typedConstraint,u as typedResolver,g as validatePredicate}from'./chunk-ZE2RY5KP.js';import {a,l}from'./chunk-TZHC4E6S.js';import {d}from'./chunk-T6IJUWYR.js';export{j as diffSnapshots,k as isSignedSnapshot,h as isSnapshotExpired,f as shallowEqual,l as signSnapshot,i as validateSnapshot,m as verifySnapshotSignature}from'./chunk-T6IJUWYR.js';var v=1e6;function J(e$1,n){try{g(e$1);}catch(r){let s=r instanceof Error?r.message:String(r);throw new Error(`[Directive] replayUnder: the ${n} predicate is invalid \u2014 ${s}`)}if(!d$1(e$1)){let r=e$1===null||typeof e$1!="object"?`${typeof e$1} \u2014 ${JSON.stringify(e$1)}`:JSON.stringify(e$1).slice(0,80);throw new Error(`[Directive] replayUnder: the ${n} predicate is not a valid FactPredicate (got ${r})`)}let t;if(e(e$1,{operator(r,s){t===void 0&&s.startsWith("$")&&!a$2.has(s)&&(t=s);},strayOperatorKey(r){t===void 0&&!a$2.has(r)&&!b.has(r)&&(t=r);}}),t!==void 0)throw new Error(`[Directive] replayUnder: the ${n} predicate uses an unknown operator "${t}" \u2014 known operators: ${[...a$2].join(", ")}`)}function Q(e){if(e&&typeof e=="object"&&!Array.isArray(e)&&Array.isArray(e.snapshots))return Z(e);let n=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.frames)?e.frames:null;if(!n)throw new Error("[Directive] toReplayFrames: history must be a JSON array of frames, an object with a `frames` array, or a history export with a `snapshots` array");if(n.length>v)throw new Error(`[Directive] toReplayFrames: history has ${n.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${v}) \u2014 split or down-sample the history`);return n.map((t,r)=>{if(t&&typeof t=="object"&&"facts"in t){let s=t,o={id:s.id??`#${r}`,facts:s.facts??{}};return typeof s.timestamp=="number"&&(o.timestamp=s.timestamp),o}return {id:`#${r}`,facts:t??{}}})}function Z(e){let n=typeof e=="string"?JSON.parse(e):e;if(Array.isArray(n))return N(n);if(!n||typeof n!="object")throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");let t=n;if(t.version!==void 0&&t.version!==1)throw new Error(`[Directive] framesFromHistory: unsupported history export version ${JSON.stringify(t.version)} \u2014 expected 1`);if(!Array.isArray(t.snapshots))throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");return N(t.snapshots)}function N(e){if(!Array.isArray(e))throw new Error("[Directive] framesFromSnapshots: expected an array of fact-state snapshots");if(e.length>v)throw new Error(`[Directive] framesFromSnapshots: history has ${e.length} snapshots, exceeds the MAX_REPLAY_FRAMES limit (${v}) \u2014 split or down-sample the history`);for(let n=0;n<e.length;n++){let t=e[n];if(!t||typeof t!="object"||!("facts"in t))throw new Error(`[Directive] framesFromSnapshots: snapshot at index ${n} is not a { facts, ... } object`)}return Q(e)}function $(e){let{frames:n,original:t,proposed:r,entityKey:s}=e,o=e.maxSamples??20,a=o>0?o:0;if(n.length>v)throw new Error(`[Directive] replayUnder: history has ${n.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${v}) \u2014 split or down-sample the history`);J(t,"original"),J(r,"proposed");let d=0,i=0,u=0,l=0,c=0,m=[],f=[],y=s?new Set:void 0,h$1=s?new Set:void 0,b;for(let D of n){let g=D.facts,S=h(t,g,b),T=h(r,g,b);S&&(d++,y?.add(g[s])),T&&(i++,h$1?.add(g[s])),S===T?c++:!S&&T?(u++,m.length<a&&m.push(G(D,t,r,b))):(l++,f.length<a&&f.push(G(D,t,r,b))),b=g;}let k={framesEvaluated:n.length,original:{matched:d},proposed:{matched:i},delta:i-d,newMatchCount:u,lostMatchCount:l,unchanged:c,newMatches:m,lostMatches:f};return y&&h$1&&(k.original.matchedEntities=y.size,k.proposed.matchedEntities=h$1.size),k}function G(e,n,t,r){let s=e.facts,o={frameId:e.id,facts:s,originalExplain:i(n,s,r),proposedExplain:i(t,s,r)};return e.timestamp!==void 0&&(o.timestamp=e.timestamp),o}var U=1e4,V=5e7;function Be(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===1&&typeof e.$hole=="string"}function q(e,n,t=new Set,r=0){if(r>c)throw new Error(`[Directive] sweepUnder: template exceeds MAX_PREDICATE_DEPTH (${c}) \u2014 flatten the template or split the sweep`);if(Be(e)){let s=e.$hole;if(!(s in n))throw new Error(`[Directive] sweepUnder: template references hole "${s}" but sweep has no values for it`);return n[s]}if(e===null||typeof e!="object")return e;if(t.has(e))throw new Error("[Directive] sweepUnder: template contains a cycle \u2014 predicate templates must be a tree");t.add(e);try{if(Array.isArray(e))return e.map(o=>q(o,n,t,r+1));let s={};for(let[o,a]of Object.entries(e))s[o]=q(a,n,t,r+1);return s}finally{t.delete(e);}}function*ee(e,n){if(e.length===0){yield {};return}let t=e[0],r=e.slice(1),s=n[t]??[];for(let o of s)for(let a of ee(r,n))yield {[t]:o,...a};}function Ne(e){let n=1;for(let t of Object.values(e))n*=t.length;return n}function Ue(e){let{frames:n,original:t,template:r,sweep:s,objective:o=g=>g.proposed.matched,entityKey:a,maxSamples:d=0}=e,i=Object.keys(s);if(i.length===0)throw new Error("[Directive] sweepUnder: `sweep` must contain at least one hole name");let u=Ne(s);if(u>U)throw new Error(`[Directive] sweepUnder: grid has ${u} points, exceeds the MAX_SWEEP_POINTS limit (${U}) \u2014 narrow the sweep ranges or split the run`);if(u===0)throw new Error("[Directive] sweepUnder: at least one hole has zero candidate values");let l=u*n.length;if(l>V)throw new Error(`[Directive] sweepUnder: ${u} points \xD7 ${n.length} frames = ${l} per-frame evaluations, exceeds the MAX_SWEEP_EVALUATIONS limit (${V}) \u2014 narrow the sweep, down-sample the history, or split the run`);let c=false,m=g=>{let S;try{S=o(g);}catch(T){return c||(c=true,console.warn(`[Directive] sweepUnder: objective threw \u2014 point will not rank (${T.message})`)),Number.NEGATIVE_INFINITY}return typeof S!="number"||!Number.isFinite(S)?(c||(c=true,console.warn(`[Directive] sweepUnder: objective returned a non-finite number (${String(S)}) \u2014 point will not rank`)),Number.NEGATIVE_INFINITY):S},f=$({frames:n,original:t,proposed:t,entityKey:a,maxSamples:d}),y={values:{},report:f,score:m(f)},h=[],b=0,k=Number.NEGATIVE_INFINITY;for(let g of ee(i,s)){let S=q(r,g),T=$({frames:n,original:t,proposed:S,entityKey:a,maxSamples:d}),O=m(T);O>k&&(k=O,b=h.length),h.push({values:g,report:T,score:O});}let D=h[b];return {points:h,bestIndex:b,best:D,baseline:y}}function W(e){let n=e&&typeof e=="object"&&!Array.isArray(e)&&"constraints"in e?e.constraints:e;if(Array.isArray(n)){let t={};for(let r of n){if(!r||typeof r!="object"||!("id"in r))throw new Error("[Directive] diffRules: array entries must be `{ id, whenSpec }` objects");let s=r;if(typeof s.id!="string")throw new Error("[Directive] diffRules: constraint `id` must be a string");t[s.id]=s.whenSpec;}return t}if(n&&typeof n=="object")return n;throw new Error("[Directive] diffRules: expected a `{ id: whenSpec }` map, an array of `{ id, whenSpec }`, or `{ constraints: ... }`")}var qe=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),We=new Set(["$all","$any","$not"]);function ne(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Le(e){if(!ne(e))return false;let n=Object.keys(e);if(n.length===0)return false;let t=false;for(let r of n){if(!r.startsWith("$"))return false;qe.has(r)&&(t=true);}return t}function M(e,n="",t=[]){if(e===null||typeof e!="object")return t;if(Array.isArray(e)){for(let r of e)if(r&&typeof r=="object"&&"fact"in r&&"op"in r){let s=r;t.push({path:n?`${n}.${String(s.fact)}`:String(s.fact),op:String(s.op),value:s.value});}return t}if("$all"in e&&Array.isArray(e.$all))return e.$all.forEach((s,o)=>{M(s,`${n}$all[${o}]`,t);}),t;if("$any"in e&&Array.isArray(e.$any))return e.$any.forEach((s,o)=>{M(s,`${n}$any[${o}]`,t);}),t;if("$not"in e)return M(e.$not,`${n}$not`,t),t;for(let[r,s]of Object.entries(e)){let o=n?`${n}.${r}`:r;if(Le(s))for(let[a,d]of Object.entries(s))t.push({path:o,op:a,value:d});else ne(s)&&!We.has(r)?M(s,o,t):t.push({path:o,op:"$eq",value:s});}return t}function w(e){return typeof e=="number"&&Number.isFinite(e)}function Ke(e,n,t){switch(e){case "$gte":case "$gt":if(w(n)&&w(t)){if(t<n)return "relaxed";if(t>n)return "tightened"}return null;case "$lte":case "$lt":if(w(n)&&w(t)){if(t>n)return "relaxed";if(t<n)return "tightened"}return null;case "$between":{if(Array.isArray(n)&&Array.isArray(t)&&n.length===2&&t.length===2&&w(n[0])&&w(n[1])&&w(t[0])&&w(t[1])){let r=n[1]-n[0],s=t[1]-t[0];if(s>r)return "relaxed";if(s<r)return "tightened"}return null}case "$in":case "$nin":{if(Array.isArray(n)&&Array.isArray(t))if(e==="$in"){if(t.length>n.length)return "relaxed";if(t.length<n.length)return "tightened"}else {if(t.length>n.length)return "tightened";if(t.length<n.length)return "relaxed"}return null}case "$contains":{if(Array.isArray(n)&&Array.isArray(t)){if(t.length>n.length)return "relaxed";if(t.length<n.length)return "tightened"}return null}default:return null}}function He(e){let n=W(e.before),t=W(e.after),s=[...new Set([...Object.keys(n),...Object.keys(t)])].sort(),o=[],a={added:0,removed:0,changed:0,unchanged:0,totalClauseChanges:0};for(let d of s){let i=n[d],u=t[d],l=d in n,c=d in t;if(l&&!c){let f=M(i),y=f.length===0?[{path:"(function-form predicate)",kind:"removed"}]:f.map(h=>({path:h.path,kind:"removed",before:{op:h.op,value:h.value}}));L(y),o.push({id:d,status:"removed",changes:y}),a.removed++,a.totalClauseChanges+=y.length;continue}if(!l&&c){let f=M(u),y=f.length===0?[{path:"(function-form predicate)",kind:"added"}]:f.map(h=>({path:h.path,kind:"added",after:{op:h.op,value:h.value}}));L(y),o.push({id:d,status:"added",changes:y}),a.added++,a.totalClauseChanges+=y.length;continue}let m=te(i,u);m.length===0?(o.push({id:d,status:"unchanged",changes:[]}),a.unchanged++):(o.push({id:d,status:"changed",changes:m}),a.changed++,a.totalClauseChanges+=m.length);}return {constraints:o,summary:a}}function te(e,n){if(e!==void 0&&n!==void 0&&(e===null||n===null||typeof e!="object"||typeof n!="object"))return d(e)===d(n)?[]:[{path:"",kind:"changed",before:{op:"$eq",value:e},after:{op:"$eq",value:n}}];let t=e===void 0?[]:M(e),r=n===void 0?[]:M(n),s=u=>`${u.path}::${u.op}`,o=new Map(t.map(u=>[s(u),u])),a=new Map(r.map(u=>[s(u),u])),d$1=new Set([...o.keys(),...a.keys()]),i=[];for(let u of d$1){let l=o.get(u),c=a.get(u);if(l&&!c){i.push({path:l.path,kind:"removed",before:{op:l.op,value:l.value}});continue}if(!l&&c){i.push({path:c.path,kind:"added",after:{op:c.op,value:c.value}});continue}if(l&&c){if(d(l.value)===d(c.value))continue;let m=Ke(l.op,l.value,c.value);i.push({path:l.path,kind:m??"changed",before:{op:l.op,value:l.value},after:{op:c.op,value:c.value}});}}return L(i),i}function L(e){e.sort((n,t)=>{let r=n.path.localeCompare(t.path);if(r!==0)return r;let s=n.before?.op??n.after?.op??"",o=t.before?.op??t.after?.op??"";return s.localeCompare(o)});}function F(e=[],n,t,r,s,o,a){return {_type:void 0,_validators:e,_typeName:n,_default:t,_transform:r,_description:s,_refinements:o,_meta:a,validate(d){return F([...e,d],n,t,r,s,o,a)}}}function p(e,n,t,r,s,o,a){return {...F(e,n,t,r,s,o,a),default(i){return p(e,n,i,r,s,o,a)},transform(i){return p([],n,void 0,l=>{let c=r?r(l):l;return i(c)},s,void 0,a)},brand(){return p(e,`Branded<${n}>`,t,r,s,o,a)},describe(i){return p(e,n,t,r,i,o,a)},refine(i,u){let l=[...o??[],{predicate:i,message:u}];return p([...e,i],n,t,r,s,l,a)},nullable(){return p([i=>i===null||e.every(u=>u(i))],`${n} | null`,t,r,s,void 0,a)},optional(){return p([i=>i===void 0||e.every(u=>u(i))],`${n} | undefined`,t,r,s,void 0,a)},meta(i){return p(e,n,t,r,s,o,i)}}}var ze=((...e)=>{if(e.length===0)return p([],"union");let n=e.map(t=>t._typeName??"unknown");return p([t=>e.some(r=>r._validators.every(s=>s(t)))],n.join(" | "))}),Xe={string(){let e=(n,t,r,s,o,a)=>({...p(n,"string",t,r,s,o,a),minLength(i){return e([...n,u=>u.length>=i],t,r,s,o,a)},maxLength(i){return e([...n,u=>u.length<=i],t,r,s,o,a)},pattern(i){return e([...n,u=>i.test(u)],t,r,s,o,a)},default(i){return e(n,i,r,s,o,a)},describe(i){return e(n,t,r,i,o,a)},refine(i,u){let l=[...o??[],{predicate:i,message:u}];return e([...n,i],t,r,s,l,a)},meta(i){return e(n,t,r,s,o,i)}});return e([n=>typeof n=="string"])},number(){let e=(n,t,r,s,o,a)=>({...p(n,"number",t,r,s,o,a),min(i){return e([...n,u=>u>=i],t,r,s,o,a)},max(i){return e([...n,u=>u<=i],t,r,s,o,a)},default(i){return e(n,i,r,s,o,a)},describe(i){return e(n,t,r,i,o,a)},refine(i,u){let l=[...o??[],{predicate:i,message:u}];return e([...n,i],t,r,s,l,a)},meta(i){return e(n,t,r,s,o,i)}});return e([n=>typeof n=="number"])},boolean(){return p([e=>typeof e=="boolean"],"boolean")},array(){let e=(n,t,r,s,o,a)=>{let d=p(n,"array",r,void 0,s,void 0,a),i=o??{value:-1};return {...d,get _lastFailedIndex(){return i.value},set _lastFailedIndex(l){i.value=l;},of(l){let c={value:-1};return e([...n,m=>{for(let f=0;f<m.length;f++)if(!l._validators.every(y=>y(m[f])))return c.value=f,false;return true}],l,r,s,c,a)},nonEmpty(){return e([...n,l=>l.length>0],t,r,s,i,a)},maxLength(l){return e([...n,c=>c.length<=l],t,r,s,i,a)},minLength(l){return e([...n,c=>c.length>=l],t,r,s,i,a)},default(l){return e(n,t,l,s,i,a)},describe(l){return e(n,t,r,l,i,a)},meta(l){return e(n,t,r,s,i,l)}}};return e([n=>Array.isArray(n)])},object(){let e=(n,t,r,s)=>({...p(n,"object",t,void 0,r,void 0,s),shape(a){return e([...n,d=>{for(let[i,u]of Object.entries(a)){let l=d[i],c=u;if(c&&!c._validators.every(m=>m(l)))return false}return true}],t,r,s)},nonNull(){return e([...n,a=>a!=null],t,r,s)},hasKeys(...a){return e([...n,d=>a.every(i=>i in d)],t,r,s)},default(a){return e(n,a,r,s)},describe(a){return e(n,t,a,s)},meta(a){return e(n,t,r,a)}});return e([n=>typeof n=="object"&&n!==null&&!Array.isArray(n)])},enum(...e){a&&e.length===0&&console.warn("[Directive] t.enum() called with no values - this will reject all strings");let n=new Set(e);return p([t=>typeof t=="string"&&n.has(t)],`enum(${e.join("|")})`)},literal(e){return p([n=>n===e],`literal(${String(e)})`)},nullable(e){let n=e._typeName??"unknown";return F([t=>t===null?true:e._validators.every(r=>r(t))],`${n} | null`)},optional(e){let n=e._typeName??"unknown";return F([t=>t===void 0?true:e._validators.every(r=>r(t))],`${n} | undefined`)},union:ze,record(e){let n=e._typeName??"unknown";return p([t=>typeof t!="object"||t===null||Array.isArray(t)?false:Object.values(t).every(r=>e._validators.every(s=>s(r)))],`Record<string, ${n}>`)},tuple(...e){a&&e.length===0&&console.warn("[Directive] t.tuple() called with no types - this will only accept empty arrays");let n=e.map(t=>t._typeName??"unknown");return p([t=>!Array.isArray(t)||t.length!==e.length?false:e.every((r,s)=>r._validators.every(o=>o(t[s])))],`[${n.join(", ")}]`)},date(){return p([e=>e instanceof Date&&!Number.isNaN(e.getTime())],"Date")},uuid(){let e=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;return p([n=>typeof n=="string"&&e.test(n)],"uuid")},email(){let e=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;return p([n=>typeof n=="string"&&e.test(n)],"email")},url(){return p([e=>{if(typeof e!="string")return false;try{return new URL(e),!0}catch{return false}}],"url")},bigint(){return p([e=>typeof e=="bigint"],"bigint")},any(){return p([],"any")},unknown(){return p([],"unknown")}};function Ye(e){if(!e||typeof e!="string"){console.warn("[Directive] Module ID must be a non-empty string");return}/^(__[a-z][a-z0-9_-]*|[a-z][a-z0-9-]*)$/i.test(e)||console.warn(`[Directive] Module ID "${e}" should follow kebab-case convention (e.g., "my-module")`);}function re(e,n,t,r,s){for(let o of e)n.has(o)||console.warn(`[Directive] ${t} "${o}" not declared in ${r}`);for(let o of n)e.has(o)||console.warn(`[Directive] ${r}["${o}"] ${s}`);}function Je(e,n){e.length===0&&console.warn("[Directive] history.snapshotEvents is an empty array \u2014 no events will create history snapshots. Omit history.snapshotEvents entirely to snapshot all events, or list specific events.");let t=new Set(Object.keys(n));for(let r of e)t.has(r)||console.warn(`[Directive] history.snapshotEvents entry "${r}" not declared in schema.events. Available events: ${[...t].join(", ")||"(none)"}`);}function Ge(e,n){let t=new Set(Object.keys(n));for(let[r,s]of Object.entries(e)){let o=s;typeof o.requirement=="string"&&!t.has(o.requirement)&&console.warn(`[Directive] Resolver "${r}" references unknown requirement type "${o.requirement}". Available types: ${[...t].join(", ")||"(none)"}`);}}function Qe(e,n){let t=n.schema?.facts??{},r=Object.keys(t);if(r.length===0)return;let s=new Set(["self","prev","current"]),o="crossModuleDeps"in n&&n.crossModuleDeps?Object.keys(n.crossModuleDeps):[];for(let a of o)s.add(a);for(let a of r)if(s.has(a))throw new Error(`[Directive] module '${e}': fact key '${a}' conflicts with a reserved namespace pivot or evaluation alias (self / prev / current / a crossModuleDep namespace). Three fixes:
|
|
2
2
|
1. Rename the fact (e.g. ${a}_)
|
|
3
3
|
2. Remove '${a}' from this module's crossModuleDeps if it's not actually needed
|
|
4
|
-
3. Move the fact under a wrapping namespace (t.object({ inner: ... }))`)}function
|
|
4
|
+
3. Move the fact under a wrapping namespace (t.object({ inner: ... }))`)}function Ze(e,n){let t=n.constraints;if(t)for(let[r,s]of Object.entries(t)){let o=s?.owns;if(o){for(let a of o)if(l.has(a)||a.startsWith("$"))throw new Error(`[Directive] module '${e}' constraint '${r}': owns key '${a}' is reserved (BLOCKED_PROPS or $-prefixed)`)}}}function Ve(e,n){Ye(e),n.schema?n.schema.facts||console.warn("[Directive] Module schema.facts is required"):console.warn("[Directive] Module schema is required"),re(new Set(Object.keys(n.derive??{})),new Set(Object.keys(n.schema?.derivations??{})),"Derivation","schema.derivations","has no matching implementation in derive"),re(new Set(Object.keys(n.events??{})),new Set(Object.keys(n.schema?.events??{})),"Event","schema.events","has no matching handler in events"),n.history?.snapshotEvents&&Je(n.history.snapshotEvents,n.schema?.events??{}),n.resolvers&&n.schema?.requirements&&Ge(n.resolvers,n.schema.requirements);}function se(e,n){Qe(e,n),Ze(e,n),a&&Ve(e,n);let t="crossModuleDeps"in n?n.crossModuleDeps:void 0;return {id:e,schema:n.schema,init:n.init,derive:n.derive??{},events:n.events??{},effects:n.effects,constraints:n.constraints,resolvers:n.resolvers,hooks:n.hooks,meta:n.meta,history:n.history,crossModuleDeps:t}}function en(e){return n=>se(n,e)}function K(){let e={pending:new Map,inflight:new Map,failed:new Map,errors:new Map,listeners:new Set};function n(){for(let i of e.listeners)i();}function t(i,u){let l=i.get(u);return l||(l=new Set,i.set(u,l)),l}function r(i){let u=e.pending.get(i)??new Set,l=e.inflight.get(i)??new Set,c=e.failed.get(i)??new Set,m=e.errors.get(i)??null;return {pending:u.size,inflight:l.size,failed:c.size,isLoading:u.size>0||l.size>0,hasError:c.size>0,lastError:m}}function s(){let i=new Set([...e.pending.keys(),...e.inflight.keys(),...e.failed.keys()]),u=new Map;for(let l of i)u.set(l,r(l));return u}function o(i){return e.listeners.add(i),()=>e.listeners.delete(i)}function a(){e.pending.clear(),e.inflight.clear(),e.failed.clear(),e.errors.clear(),n();}return {plugin:{name:"requirement-status",onRequirementCreated(i){let u=i.requirement.type;t(e.pending,u).add(i.id),e.failed.get(u)?.delete(i.id),n();},onResolverStart(i,u){let l=u.requirement.type;e.pending.get(l)?.delete(u.id),t(e.inflight,l).add(u.id),n();},onResolverComplete(i,u){let l=u.requirement.type;e.inflight.get(l)?.delete(u.id),e.pending.get(l)?.delete(u.id),n();},onResolverError(i,u,l){let c=u.requirement.type;e.inflight.get(c)?.delete(u.id),t(e.failed,c).add(u.id),e.errors.set(c,l instanceof Error?l:new Error(String(l))),n();},onResolverCancel(i,u){let l=u.requirement.type;e.pending.get(l)?.delete(u.id),e.inflight.get(l)?.delete(u.id),n();},onRequirementMet(i){let u=i.requirement.type;e.pending.get(u)?.delete(i.id),e.inflight.get(u)?.delete(i.id),n();}},getStatus:r,getAllStatus:s,subscribe:o,reset:a}}function nn(e){return n=>e.getStatus(n)}function tn(e){let n=K(),r=[...e.plugins??[],n.plugin];return {system:a$1({module:e.module,plugins:r,trace:e.trace,errorBoundary:e.errorBoundary,tickMs:e.tickMs,zeroConfig:e.zeroConfig,initialFacts:e.initialFacts}),statusPlugin:n}}function ie(){return {now:()=>Date.now(),setTimeout:(e,n)=>{let t=globalThis.setTimeout(e,n);return ()=>globalThis.clearTimeout(t)}}}function rn(e=0){let n=e,t=0,r=[];return {now:()=>n,setTimeout:(s,o)=>{let a={id:t++,deadlineMs:n+o,cb:s,canceled:false};return r.push(a),()=>{a.canceled=true;}},advanceBy:s=>{let o=n+s;for(;;){let a=r.filter(i=>!i.canceled&&i.deadlineMs<=o).sort((i,u)=>i.deadlineMs!==u.deadlineMs?i.deadlineMs-u.deadlineMs:i.id-u.id);if(a.length===0)break;let d=a[0];n=Math.max(n,d.deadlineMs),d.canceled=true,d.cb();}n=Math.max(n,o);}}}function sn(){return ie()}function H(){return {startedAtMs:null,pausedDurationMs:0,pausedAtMs:null,status:"idle",repeats:0}}function j(e,n){return e.startedAtMs===null?0:e.status==="paused"&&e.pausedAtMs!==null?Math.max(0,e.pausedAtMs-e.startedAtMs-e.pausedDurationMs):Math.max(0,n-e.startedAtMs-e.pausedDurationMs)}function ae(e,n,t){return Math.max(0,t-j(e,n))}function oe(e,n){return e.status==="running"||e.status==="paused"?e:{...e,startedAtMs:n,pausedDurationMs:0,pausedAtMs:null,status:"running",repeats:0}}function ue(e,n){return e.status!=="running"?e:{...e,pausedAtMs:n,status:"paused"}}function le(e,n){if(e.status!=="paused"||e.pausedAtMs===null)return e;let t=Math.max(0,n-e.pausedAtMs);return {...e,pausedDurationMs:e.pausedDurationMs+t,pausedAtMs:null,status:"running"}}function ce(){return H()}function de(e){return {...e,status:"completed"}}function pe(e,n){return e.startedAtMs===null||e.status==="paused"?e:{...e,startedAtMs:e.startedAtMs+n,pausedDurationMs:0,pausedAtMs:null,repeats:e.repeats+1}}function me(e,n,t){if(e.status!=="running")return {kind:"no-op"};let r=j(e,n);return t.mode==="up"?{kind:"no-op"}:t.mode==="repeat"?r>=t.ms?{kind:"repeat"}:{kind:"no-op"}:r>=t.ms?{kind:"complete"}:{kind:"no-op"}}function an(e){return {initial:H,start:oe,pause:ue,resume:le,reset:ce,complete:de,registerRepeat:n=>pe(n,e.ms),tick:(n,t)=>me(n,t,e),elapsedMs:j,remainingMs:(n,t)=>ae(n,t,e.ms)}}var xn={None:"none",Linear:"linear",Exponential:"exponential"};export{xn as Backoff,v as MAX_REPLAY_FRAMES,U as MAX_SWEEP_POINTS,de as completeTimer,se as createModule,en as createModuleFactory,K as createRequirementStatusPlugin,nn as createStatusHook,tn as createSystemWithStatus,sn as defaultClock,te as diffClauses,He as diffRules,j as elapsedMs,M as flattenPredicate,Z as framesFromHistory,N as framesFromSnapshots,H as initialTimerState,ue as pauseTimer,ie as realClock,pe as registerRepeat,ae as remainingMs,$ as replayUnder,ce as resetTimer,le as resumeTimer,oe as startTimer,Ue as sweepUnder,Xe as t,me as tickTimer,an as timerOps,Q as toReplayFrames,W as toRulesMap,rn as virtualClock};//# sourceMappingURL=index.js.map
|
|
5
5
|
//# sourceMappingURL=index.js.map
|