@neocompose/cli 0.38.4 → 0.38.6

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.
package/dist/neo.mjs CHANGED
@@ -936,7 +936,7 @@ var init_login = __esm({
936
936
  "project:release-channel:write",
937
937
  "project:release-channel:publish"
938
938
  ];
939
- sleep = (ms) => new Promise((resolve4) => setTimeout(resolve4, ms));
939
+ sleep = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms));
940
940
  }
941
941
  });
942
942
 
@@ -44110,6 +44110,18 @@ var init_neoscript = __esm({
44110
44110
  }
44111
44111
  });
44112
44112
 
44113
+ // ../src/common/collections.ts
44114
+ function indexById2(records2) {
44115
+ const indexed = /* @__PURE__ */ new Map();
44116
+ for (const record3 of records2) indexed.set(record3.id, record3);
44117
+ return indexed;
44118
+ }
44119
+ var init_collections = __esm({
44120
+ "../src/common/collections.ts"() {
44121
+ "use strict";
44122
+ }
44123
+ });
44124
+
44113
44125
  // ../src/models/classes/classes.ts
44114
44126
  function isGenericParamConstraint(value) {
44115
44127
  const v = value;
@@ -44245,6 +44257,7 @@ var RETIRED_CONSTRUCTOR_PROJECTIONS_FIELD;
44245
44257
  var init_classes = __esm({
44246
44258
  "../src/models/classes/classes.ts"() {
44247
44259
  "use strict";
44260
+ init_collections();
44248
44261
  init_core();
44249
44262
  init_docs_text2();
44250
44263
  init_member_storage();
@@ -45432,6 +45445,9 @@ function membersById(members) {
45432
45445
  });
45433
45446
  return byId;
45434
45447
  }
45448
+ function classIndexFor(classes) {
45449
+ return classesById(classes);
45450
+ }
45435
45451
  function createMergeMemo() {
45436
45452
  const byClasses = /* @__PURE__ */ new WeakMap();
45437
45453
  return (classId, classIndex, memberIndex, compute) => {
@@ -45574,8 +45590,9 @@ function findNearestAncestorSchemaPlacement(ownerClass, schemaKey, classesById2)
45574
45590
  function walkExtendsMemberChain(startId, members, pick, options) {
45575
45591
  const requireKind = options?.requireKind;
45576
45592
  const maxHops = options?.maxHops ?? 16;
45577
- const byId = membersById(members);
45578
- let cursor = byId.get(startId);
45593
+ const byId = options?.memberById === void 0 ? membersById(members) : null;
45594
+ const getMember = (id2) => options?.memberById?.(id2) ?? byId?.get(id2) ?? null;
45595
+ let cursor = getMember(startId);
45579
45596
  for (let i = 0; cursor && i < maxHops; i++) {
45580
45597
  if (requireKind !== void 0 && cursor.kind !== requireKind) {
45581
45598
  return void 0;
@@ -45584,7 +45601,7 @@ function walkExtendsMemberChain(startId, members, pick, options) {
45584
45601
  if (v !== void 0) return v;
45585
45602
  const nextId = getOptionalString(cursor, "extendsMemberId");
45586
45603
  if (nextId === void 0) return void 0;
45587
- cursor = byId.get(nextId);
45604
+ cursor = getMember(nextId);
45588
45605
  }
45589
45606
  return void 0;
45590
45607
  }
@@ -48220,6 +48237,14 @@ var init_generics = __esm({
48220
48237
  });
48221
48238
 
48222
48239
  // ../src/models/members/instance-provenance.ts
48240
+ function overlayLiteralValueContent(base, override) {
48241
+ const merged = { ...base, ...override };
48242
+ if (!("value" in override) || override.value !== null) return merged;
48243
+ for (const field of LITERAL_INSTANCE_IDENTITY_FIELDS) {
48244
+ if (!Object.hasOwn(override, field)) Reflect.deleteProperty(merged, field);
48245
+ }
48246
+ return merged;
48247
+ }
48223
48248
  function pickInstanceProvenance(source) {
48224
48249
  return {
48225
48250
  ...source.constructorArgs === void 0 ? {} : { constructorArgs: source.constructorArgs },
@@ -48238,10 +48263,19 @@ function carriesCompleteConstructionRecipe(value) {
48238
48263
  if (typeof value.instanceVariantId === "string") return true;
48239
48264
  return value.constructorArgs !== void 0;
48240
48265
  }
48266
+ var LITERAL_INSTANCE_IDENTITY_FIELDS;
48241
48267
  var init_instance_provenance = __esm({
48242
48268
  "../src/models/members/instance-provenance.ts"() {
48243
48269
  "use strict";
48244
48270
  init_member_kinds();
48271
+ LITERAL_INSTANCE_IDENTITY_FIELDS = [
48272
+ "classId",
48273
+ "constructorArgs",
48274
+ "instanceConstructorId",
48275
+ "instanceVariantId",
48276
+ "instanceVariantRowValueId",
48277
+ "genericBindings"
48278
+ ];
48245
48279
  }
48246
48280
  });
48247
48281
 
@@ -56740,6 +56774,7 @@ var init_common = __esm({
56740
56774
  "../src/common/index.ts"() {
56741
56775
  "use strict";
56742
56776
  init_benchmark();
56777
+ init_collections();
56743
56778
  init_error_message();
56744
56779
  init_retree_input_diagnostics();
56745
56780
  }
@@ -67231,7 +67266,121 @@ function validateInternalRecordRelations(args) {
67231
67266
  });
67232
67267
  }
67233
67268
  function resolveEffectiveClassRelations(args) {
67234
- const contract = (args.contracts ?? INTERNAL_RECORD_RELATION_KIND_CONTRACTS).find((candidate) => candidate.relationKind === args.relationKind);
67269
+ return createEffectiveClassRelationResolver({
67270
+ classes: args.classes,
67271
+ relations: args.relations,
67272
+ contracts: args.contracts
67273
+ }).resolve(args.relationKind, args.sourceClassId);
67274
+ }
67275
+ function createEffectiveClassRelationResolver(args) {
67276
+ const contracts = args.contracts ?? INTERNAL_RECORD_RELATION_KIND_CONTRACTS;
67277
+ const contractsByKind = /* @__PURE__ */ new Map();
67278
+ for (const contract of contracts) {
67279
+ contractsByKind.set(contract.relationKind, contract);
67280
+ }
67281
+ const classesById2 = args.classesById ?? classIndexFor(args.classes);
67282
+ const classRelationsByKind = /* @__PURE__ */ new Map();
67283
+ const relationsByIdByKind = /* @__PURE__ */ new Map();
67284
+ const directByKindAndSource = /* @__PURE__ */ new Map();
67285
+ for (const relation of args.relations) {
67286
+ if (relation.sourceRecordKind !== "class" || relation.targetRecordKind !== "class") {
67287
+ continue;
67288
+ }
67289
+ const relations = classRelationsByKind.get(relation.relationKind);
67290
+ if (relations === void 0) {
67291
+ classRelationsByKind.set(relation.relationKind, [relation]);
67292
+ } else relations.push(relation);
67293
+ }
67294
+ const relationById = (relationKind, id2) => {
67295
+ let byId = relationsByIdByKind.get(relationKind);
67296
+ if (byId === void 0) {
67297
+ byId = indexById2(classRelationsByKind.get(relationKind) ?? []);
67298
+ relationsByIdByKind.set(relationKind, byId);
67299
+ }
67300
+ return byId.get(id2);
67301
+ };
67302
+ const ancestryByClassId = /* @__PURE__ */ new Map();
67303
+ const concreteDescendantsByClassId = /* @__PURE__ */ new Map();
67304
+ const childrenByClassId = /* @__PURE__ */ new Map();
67305
+ for (const schemaClass2 of args.classes) {
67306
+ if (schemaClass2.extendsClassId === void 0) continue;
67307
+ const children = childrenByClassId.get(schemaClass2.extendsClassId);
67308
+ if (children === void 0) {
67309
+ childrenByClassId.set(schemaClass2.extendsClassId, [schemaClass2.id]);
67310
+ } else {
67311
+ children.push(schemaClass2.id);
67312
+ }
67313
+ }
67314
+ const ancestry = (classId) => {
67315
+ const cached = ancestryByClassId.get(classId);
67316
+ if (cached !== void 0) return cached;
67317
+ const resolved = classAncestry(classId, classesById2);
67318
+ ancestryByClassId.set(classId, resolved);
67319
+ return resolved;
67320
+ };
67321
+ const concreteDescendants = (classId) => {
67322
+ const cached = concreteDescendantsByClassId.get(classId);
67323
+ if (cached !== void 0) return cached;
67324
+ if (!classesById2.has(classId)) return [];
67325
+ const result = [];
67326
+ const pending = [classId];
67327
+ const visited = /* @__PURE__ */ new Set();
67328
+ while (pending.length > 0) {
67329
+ const candidateId = pending.pop();
67330
+ if (visited.has(candidateId)) {
67331
+ throw new Error(
67332
+ `Class inheritance contains a cycle at "${candidateId}".`
67333
+ );
67334
+ }
67335
+ visited.add(candidateId);
67336
+ const candidate = classesById2.get(candidateId);
67337
+ if (candidate !== void 0 && !candidate.isAbstract) {
67338
+ result.push(candidate.id);
67339
+ }
67340
+ for (const childId of childrenByClassId.get(candidateId) ?? []) {
67341
+ pending.push(childId);
67342
+ }
67343
+ }
67344
+ result.sort((left, right) => left.localeCompare(right));
67345
+ concreteDescendantsByClassId.set(classId, result);
67346
+ return result;
67347
+ };
67348
+ const directClassRelations = (relationKind, sourceClassId) => {
67349
+ let bySource = directByKindAndSource.get(relationKind);
67350
+ if (bySource === void 0) {
67351
+ bySource = /* @__PURE__ */ new Map();
67352
+ for (const relation of classRelationsByKind.get(relationKind) ?? []) {
67353
+ const declarations = bySource.get(relation.sourceRecordId);
67354
+ if (declarations === void 0) {
67355
+ bySource.set(relation.sourceRecordId, [relation]);
67356
+ } else declarations.push(relation);
67357
+ }
67358
+ directByKindAndSource.set(relationKind, bySource);
67359
+ }
67360
+ return bySource.get(sourceClassId) ?? [];
67361
+ };
67362
+ const resolve5 = (relationKind, sourceClassId) => {
67363
+ const contract = contractsByKind.get(relationKind);
67364
+ return resolveEffectiveClassRelationsFromIndex({
67365
+ relationKind,
67366
+ sourceClassId,
67367
+ contract,
67368
+ ancestry,
67369
+ concreteDescendants,
67370
+ directClassRelations
67371
+ });
67372
+ };
67373
+ return {
67374
+ classesById: classesById2,
67375
+ relationById,
67376
+ directClassRelations,
67377
+ classAncestry: ancestry,
67378
+ concreteClassDescendants: concreteDescendants,
67379
+ resolve: resolve5
67380
+ };
67381
+ }
67382
+ function resolveEffectiveClassRelationsFromIndex(args) {
67383
+ const contract = args.contract;
67235
67384
  if (contract === void 0) {
67236
67385
  throw new Error(`Unknown internal relation kind "${args.relationKind}".`);
67237
67386
  }
@@ -67243,15 +67392,12 @@ function resolveEffectiveClassRelations(args) {
67243
67392
  `Internal relation kind "${args.relationKind}" is not class-to-class.`
67244
67393
  );
67245
67394
  }
67246
- const classesById2 = new Map(
67247
- args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
67248
- );
67249
- const sourceIds = contract.sourceClassPolicy === "include-descendants" ? classAncestry(args.sourceClassId, classesById2) : [args.sourceClassId];
67395
+ const sourceIds = contract.sourceClassPolicy === "include-descendants" ? args.ancestry(args.sourceClassId) : [args.sourceClassId];
67250
67396
  const sourceDepth = new Map(
67251
67397
  sourceIds.map((sourceId3, index) => [sourceId3, index])
67252
67398
  );
67253
- const declarations = args.relations.filter(
67254
- (relation) => relation.relationKind === args.relationKind && relation.sourceRecordKind === "class" && relation.targetRecordKind === "class" && sourceDepth.has(relation.sourceRecordId)
67399
+ const declarations = sourceIds.flatMap(
67400
+ (sourceId3) => args.directClassRelations(args.relationKind, sourceId3)
67255
67401
  );
67256
67402
  if (contract.merge === "nearest-single") {
67257
67403
  const sorted = declarations.sort(
@@ -67273,11 +67419,7 @@ function resolveEffectiveClassRelations(args) {
67273
67419
  const byTarget = /* @__PURE__ */ new Map();
67274
67420
  for (const declaration of declarations) {
67275
67421
  const declarationDepth = sourceDepth.get(declaration.sourceRecordId) ?? 0;
67276
- const targetIds = contract.targetClassPolicy === "include-descendants" ? concreteClassDescendants(
67277
- declaration.targetRecordId,
67278
- args.classes,
67279
- classesById2
67280
- ) : [declaration.targetRecordId];
67422
+ const targetIds = contract.targetClassPolicy === "include-descendants" ? args.concreteDescendants(declaration.targetRecordId) : [declaration.targetRecordId];
67281
67423
  for (const targetId of targetIds) {
67282
67424
  const current = byTarget.get(targetId);
67283
67425
  if (current === void 0) {
@@ -67474,12 +67616,6 @@ function classAncestry(classId, classesById2) {
67474
67616
  }
67475
67617
  return result;
67476
67618
  }
67477
- function concreteClassDescendants(classId, classes, classesById2) {
67478
- if (!classesById2.has(classId)) return [];
67479
- return classes.filter(
67480
- (candidate) => !candidate.isAbstract && classAncestry(candidate.id, classesById2).includes(classId)
67481
- ).map((candidate) => candidate.id).sort((left, right) => left.localeCompare(right));
67482
- }
67483
67619
  function effectiveRelation(relation, targetRecordId, sourceAncestryDepth) {
67484
67620
  return {
67485
67621
  relationKind: relation.relationKind,
@@ -67511,7 +67647,9 @@ var InternalRecordRelationKind, INTERNAL_RECORD_RELATION_KIND_CONTRACTS;
67511
67647
  var init_internal_record_relations = __esm({
67512
67648
  "../src/models/project/internal-record-relations.ts"() {
67513
67649
  "use strict";
67650
+ init_collections();
67514
67651
  init_classes();
67652
+ init_inheritance();
67515
67653
  init_core();
67516
67654
  init_project_version_types();
67517
67655
  InternalRecordRelationKind = {
@@ -67667,6 +67805,7 @@ function makeEvaluatorLookups(members, values, options = {}) {
67667
67805
  const lookups = {
67668
67806
  memberById: (id2) => attrMap.get(id2) ?? null,
67669
67807
  valueById: (id2) => valMap.get(id2) ?? null,
67808
+ hasStoredValueId: (id2) => valMap.has(id2),
67670
67809
  unorderedListEntryIds: (containerValueId) => unorderedListMembership.get(containerValueId) ?? [],
67671
67810
  // An index over a plain row set has no virtual expansion: every row it
67672
67811
  // can answer with is already in `values`.
@@ -67698,9 +67837,20 @@ function evalMemberById(vm, id2) {
67698
67837
  function evalValueById(ctx, id2, runtimeValues, overlayValues) {
67699
67838
  const vm = ctx.vm;
67700
67839
  const runtime = runtimeValues?.get(id2);
67701
- if (runtime !== void 0) return runtime;
67840
+ if (runtime !== void 0) {
67841
+ if (vm.databaseVM?.hasStoredValueId?.(id2) ?? true) {
67842
+ ctx.valueDependencies?.add(id2);
67843
+ }
67844
+ return runtime;
67845
+ }
67702
67846
  const overlay = overlayValues?.get(id2);
67703
- if (overlay !== void 0) return overlay;
67847
+ if (overlay !== void 0) {
67848
+ if (vm.databaseVM?.hasStoredValueId?.(id2) ?? true) {
67849
+ ctx.valueDependencies?.add(id2);
67850
+ }
67851
+ return overlay;
67852
+ }
67853
+ ctx.valueDependencies?.add(id2);
67704
67854
  if (vm.databaseVM?.valueById) return vm.databaseVM.valueById(id2);
67705
67855
  return vm.values.find((v) => v.id === id2) ?? null;
67706
67856
  }
@@ -68110,6 +68260,9 @@ function resolveRuntimeReferenceRow(sourceValueId, ctx, withProvenance) {
68110
68260
  if (!withProvenance) return direct;
68111
68261
  const receiver = trackedRowForValueReference(ctx.thisValue, ctx);
68112
68262
  if (receiver === null) return direct;
68263
+ ctx.onUnattributableValueRead?.(
68264
+ `runtime-reference-provenance:${sourceValueId}`
68265
+ );
68113
68266
  const indexes = evaluatorIndexes(ctx);
68114
68267
  const virtualRows = ctx.vm.databaseVM?.virtualInstanceRowsForValue(receiver.id) ?? [];
68115
68268
  if (virtualRows.length > 0) {
@@ -68716,6 +68869,9 @@ function finalizeConstructorAllocations(ctx, returnValue, ownsInvocationState, r
68716
68869
  }
68717
68870
  }
68718
68871
  }
68872
+ ctx.onUnattributableValueRead?.(
68873
+ `constructor-argument-list:${argumentId}`
68874
+ );
68719
68875
  for (const candidate of evaluatorValues(ctx)) {
68720
68876
  if (candidate.containerId === argumentId) {
68721
68877
  scanCreationDataRow({
@@ -68773,6 +68929,7 @@ function finalizeConstructorAllocations(ctx, returnValue, ownsInvocationState, r
68773
68929
  if (member !== null && isMemberListBase(member)) {
68774
68930
  const entryMember = evalMemberById(ctx.vm, member.entryMemberId);
68775
68931
  if (member.listKind === "unordered") {
68932
+ ctx.onUnattributableValueRead?.(`constructed-unordered-list:${row.id}`);
68776
68933
  for (const candidate of evaluatorValues(ctx)) {
68777
68934
  if (candidate.containerId === row.id) {
68778
68935
  scanOwnedRow(candidate.id, entryMember);
@@ -69067,6 +69224,11 @@ function parameterDefaultsAsFullArguments(argumentTypes, subject) {
69067
69224
  if (!argumentTypes.every(parameterHasDefault)) return null;
69068
69225
  return fillTrailingParameterDefaults([], argumentTypes, subject);
69069
69226
  }
69227
+ function declarationInitializerArgumentValues(argumentTypes, subject, readsConstructorParameter) {
69228
+ const defaults = parameterDefaultsAsFullArguments(argumentTypes, subject);
69229
+ if (defaults !== null) return defaults;
69230
+ return readsConstructorParameter ? [] : argumentTypes.map(() => null);
69231
+ }
69070
69232
  function fillCallableCallSiteArguments(args, member, ctx) {
69071
69233
  if (member === null) return args;
69072
69234
  if (member.kind !== 13 /* Function */ && member.kind !== 23 /* NSFunction */) {
@@ -70219,6 +70381,7 @@ function staticBindingTargetId(member, ctx) {
70219
70381
  `Member '${member.name}' is not a static member.`
70220
70382
  );
70221
70383
  }
70384
+ ctx.staticMemberDependencies?.add(member.id);
70222
70385
  const storage = effectiveStaticStorage(member.id, ctx);
70223
70386
  const bindings = storage === "save" /* Save */ ? ctx.__saveStaticBindings : storage === "session" /* Session */ ? ctx.__sessionStaticBindings : void 0;
70224
70387
  if (bindings?.has(member.id)) return bindings.get(member.id) ?? null;
@@ -70266,7 +70429,6 @@ function evalStaticMember(memberId, ctx) {
70266
70429
  `Static member '${member.name}' is bound to missing value '${targetId}'.`
70267
70430
  );
70268
70431
  }
70269
- ctx.valueDependencies?.add(row.id);
70270
70432
  return row.value;
70271
70433
  }
70272
70434
  function evalPointer(pointer, scope, ctx) {
@@ -70875,6 +71037,7 @@ function delegateClosureLexicalThis(closure, ctx) {
70875
71037
  "Stored NeoDelegate closure has no resolvable value row; lexical this cannot be reconstructed from ownership."
70876
71038
  );
70877
71039
  }
71040
+ ctx.onUnattributableValueRead?.(`delegate-owner-resolution:${closureRow.id}`);
70878
71041
  const owners = [];
70879
71042
  const indexes = evaluatorIndexes(ctx);
70880
71043
  for (const [ancestorId, distance] of evaluatorOwnershipDistances(
@@ -71035,6 +71198,7 @@ function runtimeGenericEnvForValueRow(row, ctx, visited) {
71035
71198
  }
71036
71199
  function runtimeParentGenericEnv(row, ctx, visited) {
71037
71200
  const result = /* @__PURE__ */ new Map();
71201
+ ctx.onUnattributableValueRead?.(`generic-parent-resolution:${row.id}`);
71038
71202
  for (const link of evaluatorParentLinks(evaluatorIndexes(ctx), row.id)) {
71039
71203
  const parent = evalValueById(
71040
71204
  ctx,
@@ -71748,7 +71912,6 @@ function resolveValueIfId(at, ctx) {
71748
71912
  ctx.__valueOverlay
71749
71913
  );
71750
71914
  if (!row) return at;
71751
- ctx.valueDependencies?.add(row.id);
71752
71915
  const member = memberForValueRow(row, ctx);
71753
71916
  if (member !== null && isMemberListBase(member) && member.listKind === "unordered" && Array.isArray(row.value)) {
71754
71917
  return evaluatorUnorderedListEntryIds(row.id, ctx);
@@ -71765,7 +71928,6 @@ function resolveValueIfIdForMember(at, member, ctx) {
71765
71928
  ctx.__valueOverlay
71766
71929
  );
71767
71930
  if (!row) return at;
71768
- ctx.valueDependencies?.add(row.id);
71769
71931
  if (isMemberListBase(member) && member.listKind === "unordered" && Array.isArray(row.value)) {
71770
71932
  return evaluatorUnorderedListEntryIds(row.id, ctx);
71771
71933
  }
@@ -71773,6 +71935,7 @@ function resolveValueIfIdForMember(at, member, ctx) {
71773
71935
  return shouldUnwrapSingleLookupValue(member) ? unwrapSingleLookupValue(value, ctx) : value;
71774
71936
  }
71775
71937
  function evaluatorUnorderedListEntryIds(containerValueId, ctx) {
71938
+ ctx.containerDependencies?.add(containerValueId);
71776
71939
  const runtimeRows = [...ctx.__runtimeSessionValues?.values() ?? []];
71777
71940
  const overlayRows = [...ctx.__valueOverlay?.values() ?? []];
71778
71941
  const localRows = [...runtimeRows, ...overlayRows];
@@ -71798,7 +71961,6 @@ function unwrapSingleLookupValue(value, ctx) {
71798
71961
  ctx.__valueOverlay
71799
71962
  );
71800
71963
  if (next) {
71801
- ctx.valueDependencies?.add(next.id);
71802
71964
  return next.value;
71803
71965
  }
71804
71966
  }
@@ -71839,6 +72001,7 @@ function resolveMemberForValueRow(row, ctx, visited) {
71839
72001
  if (syntheticMemberId !== null) {
71840
72002
  return evalMemberById(ctx.vm, syntheticMemberId);
71841
72003
  }
72004
+ ctx.onUnattributableValueRead?.(`member-owner-resolution:${row.id}`);
71842
72005
  for (const link of evaluatorParentLinks(indexes, row.id)) {
71843
72006
  const parent = evalValueById(
71844
72007
  ctx,
@@ -71903,13 +72066,11 @@ function memberIdFromSyntheticDefaultValueId(valueId) {
71903
72066
  return valueId.slice(prefix.length, -suffix.length);
71904
72067
  }
71905
72068
  function resolveLocalizedTextId(value, ctx) {
72069
+ ctx.localizedTextDependencies?.add(value);
71906
72070
  const mainLocale = ctx.vm.localizationConfig?.mainLocale;
71907
72071
  if (mainLocale === void 0) return value;
71908
- const text = ctx.vm.localizedTexts?.find(
71909
- (candidate) => candidate.id === value
71910
- );
71911
- if (text === void 0) return value;
71912
- ctx.localizedTextDependencies?.add(text.id);
72072
+ const text = ctx.vm.databaseVM?.localizedTextById?.(value) ?? ctx.vm.localizedTexts?.find((candidate) => candidate.id === value) ?? null;
72073
+ if (text === null) return value;
71913
72074
  return text.localeValues[mainLocale]?.value ?? "";
71914
72075
  }
71915
72076
  function evalOperation(operation, scope, ctx) {
@@ -73350,6 +73511,7 @@ function bindConstructedDelegateTargets(createdValues, ctx) {
73350
73511
  `NeoDelegate method target '${target.name}' has no declaring Class placement.`
73351
73512
  );
73352
73513
  }
73514
+ ctx.onUnattributableValueRead?.(`constructed-delegate-owner:${row.id}`);
73353
73515
  const matches = [];
73354
73516
  for (const [ancestorId, distance] of evaluatorOwnershipDistances(
73355
73517
  row.id,
@@ -74097,6 +74259,17 @@ function constructorInitializerIndexes(ctx) {
74097
74259
  ctx.__constructorInitializerIndexes = built;
74098
74260
  return built;
74099
74261
  }
74262
+ function constructorById(constructorId, ctx) {
74263
+ if (ctx.__constructorById === void 0) {
74264
+ ctx.__constructorById = new Map(
74265
+ (ctx.vm.constructors ?? []).map((constructor2) => [
74266
+ constructor2.id,
74267
+ constructor2
74268
+ ])
74269
+ );
74270
+ }
74271
+ return ctx.__constructorById.get(constructorId);
74272
+ }
74100
74273
  function buildConstructorInitializerIndexes(vm) {
74101
74274
  const initializerScopeMemberIds = /* @__PURE__ */ new WeakMap();
74102
74275
  const initializerScopeMemberIdsByValueId = /* @__PURE__ */ new Map();
@@ -74133,6 +74306,9 @@ function buildConstructorInitializerIndexes(vm) {
74133
74306
  initializerScopeMemberIdsByValueId.set(valueId, rootOwnerId);
74134
74307
  }
74135
74308
  }
74309
+ const classById = new Map(
74310
+ vm.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
74311
+ );
74136
74312
  const declaringClassIdsByMemberId = /* @__PURE__ */ new Map();
74137
74313
  for (const schemaClass2 of vm.classes) {
74138
74314
  for (const memberId of Object.values(schemaClass2.schema)) {
@@ -74151,6 +74327,7 @@ function buildConstructorInitializerIndexes(vm) {
74151
74327
  return {
74152
74328
  initializerScopeMemberIds,
74153
74329
  initializerScopeMemberIdsByValueId,
74330
+ classById,
74154
74331
  declaringClassIdsByMemberId,
74155
74332
  memberById: memberById2,
74156
74333
  containerMemberIdByEntryId
@@ -74527,10 +74704,9 @@ function resolveVariantGraph(selection2, ctx) {
74527
74704
  "Base variant selection has no variant graph."
74528
74705
  );
74529
74706
  }
74530
- const record3 = (ctx.vm.variants ?? []).find(
74531
- (candidate) => candidate.id === variantId
74532
- );
74533
- if (record3 === void 0) {
74707
+ ctx.variantDependencies?.add(variantId);
74708
+ const record3 = ctx.vm.databaseVM?.variantById?.(variantId) ?? (ctx.vm.variants ?? []).find((candidate) => candidate.id === variantId) ?? null;
74709
+ if (record3 === null) {
74534
74710
  throw new NSGetterRuntimeError(
74535
74711
  `Variant '${variantId}' does not exist in this project.`
74536
74712
  );
@@ -75395,6 +75571,7 @@ function currentOwnedValueAttachments(valueId, ctx) {
75395
75571
  });
75396
75572
  }
75397
75573
  }
75574
+ ctx.onUnattributableValueRead?.(`owned-value-parents:${valueId}`);
75398
75575
  const parentIds = new Set(
75399
75576
  evaluatorParentLinks(indexes, valueId).map((link) => link.parentId)
75400
75577
  );
@@ -75671,6 +75848,9 @@ function cloneConstructorArgumentGraph(args) {
75671
75848
  if (member.listKind === "unordered") {
75672
75849
  clone.value = [];
75673
75850
  const entryEnv2 = envFromStamp(clone.genericBindings);
75851
+ args.ctx.onUnattributableValueRead?.(
75852
+ `constructor-import-list:${source.id}`
75853
+ );
75674
75854
  const entries = evaluatorValues(args.ctx).filter((row) => row.containerId === source.id).sort((left, right) => left.id.localeCompare(right.id));
75675
75855
  for (const entry of entries) {
75676
75856
  cloneRow2(entry, entryMember, entryEnv2, clone.id);
@@ -75801,7 +75981,19 @@ function materializeConstructorArgumentValue(args) {
75801
75981
  args.ctx.vm.members
75802
75982
  );
75803
75983
  const row = registerConstructorArgumentRow(args, []);
75804
- const sourceEntries = args.member.listKind === "unordered" && trackedValueId !== null ? evaluatorValues(args.ctx).filter((entry) => entry.containerId === trackedValueId).sort((left, right) => left.id.localeCompare(right.id)).map((entry) => entry.value) : args.value;
75984
+ let sourceEntries = args.value;
75985
+ if (args.member.listKind === "unordered" && trackedValueId !== null) {
75986
+ args.ctx.onUnattributableValueRead?.(
75987
+ `constructor-argument-list:${trackedValueId}`
75988
+ );
75989
+ const rows = [];
75990
+ for (const entry of evaluatorValues(args.ctx)) {
75991
+ if (entry.containerId === trackedValueId) rows.push(entry);
75992
+ }
75993
+ rows.sort((left, right) => left.id.localeCompare(right.id));
75994
+ sourceEntries = [];
75995
+ for (const entry of rows) sourceEntries.push(entry.value);
75996
+ }
75805
75997
  const ids = [];
75806
75998
  for (const [index, rawEntry] of sourceEntries.entries()) {
75807
75999
  const entryValue = constructorCollectionEntryValue(
@@ -75998,6 +76190,7 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
75998
76190
  const active = /* @__PURE__ */ new Set();
75999
76191
  const clonedBySourceId = /* @__PURE__ */ new Map();
76000
76192
  const constructorArgumentReferenceCounts = /* @__PURE__ */ new Map();
76193
+ ctx.onUnattributableValueRead?.(`class-clone:${sourceId3}`);
76001
76194
  for (const candidate of evaluatorValues(ctx)) {
76002
76195
  for (const argument2 of ownedConstructorArgumentValues(candidate, ctx)) {
76003
76196
  constructorArgumentReferenceCounts.set(
@@ -76006,7 +76199,95 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
76006
76199
  );
76007
76200
  }
76008
76201
  }
76009
- const cloneRow2 = (sourceRow, sourceMember, clonedContainerId, sourceTypeInfo) => {
76202
+ function cloneInitializerRow(sourceRow, sourceMember, id2, clonedContainerId, sourceTypeInfo) {
76203
+ if (sourceMember === null) {
76204
+ throw new NSGetterRuntimeError(
76205
+ `Class.Clone cannot evaluate initializer-backed value '${sourceRow.id}' because its owning member could not be resolved.`
76206
+ );
76207
+ }
76208
+ const indexes = constructorInitializerIndexes(ctx);
76209
+ const runtimeMemberId = Reflect.get(sourceMember, "id");
76210
+ const compileMemberId = indexes.initializerScopeMemberIds.get(sourceRow.init) ?? indexes.initializerScopeMemberIdsByValueId.get(sourceRow.id) ?? (typeof runtimeMemberId === "string" ? runtimeMemberId : null);
76211
+ const compiled = ensureInitializerCompiled({
76212
+ init: sourceRow.init,
76213
+ member: sourceMember,
76214
+ initializerCompiler: ctx.vm.initializerCompiler,
76215
+ sourceValueId: sourceRow.id,
76216
+ compileMemberId
76217
+ });
76218
+ const declaringClassId = compileMemberId === null ? void 0 : indexes.declaringClassIdsByMemberId.get(compileMemberId)?.values().next().value;
76219
+ const ownerClass = declaringClassId === void 0 ? void 0 : indexes.classById.get(declaringClassId);
76220
+ const constructorId = ownerClass?.requiredConstructorId;
76221
+ const constructor2 = typeof constructorId === "string" ? constructorById(constructorId, ctx) : void 0;
76222
+ const argumentValues = constructor2 === void 0 ? [] : declarationInitializerArgumentValues(
76223
+ constructor2.argumentTypes,
76224
+ `Class.Clone initializer on '${ownerClass?.name ?? sourceMember.name}'`,
76225
+ compiled.parameters.slice(2).some(
76226
+ (parameter4) => runtimeValueReferencesVariable(
76227
+ compiled.instructions,
76228
+ parameter4.id
76229
+ )
76230
+ )
76231
+ );
76232
+ const initializerCreatedValues = [];
76233
+ const evaluated = evaluateInitializerInContext(
76234
+ sourceRow.init,
76235
+ sourceMember,
76236
+ ctx,
76237
+ initializerCreatedValues,
76238
+ argumentValues,
76239
+ sourceRow.id,
76240
+ compileMemberId
76241
+ );
76242
+ if (evaluated.existingValueRow !== void 0) {
76243
+ const adoptedClone = cloneRow2(
76244
+ evaluated.existingValueRow,
76245
+ sourceMember,
76246
+ clonedContainerId,
76247
+ sourceTypeInfo
76248
+ );
76249
+ clonedBySourceId.set(sourceRow.id, adoptedClone);
76250
+ active.delete(sourceRow.id);
76251
+ return adoptedClone;
76252
+ }
76253
+ const {
76254
+ init: _init,
76255
+ value: _value,
76256
+ classId: _classId,
76257
+ ...sourceEnvelope
76258
+ } = sourceRow;
76259
+ void _init;
76260
+ void _value;
76261
+ void _classId;
76262
+ const clone = {
76263
+ ...sourceEnvelope,
76264
+ id: id2,
76265
+ value: evaluated.value,
76266
+ ...evaluated.classId === null ? {} : { classId: evaluated.classId },
76267
+ ...evaluated.genericBindings === void 0 ? {} : { genericBindings: { ...evaluated.genericBindings } },
76268
+ ...deepClonePlainData(pickInstanceProvenance(evaluated)),
76269
+ containerId: clonedContainerId ?? null
76270
+ };
76271
+ if (evaluated.provisionalRootId !== void 0) {
76272
+ retargetDelegateReceiverValueIds(
76273
+ [clone, ...initializerCreatedValues],
76274
+ evaluated.provisionalRootId,
76275
+ clone.id
76276
+ );
76277
+ }
76278
+ registerRuntimeSessionValue(ctx, clone);
76279
+ clonedBySourceId.set(sourceRow.id, clone);
76280
+ if (typeof clone.value === "object" && clone.value !== null) {
76281
+ ctx.__cloneSourceRowIds ??= /* @__PURE__ */ new WeakMap();
76282
+ ctx.__cloneSourceRowIds.set(clone.value, sourceRow.id);
76283
+ }
76284
+ active.delete(sourceRow.id);
76285
+ if (ctx.__indexes !== void 0) {
76286
+ indexEvaluatorRow(ctx.__indexes, clone);
76287
+ }
76288
+ return clone;
76289
+ }
76290
+ function cloneRow2(sourceRow, sourceMember, clonedContainerId, sourceTypeInfo) {
76010
76291
  if (active.has(sourceRow.id)) {
76011
76292
  throw new NSGetterRuntimeError(
76012
76293
  `Class.Clone found a cycle through owned value '${sourceRow.id}'.`
@@ -76016,6 +76297,15 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
76016
76297
  if (prior !== void 0) return prior;
76017
76298
  active.add(sourceRow.id);
76018
76299
  const id2 = freshCloneValueId();
76300
+ if (isInitValueContent(sourceRow)) {
76301
+ return cloneInitializerRow(
76302
+ sourceRow,
76303
+ sourceMember,
76304
+ id2,
76305
+ clonedContainerId,
76306
+ sourceTypeInfo
76307
+ );
76308
+ }
76019
76309
  const clone = {
76020
76310
  ...sourceRow,
76021
76311
  id: id2,
@@ -76070,6 +76360,9 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
76070
76360
  entryTypeInfo
76071
76361
  ).id;
76072
76362
  });
76363
+ ctx.onUnattributableValueRead?.(
76364
+ `class-clone-unordered-list:${sourceRow.id}`
76365
+ );
76073
76366
  for (const child of evaluatorValues(ctx)) {
76074
76367
  if (child.containerId !== sourceRow.id) continue;
76075
76368
  cloneRow2(child, entryMember, id2, entryTypeInfo);
@@ -76116,7 +76409,7 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
76116
76409
  indexEvaluatorRow(ctx.__indexes, clone);
76117
76410
  }
76118
76411
  return clone;
76119
- };
76412
+ }
76120
76413
  const rootMember = memberForValueRow(source, ctx);
76121
76414
  const typedSource = source.classId === void 0 ? { ...source, classId: runtimeClassId } : source;
76122
76415
  const clonedRoot = cloneRow2(typedSource, rootMember);
@@ -76368,6 +76661,12 @@ var init_evaluateNSGetter = __esm({
76368
76661
  if (existing !== void 0) return existing;
76369
76662
  const source = this.sourceRowById(id2);
76370
76663
  if (source === void 0) return void 0;
76664
+ if (isInitValueContent(source)) {
76665
+ const clone2 = { ...source, init: { ...source.init } };
76666
+ super.set(id2, clone2);
76667
+ this.materializedRows.push(clone2);
76668
+ return clone2;
76669
+ }
76371
76670
  let value = source.value;
76372
76671
  if (Array.isArray(value)) value = [...value];
76373
76672
  else if (typeof value === "object" && value !== null) value = { ...value };
@@ -76691,27 +76990,6 @@ function buildVirtualInstanceMaterializedIndex(args) {
76691
76990
  })
76692
76991
  };
76693
76992
  }
76694
- function firstListInParameterType(typeInfo, depth = 0) {
76695
- if (typeof typeInfo !== "object" || typeInfo === null) return null;
76696
- if (depth > CONSTRUCTOR_TYPE_WALK_DEPTH_LIMIT) return "depth-limit";
76697
- const shape = typeInfo;
76698
- if (shape.type === 6 /* List */) return "list";
76699
- const entry = firstListInParameterType(shape.entryTypeInfo, depth + 1);
76700
- if (entry !== null) return entry;
76701
- if (Array.isArray(shape.argumentTypes)) {
76702
- for (const argument2 of shape.argumentTypes) {
76703
- const nested = firstListInParameterType(argument2, depth + 1);
76704
- if (nested !== null) return nested;
76705
- }
76706
- }
76707
- return null;
76708
- }
76709
- function constructorBodyIsCorpusFree(constructor2) {
76710
- if (constructor2.code !== null && constructor2.code.trim() !== "") return false;
76711
- if ((constructor2.baseArguments ?? []).length > 0) return false;
76712
- if ((constructor2.baseInitializerFields ?? []).length > 0) return false;
76713
- return true;
76714
- }
76715
76993
  function withoutInitializerConstructionFields(init) {
76716
76994
  if (init.compiled === void 0) return init;
76717
76995
  const baseline = deepClonePlainData(init);
@@ -76769,6 +77047,31 @@ function claimVirtualIdentity(args) {
76769
77047
  }
76770
77048
  function expandStoredInstance(args) {
76771
77049
  const recorder = args.readRecorder ?? null;
77050
+ const readTracking = recorder === null ? void 0 : new InitializerReadSet();
77051
+ const trackMaterialization = readTracking === void 0 ? (materialize) => materialize() : (materialize) => {
77052
+ try {
77053
+ return materialize();
77054
+ } finally {
77055
+ for (const valueId of readTracking.valueIds) {
77056
+ recorder?.recordValueRead(valueId);
77057
+ }
77058
+ for (const textId of readTracking.localizedTextIds) {
77059
+ recorder?.recordLocalizedTextRead(textId);
77060
+ }
77061
+ for (const variantId of readTracking.variantIds) {
77062
+ recorder?.recordVariantRead(variantId);
77063
+ }
77064
+ for (const memberId of readTracking.staticMemberIds) {
77065
+ recorder?.recordStaticMemberRead(memberId);
77066
+ }
77067
+ for (const containerId of readTracking.containerIds) {
77068
+ recorder?.recordContainerMembershipRead(containerId);
77069
+ }
77070
+ if (readTracking.hasUnattributableValueRead) {
77071
+ recorder?.recordGlobalRead("initializer-runtime");
77072
+ }
77073
+ }
77074
+ };
76772
77075
  recorder?.recordValueRead(args.instanceRoot.id);
76773
77076
  const rootMember = resolveMember2(args.rootMember, args.document.members);
76774
77077
  if (!isMemberClassBase(rootMember)) {
@@ -76807,25 +77110,6 @@ function expandStoredInstance(args) {
76807
77110
  `Virtual expansion root "${args.instanceRoot.id}" has no durable overload identity for class "${classId}"; keep this historical graph materialized.`
76808
77111
  );
76809
77112
  }
76810
- if (recorder !== null && requiredConstructor !== null) {
76811
- if (!constructorBodyIsCorpusFree(requiredConstructor)) {
76812
- recorder.recordGlobalRead(
76813
- `authored-constructor-body:${requiredConstructor.id}`
76814
- );
76815
- }
76816
- for (const typeInfo of requiredConstructor.argumentTypes) {
76817
- if (firstListInParameterType(typeInfo) === null) continue;
76818
- recorder.recordGlobalRead(
76819
- `constructor-argument-list:${requiredConstructor.id}`
76820
- );
76821
- break;
76822
- }
76823
- }
76824
- if (recorder !== null && typeof instanceRoot.instanceVariantId === "string") {
76825
- recorder.recordGlobalRead(
76826
- `variant-initialize:${instanceRoot.instanceVariantId}`
76827
- );
76828
- }
76829
77113
  const storedArgs = instanceRoot.constructorArgs ?? {};
76830
77114
  if (requiredConstructor !== null && instanceRoot.constructorArgs == null) {
76831
77115
  throw new VirtualExpansionUnsupportedError(
@@ -76923,22 +77207,32 @@ function expandStoredInstance(args) {
76923
77207
  code: `virtual-replay:${args.instanceRoot.id}`,
76924
77208
  compiled
76925
77209
  };
76926
- return materializeInitializerValue({
76927
- document: args.document,
76928
- member: replayMember,
76929
- row: { ...envelope, init },
76930
- storedConstructionReplay: true,
76931
- constructionBaselineReplay: fields.length === 0
76932
- });
77210
+ return trackMaterialization(
77211
+ () => materializeInitializerValue({
77212
+ document: args.document,
77213
+ member: replayMember,
77214
+ row: { ...envelope, init },
77215
+ storedConstructionReplay: true,
77216
+ constructionBaselineReplay: fields.length === 0,
77217
+ ...readTracking === void 0 ? {} : { readTracking },
77218
+ saveStaticBindings: args.saveStaticBindings,
77219
+ sessionStaticBindings: args.sessionStaticBindings
77220
+ })
77221
+ );
76933
77222
  };
76934
77223
  const replayDeclaredDefault = () => {
76935
77224
  const stampEnv = instanceRoot.genericBindings == null || Object.keys(instanceRoot.genericBindings).length === 0 ? null : envFromStamp(instanceRoot.genericBindings);
76936
- const built = materializeMemberDefaultValue({
76937
- document: args.document,
76938
- member: replayMember,
76939
- envelope,
76940
- ...stampEnv === null ? {} : { genericEnv: stampEnv }
76941
- });
77225
+ const built = trackMaterialization(
77226
+ () => materializeMemberDefaultValue({
77227
+ document: args.document,
77228
+ member: replayMember,
77229
+ envelope,
77230
+ ...stampEnv === null ? {} : { genericEnv: stampEnv },
77231
+ ...readTracking === void 0 ? {} : { readTracking },
77232
+ saveStaticBindings: args.saveStaticBindings,
77233
+ sessionStaticBindings: args.sessionStaticBindings
77234
+ })
77235
+ );
76942
77236
  return {
76943
77237
  ...built,
76944
77238
  root: {
@@ -77049,8 +77343,7 @@ function resolveVirtualInstanceGraph(args) {
77049
77343
  const materialized = effectiveMaterializedId === null ? null : readMaterializedRow(effectiveMaterializedId);
77050
77344
  const effectiveId = materialized?.id ?? indexed.virtualId;
77051
77345
  const effective = {
77052
- ...cloneRow(indexed.expandedRow),
77053
- ...materialized === null ? {} : cloneRow(materialized),
77346
+ ...mergeExpandedAndMaterializedRow(indexed.expandedRow, materialized),
77054
77347
  id: effectiveId,
77055
77348
  // Virtual rows inherit partition and timestamps from the root. Real rows
77056
77349
  // retain their own envelope through the spread above.
@@ -77093,7 +77386,7 @@ function resolveVirtualInstanceGraph(args) {
77093
77386
  const listMember = indexed.member;
77094
77387
  effective.value = [];
77095
77388
  const childPaths = expansion.childPathsByParentPath.get(pathKey) ?? [];
77096
- recorder?.recordGlobalRead(`unordered-list-membership:${effectiveId}`);
77389
+ recorder?.recordContainerMembershipRead(effectiveId);
77097
77390
  const storedEntryIds = materializedUnorderedEntryIdsByContainerId.get(effectiveId) ?? [];
77098
77391
  const storedEntries = storedEntryIds.flatMap((storedEntryId) => {
77099
77392
  const entry = readMaterializedRow(storedEntryId);
@@ -77266,19 +77559,18 @@ function resolveVirtualInstanceGraph(args) {
77266
77559
  root: rootLocation
77267
77560
  };
77268
77561
  }
77562
+ function mergeExpandedAndMaterializedRow(expanded, materialized) {
77563
+ const expandedClone = cloneRow(expanded);
77564
+ if (materialized === null) return expandedClone;
77565
+ const materializedClone = cloneRow(materialized);
77566
+ return isLiteralValueContent(materialized) ? overlayLiteralValueContent(expandedClone, materializedClone) : { ...expandedClone, ...materializedClone };
77567
+ }
77269
77568
  function firstUnattributableExpansionMember(expansion) {
77270
77569
  for (const node of expansion.nodesByPath.values()) {
77271
77570
  const member = node.member;
77272
- if (isMemberListBase(member) && listKindOf(member) === "unordered") {
77273
- return `unordered-list-member:${node.memberId}`;
77274
- }
77275
77571
  if (CORPUS_SCANNING_MEMBER_KINDS.has(member.kind)) {
77276
77572
  return `corpus-scanning-member-kind:${node.memberId}`;
77277
77573
  }
77278
- const declaredDefault = member.defaultValue;
77279
- if (declaredDefault !== void 0 && declaredDefault !== null && "init" in declaredDefault && declaredDefault.init !== void 0 && declaredDefault.init !== null) {
77280
- return `authored-initializer-member:${node.memberId}`;
77281
- }
77282
77574
  }
77283
77575
  return null;
77284
77576
  }
@@ -78668,7 +78960,8 @@ function resolveVariantInstanceGraphForDocument(args) {
78668
78960
  const priorExpanded = expandStoredInstance({
78669
78961
  document,
78670
78962
  instanceRoot: args.priorInstanceRoot,
78671
- rootMember
78963
+ rootMember,
78964
+ readRecorder: args.readRecorder
78672
78965
  });
78673
78966
  const priorGraph = resolveVirtualInstanceGraph({
78674
78967
  document,
@@ -78676,7 +78969,8 @@ function resolveVariantInstanceGraphForDocument(args) {
78676
78969
  rootMember,
78677
78970
  expandedRoot: priorExpanded.root,
78678
78971
  expandedRows: priorExpanded.rows,
78679
- materializedRows: [...materializedById.values()]
78972
+ materializedRows: [...materializedById.values()],
78973
+ readRecorder: args.readRecorder
78680
78974
  });
78681
78975
  for (const valueId of args.answeredValueIds) {
78682
78976
  if (!priorGraph.locationsById.has(valueId)) {
@@ -78704,7 +78998,8 @@ function resolveVariantInstanceGraphForDocument(args) {
78704
78998
  const nextExpanded = expandStoredInstance({
78705
78999
  document,
78706
79000
  instanceRoot: args.nextInstanceRoot,
78707
- rootMember
79001
+ rootMember,
79002
+ readRecorder: args.readRecorder
78708
79003
  });
78709
79004
  const nextGraph = resolveVirtualInstanceGraph({
78710
79005
  document,
@@ -78712,7 +79007,8 @@ function resolveVariantInstanceGraphForDocument(args) {
78712
79007
  rootMember,
78713
79008
  expandedRoot: nextExpanded.root,
78714
79009
  expandedRows: nextExpanded.rows,
78715
- materializedRows: [...materializedById.values()]
79010
+ materializedRows: [...materializedById.values()],
79011
+ readRecorder: args.readRecorder
78716
79012
  });
78717
79013
  const root = nextGraph.rowsById.get(args.nextInstanceRoot.id);
78718
79014
  if (root === void 0) {
@@ -78787,7 +79083,8 @@ function createHeadlessVirtualInstanceResolver(args) {
78787
79083
  const expanded = expandStoredInstance({
78788
79084
  document: resolverDocument,
78789
79085
  instanceRoot,
78790
- rootMember: member
79086
+ rootMember: member,
79087
+ readRecorder: args.readRecorder
78791
79088
  });
78792
79089
  const graph = resolveVirtualInstanceGraph({
78793
79090
  document: resolverDocument,
@@ -78795,7 +79092,8 @@ function createHeadlessVirtualInstanceResolver(args) {
78795
79092
  rootMember: member,
78796
79093
  expandedRoot: expanded.root,
78797
79094
  expandedRows: expanded.rows,
78798
- materializedIndex
79095
+ materializedIndex,
79096
+ readRecorder: args.readRecorder
78799
79097
  });
78800
79098
  graphRowsByRootId.set(rootId, graph.rowsById);
78801
79099
  for (const [id2, row] of graph.rowsById) {
@@ -78816,8 +79114,11 @@ function createHeadlessVirtualInstanceResolver(args) {
78816
79114
  }
78817
79115
  };
78818
79116
  const virtualInstanceRowsForValue = (receiverValueId) => {
79117
+ args.readRecorder?.recordValuePlacementRead();
79118
+ args.readRecorder?.recordValueRead(receiverValueId);
78819
79119
  let placement = placements().get(receiverValueId) ?? null;
78820
79120
  while (placement !== null) {
79121
+ args.readRecorder?.recordValueRead(placement.valueId);
78821
79122
  const raw = rawById.get(placement.valueId);
78822
79123
  if (raw !== void 0 && isLiteralValueContent(raw) && isVirtualInstanceRootShape(raw)) {
78823
79124
  return [...expandRoot(placement.valueId, placement.memberId).values()];
@@ -78838,7 +79139,7 @@ function createHeadlessVirtualInstanceResolver(args) {
78838
79139
  }
78839
79140
  };
78840
79141
  }
78841
- var KEPT_ROW_SAMPLE_LIMIT, CORPUS_SCANNING_MEMBER_KINDS, CONSTRUCTOR_TYPE_WALK_DEPTH_LIMIT, VirtualExpansionUnsupportedError, ROOT_PATH, SYNTHETIC_LINEAGE_PREFIXES, resolverDocumentsByDocument;
79142
+ var KEPT_ROW_SAMPLE_LIMIT, CORPUS_SCANNING_MEMBER_KINDS, VirtualExpansionUnsupportedError, ROOT_PATH, SYNTHETIC_LINEAGE_PREFIXES, resolverDocumentsByDocument;
78842
79143
  var init_virtual_instance_values = __esm({
78843
79144
  "../src/database/virtual-instance-values.ts"() {
78844
79145
  "use strict";
@@ -78852,6 +79153,7 @@ var init_virtual_instance_values = __esm({
78852
79153
  init_instance_provenance();
78853
79154
  init_unordered_list_membership();
78854
79155
  init_neoscript();
79156
+ init_evaluateInitializer();
78855
79157
  init_init_backed_value_materialization();
78856
79158
  init_constructor_argument_ownership();
78857
79159
  init_constructors2();
@@ -78859,15 +79161,8 @@ var init_virtual_instance_values = __esm({
78859
79161
  KEPT_ROW_SAMPLE_LIMIT = 12;
78860
79162
  CORPUS_SCANNING_MEMBER_KINDS = /* @__PURE__ */ new Set([
78861
79163
  9 /* Lookup */,
78862
- 18 /* DialogueLookup */,
78863
- 10 /* NSProperty */,
78864
- 23 /* NSFunction */,
78865
- 13 /* Function */,
78866
- 24 /* FunctionRef */,
78867
- 25 /* NSDelegate */,
78868
- 26 /* NSAction */
79164
+ 18 /* DialogueLookup */
78869
79165
  ]);
78870
- CONSTRUCTOR_TYPE_WALK_DEPTH_LIMIT = 8;
78871
79166
  VirtualExpansionUnsupportedError = class extends Error {
78872
79167
  constructor(message) {
78873
79168
  super(message);
@@ -78881,24 +79176,74 @@ var init_virtual_instance_values = __esm({
78881
79176
  });
78882
79177
 
78883
79178
  // ../src/view-models/neoscript-evaluator/evaluateInitializer.ts
78884
- function initializerEvaluatorLookups(document) {
78885
- const key = document.evaluatorCache?.key ?? document;
78886
- const revision = document.evaluatorCache?.revision;
78887
- const cached = evaluatorLookupsByDocument.get(key);
78888
- if (cached !== void 0 && (revision === void 0 ? cached.members === document.members && cached.values === document.values : cached.revision === revision)) {
79179
+ function initializerEvaluatorCacheKey(document) {
79180
+ return document.evaluatorCache?.key ?? document;
79181
+ }
79182
+ function initializerEvaluatorCacheRevision(document) {
79183
+ return document.evaluatorCache?.revision;
79184
+ }
79185
+ function initializerEvaluatorLookups(document, readTracking) {
79186
+ const trackedHeadless = readTracking !== void 0 && document.databaseVM === void 0;
79187
+ const indexKey = initializerEvaluatorCacheKey(document);
79188
+ const lookupKey = document.databaseVM ?? indexKey;
79189
+ const revision = initializerEvaluatorCacheRevision(document);
79190
+ const cached = evaluatorLookupsByDocument.get(lookupKey);
79191
+ if (!trackedHeadless && cached !== void 0 && (revision === void 0 ? cached.members === document.members && cached.values === document.values : cached.revision === revision)) {
78889
79192
  return cached.lookups;
78890
79193
  }
78891
- const indexedLookups = makeEvaluatorLookups(
78892
- document.members,
78893
- document.values,
78894
- {
78895
- includeValueGraphIndexes: true,
78896
- constructorInitializerDocument: document
78897
- }
79194
+ if (document.databaseVM !== void 0) {
79195
+ const databaseVM = document.databaseVM;
79196
+ const lookups2 = {
79197
+ memberById: (id2) => databaseVM.memberById(id2),
79198
+ valueById: (id2) => databaseVM.valueById(id2),
79199
+ localizedTextById: (id2) => databaseVM.localizedTextById?.(id2) ?? null,
79200
+ ...databaseVM.hasStoredValueId === void 0 ? {} : {
79201
+ hasStoredValueId: (id2) => databaseVM.hasStoredValueId?.(id2) ?? false
79202
+ },
79203
+ variantById: (id2) => databaseVM.variantById?.(id2) ?? null,
79204
+ storedValuePlacementForValueId: (id2) => databaseVM.storedValuePlacementForValueId?.(id2) ?? null,
79205
+ unorderedListEntryIds: (containerValueId) => {
79206
+ const resolved = databaseVM.unorderedListEntryIds?.(containerValueId);
79207
+ if (resolved === void 0) {
79208
+ throw new Error(
79209
+ `Evaluator database resolves no unordered-list membership for container "${containerValueId}".`
79210
+ );
79211
+ }
79212
+ return resolved;
79213
+ },
79214
+ virtualInstanceRowsForValue: (receiverValueId) => databaseVM.virtualInstanceRowsForValue(receiverValueId),
79215
+ rowForValueReference: (value) => databaseVM.rowForValueReference?.(value) ?? null,
79216
+ resolveVariantInstanceGraph: (args) => {
79217
+ const resolver = databaseVM.resolveVariantInstanceGraph;
79218
+ if (resolver === void 0) {
79219
+ throw new Error(
79220
+ "Evaluator database has no virtual variant resolver."
79221
+ );
79222
+ }
79223
+ return resolver.call(databaseVM, args);
79224
+ },
79225
+ ...databaseVM.evaluatorIndexes === void 0 ? {} : { evaluatorIndexes: databaseVM.evaluatorIndexes },
79226
+ ...databaseVM.constructorInitializerIndexes === void 0 ? {} : {
79227
+ constructorInitializerIndexes: databaseVM.constructorInitializerIndexes
79228
+ }
79229
+ };
79230
+ evaluatorLookupsByDocument.set(lookupKey, {
79231
+ members: document.members,
79232
+ values: document.values,
79233
+ revision,
79234
+ lookups: lookups2
79235
+ });
79236
+ return lookups2;
79237
+ }
79238
+ const indexedLookups = indexedInitializerEvaluatorLookups(
79239
+ document,
79240
+ indexKey,
79241
+ revision
78898
79242
  );
78899
79243
  const headlessVirtualResolver = document.databaseVM === void 0 ? createHeadlessVirtualInstanceResolver({
78900
79244
  document,
78901
- resolverLookups: () => lookups
79245
+ resolverLookups: () => lookups,
79246
+ ...readTracking === void 0 ? {} : { readRecorder: virtualReadRecorder(readTracking) }
78902
79247
  }) : null;
78903
79248
  const lookups = {
78904
79249
  ...indexedLookups,
@@ -78916,11 +79261,13 @@ function initializerEvaluatorLookups(document) {
78916
79261
  resolveVariantInstanceGraph: (args) => resolveVariantInstanceGraphForDocument({
78917
79262
  document,
78918
79263
  resolverLookups: lookups,
79264
+ ...readTracking === void 0 ? {} : { readRecorder: virtualReadRecorder(readTracking) },
78919
79265
  ...args
78920
79266
  })
78921
79267
  } : {
78922
79268
  memberById: (id2) => document.databaseVM?.memberById(id2) ?? null,
78923
79269
  valueById: (id2) => document.databaseVM?.valueById(id2) ?? null,
79270
+ variantById: (id2) => document.databaseVM?.variantById?.(id2) ?? null,
78924
79271
  // The VM's `valueById` answers EXPANDED-first: a collapse-stamped
78925
79272
  // root resolves to a record the VM minted, an object the raw value
78926
79273
  // index has never seen. Reference-identity dispatch (`.Id`, `is`,
@@ -78954,7 +79301,26 @@ function initializerEvaluatorLookups(document) {
78954
79301
  }
78955
79302
  }
78956
79303
  };
78957
- evaluatorLookupsByDocument.set(key, {
79304
+ if (!trackedHeadless) {
79305
+ evaluatorLookupsByDocument.set(lookupKey, {
79306
+ members: document.members,
79307
+ values: document.values,
79308
+ revision,
79309
+ lookups
79310
+ });
79311
+ }
79312
+ return lookups;
79313
+ }
79314
+ function indexedInitializerEvaluatorLookups(document, key, revision) {
79315
+ const cached = indexedEvaluatorLookupsByDocument.get(key);
79316
+ if (cached !== void 0 && (revision === void 0 ? cached.members === document.members && cached.values === document.values : cached.revision === revision)) {
79317
+ return cached.lookups;
79318
+ }
79319
+ const lookups = makeEvaluatorLookups(document.members, document.values, {
79320
+ includeValueGraphIndexes: true,
79321
+ constructorInitializerDocument: document
79322
+ });
79323
+ indexedEvaluatorLookupsByDocument.set(key, {
78958
79324
  members: document.members,
78959
79325
  values: document.values,
78960
79326
  revision,
@@ -78962,22 +79328,61 @@ function initializerEvaluatorLookups(document) {
78962
79328
  });
78963
79329
  return lookups;
78964
79330
  }
78965
- function buildInitializerRootValueWithLookups(document, lookups) {
79331
+ function buildInitializerRootValueWithLookups(document, lookups, tracking) {
78966
79332
  const rootValue = {};
78967
79333
  for (const { root, memberId } of projectRootMembersInDisplayOrder(
78968
79334
  document.project
78969
79335
  )) {
78970
79336
  const member = lookups.memberById(memberId);
78971
- if (member === null || typeof member.valueId !== "string") {
79337
+ if (member === null) {
78972
79338
  rootValue[root.key] = null;
78973
79339
  continue;
78974
79340
  }
78975
- rootValue[root.key] = lookups.valueById(member.valueId)?.value ?? null;
79341
+ tracking?.staticMemberDependencies?.add(member.id);
79342
+ const bindings = root.storage === "save" /* Save */ ? tracking?.saveStaticBindings : root.storage === "session" /* Session */ ? tracking?.sessionStaticBindings : void 0;
79343
+ const boundTarget = staticBindingEntry(bindings, member.id);
79344
+ const targetId = boundTarget.present ? boundTarget.value : member.valueId;
79345
+ if (typeof targetId !== "string") {
79346
+ rootValue[root.key] = null;
79347
+ continue;
79348
+ }
79349
+ tracking?.valueDependencies?.add(targetId);
79350
+ rootValue[root.key] = lookups.valueById(targetId)?.value ?? null;
78976
79351
  }
78977
79352
  return rootValue;
78978
79353
  }
79354
+ function staticBindingEntry(bindings, memberId) {
79355
+ if (bindings === void 0) return { present: false, value: null };
79356
+ if (isStaticBindingMap(bindings)) {
79357
+ return {
79358
+ present: bindings.has(memberId),
79359
+ value: bindings.get(memberId) ?? null
79360
+ };
79361
+ }
79362
+ return {
79363
+ present: Object.hasOwn(bindings, memberId),
79364
+ value: bindings[memberId] ?? null
79365
+ };
79366
+ }
79367
+ function isStaticBindingMap(bindings) {
79368
+ return "get" in bindings && typeof bindings.get === "function" && "has" in bindings && typeof bindings.has === "function";
79369
+ }
79370
+ function virtualReadRecorder(reads) {
79371
+ return {
79372
+ recordValueRead: (id2) => reads.valueIds.add(id2),
79373
+ recordLocalizedTextRead: (id2) => reads.localizedTextIds.add(id2),
79374
+ recordVariantRead: (id2) => reads.variantIds.add(id2),
79375
+ recordStaticMemberRead: (id2) => reads.staticMemberIds.add(id2),
79376
+ recordContainerMembershipRead: (id2) => reads.containerIds.add(id2),
79377
+ recordValuePlacementRead: reads.recordValuePlacementRead,
79378
+ recordGlobalRead: reads.recordUnattributableValueRead
79379
+ };
79380
+ }
78979
79381
  function evaluateMemberInitializer(args) {
78980
- const databaseVM = initializerEvaluatorLookups(args.document);
79382
+ const databaseVM = initializerEvaluatorLookups(
79383
+ args.document,
79384
+ args.readTracking
79385
+ );
78981
79386
  const initializerIndexes = databaseVM.constructorInitializerIndexes;
78982
79387
  const compileMemberId = initializerIndexes?.initializerScopeMemberIds.get(args.init) ?? (args.sourceValueId === null || args.sourceValueId === void 0 ? void 0 : initializerIndexes?.initializerScopeMemberIdsByValueId.get(
78983
79388
  args.sourceValueId
@@ -79013,7 +79418,18 @@ function evaluateMemberInitializer(args) {
79013
79418
  initializerCompiler: args.document.initializerCompiler
79014
79419
  },
79015
79420
  thisValue: null,
79016
- rootValue: buildInitializerRootValueWithLookups(args.document, databaseVM),
79421
+ rootValue: buildInitializerRootValueWithLookups(args.document, databaseVM, {
79422
+ valueDependencies: args.readTracking?.valueIds,
79423
+ staticMemberDependencies: args.readTracking?.staticMemberIds,
79424
+ saveStaticBindings: args.saveStaticBindings,
79425
+ sessionStaticBindings: args.sessionStaticBindings
79426
+ }),
79427
+ valueDependencies: args.readTracking?.valueIds,
79428
+ localizedTextDependencies: args.readTracking?.localizedTextIds,
79429
+ variantDependencies: args.readTracking?.variantIds,
79430
+ containerDependencies: args.readTracking?.containerIds,
79431
+ staticMemberDependencies: args.readTracking?.staticMemberIds,
79432
+ onUnattributableValueRead: args.readTracking?.recordUnattributableValueRead,
79017
79433
  saveStaticBindings: args.saveStaticBindings,
79018
79434
  sessionStaticBindings: args.sessionStaticBindings,
79019
79435
  ...args.storedConstructionReplay === true ? {
@@ -79076,7 +79492,7 @@ function evaluateMemberInitializer(args) {
79076
79492
  }
79077
79493
  };
79078
79494
  }
79079
- var evaluatorLookupsByDocument;
79495
+ var evaluatorLookupsByDocument, indexedEvaluatorLookupsByDocument, InitializerReadSet;
79080
79496
  var init_evaluateInitializer = __esm({
79081
79497
  "../src/view-models/neoscript-evaluator/evaluateInitializer.ts"() {
79082
79498
  "use strict";
@@ -79087,6 +79503,23 @@ var init_evaluateInitializer = __esm({
79087
79503
  init_evaluateNSGetter();
79088
79504
  init_virtual_instance_values();
79089
79505
  evaluatorLookupsByDocument = /* @__PURE__ */ new WeakMap();
79506
+ indexedEvaluatorLookupsByDocument = /* @__PURE__ */ new WeakMap();
79507
+ InitializerReadSet = class {
79508
+ valueIds = /* @__PURE__ */ new Set();
79509
+ localizedTextIds = /* @__PURE__ */ new Set();
79510
+ variantIds = /* @__PURE__ */ new Set();
79511
+ containerIds = /* @__PURE__ */ new Set();
79512
+ staticMemberIds = /* @__PURE__ */ new Set();
79513
+ hasValuePlacementRead = false;
79514
+ hasUnattributableValueRead = false;
79515
+ recordUnattributableValueRead = (_reason) => {
79516
+ void _reason;
79517
+ this.hasUnattributableValueRead = true;
79518
+ };
79519
+ recordValuePlacementRead = () => {
79520
+ this.hasValuePlacementRead = true;
79521
+ };
79522
+ };
79090
79523
  }
79091
79524
  });
79092
79525
 
@@ -79102,8 +79535,12 @@ var init_neoscript_evaluator = __esm({
79102
79535
 
79103
79536
  // ../src/database/init-backed-value-materialization.ts
79104
79537
  function declarationInitializerContext(document) {
79105
- const cached = declarationInitializerContextByDocument.get(document);
79106
- if (cached !== void 0) return cached;
79538
+ const key = initializerEvaluatorCacheKey(document);
79539
+ const revision = initializerEvaluatorCacheRevision(document);
79540
+ const cached = declarationInitializerContextByDocument.get(key);
79541
+ if (cached !== void 0 && (revision === void 0 ? cached.members === document.members && cached.values === document.values : cached.revision === revision)) {
79542
+ return cached.context;
79543
+ }
79107
79544
  const initializerValueIds = new Set(
79108
79545
  document.values.filter(isInitValueContent).map((value) => value.id)
79109
79546
  );
@@ -79118,7 +79555,12 @@ function declarationInitializerContext(document) {
79118
79555
  rootOwners
79119
79556
  );
79120
79557
  const created = { valuesById, rootOwners };
79121
- declarationInitializerContextByDocument.set(document, created);
79558
+ declarationInitializerContextByDocument.set(key, {
79559
+ members: document.members,
79560
+ values: document.values,
79561
+ revision,
79562
+ context: created
79563
+ });
79122
79564
  return created;
79123
79565
  }
79124
79566
  function evaluateInitializerMaterialization(args) {
@@ -79133,7 +79575,10 @@ function evaluateInitializerMaterialization(args) {
79133
79575
  ...args.storedConstructionReplay === true ? { storedConstructionReplay: true } : {},
79134
79576
  ...args.constructionBaselineReplay === true ? { constructionBaselineReplay: true } : {},
79135
79577
  ...args.argumentValues === void 0 ? {} : { argumentValues: args.argumentValues },
79136
- sourceValueId: args.sourceValueId ?? null
79578
+ sourceValueId: args.sourceValueId ?? null,
79579
+ readTracking: args.readTracking,
79580
+ saveStaticBindings: args.saveStaticBindings,
79581
+ sessionStaticBindings: args.sessionStaticBindings
79137
79582
  });
79138
79583
  return { evaluated, createdValues, storageKeyDeclarations };
79139
79584
  }
@@ -79169,7 +79614,10 @@ function materializeInitializerValue(args) {
79169
79614
  ...args.storedConstructionReplay === true ? { storedConstructionReplay: true } : {},
79170
79615
  ...args.constructionBaselineReplay === true ? { constructionBaselineReplay: true } : {},
79171
79616
  ...args.argumentValues === void 0 ? {} : { argumentValues: args.argumentValues },
79172
- sourceValueId: args.row.id
79617
+ sourceValueId: args.row.id,
79618
+ readTracking: args.readTracking,
79619
+ saveStaticBindings: args.saveStaticBindings,
79620
+ sessionStaticBindings: args.sessionStaticBindings
79173
79621
  });
79174
79622
  const {
79175
79623
  init: _init,
@@ -79177,6 +79625,9 @@ function materializeInitializerValue(args) {
79177
79625
  classId: _classId,
79178
79626
  ...envelope
79179
79627
  } = args.row;
79628
+ void _init;
79629
+ void _value;
79630
+ void _classId;
79180
79631
  const root = {
79181
79632
  ...envelope,
79182
79633
  value: evaluated.value,
@@ -79212,6 +79663,9 @@ function materializeInitializerValue(args) {
79212
79663
  function materializeMemberDefaultValue(args) {
79213
79664
  const createdValues = [];
79214
79665
  const storageKeyDeclarations = /* @__PURE__ */ new Map();
79666
+ args.readTracking?.recordUnattributableValueRead(
79667
+ `declaration-owner-resolution:${args.envelope.id}`
79668
+ );
79215
79669
  const { valuesById, rootOwners } = declarationInitializerContext(
79216
79670
  args.document
79217
79671
  );
@@ -79232,15 +79686,14 @@ function materializeMemberDefaultValue(args) {
79232
79686
  (candidate) => candidate.id === constructorId
79233
79687
  );
79234
79688
  if (constructor2 === void 0) return [];
79235
- const defaults = parameterDefaultsAsFullArguments(
79236
- constructor2.argumentTypes,
79237
- `Declaration template on '${ownerClass.name}'`
79238
- );
79239
- if (defaults !== null) return defaults;
79240
79689
  const parameterNames = new Set(
79241
79690
  constructor2.argumentTypes.map((argument2) => argument2.name)
79242
79691
  );
79243
- return initializerReferencesAnyIdentifier(init.code, parameterNames) ? [] : constructor2.argumentTypes.map(() => null);
79692
+ return declarationInitializerArgumentValues(
79693
+ constructor2.argumentTypes,
79694
+ `Declaration template on '${ownerClass.name}'`,
79695
+ initializerReferencesAnyIdentifier(init.code, parameterNames)
79696
+ );
79244
79697
  };
79245
79698
  const built = buildDefaultMemberValue({
79246
79699
  document: args.document,
@@ -79262,7 +79715,10 @@ function materializeMemberDefaultValue(args) {
79262
79715
  init,
79263
79716
  sourceValueId ?? null
79264
79717
  ),
79265
- sourceValueId: sourceValueId ?? null
79718
+ sourceValueId: sourceValueId ?? null,
79719
+ readTracking: args.readTracking,
79720
+ saveStaticBindings: args.saveStaticBindings,
79721
+ sessionStaticBindings: args.sessionStaticBindings
79266
79722
  })
79267
79723
  });
79268
79724
  const interior = createdValues.filter((created) => created.id !== built.id);
@@ -79292,6 +79748,7 @@ var init_init_backed_value_materialization = __esm({
79292
79748
  init_inheritance();
79293
79749
  init_neoscript_evaluator();
79294
79750
  init_evaluateNSGetter();
79751
+ init_evaluateInitializer();
79295
79752
  init_value_row_owner_members();
79296
79753
  init_compile_ns_property();
79297
79754
  declarationInitializerContextByDocument = /* @__PURE__ */ new WeakMap();
@@ -87811,7 +88268,11 @@ function validateWorldLayerLinkClassTargets(args) {
87811
88268
  }
87812
88269
  }
87813
88270
  function worldLayerLinkTargetDescriptorForClass(classId, classes) {
87814
- const worldKind = resolveWorldSystemClassKind(classId, classes);
88271
+ return worldLayerLinkTargetDescriptor(
88272
+ resolveWorldSystemClassKind(classId, classes)
88273
+ );
88274
+ }
88275
+ function worldLayerLinkTargetDescriptor(worldKind) {
87815
88276
  if (worldKind === NeoWorldSystemClassKind.TileLayerLink) {
87816
88277
  return {
87817
88278
  relationKind: InternalRecordRelationKind.WorldTileLayerLinkTarget,
@@ -87833,9 +88294,11 @@ function worldLayerLinkTargetRelations(classId, descriptor, relations) {
87833
88294
  }
87834
88295
  function resolveWorldLayerLinkTarget(args) {
87835
88296
  const label = args.linkLabel ?? `Layer-link class "${args.sourceClassId}"`;
87836
- const sourceClass = args.classes.find(
87837
- (candidate) => candidate.id === args.sourceClassId
87838
- );
88297
+ const relationResolver = args.relationResolver ?? createEffectiveClassRelationResolver({
88298
+ classes: args.classes,
88299
+ relations: args.relations
88300
+ });
88301
+ const sourceClass = relationResolver.classesById.get(args.sourceClassId);
87839
88302
  if (sourceClass === void 0) {
87840
88303
  throw new Error(
87841
88304
  `${label} references missing class "${args.sourceClassId}".`
@@ -87846,21 +88309,18 @@ function resolveWorldLayerLinkTarget(args) {
87846
88309
  `${label} cannot instantiate abstract class "${args.sourceClassId}".`
87847
88310
  );
87848
88311
  }
87849
- const descriptor = worldLayerLinkTargetDescriptorForClass(
87850
- args.sourceClassId,
87851
- args.classes
88312
+ const descriptor = args.worldKindsByClassId === void 0 ? worldLayerLinkTargetDescriptorForClass(args.sourceClassId, args.classes) : worldLayerLinkTargetDescriptor(
88313
+ args.worldKindsByClassId.get(args.sourceClassId) ?? null
87852
88314
  );
87853
88315
  if (descriptor === null) {
87854
88316
  throw new Error(
87855
88317
  `${label} class "${args.sourceClassId}" is not a tile/object layer-link class.`
87856
88318
  );
87857
88319
  }
87858
- const effective = resolveEffectiveClassRelations({
87859
- relationKind: descriptor.relationKind,
87860
- sourceClassId: args.sourceClassId,
87861
- relations: args.relations,
87862
- classes: args.classes
87863
- });
88320
+ const effective = relationResolver.resolve(
88321
+ descriptor.relationKind,
88322
+ args.sourceClassId
88323
+ );
87864
88324
  if (effective.length > 1) {
87865
88325
  throw new Error(
87866
88326
  `${label} class "${args.sourceClassId}" resolves more than one effective target for relation kind "${descriptor.relationKind}".`
@@ -87868,8 +88328,8 @@ function resolveWorldLayerLinkTarget(args) {
87868
88328
  }
87869
88329
  const relationTarget = effective[0] ?? null;
87870
88330
  if (relationTarget !== null) {
87871
- const declarationClass = args.classes.find(
87872
- (candidate) => candidate.id === relationTarget.declaredSourceRecordId
88331
+ const declarationClass = relationResolver.classesById.get(
88332
+ relationTarget.declaredSourceRecordId
87873
88333
  );
87874
88334
  if (declarationClass?.system?.worldKind === NeoWorldSystemClassKind.TileLayerLink || declarationClass?.system?.worldKind === NeoWorldSystemClassKind.ObjectLayerLink) {
87875
88335
  throw new Error(
@@ -87883,9 +88343,7 @@ function resolveWorldLayerLinkTarget(args) {
87883
88343
  );
87884
88344
  }
87885
88345
  const targetClassId = relationTarget.targetRecordId;
87886
- const targetClass = args.classes.find(
87887
- (candidate) => candidate.id === targetClassId
87888
- );
88346
+ const targetClass = relationResolver.classesById.get(targetClassId);
87889
88347
  if (targetClass === void 0) {
87890
88348
  throw new Error(`${label} targets missing layer class "${targetClassId}".`);
87891
88349
  }
@@ -87894,10 +88352,7 @@ function resolveWorldLayerLinkTarget(args) {
87894
88352
  `${label} targets abstract layer class "${targetClassId}".`
87895
88353
  );
87896
88354
  }
87897
- const targetWorldKind = resolveWorldSystemClassKind(
87898
- targetClass.id,
87899
- args.classes
87900
- );
88355
+ const targetWorldKind = args.worldKindsByClassId?.get(targetClass.id) ?? resolveWorldSystemClassKind(targetClass.id, args.classes);
87901
88356
  if (targetWorldKind !== descriptor.targetWorldKind) {
87902
88357
  throw new Error(
87903
88358
  `${label} targets class "${targetClassId}" of world kind "${String(targetWorldKind)}"; expected "${descriptor.targetWorldKind}".`
@@ -98277,7 +98732,7 @@ function reconcileVariantConstructorArgs(args) {
98277
98732
  const valueById = indexRecordsById(postDocument.values);
98278
98733
  const classById = indexRecordsById(postDocument.classes);
98279
98734
  const memberById2 = indexRecordsById(postDocument.members);
98280
- const constructorById = indexRecordsById(postDocument.constructors ?? []);
98735
+ const constructorById2 = indexRecordsById(postDocument.constructors ?? []);
98281
98736
  let baseHashByValueId = null;
98282
98737
  for (const variant of variants) {
98283
98738
  const root = valueById.get(variant.valueId);
@@ -98290,7 +98745,7 @@ function reconcileVariantConstructorArgs(args) {
98290
98745
  if (schemaClass2 === void 0) continue;
98291
98746
  const constructorId = schemaClass2.requiredConstructorId;
98292
98747
  if (typeof constructorId !== "string") continue;
98293
- const constructorRecord = constructorById.get(constructorId);
98748
+ const constructorRecord = constructorById2.get(constructorId);
98294
98749
  if (constructorRecord === void 0) continue;
98295
98750
  if (typeof root.value !== "object" || root.value === null) continue;
98296
98751
  if (Array.isArray(root.value)) continue;
@@ -99463,7 +99918,7 @@ function animationFamilyClasses(document) {
99463
99918
  const classes = new Map(document.classes.map((entry) => [entry.id, entry]));
99464
99919
  const animationKinds = new Set(WORLD_SYSTEM_ANIMATION_KINDS);
99465
99920
  const result = /* @__PURE__ */ new Map();
99466
- const resolve4 = (classId, visiting) => {
99921
+ const resolve5 = (classId, visiting) => {
99467
99922
  const cached = result.get(classId);
99468
99923
  if (cached !== void 0) return cached;
99469
99924
  if (visiting.has(classId)) return false;
@@ -99475,11 +99930,11 @@ function animationFamilyClasses(document) {
99475
99930
  return true;
99476
99931
  }
99477
99932
  const nextVisiting = new Set(visiting).add(classId);
99478
- const belongs = typeof schemaClass2.extendsClassId === "string" && resolve4(schemaClass2.extendsClassId, nextVisiting);
99933
+ const belongs = typeof schemaClass2.extendsClassId === "string" && resolve5(schemaClass2.extendsClassId, nextVisiting);
99479
99934
  result.set(classId, belongs);
99480
99935
  return belongs;
99481
99936
  };
99482
- for (const classId of classes.keys()) resolve4(classId, /* @__PURE__ */ new Set());
99937
+ for (const classId of classes.keys()) resolve5(classId, /* @__PURE__ */ new Set());
99483
99938
  return new Set(
99484
99939
  [...result].flatMap(([classId, belongs]) => belongs ? [classId] : [])
99485
99940
  );
@@ -100331,6 +100786,28 @@ var init_value_base_desync = __esm({
100331
100786
  });
100332
100787
 
100333
100788
  // src/project-source/workspace-status-core.ts
100789
+ function recordUpsertChange(args) {
100790
+ if (args.base.conflictServerHash === null) {
100791
+ return {
100792
+ kind: "create",
100793
+ recordKind: args.recordKind,
100794
+ recordId: args.recordId,
100795
+ file: args.file,
100796
+ nextData: args.nextData
100797
+ };
100798
+ }
100799
+ const inConflictState = typeof args.base.conflictServerHash === "string";
100800
+ return {
100801
+ kind: "update",
100802
+ recordKind: args.recordKind,
100803
+ recordId: args.recordId,
100804
+ file: args.file,
100805
+ nextData: args.nextData,
100806
+ baseData: inConflictState ? args.base.conflictServerData : args.base.data,
100807
+ baseContentHash: args.base.contentHash,
100808
+ casBaseHash: inConflictState ? args.base.conflictServerHash : args.base.contentHash
100809
+ };
100810
+ }
100334
100811
  function listVirtualProjectSourceFilesV4(files) {
100335
100812
  const selected = files.filter((file) => {
100336
100813
  const kind = neoProjectSourceKind(file.path);
@@ -100814,16 +101291,15 @@ function computeWorkspaceStatus(workspace, options) {
100814
101291
  }
100815
101292
  const inConflictState = baseState.conflictServerHash !== void 0;
100816
101293
  if (!recordsSemanticallyEqual(record3.recordKind, fullData, baseState.data) || inConflictState) {
100817
- changes.push({
100818
- kind: "update",
100819
- recordKind: record3.recordKind,
100820
- recordId: record3.recordId,
100821
- file: record3.file,
100822
- nextData: fullData,
100823
- baseData: inConflictState ? baseState.conflictServerData : baseState.data,
100824
- baseContentHash: baseState.contentHash,
100825
- casBaseHash: inConflictState ? baseState.conflictServerHash : baseState.contentHash
100826
- });
101294
+ changes.push(
101295
+ recordUpsertChange({
101296
+ base: baseState,
101297
+ recordKind: record3.recordKind,
101298
+ recordId: record3.recordId,
101299
+ file: record3.file,
101300
+ nextData: fullData
101301
+ })
101302
+ );
100827
101303
  }
100828
101304
  }
100829
101305
  const deletedValueIds = /* @__PURE__ */ new Set();
@@ -100835,6 +101311,7 @@ function computeWorkspaceStatus(workspace, options) {
100835
101311
  (error) => error.file === recordFile && isBlockingSchemaSourceError(error)
100836
101312
  ) || conflictedFiles.includes(recordFile);
100837
101313
  if (fileStillBroken) continue;
101314
+ if (recordState.conflictServerHash === null) continue;
100838
101315
  if (recordState.recordKind === "value") {
100839
101316
  deletedValueIds.add(recordState.recordId);
100840
101317
  }
@@ -100995,16 +101472,15 @@ function computeWorkspaceStatus(workspace, options) {
100995
101472
  )) {
100996
101473
  continue;
100997
101474
  }
100998
- changes.push({
100999
- kind: "update",
101000
- recordKind: "project-file",
101001
- recordId: fileId,
101002
- file: record3.file,
101003
- nextData: record3.fullData,
101004
- baseData: base.data,
101005
- baseContentHash: base.contentHash,
101006
- casBaseHash: base.contentHash
101007
- });
101475
+ changes.push(
101476
+ recordUpsertChange({
101477
+ base,
101478
+ recordKind: "project-file",
101479
+ recordId: fileId,
101480
+ file: record3.file,
101481
+ nextData: record3.fullData
101482
+ })
101483
+ );
101008
101484
  }
101009
101485
  let binaryFiles = [];
101010
101486
  let binaryChanges = [];
@@ -110306,8 +110782,157 @@ var init_value_sources = __esm({
110306
110782
  }
110307
110783
  });
110308
110784
 
110785
+ // src/project-source/workspace-source-path.ts
110786
+ import { existsSync as existsSync3, lstatSync, realpathSync } from "node:fs";
110787
+ import { dirname as dirname4, isAbsolute as isAbsolute2, relative, resolve as resolve2, sep } from "node:path";
110788
+ function normalizeWorkspaceSourcePath(path) {
110789
+ const normalized = path.replaceAll("\\", "/");
110790
+ if (normalized.length === 0) {
110791
+ throw new Error("Project source path is empty.");
110792
+ }
110793
+ if (normalized.includes("\0")) {
110794
+ throw new Error(
110795
+ `Project source path ${JSON.stringify(path)} contains a null byte.`
110796
+ );
110797
+ }
110798
+ if (isAbsolute2(normalized)) {
110799
+ throw new Error(`Project source path ${JSON.stringify(path)} is absolute.`);
110800
+ }
110801
+ if (/^[A-Za-z]:\//u.test(normalized)) {
110802
+ throw new Error(
110803
+ `Project source path ${JSON.stringify(path)} is a Windows absolute path.`
110804
+ );
110805
+ }
110806
+ const parts = normalized.split("/");
110807
+ for (const part of parts) {
110808
+ if (part === "") {
110809
+ throw new Error(
110810
+ `Project source path ${JSON.stringify(path)} contains an empty segment.`
110811
+ );
110812
+ }
110813
+ if (part === ".") {
110814
+ throw new Error(
110815
+ `Project source path ${JSON.stringify(path)} contains a current-directory segment.`
110816
+ );
110817
+ }
110818
+ if (part === "..") {
110819
+ throw new Error(
110820
+ `Project source path ${JSON.stringify(path)} contains a parent-directory segment.`
110821
+ );
110822
+ }
110823
+ }
110824
+ return normalized;
110825
+ }
110826
+ function createWorkspaceSourcePathResolver(root) {
110827
+ const rootAbsolute = resolve2(root);
110828
+ const rootReal = realpathSync(rootAbsolute);
110829
+ return (path) => {
110830
+ const normalized = normalizeWorkspaceSourcePath(path);
110831
+ const absolute = resolve2(rootAbsolute, normalized);
110832
+ if (!containsPath(rootAbsolute, absolute)) {
110833
+ throw new Error(
110834
+ `Project source path ${JSON.stringify(path)} escapes the workspace.`
110835
+ );
110836
+ }
110837
+ const target = lstatSync(absolute, { throwIfNoEntry: false });
110838
+ if (target?.isSymbolicLink()) {
110839
+ throw new Error(
110840
+ `Project source path ${JSON.stringify(path)} targets a symbolic link.`
110841
+ );
110842
+ }
110843
+ let existing = target === void 0 ? dirname4(absolute) : absolute;
110844
+ while (!existsSync3(existing)) existing = dirname4(existing);
110845
+ if (!containsPath(rootReal, realpathSync(existing))) {
110846
+ throw new Error(
110847
+ `Project source path ${JSON.stringify(path)} traverses outside the workspace.`
110848
+ );
110849
+ }
110850
+ return absolute;
110851
+ };
110852
+ }
110853
+ function containsPath(parent, candidate) {
110854
+ const fromParent = relative(parent, candidate);
110855
+ return fromParent === "" || !isAbsolute2(fromParent) && fromParent !== ".." && !fromParent.startsWith(`..${sep}`);
110856
+ }
110857
+ var init_workspace_source_path = __esm({
110858
+ "src/project-source/workspace-source-path.ts"() {
110859
+ "use strict";
110860
+ }
110861
+ });
110862
+
110309
110863
  // src/project-source/project-documents.ts
110310
- function emitProjectDocumentFilesV4(records2) {
110864
+ function projectRecordFilesV4(...collections) {
110865
+ const files = /* @__PURE__ */ new Map();
110866
+ for (const records2 of collections) {
110867
+ for (const record3 of records2) {
110868
+ if (record3.file === void 0 || record3.file === null) continue;
110869
+ files.set(`${record3.recordKind}:${record3.recordId}`, record3.file);
110870
+ }
110871
+ }
110872
+ return files;
110873
+ }
110874
+ function authoredDefinitionPathV4(file, recordFiles) {
110875
+ let path = null;
110876
+ for (const key of file.recordKeys) {
110877
+ const candidate = recordFiles.get(key);
110878
+ if (candidate === void 0) continue;
110879
+ const normalizedCandidate = normalizeWorkspaceSourcePath(candidate);
110880
+ if (neoProjectSourceKind(normalizedCandidate) !== "definition") continue;
110881
+ if (path !== null && path !== normalizedCandidate) return null;
110882
+ path = normalizedCandidate;
110883
+ }
110884
+ return path;
110885
+ }
110886
+ function retainAuthoredDefinitionGroupingV4(files, recordFiles) {
110887
+ const grouped = /* @__PURE__ */ new Map();
110888
+ const paths = /* @__PURE__ */ new Map();
110889
+ for (const file of files) {
110890
+ const authoredPath = authoredDefinitionPathV4(file, recordFiles);
110891
+ const path = authoredPath ?? file.path;
110892
+ const folded = invariantCaseKey(path);
110893
+ const prior = grouped.get(folded);
110894
+ paths.set(file.path, path);
110895
+ if (prior === void 0) {
110896
+ grouped.set(folded, {
110897
+ path,
110898
+ content: [file.content],
110899
+ recordKeys: file.recordKeys.slice(),
110900
+ authored: authoredPath !== null
110901
+ });
110902
+ continue;
110903
+ }
110904
+ if (prior.path !== path) {
110905
+ if (prior.authored && authoredPath !== null) {
110906
+ throw new Error(
110907
+ `Authored record placements have a case-insensitive project source path collision between ${JSON.stringify(prior.path)} and ${JSON.stringify(path)}.`
110908
+ );
110909
+ }
110910
+ if (authoredPath !== null) prior.path = path;
110911
+ else if (!prior.authored) {
110912
+ throw new Error(
110913
+ `Canonical emission has a case-insensitive project source path collision between ${JSON.stringify(prior.path)} and ${JSON.stringify(path)}.`
110914
+ );
110915
+ }
110916
+ }
110917
+ prior.content.push(file.content);
110918
+ for (const key of file.recordKeys) prior.recordKeys.push(key);
110919
+ prior.authored ||= authoredPath !== null;
110920
+ paths.set(file.path, prior.path);
110921
+ }
110922
+ for (const [canonicalPath2, targetPath] of paths) {
110923
+ const finalPath = grouped.get(invariantCaseKey(targetPath))?.path;
110924
+ if (finalPath !== void 0) paths.set(canonicalPath2, finalPath);
110925
+ }
110926
+ return {
110927
+ files: grouped.values().map((file) => ({
110928
+ path: file.path,
110929
+ content: file.content.join("\n"),
110930
+ recordKeys: file.recordKeys
110931
+ })).toArray().sort((left, right) => compareCodePoints(left.path, right.path)),
110932
+ paths
110933
+ };
110934
+ }
110935
+ function emitProjectDocumentFilesV4(records2, options = {}) {
110311
110936
  const schemaRecords = [];
110312
110937
  for (const record3 of records2.values()) {
110313
110938
  if (record3.deleted || !isSchemaRecordKindV4(record3.recordKind)) continue;
@@ -110337,69 +110962,79 @@ function emitProjectDocumentFilesV4(records2) {
110337
110962
  collectionValuePaths: rootValuePathsByValueId(records2.values()),
110338
110963
  variantInitializers: variantValues.initializers
110339
110964
  });
110965
+ const sourceFiles = baseSource.files.map((file) => {
110966
+ const ownedKeys = [];
110967
+ for (const key of file.recordKeys) {
110968
+ if (key.startsWith("variant:")) {
110969
+ for (const ownedKey of variantValues.recordKeysByVariant.get(
110970
+ key.slice(8)
110971
+ ) ?? []) {
110972
+ ownedKeys.push(ownedKey);
110973
+ }
110974
+ continue;
110975
+ }
110976
+ if (!key.startsWith("member:")) continue;
110977
+ const memberId = key.slice(7);
110978
+ for (const ownedKey of staticValues.recordKeysByMember.get(memberId) ?? []) {
110979
+ ownedKeys.push(ownedKey);
110980
+ }
110981
+ for (const ownedKey of memberDefaults.recordKeysByMember.get(memberId) ?? []) {
110982
+ ownedKeys.push(ownedKey);
110983
+ }
110984
+ }
110985
+ return ownedKeys.length === 0 ? file : { ...file, recordKeys: file.recordKeys.concat(ownedKeys) };
110986
+ });
110340
110987
  const source = {
110341
110988
  ...baseSource,
110342
- files: baseSource.files.map((file) => {
110343
- const ownedKeys = file.recordKeys.flatMap((key) => {
110344
- if (key.startsWith("variant:")) {
110345
- return [
110346
- ...variantValues.recordKeysByVariant.get(key.slice(8)) ?? []
110347
- ];
110348
- }
110349
- if (!key.startsWith("member:")) return [];
110350
- const memberId = key.slice(7);
110351
- return [
110352
- ...staticValues.recordKeysByMember.get(memberId) ?? [],
110353
- ...memberDefaults.recordKeysByMember.get(memberId) ?? []
110354
- ];
110355
- });
110356
- return ownedKeys.length === 0 ? file : { ...file, recordKeys: [...file.recordKeys, ...ownedKeys] };
110357
- })
110989
+ files: sourceFiles
110358
110990
  };
110359
110991
  const classNames = new IdentifierTable();
110360
110992
  for (const schemaClass2 of manifest.classes) {
110361
110993
  classNames.assign(schemaClass2.id, schemaClass2.name);
110362
110994
  }
110363
- const migrationFiles = [...records2.values()].filter((record3) => !record3.deleted && record3.recordKind === "migration").map((record3) => {
110995
+ const migrationFiles = records2.values().filter((record3) => !record3.deleted && record3.recordKind === "migration").map((record3) => {
110364
110996
  const emitted = emitMigrationFile(record3, classNames);
110365
110997
  return {
110366
110998
  path: emitted.path,
110367
110999
  content: emitted.content,
110368
111000
  recordKeys: emitted.recordKeys
110369
111001
  };
110370
- });
111002
+ }).toArray();
110371
111003
  const supplementalFiles = emitSupplementalProjectSourcesV4(records2);
110372
- const materializedConstructors = new Map([
110373
- ...staticValues.materializedConstructors,
110374
- ...memberDefaults.materializedConstructors
110375
- ]);
110376
- const materializedConstructorOverrideKeys = new Map([
110377
- ...staticValues.materializedConstructorOverrideKeys,
110378
- ...memberDefaults.materializedConstructorOverrideKeys
110379
- ]);
111004
+ const materializedConstructors = new Map(
111005
+ staticValues.materializedConstructors
111006
+ );
111007
+ for (const [key, value] of memberDefaults.materializedConstructors) {
111008
+ materializedConstructors.set(key, value);
111009
+ }
111010
+ const materializedConstructorOverrideKeys = new Map(
111011
+ staticValues.materializedConstructorOverrideKeys
111012
+ );
111013
+ for (const [
111014
+ key,
111015
+ value
111016
+ ] of memberDefaults.materializedConstructorOverrideKeys) {
111017
+ materializedConstructorOverrideKeys.set(key, value);
111018
+ }
110380
111019
  const rootFile = emitProjectRootSourceV4(
110381
111020
  records2,
110382
111021
  manifest,
110383
111022
  materializedConstructors
110384
111023
  );
110385
111024
  const dialogueFiles = emitDialogueProjectSourcesV4(records2);
110386
- const files = [
110387
- ...source.files,
110388
- ...rootFile ? [rootFile] : [],
110389
- ...supplementalFiles,
110390
- ...dialogueFiles,
110391
- ...migrationFiles
110392
- ].sort((left, right) => compareCodePoints(left.path, right.path));
110393
- const recordFiles = new Map(source.recordFiles);
110394
- for (const file of source.files) {
110395
- for (const key of file.recordKeys) recordFiles.set(key, file.path);
110396
- }
110397
- for (const file of [
110398
- ...rootFile ? [rootFile] : [],
110399
- ...supplementalFiles,
110400
- ...dialogueFiles,
110401
- ...migrationFiles
110402
- ]) {
111025
+ const grouped = retainAuthoredDefinitionGroupingV4(
111026
+ [
111027
+ source.files,
111028
+ rootFile === null ? [] : [rootFile],
111029
+ supplementalFiles,
111030
+ dialogueFiles,
111031
+ migrationFiles
111032
+ ].values().flatMap((files2) => files2.values()),
111033
+ options.recordFiles ?? /* @__PURE__ */ new Map()
111034
+ );
111035
+ const files = grouped.files;
111036
+ const recordFiles = /* @__PURE__ */ new Map();
111037
+ for (const file of files) {
110403
111038
  for (const key of file.recordKeys) recordFiles.set(key, file.path);
110404
111039
  }
110405
111040
  for (const recovery of staticMemberOwnershipRecoveries) {
@@ -110437,7 +111072,10 @@ ${errors.map(
110437
111072
  analysis,
110438
111073
  materializedConstructors,
110439
111074
  materializedConstructorOverrideKeys,
110440
- formAlternates: source.formAlternates,
111075
+ formAlternates: source.formAlternates.map((alternate) => ({
111076
+ ...alternate,
111077
+ path: grouped.paths.get(alternate.path) ?? alternate.path
111078
+ })),
110441
111079
  staticMemberOwnershipRecoveries
110442
111080
  };
110443
111081
  }
@@ -110492,6 +111130,7 @@ var init_project_documents = __esm({
110492
111130
  init_source_diagnostics();
110493
111131
  init_source_format();
110494
111132
  init_static_member_ownership_recovery();
111133
+ init_workspace_source_path();
110495
111134
  PROJECT_SOURCE_ANALYSIS_V4_CACHE_PATH = ".neo/project-source-analysis-v4.json";
110496
111135
  SCHEMA_RECORD_KINDS2 = /* @__PURE__ */ new Set([
110497
111136
  "class",
@@ -110513,7 +111152,7 @@ var init_project_documents = __esm({
110513
111152
  // src/project-source/project-document-cache.ts
110514
111153
  import { mkdirSync as mkdirSync5, readFileSync as readFileSync5, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "node:fs";
110515
111154
  import { createHash as createHash6 } from "node:crypto";
110516
- import { dirname as dirname4, join as join5 } from "node:path";
111155
+ import { dirname as dirname5, join as join5 } from "node:path";
110517
111156
  function readProjectSourceAnalysisBuildCacheV4(root, sources) {
110518
111157
  try {
110519
111158
  const parsed = JSON.parse(
@@ -110532,12 +111171,12 @@ function readProjectSourceAnalysisBuildCacheV4(root, sources) {
110532
111171
  }
110533
111172
  function writeProjectSourceAnalysisCacheV4(root, analysis, sources) {
110534
111173
  const file = join5(root, PROJECT_SOURCE_ANALYSIS_V4_CACHE_PATH);
110535
- mkdirSync5(dirname4(file), { recursive: true });
111174
+ mkdirSync5(dirname5(file), { recursive: true });
110536
111175
  writeFileSync5(file, `${JSON.stringify(analysis, null, 2)}
110537
111176
  `, "utf8");
110538
111177
  if (sources === void 0) return;
110539
111178
  const buildFile = join5(root, PROJECT_SOURCE_BUILD_CACHE_PATH);
110540
- mkdirSync5(dirname4(buildFile), { recursive: true });
111179
+ mkdirSync5(dirname5(buildFile), { recursive: true });
110541
111180
  const temporary = `${buildFile}.${process.pid}.tmp`;
110542
111181
  writeFileSync5(
110543
111182
  temporary,
@@ -110608,7 +111247,7 @@ function readProjectSourceDocumentBuildCacheV1(root, sources) {
110608
111247
  }
110609
111248
  function writeProjectSourceDocumentBuildCacheV1(root, sources, documents) {
110610
111249
  const file = join5(root, PROJECT_SOURCE_DOCUMENT_BUILD_CACHE_PATH);
110611
- mkdirSync5(dirname4(file), { recursive: true });
111250
+ mkdirSync5(dirname5(file), { recursive: true });
110612
111251
  const temporary = `${file}.${process.pid}.tmp`;
110613
111252
  writeFileSync5(
110614
111253
  temporary,
@@ -110674,7 +111313,7 @@ var init_project_document_cache = __esm({
110674
111313
  // src/project-source/project-files.ts
110675
111314
  import { createHash as createHash7 } from "node:crypto";
110676
111315
  import {
110677
- existsSync as existsSync3,
111316
+ existsSync as existsSync4,
110678
111317
  mkdirSync as mkdirSync6,
110679
111318
  readFileSync as readFileSync6,
110680
111319
  readdirSync,
@@ -110682,7 +111321,7 @@ import {
110682
111321
  rmSync as rmSync2,
110683
111322
  writeFileSync as writeFileSync6
110684
111323
  } from "node:fs";
110685
- import { basename, dirname as dirname5, extname, join as join6, relative, sep } from "node:path";
111324
+ import { basename, dirname as dirname6, extname, join as join6, relative as relative2, sep as sep2 } from "node:path";
110686
111325
  function lowerProjectFileRegistrySourcesV4(root, state, analysis, options = {}) {
110687
111326
  const templateIds = fileTemplateIdsByName2(analysis);
110688
111327
  const declarations = analysis.files.registries.flatMap(
@@ -110717,12 +111356,12 @@ function lowerProjectFileRegistrySourcesV4(root, state, analysis, options = {})
110717
111356
  const trustedPending = options.trustedPendingFiles?.get(
110718
111357
  declaration.recordId
110719
111358
  );
110720
- if (base === null && !existsSync3(absolute) && trustedPending === void 0) {
111359
+ if (base === null && !existsSync4(absolute) && trustedPending === void 0) {
110721
111360
  throw new Error(
110722
111361
  `Pending project file ${declaration.symbol} is missing bytes at ${normalizedPath}.`
110723
111362
  );
110724
111363
  }
110725
- const binary = existsSync3(absolute) ? inspectBinaryFile(absolute, normalizedPath) : trustedPending === void 0 ? null : {
111364
+ const binary = existsSync4(absolute) ? inspectBinaryFile(absolute, normalizedPath) : trustedPending === void 0 ? null : {
110726
111365
  path: normalizedPath,
110727
111366
  kind: declaration.kind,
110728
111367
  mimeType: trustedPending.mimeType,
@@ -110824,7 +111463,7 @@ function inspectProjectBinaryStatusV4(root, state, analysis) {
110824
111463
  const baseState = state[`project-file:${declaration.recordId}`];
110825
111464
  const data = isObjectRecord2(baseState?.data) ? baseState.data : {};
110826
111465
  const absolute = join6(root, declaration.path);
110827
- const local = existsSync3(absolute) ? inspectBinaryFile(absolute, declaration.path) : null;
111466
+ const local = existsSync4(absolute) ? inspectBinaryFile(absolute, declaration.path) : null;
110828
111467
  const baseSha256 = baseState?.projectBinary?.sha256 ?? normalizeSha256V4(
110829
111468
  data.contentSha256,
110830
111469
  `project-file:${declaration.recordId} metadata`
@@ -110896,9 +111535,9 @@ function discoverProjectBinariesV4(root, explicit, ignoredPaths = []) {
110896
111535
  const candidates = [];
110897
111536
  for (const directory of ["Files/Images", "Files/AudioClips"]) {
110898
111537
  const absoluteDirectory = join6(root, directory);
110899
- if (!existsSync3(absoluteDirectory)) continue;
111538
+ if (!existsSync4(absoluteDirectory)) continue;
110900
111539
  visitBinaryFiles(absoluteDirectory, (absolute) => {
110901
- const path = normalizeSlash2(relative(root, absolute));
111540
+ const path = normalizeSlash2(relative2(root, absolute));
110902
111541
  if (!explicitPaths.has(path.toLowerCase())) {
110903
111542
  candidates.push({ stableId: path, path, absolute });
110904
111543
  }
@@ -110946,7 +111585,7 @@ function writeVerifiedBinaryDownloadV4(destination, bytes, expectedSha256) {
110946
111585
  `Downloaded project file checksum ${actual} did not match expected SHA-256 ${expectedSha256}.`
110947
111586
  );
110948
111587
  }
110949
- mkdirSync6(dirname5(destination), { recursive: true });
111588
+ mkdirSync6(dirname6(destination), { recursive: true });
110950
111589
  const temporary = `${destination}.neo-download-${process.pid}`;
110951
111590
  try {
110952
111591
  writeFileSync6(temporary, bytes);
@@ -110965,7 +111604,7 @@ function writeBinaryConflictArtifactV4(root, fileId, fileName2, bytes, expectedS
110965
111604
  safeFileName2(fileName2)
110966
111605
  );
110967
111606
  writeVerifiedBinaryDownloadV4(destination, bytes, expectedSha256);
110968
- return normalizeSlash2(relative(root, destination));
111607
+ return normalizeSlash2(relative2(root, destination));
110969
111608
  }
110970
111609
  function fileTemplateIdsByName2(analysis) {
110971
111610
  const templateIds = /* @__PURE__ */ new Map();
@@ -111154,7 +111793,7 @@ function safePathSegment2(value) {
111154
111793
  return value.replace(/[^A-Za-z0-9._-]/g, "_") || "file";
111155
111794
  }
111156
111795
  function normalizeSlash2(value) {
111157
- return value.split(sep).join("/").replaceAll("\\", "/");
111796
+ return value.split(sep2).join("/").replaceAll("\\", "/");
111158
111797
  }
111159
111798
  var SUPPORTED_BINARY_TYPES, REGISTRY_ENTRY2, assignDeterministicFileSymbols2;
111160
111799
  var init_project_files = __esm({
@@ -111197,12 +111836,12 @@ var init_supplemental_records_file_system = __esm({
111197
111836
  });
111198
111837
 
111199
111838
  // src/project-source/workspace-status.ts
111200
- import { existsSync as existsSync4, readFileSync as readFileSync7, readdirSync as readdirSync2 } from "node:fs";
111201
- import { join as join7, relative as relative2, sep as sep2 } from "node:path";
111839
+ import { existsSync as existsSync5, readFileSync as readFileSync7, readdirSync as readdirSync2 } from "node:fs";
111840
+ import { join as join7, relative as relative3, sep as sep3 } from "node:path";
111202
111841
  function isGitIgnored(scopes, absolutePath, directory) {
111203
111842
  return isNeoGitIgnored(
111204
111843
  scopes.map((scope) => ({
111205
- relativePath: relative2(scope.root, absolutePath),
111844
+ relativePath: relative3(scope.root, absolutePath),
111206
111845
  matcher: scope.matcher
111207
111846
  })),
111208
111847
  directory
@@ -111210,7 +111849,7 @@ function isGitIgnored(scopes, absolutePath, directory) {
111210
111849
  }
111211
111850
  function addGitIgnoreScope(directory, inherited) {
111212
111851
  const path = join7(directory, ".gitignore");
111213
- if (!existsSync4(path)) return inherited;
111852
+ if (!existsSync5(path)) return inherited;
111214
111853
  return [
111215
111854
  ...inherited,
111216
111855
  { root: directory, matcher: (0, import_ignore.default)().add(readFileSync7(path, "utf8")) }
@@ -111220,7 +111859,7 @@ function listNeoWorkspaceFilesV1(root) {
111220
111859
  const production = [];
111221
111860
  const specs = [];
111222
111861
  const visit = (directory, inheritedScopes) => {
111223
- if (!existsSync4(directory)) return;
111862
+ if (!existsSync5(directory)) return;
111224
111863
  const scopes = addGitIgnoreScope(directory, inheritedScopes);
111225
111864
  for (const entry of readdirSync2(directory, { withFileTypes: true })) {
111226
111865
  if (entry.isSymbolicLink()) continue;
@@ -111232,7 +111871,7 @@ function listNeoWorkspaceFilesV1(root) {
111232
111871
  continue;
111233
111872
  }
111234
111873
  if (!entry.isFile() || isGitIgnored(scopes, path, false)) continue;
111235
- const relativePath = relative2(root, path).split(sep2).join("/");
111874
+ const relativePath = relative3(root, path).split(sep3).join("/");
111236
111875
  const kind = neoProjectSourceKind(relativePath);
111237
111876
  if (kind === null) continue;
111238
111877
  if (kind === "spec") specs.push(path);
@@ -111252,7 +111891,7 @@ function listProjectTestFilesV1(root) {
111252
111891
  }
111253
111892
  function computeWorkspaceStatus2(workspace, options = {}) {
111254
111893
  const virtualSourceFiles = options.virtualSourceFiles ?? listProjectSourceFilesV4(workspace.root).map((path) => ({
111255
- path: relative2(workspace.root, path).split(sep2).join("/"),
111894
+ path: relative3(workspace.root, path).split(sep3).join("/"),
111256
111895
  content: readFileSync7(path, "utf8")
111257
111896
  }));
111258
111897
  return computeWorkspaceStatus(workspace, {
@@ -112264,7 +112903,7 @@ var init_source_record_comparison = __esm({
112264
112903
 
112265
112904
  // src/project-source/reset.ts
112266
112905
  import {
112267
- existsSync as existsSync5,
112906
+ existsSync as existsSync6,
112268
112907
  mkdirSync as mkdirSync7,
112269
112908
  readFileSync as readFileSync8,
112270
112909
  readdirSync as readdirSync3,
@@ -112272,12 +112911,20 @@ import {
112272
112911
  writeFileSync as writeFileSync7,
112273
112912
  statSync
112274
112913
  } from "node:fs";
112275
- import { dirname as dirname6, join as join8 } from "node:path";
112914
+ import { dirname as dirname7, join as join8 } from "node:path";
112276
112915
  function resetWorkspaceToProjectSourcesV4(workspace, document, options = {}) {
112277
112916
  const emissionRecords = options.regenerateSourceNames ? regenerateDialogueSourceNamesV4(document.records) : document.records;
112278
- const emitted = emitProjectDocumentFilesV4(emissionRecords);
112917
+ const emitted = emitProjectDocumentFilesV4(emissionRecords, {
112918
+ recordFiles: projectRecordFilesV4(Object.values(workspace.state.records))
112919
+ });
112279
112920
  assertUniqueEmittedPaths2(emitted.files);
112280
- const previous = managedFilesBeforeReset(workspace.root);
112921
+ const resolveSourcePath = createWorkspaceSourcePathResolver(workspace.root);
112922
+ const trackedSources = trackedProductionSourcesBeforeReset(
112923
+ workspace,
112924
+ resolveSourcePath
112925
+ );
112926
+ const previous = new Set(managedFilesBeforeReset(workspace.root));
112927
+ for (const path of trackedSources) previous.add(path);
112281
112928
  const preservedSpecs = preserveManagedSpecs(workspace.root);
112282
112929
  for (const directory of FORMAT_4_MANAGED_DIRECTORIES) {
112283
112930
  rmSync3(join8(workspace.root, directory), { recursive: true, force: true });
@@ -112289,15 +112936,18 @@ function resetWorkspaceToProjectSourcesV4(workspace, document, options = {}) {
112289
112936
  for (const privatePath of LEGACY_PRIVATE_PATHS) {
112290
112937
  rmSync3(join8(workspace.root, privatePath), { recursive: true, force: true });
112291
112938
  }
112939
+ for (const path of trackedSources) {
112940
+ rmSync3(resolveSourcePath(path), { force: true });
112941
+ }
112292
112942
  for (const [path, bytes] of preservedSpecs) {
112293
112943
  const absolute = join8(workspace.root, path);
112294
- mkdirSync7(dirname6(absolute), { recursive: true });
112944
+ mkdirSync7(dirname7(absolute), { recursive: true });
112295
112945
  writeFileSync7(absolute, bytes);
112296
112946
  }
112297
112947
  for (const file of emitted.files) {
112298
- const absolute = join8(workspace.root, file.path);
112299
- mkdirSync7(dirname6(absolute), { recursive: true });
112300
- if (existsSync5(absolute) && readFileSync8(absolute, "utf8") === file.content) {
112948
+ const absolute = resolveSourcePath(file.path);
112949
+ mkdirSync7(dirname7(absolute), { recursive: true });
112950
+ if (existsSync6(absolute) && readFileSync8(absolute, "utf8") === file.content) {
112301
112951
  continue;
112302
112952
  }
112303
112953
  writeFileSync7(absolute, file.content, "utf8");
@@ -112324,7 +112974,7 @@ function resetWorkspaceToProjectSourcesV4(workspace, document, options = {}) {
112324
112974
  workspace.config = { ...workspace.config, formatVersion: 4 };
112325
112975
  writeWorkspaceConfig(workspace.root, workspace.config);
112326
112976
  const removed = [...previous].filter(
112327
- (file) => !existsSync5(join8(workspace.root, file))
112977
+ (file) => !existsSync6(join8(workspace.root, file))
112328
112978
  ).length;
112329
112979
  return {
112330
112980
  written: emitted.files.length,
@@ -112337,7 +112987,7 @@ function preserveManagedSpecs(root) {
112337
112987
  const specs = /* @__PURE__ */ new Map();
112338
112988
  const visit = (path) => {
112339
112989
  const absolute = join8(root, path);
112340
- if (!existsSync5(absolute)) return;
112990
+ if (!existsSync6(absolute)) return;
112341
112991
  const entries = readdirSync3(absolute, { withFileTypes: true });
112342
112992
  for (const entry of entries) {
112343
112993
  if (entry.isSymbolicLink()) continue;
@@ -112352,6 +113002,20 @@ function preserveManagedSpecs(root) {
112352
113002
  for (const directory of FORMAT_4_MANAGED_DIRECTORIES) visit(directory);
112353
113003
  return specs;
112354
113004
  }
113005
+ function trackedProductionSourcesBeforeReset(workspace, resolveSourcePath) {
113006
+ const paths = /* @__PURE__ */ new Set();
113007
+ for (const record3 of Object.values(workspace.state.records)) {
113008
+ if (record3.file === void 0) continue;
113009
+ const path = normalizeWorkspaceSourcePath(record3.file);
113010
+ const kind = neoProjectSourceKind(path);
113011
+ if (kind === null || !isNeoProjectProductionSourceKind(kind)) {
113012
+ continue;
113013
+ }
113014
+ const absolute = resolveSourcePath(path);
113015
+ if (existsSync6(absolute)) paths.add(path);
113016
+ }
113017
+ return paths;
113018
+ }
112355
113019
  function assertUniqueEmittedPaths2(files) {
112356
113020
  const seen = /* @__PURE__ */ new Map();
112357
113021
  for (const file of files) {
@@ -112371,7 +113035,7 @@ function managedFilesBeforeReset(root) {
112371
113035
  collectFiles(root, directory, files);
112372
113036
  }
112373
113037
  for (const file of LEGACY_ROOT_FILES) {
112374
- if (existsSync5(join8(root, file))) files.add(file);
113038
+ if (existsSync6(join8(root, file))) files.add(file);
112375
113039
  }
112376
113040
  for (const privatePath of LEGACY_PRIVATE_PATHS) {
112377
113041
  collectFiles(root, privatePath, files);
@@ -112380,7 +113044,7 @@ function managedFilesBeforeReset(root) {
112380
113044
  }
112381
113045
  function collectFiles(root, path, files) {
112382
113046
  const absolute = join8(root, path);
112383
- if (!existsSync5(absolute)) return;
113047
+ if (!existsSync6(absolute)) return;
112384
113048
  if (statSync(absolute).isFile()) {
112385
113049
  files.add(path);
112386
113050
  return;
@@ -112399,11 +113063,13 @@ var FORMAT_4_MANAGED_DIRECTORIES, LEGACY_ROOT_FILES, LEGACY_PRIVATE_PATHS;
112399
113063
  var init_reset = __esm({
112400
113064
  "src/project-source/reset.ts"() {
112401
113065
  "use strict";
113066
+ init_src();
112402
113067
  init_workspace();
112403
113068
  init_project_documents();
112404
113069
  init_project_document_cache();
112405
113070
  init_materialized_construction_cache();
112406
113071
  init_dialogue_sources();
113072
+ init_workspace_source_path();
112407
113073
  FORMAT_4_MANAGED_DIRECTORIES = [
112408
113074
  "Classes",
112409
113075
  "Interfaces",
@@ -112544,7 +113210,7 @@ var init_http = __esm({
112544
113210
  });
112545
113211
 
112546
113212
  // src/project-source/project-file-pull.ts
112547
- import { existsSync as existsSync6, rmSync as rmSync4 } from "node:fs";
113213
+ import { existsSync as existsSync7, rmSync as rmSync4 } from "node:fs";
112548
113214
  import { join as join9 } from "node:path";
112549
113215
  async function pullProjectBinariesV4(args) {
112550
113216
  let client = args.client ?? null;
@@ -112568,7 +113234,7 @@ async function pullProjectBinariesV4(args) {
112568
113234
  const declarationPresent = args.destructive === true || args.localBinaries === void 0 || previous === void 0 || localStatus !== void 0;
112569
113235
  const path = localStatus?.path ?? previous?.projectBinary?.path ?? canonicalProjectBinaryPathV42(record3.data);
112570
113236
  const absolute = join9(args.workspace.root, path);
112571
- const localDigest = existsSync6(absolute) ? sha256File(absolute) : null;
113237
+ const localDigest = existsSync7(absolute) ? sha256File(absolute) : null;
112572
113238
  const baseDigest = previous?.projectBinary?.sha256 ?? readSha256(previous?.data) ?? null;
112573
113239
  const remoteDigest = requiredSha256(
112574
113240
  record3.data,
@@ -112651,7 +113317,7 @@ async function pullProjectBinariesV4(args) {
112651
113317
  const localStatus = localById.get(previous.recordId);
112652
113318
  const path = localStatus?.path ?? previous.projectBinary?.path ?? canonicalProjectBinaryPathV42(previous.data);
112653
113319
  const absolute = join9(args.workspace.root, path);
112654
- const localDigest = existsSync6(absolute) ? sha256File(absolute) : null;
113320
+ const localDigest = existsSync7(absolute) ? sha256File(absolute) : null;
112655
113321
  const baseDigest = previous.projectBinary?.sha256 ?? readSha256(previous.data) ?? null;
112656
113322
  const action = planBinaryMergeV4({
112657
113323
  baseDigest,
@@ -112836,10 +113502,10 @@ import {
112836
113502
  mkdirSync as mkdirSync8,
112837
113503
  writeFileSync as writeFileSync8,
112838
113504
  rmSync as rmSync5,
112839
- existsSync as existsSync7,
113505
+ existsSync as existsSync8,
112840
113506
  readFileSync as readFileSync9
112841
113507
  } from "node:fs";
112842
- import { dirname as dirname7, join as join10 } from "node:path";
113508
+ import { dirname as dirname8 } from "node:path";
112843
113509
  async function runPull(workspace, options) {
112844
113510
  if (options.reset) {
112845
113511
  await runResetPull(workspace);
@@ -112942,7 +113608,8 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
112942
113608
  if (serverRecord.deleted) continue;
112943
113609
  const baseState = workspace.state.records[key];
112944
113610
  const local = localByKey.get(key);
112945
- if (destructive || baseState === void 0) {
113611
+ const acceptedServerDeletionRecreated = baseState?.conflictServerHash === null && local === void 0;
113612
+ if (destructive || baseState === void 0 || acceptedServerDeletionRecreated) {
112946
113613
  plans.set(key, {
112947
113614
  emitData: serverRecord.data,
112948
113615
  serverHash: serverRecord.contentHash,
@@ -113161,12 +113828,19 @@ async function finishFormat4Pull(args) {
113161
113828
  ([key, record3]) => localRecords.get(key) === record3 ? [] : [key]
113162
113829
  )
113163
113830
  );
113164
- const localResult = emitProjectDocumentFilesV4(localRecords);
113831
+ const recordFiles = projectRecordFilesV4(
113832
+ Object.values(workspace.state.records),
113833
+ localStatus?.reconstructed.values() ?? []
113834
+ );
113835
+ const localResult = emitProjectDocumentFilesV4(localRecords, {
113836
+ recordFiles
113837
+ });
113165
113838
  for (const recovery of localResult.staticMemberOwnershipRecoveries ?? []) {
113166
113839
  warn(staticMemberOwnershipRecoveryMessage(recovery));
113167
113840
  }
113168
113841
  const serverResult = conflictCount === 0 ? null : emitProjectDocumentFilesV4(
113169
- buildEmitRecordSet(document, plans, "server")
113842
+ buildEmitRecordSet(document, plans, "server"),
113843
+ { recordFiles }
113170
113844
  );
113171
113845
  const binaries = await pullProjectBinariesV4({
113172
113846
  workspace,
@@ -113182,13 +113856,23 @@ async function finishFormat4Pull(args) {
113182
113856
  (serverResult?.files ?? []).map((file) => [file.path, file])
113183
113857
  );
113184
113858
  const conflictPaths = /* @__PURE__ */ new Set();
113859
+ const authoredLocalConflictKeysByPath = /* @__PURE__ */ new Map();
113185
113860
  for (const key of conflictKeys) {
113186
- const path = localResult.recordFiles.get(key) ?? serverResult?.recordFiles.get(key);
113861
+ const localPath = localResult.recordFiles.get(key);
113862
+ const serverPath = serverResult?.recordFiles.get(key);
113863
+ const path = localPath ?? serverPath ?? workspace.state.records[key]?.file;
113187
113864
  if (path) conflictPaths.add(path);
113865
+ if (path === void 0 || localPath !== void 0 || serverPath !== void 0) {
113866
+ continue;
113867
+ }
113868
+ const keys = authoredLocalConflictKeysByPath.get(path) ?? [];
113869
+ keys.push(key);
113870
+ authoredLocalConflictKeysByPath.set(path, keys);
113188
113871
  }
113189
113872
  const emittedPaths = /* @__PURE__ */ new Set([
113190
113873
  ...localByPath.keys(),
113191
- ...[...conflictPaths].filter((path) => serverByPath.has(path))
113874
+ ...[...conflictPaths].filter((path) => serverByPath.has(path)),
113875
+ ...authoredLocalConflictKeysByPath.keys()
113192
113876
  ]);
113193
113877
  const rewritePaths = projectSourcePathsRequiringRewriteV4({
113194
113878
  destructive,
@@ -113205,9 +113889,20 @@ async function finishFormat4Pull(args) {
113205
113889
  const path = localResult.recordFiles.get(key);
113206
113890
  if (path !== void 0) rewritePaths.add(path);
113207
113891
  }
113892
+ const resolveSourcePath = createWorkspaceSourcePathResolver(workspace.root);
113208
113893
  let written = 0;
113209
113894
  for (const path of emittedPaths) {
113210
- const local = localByPath.get(path)?.content;
113895
+ const absolute = resolveSourcePath(path);
113896
+ const existing = existsSync8(absolute) ? readFileSync9(absolute, "utf8") : null;
113897
+ const unprojectedConflictKeys = authoredLocalConflictKeysByPath.get(path) ?? [];
113898
+ if (unprojectedConflictKeys.length > 0 && existing === null) {
113899
+ throw new Error(
113900
+ `Cannot preserve deleted-server conflict ${unprojectedConflictKeys.join(
113901
+ ", "
113902
+ )}: its prior source file ${JSON.stringify(path)} no longer exists.`
113903
+ );
113904
+ }
113905
+ const local = unprojectedConflictKeys.length > 0 ? existing ?? void 0 : localByPath.get(path)?.content;
113211
113906
  const server = serverByPath.get(path)?.content;
113212
113907
  const content = conflictPaths.has(path) ? renderConflictFileV4({
113213
113908
  localContent: local,
@@ -113215,9 +113910,7 @@ async function finishFormat4Pull(args) {
113215
113910
  versionId: workspace.config.versionId
113216
113911
  }) : local;
113217
113912
  if (content === void 0) continue;
113218
- const absolute = join10(workspace.root, path);
113219
- mkdirSync8(dirname7(absolute), { recursive: true });
113220
- const existing = existsSync7(absolute) ? readFileSync9(absolute, "utf8") : null;
113913
+ mkdirSync8(dirname8(absolute), { recursive: true });
113221
113914
  if (existing !== null && !rewritePaths.has(path)) continue;
113222
113915
  if (existing !== content) {
113223
113916
  writeFileSync8(absolute, content, "utf8");
@@ -113227,14 +113920,19 @@ async function finishFormat4Pull(args) {
113227
113920
  let removed = 0;
113228
113921
  for (const recordState of Object.values(workspace.state.records)) {
113229
113922
  const previousPath = recordState.file;
113230
- if (previousPath === void 0 || emittedPaths.has(previousPath)) continue;
113231
- const absolute = join10(workspace.root, previousPath);
113232
- if (existsSync7(absolute)) {
113923
+ if (previousPath === void 0) continue;
113924
+ const normalizedPreviousPath = normalizeWorkspaceSourcePath(previousPath);
113925
+ if (emittedPaths.has(normalizedPreviousPath)) {
113926
+ continue;
113927
+ }
113928
+ const absolute = resolveSourcePath(previousPath);
113929
+ if (existsSync8(absolute)) {
113233
113930
  rmSync5(absolute);
113234
113931
  removed += 1;
113235
113932
  }
113236
113933
  }
113237
113934
  const records2 = {};
113935
+ const previousRecords = workspace.state.records;
113238
113936
  for (const [key, plan] of plans) {
113239
113937
  const baseState = workspace.state.records[key];
113240
113938
  const serverRecord = document.records.get(key);
@@ -113277,6 +113975,10 @@ async function finishFormat4Pull(args) {
113277
113975
  const record3 = records2[key];
113278
113976
  if (record3) record3.projectBinary = state;
113279
113977
  }
113978
+ const staleConflictTears = conflictCount === 0 ? [] : findNewlyUnanchoredConflictValues({
113979
+ previousRecords,
113980
+ records: records2
113981
+ });
113280
113982
  workspace.state.records = records2;
113281
113983
  if (nextCursor !== null) {
113282
113984
  workspace.state.documentRevisionCursor = mutableCursor(nextCursor);
@@ -113328,6 +114030,12 @@ async function finishFormat4Pull(args) {
113328
114030
  'Conflict markers were written into the affected files. Edit them to the desired final state and push \u2014 the push is the resolution. To keep one side everywhere, use "neo resolve --mine" or "neo resolve --theirs".'
113329
114031
  );
113330
114032
  for (const key of conflictKeys) console.log(` ${sym.fail} ${key}`);
114033
+ for (const tear of staleConflictTears) {
114034
+ const rowLabel = tear.unanchoredValueCount === 1 ? "row" : "rows";
114035
+ warn(
114036
+ `Conflict ${tear.recordKind} "${tear.recordId}" retained a local base that does not anchor ${tear.unanchoredValueCount} newly pulled descendant value ${rowLabel}. Resolve it with "neo resolve --mine" or "neo resolve --theirs" before pushing.`
114037
+ );
114038
+ }
113331
114039
  }
113332
114040
  if (binaries.conflicted > 0) {
113333
114041
  warn(
@@ -113336,6 +114044,65 @@ async function finishFormat4Pull(args) {
113336
114044
  for (const path of binaries.conflicts) console.log(` ${sym.fail} ${path}`);
113337
114045
  }
113338
114046
  }
114047
+ function findNewlyUnanchoredConflictValues(args) {
114048
+ const newlyLandedValueIds = /* @__PURE__ */ new Set();
114049
+ for (const [key, record3] of Object.entries(args.records)) {
114050
+ if (args.previousRecords[key] !== void 0) continue;
114051
+ if (record3.recordKind !== "value") continue;
114052
+ if (record3.file === void 0) continue;
114053
+ if (record3.conflictServerHash !== void 0) continue;
114054
+ newlyLandedValueIds.add(record3.recordId);
114055
+ }
114056
+ if (newlyLandedValueIds.size === 0) return [];
114057
+ const unanchored = new Set(
114058
+ unanchoredValueDeleteIds({
114059
+ records: args.records,
114060
+ deletedValueIds: newlyLandedValueIds
114061
+ })
114062
+ );
114063
+ if (unanchored.size === 0) return [];
114064
+ const tears = [];
114065
+ for (const conflict2 of Object.values(args.records)) {
114066
+ if (typeof conflict2.conflictServerHash !== "string") continue;
114067
+ if (conflict2.file === void 0) continue;
114068
+ const serverAnchored = /* @__PURE__ */ new Set();
114069
+ collectNamedCandidateValues(
114070
+ conflict2.conflictServerData,
114071
+ newlyLandedValueIds,
114072
+ serverAnchored
114073
+ );
114074
+ let unanchoredValueCount = 0;
114075
+ for (const valueId of serverAnchored) {
114076
+ if (!unanchored.has(valueId)) continue;
114077
+ const value = args.records[`value:${valueId}`];
114078
+ if (value?.file !== conflict2.file) continue;
114079
+ unanchoredValueCount += 1;
114080
+ }
114081
+ if (unanchoredValueCount === 0) continue;
114082
+ tears.push({
114083
+ recordKind: conflict2.recordKind,
114084
+ recordId: conflict2.recordId,
114085
+ unanchoredValueCount
114086
+ });
114087
+ }
114088
+ return tears;
114089
+ }
114090
+ function collectNamedCandidateValues(value, candidates, found) {
114091
+ if (typeof value === "string") {
114092
+ if (candidates.has(value)) found.add(value);
114093
+ return;
114094
+ }
114095
+ if (Array.isArray(value)) {
114096
+ for (const element of value) {
114097
+ collectNamedCandidateValues(element, candidates, found);
114098
+ }
114099
+ return;
114100
+ }
114101
+ if (!isObjectRecord2(value)) return;
114102
+ for (const nested of Object.values(value)) {
114103
+ collectNamedCandidateValues(nested, candidates, found);
114104
+ }
114105
+ }
113339
114106
  function deltaRequiresSourceProjectionV4(args) {
113340
114107
  const mainLocale = workspaceMainLocale(args.workspace.state.records);
113341
114108
  for (const key of args.changedRecordKeys) {
@@ -113521,12 +114288,14 @@ var init_pull = __esm({
113521
114288
  init_project_documents();
113522
114289
  init_project_document_cache();
113523
114290
  init_materialized_construction_cache();
114291
+ init_workspace_source_path();
113524
114292
  init_project_manifest();
113525
114293
  init_project_documents();
113526
114294
  init_project_file_pull();
113527
114295
  init_dialogue_sources();
113528
114296
  init_static_value_seed_records();
113529
114297
  init_static_member_ownership_recovery();
114298
+ init_value_base_desync();
113530
114299
  }
113531
114300
  });
113532
114301
 
@@ -113535,8 +114304,8 @@ var init_exports = {};
113535
114304
  __export(init_exports, {
113536
114305
  runInit: () => runInit
113537
114306
  });
113538
- import { existsSync as existsSync8, mkdirSync as mkdirSync9, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "node:fs";
113539
- import { join as join11, resolve as resolve2 } from "node:path";
114307
+ import { existsSync as existsSync9, mkdirSync as mkdirSync9, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "node:fs";
114308
+ import { join as join10, resolve as resolve3 } from "node:path";
113540
114309
  async function runInit(options) {
113541
114310
  let projectId = options.projectId;
113542
114311
  let projects = [];
@@ -113632,9 +114401,9 @@ async function runInit(options) {
113632
114401
  validate: (value) => value.trim().length > 0 ? true : "Directory must not be empty."
113633
114402
  }) : "neo";
113634
114403
  }
113635
- const root = resolve2(directory);
113636
- if (existsSync8(join11(root, NEO_CONFIG_FILE))) {
113637
- throw new Error(`"${join11(root, NEO_CONFIG_FILE)}" already exists.`);
114404
+ const root = resolve3(directory);
114405
+ if (existsSync9(join10(root, NEO_CONFIG_FILE))) {
114406
+ throw new Error(`"${join10(root, NEO_CONFIG_FILE)}" already exists.`);
113638
114407
  }
113639
114408
  mkdirSync9(root, { recursive: true });
113640
114409
  ensurePrivateStateIgnored(root);
@@ -113659,8 +114428,8 @@ async function runInit(options) {
113659
114428
  });
113660
114429
  }
113661
114430
  function ensurePrivateStateIgnored(root) {
113662
- const path = join11(root, ".gitignore");
113663
- const existing = existsSync8(path) ? readFileSync10(path, "utf8") : "";
114431
+ const path = join10(root, ".gitignore");
114432
+ const existing = existsSync9(path) ? readFileSync10(path, "utf8") : "";
113664
114433
  if (existing.split(/\r?\n/u).some((line) => line.trim() === ".neo/" || line.trim() === ".neo")) {
113665
114434
  return;
113666
114435
  }
@@ -114066,7 +114835,7 @@ async function waitForPlan(convex, planId) {
114066
114835
  `History plan "${plan.id}" failed: ${plan.error ?? "unknown error"}`
114067
114836
  );
114068
114837
  }
114069
- await new Promise((resolve4) => setTimeout(resolve4, 500));
114838
+ await new Promise((resolve5) => setTimeout(resolve5, 500));
114070
114839
  }
114071
114840
  }
114072
114841
  async function printVersionLog(convex, scope) {
@@ -115065,8 +115834,8 @@ var init_save_overlay_resolution = __esm({
115065
115834
  });
115066
115835
 
115067
115836
  // src/commands/push-body-diagnostics.ts
115068
- import { existsSync as existsSync9, readFileSync as readFileSync11 } from "node:fs";
115069
- import { join as join12 } from "node:path";
115837
+ import { existsSync as existsSync10, readFileSync as readFileSync11 } from "node:fs";
115838
+ import { join as join11 } from "node:path";
115070
115839
  function createNeoScriptBodySourceLocator(workspace, status) {
115071
115840
  const textByFile = /* @__PURE__ */ new Map();
115072
115841
  return {
@@ -115088,8 +115857,8 @@ function createNeoScriptBodySourceLocator(workspace, status) {
115088
115857
  textOf(file) {
115089
115858
  const cached = textByFile.get(file);
115090
115859
  if (cached !== void 0) return cached;
115091
- const path = join12(workspace.root, file);
115092
- const text = existsSync9(path) ? readFileSync11(path, "utf8") : null;
115860
+ const path = join11(workspace.root, file);
115861
+ const text = existsSync10(path) ? readFileSync11(path, "utf8") : null;
115093
115862
  textByFile.set(file, text);
115094
115863
  return text;
115095
115864
  }
@@ -116891,29 +117660,29 @@ var init_project_source_identity = __esm({
116891
117660
  // src/push-hook.ts
116892
117661
  import { spawn } from "node:child_process";
116893
117662
  import { createHash as createHash9 } from "node:crypto";
116894
- import { existsSync as existsSync10, readFileSync as readFileSync13, readdirSync as readdirSync4 } from "node:fs";
116895
- import { join as join13, relative as relative3, sep as sep3 } from "node:path";
117663
+ import { existsSync as existsSync11, readFileSync as readFileSync13, readdirSync as readdirSync4 } from "node:fs";
117664
+ import { join as join12, relative as relative4, sep as sep4 } from "node:path";
116896
117665
  function fingerprintPushInputs(workspace, options = {}) {
116897
117666
  const paths = /* @__PURE__ */ new Set([
116898
- join13(workspace.root, "neo.json"),
117667
+ join12(workspace.root, "neo.json"),
116899
117668
  ...listProjectSourceFilesV4(workspace.root),
116900
117669
  ...options.includeTests === false ? [] : listProjectTestFilesV1(workspace.root),
116901
- ...workspace.config.unityConfigPath === void 0 ? [] : [join13(workspace.root, workspace.config.unityConfigPath)]
117670
+ ...workspace.config.unityConfigPath === void 0 ? [] : [join12(workspace.root, workspace.config.unityConfigPath)]
116902
117671
  ]);
116903
117672
  const visitManaged = (directory) => {
116904
- if (!existsSync10(directory)) return;
117673
+ if (!existsSync11(directory)) return;
116905
117674
  for (const entry of readdirSync4(directory, { withFileTypes: true })) {
116906
117675
  if (entry.isSymbolicLink()) continue;
116907
- const path = join13(directory, entry.name);
117676
+ const path = join12(directory, entry.name);
116908
117677
  if (entry.isDirectory()) visitManaged(path);
116909
117678
  else if (entry.isFile()) paths.add(path);
116910
117679
  }
116911
117680
  };
116912
- visitManaged(join13(workspace.root, "Files", "Images"));
116913
- visitManaged(join13(workspace.root, "Files", "AudioClips"));
117681
+ visitManaged(join12(workspace.root, "Files", "Images"));
117682
+ visitManaged(join12(workspace.root, "Files", "AudioClips"));
116914
117683
  const hash = createHash9("sha256");
116915
117684
  for (const path of [...paths].sort()) {
116916
- const name = relative3(workspace.root, path).split(sep3).join("/");
117685
+ const name = relative4(workspace.root, path).split(sep4).join("/");
116917
117686
  hash.update(name);
116918
117687
  hash.update("\0");
116919
117688
  try {
@@ -117055,7 +117824,7 @@ var init_push_hook = __esm({
117055
117824
  });
117056
117825
 
117057
117826
  // src/project-source/project-file-push.ts
117058
- import { basename as basename2, join as join14 } from "node:path";
117827
+ import { basename as basename2, join as join13 } from "node:path";
117059
117828
  import { readFileSync as readFileSync14 } from "node:fs";
117060
117829
  function ensureProjectFileBinaryChangesV4(args) {
117061
117830
  for (const binary of args.binaryChanges) {
@@ -117101,7 +117870,7 @@ function prepareProjectFilePushesV4(args) {
117101
117870
  `Project file ${recordId} has upload bytes but its source change has no record data.`
117102
117871
  );
117103
117872
  }
117104
- const absolute = join14(args.workspace.root, binary.path);
117873
+ const absolute = join13(args.workspace.root, binary.path);
117105
117874
  const bytes = new Uint8Array(readFileSync14(absolute));
117106
117875
  const digest = sha256Bytes(bytes);
117107
117876
  if (binary.localSha256 !== null && digest !== binary.localSha256) {
@@ -117340,7 +118109,7 @@ function isRetryableRequestError(error) {
117340
118109
  return RETRYABLE_NETWORK_ERROR_CODES.has(error.cause.code);
117341
118110
  }
117342
118111
  async function waitForRetry(attempt, signal) {
117343
- await new Promise((resolve4, reject) => {
118112
+ await new Promise((resolve5, reject) => {
117344
118113
  const abort = () => {
117345
118114
  clearTimeout(timeout);
117346
118115
  reject(signal.reason);
@@ -117348,7 +118117,7 @@ async function waitForRetry(attempt, signal) {
117348
118117
  const timeout = setTimeout(
117349
118118
  () => {
117350
118119
  signal.removeEventListener("abort", abort);
117351
- resolve4();
118120
+ resolve5();
117352
118121
  },
117353
118122
  200 * 2 ** (attempt - 1)
117354
118123
  );
@@ -117581,11 +118350,11 @@ import {
117581
118350
  mkdirSync as mkdirSync10,
117582
118351
  writeFileSync as writeFileSync10,
117583
118352
  rmSync as rmSync6,
117584
- existsSync as existsSync11,
118353
+ existsSync as existsSync12,
117585
118354
  readFileSync as readFileSync15,
117586
118355
  statSync as statSync2
117587
118356
  } from "node:fs";
117588
- import { dirname as dirname8, join as join15, relative as relative4, sep as sep4 } from "node:path";
118357
+ import { dirname as dirname9, join as join14, relative as relative5, sep as sep5 } from "node:path";
117589
118358
  function assignPendingIds(changes, authoredValueSeeds, reconstructed3, localInitializerMaterialization) {
117590
118359
  const assigned = /* @__PURE__ */ new Map();
117591
118360
  const assign = (pendingId2) => {
@@ -118126,14 +118895,14 @@ async function waitForPollDelay(delayMs, signal) {
118126
118895
  if (signal.aborted) {
118127
118896
  throw new Error("Project transaction polling was interrupted.");
118128
118897
  }
118129
- await new Promise((resolve4, reject) => {
118898
+ await new Promise((resolve5, reject) => {
118130
118899
  const aborted = () => {
118131
118900
  clearTimeout(timer);
118132
118901
  reject(new Error("Project transaction polling was interrupted."));
118133
118902
  };
118134
118903
  const timer = setTimeout(() => {
118135
118904
  signal.removeEventListener("abort", aborted);
118136
- resolve4();
118905
+ resolve5();
118137
118906
  }, delayMs);
118138
118907
  signal.addEventListener("abort", aborted, { once: true });
118139
118908
  });
@@ -118362,7 +119131,7 @@ async function runPush(workspace, options, preparationOverride) {
118362
119131
  );
118363
119132
  }
118364
119133
  if (options.noVerify !== true) {
118365
- const preparedBuildDir = configuredHook === void 0 ? void 0 : join15(
119134
+ const preparedBuildDir = configuredHook === void 0 ? void 0 : join14(
118366
119135
  workspace.root,
118367
119136
  ".neo",
118368
119137
  "test-build",
@@ -118379,7 +119148,7 @@ async function runPush(workspace, options, preparationOverride) {
118379
119148
  const documentJson = JSON.stringify(candidate.document);
118380
119149
  mkdirSync10(preparedBuildDir, { recursive: true });
118381
119150
  writeFileSync10(
118382
- join15(preparedBuildDir, "candidate.json"),
119151
+ join14(preparedBuildDir, "candidate.json"),
118383
119152
  `${JSON.stringify({
118384
119153
  version: 1,
118385
119154
  projectFingerprint: `sha256:${preparedLocal.source.sourceHash}`,
@@ -118885,7 +119654,7 @@ async function prepareLocalCandidateV4(workspace, options = {}) {
118885
119654
  } else {
118886
119655
  const files = listProjectSourceFilesV4(workspace.root).map(
118887
119656
  (absolutePath) => {
118888
- const path = relative4(workspace.root, absolutePath).split(sep4).join("/");
119657
+ const path = relative5(workspace.root, absolutePath).split(sep5).join("/");
118889
119658
  const kind = neoProjectSourceKind(path);
118890
119659
  if (kind === null || !isNeoProjectProductionSourceKind(kind)) {
118891
119660
  throw new Error(
@@ -119204,7 +119973,12 @@ function createPendingProjectSourceIdentityV4(workspace, status, authoredValueSe
119204
119973
  });
119205
119974
  }
119206
119975
  }
119207
- const emission = emitProjectDocumentFilesV4(records2);
119976
+ const emission = emitProjectDocumentFilesV4(records2, {
119977
+ recordFiles: projectRecordFilesV4(
119978
+ Object.values(workspace.state.records),
119979
+ status.reconstructed.values()
119980
+ )
119981
+ });
119208
119982
  const files = emission.files.map((file) => {
119209
119983
  const kind = neoProjectSourceKind(file.path);
119210
119984
  if (kind === null || !isNeoProjectProductionSourceKind(kind)) {
@@ -119410,7 +120184,12 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
119410
120184
  const previousState = workspace.state;
119411
120185
  workspace.state = { ...previousState, records: nextRecords };
119412
120186
  try {
119413
- rewriteFilesFromState(workspace, emitRecords, preservedSourceFiles);
120187
+ rewriteFilesFromState(
120188
+ workspace,
120189
+ emitRecords,
120190
+ preservedSourceFiles,
120191
+ projectRecordFilesV4(localRecords.values())
120192
+ );
119414
120193
  writeWorkspaceState(workspace.root, workspace.state);
119415
120194
  } catch (error) {
119416
120195
  workspace.state = previousState;
@@ -119596,16 +120375,30 @@ function applyPushResult(workspace, result, pendingIdAssignments = /* @__PURE__
119596
120375
  if (!isObjectRecord2(result) || !Array.isArray(result.changedRecords)) {
119597
120376
  throw new Error("Transaction response is missing changedRecords.");
119598
120377
  }
120378
+ const localStatus = computeWorkspaceStatus2(workspace);
119599
120379
  const preservedSourceFiles = materializeAssignedSchemaIdsInAuthoredSource(
119600
120380
  workspace,
119601
120381
  pendingIdAssignments,
119602
- computeWorkspaceStatus2(workspace).pendingValueIdentitySites
120382
+ localStatus.pendingValueIdentitySites
120383
+ );
120384
+ const replacements = {
120385
+ exact: pendingIdAssignments,
120386
+ embedded: pendingIdAssignments.entries().toArray().sort(([left], [right]) => right.length - left.length)
120387
+ };
120388
+ const localRecords = rewriteReconstructedRecords(
120389
+ localStatus.reconstructed,
120390
+ replacements
119603
120391
  );
119604
120392
  workspace.state.records = foldChangedRecords(
119605
120393
  workspace.state.records,
119606
120394
  result.changedRecords
119607
120395
  );
119608
- rewriteFilesFromState(workspace, void 0, preservedSourceFiles);
120396
+ rewriteFilesFromState(
120397
+ workspace,
120398
+ void 0,
120399
+ preservedSourceFiles,
120400
+ projectRecordFilesV4(localRecords.values())
120401
+ );
119609
120402
  writeWorkspaceState(workspace.root, workspace.state);
119610
120403
  }
119611
120404
  function authoredMemberFormsByFile(root, alternates) {
@@ -119614,8 +120407,8 @@ function authoredMemberFormsByFile(root, alternates) {
119614
120407
  for (const alternate of alternates) {
119615
120408
  let existing = contents.get(alternate.path);
119616
120409
  if (existing === void 0) {
119617
- const absolute = join15(root, alternate.path);
119618
- existing = existsSync11(absolute) ? readFileSync15(absolute, "utf8") : null;
120410
+ const absolute = join14(root, alternate.path);
120411
+ existing = existsSync12(absolute) ? readFileSync15(absolute, "utf8") : null;
119619
120412
  contents.set(alternate.path, existing);
119620
120413
  }
119621
120414
  if (existing === null || !existing.includes(alternate.block)) continue;
@@ -119653,14 +120446,14 @@ function fileSystemEntryKey(absolute) {
119653
120446
  if (!hasInode) return `path:${absolute.toLowerCase()}`;
119654
120447
  return `inode:${stats.dev}:${stats.ino}`;
119655
120448
  }
119656
- function deleteSupersededAuthoredFiles(root, authoredPaths, emitted) {
120449
+ function deleteSupersededAuthoredFiles(resolveSourcePath, authoredPaths, emitted) {
119657
120450
  const emittedEntries = /* @__PURE__ */ new Set();
119658
120451
  for (const file of emitted) {
119659
- emittedEntries.add(fileSystemEntryKey(join15(root, file.path)));
120452
+ emittedEntries.add(fileSystemEntryKey(resolveSourcePath(file.path)));
119660
120453
  }
119661
120454
  for (const authoredPath of authoredPaths) {
119662
- const absolute = join15(root, authoredPath);
119663
- if (!existsSync11(absolute)) continue;
120455
+ const absolute = resolveSourcePath(authoredPath);
120456
+ if (!existsSync12(absolute)) continue;
119664
120457
  if (emittedEntries.has(fileSystemEntryKey(absolute))) continue;
119665
120458
  rmSync6(absolute);
119666
120459
  }
@@ -119676,8 +120469,8 @@ function rewriteFilesFromState(workspace, records2 = new Map(
119676
120469
  data: recordState.data
119677
120470
  }
119678
120471
  ])
119679
- ), preservedSourceFiles = /* @__PURE__ */ new Map()) {
119680
- const result = emitProjectDocumentFilesV4(records2);
120472
+ ), preservedSourceFiles = /* @__PURE__ */ new Map(), recordFiles = /* @__PURE__ */ new Map()) {
120473
+ const result = emitProjectDocumentFilesV4(records2, { recordFiles });
119681
120474
  const authoredForms = authoredMemberFormsByFile(
119682
120475
  workspace.root,
119683
120476
  result.formAlternates
@@ -119708,22 +120501,27 @@ function rewriteFilesFromState(workspace, records2 = new Map(
119708
120501
  );
119709
120502
  assertAssignedIdSourceRewriteValid(finalAnalysis);
119710
120503
  writeProjectSourceAnalysisCacheV4(workspace.root, finalAnalysis);
120504
+ const resolveSourcePath = createWorkspaceSourcePathResolver(workspace.root);
119711
120505
  const emittedPaths = new Set(files.map((file) => file.path));
119712
120506
  for (const recordState of Object.values(workspace.state.records)) {
119713
120507
  const previousPath = recordState.file;
119714
- if (previousPath === void 0 || emittedPaths.has(previousPath)) continue;
119715
- const absolute = join15(workspace.root, previousPath);
119716
- if (existsSync11(absolute)) rmSync6(absolute);
120508
+ if (previousPath === void 0) continue;
120509
+ const normalizedPreviousPath = normalizeWorkspaceSourcePath(previousPath);
120510
+ if (emittedPaths.has(normalizedPreviousPath)) {
120511
+ continue;
120512
+ }
120513
+ const absolute = resolveSourcePath(previousPath);
120514
+ if (existsSync12(absolute)) rmSync6(absolute);
119717
120515
  }
119718
120516
  for (const file of files) {
119719
- const absolute = join15(workspace.root, file.path);
119720
- mkdirSync10(dirname8(absolute), { recursive: true });
119721
- const existing = existsSync11(absolute) ? readFileSync15(absolute, "utf8") : null;
120517
+ const absolute = resolveSourcePath(file.path);
120518
+ mkdirSync10(dirname9(absolute), { recursive: true });
120519
+ const existing = existsSync12(absolute) ? readFileSync15(absolute, "utf8") : null;
119722
120520
  if (existing !== file.content)
119723
120521
  writeFileSync10(absolute, file.content, "utf8");
119724
120522
  }
119725
120523
  deleteSupersededAuthoredFiles(
119726
- workspace.root,
120524
+ resolveSourcePath,
119727
120525
  preservedSourceFiles.keys(),
119728
120526
  files
119729
120527
  );
@@ -119763,7 +120561,7 @@ function materializeAssignedSchemaIdsInAuthoredSource(workspace, replacements, p
119763
120561
  if (pendingIdsByUri.size === 0) return /* @__PURE__ */ new Map();
119764
120562
  const inputs = listProjectSourceFilesV4(workspace.root).map(
119765
120563
  (absolutePath) => {
119766
- const uri = relative4(workspace.root, absolutePath).split(sep4).join("/");
120564
+ const uri = relative5(workspace.root, absolutePath).split(sep5).join("/");
119767
120565
  const kind = neoProjectSourceKind(uri);
119768
120566
  if (kind === null || !isNeoProjectProductionSourceKind(kind)) {
119769
120567
  throw new Error(
@@ -120180,16 +120978,13 @@ function prepareCompleteNeoScriptBodyChanges(workspace, status, schema, options
120180
120978
  `Cannot include server-derived NeoScript refresh for member "${compiled.id}": its reconstructed working-copy row is missing.`
120181
120979
  );
120182
120980
  }
120183
- const cascadeChange = {
120184
- kind: "update",
120981
+ const cascadeChange = recordUpsertChange({
120982
+ base,
120185
120983
  recordKind: "member",
120186
120984
  recordId: compiled.id,
120187
120985
  file: reconstructed3.file,
120188
- nextData,
120189
- baseData: base.data,
120190
- baseContentHash: base.contentHash,
120191
- casBaseHash: base.conflictServerHash ?? base.contentHash
120192
- };
120986
+ nextData
120987
+ });
120193
120988
  status.changes.push(cascadeChange);
120194
120989
  changesById.set(compiled.id, cascadeChange);
120195
120990
  }
@@ -120258,16 +121053,13 @@ function prepareNSPropertySetterChanges(workspace, status) {
120258
121053
  `Cannot cascade removal of NeoScript property setter to override "${memberId}": its working-copy state is missing.`
120259
121054
  );
120260
121055
  }
120261
- const cascadeChange = {
120262
- kind: "update",
121056
+ const cascadeChange = recordUpsertChange({
121057
+ base,
120263
121058
  recordKind: "member",
120264
121059
  recordId: memberId,
120265
121060
  file: reconstructed3.file,
120266
- nextData: next,
120267
- baseData: base.data,
120268
- baseContentHash: base.contentHash,
120269
- casBaseHash: base.conflictServerHash ?? base.contentHash
120270
- };
121061
+ nextData: next
121062
+ });
120271
121063
  status.changes.push(cascadeChange);
120272
121064
  changesById.set(memberId, cascadeChange);
120273
121065
  }
@@ -120334,16 +121126,13 @@ function prepareNSFunctionBodyChanges(workspace, status) {
120334
121126
  `Cannot recompile NeoScript function override "${memberId}": its working-copy state is missing.`
120335
121127
  );
120336
121128
  }
120337
- const cascadeChange = {
120338
- kind: "update",
121129
+ const cascadeChange = recordUpsertChange({
121130
+ base,
120339
121131
  recordKind: "member",
120340
121132
  recordId: memberId,
120341
121133
  file: reconstructed3.file,
120342
- nextData: member,
120343
- baseData: base.data,
120344
- baseContentHash: base.contentHash,
120345
- casBaseHash: base.conflictServerHash ?? base.contentHash
120346
- };
121134
+ nextData: member
121135
+ });
120347
121136
  status.changes.push(cascadeChange);
120348
121137
  changesById.set(memberId, cascadeChange);
120349
121138
  }
@@ -120467,6 +121256,7 @@ var init_push = __esm({
120467
121256
  init_src();
120468
121257
  init_compiler_adapter();
120469
121258
  init_project_source_identity();
121259
+ init_workspace_source_path();
120470
121260
  init_convex();
120471
121261
  init_http();
120472
121262
  init_ui();
@@ -120553,7 +121343,7 @@ var init_registry2 = __esm({
120553
121343
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
120554
121344
  formatVersion: 3,
120555
121345
  contractVersion: "3.15",
120556
- cliVersion: "0.38.4",
121346
+ cliVersion: "0.38.6",
120557
121347
  projectFileUploadBatchSize: 32,
120558
121348
  documentRecords: {
120559
121349
  member: {
@@ -121876,11 +122666,11 @@ __export(test_exports, {
121876
122666
  });
121877
122667
  import { createHash as createHash11, randomUUID as randomUUID3 } from "node:crypto";
121878
122668
  import {
121879
- existsSync as existsSync12,
122669
+ existsSync as existsSync13,
121880
122670
  mkdirSync as mkdirSync11,
121881
122671
  readdirSync as readdirSync5,
121882
122672
  readFileSync as readFileSync16,
121883
- realpathSync,
122673
+ realpathSync as realpathSync2,
121884
122674
  renameSync as renameSync5,
121885
122675
  rmSync as rmSync7,
121886
122676
  statSync as statSync3,
@@ -121888,12 +122678,12 @@ import {
121888
122678
  } from "node:fs";
121889
122679
  import {
121890
122680
  basename as basename3,
121891
- dirname as dirname9,
121892
- isAbsolute as isAbsolute2,
121893
- join as join16,
121894
- relative as relative5,
121895
- resolve as resolve3,
121896
- sep as sep5
122681
+ dirname as dirname10,
122682
+ isAbsolute as isAbsolute3,
122683
+ join as join15,
122684
+ relative as relative6,
122685
+ resolve as resolve4,
122686
+ sep as sep6
121897
122687
  } from "node:path";
121898
122688
  import { isDeepStrictEqual } from "node:util";
121899
122689
  function isRecord10(value) {
@@ -122079,25 +122869,25 @@ function preparedHookCandidate(workspace) {
122079
122869
  return null;
122080
122870
  }
122081
122871
  try {
122082
- const directory = realpathSync(configuredDirectory);
122083
- const cacheRoot = resolve3(
122084
- realpathSync(workspace.root),
122872
+ const directory = realpathSync2(configuredDirectory);
122873
+ const cacheRoot = resolve4(
122874
+ realpathSync2(workspace.root),
122085
122875
  ".neo",
122086
122876
  "test-build"
122087
122877
  );
122088
- const pathFromRoot = relative5(cacheRoot, directory);
122089
- if (isAbsolute2(pathFromRoot)) {
122878
+ const pathFromRoot = relative6(cacheRoot, directory);
122879
+ if (isAbsolute3(pathFromRoot)) {
122090
122880
  throw new NeoTestPreparedCandidateError(
122091
122881
  "NEO_PREPARED_BUILD_DIR must not resolve to an absolute path outside this workspace's .neo/test-build directory."
122092
122882
  );
122093
122883
  }
122094
- if (pathFromRoot === ".." || pathFromRoot.startsWith(`..${sep5}`)) {
122884
+ if (pathFromRoot === ".." || pathFromRoot.startsWith(`..${sep6}`)) {
122095
122885
  throw new NeoTestPreparedCandidateError(
122096
122886
  "NEO_PREPARED_BUILD_DIR must resolve inside this workspace's .neo/test-build directory."
122097
122887
  );
122098
122888
  }
122099
122889
  const parsed = JSON.parse(
122100
- readFileSync16(join16(directory, "candidate.json"), "utf8")
122890
+ readFileSync16(join15(directory, "candidate.json"), "utf8")
122101
122891
  );
122102
122892
  if (!isRecord10(parsed)) {
122103
122893
  throw new NeoTestPreparedCandidateError(
@@ -122154,7 +122944,7 @@ function fingerprintTestCandidateInputs(workspace) {
122154
122944
  }
122155
122945
  function testCandidateCachePath(workspace, inputFingerprint) {
122156
122946
  const cacheKey = createHash11("sha256").update(inputFingerprint).digest("hex");
122157
- return join16(
122947
+ return join15(
122158
122948
  workspace.root,
122159
122949
  ".neo",
122160
122950
  "test-build",
@@ -122179,7 +122969,7 @@ function cachedTestCandidate(workspace, inputFingerprint) {
122179
122969
  }
122180
122970
  if (typeof parsed.documentSha256 !== "string") return null;
122181
122971
  const documentJson = readFileSync16(
122182
- join16(dirname9(candidatePath), "document.json"),
122972
+ join15(dirname10(candidatePath), "document.json"),
122183
122973
  "utf8"
122184
122974
  );
122185
122975
  if (createHash11("sha256").update(documentJson).digest("hex") !== parsed.documentSha256) {
@@ -122200,7 +122990,7 @@ function cacheTestCandidate(workspace, inputFingerprint, candidate) {
122200
122990
  const documentJson = JSON.stringify(candidate.document);
122201
122991
  const documentSha256 = createHash11("sha256").update(documentJson).digest("hex");
122202
122992
  const candidatePath = testCandidateCachePath(workspace, inputFingerprint);
122203
- atomicWrite(join16(dirname9(candidatePath), "document.json"), documentJson);
122993
+ atomicWrite(join15(dirname10(candidatePath), "document.json"), documentJson);
122204
122994
  atomicWrite(
122205
122995
  candidatePath,
122206
122996
  JSON.stringify({
@@ -122217,10 +123007,10 @@ function cacheTestCandidate(workspace, inputFingerprint, candidate) {
122217
123007
  }
122218
123008
  function compileSpec(workspace, document, absolutePath, projectCompilationHash2) {
122219
123009
  const scriptDocument = readDocumentArrays(document);
122220
- const path = relative5(workspace.root, absolutePath).split(sep5).join("/");
123010
+ const path = relative6(workspace.root, absolutePath).split(sep6).join("/");
122221
123011
  const source = readFileSync16(absolutePath, "utf8");
122222
123012
  const sourceHash = createHash11("sha256").update(source).digest("hex");
122223
- const artifactPath = join16(
123013
+ const artifactPath = join15(
122224
123014
  workspace.root,
122225
123015
  ".neo",
122226
123016
  "test-build",
@@ -122278,7 +123068,7 @@ function selectedSpecPaths(workspace, selectors) {
122278
123068
  const relativePaths = new Map(
122279
123069
  all.map((absolutePath) => [
122280
123070
  absolutePath,
122281
- relative5(workspace.root, absolutePath).split(sep5).join("/")
123071
+ relative6(workspace.root, absolutePath).split(sep6).join("/")
122282
123072
  ])
122283
123073
  );
122284
123074
  const normalizedSelectors = selectors.map(
@@ -122286,22 +123076,22 @@ function selectedSpecPaths(workspace, selectors) {
122286
123076
  );
122287
123077
  for (const selector of normalizedSelectors) {
122288
123078
  if (/[*?]/u.test(selector)) continue;
122289
- if (isAbsolute2(selector)) {
123079
+ if (isAbsolute3(selector)) {
122290
123080
  throw new Error(
122291
123081
  `Spec selector ${JSON.stringify(selector)} must be workspace-relative.`
122292
123082
  );
122293
123083
  }
122294
- const absolute = resolve3(workspace.root, selector);
122295
- const workspaceRelative = relative5(workspace.root, absolute);
122296
- if (workspaceRelative === ".." || workspaceRelative.startsWith(`..${sep5}`)) {
123084
+ const absolute = resolve4(workspace.root, selector);
123085
+ const workspaceRelative = relative6(workspace.root, absolute);
123086
+ if (workspaceRelative === ".." || workspaceRelative.startsWith(`..${sep6}`)) {
122297
123087
  throw new Error(
122298
123088
  `Spec selector ${JSON.stringify(selector)} is outside the workspace.`
122299
123089
  );
122300
123090
  }
122301
- if (!existsSync12(absolute)) continue;
122302
- const real = realpathSync(absolute);
122303
- const realRelative = relative5(workspace.root, real);
122304
- if (realRelative === ".." || realRelative.startsWith(`..${sep5}`)) {
123091
+ if (!existsSync13(absolute)) continue;
123092
+ const real = realpathSync2(absolute);
123093
+ const realRelative = relative6(workspace.root, real);
123094
+ if (realRelative === ".." || realRelative.startsWith(`..${sep6}`)) {
122305
123095
  throw new Error(
122306
123096
  `Spec selector ${JSON.stringify(selector)} resolves outside the workspace through a symlink.`
122307
123097
  );
@@ -122311,7 +123101,7 @@ function selectedSpecPaths(workspace, selectors) {
122311
123101
  `Spec selector ${JSON.stringify(selector)} is ignored, private, symlinked, or is not a .spec.neo file.`
122312
123102
  );
122313
123103
  }
122314
- if (statSync3(absolute).isDirectory() && !all.some((path) => path.startsWith(`${absolute}${sep5}`))) {
123104
+ if (statSync3(absolute).isDirectory() && !all.some((path) => path.startsWith(`${absolute}${sep6}`))) {
122315
123105
  throw new Error(
122316
123106
  `Spec selector ${JSON.stringify(selector)} is ignored, private, or contains no eligible .spec.neo files.`
122317
123107
  );
@@ -123044,18 +123834,18 @@ async function executeRegisteredSpec(registered, document, selected, timeoutMs,
123044
123834
  return { tests: results, failures: fileFailures, testDurationMs };
123045
123835
  }
123046
123836
  function atomicWrite(path, content) {
123047
- mkdirSync11(dirname9(path), { recursive: true });
123837
+ mkdirSync11(dirname10(path), { recursive: true });
123048
123838
  const temporary = `${path}.tmp-${String(process.pid)}-${randomUUID3()}`;
123049
123839
  writeFileSync11(temporary, content, "utf8");
123050
123840
  renameSync5(temporary, path);
123051
123841
  }
123052
123842
  function testBuildFiles(root) {
123053
- if (!existsSync12(root)) return [];
123843
+ if (!existsSync13(root)) return [];
123054
123844
  const files = [];
123055
123845
  const visit = (directory) => {
123056
123846
  for (const entry of readdirSync5(directory, { withFileTypes: true })) {
123057
123847
  if (entry.isSymbolicLink()) continue;
123058
- const path = join16(directory, entry.name);
123848
+ const path = join15(directory, entry.name);
123059
123849
  if (entry.isDirectory()) visit(path);
123060
123850
  else if (entry.isFile()) {
123061
123851
  const stats = statSync3(path);
@@ -123067,16 +123857,16 @@ function testBuildFiles(root) {
123067
123857
  return files;
123068
123858
  }
123069
123859
  function maintainNeoTestBuildCache(root, maxBytes = TEST_BUILD_CACHE_LIMIT_BYTES, now = Date.now(), protectedDirectory = process.env.NEO_PREPARED_BUILD_DIR) {
123070
- const resolvedRoot = resolve3(root);
123071
- const resolvedProtected = protectedDirectory === void 0 ? null : resolve3(protectedDirectory);
123860
+ const resolvedRoot = resolve4(root);
123861
+ const resolvedProtected = protectedDirectory === void 0 ? null : resolve4(protectedDirectory);
123072
123862
  const protectedInsideRoot = resolvedProtected !== null && (() => {
123073
- const fromRoot = relative5(resolvedRoot, resolvedProtected);
123074
- return fromRoot === "" || !fromRoot.startsWith(`..${sep5}`) && fromRoot !== ".." && !isAbsolute2(fromRoot);
123863
+ const fromRoot = relative6(resolvedRoot, resolvedProtected);
123864
+ return fromRoot === "" || !fromRoot.startsWith(`..${sep6}`) && fromRoot !== ".." && !isAbsolute3(fromRoot);
123075
123865
  })();
123076
123866
  const isProtected = (path) => {
123077
123867
  if (!protectedInsideRoot || resolvedProtected === null) return false;
123078
- const fromProtected = relative5(resolvedProtected, resolve3(path));
123079
- return fromProtected === "" || !fromProtected.startsWith(`..${sep5}`) && fromProtected !== ".." && !isAbsolute2(fromProtected);
123868
+ const fromProtected = relative6(resolvedProtected, resolve4(path));
123869
+ return fromProtected === "" || !fromProtected.startsWith(`..${sep6}`) && fromProtected !== ".." && !isAbsolute3(fromProtected);
123080
123870
  };
123081
123871
  for (const file of testBuildFiles(root)) {
123082
123872
  if (!isProtected(file.path) && basename3(file.path).includes(".tmp-") && now - file.modifiedMs >= ABANDONED_TEMP_MAX_AGE_MS) {
@@ -123116,7 +123906,7 @@ function formatStatusCounts(passed, failed, total, skipped = 0) {
123116
123906
  async function runTest(workspace, options, dependencies = {}) {
123117
123907
  const started = Date.now();
123118
123908
  const performanceStarted = performance.now();
123119
- const testBuildRoot = join16(workspace.root, ".neo", "test-build");
123909
+ const testBuildRoot = join15(workspace.root, ".neo", "test-build");
123120
123910
  maintainNeoTestBuildCache(testBuildRoot);
123121
123911
  const startedAt = new Date(started).toISOString();
123122
123912
  let projectFingerprint = null;
@@ -123220,7 +124010,7 @@ async function runTest(workspace, options, dependencies = {}) {
123220
124010
  throw new NeoTestUsageError(errorMessage2(error));
123221
124011
  }
123222
124012
  selectedFiles = selectedPaths.map(
123223
- (path) => relative5(workspace.root, path).split(sep5).join("/")
124013
+ (path) => relative6(workspace.root, path).split(sep6).join("/")
123224
124014
  );
123225
124015
  if (selectedPaths.length === 0 && options.passWithNoTests !== true) {
123226
124016
  throw new NeoTestNoTestsError(
@@ -123295,7 +124085,7 @@ async function runTest(workspace, options, dependencies = {}) {
123295
124085
  }))
123296
124086
  };
123297
124087
  atomicWrite(
123298
- join16(workspace.root, ".neo", "test-build", "v1", "manifest.json"),
124088
+ join15(workspace.root, ".neo", "test-build", "v1", "manifest.json"),
123299
124089
  `${JSON.stringify(buildManifest, null, 2)}
123300
124090
  `
123301
124091
  );
@@ -123384,7 +124174,7 @@ async function runTest(workspace, options, dependencies = {}) {
123384
124174
  if (options.outputFile !== null) {
123385
124175
  try {
123386
124176
  atomicWrite(
123387
- isAbsolute2(options.outputFile) ? options.outputFile : join16(workspace.root, options.outputFile),
124177
+ isAbsolute3(options.outputFile) ? options.outputFile : join15(workspace.root, options.outputFile),
123388
124178
  serialized
123389
124179
  );
123390
124180
  } catch (error) {
@@ -123468,7 +124258,7 @@ async function inspectNeoTestCompilation(workspace, dependencies = {}) {
123468
124258
  if (candidate.document === null) {
123469
124259
  return {
123470
124260
  files: selectedPaths.map(
123471
- (path) => relative5(workspace.root, path).split(sep5).join("/")
124261
+ (path) => relative6(workspace.root, path).split(sep6).join("/")
123472
124262
  ),
123473
124263
  errors: [
123474
124264
  {
@@ -123489,14 +124279,14 @@ async function inspectNeoTestCompilation(workspace, dependencies = {}) {
123489
124279
  compileSpec(workspace, document, path, compilationHash);
123490
124280
  } catch (error) {
123491
124281
  errors.push({
123492
- file: relative5(workspace.root, path).split(sep5).join("/"),
124282
+ file: relative6(workspace.root, path).split(sep6).join("/"),
123493
124283
  message: errorMessage2(error)
123494
124284
  });
123495
124285
  }
123496
124286
  }
123497
124287
  return {
123498
124288
  files: selectedPaths.map(
123499
- (path) => relative5(workspace.root, path).split(sep5).join("/")
124289
+ (path) => relative6(workspace.root, path).split(sep6).join("/")
123500
124290
  ),
123501
124291
  errors
123502
124292
  };
@@ -123595,10 +124385,10 @@ __export(doctor_exports, {
123595
124385
  import {
123596
124386
  constants as fsConstants,
123597
124387
  accessSync,
123598
- existsSync as existsSync13,
124388
+ existsSync as existsSync14,
123599
124389
  readFileSync as readFileSync17
123600
124390
  } from "node:fs";
123601
- import { extname as extname2, isAbsolute as isAbsolute3, join as join17, relative as relative6, sep as sep6 } from "node:path";
124391
+ import { extname as extname2, isAbsolute as isAbsolute4, join as join16, relative as relative7, sep as sep7 } from "node:path";
123602
124392
  function inspectNeoDoctor(workspace) {
123603
124393
  const formatCompatible = workspace.config.formatVersion === CURRENT_FORMAT_VERSION;
123604
124394
  const compiler = inspectCompilerContract();
@@ -123714,8 +124504,8 @@ function inspectSourceContract(workspace) {
123714
124504
  }
123715
124505
  }
123716
124506
  function inspectExtensionContract(root) {
123717
- const cachePath = join17(root, PROJECT_SOURCE_ANALYSIS_V4_CACHE_PATH);
123718
- if (!existsSync13(cachePath)) {
124507
+ const cachePath = join16(root, PROJECT_SOURCE_ANALYSIS_V4_CACHE_PATH);
124508
+ if (!existsSync14(cachePath)) {
123719
124509
  return {
123720
124510
  id: NEO_VSCODE_EXTENSION_ID,
123721
124511
  contractVersion: NEO_VSCODE_EXTENSION_CONTRACT_VERSION,
@@ -123778,7 +124568,7 @@ function inspectTrackedBinary(root, record3, errors) {
123778
124568
  const binary = record3.projectBinary;
123779
124569
  if (!binary) return;
123780
124570
  const path = binary.path.replaceAll("\\", "/");
123781
- if (isAbsolute3(path) || path.split("/").includes("..")) {
124571
+ if (isAbsolute4(path) || path.split("/").includes("..")) {
123782
124572
  errors.push(
123783
124573
  `Project file ${record3.recordId} has unsafe tracked path ${JSON.stringify(binary.path)}.`
123784
124574
  );
@@ -123798,8 +124588,8 @@ function inspectTrackedBinary(root, record3, errors) {
123798
124588
  `Project file ${record3.recordId} has an invalid SHA-256 base digest.`
123799
124589
  );
123800
124590
  }
123801
- const absolute = join17(root, path);
123802
- if (existsSync13(absolute) && !canAccess(absolute, fsConstants.R_OK)) {
124591
+ const absolute = join16(root, path);
124592
+ if (existsSync14(absolute) && !canAccess(absolute, fsConstants.R_OK)) {
123803
124593
  errors.push(`Tracked project file ${path} is not readable.`);
123804
124594
  }
123805
124595
  }
@@ -123824,7 +124614,7 @@ function canAccess(path, mode) {
123824
124614
  }
123825
124615
  }
123826
124616
  function workspacePath(root, path) {
123827
- return relative6(root, path).split(sep6).join("/");
124617
+ return relative7(root, path).split(sep7).join("/");
123828
124618
  }
123829
124619
  function errorMessage3(error) {
123830
124620
  return error instanceof Error ? error.message : String(error);
@@ -123940,8 +124730,8 @@ __export(migrate_exports, {
123940
124730
  runMigrate: () => runMigrate
123941
124731
  });
123942
124732
  import { randomUUID as randomUUID4 } from "node:crypto";
123943
- import { existsSync as existsSync14, mkdirSync as mkdirSync12, readdirSync as readdirSync6, writeFileSync as writeFileSync12 } from "node:fs";
123944
- import { join as join18 } from "node:path";
124733
+ import { existsSync as existsSync15, mkdirSync as mkdirSync12, readdirSync as readdirSync6, writeFileSync as writeFileSync12 } from "node:fs";
124734
+ import { join as join17 } from "node:path";
123945
124735
  async function runMigrate(workspace, subcommand, positional, targetRef, json, dependencies = {}) {
123946
124736
  if (subcommand === "new") {
123947
124737
  const name = positional[0];
@@ -123950,10 +124740,10 @@ async function runMigrate(workspace, subcommand, positional, targetRef, json, de
123950
124740
  "Usage: neo migrate new <name> [--target <ClassName|project>]"
123951
124741
  );
123952
124742
  }
123953
- const migrationsDir = join18(workspace.root, "Migrations");
124743
+ const migrationsDir = join17(workspace.root, "Migrations");
123954
124744
  mkdirSync12(migrationsDir, { recursive: true });
123955
124745
  let nextOrder = 1;
123956
- if (existsSync14(migrationsDir)) {
124746
+ if (existsSync15(migrationsDir)) {
123957
124747
  for (const entry of readdirSync6(migrationsDir)) {
123958
124748
  const match = /^(\d+)-/.exec(entry);
123959
124749
  if (match !== null) {
@@ -123962,8 +124752,8 @@ async function runMigrate(workspace, subcommand, positional, targetRef, json, de
123962
124752
  }
123963
124753
  }
123964
124754
  const relPath = migrationFileName(nextOrder, name);
123965
- const absolute = join18(workspace.root, relPath);
123966
- if (existsSync14(absolute)) {
124755
+ const absolute = join17(workspace.root, relPath);
124756
+ if (existsSync15(absolute)) {
123967
124757
  throw new Error(`"${relPath}" already exists.`);
123968
124758
  }
123969
124759
  const target = targetRef ?? "project";
@@ -125534,7 +126324,7 @@ async function waitForMergeTransaction(args) {
125534
126324
  status = readMergeTransactionStatus(response, status.transactionId);
125535
126325
  if (status.commitStatus === "committed") continue;
125536
126326
  if (status.commitStatus === "failed") continue;
125537
- await new Promise((resolve4) => setTimeout(resolve4, delayMs));
126327
+ await new Promise((resolve5) => setTimeout(resolve5, delayMs));
125538
126328
  delayMs = Math.min(delayMs * 2, 5e3);
125539
126329
  }
125540
126330
  }
@@ -126756,7 +127546,7 @@ __export(export_exports, {
126756
127546
  runExportUnity: () => runExportUnity
126757
127547
  });
126758
127548
  import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync13 } from "node:fs";
126759
- import { join as join19 } from "node:path";
127549
+ import { join as join18 } from "node:path";
126760
127550
  async function runExportUnity(workspace, outDir) {
126761
127551
  if (outDir === null) {
126762
127552
  throw new Error(
@@ -126768,23 +127558,23 @@ async function runExportUnity(workspace, outDir) {
126768
127558
  `/api/projects/${workspace.config.projectId}/export`,
126769
127559
  { versionId: workspace.config.versionId }
126770
127560
  );
126771
- const resourcesDir = join19(outDir, "Resources", "Neo");
126772
- const localizationDir = join19(resourcesDir, "Localization");
126773
- const scriptsDir = join19(outDir, "Scripts", "Neo");
127561
+ const resourcesDir = join18(outDir, "Resources", "Neo");
127562
+ const localizationDir = join18(resourcesDir, "Localization");
127563
+ const scriptsDir = join18(outDir, "Scripts", "Neo");
126774
127564
  mkdirSync13(localizationDir, { recursive: true });
126775
127565
  mkdirSync13(scriptsDir, { recursive: true });
126776
- writeFileSync13(join19(resourcesDir, "project.json"), response.projectJson);
127566
+ writeFileSync13(join18(resourcesDir, "project.json"), response.projectJson);
126777
127567
  writeFileSync13(
126778
- join19(scriptsDir, "NeoGeneratedTypes.cs"),
127568
+ join18(scriptsDir, "NeoGeneratedTypes.cs"),
126779
127569
  response.generatedTypes
126780
127570
  );
126781
127571
  for (const file of response.localizationFiles ?? []) {
126782
- writeFileSync13(join19(localizationDir, file.fileName), file.content);
127572
+ writeFileSync13(join18(localizationDir, file.fileName), file.content);
126783
127573
  }
126784
- console.log(`wrote ${join19(resourcesDir, "project.json")}`);
126785
- console.log(`wrote ${join19(scriptsDir, "NeoGeneratedTypes.cs")}`);
127574
+ console.log(`wrote ${join18(resourcesDir, "project.json")}`);
127575
+ console.log(`wrote ${join18(scriptsDir, "NeoGeneratedTypes.cs")}`);
126786
127576
  for (const file of response.localizationFiles ?? []) {
126787
- console.log(`wrote ${join19(localizationDir, file.fileName)}`);
127577
+ console.log(`wrote ${join18(localizationDir, file.fileName)}`);
126788
127578
  }
126789
127579
  const diagnostics = response.diagnostics ?? [];
126790
127580
  for (const diagnostic of diagnostics) {
@@ -126807,7 +127597,7 @@ __export(dev_exports, {
126807
127597
  runDev: () => runDev
126808
127598
  });
126809
127599
  import { watch } from "node:fs";
126810
- import { join as join20 } from "node:path";
127600
+ import { join as join19 } from "node:path";
126811
127601
  import { emitKeypressEvents } from "node:readline";
126812
127602
  import { ConvexClient } from "convex/browser";
126813
127603
  function isSchemaSignal(value) {
@@ -126917,7 +127707,7 @@ async function runDev(workspace, options) {
126917
127707
  };
126918
127708
  for (const dir of ["Classes", "Enums"]) {
126919
127709
  try {
126920
- watch(join20(workspace.root, dir), { persistent: true }, onFileChange);
127710
+ watch(join19(workspace.root, dir), { persistent: true }, onFileChange);
126921
127711
  } catch {
126922
127712
  }
126923
127713
  }
@@ -126973,7 +127763,7 @@ __export(resolve_exports, {
126973
127763
  workspaceFilePath: () => workspaceFilePath
126974
127764
  });
126975
127765
  import { readFileSync as readFileSync19, rmSync as rmSync8, writeFileSync as writeFileSync14 } from "node:fs";
126976
- import { join as join21 } from "node:path";
127766
+ import { join as join20 } from "node:path";
126977
127767
  function runResolve(workspace, side) {
126978
127768
  const resolvedRecords = adoptServerConflictBases(workspace);
126979
127769
  let resolvedFiles = 0;
@@ -126989,12 +127779,12 @@ function runResolve(workspace, side) {
126989
127779
  const binary = state.projectBinary;
126990
127780
  const conflict2 = binary?.conflict;
126991
127781
  if (binary === void 0 || conflict2 === void 0) continue;
126992
- const destination = join21(workspace.root, binary.path);
127782
+ const destination = join20(workspace.root, binary.path);
126993
127783
  if (side === "theirs") {
126994
127784
  if (conflict2.remoteSha256 !== null && conflict2.artifactPath !== void 0) {
126995
127785
  writeVerifiedBinaryDownloadV4(
126996
127786
  destination,
126997
- readFileSync19(join21(workspace.root, conflict2.artifactPath)),
127787
+ readFileSync19(join20(workspace.root, conflict2.artifactPath)),
126998
127788
  conflict2.remoteSha256
126999
127789
  );
127000
127790
  binary.sha256 = conflict2.remoteSha256;
@@ -127004,7 +127794,7 @@ function runResolve(workspace, side) {
127004
127794
  }
127005
127795
  }
127006
127796
  if (conflict2.artifactPath !== void 0) {
127007
- rmSync8(join21(workspace.root, conflict2.artifactPath), { force: true });
127797
+ rmSync8(join20(workspace.root, conflict2.artifactPath), { force: true });
127008
127798
  }
127009
127799
  delete binary.conflict;
127010
127800
  resolvedBinaries += 1;
@@ -127073,7 +127863,7 @@ function resolveMarkers(source, side) {
127073
127863
  return output.join("\n");
127074
127864
  }
127075
127865
  function workspaceFilePath(workspace, file) {
127076
- return join21(workspace.root, file);
127866
+ return join20(workspace.root, file);
127077
127867
  }
127078
127868
  var init_resolve = __esm({
127079
127869
  "src/commands/resolve.ts"() {
@@ -127278,7 +128068,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
127278
128068
  async function main() {
127279
128069
  const args = parseArgs(process.argv.slice(2));
127280
128070
  if (args.command === "--version") {
127281
- console.log("0.38.4");
128071
+ console.log("0.38.6");
127282
128072
  return;
127283
128073
  }
127284
128074
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {