@almadar/ui 6.10.0 → 6.12.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 (35) hide show
  1. package/dist/{EntityBindingContext-Y4zXyNJZ.d.cts → EntityBindingContext-D5lRu6p1.d.cts} +11 -0
  2. package/dist/{EntityBindingContext-Y4zXyNJZ.d.ts → EntityBindingContext-D5lRu6p1.d.ts} +11 -0
  3. package/dist/{GameAudioProvider-Dk_Y3LN3.d.cts → GameAudioProvider-D8GynTNq.d.cts} +1 -1
  4. package/dist/{GameAudioProvider-Ctceau1s.d.ts → GameAudioProvider-Dozqx4sL.d.ts} +1 -1
  5. package/dist/avl/index.cjs +250 -106
  6. package/dist/avl/index.js +209 -65
  7. package/dist/{avl-schema-parser-DncJLEn9.d.ts → avl-schema-parser-DX-aVCCm.d.ts} +1 -1
  8. package/dist/{avl-schema-parser-FQ1474v8.d.cts → avl-schema-parser-PVu8rgsy.d.cts} +1 -1
  9. package/dist/{cn-C7fvp9gH.d.ts → cn-Do5gsPBm.d.cts} +2 -100
  10. package/dist/{cn-DnLYahyL.d.cts → cn-Do5gsPBm.d.ts} +2 -100
  11. package/dist/components/index.cjs +103 -68
  12. package/dist/components/index.d.cts +44 -20
  13. package/dist/components/index.d.ts +44 -20
  14. package/dist/components/index.js +64 -29
  15. package/dist/lib/drawable/three/index.d.cts +3 -4
  16. package/dist/lib/drawable/three/index.d.ts +3 -4
  17. package/dist/lib/index.cjs +7 -23
  18. package/dist/lib/index.d.cts +6 -28
  19. package/dist/lib/index.d.ts +6 -28
  20. package/dist/lib/index.js +5 -23
  21. package/dist/{paintDispatch-B5ObLnUv.d.ts → paintDispatch-CK5uwYEq.d.cts} +50 -3
  22. package/dist/{paintDispatch-D3R8NNmV.d.cts → paintDispatch-CK5uwYEq.d.ts} +50 -3
  23. package/dist/providers/index.cjs +129 -78
  24. package/dist/providers/index.d.cts +5 -3
  25. package/dist/providers/index.d.ts +5 -3
  26. package/dist/providers/index.js +90 -39
  27. package/dist/runtime/index.cjs +249 -105
  28. package/dist/runtime/index.d.cts +27 -5
  29. package/dist/runtime/index.d.ts +27 -5
  30. package/dist/runtime/index.js +208 -64
  31. package/dist/verificationRegistry-BLsjb1oU.d.cts +110 -0
  32. package/dist/verificationRegistry-D8bHWD8Q.d.ts +110 -0
  33. package/package.json +7 -7
  34. package/dist/types-B3nHgnMG.d.cts +0 -51
  35. package/dist/types-B3nHgnMG.d.ts +0 -51
package/dist/avl/index.js CHANGED
@@ -6,8 +6,8 @@ import { createLogger, setNamespaceLevel, isLogLevelEnabled } from '@almadar/log
6
6
  import ELK from 'elkjs/lib/elk.bundled.js';
7
7
  import { MarkerType, useReactFlow, Handle, Position, getBezierPath, EdgeLabelRenderer, useNodeId, ReactFlowProvider, BaseEdge, useNodesState, useEdgesState, ReactFlow, Controls, Background, BackgroundVariant } from '@xyflow/react';
8
8
  import { useTranslate } from '@almadar/ui/hooks';
9
- import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, normalizeCallSiteConfigToValues, interpolateValue } from '@almadar/runtime';
10
- import { FieldTypeSchema, isInlineTrait, isPageReference, buildResolvedTraitConfigs, schemaToIR, getPage, mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, walkSExpr, isRenderBindingMarker, containsEntityBinding, isSExpr, isEventPayloadValue, RENDER_BINDING_MARKER, isFileValue } from '@almadar/core';
9
+ import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor, LIFECYCLE_EVENTS, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, normalizeCallSiteConfigToValues, interpolateValue } from '@almadar/runtime';
10
+ import { FieldTypeSchema, isInlineTrait, isPageReference, buildResolvedTraitConfigs, collectCallsiteCaptureChildren, schemaToIR, getPage, mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, walkSExpr, isRenderBindingMarker, containsEntityBinding, isSExpr, isEventPayloadValue, RENDER_BINDING_MARKER, getNestedValue, isFileValue } from '@almadar/core';
11
11
  import * as LucideIcons2 from 'lucide-react';
12
12
  import { Loader2, X, Code, FileText, WrapText, Check, Copy, Lightbulb, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, ArrowLeft, ZoomOut, ZoomIn, Download, DollarSign, ChevronDown, Menu as Menu$1, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, HelpCircle, PauseCircle, Search, Bold, Italic, Underline, Strikethrough, Heading1, Heading2, Heading3, ListOrdered, Quote, Link as Link$1, Minus, Eraser, TrendingUp, TrendingDown, AlertCircle, Circle, Clock, CheckCircle2, ChevronUp } from 'lucide-react';
13
13
  import { createPortal } from 'react-dom';
@@ -17,7 +17,8 @@ import { prepareSchemaForPreview, collectTraitRefsFromResolvedTrait, buildOrbita
17
17
  import { Link, Outlet, useLocation } from 'react-router-dom';
18
18
  import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light.js';
19
19
  import dark from 'react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus.js';
20
- import { orbLanguage, loloLanguage, ORB_COLORS } from '@almadar/syntax';
20
+ import { orbLanguage, loloLanguage, ORB_COLORS, translateLolo, translateOrb } from '@almadar/syntax';
21
+ import { coreTables } from '@almadar/core/i18n';
21
22
  import langJson from 'react-syntax-highlighter/dist/esm/languages/prism/json.js';
22
23
  import langJavascript from 'react-syntax-highlighter/dist/esm/languages/prism/javascript.js';
23
24
  import langTypescript from 'react-syntax-highlighter/dist/esm/languages/prism/typescript.js';
@@ -10833,8 +10834,9 @@ function getTransitions2() {
10833
10834
  return [...getState().transitions];
10834
10835
  }
10835
10836
  function recordServerResponse(orbitalName, event, response) {
10837
+ const { effectResults, ...responseFields } = response;
10836
10838
  const serverResponse = {
10837
- ...response,
10839
+ ...responseFields,
10838
10840
  orbitalName,
10839
10841
  timestamp: Date.now()
10840
10842
  };
@@ -10844,7 +10846,7 @@ function recordServerResponse(orbitalName, event, response) {
10844
10846
  from: "server",
10845
10847
  to: "server",
10846
10848
  event,
10847
- effects: [],
10849
+ effects: effectResults ?? [],
10848
10850
  serverResponse,
10849
10851
  timestamp: Date.now()
10850
10852
  };
@@ -20749,6 +20751,15 @@ function buildLineProps(errorLines, extraClassName) {
20749
20751
  };
20750
20752
  };
20751
20753
  }
20754
+ function translateProgram(source, language, lang) {
20755
+ if (lang === "en") return source;
20756
+ if (language === "lolo") return translateLolo(source, lang);
20757
+ if (language === "orb") {
20758
+ const translated = translateOrb(source, lang);
20759
+ return typeof translated === "string" ? translated : source;
20760
+ }
20761
+ return source;
20762
+ }
20752
20763
  var dynamicallyLoaded, codeLanguageLoader, orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log4, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, HIGHLIGHT_CAPACITY_BYTES, MONO_FONT_FAMILY, VIEWER_LINE_NUMBER_STYLE, CodeBlock;
20753
20764
  var init_CodeBlock = __esm({
20754
20765
  "components/core/molecules/markdown/CodeBlock.tsx"() {
@@ -21014,6 +21025,7 @@ var init_CodeBlock = __esm({
21014
21025
  showLineNumbers = false,
21015
21026
  wordWrap = false,
21016
21027
  files,
21028
+ naturalLanguages,
21017
21029
  actions,
21018
21030
  isLoading = false,
21019
21031
  error,
@@ -21060,7 +21072,48 @@ var init_CodeBlock = __esm({
21060
21072
  "replace"
21061
21073
  ]
21062
21074
  }) => {
21063
- const code = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
21075
+ const englishCode = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
21076
+ const naturalTabs = !editable && naturalLanguages && naturalLanguages.length > 1 ? naturalLanguages : void 0;
21077
+ const [naturalLanguage, setNaturalLanguage] = useState(() => naturalTabs?.[0] ?? "en");
21078
+ const activeNaturalLanguage = naturalTabs?.includes(naturalLanguage) === true ? naturalLanguage : naturalTabs?.[0] ?? "en";
21079
+ const translationCache = useMemo(() => /* @__PURE__ */ new Map(), [englishCode, files]);
21080
+ const translateFor = useCallback(
21081
+ (source, sourceLanguage, cacheKey) => {
21082
+ if (activeNaturalLanguage === "en") return source;
21083
+ const key = `${cacheKey}|${sourceLanguage}|${activeNaturalLanguage}`;
21084
+ const hit = translationCache.get(key);
21085
+ if (hit !== void 0) return hit;
21086
+ const translated = translateProgram(source, sourceLanguage, activeNaturalLanguage);
21087
+ translationCache.set(key, translated);
21088
+ return translated;
21089
+ },
21090
+ [translationCache, activeNaturalLanguage]
21091
+ );
21092
+ const code = translateFor(englishCode, language, "code");
21093
+ const naturalTabItems = naturalTabs?.map((lang) => ({
21094
+ id: `lang-${lang}`,
21095
+ label: coreTables[lang].meta.name,
21096
+ content: null
21097
+ }));
21098
+ const naturalTabStrip = naturalTabs && naturalTabItems ? /* @__PURE__ */ jsx(
21099
+ Box,
21100
+ {
21101
+ className: "border-b border-border",
21102
+ dir: coreTables[activeNaturalLanguage].meta.rtl ? "rtl" : "ltr",
21103
+ "data-testid": "codeblock-language-tabs",
21104
+ children: /* @__PURE__ */ jsx(
21105
+ Tabs,
21106
+ {
21107
+ tabs: naturalTabItems,
21108
+ activeTab: `lang-${activeNaturalLanguage}`,
21109
+ onTabChange: (id) => {
21110
+ const next = naturalTabs.find((lang) => `lang-${lang}` === id);
21111
+ if (next) setNaturalLanguage(next);
21112
+ }
21113
+ }
21114
+ )
21115
+ }
21116
+ ) : null;
21064
21117
  const activeStyle = resolveHighlightStyle(language);
21065
21118
  const overCapacity = code.length > HIGHLIGHT_CAPACITY_BYTES;
21066
21119
  const plainCodeColor = plainCodeColorOf(activeStyle);
@@ -21073,8 +21126,8 @@ var init_CodeBlock = __esm({
21073
21126
  const [wrap, setWrap] = useState(wordWrap);
21074
21127
  const [activeFileIndex, setActiveFileIndex] = useState(0);
21075
21128
  const activeFile = files?.[activeFileIndex];
21076
- const activeCode = activeFile?.code ?? code;
21077
21129
  const activeLanguage = activeFile?.language ?? language;
21130
+ const activeCode = activeFile ? translateFor(activeFile.code, activeLanguage, `file-${activeFileIndex}`) : code;
21078
21131
  const languageReady = useLanguageReady(activeLanguage);
21079
21132
  const viewerStyle = resolveHighlightStyle(activeLanguage);
21080
21133
  const viewerPlainCodeColor = plainCodeColorOf(viewerStyle);
@@ -21559,6 +21612,7 @@ var init_CodeBlock = __esm({
21559
21612
  content: null
21560
21613
  }));
21561
21614
  return /* @__PURE__ */ jsx(Card, { className: cn("overflow-hidden", className), children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column" }, children: [
21615
+ naturalTabStrip,
21562
21616
  tabItems && tabItems.length > 1 && /* @__PURE__ */ jsx(Box, { className: "border-b border-border", children: /* @__PURE__ */ jsx(
21563
21617
  Tabs,
21564
21618
  {
@@ -21620,7 +21674,7 @@ var init_CodeBlock = __esm({
21620
21674
  ]
21621
21675
  }
21622
21676
  ),
21623
- /* @__PURE__ */ jsx(Box, { className: "overflow-auto bg-muted/20", style: { maxHeight }, children: diffLines ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column" }, className: "font-mono text-xs", children: diffRowElements }) : /* @__PURE__ */ jsx("div", { className: "font-mono text-xs", children: viewerHighlightedElement }) })
21677
+ /* @__PURE__ */ jsx(Box, { className: "overflow-auto bg-muted/20", style: { maxHeight }, dir: "ltr", children: diffLines ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column" }, className: "font-mono text-xs", children: diffRowElements }) : /* @__PURE__ */ jsx("div", { className: "font-mono text-xs", children: viewerHighlightedElement }) })
21624
21678
  ] }) });
21625
21679
  }
21626
21680
  const hasHeader = showLanguageBadge || effectiveCopy;
@@ -21647,6 +21701,7 @@ var init_CodeBlock = __esm({
21647
21701
  ]
21648
21702
  }
21649
21703
  ),
21704
+ naturalTabStrip,
21650
21705
  editable ? (
21651
21706
  /* GAP-77 / GAP-82 / GAP-83: editable mode = transparent textarea on
21652
21707
  top of a Prism-highlighted SyntaxHighlighter overlay.
@@ -21798,6 +21853,7 @@ var init_CodeBlock = __esm({
21798
21853
  {
21799
21854
  ref: scrollRef,
21800
21855
  onCopy: handleSelectionCopy,
21856
+ dir: "ltr",
21801
21857
  style: {
21802
21858
  flex: 1,
21803
21859
  minHeight: 0,
@@ -21816,7 +21872,7 @@ var init_CodeBlock = __esm({
21816
21872
  )
21817
21873
  ] });
21818
21874
  },
21819
- (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.showCopy === next.showCopy && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable && prev.editable === next.editable && prev.onChange === next.onChange && prev.errorLines === next.errorLines && prev.mode === next.mode && prev.title === next.title && prev.diff === next.diff && prev.files === next.files && prev.actions === next.actions && prev.isLoading === next.isLoading && prev.error === next.error && prev.editorId === next.editorId && prev.onEditorFocus === next.onEditorFocus && prev.onEditorBlur === next.onEditorBlur && prev.onMotion === next.onMotion && prev.onOperate === next.onOperate && prev.onInsertText === next.onInsertText && prev.onSetMode === next.onSetMode && prev.motions === next.motions && prev.operators === next.operators
21875
+ (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.showCopy === next.showCopy && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable && prev.editable === next.editable && prev.onChange === next.onChange && prev.errorLines === next.errorLines && prev.mode === next.mode && prev.title === next.title && prev.diff === next.diff && prev.files === next.files && prev.naturalLanguages === next.naturalLanguages && prev.actions === next.actions && prev.isLoading === next.isLoading && prev.error === next.error && prev.editorId === next.editorId && prev.onEditorFocus === next.onEditorFocus && prev.onEditorBlur === next.onEditorBlur && prev.onMotion === next.onMotion && prev.onOperate === next.onOperate && prev.onInsertText === next.onInsertText && prev.onSetMode === next.onSetMode && prev.motions === next.motions && prev.operators === next.operators
21820
21876
  );
21821
21877
  CodeBlock.displayName = "CodeBlock";
21822
21878
  }
@@ -25511,26 +25567,6 @@ var init_ButtonGroup = __esm({
25511
25567
  ButtonGroup.displayName = "ButtonGroup";
25512
25568
  }
25513
25569
  });
25514
- function getNestedValue(obj, path) {
25515
- if (obj === null || obj === void 0 || !path) {
25516
- return void 0;
25517
- }
25518
- if (!path.includes(".")) {
25519
- return obj[path];
25520
- }
25521
- const parts = path.split(".");
25522
- let value = obj;
25523
- for (const part of parts) {
25524
- if (value === null || value === void 0) {
25525
- return void 0;
25526
- }
25527
- if (typeof value !== "object" || Array.isArray(value)) {
25528
- return void 0;
25529
- }
25530
- value = value[part];
25531
- }
25532
- return value;
25533
- }
25534
25570
  function resolveImageUrl(value) {
25535
25571
  if (typeof value === "string") {
25536
25572
  return value;
@@ -44098,11 +44134,11 @@ var init_WizardContainer = __esm({
44098
44134
  });
44099
44135
  function calculateComplexity(schema) {
44100
44136
  if (!schema) return 1;
44101
- const entities = schema.dataEntities?.length || 0;
44137
+ const entities = schema.dataEntities || 0;
44102
44138
  const pages = schema.ui?.pages?.length || 0;
44103
- const traits2 = schema.traits?.length || 0;
44139
+ const traits2 = schema.traits || 0;
44104
44140
  const sections = schema.ui?.pages?.reduce(
44105
- (acc, page) => acc + (page.sections?.length || 0),
44141
+ (acc, page) => acc + (page.sections || 0),
44106
44142
  0
44107
44143
  ) || 0;
44108
44144
  return entities * 3 + pages * 2 + traits2 * 2 + sections * 1;
@@ -58423,15 +58459,19 @@ function runTickFrame(entityId, orderedWriters, store) {
58423
58459
  }
58424
58460
  var log9 = createLogger("almadar:ui:effects:client-handlers");
58425
58461
  function createClientEffectHandlers(options) {
58426
- const { eventBus, slotSetter, navigate, navigateBack, notify, callService, liveEntity } = options;
58462
+ const { eventBus, slotSetter, navigate, navigateBack, notify, callService, liveEntity, persistDelegated } = options;
58427
58463
  return {
58428
58464
  emit: (event, payload, source) => {
58429
58465
  const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
58430
58466
  eventBus.emit(prefixedEvent, payload, source);
58431
58467
  },
58432
58468
  persist: async () => {
58433
- log9.warn("persist is server-side only, ignored on client");
58469
+ log9.debug("persist is server-side only, ignored on client");
58434
58470
  },
58471
+ // Bridge mode: the server runs every persist and the response
58472
+ // carries its outcome — tell the executor so the placeholder above is
58473
+ // never read as a denial (see `EffectHandlers.persistDelegated`).
58474
+ ...persistDelegated === true ? { persistDelegated: true } : {},
58435
58475
  // @almadar/runtime EffectHandlers.set types value:unknown — should be FieldValue (upstream fix queued)
58436
58476
  set: ((_entityId, field, value) => {
58437
58477
  if (!liveEntity) {
@@ -58528,7 +58568,6 @@ var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
58528
58568
  "do",
58529
58569
  "when"
58530
58570
  ]);
58531
- var LIFECYCLE_EVENTS = ["INIT", "LOAD", "$MOUNT"];
58532
58571
  function toTraitDefinition(binding) {
58533
58572
  return {
58534
58573
  name: binding.trait.name,
@@ -58568,17 +58607,14 @@ function classifySharedTick(tick) {
58568
58607
  if (renders) return "renderer";
58569
58608
  return "neither";
58570
58609
  }
58571
- function buildTraitRenderConfig(binding, traitConfigsByName, payload) {
58610
+ function buildTraitRenderConfig(binding, traitConfigsByName) {
58572
58611
  const declaredDefaults = collectDeclaredConfigDefaults(binding.trait);
58573
58612
  const resolvedDefaults = traitConfigsByName?.[binding.trait.name];
58574
58613
  const callSiteConfig = getBindingConfig(binding);
58575
- const callSiteOverrides = callSiteConfig ? resolveCallSitePayloadCaptures(
58576
- Object.fromEntries(
58577
- Object.entries(callSiteConfig).filter(
58578
- ([, v]) => !containsConfigForward(v)
58579
- )
58580
- ),
58581
- payload
58614
+ const callSiteOverrides = callSiteConfig ? Object.fromEntries(
58615
+ Object.entries(callSiteConfig).filter(
58616
+ ([, v]) => !containsConfigForward(v)
58617
+ )
58582
58618
  ) : void 0;
58583
58619
  if (declaredDefaults || resolvedDefaults || callSiteOverrides) {
58584
58620
  return {
@@ -58649,12 +58685,40 @@ function evalFieldDefault(value) {
58649
58685
  return value;
58650
58686
  }
58651
58687
  }
58688
+ function isPersistTraceAction(value) {
58689
+ return value === "create" || value === "update" || value === "delete" || value === "batch";
58690
+ }
58691
+ function overlayServerEffectResults(effectTraces, serverResults) {
58692
+ if (serverResults.length === 0) return effectTraces;
58693
+ const queues = /* @__PURE__ */ new Map();
58694
+ for (const result of serverResults) {
58695
+ const queue = queues.get(result.effect);
58696
+ if (queue) queue.push(result);
58697
+ else queues.set(result.effect, [result]);
58698
+ }
58699
+ return effectTraces.map((trace) => {
58700
+ const match = queues.get(trace.type)?.shift();
58701
+ if (!match) return trace;
58702
+ const resultId = match.data && typeof match.data === "object" && !Array.isArray(match.data) ? match.data.id : void 0;
58703
+ const outcome = match.success ? "success" : match.denied ? "denied" : "failed";
58704
+ return {
58705
+ ...trace,
58706
+ ...match.entityType !== void 0 ? { entityName: match.entityType } : {},
58707
+ ...match.action !== void 0 && isPersistTraceAction(match.action) ? { action: match.action } : {},
58708
+ ...resultId !== void 0 ? { resultId } : {},
58709
+ outcome,
58710
+ status: match.success ? "executed" : "failed",
58711
+ ...match.error !== void 0 ? { error: match.error } : {}
58712
+ };
58713
+ });
58714
+ }
58652
58715
  function useTraitStateMachine(traitBindings, uiSlots, options) {
58653
58716
  sharedEntityLog.debug("useTraitStateMachine start", { traitBindingsCount: traitBindings.length, traitNames: traitBindings.map((b) => b.trait.name) });
58654
58717
  const eventBus = useEventBus();
58655
58718
  const { entities } = useEntitySchema();
58656
58719
  const traitConfigsByName = options?.traitConfigsByName;
58657
58720
  const orbitalsByTrait = options?.orbitalsByTrait;
58721
+ const callsiteCaptureChildrenByTrait = options?.callsiteCaptureChildrenByTrait;
58658
58722
  const sharedEntityStore = useSharedEntityStore();
58659
58723
  const sharedGroups = useMemo(() => {
58660
58724
  const groups = /* @__PURE__ */ new Map();
@@ -58912,7 +58976,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
58912
58976
  };
58913
58977
  }, [traitBindings]);
58914
58978
  const executeTransitionEffects = useCallback(async (params) => {
58915
- const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log12 } = params;
58979
+ const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log12, callsitePayload } = params;
58916
58980
  const traitName = binding.trait.name;
58917
58981
  const linkedEntity = binding.linkedEntity || "";
58918
58982
  const entityId = payload?.entityId;
@@ -58934,7 +58998,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
58934
58998
  const effects = syncOnly ? params.effects.filter(
58935
58999
  (e) => Array.isArray(e) && SYNC_TICK_OPERATORS.has(String(e[0]))
58936
59000
  ) : params.effects;
58937
- if (effects.length === 0) return [];
59001
+ if (effects.length === 0) return { emitted: [], serverEffectResults: [] };
58938
59002
  const pendingSlots = /* @__PURE__ */ new Map();
58939
59003
  ({
58940
59004
  traitDefinition: binding.trait
@@ -58971,10 +59035,15 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
58971
59035
  // the trait's one live store — the same object bound below. This is
58972
59036
  // what makes a [runtime] entity's set (from ticks AND events) reach
58973
59037
  // the render-ui + next tick + guards.
58974
- liveEntity
59038
+ liveEntity,
59039
+ // No local persistence adapter (bridge mode, or a syncOnly tick):
59040
+ // nothing persists client-side, the server owns the write and
59041
+ // reports it — never read the placeholder as a denial.
59042
+ persistDelegated: (syncOnly ? void 0 : optionsRef.current?.persistence) === void 0
58975
59043
  });
58976
59044
  const persistence = syncOnly ? void 0 : optionsRef.current?.persistence;
58977
59045
  let handlers = clientHandlers;
59046
+ const serverEffectResults = [];
58978
59047
  if (persistence) {
58979
59048
  const sharedBindings = {
58980
59049
  // Seed `@entity` from the trait's scalar field state (a real
@@ -58986,16 +59055,16 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
58986
59055
  payload: payload || {},
58987
59056
  state: previousState
58988
59057
  };
59058
+ if (callsitePayload) {
59059
+ sharedBindings.callsitePayload = callsitePayload;
59060
+ }
58989
59061
  const sharedDeclared = collectDeclaredConfigDefaults(binding.trait);
58990
59062
  const sharedResolved = traitConfigsByName?.[traitName];
58991
59063
  const sharedCallSiteRaw = getBindingConfig(binding);
58992
- const sharedCallSite = sharedCallSiteRaw ? resolveCallSitePayloadCaptures(
58993
- Object.fromEntries(
58994
- Object.entries(sharedCallSiteRaw).filter(
58995
- ([, v]) => !containsConfigForward(v)
58996
- )
58997
- ),
58998
- payload || {}
59064
+ const sharedCallSite = sharedCallSiteRaw ? Object.fromEntries(
59065
+ Object.entries(sharedCallSiteRaw).filter(
59066
+ ([, v]) => !containsConfigForward(v)
59067
+ )
58999
59068
  ) : void 0;
59000
59069
  if (sharedDeclared || sharedResolved || sharedCallSite) {
59001
59070
  sharedBindings.config = {
@@ -59019,7 +59088,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
59019
59088
  },
59020
59089
  source: { trait: traitName },
59021
59090
  // @almadar/runtime callService types params:unknown/Promise<unknown> — should be ServiceParams/EventPayload (upstream fix queued)
59022
- callService: optionsRef.current?.callService
59091
+ callService: optionsRef.current?.callService,
59092
+ effectResults: serverEffectResults
59023
59093
  });
59024
59094
  handlers = {
59025
59095
  ...serverHandlers,
@@ -59054,7 +59124,10 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
59054
59124
  payload: payload || {},
59055
59125
  state: previousState
59056
59126
  };
59057
- const renderConfig = buildTraitRenderConfig(binding, traitConfigsByName, payload || {});
59127
+ if (callsitePayload) {
59128
+ bindingCtx.callsitePayload = callsitePayload;
59129
+ }
59130
+ const renderConfig = buildTraitRenderConfig(binding, traitConfigsByName);
59058
59131
  if (renderConfig !== void 0) {
59059
59132
  bindingCtx.config = renderConfig;
59060
59133
  }
@@ -59145,8 +59218,42 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
59145
59218
  effectCount: effects.length
59146
59219
  });
59147
59220
  }
59148
- return emittedDuringExec;
59221
+ return { emitted: emittedDuringExec, serverEffectResults };
59149
59222
  }, [eventBus, flushSlot, sharedEntityStore, publishBindingSnapshot, orbitalsByTrait]);
59223
+ const reRenderCallsiteCaptureChildren = useCallback(async (traitName, callsitePayload, entityByTrait, log12, visited = /* @__PURE__ */ new Set()) => {
59224
+ const children = callsiteCaptureChildrenByTrait?.get(traitName);
59225
+ if (!children || children.size === 0) return;
59226
+ const mgr = managerRef.current;
59227
+ const bindingMap = new Map(traitBindingsRef.current.map((b) => [b.trait.name, b]));
59228
+ for (const childName of children) {
59229
+ if (visited.has(childName)) continue;
59230
+ visited.add(childName);
59231
+ const childBinding = bindingMap.get(childName);
59232
+ if (!childBinding) continue;
59233
+ const lifecycleEvent = LIFECYCLE_EVENTS.find((evt) => mgr.canHandleEvent(childName, evt));
59234
+ if (lifecycleEvent === void 0) continue;
59235
+ const [entry] = mgr.sendEvent(lifecycleEvent, {}, void 0, entityByTrait, void 0, childName);
59236
+ if (!entry || !entry.result.executed) continue;
59237
+ log12.debug("callsite-capture-child:rerender", {
59238
+ referrer: traitName,
59239
+ child: childName,
59240
+ lifecycleEvent,
59241
+ callsitePayload: JSON.stringify(callsitePayload)
59242
+ });
59243
+ await executeTransitionEffects({
59244
+ binding: childBinding,
59245
+ effects: entry.result.effects,
59246
+ previousState: entry.result.previousState,
59247
+ newState: entry.result.newState,
59248
+ payload: {},
59249
+ flushEvent: lifecycleEvent,
59250
+ syncOnly: false,
59251
+ log: log12,
59252
+ callsitePayload
59253
+ });
59254
+ await reRenderCallsiteCaptureChildren(childName, callsitePayload, entityByTrait, log12, visited);
59255
+ }
59256
+ }, [callsiteCaptureChildrenByTrait, executeTransitionEffects]);
59150
59257
  const runTickEffects = useCallback((tick, binding) => {
59151
59258
  const traitName = binding.trait.name;
59152
59259
  const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
@@ -59284,6 +59391,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
59284
59391
  executedTraits: results.map((r2) => r2.traitName).join(",")
59285
59392
  });
59286
59393
  const emittedByTrait = /* @__PURE__ */ new Map();
59394
+ const serverEffectResultsByTrait = /* @__PURE__ */ new Map();
59287
59395
  bridgeEchoPendingRef.current.clear();
59288
59396
  for (const { traitName, result } of results) {
59289
59397
  const binding = bindingMap.get(traitName);
@@ -59328,7 +59436,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
59328
59436
  effects: JSON.stringify(result.effects)
59329
59437
  }));
59330
59438
  const _perfT2 = perfStart("processEvent:executeAll");
59331
- const emittedDuringExec = await executeTransitionEffects({
59439
+ const { emitted: emittedDuringExec, serverEffectResults: transitionServerEffectResults } = await executeTransitionEffects({
59332
59440
  binding,
59333
59441
  // upstream gap: /runtime TransitionResult.effects is unknown[] — they are SExpr at runtime (see Almadar_UI_Gaps.md)
59334
59442
  effects: result.effects,
@@ -59341,12 +59449,14 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
59341
59449
  });
59342
59450
  perfEnd("processEvent:executeAll", _perfT2);
59343
59451
  emittedByTrait.set(traitName, emittedDuringExec);
59452
+ serverEffectResultsByTrait.set(traitName, transitionServerEffectResults);
59344
59453
  for (const emittedKey of emittedDuringExec) {
59345
59454
  bridgeEchoPendingRef.current.set(
59346
59455
  emittedKey,
59347
59456
  (bridgeEchoPendingRef.current.get(emittedKey) ?? 0) + 1
59348
59457
  );
59349
59458
  }
59459
+ await reRenderCallsiteCaptureChildren(traitName, payload ?? {}, entityByTrait, stateLog);
59350
59460
  } else if (!result.executed) {
59351
59461
  if (result.guardResult === false) {
59352
59462
  stateLog.debug("guard-blocked-transition", {
@@ -59375,7 +59485,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
59375
59485
  for (const { traitName, result } of results) {
59376
59486
  if (result.executed) {
59377
59487
  updateTraitState(traitName, result.newState);
59378
- const effectTraces = result.effects.map(
59488
+ const reconstructedEffectTraces = result.effects.map(
59379
59489
  (e) => {
59380
59490
  if (Array.isArray(e)) {
59381
59491
  const head = String(e[0] ?? "unknown");
@@ -59394,6 +59504,10 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
59394
59504
  };
59395
59505
  }
59396
59506
  );
59507
+ const effectTraces = overlayServerEffectResults(
59508
+ reconstructedEffectTraces,
59509
+ serverEffectResultsByTrait.get(traitName) ?? []
59510
+ );
59397
59511
  const emittedEvents = emittedByTrait.get(traitName) ?? [];
59398
59512
  recordTransition({
59399
59513
  traitName,
@@ -59440,7 +59554,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
59440
59554
  }
59441
59555
  perfEnd("processEvent:total", _perfT0);
59442
59556
  perfEnd(`event:${normalizedEvent}`, _perfT0);
59443
- }, [entities, eventBus, sharedEntityStore]);
59557
+ }, [entities, eventBus, sharedEntityStore, reRenderCallsiteCaptureChildren]);
59444
59558
  const drainEventQueue = useCallback(async () => {
59445
59559
  if (processingRef.current) return;
59446
59560
  processingRef.current = true;
@@ -59615,7 +59729,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
59615
59729
  getConfig: (traitName) => {
59616
59730
  const binding = traitBindingsRef.current.find((b) => b.trait.name === traitName);
59617
59731
  if (binding === void 0) return void 0;
59618
- return buildTraitRenderConfig(binding, traitConfigsByName, {});
59732
+ return buildTraitRenderConfig(binding, traitConfigsByName);
59619
59733
  },
59620
59734
  getState: (traitName) => traitStatesRef.current.get(traitName)?.currentState ?? "",
59621
59735
  subscribe: (traitName, callback) => {
@@ -59664,6 +59778,23 @@ function normalizeChild(child) {
59664
59778
  props: { ...rest, ...normalizedChildren !== void 0 ? { children: normalizedChildren } : {} }
59665
59779
  };
59666
59780
  }
59781
+ function effectResultsToTraces(results) {
59782
+ if (!results) return [];
59783
+ return results.map((r2) => {
59784
+ const resultId = r2.data !== void 0 && r2.data !== null && "id" in r2.data && typeof r2.data.id === "string" ? r2.data.id : void 0;
59785
+ const outcome = r2.denied ? "denied" : r2.success ? "success" : "failed";
59786
+ return {
59787
+ type: r2.effect,
59788
+ ...r2.entityType !== void 0 ? { entityName: r2.entityType } : {},
59789
+ ...r2.action !== void 0 && (r2.action === "create" || r2.action === "update" || r2.action === "delete" || r2.action === "batch") ? { action: r2.action } : {},
59790
+ ...resultId !== void 0 ? { resultId } : {},
59791
+ outcome,
59792
+ args: [],
59793
+ status: outcome === "success" ? "executed" : "failed",
59794
+ error: r2.error
59795
+ };
59796
+ });
59797
+ }
59667
59798
  function applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraits, onNavigateBack) {
59668
59799
  for (const eff of effects) {
59669
59800
  if (eff.type === "render-ui" && eff.slot && eff.pattern) {
@@ -59745,7 +59876,7 @@ function NavStackRefBridge({ apiRef }) {
59745
59876
  }, [api, apiRef]);
59746
59877
  return null;
59747
59878
  }
59748
- function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onNavigateBack, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits, children }) {
59879
+ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onNavigateBack, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, callsiteCaptureChildrenByTrait, serverActiveTraits, children }) {
59749
59880
  const bridge = useServerBridge();
59750
59881
  const activeTraitNames = useMemo(
59751
59882
  () => new Set(traits2.map((b) => b.trait.name).filter((n) => !!n)),
@@ -59774,12 +59905,12 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
59774
59905
  continue;
59775
59906
  }
59776
59907
  void bridge.sendEvent(name, event, withActiveTraits(payload)).then(({ effects, meta }) => {
59777
- recordServerResponse(name, event, meta);
59908
+ recordServerResponse(name, event, { ...meta, effectResults: effectResultsToTraces(meta.effectResults) });
59778
59909
  applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNames, onNavigateBack);
59779
59910
  });
59780
59911
  }
59781
59912
  }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits]);
59782
- const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, navigateBack: onNavigateBack, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams } : { navigate: onNavigate, navigateBack: onNavigateBack, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams };
59913
+ const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, navigateBack: onNavigateBack, traitConfigsByName, orbitalsByTrait, embeddedTraits, callsiteCaptureChildrenByTrait, initPayload: routeParams } : { navigate: onNavigate, navigateBack: onNavigateBack, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, callsiteCaptureChildrenByTrait, initPayload: routeParams };
59783
59914
  const { sendEvent, entityBindingSource } = useTraitStateMachine(traits2, uiSlots, opts);
59784
59915
  const initSentRef = useRef(false);
59785
59916
  const prevTraitsRef = useRef(void 0);
@@ -59821,7 +59952,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
59821
59952
  (async () => {
59822
59953
  for (const name of orbitalNames) {
59823
59954
  const { effects, meta } = await bridge.sendEvent(name, "INIT", withActiveTraits({ ...routeParams ?? {} }));
59824
- recordServerResponse(name, "INIT", meta);
59955
+ recordServerResponse(name, "INIT", { ...meta, effectResults: effectResultsToTraces(meta.effectResults) });
59825
59956
  const effectTraces = [
59826
59957
  { type: "fetch", args: [], status: "executed" },
59827
59958
  ...effects.map((eff) => ({
@@ -59954,6 +60085,18 @@ function SchemaRunner({ schema, serverUrl, transport, getAccessToken, mockData,
59954
60085
  () => buildResolvedTraitConfigs(schema),
59955
60086
  [schema]
59956
60087
  );
60088
+ const callsiteCaptureChildrenByTrait = useMemo(() => {
60089
+ const merged = /* @__PURE__ */ new Map();
60090
+ const orbitals = schema?.orbitals;
60091
+ if (orbitals) {
60092
+ for (const orbital of orbitals) {
60093
+ for (const [referrer, children] of collectCallsiteCaptureChildren(orbital)) {
60094
+ merged.set(referrer, children);
60095
+ }
60096
+ }
60097
+ }
60098
+ return merged;
60099
+ }, [schema]);
59957
60100
  const embeddedTraits = useMemo(() => {
59958
60101
  const set = collectEmbeddedTraits(schema);
59959
60102
  xOrbitalLog.info("SchemaRunner:embeddedTraits", {
@@ -59990,6 +60133,7 @@ function SchemaRunner({ schema, serverUrl, transport, getAccessToken, mockData,
59990
60133
  traitConfigsByName,
59991
60134
  orbitalsByTrait,
59992
60135
  embeddedTraits,
60136
+ callsiteCaptureChildrenByTrait,
59993
60137
  serverActiveTraits,
59994
60138
  onNavigate,
59995
60139
  onNavigateBack,
@@ -60665,7 +60809,7 @@ function generateMockPayload(payloadSchema, schema, linkedEntity, mockData) {
60665
60809
  cur[parts[parts.length - 1]] = value;
60666
60810
  };
60667
60811
  for (const field of payloadSchema) {
60668
- let value = valueForType(field.type, field.entityType);
60812
+ let value = valueForType(field.type, field.entity);
60669
60813
  if (linkedFirstRow !== void 0 && field.name.includes(".") && (typeof value === "string" || typeof value === "number" || typeof value === "boolean")) {
60670
60814
  const tail = field.name.split(".").pop();
60671
60815
  const fromRow = linkedFirstRow[tail];
@@ -1,7 +1,7 @@
1
1
  import { AnimationName, Asset, ScenePos, EventEmit, JsonObject, SExpr } from '@almadar/core';
2
2
  import React__default from 'react';
3
3
  import * as THREE from 'three';
4
- import { D as DrawableNode } from './paintDispatch-B5ObLnUv.js';
4
+ import { D as DrawableNode } from './paintDispatch-CK5uwYEq.js';
5
5
 
6
6
  /**
7
7
  * Sprite Sheet Animation Types
@@ -1,7 +1,7 @@
1
1
  import { AnimationName, Asset, ScenePos, EventEmit, JsonObject, SExpr } from '@almadar/core';
2
2
  import React__default from 'react';
3
3
  import * as THREE from 'three';
4
- import { D as DrawableNode } from './paintDispatch-D3R8NNmV.cjs';
4
+ import { D as DrawableNode } from './paintDispatch-CK5uwYEq.cjs';
5
5
 
6
6
  /**
7
7
  * Sprite Sheet Animation Types