@almadar/shell-web 1.0.0 → 1.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.
Files changed (109) hide show
  1. package/LICENSE +72 -0
  2. package/dist/AvlGlyph-KZMJDBEB.js +5 -0
  3. package/dist/AvlStateMachine-KVZMFHFU.js +8 -0
  4. package/dist/AvlTransitionDetail-7DVGV27I.js +10 -0
  5. package/dist/AvlTransitionExplainer-RMJ5LQLK.js +11 -0
  6. package/dist/BehaviorView-EYRPME67.js +10 -0
  7. package/dist/{FileTree-BCFnBEuQ.d.ts → FileTree-B3GDAjaQ.d.ts} +131 -4
  8. package/dist/FlowCanvas-J54627TC.js +23 -0
  9. package/dist/{FlowCanvas-3JRMNJLV.css → FlowCanvas-R4LL3KRI.css} +190 -192
  10. package/dist/{GameAudioProvider-ceM_n0ey.d.ts → GameAudioProvider-BgWOOYT3.d.ts} +15 -20
  11. package/dist/{KernelEngineContext-CcxGYtlr.d.ts → KernelEngineContext-BPx-q0iw.d.ts} +15 -2
  12. package/dist/{LayersPanel-M2LHWUFF.js → LayersPanel-PSXI4EHG.js} +4 -4
  13. package/dist/ModuleCard-TNRLL45H.js +6 -0
  14. package/dist/{OrbInspector-MHLJ6OEE.css → OrbInspector-2EGVZLOJ.css} +190 -192
  15. package/dist/OrbInspector-UBEQWWZ2.js +23 -0
  16. package/dist/{parseLessonSegments-GpCeMrb2.d.ts → SegmentRenderer-BAQ6Jwf6.d.ts} +4 -20
  17. package/dist/{Select-B-iDdnvE.d.ts → Select-BJ8Fgc8A.d.ts} +1 -1
  18. package/dist/{UISlotContext-Dl_ewwCI.d.ts → UISlotContext-7r0SQdTL.d.ts} +1 -1
  19. package/dist/UISlotRenderer-5OURMAP2.js +23 -0
  20. package/dist/{UISlotRenderer-KVFO6J7R.css → UISlotRenderer-SJBSQGBQ.css} +190 -192
  21. package/dist/auth/react/index.js +7 -6
  22. package/dist/avl/index.css +190 -192
  23. package/dist/avl/index.d.ts +19 -7
  24. package/dist/avl/index.js +170 -39
  25. package/dist/{chunk-AE7VCQB6.js → chunk-2LNXLMK3.js} +2 -2
  26. package/dist/{chunk-REXYVBUO.js → chunk-3DA36FOA.js} +1 -1
  27. package/dist/{chunk-UXLE3IPR.js → chunk-3UQNFRYV.js} +207 -9
  28. package/dist/{chunk-AGXD77SL.js → chunk-3YUMGEEW.js} +1 -1
  29. package/dist/{chunk-K4MOPSEL.js → chunk-6RXP5ZXE.js} +7 -8
  30. package/dist/{chunk-E6KA4J6N.js → chunk-7UCL26QB.js} +4 -5
  31. package/dist/{chunk-57DC34LY.js → chunk-AL2XXMYR.js} +2 -2
  32. package/dist/{chunk-YHMRX6YA.js → chunk-ANTJUQRD.js} +53 -13
  33. package/dist/{chunk-P4ZFUQFF.js → chunk-AZ74UPG6.js} +4 -1
  34. package/dist/{chunk-ROICKAU7.js → chunk-B23EZH2P.js} +3 -3
  35. package/dist/{chunk-CPLN6NBQ.js → chunk-CCO2ZH7F.js} +3 -4
  36. package/dist/{chunk-4YXBKHHM.js → chunk-D5FJU4XC.js} +87 -16
  37. package/dist/{chunk-HH5KSMH5.js → chunk-DPDKBY6Z.js} +1 -1
  38. package/dist/{chunk-A2LR6VQQ.js → chunk-ECC3WQIB.js} +9 -93
  39. package/dist/{chunk-VO2TTLS5.js → chunk-GHAF7QUD.js} +1 -1
  40. package/dist/{chunk-TXAUOLWZ.js → chunk-HA2BYO5E.js} +1 -1
  41. package/dist/{chunk-ILQXJ2AR.js → chunk-JEN4EIUF.js} +1 -1
  42. package/dist/{chunk-UTDC2NEA.js → chunk-KTYOYEVA.js} +1 -1
  43. package/dist/{chunk-X3DMMX27.js → chunk-LINJRTNB.js} +2 -2
  44. package/dist/{chunk-TUPZWTRE.js → chunk-LKL5RULQ.js} +467 -141
  45. package/dist/{chunk-UU57VNS2.js → chunk-PWXZN5G5.js} +2 -2
  46. package/dist/{chunk-SP5CDJ6K.js → chunk-RDPELAFQ.js} +4 -4
  47. package/dist/{chunk-PRXQGGCO.js → chunk-S3LS3B7N.js} +1 -1
  48. package/dist/{chunk-LHP2TK7O.js → chunk-TAEOMNDK.js} +3611 -4737
  49. package/dist/{chunk-3S54FWRC.js → chunk-UFQLHCFJ.js} +1 -1
  50. package/dist/{chunk-AB3X7QTE.js → chunk-V5SVGUYN.js} +2 -3
  51. package/dist/{chunk-3VZ36ZKO.js → chunk-ZDRDJKYB.js} +5 -2
  52. package/dist/components/index.css +190 -192
  53. package/dist/components/index.d.ts +568 -190
  54. package/dist/components/index.js +27 -30
  55. package/dist/context/index.d.ts +2 -2
  56. package/dist/context/index.js +5 -5
  57. package/dist/core.d.ts +21 -4
  58. package/dist/core.js +1 -1
  59. package/dist/{fx-CmQjnHmT.d.ts → fx-Bx5RqplG.d.ts} +10 -7
  60. package/dist/hooks/index.d.ts +8 -8
  61. package/dist/hooks/index.js +6 -6
  62. package/dist/index.d.ts +4 -0
  63. package/dist/index.js +2 -2
  64. package/dist/{katexPlugin-FA7NX4PE.css → katexPlugin-BUHVNRBJ.css} +1 -1
  65. package/dist/{kernel-client-TZKGHJRY.js → kernel-client-NMZ56JVU.js} +60 -6
  66. package/dist/{kernel-wire-wNdAPfhJ.d.ts → kernel-wire-CRsHtLsf.d.ts} +8 -1
  67. package/dist/lib/index.d.ts +3 -4
  68. package/dist/lib/index.js +435 -4
  69. package/dist/providers/index.css +190 -192
  70. package/dist/providers/index.d.ts +6 -8
  71. package/dist/providers/index.js +21 -25
  72. package/dist/renderer/index.d.ts +3 -79
  73. package/dist/renderer/index.js +2 -2
  74. package/dist/runtime/index.css +190 -192
  75. package/dist/runtime/index.d.ts +9 -2
  76. package/dist/runtime/index.js +20 -23
  77. package/dist/ssr/index.cjs +105 -28
  78. package/dist/ssr/index.js +106 -29
  79. package/dist/test-support.js +2 -2
  80. package/dist/{useUISlots-CiobNFGb.d.ts → useUISlots-BLcGd__D.d.ts} +2 -0
  81. package/dist/{paintDispatch-CuJLsr9Y.d.ts → verificationRegistry-BLuQU1JV.d.ts} +127 -15
  82. package/package.json +10 -38
  83. package/src/core/locales/ar.json +10 -1
  84. package/src/core/locales/en.json +10 -1
  85. package/src/core/locales/sl.json +10 -1
  86. package/tailwind-preset.cjs +8 -4
  87. package/dist/AvlGlyph-EPJKFEO3.js +0 -6
  88. package/dist/AvlStateMachine-RKZIKNGC.js +0 -9
  89. package/dist/AvlTransitionDetail-63SD6GZF.js +0 -11
  90. package/dist/AvlTransitionExplainer-ZBTLOM3T.js +0 -12
  91. package/dist/BehaviorView-YS5G4GNB.js +0 -11
  92. package/dist/Canvas3DHost-BkZQB5l2.d.ts +0 -552
  93. package/dist/FlowCanvas-AUMTWMNG.js +0 -26
  94. package/dist/ModuleCard-QHDGK5XK.js +0 -7
  95. package/dist/OrbInspector-QCPEPUPH.js +0 -26
  96. package/dist/UISlotRenderer-C7WWOK43.js +0 -26
  97. package/dist/avl-3d-context-BycmO6tG.d.ts +0 -201
  98. package/dist/avl-schema-parser-CtJxJ9KU.d.ts +0 -132
  99. package/dist/avl-zoom-state-CKMVuBFg.d.ts +0 -17
  100. package/dist/chunk-4T3P43NS.js +0 -1133
  101. package/dist/chunk-DZBQA2OW.js +0 -176
  102. package/dist/chunk-EOWMARUB.js +0 -16
  103. package/dist/chunk-GFXCPUMX.js +0 -1334
  104. package/dist/chunk-ILZ7ORX7.js +0 -432
  105. package/dist/three/index.css +0 -503
  106. package/dist/three/index.d.ts +0 -1185
  107. package/dist/three/index.js +0 -3908
  108. package/dist/verificationRegistry-CVrcxG1s.d.ts +0 -122
  109. /package/dist/{katexPlugin-NCDKOOQY.js → katexPlugin-WGJ4JFZU.js} +0 -0
@@ -1,5 +1,5 @@
1
- import { perfStore, pushPerfEntry } from './chunk-3VZ36ZKO.js';
2
- import { isMotionEnabled } from './chunk-4YXBKHHM.js';
1
+ import { perfStore, pushPerfEntry } from './chunk-ZDRDJKYB.js';
2
+ import { isMotionEnabled } from './chunk-D5FJU4XC.js';
3
3
  import { useRef, useLayoutEffect, useSyncExternalStore } from 'react';
4
4
  import { ENTER_DELAY_STEPS, ENTER_ANIMATIONS, isFileValue } from '@almadar/core';
5
5
  export { getNestedValue } from '@almadar/core';
@@ -514,42 +514,26 @@ function middleSnake(a, aLo, aHi, b, bLo, bHi) {
514
514
  }
515
515
  throw new Error("computeLineDiff: no middle snake \u2014 unreachable for differing texts");
516
516
  }
517
- function usePerfBuffer() {
518
- return useSyncExternalStore(perfStore.subscribe, perfStore.getSnapshot, perfStore.getSnapshot);
519
- }
520
- var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
521
- pushPerfEntry({
522
- name: `profiler:${id}:${phase}`,
523
- durationMs: actualDuration,
524
- ts: commitTime,
525
- detail: { baseDuration }
526
- });
527
- };
528
517
 
529
- // src/lib/lessonSegmentUtils.ts
530
- function parseMarkdownWithCodeBlocks(content) {
531
- const segments = [];
532
- const codeBlockRegex = /```([^\n\r]*)\r?\n([\s\S]*?)```/g;
533
- let lastIndex = 0;
534
- let match;
535
- while ((match = codeBlockRegex.exec(content)) !== null) {
536
- const before = content.slice(lastIndex, match.index);
537
- if (before.trim()) {
538
- segments.push({ type: "markdown", content: before });
539
- }
540
- const tokens = match[1].trim().split(/\s+/).filter(Boolean);
541
- let rawLanguage = tokens[0] ?? "text";
542
- const suffixRunnable = rawLanguage.endsWith("-runnable");
543
- const runnable = suffixRunnable || tokens.includes("run");
544
- const baseLanguage = suffixRunnable ? rawLanguage.slice(0, -"-runnable".length) || "text" : rawLanguage;
545
- segments.push({ type: "code", language: baseLanguage, content: match[2].trim(), runnable });
546
- lastIndex = codeBlockRegex.lastIndex;
547
- }
548
- const remaining = content.slice(lastIndex);
549
- if (remaining.trim()) {
550
- segments.push({ type: "markdown", content: remaining });
551
- }
552
- return segments;
518
+ // src/lib/keyMapEvent.ts
519
+ function isEditableTarget(target) {
520
+ if (!(target instanceof HTMLElement)) return false;
521
+ const tag = target.tagName;
522
+ if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
523
+ if (target.isContentEditable || target.contentEditable === "true") return true;
524
+ const attr = target.getAttribute("contenteditable");
525
+ return attr === "" || attr === "true" || attr === "plaintext-only";
526
+ }
527
+ function keyMapCode(e) {
528
+ let code = e.code;
529
+ if (e.altKey) code = `Alt+${code}`;
530
+ if (e.shiftKey) code = `Shift+${code}`;
531
+ if (e.metaKey || e.ctrlKey) code = `Mod+${code}`;
532
+ return code;
533
+ }
534
+ function resolveKeyMapEvent(map, e) {
535
+ if (!map || isEditableTarget(e.target)) return void 0;
536
+ return map[keyMapCode(e)] ?? map[e.code];
553
537
  }
554
538
  function resolveImageUrl(value) {
555
539
  if (typeof value === "string") {
@@ -560,6 +544,414 @@ function resolveImageUrl(value) {
560
544
  }
561
545
  return void 0;
562
546
  }
547
+ var log = createLogger("almadar:bridge");
548
+ var MAX_TRANSITIONS = 500;
549
+ function getState() {
550
+ if (typeof window !== "undefined") {
551
+ const w = window;
552
+ if (!w.__verificationRegistryState) {
553
+ w.__verificationRegistryState = {
554
+ checks: /* @__PURE__ */ new Map(),
555
+ transitions: [],
556
+ bridgeHealth: null,
557
+ listeners: /* @__PURE__ */ new Set(),
558
+ traitSnapshots: /* @__PURE__ */ new Map()
559
+ };
560
+ }
561
+ return w.__verificationRegistryState;
562
+ }
563
+ return {
564
+ checks: /* @__PURE__ */ new Map(),
565
+ transitions: [],
566
+ bridgeHealth: null,
567
+ listeners: /* @__PURE__ */ new Set(),
568
+ traitSnapshots: /* @__PURE__ */ new Map()
569
+ };
570
+ }
571
+ function notifyListeners() {
572
+ getState().listeners.forEach((l) => l());
573
+ exposeOnWindow();
574
+ }
575
+ function registerCheck(id, label, status = "pending", details) {
576
+ getState().checks.set(id, { id, label, status, details, updatedAt: Date.now() });
577
+ notifyListeners();
578
+ }
579
+ function updateCheck(id, status, details) {
580
+ const check = getState().checks.get(id);
581
+ if (check) {
582
+ check.status = status;
583
+ if (details !== void 0) check.details = details;
584
+ check.updatedAt = Date.now();
585
+ } else {
586
+ getState().checks.set(id, { id, label: id, status, details, updatedAt: Date.now() });
587
+ }
588
+ notifyListeners();
589
+ }
590
+ function getAllChecks() {
591
+ return Array.from(getState().checks.values());
592
+ }
593
+ function recordTransition(trace) {
594
+ const entry = {
595
+ ...trace,
596
+ id: `t-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
597
+ };
598
+ log.debug("transition:recorded", { trait: trace.traitName, from: trace.from, to: trace.to, event: trace.event, effectCount: trace.effects.length });
599
+ getState().transitions.push(entry);
600
+ if (getState().transitions.length > MAX_TRANSITIONS) {
601
+ getState().transitions.shift();
602
+ }
603
+ if (entry.event === "INIT") {
604
+ const hasFetch = entry.effects.some((e) => e.type === "fetch");
605
+ const hasEntitySeed = entry.effects.some(
606
+ (e) => e.type === "set" && typeof e.args[0] === "string" && e.args[0].startsWith("@entity.")
607
+ );
608
+ const checkId = `init-fetch-${entry.traitName}`;
609
+ if (hasFetch || hasEntitySeed) {
610
+ registerCheck(
611
+ checkId,
612
+ `INIT transition for "${entry.traitName}" has fetch or entity-seed effect`,
613
+ "pass"
614
+ );
615
+ } else {
616
+ const rendersEntityData = entry.effects.some(
617
+ (e) => e.type === "render-ui" && JSON.stringify(e.args).includes("@entity.")
618
+ );
619
+ if (rendersEntityData) {
620
+ const siblingSeeds = getState().transitions.some(
621
+ (t) => t.event === "INIT" && t.effects.some(
622
+ (e) => e.type === "fetch" || e.type === "set" && typeof e.args[0] === "string" && e.args[0].startsWith("@entity.")
623
+ )
624
+ );
625
+ if (siblingSeeds) {
626
+ registerCheck(
627
+ checkId,
628
+ `INIT transition for "${entry.traitName}" has sibling entity-seed (shared entity)`,
629
+ "pass"
630
+ );
631
+ } else {
632
+ registerCheck(
633
+ checkId,
634
+ `INIT transition for "${entry.traitName}" missing fetch effect`,
635
+ "fail",
636
+ "Entity-bound render-ui without a fetch effect will show empty data"
637
+ );
638
+ }
639
+ }
640
+ }
641
+ }
642
+ const failedEffects = entry.effects.filter((e) => e.status === "failed");
643
+ if (failedEffects.length > 0) {
644
+ registerCheck(
645
+ `effects-${entry.id}`,
646
+ `Effects failed in ${entry.traitName}: ${entry.from} -> ${entry.to}`,
647
+ "fail",
648
+ failedEffects.map((e) => `${e.type}: ${e.error}`).join("; ")
649
+ );
650
+ }
651
+ notifyListeners();
652
+ }
653
+ function getTransitions() {
654
+ return [...getState().transitions];
655
+ }
656
+ function getTransitionsForTrait(traitName) {
657
+ return getState().transitions.filter((t) => t.traitName === traitName);
658
+ }
659
+ function recordServerResponse(orbitalName, event, response) {
660
+ const { effectResults, ...responseFields } = response;
661
+ const serverResponse = {
662
+ ...responseFields,
663
+ orbitalName,
664
+ timestamp: Date.now()
665
+ };
666
+ const entry = {
667
+ id: `srv-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
668
+ traitName: `server:${orbitalName}`,
669
+ from: "server",
670
+ to: "server",
671
+ event,
672
+ effects: effectResults ?? [],
673
+ serverResponse,
674
+ timestamp: Date.now()
675
+ };
676
+ getState().transitions.push(entry);
677
+ if (getState().transitions.length > MAX_TRANSITIONS) {
678
+ getState().transitions.shift();
679
+ }
680
+ if (!response.success && response.error) {
681
+ registerCheck(
682
+ `server-error-${entry.id}`,
683
+ `Server error for ${orbitalName}:${event}`,
684
+ "fail",
685
+ response.error
686
+ );
687
+ }
688
+ notifyListeners();
689
+ }
690
+ function serverEffectTraces(results) {
691
+ if (!results) return [];
692
+ return results.map((r) => {
693
+ const resultId = typeof r.data === "object" && r.data !== null && !Array.isArray(r.data) && "id" in r.data && typeof r.data.id === "string" ? r.data.id : void 0;
694
+ const outcome = r.denied ? "denied" : r.success ? "success" : "failed";
695
+ return {
696
+ type: r.effect,
697
+ ...r.entityType !== void 0 ? { entityName: r.entityType } : {},
698
+ ...r.action === "create" || r.action === "update" || r.action === "delete" || r.action === "batch" ? { action: r.action } : {},
699
+ ...resultId !== void 0 ? { resultId } : {},
700
+ outcome,
701
+ args: [],
702
+ status: outcome === "success" ? "executed" : "failed",
703
+ ...r.error !== void 0 ? { error: r.error } : {},
704
+ ...r.target !== void 0 ? { target: r.target } : {},
705
+ ...r.routed !== void 0 ? { routed: r.routed } : {}
706
+ };
707
+ });
708
+ }
709
+ function recordOrbitalResponse(orbitalName, request, response) {
710
+ recordServerResponse(orbitalName, request.event, {
711
+ success: response.success,
712
+ transitioned: response.transitioned,
713
+ emitted: response.emittedEvents.map((e) => ({ event: e.event, ...e.payload !== void 0 ? { payload: e.payload } : {} })),
714
+ emittedEvents: response.emittedEvents.map((e) => e.event),
715
+ clientEffects: response.clientEffectsByTrait?.length ?? 0,
716
+ dataEntities: Object.fromEntries(Object.entries(response.data ?? {}).map(([name, rows]) => [name, rows.length])),
717
+ ...response.error !== void 0 ? { error: response.error } : {},
718
+ effectResults: serverEffectTraces(response.effectResults)
719
+ });
720
+ }
721
+ function recordingTransport(transport) {
722
+ const subscribe = transport.subscribe?.bind(transport);
723
+ const subscribeHostDispatches = transport.subscribeHostDispatches?.bind(transport);
724
+ return {
725
+ ...transport.hostsBrowserStore !== void 0 ? { hostsBrowserStore: transport.hostsBrowserStore } : {},
726
+ register: (schema) => transport.register(schema),
727
+ unregister: () => transport.unregister(),
728
+ send: async (orbitalName, request) => {
729
+ const response = await transport.send(orbitalName, request);
730
+ recordOrbitalResponse(orbitalName, request, response);
731
+ return response;
732
+ },
733
+ ...subscribe !== void 0 ? { subscribe } : {},
734
+ ...subscribeHostDispatches !== void 0 ? { subscribeHostDispatches } : {}
735
+ };
736
+ }
737
+ function updateBridgeHealth(health) {
738
+ getState().bridgeHealth = { ...health };
739
+ const checkId = "server-bridge";
740
+ if (health.connected) {
741
+ registerCheck(checkId, "Server bridge connected", "pass");
742
+ } else {
743
+ registerCheck(
744
+ checkId,
745
+ "Server bridge disconnected",
746
+ "fail",
747
+ health.lastError || "Bridge is not connected"
748
+ );
749
+ }
750
+ notifyListeners();
751
+ }
752
+ function getBridgeHealth() {
753
+ const bh = getState().bridgeHealth;
754
+ return bh ? { ...bh } : null;
755
+ }
756
+ function getSummary() {
757
+ const allChecks = getAllChecks();
758
+ return {
759
+ totalChecks: allChecks.length,
760
+ passed: allChecks.filter((c) => c.status === "pass").length,
761
+ failed: allChecks.filter((c) => c.status === "fail").length,
762
+ warnings: allChecks.filter((c) => c.status === "warn").length,
763
+ pending: allChecks.filter((c) => c.status === "pending").length
764
+ };
765
+ }
766
+ function getSnapshot() {
767
+ return {
768
+ checks: getAllChecks(),
769
+ transitions: getTransitions(),
770
+ bridge: getBridgeHealth(),
771
+ summary: getSummary(),
772
+ traits: getTraitSnapshots()
773
+ };
774
+ }
775
+ function getTraitSnapshots() {
776
+ const snapshots = [];
777
+ for (const [traitName, getter] of getState().traitSnapshots.entries()) {
778
+ try {
779
+ snapshots.push(getter());
780
+ } catch (err) {
781
+ log.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
782
+ }
783
+ }
784
+ return snapshots;
785
+ }
786
+ function subscribeToVerification(listener) {
787
+ getState().listeners.add(listener);
788
+ return () => getState().listeners.delete(listener);
789
+ }
790
+ function defaultGetTraitState(traitName) {
791
+ const getter = getState().traitSnapshots.get(traitName);
792
+ if (getter === void 0) return void 0;
793
+ try {
794
+ return getter().currentState;
795
+ } catch {
796
+ return void 0;
797
+ }
798
+ }
799
+ function verifierAttached() {
800
+ return typeof window !== "undefined" && window.__ALMADAR_VERIFY__ === true;
801
+ }
802
+ function exposeOnWindow() {
803
+ if (typeof window === "undefined") return;
804
+ if (!window.__orbitalVerification) {
805
+ window.__orbitalVerification = {
806
+ getSnapshot,
807
+ getChecks: getAllChecks,
808
+ getTransitions,
809
+ getBridge: getBridgeHealth,
810
+ getSummary,
811
+ waitForTransition,
812
+ getTraitSnapshots,
813
+ getTraitState: defaultGetTraitState
814
+ };
815
+ } else {
816
+ if (!window.__orbitalVerification.getTraitSnapshots) {
817
+ window.__orbitalVerification.getTraitSnapshots = getTraitSnapshots;
818
+ }
819
+ if (!window.__orbitalVerification.getTraitState) {
820
+ window.__orbitalVerification.getTraitState = defaultGetTraitState;
821
+ }
822
+ }
823
+ }
824
+ function waitForTransition(event, timeoutMs = 1e4) {
825
+ return new Promise((resolve) => {
826
+ const existing = getState().transitions.find((t) => t.event === event);
827
+ if (existing) {
828
+ resolve(existing);
829
+ return;
830
+ }
831
+ const timeout = setTimeout(() => {
832
+ unsub();
833
+ resolve(null);
834
+ }, timeoutMs);
835
+ const unsub = subscribeToVerification(() => {
836
+ const found = getState().transitions.find((t) => t.event === event);
837
+ if (found) {
838
+ clearTimeout(timeout);
839
+ unsub();
840
+ resolve(found);
841
+ }
842
+ });
843
+ });
844
+ }
845
+ function bindEventBus(eventBus) {
846
+ if (typeof window === "undefined") return;
847
+ log.info("bindEventBus", { hasOnAny: !!eventBus.onAny });
848
+ exposeOnWindow();
849
+ if (window.__orbitalVerification) {
850
+ window.__orbitalVerification.sendEvent = (event, payload, traitScope) => {
851
+ const prefixed = event.startsWith("UI:") ? event : traitScope ? `UI:${traitScope}.${event}` : `UI:${event}`;
852
+ log.debug("sendEvent", { event: prefixed, traitScope, payloadKeys: payload ? Object.keys(payload) : [] });
853
+ eventBus.emit(prefixed, payload);
854
+ };
855
+ const MAX_EVENT_LOG = 5e3;
856
+ const eventLog = [];
857
+ let eventLogDropped = 0;
858
+ const bumpEpoch = () => {
859
+ window.__orbitalVerification.eventLogEpoch = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
860
+ };
861
+ window.__orbitalVerification.eventLog = eventLog;
862
+ window.__orbitalVerification.eventLogDropped = 0;
863
+ bumpEpoch();
864
+ window.__orbitalVerification.clearEventLog = () => {
865
+ eventLog.length = 0;
866
+ eventLogDropped = 0;
867
+ window.__orbitalVerification.eventLogDropped = 0;
868
+ bumpEpoch();
869
+ };
870
+ if (eventBus.onAny) {
871
+ const verificationRegistryEventLogger = (event) => {
872
+ eventLog.push({
873
+ type: event.type,
874
+ payload: event.payload,
875
+ ...event.source === void 0 ? {} : { source: event.source },
876
+ timestamp: Date.now()
877
+ });
878
+ if (eventLog.length > MAX_EVENT_LOG) {
879
+ eventLog.shift();
880
+ eventLogDropped += 1;
881
+ window.__orbitalVerification.eventLogDropped = eventLogDropped;
882
+ }
883
+ };
884
+ Object.defineProperty(verificationRegistryEventLogger, "name", {
885
+ value: "verificationRegistry:eventLog"
886
+ });
887
+ eventBus.onAny(verificationRegistryEventLogger);
888
+ }
889
+ }
890
+ }
891
+ function bindConfigApplier(applyConfig) {
892
+ if (typeof window === "undefined") return () => {
893
+ };
894
+ exposeOnWindow();
895
+ const bridge = window.__orbitalVerification;
896
+ if (!bridge) return () => {
897
+ };
898
+ bridge.applyConfig = applyConfig;
899
+ return () => {
900
+ if (bridge.applyConfig === applyConfig) delete bridge.applyConfig;
901
+ };
902
+ }
903
+ function bindTraitStateGetter(getter) {
904
+ if (typeof window === "undefined") return;
905
+ exposeOnWindow();
906
+ if (window.__orbitalVerification) {
907
+ window.__orbitalVerification.getTraitState = getter;
908
+ }
909
+ }
910
+ function registerTraitSnapshot(traitName, getter) {
911
+ if (typeof window === "undefined") return () => {
912
+ };
913
+ getState().traitSnapshots.set(traitName, getter);
914
+ exposeOnWindow();
915
+ notifyListeners();
916
+ return () => {
917
+ const s = getState();
918
+ if (s.traitSnapshots.get(traitName) === getter) {
919
+ s.traitSnapshots.delete(traitName);
920
+ notifyListeners();
921
+ }
922
+ };
923
+ }
924
+ function bindCanvasCapture(captureFn) {
925
+ if (typeof window === "undefined") return;
926
+ exposeOnWindow();
927
+ if (window.__orbitalVerification) {
928
+ window.__orbitalVerification.captureFrame = captureFn;
929
+ }
930
+ }
931
+ function bindLastDrawables(getDrawables) {
932
+ if (typeof window === "undefined") return;
933
+ exposeOnWindow();
934
+ if (window.__orbitalVerification) {
935
+ window.__orbitalVerification.getLastDrawables = getDrawables;
936
+ }
937
+ }
938
+ function updateAssetStatus(url, status) {
939
+ if (typeof window === "undefined") return;
940
+ exposeOnWindow();
941
+ if (window.__orbitalVerification) {
942
+ if (!window.__orbitalVerification.assetStatus) {
943
+ window.__orbitalVerification.assetStatus = {};
944
+ }
945
+ window.__orbitalVerification.assetStatus[url] = status;
946
+ }
947
+ }
948
+ function clearVerification() {
949
+ getState().checks.clear();
950
+ getState().transitions.length = 0;
951
+ getState().bridgeHealth = null;
952
+ notifyListeners();
953
+ }
954
+ exposeOnWindow();
563
955
 
564
956
  // src/lib/parseContentSegments.ts
565
957
  function tryParseOrbitalSchema(code) {
@@ -573,7 +965,7 @@ function tryParseOrbitalSchema(code) {
573
965
  }
574
966
  return null;
575
967
  }
576
- function parseMarkdownWithCodeBlocks2(content) {
968
+ function parseMarkdownWithCodeBlocks(content) {
577
969
  if (!content) return [];
578
970
  const segments = [];
579
971
  const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
@@ -612,7 +1004,7 @@ function parseContentSegments(content) {
612
1004
  while ((match = tagRegex.exec(content)) !== null) {
613
1005
  const before = content.slice(lastIndex, match.index);
614
1006
  if (before.trim()) {
615
- segments.push(...parseMarkdownWithCodeBlocks2(before));
1007
+ segments.push(...parseMarkdownWithCodeBlocks(before));
616
1008
  }
617
1009
  segments.push({
618
1010
  type: "quiz",
@@ -623,12 +1015,12 @@ function parseContentSegments(content) {
623
1015
  }
624
1016
  const remaining = content.slice(lastIndex);
625
1017
  if (remaining.trim()) {
626
- segments.push(...parseMarkdownWithCodeBlocks2(remaining));
1018
+ segments.push(...parseMarkdownWithCodeBlocks(remaining));
627
1019
  }
628
1020
  return segments;
629
1021
  }
630
1022
  var NAMESPACE = "almadar:ui:debug";
631
- var log = createLogger(NAMESPACE);
1023
+ var log2 = createLogger(NAMESPACE);
632
1024
  var inputLog = createLogger("almadar:ui:debug:input");
633
1025
  var collisionLog = createLogger("almadar:ui:debug:collision");
634
1026
  var physicsLog = createLogger("almadar:ui:debug:physics");
@@ -644,9 +1036,9 @@ function debug(...args) {
644
1036
  const [first, ...rest] = args;
645
1037
  const message = typeof first === "string" ? first : "<debug>";
646
1038
  if (rest.length === 0 && typeof first === "string") {
647
- log.debug(message);
1039
+ log2.debug(message);
648
1040
  } else {
649
- log.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
1041
+ log2.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
650
1042
  }
651
1043
  }
652
1044
  function debugGroup(label) {
@@ -659,13 +1051,13 @@ function debugWarn(...args) {
659
1051
  if (!gateEnabled("WARN")) return;
660
1052
  const [first, ...rest] = args;
661
1053
  const message = typeof first === "string" ? first : "<warn>";
662
- log.warn(message, rest.length > 0 ? { args: formatArgs(rest) } : void 0);
1054
+ log2.warn(message, rest.length > 0 ? { args: formatArgs(rest) } : void 0);
663
1055
  }
664
1056
  function debugError(...args) {
665
1057
  if (!gateEnabled("ERROR")) return;
666
1058
  const [first, ...rest] = args;
667
1059
  const message = typeof first === "string" ? first : "<error>";
668
- log.error(message, rest.length > 0 ? { args: formatArgs(rest) } : void 0);
1060
+ log2.error(message, rest.length > 0 ? { args: formatArgs(rest) } : void 0);
669
1061
  }
670
1062
  function debugTable(data) {
671
1063
  if (gateEnabled("DEBUG")) console.table(data);
@@ -715,19 +1107,19 @@ function toLogMetaValue(v) {
715
1107
  // src/lib/traitRegistry.ts
716
1108
  var traits = /* @__PURE__ */ new Map();
717
1109
  var listeners = /* @__PURE__ */ new Set();
718
- function notifyListeners() {
1110
+ function notifyListeners2() {
719
1111
  listeners.forEach((listener) => listener());
720
1112
  }
721
1113
  function registerTrait(info) {
722
1114
  traits.set(info.id, info);
723
- notifyListeners();
1115
+ notifyListeners2();
724
1116
  }
725
1117
  function updateTraitState(id, newState) {
726
1118
  const trait = traits.get(id);
727
1119
  if (trait) {
728
1120
  trait.currentState = newState;
729
1121
  trait.transitionCount++;
730
- notifyListeners();
1122
+ notifyListeners2();
731
1123
  }
732
1124
  }
733
1125
  function updateGuardResult(traitId, guardName, result) {
@@ -736,13 +1128,13 @@ function updateGuardResult(traitId, guardName, result) {
736
1128
  const guard = trait.guards.find((g) => g.name === guardName);
737
1129
  if (guard) {
738
1130
  guard.lastResult = result;
739
- notifyListeners();
1131
+ notifyListeners2();
740
1132
  }
741
1133
  }
742
1134
  }
743
1135
  function unregisterTrait(id) {
744
1136
  traits.delete(id);
745
- notifyListeners();
1137
+ notifyListeners2();
746
1138
  }
747
1139
  function getAllTraits() {
748
1140
  return Array.from(traits.values());
@@ -756,18 +1148,29 @@ function subscribeToTraitChanges(listener) {
756
1148
  }
757
1149
  function clearTraits() {
758
1150
  traits.clear();
759
- notifyListeners();
1151
+ notifyListeners2();
1152
+ }
1153
+ function usePerfBuffer() {
1154
+ return useSyncExternalStore(perfStore.subscribe, perfStore.getSnapshot, perfStore.getSnapshot);
760
1155
  }
1156
+ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
1157
+ pushPerfEntry({
1158
+ name: `profiler:${id}:${phase}`,
1159
+ durationMs: actualDuration,
1160
+ ts: commitTime,
1161
+ detail: { baseDuration }
1162
+ });
1163
+ };
761
1164
 
762
1165
  // src/lib/tickRegistry.ts
763
1166
  var ticks = /* @__PURE__ */ new Map();
764
1167
  var listeners2 = /* @__PURE__ */ new Set();
765
- function notifyListeners2() {
1168
+ function notifyListeners3() {
766
1169
  listeners2.forEach((listener) => listener());
767
1170
  }
768
1171
  function registerTick(tick) {
769
1172
  ticks.set(tick.id, tick);
770
- notifyListeners2();
1173
+ notifyListeners3();
771
1174
  }
772
1175
  function updateTickExecution(id, timestamp) {
773
1176
  const tick = ticks.get(id);
@@ -775,19 +1178,19 @@ function updateTickExecution(id, timestamp) {
775
1178
  tick.lastExecuted = timestamp;
776
1179
  tick.nextExecution = timestamp + tick.interval;
777
1180
  tick.executionCount++;
778
- notifyListeners2();
1181
+ notifyListeners3();
779
1182
  }
780
1183
  }
781
1184
  function setTickActive(id, isActive) {
782
1185
  const tick = ticks.get(id);
783
1186
  if (tick) {
784
1187
  tick.isActive = isActive;
785
- notifyListeners2();
1188
+ notifyListeners3();
786
1189
  }
787
1190
  }
788
1191
  function unregisterTick(id) {
789
1192
  ticks.delete(id);
790
- notifyListeners2();
1193
+ notifyListeners3();
791
1194
  }
792
1195
  function getAllTicks() {
793
1196
  return Array.from(ticks.values());
@@ -801,14 +1204,14 @@ function subscribeToTickChanges(listener) {
801
1204
  }
802
1205
  function clearTicks() {
803
1206
  ticks.clear();
804
- notifyListeners2();
1207
+ notifyListeners3();
805
1208
  }
806
1209
 
807
1210
  // src/lib/guardRegistry.ts
808
1211
  var guardHistory = [];
809
1212
  var listeners3 = /* @__PURE__ */ new Set();
810
1213
  var MAX_HISTORY = 100;
811
- function notifyListeners3() {
1214
+ function notifyListeners4() {
812
1215
  listeners3.forEach((listener) => listener());
813
1216
  }
814
1217
  function recordGuardEvaluation(evaluation) {
@@ -821,7 +1224,7 @@ function recordGuardEvaluation(evaluation) {
821
1224
  if (guardHistory.length > MAX_HISTORY) {
822
1225
  guardHistory.pop();
823
1226
  }
824
- notifyListeners3();
1227
+ notifyListeners4();
825
1228
  }
826
1229
  function getGuardHistory() {
827
1230
  return [...guardHistory];
@@ -838,7 +1241,7 @@ function subscribeToGuardChanges(listener) {
838
1241
  }
839
1242
  function clearGuardHistory() {
840
1243
  guardHistory.length = 0;
841
- notifyListeners3();
1244
+ notifyListeners4();
842
1245
  }
843
1246
 
844
1247
  // src/lib/entityDebug.ts
@@ -880,7 +1283,7 @@ function getEntitiesByType(type) {
880
1283
  var events = [];
881
1284
  var listeners4 = /* @__PURE__ */ new Set();
882
1285
  var MAX_EVENTS = 500;
883
- function notifyListeners4() {
1286
+ function notifyListeners5() {
884
1287
  listeners4.forEach((listener) => listener());
885
1288
  }
886
1289
  function logDebugEvent(type, source, message, data) {
@@ -896,7 +1299,7 @@ function logDebugEvent(type, source, message, data) {
896
1299
  if (events.length > MAX_EVENTS) {
897
1300
  events.pop();
898
1301
  }
899
- notifyListeners4();
1302
+ notifyListeners5();
900
1303
  }
901
1304
  function logStateChange(source, from, to, event) {
902
1305
  logDebugEvent("state-change", source, `${from} \u2192 ${to}`, { from, to, event: event ?? null });
@@ -934,7 +1337,7 @@ function subscribeToDebugEvents(listener) {
934
1337
  }
935
1338
  function clearDebugEvents() {
936
1339
  events.length = 0;
937
- notifyListeners4();
1340
+ notifyListeners5();
938
1341
  }
939
1342
 
940
1343
  // src/lib/debugUtils.ts
@@ -971,81 +1374,4 @@ function initDebugShortcut() {
971
1374
  return () => window.removeEventListener("keydown", handleKeyDown);
972
1375
  }
973
1376
 
974
- // src/lib/parseLessonSegments.ts
975
- function extractTagContent(content, tagName) {
976
- const closedTagRegex = new RegExp(`<${tagName}>([\\s\\S]*?)<\\/${tagName}>`, "i");
977
- const closedMatch = content.match(closedTagRegex);
978
- if (closedMatch) {
979
- return { content: closedMatch[1].trim(), fullMatch: closedMatch[0] };
980
- }
981
- const unclosedTagRegex = new RegExp(
982
- `<${tagName}>([\\s\\S]*?)(?=<(?:activate|connect|reflect|bloom|prq|question|answer|visualize)|\\n\\n#|$)`,
983
- "i"
984
- );
985
- const unclosedMatch = content.match(unclosedTagRegex);
986
- if (unclosedMatch) {
987
- return { content: unclosedMatch[1].trim(), fullMatch: unclosedMatch[0] };
988
- }
989
- return null;
990
- }
991
- function parseLessonSegments(lesson) {
992
- if (!lesson) return [];
993
- let content = lesson.replace(/<prq>[\s\S]*?<\/prq>/gi, "").trim();
994
- const segments = [];
995
- const activateResult = extractTagContent(content, "activate");
996
- if (activateResult) {
997
- segments.push({ type: "activate", question: activateResult.content });
998
- content = content.replace(activateResult.fullMatch, "").trim();
999
- }
1000
- const connectResult = extractTagContent(content, "connect");
1001
- if (connectResult) {
1002
- segments.push({ type: "connect", content: connectResult.content });
1003
- content = content.replace(connectResult.fullMatch, "").trim();
1004
- }
1005
- const tagRegex = new RegExp(
1006
- '(?<reflect><reflect>(?<reflectClosed>[\\s\\S]*?)<\\/reflect>)|(?<reflectUnclosed><reflect>(?<reflectOpen>[\\s\\S]*?)(?=<(?:activate|connect|reflect|bloom|prq|question|answer|visualize)|\\n\\n#|$))|(?<bloom><bloom\\s+level="(?<bloomLevel>remember|understand|apply|analyze|evaluate|create)">(?<bloomClosed>[\\s\\S]*?)<\\/bloom>)|(?<bloomUnclosed><bloom\\s+level="(?<bloomLevelUn>remember|understand|apply|analyze|evaluate|create)">(?<bloomOpen>[\\s\\S]*?)(?=<(?:activate|connect|reflect|bloom|prq|question|answer|visualize)|\\n\\n#|$))|(?<quiz><question>(?<quizQuestion>[\\s\\S]*?)<\\/question>\\s*<answer>(?<quizAnswer>[\\s\\S]*?)<\\/answer>)|(?<visualize><visualize\\s+type="(?<vizType>algorithms|math|physics|biology|chemistry|probability)"\\s+description="(?<vizDesc>[^"]*?)"\\s*\\/?>)',
1007
- "gi"
1008
- );
1009
- let lastIndex = 0;
1010
- let match;
1011
- while ((match = tagRegex.exec(content)) !== null) {
1012
- const before = content.slice(lastIndex, match.index);
1013
- if (before.trim()) {
1014
- segments.push(...parseMarkdownWithCodeBlocks(before));
1015
- }
1016
- const g = match.groups ?? {};
1017
- if (g.reflect || g.reflectUnclosed) {
1018
- const prompt = (g.reflectClosed ?? g.reflectOpen ?? "").trim();
1019
- if (prompt) segments.push({ type: "reflect", prompt });
1020
- } else if (g.bloom || g.bloomUnclosed) {
1021
- const level = g.bloomLevel ?? g.bloomLevelUn;
1022
- const bloomContent = g.bloomClosed ?? g.bloomOpen ?? "";
1023
- if (level && bloomContent) {
1024
- const qMatch = bloomContent.match(/<question>([\s\S]*?)<\/question>/i);
1025
- const aMatch = bloomContent.match(/<answer>([\s\S]*?)<\/answer>/i);
1026
- if (qMatch && aMatch) {
1027
- segments.push({ type: "bloom", level, question: qMatch[1].trim(), answer: aMatch[1].trim() });
1028
- } else if (qMatch) {
1029
- segments.push({ type: "bloom", level, question: qMatch[1].trim(), answer: "(Answer not provided)" });
1030
- } else {
1031
- const clean = bloomContent.replace(/^\*\*Question\s*\d*:?\*\*\s*/i, "").replace(/^\*\*Q\d*:?\*\*\s*/i, "").trim();
1032
- if (clean) segments.push({ type: "bloom", level, question: clean, answer: "(See answers section below)" });
1033
- }
1034
- }
1035
- } else if (g.quiz) {
1036
- segments.push({ type: "quiz", question: g.quizQuestion.trim(), answer: g.quizAnswer.trim() });
1037
- } else if (g.visualize) {
1038
- segments.push({
1039
- type: "visualization",
1040
- visualizationType: g.vizType,
1041
- description: g.vizDesc ?? ""
1042
- });
1043
- }
1044
- lastIndex = tagRegex.lastIndex;
1045
- }
1046
- const remaining = content.slice(lastIndex);
1047
- if (remaining.trim()) segments.push(...parseMarkdownWithCodeBlocks(remaining));
1048
- return segments;
1049
- }
1050
-
1051
- export { EDITOR_MOTIONS, EDITOR_OPERATORS, ENTER_SLOT_CLASS, INDENT_UNIT, MAX_ENTER_DELAY, applyMotion, applyOperator, asEnterAnimation, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, computeLineDiff, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, enterClassName, getAllTicks, getAllTraits, getDebugEvents, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getRecentEvents, getRecentGuardEvaluations, getTick, getTrait, initDebugShortcut, isDebugEnabled, isDebugEnabled2, isEditorMotion, isEditorOperator, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, motionRange, onDebugToggle, parseContentSegments, parseLessonSegments, parseMarkdownWithCodeBlocks, parseMarkdownWithCodeBlocks2, profilerOnRender, recordGuardEvaluation, registerTick, registerTrait, resolveImageUrl, setDebugEnabled, setEntityProvider, setTickActive, slotPlaysDefaultEnter, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, toggleDebug, unregisterTick, unregisterTrait, updateGuardResult, updateTickExecution, updateTraitState, usePerfBuffer, useSlotEnterRestart };
1377
+ export { EDITOR_MOTIONS, EDITOR_OPERATORS, ENTER_SLOT_CLASS, INDENT_UNIT, MAX_ENTER_DELAY, applyMotion, applyOperator, asEnterAnimation, bindCanvasCapture, bindConfigApplier, bindEventBus, bindLastDrawables, bindTraitStateGetter, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, clearVerification, computeLineDiff, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, enterClassName, getAllChecks, getAllTicks, getAllTraits, getBridgeHealth, getDebugEvents, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getRecentEvents, getRecentGuardEvaluations, getSnapshot, getSummary, getTick, getTrait, getTraitSnapshots, getTransitions, getTransitionsForTrait, initDebugShortcut, isDebugEnabled, isDebugEnabled2, isEditableTarget, isEditorMotion, isEditorOperator, keyMapCode, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, motionRange, onDebugToggle, parseContentSegments, parseMarkdownWithCodeBlocks, profilerOnRender, recordGuardEvaluation, recordOrbitalResponse, recordServerResponse, recordTransition, recordingTransport, registerCheck, registerTick, registerTrait, registerTraitSnapshot, resolveImageUrl, resolveKeyMapEvent, serverEffectTraces, setDebugEnabled, setEntityProvider, setTickActive, slotPlaysDefaultEnter, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, subscribeToVerification, toggleDebug, unregisterTick, unregisterTrait, updateAssetStatus, updateBridgeHealth, updateCheck, updateGuardResult, updateTickExecution, updateTraitState, usePerfBuffer, useSlotEnterRestart, verifierAttached, waitForTransition };