@neocompose/cli 0.53.1 → 0.53.3

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
@@ -7456,7 +7456,7 @@ var init_strict_resolver = __esm({
7456
7456
  }
7457
7457
  return resolved.pointer.value;
7458
7458
  }
7459
- resolveAssignment(statement, scope) {
7459
+ resolveAssignment(statement, scope, assignmentContext = "ordinary") {
7460
7460
  if (!isAssignmentTarget(statement.target)) {
7461
7461
  throw new CompileError(
7462
7462
  "Assignment target must be a variable, member, or indexed value.",
@@ -7494,9 +7494,27 @@ var init_strict_resolver = __esm({
7494
7494
  statement.pos
7495
7495
  );
7496
7496
  }
7497
- if (!writability || writability === "readOnly" /* ReadOnly */ || writability === "immutable" /* Immutable */) {
7497
+ if (target.symbol?.readonlyDeclaration === true) {
7498
7498
  throw new CompileError(
7499
- target.symbol?.readonlyDeclaration === true ? `Member '${target.symbol.name}' is readonly and can only be changed through its class default.` : writability === "immutable" /* Immutable */ ? "Cannot assign because the target's effective storage is immutable." : `Cannot assign to a read-only ${this.describe(target.type)} value.`,
7499
+ `Member '${target.symbol.name}' is readonly and can only be changed through its class default.`,
7500
+ statement.pos
7501
+ );
7502
+ }
7503
+ if (writability === void 0) {
7504
+ throw new CompileError(
7505
+ `Cannot assign to a read-only ${this.describe(target.type)} value.`,
7506
+ statement.pos
7507
+ );
7508
+ }
7509
+ if (writability === "readOnly" /* ReadOnly */) {
7510
+ throw new CompileError(
7511
+ `Cannot assign to a read-only ${this.describe(target.type)} value.`,
7512
+ statement.pos
7513
+ );
7514
+ }
7515
+ if (writability === "immutable" /* Immutable */ && assignmentContext !== "initializer") {
7516
+ throw new CompileError(
7517
+ "Cannot assign because the target's effective storage is immutable.",
7500
7518
  statement.pos
7501
7519
  );
7502
7520
  }
@@ -9281,16 +9299,22 @@ var init_strict_resolver = __esm({
9281
9299
  const registryEntry = this.resolveRegistryEntry(receiver, name, pos);
9282
9300
  if (registryEntry) return registryEntry;
9283
9301
  if (receiver.indexSurface) {
9284
- const index = (this.context.project.listIndexes ?? []).find(
9285
- (candidate) => candidate.listMemberId === receiver.indexSurface?.listMemberId && candidate.name === name
9302
+ const surface = receiver.indexSurface;
9303
+ const declared = this.indexesFor(surface).find(
9304
+ (candidate) => candidate.name === name
9286
9305
  );
9287
- if (!index) {
9306
+ if (!declared) {
9288
9307
  throw new CompileError(
9289
9308
  `List index surface has no declared index '${name}'.`,
9290
9309
  pos
9291
9310
  );
9292
9311
  }
9293
- const viewValueType = index.unique ? index.valueType : {
9312
+ const index = {
9313
+ ...declared,
9314
+ keyType: this.boundIndexKeyType(declared, surface.elementType),
9315
+ valueType: surface.elementType
9316
+ };
9317
+ const viewValueType = index.unique ? { ...index.valueType, nullable: true } : {
9294
9318
  kind: "list",
9295
9319
  elementType: { ...index.valueType, nullable: false },
9296
9320
  readOnly: true
@@ -9309,10 +9333,7 @@ var init_strict_resolver = __esm({
9309
9333
  indexCollectionPointer: receiver.pointer
9310
9334
  };
9311
9335
  }
9312
- const receiverListMemberId = receiver.type.kind === "list" ? receiver.type.listMemberId : void 0;
9313
- if (receiver.type.kind === "list" && name === "Index" && receiverListMemberId && (this.context.project.listIndexes ?? []).some(
9314
- (candidate) => candidate.listMemberId === receiverListMemberId
9315
- )) {
9336
+ if (receiver.type.kind === "list" && name === "Index" && this.indexesFor(receiver.type).length > 0) {
9316
9337
  return {
9317
9338
  pointer: receiver.pointer,
9318
9339
  type: { kind: "primitive", name: "unknown" },
@@ -9462,6 +9483,23 @@ var init_strict_resolver = __esm({
9462
9483
  pos
9463
9484
  );
9464
9485
  }
9486
+ boundIndexKeyType(index, entryType) {
9487
+ const entry = neoScriptMemberLookupType(entryType);
9488
+ if (entry.kind !== "named") return index.keyType;
9489
+ const declaring = this.project.typeById.get(entry.typeId);
9490
+ if (!declaring) return index.keyType;
9491
+ const key = declaring.members.find((member) => member.name === index.name);
9492
+ return substituteTypeParameters(
9493
+ key?.type ?? index.keyType,
9494
+ entry,
9495
+ declaring
9496
+ );
9497
+ }
9498
+ /** The indexes declared on a schema-backed List, keyed by its member. */
9499
+ indexesFor(type) {
9500
+ if (type.listMemberId === void 0) return [];
9501
+ return this.project.indexesByListMemberId.get(type.listMemberId) ?? [];
9502
+ }
9465
9503
  /**
9466
9504
  * P42 §2.3. `Images.<Name>` / `AudioClips.<Name>`.
9467
9505
  *
@@ -10341,7 +10379,8 @@ var init_strict_resolver = __esm({
10341
10379
  receiver: { kind: "ident", name, pos: entry.pos }
10342
10380
  }
10343
10381
  },
10344
- initializerScope
10382
+ initializerScope,
10383
+ "initializer"
10345
10384
  );
10346
10385
  if (assignment.type !== "assign" /* Assign */) {
10347
10386
  throw new CompileError(
@@ -16354,6 +16393,28 @@ function effectiveSourceAccessModifier(modifiers, ownerKind) {
16354
16393
  if (explicit !== void 0) return explicit;
16355
16394
  return ownerKind === "interface" ? "public" : "private";
16356
16395
  }
16396
+ function sourceMemberKeyArgument(annotation2) {
16397
+ const positional = annotation2.arguments[0];
16398
+ const argument2 = annotation2.arguments.find((entry) => entry.name === "member") ?? (positional !== void 0 && positional.name === void 0 ? positional : void 0);
16399
+ if (argument2 === void 0) return null;
16400
+ const text = argument2.text.trim();
16401
+ return {
16402
+ key: /^[A-Za-z_][A-Za-z0-9_]*$/.test(text) ? text : null,
16403
+ range: argument2.range
16404
+ };
16405
+ }
16406
+ function* sourceListIndexAnnotations(annotations) {
16407
+ for (const annotation2 of annotations) {
16408
+ if (annotation2.name !== "index") continue;
16409
+ const key = sourceMemberKeyArgument(annotation2)?.key;
16410
+ if (!key) continue;
16411
+ yield {
16412
+ key,
16413
+ unique: annotation2.arguments.find((argument2) => argument2.name === "kind")?.text.trim() === ".Unique",
16414
+ annotation: annotation2
16415
+ };
16416
+ }
16417
+ }
16357
16418
  var init_project_source_ast = __esm({
16358
16419
  "../packages/neoscript-language/src/project-source-ast.ts"() {
16359
16420
  "use strict";
@@ -22751,7 +22812,7 @@ function validateMember(uri, member, ownerName, documentKind, ownerScope, enviro
22751
22812
  );
22752
22813
  validateTypeAnnotations(uri, member.type, environment, diagnostics);
22753
22814
  if (documentKind !== "flow") {
22754
- validateListAnnotations(uri, member, environment, diagnostics);
22815
+ validateListAnnotations(uri, member, ownerName, environment, diagnostics);
22755
22816
  }
22756
22817
  const scope = new Map(ownerScope);
22757
22818
  if (member.kind === "function") {
@@ -23965,14 +24026,21 @@ function anchorPosition(anchor, offset) {
23965
24026
  return { line: anchor.start.line + line, character };
23966
24027
  }
23967
24028
  function sourceClassFieldByName(declaration, name, environment, initialBindings = /* @__PURE__ */ new Map()) {
24029
+ const resolved = sourceClassMemberByName(
24030
+ declaration,
24031
+ name,
24032
+ environment,
24033
+ initialBindings
24034
+ );
24035
+ return resolved?.member.kind === "field" ? resolved : void 0;
24036
+ }
24037
+ function sourceClassMemberByName(declaration, name, environment, initialBindings = /* @__PURE__ */ new Map()) {
23968
24038
  const visited = /* @__PURE__ */ new Set();
23969
24039
  let current = declaration;
23970
24040
  let bindings = initialBindings;
23971
24041
  while (current !== void 0 && !visited.has(current.name)) {
23972
24042
  visited.add(current.name);
23973
- const member = current.members.find(
23974
- (candidate) => candidate.kind === "field" && candidate.name === name
23975
- );
24043
+ const member = current.members.find((candidate) => candidate.name === name);
23976
24044
  if (member !== void 0) return { member, bindings };
23977
24045
  const base = current.baseTypes.find(
23978
24046
  (candidate) => environment.types.has(candidate.name)
@@ -24202,20 +24270,17 @@ function semanticMemberType(member, environment, bindings = /* @__PURE__ */ new
24202
24270
  if (type.name !== "List") return type;
24203
24271
  const entryType = type.arguments?.[0];
24204
24272
  if (!entryType) return type;
24205
- const entryClass = environment.types.get(entryType.name);
24206
- if (!entryClass) return type;
24207
24273
  const indexes2 = /* @__PURE__ */ new Map();
24208
- for (const annotation2 of member.annotations) {
24209
- if (annotation2.name !== "index") continue;
24210
- const key = memberKeyArgument(annotation2)?.key;
24211
- if (!key) continue;
24212
- const field = resolveEntryField(entryClass, key, environment);
24274
+ for (const index of sourceListIndexAnnotations(member.annotations)) {
24275
+ const field = sourceClassMemberForType(entryType, index.key, environment);
24213
24276
  if (!field) continue;
24214
- const unique = contextualAnnotationEnum([annotation2], "index", "kind") === "Unique";
24215
- const valueType = unique ? { ...entryType, nullable: true } : { name: "List", arguments: [{ ...entryType, nullable: false }] };
24216
- indexes2.set(key, {
24277
+ const valueType = index.unique ? { ...entryType, nullable: true } : { name: "List", arguments: [{ ...entryType, nullable: false }] };
24278
+ indexes2.set(index.key, {
24217
24279
  name: "Dictionary",
24218
- arguments: [semanticType(field.type), valueType]
24280
+ arguments: [
24281
+ substituteSemanticType(semanticType(field.member.type), field.bindings),
24282
+ valueType
24283
+ ]
24219
24284
  });
24220
24285
  }
24221
24286
  return indexes2.size === 0 ? type : { ...type, listIndexes: indexes2 };
@@ -24449,15 +24514,18 @@ function contextualAnnotationEnum(annotations, name, field) {
24449
24514
  const value = annotations.find((annotation2) => annotation2.name === name)?.arguments.find((argument2) => argument2.name === field)?.text.trim();
24450
24515
  return value?.startsWith(".") ? value.slice(1) : null;
24451
24516
  }
24452
- function validateListAnnotations(uri, member, environment, diagnostics) {
24517
+ function validateListAnnotations(uri, member, ownerName, environment, diagnostics) {
24453
24518
  const declared = member.annotations.filter(
24454
24519
  (annotation2) => annotation2.name === "index" || annotation2.name === "column"
24455
24520
  );
24456
24521
  if (declared.length === 0) return;
24457
- const entryClass = listEntryClass(member.type, environment);
24522
+ const entryType = listEntryType(
24523
+ member.type,
24524
+ environment.types.get(ownerName)
24525
+ );
24458
24526
  const seen = /* @__PURE__ */ new Set();
24459
24527
  for (const annotation2 of declared) {
24460
- const target = memberKeyArgument(annotation2);
24528
+ const target = sourceMemberKeyArgument(annotation2);
24461
24529
  if (target === null) {
24462
24530
  pushDiagnostic(
24463
24531
  diagnostics,
@@ -24492,20 +24560,25 @@ function validateListAnnotations(uri, member, environment, diagnostics) {
24492
24560
  if (annotation2.name === "column" && target.key === LIST_COLUMN_INHERITANCE_KEY) {
24493
24561
  continue;
24494
24562
  }
24495
- if (entryClass === null) continue;
24496
- const field = resolveEntryField(entryClass, target.key, environment);
24497
- if (field === null) {
24563
+ if (entryType === null) continue;
24564
+ if (!environment.types.has(entryType.name)) continue;
24565
+ const field = sourceClassMemberForType(entryType, target.key, environment);
24566
+ if (field === void 0) {
24498
24567
  pushDiagnostic(
24499
24568
  diagnostics,
24500
24569
  uri,
24501
24570
  target.range,
24502
24571
  "unresolved-list-annotation-member",
24503
- `@${annotation2.name}(member: ${target.key}) on '${member.name}' does not resolve on list entry class '${entryClass.name}'.`
24572
+ `@${annotation2.name}(member: ${target.key}) on '${member.name}' does not resolve on list entry class '${entryType.name}'.`
24504
24573
  );
24505
24574
  continue;
24506
24575
  }
24507
24576
  if (annotation2.name !== "index") continue;
24508
- const domainError = indexKeyDomainError(field, environment);
24577
+ const domainError = indexKeyDomainError(
24578
+ field.member,
24579
+ substituteSemanticType(semanticType(field.member.type), field.bindings),
24580
+ environment
24581
+ );
24509
24582
  if (domainError !== null) {
24510
24583
  pushDiagnostic(
24511
24584
  diagnostics,
@@ -24517,46 +24590,45 @@ function validateListAnnotations(uri, member, environment, diagnostics) {
24517
24590
  }
24518
24591
  }
24519
24592
  }
24520
- function memberKeyArgument(annotation2) {
24521
- const positional = annotation2.arguments[0];
24522
- const argument2 = annotation2.arguments.find((entry) => entry.name === "member") ?? (positional !== void 0 && positional.name === void 0 ? positional : void 0);
24523
- if (argument2 === void 0) return null;
24524
- const text = argument2.text.trim();
24525
- return {
24526
- key: IDENTIFIER_PATTERN.test(text) ? text : null,
24527
- range: argument2.range
24528
- };
24529
- }
24530
- function listEntryClass(type, environment) {
24593
+ function listEntryType(type, owner) {
24531
24594
  if (type.name !== "List" && type.name !== "Set") return null;
24532
- const entry = type.typeArguments[0];
24533
- if (entry === void 0) return null;
24534
- return environment.types.get(entry.name) ?? null;
24535
- }
24536
- function resolveEntryField(entryClass, key, environment) {
24595
+ let entry = type.typeArguments[0];
24537
24596
  const visited = /* @__PURE__ */ new Set();
24538
- let current = entryClass;
24539
- while (current !== void 0 && !visited.has(current.name)) {
24540
- visited.add(current.name);
24541
- const match = current.members.find((entry) => entry.name === key);
24542
- if (match !== void 0) return match;
24543
- current = current.baseTypes.map((base) => environment.types.get(base.name)).find((base) => base !== void 0);
24597
+ while (entry !== void 0) {
24598
+ const name = entry.name;
24599
+ const parameter4 = owner?.genericParameters.find(
24600
+ (candidate) => candidate.name === name
24601
+ );
24602
+ if (!parameter4) return semanticType(entry);
24603
+ if (visited.has(parameter4.name)) return null;
24604
+ visited.add(parameter4.name);
24605
+ entry = parameter4.constraint;
24544
24606
  }
24545
24607
  return null;
24546
24608
  }
24547
- function indexKeyDomainError(field, environment) {
24609
+ function sourceClassMemberForType(type, name, environment) {
24610
+ const declaration = environment.types.get(type.name);
24611
+ if (!declaration) return void 0;
24612
+ const bindings = /* @__PURE__ */ new Map();
24613
+ for (const [index, parameter4] of declaration.genericParameters.entries()) {
24614
+ const argument2 = type.arguments?.[index];
24615
+ if (argument2) bindings.set(parameter4.name, argument2);
24616
+ }
24617
+ return sourceClassMemberByName(declaration, name, environment, bindings);
24618
+ }
24619
+ function indexKeyDomainError(field, type, environment) {
24548
24620
  if (field.kind !== "field") {
24549
24621
  return `'${field.name}' is a ${field.kind}, and index keys require a stored field`;
24550
24622
  }
24551
- if (field.type.name === "string") {
24623
+ if (type.name === "string") {
24552
24624
  return annotationEnumOption(field.annotations, "settings", "format") === "Plain" ? null : `'${field.name}' is localized, and String index keys must be plain`;
24553
24625
  }
24554
- if (environment.enums.has(field.type.name)) return null;
24555
- const entry = field.type.typeArguments[0];
24556
- if (field.type.name === "List" && entry !== void 0 && environment.enums.has(entry.name) && annotationEnumOption(field.annotations, "settings", "selection") === "Multi") {
24626
+ if (environment.enums.has(type.name)) return null;
24627
+ const entry = type.arguments?.[0];
24628
+ if (type.name === "List" && entry !== void 0 && environment.enums.has(entry.name) && annotationEnumOption(field.annotations, "settings", "selection") === "Multi") {
24557
24629
  return `'${field.name}' is a multi-select Enum, and index keys require a single-select Enum`;
24558
24630
  }
24559
- return `'${field.name}' is a ${field.type.name} field, and index keys require a plain String or a single-select Enum`;
24631
+ return `'${field.name}' is a ${type.name} field, and index keys require a plain String or a single-select Enum`;
24560
24632
  }
24561
24633
  function annotationEnumOption(annotations, name, field) {
24562
24634
  const value = annotations.find((annotation2) => annotation2.name === name)?.arguments.find((argument2) => argument2.name === field)?.text.trim();
@@ -24711,10 +24783,11 @@ function classDerivesFromName(name, ancestorName, environment, seen = /* @__PURE
24711
24783
  return classDerivesFromName(base.name, ancestorName, environment, seen);
24712
24784
  });
24713
24785
  }
24714
- var NEO_VARIANT_FOLDER_SETTING, primitiveType, IDENTIFIER_PATTERN, LIST_COLUMN_INHERITANCE_KEY, SEMANTIC_PRIMITIVE_TYPE_NAMES;
24786
+ var NEO_VARIANT_FOLDER_SETTING, primitiveType, LIST_COLUMN_INHERITANCE_KEY, SEMANTIC_PRIMITIVE_TYPE_NAMES;
24715
24787
  var init_project_source_semantics = __esm({
24716
24788
  "../packages/neoscript-language/src/project-source-semantics.ts"() {
24717
24789
  "use strict";
24790
+ init_project_source_ast();
24718
24791
  init_project_local_values();
24719
24792
  init_language_spec();
24720
24793
  init_project_schema_contract_generated();
@@ -24727,7 +24800,6 @@ var init_project_source_semantics = __esm({
24727
24800
  init_project_root();
24728
24801
  NEO_VARIANT_FOLDER_SETTING = "folder";
24729
24802
  primitiveType = (name) => ({ name });
24730
- IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
24731
24803
  LIST_COLUMN_INHERITANCE_KEY = "__other__";
24732
24804
  SEMANTIC_PRIMITIVE_TYPE_NAMES = /* @__PURE__ */ new Set([
24733
24805
  "bool",
@@ -25326,8 +25398,29 @@ function buildProjectGraph(documents) {
25326
25398
  writable: false
25327
25399
  });
25328
25400
  }
25401
+ const listIndexes2 = [];
25402
+ for (const { member, symbol, uri } of memberInfo.values()) {
25403
+ if (symbol.type.kind !== "list") continue;
25404
+ const entryType = symbol.type.elementType;
25405
+ const entrySchema = neoScriptMemberLookupType(entryType);
25406
+ if (entrySchema.kind !== "named") continue;
25407
+ const entryMembers = effectiveMembers.get(entrySchema.typeId);
25408
+ for (const index of sourceListIndexAnnotations(member.annotations)) {
25409
+ const key = entryMembers?.find((field) => field.name === index.key);
25410
+ if (key === void 0) continue;
25411
+ listIndexes2.push({
25412
+ id: `${symbol.id}:index:${key.name}`,
25413
+ listMemberId: symbol.id,
25414
+ name: key.name,
25415
+ keyType: key.type,
25416
+ valueType: entryType,
25417
+ unique: index.unique,
25418
+ location: location(uri, index.annotation.range)
25419
+ });
25420
+ }
25421
+ }
25329
25422
  return {
25330
- project: { version: 1, types, globals, roots },
25423
+ project: { version: 1, types, globals, roots, listIndexes: listIndexes2 },
25331
25424
  declarationsByName,
25332
25425
  typeIdsByName: typeIds,
25333
25426
  memberInfo
@@ -25338,7 +25431,8 @@ function sourceMemberSymbol(member, owner, typeIds, source) {
25338
25431
  member.annotations,
25339
25432
  `member:${owner.id}:${member.name}`
25340
25433
  );
25341
- const type = sourceTypeRef(member.type, owner, typeIds);
25434
+ const declaredType = sourceTypeRef(member.type, owner, typeIds);
25435
+ const type = declaredType.kind === "list" ? { ...declaredType, listMemberId: id2 } : declaredType;
25342
25436
  const staticMember = member.modifiers.includes("static");
25343
25437
  const readonlyDeclaration = member.modifiers.includes("readonly");
25344
25438
  const common = {
@@ -31783,9 +31877,9 @@ function assertDialogue(value, path) {
31783
31877
  (entry, index) => assertMember(entry, `${path}.functions[${index}]`)
31784
31878
  );
31785
31879
  array(dialogue.members, `${path}.members`).forEach((entry, index) => {
31786
- const memberPath2 = `${path}.members[${index}]`;
31787
- const member = record(entry, memberPath2);
31788
- exactKeys(member, memberPath2, [
31880
+ const memberPath3 = `${path}.members[${index}]`;
31881
+ const member = record(entry, memberPath3);
31882
+ exactKeys(member, memberPath3, [
31789
31883
  "id",
31790
31884
  "state",
31791
31885
  "source",
@@ -31796,16 +31890,16 @@ function assertDialogue(value, path) {
31796
31890
  "arguments",
31797
31891
  "content"
31798
31892
  ]);
31799
- assertIdentity(member, memberPath2);
31800
- string(member.name, `${memberPath2}.name`);
31801
- string(member.graphType, `${memberPath2}.graphType`);
31893
+ assertIdentity(member, memberPath3);
31894
+ string(member.name, `${memberPath3}.name`);
31895
+ string(member.graphType, `${memberPath3}.graphType`);
31802
31896
  if (member.destination !== null) {
31803
- string(member.destination, `${memberPath2}.destination`);
31897
+ string(member.destination, `${memberPath3}.destination`);
31804
31898
  }
31805
- string(member.initializer, `${memberPath2}.initializer`);
31806
- assertFlowArguments(member.arguments, `${memberPath2}.arguments`);
31899
+ string(member.initializer, `${memberPath3}.initializer`);
31900
+ assertFlowArguments(member.arguments, `${memberPath3}.arguments`);
31807
31901
  if (member.content !== null) {
31808
- assertDialogueContent(member.content, `${memberPath2}.content`);
31902
+ assertDialogueContent(member.content, `${memberPath3}.content`);
31809
31903
  }
31810
31904
  });
31811
31905
  }
@@ -34796,6 +34890,111 @@ var init_src = __esm({
34796
34890
  }
34797
34891
  });
34798
34892
 
34893
+ // src/project-source/lower-support.ts
34894
+ function identityMap(declarations, kind) {
34895
+ return new Map(
34896
+ declarations.map((declaration) => [
34897
+ declaration.name,
34898
+ materializedId(declaration, kind, declaration.name)
34899
+ ])
34900
+ );
34901
+ }
34902
+ function sourceIdentity2(identity2, kind, name) {
34903
+ const sourceSpan = span(identity2);
34904
+ return {
34905
+ symbolId: `${kind}:${materializedIdentityId(identity2, kind, name)}`,
34906
+ kind,
34907
+ span: sourceSpan,
34908
+ selectionSpan: sourceSpan
34909
+ };
34910
+ }
34911
+ function span(identity2) {
34912
+ return {
34913
+ path: identity2.source.uri,
34914
+ start: { ...identity2.source.range.start },
34915
+ end: { ...identity2.source.range.end }
34916
+ };
34917
+ }
34918
+ function materializedId(identity2, kind, name) {
34919
+ return materializedIdentityId(identity2, kind, name);
34920
+ }
34921
+ function materializedIdentityId(identity2, kind, name) {
34922
+ return identity2.id ?? `__pending__:${kind}:${encodeURIComponent(identity2.source.uri)}:${identity2.source.range.start.line}:${identity2.source.range.start.character}:${encodeURIComponent(name)}`;
34923
+ }
34924
+ function expressionArguments(expression) {
34925
+ const result = /* @__PURE__ */ new Map();
34926
+ expression.args.forEach((entry, index) => {
34927
+ const name = expression.argumentNames?.[index] ?? null;
34928
+ if (name === null) {
34929
+ throw new Error(
34930
+ "Project configuration constructors require named arguments."
34931
+ );
34932
+ }
34933
+ if (result.has(name)) {
34934
+ throw new Error(
34935
+ `Constructor argument ${JSON.stringify(name)} is duplicated.`
34936
+ );
34937
+ }
34938
+ result.set(name, entry);
34939
+ });
34940
+ return result;
34941
+ }
34942
+ function annotation(annotations, name) {
34943
+ return annotations.find((entry) => entry.name === name);
34944
+ }
34945
+ function argument(value, name) {
34946
+ return value?.arguments.find((entry) => entry.name === name)?.expression ?? null;
34947
+ }
34948
+ function parseAnnotationExpression(value) {
34949
+ return parseExpression(value);
34950
+ }
34951
+ function stringArgument(value, name) {
34952
+ const raw = argument(value, name);
34953
+ if (raw === null) return null;
34954
+ const expression = parseAnnotationExpression(raw);
34955
+ return expression.kind === "litString" ? expression.value : null;
34956
+ }
34957
+ function contextualEnumArgument(value, name) {
34958
+ const raw = argument(value, name);
34959
+ if (raw === null) return null;
34960
+ const expression = parseAnnotationExpression(raw);
34961
+ return expression.kind === "contextualEnum" ? expression.name : null;
34962
+ }
34963
+ function systemMetadata(annotations) {
34964
+ const system = annotation(annotations, "system");
34965
+ if (!system) return null;
34966
+ const kind = contextualEnumArgument(system, "kind");
34967
+ if (kind === null) {
34968
+ throw new Error("@system requires a kind inferred enum argument.");
34969
+ }
34970
+ const worldKind = contextualEnumArgument(system, "worldKind");
34971
+ return {
34972
+ kind: lowerFirst2(kind),
34973
+ worldKind: worldKind ? lowerFirst2(worldKind) : null
34974
+ };
34975
+ }
34976
+ function requiredName(values, name, kind) {
34977
+ const value = values.get(name);
34978
+ if (!value) throw new Error(`Unknown ${kind} ${JSON.stringify(name)}.`);
34979
+ return value;
34980
+ }
34981
+ function lowerFirst2(value) {
34982
+ return value.length ? `${value[0].toLowerCase()}${value.slice(1)}` : value;
34983
+ }
34984
+ function indexFirstById(values) {
34985
+ const result = /* @__PURE__ */ new Map();
34986
+ for (const value of values) {
34987
+ if (!result.has(value.id)) result.set(value.id, value);
34988
+ }
34989
+ return result;
34990
+ }
34991
+ var init_lower_support = __esm({
34992
+ "src/project-source/lower-support.ts"() {
34993
+ "use strict";
34994
+ init_src();
34995
+ }
34996
+ });
34997
+
34799
34998
  // src/project-source/local-values.ts
34800
34999
  function validateLocalValuePlacementsV4(value) {
34801
35000
  if (!Array.isArray(value))
@@ -34870,6 +35069,23 @@ function validateLocalValuePlacementsV4(value) {
34870
35069
  for (const entry of active) visited.add(entry);
34871
35070
  }
34872
35071
  }
35072
+ function* staticMembersInitializedByName(analysis) {
35073
+ for (const sourceClass of analysis.schema.classes) {
35074
+ for (const declaration of sourceClass.members) {
35075
+ if (!declaration.modifiers.includes("static")) continue;
35076
+ if (declaration.kind !== "field" || declaration.initializer === null)
35077
+ continue;
35078
+ const name = declaration.initializer.trim();
35079
+ if (!/^[A-Za-z_]\w*$/u.test(name)) continue;
35080
+ const path = `${sourceClass.name}.${declaration.name}`;
35081
+ yield {
35082
+ name,
35083
+ memberId: materializedId(declaration, "member", path),
35084
+ path
35085
+ };
35086
+ }
35087
+ }
35088
+ }
34873
35089
  function typeText2(type) {
34874
35090
  return type.name + (type.arguments.length === 0 ? "" : `<${type.arguments.map(typeText2).join(", ")}>`) + (type.nullable ? "?" : "");
34875
35091
  }
@@ -34879,12 +35095,15 @@ var init_local_values = __esm({
34879
35095
  "use strict";
34880
35096
  init_workspace_source_path();
34881
35097
  init_src();
35098
+ init_lower_support();
34882
35099
  LocalValueBindingsV4 = class {
34883
35100
  definitions = /* @__PURE__ */ new Map();
34884
35101
  expressions = /* @__PURE__ */ new Map();
34885
35102
  owners = /* @__PURE__ */ new Map();
35103
+ /** Static members whose initializer is a bare local name, by that name. */
35104
+ ownerMembers = /* @__PURE__ */ new Map();
34886
35105
  scalarTypes;
34887
- constructor(globals, enumNames = []) {
35106
+ constructor(globals, enumNames = [], ownerMembers = []) {
34888
35107
  const scalarTypes = /* @__PURE__ */ new Set(["string", "int", "float", "decimal", "bool"]);
34889
35108
  for (const name of enumNames) scalarTypes.add(name);
34890
35109
  this.scalarTypes = scalarTypes;
@@ -34893,6 +35112,12 @@ var init_local_values = __esm({
34893
35112
  throw new Error(`Duplicate local value ${global.name}.`);
34894
35113
  this.definitions.set(global.name, global);
34895
35114
  }
35115
+ for (const owner of ownerMembers) {
35116
+ if (!this.definitions.has(owner.name)) continue;
35117
+ const members = this.ownerMembers.get(owner.name) ?? [];
35118
+ members.push({ memberId: owner.memberId, path: owner.path });
35119
+ this.ownerMembers.set(owner.name, members);
35120
+ }
34896
35121
  }
34897
35122
  resolve(expression, source, valueId) {
34898
35123
  if (expression.kind !== "ident") return { expression, source };
@@ -34931,6 +35156,44 @@ var init_local_values = __esm({
34931
35156
  has(name) {
34932
35157
  return this.definitions.has(name);
34933
35158
  }
35159
+ /**
35160
+ * The row a local names, answered without its owning assignment having
35161
+ * lowered, so the answer does not depend on which file lowered first: the
35162
+ * `@id` its declaration carries (through any alias chain), else the static
35163
+ * member whose initializer is the local, whose row derives from the member.
35164
+ * `null` for a local no push has identified yet.
35165
+ */
35166
+ declaredTarget(name) {
35167
+ const definition2 = this.definitions.get(name);
35168
+ if (definition2 === void 0) return null;
35169
+ const chain = /* @__PURE__ */ new Set();
35170
+ let global = definition2;
35171
+ let expression;
35172
+ for (; ; ) {
35173
+ if (chain.has(global.name))
35174
+ throw new Error(`Local initializer cycle reaches ${global.name}.`);
35175
+ chain.add(global.name);
35176
+ expression = this.expressions.get(global.name) ?? parseExpression(global.initializer);
35177
+ this.expressions.set(global.name, expression);
35178
+ const alias = expression.kind === "ident" ? this.definitions.get(expression.name) : void 0;
35179
+ if (alias === void 0) break;
35180
+ global = alias;
35181
+ }
35182
+ const typeName = definition2.type.name;
35183
+ const id2 = expression.kind === "annotated" ? expression.annotations.find((entry) => entry.name === "id")?.args[0] : void 0;
35184
+ if (id2 !== void 0 && id2.kind === "litString" && id2.value.length > 0) {
35185
+ return { id: id2.value, typeName };
35186
+ }
35187
+ const owners = this.ownerMembers.get(name);
35188
+ if (owners === void 0) return null;
35189
+ if (owners.length !== 1) {
35190
+ throw new Error(
35191
+ `Reference(${name}) requires exactly one owning assignment.`
35192
+ );
35193
+ }
35194
+ const owner = owners[0];
35195
+ return { ownerMemberId: owner.memberId, ownerPath: owner.path, typeName };
35196
+ }
34934
35197
  target(name) {
34935
35198
  const owners = this.owners.get(name);
34936
35199
  if (owners?.size !== 1)
@@ -59609,7 +59872,7 @@ function emitSupplementalProjectSourcesV4(records2, binaryPaths) {
59609
59872
  (candidate) => candidate.recordKind === "priority-group"
59610
59873
  )) {
59611
59874
  const data = recordData(record6);
59612
- const name = requiredName(data, record6);
59875
+ const name = requiredName2(data, record6);
59613
59876
  files.push({
59614
59877
  path: defaultDeclarationPathV4("PriorityGroups", name, record6.recordId),
59615
59878
  content: emitPriorityGroup(data, record6.recordId, name),
@@ -59620,7 +59883,7 @@ function emitSupplementalProjectSourcesV4(records2, binaryPaths) {
59620
59883
  (candidate) => candidate.recordKind === "dialogue-group"
59621
59884
  )) {
59622
59885
  const data = recordData(record6);
59623
- const name = requiredName(data, record6);
59886
+ const name = requiredName2(data, record6);
59624
59887
  files.push({
59625
59888
  path: defaultDeclarationPathV4("DialogueGroups", name, record6.recordId),
59626
59889
  content: emitDialogueGroup(
@@ -60380,7 +60643,7 @@ function recordData(record6) {
60380
60643
  }
60381
60644
  return record6.data;
60382
60645
  }
60383
- function requiredName(data, record6) {
60646
+ function requiredName2(data, record6) {
60384
60647
  if (typeof data.name !== "string") {
60385
60648
  throw new Error(`${record6.recordKind}:${record6.recordId} has no name.`);
60386
60649
  }
@@ -60391,7 +60654,7 @@ function namesById(records2, kind) {
60391
60654
  return new Map(
60392
60655
  records2.filter((record6) => record6.recordKind === kind).map((record6) => [
60393
60656
  record6.recordId,
60394
- requiredName(recordData(record6), record6)
60657
+ requiredName2(recordData(record6), record6)
60395
60658
  ])
60396
60659
  );
60397
60660
  }
@@ -60512,9 +60775,9 @@ function lowerSystemMetadata(annotations) {
60512
60775
  throw new Error("@system worldKind must be an inferred enum or null.");
60513
60776
  }
60514
60777
  return {
60515
- kind: lowerFirst2(kindExpression.name),
60778
+ kind: lowerFirst3(kindExpression.name),
60516
60779
  ...worldKindExpression === void 0 ? {} : {
60517
- worldKind: worldKindExpression.kind === "contextualEnum" ? lowerFirst2(worldKindExpression.name) : null
60780
+ worldKind: worldKindExpression.kind === "contextualEnum" ? lowerFirst3(worldKindExpression.name) : null
60518
60781
  }
60519
60782
  };
60520
60783
  }
@@ -60524,7 +60787,7 @@ function hasAnnotation(annotations, name) {
60524
60787
  function enumCase2(value) {
60525
60788
  return value.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join("");
60526
60789
  }
60527
- function lowerFirst2(value) {
60790
+ function lowerFirst3(value) {
60528
60791
  return `${value[0]?.toLowerCase() ?? ""}${value.slice(1)}`;
60529
60792
  }
60530
60793
  function assertProjectIdentifier2(value, kind) {
@@ -71125,6 +71388,33 @@ function exportInitializerCollections(created, writes, ctx) {
71125
71388
  });
71126
71389
  return [...exported, ...extra];
71127
71390
  }
71391
+ function prepareSessionValueExport(ctx, checkpoint, writes) {
71392
+ const created = createdSessionValuesSince(ctx, checkpoint);
71393
+ if (created.length === 0) return;
71394
+ const invocationWrites = ctx.__executionState?.writes ?? writes;
71395
+ const exported = exportInitializerCollections(
71396
+ created,
71397
+ invocationWrites === writes || writes.length === 0 ? invocationWrites : [...invocationWrites, ...writes],
71398
+ ctx
71399
+ );
71400
+ if (exported === created) return;
71401
+ const replacements = /* @__PURE__ */ new Map();
71402
+ for (const row of exported) {
71403
+ const existing = ctx.__runtimeSessionValues?.get(row.id);
71404
+ if (existing === void 0) registerRuntimeSessionValue(ctx, row);
71405
+ else if (existing !== row) replacements.set(row.id, row);
71406
+ }
71407
+ return replacements;
71408
+ }
71409
+ function exportedSessionValuesSince(ctx, checkpoint, replacements) {
71410
+ const created = createdSessionValuesSince(ctx, checkpoint);
71411
+ if (replacements !== void 0) {
71412
+ for (const [index, row] of created.entries()) {
71413
+ created[index] = replacements.get(row.id) ?? row;
71414
+ }
71415
+ }
71416
+ return created;
71417
+ }
71128
71418
  function evaluateNSGetter(getter, ctx) {
71129
71419
  return evaluateNSGetterWithEffects(getter, ctx).value;
71130
71420
  }
@@ -71189,19 +71479,20 @@ function evaluateNSGetterWithEffects(getter, ctx, argumentValues = [], options =
71189
71479
  const rootIndex = created.findIndex(
71190
71480
  (row) => row.value === result.value
71191
71481
  );
71192
- const exported = exportInitializerCollections(
71482
+ const exported2 = exportInitializerCollections(
71193
71483
  created,
71194
71484
  writes,
71195
71485
  runtimeCtx
71196
71486
  );
71197
- if (exported !== created) {
71198
- for (const row of exported)
71487
+ if (exported2 !== created) {
71488
+ for (const row of exported2)
71199
71489
  registerRuntimeSessionValue(runtimeCtx, row);
71200
71490
  invalidateEvaluatorIndexes(runtimeCtx, null);
71201
71491
  }
71202
- const exportedRoot = exported[rootIndex];
71492
+ const exportedRoot = exported2[rootIndex];
71203
71493
  if (exportedRoot !== void 0) result.value = exportedRoot.value;
71204
71494
  }
71495
+ const exported = !options.exportInitializerValues && options.sessionValueExport !== "defer" ? prepareSessionValueExport(runtimeCtx, creationCheckpoint, writes) : void 0;
71205
71496
  finalizeConstructorAllocations(
71206
71497
  runtimeCtx,
71207
71498
  result.value,
@@ -71209,9 +71500,10 @@ function evaluateNSGetterWithEffects(getter, ctx, argumentValues = [], options =
71209
71500
  getter.typeInfo
71210
71501
  );
71211
71502
  result.value = preserveReadOnlyReturnIdentity(result.value, runtimeCtx);
71212
- const createdSessionValues = createdSessionValuesSince(
71503
+ const createdSessionValues = exportedSessionValuesSince(
71213
71504
  runtimeCtx,
71214
- creationCheckpoint
71505
+ creationCheckpoint,
71506
+ exported
71215
71507
  );
71216
71508
  return createdSessionValues.length === 0 ? { value: result.value, writes } : { value: result.value, writes, createdSessionValues };
71217
71509
  }
@@ -71230,6 +71522,7 @@ function evaluateNSVoidBody(action, ctx) {
71230
71522
  consumeBudget(runtimeCtx, "workUnits", 1, "work unit");
71231
71523
  const creationCheckpoint = sessionCreationCheckpoint(runtimeCtx);
71232
71524
  const scope = createTopLevelScope(runtimeCtx);
71525
+ let exported;
71233
71526
  try {
71234
71527
  const result = evalInstructions(action.instructions, scope, runtimeCtx, {
71235
71528
  allowFallthroughReturn: true,
@@ -71243,14 +71536,20 @@ function evaluateNSVoidBody(action, ctx) {
71243
71536
  }
71244
71537
  }
71245
71538
  rejectEscapedLoopTransfer(result, "NeoScript action");
71539
+ exported = prepareSessionValueExport(
71540
+ runtimeCtx,
71541
+ creationCheckpoint,
71542
+ writes
71543
+ );
71246
71544
  finalizeConstructorAllocations(runtimeCtx, void 0, ownsInvocationState);
71247
71545
  } catch (error) {
71248
71546
  finalizeConstructorAllocations(runtimeCtx, void 0, ownsInvocationState);
71249
71547
  throw error;
71250
71548
  }
71251
- const createdSessionValues = createdSessionValuesSince(
71549
+ const createdSessionValues = exportedSessionValuesSince(
71252
71550
  runtimeCtx,
71253
- creationCheckpoint
71551
+ creationCheckpoint,
71552
+ exported
71254
71553
  );
71255
71554
  return createdSessionValues.length === 0 ? { writes } : { writes, createdSessionValues };
71256
71555
  }
@@ -71262,6 +71561,7 @@ function evaluateNSFunction(action, ctx, args) {
71262
71561
  const creationCheckpoint = sessionCreationCheckpoint(runtimeCtx);
71263
71562
  const runtimeArgs = remapRuntimeArguments(args, runtimeCtx);
71264
71563
  let value;
71564
+ let exported;
71265
71565
  try {
71266
71566
  value = executeCompiledFunction(
71267
71567
  action,
@@ -71269,6 +71569,11 @@ function evaluateNSFunction(action, ctx, args) {
71269
71569
  runtimeArgs,
71270
71570
  action.typeInfo.type === 0 /* Null */
71271
71571
  );
71572
+ exported = prepareSessionValueExport(
71573
+ runtimeCtx,
71574
+ creationCheckpoint,
71575
+ writes
71576
+ );
71272
71577
  finalizeConstructorAllocations(
71273
71578
  runtimeCtx,
71274
71579
  value,
@@ -71279,9 +71584,10 @@ function evaluateNSFunction(action, ctx, args) {
71279
71584
  finalizeConstructorAllocations(runtimeCtx, void 0, ownsInvocationState);
71280
71585
  throw error;
71281
71586
  }
71282
- const createdSessionValues = createdSessionValuesSince(
71587
+ const createdSessionValues = exportedSessionValuesSince(
71283
71588
  runtimeCtx,
71284
- creationCheckpoint
71589
+ creationCheckpoint,
71590
+ exported
71285
71591
  );
71286
71592
  return createdSessionValues.length === 0 ? { value, writes } : { value, writes, createdSessionValues };
71287
71593
  }
@@ -74517,10 +74823,15 @@ function dispatchNSGetterById(memberId, receiver, ctx) {
74517
74823
  }
74518
74824
  const innerStack = new Set(stack);
74519
74825
  innerStack.add(memberId);
74520
- return evaluateNSGetter(getter, {
74521
- ...bindThisValue(ctx, receiver),
74522
- __getterCallStack: innerStack
74523
- });
74826
+ return evaluateNSGetterWithEffects(
74827
+ getter,
74828
+ {
74829
+ ...bindThisValue(ctx, receiver),
74830
+ __getterCallStack: innerStack
74831
+ },
74832
+ [],
74833
+ { sessionValueExport: "defer" }
74834
+ ).value;
74524
74835
  }
74525
74836
  function resolveCompiledGetter(memberId, ctx) {
74526
74837
  const cache = evaluatorResolutionCache(ctx).compiledGetterByMemberId;
@@ -77846,7 +78157,10 @@ function evaluateInitializerInContext(init, member, ctx, createdValues, argument
77846
78157
  compiled,
77847
78158
  initializerCtx,
77848
78159
  argumentValues,
77849
- { initializerResult: { member, genericEnv } }
78160
+ {
78161
+ initializerResult: { member, genericEnv },
78162
+ sessionValueExport: "defer"
78163
+ }
77850
78164
  );
77851
78165
  } finally {
77852
78166
  closeFrame();
@@ -79784,15 +80098,22 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
79784
80098
  }
79785
80099
  const active = /* @__PURE__ */ new Set();
79786
80100
  const clonedBySourceId = /* @__PURE__ */ new Map();
79787
- const constructorArgumentReferenceCounts = /* @__PURE__ */ new Map();
79788
80101
  ctx.onUnattributableValueRead?.(`class-clone:${sourceId3}`);
79789
- for (const candidate of evaluatorValues(ctx)) {
79790
- for (const argument2 of ownedConstructorArgumentValues(candidate, ctx)) {
79791
- constructorArgumentReferenceCounts.set(
79792
- argument2.id,
79793
- (constructorArgumentReferenceCounts.get(argument2.id) ?? 0) + 1
79794
- );
80102
+ const constructorArgumentCandidates = evaluatorValues(ctx);
80103
+ let constructorArgumentReferenceCounts = null;
80104
+ function constructorArgumentReferenceCount(valueId) {
80105
+ if (constructorArgumentReferenceCounts === null) {
80106
+ constructorArgumentReferenceCounts = /* @__PURE__ */ new Map();
80107
+ for (const candidate of constructorArgumentCandidates) {
80108
+ for (const argument2 of ownedConstructorArgumentValues(candidate, ctx)) {
80109
+ constructorArgumentReferenceCounts.set(
80110
+ argument2.id,
80111
+ (constructorArgumentReferenceCounts.get(argument2.id) ?? 0) + 1
80112
+ );
80113
+ }
80114
+ }
79795
80115
  }
80116
+ return constructorArgumentReferenceCounts.get(valueId) ?? 0;
79796
80117
  }
79797
80118
  function cloneInitializerRow(sourceRow, sourceMember, id2, clonedContainerId, sourceTypeInfo) {
79798
80119
  if (sourceMember === null) {
@@ -79985,7 +80306,6 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
79985
80306
  constructorArgs[argument2.parameterId] = alreadyCloned.id;
79986
80307
  continue;
79987
80308
  }
79988
- if (constructorArgumentReferenceCounts.get(argument2.id) !== 1) continue;
79989
80309
  const argumentRow = evalValueById(
79990
80310
  ctx,
79991
80311
  argument2.id,
@@ -79996,6 +80316,7 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
79996
80316
  if (activeStaticBindingRoot(argument2.id, ctx) !== null || memberForValueRow(argumentRow, ctx) !== null) {
79997
80317
  continue;
79998
80318
  }
80319
+ if (constructorArgumentReferenceCount(argument2.id) !== 1) continue;
79999
80320
  constructorArgs[argument2.parameterId] = cloneRow2(
80000
80321
  argumentRow,
80001
80322
  null,
@@ -82937,7 +83258,7 @@ function rewriteExpandedRow(node, expansion) {
82937
83258
  const rewrite = (id2) => expansion.nodesByExpandedId.get(id2)?.virtualId ?? id2;
82938
83259
  const row = cloneRow(node.expandedRow);
82939
83260
  row.id = node.virtualId;
82940
- if (isMemberClassBase(node.member) || isMemberDictionaryBase(node.member)) {
83261
+ if (row.value !== null && (isMemberClassBase(node.member) || isMemberDictionaryBase(node.member))) {
82941
83262
  row.value = Object.fromEntries(
82942
83263
  Object.entries(stringRecord2(row.value)).map(([key, childId]) => [
82943
83264
  key,
@@ -96056,176 +96377,6 @@ function orderLocalizedTextWritesBesideLinks(prepared) {
96056
96377
  });
96057
96378
  return ordered;
96058
96379
  }
96059
- function planProjectVersionTransaction(changes, atomicGroups, options = {}) {
96060
- if (changes.length === 0) {
96061
- throw new Error("A project-version transaction plan requires changes.");
96062
- }
96063
- if (options.basePayloadBytes !== void 0 && options.basePayloadBytes.length !== changes.length)
96064
- throw new Error("Transaction base payload sizes must cover every change.");
96065
- const changeCosts = changes.map(
96066
- (change, index) => estimateProjectVersionChangeCost(change, options.basePayloadBytes?.[index])
96067
- );
96068
- const groups = normalizeAtomicGroups(changes.length, atomicGroups);
96069
- let totalEstimatedCost = changeCosts.reduce(
96070
- addProjectVersionTransactionBudgets,
96071
- IMMEDIATE_FIXED_COST
96072
- );
96073
- if (changes.some(projectVersionChangeCanTriggerWholeGraphValidation)) {
96074
- totalEstimatedCost = addProjectVersionTransactionBudgets(
96075
- totalEstimatedCost,
96076
- WHOLE_GRAPH_VALIDATION_SURCHARGE
96077
- );
96078
- }
96079
- const limitingResource = firstExceededResource(
96080
- totalEstimatedCost,
96081
- PROJECT_TRANSACTION_IMMEDIATE_BUDGET
96082
- );
96083
- if (limitingResource === null && options.forceAsync !== true) {
96084
- return {
96085
- path: "immediate",
96086
- limitingResource: null,
96087
- totalEstimatedCost,
96088
- chunks: [
96089
- {
96090
- firstChangeIndex: 0,
96091
- changeCount: changes.length,
96092
- estimatedCost: totalEstimatedCost
96093
- }
96094
- ]
96095
- };
96096
- }
96097
- const stagedChangeCosts = changes.map((change, index) => {
96098
- const cost = changeCosts[index];
96099
- const receiptBytes = 2 * KIB + new TextEncoder().encode(change.recordId).byteLength;
96100
- return addProjectVersionTransactionBudgets(cost, {
96101
- ...EMPTY_BUDGET,
96102
- bytesRead: receiptBytes,
96103
- bytesWritten: receiptBytes,
96104
- documentsRead: 1,
96105
- documentsWritten: 1,
96106
- databaseQueries: 1,
96107
- indexRanges: 1
96108
- });
96109
- });
96110
- const chunks = [];
96111
- let firstChangeIndex = 0;
96112
- let chunkCost = CHUNK_FIXED_COST;
96113
- let changeCount = 0;
96114
- for (const group of groups) {
96115
- const groupCost = stagedChangeCosts.slice(group.firstChangeIndex, group.firstChangeIndex + group.changeCount).reduce(addProjectVersionTransactionBudgets, EMPTY_BUDGET);
96116
- const nativeExceeded = firstExceededResource(
96117
- addProjectVersionTransactionBudgets(CHUNK_FIXED_COST, groupCost),
96118
- PROJECT_TRANSACTION_SINGLE_CHANGE_NATIVE_BUDGET
96119
- );
96120
- if (nativeExceeded !== null) {
96121
- throw new Error(
96122
- `Project-version atomic group starting at change ${group.firstChangeIndex} (${group.changeCount} changes) exceeds the native worker budget for ${nativeExceeded}.`
96123
- );
96124
- }
96125
- const nextCost = addProjectVersionTransactionBudgets(chunkCost, groupCost);
96126
- const exceeded = firstExceededResource(
96127
- nextCost,
96128
- PROJECT_TRANSACTION_WORKER_BUDGET
96129
- );
96130
- if (exceeded !== null && changeCount > 0) {
96131
- chunks.push({ firstChangeIndex, changeCount, estimatedCost: chunkCost });
96132
- firstChangeIndex = group.firstChangeIndex;
96133
- changeCount = 0;
96134
- chunkCost = CHUNK_FIXED_COST;
96135
- }
96136
- chunkCost = addProjectVersionTransactionBudgets(chunkCost, groupCost);
96137
- changeCount += group.changeCount;
96138
- }
96139
- if (changeCount > 0) {
96140
- chunks.push({ firstChangeIndex, changeCount, estimatedCost: chunkCost });
96141
- }
96142
- return {
96143
- path: "asynchronous",
96144
- limitingResource,
96145
- totalEstimatedCost,
96146
- chunks
96147
- };
96148
- }
96149
- function projectVersionChangeCanTriggerWholeGraphValidation(change) {
96150
- if (change.recordKind === "enum" || change.recordKind === "member" || change.recordKind === "project" || change.recordKind === "internal-record-relation") {
96151
- return true;
96152
- }
96153
- if (change.recordKind === "class") return change.operation !== "create";
96154
- if (change.recordKind !== "value") return false;
96155
- if (change.operation === "delete") return true;
96156
- return valueChangeCarriesWorldLayerOverride(change);
96157
- }
96158
- function valueChangeCarriesWorldLayerOverride(change) {
96159
- const nextData = change.nextData;
96160
- if (nextData === null || typeof nextData !== "object") return false;
96161
- if (Array.isArray(nextData)) return false;
96162
- const value = nextData.value;
96163
- if (value === null || typeof value !== "object") return false;
96164
- if (Array.isArray(value)) return false;
96165
- return typeof value.layerOverrideValueId === "string";
96166
- }
96167
- function normalizeAtomicGroups(changeCount, groups) {
96168
- if (groups === void 0) {
96169
- return Array.from({ length: changeCount }, (_, firstChangeIndex) => ({
96170
- firstChangeIndex,
96171
- changeCount: 1
96172
- }));
96173
- }
96174
- let nextChangeIndex = 0;
96175
- for (const group of groups) {
96176
- if (!Number.isSafeInteger(group.firstChangeIndex) || !Number.isSafeInteger(group.changeCount) || group.firstChangeIndex !== nextChangeIndex || group.changeCount < 1) {
96177
- throw new Error(
96178
- "Project-version atomic groups must be positive, ordered, and contiguous."
96179
- );
96180
- }
96181
- nextChangeIndex += group.changeCount;
96182
- }
96183
- if (nextChangeIndex !== changeCount) {
96184
- throw new Error(
96185
- `Project-version atomic groups cover ${nextChangeIndex}/${changeCount} changes.`
96186
- );
96187
- }
96188
- return [...groups];
96189
- }
96190
- function estimateProjectVersionChangeCost(change, basePayloadBytes) {
96191
- const encoded = canonicalJsonStringify(change);
96192
- const payloadBytes = new TextEncoder().encode(encoded).byteLength;
96193
- const hasBase = change.operation !== "create";
96194
- if (basePayloadBytes !== void 0 && (!Number.isSafeInteger(basePayloadBytes) || basePayloadBytes < 0))
96195
- throw new Error(
96196
- "Transaction base payload size must be a nonnegative byte count."
96197
- );
96198
- const baseBytes = hasBase ? basePayloadBytes ?? payloadBytes : 0;
96199
- const nextStoredBytes = change.operation === "delete" ? baseBytes : payloadBytes;
96200
- const counts = changeCountCost(change);
96201
- return {
96202
- argumentBytes: payloadBytes + 128,
96203
- bytesRead: payloadBytes + 2 * baseBytes + CHANGE_BYTES_READ_OVERHEAD,
96204
- // Live records appear in the snapshot, result data, result snapshot and diff.
96205
- bytesWritten: (change.operation === "delete" ? 2 * baseBytes + payloadBytes : 4 * nextStoredBytes) + CHANGE_BYTES_WRITTEN_OVERHEAD,
96206
- documentsRead: counts.documentsRead,
96207
- documentsWritten: counts.documentsWritten,
96208
- databaseQueries: counts.databaseQueries,
96209
- // Not metered by Convex: `TransactionMetrics` reports seven dimensions and
96210
- // this is not one of them, so it cannot be measured the way the others
96211
- // were. Every index range a change opens is also a database query, so the
96212
- // measured query count is a strict upper bound on it. Charging exactly
96213
- // that keeps the dimension a true bound instead of an invented number,
96214
- // and keeps it dominated by `databaseQueries` rather than silently
96215
- // becoming the binding constraint on a well-measured plan.
96216
- indexRanges: counts.databaseQueries,
96217
- functionsScheduled: 0,
96218
- scheduledFunctionArgsBytes: 0,
96219
- // Deleted result rows still carry the complete tombstone snapshot.
96220
- returnBytes: (change.operation === "delete" ? baseBytes : 2 * nextStoredBytes) + 512
96221
- };
96222
- }
96223
- function changeCountCost(change) {
96224
- if (change.recordKind === "value") {
96225
- return VALUE_CHANGE_COUNT_COSTS[change.operation];
96226
- }
96227
- return SCHEMA_CHANGE_COUNT_COSTS[change.operation];
96228
- }
96229
96380
  function addProjectVersionTransactionBudgets(left, right) {
96230
96381
  return {
96231
96382
  argumentBytes: left.argumentBytes + right.argumentBytes,
@@ -96240,15 +96391,7 @@ function addProjectVersionTransactionBudgets(left, right) {
96240
96391
  returnBytes: left.returnBytes + right.returnBytes
96241
96392
  };
96242
96393
  }
96243
- function firstExceededResource(cost, target) {
96244
- for (const resource of Object.keys(
96245
- EMPTY_BUDGET
96246
- )) {
96247
- if (cost[resource] > target[resource]) return resource;
96248
- }
96249
- return null;
96250
- }
96251
- var KIB, MIB, PROJECT_TRANSACTION_CHUNK_PAYLOAD_TARGET_BYTES, PROJECT_TRANSACTION_IMMEDIATE_BUDGET, PROJECT_TRANSACTION_WORKER_BUDGET, PROJECT_TRANSACTION_SINGLE_CHANGE_NATIVE_BUDGET, EMPTY_BUDGET, CHUNK_GRAPH_VALIDATION_RESERVE, CHUNK_FIXED_COST, IMMEDIATE_FIXED_COST, WHOLE_GRAPH_VALIDATION_SURCHARGE, VALUE_CHANGE_COUNT_COSTS, SCHEMA_CHANGE_COUNT_COSTS, CHANGE_BYTES_READ_OVERHEAD, CHANGE_BYTES_WRITTEN_OVERHEAD;
96394
+ var KIB, MIB, PROJECT_TRANSACTION_CHUNK_PAYLOAD_TARGET_BYTES, PROJECT_TRANSACTION_IMMEDIATE_BUDGET, PROJECT_TRANSACTION_WORKER_BUDGET, PROJECT_TRANSACTION_SINGLE_CHANGE_NATIVE_BUDGET, EMPTY_BUDGET, CHUNK_GRAPH_VALIDATION_RESERVE, CHUNK_FIXED_COST, IMMEDIATE_FIXED_COST, WHOLE_GRAPH_VALIDATION_SURCHARGE, CHANGE_BYTES_READ_OVERHEAD, CHANGE_BYTES_WRITTEN_OVERHEAD;
96252
96395
  var init_project_version_transaction_planning = __esm({
96253
96396
  "../src/database/project-version-transaction-planning.ts"() {
96254
96397
  "use strict";
@@ -96340,16 +96483,6 @@ var init_project_version_transaction_planning = __esm({
96340
96483
  databaseQueries: 410,
96341
96484
  indexRanges: 410
96342
96485
  };
96343
- VALUE_CHANGE_COUNT_COSTS = {
96344
- create: { documentsRead: 3, documentsWritten: 3, databaseQueries: 8 },
96345
- update: { documentsRead: 6, documentsWritten: 3, databaseQueries: 9 },
96346
- delete: { documentsRead: 6, documentsWritten: 3, databaseQueries: 14 }
96347
- };
96348
- SCHEMA_CHANGE_COUNT_COSTS = {
96349
- create: { documentsRead: 9, documentsWritten: 7, databaseQueries: 9 },
96350
- update: { documentsRead: 6, documentsWritten: 5, databaseQueries: 22 },
96351
- delete: { documentsRead: 6, documentsWritten: 5, databaseQueries: 22 }
96352
- };
96353
96486
  CHANGE_BYTES_READ_OVERHEAD = 4 * KIB;
96354
96487
  CHANGE_BYTES_WRITTEN_OVERHEAD = 4 * KIB;
96355
96488
  }
@@ -101603,12 +101736,12 @@ var init_animation_clips = __esm({
101603
101736
  * fix.
101604
101737
  */
101605
101738
  validateStructuredLeafPartial(args) {
101606
- const memberPath2 = args.path.join(".");
101739
+ const memberPath3 = args.path.join(".");
101607
101740
  const prefix = `Animation clip "${args.clipName}" frame ${args.frameIndex}`;
101608
101741
  const kind = args.member.kind;
101609
101742
  if (!isStructuredLeafKind(kind)) {
101610
101743
  throw new Error(
101611
- `${prefix} member "${memberPath2}" is of kind ${MemberKind[kind]}, which has no addressable fields, so it cannot take a "${STRUCTURED_LEAF_PARTIAL_KEY}" field override.`
101744
+ `${prefix} member "${memberPath3}" is of kind ${MemberKind[kind]}, which has no addressable fields, so it cannot take a "${STRUCTURED_LEAF_PARTIAL_KEY}" field override.`
101612
101745
  );
101613
101746
  }
101614
101747
  const kindLabel = MemberKind[kind];
@@ -101617,7 +101750,7 @@ var init_animation_clips = __esm({
101617
101750
  args.member.id
101618
101751
  ])) {
101619
101752
  throw new Error(
101620
- `${prefix} ${kindLabel} member "${memberPath2}" cannot take a "${STRUCTURED_LEAF_PARTIAL_KEY}" field override; member "${args.member.name}" is not a writable Save/Session override leaf.`
101753
+ `${prefix} ${kindLabel} member "${memberPath3}" cannot take a "${STRUCTURED_LEAF_PARTIAL_KEY}" field override; member "${args.member.name}" is not a writable Save/Session override leaf.`
101621
101754
  );
101622
101755
  }
101623
101756
  const violation = structuredLeafPartialViolation(
@@ -101626,14 +101759,14 @@ var init_animation_clips = __esm({
101626
101759
  kindLabel
101627
101760
  );
101628
101761
  if (violation !== null) {
101629
- throw new Error(`${prefix} member "${memberPath2}" ${violation}.`);
101762
+ throw new Error(`${prefix} member "${memberPath3}" ${violation}.`);
101630
101763
  }
101631
101764
  const resolution = this.resolveDefinitionChildResolution(
101632
101765
  args.definitionNode,
101633
101766
  args.schemaKey,
101634
101767
  args.member
101635
101768
  );
101636
- const descent = `${prefix} cannot descend into ${kindLabel} member "${memberPath2}"`;
101769
+ const descent = `${prefix} cannot descend into ${kindLabel} member "${memberPath3}"`;
101637
101770
  if (resolution.node === null) {
101638
101771
  if (resolution.absence.reason === "nullDefault") {
101639
101772
  throw new Error(
@@ -106922,111 +107055,6 @@ var init_value_record_comparison = __esm({
106922
107055
  }
106923
107056
  });
106924
107057
 
106925
- // src/project-source/lower-support.ts
106926
- function identityMap(declarations, kind) {
106927
- return new Map(
106928
- declarations.map((declaration) => [
106929
- declaration.name,
106930
- materializedId(declaration, kind, declaration.name)
106931
- ])
106932
- );
106933
- }
106934
- function sourceIdentity2(identity2, kind, name) {
106935
- const sourceSpan = span(identity2);
106936
- return {
106937
- symbolId: `${kind}:${materializedIdentityId(identity2, kind, name)}`,
106938
- kind,
106939
- span: sourceSpan,
106940
- selectionSpan: sourceSpan
106941
- };
106942
- }
106943
- function span(identity2) {
106944
- return {
106945
- path: identity2.source.uri,
106946
- start: { ...identity2.source.range.start },
106947
- end: { ...identity2.source.range.end }
106948
- };
106949
- }
106950
- function materializedId(identity2, kind, name) {
106951
- return materializedIdentityId(identity2, kind, name);
106952
- }
106953
- function materializedIdentityId(identity2, kind, name) {
106954
- return identity2.id ?? `__pending__:${kind}:${encodeURIComponent(identity2.source.uri)}:${identity2.source.range.start.line}:${identity2.source.range.start.character}:${encodeURIComponent(name)}`;
106955
- }
106956
- function expressionArguments(expression) {
106957
- const result = /* @__PURE__ */ new Map();
106958
- expression.args.forEach((entry, index) => {
106959
- const name = expression.argumentNames?.[index] ?? null;
106960
- if (name === null) {
106961
- throw new Error(
106962
- "Project configuration constructors require named arguments."
106963
- );
106964
- }
106965
- if (result.has(name)) {
106966
- throw new Error(
106967
- `Constructor argument ${JSON.stringify(name)} is duplicated.`
106968
- );
106969
- }
106970
- result.set(name, entry);
106971
- });
106972
- return result;
106973
- }
106974
- function annotation(annotations, name) {
106975
- return annotations.find((entry) => entry.name === name);
106976
- }
106977
- function argument(value, name) {
106978
- return value?.arguments.find((entry) => entry.name === name)?.expression ?? null;
106979
- }
106980
- function parseAnnotationExpression(value) {
106981
- return parseExpression(value);
106982
- }
106983
- function stringArgument(value, name) {
106984
- const raw = argument(value, name);
106985
- if (raw === null) return null;
106986
- const expression = parseAnnotationExpression(raw);
106987
- return expression.kind === "litString" ? expression.value : null;
106988
- }
106989
- function contextualEnumArgument(value, name) {
106990
- const raw = argument(value, name);
106991
- if (raw === null) return null;
106992
- const expression = parseAnnotationExpression(raw);
106993
- return expression.kind === "contextualEnum" ? expression.name : null;
106994
- }
106995
- function systemMetadata(annotations) {
106996
- const system = annotation(annotations, "system");
106997
- if (!system) return null;
106998
- const kind = contextualEnumArgument(system, "kind");
106999
- if (kind === null) {
107000
- throw new Error("@system requires a kind inferred enum argument.");
107001
- }
107002
- const worldKind = contextualEnumArgument(system, "worldKind");
107003
- return {
107004
- kind: lowerFirst3(kind),
107005
- worldKind: worldKind ? lowerFirst3(worldKind) : null
107006
- };
107007
- }
107008
- function requiredName2(values, name, kind) {
107009
- const value = values.get(name);
107010
- if (!value) throw new Error(`Unknown ${kind} ${JSON.stringify(name)}.`);
107011
- return value;
107012
- }
107013
- function lowerFirst3(value) {
107014
- return value.length ? `${value[0].toLowerCase()}${value.slice(1)}` : value;
107015
- }
107016
- function indexFirstById(values) {
107017
- const result = /* @__PURE__ */ new Map();
107018
- for (const value of values) {
107019
- if (!result.has(value.id)) result.set(value.id, value);
107020
- }
107021
- return result;
107022
- }
107023
- var init_lower_support = __esm({
107024
- "src/project-source/lower-support.ts"() {
107025
- "use strict";
107026
- init_src();
107027
- }
107028
- });
107029
-
107030
107058
  // src/project-source/lower-configuration.ts
107031
107059
  function lowerConfiguration(base, analysis) {
107032
107060
  const globals = analysis.configuration.globals;
@@ -107978,7 +108006,7 @@ function nullableStatusConstructorArgument(argumentsValue, name, fallback, statu
107978
108006
  }
107979
108007
  function resolveStatusExpression(expression, statusIdsByName) {
107980
108008
  if (expression.kind === "ident") {
107981
- return requiredName2(
108009
+ return requiredName(
107982
108010
  statusIdsByName,
107983
108011
  expression.name,
107984
108012
  "localization status"
@@ -108054,6 +108082,200 @@ var init_lower_configuration = __esm({
108054
108082
  }
108055
108083
  });
108056
108084
 
108085
+ // src/project-source/initializer-reference-spellings.ts
108086
+ function sourceOffsetAt(source, pos) {
108087
+ let offset = 0;
108088
+ for (let line = 1; line < pos.line; line += 1) {
108089
+ const next = source.indexOf("\n", offset);
108090
+ if (next < 0) return null;
108091
+ offset = next + 1;
108092
+ }
108093
+ return Math.min(offset + pos.column - 1, source.length);
108094
+ }
108095
+ function settleInitializerReferenceSpellings(code, settle) {
108096
+ const splices = [];
108097
+ const pending = [parseExpression(code)];
108098
+ while (pending.length > 0) {
108099
+ const node = pending.pop();
108100
+ switch (node.kind) {
108101
+ case "call": {
108102
+ const target = settle(node);
108103
+ if (target === null) {
108104
+ pending.push(node.callee, ...node.args);
108105
+ break;
108106
+ }
108107
+ const start = sourceOffsetAt(code, node.callee.pos);
108108
+ const end = start === null ? null : referenceCallEnd(code, start);
108109
+ if (start === null || end === null) break;
108110
+ splices.push({
108111
+ start,
108112
+ end,
108113
+ text: `Reference<${target.typeName}>(id: ${JSON.stringify(target.id)})`
108114
+ });
108115
+ break;
108116
+ }
108117
+ case "annotated":
108118
+ pending.push(node.expression);
108119
+ break;
108120
+ case "new":
108121
+ pending.push(...node.args);
108122
+ for (const entry of node.initializer ?? []) pending.push(entry.value);
108123
+ break;
108124
+ case "litList":
108125
+ pending.push(...node.elements);
108126
+ break;
108127
+ case "litDict":
108128
+ for (const entry of node.entries) pending.push(entry.value);
108129
+ break;
108130
+ case "member":
108131
+ pending.push(node.receiver);
108132
+ break;
108133
+ case "index":
108134
+ pending.push(node.receiver, node.index);
108135
+ break;
108136
+ case "binary":
108137
+ case "coalesce":
108138
+ pending.push(node.left, node.right);
108139
+ break;
108140
+ case "conditional":
108141
+ pending.push(node.condition, node.whenTrue, node.whenFalse);
108142
+ break;
108143
+ case "unary":
108144
+ case "force":
108145
+ case "is":
108146
+ pending.push(node.operand);
108147
+ break;
108148
+ }
108149
+ }
108150
+ if (splices.length === 0) return code;
108151
+ splices.sort((left, right) => right.start - left.start);
108152
+ let settled = code;
108153
+ for (const splice of splices) {
108154
+ settled = settled.slice(0, splice.start) + splice.text + settled.slice(splice.end);
108155
+ }
108156
+ return settled;
108157
+ }
108158
+ function referenceCallEnd(code, start) {
108159
+ const open = code.indexOf("(", start);
108160
+ if (open < 0) return null;
108161
+ let depth = 0;
108162
+ let quoted = null;
108163
+ for (let index = open; index < code.length; index += 1) {
108164
+ const character = code[index];
108165
+ if (quoted !== null) {
108166
+ if (character === "\\") index += 1;
108167
+ else if (character === quoted) quoted = null;
108168
+ continue;
108169
+ }
108170
+ if (character === '"' || character === "'") quoted = character;
108171
+ else if (character === "(") depth += 1;
108172
+ else if (character === ")") {
108173
+ depth -= 1;
108174
+ if (depth === 0) return index + 1;
108175
+ }
108176
+ }
108177
+ return null;
108178
+ }
108179
+ function memberValueIdV4(memberId) {
108180
+ return isPendingId(memberId) ? pendingMemberValueId(memberId) : derivedMemberValueId(memberId);
108181
+ }
108182
+ function referencedSymbolPath(call) {
108183
+ if (call.callee.kind !== "ident" || call.callee.name !== "Reference") {
108184
+ return null;
108185
+ }
108186
+ if ((call.typeArguments?.length ?? 0) > 1) return null;
108187
+ if (call.args.length !== 1) return null;
108188
+ if (typeof call.argumentNames?.[0] === "string") return null;
108189
+ const path = memberPath(call.args[0]);
108190
+ if (path === null) return null;
108191
+ const typeArgument = call.typeArguments?.[0];
108192
+ return {
108193
+ path,
108194
+ genericTypeName: typeArgument === void 0 ? null : astTypeNameV4(typeArgument)
108195
+ };
108196
+ }
108197
+ function memberPath(expression) {
108198
+ if (expression.kind === "ident") return expression.name;
108199
+ if (expression.kind !== "member") return null;
108200
+ const receiver = memberPath(expression.receiver);
108201
+ return receiver === null ? null : `${receiver}.${expression.name}`;
108202
+ }
108203
+ function unidentifiedLocalReferenceError(name) {
108204
+ return new Error(
108205
+ `Reference(${name}) inside a constructed initializer needs ${name} to carry an @id. Push the declaration of ${name} first, then reference it.`
108206
+ );
108207
+ }
108208
+ function createSchemaInitializerReferenceSettlerV4(args) {
108209
+ let sourceStatics = null;
108210
+ const readSourceStatics = () => {
108211
+ if (sourceStatics !== null) return sourceStatics;
108212
+ const statics = /* @__PURE__ */ new Map();
108213
+ for (const sourceClass of args.analysis.schema.classes) {
108214
+ for (const declaration of sourceClass.members) {
108215
+ if (!declaration.modifiers.includes("static")) continue;
108216
+ if (declaration.kind !== "field") continue;
108217
+ const path = `${sourceClass.name}.${declaration.name}`;
108218
+ statics.set(path, {
108219
+ memberId: materializedId(declaration, "member", path),
108220
+ typeName: declaration.type.name
108221
+ });
108222
+ }
108223
+ }
108224
+ sourceStatics = statics;
108225
+ return statics;
108226
+ };
108227
+ const staticValueId = (path, memberId) => args.staticValueIdsBySymbol.get(path) ?? memberValueIdV4(memberId);
108228
+ const settle = (call) => {
108229
+ const spelled = referencedSymbolPath(call);
108230
+ if (spelled === null) return null;
108231
+ if (args.localValues.has(spelled.path)) {
108232
+ const declared = args.localValues.declaredTarget(spelled.path);
108233
+ if (declared === null)
108234
+ throw unidentifiedLocalReferenceError(spelled.path);
108235
+ const typeName2 = spelled.genericTypeName ?? declared.typeName;
108236
+ if ("id" in declared) return { id: declared.id, typeName: typeName2 };
108237
+ return {
108238
+ id: staticValueId(declared.ownerPath, declared.ownerMemberId),
108239
+ typeName: typeName2
108240
+ };
108241
+ }
108242
+ const source = readSourceStatics().get(spelled.path);
108243
+ if (source !== void 0) {
108244
+ return {
108245
+ id: staticValueId(spelled.path, source.memberId),
108246
+ typeName: spelled.genericTypeName ?? source.typeName
108247
+ };
108248
+ }
108249
+ const stored = args.staticValueIdsBySymbol.get(spelled.path);
108250
+ if (stored === void 0) return null;
108251
+ const typeName = spelled.genericTypeName ?? storedStaticTypeName(args.manifest, spelled.path);
108252
+ return typeName === null ? null : { id: stored, typeName };
108253
+ };
108254
+ return (code) => settleInitializerReferenceSpellings(code, settle);
108255
+ }
108256
+ function storedStaticTypeName(manifest, path) {
108257
+ const separator = path.lastIndexOf(".");
108258
+ if (separator < 0) return null;
108259
+ const className = path.slice(0, separator);
108260
+ const memberName = path.slice(separator + 1);
108261
+ const schemaClass2 = manifest.classes.find(
108262
+ (entry) => entry.name === className
108263
+ );
108264
+ const memberId = schemaClass2?.schema[memberName];
108265
+ const member = manifest.members.find((entry) => entry.id === memberId);
108266
+ if (member?.kind !== "class") return null;
108267
+ return manifest.classes.find((entry) => entry.id === member.classId)?.name ?? null;
108268
+ }
108269
+ var init_initializer_reference_spellings = __esm({
108270
+ "src/project-source/initializer-reference-spellings.ts"() {
108271
+ "use strict";
108272
+ init_member_value_id();
108273
+ init_src();
108274
+ init_key_reference_spelling();
108275
+ init_lower_support();
108276
+ }
108277
+ });
108278
+
108057
108279
  // ../src/models/members/required-constructor-id.ts
108058
108280
  function derivedRequiredConstructorId(classId) {
108059
108281
  return inSystemRecordNamespaceOf(
@@ -108506,9 +108728,9 @@ function lowerClass(context, declaration) {
108506
108728
  if (classBases.length > 1) {
108507
108729
  throw new Error(`Class ${declaration.name} has more than one Class base.`);
108508
108730
  }
108509
- const extendsClassId = classBases[0] ? requiredName2(context.classIdsByName, classBases[0].name, "class") : null;
108731
+ const extendsClassId = classBases[0] ? requiredName(context.classIdsByName, classBases[0].name, "class") : null;
108510
108732
  const implementsInterfaceIds = declaration.baseTypes.filter((type) => context.interfaceIdsByName.has(type.name)).map(
108511
- (type) => requiredName2(context.interfaceIdsByName, type.name, "interface")
108733
+ (type) => requiredName(context.interfaceIdsByName, type.name, "interface")
108512
108734
  );
108513
108735
  const schema = {};
108514
108736
  const schemaKeyOrder = [];
@@ -109141,7 +109363,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
109141
109363
  entryMemberId: entryId,
109142
109364
  key: keyType.name === "string" ? { kind: "string" } : {
109143
109365
  kind: "enum",
109144
- enumId: requiredName2(context.enumIdsByName, keyType.name, "enum")
109366
+ enumId: requiredName(context.enumIdsByName, keyType.name, "enum")
109145
109367
  }
109146
109368
  };
109147
109369
  }
@@ -109201,7 +109423,7 @@ function inheritedMember(context, memberId) {
109201
109423
  function lowerListIndexes(ownerClass, declaration) {
109202
109424
  const declared = /* @__PURE__ */ new Set();
109203
109425
  return declaration.annotations.filter((entry) => entry.name === "index").map((entry) => {
109204
- const schemaKey = memberKeyArgument2(entry, ownerClass, declaration);
109426
+ const schemaKey = memberKeyArgument(entry, ownerClass, declaration);
109205
109427
  if (declared.has(schemaKey)) {
109206
109428
  throw new Error(
109207
109429
  `@index(member: ${schemaKey}) is declared more than once on ${ownerClass.name}.${declaration.name}.`
@@ -109217,7 +109439,7 @@ function lowerListIndexes(ownerClass, declaration) {
109217
109439
  function lowerListColumns(ownerClass, declaration) {
109218
109440
  const declared = /* @__PURE__ */ new Set();
109219
109441
  return declaration.annotations.filter((entry) => entry.name === "column").map((entry) => {
109220
- const memberKey = memberKeyArgument2(entry, ownerClass, declaration);
109442
+ const memberKey = memberKeyArgument(entry, ownerClass, declaration);
109221
109443
  if (declared.has(memberKey)) {
109222
109444
  throw new Error(
109223
109445
  `@column(member: ${memberKey}) is declared more than once on ${ownerClass.name}.${declaration.name}.`
@@ -109236,7 +109458,7 @@ function lowerListColumns(ownerClass, declaration) {
109236
109458
  };
109237
109459
  });
109238
109460
  }
109239
- function memberKeyArgument2(value, ownerClass, declaration) {
109461
+ function memberKeyArgument(value, ownerClass, declaration) {
109240
109462
  const positional = value.arguments[0];
109241
109463
  const raw = argument(value, "member") ?? (positional !== void 0 && positional.name === void 0 ? positional.expression : null);
109242
109464
  if (raw === null) {
@@ -109498,7 +109720,7 @@ function lowerInterface(context, declaration) {
109498
109720
  ...declaration.docsText === void 0 ? {} : { docsText: declaration.docsText },
109499
109721
  members,
109500
109722
  extendsInterfaceIds: declaration.baseTypes.map(
109501
- (type) => requiredName2(context.interfaceIdsByName, type.name, "interface")
109723
+ (type) => requiredName(context.interfaceIdsByName, type.name, "interface")
109502
109724
  ),
109503
109725
  system: systemMetadata(declaration.annotations) ?? base?.system ?? null
109504
109726
  };
@@ -109595,7 +109817,7 @@ function lowerType(context, type, ownerClass) {
109595
109817
  kind: "dictionary",
109596
109818
  nullable: nullable2,
109597
109819
  entryType: lowerType(context, requiredTypeArgument(type, 1), ownerClass),
109598
- keyEnumId: key.name === "string" ? null : requiredName2(context.enumIdsByName, key.name, "enum"),
109820
+ keyEnumId: key.name === "string" ? null : requiredName(context.enumIdsByName, key.name, "enum"),
109599
109821
  readOnly: false
109600
109822
  };
109601
109823
  }
@@ -109675,7 +109897,13 @@ function lowerDefault(context, initializer, type, ownerClass, base, memberId, st
109675
109897
  }
109676
109898
  const expression = parseExpression(initializer);
109677
109899
  if (positionRequiresEvaluation(context, expression, type, ownerClass)) {
109678
- return { init: { code: normalizeInitializerSource(initializer) } };
109900
+ return {
109901
+ init: {
109902
+ code: context.settleInitializerReferences(
109903
+ normalizeInitializerSource(initializer)
109904
+ )
109905
+ }
109906
+ };
109679
109907
  }
109680
109908
  if (context.rowBackedDefaultMemberIds.has(memberId) && base?.defaultValue && !("serverValueId" in base.defaultValue)) {
109681
109909
  return base.defaultValue;
@@ -110000,7 +110228,7 @@ function lowerExpressionValue(context, expression, declaredExpected, ownerClass,
110000
110228
  );
110001
110229
  }
110002
110230
  const className = explicitPartial ? expectedType.name : expression.className ?? expectedType.name;
110003
- const classId = requiredName2(context.classIdsByName, className, "class");
110231
+ const classId = requiredName(context.classIdsByName, className, "class");
110004
110232
  const innerEnvironment = constructedGenericEnvironment(
110005
110233
  context,
110006
110234
  classId,
@@ -110180,15 +110408,6 @@ function isStoredActionLiteral(type, expression) {
110180
110408
  while (current.kind === "annotated") current = current.expression;
110181
110409
  return current.kind === "litList";
110182
110410
  }
110183
- function sourceOffsetAt(source, pos) {
110184
- let offset = 0;
110185
- for (let line = 1; line < pos.line; line += 1) {
110186
- const next = source.indexOf("\n", offset);
110187
- if (next < 0) return null;
110188
- offset = next + 1;
110189
- }
110190
- return Math.min(offset + pos.column - 1, source.length);
110191
- }
110192
110411
  function lambdaExpressionSource(source, lambda) {
110193
110412
  const start = sourceOffsetAt(source, lambda.pos);
110194
110413
  if (start === null) return null;
@@ -110668,14 +110887,14 @@ function genericConstraint(context, ownerClass, parameterId, type, baseConstrain
110668
110887
  }
110669
110888
  return {
110670
110889
  kind: "enum",
110671
- enumId: requiredName2(context.enumIdsByName, type.name, "enum")
110890
+ enumId: requiredName(context.enumIdsByName, type.name, "enum")
110672
110891
  };
110673
110892
  }
110674
110893
  function inheritedMemberId(context, ownerClass, name) {
110675
110894
  const directBase = ownerClass.baseTypes.find(
110676
110895
  (entry) => context.classIdsByName.has(entry.name)
110677
110896
  );
110678
- const classId = directBase ? requiredName2(context.classIdsByName, directBase.name, "class") : null;
110897
+ const classId = directBase ? requiredName(context.classIdsByName, directBase.name, "class") : null;
110679
110898
  return effectiveMemberIdByName(context, classId, name);
110680
110899
  }
110681
110900
  function effectiveMemberIdByName(context, startClassId, name) {
@@ -110698,7 +110917,7 @@ function effectiveMemberIdByName(context, startClassId, name) {
110698
110917
  const sourceBase = sourceClass.baseTypes.find(
110699
110918
  (entry) => context.classIdsByName.has(entry.name)
110700
110919
  );
110701
- classId = sourceBase ? requiredName2(context.classIdsByName, sourceBase.name, "class") : null;
110920
+ classId = sourceBase ? requiredName(context.classIdsByName, sourceBase.name, "class") : null;
110702
110921
  continue;
110703
110922
  }
110704
110923
  const pulledClass = context.baseClasses.get(classId);
@@ -111014,6 +111233,7 @@ var UNSET_LIST_COLUMN_WIDTH, EMPTY_GENERIC_TYPE_ENVIRONMENT, DICTIONARY_KEY_TYPE
111014
111233
  var init_lower_members = __esm({
111015
111234
  "src/project-source/lower-members.ts"() {
111016
111235
  "use strict";
111236
+ init_initializer_reference_spellings();
111017
111237
  init_src();
111018
111238
  init_src2();
111019
111239
  init_lower_support();
@@ -111218,7 +111438,7 @@ function genericRelationEndpoint(context, expression, relationKind, side, prior)
111218
111438
  }
111219
111439
  return {
111220
111440
  recordKind: "class",
111221
- recordId: requiredName2(context.classIdsByName, expression.name, "class")
111441
+ recordId: requiredName(context.classIdsByName, expression.name, "class")
111222
111442
  };
111223
111443
  }
111224
111444
  if (expression.kind === "member" && expression.receiver.kind === "ident" && expected === "value") {
@@ -111326,7 +111546,7 @@ function relationExpressionIdentity(expression) {
111326
111546
  }
111327
111547
  function relationTargetClassId(context, expression) {
111328
111548
  if (expression.kind === "ident") {
111329
- return requiredName2(context.classIdsByName, expression.name, "class");
111549
+ return requiredName(context.classIdsByName, expression.name, "class");
111330
111550
  }
111331
111551
  if (expression.kind === "call" && expression.callee.kind === "ident" && expression.callee.name === "Reference") {
111332
111552
  const index = expression.argumentNames?.findIndex((name) => name === "id") ?? -1;
@@ -111374,7 +111594,7 @@ function lowerVariants(context, analysis) {
111374
111594
  );
111375
111595
  const variants = variantGlobals(analysis).map((global) => {
111376
111596
  const className = owningClassName(global);
111377
- const classId = requiredName2(context.classIdsByName, className, "class");
111597
+ const classId = requiredName(context.classIdsByName, className, "class");
111378
111598
  const variantId = variantRecordId(global, global.type.name);
111379
111599
  return {
111380
111600
  id: variantId,
@@ -111406,7 +111626,7 @@ function variantValueBindingsV4(manifest, analysis) {
111406
111626
  targetClassId: variant2.classId,
111407
111627
  targetClassName: requiredClassName2(classNames, variant2.classId),
111408
111628
  variantTypeName: global.type.name,
111409
- valueClassId: global.type.name === NEO_LOOKUP_VARIANT_TYPE_NAME ? requiredName2(
111629
+ valueClassId: global.type.name === NEO_LOOKUP_VARIANT_TYPE_NAME ? requiredName(
111410
111630
  new Map(
111411
111631
  manifest.classes.map((entry) => [entry.name, entry.id])
111412
111632
  ),
@@ -111441,7 +111661,7 @@ function lowerVariantFolders(context, analysis) {
111441
111661
  return {
111442
111662
  id: variantRecordId(global, NEO_VARIANT_FOLDER_TYPE_NAME),
111443
111663
  source: sourceIdentity2(global, "variantFolder", global.name),
111444
- classId: requiredName2(context.classIdsByName, className, "class"),
111664
+ classId: requiredName(context.classIdsByName, className, "class"),
111445
111665
  path: folderPath2(global),
111446
111666
  binding: folderBinding(context, global)
111447
111667
  };
@@ -111641,6 +111861,7 @@ var init_lower_variants = __esm({
111641
111861
  // src/project-source/lower-schema.ts
111642
111862
  function lowerProjectSchemaV4(base, analysis, options = {}) {
111643
111863
  const classIdsByName = identityMap(analysis.schema.classes, "class");
111864
+ const staticValueIdsBySymbol3 = options.staticValueIdsBySymbol ?? /* @__PURE__ */ new Map();
111644
111865
  const interfaceIdsByName = identityMap(
111645
111866
  analysis.schema.interfaces,
111646
111867
  "interface"
@@ -111716,7 +111937,17 @@ function lowerProjectSchemaV4(base, analysis, options = {}) {
111716
111937
  loweredMembers: /* @__PURE__ */ new Map(),
111717
111938
  entryTypesByEntryId: /* @__PURE__ */ new Map(),
111718
111939
  placements: /* @__PURE__ */ new Map(),
111719
- staticValueIdsBySymbol: options.staticValueIdsBySymbol ?? /* @__PURE__ */ new Map(),
111940
+ staticValueIdsBySymbol: staticValueIdsBySymbol3,
111941
+ settleInitializerReferences: createSchemaInitializerReferenceSettlerV4({
111942
+ analysis,
111943
+ manifest: base,
111944
+ staticValueIdsBySymbol: staticValueIdsBySymbol3,
111945
+ localValues: new LocalValueBindingsV4(
111946
+ analysis.values.globals,
111947
+ analysis.schema.enums.map((declaration) => declaration.name),
111948
+ staticMembersInitializedByName(analysis)
111949
+ )
111950
+ }),
111720
111951
  templateIdsByName: new Map(
111721
111952
  analysis.configuration.globals.flatMap(
111722
111953
  (global) => global.type.name === "TextureTemplate" ? [
@@ -111849,6 +112080,8 @@ var init_lower_schema = __esm({
111849
112080
  init_lower_relations();
111850
112081
  init_lower_variants();
111851
112082
  init_lower_support();
112083
+ init_initializer_reference_spellings();
112084
+ init_local_values();
111852
112085
  }
111853
112086
  });
111854
112087
 
@@ -115321,7 +115554,7 @@ function materializedInitializerReconciliationFailuresV4(args) {
115321
115554
  `Cannot reconcile stored construction for value "${valueId}": its canonical pulled constructor expression is unavailable.`
115322
115555
  );
115323
115556
  }
115324
- const authoredConstructionChanged = args.manifest !== void 0 && canonicalExpression !== constructorExpressionSlice(reconciliation.code);
115557
+ const authoredConstructionChanged = args.manifest !== void 0 && canonicalExpression !== reconciliation.construction;
115325
115558
  authoredConstructionChangedByValueId.set(
115326
115559
  valueId,
115327
115560
  authoredConstructionChanged
@@ -115710,7 +115943,6 @@ var init_local_initializer_materialization = __esm({
115710
115943
  init_src();
115711
115944
  init_projection();
115712
115945
  init_source_diagnostics();
115713
- init_init_source();
115714
115946
  init_initializer_replay();
115715
115947
  init_materialized_construction_cache();
115716
115948
  init_neoscript_build_cache();
@@ -119959,7 +120191,8 @@ function buildValueLowerContext(state, manifest, options = {}) {
119959
120191
  return {
119960
120192
  localValues: registry.localValues ??= new LocalValueBindingsV4(
119961
120193
  options.analysis?.values.globals ?? [],
119962
- manifest.enums.values().map((entry) => entry.name)
120194
+ manifest.enums.values().map((entry) => entry.name),
120195
+ options.analysis === void 0 ? [] : staticMembersInitializedByName(options.analysis)
119963
120196
  ),
119964
120197
  state,
119965
120198
  members,
@@ -121061,7 +121294,7 @@ function memberInitializerRequiresEvaluation(context, member, expression, source
121061
121294
  return requiresEvaluation;
121062
121295
  }
121063
121296
  function isSchemaMemberValueRead(context, expression, source) {
121064
- const path = memberPath(annotatedValue(expression).expression);
121297
+ const path = memberPath2(annotatedValue(expression).expression);
121065
121298
  if (path === null) return false;
121066
121299
  const parts = path.split(".");
121067
121300
  const name = parts.at(-1);
@@ -121724,7 +121957,10 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
121724
121957
  nodeType: "initializer",
121725
121958
  id: valueId,
121726
121959
  memberId: member.id,
121727
- code,
121960
+ code: settleInitializerReferenceSpellings(
121961
+ code,
121962
+ (call) => settledReferenceTarget(context, call)
121963
+ ),
121728
121964
  ...containerId === void 0 ? {} : { containerId }
121729
121965
  };
121730
121966
  registerSeedRow(context, rows, initRow, source, sourceExpression);
@@ -122369,6 +122605,10 @@ function lowerValueRow(context, member, sourceExpression, expectedValueId, sourc
122369
122605
  );
122370
122606
  }
122371
122607
  indexInitAuthoredRowIds(context, code, source.label);
122608
+ const compiledCode = settleInitializerReferenceSpellings(
122609
+ code,
122610
+ (call) => settledReferenceTarget(context, call)
122611
+ );
122372
122612
  const storedConstructorArgs = isObjectRecord2(base.constructorArgs) ? base.constructorArgs : null;
122373
122613
  if (resolvedMember.kind !== "class" && isLiteralValueContent(base)) {
122374
122614
  addReconstructed(
@@ -122403,7 +122643,8 @@ function lowerValueRow(context, member, sourceExpression, expectedValueId, sourc
122403
122643
  if (source.purpose === "stored" || requiresCanonicalConstruction) {
122404
122644
  context.initializerReconciliations.set(expectedValueId, {
122405
122645
  valueId: expectedValueId,
122406
- code,
122646
+ code: compiledCode,
122647
+ construction: authoredConstruction,
122407
122648
  storedConstructorArgs: storedConstructorArgs === null ? null : structuredClone(storedConstructorArgs),
122408
122649
  // Only a construction this pass could not apply is a conflict. A
122409
122650
  // re-projected one landed on the rows the canonical expression is
@@ -122435,7 +122676,7 @@ function lowerValueRow(context, member, sourceExpression, expectedValueId, sourc
122435
122676
  context,
122436
122677
  "value",
122437
122678
  expectedValueId,
122438
- { ...literalFields, init: { code } },
122679
+ { ...literalFields, init: { code: compiledCode } },
122439
122680
  source.source
122440
122681
  );
122441
122682
  return expectedValueId;
@@ -123815,7 +124056,7 @@ function requiredDecimal(expression) {
123815
124056
  }
123816
124057
  function sourceValueSymbol(context, expression) {
123817
124058
  const unwrapped = annotatedValue(expression).expression;
123818
- const path = memberPath(unwrapped);
124059
+ const path = memberPath2(unwrapped);
123819
124060
  return path === null ? null : context.staticValueIdsBySymbol.get(path) ?? null;
123820
124061
  }
123821
124062
  function resolveKeyReferenceMemberDefaultsV4(args) {
@@ -123899,12 +124140,12 @@ function referenceTargetSpelling(context, expression) {
123899
124140
  };
123900
124141
  }
123901
124142
  const resolved = referenceTargetBySymbol(context, argument2, genericTypeName);
123902
- const path = memberPath(argument2);
124143
+ const path = memberPath2(argument2);
123903
124144
  if (resolved === null || path === null) return null;
123904
124145
  return { spelling: "symbol", path, resolved };
123905
124146
  }
123906
124147
  function referenceTargetBySymbol(context, argument2, genericTypeName) {
123907
- const path = memberPath(argument2);
124148
+ const path = memberPath2(argument2);
123908
124149
  if (path === null) return null;
123909
124150
  const valueId = context.staticValueIdsBySymbol.get(path);
123910
124151
  if (valueId) {
@@ -123924,6 +124165,22 @@ function referenceTargetBySymbol(context, argument2, genericTypeName) {
123924
124165
  genericTypeName
123925
124166
  } : null;
123926
124167
  }
124168
+ function settledReferenceTarget(context, call) {
124169
+ const target = referenceTargetSpelling(context, call);
124170
+ if (target?.spelling === "symbol") {
124171
+ const typeName2 = target.resolved.genericTypeName ?? target.resolved.typeName;
124172
+ return typeName2 === null ? null : { id: target.resolved.id, typeName: typeName2 };
124173
+ }
124174
+ if (target?.spelling !== "local") return null;
124175
+ const declared = context.localValues.declaredTarget(target.name);
124176
+ if (declared === null) throw unidentifiedLocalReferenceError(target.name);
124177
+ const typeName = target.typeName ?? declared.typeName;
124178
+ if ("id" in declared) return { id: declared.id, typeName };
124179
+ return {
124180
+ id: context.staticValueIdsBySymbol.get(declared.ownerPath) ?? memberValueId(declared.ownerMemberId),
124181
+ typeName
124182
+ };
124183
+ }
123927
124184
  function referenceTargetById(context, id2, genericTypeName) {
123928
124185
  const pendingValue = context.pendingValues.get(id2);
123929
124186
  if (pendingValue !== void 0) {
@@ -124419,7 +124676,7 @@ function indexSourceStaticTargets(targets, state, analysis, manifest, parsedInit
124419
124676
  }
124420
124677
  }
124421
124678
  function sourceValueSymbolFromMap(targets, expression) {
124422
- const path = memberPath(annotatedValue(expression).expression);
124679
+ const path = memberPath2(annotatedValue(expression).expression);
124423
124680
  return path === null ? null : targets.get(path) ?? null;
124424
124681
  }
124425
124682
  function returnedSymbol(body) {
@@ -124437,7 +124694,7 @@ function returnedSymbol(body) {
124437
124694
  function firstReturnedMemberPath(statements) {
124438
124695
  for (const statement of statements) {
124439
124696
  if (statement.kind === "return") {
124440
- const path = statement.expr === null ? null : memberPath(statement.expr);
124697
+ const path = statement.expr === null ? null : memberPath2(statement.expr);
124441
124698
  if (path !== null) return path;
124442
124699
  continue;
124443
124700
  }
@@ -124560,7 +124817,7 @@ function classMemberByName(context, classId, name) {
124560
124817
  );
124561
124818
  }
124562
124819
  function lowerFunctionReference(context, expression, ownerClassId) {
124563
- const symbol = memberPath(expression);
124820
+ const symbol = memberPath2(expression);
124564
124821
  if (symbol === null || symbol.includes(".")) {
124565
124822
  throw new Error("FunctionRef values require a bare function symbol.");
124566
124823
  }
@@ -124609,7 +124866,7 @@ function lowerActionListener2(context, element, ownerClassId, index) {
124609
124866
  `NeoAction listener ${index} is a lambda. A listener must be a member reference: extract the body to an NSFunction member and subscribe that member instead.`
124610
124867
  );
124611
124868
  }
124612
- const path = memberPath(expression);
124869
+ const path = memberPath2(expression);
124613
124870
  if (path === null) {
124614
124871
  throw new Error(
124615
124872
  `NeoAction listener ${index} must name a function, NSFunction, NSDelegate, or NeoAction member on the current Class or a receiver reachable through root.`
@@ -124666,7 +124923,7 @@ function lowerDelegateValue(context, expression, ownerClassId, authoredSlice) {
124666
124923
  }
124667
124924
  return { code };
124668
124925
  }
124669
- const path = memberPath(expression);
124926
+ const path = memberPath2(expression);
124670
124927
  const symbol = path?.startsWith("this.") ? path.slice("this.".length) : path;
124671
124928
  if (symbol === null || symbol === void 0 || symbol.includes(".")) {
124672
124929
  throw new Error(
@@ -124687,7 +124944,7 @@ function lowerDelegateValue(context, expression, ownerClassId, authoredSlice) {
124687
124944
  return { memberId: target.id, valueId: null };
124688
124945
  }
124689
124946
  function fileTargetId(context, expression, registry) {
124690
- const path = memberPath(expression);
124947
+ const path = memberPath2(expression);
124691
124948
  if (path !== null) {
124692
124949
  if (!path.startsWith(`${registry}.`)) return null;
124693
124950
  return context.projectFileIdsBySymbol.get(path) ?? null;
@@ -124699,10 +124956,10 @@ function fileTargetId(context, expression, registry) {
124699
124956
  }
124700
124957
  return null;
124701
124958
  }
124702
- function memberPath(expression) {
124959
+ function memberPath2(expression) {
124703
124960
  if (expression.kind === "ident") return expression.name;
124704
124961
  if (expression.kind !== "member") return null;
124705
- const receiver = memberPath(expression.receiver);
124962
+ const receiver = memberPath2(expression.receiver);
124706
124963
  return receiver === null ? null : `${receiver}.${expression.name}`;
124707
124964
  }
124708
124965
  function annotatedValue(expression) {
@@ -126748,6 +127005,7 @@ var init_value_sources = __esm({
126748
127005
  init_initializer_replay();
126749
127006
  init_key_reference_spelling();
126750
127007
  init_local_values();
127008
+ init_initializer_reference_spellings();
126751
127009
  init_lower_members();
126752
127010
  init_lower_variants();
126753
127011
  init_member_kind_type_names();
@@ -128145,16 +128403,6 @@ var init_api = __esm({
128145
128403
  });
128146
128404
 
128147
128405
  // src/convex.ts
128148
- var convex_exports = {};
128149
- __export(convex_exports, {
128150
- api: () => api2,
128151
- convexHttpActionUrl: () => convexHttpActionUrl,
128152
- createConvexClient: () => createConvexClient,
128153
- createConvexClientForApi: () => createConvexClientForApi,
128154
- createConvexPushConnection: () => createConvexPushConnection,
128155
- mintConvexJwt: () => mintConvexJwt,
128156
- resolveConvexUrl: () => resolveConvexUrl
128157
- });
128158
128406
  import { gzipSync } from "node:zlib";
128159
128407
  import { ConvexClient, ConvexHttpClient } from "convex/browser";
128160
128408
  import { Buffer as Buffer2 } from "node:buffer";
@@ -129843,6 +130091,7 @@ __export(push_exports, {
129843
130091
  applyPushResult: () => applyPushResult,
129844
130092
  assignPendingIds: () => assignPendingIds,
129845
130093
  buildPostPushCompileSchema: () => buildPostPushCompileSchema,
130094
+ commitProjectVersionChanges: () => commitProjectVersionChanges,
129846
130095
  createPendingProjectSourceIdentityV4: () => createPendingProjectSourceIdentityV4,
129847
130096
  prepareCompleteNeoScriptBodyChanges: () => prepareCompleteNeoScriptBodyChanges,
129848
130097
  prepareLocalCandidateV4: () => prepareLocalCandidateV4,
@@ -130074,6 +130323,81 @@ function pendingInterfaceMemberSymbolOwner(value) {
130074
130323
  if (!/^\d+$/u.test(parts[4] ?? "")) return null;
130075
130324
  return owner;
130076
130325
  }
130326
+ async function commitProjectVersionChanges(args) {
130327
+ const { workspace } = args;
130328
+ const body = {
130329
+ operation: args.operation,
130330
+ changes: args.changes,
130331
+ authoredValueSeeds: [],
130332
+ initializerMaterialization: { roots: [] },
130333
+ stagedFiles: [],
130334
+ stagedUploadSessionId: null,
130335
+ // The asynchronous path keys reconnects on this identity; the rows name
130336
+ // the commit, so the same repair resubmitted is the same transaction.
130337
+ sourceHash: createHash10("sha256").update(
130338
+ JSON.stringify(
130339
+ args.changes.map((change) => `${change.recordKind}:${change.recordId}`).sort()
130340
+ )
130341
+ ).digest("hex"),
130342
+ pendingIdAssignments: {},
130343
+ summary: args.summary,
130344
+ headTransactionHash: workspace.state.headTransactionHash ?? null,
130345
+ derivedEdgeExtractorVersion: PROJECT_SNAPSHOT_DERIVED_EDGE_EXTRACTOR_VERSION,
130346
+ forceRecompile: false
130347
+ };
130348
+ const reporter = createPushProgressReporter(args.json, args.progressLabel);
130349
+ reporter.report({
130350
+ type: "project-transaction-progress",
130351
+ transactionId: null,
130352
+ phase: "submitting",
130353
+ totalChangeCount: args.changes.length,
130354
+ appliedChangeCount: 0,
130355
+ totalChunkCount: null,
130356
+ appliedChunkCount: 0,
130357
+ errorCode: null,
130358
+ errorMessage: null
130359
+ });
130360
+ try {
130361
+ const connection = await createConvexPushConnection(workspace);
130362
+ let response;
130363
+ try {
130364
+ response = await connection.submit(body, false);
130365
+ } catch (error) {
130366
+ if (!(error instanceof NeoApiError) || error.status !== 413 || !isObjectRecord2(error.body) || error.body.error !== "schema-commit-route-required")
130367
+ throw error;
130368
+ response = await NeoApiClient.forBaseUrl(
130369
+ workspace.config.apiBaseUrl
130370
+ ).post(
130371
+ `/api/projects/${workspace.config.projectId}/versions/${workspace.config.versionId}/schema/commit`,
130372
+ body
130373
+ );
130374
+ }
130375
+ const accepted = readAcceptedProjectVersionCommitResponse(response);
130376
+ if (accepted === null) {
130377
+ if (!isObjectRecord2(response) || typeof response.kind !== "string") {
130378
+ throw new Error(
130379
+ "Project transaction response is neither accepted nor an immediate commit result."
130380
+ );
130381
+ }
130382
+ return {
130383
+ kind: response.kind === "noop" ? "noop" : "committed",
130384
+ transactionId: immediateTransactionId(response)
130385
+ };
130386
+ }
130387
+ const completed = await waitForAcceptedProjectVersionTransaction({
130388
+ workspace,
130389
+ accepted,
130390
+ reporter,
130391
+ connection
130392
+ });
130393
+ return {
130394
+ kind: completed.totalChangeCount === 0 ? "noop" : "committed",
130395
+ transactionId: completed.transactionId
130396
+ };
130397
+ } finally {
130398
+ reporter.stop();
130399
+ }
130400
+ }
130077
130401
  function readAcceptedProjectVersionCommitResponse(value) {
130078
130402
  if (!isObjectRecord2(value) || value.kind !== "accepted") return null;
130079
130403
  if (typeof value.transactionId !== "string") {
@@ -130255,9 +130579,9 @@ function readNullableString(value, field) {
130255
130579
  function isProjectVersionTransactionCommitStatus(value) {
130256
130580
  return value === "preparing" || value === "waiting" || value === "queued" || value === "applying" || value === "reverting" || value === "noop" || value === "committed" || value === "failed";
130257
130581
  }
130258
- function createPushProgressReporter(json) {
130582
+ function createPushProgressReporter(json, label = "Pushing\u2026") {
130259
130583
  const animated = process.stdout.isTTY === true && !json;
130260
- const indicator = animated ? spinner("Pushing\u2026") : null;
130584
+ const indicator = animated ? spinner(label) : null;
130261
130585
  let lastStructuredEvent = "";
130262
130586
  return {
130263
130587
  report(event) {
@@ -138393,7 +138717,7 @@ var init_registry2 = __esm({
138393
138717
  "schema-contract/registry.mjs"() {
138394
138718
  "use strict";
138395
138719
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
138396
- cliVersion: "0.53.1",
138720
+ cliVersion: "0.53.3",
138397
138721
  projectFileUploadBatchSize: 32,
138398
138722
  documentRecords: {
138399
138723
  member: {
@@ -141885,8 +142209,7 @@ async function repairUnprojectedValueRows(workspace, findings, yes) {
141885
142209
  return;
141886
142210
  }
141887
142211
  const rows = plan.roots.flatMap((root) => root.rows);
141888
- const pulledHeadTransactionHash = workspace.state.headTransactionHash;
141889
- if (typeof pulledHeadTransactionHash !== "string") {
142212
+ if (typeof workspace.state.headTransactionHash !== "string") {
141890
142213
  throw new Error(
141891
142214
  'This workspace has no recorded project head, so `neo doctor --fix` cannot prove its deletions land on the state the audit read. Run "neo pull", then rerun.'
141892
142215
  );
@@ -141920,7 +142243,7 @@ async function repairUnprojectedValueRows(workspace, findings, yes) {
141920
142243
  console.log("Cancelled. No records were deleted.");
141921
142244
  return;
141922
142245
  }
141923
- const { api: api3, createConvexClient: createConvexClient2 } = await Promise.resolve().then(() => (init_convex(), convex_exports));
142246
+ const { commitProjectVersionChanges: commitProjectVersionChanges2 } = await Promise.resolve().then(() => (init_push(), push_exports));
141924
142247
  const { createProjectVersionIntent: createProjectVersionIntent2 } = await Promise.resolve().then(() => (init_project_version_intents(), project_version_intents_exports));
141925
142248
  const changes = rows.map((row) => ({
141926
142249
  recordKind: "value",
@@ -141932,95 +142255,44 @@ async function repairUnprojectedValueRows(workspace, findings, yes) {
141932
142255
  source: "neo-cli-doctor"
141933
142256
  })
141934
142257
  }));
141935
- const batchSize = immediateCommitBatchSize(changes);
141936
- const convex = await createConvexClient2(workspace);
141937
- const progress = spinner(`Deleting ${rowLabel(rows.length)}\u2026`);
141938
- let deleted = 0;
141939
- let expectedHeadTransactionHash = pulledHeadTransactionHash;
141940
- for (let index = 0; index < changes.length; index += batchSize) {
141941
- const batch = changes.slice(index, index + batchSize);
141942
- let transactionHash;
141943
- try {
141944
- const result = await convex.mutation(
141945
- api3.serverProjectRecordOperations.commitFromSession,
141946
- {
141947
- projectId: workspace.config.projectId,
141948
- versionId: workspace.config.versionId,
141949
- operation: "delete",
141950
- changes: batch,
141951
- summary: `neo doctor --fix (${rowLabel(batch.length)})`,
141952
- expectedHeadTransactionHash
141953
- }
141954
- );
141955
- transactionHash = committedTransactionHash(result);
141956
- } catch (error) {
141957
- progress.fail(
141958
- deleted === 0 ? `Failed to delete ${rowLabel(batch.length)}.` : `Failed after deleting ${rowLabel(deleted)}.`
141959
- );
141960
- throw repairFailure(error, deleted);
141961
- }
141962
- if (transactionHash === null) continue;
141963
- expectedHeadTransactionHash = transactionHash;
141964
- deleted += batch.length;
141965
- progress.update(
141966
- `Deleting ${rowLabel(rows.length)}\u2026 ${String(deleted)} done`
141967
- );
141968
- }
141969
- progress.succeed(`Deleted ${rowLabel(deleted)} across ${rootLabel}.`);
141970
- console.log('Run "neo pull" to refresh the working copy.');
141971
- }
141972
- function immediateCommitBatchSize(changes) {
141973
- let fits = 0;
141974
- let low = 1;
141975
- let high = changes.length;
141976
- while (low <= high) {
141977
- const size = Math.floor((low + high) / 2);
141978
- if (planProjectVersionTransaction(changes.slice(0, size)).path === "immediate") {
141979
- fits = size;
141980
- low = size + 1;
141981
- } else {
141982
- high = size - 1;
141983
- }
141984
- }
141985
- if (fits === 0) {
141986
- throw new Error(
141987
- "Deleting a single value row exceeds the immediate transaction budget, so `neo doctor --fix` cannot commit anything. The transaction cost model needs to change before this repair can run."
141988
- );
141989
- }
141990
- return fits;
141991
- }
141992
- function committedTransactionHash(result) {
141993
- if (!isObjectRecord2(result)) {
141994
- throw new Error(
141995
- "Doctor repair committed a deletion but the server returned no transaction envelope."
141996
- );
142258
+ let committed;
142259
+ try {
142260
+ committed = await commitProjectVersionChanges2({
142261
+ workspace,
142262
+ operation: "delete",
142263
+ changes,
142264
+ summary: `neo doctor --fix (${rowLabel(rows.length)})`,
142265
+ progressLabel: `Deleting ${rowLabel(rows.length)}\u2026`,
142266
+ json: false
142267
+ });
142268
+ } catch (error) {
142269
+ throw repairFailure(error);
141997
142270
  }
141998
- if (result.transaction === null) return null;
141999
- const transactionHash = isObjectRecord2(result.transaction) ? result.transaction.transactionHash : void 0;
142000
- if (typeof transactionHash !== "string") {
142001
- throw new Error(
142002
- "Doctor repair committed a transaction that carries no hash, so the remaining deletions have no fast-forward base."
142271
+ if (committed.kind === "noop") {
142272
+ console.log(
142273
+ `${sym.info} Nothing to delete: the ${rowLabel(rows.length)} were already gone.`
142003
142274
  );
142275
+ } else {
142276
+ success(`Deleted ${rowLabel(rows.length)} across ${rootLabel}.`);
142004
142277
  }
142005
- return transactionHash;
142278
+ console.log('Run "neo pull" to refresh the working copy.');
142006
142279
  }
142007
- function repairFailure(error, deleted) {
142008
- const applied = deleted === 0 ? "" : ` ${rowLabel(deleted)} were already deleted.`;
142009
- const code = convexErrorCode(error);
142280
+ function repairFailure(error) {
142281
+ const code = writeRefusalCode(error);
142010
142282
  if (code === "non-fast-forward" || code === "base-hash-conflict") {
142011
142283
  return new Error(
142012
- `neo doctor --fix was refused: the project moved on since this workspace pulled, so the audit is stale.${applied} Run \`neo pull\` to re-derive it, then rerun.`,
142284
+ "neo doctor --fix was refused: the project moved on since this workspace pulled, so the audit is stale. Run `neo pull` to re-derive it, then rerun.",
142013
142285
  { cause: error }
142014
142286
  );
142015
142287
  }
142016
142288
  return new Error(
142017
- `neo doctor --fix could not delete the audited rows: ${errorMessage3(error)}${applied}`,
142289
+ `neo doctor --fix could not delete the audited rows: ${errorMessage3(error)}`,
142018
142290
  { cause: error }
142019
142291
  );
142020
142292
  }
142021
- function convexErrorCode(error) {
142293
+ function writeRefusalCode(error) {
142022
142294
  if (!isObjectRecord2(error)) return null;
142023
- const data = error.data;
142295
+ const data = error instanceof NeoApiError ? error.body : error.data;
142024
142296
  if (!isObjectRecord2(data)) return null;
142025
142297
  return typeof data.error === "string" ? data.error : null;
142026
142298
  }
@@ -142035,8 +142307,8 @@ var init_doctor = __esm({
142035
142307
  init_source_diagnostics();
142036
142308
  init_project_documents();
142037
142309
  init_project_integrity();
142038
- init_project_version_transaction_planning();
142039
142310
  init_projection();
142311
+ init_http();
142040
142312
  NEO_COMPILER_CONTRACT = "ProjectSourceAnalysisV4";
142041
142313
  NEO_VSCODE_EXTENSION_ID = "neocompose.neo-compose-neoscript";
142042
142314
  NEO_VSCODE_EXTENSION_CONTRACT_VERSION = "0.3.0";
@@ -144995,16 +145267,16 @@ function dryrunOwnership(document, valueById, saveBindings = /* @__PURE__ */ new
144995
145267
  return memberById2.get(memberId)?.valueId;
144996
145268
  };
144997
145269
  const visitedPlacements = /* @__PURE__ */ new Set();
144998
- const walkOwnedGraph = (memberPath2, valueId) => {
144999
- const memberId = memberPath2.at(-1);
145270
+ const walkOwnedGraph = (memberPath3, valueId) => {
145271
+ const memberId = memberPath3.at(-1);
145000
145272
  if (memberId === void 0) return;
145001
- const visitKey = `${memberPath2.join("/")}\0${valueId}`;
145273
+ const visitKey = `${memberPath3.join("/")}\0${valueId}`;
145002
145274
  if (visitedPlacements.has(visitKey)) return;
145003
145275
  visitedPlacements.add(visitKey);
145004
145276
  const value = valueById.get(valueId);
145005
145277
  const member = memberById2.get(memberId);
145006
145278
  if (value === void 0 || member === void 0) return;
145007
- const storage = storageResolver.effectiveStorageForPath(memberPath2);
145279
+ const storage = storageResolver.effectiveStorageForPath(memberPath3);
145008
145280
  if (storage === 2 /* Save */) saveOwned.add(valueId);
145009
145281
  if (storage === 3 /* Session */) sessionOwned.add(valueId);
145010
145282
  if (member.kind === 7 /* Class */ && isObjectRecord2(value.value)) {
@@ -145016,7 +145288,7 @@ function dryrunOwnership(document, valueById, saveBindings = /* @__PURE__ */ new
145016
145288
  for (const [key, childValueId] of Object.entries(value.value)) {
145017
145289
  const childMemberId = childMemberByKey.get(key);
145018
145290
  if (childMemberId !== void 0 && typeof childValueId === "string") {
145019
- walkOwnedGraph([...memberPath2, childMemberId], childValueId);
145291
+ walkOwnedGraph([...memberPath3, childMemberId], childValueId);
145020
145292
  }
145021
145293
  }
145022
145294
  return;
@@ -145027,7 +145299,7 @@ function dryrunOwnership(document, valueById, saveBindings = /* @__PURE__ */ new
145027
145299
  if (entryMemberId === void 0) return;
145028
145300
  for (const childValueId of membership.get(valueId) ?? []) {
145029
145301
  if (typeof childValueId === "string") {
145030
- walkOwnedGraph([...memberPath2, entryMemberId], childValueId);
145302
+ walkOwnedGraph([...memberPath3, entryMemberId], childValueId);
145031
145303
  }
145032
145304
  }
145033
145305
  return;
@@ -145038,7 +145310,7 @@ function dryrunOwnership(document, valueById, saveBindings = /* @__PURE__ */ new
145038
145310
  const childIds = Array.isArray(value.value) ? value.value : Object.values(value.value);
145039
145311
  for (const childValueId of childIds) {
145040
145312
  if (typeof childValueId === "string") {
145041
- walkOwnedGraph([...memberPath2, entryMemberId], childValueId);
145313
+ walkOwnedGraph([...memberPath3, entryMemberId], childValueId);
145042
145314
  }
145043
145315
  }
145044
145316
  }
@@ -146266,7 +146538,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
146266
146538
  async function main() {
146267
146539
  const args = parseArgs(process.argv.slice(2));
146268
146540
  if (args.command === "--version") {
146269
- console.log("0.53.1");
146541
+ console.log("0.53.3");
146270
146542
  return;
146271
146543
  }
146272
146544
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {