@neocompose/cli 0.32.3 → 0.32.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.32.4] - 2026-08-18
4
+
5
+ ### Fixed
6
+
7
+ - Validate identifiers in their actual namespace so qualified member labels,
8
+ enum options, registry entries, and schema keys may reuse unrelated builtin
9
+ type or module names such as `Set`, `Dictionary`, `List`, and `Math`, while
10
+ preserving real keyword, binding, global namespace, and codegen conflicts.
11
+ - Share those contextual rules across project compilation, schema validation,
12
+ rename analysis, CLI emission, generated file registries, and server-side
13
+ validation so `neo test`, `neo script check --all`, dry runs, and pushes agree.
14
+
3
15
  ## [0.32.3] - 2026-08-18
4
16
 
5
17
  ### Fixed
package/dist/neo.mjs CHANGED
@@ -2833,12 +2833,6 @@ function referenceAtPosition(snapshot, position) {
2833
2833
  snapshot.source.offsetAt(position)
2834
2834
  );
2835
2835
  }
2836
- function isValidNeoIdentifier(name) {
2837
- return IDENTIFIER_PATTERN.test(name) && !RESERVED_NAMES.has(name);
2838
- }
2839
- function isValidRenameIdentifier(name) {
2840
- return isValidNeoIdentifier(name);
2841
- }
2842
2836
  function contextualCompletionItems(snapshot, offset, word) {
2843
2837
  const items = [];
2844
2838
  const expectedType = expectedTypeAt(snapshot, word.start);
@@ -4609,20 +4603,11 @@ function isConstructorTypeReference(snapshot, reference2) {
4609
4603
  (call) => call.kind === "constructor" && call.nameRange.start.line === reference2.range.start.line && call.nameRange.start.character === reference2.range.start.character
4610
4604
  );
4611
4605
  }
4612
- var IDENTIFIER_PATTERN, RESERVED_NAMES;
4613
4606
  var init_analyzer = __esm({
4614
4607
  "../packages/neoscript-language/src/analyzer.ts"() {
4615
4608
  "use strict";
4616
4609
  init_language_spec();
4617
4610
  init_project();
4618
- IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
4619
- RESERVED_NAMES = /* @__PURE__ */ new Set([
4620
- ...NEOSCRIPT_KEYWORDS,
4621
- ...NEOSCRIPT_PRIMITIVE_TYPES,
4622
- ...NEOSCRIPT_BUILTIN_NAMESPACES,
4623
- "Dictionary",
4624
- "Set"
4625
- ]);
4626
4611
  }
4627
4612
  });
4628
4613
 
@@ -5923,10 +5908,22 @@ var init_strict_compile_error = __esm({
5923
5908
  function isValidNeoProjectIdentifier(name) {
5924
5909
  return PROJECT_IDENTIFIER_PATTERN.test(name) && !PROJECT_RESERVED_NAMES.has(name);
5925
5910
  }
5911
+ function isValidNeoProjectMemberIdentifier(name) {
5912
+ return PROJECT_IDENTIFIER_PATTERN.test(name) && !PROJECT_MEMBER_RESERVED_NAMES.has(name);
5913
+ }
5914
+ function isValidNeoProjectBindingIdentifier(name) {
5915
+ return PROJECT_IDENTIFIER_PATTERN.test(name) && !PROJECT_BINDING_RESERVED_NAMES.has(name);
5916
+ }
5917
+ function isValidNeoScriptBindingIdentifier(name) {
5918
+ return PROJECT_IDENTIFIER_PATTERN.test(name) && !INLINE_BINDING_RESERVED_NAMES.has(name);
5919
+ }
5926
5920
  function isNeoProjectReservedName(name) {
5927
5921
  return PROJECT_RESERVED_NAMES.has(name);
5928
5922
  }
5929
- var PROJECT_IDENTIFIER_PATTERN, PROJECT_RESERVED_NAMES;
5923
+ function isNeoProjectMemberReservedName(name) {
5924
+ return PROJECT_MEMBER_RESERVED_NAMES.has(name);
5925
+ }
5926
+ var PROJECT_IDENTIFIER_PATTERN, PROJECT_RESERVED_NAMES, PROJECT_MEMBER_RESERVED_NAMES, PROJECT_BINDING_RESERVED_NAMES, INLINE_BINDING_RESERVED_NAMES;
5930
5927
  var init_project_source_identifiers = __esm({
5931
5928
  "../packages/neoscript-language/src/project-source-identifiers.ts"() {
5932
5929
  "use strict";
@@ -5936,6 +5933,20 @@ var init_project_source_identifiers = __esm({
5936
5933
  ...NEOSCRIPT_KEYWORDS,
5937
5934
  ...NEOSCRIPT_BUILTIN_NAMESPACES
5938
5935
  ]);
5936
+ PROJECT_MEMBER_RESERVED_NAMES = new Set(NEOSCRIPT_KEYWORDS);
5937
+ PROJECT_BINDING_RESERVED_NAMES = /* @__PURE__ */ new Set([
5938
+ ...PROJECT_RESERVED_NAMES,
5939
+ "this",
5940
+ "root",
5941
+ "context"
5942
+ ]);
5943
+ INLINE_BINDING_RESERVED_NAMES = /* @__PURE__ */ new Set([
5944
+ ...PROJECT_BINDING_RESERVED_NAMES,
5945
+ ...NEOSCRIPT_PRIMITIVE_TYPES,
5946
+ "Dictionary",
5947
+ "List",
5948
+ "Set"
5949
+ ]);
5939
5950
  }
5940
5951
  });
5941
5952
 
@@ -6522,7 +6533,7 @@ var init_strict_parser = __esm({
6522
6533
  }
6523
6534
  expectMemberName() {
6524
6535
  const token = this.peek();
6525
- if (token.kind === "ident" || token.kind === "keyword" && (token.text === "native" || isValidNeoProjectIdentifier(token.text))) {
6536
+ if (token.kind === "ident" || token.kind === "keyword" && (token.text === "native" || isValidNeoProjectMemberIdentifier(token.text))) {
6526
6537
  return this.next();
6527
6538
  }
6528
6539
  throw new CompileError(
@@ -17961,12 +17972,15 @@ function projectTokenAt(document, position) {
17961
17972
  const containing = tokens.find(
17962
17973
  (token) => token.start <= offset && offset < token.end
17963
17974
  );
17964
- if (containing?.kind === "identifier") return containing;
17975
+ if (isProjectNameToken(containing)) return containing;
17965
17976
  const touching = tokens.find(
17966
- (token) => token.kind === "identifier" && token.end === offset
17977
+ (token) => isProjectNameToken(token) && token.end === offset
17967
17978
  );
17968
17979
  return touching ?? containing;
17969
17980
  }
17981
+ function isProjectNameToken(token) {
17982
+ return token !== void 0 && (token.kind === "identifier" || token.kind === "type" || token.kind === "keyword");
17983
+ }
17970
17984
  function projectTokens(document) {
17971
17985
  const cached = PROJECT_TOKEN_CACHE.get(document);
17972
17986
  if (cached) return cached;
@@ -18129,7 +18143,7 @@ function collectGlobalChildEntries(sourceText, declaration) {
18129
18143
  continue;
18130
18144
  }
18131
18145
  const name = tokens[index + 1];
18132
- if ((token.kind === "type" || token.kind === "identifier") && name?.kind === "identifier" && tokens[index + 2]?.text === "=" && tokens[index + 3]?.text !== "=" && // A pending annotation or statement boundary precedes a declaration;
18146
+ if ((token.kind === "type" || token.kind === "identifier") && isProjectNameToken(name) && isValidNeoProjectMemberIdentifier(name.text) && tokens[index + 2]?.text === "=" && tokens[index + 3]?.text !== "=" && // A pending annotation or statement boundary precedes a declaration;
18133
18147
  // `key: value` fields and expression member accesses never do.
18134
18148
  tokens[index - 1]?.text !== "." && tokens[index - 1]?.text !== ":") {
18135
18149
  entries.push({
@@ -18184,6 +18198,7 @@ var init_project_source_registry = __esm({
18184
18198
  "../packages/neoscript-language/src/project-source-registry.ts"() {
18185
18199
  "use strict";
18186
18200
  init_lexer();
18201
+ init_project_source_identifiers();
18187
18202
  init_project_source_tokens();
18188
18203
  }
18189
18204
  });
@@ -23869,7 +23884,7 @@ function memberKeyArgument(annotation2) {
23869
23884
  if (argument2 === void 0) return null;
23870
23885
  const text = argument2.text.trim();
23871
23886
  return {
23872
- key: IDENTIFIER_PATTERN2.test(text) ? text : null,
23887
+ key: IDENTIFIER_PATTERN.test(text) ? text : null,
23873
23888
  range: argument2.range
23874
23889
  };
23875
23890
  }
@@ -24058,7 +24073,7 @@ function classDerivesFromName(name, ancestorName, environment, seen = /* @__PURE
24058
24073
  return classDerivesFromName(base.name, ancestorName, environment, seen);
24059
24074
  });
24060
24075
  }
24061
- var NEO_VARIANT_FOLDER_SETTING, primitiveType, IDENTIFIER_PATTERN2, LIST_COLUMN_INHERITANCE_KEY;
24076
+ var NEO_VARIANT_FOLDER_SETTING, primitiveType, IDENTIFIER_PATTERN, LIST_COLUMN_INHERITANCE_KEY;
24062
24077
  var init_project_source_semantics = __esm({
24063
24078
  "../packages/neoscript-language/src/project-source-semantics.ts"() {
24064
24079
  "use strict";
@@ -24073,7 +24088,7 @@ var init_project_source_semantics = __esm({
24073
24088
  init_project_root();
24074
24089
  NEO_VARIANT_FOLDER_SETTING = "folder";
24075
24090
  primitiveType = (name) => ({ name });
24076
- IDENTIFIER_PATTERN2 = /^[A-Za-z_][A-Za-z0-9_]*$/;
24091
+ IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
24077
24092
  LIST_COLUMN_INHERITANCE_KEY = "__other__";
24078
24093
  }
24079
24094
  });
@@ -27047,14 +27062,16 @@ function collectFlowSymbols(uri, content, ownerName, scopeRange, symbols, diagno
27047
27062
  }
27048
27063
  }
27049
27064
  function collectSymbol(uri, kind, name, range2, annotations, ownerName, symbols, diagnostics, scopeRange, detail, callable2, documentation, staticMember) {
27050
- if (isNeoProjectReservedName(name)) {
27065
+ const memberLabel2 = kind === "member" || kind === "enumOption" || kind === "graphChild";
27066
+ const reserved = memberLabel2 ? isNeoProjectMemberReservedName(name) : isNeoProjectReservedName(name);
27067
+ if (reserved) {
27051
27068
  diagnostics.push({
27052
27069
  uri,
27053
27070
  range: range2,
27054
27071
  severity: "error",
27055
27072
  source: "neo-project",
27056
27073
  code: "reserved-project-name",
27057
- message: `'${name}' is a reserved Neo keyword and cannot be used as a persisted source name without the language's identifier escape syntax.`
27074
+ message: `'${name}' is reserved in this Neo declaration context and cannot be used as a persisted source name without the language's identifier escape syntax.`
27058
27075
  });
27059
27076
  }
27060
27077
  const id2 = sourceId(uri, annotations, diagnostics);
@@ -28523,7 +28540,7 @@ function projectVariantScopeCompletion(analysis, document, position) {
28523
28540
  }
28524
28541
  function projectVariantPathSymbolAt(analysis, document, position) {
28525
28542
  const token = projectTokenAt(document, position);
28526
- if (!token || token.kind !== "identifier") return null;
28543
+ if (!isProjectNameToken(token)) return null;
28527
28544
  const tokens = projectTokens(document);
28528
28545
  const tokenIndex = tokens.findIndex(
28529
28546
  (candidate) => candidate.start === token.start && candidate.end === token.end
@@ -28534,7 +28551,7 @@ function projectVariantPathSymbolAt(analysis, document, position) {
28534
28551
  for (; ; ) {
28535
28552
  const dot = tokens[cursor];
28536
28553
  const owner = tokens[cursor - 1];
28537
- if (dot?.text !== "." || owner?.kind !== "identifier") break;
28554
+ if (dot?.text !== "." || !isProjectNameToken(owner)) break;
28538
28555
  segments.unshift(owner.text);
28539
28556
  cursor -= 2;
28540
28557
  }
@@ -29187,10 +29204,12 @@ function projectSemanticTokens(document, analysis) {
29187
29204
  return [];
29188
29205
  }
29189
29206
  const declaration = symbolsDeclaredAt(index, document.uri, token.range)[0];
29190
- const resolved = token.kind === "identifier" ? indexedProjectSymbolAt(analysis, document, token.range.start, index)?.symbol : void 0;
29207
+ const resolved = isProjectNameToken(token) ? indexedProjectSymbolAt(analysis, document, token.range.start, index)?.symbol : void 0;
29191
29208
  let type;
29192
29209
  if (declaration) {
29193
29210
  type = projectSemanticTokenType(declaration);
29211
+ } else if (resolved) {
29212
+ type = projectSemanticTokenType(resolved);
29194
29213
  } else if (token.kind === "keyword") type = "keyword";
29195
29214
  else if (token.kind === "type") type = "type";
29196
29215
  else if (token.kind === "string") type = "string";
@@ -29242,7 +29261,14 @@ function projectSymbolAt(analysis, document, position) {
29242
29261
  }
29243
29262
  function indexedProjectSymbolAt(analysis, document, position, index) {
29244
29263
  const token = projectTokenAt(document, position);
29245
- if (!token || token.kind !== "identifier") return null;
29264
+ if (!isProjectNameToken(token)) return null;
29265
+ const body = projectBodySnapshotAt(analysis, document, position);
29266
+ if (body) {
29267
+ const reference2 = referenceAtPosition(body, position);
29268
+ const symbolId = reference2 ? resolveReferenceSymbolId(body, reference2) : null;
29269
+ const symbol = symbolId ? analysis.symbols.find((candidate) => candidate.id === symbolId) : void 0;
29270
+ if (symbol) return { token, symbol };
29271
+ }
29246
29272
  const exact = symbolsDeclaredAt(index, document.uri, token.range);
29247
29273
  if (exact.length === 1) return { token, symbol: exact[0] };
29248
29274
  const candidates = index.byName.get(token.text) ?? [];
@@ -29299,7 +29325,7 @@ function indexedProjectSymbolAt(analysis, document, position, index) {
29299
29325
  dotOwner.range.start,
29300
29326
  index
29301
29327
  );
29302
- const ownerNames = resolvedOwner ? projectReceiverOwnerNames(analysis, resolvedOwner.symbol) : [dotOwner.text];
29328
+ const ownerNames = dotOwner.text === "this" && owner ? projectTypeAndBaseOwnerNames(analysis, owner) : resolvedOwner ? projectReceiverOwnerNames(analysis, resolvedOwner.symbol) : [dotOwner.text];
29303
29329
  const qualified = visibleCandidates.filter(
29304
29330
  (symbol) => symbol.ownerName !== void 0 && ownerNames.includes(symbol.ownerName) && (resolvedOwner === null || projectQualifiedSymbolMatchesReceiver(symbol, resolvedOwner.symbol))
29305
29331
  );
@@ -29334,27 +29360,33 @@ function projectQualifiedSymbolMatchesReceiver(symbol, receiver) {
29334
29360
  }
29335
29361
  function projectReceiverOwnerNames(analysis, receiver) {
29336
29362
  const result = [];
29337
- const visitedTypes = /* @__PURE__ */ new Set();
29338
- const appendTypeAndBases = (typeName2) => {
29339
- if (visitedTypes.has(typeName2)) return;
29340
- visitedTypes.add(typeName2);
29341
- if (!result.includes(typeName2)) result.push(typeName2);
29342
- const declaration = findTypeDeclaration(analysis, typeName2);
29363
+ if (receiver.kind === "global") {
29364
+ result.push(receiver.name);
29365
+ }
29366
+ const typeName = projectSymbolTypeName(receiver);
29367
+ if (typeName)
29368
+ result.push(...projectTypeAndBaseOwnerNames(analysis, typeName));
29369
+ return result;
29370
+ }
29371
+ function projectTypeAndBaseOwnerNames(analysis, typeName) {
29372
+ const result = [];
29373
+ const visited = /* @__PURE__ */ new Set();
29374
+ const append = (candidateName) => {
29375
+ if (visited.has(candidateName)) return;
29376
+ visited.add(candidateName);
29377
+ result.push(candidateName);
29378
+ const declaration = findTypeDeclaration(analysis, candidateName);
29343
29379
  if (declaration?.kind !== "class" && declaration?.kind !== "interface") {
29344
29380
  return;
29345
29381
  }
29346
29382
  for (const base of declaration.baseTypes) {
29347
29383
  const resolved = findTypeDeclaration(analysis, base.name);
29348
29384
  if (resolved?.kind === "class" || resolved?.kind === "interface") {
29349
- appendTypeAndBases(base.name);
29385
+ append(base.name);
29350
29386
  }
29351
29387
  }
29352
29388
  };
29353
- if (receiver.kind === "global") {
29354
- result.push(receiver.name);
29355
- }
29356
- const typeName = projectSymbolTypeName(receiver);
29357
- if (typeName) appendTypeAndBases(typeName);
29389
+ append(typeName);
29358
29390
  return result;
29359
29391
  }
29360
29392
  function contextualProjectEnumOptionSymbol(analysis, document, token, candidates, source) {
@@ -33099,6 +33131,8 @@ var init_service = __esm({
33099
33131
  init_analyzer();
33100
33132
  init_compiler();
33101
33133
  init_formatter();
33134
+ init_generated_csharp_identifiers();
33135
+ init_project_source_identifiers();
33102
33136
  init_project_source_analysis();
33103
33137
  init_project_source_construction_quick_fixes();
33104
33138
  init_project_source_language_features();
@@ -33320,9 +33354,25 @@ var init_service = __esm({
33320
33354
  return { range: reference2.range, placeholder: reference2.name };
33321
33355
  }
33322
33356
  rename(uri, position, newName) {
33323
- if (!isValidRenameIdentifier(newName)) {
33357
+ const state = this.requireState(uri);
33358
+ let validName;
33359
+ if (isProjectDocument(state.document, state.context)) {
33360
+ const resolved = projectSymbolAt(
33361
+ this.projectAnalysis(),
33362
+ state.document,
33363
+ position
33364
+ );
33365
+ if (!resolved) return null;
33366
+ const memberLabel2 = resolved.symbol.kind === "member" || resolved.symbol.kind === "enumOption" || resolved.symbol.kind === "graphChild";
33367
+ const binding = resolved.symbol.kind === "parameter" || resolved.symbol.kind === "genericParameter" || resolved.symbol.kind === "flowBinding";
33368
+ const validNeoName = memberLabel2 ? isValidNeoProjectMemberIdentifier(newName) : binding ? isValidNeoProjectBindingIdentifier(newName) : isValidNeoProjectIdentifier(newName);
33369
+ validName = validNeoName && isGeneratedCSharpIdentifier(newName) && !isGeneratedCSharpReservedKeyword(newName);
33370
+ } else {
33371
+ validName = isValidNeoScriptBindingIdentifier(newName);
33372
+ }
33373
+ if (!validName) {
33324
33374
  throw new Error(
33325
- `Cannot rename a NeoScript symbol to "${newName}": use a non-keyword identifier containing letters, digits, or underscores.`
33375
+ `Cannot rename a NeoScript symbol to "${newName}": use an identifier valid in this declaration context and generated C#.`
33326
33376
  );
33327
33377
  }
33328
33378
  const prepared = this.prepareRename(uri, position);
@@ -33422,7 +33472,7 @@ var init_service = __esm({
33422
33472
  }
33423
33473
  projectReferences(document, position, includeDeclaration) {
33424
33474
  const token = projectTokenAt(document, position);
33425
- if (!token || token.kind !== "identifier") return [];
33475
+ if (!isProjectNameToken(token)) return [];
33426
33476
  const analysis = this.projectAnalysis();
33427
33477
  const resolved = projectSymbolAt(analysis, document, position);
33428
33478
  if (!resolved) return [];
@@ -33431,7 +33481,7 @@ var init_service = __esm({
33431
33481
  for (const state of this.documents.values()) {
33432
33482
  if (!isProjectDocument(state.document, state.context)) continue;
33433
33483
  for (const candidate of projectTokens(state.document)) {
33434
- if (candidate.kind !== "identifier" || candidate.text !== token.text) {
33484
+ if (!isProjectNameToken(candidate) || candidate.text !== token.text) {
33435
33485
  continue;
33436
33486
  }
33437
33487
  const candidateSymbol = projectSymbolAt(
@@ -41184,6 +41234,46 @@ var init_docs_text2 = __esm({
41184
41234
  }
41185
41235
  });
41186
41236
 
41237
+ // ../src/models/project-source-identifiers.ts
41238
+ function isValidGeneratedIdentifier(value) {
41239
+ return typeof value === "string" && isGeneratedCSharpIdentifier(value) && !isGeneratedCSharpReservedKeyword(value);
41240
+ }
41241
+ function isValidProjectSourceIdentifier(value) {
41242
+ return isValidGeneratedIdentifier(value) && isValidNeoProjectIdentifier(value);
41243
+ }
41244
+ function isValidProjectMemberIdentifier(value) {
41245
+ return isValidGeneratedIdentifier(value) && isValidNeoProjectMemberIdentifier(value);
41246
+ }
41247
+ function isValidProjectBindingIdentifier(value) {
41248
+ return isValidGeneratedIdentifier(value) && isValidNeoProjectBindingIdentifier(value);
41249
+ }
41250
+ var init_project_source_identifiers2 = __esm({
41251
+ "../src/models/project-source-identifiers.ts"() {
41252
+ "use strict";
41253
+ init_src();
41254
+ }
41255
+ });
41256
+
41257
+ // ../src/models/schema-identifiers.ts
41258
+ function isValidSchemaAuthoredIdentifier(value) {
41259
+ return isValidProjectSourceIdentifier(value);
41260
+ }
41261
+ function isValidSchemaMemberIdentifier(value) {
41262
+ return isValidProjectMemberIdentifier(value);
41263
+ }
41264
+ function isValidSchemaBindingIdentifier(value) {
41265
+ return isValidProjectBindingIdentifier(value);
41266
+ }
41267
+ function isValidSchemaNSFunctionBindingIdentifier(value) {
41268
+ return isValidSchemaBindingIdentifier(value) && value !== "value";
41269
+ }
41270
+ var init_schema_identifiers = __esm({
41271
+ "../src/models/schema-identifiers.ts"() {
41272
+ "use strict";
41273
+ init_project_source_identifiers2();
41274
+ }
41275
+ });
41276
+
41187
41277
  // ../src/models/neoscript/neoscript-types.ts
41188
41278
  var NS_TYPE_UNKNOWN, NS_TYPE_VOID, NSAssignmentOperator, NSWritability, NSCollectionMutation;
41189
41279
  var init_neoscript_types = __esm({
@@ -42755,12 +42845,20 @@ function isMemberAccessModifierKind(value) {
42755
42845
  if (value === "protected") return true;
42756
42846
  return value === "private";
42757
42847
  }
42758
- function isValidCallableIdentifier(value) {
42759
- if (typeof value !== "string") return false;
42760
- if (!FunctionMemberNamePattern.test(value)) return false;
42848
+ function isValidCallableMemberIdentifier(value) {
42849
+ if (!isValidSchemaMemberIdentifier(value)) return false;
42850
+ if (value.startsWith("__")) return false;
42851
+ return true;
42852
+ }
42853
+ function isValidCallableArgumentIdentifier(value) {
42854
+ if (!isValidSchemaBindingIdentifier(value)) return false;
42761
42855
  if (value.startsWith("__")) return false;
42762
42856
  return !FunctionArgumentReservedNames.has(value);
42763
42857
  }
42858
+ function isValidNSFunctionArgumentIdentifier(value) {
42859
+ if (!isValidSchemaNSFunctionBindingIdentifier(value)) return false;
42860
+ return !value.startsWith("__");
42861
+ }
42764
42862
  function isMemberListColumnSettings(value) {
42765
42863
  if (!value) return false;
42766
42864
  if (typeof value !== "object") return false;
@@ -43124,7 +43222,7 @@ function isMemberAudioBase(value) {
43124
43222
  function isMemberFunctionBase(value) {
43125
43223
  const v = asMemberBaseForKind(value, 13 /* Function */);
43126
43224
  if (v === null) return false;
43127
- if (!isValidCallableIdentifier(v.name)) return false;
43225
+ if (!isValidCallableMemberIdentifier(v.name)) return false;
43128
43226
  if (!isNSFunctionReturnTypeInfo(v.returnTypeInfo)) return false;
43129
43227
  if (!Array.isArray(v.argumentTypes)) return false;
43130
43228
  if (typeof v.deferred !== "boolean") return false;
@@ -43132,7 +43230,7 @@ function isMemberFunctionBase(value) {
43132
43230
  const argumentTypes = [];
43133
43231
  for (const arg of v.argumentTypes) {
43134
43232
  if (!isNSFunctionArgumentTypeInfo(arg)) return false;
43135
- if (!isValidCallableIdentifier(arg.name)) return false;
43233
+ if (!isValidCallableArgumentIdentifier(arg.name)) return false;
43136
43234
  if (arg.type === NS_TYPE_UNKNOWN) return false;
43137
43235
  if (names.has(arg.name)) return false;
43138
43236
  names.add(arg.name);
@@ -43178,7 +43276,7 @@ function isNSFunctionUIBody(value) {
43178
43276
  function isMemberNSFunctionBase(value) {
43179
43277
  const v = asMemberBaseForKind(value, 23 /* NSFunction */);
43180
43278
  if (v === null) return false;
43181
- if (!isValidCallableIdentifier(v.name)) return false;
43279
+ if (!isValidCallableMemberIdentifier(v.name)) return false;
43182
43280
  if (v.required !== false) return false;
43183
43281
  if (v.defaultValue !== void 0 && v.defaultValue !== null) return false;
43184
43282
  if (v.storage !== void 0 && v.storage !== null) return false;
@@ -43194,8 +43292,7 @@ function isMemberNSFunctionBase(value) {
43194
43292
  for (const argument2 of v.argumentTypes) {
43195
43293
  if (!isNSFunctionArgumentTypeInfo(argument2)) return false;
43196
43294
  if (argument2.type === NS_TYPE_UNKNOWN) return false;
43197
- if (!isValidCallableIdentifier(argument2.name)) return false;
43198
- if (NSFunctionArgumentReservedNames.has(argument2.name)) return false;
43295
+ if (!isValidNSFunctionArgumentIdentifier(argument2.name)) return false;
43199
43296
  if (names.has(argument2.name)) return false;
43200
43297
  names.add(argument2.name);
43201
43298
  argumentTypes.push(argument2);
@@ -43273,7 +43370,7 @@ function isMemberDelegateBase(value) {
43273
43370
  const names = /* @__PURE__ */ new Set();
43274
43371
  for (const argument2 of v.argumentTypes) {
43275
43372
  if (!isNSFunctionArgumentTypeInfo(argument2)) return false;
43276
- if (!isValidCallableIdentifier(argument2.name)) return false;
43373
+ if (!isValidCallableArgumentIdentifier(argument2.name)) return false;
43277
43374
  if (argument2.type === NS_TYPE_UNKNOWN) return false;
43278
43375
  if (names.has(argument2.name)) return false;
43279
43376
  names.add(argument2.name);
@@ -43312,7 +43409,7 @@ function isMemberActionBase(value) {
43312
43409
  const names = /* @__PURE__ */ new Set();
43313
43410
  for (const argument2 of v.argumentTypes) {
43314
43411
  if (!isNSFunctionArgumentTypeInfo(argument2)) return false;
43315
- if (!isValidCallableIdentifier(argument2.name)) return false;
43412
+ if (!isValidCallableArgumentIdentifier(argument2.name)) return false;
43316
43413
  if (argument2.type === NS_TYPE_UNKNOWN) return false;
43317
43414
  if (names.has(argument2.name)) return false;
43318
43415
  names.add(argument2.name);
@@ -43616,7 +43713,7 @@ function isMemberOverrideProps(value) {
43616
43713
  if (v.setter !== void 0 && !isNSVoidBody(v.setter)) return false;
43617
43714
  const isCallableOverride = v.kind === 13 /* Function */ || v.kind === 23 /* NSFunction */;
43618
43715
  if (isCallableOverride) {
43619
- if (!isValidCallableIdentifier(v.name)) return false;
43716
+ if (!isValidCallableMemberIdentifier(v.name)) return false;
43620
43717
  if (v.returnTypeInfo !== void 0) return false;
43621
43718
  if (v.argumentTypes !== void 0) return false;
43622
43719
  if (v.deferred !== void 0) return false;
@@ -43693,37 +43790,23 @@ function isAnyMember(value) {
43693
43790
  function isAnyMemberAuthoredOrCompiled(value) {
43694
43791
  return isAnyMember(value) || isUncompiledMemberNSFunctionOverride(value);
43695
43792
  }
43696
- var FunctionMemberNamePattern, FunctionArgumentReservedNames, NSFunctionArgumentReservedNames, DECIMAL_STRING_PATTERN, DECIMAL_MAX_SIGNIFICANT_DIGITS, DECIMAL_MAX_SCALE;
43793
+ var FunctionArgumentReservedNames, NSFunctionArgumentReservedNames, DECIMAL_STRING_PATTERN, DECIMAL_MAX_SIGNIFICANT_DIGITS, DECIMAL_MAX_SCALE;
43697
43794
  var init_member_kinds = __esm({
43698
43795
  "../src/models/members/member-kinds.ts"() {
43699
43796
  "use strict";
43700
43797
  init_core();
43701
43798
  init_docs_text2();
43799
+ init_schema_identifiers();
43702
43800
  init_neoscript();
43703
43801
  init_classes();
43704
43802
  init_member_kind_enum();
43705
43803
  init_member_storage();
43706
43804
  init_structured_leaf_fields();
43707
43805
  init_member_kind_enum();
43708
- FunctionMemberNamePattern = /^[A-Za-z_][A-Za-z0-9_]*$/;
43709
43806
  FunctionArgumentReservedNames = /* @__PURE__ */ new Set([
43710
43807
  "this",
43711
43808
  "root",
43712
- "context",
43713
- "true",
43714
- "false",
43715
- "null",
43716
- "void",
43717
- "if",
43718
- "else",
43719
- "return",
43720
- "throw",
43721
- "var",
43722
- "int",
43723
- "float",
43724
- "decimal",
43725
- "string",
43726
- "bool"
43809
+ "context"
43727
43810
  ]);
43728
43811
  NSFunctionArgumentReservedNames = /* @__PURE__ */ new Set([
43729
43812
  ...FunctionArgumentReservedNames,
@@ -47819,28 +47902,6 @@ var init_files = __esm({
47819
47902
  }
47820
47903
  });
47821
47904
 
47822
- // ../src/models/project-source-identifiers.ts
47823
- function isValidProjectSourceIdentifier(value) {
47824
- return typeof value === "string" && isValidNeoProjectIdentifier(value) && isGeneratedCSharpIdentifier(value) && !isGeneratedCSharpReservedKeyword(value);
47825
- }
47826
- var init_project_source_identifiers2 = __esm({
47827
- "../src/models/project-source-identifiers.ts"() {
47828
- "use strict";
47829
- init_src();
47830
- }
47831
- });
47832
-
47833
- // ../src/models/schema-identifiers.ts
47834
- function isValidSchemaAuthoredIdentifier(value) {
47835
- return isValidProjectSourceIdentifier(value);
47836
- }
47837
- var init_schema_identifiers = __esm({
47838
- "../src/models/schema-identifiers.ts"() {
47839
- "use strict";
47840
- init_project_source_identifiers2();
47841
- }
47842
- });
47843
-
47844
47905
  // ../src/models/enum/enum-types.ts
47845
47906
  function isValidEnumOptionId(id2) {
47846
47907
  if (typeof id2 !== "string" || id2.length === 0) return false;
@@ -47852,7 +47913,7 @@ function isProspectiveEnumOptionId(id2) {
47852
47913
  return isValidEnumOptionId(id2);
47853
47914
  }
47854
47915
  function isValidEnumOptionName(name) {
47855
- return isValidSchemaAuthoredIdentifier(name);
47916
+ return isValidSchemaMemberIdentifier(name);
47856
47917
  }
47857
47918
  function isEnumOptionWithIds(value, isOptionId) {
47858
47919
  const v = value;
@@ -50794,14 +50855,14 @@ function listAnnotations(member) {
50794
50855
  if (member.kind !== "list") return [];
50795
50856
  return [
50796
50857
  ...member.indexes.map((entry) => {
50797
- assertIdentifier(entry.schemaKey, "list index member");
50858
+ assertMemberIdentifier(entry.schemaKey, "list index member");
50798
50859
  return `@index(${[
50799
50860
  `member: ${entry.schemaKey}`,
50800
50861
  ...entry.unique ? ["unique: true"] : []
50801
50862
  ].join(", ")})`;
50802
50863
  }),
50803
50864
  ...member.columns.map((entry) => {
50804
- assertIdentifier(entry.memberKey, "list column member");
50865
+ assertMemberIdentifier(entry.memberKey, "list column member");
50805
50866
  return `@column(${[
50806
50867
  `member: ${entry.memberKey}`,
50807
50868
  ...entry.width === null ? [] : [`width: ${entry.width}`],
@@ -51236,7 +51297,7 @@ function renderNestedValue(context, member, value) {
51236
51297
  return renderDefaultValue(context, member, { value, classId: null });
51237
51298
  }
51238
51299
  function emitTextureTemplate(value) {
51239
- assertIdentifier(value.name, "texture template");
51300
+ assertProjectIdentifier(value.name, "texture template");
51240
51301
  const platformSettings = `new(
51241
51302
  ${namedArguments(
51242
51303
  [
@@ -51429,7 +51490,7 @@ function emitVector4(value) {
51429
51490
  return `new(x: ${value.x}, y: ${value.y}, z: ${value.z}, w: ${value.w})`;
51430
51491
  }
51431
51492
  function emitAudioTemplate(value) {
51432
- assertIdentifier(value.name, "audio template");
51493
+ assertProjectIdentifier(value.name, "audio template");
51433
51494
  const enumArguments = /* @__PURE__ */ new Set([
51434
51495
  "loadType",
51435
51496
  "compressionFormat",
@@ -51634,7 +51695,7 @@ function emitVariantFiles(context, variantInitializers) {
51634
51695
  function emitVariantFolder(context, className, folder) {
51635
51696
  for (const segment of folder.path.split("/")) {
51636
51697
  if (segment.length === 0) continue;
51637
- assertIdentifier(segment, "variant folder path segment");
51698
+ assertProjectIdentifier(segment, "variant folder path segment");
51638
51699
  }
51639
51700
  if (folder.binding === null) {
51640
51701
  return `${id(folder.id)}NeoVariantFolder<${className}> ${variantFolderSymbol(folder)} = new(${quote(folder.path)});`;
@@ -51654,7 +51715,7 @@ function emitVariantFolder(context, className, folder) {
51654
51715
  );`;
51655
51716
  }
51656
51717
  function emitVariant(context, className, variant, folder, variantInitializers) {
51657
- assertIdentifier(variant.name, "variant");
51718
+ assertProjectIdentifier(variant.name, "variant");
51658
51719
  const initializer = variantInitializers.get(variant.id);
51659
51720
  if (initializer === void 0) {
51660
51721
  throw new Error(
@@ -51709,13 +51770,20 @@ function assertUniqueEmittedPaths(files) {
51709
51770
  paths.set(key, file);
51710
51771
  }
51711
51772
  }
51712
- function assertIdentifier(value, kind) {
51713
- if (!isValidNeoIdentifier(value)) {
51773
+ function assertProjectIdentifier(value, kind) {
51774
+ if (!isValidNeoProjectIdentifier(value)) {
51714
51775
  throw new Error(
51715
51776
  `Persisted ${kind} name ${quote(value)} is not a valid Neo identifier; repair the server record before format-4 conversion.`
51716
51777
  );
51717
51778
  }
51718
51779
  }
51780
+ function assertMemberIdentifier(value, kind) {
51781
+ if (!isValidNeoProjectMemberIdentifier(value)) {
51782
+ throw new Error(
51783
+ `Persisted ${kind} name ${quote(value)} is not a valid Neo member identifier; repair the server record before format-4 conversion.`
51784
+ );
51785
+ }
51786
+ }
51719
51787
  function required(map, key, kind) {
51720
51788
  const value = map.get(key);
51721
51789
  if (!value) throw new Error(`Unknown ${kind} ${quote(key)}.`);
@@ -51829,7 +51897,7 @@ function assignDeterministicProjectFileSymbols(files, reservedSymbols = []) {
51829
51897
  const candidate = `${item.base}${collidesByStem ? item.extension : ""}`;
51830
51898
  let symbol = candidate;
51831
51899
  let suffix = 2;
51832
- while (used.has(symbol.toLowerCase()) || !isValidNeoIdentifier(symbol))
51900
+ while (used.has(symbol.toLowerCase()) || !isValidNeoProjectMemberIdentifier(symbol))
51833
51901
  symbol = `${candidate}_${suffix++}`;
51834
51902
  used.add(symbol.toLowerCase());
51835
51903
  result.set(item.stableId, symbol);
@@ -52450,7 +52518,7 @@ ${args.map(([name, value]) => ` ${name}: ${value},`).join("\n")}
52450
52518
  `;
52451
52519
  }
52452
52520
  function emitPriorityGroup(data, recordId, name) {
52453
- assertIdentifier2(name, "priority group");
52521
+ assertProjectIdentifier2(name, "priority group");
52454
52522
  const options = Array.isArray(data.options) ? data.options : [];
52455
52523
  const body = options.map((option, index) => {
52456
52524
  if (!isObjectRecord2(option) || typeof option.id !== "string" || typeof option.name !== "string") {
@@ -52458,7 +52526,7 @@ function emitPriorityGroup(data, recordId, name) {
52458
52526
  `Priority group ${recordId} option ${index} is malformed.`
52459
52527
  );
52460
52528
  }
52461
- assertIdentifier2(option.name, "priority option");
52529
+ assertMemberIdentifier2(option.name, "priority option");
52462
52530
  return ` @id(${quote2(option.id)})
52463
52531
  PriorityOption ${option.name} = new();`;
52464
52532
  });
@@ -52473,7 +52541,7 @@ ${body.join("\n\n")}
52473
52541
  `;
52474
52542
  }
52475
52543
  function emitDialogueGroup(data, recordId, name, priorityNames, dialogueNames, uiLogicResolver) {
52476
- assertIdentifier2(name, "dialogue group");
52544
+ assertProjectIdentifier2(name, "dialogue group");
52477
52545
  const kind = data.type === 1 ? "Lookup" : data.type === 2 ? "Folder" : "Standard";
52478
52546
  const args = [["kind", `.${kind}`]];
52479
52547
  const priority = reference(
@@ -52545,7 +52613,7 @@ function collectDialogueGroupFunctions(data, groupId, resolver) {
52545
52613
  let functionName = functionNameById.get(functionId);
52546
52614
  const code = typeof value.code === "string" ? value.code.trim() : value.type === 0 ? uiConditionSource(value.getter, resolver) : null;
52547
52615
  if (functionName === void 0) {
52548
- assertIdentifier2(requestedName, "dialogue group function");
52616
+ assertMemberIdentifier2(requestedName, "dialogue group function");
52549
52617
  functionName = uniqueIdentifier(requestedName, names);
52550
52618
  functions.set(functionId, { id: functionId, name: functionName, code });
52551
52619
  functionNameById.set(functionId, functionName);
@@ -53107,7 +53175,7 @@ function requiredName(data, record3) {
53107
53175
  if (typeof data.name !== "string") {
53108
53176
  throw new Error(`${record3.recordKind}:${record3.recordId} has no name.`);
53109
53177
  }
53110
- assertIdentifier2(data.name, record3.recordKind);
53178
+ assertProjectIdentifier2(data.name, record3.recordKind);
53111
53179
  return data.name;
53112
53180
  }
53113
53181
  function namesById(records2, kind) {
@@ -53199,7 +53267,7 @@ function normalizeSource(value) {
53199
53267
  return value.replace(/\s+/gu, " ").trim();
53200
53268
  }
53201
53269
  function isIdentifier(value) {
53202
- return /^[A-Za-z_][A-Za-z0-9_]*$/u.test(value);
53270
+ return isValidNeoProjectMemberIdentifier(value);
53203
53271
  }
53204
53272
  function reference(value, names, type) {
53205
53273
  if (value === void 0 || value === null) return null;
@@ -53250,13 +53318,20 @@ function enumCase2(value) {
53250
53318
  function lowerFirst2(value) {
53251
53319
  return `${value[0]?.toLowerCase() ?? ""}${value.slice(1)}`;
53252
53320
  }
53253
- function assertIdentifier2(value, kind) {
53254
- if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
53321
+ function assertProjectIdentifier2(value, kind) {
53322
+ if (!isValidNeoProjectIdentifier(value)) {
53255
53323
  throw new Error(
53256
53324
  `${kind} name ${JSON.stringify(value)} is not a valid Neo identifier.`
53257
53325
  );
53258
53326
  }
53259
53327
  }
53328
+ function assertMemberIdentifier2(value, kind) {
53329
+ if (!isValidNeoProjectMemberIdentifier(value)) {
53330
+ throw new Error(
53331
+ `${kind} name ${JSON.stringify(value)} is not a valid Neo member identifier.`
53332
+ );
53333
+ }
53334
+ }
53260
53335
  function uniqueIdentifier(requested, used) {
53261
53336
  let candidate = requested;
53262
53337
  let suffix = 2;
@@ -53967,6 +54042,7 @@ var init_interface_validation = __esm({
53967
54042
  "../src/models/interfaces/interface-validation.ts"() {
53968
54043
  "use strict";
53969
54044
  init_member_kinds();
54045
+ init_schema_identifiers();
53970
54046
  init_interface_conformance();
53971
54047
  init_interface_graph();
53972
54048
  }
@@ -72799,22 +72875,22 @@ var init_init_backed_value_materialization = __esm({
72799
72875
  function hasRejectedConstructorKey(value) {
72800
72876
  return REJECTED_CONSTRUCTOR_KEYS.some((key) => value[key] !== void 0);
72801
72877
  }
72802
- function isNamedBaseClauseEntry(value) {
72878
+ function isNamedBaseClauseEntry(value, nameIsValid) {
72803
72879
  if (typeof value !== "object" || value === null) return false;
72804
72880
  if (Array.isArray(value)) return false;
72805
72881
  const candidate = value;
72806
72882
  if (!Object.keys(candidate).every((key) => key === "name" || key === "code")) {
72807
72883
  return false;
72808
72884
  }
72809
- if (!isValidCallableIdentifier(candidate.name)) return false;
72885
+ if (!nameIsValid(candidate.name)) return false;
72810
72886
  if (typeof candidate.code !== "string") return false;
72811
72887
  return candidate.code.length > 0;
72812
72888
  }
72813
72889
  function isNeoConstructorBaseArgument(value) {
72814
- return isNamedBaseClauseEntry(value);
72890
+ return isNamedBaseClauseEntry(value, isValidCallableArgumentIdentifier);
72815
72891
  }
72816
72892
  function isNeoConstructorBaseInitializerField(value) {
72817
- return isNamedBaseClauseEntry(value);
72893
+ return isNamedBaseClauseEntry(value, isValidSchemaMemberIdentifier);
72818
72894
  }
72819
72895
  function isNeoClassConstructorBase(value) {
72820
72896
  if (typeof value !== "object" || value === null) return false;
@@ -72830,7 +72906,7 @@ function isNeoClassConstructorBase(value) {
72830
72906
  const argumentTypes = [];
72831
72907
  for (const argument2 of v.argumentTypes) {
72832
72908
  if (!isNSFunctionArgumentTypeInfo(argument2)) return false;
72833
- if (!isValidCallableIdentifier(argument2.name)) return false;
72909
+ if (!isValidCallableArgumentIdentifier(argument2.name)) return false;
72834
72910
  if (parameterNames.has(argument2.name)) return false;
72835
72911
  parameterNames.add(argument2.name);
72836
72912
  argumentTypes.push(argument2);
@@ -72929,6 +73005,7 @@ var init_constructors = __esm({
72929
73005
  init_core();
72930
73006
  init_docs_text2();
72931
73007
  init_member_kinds();
73008
+ init_schema_identifiers();
72932
73009
  init_neoscript();
72933
73010
  REJECTED_CONSTRUCTOR_KEYS = [
72934
73011
  "bodyMode",
@@ -83113,8 +83190,20 @@ function stableValue(value) {
83113
83190
  function stableTypeInfo(value) {
83114
83191
  return JSON.stringify(stableValue(value));
83115
83192
  }
83116
- function isOpaqueCallableIdentifier(value) {
83117
- return typeof value === "string" && OPAQUE_CALLABLE_IDENTIFIER_PATTERN.test(value) && !value.startsWith("__") && !OPAQUE_CALLABLE_RESERVED_NAMES.has(value);
83193
+ function isOpaqueGeneratedIdentifier(value, neoPredicate) {
83194
+ return typeof value === "string" && neoPredicate(value) && isGeneratedCSharpIdentifier(value) && !isGeneratedCSharpReservedKeyword(value);
83195
+ }
83196
+ function isOpaqueSchemaMemberIdentifier(value) {
83197
+ return isOpaqueGeneratedIdentifier(value, isValidNeoProjectMemberIdentifier);
83198
+ }
83199
+ function isOpaqueCallableMemberIdentifier(value) {
83200
+ return isOpaqueSchemaMemberIdentifier(value) && !value.startsWith("__");
83201
+ }
83202
+ function isOpaqueCallableArgumentIdentifier(value) {
83203
+ return isOpaqueGeneratedIdentifier(value, isValidNeoProjectBindingIdentifier) && !value.startsWith("__");
83204
+ }
83205
+ function isOpaqueNSFunctionArgumentIdentifier(value) {
83206
+ return isOpaqueCallableArgumentIdentifier(value) && value !== "value";
83118
83207
  }
83119
83208
  function isOpaqueNSTypeInfo(value, ancestors = /* @__PURE__ */ new Set()) {
83120
83209
  if (!isRecord7(value) || typeof value.required !== "boolean") return false;
@@ -83208,11 +83297,11 @@ function isOpaqueNSFunctionReturnTypeInfo(value) {
83208
83297
  return isOpaqueNSTypeInfo(value);
83209
83298
  }
83210
83299
  function isOpaqueNSFunctionArgumentTypeInfo(value) {
83211
- return isOpaqueNSTypeInfo(value) && isOpaqueCallableIdentifier(value.name) && !opaqueTypeInfoContainsUnknown(value) && hasValidOpaqueParameterDefault(value);
83300
+ return isOpaqueNSTypeInfo(value) && isOpaqueNSFunctionArgumentIdentifier(value.name) && !opaqueTypeInfoContainsUnknown(value) && hasValidOpaqueParameterDefault(value);
83212
83301
  }
83213
83302
  function isOpaqueConstructorArgumentTypeInfo(value) {
83214
83303
  if (!isRecord7(value)) return false;
83215
- return isOpaqueNSTypeInfo(value) && (value.name === "value" || isOpaqueCallableIdentifier(value.name)) && !opaqueTypeInfoContainsUnknown(value) && hasValidOpaqueParameterDefault(value);
83304
+ return isOpaqueNSTypeInfo(value) && isOpaqueCallableArgumentIdentifier(value.name) && !opaqueTypeInfoContainsUnknown(value) && hasValidOpaqueParameterDefault(value);
83216
83305
  }
83217
83306
  function hasValidOpaqueParameterDefault(value) {
83218
83307
  const wrapper = value.defaultValue;
@@ -84665,7 +84754,8 @@ function assertOpaqueBaseClauseListValid(declaredConstructor, spec) {
84665
84754
  `Constructor "${declaredConstructor.id}" has a ${spec.entryLabel} that is not an object.`
84666
84755
  );
84667
84756
  }
84668
- if (!isOpaqueCallableIdentifier(entry.name)) {
84757
+ const nameIsValid = spec.nameKind === "member" ? isOpaqueSchemaMemberIdentifier : isOpaqueCallableArgumentIdentifier;
84758
+ if (!nameIsValid(entry.name)) {
84669
84759
  throw new Error(
84670
84760
  `Constructor "${declaredConstructor.id}" has a ${spec.entryLabel} with an invalid name.`
84671
84761
  );
@@ -84966,7 +85056,7 @@ function assertOpaqueMemberDefaultValueValid(member) {
84966
85056
  }
84967
85057
  function assertOpaqueNSFunctionValid(member, membersById) {
84968
85058
  if (member.kind !== 23) return;
84969
- if (!isOpaqueCallableIdentifier(member.name)) {
85059
+ if (!isOpaqueCallableMemberIdentifier(member.name)) {
84970
85060
  throw new Error(`NSFunction "${member.id}" name is invalid.`);
84971
85061
  }
84972
85062
  if (member.storage !== void 0 && member.storage !== null) {
@@ -85102,34 +85192,14 @@ function assertOpaqueNSFunctionValid(member, membersById) {
85102
85192
  deferred: member.deferred
85103
85193
  });
85104
85194
  }
85105
- var NEO_OBJECT_WORLD_KIND, READ_ONLY_SYNTHETIC_VALUE_ID_PREFIX2, OPAQUE_CALLABLE_IDENTIFIER_PATTERN, OPAQUE_CALLABLE_RESERVED_NAMES, REJECTED_OPAQUE_CONSTRUCTOR_KEYS, OPAQUE_INITIALIZER_KEYS, OPAQUE_BASE_ARGUMENTS_SPEC, OPAQUE_BASE_INITIALIZER_FIELDS_SPEC;
85195
+ var NEO_OBJECT_WORLD_KIND, READ_ONLY_SYNTHETIC_VALUE_ID_PREFIX2, REJECTED_OPAQUE_CONSTRUCTOR_KEYS, OPAQUE_INITIALIZER_KEYS, OPAQUE_BASE_ARGUMENTS_SPEC, OPAQUE_BASE_INITIALIZER_FIELDS_SPEC;
85106
85196
  var init_projectInterfaceValidation = __esm({
85107
85197
  "../convex/projectInterfaceValidation.ts"() {
85108
85198
  "use strict";
85109
85199
  init_projectVariantValidation();
85200
+ init_src();
85110
85201
  NEO_OBJECT_WORLD_KIND = "object";
85111
85202
  READ_ONLY_SYNTHETIC_VALUE_ID_PREFIX2 = "__neo_readonly_default:";
85112
- OPAQUE_CALLABLE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
85113
- OPAQUE_CALLABLE_RESERVED_NAMES = /* @__PURE__ */ new Set([
85114
- "this",
85115
- "root",
85116
- "context",
85117
- "value",
85118
- "true",
85119
- "false",
85120
- "null",
85121
- "void",
85122
- "if",
85123
- "else",
85124
- "return",
85125
- "throw",
85126
- "var",
85127
- "int",
85128
- "float",
85129
- "decimal",
85130
- "string",
85131
- "bool"
85132
- ]);
85133
85203
  REJECTED_OPAQUE_CONSTRUCTOR_KEYS = [
85134
85204
  "bodyMode",
85135
85205
  "uiAction",
@@ -85140,6 +85210,7 @@ var init_projectInterfaceValidation = __esm({
85140
85210
  OPAQUE_BASE_ARGUMENTS_SPEC = {
85141
85211
  authoredKey: "baseArguments",
85142
85212
  compiledKey: "compiledBaseArguments",
85213
+ nameKind: "parameter",
85143
85214
  entryLabel: "base argument",
85144
85215
  compiledLabel: "compiled base arguments",
85145
85216
  clauseLabel: "a base call"
@@ -85147,6 +85218,7 @@ var init_projectInterfaceValidation = __esm({
85147
85218
  OPAQUE_BASE_INITIALIZER_FIELDS_SPEC = {
85148
85219
  authoredKey: "baseInitializerFields",
85149
85220
  compiledKey: "compiledBaseInitializerFields",
85221
+ nameKind: "member",
85150
85222
  entryLabel: "base initializer field",
85151
85223
  compiledLabel: "compiled base initializer fields",
85152
85224
  clauseLabel: "a base initializer block"
@@ -85158,34 +85230,37 @@ var init_projectInterfaceValidation = __esm({
85158
85230
  function isRecord8(value) {
85159
85231
  return typeof value === "object" && value !== null && !Array.isArray(value);
85160
85232
  }
85161
- function assertIdentifier3(value, label) {
85162
- if (isValidSchemaAuthoredIdentifier(value)) return;
85233
+ function assertIdentifier(value, label, predicate) {
85234
+ if (predicate(value)) return;
85163
85235
  throw new Error(
85164
85236
  `${label} must be a valid Neo/codegen identifier; use letters, digits, and underscores, begin with a letter or underscore, and avoid reserved language keywords.`
85165
85237
  );
85166
85238
  }
85167
- function assertArgumentIdentifiers(value, ownerLabel) {
85239
+ function assertArgumentIdentifiers(value, ownerLabel, predicate) {
85168
85240
  if (!Array.isArray(value)) return;
85169
85241
  for (let index = 0; index < value.length; index += 1) {
85170
85242
  const argument2 = value[index];
85171
85243
  if (!isRecord8(argument2)) continue;
85172
- assertIdentifier3(
85244
+ assertIdentifier(
85173
85245
  argument2.name,
85174
- `${ownerLabel} parameter ${index + 1} name ${JSON.stringify(argument2.name)}`
85246
+ `${ownerLabel} parameter ${index + 1} name ${JSON.stringify(argument2.name)}`,
85247
+ predicate
85175
85248
  );
85176
85249
  }
85177
85250
  }
85178
85251
  function assertClassIdentifiers(recordId, value) {
85179
85252
  if (!isRecord8(value)) return;
85180
- assertIdentifier3(
85253
+ assertIdentifier(
85181
85254
  value.name,
85182
- `Class "${recordId}" name ${JSON.stringify(value.name)}`
85255
+ `Class "${recordId}" name ${JSON.stringify(value.name)}`,
85256
+ isValidSchemaAuthoredIdentifier
85183
85257
  );
85184
85258
  if (isRecord8(value.schema)) {
85185
85259
  for (const schemaKey of Object.keys(value.schema)) {
85186
- assertIdentifier3(
85260
+ assertIdentifier(
85187
85261
  schemaKey,
85188
- `Class "${recordId}" schema key ${JSON.stringify(schemaKey)}`
85262
+ `Class "${recordId}" schema key ${JSON.stringify(schemaKey)}`,
85263
+ isValidSchemaMemberIdentifier
85189
85264
  );
85190
85265
  }
85191
85266
  }
@@ -85193,17 +85268,19 @@ function assertClassIdentifiers(recordId, value) {
85193
85268
  for (let index = 0; index < value.genericParams.length; index += 1) {
85194
85269
  const parameter4 = value.genericParams[index];
85195
85270
  if (!isRecord8(parameter4)) continue;
85196
- assertIdentifier3(
85271
+ assertIdentifier(
85197
85272
  parameter4.name,
85198
- `Class "${recordId}" generic parameter ${index + 1} name ${JSON.stringify(parameter4.name)}`
85273
+ `Class "${recordId}" generic parameter ${index + 1} name ${JSON.stringify(parameter4.name)}`,
85274
+ isValidSchemaBindingIdentifier
85199
85275
  );
85200
85276
  }
85201
85277
  }
85202
85278
  function assertEnumIdentifiers(recordId, value) {
85203
85279
  if (!isRecord8(value)) return;
85204
- assertIdentifier3(
85280
+ assertIdentifier(
85205
85281
  value.name,
85206
- `Enum "${recordId}" name ${JSON.stringify(value.name)}`
85282
+ `Enum "${recordId}" name ${JSON.stringify(value.name)}`,
85283
+ isValidSchemaAuthoredIdentifier
85207
85284
  );
85208
85285
  if (!isRecord8(value.options)) return;
85209
85286
  const optionIdsByFoldedName = /* @__PURE__ */ new Map();
@@ -85219,9 +85296,10 @@ function assertEnumIdentifiers(recordId, value) {
85219
85296
  `Enum "${recordId}" option "${optionId}" must embed the same stable id.`
85220
85297
  );
85221
85298
  }
85222
- assertIdentifier3(
85299
+ assertIdentifier(
85223
85300
  option.name,
85224
- `Enum "${recordId}" option "${optionId}" name ${JSON.stringify(option.name)}`
85301
+ `Enum "${recordId}" option "${optionId}" name ${JSON.stringify(option.name)}`,
85302
+ isValidSchemaMemberIdentifier
85225
85303
  );
85226
85304
  const foldedName = option.name.toLowerCase();
85227
85305
  const collidingOptionId = optionIdsByFoldedName.get(foldedName);
@@ -85235,20 +85313,23 @@ function assertEnumIdentifiers(recordId, value) {
85235
85313
  }
85236
85314
  function assertInterfaceIdentifiers(recordId, value) {
85237
85315
  if (!isRecord8(value)) return;
85238
- assertIdentifier3(
85316
+ assertIdentifier(
85239
85317
  value.name,
85240
- `Interface "${recordId}" name ${JSON.stringify(value.name)}`
85318
+ `Interface "${recordId}" name ${JSON.stringify(value.name)}`,
85319
+ isValidSchemaAuthoredIdentifier
85241
85320
  );
85242
85321
  if (!isRecord8(value.members)) return;
85243
85322
  for (const [memberKey, member] of Object.entries(value.members)) {
85244
- assertIdentifier3(
85323
+ assertIdentifier(
85245
85324
  memberKey,
85246
- `Interface "${recordId}" member name ${JSON.stringify(memberKey)}`
85325
+ `Interface "${recordId}" member name ${JSON.stringify(memberKey)}`,
85326
+ isValidSchemaMemberIdentifier
85247
85327
  );
85248
85328
  if (!isRecord8(member) || member.kind !== "function") continue;
85249
85329
  assertArgumentIdentifiers(
85250
85330
  member.argumentTypes,
85251
- `Interface "${recordId}" function "${memberKey}"`
85331
+ `Interface "${recordId}" function "${memberKey}"`,
85332
+ isValidSchemaNSFunctionBindingIdentifier
85252
85333
  );
85253
85334
  }
85254
85335
  }
@@ -85260,15 +85341,17 @@ function isCallableOrPropertyMemberKind(value) {
85260
85341
  function assertMemberIdentifiers(recordId, value, directlyAuthoredMemberIds) {
85261
85342
  if (!isRecord8(value)) return;
85262
85343
  if (directlyAuthoredMemberIds.has(recordId) || isCallableOrPropertyMemberKind(value)) {
85263
- assertIdentifier3(
85344
+ assertIdentifier(
85264
85345
  value.name,
85265
- `Member "${recordId}" name ${JSON.stringify(value.name)}`
85346
+ `Member "${recordId}" name ${JSON.stringify(value.name)}`,
85347
+ isValidSchemaMemberIdentifier
85266
85348
  );
85267
85349
  }
85268
85350
  if (value.kind !== 13 && value.kind !== 23) return;
85269
85351
  assertArgumentIdentifiers(
85270
85352
  value.argumentTypes,
85271
- `Function member "${recordId}"`
85353
+ `Function member "${recordId}"`,
85354
+ value.kind === 23 ? isValidSchemaNSFunctionBindingIdentifier : isValidSchemaBindingIdentifier
85272
85355
  );
85273
85356
  }
85274
85357
  function assertSchemaIdentifierWriteChangesValid(changes, directlyAuthoredMemberIds) {
@@ -112267,7 +112350,7 @@ var init_registry2 = __esm({
112267
112350
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
112268
112351
  formatVersion: 3,
112269
112352
  contractVersion: "3.13",
112270
- cliVersion: "0.32.3",
112353
+ cliVersion: "0.32.4",
112271
112354
  projectFileUploadBatchSize: 32,
112272
112355
  documentRecords: {
112273
112356
  member: {
@@ -118862,7 +118945,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
118862
118945
  async function main() {
118863
118946
  const args = parseArgs(process.argv.slice(2));
118864
118947
  if (args.command === "--version") {
118865
- console.log("0.32.3");
118948
+ console.log("0.32.4");
118866
118949
  return;
118867
118950
  }
118868
118951
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.32.3",
3
+ "version": "0.32.4",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -9,7 +9,7 @@ description: >-
9
9
  `@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
10
10
  ---
11
11
 
12
- <!-- reviewed-through-cli: 0.32.3 -->
12
+ <!-- reviewed-through-cli: 0.32.4 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -83,7 +83,7 @@ wrappers.
83
83
  The marker near the top of `SKILL.md` must exactly match the package version:
84
84
 
85
85
  ```html
86
- <!-- reviewed-through-cli: 0.32.3 -->
86
+ <!-- reviewed-through-cli: 0.32.4 -->
87
87
  ```
88
88
 
89
89
  The quoted version above is checked too, so this instruction cannot go stale
@@ -21,10 +21,14 @@ migration, or `.neoflow` file. NeoFlow has its own single-dialogue exception.
21
21
  Persist the declared identifier as the schema name; there is no separate
22
22
  technical/display name. Keep existing IDs stable.
23
23
 
24
- NeoScript keywords are case-sensitive. Lexer-classified type names remain
25
- legal in contextual identifier slots, so a member, parameter, or enum option
26
- may be named `Set` or `Dictionary`; lowercase keywords such as `class` and
27
- `return`, plus the builtin `Math` namespace, remain reserved.
24
+ NeoScript keywords are case-sensitive. Qualified member labels, schema keys,
25
+ registry entries, and enum options occupy their owner's namespace, so they may
26
+ reuse unrelated builtin names such as `Set`, `Dictionary`, `List`, or `Math`.
27
+ Type-token spellings such as `Set` and `Dictionary` are also legal parameters.
28
+ Actual lowercase grammar keywords such as `class` and `return` remain
29
+ reserved. Top-level declarations and bindings retain their own reservations:
30
+ for example, neither may shadow the unqualified builtin `Math` namespace, and
31
+ implicit bindings such as `this`, `root`, and `context` cannot be parameters.
28
32
 
29
33
  ```neo
30
34
  @id("interface-named-id")
@@ -108,8 +108,10 @@ language's `float`-to-`int` conversions: they return `int` for `int` and
108
108
  at runtime. `Round` rounds midpoints to even, matching `decimal.Round(0)`.
109
109
  `Sign` always returns `int`; `Sqrt` takes `int` or `float` only.
110
110
 
111
- `Math` is a qualifier, never a type or a value, and the name is reserved: no
112
- Class, enum, member, parameter, or local may be named `Math`.
111
+ `Math` is an unqualified builtin qualifier, never a type or value, so no Class,
112
+ enum, parameter, or local may shadow it. Qualified members use their owner's
113
+ namespace and may be named `Math`; access one as `this.Math` or
114
+ `SomeValue.Math` without colliding with the builtin qualifier.
113
115
 
114
116
  ## Logical operators
115
117