@almadar/ui 3.1.4 → 3.2.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.
@@ -11916,12 +11916,19 @@ function getState() {
11916
11916
  checks: /* @__PURE__ */ new Map(),
11917
11917
  transitions: [],
11918
11918
  bridgeHealth: null,
11919
- listeners: /* @__PURE__ */ new Set()
11919
+ listeners: /* @__PURE__ */ new Set(),
11920
+ traitSnapshots: /* @__PURE__ */ new Map()
11920
11921
  };
11921
11922
  }
11922
11923
  return w.__verificationRegistryState;
11923
11924
  }
11924
- return { checks: /* @__PURE__ */ new Map(), transitions: [], bridgeHealth: null, listeners: /* @__PURE__ */ new Set() };
11925
+ return {
11926
+ checks: /* @__PURE__ */ new Map(),
11927
+ transitions: [],
11928
+ bridgeHealth: null,
11929
+ listeners: /* @__PURE__ */ new Set(),
11930
+ traitSnapshots: /* @__PURE__ */ new Map()
11931
+ };
11925
11932
  }
11926
11933
  function notifyListeners() {
11927
11934
  getState().listeners.forEach((l) => l());
@@ -12028,9 +12035,21 @@ function getSnapshot() {
12028
12035
  checks: getAllChecks(),
12029
12036
  transitions: getTransitions2(),
12030
12037
  bridge: getBridgeHealth(),
12031
- summary: getSummary()
12038
+ summary: getSummary(),
12039
+ traits: getTraitSnapshots()
12032
12040
  };
12033
12041
  }
12042
+ function getTraitSnapshots() {
12043
+ const snapshots = [];
12044
+ for (const [traitName, getter] of getState().traitSnapshots.entries()) {
12045
+ try {
12046
+ snapshots.push(getter());
12047
+ } catch (err) {
12048
+ log2.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
12049
+ }
12050
+ }
12051
+ return snapshots;
12052
+ }
12034
12053
  function subscribeToVerification(listener) {
12035
12054
  getState().listeners.add(listener);
12036
12055
  return () => getState().listeners.delete(listener);
@@ -12044,8 +12063,11 @@ function exposeOnWindow() {
12044
12063
  getTransitions: getTransitions2,
12045
12064
  getBridge: getBridgeHealth,
12046
12065
  getSummary,
12047
- waitForTransition
12066
+ waitForTransition,
12067
+ getTraitSnapshots
12048
12068
  };
12069
+ } else if (!window.__orbitalVerification.getTraitSnapshots) {
12070
+ window.__orbitalVerification.getTraitSnapshots = getTraitSnapshots;
12049
12071
  }
12050
12072
  }
12051
12073
  function waitForTransition(event, timeoutMs = 1e4) {
package/dist/avl/index.js CHANGED
@@ -11870,12 +11870,19 @@ function getState() {
11870
11870
  checks: /* @__PURE__ */ new Map(),
11871
11871
  transitions: [],
11872
11872
  bridgeHealth: null,
11873
- listeners: /* @__PURE__ */ new Set()
11873
+ listeners: /* @__PURE__ */ new Set(),
11874
+ traitSnapshots: /* @__PURE__ */ new Map()
11874
11875
  };
11875
11876
  }
11876
11877
  return w.__verificationRegistryState;
11877
11878
  }
11878
- return { checks: /* @__PURE__ */ new Map(), transitions: [], bridgeHealth: null, listeners: /* @__PURE__ */ new Set() };
11879
+ return {
11880
+ checks: /* @__PURE__ */ new Map(),
11881
+ transitions: [],
11882
+ bridgeHealth: null,
11883
+ listeners: /* @__PURE__ */ new Set(),
11884
+ traitSnapshots: /* @__PURE__ */ new Map()
11885
+ };
11879
11886
  }
11880
11887
  function notifyListeners() {
11881
11888
  getState().listeners.forEach((l) => l());
@@ -11982,9 +11989,21 @@ function getSnapshot() {
11982
11989
  checks: getAllChecks(),
11983
11990
  transitions: getTransitions2(),
11984
11991
  bridge: getBridgeHealth(),
11985
- summary: getSummary()
11992
+ summary: getSummary(),
11993
+ traits: getTraitSnapshots()
11986
11994
  };
11987
11995
  }
11996
+ function getTraitSnapshots() {
11997
+ const snapshots = [];
11998
+ for (const [traitName, getter] of getState().traitSnapshots.entries()) {
11999
+ try {
12000
+ snapshots.push(getter());
12001
+ } catch (err) {
12002
+ log2.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
12003
+ }
12004
+ }
12005
+ return snapshots;
12006
+ }
11988
12007
  function subscribeToVerification(listener) {
11989
12008
  getState().listeners.add(listener);
11990
12009
  return () => getState().listeners.delete(listener);
@@ -11998,8 +12017,11 @@ function exposeOnWindow() {
11998
12017
  getTransitions: getTransitions2,
11999
12018
  getBridge: getBridgeHealth,
12000
12019
  getSummary,
12001
- waitForTransition
12020
+ waitForTransition,
12021
+ getTraitSnapshots
12002
12022
  };
12023
+ } else if (!window.__orbitalVerification.getTraitSnapshots) {
12024
+ window.__orbitalVerification.getTraitSnapshots = getTraitSnapshots;
12003
12025
  }
12004
12026
  }
12005
12027
  function waitForTransition(event, timeoutMs = 1e4) {
@@ -7443,12 +7443,19 @@ function getState() {
7443
7443
  checks: /* @__PURE__ */ new Map(),
7444
7444
  transitions: [],
7445
7445
  bridgeHealth: null,
7446
- listeners: /* @__PURE__ */ new Set()
7446
+ listeners: /* @__PURE__ */ new Set(),
7447
+ traitSnapshots: /* @__PURE__ */ new Map()
7447
7448
  };
7448
7449
  }
7449
7450
  return w.__verificationRegistryState;
7450
7451
  }
7451
- return { checks: /* @__PURE__ */ new Map(), transitions: [], bridgeHealth: null, listeners: /* @__PURE__ */ new Set() };
7452
+ return {
7453
+ checks: /* @__PURE__ */ new Map(),
7454
+ transitions: [],
7455
+ bridgeHealth: null,
7456
+ listeners: /* @__PURE__ */ new Set(),
7457
+ traitSnapshots: /* @__PURE__ */ new Map()
7458
+ };
7452
7459
  }
7453
7460
  function getAllChecks() {
7454
7461
  return Array.from(getState().checks.values());
@@ -7475,9 +7482,21 @@ function getSnapshot() {
7475
7482
  checks: getAllChecks(),
7476
7483
  transitions: getTransitions(),
7477
7484
  bridge: getBridgeHealth(),
7478
- summary: getSummary()
7485
+ summary: getSummary(),
7486
+ traits: getTraitSnapshots()
7479
7487
  };
7480
7488
  }
7489
+ function getTraitSnapshots() {
7490
+ const snapshots = [];
7491
+ for (const [traitName, getter] of getState().traitSnapshots.entries()) {
7492
+ try {
7493
+ snapshots.push(getter());
7494
+ } catch (err) {
7495
+ log2.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
7496
+ }
7497
+ }
7498
+ return snapshots;
7499
+ }
7481
7500
  function subscribeToVerification(listener) {
7482
7501
  getState().listeners.add(listener);
7483
7502
  return () => getState().listeners.delete(listener);
@@ -7491,8 +7510,11 @@ function exposeOnWindow() {
7491
7510
  getTransitions,
7492
7511
  getBridge: getBridgeHealth,
7493
7512
  getSummary,
7494
- waitForTransition
7513
+ waitForTransition,
7514
+ getTraitSnapshots
7495
7515
  };
7516
+ } else if (!window.__orbitalVerification.getTraitSnapshots) {
7517
+ window.__orbitalVerification.getTraitSnapshots = getTraitSnapshots;
7496
7518
  }
7497
7519
  }
7498
7520
  function waitForTransition(event, timeoutMs = 1e4) {
@@ -7533,10 +7555,11 @@ function updateAssetStatus(url, status) {
7533
7555
  window.__orbitalVerification.assetStatus[url] = status;
7534
7556
  }
7535
7557
  }
7558
+ var log2;
7536
7559
  var init_verificationRegistry = __esm({
7537
7560
  "lib/verificationRegistry.ts"() {
7538
7561
  init_logger();
7539
- createLogger("almadar:bridge");
7562
+ log2 = createLogger("almadar:bridge");
7540
7563
  exposeOnWindow();
7541
7564
  }
7542
7565
  });
@@ -7398,12 +7398,19 @@ function getState() {
7398
7398
  checks: /* @__PURE__ */ new Map(),
7399
7399
  transitions: [],
7400
7400
  bridgeHealth: null,
7401
- listeners: /* @__PURE__ */ new Set()
7401
+ listeners: /* @__PURE__ */ new Set(),
7402
+ traitSnapshots: /* @__PURE__ */ new Map()
7402
7403
  };
7403
7404
  }
7404
7405
  return w.__verificationRegistryState;
7405
7406
  }
7406
- return { checks: /* @__PURE__ */ new Map(), transitions: [], bridgeHealth: null, listeners: /* @__PURE__ */ new Set() };
7407
+ return {
7408
+ checks: /* @__PURE__ */ new Map(),
7409
+ transitions: [],
7410
+ bridgeHealth: null,
7411
+ listeners: /* @__PURE__ */ new Set(),
7412
+ traitSnapshots: /* @__PURE__ */ new Map()
7413
+ };
7407
7414
  }
7408
7415
  function getAllChecks() {
7409
7416
  return Array.from(getState().checks.values());
@@ -7430,9 +7437,21 @@ function getSnapshot() {
7430
7437
  checks: getAllChecks(),
7431
7438
  transitions: getTransitions(),
7432
7439
  bridge: getBridgeHealth(),
7433
- summary: getSummary()
7440
+ summary: getSummary(),
7441
+ traits: getTraitSnapshots()
7434
7442
  };
7435
7443
  }
7444
+ function getTraitSnapshots() {
7445
+ const snapshots = [];
7446
+ for (const [traitName, getter] of getState().traitSnapshots.entries()) {
7447
+ try {
7448
+ snapshots.push(getter());
7449
+ } catch (err) {
7450
+ log2.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
7451
+ }
7452
+ }
7453
+ return snapshots;
7454
+ }
7436
7455
  function subscribeToVerification(listener) {
7437
7456
  getState().listeners.add(listener);
7438
7457
  return () => getState().listeners.delete(listener);
@@ -7446,8 +7465,11 @@ function exposeOnWindow() {
7446
7465
  getTransitions,
7447
7466
  getBridge: getBridgeHealth,
7448
7467
  getSummary,
7449
- waitForTransition
7468
+ waitForTransition,
7469
+ getTraitSnapshots
7450
7470
  };
7471
+ } else if (!window.__orbitalVerification.getTraitSnapshots) {
7472
+ window.__orbitalVerification.getTraitSnapshots = getTraitSnapshots;
7451
7473
  }
7452
7474
  }
7453
7475
  function waitForTransition(event, timeoutMs = 1e4) {
@@ -7488,10 +7510,11 @@ function updateAssetStatus(url, status) {
7488
7510
  window.__orbitalVerification.assetStatus[url] = status;
7489
7511
  }
7490
7512
  }
7513
+ var log2;
7491
7514
  var init_verificationRegistry = __esm({
7492
7515
  "lib/verificationRegistry.ts"() {
7493
7516
  init_logger();
7494
- createLogger("almadar:bridge");
7517
+ log2 = createLogger("almadar:bridge");
7495
7518
  exposeOnWindow();
7496
7519
  }
7497
7520
  });
@@ -493,12 +493,19 @@ function getState() {
493
493
  checks: /* @__PURE__ */ new Map(),
494
494
  transitions: [],
495
495
  bridgeHealth: null,
496
- listeners: /* @__PURE__ */ new Set()
496
+ listeners: /* @__PURE__ */ new Set(),
497
+ traitSnapshots: /* @__PURE__ */ new Map()
497
498
  };
498
499
  }
499
500
  return w.__verificationRegistryState;
500
501
  }
501
- return { checks: /* @__PURE__ */ new Map(), transitions: [], bridgeHealth: null, listeners: /* @__PURE__ */ new Set() };
502
+ return {
503
+ checks: /* @__PURE__ */ new Map(),
504
+ transitions: [],
505
+ bridgeHealth: null,
506
+ listeners: /* @__PURE__ */ new Set(),
507
+ traitSnapshots: /* @__PURE__ */ new Map()
508
+ };
502
509
  }
503
510
  function notifyListeners5() {
504
511
  getState().listeners.forEach((l) => l());
@@ -634,9 +641,21 @@ function getSnapshot() {
634
641
  checks: getAllChecks(),
635
642
  transitions: getTransitions(),
636
643
  bridge: getBridgeHealth(),
637
- summary: getSummary()
644
+ summary: getSummary(),
645
+ traits: getTraitSnapshots()
638
646
  };
639
647
  }
648
+ function getTraitSnapshots() {
649
+ const snapshots = [];
650
+ for (const [traitName, getter] of getState().traitSnapshots.entries()) {
651
+ try {
652
+ snapshots.push(getter());
653
+ } catch (err) {
654
+ log.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
655
+ }
656
+ }
657
+ return snapshots;
658
+ }
640
659
  function subscribeToVerification(listener) {
641
660
  getState().listeners.add(listener);
642
661
  return () => getState().listeners.delete(listener);
@@ -650,8 +669,11 @@ function exposeOnWindow() {
650
669
  getTransitions,
651
670
  getBridge: getBridgeHealth,
652
671
  getSummary,
653
- waitForTransition
672
+ waitForTransition,
673
+ getTraitSnapshots
654
674
  };
675
+ } else if (!window.__orbitalVerification.getTraitSnapshots) {
676
+ window.__orbitalVerification.getTraitSnapshots = getTraitSnapshots;
655
677
  }
656
678
  }
657
679
  function waitForTransition(event, timeoutMs = 1e4) {
@@ -710,6 +732,20 @@ function bindTraitStateGetter(getter) {
710
732
  window.__orbitalVerification.getTraitState = getter;
711
733
  }
712
734
  }
735
+ function registerTraitSnapshot(traitName, getter) {
736
+ if (typeof window === "undefined") return () => {
737
+ };
738
+ getState().traitSnapshots.set(traitName, getter);
739
+ exposeOnWindow();
740
+ notifyListeners5();
741
+ return () => {
742
+ const s = getState();
743
+ if (s.traitSnapshots.get(traitName) === getter) {
744
+ s.traitSnapshots.delete(traitName);
745
+ notifyListeners5();
746
+ }
747
+ };
748
+ }
713
749
  function bindCanvasCapture(captureFn) {
714
750
  if (typeof window === "undefined") return;
715
751
  exposeOnWindow();
@@ -1558,6 +1594,7 @@ exports.getSnapshot = getSnapshot;
1558
1594
  exports.getSummary = getSummary;
1559
1595
  exports.getTick = getTick;
1560
1596
  exports.getTrait = getTrait;
1597
+ exports.getTraitSnapshots = getTraitSnapshots;
1561
1598
  exports.getTransitions = getTransitions;
1562
1599
  exports.getTransitionsForTrait = getTransitionsForTrait;
1563
1600
  exports.initDebugShortcut = initDebugShortcut;
@@ -1578,6 +1615,7 @@ exports.recordTransition = recordTransition;
1578
1615
  exports.registerCheck = registerCheck;
1579
1616
  exports.registerTick = registerTick;
1580
1617
  exports.registerTrait = registerTrait;
1618
+ exports.registerTraitSnapshot = registerTraitSnapshot;
1581
1619
  exports.renderStateMachineToDomData = renderStateMachineToDomData;
1582
1620
  exports.renderStateMachineToSvg = renderStateMachineToSvg;
1583
1621
  exports.setDebugEnabled = setDebugEnabled;
package/dist/lib/index.js CHANGED
@@ -491,12 +491,19 @@ function getState() {
491
491
  checks: /* @__PURE__ */ new Map(),
492
492
  transitions: [],
493
493
  bridgeHealth: null,
494
- listeners: /* @__PURE__ */ new Set()
494
+ listeners: /* @__PURE__ */ new Set(),
495
+ traitSnapshots: /* @__PURE__ */ new Map()
495
496
  };
496
497
  }
497
498
  return w.__verificationRegistryState;
498
499
  }
499
- return { checks: /* @__PURE__ */ new Map(), transitions: [], bridgeHealth: null, listeners: /* @__PURE__ */ new Set() };
500
+ return {
501
+ checks: /* @__PURE__ */ new Map(),
502
+ transitions: [],
503
+ bridgeHealth: null,
504
+ listeners: /* @__PURE__ */ new Set(),
505
+ traitSnapshots: /* @__PURE__ */ new Map()
506
+ };
500
507
  }
501
508
  function notifyListeners5() {
502
509
  getState().listeners.forEach((l) => l());
@@ -632,9 +639,21 @@ function getSnapshot() {
632
639
  checks: getAllChecks(),
633
640
  transitions: getTransitions(),
634
641
  bridge: getBridgeHealth(),
635
- summary: getSummary()
642
+ summary: getSummary(),
643
+ traits: getTraitSnapshots()
636
644
  };
637
645
  }
646
+ function getTraitSnapshots() {
647
+ const snapshots = [];
648
+ for (const [traitName, getter] of getState().traitSnapshots.entries()) {
649
+ try {
650
+ snapshots.push(getter());
651
+ } catch (err) {
652
+ log.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
653
+ }
654
+ }
655
+ return snapshots;
656
+ }
638
657
  function subscribeToVerification(listener) {
639
658
  getState().listeners.add(listener);
640
659
  return () => getState().listeners.delete(listener);
@@ -648,8 +667,11 @@ function exposeOnWindow() {
648
667
  getTransitions,
649
668
  getBridge: getBridgeHealth,
650
669
  getSummary,
651
- waitForTransition
670
+ waitForTransition,
671
+ getTraitSnapshots
652
672
  };
673
+ } else if (!window.__orbitalVerification.getTraitSnapshots) {
674
+ window.__orbitalVerification.getTraitSnapshots = getTraitSnapshots;
653
675
  }
654
676
  }
655
677
  function waitForTransition(event, timeoutMs = 1e4) {
@@ -708,6 +730,20 @@ function bindTraitStateGetter(getter) {
708
730
  window.__orbitalVerification.getTraitState = getter;
709
731
  }
710
732
  }
733
+ function registerTraitSnapshot(traitName, getter) {
734
+ if (typeof window === "undefined") return () => {
735
+ };
736
+ getState().traitSnapshots.set(traitName, getter);
737
+ exposeOnWindow();
738
+ notifyListeners5();
739
+ return () => {
740
+ const s = getState();
741
+ if (s.traitSnapshots.get(traitName) === getter) {
742
+ s.traitSnapshots.delete(traitName);
743
+ notifyListeners5();
744
+ }
745
+ };
746
+ }
711
747
  function bindCanvasCapture(captureFn) {
712
748
  if (typeof window === "undefined") return;
713
749
  exposeOnWindow();
@@ -1505,4 +1541,4 @@ function parseContentSegments(content) {
1505
1541
  return segments;
1506
1542
  }
1507
1543
 
1508
- export { ApiError, DEFAULT_CONFIG, apiClient, bindCanvasCapture, bindEventBus, bindTraitStateGetter, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, clearVerification, cn, createLogger, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, extractOutputsFromTransitions, extractStateMachine, formatGuard, formatNestedFieldLabel, generateCorrelationId, getAllChecks, getAllTicks, getAllTraits, getBridgeHealth, getDebugEvents, getEffectSummary, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getSnapshot, getSummary, getTick, getTrait, getTransitions, getTransitionsForTrait, initDebugShortcut, isDebugEnabled, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, parseContentSegments, parseMarkdownWithCodeBlocks, recordGuardEvaluation, recordServerResponse, recordTransition, registerCheck, registerTick, registerTrait, renderStateMachineToDomData, renderStateMachineToSvg, setDebugEnabled, setEntityProvider, setTickActive, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, subscribeToVerification, toggleDebug, unregisterTick, unregisterTrait, updateAssetStatus, updateBridgeHealth, updateCheck, updateGuardResult, updateTickExecution, updateTraitState, waitForTransition };
1544
+ export { ApiError, DEFAULT_CONFIG, apiClient, bindCanvasCapture, bindEventBus, bindTraitStateGetter, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, clearVerification, cn, createLogger, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, extractOutputsFromTransitions, extractStateMachine, formatGuard, formatNestedFieldLabel, generateCorrelationId, getAllChecks, getAllTicks, getAllTraits, getBridgeHealth, getDebugEvents, getEffectSummary, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getSnapshot, getSummary, getTick, getTrait, getTraitSnapshots, getTransitions, getTransitionsForTrait, initDebugShortcut, isDebugEnabled, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, parseContentSegments, parseMarkdownWithCodeBlocks, recordGuardEvaluation, recordServerResponse, recordTransition, registerCheck, registerTick, registerTrait, registerTraitSnapshot, renderStateMachineToDomData, renderStateMachineToSvg, setDebugEnabled, setEntityProvider, setTickActive, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, subscribeToVerification, toggleDebug, unregisterTick, unregisterTrait, updateAssetStatus, updateBridgeHealth, updateCheck, updateGuardResult, updateTickExecution, updateTraitState, waitForTransition };
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * @packageDocumentation
11
11
  */
12
- import type { BusEvent, EventPayload } from '@almadar/core';
12
+ import type { BusEvent, BusEventSource, EntityRow, EventPayload } from '@almadar/core';
13
13
  export type CheckStatus = "pass" | "fail" | "pending" | "warn";
14
14
  export interface VerificationCheck {
15
15
  id: string;
@@ -63,13 +63,67 @@ export interface VerificationSummary {
63
63
  warnings: number;
64
64
  pending: number;
65
65
  }
66
+ /**
67
+ * Per-trait state snapshot exposed to the verifier so it can assert that
68
+ * reducer data (populated by fetch/persist transitions) and the last
69
+ * dispatched payload land in the DOM correctly (VG4/VG6/VG11a/b/c).
70
+ *
71
+ * Mirrors what `useTraitStateMachine` / generated trait logic hooks keep
72
+ * internally, without the verifier having to parse rendered text.
73
+ */
74
+ export interface TraitStateSnapshot {
75
+ /** Trait name as declared in the schema. */
76
+ traitName: string;
77
+ /** Current state machine state. */
78
+ currentState: string;
79
+ /** Declared state names for this trait (non-empty for healthy trait refs). */
80
+ states: string[];
81
+ /** Declared event keys for this trait (non-empty for healthy trait refs). */
82
+ events: string[];
83
+ /**
84
+ * Entity data keyed by entity name. Same shape the trait reducer holds
85
+ * in `state.data`. Snapshot-on-read; mutating the returned arrays does
86
+ * not affect the live reducer.
87
+ */
88
+ data: Record<string, EntityRow[]>;
89
+ /** Payload of the last event the state machine processed, if any. */
90
+ lastPayload?: EventPayload;
91
+ /**
92
+ * Last event the walker (or a UI click) dispatched into this trait.
93
+ * Used by VG11a to resolve `@payload.X` expected values.
94
+ */
95
+ lastEventDispatched?: {
96
+ event: string;
97
+ payload?: EventPayload;
98
+ source?: BusEventSource;
99
+ timestamp: number;
100
+ };
101
+ /**
102
+ * Bus events received from the server's `emittedEvents` cascade since the
103
+ * last user dispatch. VG4 compares the length against the number of
104
+ * `emit: { success/failure: ... }` entries on the triggering transition.
105
+ */
106
+ cascadeReceived: Array<{
107
+ event: string;
108
+ payload?: EventPayload;
109
+ timestamp: number;
110
+ }>;
111
+ }
66
112
  export interface VerificationSnapshot {
67
113
  checks: VerificationCheck[];
68
114
  transitions: TransitionTrace[];
69
115
  bridge: BridgeHealth | null;
70
116
  summary: VerificationSummary;
117
+ /** Per-trait reducer snapshot (populated once `bindTraitSnapshotGetter` runs). */
118
+ traits: TraitStateSnapshot[];
71
119
  }
72
120
  type ChangeListener = () => void;
121
+ /**
122
+ * Per-trait snapshot getter. Each generated trait logic hook (or
123
+ * `useTraitStateMachine` trait binding) registers one on mount so the
124
+ * verifier can read the live reducer state for that trait.
125
+ */
126
+ export type TraitSnapshotGetter = () => TraitStateSnapshot;
73
127
  export declare function registerCheck(id: string, label: string, status?: CheckStatus, details?: string): void;
74
128
  export declare function updateCheck(id: string, status: CheckStatus, details?: string): void;
75
129
  export declare function getAllChecks(): VerificationCheck[];
@@ -86,6 +140,15 @@ export declare function updateBridgeHealth(health: BridgeHealth): void;
86
140
  export declare function getBridgeHealth(): BridgeHealth | null;
87
141
  export declare function getSummary(): VerificationSummary;
88
142
  export declare function getSnapshot(): VerificationSnapshot;
143
+ /**
144
+ * Per-trait snapshot for the verifier.
145
+ *
146
+ * Iterates every registered trait getter and collects the live reducer
147
+ * state. Empty until at least one trait hook calls `registerTraitSnapshot`.
148
+ * A getter that throws is logged and skipped — one broken trait must not
149
+ * poison the rest of the snapshot.
150
+ */
151
+ export declare function getTraitSnapshots(): TraitStateSnapshot[];
89
152
  export declare function subscribeToVerification(listener: ChangeListener): () => void;
90
153
  /** Asset load status for canvas verification */
91
154
  export type AssetLoadStatus = "loaded" | "failed" | "pending";
@@ -108,6 +171,8 @@ interface OrbitalVerificationAPI {
108
171
  sendEvent?: (event: string, payload?: Record<string, unknown>) => void;
109
172
  /** Get current trait state */
110
173
  getTraitState?: (traitName: string) => string | undefined;
174
+ /** Per-trait reducer snapshots (VG4/VG6/VG11a/b/c). */
175
+ getTraitSnapshots?: () => TraitStateSnapshot[];
111
176
  /** Capture a canvas frame as PNG data URL. Registered by game organisms. */
112
177
  captureFrame?: () => string | null;
113
178
  /** Asset load status map. Registered by game organisms. */
@@ -139,6 +204,17 @@ export declare function bindEventBus(eventBus: {
139
204
  * Bind a trait state getter so automation can query current states.
140
205
  */
141
206
  export declare function bindTraitStateGetter(getter: (traitName: string) => string | undefined): void;
207
+ /**
208
+ * Register a per-trait snapshot provider. The generated trait logic hook
209
+ * (or `useTraitStateMachine`) calls this once on mount, passing a getter
210
+ * that reads the current reducer state via a ref. Returns an unregister
211
+ * function for cleanup on unmount.
212
+ *
213
+ * Calling this twice for the same `traitName` replaces the previous
214
+ * getter (e.g. page navigation remounts the trait; the new registration
215
+ * wins).
216
+ */
217
+ export declare function registerTraitSnapshot(traitName: string, getter: TraitSnapshotGetter): () => void;
142
218
  /**
143
219
  * Register a canvas frame capture function.
144
220
  * Called by game organisms (IsometricCanvas, PlatformerCanvas, SimulationCanvas)
@@ -8901,12 +8901,19 @@ function getState() {
8901
8901
  checks: /* @__PURE__ */ new Map(),
8902
8902
  transitions: [],
8903
8903
  bridgeHealth: null,
8904
- listeners: /* @__PURE__ */ new Set()
8904
+ listeners: /* @__PURE__ */ new Set(),
8905
+ traitSnapshots: /* @__PURE__ */ new Map()
8905
8906
  };
8906
8907
  }
8907
8908
  return w.__verificationRegistryState;
8908
8909
  }
8909
- return { checks: /* @__PURE__ */ new Map(), transitions: [], bridgeHealth: null, listeners: /* @__PURE__ */ new Set() };
8910
+ return {
8911
+ checks: /* @__PURE__ */ new Map(),
8912
+ transitions: [],
8913
+ bridgeHealth: null,
8914
+ listeners: /* @__PURE__ */ new Set(),
8915
+ traitSnapshots: /* @__PURE__ */ new Map()
8916
+ };
8910
8917
  }
8911
8918
  function notifyListeners() {
8912
8919
  getState().listeners.forEach((l) => l());
@@ -8983,9 +8990,21 @@ function getSnapshot() {
8983
8990
  checks: getAllChecks(),
8984
8991
  transitions: getTransitions(),
8985
8992
  bridge: getBridgeHealth(),
8986
- summary: getSummary()
8993
+ summary: getSummary(),
8994
+ traits: getTraitSnapshots()
8987
8995
  };
8988
8996
  }
8997
+ function getTraitSnapshots() {
8998
+ const snapshots = [];
8999
+ for (const [traitName, getter] of getState().traitSnapshots.entries()) {
9000
+ try {
9001
+ snapshots.push(getter());
9002
+ } catch (err) {
9003
+ log2.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
9004
+ }
9005
+ }
9006
+ return snapshots;
9007
+ }
8989
9008
  function subscribeToVerification(listener) {
8990
9009
  getState().listeners.add(listener);
8991
9010
  return () => getState().listeners.delete(listener);
@@ -8999,8 +9018,11 @@ function exposeOnWindow() {
8999
9018
  getTransitions,
9000
9019
  getBridge: getBridgeHealth,
9001
9020
  getSummary,
9002
- waitForTransition
9021
+ waitForTransition,
9022
+ getTraitSnapshots
9003
9023
  };
9024
+ } else if (!window.__orbitalVerification.getTraitSnapshots) {
9025
+ window.__orbitalVerification.getTraitSnapshots = getTraitSnapshots;
9004
9026
  }
9005
9027
  }
9006
9028
  function waitForTransition(event, timeoutMs = 1e4) {
@@ -8856,12 +8856,19 @@ function getState() {
8856
8856
  checks: /* @__PURE__ */ new Map(),
8857
8857
  transitions: [],
8858
8858
  bridgeHealth: null,
8859
- listeners: /* @__PURE__ */ new Set()
8859
+ listeners: /* @__PURE__ */ new Set(),
8860
+ traitSnapshots: /* @__PURE__ */ new Map()
8860
8861
  };
8861
8862
  }
8862
8863
  return w.__verificationRegistryState;
8863
8864
  }
8864
- return { checks: /* @__PURE__ */ new Map(), transitions: [], bridgeHealth: null, listeners: /* @__PURE__ */ new Set() };
8865
+ return {
8866
+ checks: /* @__PURE__ */ new Map(),
8867
+ transitions: [],
8868
+ bridgeHealth: null,
8869
+ listeners: /* @__PURE__ */ new Set(),
8870
+ traitSnapshots: /* @__PURE__ */ new Map()
8871
+ };
8865
8872
  }
8866
8873
  function notifyListeners() {
8867
8874
  getState().listeners.forEach((l) => l());
@@ -8938,9 +8945,21 @@ function getSnapshot() {
8938
8945
  checks: getAllChecks(),
8939
8946
  transitions: getTransitions(),
8940
8947
  bridge: getBridgeHealth(),
8941
- summary: getSummary()
8948
+ summary: getSummary(),
8949
+ traits: getTraitSnapshots()
8942
8950
  };
8943
8951
  }
8952
+ function getTraitSnapshots() {
8953
+ const snapshots = [];
8954
+ for (const [traitName, getter] of getState().traitSnapshots.entries()) {
8955
+ try {
8956
+ snapshots.push(getter());
8957
+ } catch (err) {
8958
+ log2.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
8959
+ }
8960
+ }
8961
+ return snapshots;
8962
+ }
8944
8963
  function subscribeToVerification(listener) {
8945
8964
  getState().listeners.add(listener);
8946
8965
  return () => getState().listeners.delete(listener);
@@ -8954,8 +8973,11 @@ function exposeOnWindow() {
8954
8973
  getTransitions,
8955
8974
  getBridge: getBridgeHealth,
8956
8975
  getSummary,
8957
- waitForTransition
8976
+ waitForTransition,
8977
+ getTraitSnapshots
8958
8978
  };
8979
+ } else if (!window.__orbitalVerification.getTraitSnapshots) {
8980
+ window.__orbitalVerification.getTraitSnapshots = getTraitSnapshots;
8959
8981
  }
8960
8982
  }
8961
8983
  function waitForTransition(event, timeoutMs = 1e4) {
@@ -869,12 +869,19 @@ function getState() {
869
869
  checks: /* @__PURE__ */ new Map(),
870
870
  transitions: [],
871
871
  bridgeHealth: null,
872
- listeners: /* @__PURE__ */ new Set()
872
+ listeners: /* @__PURE__ */ new Set(),
873
+ traitSnapshots: /* @__PURE__ */ new Map()
873
874
  };
874
875
  }
875
876
  return w.__verificationRegistryState;
876
877
  }
877
- return { checks: /* @__PURE__ */ new Map(), transitions: [], bridgeHealth: null, listeners: /* @__PURE__ */ new Set() };
878
+ return {
879
+ checks: /* @__PURE__ */ new Map(),
880
+ transitions: [],
881
+ bridgeHealth: null,
882
+ listeners: /* @__PURE__ */ new Set(),
883
+ traitSnapshots: /* @__PURE__ */ new Map()
884
+ };
878
885
  }
879
886
  function notifyListeners2() {
880
887
  getState().listeners.forEach((l) => l());
@@ -981,9 +988,21 @@ function getSnapshot2() {
981
988
  checks: getAllChecks(),
982
989
  transitions: getTransitions(),
983
990
  bridge: getBridgeHealth(),
984
- summary: getSummary()
991
+ summary: getSummary(),
992
+ traits: getTraitSnapshots()
985
993
  };
986
994
  }
995
+ function getTraitSnapshots() {
996
+ const snapshots = [];
997
+ for (const [traitName, getter] of getState().traitSnapshots.entries()) {
998
+ try {
999
+ snapshots.push(getter());
1000
+ } catch (err) {
1001
+ log2.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
1002
+ }
1003
+ }
1004
+ return snapshots;
1005
+ }
987
1006
  function subscribeToVerification(listener) {
988
1007
  getState().listeners.add(listener);
989
1008
  return () => getState().listeners.delete(listener);
@@ -997,8 +1016,11 @@ function exposeOnWindow() {
997
1016
  getTransitions,
998
1017
  getBridge: getBridgeHealth,
999
1018
  getSummary,
1000
- waitForTransition
1019
+ waitForTransition,
1020
+ getTraitSnapshots
1001
1021
  };
1022
+ } else if (!window.__orbitalVerification.getTraitSnapshots) {
1023
+ window.__orbitalVerification.getTraitSnapshots = getTraitSnapshots;
1002
1024
  }
1003
1025
  }
1004
1026
  function waitForTransition(event, timeoutMs = 1e4) {
@@ -824,12 +824,19 @@ function getState() {
824
824
  checks: /* @__PURE__ */ new Map(),
825
825
  transitions: [],
826
826
  bridgeHealth: null,
827
- listeners: /* @__PURE__ */ new Set()
827
+ listeners: /* @__PURE__ */ new Set(),
828
+ traitSnapshots: /* @__PURE__ */ new Map()
828
829
  };
829
830
  }
830
831
  return w.__verificationRegistryState;
831
832
  }
832
- return { checks: /* @__PURE__ */ new Map(), transitions: [], bridgeHealth: null, listeners: /* @__PURE__ */ new Set() };
833
+ return {
834
+ checks: /* @__PURE__ */ new Map(),
835
+ transitions: [],
836
+ bridgeHealth: null,
837
+ listeners: /* @__PURE__ */ new Set(),
838
+ traitSnapshots: /* @__PURE__ */ new Map()
839
+ };
833
840
  }
834
841
  function notifyListeners2() {
835
842
  getState().listeners.forEach((l) => l());
@@ -936,9 +943,21 @@ function getSnapshot2() {
936
943
  checks: getAllChecks(),
937
944
  transitions: getTransitions(),
938
945
  bridge: getBridgeHealth(),
939
- summary: getSummary()
946
+ summary: getSummary(),
947
+ traits: getTraitSnapshots()
940
948
  };
941
949
  }
950
+ function getTraitSnapshots() {
951
+ const snapshots = [];
952
+ for (const [traitName, getter] of getState().traitSnapshots.entries()) {
953
+ try {
954
+ snapshots.push(getter());
955
+ } catch (err) {
956
+ log2.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
957
+ }
958
+ }
959
+ return snapshots;
960
+ }
942
961
  function subscribeToVerification(listener) {
943
962
  getState().listeners.add(listener);
944
963
  return () => getState().listeners.delete(listener);
@@ -952,8 +971,11 @@ function exposeOnWindow() {
952
971
  getTransitions,
953
972
  getBridge: getBridgeHealth,
954
973
  getSummary,
955
- waitForTransition
974
+ waitForTransition,
975
+ getTraitSnapshots
956
976
  };
977
+ } else if (!window.__orbitalVerification.getTraitSnapshots) {
978
+ window.__orbitalVerification.getTraitSnapshots = getTraitSnapshots;
957
979
  }
958
980
  }
959
981
  function waitForTransition(event, timeoutMs = 1e4) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "3.1.4",
3
+ "version": "3.2.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",