@almadar/runtime 6.71.0 → 6.73.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.
@@ -1,12 +1,12 @@
1
1
  import { parseCron, cronMinuteKey, cronMatches } from './chunk-OU3ITB5S.js';
2
- import { createContextFromBindings, interpolateValue, deferEntityBindings } from './chunk-ZJ62H3ES.js';
2
+ import { createContextFromBindings, interpolateValue, deferEntityBindings } from './chunk-ZWAOJT6R.js';
3
3
  import { seedRandom, randomArrayElement, randomInt, shuffleArray, randomPastDate } from './chunk-T4VDAB4C.js';
4
4
  import { collectTraitRefsFromValue, collectTraitRefsFromEffects } from './chunk-SCRAHWOC.js';
5
5
  import { createLogger, setNamespaceLevel } from '@almadar/logger';
6
6
  import { evaluateGuard, SExpressionEvaluator } from '@almadar/evaluator';
7
- import { OrbitalSchemaSchema, isInlineTrait, isEntityCall, isEntityReference, parseEntityRef, parseImportedTraitRef, isPageReference, isPageReferenceString, isPageReferenceObject, parsePageRef, isReferenceConfigType, configRefEventKnob, normalizeCallSiteConfigToValues, resolveConfigRefEventName, eventListPropsOf } from '@almadar/core';
7
+ import { OrbitalSchemaSchema, isInlineTrait, isEntityCall, isEntityReference, parseEntityRef, parseImportedTraitRef, isPageReference, isPageReferenceString, isPageReferenceObject, parsePageRef, parseOrbitalRef, overrideDeclaredKnobs, asTraitId, asEntityId, asPageId, asOrbitalId, deriveId, isReferenceConfigType, configRefEventKnob, normalizeCallSiteConfigToValues, resolveConfigRefEventName, isCallSiteConfigDeclaration, asEventId, ledgerRename, idPrefix, eventListPropsOf } from '@almadar/core';
8
8
  export { normalizeCallSiteConfigToValues } from '@almadar/core';
9
- import { sampleRowCount, sampleRow } from '@almadar/core/mock';
9
+ import { sampleRowCount, sampleRow, identityEntitiesOf, roleVocabularyOf } from '@almadar/core/mock';
10
10
 
11
11
  var log = createLogger("almadar:runtime:eventbus");
12
12
  var EventBus = class {
@@ -324,6 +324,7 @@ function isValidDurationString(interval) {
324
324
  return /^(\d+)(ms|s|m|h)?$/.test(interval);
325
325
  }
326
326
  var smLog = createLogger("almadar:runtime:sm");
327
+ var LIFECYCLE_EVENTS = ["INIT", "LOAD", "$MOUNT"];
327
328
  function findInitialState(trait) {
328
329
  if (!trait.states || trait.states.length === 0) {
329
330
  smLog.warn("trait-has-no-states", { trait: trait.name });
@@ -1197,13 +1198,23 @@ var EffectExecutor = class _EffectExecutor {
1197
1198
  const isCompound = operator === "do" || operator === "when" || operator === "let" || operator === "if";
1198
1199
  const resolvedArgs = isCompound ? rawArgs : resolveArgs(rawArgs, this.bindings, this.strictBindings, this.contextExtensions);
1199
1200
  try {
1200
- await this.dispatch(operator, resolvedArgs);
1201
- results.push({
1202
- type: operator,
1203
- args: resolvedArgs,
1204
- status: "executed",
1205
- durationMs: Date.now() - start
1206
- });
1201
+ const outcome = await this.dispatch(operator, resolvedArgs);
1202
+ if (outcome?.failed) {
1203
+ results.push({
1204
+ type: operator,
1205
+ args: resolvedArgs,
1206
+ status: "failed",
1207
+ error: outcome.error,
1208
+ durationMs: Date.now() - start
1209
+ });
1210
+ } else {
1211
+ results.push({
1212
+ type: operator,
1213
+ args: resolvedArgs,
1214
+ status: "executed",
1215
+ durationMs: Date.now() - start
1216
+ });
1217
+ }
1207
1218
  } catch (error) {
1208
1219
  const errorMessage = error instanceof Error ? error.message : String(error);
1209
1220
  results.push({
@@ -1260,10 +1271,10 @@ var EffectExecutor = class _EffectExecutor {
1260
1271
  this.handlers.emit(eventName, payload, this.sourceStamp(), fromPersistSuccess);
1261
1272
  }
1262
1273
  }
1263
- emitFailure(emit, err) {
1274
+ emitFailure(emit, err, extra) {
1264
1275
  if (!emit?.failure) return;
1265
1276
  const error = err instanceof Error ? err.message : String(err);
1266
- this.handlers.emit(emit.failure, { error }, this.sourceStamp());
1277
+ this.handlers.emit(emit.failure, { ...extra, error }, this.sourceStamp());
1267
1278
  }
1268
1279
  /**
1269
1280
  * Narrow the generic emit config into the `os/watch-*` handler surface
@@ -1310,6 +1321,14 @@ var EffectExecutor = class _EffectExecutor {
1310
1321
  // ==========================================================================
1311
1322
  // Effect Dispatch
1312
1323
  // ==========================================================================
1324
+ /**
1325
+ * Dispatches one effect. Returns `void` for the ordinary case (the
1326
+ * caller only cares whether it threw). A `persist` that resolves
1327
+ * without throwing — the store DENIED the write, signalled by return
1328
+ * value rather than an exception, per the "close the circuit" doctrine
1329
+ * — reports that outcome here so `executeWithResults` can record it as
1330
+ * `status: 'failed'` instead of the default `'executed'`.
1331
+ */
1313
1332
  async dispatch(operator, args) {
1314
1333
  switch (operator) {
1315
1334
  // === Universal Effects ===
@@ -1383,6 +1402,15 @@ var EffectExecutor = class _EffectExecutor {
1383
1402
  success: emitCfg?.success,
1384
1403
  failure: emitCfg?.failure
1385
1404
  });
1405
+ if (this.handlers.persistDelegated === true) {
1406
+ persistLog.debug("persist:delegated", {
1407
+ action,
1408
+ entityType: action === "batch" ? "batch" : args[1],
1409
+ traitName: this.context.traitName,
1410
+ transition: this.context.transition
1411
+ });
1412
+ return;
1413
+ }
1386
1414
  try {
1387
1415
  if (action === "batch") {
1388
1416
  const operations = args[1];
@@ -1406,16 +1434,38 @@ var EffectExecutor = class _EffectExecutor {
1406
1434
  const entityType = args[1];
1407
1435
  const data = args[2];
1408
1436
  const persisted = await this.handlers.persist(action, entityType, data);
1409
- const successPayload = persisted ?? data;
1410
- const dataId = typeof successPayload === "string" ? successPayload : successPayload && typeof successPayload === "object" ? successPayload.id : void 0;
1411
- persistLog.debug("persist:success", {
1412
- action,
1413
- entityType,
1414
- dataId,
1415
- willEmit: emitCfg?.success
1416
- });
1417
- this.emitSuccess(emitCfg, "success", successPayload, true);
1418
- persistLog.debug("persist:emit-fired", { action, eventName: emitCfg?.success });
1437
+ if (persisted === void 0) {
1438
+ const attemptedId = typeof data === "string" ? data : data && typeof data === "object" ? data.id : void 0;
1439
+ persistLog.error("persist:denied", { action, entityType, attemptedId });
1440
+ const deniedError = `persist ${action} ${entityType} was denied or failed`;
1441
+ this.emitFailure(
1442
+ emitCfg,
1443
+ new Error(deniedError),
1444
+ { entityType, id: attemptedId }
1445
+ );
1446
+ return { failed: true, error: deniedError };
1447
+ } else {
1448
+ const dataId = typeof persisted === "string" ? persisted : persisted.id;
1449
+ persistLog.debug("persist:success", {
1450
+ action,
1451
+ entityType,
1452
+ dataId,
1453
+ willEmit: emitCfg?.success
1454
+ });
1455
+ if (action === "create" && this.bindings.entity && typeof dataId === "string") {
1456
+ const boundId = this.bindings.entity.id;
1457
+ const submittedId = data && typeof data === "object" ? data.id : void 0;
1458
+ if (boundId === void 0 || boundId === submittedId) {
1459
+ this.bindings.entity.id = dataId;
1460
+ persistLog.debug("persist:create-bound-id", {
1461
+ entityType,
1462
+ id: dataId
1463
+ });
1464
+ }
1465
+ }
1466
+ this.emitSuccess(emitCfg, "success", persisted, true);
1467
+ persistLog.debug("persist:emit-fired", { action, eventName: emitCfg?.success });
1468
+ }
1419
1469
  }
1420
1470
  } catch (err) {
1421
1471
  persistLog.error("persist:error", {
@@ -1450,8 +1500,16 @@ var EffectExecutor = class _EffectExecutor {
1450
1500
  const emitCfg = this.extractEmitConfig(rawOpt);
1451
1501
  try {
1452
1502
  const result = await this.handlers.fetch(entityType, options);
1453
- const payload = result ? { data: result.rows, totalCount: result.total } : { data: null, totalCount: 0 };
1454
- this.emitSuccess(emitCfg, "success", payload);
1503
+ if (result === null) {
1504
+ if (options?.id !== void 0) {
1505
+ this.emitFailure(emitCfg, new Error(`${entityType} ${options.id} not found`));
1506
+ } else {
1507
+ this.emitSuccess(emitCfg, "success", { data: [], totalCount: 0 });
1508
+ }
1509
+ } else {
1510
+ const payload = { data: result.rows, totalCount: result.total };
1511
+ this.emitSuccess(emitCfg, "success", payload);
1512
+ }
1455
1513
  } catch (err) {
1456
1514
  this.emitFailure(emitCfg, err);
1457
1515
  throw err;
@@ -2642,7 +2700,11 @@ var MockPersistenceAdapter = class _MockPersistenceAdapter {
2642
2700
  async create(entityType, data) {
2643
2701
  const store = this.getStore(entityType);
2644
2702
  this.assertFileValuesWithinCeiling(entityType, data);
2645
- const id = this.nextId(entityType);
2703
+ const suppliedId = typeof data.id === "string" && data.id.length > 0 ? data.id : void 0;
2704
+ if (suppliedId && store.has(suppliedId)) {
2705
+ throw new Error(`Entity ${entityType} with id ${suppliedId} already exists`);
2706
+ }
2707
+ const id = suppliedId ?? this.nextId(entityType);
2646
2708
  const now = (/* @__PURE__ */ new Date()).toISOString();
2647
2709
  const withDefaults = this.applyFieldDefaults(entityType, data);
2648
2710
  const item = {
@@ -2904,6 +2966,7 @@ var HttpLoader = class {
2904
2966
  data: {
2905
2967
  orbital,
2906
2968
  orbitals: schema.orbitals,
2969
+ ...schema.config ? { schemaConfig: schema.config } : {},
2907
2970
  sourcePath: schemaResult.data.sourcePath,
2908
2971
  importPath
2909
2972
  }
@@ -3113,7 +3176,7 @@ async function getExternalLoaderModule() {
3113
3176
  return null;
3114
3177
  }
3115
3178
  try {
3116
- externalLoaderModule = await import('./external-loader-YUUADLAP.js');
3179
+ externalLoaderModule = await import('./external-loader-CISUEINQ.js');
3117
3180
  return externalLoaderModule;
3118
3181
  } catch {
3119
3182
  return null;
@@ -3287,6 +3350,7 @@ var UnifiedLoader = class {
3287
3350
  data: {
3288
3351
  orbital: found,
3289
3352
  orbitals: schema.orbitals,
3353
+ ...schema.config ? { schemaConfig: schema.config } : {},
3290
3354
  sourcePath: schemaResult.data.sourcePath,
3291
3355
  importPath
3292
3356
  }
@@ -3303,6 +3367,7 @@ var UnifiedLoader = class {
3303
3367
  data: {
3304
3368
  orbital: schema.orbitals[0],
3305
3369
  orbitals: schema.orbitals,
3370
+ ...schema.config ? { schemaConfig: schema.config } : {},
3306
3371
  sourcePath: schemaResult.data.sourcePath,
3307
3372
  importPath
3308
3373
  }
@@ -3637,6 +3702,232 @@ function spliceLambdaTraitRefs(traits, pages) {
3637
3702
  }
3638
3703
  }
3639
3704
 
3705
+ // src/resolver/sentinel-resolution.ts
3706
+ var PRIMITIVE_TYPE_ARG_NAMES = /* @__PURE__ */ new Set([
3707
+ "string",
3708
+ "money",
3709
+ "any",
3710
+ "icon",
3711
+ "component",
3712
+ "email",
3713
+ "url",
3714
+ "phone",
3715
+ "uuid",
3716
+ "image",
3717
+ "node",
3718
+ "json",
3719
+ "render-ui",
3720
+ "relation",
3721
+ "int",
3722
+ "float",
3723
+ "number",
3724
+ "duration",
3725
+ "bool",
3726
+ "boolean",
3727
+ "date",
3728
+ "datetime",
3729
+ "timestamp",
3730
+ "object",
3731
+ "sexpr",
3732
+ "scalar"
3733
+ ]);
3734
+ var BARE_PAYLOAD_CARRIER = "value";
3735
+ function resolveTypeArgValue(value, entitiesByName, typesByName) {
3736
+ if (PRIMITIVE_TYPE_ARG_NAMES.has(value)) {
3737
+ return { kind: "scalar", primitive: value };
3738
+ }
3739
+ const entity = entitiesByName.get(value);
3740
+ if (entity) {
3741
+ return { kind: "entity", entity };
3742
+ }
3743
+ const shape = typesByName[value];
3744
+ if (shape) {
3745
+ return { kind: "struct", shape };
3746
+ }
3747
+ return void 0;
3748
+ }
3749
+ function entityFieldToPayloadField(f) {
3750
+ if (f.type === "object" && f.items) {
3751
+ const valueType = fieldTypeTagOf(f.items);
3752
+ return {
3753
+ name: f.name ?? "",
3754
+ type: `Map<string,${valueType}>`,
3755
+ ...f.required !== void 0 ? { required: f.required } : {}
3756
+ };
3757
+ }
3758
+ let properties;
3759
+ if (f.type === "object" && f.properties) {
3760
+ properties = Object.values(f.properties).map(entityFieldToPayloadField);
3761
+ } else if (f.type === "union" && f.properties) {
3762
+ const ordered = f.values ?? Object.keys(f.properties);
3763
+ properties = ordered.map((k) => f.properties?.[k]).filter((v) => v !== void 0).map(entityFieldToPayloadField);
3764
+ } else if (f.type === "array" && f.items) {
3765
+ properties = entityFieldToPayloadField(f.items).properties;
3766
+ }
3767
+ const isArrayOfStruct = f.type === "array" && properties !== void 0;
3768
+ return {
3769
+ name: f.name ?? "",
3770
+ type: isArrayOfStruct ? "[object]" : fieldTypeTagOf(f),
3771
+ ...f.required !== void 0 ? { required: f.required } : {},
3772
+ ...properties && properties.length > 0 ? { properties } : {}
3773
+ };
3774
+ }
3775
+ function fieldTypeTagOf(f) {
3776
+ return f.type;
3777
+ }
3778
+ function entityFieldsToPayloadFields(entity) {
3779
+ return entity.fields.map(entityFieldToPayloadField);
3780
+ }
3781
+ function flattenBareEntityPayload(fields, entityDef, subs) {
3782
+ if (fields.length !== 1) return false;
3783
+ const field = fields[0];
3784
+ if (field.name !== BARE_PAYLOAD_CARRIER) return false;
3785
+ let entity;
3786
+ if (field.type === "@entity") {
3787
+ entity = entityDef;
3788
+ } else if (field.type === "object" && field.properties) {
3789
+ entity = entityDef;
3790
+ } else if (field.type.startsWith("$")) {
3791
+ const sub = subs.get(field.type.slice(1));
3792
+ entity = sub?.kind === "entity" ? sub.entity : void 0;
3793
+ }
3794
+ if (!entity) return false;
3795
+ fields.length = 0;
3796
+ fields.push(...entityFieldsToPayloadFields(entity));
3797
+ return true;
3798
+ }
3799
+ function resolveSentinelFields(fields, entityDef, subs, declaredNames) {
3800
+ let changed = false;
3801
+ for (const field of fields) {
3802
+ const isSelfRef = field.type === "@entity" || field.type === "[@entity]";
3803
+ if (isSelfRef) {
3804
+ if (entityDef) {
3805
+ const isArray = field.type.startsWith("[");
3806
+ field.type = isArray ? "[object]" : "object";
3807
+ field.properties = entityFieldsToPayloadFields(entityDef);
3808
+ field.entity = entityDef.name;
3809
+ changed = true;
3810
+ }
3811
+ continue;
3812
+ }
3813
+ const isArraySentinel = field.type.startsWith("[$") && field.type.endsWith("]");
3814
+ const isBareSentinel = !isArraySentinel && field.type.startsWith("$");
3815
+ if (isBareSentinel || isArraySentinel) {
3816
+ const paramName = isArraySentinel ? field.type.slice(2, -1) : field.type.slice(1);
3817
+ const sub = subs.get(paramName);
3818
+ if (sub) {
3819
+ switch (sub.kind) {
3820
+ case "scalar":
3821
+ field.type = isArraySentinel ? `[${sub.primitive}]` : sub.primitive;
3822
+ field.properties = void 0;
3823
+ break;
3824
+ case "entity":
3825
+ field.type = isArraySentinel ? "[object]" : "object";
3826
+ field.properties = entityFieldsToPayloadFields(sub.entity);
3827
+ field.entity = sub.entity.name;
3828
+ break;
3829
+ case "struct":
3830
+ field.type = isArraySentinel ? "[object]" : "object";
3831
+ field.properties = [...sub.shape];
3832
+ break;
3833
+ }
3834
+ changed = true;
3835
+ continue;
3836
+ }
3837
+ if (declaredNames.has(paramName)) {
3838
+ continue;
3839
+ }
3840
+ if (entityDef) {
3841
+ field.type = isArraySentinel ? "[object]" : "object";
3842
+ field.properties = entityFieldsToPayloadFields(entityDef);
3843
+ field.entity = entityDef.name;
3844
+ changed = true;
3845
+ }
3846
+ continue;
3847
+ }
3848
+ if (field.properties) {
3849
+ const mutableProps = field.properties;
3850
+ changed = resolveSentinelFields(mutableProps, entityDef, subs, declaredNames) || changed;
3851
+ }
3852
+ }
3853
+ return changed;
3854
+ }
3855
+ function resolvePayloadEntitySchema(payloadEntity, setPayloadSchema, entitiesByName) {
3856
+ if (!payloadEntity) return false;
3857
+ const entity = entitiesByName.get(payloadEntity);
3858
+ if (!entity) return false;
3859
+ setPayloadSchema(entityFieldsToPayloadFields(entity));
3860
+ return true;
3861
+ }
3862
+ function resolveTraitTypeParamSentinels(trait, entityDef, entitiesByName, typesByName, typeArgs) {
3863
+ const declared = trait.typeParams ?? [];
3864
+ const subs = /* @__PURE__ */ new Map();
3865
+ const declaredNames = /* @__PURE__ */ new Set();
3866
+ for (const p of declared) {
3867
+ declaredNames.add(p.name);
3868
+ const argValue = typeArgs?.[p.name];
3869
+ let sub;
3870
+ if (argValue !== void 0) {
3871
+ sub = resolveTypeArgValue(argValue, entitiesByName, typesByName);
3872
+ } else if (p.kind === "Entity" && entityDef) {
3873
+ sub = { kind: "entity", entity: entityDef };
3874
+ } else if (p.default) {
3875
+ sub = resolveTypeArgValue(p.default, entitiesByName, typesByName);
3876
+ }
3877
+ if (sub) subs.set(p.name, sub);
3878
+ }
3879
+ let changed = false;
3880
+ for (const emit of trait.emits ?? []) {
3881
+ if (!emit.payloadSchema) continue;
3882
+ if (resolvePayloadEntitySchema(
3883
+ emit.payloadEntity,
3884
+ (schema2) => {
3885
+ emit.payloadSchema = schema2;
3886
+ },
3887
+ entitiesByName
3888
+ )) {
3889
+ changed = true;
3890
+ continue;
3891
+ }
3892
+ const schema = emit.payloadSchema;
3893
+ if (flattenBareEntityPayload(schema, entityDef, subs)) {
3894
+ changed = true;
3895
+ } else {
3896
+ changed = resolveSentinelFields(schema, entityDef, subs, declaredNames) || changed;
3897
+ }
3898
+ }
3899
+ for (const ev of trait.stateMachine?.events ?? []) {
3900
+ if (!ev.payloadSchema) continue;
3901
+ if (resolvePayloadEntitySchema(
3902
+ ev.payloadEntity,
3903
+ (schema2) => {
3904
+ ev.payloadSchema = schema2;
3905
+ },
3906
+ entitiesByName
3907
+ )) {
3908
+ changed = true;
3909
+ continue;
3910
+ }
3911
+ const schema = ev.payloadSchema;
3912
+ if (flattenBareEntityPayload(schema, entityDef, subs)) {
3913
+ changed = true;
3914
+ } else {
3915
+ changed = resolveSentinelFields(schema, entityDef, subs, declaredNames) || changed;
3916
+ }
3917
+ }
3918
+ return changed;
3919
+ }
3920
+ function resolveOrbitalTypeParamSentinels(traits, primaryEntity, auxiliaryEntities, orbitalTypes) {
3921
+ const entitiesByName = /* @__PURE__ */ new Map();
3922
+ entitiesByName.set(primaryEntity.name, primaryEntity);
3923
+ for (const e of auxiliaryEntities) entitiesByName.set(e.name, e);
3924
+ const typesByName = orbitalTypes ?? {};
3925
+ for (const rt of traits) {
3926
+ const entityDef = rt.trait.linkedEntity ? entitiesByName.get(rt.trait.linkedEntity) : void 0;
3927
+ resolveTraitTypeParamSentinels(rt.trait, entityDef, entitiesByName, typesByName, rt.typeArgs);
3928
+ }
3929
+ }
3930
+
3640
3931
  // src/resolver/reference-resolver.ts
3641
3932
  var refResolverLog = createLogger("almadar:runtime:ref-resolver");
3642
3933
  function indexOrbitalNodes(orbital, idIndex) {
@@ -3910,6 +4201,25 @@ function renameTraitEmbedsInValue(node, subs) {
3910
4201
  }
3911
4202
  return next;
3912
4203
  }
4204
+ function renameEntityNameTokensInValue(node, entitySubs) {
4205
+ if (node === null || node === void 0) return node;
4206
+ if (typeof node === "string") {
4207
+ if (!node.startsWith("@")) return node;
4208
+ const rest = node.slice(1);
4209
+ const dot = rest.search(/[.[]/);
4210
+ const name = dot === -1 ? rest : rest.slice(0, dot);
4211
+ const suffix = dot === -1 ? "" : rest.slice(dot);
4212
+ const to = entitySubs.get(name);
4213
+ return to === void 0 ? node : `@${to}${suffix}`;
4214
+ }
4215
+ if (Array.isArray(node)) return node.map((item) => renameEntityNameTokensInValue(item, entitySubs));
4216
+ if (typeof node !== "object") return node;
4217
+ const next = {};
4218
+ for (const [key, value] of Object.entries(node)) {
4219
+ next[key] = renameEntityNameTokensInValue(value, entitySubs);
4220
+ }
4221
+ return next;
4222
+ }
3913
4223
  function renameTraitEmbeds(trait, subs) {
3914
4224
  if (subs.size === 0) return trait;
3915
4225
  const sm = trait.stateMachine;
@@ -3956,6 +4266,36 @@ function findTraitEntryInOrbital(orbital, localName) {
3956
4266
  }
3957
4267
  return null;
3958
4268
  }
4269
+ function homeOrbitalConfigForTrait(imported, traitName) {
4270
+ for (const o of importedOrbitals(imported)) {
4271
+ if (findTraitEntryInOrbital(o, traitName)) return o.config;
4272
+ }
4273
+ return void 0;
4274
+ }
4275
+ function findPageEntryInOrbital(orbital, localName) {
4276
+ for (const pageRef of orbital.pages ?? []) {
4277
+ if (typeof pageRef === "string") continue;
4278
+ if (!("ref" in pageRef)) {
4279
+ if (pageRef.name === localName) return pageRef;
4280
+ continue;
4281
+ }
4282
+ const refObj = pageRef;
4283
+ if (parsePageRef(refObj.ref)?.pageName === localName) return refObj;
4284
+ }
4285
+ return null;
4286
+ }
4287
+ function toPageTraitRef(traitRef) {
4288
+ if (typeof traitRef === "string") return { ref: traitRef };
4289
+ if ("stateMachine" in traitRef) return { ref: traitRef.name };
4290
+ const refObj = traitRef;
4291
+ return {
4292
+ ref: refObj.name ?? refObj.ref,
4293
+ ...refObj.refId !== void 0 ? { refId: refObj.refId } : {},
4294
+ ...refObj.linkedEntity !== void 0 ? { linkedEntity: refObj.linkedEntity } : {},
4295
+ ...refObj.linkedEntityId !== void 0 ? { linkedEntityId: refObj.linkedEntityId } : {},
4296
+ ...refObj.config !== void 0 ? { config: refObj.config } : {}
4297
+ };
4298
+ }
3959
4299
  function traitEmbedNamesOf(trait) {
3960
4300
  const found = /* @__PURE__ */ new Set();
3961
4301
  const walk = (node) => {
@@ -3975,34 +4315,183 @@ function traitEmbedNamesOf(trait) {
3975
4315
  if (typeof node !== "object") return;
3976
4316
  for (const value of Object.values(node)) walk(value);
3977
4317
  };
3978
- for (const t of trait.stateMachine?.transitions ?? []) walk(t.effects);
3979
- for (const tick of trait.ticks ?? []) walk(tick.effects);
4318
+ for (const t of trait.stateMachine?.transitions ?? []) {
4319
+ walk(t.guard);
4320
+ walk(t.effects);
4321
+ }
4322
+ for (const tick of trait.ticks ?? []) {
4323
+ walk(tick.guard);
4324
+ walk(tick.effects);
4325
+ }
3980
4326
  for (const field of Object.values(trait.config ?? {})) walk(field.default);
3981
- return [...found];
4327
+ return [...found].sort();
3982
4328
  }
3983
- function resolveForwardedSiblingConfig(trait, parent) {
4329
+ function resolveForwardedSiblingConfigFrom(trait, parentChain, orbitalConfig, schemaConfig) {
3984
4330
  const declared = trait.config;
3985
- const parentDeclared = parent?.config;
3986
- if (!declared || !parentDeclared) return trait;
4331
+ if (!declared) return trait;
4332
+ const next = resolveConfigForwards(declared, parentChain, orbitalConfig, void 0, void 0, schemaConfig);
4333
+ return next ? { ...trait, config: next } : trait;
4334
+ }
4335
+ function callSiteRungValue(rungConfig, knob) {
4336
+ const entry = rungConfig[knob];
4337
+ if (entry === void 0) return void 0;
4338
+ return isCallSiteConfigDeclaration(entry) ? entry.default : entry;
4339
+ }
4340
+ function walkConfigForwardChain(forward, parentChain, orbitalConfig, upstreamOrbitalConfig, upstreamSchemaConfig, schemaConfig) {
4341
+ let knob = forward.slice("@config.".length);
4342
+ if (knob.length === 0 || knob.includes(".")) return void 0;
4343
+ let value;
4344
+ let currentForward = forward;
4345
+ for (const rungConfig of parentChain) {
4346
+ const rungValue = callSiteRungValue(rungConfig, knob);
4347
+ if (rungValue === void 0 || rungValue === currentForward) continue;
4348
+ if (typeof rungValue === "string" && rungValue.startsWith("@config.")) {
4349
+ const nextKnob = rungValue.slice("@config.".length);
4350
+ if (nextKnob.length === 0 || nextKnob.includes(".") || nextKnob === knob) continue;
4351
+ knob = nextKnob;
4352
+ currentForward = rungValue;
4353
+ continue;
4354
+ }
4355
+ value = rungValue;
4356
+ break;
4357
+ }
4358
+ if (value === void 0 || value === currentForward) value = orbitalConfig?.[knob]?.default;
4359
+ if (value === void 0 || value === currentForward) value = upstreamOrbitalConfig?.[knob]?.default;
4360
+ if (value === void 0 || value === currentForward) value = upstreamSchemaConfig?.[knob]?.default;
4361
+ if (value === void 0 || value === currentForward) value = schemaConfig?.[knob]?.default;
4362
+ if (value === void 0 || value === currentForward) return void 0;
4363
+ return value;
4364
+ }
4365
+ function resolveConfigForwards(declared, parentChain, orbitalConfig, upstreamOrbitalConfig, upstreamSchemaConfig, schemaConfig) {
3987
4366
  let next;
3988
4367
  for (const [key, field] of Object.entries(declared)) {
3989
4368
  const forward = field.default;
3990
4369
  if (typeof forward !== "string" || !forward.startsWith("@config.")) continue;
3991
- const knob = forward.slice("@config.".length);
3992
- if (knob.length === 0 || knob.includes(".")) continue;
3993
- const value = parentDeclared[knob]?.default;
3994
- if (value === void 0 || value === forward) continue;
4370
+ const value = walkConfigForwardChain(
4371
+ forward,
4372
+ parentChain,
4373
+ orbitalConfig,
4374
+ upstreamOrbitalConfig,
4375
+ upstreamSchemaConfig,
4376
+ schemaConfig
4377
+ );
4378
+ if (value === void 0) continue;
3995
4379
  next ??= { ...declared };
3996
- next[key] = { ...field, default: value };
4380
+ next[key] = { ...field, default: value, forwardedFrom: forward };
3997
4381
  }
3998
- return next ? { ...trait, config: next } : trait;
4382
+ return next;
4383
+ }
4384
+ function resolveCallSiteConfigForwards(config, parentChain, orbitalConfig, schemaConfig) {
4385
+ let next;
4386
+ for (const [key, entry] of Object.entries(config)) {
4387
+ const forward = isCallSiteConfigDeclaration(entry) ? entry.default : entry;
4388
+ if (typeof forward !== "string" || !forward.startsWith("@config.")) continue;
4389
+ const value = walkConfigForwardChain(forward, parentChain, orbitalConfig, void 0, void 0, schemaConfig);
4390
+ if (value === void 0) continue;
4391
+ next ??= { ...config };
4392
+ next[key] = isCallSiteConfigDeclaration(entry) ? { ...entry, default: value, forwardedFrom: forward } : value;
4393
+ }
4394
+ return next;
4395
+ }
4396
+ function traitRefEmbedNamesOf(traitRef) {
4397
+ if (typeof traitRef === "string") return [];
4398
+ return traitEmbedNamesOf(traitRef);
4399
+ }
4400
+ function traitRefLocalName(traitRef) {
4401
+ if (typeof traitRef === "string") {
4402
+ return parseImportedTraitRef(traitRef)?.traitName ?? traitRef;
4403
+ }
4404
+ if ("stateMachine" in traitRef) return traitRef.name;
4405
+ const refObj = traitRef;
4406
+ return refObj.name ?? parseImportedTraitRef(refObj.ref)?.traitName ?? refObj.ref;
4407
+ }
4408
+ function traitRefConfigOf(traitRef) {
4409
+ if (typeof traitRef === "string") return void 0;
4410
+ return traitRef.config;
4411
+ }
4412
+ function buildEmbedGraph(traitRefs) {
4413
+ const out = /* @__PURE__ */ new Map();
4414
+ for (const traitRef of traitRefs) {
4415
+ const referrerName = traitRefLocalName(traitRef);
4416
+ if (!referrerName) continue;
4417
+ for (const child of traitRefEmbedNamesOf(traitRef)) {
4418
+ if (child === referrerName) continue;
4419
+ if (!out.has(child)) out.set(child, referrerName);
4420
+ }
4421
+ }
4422
+ return out;
3999
4423
  }
4000
- function applyLinkedEntityRename(trait, linkedEntity) {
4424
+ function embedderChain(localName, traitRefs, graph) {
4425
+ const chain = [];
4426
+ const visited = /* @__PURE__ */ new Set([localName]);
4427
+ let cur = graph.get(localName);
4428
+ let hops = 0;
4429
+ while (cur !== void 0 && !visited.has(cur) && hops < traitRefs.length) {
4430
+ visited.add(cur);
4431
+ hops++;
4432
+ const entry = traitRefs.find((t) => traitRefLocalName(t) === cur);
4433
+ const entryConfig = entry ? traitRefConfigOf(entry) : void 0;
4434
+ if (entryConfig) chain.push(entryConfig);
4435
+ cur = graph.get(cur);
4436
+ }
4437
+ return chain;
4438
+ }
4439
+ function resolveEmbedderConfigForward(config, localName, embedCtx, schemaConfig) {
4440
+ const chain = embedderChain(localName, embedCtx.traitRefs, embedCtx.embedGraph);
4441
+ const next = resolveCallSiteConfigForwards(config, chain, embedCtx.orbitalConfig, schemaConfig);
4442
+ return next ? next : config;
4443
+ }
4444
+ function consumerKnownEntityRebindSubs(trait, entityIds) {
4445
+ const out = /* @__PURE__ */ new Map();
4446
+ const refs = trait.entityRefIds;
4447
+ if (!refs) return out;
4448
+ const idToConsumerName = /* @__PURE__ */ new Map();
4449
+ for (const [name, id] of entityIds) {
4450
+ if (!idToConsumerName.has(id)) idToConsumerName.set(id, name);
4451
+ }
4452
+ for (const [tokenName, entityId] of Object.entries(refs)) {
4453
+ const consumerName = idToConsumerName.get(entityId);
4454
+ if (consumerName !== void 0 && consumerName !== tokenName) {
4455
+ out.set(tokenName, consumerName);
4456
+ }
4457
+ }
4458
+ return out;
4459
+ }
4460
+ function staleEntityRebindSubs(trait, newEntity) {
4461
+ const out = /* @__PURE__ */ new Map();
4462
+ const boundId = trait.linkedEntityId;
4463
+ const refs = trait.entityRefIds;
4464
+ if (boundId && refs) {
4465
+ for (const [tokenName, entityId] of Object.entries(refs)) {
4466
+ if (entityId === boundId) out.set(tokenName, newEntity);
4467
+ }
4468
+ }
4469
+ return out;
4470
+ }
4471
+ function applyLinkedEntityRename(trait, linkedEntity, entityIds) {
4001
4472
  const atomLinked = trait.linkedEntity;
4002
- if (!linkedEntity || !atomLinked || linkedEntity === atomLinked) return trait;
4003
- const sm = trait.stateMachine;
4004
- if (!sm) return { ...trait, linkedEntity };
4473
+ const entitySubs = consumerKnownEntityRebindSubs(trait, entityIds);
4474
+ if (!linkedEntity || !atomLinked || linkedEntity === atomLinked) {
4475
+ return rewriteEntityTypedConfigValues(rewriteEntityRefIds(trait, entitySubs, entityIds), entitySubs, entityIds);
4476
+ }
4477
+ for (const [from, to] of staleEntityRebindSubs(trait, linkedEntity)) {
4478
+ entitySubs.set(from, to);
4479
+ }
4480
+ entitySubs.set(atomLinked, linkedEntity);
4005
4481
  const rename = (name) => name === atomLinked ? linkedEntity : void 0;
4482
+ const sm = trait.stateMachine;
4483
+ const rebound = {
4484
+ ...trait,
4485
+ linkedEntity,
4486
+ linkedEntityId: entityIds.get(linkedEntity)
4487
+ };
4488
+ if (!sm) {
4489
+ return rewriteEntityTypedConfigValues(
4490
+ renamePayloadEntityMarkers(rewriteEntityRefIds(rebound, entitySubs, entityIds), rename),
4491
+ entitySubs,
4492
+ entityIds
4493
+ );
4494
+ }
4006
4495
  const nextTransitions = (sm.transitions ?? []).map((t) => {
4007
4496
  const nextEffects = t.effects ? renameEntityInEffects(
4008
4497
  t.effects,
@@ -4017,11 +4506,18 @@ function applyLinkedEntityRename(trait, linkedEntity) {
4017
4506
  to: linkedEntity,
4018
4507
  transitionCount: nextTransitions.length
4019
4508
  });
4020
- return {
4021
- ...trait,
4022
- linkedEntity,
4023
- stateMachine: { ...sm, transitions: nextTransitions }
4024
- };
4509
+ return rewriteEntityTypedConfigValues(
4510
+ renamePayloadEntityMarkers(
4511
+ rewriteEntityRefIds(
4512
+ { ...rebound, stateMachine: { ...sm, transitions: nextTransitions } },
4513
+ entitySubs,
4514
+ entityIds
4515
+ ),
4516
+ rename
4517
+ ),
4518
+ entitySubs,
4519
+ entityIds
4520
+ );
4025
4521
  }
4026
4522
  function resolveEntityTokensById(trait, idIndex) {
4027
4523
  const map = trait.entityRefIds;
@@ -4105,7 +4601,7 @@ function resolveConfigRefsById(trait, idIndex) {
4105
4601
  });
4106
4602
  return { ...trait, config: nextSchema };
4107
4603
  }
4108
- function applyEventRenames(trait, renames) {
4604
+ function applyEventRenames(trait, renames, keptFinalNames) {
4109
4605
  if (!renames || Object.keys(renames).length === 0) return trait;
4110
4606
  const rename = (k) => k !== void 0 && k in renames ? renames[k] : k;
4111
4607
  const sm = trait.stateMachine;
@@ -4135,7 +4631,9 @@ function applyEventRenames(trait, renames) {
4135
4631
  );
4136
4632
  const nextListens = (trait.listens ?? []).map((l) => {
4137
4633
  const sourced = l.source !== void 0 && l.source.kind !== "any";
4138
- const nextEvent = sourced ? l.event : rename(l.event) ?? l.event;
4634
+ const sourceTraitName = l.source && l.source.kind !== "any" ? l.source.trait : void 0;
4635
+ const fromThisImport = sourceTraitName !== void 0 && keptFinalNames !== void 0 && keptFinalNames.has(sourceTraitName);
4636
+ const nextEvent = sourced && !fromThisImport ? l.event : rename(l.event) ?? l.event;
4139
4637
  const nextTriggers = rename(l.triggers) ?? l.triggers;
4140
4638
  return nextEvent === l.event && nextTriggers === l.triggers ? l : { ...l, event: nextEvent, triggers: nextTriggers };
4141
4639
  });
@@ -4170,17 +4668,44 @@ function applyEventRenamesToCallSiteConfig(config, declared, renames) {
4170
4668
  }
4171
4669
  return touched ? next : config;
4172
4670
  }
4671
+ function resolvedKnobValues(before, after, knobs) {
4672
+ const out = /* @__PURE__ */ new Map();
4673
+ if (knobs.length === 0) return out;
4674
+ const knobSet = new Set(knobs);
4675
+ const beforeEmits = before.emits ?? [];
4676
+ const afterEmits = after.emits ?? [];
4677
+ for (let i = 0; i < beforeEmits.length; i++) {
4678
+ const knob = configRefEventKnob(beforeEmits[i].event);
4679
+ if (knob !== void 0 && knobSet.has(knob)) out.set(knob, afterEmits[i].event);
4680
+ }
4681
+ return out;
4682
+ }
4683
+ function foldEventRenameOntoDeclaredKnobs(trait, resolved, eventRenames) {
4684
+ if (!eventRenames || resolved.size === 0 || !trait.config) return trait;
4685
+ let nextConfig;
4686
+ for (const [knob, resolvedValue] of resolved) {
4687
+ const renamed = eventRenames[resolvedValue];
4688
+ if (renamed === void 0 || renamed === resolvedValue) continue;
4689
+ const field = trait.config[knob];
4690
+ if (!field) continue;
4691
+ nextConfig ??= { ...trait.config };
4692
+ nextConfig[knob] = { ...field, default: renamed };
4693
+ }
4694
+ return nextConfig ? { ...trait, config: nextConfig } : trait;
4695
+ }
4173
4696
  function resolveConfigRefEmitNames(trait, callSiteConfig) {
4174
4697
  const emits = trait.emits ?? [];
4175
4698
  const hasRef = emits.some((em) => configRefEventKnob(em.event) !== void 0);
4176
- if (!hasRef) return { trait, errors: [] };
4699
+ if (!hasRef) return { trait, errors: [], resolvedKnobs: [] };
4177
4700
  const effectiveConfig = {
4178
4701
  ...normalizeCallSiteConfigToValues(trait.config) ?? {},
4179
4702
  ...normalizeCallSiteConfigToValues(callSiteConfig) ?? {}
4180
4703
  };
4181
4704
  const errors = [];
4705
+ const resolvedTriples = [];
4182
4706
  const nextEmits = emits.map((em) => {
4183
- if (configRefEventKnob(em.event) === void 0) return em;
4707
+ const knob = configRefEventKnob(em.event);
4708
+ if (knob === void 0) return em;
4184
4709
  const result = resolveConfigRefEventName(em.event, trait.config, effectiveConfig);
4185
4710
  if (!result.ok) {
4186
4711
  errors.push(
@@ -4193,117 +4718,1316 @@ function resolveConfigRefEmitNames(trait, callSiteConfig) {
4193
4718
  ref: em.event,
4194
4719
  resolved: result.value
4195
4720
  });
4721
+ resolvedTriples.push({ knob, from: em.event, to: result.value });
4196
4722
  return { ...em, event: result.value };
4197
4723
  });
4198
- return { trait: { ...trait, emits: nextEmits }, errors };
4724
+ const sm = trait.stateMachine;
4725
+ const nextEvents = resolvedTriples.length > 0 && sm ? sm.events.map((ev) => {
4726
+ const hit = resolvedTriples.find((t) => t.from === ev.key);
4727
+ return hit ? { ...ev, key: hit.to } : ev;
4728
+ }) : sm?.events;
4729
+ return {
4730
+ trait: {
4731
+ ...trait,
4732
+ emits: nextEmits,
4733
+ ...sm && nextEvents !== sm.events ? { stateMachine: { ...sm, events: nextEvents } } : {}
4734
+ },
4735
+ errors,
4736
+ resolvedKnobs: resolvedTriples.map((t) => t.knob)
4737
+ };
4199
4738
  }
4200
- var ReferenceResolver = class {
4201
- loader;
4202
- options;
4203
- localTraits;
4204
- /** id-keyed mirror of `localTraits`, populated wherever the trait carries an `id`. */
4205
- localTraitsById = /* @__PURE__ */ new Map();
4206
- /** Import scope of each loaded source orbital, keyed by its source path. */
4207
- sourceImportsCache = /* @__PURE__ */ new Map();
4208
- loaderInitialized = false;
4209
- constructor(options) {
4210
- this.options = options;
4211
- this.loader = options.loader;
4212
- this.localTraits = options.localTraits ?? /* @__PURE__ */ new Map();
4213
- for (const trait of this.localTraits.values()) {
4214
- if (trait.id) {
4215
- this.localTraitsById.set(trait.id, trait);
4216
- }
4739
+ function foldCallSiteConfigOntoTrait(trait, callSiteConfig) {
4740
+ if (!callSiteConfig) return trait;
4741
+ const declared = trait.config;
4742
+ const overrideValues = {};
4743
+ const overriddenKeys = /* @__PURE__ */ new Set();
4744
+ const newDeclarations = {};
4745
+ for (const [key, entry] of Object.entries(callSiteConfig)) {
4746
+ const isDecl = isCallSiteConfigDeclaration(entry);
4747
+ const value = isDecl ? entry.default : entry;
4748
+ if (declared && key in declared) {
4749
+ if (value !== void 0) {
4750
+ overrideValues[key] = value;
4751
+ overriddenKeys.add(key);
4752
+ }
4753
+ } else if (isDecl) {
4754
+ newDeclarations[key] = entry;
4755
+ }
4756
+ }
4757
+ if (overriddenKeys.size === 0 && Object.keys(newDeclarations).length === 0) {
4758
+ return trait;
4759
+ }
4760
+ let nextConfig = overrideDeclaredKnobs(declared ?? {}, overrideValues);
4761
+ if (overriddenKeys.size > 0) {
4762
+ const patched = { ...nextConfig };
4763
+ for (const key of overriddenKeys) {
4764
+ const field = patched[key];
4765
+ if (!field) continue;
4766
+ const entry = callSiteConfig[key];
4767
+ const entryDecl = isCallSiteConfigDeclaration(entry) ? entry : void 0;
4768
+ patched[key] = {
4769
+ ...field,
4770
+ forwardedFrom: entryDecl?.forwardedFrom,
4771
+ // The atom's OWN `refId` (a reference-config field's declared
4772
+ // default names a SPECIFIC node by id) describes the ATOM's OWN
4773
+ // `default`, not whatever this override just replaced it with —
4774
+ // carrying it forward unchanged left a STALE id bound to the NEW
4775
+ // literal string, so the id-index's "current name" correction
4776
+ // (`resolveConfigRefsById`) silently rewrote the override BACK to
4777
+ // the atom's own default target — found via std-notes'
4778
+ // `NoteGlobalSearch`: `idleContent`'s override says `@trait.
4779
+ // NoteCatalog` but the atom's OWN stale `refId` (still pointing at
4780
+ // `AppSearchIdleHint`, the atom's default) rewrote the sibling-pull
4781
+ // target back to it (rung 2: an override with no id of its own
4782
+ // names no id, so it must clear the atom's). An override that
4783
+ // carries ITS OWN `refId` (an annotated, id-aware override) wins
4784
+ // instead — same precedence a `default` override already has.
4785
+ refId: entryDecl?.refId,
4786
+ ...entryDecl?.label !== void 0 ? { label: entryDecl.label } : {},
4787
+ ...entryDecl?.description !== void 0 ? { description: entryDecl.description } : {},
4788
+ ...entryDecl?.synonyms !== void 0 ? { synonyms: entryDecl.synonyms } : {},
4789
+ ...entryDecl?.tier !== void 0 ? { tier: entryDecl.tier } : {}
4790
+ };
4217
4791
  }
4792
+ nextConfig = patched;
4218
4793
  }
4219
- async ensureLoader() {
4220
- if (this.loader || this.loaderInitialized) return;
4221
- this.loaderInitialized = true;
4222
- try {
4223
- const { ExternalOrbitalLoader } = await import('./external-loader-YUUADLAP.js');
4224
- this.loader = new ExternalOrbitalLoader(this.options);
4225
- } catch {
4226
- }
4794
+ if (Object.keys(newDeclarations).length > 0) {
4795
+ nextConfig = { ...nextConfig, ...newDeclarations };
4227
4796
  }
4228
- /**
4229
- * Resolve all references in an orbital.
4230
- */
4231
- async resolve(orbital, sourcePath, chain) {
4232
- const errors = [];
4233
- const warnings = [];
4234
- const importChain = chain ?? { push: () => null, pop: () => {
4235
- }, clone() {
4236
- return this;
4237
- } };
4238
- const traitsList = orbital.traits ?? [];
4239
- const alreadyResolved = traitsList.length > 0 && traitsList.every((t) => isInlineTrait(t));
4240
- const importsResult = alreadyResolved ? { success: true, data: { orbitals: /* @__PURE__ */ new Map(), idIndex: /* @__PURE__ */ new Map() }} : await this.resolveImports(orbital.uses ?? [], sourcePath, importChain);
4241
- if (!importsResult.success) {
4242
- return { success: false, errors: importsResult.errors };
4243
- }
4244
- const imports = importsResult.data;
4245
- imports.idIndex = buildIdIndex(orbital, imports.orbitals);
4246
- const entityResult = this.resolveEntity(orbital.entity, imports);
4247
- if (!entityResult.success) {
4248
- errors.push(...entityResult.errors);
4249
- }
4250
- const traitsResult = this.resolveTraits(orbital.traits, imports);
4251
- if (!traitsResult.success) {
4252
- errors.push(...traitsResult.errors);
4253
- }
4254
- const pagesResult = this.resolvePages(orbital.pages, imports);
4255
- if (!pagesResult.success) {
4256
- errors.push(...pagesResult.errors);
4257
- }
4258
- if (errors.length > 0) {
4259
- return { success: false, errors };
4260
- }
4261
- if (!entityResult.success || !traitsResult.success || !pagesResult.success) {
4262
- return { success: false, errors: ["Internal error: unexpected failure state"] };
4263
- }
4264
- const pullErrors = await this.pullSiblingTraits(traitsResult.data, imports, importChain);
4265
- if (pullErrors.length > 0) {
4266
- return { success: false, errors: pullErrors };
4267
- }
4268
- for (const resolvedTrait of traitsResult.data) {
4269
- resolvedTrait.trait = resolveEntityTokensById(resolvedTrait.trait, imports.idIndex);
4270
- resolvedTrait.trait = resolveConfigRefsById(resolvedTrait.trait, imports.idIndex);
4797
+ return { ...trait, config: nextConfig };
4798
+ }
4799
+ var ROW_ALIAS_TOKEN_PREFIXES = ["@entity.", "@item.", "@row."];
4800
+ var ROW_ALIAS_ROOTS = /* @__PURE__ */ new Set(["@entity", "@item", "@row"]);
4801
+ var FIELD_NAME_MEMBER_KEYS = ["key", "name", "field"];
4802
+ function rewriteEntityFieldTokensInValue(node, subs) {
4803
+ if (node === null || node === void 0) return node;
4804
+ if (typeof node === "string") {
4805
+ for (const prefix of ROW_ALIAS_TOKEN_PREFIXES) {
4806
+ if (!node.startsWith(prefix)) continue;
4807
+ const rest = node.slice(prefix.length);
4808
+ const dot = rest.search(/[.[]/);
4809
+ const name = dot === -1 ? rest : rest.slice(0, dot);
4810
+ const suffix = dot === -1 ? "" : rest.slice(dot);
4811
+ const to = subs.get(name);
4812
+ return to === void 0 ? node : `${prefix}${to}${suffix}`;
4271
4813
  }
4272
- try {
4273
- spliceLambdaTraitRefs(traitsResult.data, pagesResult.data);
4274
- } catch (e) {
4275
- if (e instanceof LambdaSpliceError) {
4276
- return { success: false, errors: [e.message] };
4814
+ return node;
4815
+ }
4816
+ if (Array.isArray(node)) {
4817
+ if (node.length >= 3 && node[0] === "object/get" && typeof node[1] === "string" && ROW_ALIAS_ROOTS.has(node[1]) && typeof node[2] === "string") {
4818
+ const to = subs.get(node[2]);
4819
+ if (to !== void 0) {
4820
+ const rewritten = node.map((item) => rewriteEntityFieldTokensInValue(item, subs));
4821
+ rewritten[2] = to;
4822
+ return rewritten;
4277
4823
  }
4278
- throw e;
4279
4824
  }
4280
- return {
4281
- success: true,
4282
- data: {
4283
- name: orbital.name,
4284
- entity: entityResult.data.entity,
4285
- entitySource: entityResult.data.source,
4286
- traits: traitsResult.data,
4287
- pages: pagesResult.data,
4288
- imports,
4289
- original: orbital
4290
- },
4291
- warnings
4292
- };
4825
+ return node.map((item) => rewriteEntityFieldTokensInValue(item, subs));
4293
4826
  }
4294
- /**
4295
- * Resolve `uses` declarations to loaded orbitals.
4296
- */
4297
- async resolveImports(uses, sourcePath, chain) {
4298
- const errors = [];
4299
- const orbitals = /* @__PURE__ */ new Map();
4300
- if (this.options.skipExternalLoading) {
4827
+ if (typeof node !== "object") return node;
4828
+ const next = {};
4829
+ for (const [key, value] of Object.entries(node)) {
4830
+ if (FIELD_NAME_MEMBER_KEYS.includes(key) && typeof value === "string") {
4831
+ const to = subs.get(value);
4832
+ next[key] = to === void 0 ? value : to;
4833
+ continue;
4834
+ }
4835
+ next[key] = rewriteEntityFieldTokensInValue(value, subs);
4836
+ }
4837
+ return next;
4838
+ }
4839
+ function rewriteBareFieldNameConfigDefault(value, fieldSubs) {
4840
+ if (typeof value === "string") {
4841
+ if (value === "" || value.startsWith("@")) return value;
4842
+ return fieldSubs.get(value) ?? value;
4843
+ }
4844
+ if (Array.isArray(value) && value.every((v) => typeof v === "string")) {
4845
+ return value.map((v) => v === "" || v.startsWith("@") ? v : fieldSubs.get(v) ?? v);
4846
+ }
4847
+ return value;
4848
+ }
4849
+ function rewriteEntityFieldsInConfig(config, fieldSubs) {
4850
+ if (fieldSubs.size === 0 || !config) return config;
4851
+ const rewrite = (v) => rewriteEntityFieldTokensInValue(v, fieldSubs);
4852
+ const nextConfig = {};
4853
+ for (const [key, field] of Object.entries(config)) {
4854
+ if (field.default === void 0) {
4855
+ nextConfig[key] = field;
4856
+ continue;
4857
+ }
4858
+ const afterSigils = rewrite(field.default);
4859
+ nextConfig[key] = {
4860
+ ...field,
4861
+ default: rewriteBareFieldNameConfigDefault(afterSigils, fieldSubs)
4862
+ };
4863
+ }
4864
+ return nextConfig;
4865
+ }
4866
+ function rewriteEntityFieldsInTrait(trait, fieldSubs) {
4867
+ if (fieldSubs.size === 0) return trait;
4868
+ const rewrite = (v) => rewriteEntityFieldTokensInValue(v, fieldSubs);
4869
+ const next = { ...trait };
4870
+ const sm = trait.stateMachine;
4871
+ if (sm) {
4872
+ next.stateMachine = {
4873
+ ...sm,
4874
+ transitions: (sm.transitions ?? []).map((t) => ({
4875
+ ...t,
4876
+ ...t.guard !== void 0 ? { guard: rewrite(t.guard) } : {},
4877
+ ...t.effects ? { effects: rewrite(t.effects) } : {}
4878
+ }))
4879
+ };
4880
+ }
4881
+ if (trait.ticks) {
4882
+ next.ticks = trait.ticks.map((tick) => ({
4883
+ ...tick,
4884
+ ...tick.guard !== void 0 ? { guard: rewrite(tick.guard) } : {},
4885
+ effects: rewrite(tick.effects)
4886
+ }));
4887
+ }
4888
+ if (trait.listens) {
4889
+ next.listens = trait.listens.map((l) => ({
4890
+ ...l,
4891
+ ...l.guard !== void 0 ? { guard: rewrite(l.guard) } : {},
4892
+ ...l.payloadMapping ? { payloadMapping: rewrite(l.payloadMapping) } : {}
4893
+ }));
4894
+ }
4895
+ if (trait.initialEffects) {
4896
+ next.initialEffects = rewrite(trait.initialEffects);
4897
+ }
4898
+ if (trait.config) {
4899
+ next.config = rewriteEntityFieldsInConfig(trait.config, fieldSubs);
4900
+ }
4901
+ return next;
4902
+ }
4903
+ function rewriteEntityFieldsInEntity(entity, fieldSubs) {
4904
+ if (fieldSubs.size === 0) return entity;
4905
+ const rewrite = (v) => rewriteEntityFieldTokensInValue(v, fieldSubs);
4906
+ return {
4907
+ ...entity,
4908
+ fields: entity.fields.map((f) => f.name && fieldSubs.has(f.name) ? { ...f, name: fieldSubs.get(f.name) } : f),
4909
+ ...entity.read_policy !== void 0 ? { read_policy: rewrite(entity.read_policy) } : {},
4910
+ ...entity.create_policy !== void 0 ? { create_policy: rewrite(entity.create_policy) } : {},
4911
+ ...entity.update_policy !== void 0 ? { update_policy: rewrite(entity.update_policy) } : {},
4912
+ ...entity.delete_policy !== void 0 ? { delete_policy: rewrite(entity.delete_policy) } : {}
4913
+ };
4914
+ }
4915
+ var USER_FIELD_PREFIX = "@user.";
4916
+ function directUserField(node) {
4917
+ if (typeof node !== "string" || !node.startsWith(USER_FIELD_PREFIX)) return void 0;
4918
+ const rest = node.slice(USER_FIELD_PREFIX.length);
4919
+ return rest.length > 0 && !/[.[]/.test(rest) ? rest : void 0;
4920
+ }
4921
+ var EQUALITY_OPS = /* @__PURE__ */ new Set(["=", "==", "!=", "!==", "eq", "neq"]);
4922
+ var NEGATED_EQUALITY_OPS = /* @__PURE__ */ new Set(["!=", "!==", "neq"]);
4923
+ function literalHaystackMembers(items) {
4924
+ const isListCall = items[0] === "list";
4925
+ const members = isListCall ? items.slice(1) : items;
4926
+ return members.every((v) => typeof v === "string") ? [...members] : void 0;
4927
+ }
4928
+ function rewriteRoleLiteralsInValue(node, roleFields, roles) {
4929
+ if (node === null || node === void 0) return node;
4930
+ if (Array.isArray(node)) {
4931
+ const head = node[0];
4932
+ if (typeof head === "string" && EQUALITY_OPS.has(head) && node.length === 3) {
4933
+ const [, left, right] = node;
4934
+ const leftField = directUserField(left);
4935
+ const rightField = directUserField(right);
4936
+ const userField = leftField !== void 0 && rightField === void 0 ? leftField : rightField !== void 0 && leftField === void 0 ? rightField : void 0;
4937
+ if (userField !== void 0 && roleFields.has(userField)) {
4938
+ const literalSide = leftField !== void 0 ? right : left;
4939
+ if (typeof literalSide === "string" && literalSide in roles) {
4940
+ const targets = roles[literalSide];
4941
+ if (targets.length === 1) {
4942
+ return leftField !== void 0 ? [head, left, targets[0]] : [head, targets[0], right];
4943
+ }
4944
+ const includesExpr = ["array/includes", [...targets], leftField !== void 0 ? left : right];
4945
+ return NEGATED_EQUALITY_OPS.has(head) ? ["not", includesExpr] : includesExpr;
4946
+ }
4947
+ }
4948
+ }
4949
+ if (head === "array/includes" && node.length === 3 && Array.isArray(node[1])) {
4950
+ const needleField = directUserField(node[2]);
4951
+ if (needleField !== void 0 && roleFields.has(needleField)) {
4952
+ const members = literalHaystackMembers(node[1]);
4953
+ if (members !== void 0) {
4954
+ const expanded = [];
4955
+ for (const literal of members) {
4956
+ const mapped = roles[literal];
4957
+ if (mapped) {
4958
+ for (const target of mapped) if (!expanded.includes(target)) expanded.push(target);
4959
+ } else if (!expanded.includes(literal)) {
4960
+ expanded.push(literal);
4961
+ }
4962
+ }
4963
+ const isListCall = node[1][0] === "list";
4964
+ return ["array/includes", isListCall ? ["list", ...expanded] : expanded, node[2]];
4965
+ }
4966
+ }
4967
+ }
4968
+ return node.map((item) => rewriteRoleLiteralsInValue(item, roleFields, roles));
4969
+ }
4970
+ if (typeof node !== "object") return node;
4971
+ const next = {};
4972
+ for (const [key, value] of Object.entries(node)) {
4973
+ next[key] = rewriteRoleLiteralsInValue(value, roleFields, roles);
4974
+ }
4975
+ return next;
4976
+ }
4977
+ function rewriteRoleLiteralsInTrait(trait, roleFields, roles) {
4978
+ if (roleFields.size === 0 || Object.keys(roles).length === 0) return trait;
4979
+ const rewrite = (v) => rewriteRoleLiteralsInValue(v, roleFields, roles);
4980
+ const next = { ...trait };
4981
+ const sm = trait.stateMachine;
4982
+ if (sm) {
4983
+ next.stateMachine = {
4984
+ ...sm,
4985
+ transitions: (sm.transitions ?? []).map((t) => ({
4986
+ ...t,
4987
+ ...t.guard !== void 0 ? { guard: rewrite(t.guard) } : {},
4988
+ ...t.effects ? { effects: rewrite(t.effects) } : {}
4989
+ }))
4990
+ };
4991
+ }
4992
+ if (trait.ticks) {
4993
+ next.ticks = trait.ticks.map((tick) => ({
4994
+ ...tick,
4995
+ ...tick.guard !== void 0 ? { guard: rewrite(tick.guard) } : {},
4996
+ effects: rewrite(tick.effects)
4997
+ }));
4998
+ }
4999
+ if (trait.listens) {
5000
+ next.listens = trait.listens.map((l) => ({
5001
+ ...l,
5002
+ ...l.guard !== void 0 ? { guard: rewrite(l.guard) } : {},
5003
+ ...l.payloadMapping ? { payloadMapping: rewrite(l.payloadMapping) } : {}
5004
+ }));
5005
+ }
5006
+ if (trait.initialEffects) {
5007
+ next.initialEffects = rewrite(trait.initialEffects);
5008
+ }
5009
+ if (trait.config) {
5010
+ const nextConfig = {};
5011
+ for (const [key, field] of Object.entries(trait.config)) {
5012
+ nextConfig[key] = field.default === void 0 ? field : { ...field, default: rewrite(field.default) };
5013
+ }
5014
+ next.config = nextConfig;
5015
+ }
5016
+ if (trait.sourceEntityDefinition) {
5017
+ next.sourceEntityDefinition = rewriteRoleLiteralsInEntity(trait.sourceEntityDefinition, roleFields, roles);
5018
+ }
5019
+ return next;
5020
+ }
5021
+ function rewriteRoleLiteralsInEntity(entity, roleFields, roles) {
5022
+ if (roleFields.size === 0 || Object.keys(roles).length === 0) return entity;
5023
+ const rewrite = (v) => rewriteRoleLiteralsInValue(v, roleFields, roles);
5024
+ return {
5025
+ ...entity,
5026
+ ...entity.read_policy !== void 0 ? { read_policy: rewrite(entity.read_policy) } : {},
5027
+ ...entity.create_policy !== void 0 ? { create_policy: rewrite(entity.create_policy) } : {},
5028
+ ...entity.update_policy !== void 0 ? { update_policy: rewrite(entity.update_policy) } : {},
5029
+ ...entity.delete_policy !== void 0 ? { delete_policy: rewrite(entity.delete_policy) } : {}
5030
+ };
5031
+ }
5032
+ function renameRelationTargetsInField(field, entitySubs, entityIds) {
5033
+ let next = field;
5034
+ if (next.type === "relation") {
5035
+ const to = entitySubs.get(next.relation.entity);
5036
+ if (to !== void 0) {
5037
+ next = { ...next, relation: { ...next.relation, entity: to, entityId: entityIds.get(to) } };
5038
+ }
5039
+ }
5040
+ if ((next.type === "array" || next.type === "object") && next.items) {
5041
+ next = { ...next, items: renameRelationTargetsInField(next.items, entitySubs, entityIds) };
5042
+ }
5043
+ if (next.properties) {
5044
+ const nextProperties = {};
5045
+ for (const [key, value] of Object.entries(next.properties)) {
5046
+ nextProperties[key] = renameRelationTargetsInField(value, entitySubs, entityIds);
5047
+ }
5048
+ next = { ...next, properties: nextProperties };
5049
+ }
5050
+ return next;
5051
+ }
5052
+ function renameEntityRelationTargets(entity, entitySubs, entityIds) {
5053
+ if (entitySubs.size === 0) return entity;
5054
+ return { ...entity, fields: entity.fields.map((f) => renameRelationTargetsInField(f, entitySubs, entityIds)) };
5055
+ }
5056
+ function renameSourceEntityDefinition(trait, subs, entityIds) {
5057
+ const src = trait.sourceEntityDefinition;
5058
+ if (!src || subs.size === 0) return trait;
5059
+ const renamedName = subs.get(src.name) ?? src.name;
5060
+ const nextSrc = renameEntityRelationTargets({ ...src, name: renamedName }, subs, entityIds);
5061
+ return { ...trait, sourceEntityDefinition: nextSrc };
5062
+ }
5063
+ function renamePayloadEntity(fields, rename) {
5064
+ return fields.map((field) => {
5065
+ const renamedEntity = field.entity !== void 0 ? rename(field.entity) : void 0;
5066
+ const renamedProps = field.properties ? renamePayloadEntity(field.properties, rename) : field.properties;
5067
+ return {
5068
+ ...field,
5069
+ ...renamedEntity !== void 0 ? { entity: renamedEntity } : {},
5070
+ ...renamedProps !== void 0 ? { properties: renamedProps } : {}
5071
+ };
5072
+ });
5073
+ }
5074
+ function renamePayloadEntityMarkers(trait, rename) {
5075
+ const sm = trait.stateMachine;
5076
+ const nextEvents = sm?.events ? sm.events.map((ev) => {
5077
+ const renamedEntity = ev.payloadEntity !== void 0 ? rename(ev.payloadEntity) : void 0;
5078
+ if (!ev.payloadSchema && renamedEntity === void 0) return ev;
5079
+ return {
5080
+ ...ev,
5081
+ ...ev.payloadSchema ? { payloadSchema: renamePayloadEntity(ev.payloadSchema, rename) } : {},
5082
+ ...renamedEntity !== void 0 ? { payloadEntity: renamedEntity } : {}
5083
+ };
5084
+ }) : void 0;
5085
+ const nextEmits = trait.emits ? trait.emits.map((em) => {
5086
+ const renamedEntity = em.payloadEntity !== void 0 ? rename(em.payloadEntity) : void 0;
5087
+ if (!em.payloadSchema && renamedEntity === void 0) return em;
5088
+ return {
5089
+ ...em,
5090
+ ...em.payloadSchema ? { payloadSchema: renamePayloadEntity(em.payloadSchema, rename) } : {},
5091
+ ...renamedEntity !== void 0 ? { payloadEntity: renamedEntity } : {}
5092
+ };
5093
+ }) : void 0;
5094
+ return {
5095
+ ...trait,
5096
+ ...sm && nextEvents ? { stateMachine: { ...sm, events: nextEvents } } : {},
5097
+ ...nextEmits ? { emits: nextEmits } : {}
5098
+ };
5099
+ }
5100
+ function walkEntityInPayloadMapping(payloadMapping, rename, props) {
5101
+ const next = {};
5102
+ for (const [key, value] of Object.entries(payloadMapping)) {
5103
+ next[key] = renameEntityInEffect(value, rename, props);
5104
+ }
5105
+ return next;
5106
+ }
5107
+ function renameEntitiesInTrait(trait, entitySubs, entityIds) {
5108
+ if (entitySubs.size === 0) return trait;
5109
+ const rename = (name) => entitySubs.get(name);
5110
+ const withTokens = (value) => renameEntityNameTokensInValue(value, entitySubs);
5111
+ const nextLinked = trait.linkedEntity !== void 0 ? entitySubs.get(trait.linkedEntity) ?? trait.linkedEntity : trait.linkedEntity;
5112
+ const sm = trait.stateMachine;
5113
+ const nextTransitions = sm?.transitions ? sm.transitions.map((t) => ({
5114
+ ...t,
5115
+ ...t.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(t.guard, rename, REBIND_ENTITY_PROPS)) } : {},
5116
+ effects: t.effects ? withTokens(renameEntityInEffects(t.effects, rename, REBIND_ENTITY_PROPS)) : t.effects
5117
+ })) : sm?.transitions;
5118
+ const nextTicks = trait.ticks ? trait.ticks.map((tick) => ({
5119
+ ...tick,
5120
+ ...tick.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(tick.guard, rename, REBIND_ENTITY_PROPS)) } : {},
5121
+ effects: withTokens(renameEntityInEffects(
5122
+ tick.effects,
5123
+ rename,
5124
+ REBIND_ENTITY_PROPS
5125
+ ))
5126
+ })) : trait.ticks;
5127
+ const nextListens = trait.listens ? trait.listens.map((l) => ({
5128
+ ...l,
5129
+ ...l.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(l.guard, rename, REBIND_ENTITY_PROPS)) } : {},
5130
+ ...l.payloadMapping ? { payloadMapping: withTokens(walkEntityInPayloadMapping(l.payloadMapping, rename, REBIND_ENTITY_PROPS)) } : {}
5131
+ })) : trait.listens;
5132
+ const nextInitial = trait.initialEffects ? withTokens(renameEntityInEffects(
5133
+ trait.initialEffects,
5134
+ rename,
5135
+ REBIND_ENTITY_PROPS
5136
+ )) : trait.initialEffects;
5137
+ return rewriteEntityTypedConfigValues(
5138
+ renamePayloadEntityMarkers(
5139
+ {
5140
+ ...trait,
5141
+ linkedEntity: nextLinked,
5142
+ ...sm ? { stateMachine: { ...sm, transitions: nextTransitions ?? [] } } : {},
5143
+ ...nextTicks !== void 0 ? { ticks: nextTicks } : {},
5144
+ ...nextListens !== void 0 ? { listens: nextListens } : {},
5145
+ ...nextInitial !== void 0 ? { initialEffects: nextInitial } : {}
5146
+ },
5147
+ rename
5148
+ ),
5149
+ entitySubs,
5150
+ entityIds
5151
+ );
5152
+ }
5153
+ function rewriteEntityRefIds(trait, entitySubs, entityIds) {
5154
+ const refs = trait.entityRefIds;
5155
+ if (!refs) return trait;
5156
+ const out = {};
5157
+ for (const [from, oldId] of Object.entries(refs)) {
5158
+ const name = entitySubs.get(from) ?? from;
5159
+ out[name] = entityIds.get(name) ?? oldId;
5160
+ }
5161
+ return { ...trait, entityRefIds: out };
5162
+ }
5163
+ function rewriteEntityTypedConfigValues(trait, entitySubs, entityIds) {
5164
+ if (entitySubs.size === 0 || !trait.config) return trait;
5165
+ let changed = false;
5166
+ const nextConfig = { ...trait.config };
5167
+ for (const [key, field] of Object.entries(trait.config)) {
5168
+ if (field.type !== "entity" || typeof field.default !== "string") continue;
5169
+ const to = entitySubs.get(field.default);
5170
+ if (to === void 0) continue;
5171
+ changed = true;
5172
+ nextConfig[key] = { ...field, default: to, refId: entityIds.get(to) };
5173
+ }
5174
+ return changed ? { ...trait, config: nextConfig } : trait;
5175
+ }
5176
+ function applyAliasEntityRenames(trait, subs, entityIds) {
5177
+ if (subs.size === 0) return trait;
5178
+ const rename = (name) => subs.get(name);
5179
+ const withTokens = (value) => renameEntityNameTokensInValue(value, subs);
5180
+ const sm = trait.stateMachine;
5181
+ const nextTransitions = sm?.transitions ? sm.transitions.map((t) => ({
5182
+ ...t,
5183
+ ...t.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(t.guard, rename, REBIND_ENTITY_PROPS)) } : {},
5184
+ effects: t.effects ? withTokens(renameEntityInEffects(t.effects, rename, REBIND_ENTITY_PROPS)) : t.effects
5185
+ })) : sm?.transitions;
5186
+ const nextTicks = trait.ticks ? trait.ticks.map((tick) => ({
5187
+ ...tick,
5188
+ ...tick.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(tick.guard, rename, REBIND_ENTITY_PROPS)) } : {},
5189
+ effects: withTokens(
5190
+ renameEntityInEffects(tick.effects, rename, REBIND_ENTITY_PROPS)
5191
+ )
5192
+ })) : trait.ticks;
5193
+ const next = {
5194
+ ...trait,
5195
+ ...sm ? { stateMachine: { ...sm, transitions: nextTransitions ?? [] } } : {},
5196
+ ...nextTicks !== void 0 ? { ticks: nextTicks } : {}
5197
+ };
5198
+ return rewriteEntityRefIds(next, subs, entityIds);
5199
+ }
5200
+ function collectEntityNamesInTrait(trait, candidates) {
5201
+ const collected = /* @__PURE__ */ new Set();
5202
+ const collect = (name) => {
5203
+ if (candidates.has(name)) collected.add(name);
5204
+ return void 0;
5205
+ };
5206
+ const sm = trait.stateMachine;
5207
+ for (const t of sm?.transitions ?? []) {
5208
+ if (t.guard !== void 0) renameEntityInEffect(t.guard, collect, REBIND_ENTITY_PROPS);
5209
+ if (t.effects) renameEntityInEffects(t.effects, collect, REBIND_ENTITY_PROPS);
5210
+ }
5211
+ for (const tick of trait.ticks ?? []) {
5212
+ if (tick.guard !== void 0) renameEntityInEffect(tick.guard, collect, REBIND_ENTITY_PROPS);
5213
+ renameEntityInEffects(tick.effects, collect, REBIND_ENTITY_PROPS);
5214
+ }
5215
+ for (const l of trait.listens ?? []) {
5216
+ if (l.guard !== void 0) renameEntityInEffect(l.guard, collect, REBIND_ENTITY_PROPS);
5217
+ if (l.payloadMapping) walkEntityInPayloadMapping(l.payloadMapping, collect, REBIND_ENTITY_PROPS);
5218
+ }
5219
+ if (trait.initialEffects) {
5220
+ renameEntityInEffects(trait.initialEffects, collect, REBIND_ENTITY_PROPS);
5221
+ }
5222
+ return collected;
5223
+ }
5224
+ function collectRelationTargets(field, candidates, out) {
5225
+ if (field.type === "relation" && candidates.has(field.relation.entity)) out.add(field.relation.entity);
5226
+ if ((field.type === "array" || field.type === "object") && field.items) {
5227
+ collectRelationTargets(field.items, candidates, out);
5228
+ }
5229
+ if (field.properties) {
5230
+ for (const value of Object.values(field.properties)) collectRelationTargets(value, candidates, out);
5231
+ }
5232
+ }
5233
+ function relationTargetsOfEntity(entity, candidates) {
5234
+ const out = /* @__PURE__ */ new Set();
5235
+ for (const field of entity.fields) collectRelationTargets(field, candidates, out);
5236
+ return out;
5237
+ }
5238
+ function rewriteListenSources(trait, subs, idByName, orbitalRename, alias, listenSourceTargets) {
5239
+ const listens = trait.listens;
5240
+ if (!listens || listens.length === 0) return trait;
5241
+ let changed = false;
5242
+ const nextListens = listens.map((listen) => {
5243
+ const source = listen.source;
5244
+ if (!source) return listen;
5245
+ if (source.kind === "trait") {
5246
+ const target = subs.get(source.trait);
5247
+ if (target === void 0 || target === source.trait) return listen;
5248
+ changed = true;
5249
+ const traitId = idByName.get(target);
5250
+ return {
5251
+ ...listen,
5252
+ source: { kind: "trait", trait: target, ...traitId ? { traitId } : {} }
5253
+ };
5254
+ }
5255
+ if (source.kind === "orbital") {
5256
+ if (orbitalRename && source.orbital === orbitalRename.from) {
5257
+ const targetTrait = subs.get(source.trait) ?? source.trait;
5258
+ changed = true;
5259
+ const traitId = idByName.get(targetTrait);
5260
+ return {
5261
+ ...listen,
5262
+ source: {
5263
+ kind: "orbital",
5264
+ orbital: orbitalRename.to,
5265
+ trait: targetTrait,
5266
+ ...traitId ? { traitId } : {}
5267
+ }
5268
+ };
5269
+ }
5270
+ const info = alias && listenSourceTargets ? listenSourceTargets.get(siblingImportKey(alias, source.orbital)) : void 0;
5271
+ if (info) {
5272
+ const target = info.traitSubs.get(source.trait);
5273
+ changed = true;
5274
+ return {
5275
+ ...listen,
5276
+ source: {
5277
+ kind: "orbital",
5278
+ orbital: info.localName,
5279
+ trait: target?.finalName ?? source.trait,
5280
+ ...target?.finalId ? { traitId: target.finalId } : {}
5281
+ }
5282
+ };
5283
+ }
5284
+ }
5285
+ return listen;
5286
+ });
5287
+ return changed ? { ...trait, listens: nextListens } : trait;
5288
+ }
5289
+ function isInlineEntity(ref) {
5290
+ return !isEntityReference(ref) && !isEntityCall(ref);
5291
+ }
5292
+ function inlineEntityRefsOf(orbital) {
5293
+ return [orbital.entity, ...orbital.auxiliaryEntities ?? []].filter(isInlineEntity);
5294
+ }
5295
+ function entityByNameForAlias(imports, alias, entityName) {
5296
+ const imported = imports.orbitals.get(alias);
5297
+ if (!imported) return void 0;
5298
+ for (const o of importedOrbitals(imported)) {
5299
+ const found = inlineEntityRefsOf(o).find((e) => e.name === entityName);
5300
+ if (found) return found;
5301
+ }
5302
+ return void 0;
5303
+ }
5304
+ function entityByNameAnyAlias(imports, entityName) {
5305
+ const aliases = Array.from(imports.orbitals.keys()).sort();
5306
+ for (const alias of aliases) {
5307
+ const found = entityByNameForAlias(imports, alias, entityName);
5308
+ if (found) return found;
5309
+ }
5310
+ return void 0;
5311
+ }
5312
+ function ownedTraitEntryFor(imports, alias, traitName) {
5313
+ const imported = imports.orbitals.get(alias);
5314
+ if (!imported) return void 0;
5315
+ const owner = importedOrbitals(imported).find(
5316
+ (o) => findTraitEntryInOrbital(o, traitName) !== null
5317
+ );
5318
+ if (!owner || !isInlineEntity(owner.entity)) return void 0;
5319
+ return { owner, ownerEntity: owner.entity, entry: findTraitEntryInOrbital(owner, traitName) };
5320
+ }
5321
+ function boundTraitOrbitalBinding(imports, alias, traitName) {
5322
+ const imported = imports.orbitals.get(alias);
5323
+ if (imported?.resolvedOrbitals) {
5324
+ for (const ro of imported.resolvedOrbitals) {
5325
+ const entry = findTraitEntryInOrbital(ro.original, traitName);
5326
+ if (!entry) continue;
5327
+ const bound2 = entry.linkedEntity;
5328
+ const resolvedEntities = [ro.entity, ...ro.auxiliaryEntities ?? []];
5329
+ const boundEntity2 = bound2 !== void 0 ? resolvedEntities.find((e) => e.name === bound2) : void 0;
5330
+ const requiredData2 = new Set(
5331
+ ro.traits.find((rt) => rt.trait.name === traitName)?.trait.entityContract?.requires ?? []
5332
+ );
5333
+ return { owner: ro.original, ownerEntity: ro.entity, entity: boundEntity2 ?? ro.entity, requiredData: requiredData2 };
5334
+ }
5335
+ }
5336
+ const owned = ownedTraitEntryFor(imports, alias, traitName);
5337
+ if (!owned) return void 0;
5338
+ const ownerEntities = inlineEntityRefsOf(owned.owner);
5339
+ const bound = owned.entry?.linkedEntity;
5340
+ const boundEntity = bound !== void 0 ? ownerEntities.find((e) => e.name === bound) : void 0;
5341
+ const requiredData = new Set(
5342
+ owned.entry && "stateMachine" in owned.entry ? owned.entry.entityContract?.requires ?? [] : []
5343
+ );
5344
+ return { owner: owned.owner, ownerEntity: owned.ownerEntity, entity: boundEntity ?? owned.ownerEntity, requiredData };
5345
+ }
5346
+ function auxEntitiesFromUnrebindTraitRefs(orbitalTraits, imports) {
5347
+ const out = [];
5348
+ const seen = /* @__PURE__ */ new Set();
5349
+ const push = (e) => {
5350
+ if (!seen.has(e.name)) {
5351
+ seen.add(e.name);
5352
+ out.push(e);
5353
+ }
5354
+ };
5355
+ for (const tr of orbitalTraits) {
5356
+ let ref;
5357
+ let linkedEntity;
5358
+ if (typeof tr === "string") {
5359
+ ref = tr;
5360
+ } else if ("ref" in tr) {
5361
+ ref = tr.ref;
5362
+ linkedEntity = tr.linkedEntity;
5363
+ } else {
5364
+ continue;
5365
+ }
5366
+ const parsed = parseImportedTraitRef(ref);
5367
+ if (!parsed) continue;
5368
+ const binding = boundTraitOrbitalBinding(imports, parsed.alias, parsed.traitName);
5369
+ if (!binding) continue;
5370
+ if (linkedEntity === void 0) {
5371
+ push(binding.entity);
5372
+ }
5373
+ for (const e of inlineEntityRefsOf(binding.owner)) {
5374
+ if (e.name !== binding.ownerEntity.name) push(e);
5375
+ }
5376
+ }
5377
+ return out;
5378
+ }
5379
+ function rewriteSelfRelationTarget(field, oldName, newName, newId) {
5380
+ if (field.type === "relation" && field.relation.entity === oldName) {
5381
+ field.relation = { ...field.relation, entity: newName, entityId: newId };
5382
+ }
5383
+ if (field.type === "array" && field.items) {
5384
+ rewriteSelfRelationTarget(field.items, oldName, newName, newId);
5385
+ }
5386
+ if (field.type === "object" && field.items) {
5387
+ rewriteSelfRelationTarget(field.items, oldName, newName, newId);
5388
+ }
5389
+ if (field.properties) {
5390
+ for (const key of Object.keys(field.properties)) {
5391
+ rewriteSelfRelationTarget(field.properties[key], oldName, newName, newId);
5392
+ }
5393
+ }
5394
+ }
5395
+ function mergeImportedEntityFields(callerEntity, importedEntity, intrinsicOnly, requiredData) {
5396
+ const existingNames = new Set(
5397
+ callerEntity.fields.map((f) => f.name).filter((n) => n !== void 0)
5398
+ );
5399
+ const oldName = importedEntity.name;
5400
+ const newName = callerEntity.name;
5401
+ const newId = callerEntity.id;
5402
+ for (const field of importedEntity.fields) {
5403
+ if (intrinsicOnly && field.intrinsic !== true) continue;
5404
+ if (field.name === void 0) continue;
5405
+ if (requiredData.has(field.name) && field.intrinsic !== true) continue;
5406
+ if (existingNames.has(field.name)) continue;
5407
+ const cloned = structuredClone(field);
5408
+ rewriteSelfRelationTarget(cloned, oldName, newName, newId);
5409
+ callerEntity.fields.push(cloned);
5410
+ }
5411
+ }
5412
+ function mergeImportedEntityFieldsIntoOrbital(orbitalTraits, entity, declaredAuxEntities, imports) {
5413
+ const mergedAliases = /* @__PURE__ */ new Set();
5414
+ const pending = [];
5415
+ for (const tr of orbitalTraits) {
5416
+ let ref;
5417
+ let linkedEntity;
5418
+ if (typeof tr === "string") {
5419
+ ref = tr;
5420
+ } else if ("ref" in tr) {
5421
+ ref = tr.ref;
5422
+ linkedEntity = tr.linkedEntity;
5423
+ } else {
5424
+ continue;
5425
+ }
5426
+ const parsed = parseImportedTraitRef(ref);
5427
+ if (!parsed) continue;
5428
+ const binding = boundTraitOrbitalBinding(imports, parsed.alias, parsed.traitName);
5429
+ if (!binding) continue;
5430
+ const carriesFields = linkedEntity !== void 0 ? true : binding.entity.name === entity.name;
5431
+ if (!carriesFields) continue;
5432
+ const key = `${parsed.alias}\0${parsed.traitName}`;
5433
+ if (mergedAliases.has(key)) continue;
5434
+ mergedAliases.add(key);
5435
+ pending.push({
5436
+ target: linkedEntity,
5437
+ imported: binding.entity,
5438
+ intrinsicOnly: linkedEntity === void 0,
5439
+ requiredData: binding.requiredData
5440
+ });
5441
+ }
5442
+ for (const pm of pending) {
5443
+ const auxTarget = pm.target !== void 0 && pm.target !== entity.name ? declaredAuxEntities.find((e) => e.name === pm.target) : void 0;
5444
+ mergeImportedEntityFields(auxTarget ?? entity, pm.imported, pm.intrinsicOnly, pm.requiredData);
5445
+ }
5446
+ }
5447
+ function consumerEntityIdsOf(orbitals) {
5448
+ const out = /* @__PURE__ */ new Map();
5449
+ for (const orbital of orbitals) {
5450
+ for (const entity of inlineEntityRefsOf(orbital)) {
5451
+ if (entity.id) out.set(entity.name, entity.id);
5452
+ }
5453
+ }
5454
+ return out;
5455
+ }
5456
+ function materializedPrimaryEntity(upstreamEntity, upstreamOrbitalId, ref, localName) {
5457
+ const name = ref.entity ?? `${localName}${upstreamEntity.name}`;
5458
+ const id = asEntityId(
5459
+ deriveMaterializedId(upstreamEntity.id, upstreamOrbitalId, upstreamEntity.name, localName, "entity")
5460
+ );
5461
+ return { name, id };
5462
+ }
5463
+ function materializedTraitSubs(upstreamId, traits, ref, localName) {
5464
+ const onlySet = ref.only ? new Set(ref.only) : void 0;
5465
+ const omitSet = new Set(ref.omit ?? []);
5466
+ const out = /* @__PURE__ */ new Map();
5467
+ for (const rt of traits) {
5468
+ const name = rt.trait.name;
5469
+ if (!name) continue;
5470
+ const keep = onlySet ? onlySet.has(name) : !omitSet.has(name);
5471
+ if (!keep) continue;
5472
+ out.set(name, {
5473
+ finalName: `${localName}${name}`,
5474
+ finalId: asTraitId(deriveMaterializedId(rt.trait.id, upstreamId, name, localName, "trait"))
5475
+ });
5476
+ }
5477
+ return out;
5478
+ }
5479
+ function siblingImportKey(alias, upstreamOrbitalName) {
5480
+ return `${alias}\0${upstreamOrbitalName}`;
5481
+ }
5482
+ function applyExtendFields(entity, extend, fieldSubs, consumerEntityIds, localName) {
5483
+ if (!extend || extend.length === 0) return { entity, errors: [] };
5484
+ const errors = [];
5485
+ const taken = new Set(entity.fields.map((f) => f.name).filter((n) => Boolean(n)));
5486
+ for (const target of fieldSubs.values()) taken.add(target);
5487
+ const added = [];
5488
+ for (const field of extend) {
5489
+ const name = field.name;
5490
+ if (!name) continue;
5491
+ if (taken.has(name)) {
5492
+ errors.push(
5493
+ `Orbital "${localName}" declares extend field "${name}" but the upstream primary entity already has a field of that name after "fields {}" renames (ORB_O_EXTEND_FIELD_COLLISION)`
5494
+ );
5495
+ continue;
5496
+ }
5497
+ taken.add(name);
5498
+ if (field.type === "relation" && !field.relation.entityId) {
5499
+ const targetId = consumerEntityIds.get(field.relation.entity);
5500
+ added.push(targetId ? { ...field, relation: { ...field.relation, entityId: targetId } } : field);
5501
+ continue;
5502
+ }
5503
+ added.push(field);
5504
+ }
5505
+ if (added.length === 0) return { entity, errors };
5506
+ return { entity: { ...entity, fields: [...entity.fields, ...added] }, errors };
5507
+ }
5508
+ function deriveMaterializedId(sourceId, upstreamOrbitalId, sourceName, localName, kind) {
5509
+ const parent = sourceId ?? `${idPrefix(kind)}orbital-import-seed:${upstreamOrbitalId ?? "no-orbital-id"}:${sourceName}`;
5510
+ return deriveId(parent, localName);
5511
+ }
5512
+ function navigatePathSegments(path) {
5513
+ return path.split("/").filter((segment) => segment.length > 0);
5514
+ }
5515
+ function navigateParamStrippedPrefix(path) {
5516
+ const segments = navigatePathSegments(path);
5517
+ const last = segments[segments.length - 1];
5518
+ if (last === void 0 || !last.startsWith(":")) return void 0;
5519
+ return `/${segments.slice(0, -1).join("/")}/`;
5520
+ }
5521
+ function rewriteConcatPrefix(literalPrefix, pathMap) {
5522
+ const normalized = literalPrefix.endsWith("/") ? literalPrefix : `${literalPrefix}/`;
5523
+ for (const [upstreamPath, finalPath] of pathMap) {
5524
+ const stripped = navigateParamStrippedPrefix(upstreamPath);
5525
+ if (stripped === void 0 || stripped !== normalized) continue;
5526
+ const finalStripped = navigateParamStrippedPrefix(finalPath);
5527
+ if (finalStripped !== void 0) return finalStripped;
5528
+ }
5529
+ return void 0;
5530
+ }
5531
+ function rewriteNavigateTargets(node, pathMap) {
5532
+ if (node === null || node === void 0) return node;
5533
+ if (Array.isArray(node)) {
5534
+ if (node[0] === "navigate" && node.length >= 2) {
5535
+ const target = node[1];
5536
+ if (typeof target === "string" && pathMap.has(target)) {
5537
+ return [node[0], pathMap.get(target), ...node.slice(2).map((v) => rewriteNavigateTargets(v, pathMap))];
5538
+ }
5539
+ if (Array.isArray(target) && target[0] === "str/concat" && typeof target[1] === "string" && target[1].startsWith("/")) {
5540
+ const rewrittenPrefix = rewriteConcatPrefix(target[1], pathMap);
5541
+ const nextTarget = rewrittenPrefix !== void 0 ? [target[0], rewrittenPrefix, ...target.slice(2)] : target;
5542
+ return [node[0], nextTarget, ...node.slice(2).map((v) => rewriteNavigateTargets(v, pathMap))];
5543
+ }
5544
+ }
5545
+ return node.map((item) => rewriteNavigateTargets(item, pathMap));
5546
+ }
5547
+ if (typeof node !== "object") return node;
5548
+ const next = {};
5549
+ for (const [key, value] of Object.entries(node)) {
5550
+ next[key] = rewriteNavigateTargets(value, pathMap);
5551
+ }
5552
+ return next;
5553
+ }
5554
+ function rewriteTraitNavigateTargets(trait, pathMap) {
5555
+ if (pathMap.size === 0) return trait;
5556
+ const rewrite = (v) => rewriteNavigateTargets(v, pathMap);
5557
+ const next = { ...trait };
5558
+ const sm = trait.stateMachine;
5559
+ if (sm) {
5560
+ next.stateMachine = {
5561
+ ...sm,
5562
+ transitions: (sm.transitions ?? []).map(
5563
+ (t) => t.effects ? { ...t, effects: rewrite(t.effects) } : t
5564
+ )
5565
+ };
5566
+ }
5567
+ if (trait.ticks) {
5568
+ next.ticks = trait.ticks.map((tick) => ({ ...tick, effects: rewrite(tick.effects) }));
5569
+ }
5570
+ if (trait.initialEffects) {
5571
+ next.initialEffects = rewrite(trait.initialEffects);
5572
+ }
5573
+ return next;
5574
+ }
5575
+ function rewriteConfigPagePaths(node, pathMap) {
5576
+ if (typeof node === "string") return pathMap.get(node) ?? node;
5577
+ if (Array.isArray(node)) return node.map((item) => rewriteConfigPagePaths(item, pathMap));
5578
+ if (node !== null && typeof node === "object") {
5579
+ const next = {};
5580
+ for (const [key, value] of Object.entries(node)) {
5581
+ next[key] = rewriteConfigPagePaths(value, pathMap);
5582
+ }
5583
+ return next;
5584
+ }
5585
+ return node;
5586
+ }
5587
+ function rewriteTraitConfigPagePaths(trait, pathMap) {
5588
+ if (pathMap.size === 0 || !trait.config) return trait;
5589
+ const nextConfig = {};
5590
+ for (const [key, field] of Object.entries(trait.config)) {
5591
+ nextConfig[key] = field.default === void 0 ? field : { ...field, default: rewriteConfigPagePaths(field.default, pathMap) };
5592
+ }
5593
+ return { ...trait, config: nextConfig };
5594
+ }
5595
+ function foldUseConfigOverride(declared, override, context) {
5596
+ if (!override) return declared;
5597
+ const values = {};
5598
+ for (const [key, field] of Object.entries(override)) {
5599
+ if (!(key in declared)) {
5600
+ refResolverLog.warn("use-config:unknown-knob", { ...context, key });
5601
+ continue;
5602
+ }
5603
+ if (field.default !== void 0) values[key] = field.default;
5604
+ }
5605
+ return Object.keys(values).length > 0 ? overrideDeclaredKnobs(declared, values) : declared;
5606
+ }
5607
+ function forwardConsumerAppKnobs(folded, consumer) {
5608
+ if (!consumer) return folded;
5609
+ const forwards = {};
5610
+ for (const [key, field] of Object.entries(folded)) {
5611
+ const token = field.default;
5612
+ if (typeof token !== "string" || !token.startsWith("@config.")) continue;
5613
+ const source = token.slice("@config.".length);
5614
+ if (source.includes(".") || !(source in consumer)) continue;
5615
+ if (consumer[source].default === void 0) continue;
5616
+ forwards[key] = source;
5617
+ }
5618
+ if (Object.keys(forwards).length === 0) return folded;
5619
+ const next = { ...folded };
5620
+ for (const [key, source] of Object.entries(forwards)) {
5621
+ next[key] = { ...folded[key], default: consumer[source].default, forwardedFrom: `@config.${source}` };
5622
+ }
5623
+ return next;
5624
+ }
5625
+ var ReferenceResolver = class _ReferenceResolver {
5626
+ loader;
5627
+ options;
5628
+ localTraits;
5629
+ /** id-keyed mirror of `localTraits`, populated wherever the trait carries an `id`. */
5630
+ localTraitsById = /* @__PURE__ */ new Map();
5631
+ /** Import scope of each loaded source orbital, keyed by its source path. */
5632
+ sourceImportsCache = /* @__PURE__ */ new Map();
5633
+ /**
5634
+ * {@link preResolveImportFile}'s cache, keyed by absolute source path —
5635
+ * `null` for a file whose own pre-resolution failed (best-effort, cached
5636
+ * too, so a repeat import doesn't retry a doomed resolve). Distinct from
5637
+ * {@link sourceImportsCache} (raw import SCOPE, no trait resolution) —
5638
+ * this holds the file's fully RESOLVED orbitals.
5639
+ */
5640
+ importFileResolveCache = /* @__PURE__ */ new Map();
5641
+ loaderInitialized = false;
5642
+ /** The schema's declared `config {}` — outermost rung of the forwarded-config chain (§4.5). */
5643
+ schemaConfig;
5644
+ /**
5645
+ * Schema-wide CONSUMER entity NAME → id, growing as each of THIS
5646
+ * schema's own orbitals finishes resolving. JS twin of the compiled
5647
+ * path's `consumer_entity_ids` (`orbital-compiler/src/phases/inline/
5648
+ * mod.rs`), extended the same way: once per orbital, right after it
5649
+ * resolves. Extended ONLY by {@link noteResolvedEntityIds} — called by
5650
+ * the free function {@link resolveSchema} after each of ITS OWN orbitals
5651
+ * finishes — never automatically inside `resolve()` itself, so the
5652
+ * nested `this.resolve()` call {@link materializeOrbitalRef} makes for an
5653
+ * external upstream orbital (a DIFFERENT file, never this consumer
5654
+ * schema) cannot pollute it.
5655
+ */
5656
+ schemaEntityIds = /* @__PURE__ */ new Map();
5657
+ /**
5658
+ * Entity NAME → id visible to the orbital CURRENTLY being resolved:
5659
+ * {@link schemaEntityIds} (every name an EARLIER orbital in this schema
5660
+ * already established) plus the current orbital's own declared primary +
5661
+ * auxiliary entities — JS twin of the compiled path's per-orbital `entity_
5662
+ * ids = consumer_entity_ids.clone(); entity_ids.extend(collect_orbital_
5663
+ * entity_ids(orbital))`, timed the same way (before this orbital's own
5664
+ * trait composition runs). Read by {@link applyLinkedEntityRename}'s call
5665
+ * sites so a call-site `-> Entity` rebind can REFRESH (never merely drop)
5666
+ * the trait's `entityRefIds` side-map when the rebind target's id is
5667
+ * already known — the gap `std-api-gateway` exposed: `RouteOrbital`'s
5668
+ * no-rebind `Audit.traits.AuditCaptureListener` pull establishes
5669
+ * `AuditEntry`'s id; `GatewayUserOrbital`, resolved LATER in the same
5670
+ * schema, rebinds `Browse.traits.BrowseItemBrowse -> AuditEntry` and must
5671
+ * see it. `resolve()` re-sets this fresh at its own entry (no restore
5672
+ * needed once it returns): nothing reads it once `resolve()` has
5673
+ * returned, and no `resolve()` call is ever active while another is on
5674
+ * this instance — the only recursive `this.resolve()` call
5675
+ * (`materializeOrbitalRef`'s upstream re-resolve) runs strictly BEFORE
5676
+ * `resolveSchema`'s own per-orbital loop begins, never nested inside it.
5677
+ */
5678
+ entityIdsInScope = /* @__PURE__ */ new Map();
5679
+ /**
5680
+ * Per-orbital name → the FINAL trait names {@link pullSiblingTraits}
5681
+ * auto-pulled for it (`ResolvedOrbital.name` keyed, set once per `resolve()`
5682
+ * call). JS twin of Rust's `pulled_by_orbital` (`inline/mod.rs`) — read by
5683
+ * {@link uniquifyCrossOrbitalPulledSiblings}, run once by the free
5684
+ * function {@link resolveSchema} AFTER every orbital in the schema has
5685
+ * resolved, because the rename decision (does this pulled name collide
5686
+ * with ANOTHER orbital's own declared trait name?) needs the WHOLE
5687
+ * schema's roster, not just this orbital's — exactly why Rust's own
5688
+ * `uniquify_cross_orbital_pulled_siblings` runs once, after its per-orbital
5689
+ * inline loop, not inside `inline_orbital` itself.
5690
+ */
5691
+ pulledTraitNamesByOrbital = /* @__PURE__ */ new Map();
5692
+ /**
5693
+ * Seed {@link schemaEntityIds} with EVERY orbital's PRIMARY (+ any
5694
+ * already-declared auxiliary) entity name → id, from the RAW pre-resolve
5695
+ * schema — JS twin of the compiled path's `consumer_entity_ids` INITIAL
5696
+ * build (`orbital-compiler/src/phases/inline/mod.rs`, `schema.orbitals
5697
+ * .iter().flat_map(...)`), which scans ALL orbitals' primaries up front,
5698
+ * before ANY of them inlines — not just the ones resolved so far. Without
5699
+ * this, an EARLY-resolved orbital's own `entityRefIds` secondary
5700
+ * references to a LATER orbital's primary entity (`RouteOrbital`'s
5701
+ * `entityRefIds["RateBucket"]`, `RateBucket` being a DIFFERENT, not-yet-
5702
+ * resolved orbital's own primary in `std-api-gateway`) would see nothing
5703
+ * in {@link entityIdsInScope} and {@link consumerKnownEntityRebindSubs}
5704
+ * would never refresh the stale atom-baked id. Called by {@link
5705
+ * resolveSchema} ONCE, before its per-orbital loop begins; {@link
5706
+ * noteResolvedEntityIds} then keeps widening past this seed with each
5707
+ * orbital's post-resolve auxiliary discoveries (Gap #22, sibling pulls),
5708
+ * same as before.
5709
+ */
5710
+ seedSchemaEntityIds(orbitals) {
5711
+ const next = new Map(this.schemaEntityIds);
5712
+ for (const orbital of orbitals) {
5713
+ for (const e of inlineEntityRefsOf(orbital)) {
5714
+ if (e.id) next.set(e.name, e.id);
5715
+ }
5716
+ }
5717
+ this.schemaEntityIds = next;
5718
+ }
5719
+ /**
5720
+ * Extend {@link schemaEntityIds} with a just-resolved orbital's FINAL
5721
+ * entity set — primary + every auxiliary entity resolution carried in
5722
+ * (including a no-rebind sibling pull's own bound entity,
5723
+ * `ResolvedOrbital.auxiliaryEntities`). Mirrors the compiled path's
5724
+ * `consumer_entity_ids.extend(collect_orbital_entity_ids(orbital))`,
5725
+ * called the same way: once per orbital, immediately after it resolves.
5726
+ * Called by {@link resolveSchema}'s own per-orbital loop only.
5727
+ */
5728
+ noteResolvedEntityIds(resolved) {
5729
+ const next = new Map(this.schemaEntityIds);
5730
+ if (resolved.entity.id) next.set(resolved.entity.name, resolved.entity.id);
5731
+ for (const aux of resolved.auxiliaryEntities ?? []) {
5732
+ if (aux.id) next.set(aux.name, aux.id);
5733
+ }
5734
+ this.schemaEntityIds = next;
5735
+ }
5736
+ /**
5737
+ * Make auto-pulled sibling traits app-unique across orbitals — JS twin of
5738
+ * Rust's `uniquify_cross_orbital_pulled_siblings` (`inline/mod.rs`), called
5739
+ * by the free function {@link resolveSchema} once every orbital in the
5740
+ * schema has resolved (mirroring Rust's own post-per-orbital-loop timing:
5741
+ * the rename decision needs the WHOLE schema's trait-name roster, built
5742
+ * fresh here rather than grown incrementally like {@link schemaEntityIds}).
5743
+ * An auto-pulled sibling keeps its source name within its OWN orbital, so a
5744
+ * `@trait.<Sibling>` reference inside that orbital still resolves — but
5745
+ * when TWO orbitals in the same schema each declare (pulled OR explicit) a
5746
+ * trait of the SAME name, that name collides app-wide. Only renames a
5747
+ * PULLED copy (never an explicitly-authored trait ref —
5748
+ * {@link pulledTraitNamesByOrbital} is the eligibility set) whose name is
5749
+ * ALSO declared by at least one OTHER orbital, prefixing it with the
5750
+ * owning orbital's own name; the prefixed name must itself be free
5751
+ * schema-wide or the rename is skipped (matches Rust: a collision on the
5752
+ * PREFIXED name is left for the validator, never silently double-renamed).
5753
+ * Mutates `orbitals`' traits in place, same mutation style as
5754
+ * {@link pullSiblingTraits}.
5755
+ */
5756
+ uniquifyCrossOrbitalPulledSiblings(orbitals) {
5757
+ if (this.pulledTraitNamesByOrbital.size === 0) return;
5758
+ const nameOrbitalCount = /* @__PURE__ */ new Map();
5759
+ for (const orbital of orbitals) {
5760
+ const local = new Set(
5761
+ orbital.traits.map((rt) => rt.trait.name).filter((n) => Boolean(n))
5762
+ );
5763
+ for (const name of local) {
5764
+ nameOrbitalCount.set(name, (nameOrbitalCount.get(name) ?? 0) + 1);
5765
+ }
5766
+ }
5767
+ for (const orbital of orbitals) {
5768
+ const pulledNames = this.pulledTraitNamesByOrbital.get(orbital.name);
5769
+ if (!pulledNames || pulledNames.size === 0) continue;
5770
+ const renames = /* @__PURE__ */ new Map();
5771
+ for (const oldName of pulledNames) {
5772
+ if ((nameOrbitalCount.get(oldName) ?? 0) <= 1) continue;
5773
+ const newName = `${orbital.name}${oldName}`;
5774
+ if (nameOrbitalCount.has(newName)) continue;
5775
+ renames.set(oldName, newName);
5776
+ }
5777
+ if (renames.size === 0) continue;
5778
+ for (const rt of orbital.traits) {
5779
+ if (rt.trait.name && renames.has(rt.trait.name)) {
5780
+ rt.trait = { ...rt.trait, name: renames.get(rt.trait.name) };
5781
+ }
5782
+ }
5783
+ const idByName = /* @__PURE__ */ new Map();
5784
+ for (const rt of orbital.traits) {
5785
+ if (rt.trait.name) idByName.set(rt.trait.name, rt.trait.id);
5786
+ }
5787
+ for (const rt of orbital.traits) {
5788
+ rt.trait = renameTraitEmbeds(rt.trait, renames);
5789
+ rt.trait = rewriteListenSources(rt.trait, renames, idByName);
5790
+ }
5791
+ }
5792
+ }
5793
+ constructor(options) {
5794
+ this.options = options;
5795
+ this.loader = options.loader;
5796
+ this.schemaConfig = options.schemaConfig;
5797
+ this.localTraits = options.localTraits ?? /* @__PURE__ */ new Map();
5798
+ for (const trait of this.localTraits.values()) {
5799
+ if (trait.id) {
5800
+ this.localTraitsById.set(trait.id, trait);
5801
+ }
5802
+ }
5803
+ }
5804
+ async ensureLoader() {
5805
+ if (this.loader || this.loaderInitialized) return;
5806
+ this.loaderInitialized = true;
5807
+ try {
5808
+ const { ExternalOrbitalLoader } = await import('./external-loader-CISUEINQ.js');
5809
+ this.loader = new ExternalOrbitalLoader(this.options);
5810
+ } catch {
5811
+ }
5812
+ }
5813
+ /**
5814
+ * Resolve all references in an orbital.
5815
+ */
5816
+ async resolve(orbital, sourcePath, chain, opts) {
5817
+ const errors = [];
5818
+ const warnings = [];
5819
+ const importChain = chain ?? { push: () => null, pop: () => {
5820
+ }, clone() {
5821
+ return this;
5822
+ } };
5823
+ this.entityIdsInScope = new Map([...this.schemaEntityIds, ...inlineEntityRefsOf(orbital).flatMap((e) => e.id ? [[e.name, e.id]] : [])]);
5824
+ const traitsList = orbital.traits ?? [];
5825
+ const alreadyResolved = traitsList.length > 0 && traitsList.every((t) => isInlineTrait(t));
5826
+ const importsResult = alreadyResolved ? { success: true, data: { orbitals: /* @__PURE__ */ new Map(), idIndex: /* @__PURE__ */ new Map() }} : await this.resolveImports(orbital.uses ?? [], sourcePath, importChain);
5827
+ if (!importsResult.success) {
5828
+ return { success: false, errors: importsResult.errors };
5829
+ }
5830
+ const imports = importsResult.data;
5831
+ imports.idIndex = buildIdIndex(orbital, imports.orbitals);
5832
+ const gap22AuxEntities = auxEntitiesFromUnrebindTraitRefs(orbital.traits ?? [], imports);
5833
+ if (gap22AuxEntities.length > 0) {
5834
+ const next = new Map(this.entityIdsInScope);
5835
+ for (const e of gap22AuxEntities) {
5836
+ if (e.id && !next.has(e.name)) next.set(e.name, e.id);
5837
+ }
5838
+ this.entityIdsInScope = next;
5839
+ }
5840
+ if (isInlineEntity(orbital.entity)) {
5841
+ mergeImportedEntityFieldsIntoOrbital(
5842
+ orbital.traits ?? [],
5843
+ orbital.entity,
5844
+ (orbital.auxiliaryEntities ?? []).filter(isInlineEntity),
5845
+ imports
5846
+ );
5847
+ }
5848
+ const entityResult = this.resolveEntity(orbital.entity, imports);
5849
+ if (!entityResult.success) {
5850
+ errors.push(...entityResult.errors);
5851
+ }
5852
+ const traitsResult = await this.resolveTraits(orbital.traits, imports, importChain, orbital.config);
5853
+ if (!traitsResult.success) {
5854
+ errors.push(...traitsResult.errors);
5855
+ }
5856
+ const pagesResult = await this.resolvePages(orbital.pages, imports, importChain);
5857
+ if (!pagesResult.success) {
5858
+ errors.push(...pagesResult.errors);
5859
+ }
5860
+ if (errors.length > 0) {
5861
+ return { success: false, errors };
5862
+ }
5863
+ if (!entityResult.success || !traitsResult.success || !pagesResult.success) {
5864
+ return { success: false, errors: ["Internal error: unexpected failure state"] };
5865
+ }
5866
+ const { errors: pullErrors, auxEntities: pulledAuxEntities, pulledNames } = await this.pullSiblingTraits(
5867
+ traitsResult.data,
5868
+ imports,
5869
+ importChain,
5870
+ orbital.config
5871
+ );
5872
+ if (pullErrors.length > 0) {
5873
+ return { success: false, errors: pullErrors };
5874
+ }
5875
+ this.pulledTraitNamesByOrbital.set(orbital.name, pulledNames);
5876
+ const known = /* @__PURE__ */ new Set([entityResult.data.entity.name]);
5877
+ const declaredAux = (orbital.auxiliaryEntities ?? []).filter(isInlineEntity);
5878
+ for (const e of declaredAux) known.add(e.name);
5879
+ const combined = [...declaredAux];
5880
+ for (const e of [...gap22AuxEntities, ...pulledAuxEntities]) {
5881
+ if (!known.has(e.name)) {
5882
+ known.add(e.name);
5883
+ combined.push(e);
5884
+ }
5885
+ }
5886
+ const resolvedAuxEntities = combined.length > 0 ? combined : void 0;
5887
+ for (const resolvedTrait of traitsResult.data) {
5888
+ resolvedTrait.trait = resolveEntityTokensById(resolvedTrait.trait, imports.idIndex);
5889
+ resolvedTrait.trait = resolveConfigRefsById(resolvedTrait.trait, imports.idIndex);
5890
+ }
5891
+ try {
5892
+ spliceLambdaTraitRefs(traitsResult.data, pagesResult.data);
5893
+ } catch (e) {
5894
+ if (e instanceof LambdaSpliceError) {
5895
+ return { success: false, errors: [e.message] };
5896
+ }
5897
+ throw e;
5898
+ }
5899
+ if (!opts?.skipTypeParamSentinels) {
5900
+ resolveOrbitalTypeParamSentinels(
5901
+ traitsResult.data,
5902
+ entityResult.data.entity,
5903
+ resolvedAuxEntities ?? [],
5904
+ orbital.types
5905
+ );
5906
+ }
5907
+ return {
5908
+ success: true,
5909
+ data: {
5910
+ name: orbital.name,
5911
+ entity: entityResult.data.entity,
5912
+ entitySource: entityResult.data.source,
5913
+ traits: traitsResult.data,
5914
+ ...resolvedAuxEntities ? { auxiliaryEntities: resolvedAuxEntities } : {},
5915
+ pages: pagesResult.data,
5916
+ imports,
5917
+ original: orbital
5918
+ },
5919
+ warnings
5920
+ };
5921
+ }
5922
+ /**
5923
+ * Pre-resolve one imported FILE's own orbitals to completion — its own
5924
+ * `uses` (recursively, through THIS same method), its own trait refs,
5925
+ * its own sibling pulls, its own entity-ref-id rebinds — BEFORE the
5926
+ * consumer that names this alias ever folds or pulls from it. JS twin
5927
+ * of Rust's per-`uses` recursive `inline_orbital` call (`orbital-
5928
+ * compiler/src/phases/inline/mod.rs:1001-1013`): every `uses` alias's
5929
+ * OWN orbitals are inlined to completion, ahead of `ctx.add_alias_multi`
5930
+ * registering the alias for the consumer's own lookups. Without this, a
5931
+ * sibling-pull collision that is a genuine top-level PEER collision
5932
+ * INSIDE the imported file (`std-approval-request.orb`'s
5933
+ * `InlineBrowseItemBrowse6`/`…10`, both `ref: Dense.traits.
5934
+ * BrowseItemBrowse`, each embedding `@trait.DataGrid1`) never becomes
5935
+ * visible as a peer collision to the CONSUMER's own {@link
5936
+ * pullSiblingTraits} call — it arrives already flattened one level
5937
+ * deeper, sharing one JS-visible owner (see that method's own
5938
+ * drain-order doc for the full trace this ports).
5939
+ *
5940
+ * Cached per absolute `sourcePath` ({@link importFileResolveCache}) —
5941
+ * "a file imported twice resolves once" — so the cache must not bake in
5942
+ * any ONE call site's `uses { config }` override: the child resolver
5943
+ * below is seeded with this FILE's own raw, un-folded `config {}`
5944
+ * (`fileSchemaConfig`), never a folded override. A genuinely
5945
+ * call-site-configured explicit ref (`Alias.traits.X { config: {…} }`)
5946
+ * still resolves through the pre-existing lazy path
5947
+ * ({@link resolveTraitEntry} / {@link resolveTraitRefString}), which
5948
+ * this cache does not touch.
5949
+ *
5950
+ * Runs on a FRESH child `ReferenceResolver`, never `this` — `resolve()`'s
5951
+ * own `entityIdsInScope` / `schemaEntityIds` / `pulledTraitNamesByOrbital`
5952
+ * are single mutable instance state scoped to ONE active `resolve()` call
5953
+ * tree (see {@link entityIdsInScope}'s own doc: "no `resolve()` call is
5954
+ * ever active while another is on this instance"); reusing `this` here
5955
+ * would nest a `resolve()` call inside the CONSUMER's own still-active
5956
+ * `resolve()` → `resolveImports` call and corrupt that state once this
5957
+ * nested call returns. The child reuses `this.loader` (and therefore its
5958
+ * underlying `LoaderCache`) so raw parsing still dedupes exactly as
5959
+ * before. `chain` is threaded through unchanged (not cloned, matching
5960
+ * every other cross-call `chain` hand-off in this file) so genuine `uses`
5961
+ * cycles are still caught by the loader.
5962
+ *
5963
+ * Mirrors {@link resolveSchema}'s own orchestration (flatten orbital
5964
+ * references → collect local traits → seed schema entity ids →
5965
+ * per-orbital `resolve()` → `uniquifyCrossOrbitalPulledSiblings`) rather
5966
+ * than calling that free function directly — it accepts no `chain`
5967
+ * parameter, so a direct call would silently drop cycle protection one
5968
+ * level in.
5969
+ *
5970
+ * Best-effort: returns `null` (never throws) on any failure — a caller
5971
+ * falls back to the pre-existing raw-ref walk, matching this file's
5972
+ * other best-effort pre-passes (e.g. {@link precomputeReferenceFormPrimaryIds}).
5973
+ */
5974
+ async preResolveImportFile(fileOrbitals, sourcePath, fileSchemaConfig, chain) {
5975
+ const cached = this.importFileResolveCache.get(sourcePath);
5976
+ if (cached !== void 0) return cached;
5977
+ let result;
5978
+ try {
5979
+ result = await this.preResolveImportFileUncached(fileOrbitals, sourcePath, fileSchemaConfig, chain);
5980
+ } catch {
5981
+ result = null;
5982
+ }
5983
+ this.importFileResolveCache.set(sourcePath, result);
5984
+ return result;
5985
+ }
5986
+ async preResolveImportFileUncached(fileOrbitals, sourcePath, fileSchemaConfig, chain) {
5987
+ const child = new _ReferenceResolver({
5988
+ ...this.options,
5989
+ loader: this.loader,
5990
+ schemaConfig: fileSchemaConfig
5991
+ });
5992
+ const fileSchema = {
5993
+ name: sourcePath,
5994
+ orbitals: fileOrbitals,
5995
+ ...fileSchemaConfig ? { config: fileSchemaConfig } : {}
5996
+ };
5997
+ const flattenResult = await child.resolveOrbitalImports(fileSchema, { skipTypeParamSentinels: true });
5998
+ if (!flattenResult.success) return null;
5999
+ const orbitals = flattenResult.data;
6000
+ const inlineTraits = orbitals.flatMap(
6001
+ (o) => o.traits.filter((t) => typeof t !== "string" && "stateMachine" in t)
6002
+ );
6003
+ child.addLocalTraits(inlineTraits);
6004
+ child.seedSchemaEntityIds(orbitals);
6005
+ const resolved = [];
6006
+ for (const orbital of orbitals) {
6007
+ const result = await child.resolve(orbital, sourcePath, chain, { skipTypeParamSentinels: true });
6008
+ if (!result.success) return null;
6009
+ resolved.push(result.data);
6010
+ child.noteResolvedEntityIds(result.data);
6011
+ }
6012
+ return resolved;
6013
+ }
6014
+ /**
6015
+ * Resolve `uses` declarations to loaded orbitals.
6016
+ */
6017
+ async resolveImports(uses, sourcePath, chain) {
6018
+ const errors = [];
6019
+ const orbitals = /* @__PURE__ */ new Map();
6020
+ if (this.options.skipExternalLoading) {
4301
6021
  return {
4302
6022
  success: true,
4303
6023
  data: { orbitals, idIndex: /* @__PURE__ */ new Map() },
4304
6024
  warnings: ["External loading skipped"]
4305
6025
  };
4306
6026
  }
6027
+ const effectiveChain = chain ?? { push: () => null, pop: () => {
6028
+ }, clone() {
6029
+ return this;
6030
+ } };
4307
6031
  for (const use of uses) {
4308
6032
  if (orbitals.has(use.as)) {
4309
6033
  errors.push(`Duplicate import alias: ${use.as}`);
@@ -4318,18 +6042,32 @@ var ReferenceResolver = class {
4318
6042
  use.from,
4319
6043
  void 0,
4320
6044
  sourcePath,
4321
- chain
6045
+ effectiveChain
4322
6046
  );
4323
6047
  if (!loadResult.success) {
4324
6048
  errors.push(`Failed to load "${use.from}" as "${use.as}": ${loadResult.error}`);
4325
6049
  continue;
4326
6050
  }
6051
+ const fileOrbitals = loadResult.data.orbitals ?? [loadResult.data.orbital];
6052
+ const resolvedOrbitals = await this.preResolveImportFile(
6053
+ fileOrbitals,
6054
+ loadResult.data.sourcePath,
6055
+ loadResult.data.schemaConfig,
6056
+ effectiveChain
6057
+ );
4327
6058
  orbitals.set(use.as, {
4328
6059
  alias: use.as,
4329
6060
  from: use.from,
4330
6061
  orbital: loadResult.data.orbital,
4331
- orbitals: loadResult.data.orbitals ?? [loadResult.data.orbital],
4332
- sourcePath: loadResult.data.sourcePath
6062
+ orbitals: fileOrbitals,
6063
+ sourcePath: loadResult.data.sourcePath,
6064
+ ...resolvedOrbitals ? { resolvedOrbitals } : {},
6065
+ ...loadResult.data.schemaConfig ? {
6066
+ schemaConfig: forwardConsumerAppKnobs(
6067
+ foldUseConfigOverride(loadResult.data.schemaConfig, use.config, use),
6068
+ this.schemaConfig
6069
+ )
6070
+ } : {}
4333
6071
  });
4334
6072
  }
4335
6073
  if (errors.length > 0) {
@@ -4420,14 +6158,79 @@ var ReferenceResolver = class {
4420
6158
  }
4421
6159
  return entityRef;
4422
6160
  }
6161
+ /**
6162
+ * The ATOM's OWN trait `alias.traits.traitName` resolves to — no call-site
6163
+ * overrides applied (`callSiteConfig` omitted) — so its DECLARED
6164
+ * `linkedEntity` can drive {@link buildAliasEntityRenames}. Same lookup
6165
+ * `resolveTraitRefString`'s imported branch performs to find the base
6166
+ * `trait` before any rebind, factored out so the pre-pass and the main
6167
+ * resolve share one lookup rather than two. `null` when the alias or
6168
+ * trait cannot be found — the pre-pass simply skips that entry, same as a
6169
+ * lookup failure anywhere else in this best-effort pass.
6170
+ */
6171
+ async atomOwnTrait(alias, traitName, imports, chain) {
6172
+ const imported = imports.orbitals.get(alias);
6173
+ if (!imported) return null;
6174
+ for (const o of importedOrbitals(imported)) {
6175
+ const entry = findTraitEntryInOrbital(o, traitName);
6176
+ if (!entry) continue;
6177
+ const entryResolved = await this.resolveTraitEntry(imported, entry, traitName, chain, imports);
6178
+ return entryResolved.success ? entryResolved.data.trait : null;
6179
+ }
6180
+ return null;
6181
+ }
6182
+ /**
6183
+ * Alias-scoped cross-trait entity-rebind propagation — JS twin of Rust's
6184
+ * `alias_entity_renames` pre-pass (`inline/trait.rs::inline_traits`). One
6185
+ * explicit pull's `linkedEntity` override (`Button.traits.ButtonRender ->
6186
+ * Route`) establishes a rebind (the atom's OWN declared `linkedEntity` →
6187
+ * the override) that a SIBLING pull from the SAME alias with NO rebind of
6188
+ * its own (`Button.traits.ButtonRender`, no `->`) never sees through
6189
+ * {@link applyLinkedEntityRename} — that call only ever knows ITS OWN
6190
+ * delta. But the no-rebind pull's `entityRefIds` side-map can still carry
6191
+ * a SECONDARY, positional reference to that same atom-local name (a
6192
+ * "self" entry keyed by the atom's own bound entity), which nothing else
6193
+ * rewrites — `std-api-gateway`'s `RouteOrbital.InlineButtonRender3`
6194
+ * (`Button.traits.ButtonRender`, no rebind) recovers `entityRefIds`'
6195
+ * `ButtonItem` key to `Route` only because `InlineButtonRender9` (`Button.
6196
+ * traits.ButtonRender -> Route`) established the rebind earlier in the
6197
+ * SAME orbital's `traits` list. Scanned once per orbital, over every
6198
+ * EXPLICIT `Alias.traits.X -> Y` entry in `traitRefs`: `(alias, atom's
6199
+ * declared linkedEntity) -> override`. First rebind for a given `(alias,
6200
+ * atomLocal)` pair wins (`Map.set` only on a fresh key), matching Rust's
6201
+ * `.or_insert_with`.
6202
+ */
6203
+ async buildAliasEntityRenames(traitRefs, imports, chain) {
6204
+ const out = /* @__PURE__ */ new Map();
6205
+ for (const traitRef of traitRefs) {
6206
+ if (typeof traitRef === "string" || "stateMachine" in traitRef || !("ref" in traitRef)) continue;
6207
+ const refObj = traitRef;
6208
+ if (!refObj.linkedEntity) continue;
6209
+ const parsed = parseImportedTraitRef(refObj.ref);
6210
+ if (!parsed) continue;
6211
+ const atomTrait = await this.atomOwnTrait(parsed.alias, parsed.traitName, imports, chain);
6212
+ const atomLocal = atomTrait?.linkedEntity;
6213
+ if (!atomLocal || atomLocal === refObj.linkedEntity) continue;
6214
+ const forAlias = out.get(parsed.alias) ?? /* @__PURE__ */ new Map();
6215
+ if (!forAlias.has(atomLocal)) forAlias.set(atomLocal, refObj.linkedEntity);
6216
+ out.set(parsed.alias, forAlias);
6217
+ }
6218
+ return out;
6219
+ }
4423
6220
  /**
4424
6221
  * Resolve trait references.
4425
6222
  */
4426
- resolveTraits(traitRefs, imports) {
6223
+ async resolveTraits(traitRefs, imports, chain, orbitalConfig) {
4427
6224
  const errors = [];
4428
6225
  const resolved = [];
6226
+ const embedCtx = {
6227
+ traitRefs,
6228
+ embedGraph: buildEmbedGraph(traitRefs),
6229
+ orbitalConfig
6230
+ };
6231
+ const aliasEntityRenames = await this.buildAliasEntityRenames(traitRefs, imports, chain);
4429
6232
  for (const traitRef of traitRefs) {
4430
- const result = this.resolveTraitRef(traitRef, imports);
6233
+ const result = await this.resolveTraitRef(traitRef, imports, chain, embedCtx, aliasEntityRenames);
4431
6234
  if (!result.success) {
4432
6235
  errors.push(...result.errors);
4433
6236
  } else {
@@ -4458,6 +6261,99 @@ var ReferenceResolver = class {
4458
6261
  this.sourceImportsCache.set(key, result.data);
4459
6262
  return result.data;
4460
6263
  }
6264
+ /**
6265
+ * The concrete base `Trait` a trait entry (found under `localName` in
6266
+ * `imported`) resolves to — an inline entry resolves its own
6267
+ * `@config.<knob>` emit refs against `callSiteConfig` (the ref hop that
6268
+ * led here, e.g. `std-approval-gate`'s `CloseButton = Button.traits.
6269
+ * ButtonRender { config: { action: CLOSE } }` resolving `ButtonRender`
6270
+ * itself); a ref-shaped entry (an atom's sub-view declared `trait X =
6271
+ * Y.traits.Z {…}` INSIDE the source atom, e.g. `std-note`'s
6272
+ * `NoteSubpages = RecordDetail.traits.RecordItemDetail`) recurses through
6273
+ * that source's own import scope via {@link importsOfSource} — the
6274
+ * entry's own declared overrides are its call site. Single owner for
6275
+ * `pullSiblingTraits`' sibling pull and `resolveTraitRefString`'s
6276
+ * imported branch, both of which used to reach `findTraitInOrbital`'s
6277
+ * `stateMachine`-gated lookup (its ref arm did nothing), silently failing
6278
+ * to resolve a nested ref (ledger (i)).
6279
+ *
6280
+ * `callSiteConfig` MUST be threaded by any caller that goes on to fold a
6281
+ * call-site config of its own onto the returned trait
6282
+ * (`resolveTraitRefString`'s ref-imported branch, ledger (o)) — the
6283
+ * `@config.<knob>` emit-name substitution is destructive
6284
+ * (`resolveConfigRefEmitNames` rewrites the marker to a concrete literal
6285
+ * in place), so resolving it here with the WRONG effective config
6286
+ * (the atom's own bare default, absent the override) permanently loses
6287
+ * the override: a second `resolveConfigRefEmitNames` call downstream sees
6288
+ * no more `@config.<knob>` marker to substitute and silently no-ops.
6289
+ * `pullSiblingTraits` (no further fold of its own) omits it, matching its
6290
+ * prior no-callSiteConfig behavior exactly.
6291
+ */
6292
+ async resolveTraitEntry(imported, entry, localName, chain, homeImports, callSiteConfig) {
6293
+ if ("stateMachine" in entry) {
6294
+ const { trait, errors } = resolveConfigRefEmitNames(entry, callSiteConfig);
6295
+ if (errors.length > 0) return { success: false, errors };
6296
+ return {
6297
+ success: true,
6298
+ data: { trait, embedScope: { imports: homeImports, alias: imported.alias } },
6299
+ warnings: []
6300
+ };
6301
+ }
6302
+ const refObj = entry;
6303
+ const srcImports = await this.importsOfSource(imported, chain);
6304
+ if (!srcImports) {
6305
+ return {
6306
+ success: false,
6307
+ errors: [
6308
+ `Trait "${localName}" in imported behavior could not resolve its own import scope to follow ref "${refObj.ref}"`
6309
+ ]
6310
+ };
6311
+ }
6312
+ const nested = await this.resolveTraitRefString(
6313
+ refObj.ref,
6314
+ srcImports,
6315
+ chain,
6316
+ refObj.config,
6317
+ refObj.linkedEntity,
6318
+ refObj.name ?? localName,
6319
+ refObj.events,
6320
+ refObj.listens,
6321
+ refObj.refId,
6322
+ refObj.typeArgs
6323
+ );
6324
+ if (!nested.success) return nested;
6325
+ return {
6326
+ success: true,
6327
+ data: {
6328
+ trait: nested.data.trait,
6329
+ embedScope: nested.data.embedScope ?? { imports: srcImports, alias: imported.alias },
6330
+ ...nested.data.typeArgs !== void 0 ? { typeArgs: nested.data.typeArgs } : {}
6331
+ },
6332
+ warnings: nested.warnings
6333
+ };
6334
+ }
6335
+ /**
6336
+ * The concrete `Page` a page entry (found under `localName` in `imported`)
6337
+ * resolves to — an inline `Page` passes through; a `PageRefObject` (a
6338
+ * re-exported page declared inside the SOURCE orbital's own `pages {}`,
6339
+ * {@link findPageEntryInOrbital}'s ref arm) recurses through that source's
6340
+ * own import scope via {@link importsOfSource} and
6341
+ * {@link resolvePageRefObject} — the page twin of {@link resolveTraitEntry}
6342
+ * (nested refs, ledger (i)).
6343
+ */
6344
+ async resolvePageEntry(imported, entry, chain) {
6345
+ if (!("ref" in entry)) return { success: true, data: { page: entry }, warnings: [] };
6346
+ const srcImports = await this.importsOfSource(imported, chain);
6347
+ if (!srcImports) {
6348
+ return {
6349
+ success: false,
6350
+ errors: [`Page in imported behavior could not resolve its own import scope to follow ref "${entry.ref}"`]
6351
+ };
6352
+ }
6353
+ const nested = await this.resolvePageRefObject(entry, srcImports, chain);
6354
+ if (!nested.success) return nested;
6355
+ return { success: true, data: { page: nested.data.page }, warnings: nested.warnings };
6356
+ }
4461
6357
  /**
4462
6358
  * Sibling-trait auto-pull — the JS twin of the compiler's
4463
6359
  * `phases/inline/trait.rs` pass, appending to `resolved` in place.
@@ -4479,7 +6375,8 @@ var ReferenceResolver = class {
4479
6375
  * source name; later owners pull under `<Owner><Sibling>` — unique by
4480
6376
  * construction, since owner names are unique within the orbital.
4481
6377
  */
4482
- async pullSiblingTraits(resolved, imports, chain) {
6378
+ async pullSiblingTraits(resolved, imports, chain, orbitalConfig) {
6379
+ const auxEntities = [];
4483
6380
  const work = [];
4484
6381
  const ownerSubs = /* @__PURE__ */ new Map();
4485
6382
  const subsFor = (owner) => {
@@ -4495,18 +6392,48 @@ var ReferenceResolver = class {
4495
6392
  const owner = rt.trait.name;
4496
6393
  subsFor(owner).set(rt.source.traitName, owner);
4497
6394
  for (const sibling of traitEmbedNamesOf(rt.trait)) {
4498
- work.push({ alias: rt.source.alias, sibling, linkedEntity: rt.linkedEntity, parent: owner, owner });
6395
+ work.push({
6396
+ alias: rt.source.alias,
6397
+ fallback: rt.embedScope,
6398
+ sibling,
6399
+ linkedEntity: rt.linkedEntity,
6400
+ parent: owner,
6401
+ owner,
6402
+ // Top-level SEED — always starts with the raw-walk-first gate
6403
+ // (see {@link PullItem.preResolvedScope}'s own doc).
6404
+ preResolvedScope: void 0
6405
+ });
4499
6406
  }
4500
6407
  }
4501
- if (work.length === 0) return [];
6408
+ if (work.length === 0) return { errors: [], auxEntities: [], pulledNames: /* @__PURE__ */ new Set() };
4502
6409
  const errors = [];
4503
6410
  const consumerDeclared = new Set(resolved.map((r) => r.trait.name).filter(Boolean));
6411
+ const consumerDeclaredProvenance = /* @__PURE__ */ new Map();
6412
+ for (const rt of resolved) {
6413
+ if (rt.source.type === "imported" && rt.trait.name) {
6414
+ consumerDeclaredProvenance.set(rt.trait.name, { alias: rt.source.alias, traitName: rt.source.traitName });
6415
+ }
6416
+ }
4504
6417
  const seen = new Set(consumerDeclared);
4505
6418
  const visited = /* @__PURE__ */ new Set();
4506
6419
  const pulledAs = /* @__PURE__ */ new Map();
4507
6420
  const ownerOf = /* @__PURE__ */ new Map();
6421
+ const parentOf = /* @__PURE__ */ new Map();
4508
6422
  const parentRewrites = /* @__PURE__ */ new Map();
4509
6423
  const pulled = [];
6424
+ const embedderChain2 = (finalName) => {
6425
+ const chain2 = [];
6426
+ const seenNames = /* @__PURE__ */ new Set();
6427
+ let cur = finalName;
6428
+ while (cur !== void 0 && !seenNames.has(cur)) {
6429
+ seenNames.add(cur);
6430
+ const t = resolved.find((r) => r.trait.name === cur)?.trait ?? pulled.find((r) => r.trait.name === cur)?.trait;
6431
+ if (!t) break;
6432
+ if (t.config) chain2.push(t.config);
6433
+ cur = parentOf.get(cur);
6434
+ }
6435
+ return chain2;
6436
+ };
4510
6437
  const noteRewrite = (parent, from, to) => {
4511
6438
  let m = parentRewrites.get(parent);
4512
6439
  if (!m) {
@@ -4516,8 +6443,8 @@ var ReferenceResolver = class {
4516
6443
  m.set(from, to);
4517
6444
  };
4518
6445
  for (let item = work.pop(); item !== void 0; item = work.pop()) {
4519
- const { alias, sibling, linkedEntity, parent, owner } = item;
4520
- const pullKey = `${alias}\0${sibling}\0${owner}`;
6446
+ const { alias, fallback, sibling, linkedEntity, parent, owner, preResolvedScope } = item;
6447
+ const pullKey = `${alias} ${sibling} ${owner} ${parent}`;
4521
6448
  const existing = pulledAs.get(pullKey);
4522
6449
  if (existing !== void 0) {
4523
6450
  if (existing !== sibling) noteRewrite(parent, sibling, existing);
@@ -4525,73 +6452,122 @@ var ReferenceResolver = class {
4525
6452
  }
4526
6453
  let finalName = sibling;
4527
6454
  if (seen.has(sibling)) {
4528
- if (consumerDeclared.has(sibling)) continue;
4529
- finalName = `${owner}${sibling}`;
6455
+ const provenance = consumerDeclaredProvenance.get(sibling);
6456
+ if (consumerDeclared.has(sibling) && provenance?.alias === alias && provenance.traitName === sibling) {
6457
+ continue;
6458
+ }
6459
+ finalName = `${parent}${sibling}`;
4530
6460
  if (seen.has(finalName)) continue;
4531
6461
  }
4532
6462
  if (visited.has(pullKey)) continue;
4533
6463
  visited.add(pullKey);
4534
- const imported = imports.orbitals.get(alias);
4535
- if (!imported) continue;
4536
- let atomEntry = null;
4537
- for (const o of importedOrbitals(imported)) {
4538
- atomEntry = findTraitEntryInOrbital(o, sibling);
4539
- if (atomEntry) break;
4540
- }
4541
- if (!atomEntry) continue;
6464
+ let searchImports = imports;
6465
+ let searchAlias = alias;
4542
6466
  let atomTrait;
4543
- if ("stateMachine" in atomEntry) {
4544
- const { trait: cfgResolved, errors: cfgErrors } = resolveConfigRefEmitNames(
4545
- atomEntry
4546
- );
4547
- if (cfgErrors.length > 0) {
4548
- errors.push(...cfgErrors);
4549
- continue;
6467
+ let childScope;
6468
+ let foundTypeArgs;
6469
+ let childPreResolvedScope;
6470
+ if (preResolvedScope) {
6471
+ const found = preResolvedScope.traits.find((rt) => rt.trait.name === sibling);
6472
+ if (found) {
6473
+ atomTrait = found.trait;
6474
+ childScope = { imports: searchImports, alias: searchAlias };
6475
+ foundTypeArgs = found.typeArgs;
6476
+ childPreResolvedScope = preResolvedScope;
4550
6477
  }
4551
- atomTrait = cfgResolved;
4552
- } else {
4553
- const srcImports = await this.importsOfSource(imported, chain);
4554
- if (!srcImports) continue;
4555
- const refObj = atomEntry;
4556
- const nested = this.resolveTraitRefString(
4557
- refObj.ref,
4558
- srcImports,
4559
- refObj.config,
4560
- refObj.linkedEntity,
4561
- refObj.name ?? sibling,
4562
- refObj.events,
4563
- refObj.listens,
4564
- refObj.refId
4565
- );
4566
- if (!nested.success) {
4567
- errors.push(...nested.errors);
4568
- continue;
6478
+ }
6479
+ if (!atomTrait) {
6480
+ let imported = imports.orbitals.get(alias);
6481
+ let atomEntry = null;
6482
+ let atomOrbitalIndex = -1;
6483
+ if (imported) {
6484
+ const list = importedOrbitals(imported);
6485
+ for (let i = 0; i < list.length; i++) {
6486
+ atomEntry = findTraitEntryInOrbital(list[i], sibling);
6487
+ if (atomEntry) {
6488
+ atomOrbitalIndex = i;
6489
+ break;
6490
+ }
6491
+ }
6492
+ }
6493
+ if (!atomEntry && fallback) {
6494
+ const fbImported = fallback.imports.orbitals.get(fallback.alias);
6495
+ if (fbImported) {
6496
+ const list = importedOrbitals(fbImported);
6497
+ for (let i = 0; i < list.length; i++) {
6498
+ atomEntry = findTraitEntryInOrbital(list[i], sibling);
6499
+ if (atomEntry) {
6500
+ imported = fbImported;
6501
+ searchImports = fallback.imports;
6502
+ searchAlias = fallback.alias;
6503
+ atomOrbitalIndex = i;
6504
+ break;
6505
+ }
6506
+ }
6507
+ }
6508
+ }
6509
+ if (!imported || !atomEntry) continue;
6510
+ const preResolvedOrbital = imported.resolvedOrbitals?.[atomOrbitalIndex];
6511
+ const preResolved = preResolvedOrbital?.traits.find((rt) => rt.trait.name === sibling);
6512
+ if (preResolved) {
6513
+ atomTrait = preResolved.trait;
6514
+ childScope = { imports: searchImports, alias: searchAlias };
6515
+ foundTypeArgs = preResolved.typeArgs;
6516
+ childPreResolvedScope = preResolvedOrbital;
6517
+ } else {
6518
+ const entryResolved = await this.resolveTraitEntry(imported, atomEntry, sibling, chain, searchImports);
6519
+ if (!entryResolved.success) {
6520
+ errors.push(...entryResolved.errors);
6521
+ continue;
6522
+ }
6523
+ atomTrait = entryResolved.data.trait;
6524
+ childScope = entryResolved.data.embedScope;
6525
+ foundTypeArgs = entryResolved.data.typeArgs;
4569
6526
  }
4570
- atomTrait = nested.data.trait;
4571
6527
  }
4572
- const embedder = resolved.find((r) => r.trait.name === parent)?.trait ?? pulled.find((r) => r.trait.name === parent)?.trait;
4573
- let copy = resolveForwardedSiblingConfig(
4574
- applyLinkedEntityRename(atomTrait, linkedEntity),
4575
- embedder
6528
+ if (!atomTrait || !childScope) continue;
6529
+ const nextFallback = childScope.alias === searchAlias && childScope.imports === searchImports ? void 0 : childScope;
6530
+ let copy = resolveForwardedSiblingConfigFrom(
6531
+ applyLinkedEntityRename(atomTrait, linkedEntity, this.entityIdsInScope),
6532
+ embedderChain2(parent),
6533
+ orbitalConfig,
6534
+ this.schemaConfig
4576
6535
  );
4577
6536
  if (finalName !== sibling) {
4578
6537
  copy = { ...copy, name: finalName };
4579
6538
  noteRewrite(parent, sibling, finalName);
4580
6539
  }
6540
+ const childParent = childPreResolvedScope ? parent : finalName;
4581
6541
  for (const next of traitEmbedNamesOf(copy)) {
4582
- work.push({ alias, sibling: next, linkedEntity, parent: finalName, owner });
6542
+ work.push({
6543
+ alias,
6544
+ fallback: nextFallback,
6545
+ sibling: next,
6546
+ linkedEntity,
6547
+ parent: childParent,
6548
+ owner,
6549
+ preResolvedScope: childPreResolvedScope
6550
+ });
4583
6551
  }
4584
6552
  pulledAs.set(pullKey, finalName);
4585
6553
  subsFor(owner).set(sibling, finalName);
4586
6554
  ownerOf.set(finalName, owner);
6555
+ parentOf.set(finalName, parent);
4587
6556
  seen.add(finalName);
4588
6557
  pulled.push({
4589
6558
  trait: copy,
4590
6559
  source: { type: "imported", alias, traitName: sibling },
4591
- ...linkedEntity !== void 0 ? { linkedEntity } : {}
6560
+ ...linkedEntity !== void 0 ? { linkedEntity } : {},
6561
+ ...foundTypeArgs !== void 0 ? { typeArgs: foundTypeArgs } : {}
4592
6562
  });
6563
+ if (copy.linkedEntity !== void 0) {
6564
+ const aux = entityByNameForAlias(imports, alias, copy.linkedEntity) ?? entityByNameAnyAlias(imports, copy.linkedEntity);
6565
+ if (aux) auxEntities.push(aux);
6566
+ }
6567
+ }
6568
+ if (pulled.length === 0 && parentRewrites.size === 0) {
6569
+ return { errors, auxEntities, pulledNames: /* @__PURE__ */ new Set() };
4593
6570
  }
4594
- if (pulled.length === 0 && parentRewrites.size === 0) return errors;
4595
6571
  const applyRewrites = (rt) => {
4596
6572
  const subs = rt.trait.name ? parentRewrites.get(rt.trait.name) : void 0;
4597
6573
  if (subs) rt.trait = renameTraitEmbeds(rt.trait, subs);
@@ -4603,39 +6579,29 @@ var ReferenceResolver = class {
4603
6579
  if (rt.trait.name) idByName.set(rt.trait.name, rt.trait.id);
4604
6580
  }
4605
6581
  for (const rt of pulled) {
4606
- const listens = rt.trait.listens;
4607
6582
  const owner = rt.trait.name ? ownerOf.get(rt.trait.name) : void 0;
4608
6583
  const subs = owner ? ownerSubs.get(owner) : void 0;
4609
- if (!listens || listens.length === 0 || !subs) continue;
4610
- let changed = false;
4611
- const nextListens = listens.map((listen) => {
4612
- const source = listen.source;
4613
- if (!source || source.kind !== "trait") return listen;
4614
- const target = subs.get(source.trait);
4615
- if (target === void 0 || target === source.trait) return listen;
4616
- changed = true;
4617
- const traitId = idByName.get(target);
4618
- return {
4619
- ...listen,
4620
- source: { kind: "trait", trait: target, ...traitId ? { traitId } : {} }
4621
- };
4622
- });
4623
- if (changed) rt.trait = { ...rt.trait, listens: nextListens };
6584
+ if (!subs) continue;
6585
+ rt.trait = rewriteListenSources(rt.trait, subs, idByName);
4624
6586
  }
4625
6587
  refResolverLog.info("sibling-pull", {
4626
6588
  pulled: pulled.map((p) => ({
4627
6589
  trait: p.trait.name,
4628
6590
  owner: p.trait.name ? ownerOf.get(p.trait.name) : void 0,
6591
+ parent: p.trait.name ? parentOf.get(p.trait.name) : void 0,
4629
6592
  linkedEntity: p.linkedEntity ?? p.trait.linkedEntity
4630
6593
  }))
4631
6594
  });
4632
6595
  resolved.push(...pulled);
4633
- return errors;
6596
+ const pulledNames = new Set(
6597
+ pulled.map((p) => p.trait.name).filter((n) => Boolean(n))
6598
+ );
6599
+ return { errors, auxEntities, pulledNames };
4634
6600
  }
4635
6601
  /**
4636
6602
  * Resolve a single trait reference.
4637
6603
  */
4638
- resolveTraitRef(traitRef, imports) {
6604
+ async resolveTraitRef(traitRef, imports, chain, embedCtx, aliasEntityRenames) {
4639
6605
  if (typeof traitRef !== "string" && "stateMachine" in traitRef) {
4640
6606
  const { trait: resolvedInline, errors } = resolveConfigRefEmitNames(traitRef);
4641
6607
  if (errors.length > 0) {
@@ -4655,16 +6621,33 @@ var ReferenceResolver = class {
4655
6621
  return this.resolveTraitRefString(
4656
6622
  refObj.ref,
4657
6623
  imports,
6624
+ chain,
4658
6625
  refObj.config,
4659
6626
  refObj.linkedEntity,
4660
6627
  refObj.name,
4661
6628
  refObj.events,
4662
6629
  refObj.listens,
4663
- refObj.refId
6630
+ refObj.refId,
6631
+ refObj.typeArgs,
6632
+ embedCtx,
6633
+ aliasEntityRenames
4664
6634
  );
4665
6635
  }
4666
6636
  if (typeof traitRef === "string") {
4667
- return this.resolveTraitRefString(traitRef, imports);
6637
+ return this.resolveTraitRefString(
6638
+ traitRef,
6639
+ imports,
6640
+ chain,
6641
+ void 0,
6642
+ void 0,
6643
+ void 0,
6644
+ void 0,
6645
+ void 0,
6646
+ void 0,
6647
+ void 0,
6648
+ embedCtx,
6649
+ aliasEntityRenames
6650
+ );
4668
6651
  }
4669
6652
  return {
4670
6653
  success: false,
@@ -4674,8 +6657,10 @@ var ReferenceResolver = class {
4674
6657
  /**
4675
6658
  * Resolve a trait reference string.
4676
6659
  */
4677
- resolveTraitRefString(ref, imports, config, linkedEntity, overrideName, eventRenames, listensOverride, refId) {
6660
+ async resolveTraitRefString(ref, imports, chain, config, linkedEntity, overrideName, eventRenames, listensOverride, refId, typeArgs, embedCtx, aliasEntityRenames) {
4678
6661
  const parsed = parseImportedTraitRef(ref);
6662
+ const localName = overrideName ?? (parsed ? parsed.traitName : ref);
6663
+ const resolvedConfig = config && embedCtx ? resolveEmbedderConfigForward(config, localName, embedCtx, this.schemaConfig) : config;
4679
6664
  if (parsed) {
4680
6665
  const imported = imports.orbitals.get(parsed.alias);
4681
6666
  if (!imported) {
@@ -4687,9 +6672,27 @@ var ReferenceResolver = class {
4687
6672
  };
4688
6673
  }
4689
6674
  let trait = null;
4690
- for (const o of importedOrbitals(imported)) {
4691
- trait = this.findTraitInOrbital(o, parsed.traitName, refId, imports.idIndex);
4692
- if (trait) break;
6675
+ let embedScope = { imports, alias: parsed.alias };
6676
+ const idEntry = refId ? imports.idIndex?.get(refId) : void 0;
6677
+ if (idEntry && idEntry.kind === "trait") {
6678
+ trait = idEntry.node;
6679
+ } else {
6680
+ for (const o of importedOrbitals(imported)) {
6681
+ const entry = findTraitEntryInOrbital(o, parsed.traitName);
6682
+ if (!entry) continue;
6683
+ const entryResolved = await this.resolveTraitEntry(
6684
+ imported,
6685
+ entry,
6686
+ parsed.traitName,
6687
+ chain,
6688
+ imports,
6689
+ resolvedConfig
6690
+ );
6691
+ if (!entryResolved.success) return entryResolved;
6692
+ trait = entryResolved.data.trait;
6693
+ embedScope = entryResolved.data.embedScope;
6694
+ break;
6695
+ }
4693
6696
  }
4694
6697
  if (!trait) {
4695
6698
  const available = importedOrbitals(imported).flatMap((o) => this.listTraitsInOrbital(o));
@@ -4700,15 +6703,36 @@ var ReferenceResolver = class {
4700
6703
  ]
4701
6704
  };
4702
6705
  }
6706
+ if (embedCtx && trait.config) {
6707
+ const homeResolvedConfig = resolveConfigForwards(
6708
+ trait.config,
6709
+ embedderChain(localName, embedCtx.traitRefs, embedCtx.embedGraph),
6710
+ embedCtx.orbitalConfig,
6711
+ homeOrbitalConfigForTrait(imported, parsed.traitName),
6712
+ imported.schemaConfig,
6713
+ this.schemaConfig
6714
+ );
6715
+ if (homeResolvedConfig) {
6716
+ trait = { ...trait, config: homeResolvedConfig };
6717
+ }
6718
+ }
4703
6719
  const baseTrait = overrideName ? { ...trait, name: overrideName } : trait;
4704
- const { trait: configResolvedTrait, errors: configRefErrors } = resolveConfigRefEmitNames(baseTrait, config);
6720
+ const { trait: configResolvedTrait, errors: configRefErrors, resolvedKnobs } = resolveConfigRefEmitNames(baseTrait, resolvedConfig);
4705
6721
  if (configRefErrors.length > 0) {
4706
6722
  return { success: false, errors: configRefErrors };
4707
6723
  }
4708
- const reboundTrait = applyLinkedEntityRename(configResolvedTrait, linkedEntity);
4709
- const renamedTrait = applyEventRenames(reboundTrait, eventRenames);
4710
- const renamedConfig = applyEventRenamesToCallSiteConfig(config, reboundTrait.config, eventRenames);
4711
- const finalTrait = listensOverride !== void 0 ? { ...renamedTrait, listens: listensOverride } : renamedTrait;
6724
+ const reboundTrait = applyLinkedEntityRename(configResolvedTrait, linkedEntity, this.entityIdsInScope);
6725
+ const aliasSubs = aliasEntityRenames?.get(parsed.alias);
6726
+ const aliasReboundTrait = aliasSubs ? applyAliasEntityRenames(reboundTrait, aliasSubs, this.entityIdsInScope) : reboundTrait;
6727
+ const renamedTrait = applyEventRenames(aliasReboundTrait, eventRenames);
6728
+ const foldedTrait = foldEventRenameOntoDeclaredKnobs(
6729
+ renamedTrait,
6730
+ resolvedKnobValues(baseTrait, configResolvedTrait, resolvedKnobs),
6731
+ eventRenames
6732
+ );
6733
+ const renamedConfig = applyEventRenamesToCallSiteConfig(resolvedConfig, reboundTrait.config, eventRenames);
6734
+ const configFoldedTrait = foldCallSiteConfigOntoTrait(foldedTrait, renamedConfig);
6735
+ const finalTrait = listensOverride !== void 0 ? { ...configFoldedTrait, listens: listensOverride } : configFoldedTrait;
4712
6736
  if (listensOverride !== void 0) {
4713
6737
  refResolverLog.info("listens-override:imported", {
4714
6738
  trait: finalTrait.name,
@@ -4723,7 +6747,9 @@ var ReferenceResolver = class {
4723
6747
  trait: finalTrait,
4724
6748
  source: { type: "imported", alias: parsed.alias, traitName: parsed.traitName },
4725
6749
  config: renamedConfig,
4726
- linkedEntity
6750
+ linkedEntity,
6751
+ embedScope,
6752
+ ...typeArgs !== void 0 ? { typeArgs } : {}
4727
6753
  },
4728
6754
  warnings: []
4729
6755
  };
@@ -4731,14 +6757,20 @@ var ReferenceResolver = class {
4731
6757
  const localTrait = (refId && this.localTraitsById.get(refId)) ?? this.localTraits.get(ref);
4732
6758
  if (localTrait) {
4733
6759
  const baseLocal = overrideName ? { ...localTrait, name: overrideName } : localTrait;
4734
- const { trait: configResolvedLocal, errors: localConfigRefErrors } = resolveConfigRefEmitNames(baseLocal, config);
6760
+ const { trait: configResolvedLocal, errors: localConfigRefErrors, resolvedKnobs: localResolvedKnobs } = resolveConfigRefEmitNames(baseLocal, resolvedConfig);
4735
6761
  if (localConfigRefErrors.length > 0) {
4736
6762
  return { success: false, errors: localConfigRefErrors };
4737
6763
  }
4738
- const reboundLocal = applyLinkedEntityRename(configResolvedLocal, linkedEntity);
6764
+ const reboundLocal = applyLinkedEntityRename(configResolvedLocal, linkedEntity, this.entityIdsInScope);
4739
6765
  const renamedLocalTrait = applyEventRenames(reboundLocal, eventRenames);
4740
- const renamedLocalConfig = applyEventRenamesToCallSiteConfig(config, reboundLocal.config, eventRenames);
4741
- const finalLocalTrait = listensOverride !== void 0 ? { ...renamedLocalTrait, listens: listensOverride } : renamedLocalTrait;
6766
+ const foldedLocalTrait = foldEventRenameOntoDeclaredKnobs(
6767
+ renamedLocalTrait,
6768
+ resolvedKnobValues(baseLocal, configResolvedLocal, localResolvedKnobs),
6769
+ eventRenames
6770
+ );
6771
+ const renamedLocalConfig = applyEventRenamesToCallSiteConfig(resolvedConfig, reboundLocal.config, eventRenames);
6772
+ const configFoldedLocalTrait = foldCallSiteConfigOntoTrait(foldedLocalTrait, renamedLocalConfig);
6773
+ const finalLocalTrait = listensOverride !== void 0 ? { ...configFoldedLocalTrait, listens: listensOverride } : configFoldedLocalTrait;
4742
6774
  if (listensOverride !== void 0) {
4743
6775
  refResolverLog.info("listens-override:local", {
4744
6776
  trait: finalLocalTrait.name,
@@ -4753,7 +6785,8 @@ var ReferenceResolver = class {
4753
6785
  trait: finalLocalTrait,
4754
6786
  source: { type: "local", name: ref },
4755
6787
  config: renamedLocalConfig,
4756
- linkedEntity
6788
+ linkedEntity,
6789
+ ...typeArgs !== void 0 ? { typeArgs } : {}
4757
6790
  },
4758
6791
  warnings: []
4759
6792
  };
@@ -4765,31 +6798,6 @@ var ReferenceResolver = class {
4765
6798
  ]
4766
6799
  };
4767
6800
  }
4768
- /**
4769
- * Find a trait in an orbital by name. Id-primary: when the calling ref
4770
- * carries a `refId` and the id index has a matching trait entry, return it
4771
- * directly — else fall back to the existing name match unchanged.
4772
- */
4773
- findTraitInOrbital(orbital, traitName, refId, idIndex) {
4774
- if (refId && idIndex) {
4775
- const entry = idIndex.get(refId);
4776
- if (entry && entry.kind === "trait") {
4777
- return entry.node;
4778
- }
4779
- }
4780
- for (const traitRef of orbital.traits) {
4781
- if (typeof traitRef !== "string" && "stateMachine" in traitRef) {
4782
- if (traitRef.name === traitName) {
4783
- return traitRef;
4784
- }
4785
- }
4786
- if (typeof traitRef !== "string" && "ref" in traitRef) {
4787
- const refObj = traitRef;
4788
- if (refObj.ref === traitName || refObj.name === traitName) ;
4789
- }
4790
- }
4791
- return null;
4792
- }
4793
6801
  /**
4794
6802
  * List trait names in an orbital.
4795
6803
  */
@@ -4805,11 +6813,11 @@ var ReferenceResolver = class {
4805
6813
  /**
4806
6814
  * Resolve page references.
4807
6815
  */
4808
- resolvePages(pageRefs, imports) {
6816
+ async resolvePages(pageRefs, imports, chain) {
4809
6817
  const errors = [];
4810
6818
  const resolved = [];
4811
6819
  for (const pageRef of pageRefs) {
4812
- const result = this.resolvePageRef(pageRef, imports);
6820
+ const result = await this.resolvePageRef(pageRef, imports, chain);
4813
6821
  if (!result.success) {
4814
6822
  errors.push(...result.errors);
4815
6823
  } else {
@@ -4824,7 +6832,7 @@ var ReferenceResolver = class {
4824
6832
  /**
4825
6833
  * Resolve a single page reference.
4826
6834
  */
4827
- resolvePageRef(pageRef, imports) {
6835
+ async resolvePageRef(pageRef, imports, chain) {
4828
6836
  if (!isPageReference(pageRef)) {
4829
6837
  return {
4830
6838
  success: true,
@@ -4837,10 +6845,10 @@ var ReferenceResolver = class {
4837
6845
  };
4838
6846
  }
4839
6847
  if (isPageReferenceString(pageRef)) {
4840
- return this.resolvePageRefString(pageRef, imports);
6848
+ return this.resolvePageRefString(pageRef, imports, chain);
4841
6849
  }
4842
6850
  if (isPageReferenceObject(pageRef)) {
4843
- return this.resolvePageRefObject(pageRef, imports);
6851
+ return this.resolvePageRefObject(pageRef, imports, chain);
4844
6852
  }
4845
6853
  return {
4846
6854
  success: false,
@@ -4850,7 +6858,7 @@ var ReferenceResolver = class {
4850
6858
  /**
4851
6859
  * Resolve a page reference string.
4852
6860
  */
4853
- resolvePageRefString(ref, imports, refId) {
6861
+ async resolvePageRefString(ref, imports, chain, refId) {
4854
6862
  const parsed = parsePageRef(ref);
4855
6863
  if (!parsed) {
4856
6864
  return {
@@ -4868,9 +6876,18 @@ var ReferenceResolver = class {
4868
6876
  };
4869
6877
  }
4870
6878
  let page = null;
4871
- for (const o of importedOrbitals(imported)) {
4872
- page = this.findPageInOrbital(o, parsed.pageName, refId, imports.idIndex);
4873
- if (page) break;
6879
+ const idEntry = refId ? imports.idIndex?.get(refId) : void 0;
6880
+ if (idEntry && idEntry.kind === "page") {
6881
+ page = { ...idEntry.node };
6882
+ } else {
6883
+ for (const o of importedOrbitals(imported)) {
6884
+ const entry = findPageEntryInOrbital(o, parsed.pageName);
6885
+ if (!entry) continue;
6886
+ const entryResolved = await this.resolvePageEntry(imported, entry, chain);
6887
+ if (!entryResolved.success) return entryResolved;
6888
+ page = entryResolved.data.page;
6889
+ break;
6890
+ }
4874
6891
  }
4875
6892
  if (!page) {
4876
6893
  const available = importedOrbitals(imported).flatMap((o) => this.listPagesInOrbital(o));
@@ -4892,10 +6909,18 @@ var ReferenceResolver = class {
4892
6909
  };
4893
6910
  }
4894
6911
  /**
4895
- * Resolve a page reference object with optional path override.
6912
+ * Resolve a page reference object, applying every call-site override
6913
+ * `path` (direct assignment), `linkedEntity` (rebind `primaryEntity` and
6914
+ * every page-level trait pointer that named the old entity), and `traits`
6915
+ * (full replacement) — mirroring the compiler's `apply_overrides_to_page`
6916
+ * (`phases/inline/page.rs:21-93`). `Page.traits` is a `PageTraitRef[]`
6917
+ * pointer list (a trait's own body lives in the orbital's `traits {}`, not
6918
+ * on the page), so unlike Rust's `TraitReference` the `linkedEntity` rebind
6919
+ * only ever touches each pointer's OWN `linkedEntity` field — there is no
6920
+ * inline trait body here to walk with `renameEntitiesInTrait`.
4896
6921
  */
4897
- resolvePageRefObject(refObj, imports) {
4898
- const baseResult = this.resolvePageRefString(refObj.ref, imports, refObj.refId);
6922
+ async resolvePageRefObject(refObj, imports, chain) {
6923
+ const baseResult = await this.resolvePageRefString(refObj.ref, imports, chain, refObj.refId);
4899
6924
  if (!baseResult.success) {
4900
6925
  return baseResult;
4901
6926
  }
@@ -4909,36 +6934,25 @@ var ReferenceResolver = class {
4909
6934
  resolved.pathOverridden = true;
4910
6935
  resolved.originalPath = originalPath;
4911
6936
  }
6937
+ if (refObj.linkedEntity) {
6938
+ const oldEntity = resolved.page.primaryEntity;
6939
+ const newEntity = refObj.linkedEntity;
6940
+ const rebindPointers = (pointers) => oldEntity && oldEntity !== newEntity ? pointers?.map((pt) => pt.linkedEntity === oldEntity ? { ...pt, linkedEntity: newEntity } : pt) : pointers;
6941
+ resolved.page = {
6942
+ ...resolved.page,
6943
+ primaryEntity: newEntity,
6944
+ traits: rebindPointers(resolved.page.traits)
6945
+ };
6946
+ }
6947
+ if (refObj.traits) {
6948
+ resolved.page = { ...resolved.page, traits: refObj.traits.map(toPageTraitRef) };
6949
+ }
4912
6950
  return {
4913
6951
  success: true,
4914
6952
  data: resolved,
4915
6953
  warnings: baseResult.warnings
4916
6954
  };
4917
6955
  }
4918
- /**
4919
- * Find a page in an orbital by name. Id-primary: when the calling ref
4920
- * carries a `refId` and the id index has a matching page entry, return it
4921
- * directly — else fall back to the existing name match unchanged.
4922
- */
4923
- findPageInOrbital(orbital, pageName, refId, idIndex) {
4924
- if (refId && idIndex) {
4925
- const entry = idIndex.get(refId);
4926
- if (entry && entry.kind === "page") {
4927
- return { ...entry.node };
4928
- }
4929
- }
4930
- const pages = orbital.pages;
4931
- if (!pages) return null;
4932
- for (const pageRef of pages) {
4933
- if (typeof pageRef !== "string" && !("ref" in pageRef)) {
4934
- const page = pageRef;
4935
- if (page.name === pageName) {
4936
- return { ...page };
4937
- }
4938
- }
4939
- }
4940
- return null;
4941
- }
4942
6956
  /**
4943
6957
  * List page names in an orbital.
4944
6958
  */
@@ -4953,6 +6967,645 @@ var ReferenceResolver = class {
4953
6967
  }
4954
6968
  return names;
4955
6969
  }
6970
+ /**
6971
+ * Flatten every reference-form orbital (`orbital X = Alias.orbitals.Y
6972
+ * { … }`, docs/Almadar_Orbital_Import.md §4) in a schema BEFORE the
6973
+ * ordinary per-orbital {@link resolve} pass runs — the interpreter-path
6974
+ * twin of the (not-yet-landed) compiler's inline-phase flatten. After this
6975
+ * call, no returned `OrbitalDefinition` carries `.reference`.
6976
+ */
6977
+ async resolveOrbitalImports(schema, opts) {
6978
+ const errors = [];
6979
+ const flattened = [];
6980
+ const chain = { push: () => null, pop: () => {
6981
+ }, clone() {
6982
+ return this;
6983
+ } };
6984
+ const visiting = /* @__PURE__ */ new Set();
6985
+ const consumerEntityIds = consumerEntityIdsOf(schema.orbitals);
6986
+ for (const [name, id] of await this.precomputeReferenceFormPrimaryIds(schema, chain)) {
6987
+ if (!consumerEntityIds.has(name)) consumerEntityIds.set(name, id);
6988
+ }
6989
+ const listenSourceTargets = await this.precomputeReferenceFormListenTargets(schema.orbitals, chain);
6990
+ const consumerRoster = identityEntitiesOf(schema.orbitals);
6991
+ for (const orbital of schema.orbitals) {
6992
+ if (!orbital.reference) {
6993
+ if (!opts?.skipTypeParamSentinels && isInlineEntity(orbital.entity)) {
6994
+ resolveOrbitalTypeParamSentinels(
6995
+ orbital.traits.filter(isInlineTrait).map((t) => ({ trait: t })),
6996
+ orbital.entity,
6997
+ (orbital.auxiliaryEntities ?? []).filter(isInlineEntity),
6998
+ orbital.types
6999
+ );
7000
+ }
7001
+ flattened.push(orbital);
7002
+ continue;
7003
+ }
7004
+ const result = await this.resolveOrbitalRefChain(
7005
+ orbital,
7006
+ void 0,
7007
+ chain,
7008
+ visiting,
7009
+ consumerEntityIds,
7010
+ consumerRoster,
7011
+ listenSourceTargets
7012
+ );
7013
+ if (!result.success) {
7014
+ errors.push(...result.errors);
7015
+ continue;
7016
+ }
7017
+ if (!opts?.skipTypeParamSentinels && isInlineEntity(result.data.entity)) {
7018
+ resolveOrbitalTypeParamSentinels(
7019
+ result.data.traits.filter(isInlineTrait).map((t) => ({ trait: t })),
7020
+ result.data.entity,
7021
+ (result.data.auxiliaryEntities ?? []).filter(isInlineEntity),
7022
+ result.data.types
7023
+ );
7024
+ }
7025
+ flattened.push(result.data);
7026
+ }
7027
+ if (errors.length > 0) return { success: false, errors };
7028
+ reconcileOrbitalRefEventIdRenames(schema, flattened);
7029
+ return { success: true, data: flattened, warnings: [] };
7030
+ }
7031
+ /**
7032
+ * (B) The materialized primary name → derived id of every REFERENCE-FORM
7033
+ * orbital this schema declares (`orbital X = Alias.orbitals.Y { … }`),
7034
+ * computed order-free — WITHOUT requiring any other orbital in `schema`
7035
+ * to have resolved first, and without recursively flattening the
7036
+ * upstream. Each reference's alias is loaded via the ordinary
7037
+ * `resolveImports` path, which the loader caches by absolute path (see
7038
+ * `ExternalOrbitalLoader`'s `LoaderCache`) — the REAL flatten
7039
+ * (`resolveOrbitalRefChain`) moments later is then a cache hit, no
7040
+ * duplicate work — and its named orbital looked up directly in the
7041
+ * loaded (un-flattened) schema: an upstream's OWN primary entity id/name
7042
+ * never change through resolution (only a CONSUMER-side CLONE gets a
7043
+ * fresh derived id), so this shallow load's entity is exactly what the
7044
+ * real flatten pass would see too. Uses the SAME `materializedPrimaryEntity`
7045
+ * pair `materializeOrbitalRef` computes for itself — one owner. JS twin
7046
+ * of the compiled path's `precompute_reference_form_primary_ids`.
7047
+ *
7048
+ * Best-effort: a reference this pre-pass cannot resolve (unknown alias,
7049
+ * malformed reference string, upstream orbital not found, load failure)
7050
+ * is silently skipped here — the REAL `resolveOrbitalRefChain` call
7051
+ * moments later still surfaces the actual error for it.
7052
+ */
7053
+ async precomputeReferenceFormPrimaryIds(schema, chain) {
7054
+ const out = /* @__PURE__ */ new Map();
7055
+ for (const orbital of schema.orbitals) {
7056
+ const ref = orbital.reference;
7057
+ if (!ref) continue;
7058
+ const parsed = parseOrbitalRef(ref.ref);
7059
+ if (!parsed) continue;
7060
+ const importsResult = await this.resolveImports(orbital.uses ?? [], void 0, chain);
7061
+ if (!importsResult.success) continue;
7062
+ const imported = importsResult.data.orbitals.get(parsed.alias);
7063
+ if (!imported) continue;
7064
+ const upstream = importedOrbitals(imported).find((o) => o.name === parsed.orbitalName);
7065
+ if (!upstream || !isInlineEntity(upstream.entity)) continue;
7066
+ const { name, id } = materializedPrimaryEntity(upstream.entity, upstream.id, ref, orbital.name);
7067
+ out.set(name, id);
7068
+ }
7069
+ return out;
7070
+ }
7071
+ /**
7072
+ * G1 (`docs/Almadar_Compiler_Gaps.md` §82): every reference-form
7073
+ * orbital's OWN materialized trait set, keyed by {@link siblingImportKey}
7074
+ * (upstream alias + upstream orbital name), mapped to that import's local
7075
+ * orbital name + every kept trait's final name/id ({@link
7076
+ * materializedTraitSubs}). Computed order-free — WITHOUT requiring any
7077
+ * other orbital in `schema` to have resolved first — same precompute
7078
+ * shape as {@link precomputeReferenceFormPrimaryIds}, but for LISTEN-
7079
+ * SOURCE rewriting: consulted by {@link rewriteListenSources} so a source
7080
+ * naming ANY reference-form orbital of this schema resolves regardless of
7081
+ * declaration order. Unlike the entity-id precompute, this resolves the
7082
+ * upstream's OWN traits via the ordinary `this.resolve()` pass (the same
7083
+ * call {@link materializeOrbitalRef} makes on its own upstream, with the
7084
+ * same `schemaConfig` save/restore) rather than reading the raw unresolved
7085
+ * schema — the JS identity model has no pre-resolve declaration id for a
7086
+ * COMPOSED trait reference (unlike the compiled path's V4 dual-carry
7087
+ * `TraitReference::Reference.id`), so a shallow read would silently
7088
+ * under-report every composed trait's id.
7089
+ *
7090
+ * Best-effort: a reference this pre-pass cannot resolve (unknown alias,
7091
+ * malformed reference string, upstream orbital not found, itself still
7092
+ * reference-form, load/resolve failure) is silently skipped here — the
7093
+ * REAL `resolveOrbitalRefChain`/`materializeOrbitalRef` call moments
7094
+ * later still surfaces the actual error for it.
7095
+ */
7096
+ async precomputeReferenceFormListenTargets(orbitals, chain) {
7097
+ const out = /* @__PURE__ */ new Map();
7098
+ for (const orbital of orbitals) {
7099
+ const ref = orbital.reference;
7100
+ if (!ref) continue;
7101
+ const parsed = parseOrbitalRef(ref.ref);
7102
+ if (!parsed) continue;
7103
+ const importsResult = await this.resolveImports(orbital.uses ?? [], void 0, chain);
7104
+ if (!importsResult.success) continue;
7105
+ const imported = importsResult.data.orbitals.get(parsed.alias);
7106
+ if (!imported) continue;
7107
+ const upstream = importedOrbitals(imported).find((o) => o.name === parsed.orbitalName);
7108
+ if (!upstream || upstream.reference) continue;
7109
+ const savedSchemaConfig = this.schemaConfig;
7110
+ this.schemaConfig = imported.schemaConfig;
7111
+ let resolvedUpstream;
7112
+ try {
7113
+ resolvedUpstream = await this.resolve(upstream, imported.sourcePath, chain);
7114
+ } finally {
7115
+ this.schemaConfig = savedSchemaConfig;
7116
+ }
7117
+ if (!resolvedUpstream.success) continue;
7118
+ const traitSubs = materializedTraitSubs(upstream.id, resolvedUpstream.data.traits, ref, orbital.name);
7119
+ out.set(siblingImportKey(parsed.alias, parsed.orbitalName), { localName: orbital.name, traitSubs });
7120
+ }
7121
+ return out;
7122
+ }
7123
+ /**
7124
+ * Resolve one reference-form orbital, recursing into the upstream first
7125
+ * when IT is also reference-form ("already fully inlined because inline
7126
+ * recursed into every loaded orbital" — docs/Almadar_Orbital_Import.md §9
7127
+ * step 3 — the JS resolver needs its own cycle guard since it has no
7128
+ * file-level inline-order pass to lean on).
7129
+ */
7130
+ async resolveOrbitalRefChain(orbital, sourcePath, chain, visiting, consumerEntityIds, consumerRoster, listenSourceTargets) {
7131
+ const ref = orbital.reference;
7132
+ if (!ref) return { success: true, data: orbital, warnings: [] };
7133
+ const parsed = parseOrbitalRef(ref.ref);
7134
+ if (!parsed) {
7135
+ return {
7136
+ success: false,
7137
+ errors: [`Invalid orbital reference format: ${ref.ref}. Expected "Alias.orbitals.OrbitalName"`]
7138
+ };
7139
+ }
7140
+ const importsResult = await this.resolveImports(orbital.uses ?? [], sourcePath, chain);
7141
+ if (!importsResult.success) return { success: false, errors: importsResult.errors };
7142
+ const imported = importsResult.data.orbitals.get(parsed.alias);
7143
+ if (!imported) {
7144
+ return {
7145
+ success: false,
7146
+ errors: [
7147
+ `Unknown import alias in orbital reference: ${parsed.alias}. Available aliases: ${Array.from(importsResult.data.orbitals.keys()).join(", ") || "none"}`
7148
+ ]
7149
+ };
7150
+ }
7151
+ const candidates = importedOrbitals(imported);
7152
+ let upstream = candidates.find((o) => o.name === parsed.orbitalName);
7153
+ if (!upstream) {
7154
+ return {
7155
+ success: false,
7156
+ errors: [
7157
+ `Orbital "${parsed.orbitalName}" not found in imported behavior "${parsed.alias}". Available orbitals: ${candidates.map((o) => o.name).join(", ") || "none"}`
7158
+ ]
7159
+ };
7160
+ }
7161
+ const cycleKey = `${imported.sourcePath}::${parsed.orbitalName}`;
7162
+ if (visiting.has(cycleKey)) {
7163
+ return {
7164
+ success: false,
7165
+ errors: [
7166
+ `Circular orbital reference: "${orbital.name}" imports "${parsed.alias}.orbitals.${parsed.orbitalName}" while that orbital is itself being resolved`
7167
+ ]
7168
+ };
7169
+ }
7170
+ visiting.add(cycleKey);
7171
+ if (upstream.reference) {
7172
+ const nestedListenSourceTargets = await this.precomputeReferenceFormListenTargets(candidates, chain);
7173
+ const nested = await this.resolveOrbitalRefChain(
7174
+ upstream,
7175
+ imported.sourcePath,
7176
+ chain,
7177
+ visiting,
7178
+ consumerEntityIds,
7179
+ consumerRoster,
7180
+ nestedListenSourceTargets
7181
+ );
7182
+ if (!nested.success) {
7183
+ visiting.delete(cycleKey);
7184
+ return nested;
7185
+ }
7186
+ upstream = nested.data;
7187
+ }
7188
+ visiting.delete(cycleKey);
7189
+ const materialized = await this.materializeOrbitalRef(
7190
+ upstream,
7191
+ ref,
7192
+ orbital.name,
7193
+ orbital.id,
7194
+ imported.sourcePath,
7195
+ chain,
7196
+ candidates,
7197
+ consumerEntityIds,
7198
+ consumerRoster,
7199
+ imported.schemaConfig,
7200
+ parsed.alias,
7201
+ listenSourceTargets
7202
+ );
7203
+ if (!materialized.success) return materialized;
7204
+ const siblingTraits = orbital.traits ?? [];
7205
+ return {
7206
+ success: true,
7207
+ data: {
7208
+ ...materialized.data,
7209
+ ...siblingTraits.length > 0 ? { traits: [...materialized.data.traits, ...siblingTraits] } : {},
7210
+ uses: orbital.uses
7211
+ },
7212
+ warnings: materialized.warnings
7213
+ };
7214
+ }
7215
+ /**
7216
+ * Materialize a reference-form orbital: flatten the (already-inlined)
7217
+ * upstream orbital's whole trait/entity/page closure into the consumer,
7218
+ * unconditionally prefixed by `localName` (docs/Almadar_Orbital_Import.md
7219
+ * §4.3). JS twin of the (not-yet-landed) compiler's
7220
+ * `resolve_orbital_reference`.
7221
+ */
7222
+ async materializeOrbitalRef(upstream, ref, localName, localId, sourcePath, chain, aliasOrbitals, consumerEntityIds, consumerRoster, importedSchemaConfig, alias, listenSourceTargets) {
7223
+ const savedSchemaConfig = this.schemaConfig;
7224
+ this.schemaConfig = importedSchemaConfig;
7225
+ let resolvedUpstream;
7226
+ try {
7227
+ resolvedUpstream = await this.resolve(upstream, sourcePath, chain);
7228
+ } finally {
7229
+ this.schemaConfig = savedSchemaConfig;
7230
+ }
7231
+ if (!resolvedUpstream.success) {
7232
+ return {
7233
+ success: false,
7234
+ errors: resolvedUpstream.errors.map(
7235
+ (e) => `Orbital reference "${localName}" (${ref.ref}): ${e}`
7236
+ )
7237
+ };
7238
+ }
7239
+ const {
7240
+ entity: upstreamEntity,
7241
+ traits: upstreamTraits,
7242
+ pages: upstreamPages,
7243
+ // (C) the RESOLVED aux-entity set — includes whatever sibling-pull
7244
+ // surfaced (`pullSiblingTraits`'s aux-entity carry), never just
7245
+ // `upstream.auxiliaryEntities` (the pre-resolve INPUT, which misses
7246
+ // every un-rebound composed atom's own entity).
7247
+ auxiliaryEntities: upstreamAuxiliaryEntities
7248
+ } = resolvedUpstream.data;
7249
+ const onlySet = ref.only ? new Set(ref.only) : void 0;
7250
+ const omitSet = new Set(ref.omit ?? []);
7251
+ const keptTraits = upstreamTraits.filter(
7252
+ (rt) => onlySet ? onlySet.has(rt.trait.name) : !omitSet.has(rt.trait.name)
7253
+ );
7254
+ const keptNames = new Set(keptTraits.map((rt) => rt.trait.name));
7255
+ const removedNames = new Set(
7256
+ upstreamTraits.map((rt) => rt.trait.name).filter((n) => !keptNames.has(n))
7257
+ );
7258
+ const errors = [];
7259
+ for (const rt of keptTraits) {
7260
+ for (const embed of traitEmbedNamesOf(rt.trait)) {
7261
+ if (removedNames.has(embed)) {
7262
+ errors.push(
7263
+ `Orbital "${localName}" omits trait "${embed}" but surviving trait "${rt.trait.name}" still embeds it via @trait.${embed} (ORB_O_OMIT_EMBEDDED_TRAIT)`
7264
+ );
7265
+ }
7266
+ }
7267
+ }
7268
+ if (errors.length > 0) return { success: false, errors };
7269
+ let auxEntities = upstreamAuxiliaryEntities ?? [];
7270
+ const subs = /* @__PURE__ */ new Map();
7271
+ for (const rt of keptTraits) subs.set(rt.trait.name, `${localName}${rt.trait.name}`);
7272
+ const keptFinalNames = new Set(subs.values());
7273
+ const { name: primaryFinalName, id: primaryId } = materializedPrimaryEntity(
7274
+ upstreamEntity,
7275
+ upstream.id,
7276
+ ref,
7277
+ localName
7278
+ );
7279
+ subs.set(upstreamEntity.name, primaryFinalName);
7280
+ for (const e of auxEntities) subs.set(e.name, `${localName}${e.name}`);
7281
+ const fieldSubs = new Map(Object.entries(ref.fields ?? {}));
7282
+ const closure = /* @__PURE__ */ new Set([upstreamEntity.name, ...auxEntities.map((e) => e.name)]);
7283
+ const upstreamUniverse = /* @__PURE__ */ new Set();
7284
+ const upstreamUniverseEntities = /* @__PURE__ */ new Map();
7285
+ const primaryEntityNames = /* @__PURE__ */ new Set();
7286
+ for (const o of aliasOrbitals) {
7287
+ if (o.name === upstream.name) continue;
7288
+ if (isInlineEntity(o.entity)) primaryEntityNames.add(o.entity.name);
7289
+ for (const entity of inlineEntityRefsOf(o)) {
7290
+ if (!closure.has(entity.name)) {
7291
+ upstreamUniverse.add(entity.name);
7292
+ upstreamUniverseEntities.set(entity.name, entity);
7293
+ }
7294
+ }
7295
+ }
7296
+ const entityIds = /* @__PURE__ */ new Map();
7297
+ if (ref.entities) {
7298
+ for (const [upstreamKey, consumerName] of Object.entries(ref.entities)) {
7299
+ if (!upstreamUniverse.has(upstreamKey)) {
7300
+ errors.push(
7301
+ `Orbital "${localName}" declares entities { ${upstreamKey}: ${consumerName} } but "${upstreamKey}" is not an out-of-orbital entity of upstream alias "${upstream.name}" (ORB_O_ENTITY_UNKNOWN_KEY)`
7302
+ );
7303
+ continue;
7304
+ }
7305
+ const consumerId = consumerEntityIds.get(consumerName);
7306
+ if (consumerId === void 0) {
7307
+ errors.push(
7308
+ `Orbital "${localName}" entities { ${upstreamKey}: ${consumerName} } targets "${consumerName}", which the consumer schema does not declare (ORB_O_ENTITY_TARGET_UNKNOWN)`
7309
+ );
7310
+ continue;
7311
+ }
7312
+ subs.set(upstreamKey, consumerName);
7313
+ entityIds.set(consumerName, consumerId);
7314
+ }
7315
+ if (errors.length > 0) return { success: false, errors };
7316
+ }
7317
+ const referenced = /* @__PURE__ */ new Set();
7318
+ for (const rt of keptTraits) {
7319
+ if (rt.trait.linkedEntity && upstreamUniverse.has(rt.trait.linkedEntity)) {
7320
+ referenced.add(rt.trait.linkedEntity);
7321
+ }
7322
+ for (const name of collectEntityNamesInTrait(rt.trait, upstreamUniverse)) referenced.add(name);
7323
+ if (rt.trait.sourceEntityDefinition) {
7324
+ for (const name of relationTargetsOfEntity(rt.trait.sourceEntityDefinition, upstreamUniverse)) {
7325
+ referenced.add(name);
7326
+ }
7327
+ }
7328
+ }
7329
+ for (const name of relationTargetsOfEntity(upstreamEntity, upstreamUniverse)) referenced.add(name);
7330
+ for (const aux of auxEntities) {
7331
+ for (const name of relationTargetsOfEntity(aux, upstreamUniverse)) referenced.add(name);
7332
+ }
7333
+ for (const rp of upstreamPages) {
7334
+ if (rp.page.primaryEntity && upstreamUniverse.has(rp.page.primaryEntity)) {
7335
+ referenced.add(rp.page.primaryEntity);
7336
+ }
7337
+ for (const tr of rp.page.traits ?? []) {
7338
+ if (tr.linkedEntity && upstreamUniverse.has(tr.linkedEntity)) referenced.add(tr.linkedEntity);
7339
+ }
7340
+ }
7341
+ for (const name of referenced) {
7342
+ if (subs.has(name)) continue;
7343
+ const definition = upstreamUniverseEntities.get(name);
7344
+ const auxOnly = definition !== void 0 && !primaryEntityNames.has(name);
7345
+ if (definition && auxOnly && !definition.identity) {
7346
+ auxEntities = [...auxEntities, definition];
7347
+ subs.set(name, `${localName}${name}`);
7348
+ continue;
7349
+ }
7350
+ errors.push(
7351
+ `Orbital "${localName}" references out-of-orbital entity "${name}" with no "${name}: <consumer entity>" mapping in entities {} (ORB_O_ENTITY_UNMAPPED)`
7352
+ );
7353
+ }
7354
+ if (errors.length > 0) return { success: false, errors };
7355
+ const roleFields = /* @__PURE__ */ new Map();
7356
+ for (const entity of identityEntitiesOf(aliasOrbitals)) {
7357
+ for (const field of entity.fields) {
7358
+ if (!field.name) continue;
7359
+ const vocab = roleVocabularyOf(entity, field.name);
7360
+ if (vocab) roleFields.set(field.name, vocab);
7361
+ }
7362
+ }
7363
+ const consumerRoleFields = /* @__PURE__ */ new Map();
7364
+ for (const entity of consumerRoster) {
7365
+ for (const field of entity.fields) {
7366
+ if (!field.name) continue;
7367
+ const vocab = roleVocabularyOf(entity, field.name);
7368
+ if (!vocab) continue;
7369
+ let values = consumerRoleFields.get(field.name);
7370
+ if (!values) {
7371
+ values = /* @__PURE__ */ new Set();
7372
+ consumerRoleFields.set(field.name, values);
7373
+ }
7374
+ for (const value of vocab) values.add(value);
7375
+ }
7376
+ }
7377
+ for (const [literal, targets] of Object.entries(ref.roles ?? {})) {
7378
+ const matchingFields = [...roleFields.entries()].filter(([, vocab]) => vocab.includes(literal)).map(([field]) => field).sort();
7379
+ if (matchingFields.length === 0) {
7380
+ errors.push(
7381
+ `Orbital "${localName}" declares roles { ${literal}: ... } but upstream alias "${upstream.name}"'s roster declares no role field with literal "${literal}" in its vocabulary (ORB_O_ROLE_UNKNOWN_UPSTREAM)`
7382
+ );
7383
+ continue;
7384
+ }
7385
+ for (const field of matchingFields) {
7386
+ const allowed = consumerRoleFields.get(field);
7387
+ for (const target of targets) {
7388
+ if (allowed?.has(target)) continue;
7389
+ errors.push(
7390
+ `Orbital "${localName}" roles { ${literal}: ${target} } targets "${target}", which is not a member of consumer field "${field}" on the roster (values: ${allowed ? [...allowed].sort().join(", ") : "(none)"}) (ORB_O_ROLE_TARGET_NOT_MEMBER)`
7391
+ );
7392
+ }
7393
+ }
7394
+ }
7395
+ if (errors.length > 0) return { success: false, errors };
7396
+ const declaredConfig = upstream.config;
7397
+ if (ref.config) {
7398
+ for (const key of Object.keys(ref.config)) {
7399
+ if (!declaredConfig || !(key in declaredConfig)) {
7400
+ errors.push(
7401
+ `Orbital "${localName}" overrides config "${key}" but upstream orbital "${upstream.name}" does not declare that knob (ORB_O_CONFIG_UNKNOWN_KEY)`
7402
+ );
7403
+ }
7404
+ }
7405
+ if (errors.length > 0) return { success: false, errors };
7406
+ }
7407
+ const configOverrideValues = {};
7408
+ for (const [key, field] of Object.entries(ref.config ?? {})) {
7409
+ if (field.default !== void 0) configOverrideValues[key] = field.default;
7410
+ }
7411
+ const foldedConfig = declaredConfig ? overrideDeclaredKnobs(declaredConfig, configOverrideValues) : void 0;
7412
+ const idByName = /* @__PURE__ */ new Map();
7413
+ const materializedTraits = keptTraits.map((rt) => {
7414
+ const finalName = subs.get(rt.trait.name);
7415
+ const finalId = asTraitId(deriveMaterializedId(rt.trait.id, upstream.id, rt.trait.name, localName, "trait"));
7416
+ idByName.set(finalName, finalId);
7417
+ return { ...rt.trait, name: finalName, id: finalId };
7418
+ });
7419
+ const embeddersOf = /* @__PURE__ */ new Map();
7420
+ for (const t of materializedTraits) {
7421
+ for (const embed of traitEmbedNamesOf(t)) {
7422
+ const embedFinal = subs.get(embed);
7423
+ if (!embedFinal) continue;
7424
+ let embedders = embeddersOf.get(embedFinal);
7425
+ if (!embedders) {
7426
+ embedders = [];
7427
+ embeddersOf.set(embedFinal, embedders);
7428
+ }
7429
+ embedders.push(t.name);
7430
+ }
7431
+ }
7432
+ const parentConfigs = new Map(
7433
+ materializedTraits.map((t) => [t.name, t.config])
7434
+ );
7435
+ const transitiveEmbedderChain = (name) => {
7436
+ const chain2 = [];
7437
+ const seenNames = /* @__PURE__ */ new Set([name]);
7438
+ let cur = embeddersOf.get(name)?.[0];
7439
+ while (cur !== void 0 && !seenNames.has(cur)) {
7440
+ seenNames.add(cur);
7441
+ const cfg = parentConfigs.get(cur);
7442
+ if (cfg) chain2.push(cfg);
7443
+ cur = embeddersOf.get(cur)?.[0];
7444
+ }
7445
+ return chain2;
7446
+ };
7447
+ entityIds.set(primaryFinalName, primaryId);
7448
+ for (const e of auxEntities) {
7449
+ entityIds.set(
7450
+ subs.get(e.name),
7451
+ asEntityId(deriveMaterializedId(e.id, upstream.id, e.name, localName, "entity"))
7452
+ );
7453
+ }
7454
+ const upstreamPathSet = new Set(upstreamPages.map((rp) => rp.page.path));
7455
+ for (const path of [...Object.keys(ref.pages ?? {}), ...Object.keys(ref.mounts ?? {})]) {
7456
+ if (!upstreamPathSet.has(path)) {
7457
+ errors.push(
7458
+ `Orbital "${localName}" names page path "${path}" but upstream orbital "${upstream.name}" has no page at that path (ORB_O_PAGE_UNKNOWN_PATH)`
7459
+ );
7460
+ }
7461
+ }
7462
+ if (errors.length > 0) return { success: false, errors };
7463
+ const pathMap = new Map(
7464
+ upstreamPages.map((rp) => [rp.page.path, ref.pages?.[rp.page.path] ?? rp.page.path])
7465
+ );
7466
+ const orbitalRename = upstream.name !== localName ? { from: upstream.name, to: localName } : void 0;
7467
+ const finalTraits = materializedTraits.map((trait) => {
7468
+ let next = renameTraitEmbeds(trait, subs);
7469
+ next = renameEntitiesInTrait(next, subs, entityIds);
7470
+ if (next.linkedEntity !== void 0) {
7471
+ const linkedEntityId = entityIds.get(next.linkedEntity);
7472
+ if (linkedEntityId !== void 0) next = { ...next, linkedEntityId };
7473
+ }
7474
+ next = rewriteEntityRefIds(next, subs, entityIds);
7475
+ next = renameSourceEntityDefinition(next, subs, entityIds);
7476
+ next = rewriteRoleLiteralsInTrait(next, roleFields, ref.roles ?? {});
7477
+ if (fieldSubs.size > 0) next = rewriteEntityFieldsInTrait(next, fieldSubs);
7478
+ next = rewriteListenSources(next, subs, idByName, orbitalRename, alias, listenSourceTargets);
7479
+ if (pathMap.size > 0) {
7480
+ next = rewriteTraitNavigateTargets(next, pathMap);
7481
+ }
7482
+ for (const embedderName of embeddersOf.get(trait.name) ?? []) {
7483
+ const embedderConfig = parentConfigs.get(embedderName);
7484
+ next = resolveForwardedSiblingConfigFrom(next, embedderConfig ? [embedderConfig] : []);
7485
+ }
7486
+ next = resolveForwardedSiblingConfigFrom(next, transitiveEmbedderChain(trait.name));
7487
+ next = resolveForwardedSiblingConfigFrom(next, [], foldedConfig, importedSchemaConfig);
7488
+ if (fieldSubs.size > 0 && next.config) {
7489
+ next = { ...next, config: rewriteEntityFieldsInConfig(next.config, fieldSubs) };
7490
+ }
7491
+ if (pathMap.size > 0) {
7492
+ next = rewriteTraitConfigPagePaths(next, pathMap);
7493
+ }
7494
+ next = applyEventRenames(next, ref.events, keptFinalNames);
7495
+ return next;
7496
+ });
7497
+ const renamedPrimaryEntity = rewriteRoleLiteralsInEntity(
7498
+ renameEntityRelationTargets(
7499
+ rewriteEntityFieldsInEntity(
7500
+ {
7501
+ ...upstreamEntity,
7502
+ name: primaryFinalName,
7503
+ id: primaryId
7504
+ },
7505
+ fieldSubs
7506
+ ),
7507
+ subs,
7508
+ entityIds
7509
+ ),
7510
+ roleFields,
7511
+ ref.roles ?? {}
7512
+ );
7513
+ const extendResult = applyExtendFields(
7514
+ renamedPrimaryEntity,
7515
+ ref.extend,
7516
+ fieldSubs,
7517
+ consumerEntityIds,
7518
+ localName
7519
+ );
7520
+ if (extendResult.errors.length > 0) return { success: false, errors: extendResult.errors };
7521
+ const primaryEntity = extendResult.entity;
7522
+ const finalAuxEntities = auxEntities.map((e) => {
7523
+ const finalName = subs.get(e.name);
7524
+ return rewriteRoleLiteralsInEntity(
7525
+ renameEntityRelationTargets(
7526
+ rewriteEntityFieldsInEntity(
7527
+ {
7528
+ ...e,
7529
+ name: finalName,
7530
+ id: entityIds.get(finalName)
7531
+ },
7532
+ fieldSubs
7533
+ ),
7534
+ subs,
7535
+ entityIds
7536
+ ),
7537
+ roleFields,
7538
+ ref.roles ?? {}
7539
+ );
7540
+ });
7541
+ const finalPages = upstreamPages.map((rp) => {
7542
+ const original = rp.page;
7543
+ const mountNames = ref.mounts?.[original.path] ?? [];
7544
+ const finalPageTraits = [
7545
+ ...(original.traits ?? []).filter((tr) => !removedNames.has(tr.ref)).map((tr) => {
7546
+ const finalRef = subs.get(tr.ref) ?? tr.ref;
7547
+ const refId = idByName.get(finalRef);
7548
+ return {
7549
+ ...tr,
7550
+ ref: finalRef,
7551
+ ...refId !== void 0 ? { refId } : {},
7552
+ ...tr.linkedEntity !== void 0 ? { linkedEntity: subs.get(tr.linkedEntity) ?? tr.linkedEntity } : {}
7553
+ };
7554
+ }),
7555
+ ...mountNames.map((name) => ({ ref: name }))
7556
+ ];
7557
+ return {
7558
+ ...original,
7559
+ // Gap (E) — unconditionally prefixed, same as traits/entities (§4.3):
7560
+ // two imports of the same upstream orbital with distinct `pages {}`
7561
+ // path maps must not collide on page NAME (`Duplicate page name`).
7562
+ // `id` is the page-scope sibling of `deriveMaterializedId` (never
7563
+ // `mintId`) — fresh and pairwise-disjoint across imports, same as
7564
+ // trait/entity ids above.
7565
+ name: `${localName}${original.name}`,
7566
+ id: asPageId(deriveMaterializedId(original.id, upstream.id, original.name, localName, "page")),
7567
+ path: pathMap.get(original.path) ?? original.path,
7568
+ ...original.primaryEntity !== void 0 ? { primaryEntity: subs.get(original.primaryEntity) ?? original.primaryEntity } : {},
7569
+ traits: finalPageTraits
7570
+ };
7571
+ });
7572
+ const forwardedKnobs = /* @__PURE__ */ new Set();
7573
+ for (const rt of keptTraits) {
7574
+ for (const field of Object.values(rt.trait.config ?? {})) {
7575
+ if (typeof field.default === "string" && field.default.startsWith("@config.")) {
7576
+ const knob = field.default.slice("@config.".length);
7577
+ if (knob.length > 0 && !knob.includes(".")) forwardedKnobs.add(knob);
7578
+ }
7579
+ }
7580
+ }
7581
+ const prunedConfig = foldedConfig ? Object.fromEntries(Object.entries(foldedConfig).filter(([key]) => forwardedKnobs.has(key))) : void 0;
7582
+ const orbitalId = localId ?? (upstream.id ? asOrbitalId(deriveId(upstream.id, localName)) : void 0);
7583
+ refResolverLog.info("orbital-import:materialize", {
7584
+ local: localName,
7585
+ upstream: upstream.name,
7586
+ traits: finalTraits.length,
7587
+ pages: finalPages.length
7588
+ });
7589
+ return {
7590
+ success: true,
7591
+ data: {
7592
+ ...upstream,
7593
+ name: localName,
7594
+ ...orbitalId ? { id: orbitalId } : {},
7595
+ entity: primaryEntity,
7596
+ ...finalAuxEntities.length > 0 ? { auxiliaryEntities: finalAuxEntities } : {},
7597
+ traits: finalTraits,
7598
+ pages: finalPages,
7599
+ emits: void 0,
7600
+ listens: void 0,
7601
+ exposes: void 0,
7602
+ ...prunedConfig ? { config: prunedConfig } : { config: void 0 },
7603
+ uses: void 0,
7604
+ reference: void 0
7605
+ },
7606
+ warnings: []
7607
+ };
7608
+ }
4956
7609
  /**
4957
7610
  * Add local traits for resolution.
4958
7611
  */
@@ -4971,29 +7624,148 @@ var ReferenceResolver = class {
4971
7624
  this.loader?.clearCache();
4972
7625
  }
4973
7626
  };
7627
+ function isInlineTraitWithStateMachine(tr) {
7628
+ return isInlineTrait(tr);
7629
+ }
7630
+ function reconcileOrbitalRefEventIdRenames(schema, flattened) {
7631
+ if (!schema.ledger) return;
7632
+ const renamedRefs = schema.orbitals.filter((o) => o.reference?.events && Object.keys(o.reference.events).length > 0).map((o) => ({ localName: o.name, eventSubs: o.reference.events }));
7633
+ if (renamedRefs.length === 0) return;
7634
+ const sites = [];
7635
+ for (const { localName, eventSubs } of renamedRefs) {
7636
+ const newKeys = new Set(Object.values(eventSubs));
7637
+ const orbital = flattened.find((o) => o.name === localName);
7638
+ if (!orbital) continue;
7639
+ for (const tr of orbital.traits) {
7640
+ if (!isInlineTraitWithStateMachine(tr)) continue;
7641
+ for (const ev of tr.stateMachine?.events ?? []) {
7642
+ if (!ev.id || !newKeys.has(ev.key)) continue;
7643
+ const entry = schema.ledger.entries[ev.id];
7644
+ if (!entry || entry.curName === ev.key) continue;
7645
+ sites.push({ orbitalName: orbital.name, traitName: tr.name, oldId: ev.id, newKey: ev.key });
7646
+ }
7647
+ }
7648
+ }
7649
+ if (sites.length === 0) return;
7650
+ const candidateIds = new Set(sites.map((s) => s.oldId));
7651
+ const owners = /* @__PURE__ */ new Map();
7652
+ for (const orbital of flattened) {
7653
+ for (const tr of orbital.traits) {
7654
+ if (!isInlineTraitWithStateMachine(tr)) continue;
7655
+ for (const ev of tr.stateMachine?.events ?? []) {
7656
+ if (ev.id && candidateIds.has(ev.id)) {
7657
+ const ownerKey = `${orbital.name}\0${tr.name}`;
7658
+ const set = owners.get(ev.id) ?? /* @__PURE__ */ new Set();
7659
+ set.add(ownerKey);
7660
+ owners.set(ev.id, set);
7661
+ }
7662
+ }
7663
+ }
7664
+ }
7665
+ const renameInPlace = /* @__PURE__ */ new Map();
7666
+ const deriveSites = [];
7667
+ const seen = /* @__PURE__ */ new Set();
7668
+ for (const site of sites) {
7669
+ const ownerCount = owners.get(site.oldId)?.size ?? 1;
7670
+ if (ownerCount <= 1) {
7671
+ renameInPlace.set(site.oldId, site.newKey);
7672
+ } else if (!seen.has(site.oldId)) {
7673
+ seen.add(site.oldId);
7674
+ deriveSites.push({ site, newId: asEventId(deriveId(site.oldId, site.newKey)) });
7675
+ }
7676
+ }
7677
+ for (const { site, newId } of deriveSites) {
7678
+ const orbital = flattened.find((o) => o.name === site.orbitalName);
7679
+ if (!orbital) continue;
7680
+ orbital.traits = orbital.traits.map((tr) => {
7681
+ if (!isInlineTraitWithStateMachine(tr) || tr.name !== site.traitName) return tr;
7682
+ let next = tr;
7683
+ if (next.stateMachine?.events) {
7684
+ next = {
7685
+ ...next,
7686
+ stateMachine: {
7687
+ ...next.stateMachine,
7688
+ events: next.stateMachine.events.map((ev) => ev.id === site.oldId ? { ...ev, id: newId } : ev),
7689
+ transitions: (next.stateMachine.transitions ?? []).map(
7690
+ (t) => t.eventId === site.oldId ? { ...t, eventId: newId } : t
7691
+ )
7692
+ }
7693
+ };
7694
+ }
7695
+ if (next.emits) {
7696
+ next = {
7697
+ ...next,
7698
+ emits: next.emits.map(
7699
+ (e) => typeof e !== "string" && e.eventId === site.oldId ? { ...e, eventId: newId } : e
7700
+ )
7701
+ };
7702
+ }
7703
+ if (next.listens) {
7704
+ next = {
7705
+ ...next,
7706
+ listens: next.listens.map((l) => {
7707
+ const eventId = l.eventId === site.oldId ? newId : l.eventId;
7708
+ const triggersId = l.triggersId === site.oldId ? newId : l.triggersId;
7709
+ return eventId === l.eventId && triggersId === l.triggersId ? l : { ...l, eventId, triggersId };
7710
+ })
7711
+ };
7712
+ }
7713
+ return next;
7714
+ });
7715
+ }
7716
+ const at = (/* @__PURE__ */ new Date()).toISOString();
7717
+ let ledger = schema.ledger;
7718
+ for (const [oldId, newKey] of renameInPlace) {
7719
+ ledger = ledgerRename(ledger, oldId, newKey, at);
7720
+ }
7721
+ for (const { site, newId } of deriveSites) {
7722
+ const src = ledger.entries[site.oldId];
7723
+ if (!src) continue;
7724
+ const ownerTrait = flattened.find((o) => o.name === site.orbitalName)?.traits.find((tr) => isInlineTraitWithStateMachine(tr) && tr.name === site.traitName);
7725
+ const newEntry = {
7726
+ id: newId,
7727
+ kind: src.kind,
7728
+ bakedName: src.bakedName,
7729
+ curName: site.newKey,
7730
+ renames: [...src.renames, { from: src.curName, to: site.newKey, at }],
7731
+ owner: src.owner,
7732
+ ...ownerTrait?.id !== void 0 ? { parent: ownerTrait.id } : {}
7733
+ };
7734
+ ledger = { ...ledger, entries: { ...ledger.entries, [newId]: newEntry } };
7735
+ }
7736
+ schema.ledger = ledger;
7737
+ }
4974
7738
  async function resolveSchema(schema, options) {
4975
- const resolver = new ReferenceResolver(options);
7739
+ const resolver = new ReferenceResolver({ ...options, schemaConfig: schema.config });
4976
7740
  const errors = [];
4977
7741
  const warnings = [];
4978
7742
  const resolved = [];
4979
- for (const orbital of schema.orbitals) {
7743
+ const flattenResult = await resolver.resolveOrbitalImports(schema);
7744
+ if (!flattenResult.success) {
7745
+ return { success: false, errors: flattenResult.errors };
7746
+ }
7747
+ const orbitals = flattenResult.data;
7748
+ for (const orbital of orbitals) {
4980
7749
  const inlineTraits = orbital.traits.filter(
4981
7750
  (t) => typeof t !== "string" && "stateMachine" in t
4982
7751
  );
4983
7752
  resolver.addLocalTraits(inlineTraits);
4984
7753
  }
4985
- for (const orbital of schema.orbitals) {
7754
+ resolver.seedSchemaEntityIds(orbitals);
7755
+ for (const orbital of orbitals) {
4986
7756
  const result = await resolver.resolve(orbital);
4987
7757
  if (!result.success) {
4988
7758
  errors.push(`Orbital "${orbital.name}": ${result.errors.join(", ")}`);
4989
7759
  } else {
4990
7760
  resolved.push(result.data);
7761
+ resolver.noteResolvedEntityIds(result.data);
4991
7762
  warnings.push(...result.warnings.map((w) => `Orbital "${orbital.name}": ${w}`));
4992
7763
  }
4993
7764
  }
4994
7765
  if (errors.length > 0) {
4995
7766
  return { success: false, errors };
4996
7767
  }
7768
+ resolver.uniquifyCrossOrbitalPulledSiblings(resolved);
4997
7769
  return { success: true, data: resolved, warnings };
4998
7770
  }
4999
7771
 
@@ -5208,4 +7980,4 @@ var InMemoryPersistence = class {
5208
7980
  }
5209
7981
  };
5210
7982
 
5211
- export { EffectExecutor, EventBus, HANDLER_MANIFEST, InMemoryPersistence, MockPersistenceAdapter, StateMachineManager, TickScheduler, buildEmitsFromTraits, collectDeclaredConfigDefaults, collectDeclaredEntityDefaults, createInitialTraitState, createMockPersistence, createTestExecutor, createTickScheduler, createUnifiedLoader, findInitialState, findTransition, formatPayloadValidationError, getIsolatedCollectionName, getNamespacedEvent, isBrowser, isElectron, isNamespacedEvent, isNode, isValidDurationString, normalizeEventKey, parseDurationString, parseNamespacedEvent, preprocessSchema, processEvent, validateEventPayload, validatePayloadShapes };
7983
+ export { EffectExecutor, EventBus, HANDLER_MANIFEST, InMemoryPersistence, LIFECYCLE_EVENTS, MockPersistenceAdapter, StateMachineManager, TickScheduler, buildEmitsFromTraits, collectDeclaredConfigDefaults, collectDeclaredEntityDefaults, createInitialTraitState, createMockPersistence, createTestExecutor, createTickScheduler, createUnifiedLoader, findInitialState, findTransition, formatPayloadValidationError, getIsolatedCollectionName, getNamespacedEvent, isBrowser, isElectron, isNamespacedEvent, isNode, isValidDurationString, normalizeEventKey, parseDurationString, parseNamespacedEvent, preprocessSchema, processEvent, validateEventPayload, validatePayloadShapes };