@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
@@ -5,8 +5,8 @@ export { EntitySchemaProvider, ServerBridgeProvider, TraitContext, TraitProvider
5
5
  import { createLogger, setNamespaceLevel, isLogLevelEnabled } from '@almadar/logger';
6
6
  import { perfStore, pushPerfEntry, wrapCallbackForEvent, perfStart, perfEnd, perfGauge, prepareSchemaForPreview, perfTimeAsync, collectTraitRefsFromResolvedTrait, buildOrbitalsByTrait, collectEmbeddedTraits } from '@almadar/runtime/ui';
7
7
  export { PERF_NAMESPACE, adjustSchemaForMockData, buildMockData, clearPerf, perfEnd, perfStart, perfTime, prepareSchemaForPreview, wrapCallbackForEvent } from '@almadar/runtime/ui';
8
- import { StateMachineManager, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, InMemoryPersistence, normalizeCallSiteConfigToValues, interpolateValue } from '@almadar/runtime';
9
- import { UI_SLOTS, mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, walkSExpr, buildResolvedTraitConfigs, isRenderBindingMarker, isFileValue, isInlineTrait, containsEntityBinding, isSExpr, isEventPayloadValue, RENDER_BINDING_MARKER } from '@almadar/core';
8
+ import { StateMachineManager, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor, LIFECYCLE_EVENTS, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, InMemoryPersistence, normalizeCallSiteConfigToValues, interpolateValue } from '@almadar/runtime';
9
+ import { UI_SLOTS, mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, walkSExpr, buildResolvedTraitConfigs, collectCallsiteCaptureChildren, isRenderBindingMarker, getNestedValue, isFileValue, isInlineTrait, containsEntityBinding, isSExpr, isEventPayloadValue, RENDER_BINDING_MARKER } from '@almadar/core';
10
10
  import { clsx } from 'clsx';
11
11
  import { twMerge } from 'tailwind-merge';
12
12
  import * as LucideIcons2 from 'lucide-react';
@@ -20,7 +20,8 @@ import { Link, Outlet, useLocation } from 'react-router-dom';
20
20
  import ELK from 'elkjs/lib/elk.bundled.js';
21
21
  import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light.js';
22
22
  import dark from 'react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus.js';
23
- import { orbLanguage, loloLanguage, ORB_COLORS } from '@almadar/syntax';
23
+ import { orbLanguage, loloLanguage, ORB_COLORS, translateLolo, translateOrb } from '@almadar/syntax';
24
+ import { coreTables } from '@almadar/core/i18n';
24
25
  import langJson from 'react-syntax-highlighter/dist/esm/languages/prism/json.js';
25
26
  import langJavascript from 'react-syntax-highlighter/dist/esm/languages/prism/javascript.js';
26
27
  import langTypescript from 'react-syntax-highlighter/dist/esm/languages/prism/typescript.js';
@@ -7656,8 +7657,9 @@ function getTransitions() {
7656
7657
  return [...getState().transitions];
7657
7658
  }
7658
7659
  function recordServerResponse(orbitalName, event, response) {
7660
+ const { effectResults, ...responseFields } = response;
7659
7661
  const serverResponse = {
7660
- ...response,
7662
+ ...responseFields,
7661
7663
  orbitalName,
7662
7664
  timestamp: Date.now()
7663
7665
  };
@@ -7667,7 +7669,7 @@ function recordServerResponse(orbitalName, event, response) {
7667
7669
  from: "server",
7668
7670
  to: "server",
7669
7671
  event,
7670
- effects: [],
7672
+ effects: effectResults ?? [],
7671
7673
  serverResponse,
7672
7674
  timestamp: Date.now()
7673
7675
  };
@@ -18279,6 +18281,15 @@ function buildLineProps(errorLines, extraClassName) {
18279
18281
  };
18280
18282
  };
18281
18283
  }
18284
+ function translateProgram(source, language, lang) {
18285
+ if (lang === "en") return source;
18286
+ if (language === "lolo") return translateLolo(source, lang);
18287
+ if (language === "orb") {
18288
+ const translated = translateOrb(source, lang);
18289
+ return typeof translated === "string" ? translated : source;
18290
+ }
18291
+ return source;
18292
+ }
18282
18293
  var dynamicallyLoaded, codeLanguageLoader, orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log6, 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;
18283
18294
  var init_CodeBlock = __esm({
18284
18295
  "components/core/molecules/markdown/CodeBlock.tsx"() {
@@ -18544,6 +18555,7 @@ var init_CodeBlock = __esm({
18544
18555
  showLineNumbers = false,
18545
18556
  wordWrap = false,
18546
18557
  files,
18558
+ naturalLanguages,
18547
18559
  actions,
18548
18560
  isLoading = false,
18549
18561
  error,
@@ -18590,7 +18602,48 @@ var init_CodeBlock = __esm({
18590
18602
  "replace"
18591
18603
  ]
18592
18604
  }) => {
18593
- const code = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
18605
+ const englishCode = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
18606
+ const naturalTabs = !editable && naturalLanguages && naturalLanguages.length > 1 ? naturalLanguages : void 0;
18607
+ const [naturalLanguage, setNaturalLanguage] = useState(() => naturalTabs?.[0] ?? "en");
18608
+ const activeNaturalLanguage = naturalTabs?.includes(naturalLanguage) === true ? naturalLanguage : naturalTabs?.[0] ?? "en";
18609
+ const translationCache = useMemo(() => /* @__PURE__ */ new Map(), [englishCode, files]);
18610
+ const translateFor = useCallback(
18611
+ (source, sourceLanguage, cacheKey) => {
18612
+ if (activeNaturalLanguage === "en") return source;
18613
+ const key = `${cacheKey}|${sourceLanguage}|${activeNaturalLanguage}`;
18614
+ const hit = translationCache.get(key);
18615
+ if (hit !== void 0) return hit;
18616
+ const translated = translateProgram(source, sourceLanguage, activeNaturalLanguage);
18617
+ translationCache.set(key, translated);
18618
+ return translated;
18619
+ },
18620
+ [translationCache, activeNaturalLanguage]
18621
+ );
18622
+ const code = translateFor(englishCode, language, "code");
18623
+ const naturalTabItems = naturalTabs?.map((lang) => ({
18624
+ id: `lang-${lang}`,
18625
+ label: coreTables[lang].meta.name,
18626
+ content: null
18627
+ }));
18628
+ const naturalTabStrip = naturalTabs && naturalTabItems ? /* @__PURE__ */ jsx(
18629
+ Box,
18630
+ {
18631
+ className: "border-b border-border",
18632
+ dir: coreTables[activeNaturalLanguage].meta.rtl ? "rtl" : "ltr",
18633
+ "data-testid": "codeblock-language-tabs",
18634
+ children: /* @__PURE__ */ jsx(
18635
+ Tabs,
18636
+ {
18637
+ tabs: naturalTabItems,
18638
+ activeTab: `lang-${activeNaturalLanguage}`,
18639
+ onTabChange: (id) => {
18640
+ const next = naturalTabs.find((lang) => `lang-${lang}` === id);
18641
+ if (next) setNaturalLanguage(next);
18642
+ }
18643
+ }
18644
+ )
18645
+ }
18646
+ ) : null;
18594
18647
  const activeStyle = resolveHighlightStyle(language);
18595
18648
  const overCapacity = code.length > HIGHLIGHT_CAPACITY_BYTES;
18596
18649
  const plainCodeColor = plainCodeColorOf(activeStyle);
@@ -18603,8 +18656,8 @@ var init_CodeBlock = __esm({
18603
18656
  const [wrap, setWrap] = useState(wordWrap);
18604
18657
  const [activeFileIndex, setActiveFileIndex] = useState(0);
18605
18658
  const activeFile = files?.[activeFileIndex];
18606
- const activeCode = activeFile?.code ?? code;
18607
18659
  const activeLanguage = activeFile?.language ?? language;
18660
+ const activeCode = activeFile ? translateFor(activeFile.code, activeLanguage, `file-${activeFileIndex}`) : code;
18608
18661
  const languageReady = useLanguageReady(activeLanguage);
18609
18662
  const viewerStyle = resolveHighlightStyle(activeLanguage);
18610
18663
  const viewerPlainCodeColor = plainCodeColorOf(viewerStyle);
@@ -19089,6 +19142,7 @@ var init_CodeBlock = __esm({
19089
19142
  content: null
19090
19143
  }));
19091
19144
  return /* @__PURE__ */ jsx(Card, { className: cn("overflow-hidden", className), children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column" }, children: [
19145
+ naturalTabStrip,
19092
19146
  tabItems && tabItems.length > 1 && /* @__PURE__ */ jsx(Box, { className: "border-b border-border", children: /* @__PURE__ */ jsx(
19093
19147
  Tabs,
19094
19148
  {
@@ -19150,7 +19204,7 @@ var init_CodeBlock = __esm({
19150
19204
  ]
19151
19205
  }
19152
19206
  ),
19153
- /* @__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 }) })
19207
+ /* @__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 }) })
19154
19208
  ] }) });
19155
19209
  }
19156
19210
  const hasHeader = showLanguageBadge || effectiveCopy;
@@ -19177,6 +19231,7 @@ var init_CodeBlock = __esm({
19177
19231
  ]
19178
19232
  }
19179
19233
  ),
19234
+ naturalTabStrip,
19180
19235
  editable ? (
19181
19236
  /* GAP-77 / GAP-82 / GAP-83: editable mode = transparent textarea on
19182
19237
  top of a Prism-highlighted SyntaxHighlighter overlay.
@@ -19328,6 +19383,7 @@ var init_CodeBlock = __esm({
19328
19383
  {
19329
19384
  ref: scrollRef,
19330
19385
  onCopy: handleSelectionCopy,
19386
+ dir: "ltr",
19331
19387
  style: {
19332
19388
  flex: 1,
19333
19389
  minHeight: 0,
@@ -19346,7 +19402,7 @@ var init_CodeBlock = __esm({
19346
19402
  )
19347
19403
  ] });
19348
19404
  },
19349
- (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
19405
+ (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
19350
19406
  );
19351
19407
  CodeBlock.displayName = "CodeBlock";
19352
19408
  }
@@ -22991,26 +23047,6 @@ var init_ButtonGroup = __esm({
22991
23047
  ButtonGroup.displayName = "ButtonGroup";
22992
23048
  }
22993
23049
  });
22994
- function getNestedValue(obj, path) {
22995
- if (obj === null || obj === void 0 || !path) {
22996
- return void 0;
22997
- }
22998
- if (!path.includes(".")) {
22999
- return obj[path];
23000
- }
23001
- const parts = path.split(".");
23002
- let value = obj;
23003
- for (const part of parts) {
23004
- if (value === null || value === void 0) {
23005
- return void 0;
23006
- }
23007
- if (typeof value !== "object" || Array.isArray(value)) {
23008
- return void 0;
23009
- }
23010
- value = value[part];
23011
- }
23012
- return value;
23013
- }
23014
23050
  function resolveImageUrl(value) {
23015
23051
  if (typeof value === "string") {
23016
23052
  return value;
@@ -41598,11 +41634,11 @@ var init_WizardContainer = __esm({
41598
41634
  });
41599
41635
  function calculateComplexity(schema) {
41600
41636
  if (!schema) return 1;
41601
- const entities = schema.dataEntities?.length || 0;
41637
+ const entities = schema.dataEntities || 0;
41602
41638
  const pages = schema.ui?.pages?.length || 0;
41603
- const traits2 = schema.traits?.length || 0;
41639
+ const traits2 = schema.traits || 0;
41604
41640
  const sections = schema.ui?.pages?.reduce(
41605
- (acc, page) => acc + (page.sections?.length || 0),
41641
+ (acc, page) => acc + (page.sections || 0),
41606
41642
  0
41607
41643
  ) || 0;
41608
41644
  return entities * 3 + pages * 2 + traits2 * 2 + sections * 1;
@@ -52377,15 +52413,19 @@ function runTickFrame(entityId, orderedWriters, store) {
52377
52413
  }
52378
52414
  var log3 = createLogger("almadar:ui:effects:client-handlers");
52379
52415
  function createClientEffectHandlers(options) {
52380
- const { eventBus, slotSetter, navigate, navigateBack, notify, callService, liveEntity } = options;
52416
+ const { eventBus, slotSetter, navigate, navigateBack, notify, callService, liveEntity, persistDelegated } = options;
52381
52417
  return {
52382
52418
  emit: (event, payload, source) => {
52383
52419
  const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
52384
52420
  eventBus.emit(prefixedEvent, payload, source);
52385
52421
  },
52386
52422
  persist: async () => {
52387
- log3.warn("persist is server-side only, ignored on client");
52423
+ log3.debug("persist is server-side only, ignored on client");
52388
52424
  },
52425
+ // Bridge mode: the server runs every persist and the response
52426
+ // carries its outcome — tell the executor so the placeholder above is
52427
+ // never read as a denial (see `EffectHandlers.persistDelegated`).
52428
+ ...persistDelegated === true ? { persistDelegated: true } : {},
52389
52429
  // @almadar/runtime EffectHandlers.set types value:unknown — should be FieldValue (upstream fix queued)
52390
52430
  set: ((_entityId, field, value) => {
52391
52431
  if (!liveEntity) {
@@ -52654,7 +52694,6 @@ var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
52654
52694
  "do",
52655
52695
  "when"
52656
52696
  ]);
52657
- var LIFECYCLE_EVENTS = ["INIT", "LOAD", "$MOUNT"];
52658
52697
  function toTraitDefinition(binding) {
52659
52698
  return {
52660
52699
  name: binding.trait.name,
@@ -52694,17 +52733,14 @@ function classifySharedTick(tick) {
52694
52733
  if (renders) return "renderer";
52695
52734
  return "neither";
52696
52735
  }
52697
- function buildTraitRenderConfig(binding, traitConfigsByName, payload) {
52736
+ function buildTraitRenderConfig(binding, traitConfigsByName) {
52698
52737
  const declaredDefaults = collectDeclaredConfigDefaults(binding.trait);
52699
52738
  const resolvedDefaults = traitConfigsByName?.[binding.trait.name];
52700
52739
  const callSiteConfig = getBindingConfig(binding);
52701
- const callSiteOverrides = callSiteConfig ? resolveCallSitePayloadCaptures(
52702
- Object.fromEntries(
52703
- Object.entries(callSiteConfig).filter(
52704
- ([, v]) => !containsConfigForward(v)
52705
- )
52706
- ),
52707
- payload
52740
+ const callSiteOverrides = callSiteConfig ? Object.fromEntries(
52741
+ Object.entries(callSiteConfig).filter(
52742
+ ([, v]) => !containsConfigForward(v)
52743
+ )
52708
52744
  ) : void 0;
52709
52745
  if (declaredDefaults || resolvedDefaults || callSiteOverrides) {
52710
52746
  return {
@@ -52775,12 +52811,40 @@ function evalFieldDefault(value) {
52775
52811
  return value;
52776
52812
  }
52777
52813
  }
52814
+ function isPersistTraceAction(value) {
52815
+ return value === "create" || value === "update" || value === "delete" || value === "batch";
52816
+ }
52817
+ function overlayServerEffectResults(effectTraces, serverResults) {
52818
+ if (serverResults.length === 0) return effectTraces;
52819
+ const queues = /* @__PURE__ */ new Map();
52820
+ for (const result of serverResults) {
52821
+ const queue = queues.get(result.effect);
52822
+ if (queue) queue.push(result);
52823
+ else queues.set(result.effect, [result]);
52824
+ }
52825
+ return effectTraces.map((trace) => {
52826
+ const match = queues.get(trace.type)?.shift();
52827
+ if (!match) return trace;
52828
+ const resultId = match.data && typeof match.data === "object" && !Array.isArray(match.data) ? match.data.id : void 0;
52829
+ const outcome = match.success ? "success" : match.denied ? "denied" : "failed";
52830
+ return {
52831
+ ...trace,
52832
+ ...match.entityType !== void 0 ? { entityName: match.entityType } : {},
52833
+ ...match.action !== void 0 && isPersistTraceAction(match.action) ? { action: match.action } : {},
52834
+ ...resultId !== void 0 ? { resultId } : {},
52835
+ outcome,
52836
+ status: match.success ? "executed" : "failed",
52837
+ ...match.error !== void 0 ? { error: match.error } : {}
52838
+ };
52839
+ });
52840
+ }
52778
52841
  function useTraitStateMachine(traitBindings, uiSlots, options) {
52779
52842
  sharedEntityLog.debug("useTraitStateMachine start", { traitBindingsCount: traitBindings.length, traitNames: traitBindings.map((b) => b.trait.name) });
52780
52843
  const eventBus = useEventBus();
52781
52844
  const { entities } = useEntitySchema();
52782
52845
  const traitConfigsByName = options?.traitConfigsByName;
52783
52846
  const orbitalsByTrait = options?.orbitalsByTrait;
52847
+ const callsiteCaptureChildrenByTrait = options?.callsiteCaptureChildrenByTrait;
52784
52848
  const sharedEntityStore = useSharedEntityStore();
52785
52849
  const sharedGroups = useMemo(() => {
52786
52850
  const groups = /* @__PURE__ */ new Map();
@@ -53038,7 +53102,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53038
53102
  };
53039
53103
  }, [traitBindings]);
53040
53104
  const executeTransitionEffects = useCallback(async (params) => {
53041
- const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log11 } = params;
53105
+ const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log11, callsitePayload } = params;
53042
53106
  const traitName = binding.trait.name;
53043
53107
  const linkedEntity = binding.linkedEntity || "";
53044
53108
  const entityId = payload?.entityId;
@@ -53060,7 +53124,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53060
53124
  const effects = syncOnly ? params.effects.filter(
53061
53125
  (e) => Array.isArray(e) && SYNC_TICK_OPERATORS.has(String(e[0]))
53062
53126
  ) : params.effects;
53063
- if (effects.length === 0) return [];
53127
+ if (effects.length === 0) return { emitted: [], serverEffectResults: [] };
53064
53128
  const pendingSlots = /* @__PURE__ */ new Map();
53065
53129
  ({
53066
53130
  traitDefinition: binding.trait
@@ -53097,10 +53161,15 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53097
53161
  // the trait's one live store — the same object bound below. This is
53098
53162
  // what makes a [runtime] entity's set (from ticks AND events) reach
53099
53163
  // the render-ui + next tick + guards.
53100
- liveEntity
53164
+ liveEntity,
53165
+ // No local persistence adapter (bridge mode, or a syncOnly tick):
53166
+ // nothing persists client-side, the server owns the write and
53167
+ // reports it — never read the placeholder as a denial.
53168
+ persistDelegated: (syncOnly ? void 0 : optionsRef.current?.persistence) === void 0
53101
53169
  });
53102
53170
  const persistence = syncOnly ? void 0 : optionsRef.current?.persistence;
53103
53171
  let handlers = clientHandlers;
53172
+ const serverEffectResults = [];
53104
53173
  if (persistence) {
53105
53174
  const sharedBindings = {
53106
53175
  // Seed `@entity` from the trait's scalar field state (a real
@@ -53112,16 +53181,16 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53112
53181
  payload: payload || {},
53113
53182
  state: previousState
53114
53183
  };
53184
+ if (callsitePayload) {
53185
+ sharedBindings.callsitePayload = callsitePayload;
53186
+ }
53115
53187
  const sharedDeclared = collectDeclaredConfigDefaults(binding.trait);
53116
53188
  const sharedResolved = traitConfigsByName?.[traitName];
53117
53189
  const sharedCallSiteRaw = getBindingConfig(binding);
53118
- const sharedCallSite = sharedCallSiteRaw ? resolveCallSitePayloadCaptures(
53119
- Object.fromEntries(
53120
- Object.entries(sharedCallSiteRaw).filter(
53121
- ([, v]) => !containsConfigForward(v)
53122
- )
53123
- ),
53124
- payload || {}
53190
+ const sharedCallSite = sharedCallSiteRaw ? Object.fromEntries(
53191
+ Object.entries(sharedCallSiteRaw).filter(
53192
+ ([, v]) => !containsConfigForward(v)
53193
+ )
53125
53194
  ) : void 0;
53126
53195
  if (sharedDeclared || sharedResolved || sharedCallSite) {
53127
53196
  sharedBindings.config = {
@@ -53145,7 +53214,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53145
53214
  },
53146
53215
  source: { trait: traitName },
53147
53216
  // @almadar/runtime callService types params:unknown/Promise<unknown> — should be ServiceParams/EventPayload (upstream fix queued)
53148
- callService: optionsRef.current?.callService
53217
+ callService: optionsRef.current?.callService,
53218
+ effectResults: serverEffectResults
53149
53219
  });
53150
53220
  handlers = {
53151
53221
  ...serverHandlers,
@@ -53180,7 +53250,10 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53180
53250
  payload: payload || {},
53181
53251
  state: previousState
53182
53252
  };
53183
- const renderConfig = buildTraitRenderConfig(binding, traitConfigsByName, payload || {});
53253
+ if (callsitePayload) {
53254
+ bindingCtx.callsitePayload = callsitePayload;
53255
+ }
53256
+ const renderConfig = buildTraitRenderConfig(binding, traitConfigsByName);
53184
53257
  if (renderConfig !== void 0) {
53185
53258
  bindingCtx.config = renderConfig;
53186
53259
  }
@@ -53271,8 +53344,42 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53271
53344
  effectCount: effects.length
53272
53345
  });
53273
53346
  }
53274
- return emittedDuringExec;
53347
+ return { emitted: emittedDuringExec, serverEffectResults };
53275
53348
  }, [eventBus, flushSlot, sharedEntityStore, publishBindingSnapshot, orbitalsByTrait]);
53349
+ const reRenderCallsiteCaptureChildren = useCallback(async (traitName, callsitePayload, entityByTrait, log11, visited = /* @__PURE__ */ new Set()) => {
53350
+ const children = callsiteCaptureChildrenByTrait?.get(traitName);
53351
+ if (!children || children.size === 0) return;
53352
+ const mgr = managerRef.current;
53353
+ const bindingMap = new Map(traitBindingsRef.current.map((b) => [b.trait.name, b]));
53354
+ for (const childName of children) {
53355
+ if (visited.has(childName)) continue;
53356
+ visited.add(childName);
53357
+ const childBinding = bindingMap.get(childName);
53358
+ if (!childBinding) continue;
53359
+ const lifecycleEvent = LIFECYCLE_EVENTS.find((evt) => mgr.canHandleEvent(childName, evt));
53360
+ if (lifecycleEvent === void 0) continue;
53361
+ const [entry] = mgr.sendEvent(lifecycleEvent, {}, void 0, entityByTrait, void 0, childName);
53362
+ if (!entry || !entry.result.executed) continue;
53363
+ log11.debug("callsite-capture-child:rerender", {
53364
+ referrer: traitName,
53365
+ child: childName,
53366
+ lifecycleEvent,
53367
+ callsitePayload: JSON.stringify(callsitePayload)
53368
+ });
53369
+ await executeTransitionEffects({
53370
+ binding: childBinding,
53371
+ effects: entry.result.effects,
53372
+ previousState: entry.result.previousState,
53373
+ newState: entry.result.newState,
53374
+ payload: {},
53375
+ flushEvent: lifecycleEvent,
53376
+ syncOnly: false,
53377
+ log: log11,
53378
+ callsitePayload
53379
+ });
53380
+ await reRenderCallsiteCaptureChildren(childName, callsitePayload, entityByTrait, log11, visited);
53381
+ }
53382
+ }, [callsiteCaptureChildrenByTrait, executeTransitionEffects]);
53276
53383
  const runTickEffects = useCallback((tick, binding) => {
53277
53384
  const traitName = binding.trait.name;
53278
53385
  const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
@@ -53410,6 +53517,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53410
53517
  executedTraits: results.map((r) => r.traitName).join(",")
53411
53518
  });
53412
53519
  const emittedByTrait = /* @__PURE__ */ new Map();
53520
+ const serverEffectResultsByTrait = /* @__PURE__ */ new Map();
53413
53521
  bridgeEchoPendingRef.current.clear();
53414
53522
  for (const { traitName, result } of results) {
53415
53523
  const binding = bindingMap.get(traitName);
@@ -53454,7 +53562,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53454
53562
  effects: JSON.stringify(result.effects)
53455
53563
  }));
53456
53564
  const _perfT2 = perfStart("processEvent:executeAll");
53457
- const emittedDuringExec = await executeTransitionEffects({
53565
+ const { emitted: emittedDuringExec, serverEffectResults: transitionServerEffectResults } = await executeTransitionEffects({
53458
53566
  binding,
53459
53567
  // upstream gap: /runtime TransitionResult.effects is unknown[] — they are SExpr at runtime (see Almadar_UI_Gaps.md)
53460
53568
  effects: result.effects,
@@ -53467,12 +53575,14 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53467
53575
  });
53468
53576
  perfEnd("processEvent:executeAll", _perfT2);
53469
53577
  emittedByTrait.set(traitName, emittedDuringExec);
53578
+ serverEffectResultsByTrait.set(traitName, transitionServerEffectResults);
53470
53579
  for (const emittedKey of emittedDuringExec) {
53471
53580
  bridgeEchoPendingRef.current.set(
53472
53581
  emittedKey,
53473
53582
  (bridgeEchoPendingRef.current.get(emittedKey) ?? 0) + 1
53474
53583
  );
53475
53584
  }
53585
+ await reRenderCallsiteCaptureChildren(traitName, payload ?? {}, entityByTrait, stateLog);
53476
53586
  } else if (!result.executed) {
53477
53587
  if (result.guardResult === false) {
53478
53588
  stateLog.debug("guard-blocked-transition", {
@@ -53501,7 +53611,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53501
53611
  for (const { traitName, result } of results) {
53502
53612
  if (result.executed) {
53503
53613
  updateTraitState(traitName, result.newState);
53504
- const effectTraces = result.effects.map(
53614
+ const reconstructedEffectTraces = result.effects.map(
53505
53615
  (e) => {
53506
53616
  if (Array.isArray(e)) {
53507
53617
  const head = String(e[0] ?? "unknown");
@@ -53520,6 +53630,10 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53520
53630
  };
53521
53631
  }
53522
53632
  );
53633
+ const effectTraces = overlayServerEffectResults(
53634
+ reconstructedEffectTraces,
53635
+ serverEffectResultsByTrait.get(traitName) ?? []
53636
+ );
53523
53637
  const emittedEvents = emittedByTrait.get(traitName) ?? [];
53524
53638
  recordTransition({
53525
53639
  traitName,
@@ -53566,7 +53680,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53566
53680
  }
53567
53681
  perfEnd("processEvent:total", _perfT0);
53568
53682
  perfEnd(`event:${normalizedEvent}`, _perfT0);
53569
- }, [entities, eventBus, sharedEntityStore]);
53683
+ }, [entities, eventBus, sharedEntityStore, reRenderCallsiteCaptureChildren]);
53570
53684
  const drainEventQueue = useCallback(async () => {
53571
53685
  if (processingRef.current) return;
53572
53686
  processingRef.current = true;
@@ -53741,7 +53855,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53741
53855
  getConfig: (traitName) => {
53742
53856
  const binding = traitBindingsRef.current.find((b) => b.trait.name === traitName);
53743
53857
  if (binding === void 0) return void 0;
53744
- return buildTraitRenderConfig(binding, traitConfigsByName, {});
53858
+ return buildTraitRenderConfig(binding, traitConfigsByName);
53745
53859
  },
53746
53860
  getState: (traitName) => traitStatesRef.current.get(traitName)?.currentState ?? "",
53747
53861
  subscribe: (traitName, callback) => {
@@ -53893,6 +54007,23 @@ function normalizeChild(child) {
53893
54007
  props: { ...rest, ...normalizedChildren !== void 0 ? { children: normalizedChildren } : {} }
53894
54008
  };
53895
54009
  }
54010
+ function effectResultsToTraces(results) {
54011
+ if (!results) return [];
54012
+ return results.map((r) => {
54013
+ const resultId = r.data !== void 0 && r.data !== null && "id" in r.data && typeof r.data.id === "string" ? r.data.id : void 0;
54014
+ const outcome = r.denied ? "denied" : r.success ? "success" : "failed";
54015
+ return {
54016
+ type: r.effect,
54017
+ ...r.entityType !== void 0 ? { entityName: r.entityType } : {},
54018
+ ...r.action !== void 0 && (r.action === "create" || r.action === "update" || r.action === "delete" || r.action === "batch") ? { action: r.action } : {},
54019
+ ...resultId !== void 0 ? { resultId } : {},
54020
+ outcome,
54021
+ args: [],
54022
+ status: outcome === "success" ? "executed" : "failed",
54023
+ error: r.error
54024
+ };
54025
+ });
54026
+ }
53896
54027
  function applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraits, onNavigateBack) {
53897
54028
  for (const eff of effects) {
53898
54029
  if (eff.type === "render-ui" && eff.slot && eff.pattern) {
@@ -53974,7 +54105,7 @@ function NavStackRefBridge({ apiRef }) {
53974
54105
  }, [api, apiRef]);
53975
54106
  return null;
53976
54107
  }
53977
- function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onNavigateBack, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits, children }) {
54108
+ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onNavigateBack, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, callsiteCaptureChildrenByTrait, serverActiveTraits, children }) {
53978
54109
  const bridge = useServerBridge();
53979
54110
  const activeTraitNames = useMemo(
53980
54111
  () => new Set(traits2.map((b) => b.trait.name).filter((n) => !!n)),
@@ -54003,12 +54134,12 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
54003
54134
  continue;
54004
54135
  }
54005
54136
  void bridge.sendEvent(name, event, withActiveTraits(payload)).then(({ effects, meta }) => {
54006
- recordServerResponse(name, event, meta);
54137
+ recordServerResponse(name, event, { ...meta, effectResults: effectResultsToTraces(meta.effectResults) });
54007
54138
  applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNames, onNavigateBack);
54008
54139
  });
54009
54140
  }
54010
54141
  }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits]);
54011
- const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, navigateBack: onNavigateBack, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams } : { navigate: onNavigate, navigateBack: onNavigateBack, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams };
54142
+ 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 };
54012
54143
  const { sendEvent, entityBindingSource } = useTraitStateMachine(traits2, uiSlots, opts);
54013
54144
  const initSentRef = useRef(false);
54014
54145
  const prevTraitsRef = useRef(void 0);
@@ -54050,7 +54181,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
54050
54181
  (async () => {
54051
54182
  for (const name of orbitalNames) {
54052
54183
  const { effects, meta } = await bridge.sendEvent(name, "INIT", withActiveTraits({ ...routeParams ?? {} }));
54053
- recordServerResponse(name, "INIT", meta);
54184
+ recordServerResponse(name, "INIT", { ...meta, effectResults: effectResultsToTraces(meta.effectResults) });
54054
54185
  const effectTraces = [
54055
54186
  { type: "fetch", args: [], status: "executed" },
54056
54187
  ...effects.map((eff) => ({
@@ -54183,6 +54314,18 @@ function SchemaRunner({ schema, serverUrl, transport, getAccessToken, mockData,
54183
54314
  () => buildResolvedTraitConfigs(schema),
54184
54315
  [schema]
54185
54316
  );
54317
+ const callsiteCaptureChildrenByTrait = useMemo(() => {
54318
+ const merged = /* @__PURE__ */ new Map();
54319
+ const orbitals = schema?.orbitals;
54320
+ if (orbitals) {
54321
+ for (const orbital of orbitals) {
54322
+ for (const [referrer, children] of collectCallsiteCaptureChildren(orbital)) {
54323
+ merged.set(referrer, children);
54324
+ }
54325
+ }
54326
+ }
54327
+ return merged;
54328
+ }, [schema]);
54186
54329
  const embeddedTraits = useMemo(() => {
54187
54330
  const set = collectEmbeddedTraits(schema);
54188
54331
  xOrbitalLog.info("SchemaRunner:embeddedTraits", {
@@ -54219,6 +54362,7 @@ function SchemaRunner({ schema, serverUrl, transport, getAccessToken, mockData,
54219
54362
  traitConfigsByName,
54220
54363
  orbitalsByTrait,
54221
54364
  embeddedTraits,
54365
+ callsiteCaptureChildrenByTrait,
54222
54366
  serverActiveTraits,
54223
54367
  onNavigate,
54224
54368
  onNavigateBack,