@neocompose/cli 0.36.2 → 0.36.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/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.36.3] - 2026-08-19
4
+
5
+ ### Fixed
6
+
7
+ - Preserve nullable List and Dictionary entry declarations in persisted
8
+ compiler contexts, and keep abstract stored collection fields writable
9
+ through the concrete subclass storage that implements them. Indexed
10
+ `is`-pattern reads and writes such as `Stacks[index] = null` now agree in
11
+ source analysis, IntelliSense, `neo script check --all`, and push replay.
12
+ - Run `neo script check --all` against one locally reconstructed prospective
13
+ project document instead of fetching a stale server document through a
14
+ separate path. New records, managed files, dialogues, and stored bodies are
15
+ validated with the same source transaction visible to local member bodies.
16
+ - Compile canonical `Reference<NeoImage>(id: ...).Slice(...)` and
17
+ `Reference<NeoAudioClip>(id: ...)` file fallbacks when a pulled file has no
18
+ registry symbol, and accept `List.Repeat<T>(value, count)` when an explicit
19
+ entry type is needed for values such as `null`.
20
+ - Include same-transaction texture and audio import-template changes in the
21
+ prospective document before validating managed-file defaults.
22
+
3
23
  ## [0.36.2] - 2026-08-19
4
24
 
5
25
  ### Fixed
package/dist/neo.mjs CHANGED
@@ -1278,6 +1278,12 @@ function neoScriptRegistryEntryType(typeName) {
1278
1278
  }
1279
1279
  return REGISTRY_ENTRY_TYPES[typeName] ?? null;
1280
1280
  }
1281
+ function neoScriptRegistryReferenceType(entryTypeName) {
1282
+ for (const definition2 of Object.values(REGISTRY_ENTRY_TYPES)) {
1283
+ if (definition2.entryType === entryTypeName) return definition2.refType;
1284
+ }
1285
+ return null;
1286
+ }
1281
1287
  function parameter(name, type) {
1282
1288
  return { name, type };
1283
1289
  }
@@ -11398,6 +11404,19 @@ var init_strict_resolver = __esm({
11398
11404
  expression.pos
11399
11405
  );
11400
11406
  }
11407
+ if (isPrimitive(referencedType, "ImageRef") || isPrimitive(referencedType, "AudioClipRef")) {
11408
+ if (hasProvenanceArgument) {
11409
+ throw new CompileError(
11410
+ `Reference<${referenceTypeArgument.kind === "named" ? referenceTypeArgument.name : "file"}> does not support withProvenance because a project file reference is a file id, not a value-row reference.`,
11411
+ expression.pos
11412
+ );
11413
+ }
11414
+ return literal(
11415
+ referencedType,
11416
+ expression.args[0].value,
11417
+ this.project
11418
+ );
11419
+ }
11401
11420
  return {
11402
11421
  pointer: {
11403
11422
  type: "reference" /* Reference */,
@@ -11407,6 +11426,37 @@ var init_strict_resolver = __esm({
11407
11426
  type: referencedType
11408
11427
  };
11409
11428
  }
11429
+ if (expression.typeArguments && expression.callee.kind === "member" && expression.callee.receiver.kind === "ident" && expression.callee.receiver.name === NEOSCRIPT_LIST_TYPE_NAME) {
11430
+ if (expression.callee.name !== NEOSCRIPT_LIST_REPEAT_NAME) {
11431
+ throw new CompileError(
11432
+ `'${NEOSCRIPT_LIST_TYPE_NAME}' has no generic static member '${expression.callee.name}'.`,
11433
+ expression.pos
11434
+ );
11435
+ }
11436
+ if (expression.typeArguments.length !== 1) {
11437
+ throw new CompileError(
11438
+ `${NEOSCRIPT_LIST_TYPE_NAME}.${NEOSCRIPT_LIST_REPEAT_NAME}<T> requires exactly one entry type argument.`,
11439
+ expression.pos
11440
+ );
11441
+ }
11442
+ const entryTypeArgument = expression.typeArguments[0];
11443
+ if (entryTypeArgument === void 0) {
11444
+ throw new CompileError(
11445
+ `${NEOSCRIPT_LIST_TYPE_NAME}.${NEOSCRIPT_LIST_REPEAT_NAME}<T> requires exactly one entry type argument.`,
11446
+ expression.pos
11447
+ );
11448
+ }
11449
+ return this.resolveListStaticCall(
11450
+ expression.callee.name,
11451
+ expression.args,
11452
+ scope,
11453
+ {
11454
+ kind: "list",
11455
+ elementType: this.resolveType(entryTypeArgument)
11456
+ },
11457
+ expression.pos
11458
+ );
11459
+ }
11410
11460
  if (expression.typeArguments) {
11411
11461
  throw new CompileError(
11412
11462
  "Generic intrinsic calls require a declaration-aware project source context.",
@@ -15209,11 +15259,17 @@ var init_strict_resolver = __esm({
15209
15259
  */
15210
15260
  assertActionControlAccessible(action, operation, pos) {
15211
15261
  const symbol = action.symbol;
15212
- const owner = symbol === void 0 ? void 0 : symbol.inheritedFrom ? this.project.typeById.get(symbol.inheritedFrom.typeId) : [...this.project.typeById.values()].find(
15213
- (type) => type.members.some(
15214
- (candidate) => candidate.id === symbol.id && candidate.inheritedFrom === void 0
15215
- )
15216
- );
15262
+ let owner = symbol?.inheritedFrom ? this.project.typeById.get(symbol.inheritedFrom.typeId) : void 0;
15263
+ if (symbol !== void 0 && symbol.inheritedFrom === void 0) {
15264
+ for (const type of this.project.typeById.values()) {
15265
+ if (type.members.some(
15266
+ (candidate) => candidate.id === symbol.id && candidate.inheritedFrom === void 0
15267
+ )) {
15268
+ owner = type;
15269
+ break;
15270
+ }
15271
+ }
15272
+ }
15217
15273
  if (symbol !== void 0 && owner !== void 0 && memberAccessFailure({
15218
15274
  project: this.project,
15219
15275
  context: this.context,
@@ -15535,6 +15591,11 @@ var init_strict_resolver = __esm({
15535
15591
  resolved = { kind: "primitive", name: builtin };
15536
15592
  break;
15537
15593
  }
15594
+ const registryReference = neoScriptRegistryReferenceType(type.name);
15595
+ if (registryReference) {
15596
+ resolved = registryReference;
15597
+ break;
15598
+ }
15538
15599
  const named = this.project.typeByName.get(type.name);
15539
15600
  if (!named)
15540
15601
  throw new CompileError(`Unknown type '${type.name}'`, type.pos);
@@ -32603,10 +32664,8 @@ function attachConstructorSignature(type, environment) {
32603
32664
  type.id,
32604
32665
  environment
32605
32666
  );
32606
- if ([...genericEnvironment.values()].some(
32607
- (binding) => binding.kind === "unbound"
32608
- )) {
32609
- return type;
32667
+ for (const binding of genericEnvironment.values()) {
32668
+ if (binding.kind === "unbound") return type;
32610
32669
  }
32611
32670
  const constructorSignature2 = buildNeoScriptConstructorSignature(
32612
32671
  type.id,
@@ -32939,7 +32998,7 @@ function memberSymbol(member, schemaKey, environment, field) {
32939
32998
  writable: false
32940
32999
  };
32941
33000
  }
32942
- const writable = isReadOnly ? false : kind === "computed" ? computedHasSetter(member, field) : modifier !== "abstract" && member.locked !== true;
33001
+ const writable = isReadOnly ? false : kind === "computed" ? computedHasSetter(member, field) : member.locked !== true;
32943
33002
  const storage = typeof member.storage === "string" ? member.storage : void 0;
32944
33003
  const writability = isReadOnly ? "readOnly" : kind === "computed" ? writable ? "setter" : "readOnly" : !writable ? "readOnly" : storage === "immutable" || storage === "save" || storage === "session" ? storage : isStatic && ownerClassId ? staticDefaultWritability(ownerClassId, environment) : void 0;
32945
33004
  const lookupCollectionMemberId = kind === "lookup" ? string2(member.collectionMemberId, `${field}.collectionMemberId`) : null;
@@ -33475,9 +33534,12 @@ function memberType(member, environment, visiting, field) {
33475
33534
  };
33476
33535
  }
33477
33536
  if (kind === "variant") {
33478
- const variantClass = [...environment.classes.values()].find(
33479
- (candidate) => candidate.name === NEO_VARIANT_TYPE_NAME
33480
- );
33537
+ let variantClass;
33538
+ for (const candidate of environment.classes.values()) {
33539
+ if (candidate.name !== NEO_VARIANT_TYPE_NAME) continue;
33540
+ variantClass = candidate;
33541
+ break;
33542
+ }
33481
33543
  if (variantClass === void 0) return { ...unknownType(), nullable };
33482
33544
  return {
33483
33545
  kind: "named",
@@ -61766,7 +61828,8 @@ function interfaceToLanguageType(neoInterface, context) {
61766
61828
  closure = [neoInterface];
61767
61829
  }
61768
61830
  const members = /* @__PURE__ */ new Map();
61769
- for (const source of [...closure].reverse()) {
61831
+ for (let index = closure.length - 1; index >= 0; index -= 1) {
61832
+ const source = closure[index];
61770
61833
  for (const key of getInterfaceMemberKeyOrder(source)) {
61771
61834
  const member = source.members[key];
61772
61835
  if (!member) continue;
@@ -62013,13 +62076,11 @@ function memberRuntimeType(record3, context, seen = /* @__PURE__ */ new Set(), g
62013
62076
  const projectedEntry = entry ? substituteForGenericEnvironment(entry, genericEnvironment, context) : null;
62014
62077
  return {
62015
62078
  kind: "list",
62016
- elementType: projectedEntry ? requiredType(
62017
- memberRuntimeType(
62018
- projectedEntry,
62019
- context,
62020
- nextSeen,
62021
- genericEnvironment
62022
- )
62079
+ elementType: projectedEntry ? memberRuntimeType(
62080
+ projectedEntry,
62081
+ context,
62082
+ nextSeen,
62083
+ genericEnvironment
62023
62084
  ) : UNKNOWN_TYPE2,
62024
62085
  listMemberId: record3.id,
62025
62086
  nullable: !required2
@@ -62032,13 +62093,11 @@ function memberRuntimeType(record3, context, seen = /* @__PURE__ */ new Set(), g
62032
62093
  return {
62033
62094
  kind: "dictionary",
62034
62095
  keyType: member.keyKind === "enum" && member.keyEnumId ? namedType(member.keyEnumId, true) : primitive2("string", true),
62035
- valueType: projectedEntry ? requiredType(
62036
- memberRuntimeType(
62037
- projectedEntry,
62038
- context,
62039
- nextSeen,
62040
- genericEnvironment
62041
- )
62096
+ valueType: projectedEntry ? memberRuntimeType(
62097
+ projectedEntry,
62098
+ context,
62099
+ nextSeen,
62100
+ genericEnvironment
62042
62101
  ) : UNKNOWN_TYPE2,
62043
62102
  nullable: !required2
62044
62103
  };
@@ -63037,7 +63096,10 @@ function initializerReferencesLexicalThis(source) {
63037
63096
  }
63038
63097
  function initializerReferencesAnyIdentifier(source, names) {
63039
63098
  const identifiers = initializerReferencedIdentifiers(source);
63040
- return [...names].some((name) => identifiers.has(name));
63099
+ for (const name of names) {
63100
+ if (identifiers.has(name)) return true;
63101
+ }
63102
+ return false;
63041
63103
  }
63042
63104
  function compileNSPropertyBodies(args) {
63043
63105
  if (args.member.kind !== 10 /* NSProperty */) return;
@@ -63639,7 +63701,7 @@ function declaredConstructorsOfClass(constructors, schemaClass2) {
63639
63701
  });
63640
63702
  }
63641
63703
  function argumentNameSetKey2(names) {
63642
- return [...names].map((name) => name.toLowerCase()).sort().join(", ");
63704
+ return names.map((name) => name.toLowerCase()).sort().join(", ");
63643
63705
  }
63644
63706
  function describeConstructorOverloads(constructors) {
63645
63707
  return constructors.map(
@@ -63739,7 +63801,7 @@ function resolveMemberDeclaredTypeInfoInternal(member, members, seen) {
63739
63801
  return {
63740
63802
  type: resolved.kind,
63741
63803
  required: resolved.required,
63742
- entryTypeInfo: { ...entryTypeInfo, required: true },
63804
+ entryTypeInfo,
63743
63805
  ...isMemberDictionaryBase(resolved) && resolved.keyEnumId ? { keyEnumId: resolved.keyEnumId } : {}
63744
63806
  };
63745
63807
  }
@@ -92000,7 +92062,12 @@ function materializeAuthoredListItems(args) {
92000
92062
  args.member.entryMemberId
92001
92063
  );
92002
92064
  const unordered = listKindOf(args.member) === "unordered";
92003
- const ids = unordered ? [...args.authoredRows.values()].filter((row) => row.containerId === args.row.id).map((row) => row.id) : args.row.value;
92065
+ const ids = unordered ? [] : args.row.value;
92066
+ if (unordered) {
92067
+ for (const row of args.authoredRows.values()) {
92068
+ if (row.containerId === args.row.id) ids.push(row.id);
92069
+ }
92070
+ }
92004
92071
  const materializedIds = [];
92005
92072
  for (const childId of ids) {
92006
92073
  if (typeof childId !== "string") {
@@ -92259,6 +92326,12 @@ function initBackedValueRow(value) {
92259
92326
  if (!isMemberValue(value)) return null;
92260
92327
  return isInitValueContent(value) ? value : null;
92261
92328
  }
92329
+ function valueIdsFromRows(explicitRows, sweepRows) {
92330
+ const ids = /* @__PURE__ */ new Set();
92331
+ for (const row of explicitRows) ids.add(row.id);
92332
+ for (const row of sweepRows) ids.add(row.id);
92333
+ return ids;
92334
+ }
92262
92335
  function prepareServerOwnedValueInitializerBodies(args) {
92263
92336
  const explicitRows = /* @__PURE__ */ new Map();
92264
92337
  for (let index = 0; index < args.prepared.length; index += 1) {
@@ -92280,10 +92353,7 @@ function prepareServerOwnedValueInitializerBodies(args) {
92280
92353
  args.postDocument,
92281
92354
  args.prepared
92282
92355
  );
92283
- const targetIds = /* @__PURE__ */ new Set([
92284
- ...[...explicitRows.values()].map((row) => row.id),
92285
- ...sweepRows.map((row) => row.id)
92286
- ]);
92356
+ const targetIds = valueIdsFromRows(explicitRows.values(), sweepRows);
92287
92357
  const valuesById = new Map(
92288
92358
  committedDocument.values.map((value) => [value.id, value])
92289
92359
  );
@@ -92410,10 +92480,7 @@ function prepareServerOwnedDelegateValueBodies(args) {
92410
92480
  args.postDocument,
92411
92481
  args.prepared
92412
92482
  );
92413
- const targetIds = /* @__PURE__ */ new Set([
92414
- ...[...explicitRows.values()].map((row) => row.id),
92415
- ...sweepRows.map((row) => row.id)
92416
- ]);
92483
+ const targetIds = valueIdsFromRows(explicitRows.values(), sweepRows);
92417
92484
  const rootOwnerByValueId = /* @__PURE__ */ new Map();
92418
92485
  const delegateScope = withVariantOwnershipRoots(
92419
92486
  committedDocument,
@@ -92964,6 +93031,20 @@ function applyProjectVersionWriteChanges(document, changes) {
92964
93031
  changes,
92965
93032
  "project-file"
92966
93033
  ),
93034
+ // Import-setting templates are part of the same file graph. A new file
93035
+ // may select a new template in one source transaction, and default-value
93036
+ // materialization validates that relationship immediately against this
93037
+ // post-write document.
93038
+ textureTemplates: applyArrayChanges(
93039
+ document.textureTemplates ?? [],
93040
+ changes,
93041
+ "unity-texture-template"
93042
+ ),
93043
+ audioClipTemplates: applyArrayChanges(
93044
+ document.audioClipTemplates ?? [],
93045
+ changes,
93046
+ "unity-audio-clip-template"
93047
+ ),
92967
93048
  internalRecordRelations: applyArrayChanges(
92968
93049
  document.internalRecordRelations ?? [],
92969
93050
  changes,
@@ -94884,7 +94965,7 @@ function listVirtualProjectSourceFilesV4(files) {
94884
94965
  const kind = neoProjectSourceKind(file.path);
94885
94966
  return kind !== null && isNeoProjectProductionSourceKind(kind) && !neoProjectPathHasIgnoredDirectory(file.path);
94886
94967
  });
94887
- const sorted = [...selected].sort(
94968
+ const sorted = selected.sort(
94888
94969
  (left, right) => compareWorkspacePaths(left.path, right.path)
94889
94970
  );
94890
94971
  for (let index = 1; index < sorted.length; index += 1) {
@@ -95525,14 +95606,24 @@ function computeWorkspaceStatus(workspace, options) {
95525
95606
  (binary) => binary.action !== "unchanged" && binary.action !== "converged"
95526
95607
  );
95527
95608
  reportPhase("binary-inspection");
95528
- const invalidatedFileIds = /* @__PURE__ */ new Set([
95529
- ...binaryFiles.filter(
95530
- (binary) => binary.action === "create" || binary.action === "upload"
95531
- ).map((binary) => binary.fileId),
95532
- ...options.trustedPendingProjectFiles?.keys() ?? []
95533
- ]);
95609
+ const invalidatedFileIds = /* @__PURE__ */ new Set();
95610
+ for (const binary of binaryFiles) {
95611
+ if (binary.action === "create" || binary.action === "upload") {
95612
+ invalidatedFileIds.add(binary.fileId);
95613
+ }
95614
+ }
95615
+ for (const fileId of options.trustedPendingProjectFiles?.keys() ?? []) {
95616
+ invalidatedFileIds.add(fileId);
95617
+ }
95618
+ if (options.skipProjectBinaryInspection) {
95619
+ for (const record3 of reconstructed3.values()) {
95620
+ if (record3.recordKind === "project-file" && record3.fullData.status !== "uploaded") {
95621
+ invalidatedFileIds.add(record3.recordId);
95622
+ }
95623
+ }
95624
+ }
95534
95625
  for (const message of validateFinalizedFileAssignmentsV4(
95535
- [...reconstructed3.values()].map((record3) => ({
95626
+ Array.from(reconstructed3.values(), (record3) => ({
95536
95627
  recordKind: record3.recordKind,
95537
95628
  data: record3.fullData
95538
95629
  })),
@@ -95585,10 +95676,13 @@ function computeWorkspaceStatus(workspace, options) {
95585
95676
  intent: createNeoCliPushIntent(change),
95586
95677
  expectedBaseContentHash: change.kind === "create" ? null : change.casBaseHash ?? null
95587
95678
  })),
95588
- authoredValueSeeds: [...authoredValueSeeds].map(([memberId, seed]) => ({
95589
- memberId,
95590
- ...seed
95591
- }))
95679
+ authoredValueSeeds: Array.from(
95680
+ authoredValueSeeds,
95681
+ ([memberId, seed]) => ({
95682
+ memberId,
95683
+ ...seed
95684
+ })
95685
+ )
95592
95686
  });
95593
95687
  } catch (error) {
95594
95688
  parseErrors.push(
@@ -95911,12 +96005,23 @@ function prospectiveAnimationRecords(base, reconstructed3, changes, seeds) {
95911
96005
  const key = recordStateKey(change.recordKind, change.recordId);
95912
96006
  if (change.kind === "delete") prospective.delete(key);
95913
96007
  }
95914
- const projectRecord = [...prospective.values()].find(
95915
- (record3) => record3.recordKind === "project"
95916
- ) ?? [...reconstructed3.values()].filter((record3) => record3.recordKind === "project").map((record3) => ({
95917
- recordKind: record3.recordKind,
95918
- data: record3.fullData
95919
- }))[0];
96008
+ let projectRecord;
96009
+ for (const record3 of prospective.values()) {
96010
+ if (record3.recordKind === "project") {
96011
+ projectRecord = record3;
96012
+ break;
96013
+ }
96014
+ }
96015
+ if (projectRecord === void 0) {
96016
+ for (const record3 of reconstructed3.values()) {
96017
+ if (record3.recordKind !== "project") continue;
96018
+ projectRecord = {
96019
+ recordKind: record3.recordKind,
96020
+ data: record3.fullData
96021
+ };
96022
+ break;
96023
+ }
96024
+ }
95920
96025
  const projectId = projectRecord?.data.id;
95921
96026
  const seedEnvelope = typeof projectId === "string" ? { projectId, createdAt: 0, updatedAt: 0 } : {};
95922
96027
  for (const [key, record3] of reconstructed3) {
@@ -97317,43 +97422,47 @@ function compilePulledMemberInitializerBodyV4(document, memberId, compilationPro
97317
97422
  }
97318
97423
  function readPulledProjectDocumentV4(records2) {
97319
97424
  const raw = structuredClone(
97320
- pulledProjectDocumentRaw(replayWorkspace(records2))
97321
- );
97322
- return readProjectDocument(
97323
- completeProspectiveMemberCreateEnvelopes(
97324
- completeProspectiveLocalizedTexts(raw)
97325
- ),
97326
- {
97327
- constructors: "authored-or-compiled",
97328
- identities: "prospective",
97329
- members: "authored-or-compiled"
97330
- }
97425
+ pulledProjectDocumentRaw(
97426
+ replayWorkspace(completeProspectiveRecordCreateEnvelopes(records2))
97427
+ )
97331
97428
  );
97429
+ return readProjectDocument(completeProspectiveLocalizedTexts(raw), {
97430
+ constructors: "authored-or-compiled",
97431
+ identities: "prospective",
97432
+ members: "authored-or-compiled"
97433
+ });
97332
97434
  }
97333
- function completeProspectiveMemberCreateEnvelopes(raw) {
97334
- const members = raw.members;
97335
- if (!Array.isArray(members)) return raw;
97336
- if (!members.some(isPendingMemberWithoutCreateEnvelope)) return raw;
97337
- const project = raw.project;
97338
- if (!isObjectRecord2(project) || typeof project.id !== "string") {
97435
+ function completeProspectiveRecordCreateEnvelopes(records2) {
97436
+ let project;
97437
+ for (const record3 of records2.values()) {
97438
+ if (!record3.deleted && record3.recordKind === "project" && isObjectRecord2(record3.data)) {
97439
+ project = record3;
97440
+ break;
97441
+ }
97442
+ }
97443
+ const projectId = isObjectRecord2(project?.data) ? project.data.id : null;
97444
+ if (typeof projectId !== "string") {
97339
97445
  throw new Error(
97340
- "Pending source-authored members need the server create envelope, but the project record has no id."
97446
+ "Prospective source-authored records need the server create envelope, but the project record has no id."
97341
97447
  );
97342
97448
  }
97343
- return {
97344
- ...raw,
97345
- members: members.map(
97346
- (member) => isPendingMemberWithoutCreateEnvelope(member) ? {
97347
- projectId: project.id,
97449
+ const completed = /* @__PURE__ */ new Map();
97450
+ for (const [key, record3] of records2) {
97451
+ if (record3.deleted || record3.recordKind === "project" || !isObjectRecord2(record3.data) || typeof record3.data.id !== "string" || typeof record3.data.projectId === "string" && typeof record3.data.createdAt === "number" && typeof record3.data.updatedAt === "number") {
97452
+ completed.set(key, record3);
97453
+ continue;
97454
+ }
97455
+ completed.set(key, {
97456
+ ...record3,
97457
+ data: {
97458
+ projectId,
97348
97459
  createdAt: 0,
97349
97460
  updatedAt: 0,
97350
- ...member
97351
- } : member
97352
- )
97353
- };
97354
- }
97355
- function isPendingMemberWithoutCreateEnvelope(value) {
97356
- return isObjectRecord2(value) && typeof value.id === "string" && value.id.startsWith("__pending__:") && (typeof value.projectId !== "string" || typeof value.createdAt !== "number" || typeof value.updatedAt !== "number");
97461
+ ...record3.data
97462
+ }
97463
+ });
97464
+ }
97465
+ return completed;
97357
97466
  }
97358
97467
  function completeProspectiveLocalizedTexts(raw) {
97359
97468
  const localizedTexts = raw.localizedTexts;
@@ -109225,7 +109334,7 @@ function qualifiedMemberLabel(thisClass, member) {
109225
109334
  if (typeof thisClass.name !== "string") return `'${memberName}'`;
109226
109335
  return `'${thisClass.name}.${memberName}'`;
109227
109336
  }
109228
- function analyzeWorkspaceProjectManifestV4(workspace) {
109337
+ function analyzeWorkspaceProjectV4(workspace) {
109229
109338
  const status = computeWorkspaceStatus2(workspace, {
109230
109339
  skipProjectBinaryInspection: true
109231
109340
  });
@@ -109250,13 +109359,35 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
109250
109359
  data: record3.fullData
109251
109360
  });
109252
109361
  }
109253
- return documentsToProjectSchemaManifest(documents);
109362
+ const records2 = /* @__PURE__ */ new Map();
109363
+ for (const record3 of status.reconstructed.values()) {
109364
+ records2.set(`${record3.recordKind}:${record3.recordId}`, {
109365
+ recordKind: record3.recordKind,
109366
+ recordId: record3.recordId,
109367
+ contentHash: "local-script-check",
109368
+ deleted: false,
109369
+ data: record3.fullData
109370
+ });
109371
+ }
109372
+ return {
109373
+ manifest: documentsToProjectSchemaManifest(documents),
109374
+ document: readDocumentArrays(
109375
+ readPulledProjectDocumentV4(records2)
109376
+ )
109377
+ };
109254
109378
  }
109255
109379
  async function runScript(workspace, command, options, dependencies = {}) {
109256
109380
  let localCheckManifest = null;
109381
+ let localCheckDocument = null;
109257
109382
  const targetsLocalMember = (command === "check" || command === "compile") && options.memberRef !== null;
109258
109383
  if (command === "check" && options.all || targetsLocalMember) {
109259
- localCheckManifest = (dependencies.analyzeWorkspaceManifest ?? analyzeWorkspaceProjectManifestV4)(workspace);
109384
+ if (dependencies.analyzeWorkspaceManifest === void 0) {
109385
+ const localProject = analyzeWorkspaceProjectV4(workspace);
109386
+ localCheckManifest = localProject.manifest;
109387
+ localCheckDocument = localProject.document;
109388
+ } else {
109389
+ localCheckManifest = dependencies.analyzeWorkspaceManifest(workspace);
109390
+ }
109260
109391
  if (targetsLocalMember) {
109261
109392
  const localTarget = resolveLocalScriptMember(
109262
109393
  localCheckManifest,
@@ -109276,6 +109407,10 @@ async function runScript(workspace, command, options, dependencies = {}) {
109276
109407
  return;
109277
109408
  }
109278
109409
  }
109410
+ if (command === "check" && options.all && localCheckManifest !== null && localCheckDocument !== null) {
109411
+ runCheckAll(localCheckDocument, localCheckManifest, options);
109412
+ return;
109413
+ }
109279
109414
  const client = NeoApiClient.forBaseUrl(workspace.config.apiBaseUrl);
109280
109415
  const { raw } = await fetchProjectDocument(workspace);
109281
109416
  const document = readDocumentArrays(raw);
@@ -110219,6 +110354,7 @@ var init_script = __esm({
110219
110354
  init_workspace_status();
110220
110355
  init_source_diagnostics();
110221
110356
  init_project_documents();
110357
+ init_initializer_replay();
110222
110358
  init_push_body_diagnostics();
110223
110359
  RETURN_SHORTHANDS = {
110224
110360
  // MemberKind numerics: Bool=1, Int=2, String=3, Float=4.
@@ -113874,7 +114010,7 @@ var init_registry2 = __esm({
113874
114010
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
113875
114011
  formatVersion: 3,
113876
114012
  contractVersion: "3.14",
113877
- cliVersion: "0.36.2",
114013
+ cliVersion: "0.36.3",
113878
114014
  projectFileUploadBatchSize: 32,
113879
114015
  documentRecords: {
113880
114016
  member: {
@@ -120476,7 +120612,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
120476
120612
  async function main() {
120477
120613
  const args = parseArgs(process.argv.slice(2));
120478
120614
  if (args.command === "--version") {
120479
- console.log("0.36.2");
120615
+ console.log("0.36.3");
120480
120616
  return;
120481
120617
  }
120482
120618
  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.36.2",
3
+ "version": "0.36.3",
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.36.2 -->
12
+ <!-- reviewed-through-cli: 0.36.3 -->
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.36.2 -->
86
+ <!-- reviewed-through-cli: 0.36.3 -->
87
87
  ```
88
88
 
89
89
  The quoted version above is checked too, so this instruction cannot go stale
@@ -78,6 +78,11 @@ neo script eval --function Outpost.RefreshUnlock --this-value <id> --args '[3]'
78
78
 
79
79
  Prefer `--json` for automation.
80
80
 
81
+ `neo script check --all` reconstructs the prospective project entirely from
82
+ the local workspace. It checks local schema bodies and stored dialogue,
83
+ migration, and text-variable bodies against that same source transaction, so
84
+ new declarations do not depend on a prior push or a network fetch.
85
+
81
86
  Inside an inline Class body, unqualified names resolve against that Class;
82
87
  invoke delegate and action members directly with `Selector()` or `OnChanged()`.
83
88
  Spell a zero-argument action as bare `NeoAction`; type arguments name action
@@ -196,11 +201,13 @@ instead of hand-counting a literal or looping around `Add`:
196
201
  List<int> scores = List.Repeat(0, 10);
197
202
  ```
198
203
 
199
- The entry type is inferred from the value and joined with the assignment
200
- context, exactly like a list literal, so assigning `List.Repeat(0, 4)` to a
201
- `List<float>` widens the entries to `float`. Never spell type arguments on the
202
- qualifier: `List<int>.Repeat(0, 3)` is an error, and bare `List` is a
203
- qualifier, not a value.
204
+ The entry type is normally inferred from the value and joined with the
205
+ assignment context, exactly like a list literal, so assigning
206
+ `List.Repeat(0, 4)` to a `List<float>` widens the entries to `float`. When the
207
+ value cannot carry the type by itself, use a call-site type argument, for
208
+ example `List.Repeat<InventoryItemStack?>(null, slotCount)`. Never spell type
209
+ arguments on the qualifier: `List<int>.Repeat(0, 3)` is an error, and bare
210
+ `List` is a qualifier, not a value.
204
211
 
205
212
  `count` must be an `int` — a `float` count is a compile error, and a negative
206
213
  count fails at runtime with `List.Repeat count must be non-negative; got