@neocompose/cli 0.62.2 → 0.63.0
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 +9 -0
- package/dist/neo.mjs +157 -11
- package/dist/test-worker.mjs +29 -2
- 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 +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.63.0] - 2026-10-02
|
|
4
|
+
|
|
5
|
+
- Add `@effect` for class member functions. The Unity runtime runs an effect for every live instance, then reruns it whenever data it read changes. `@effect(kind: .None)` stops an inherited effect. An effect must be an immediate, parameterless `void` instance function with a NeoScript or abstract body; anything else reports `invalid-effect` at its source.
|
|
6
|
+
- Pull functions with empty bodies instead of failing on their stored empty source.
|
|
7
|
+
|
|
8
|
+
## [0.62.3] - 2026-10-02
|
|
9
|
+
|
|
10
|
+
- `neo export unity` saves the server codegen revision in the generated-file manifest, matching Unity synchronization. Server codegen changes now invalidate incremental Unity exports even when project records have not changed. Unchanged generated C# files retain their contents and timestamps.
|
|
11
|
+
|
|
3
12
|
## [0.62.2] - 2026-10-02
|
|
4
13
|
|
|
5
14
|
- Speed up `neo test` after production edits by sharing one indexed compiler context across specs and omitting the push-only source serialization round trip. Production compilation and whole-graph validation still run.
|
package/dist/neo.mjs
CHANGED
|
@@ -19678,6 +19678,7 @@ var init_project_schema_contract_generated = __esm({
|
|
|
19678
19678
|
"argumentTypes",
|
|
19679
19679
|
"dispatch",
|
|
19680
19680
|
"bodyMode",
|
|
19681
|
+
"effect",
|
|
19681
19682
|
"uiAction",
|
|
19682
19683
|
"templateId",
|
|
19683
19684
|
"genericParamId"
|
|
@@ -19881,6 +19882,10 @@ var init_project_schema_contract_generated = __esm({
|
|
|
19881
19882
|
"Sprite",
|
|
19882
19883
|
"Audio"
|
|
19883
19884
|
],
|
|
19885
|
+
"NeoEffectKind": [
|
|
19886
|
+
"None",
|
|
19887
|
+
"Auto"
|
|
19888
|
+
],
|
|
19884
19889
|
"NeoProjectRecordKind": [
|
|
19885
19890
|
"Project",
|
|
19886
19891
|
"Member",
|
|
@@ -24245,6 +24250,9 @@ function fieldsForAnnotation(name, context, environment) {
|
|
|
24245
24250
|
if (context.kind === "type") return null;
|
|
24246
24251
|
if (name === "storage") return storageFields(context);
|
|
24247
24252
|
if (name === "distribution") return distributionFields(context);
|
|
24253
|
+
if (name === "effect") {
|
|
24254
|
+
return context.kind === "member" && context.memberKind === "function" ? [{ name: "kind", type: "NeoEffectKind" }] : null;
|
|
24255
|
+
}
|
|
24248
24256
|
if (name === "relations") return relationFields(context, environment);
|
|
24249
24257
|
if (name === "system") {
|
|
24250
24258
|
return context.kind === "class" || context.kind === "schema" || context.kind === "member" ? markerFields("NeoSystemAttribute") : null;
|
|
@@ -27804,11 +27812,23 @@ function validateMembers(environment, diagnostics) {
|
|
|
27804
27812
|
);
|
|
27805
27813
|
}
|
|
27806
27814
|
}
|
|
27815
|
+
for (const member of ref.declaration.members) {
|
|
27816
|
+
const effect = effectAnnotation(member);
|
|
27817
|
+
if (effect === void 0) continue;
|
|
27818
|
+
diagnose(
|
|
27819
|
+
diagnostics,
|
|
27820
|
+
ref.uri,
|
|
27821
|
+
effect.nameRange,
|
|
27822
|
+
"invalid-effect",
|
|
27823
|
+
`Interface member '${ref.declaration.name}.${member.name}' cannot be an @effect; only class member functions can.`
|
|
27824
|
+
);
|
|
27825
|
+
}
|
|
27807
27826
|
validateInterfaceMemberConflicts(ref, environment, diagnostics);
|
|
27808
27827
|
}
|
|
27809
27828
|
for (const ref of environment.classes.values()) {
|
|
27810
27829
|
validateClassMemberModifiers(ref, environment, diagnostics);
|
|
27811
27830
|
validateClassOverrides(ref, environment, diagnostics);
|
|
27831
|
+
validateEffects(ref, environment, diagnostics);
|
|
27812
27832
|
if (ref.declaration.modifiers.includes("abstract")) {
|
|
27813
27833
|
validateAbstractInterfaceMembers(ref, environment, diagnostics);
|
|
27814
27834
|
} else {
|
|
@@ -28234,6 +28254,70 @@ function validateClassOverrides(ref, environment, diagnostics) {
|
|
|
28234
28254
|
}
|
|
28235
28255
|
}
|
|
28236
28256
|
}
|
|
28257
|
+
function validateEffects(ref, environment, diagnostics) {
|
|
28258
|
+
let inherited;
|
|
28259
|
+
for (const member of ref.declaration.members) {
|
|
28260
|
+
if (member.kind !== "function") continue;
|
|
28261
|
+
const annotation2 = effectAnnotation(member);
|
|
28262
|
+
let kind = annotation2 === void 0 ? void 0 : effectKind(annotation2);
|
|
28263
|
+
if (annotation2 === void 0) {
|
|
28264
|
+
if (!member.modifiers.includes("override") || !member.modifiers.includes("native")) {
|
|
28265
|
+
continue;
|
|
28266
|
+
}
|
|
28267
|
+
inherited ??= inheritedClassMembers(ref, environment);
|
|
28268
|
+
kind = inheritedEffectKind(inherited, member.name);
|
|
28269
|
+
}
|
|
28270
|
+
if (kind !== "Auto") continue;
|
|
28271
|
+
const problem = effectIneligibility(member);
|
|
28272
|
+
if (problem === null) continue;
|
|
28273
|
+
diagnose(
|
|
28274
|
+
diagnostics,
|
|
28275
|
+
ref.uri,
|
|
28276
|
+
annotation2?.nameRange ?? member.nameRange,
|
|
28277
|
+
"invalid-effect",
|
|
28278
|
+
`'${ref.declaration.name}.${member.name}' cannot be an @effect: ${problem}.`
|
|
28279
|
+
);
|
|
28280
|
+
}
|
|
28281
|
+
}
|
|
28282
|
+
function effectAnnotation(member) {
|
|
28283
|
+
return member.annotations.find((entry) => entry.name === "effect");
|
|
28284
|
+
}
|
|
28285
|
+
function effectKind(annotation2) {
|
|
28286
|
+
if (annotation2.arguments.length === 0) return "Auto";
|
|
28287
|
+
const argument2 = annotation2.arguments.find((entry) => entry.name === "kind") ?? annotation2.arguments.find((entry) => entry.name === void 0);
|
|
28288
|
+
if (argument2 === void 0) return void 0;
|
|
28289
|
+
let expression;
|
|
28290
|
+
try {
|
|
28291
|
+
expression = parseExpression(argument2.text);
|
|
28292
|
+
} catch (error) {
|
|
28293
|
+
if (error instanceof CompileError) return void 0;
|
|
28294
|
+
throw error;
|
|
28295
|
+
}
|
|
28296
|
+
return expression.kind === "contextualEnum" ? expression.name : void 0;
|
|
28297
|
+
}
|
|
28298
|
+
function inheritedEffectKind(inherited, name) {
|
|
28299
|
+
for (let index = inherited.length - 1; index >= 0; index -= 1) {
|
|
28300
|
+
const view = inherited[index];
|
|
28301
|
+
if (!namesEqual(view.member.name, name)) continue;
|
|
28302
|
+
const annotation2 = effectAnnotation(view.member);
|
|
28303
|
+
if (annotation2 !== void 0) return effectKind(annotation2);
|
|
28304
|
+
}
|
|
28305
|
+
return void 0;
|
|
28306
|
+
}
|
|
28307
|
+
function effectIneligibility(member) {
|
|
28308
|
+
if (member.modifiers.includes("static")) {
|
|
28309
|
+
return "a static function has no instance to run for";
|
|
28310
|
+
}
|
|
28311
|
+
if (member.modifiers.includes("native")) {
|
|
28312
|
+
return "a native function has no NeoScript reads to track";
|
|
28313
|
+
}
|
|
28314
|
+
if (member.modifiers.includes("async")) {
|
|
28315
|
+
return "an effect runs immediately and cannot be async";
|
|
28316
|
+
}
|
|
28317
|
+
if (member.type.name !== "void") return "an effect must return void";
|
|
28318
|
+
if (member.parameters.length > 0) return "an effect takes no parameters";
|
|
28319
|
+
return null;
|
|
28320
|
+
}
|
|
28237
28321
|
function isPlatformImplementedSystemMember(member) {
|
|
28238
28322
|
if (!member.modifiers.includes("protected")) return false;
|
|
28239
28323
|
return member.annotations.some((entry) => entry.name === "system");
|
|
@@ -28699,6 +28783,8 @@ var init_project_source_type_checker = __esm({
|
|
|
28699
28783
|
init_language_spec();
|
|
28700
28784
|
init_project_source_ast();
|
|
28701
28785
|
init_lexer();
|
|
28786
|
+
init_executable_parser();
|
|
28787
|
+
init_strict_compile_error();
|
|
28702
28788
|
init_project_source_accessors();
|
|
28703
28789
|
init_project_source_identifiers();
|
|
28704
28790
|
BUILTIN_ARITY = /* @__PURE__ */ new Map([
|
|
@@ -30106,6 +30192,7 @@ function projectDeclarationAnnotationNames(declaration) {
|
|
|
30106
30192
|
}
|
|
30107
30193
|
function projectMemberAnnotationNames(member) {
|
|
30108
30194
|
const names = ["id", "settings", "storage", "distribution"];
|
|
30195
|
+
if (member?.kind === "function") names.push("effect");
|
|
30109
30196
|
if (member?.type.name === "List") names.push("index", "column");
|
|
30110
30197
|
return names;
|
|
30111
30198
|
}
|
|
@@ -31770,6 +31857,8 @@ function annotationSignatureParameters(name) {
|
|
|
31770
31857
|
return ["StorageKind allowed"];
|
|
31771
31858
|
case "distribution":
|
|
31772
31859
|
return ["NeoSubtreeDistribution kind"];
|
|
31860
|
+
case "effect":
|
|
31861
|
+
return ["NeoEffectKind kind"];
|
|
31773
31862
|
case "relations":
|
|
31774
31863
|
return ["relation descriptors"];
|
|
31775
31864
|
case "incomplete":
|
|
@@ -40021,7 +40110,7 @@ function assertMemberInvariants(member, path) {
|
|
|
40021
40110
|
fail2("script", "is required for a concrete scripted member.");
|
|
40022
40111
|
}
|
|
40023
40112
|
}
|
|
40024
|
-
var nonEmptyString, nullableString2, nullableId, finiteNumber, nullableNumber, nullableInteger, jsonValueSchema, schemaSourcePositionSchema, schemaSourceSpanSchema, schemaSourceSymbolKinds, schemaSourceIdentitySchema, memberSourceIdentitySchema, systemProtectionKindSchema, worldSystemClassKindSchema, schemaSystemMetadataSchema, schemaGenericBindingSchema, schemaGenericBindingRecordSchema, genericConstraintSchema, schemaGenericParameterSchema, primitiveTypeKinds, schemaTypeCache, returnTypeCache, schemaTypeSchema, schemaFunctionReturnTypeSchema, schemaParameterDefaultSchema, schemaFunctionArgumentSchema, memberOwnerSchema, schemaDefaultValueSchema, propertyScriptSchema, functionScriptSchema, commonMemberEntries, schemaMemberCommonSchema, simpleMemberSchemas, dictionaryKeySchema, schemaListIndexSchema, schemaListColumnSchema, callableEntries, schemaMemberSchema, SchemaMemberContractError;
|
|
40113
|
+
var nonEmptyString, nullableString2, nullableId, finiteNumber, nullableNumber, nullableInteger, jsonValueSchema, schemaSourcePositionSchema, schemaSourceSpanSchema, schemaSourceSymbolKinds, schemaSourceIdentitySchema, memberSourceIdentitySchema, systemProtectionKindSchema, worldSystemClassKindSchema, schemaSystemMetadataSchema, schemaGenericBindingSchema, schemaGenericBindingRecordSchema, genericConstraintSchema, schemaGenericParameterSchema, primitiveTypeKinds, schemaTypeCache, returnTypeCache, schemaTypeSchema, schemaFunctionReturnTypeSchema, schemaParameterDefaultSchema, schemaFunctionArgumentSchema, memberOwnerSchema, schemaDefaultValueSchema, propertyScriptSchema, functionScriptSchema, commonMemberEntries, schemaMemberCommonSchema, simpleMemberSchemas, dictionaryKeySchema, schemaListIndexSchema, schemaListColumnSchema, callableEntries, functionEffectSchema, schemaMemberSchema, SchemaMemberContractError;
|
|
40025
40114
|
var init_schema_member = __esm({
|
|
40026
40115
|
"../packages/manifest/src/schema-member.ts"() {
|
|
40027
40116
|
"use strict";
|
|
@@ -40346,6 +40435,7 @@ var init_schema_member = __esm({
|
|
|
40346
40435
|
returnType: schemaFunctionReturnTypeSchema,
|
|
40347
40436
|
arguments: array2(schemaFunctionArgumentSchema)
|
|
40348
40437
|
};
|
|
40438
|
+
functionEffectSchema = optional(picklist(["none", "auto"]));
|
|
40349
40439
|
schemaMemberSchema = variant("kind", [
|
|
40350
40440
|
...simpleMemberSchemas,
|
|
40351
40441
|
memberSchema("int", {
|
|
@@ -40408,11 +40498,13 @@ var init_schema_member = __esm({
|
|
|
40408
40498
|
}),
|
|
40409
40499
|
memberSchema("function", {
|
|
40410
40500
|
...callableEntries,
|
|
40411
|
-
deferred: boolean2()
|
|
40501
|
+
deferred: boolean2(),
|
|
40502
|
+
effect: functionEffectSchema
|
|
40412
40503
|
}),
|
|
40413
40504
|
memberSchema("scriptFunction", {
|
|
40414
40505
|
...callableEntries,
|
|
40415
40506
|
deferred: boolean2(),
|
|
40507
|
+
effect: functionEffectSchema,
|
|
40416
40508
|
bodyMode: optional(literal2("ui")),
|
|
40417
40509
|
uiAction: optional(jsonValueSchema),
|
|
40418
40510
|
script: nullable(functionScriptSchema)
|
|
@@ -40503,6 +40595,7 @@ var init_document_contracts = __esm({
|
|
|
40503
40595
|
"argumentTypes",
|
|
40504
40596
|
"dispatch",
|
|
40505
40597
|
"bodyMode",
|
|
40598
|
+
"effect",
|
|
40506
40599
|
"uiAction",
|
|
40507
40600
|
"templateId",
|
|
40508
40601
|
"genericParamId"
|
|
@@ -42207,12 +42300,24 @@ function memberFromDocument(record6, members, owners, classNames, context) {
|
|
|
42207
42300
|
FUNCTION_DISPATCH,
|
|
42208
42301
|
record6,
|
|
42209
42302
|
"dispatch"
|
|
42210
|
-
) === "asynchronous"
|
|
42303
|
+
) === "asynchronous",
|
|
42304
|
+
// The row's own value, not the chain's: an override without `@effect`
|
|
42305
|
+
// inherits, and resolving here would emit the ancestor's kind back
|
|
42306
|
+
// into the override's source as phantom drift.
|
|
42307
|
+
...data.effect === void 0 || data.effect === null ? {} : {
|
|
42308
|
+
effect: ordinalValue(
|
|
42309
|
+
data.effect,
|
|
42310
|
+
FUNCTION_EFFECT,
|
|
42311
|
+
record6,
|
|
42312
|
+
"effect"
|
|
42313
|
+
)
|
|
42314
|
+
}
|
|
42211
42315
|
};
|
|
42212
42316
|
if (kind === MEMBER_KIND.Function) {
|
|
42213
42317
|
return { ...common, kind: "function", ...signature };
|
|
42214
42318
|
}
|
|
42215
|
-
const
|
|
42319
|
+
const codeValue = field("code", null);
|
|
42320
|
+
const code = codeValue === "" ? "" : optionalStringOrNull(codeValue);
|
|
42216
42321
|
const bodyModeValue = ordinalValue(
|
|
42217
42322
|
field("bodyMode", 0),
|
|
42218
42323
|
FUNCTION_BODY,
|
|
@@ -42458,6 +42563,9 @@ function memberToDocumentFields(member, baseData3) {
|
|
|
42458
42563
|
if (member.deferred || isOverride) {
|
|
42459
42564
|
fields.dispatch = member.deferred ? 1 : 0;
|
|
42460
42565
|
}
|
|
42566
|
+
if (member.effect !== void 0) {
|
|
42567
|
+
fields.effect = FUNCTION_EFFECT.indexOf(member.effect);
|
|
42568
|
+
}
|
|
42461
42569
|
if (member.kind === "scriptFunction" && member.script !== null && member.bodyMode !== "ui") {
|
|
42462
42570
|
fields.code = member.script.sourceText;
|
|
42463
42571
|
}
|
|
@@ -43252,7 +43360,7 @@ function invalidDocument(record6, path, message) {
|
|
|
43252
43360
|
`${record6.recordKind}:${record6.recordId}.${path} ${message}.`
|
|
43253
43361
|
);
|
|
43254
43362
|
}
|
|
43255
|
-
var MEMBER_KIND, MEMBER_MODIFIERS, MEMBER_ACCESS, MEMBER_STORAGE, MEMBER_DISTRIBUTION, STRING_FORMAT, MEMBER_SEARCH_BY, MEMBER_SELECTION, FUNCTION_DISPATCH, FUNCTION_BODY, MEMBER_PAYLOAD, DICTIONARY_KEY, LIST_KIND, LIST_INDEX, COLUMN_VISIBILITY, COLUMN_PIN, COLUMN_OVERFLOW, GENERIC_BINDING, TYPE_KIND_BY_MEMBER_KIND, SIMPLE_MEMBER_KIND_BY_KIND, MEMBER_KIND_BY_KIND, TYPE_MEMBER_KIND_BY_KIND, MEMBER_IDENTITY_FIELDS, INHERITED_MEMBER_ORDINAL_FIELDS, NULLABLE_OVERRIDE_MEMBER_FIELDS;
|
|
43363
|
+
var MEMBER_KIND, MEMBER_MODIFIERS, MEMBER_ACCESS, MEMBER_STORAGE, MEMBER_DISTRIBUTION, STRING_FORMAT, MEMBER_SEARCH_BY, MEMBER_SELECTION, FUNCTION_DISPATCH, FUNCTION_BODY, FUNCTION_EFFECT, MEMBER_PAYLOAD, DICTIONARY_KEY, LIST_KIND, LIST_INDEX, COLUMN_VISIBILITY, COLUMN_PIN, COLUMN_OVERFLOW, GENERIC_BINDING, TYPE_KIND_BY_MEMBER_KIND, SIMPLE_MEMBER_KIND_BY_KIND, MEMBER_KIND_BY_KIND, TYPE_MEMBER_KIND_BY_KIND, MEMBER_IDENTITY_FIELDS, INHERITED_MEMBER_ORDINAL_FIELDS, NULLABLE_OVERRIDE_MEMBER_FIELDS;
|
|
43256
43364
|
var init_codecs = __esm({
|
|
43257
43365
|
"src/project-manifest/record-adapters/codecs.ts"() {
|
|
43258
43366
|
"use strict";
|
|
@@ -43303,6 +43411,7 @@ var init_codecs = __esm({
|
|
|
43303
43411
|
MEMBER_SELECTION = ["single", "multi"];
|
|
43304
43412
|
FUNCTION_DISPATCH = ["synchronous", "asynchronous"];
|
|
43305
43413
|
FUNCTION_BODY = ["code", "ui"];
|
|
43414
|
+
FUNCTION_EFFECT = ["none", "auto"];
|
|
43306
43415
|
MEMBER_PAYLOAD = ["full", "partial"];
|
|
43307
43416
|
DICTIONARY_KEY = ["string", "enum"];
|
|
43308
43417
|
LIST_KIND = ["ordered", "unordered"];
|
|
@@ -49170,6 +49279,9 @@ var init_structured_leaf_fields = __esm({
|
|
|
49170
49279
|
});
|
|
49171
49280
|
|
|
49172
49281
|
// ../src/models/members/member-kinds.ts
|
|
49282
|
+
function isFunctionEffectKind(value) {
|
|
49283
|
+
return value === 0 /* None */ || value === 1 /* Auto */;
|
|
49284
|
+
}
|
|
49173
49285
|
function isMemberAccessKind(value) {
|
|
49174
49286
|
return MEMBER_ACCESS_KINDS.includes(value);
|
|
49175
49287
|
}
|
|
@@ -49918,6 +50030,11 @@ function hasValidStorageField(v, allowNull) {
|
|
|
49918
50030
|
if (typeof v.kind !== "number") return false;
|
|
49919
50031
|
return memberKindSupportsStorage(v.kind);
|
|
49920
50032
|
}
|
|
50033
|
+
function hasValidEffectField(v) {
|
|
50034
|
+
if (v.effect === void 0) return true;
|
|
50035
|
+
if (!isFunctionEffectKind(v.effect)) return false;
|
|
50036
|
+
return v.kind === 13 /* Function */ || v.kind === 23 /* NSFunction */;
|
|
50037
|
+
}
|
|
49921
50038
|
function hasValidDistributionField(v) {
|
|
49922
50039
|
if (v.distribution === void 0) return true;
|
|
49923
50040
|
if (!isNeoSubtreeDistributionKind(v.distribution)) return false;
|
|
@@ -49948,6 +50065,7 @@ function isMemberBase(value) {
|
|
|
49948
50065
|
}
|
|
49949
50066
|
if (!hasValidStorageField(v, true)) return false;
|
|
49950
50067
|
if (!hasValidDistributionField(v)) return false;
|
|
50068
|
+
if (!hasValidEffectField(v)) return false;
|
|
49951
50069
|
const storageKey = getField(value, "storageKey");
|
|
49952
50070
|
if (storageKey !== void 0 && storageKey !== null && typeof storageKey !== "string")
|
|
49953
50071
|
return false;
|
|
@@ -50047,6 +50165,7 @@ function isMemberOverrideBase(value) {
|
|
|
50047
50165
|
}
|
|
50048
50166
|
if (!hasValidStorageField(v, false)) return false;
|
|
50049
50167
|
if (!hasValidDistributionField(v)) return false;
|
|
50168
|
+
if (!hasValidEffectField(v)) return false;
|
|
50050
50169
|
if (v.defaultValue !== void 0 && v.defaultValue !== null && !isMemberValueBase(v.defaultValue)) {
|
|
50051
50170
|
return false;
|
|
50052
50171
|
}
|
|
@@ -59706,6 +59825,7 @@ function emitMember(context, member, enclosingClassId) {
|
|
|
59706
59825
|
// P76 §1 is never materialized into source, so a member that omits the
|
|
59707
59826
|
// annotation round-trips as an omission.
|
|
59708
59827
|
...member.distribution ? [`@distribution(kind: .${enumCase(member.distribution)})`] : [],
|
|
59828
|
+
...(member.kind === "function" || member.kind === "scriptFunction") && member.effect !== void 0 ? [member.effect === "auto" ? "@effect" : "@effect(kind: .None)"] : [],
|
|
59709
59829
|
...memberSettings(context, member),
|
|
59710
59830
|
...listAnnotations(member),
|
|
59711
59831
|
...member.system ? [systemAnnotation2(member.system)] : []
|
|
@@ -62578,6 +62698,11 @@ function lowerMemberKind(context, ownerClass, declaration, id2, owner) {
|
|
|
62578
62698
|
};
|
|
62579
62699
|
}
|
|
62580
62700
|
);
|
|
62701
|
+
const effect = functionEffectValue(
|
|
62702
|
+
annotation(declaration.annotations, "effect"),
|
|
62703
|
+
ownerClass,
|
|
62704
|
+
declaration
|
|
62705
|
+
);
|
|
62581
62706
|
const settings = annotation(declaration.annotations, "settings");
|
|
62582
62707
|
const logicMode = contextualEnumArgument(settings, "logic");
|
|
62583
62708
|
if (logicMode !== null && logicMode !== "UI") {
|
|
@@ -62604,6 +62729,7 @@ function lowerMemberKind(context, ownerClass, declaration, id2, owner) {
|
|
|
62604
62729
|
returnType,
|
|
62605
62730
|
arguments: argumentsValue,
|
|
62606
62731
|
deferred: declaration.modifiers.includes("async"),
|
|
62732
|
+
...effect,
|
|
62607
62733
|
...logicMode === "UI" ? { bodyMode: "ui", uiAction } : {},
|
|
62608
62734
|
script: {
|
|
62609
62735
|
kind: "function",
|
|
@@ -62621,6 +62747,7 @@ function lowerMemberKind(context, ownerClass, declaration, id2, owner) {
|
|
|
62621
62747
|
returnType,
|
|
62622
62748
|
arguments: argumentsValue,
|
|
62623
62749
|
deferred: declaration.modifiers.includes("async"),
|
|
62750
|
+
...effect,
|
|
62624
62751
|
bodyMode: "ui",
|
|
62625
62752
|
...uiAction === void 0 ? {} : { uiAction },
|
|
62626
62753
|
script: null
|
|
@@ -62633,6 +62760,7 @@ function lowerMemberKind(context, ownerClass, declaration, id2, owner) {
|
|
|
62633
62760
|
returnType,
|
|
62634
62761
|
arguments: argumentsValue,
|
|
62635
62762
|
deferred: declaration.modifiers.includes("async"),
|
|
62763
|
+
...effect,
|
|
62636
62764
|
script: null
|
|
62637
62765
|
};
|
|
62638
62766
|
}
|
|
@@ -62641,7 +62769,8 @@ function lowerMemberKind(context, ownerClass, declaration, id2, owner) {
|
|
|
62641
62769
|
kind: "function",
|
|
62642
62770
|
returnType,
|
|
62643
62771
|
arguments: argumentsValue,
|
|
62644
|
-
deferred: declaration.modifiers.includes("async")
|
|
62772
|
+
deferred: declaration.modifiers.includes("async"),
|
|
62773
|
+
...effect
|
|
62645
62774
|
};
|
|
62646
62775
|
}
|
|
62647
62776
|
return lowerFieldMember(
|
|
@@ -62771,6 +62900,16 @@ function distributionValue(value, ownerClass, declaration) {
|
|
|
62771
62900
|
`@distribution on ${site} has unknown kind ".${kind}". Valid kinds are .Sparse and .Packed.`
|
|
62772
62901
|
);
|
|
62773
62902
|
}
|
|
62903
|
+
function functionEffectValue(value, ownerClass, declaration) {
|
|
62904
|
+
if (value === void 0) return {};
|
|
62905
|
+
if (value.arguments.length === 0) return { effect: "auto" };
|
|
62906
|
+
const kind = contextualEnumArgument(value, "kind");
|
|
62907
|
+
if (kind === "None") return { effect: "none" };
|
|
62908
|
+
if (kind === "Auto") return { effect: "auto" };
|
|
62909
|
+
throw new Error(
|
|
62910
|
+
`@effect on ${ownerClass.name}.${declaration.name} has unknown kind${kind === null ? "" : ` ".${kind}"`}. Valid kinds are .None and .Auto.`
|
|
62911
|
+
);
|
|
62912
|
+
}
|
|
62774
62913
|
function resolvedMemberStorage(context, memberId, visited = /* @__PURE__ */ new Set()) {
|
|
62775
62914
|
if (visited.has(memberId)) return null;
|
|
62776
62915
|
visited.add(memberId);
|
|
@@ -147462,7 +147601,7 @@ var init_registry2 = __esm({
|
|
|
147462
147601
|
"../packages/manifest/schema-contract/registry.mjs"() {
|
|
147463
147602
|
"use strict";
|
|
147464
147603
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
147465
|
-
cliVersion: "0.
|
|
147604
|
+
cliVersion: "0.63.0",
|
|
147466
147605
|
projectFileUploadBatchSize: 32,
|
|
147467
147606
|
documentRecords: {
|
|
147468
147607
|
member: {
|
|
@@ -147514,6 +147653,10 @@ var init_registry2 = __esm({
|
|
|
147514
147653
|
"argumentTypes",
|
|
147515
147654
|
"dispatch",
|
|
147516
147655
|
"bodyMode",
|
|
147656
|
+
// P97 §1.1. No normalization rule, like `distribution`: absence means
|
|
147657
|
+
// unset (a declaration resolves to `.None`, an override inherits) and
|
|
147658
|
+
// explicit ordinal 0 is an authored `.None` that stops inheritance.
|
|
147659
|
+
"effect",
|
|
147517
147660
|
"uiAction",
|
|
147518
147661
|
"templateId",
|
|
147519
147662
|
"genericParamId"
|
|
@@ -147816,7 +147959,8 @@ var init_registry2 = __esm({
|
|
|
147816
147959
|
NeoColumnVisibility: ["Visible", "Hidden"],
|
|
147817
147960
|
NeoColumnPin: ["None", "Leading"],
|
|
147818
147961
|
NeoColumnOverflow: ["Clip", "Wrap"],
|
|
147819
|
-
NeoFileKind: ["Sprite", "Audio"]
|
|
147962
|
+
NeoFileKind: ["Sprite", "Audio"],
|
|
147963
|
+
NeoEffectKind: ["None", "Auto"]
|
|
147820
147964
|
},
|
|
147821
147965
|
markers: {
|
|
147822
147966
|
NeoSchemaClassAttribute: {
|
|
@@ -155535,7 +155679,7 @@ function readManifest(path) {
|
|
|
155535
155679
|
});
|
|
155536
155680
|
return { projectId: data.projectId, files };
|
|
155537
155681
|
}
|
|
155538
|
-
function writeUnityGeneratedFiles(directory, projectId, files) {
|
|
155682
|
+
function writeUnityGeneratedFiles(directory, projectId, files, codegenRevision) {
|
|
155539
155683
|
if (!Array.isArray(files) || files.length === 0)
|
|
155540
155684
|
throw new Error(
|
|
155541
155685
|
"The export returned no generated files. Update the server before exporting Unity code."
|
|
@@ -155599,6 +155743,7 @@ function writeUnityGeneratedFiles(directory, projectId, files) {
|
|
|
155599
155743
|
{
|
|
155600
155744
|
schemaVersion: 1,
|
|
155601
155745
|
projectId,
|
|
155746
|
+
codegenRevision,
|
|
155602
155747
|
files: [...files].sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0).map((file) => ({
|
|
155603
155748
|
id: file.id,
|
|
155604
155749
|
path: file.path,
|
|
@@ -155680,7 +155825,8 @@ async function runExportUnity(workspace, outDir) {
|
|
|
155680
155825
|
writeUnityGeneratedFiles(
|
|
155681
155826
|
scriptsDir,
|
|
155682
155827
|
response.projectId,
|
|
155683
|
-
response.generatedFiles
|
|
155828
|
+
response.generatedFiles,
|
|
155829
|
+
response.codegenRevision
|
|
155684
155830
|
);
|
|
155685
155831
|
writeFileSync16(join19(resourcesDir, "project.json"), response.projectJson);
|
|
155686
155832
|
for (const file of response.localizationFiles ?? []) {
|
|
@@ -156229,7 +156375,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
156229
156375
|
async function main() {
|
|
156230
156376
|
const args = parseArgs(process.argv.slice(2));
|
|
156231
156377
|
if (args.command === "--version") {
|
|
156232
|
-
console.log("0.
|
|
156378
|
+
console.log("0.63.0");
|
|
156233
156379
|
return;
|
|
156234
156380
|
}
|
|
156235
156381
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/dist/test-worker.mjs
CHANGED
|
@@ -15569,6 +15569,9 @@ var NSFunctionArgumentReservedNames = /* @__PURE__ */ new Set([
|
|
|
15569
15569
|
...FunctionArgumentReservedNames,
|
|
15570
15570
|
"value"
|
|
15571
15571
|
]);
|
|
15572
|
+
function isFunctionEffectKind(value) {
|
|
15573
|
+
return value === 0 /* None */ || value === 1 /* Auto */;
|
|
15574
|
+
}
|
|
15572
15575
|
var CHAIN_RESOLVED_OPTIONAL_MEMBER_FIELDS = [
|
|
15573
15576
|
"storageKey",
|
|
15574
15577
|
"minValue",
|
|
@@ -16310,6 +16313,11 @@ function hasValidStorageField(v, allowNull) {
|
|
|
16310
16313
|
if (typeof v.kind !== "number") return false;
|
|
16311
16314
|
return memberKindSupportsStorage(v.kind);
|
|
16312
16315
|
}
|
|
16316
|
+
function hasValidEffectField(v) {
|
|
16317
|
+
if (v.effect === void 0) return true;
|
|
16318
|
+
if (!isFunctionEffectKind(v.effect)) return false;
|
|
16319
|
+
return v.kind === 13 /* Function */ || v.kind === 23 /* NSFunction */;
|
|
16320
|
+
}
|
|
16313
16321
|
function hasValidDistributionField(v) {
|
|
16314
16322
|
if (v.distribution === void 0) return true;
|
|
16315
16323
|
if (!isNeoSubtreeDistributionKind(v.distribution)) return false;
|
|
@@ -16340,6 +16348,7 @@ function isMemberBase(value) {
|
|
|
16340
16348
|
}
|
|
16341
16349
|
if (!hasValidStorageField(v, true)) return false;
|
|
16342
16350
|
if (!hasValidDistributionField(v)) return false;
|
|
16351
|
+
if (!hasValidEffectField(v)) return false;
|
|
16343
16352
|
const storageKey = getField(value, "storageKey");
|
|
16344
16353
|
if (storageKey !== void 0 && storageKey !== null && typeof storageKey !== "string")
|
|
16345
16354
|
return false;
|
|
@@ -16439,6 +16448,7 @@ function isMemberOverrideBase(value) {
|
|
|
16439
16448
|
}
|
|
16440
16449
|
if (!hasValidStorageField(v, false)) return false;
|
|
16441
16450
|
if (!hasValidDistributionField(v)) return false;
|
|
16451
|
+
if (!hasValidEffectField(v)) return false;
|
|
16442
16452
|
if (v.defaultValue !== void 0 && v.defaultValue !== null && !isMemberValueBase(v.defaultValue)) {
|
|
16443
16453
|
return false;
|
|
16444
16454
|
}
|
|
@@ -20142,6 +20152,7 @@ var SCHEMA_DOCUMENT_FIELD_CONTRACTS = {
|
|
|
20142
20152
|
"argumentTypes",
|
|
20143
20153
|
"dispatch",
|
|
20144
20154
|
"bodyMode",
|
|
20155
|
+
"effect",
|
|
20145
20156
|
"uiAction",
|
|
20146
20157
|
"templateId",
|
|
20147
20158
|
"genericParamId"
|
|
@@ -44757,6 +44768,7 @@ var MEMBER_SEARCH_BY = ["none", "memberKey"];
|
|
|
44757
44768
|
var MEMBER_SELECTION = ["single", "multi"];
|
|
44758
44769
|
var FUNCTION_DISPATCH = ["synchronous", "asynchronous"];
|
|
44759
44770
|
var FUNCTION_BODY = ["code", "ui"];
|
|
44771
|
+
var FUNCTION_EFFECT = ["none", "auto"];
|
|
44760
44772
|
var MEMBER_PAYLOAD = ["full", "partial"];
|
|
44761
44773
|
var DICTIONARY_KEY = ["string", "enum"];
|
|
44762
44774
|
var LIST_KIND = ["ordered", "unordered"];
|
|
@@ -45094,12 +45106,24 @@ function memberFromDocument(record2, members, owners, classNames, context) {
|
|
|
45094
45106
|
FUNCTION_DISPATCH,
|
|
45095
45107
|
record2,
|
|
45096
45108
|
"dispatch"
|
|
45097
|
-
) === "asynchronous"
|
|
45109
|
+
) === "asynchronous",
|
|
45110
|
+
// The row's own value, not the chain's: an override without `@effect`
|
|
45111
|
+
// inherits, and resolving here would emit the ancestor's kind back
|
|
45112
|
+
// into the override's source as phantom drift.
|
|
45113
|
+
...data.effect === void 0 || data.effect === null ? {} : {
|
|
45114
|
+
effect: ordinalValue(
|
|
45115
|
+
data.effect,
|
|
45116
|
+
FUNCTION_EFFECT,
|
|
45117
|
+
record2,
|
|
45118
|
+
"effect"
|
|
45119
|
+
)
|
|
45120
|
+
}
|
|
45098
45121
|
};
|
|
45099
45122
|
if (kind === MEMBER_KIND.Function) {
|
|
45100
45123
|
return { ...common, kind: "function", ...signature };
|
|
45101
45124
|
}
|
|
45102
|
-
const
|
|
45125
|
+
const codeValue = field("code", null);
|
|
45126
|
+
const code = codeValue === "" ? "" : optionalStringOrNull(codeValue);
|
|
45103
45127
|
const bodyModeValue = ordinalValue(
|
|
45104
45128
|
field("bodyMode", 0),
|
|
45105
45129
|
FUNCTION_BODY,
|
|
@@ -45365,6 +45389,9 @@ function memberToDocumentFields(member, baseData) {
|
|
|
45365
45389
|
if (member.deferred || isOverride) {
|
|
45366
45390
|
fields.dispatch = member.deferred ? 1 : 0;
|
|
45367
45391
|
}
|
|
45392
|
+
if (member.effect !== void 0) {
|
|
45393
|
+
fields.effect = FUNCTION_EFFECT.indexOf(member.effect);
|
|
45394
|
+
}
|
|
45368
45395
|
if (member.kind === "scriptFunction" && member.script !== null && member.bodyMode !== "ui") {
|
|
45369
45396
|
fields.code = member.script.sourceText;
|
|
45370
45397
|
}
|
package/package.json
CHANGED
|
@@ -110,7 +110,7 @@ wrappers.
|
|
|
110
110
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
111
111
|
|
|
112
112
|
```html
|
|
113
|
-
<!-- reviewed-through-cli: 0.
|
|
113
|
+
<!-- reviewed-through-cli: 0.63.0 -->
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -105,6 +105,12 @@ Use context-aware typed annotations:
|
|
|
105
105
|
explicitly stored. A packed subtree shares its parent's document-size limit,
|
|
106
106
|
so a write that would exceed the hard limit fails instead of falling back.
|
|
107
107
|
`.Packed` is rejected on a List whose `listKind` is unordered.
|
|
108
|
+
- `@effect` only on a class member function. The Unity runtime runs it for
|
|
109
|
+
every live instance and reruns it whenever data it read changes; the web
|
|
110
|
+
editor, `neo test`, and dry runs never run effects. It must be an immediate,
|
|
111
|
+
parameterless `void` instance function with a NeoScript or abstract body.
|
|
112
|
+
An override without the annotation inherits; `@effect(kind: .None)` stops
|
|
113
|
+
an inherited effect. Use it instead of polling or relaying changes by hand.
|
|
108
114
|
|
|
109
115
|
Use numeric literals for numeric limits. Keep annotations separate instead of
|
|
110
116
|
inventing a generic metadata bag.
|