@neocompose/cli 0.36.1 → 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 +32 -0
- package/dist/neo.mjs +276 -97
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +1 -1
- package/skills/neocompose-cli/references/cli-development.md +1 -1
- package/skills/neocompose-cli/references/declarations-and-construction.md +4 -0
- package/skills/neocompose-cli/references/neoscript.md +12 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
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
|
+
|
|
23
|
+
## [0.36.2] - 2026-08-19
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Report invalid ordinary member initializers at their authored file and token
|
|
28
|
+
in the CLI and editor. C# numeric suffixes such as `0f` now explain that the
|
|
29
|
+
suffix should be removed instead of surfacing as `<project>:1:1` with an EOF
|
|
30
|
+
parser error.
|
|
31
|
+
- Accept `null` as the literal default of a nullable `NeoDelegate`, preventing
|
|
32
|
+
valid pending delegate members from failing prospective project,
|
|
33
|
+
initializer-materialization, and animation validation.
|
|
34
|
+
|
|
3
35
|
## [0.36.1] - 2026-08-19
|
|
4
36
|
|
|
5
37
|
### 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
|
-
|
|
15213
|
-
|
|
15214
|
-
|
|
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);
|
|
@@ -22973,7 +23034,15 @@ function validateDeclaration(uri, declaration, documentKind, environment, diagno
|
|
|
22973
23034
|
scope.set(member.name, semanticType(member.type));
|
|
22974
23035
|
}
|
|
22975
23036
|
for (const member of declaration.members) {
|
|
22976
|
-
validateMember(
|
|
23037
|
+
validateMember(
|
|
23038
|
+
uri,
|
|
23039
|
+
member,
|
|
23040
|
+
declaration.name,
|
|
23041
|
+
documentKind,
|
|
23042
|
+
scope,
|
|
23043
|
+
environment,
|
|
23044
|
+
diagnostics
|
|
23045
|
+
);
|
|
22977
23046
|
}
|
|
22978
23047
|
if (declaration.kind === "class") {
|
|
22979
23048
|
validateRetiredParameterReads(uri, declaration, scope, diagnostics);
|
|
@@ -23243,7 +23312,7 @@ function slotPosition(start, pos) {
|
|
|
23243
23312
|
}
|
|
23244
23313
|
return { line: start.line + pos.line - 1, character: pos.column - 1 };
|
|
23245
23314
|
}
|
|
23246
|
-
function validateMember(uri, member, documentKind, ownerScope, environment, diagnostics) {
|
|
23315
|
+
function validateMember(uri, member, ownerName, documentKind, ownerScope, environment, diagnostics) {
|
|
23247
23316
|
const memberType2 = semanticType(member.type);
|
|
23248
23317
|
validateAnnotations(
|
|
23249
23318
|
uri,
|
|
@@ -23285,7 +23354,11 @@ function validateMember(uri, member, documentKind, ownerScope, environment, diag
|
|
|
23285
23354
|
environment,
|
|
23286
23355
|
member.initializer.range,
|
|
23287
23356
|
diagnostics,
|
|
23288
|
-
anchorOf(member.initializer)
|
|
23357
|
+
anchorOf(member.initializer),
|
|
23358
|
+
{
|
|
23359
|
+
code: "invalid-project-member-initializer",
|
|
23360
|
+
label: `Member '${ownerName}.${member.name}' initializer`
|
|
23361
|
+
}
|
|
23289
23362
|
);
|
|
23290
23363
|
}
|
|
23291
23364
|
if (documentKind === "flow" && member.flowInitializer?.body?.kind === "block") {
|
|
@@ -23789,7 +23862,7 @@ function settingsClassFields(name) {
|
|
|
23789
23862
|
function anchorOf(source) {
|
|
23790
23863
|
return { text: source.text, start: source.range.start };
|
|
23791
23864
|
}
|
|
23792
|
-
function validateExpressionText(uri, text, expected, scope, environment, range2, diagnostics, anchor) {
|
|
23865
|
+
function validateExpressionText(uri, text, expected, scope, environment, range2, diagnostics, anchor, syntaxDiagnostic) {
|
|
23793
23866
|
try {
|
|
23794
23867
|
validateExpression(
|
|
23795
23868
|
parseExpression(text),
|
|
@@ -23803,7 +23876,37 @@ function validateExpressionText(uri, text, expected, scope, environment, range2,
|
|
|
23803
23876
|
);
|
|
23804
23877
|
} catch (error) {
|
|
23805
23878
|
if (!(error instanceof CompileError)) throw error;
|
|
23879
|
+
if (syntaxDiagnostic !== void 0) {
|
|
23880
|
+
const errorRange = anchor === void 0 ? range2 : anchorSpan(
|
|
23881
|
+
anchor,
|
|
23882
|
+
{ line: error.line, column: error.column },
|
|
23883
|
+
anchorOffset(anchor, error) < text.length ? 1 : 0
|
|
23884
|
+
);
|
|
23885
|
+
pushDiagnostic(
|
|
23886
|
+
diagnostics,
|
|
23887
|
+
uri,
|
|
23888
|
+
errorRange,
|
|
23889
|
+
syntaxDiagnostic.code,
|
|
23890
|
+
memberInitializerSyntaxMessage(syntaxDiagnostic.label, text, error)
|
|
23891
|
+
);
|
|
23892
|
+
return;
|
|
23893
|
+
}
|
|
23894
|
+
}
|
|
23895
|
+
}
|
|
23896
|
+
function memberInitializerSyntaxMessage(label, text, error) {
|
|
23897
|
+
const anchor = {
|
|
23898
|
+
text,
|
|
23899
|
+
start: { line: 0, character: 0 }
|
|
23900
|
+
};
|
|
23901
|
+
const offset = anchorOffset(anchor, error);
|
|
23902
|
+
const suffix = text[offset];
|
|
23903
|
+
const previous = text[offset - 1];
|
|
23904
|
+
const next = text[offset + 1];
|
|
23905
|
+
if (suffix !== void 0 && previous !== void 0 && /[fFdDmM]/u.test(suffix) && /[0-9]/u.test(previous) && (next === void 0 || !/[A-Za-z0-9_]/u.test(next))) {
|
|
23906
|
+
return `${label} uses unsupported C# numeric suffix '${suffix}'. NeoScript numeric literals do not use suffixes; remove '${suffix}'.`;
|
|
23806
23907
|
}
|
|
23908
|
+
const detail = error.message.replace(/^\d+:\d+:\s*/u, "");
|
|
23909
|
+
return `${label} could not be parsed: ${detail}`;
|
|
23807
23910
|
}
|
|
23808
23911
|
function validateFunctionBody(uri, text, returnType, scope, environment, range2, diagnostics) {
|
|
23809
23912
|
try {
|
|
@@ -32561,10 +32664,8 @@ function attachConstructorSignature(type, environment) {
|
|
|
32561
32664
|
type.id,
|
|
32562
32665
|
environment
|
|
32563
32666
|
);
|
|
32564
|
-
|
|
32565
|
-
(binding
|
|
32566
|
-
)) {
|
|
32567
|
-
return type;
|
|
32667
|
+
for (const binding of genericEnvironment.values()) {
|
|
32668
|
+
if (binding.kind === "unbound") return type;
|
|
32568
32669
|
}
|
|
32569
32670
|
const constructorSignature2 = buildNeoScriptConstructorSignature(
|
|
32570
32671
|
type.id,
|
|
@@ -32897,7 +32998,7 @@ function memberSymbol(member, schemaKey, environment, field) {
|
|
|
32897
32998
|
writable: false
|
|
32898
32999
|
};
|
|
32899
33000
|
}
|
|
32900
|
-
const writable = isReadOnly ? false : kind === "computed" ? computedHasSetter(member, field) :
|
|
33001
|
+
const writable = isReadOnly ? false : kind === "computed" ? computedHasSetter(member, field) : member.locked !== true;
|
|
32901
33002
|
const storage = typeof member.storage === "string" ? member.storage : void 0;
|
|
32902
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;
|
|
32903
33004
|
const lookupCollectionMemberId = kind === "lookup" ? string2(member.collectionMemberId, `${field}.collectionMemberId`) : null;
|
|
@@ -33433,9 +33534,12 @@ function memberType(member, environment, visiting, field) {
|
|
|
33433
33534
|
};
|
|
33434
33535
|
}
|
|
33435
33536
|
if (kind === "variant") {
|
|
33436
|
-
|
|
33437
|
-
|
|
33438
|
-
|
|
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
|
+
}
|
|
33439
33543
|
if (variantClass === void 0) return { ...unknownType(), nullable };
|
|
33440
33544
|
return {
|
|
33441
33545
|
kind: "named",
|
|
@@ -44538,6 +44642,7 @@ function isMemberDelegateBase(value) {
|
|
|
44538
44642
|
if (defaultValue === void 0 || defaultValue === null) return true;
|
|
44539
44643
|
if (!isMemberValueBase(defaultValue)) return false;
|
|
44540
44644
|
if (isInitValueContent(defaultValue)) return true;
|
|
44645
|
+
if (defaultValue.value === null) return v.required === false;
|
|
44541
44646
|
return isNSDelegateValue(defaultValue.value);
|
|
44542
44647
|
}
|
|
44543
44648
|
function nsActionListenerIdentity(listener) {
|
|
@@ -61723,7 +61828,8 @@ function interfaceToLanguageType(neoInterface, context) {
|
|
|
61723
61828
|
closure = [neoInterface];
|
|
61724
61829
|
}
|
|
61725
61830
|
const members = /* @__PURE__ */ new Map();
|
|
61726
|
-
for (
|
|
61831
|
+
for (let index = closure.length - 1; index >= 0; index -= 1) {
|
|
61832
|
+
const source = closure[index];
|
|
61727
61833
|
for (const key of getInterfaceMemberKeyOrder(source)) {
|
|
61728
61834
|
const member = source.members[key];
|
|
61729
61835
|
if (!member) continue;
|
|
@@ -61970,13 +62076,11 @@ function memberRuntimeType(record3, context, seen = /* @__PURE__ */ new Set(), g
|
|
|
61970
62076
|
const projectedEntry = entry ? substituteForGenericEnvironment(entry, genericEnvironment, context) : null;
|
|
61971
62077
|
return {
|
|
61972
62078
|
kind: "list",
|
|
61973
|
-
elementType: projectedEntry ?
|
|
61974
|
-
|
|
61975
|
-
|
|
61976
|
-
|
|
61977
|
-
|
|
61978
|
-
genericEnvironment
|
|
61979
|
-
)
|
|
62079
|
+
elementType: projectedEntry ? memberRuntimeType(
|
|
62080
|
+
projectedEntry,
|
|
62081
|
+
context,
|
|
62082
|
+
nextSeen,
|
|
62083
|
+
genericEnvironment
|
|
61980
62084
|
) : UNKNOWN_TYPE2,
|
|
61981
62085
|
listMemberId: record3.id,
|
|
61982
62086
|
nullable: !required2
|
|
@@ -61989,13 +62093,11 @@ function memberRuntimeType(record3, context, seen = /* @__PURE__ */ new Set(), g
|
|
|
61989
62093
|
return {
|
|
61990
62094
|
kind: "dictionary",
|
|
61991
62095
|
keyType: member.keyKind === "enum" && member.keyEnumId ? namedType(member.keyEnumId, true) : primitive2("string", true),
|
|
61992
|
-
valueType: projectedEntry ?
|
|
61993
|
-
|
|
61994
|
-
|
|
61995
|
-
|
|
61996
|
-
|
|
61997
|
-
genericEnvironment
|
|
61998
|
-
)
|
|
62096
|
+
valueType: projectedEntry ? memberRuntimeType(
|
|
62097
|
+
projectedEntry,
|
|
62098
|
+
context,
|
|
62099
|
+
nextSeen,
|
|
62100
|
+
genericEnvironment
|
|
61999
62101
|
) : UNKNOWN_TYPE2,
|
|
62000
62102
|
nullable: !required2
|
|
62001
62103
|
};
|
|
@@ -62994,7 +63096,10 @@ function initializerReferencesLexicalThis(source) {
|
|
|
62994
63096
|
}
|
|
62995
63097
|
function initializerReferencesAnyIdentifier(source, names) {
|
|
62996
63098
|
const identifiers = initializerReferencedIdentifiers(source);
|
|
62997
|
-
|
|
63099
|
+
for (const name of names) {
|
|
63100
|
+
if (identifiers.has(name)) return true;
|
|
63101
|
+
}
|
|
63102
|
+
return false;
|
|
62998
63103
|
}
|
|
62999
63104
|
function compileNSPropertyBodies(args) {
|
|
63000
63105
|
if (args.member.kind !== 10 /* NSProperty */) return;
|
|
@@ -63596,7 +63701,7 @@ function declaredConstructorsOfClass(constructors, schemaClass2) {
|
|
|
63596
63701
|
});
|
|
63597
63702
|
}
|
|
63598
63703
|
function argumentNameSetKey2(names) {
|
|
63599
|
-
return
|
|
63704
|
+
return names.map((name) => name.toLowerCase()).sort().join(", ");
|
|
63600
63705
|
}
|
|
63601
63706
|
function describeConstructorOverloads(constructors) {
|
|
63602
63707
|
return constructors.map(
|
|
@@ -63696,7 +63801,7 @@ function resolveMemberDeclaredTypeInfoInternal(member, members, seen) {
|
|
|
63696
63801
|
return {
|
|
63697
63802
|
type: resolved.kind,
|
|
63698
63803
|
required: resolved.required,
|
|
63699
|
-
entryTypeInfo
|
|
63804
|
+
entryTypeInfo,
|
|
63700
63805
|
...isMemberDictionaryBase(resolved) && resolved.keyEnumId ? { keyEnumId: resolved.keyEnumId } : {}
|
|
63701
63806
|
};
|
|
63702
63807
|
}
|
|
@@ -91957,7 +92062,12 @@ function materializeAuthoredListItems(args) {
|
|
|
91957
92062
|
args.member.entryMemberId
|
|
91958
92063
|
);
|
|
91959
92064
|
const unordered = listKindOf(args.member) === "unordered";
|
|
91960
|
-
const ids = unordered ? [
|
|
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
|
+
}
|
|
91961
92071
|
const materializedIds = [];
|
|
91962
92072
|
for (const childId of ids) {
|
|
91963
92073
|
if (typeof childId !== "string") {
|
|
@@ -92216,6 +92326,12 @@ function initBackedValueRow(value) {
|
|
|
92216
92326
|
if (!isMemberValue(value)) return null;
|
|
92217
92327
|
return isInitValueContent(value) ? value : null;
|
|
92218
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
|
+
}
|
|
92219
92335
|
function prepareServerOwnedValueInitializerBodies(args) {
|
|
92220
92336
|
const explicitRows = /* @__PURE__ */ new Map();
|
|
92221
92337
|
for (let index = 0; index < args.prepared.length; index += 1) {
|
|
@@ -92237,10 +92353,7 @@ function prepareServerOwnedValueInitializerBodies(args) {
|
|
|
92237
92353
|
args.postDocument,
|
|
92238
92354
|
args.prepared
|
|
92239
92355
|
);
|
|
92240
|
-
const targetIds =
|
|
92241
|
-
...[...explicitRows.values()].map((row) => row.id),
|
|
92242
|
-
...sweepRows.map((row) => row.id)
|
|
92243
|
-
]);
|
|
92356
|
+
const targetIds = valueIdsFromRows(explicitRows.values(), sweepRows);
|
|
92244
92357
|
const valuesById = new Map(
|
|
92245
92358
|
committedDocument.values.map((value) => [value.id, value])
|
|
92246
92359
|
);
|
|
@@ -92367,10 +92480,7 @@ function prepareServerOwnedDelegateValueBodies(args) {
|
|
|
92367
92480
|
args.postDocument,
|
|
92368
92481
|
args.prepared
|
|
92369
92482
|
);
|
|
92370
|
-
const targetIds =
|
|
92371
|
-
...[...explicitRows.values()].map((row) => row.id),
|
|
92372
|
-
...sweepRows.map((row) => row.id)
|
|
92373
|
-
]);
|
|
92483
|
+
const targetIds = valueIdsFromRows(explicitRows.values(), sweepRows);
|
|
92374
92484
|
const rootOwnerByValueId = /* @__PURE__ */ new Map();
|
|
92375
92485
|
const delegateScope = withVariantOwnershipRoots(
|
|
92376
92486
|
committedDocument,
|
|
@@ -92921,6 +93031,20 @@ function applyProjectVersionWriteChanges(document, changes) {
|
|
|
92921
93031
|
changes,
|
|
92922
93032
|
"project-file"
|
|
92923
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
|
+
),
|
|
92924
93048
|
internalRecordRelations: applyArrayChanges(
|
|
92925
93049
|
document.internalRecordRelations ?? [],
|
|
92926
93050
|
changes,
|
|
@@ -94841,7 +94965,7 @@ function listVirtualProjectSourceFilesV4(files) {
|
|
|
94841
94965
|
const kind = neoProjectSourceKind(file.path);
|
|
94842
94966
|
return kind !== null && isNeoProjectProductionSourceKind(kind) && !neoProjectPathHasIgnoredDirectory(file.path);
|
|
94843
94967
|
});
|
|
94844
|
-
const sorted =
|
|
94968
|
+
const sorted = selected.sort(
|
|
94845
94969
|
(left, right) => compareWorkspacePaths(left.path, right.path)
|
|
94846
94970
|
);
|
|
94847
94971
|
for (let index = 1; index < sorted.length; index += 1) {
|
|
@@ -95482,14 +95606,24 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
95482
95606
|
(binary) => binary.action !== "unchanged" && binary.action !== "converged"
|
|
95483
95607
|
);
|
|
95484
95608
|
reportPhase("binary-inspection");
|
|
95485
|
-
const invalidatedFileIds = /* @__PURE__ */ new Set(
|
|
95486
|
-
|
|
95487
|
-
|
|
95488
|
-
|
|
95489
|
-
|
|
95490
|
-
|
|
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
|
+
}
|
|
95491
95625
|
for (const message of validateFinalizedFileAssignmentsV4(
|
|
95492
|
-
|
|
95626
|
+
Array.from(reconstructed3.values(), (record3) => ({
|
|
95493
95627
|
recordKind: record3.recordKind,
|
|
95494
95628
|
data: record3.fullData
|
|
95495
95629
|
})),
|
|
@@ -95542,10 +95676,13 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
95542
95676
|
intent: createNeoCliPushIntent(change),
|
|
95543
95677
|
expectedBaseContentHash: change.kind === "create" ? null : change.casBaseHash ?? null
|
|
95544
95678
|
})),
|
|
95545
|
-
authoredValueSeeds:
|
|
95546
|
-
|
|
95547
|
-
|
|
95548
|
-
|
|
95679
|
+
authoredValueSeeds: Array.from(
|
|
95680
|
+
authoredValueSeeds,
|
|
95681
|
+
([memberId, seed]) => ({
|
|
95682
|
+
memberId,
|
|
95683
|
+
...seed
|
|
95684
|
+
})
|
|
95685
|
+
)
|
|
95549
95686
|
});
|
|
95550
95687
|
} catch (error) {
|
|
95551
95688
|
parseErrors.push(
|
|
@@ -95868,12 +96005,23 @@ function prospectiveAnimationRecords(base, reconstructed3, changes, seeds) {
|
|
|
95868
96005
|
const key = recordStateKey(change.recordKind, change.recordId);
|
|
95869
96006
|
if (change.kind === "delete") prospective.delete(key);
|
|
95870
96007
|
}
|
|
95871
|
-
|
|
95872
|
-
|
|
95873
|
-
|
|
95874
|
-
|
|
95875
|
-
|
|
95876
|
-
|
|
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
|
+
}
|
|
95877
96025
|
const projectId = projectRecord?.data.id;
|
|
95878
96026
|
const seedEnvelope = typeof projectId === "string" ? { projectId, createdAt: 0, updatedAt: 0 } : {};
|
|
95879
96027
|
for (const [key, record3] of reconstructed3) {
|
|
@@ -97274,43 +97422,47 @@ function compilePulledMemberInitializerBodyV4(document, memberId, compilationPro
|
|
|
97274
97422
|
}
|
|
97275
97423
|
function readPulledProjectDocumentV4(records2) {
|
|
97276
97424
|
const raw = structuredClone(
|
|
97277
|
-
pulledProjectDocumentRaw(
|
|
97278
|
-
|
|
97279
|
-
|
|
97280
|
-
completeProspectiveMemberCreateEnvelopes(
|
|
97281
|
-
completeProspectiveLocalizedTexts(raw)
|
|
97282
|
-
),
|
|
97283
|
-
{
|
|
97284
|
-
constructors: "authored-or-compiled",
|
|
97285
|
-
identities: "prospective",
|
|
97286
|
-
members: "authored-or-compiled"
|
|
97287
|
-
}
|
|
97425
|
+
pulledProjectDocumentRaw(
|
|
97426
|
+
replayWorkspace(completeProspectiveRecordCreateEnvelopes(records2))
|
|
97427
|
+
)
|
|
97288
97428
|
);
|
|
97429
|
+
return readProjectDocument(completeProspectiveLocalizedTexts(raw), {
|
|
97430
|
+
constructors: "authored-or-compiled",
|
|
97431
|
+
identities: "prospective",
|
|
97432
|
+
members: "authored-or-compiled"
|
|
97433
|
+
});
|
|
97289
97434
|
}
|
|
97290
|
-
function
|
|
97291
|
-
|
|
97292
|
-
|
|
97293
|
-
|
|
97294
|
-
|
|
97295
|
-
|
|
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") {
|
|
97296
97445
|
throw new Error(
|
|
97297
|
-
"
|
|
97446
|
+
"Prospective source-authored records need the server create envelope, but the project record has no id."
|
|
97298
97447
|
);
|
|
97299
97448
|
}
|
|
97300
|
-
|
|
97301
|
-
|
|
97302
|
-
|
|
97303
|
-
(
|
|
97304
|
-
|
|
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,
|
|
97305
97459
|
createdAt: 0,
|
|
97306
97460
|
updatedAt: 0,
|
|
97307
|
-
...
|
|
97308
|
-
}
|
|
97309
|
-
)
|
|
97310
|
-
}
|
|
97311
|
-
|
|
97312
|
-
function isPendingMemberWithoutCreateEnvelope(value) {
|
|
97313
|
-
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;
|
|
97314
97466
|
}
|
|
97315
97467
|
function completeProspectiveLocalizedTexts(raw) {
|
|
97316
97468
|
const localizedTexts = raw.localizedTexts;
|
|
@@ -109182,7 +109334,7 @@ function qualifiedMemberLabel(thisClass, member) {
|
|
|
109182
109334
|
if (typeof thisClass.name !== "string") return `'${memberName}'`;
|
|
109183
109335
|
return `'${thisClass.name}.${memberName}'`;
|
|
109184
109336
|
}
|
|
109185
|
-
function
|
|
109337
|
+
function analyzeWorkspaceProjectV4(workspace) {
|
|
109186
109338
|
const status = computeWorkspaceStatus2(workspace, {
|
|
109187
109339
|
skipProjectBinaryInspection: true
|
|
109188
109340
|
});
|
|
@@ -109207,13 +109359,35 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
109207
109359
|
data: record3.fullData
|
|
109208
109360
|
});
|
|
109209
109361
|
}
|
|
109210
|
-
|
|
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
|
+
};
|
|
109211
109378
|
}
|
|
109212
109379
|
async function runScript(workspace, command, options, dependencies = {}) {
|
|
109213
109380
|
let localCheckManifest = null;
|
|
109381
|
+
let localCheckDocument = null;
|
|
109214
109382
|
const targetsLocalMember = (command === "check" || command === "compile") && options.memberRef !== null;
|
|
109215
109383
|
if (command === "check" && options.all || targetsLocalMember) {
|
|
109216
|
-
|
|
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
|
+
}
|
|
109217
109391
|
if (targetsLocalMember) {
|
|
109218
109392
|
const localTarget = resolveLocalScriptMember(
|
|
109219
109393
|
localCheckManifest,
|
|
@@ -109233,6 +109407,10 @@ async function runScript(workspace, command, options, dependencies = {}) {
|
|
|
109233
109407
|
return;
|
|
109234
109408
|
}
|
|
109235
109409
|
}
|
|
109410
|
+
if (command === "check" && options.all && localCheckManifest !== null && localCheckDocument !== null) {
|
|
109411
|
+
runCheckAll(localCheckDocument, localCheckManifest, options);
|
|
109412
|
+
return;
|
|
109413
|
+
}
|
|
109236
109414
|
const client = NeoApiClient.forBaseUrl(workspace.config.apiBaseUrl);
|
|
109237
109415
|
const { raw } = await fetchProjectDocument(workspace);
|
|
109238
109416
|
const document = readDocumentArrays(raw);
|
|
@@ -110176,6 +110354,7 @@ var init_script = __esm({
|
|
|
110176
110354
|
init_workspace_status();
|
|
110177
110355
|
init_source_diagnostics();
|
|
110178
110356
|
init_project_documents();
|
|
110357
|
+
init_initializer_replay();
|
|
110179
110358
|
init_push_body_diagnostics();
|
|
110180
110359
|
RETURN_SHORTHANDS = {
|
|
110181
110360
|
// MemberKind numerics: Bool=1, Int=2, String=3, Float=4.
|
|
@@ -113831,7 +114010,7 @@ var init_registry2 = __esm({
|
|
|
113831
114010
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
113832
114011
|
formatVersion: 3,
|
|
113833
114012
|
contractVersion: "3.14",
|
|
113834
|
-
cliVersion: "0.36.
|
|
114013
|
+
cliVersion: "0.36.3",
|
|
113835
114014
|
projectFileUploadBatchSize: 32,
|
|
113836
114015
|
documentRecords: {
|
|
113837
114016
|
member: {
|
|
@@ -120433,7 +120612,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
120433
120612
|
async function main() {
|
|
120434
120613
|
const args = parseArgs(process.argv.slice(2));
|
|
120435
120614
|
if (args.command === "--version") {
|
|
120436
|
-
console.log("0.36.
|
|
120615
|
+
console.log("0.36.3");
|
|
120437
120616
|
return;
|
|
120438
120617
|
}
|
|
120439
120618
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/package.json
CHANGED
|
@@ -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.
|
|
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
|
|
@@ -154,6 +154,10 @@ components must be numeric literals. When a computed list or dictionary entry
|
|
|
154
154
|
carries an authored `@id`, parenthesize the expression — `@id("row")
|
|
155
155
|
(A.B / A.C)` — so the annotation names the row rather than its left operand.
|
|
156
156
|
|
|
157
|
+
Numeric literals do not use C# suffixes: write `0` or `0.5`, not `0f` or
|
|
158
|
+
`0.5f`. The declared/contextual type determines whether a literal is stored as
|
|
159
|
+
an int, float, or decimal.
|
|
160
|
+
|
|
157
161
|
A direct field or property read is computed too, whether it is local,
|
|
158
162
|
qualified static, or reached through a stable root path. For example,
|
|
159
163
|
`protected int Slots = FeatureFlags.StartInventorySize;` evaluates the current
|
|
@@ -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
|
|
200
|
-
context, exactly like a list literal, so assigning
|
|
201
|
-
`List<float>` widens the entries to `float`.
|
|
202
|
-
|
|
203
|
-
|
|
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
|