@neocompose/cli 0.31.14 → 0.31.17
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,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.31.17] - 2026-08-18
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Accept runtime interface patterns on open Class hierarchies while retaining
|
|
8
|
+
impossible-pattern diagnostics for sealed Classes.
|
|
9
|
+
- Recognize typed NeoScript setters as writable from initializers and function
|
|
10
|
+
bodies, including compound assignments, and compile their setter bodies.
|
|
11
|
+
- Preserve `NeoVariant<T>` member types in the local manifest used by
|
|
12
|
+
`neo script check --all`, matching `neo test` candidate compilation.
|
|
13
|
+
|
|
14
|
+
## [0.31.16] - 2026-08-18
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Resolve unordered List membership from entry `containerId` rows during
|
|
19
|
+
NeoScript evaluation, so root-backed indexes and collection operations see
|
|
20
|
+
stored entries in CLI tests, web previews, and world construction.
|
|
21
|
+
|
|
22
|
+
## [0.31.15] - 2026-08-18
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- Accept authored internal record relation creates without server-owned project
|
|
27
|
+
and timestamp metadata, including durable pushes, and mirror the server's
|
|
28
|
+
metadata stamping during dry-run validation.
|
|
29
|
+
|
|
3
30
|
## [0.31.14] - 2026-08-18
|
|
4
31
|
|
|
5
32
|
### Fixed
|
package/dist/neo.mjs
CHANGED
|
@@ -8817,6 +8817,18 @@ function typesOverlap(left, right, project) {
|
|
|
8817
8817
|
if (isNull(right)) return isNullable(left);
|
|
8818
8818
|
if (isNeoScriptTypeAssignable(left, right, project) || isNeoScriptTypeAssignable(right, left, project))
|
|
8819
8819
|
return true;
|
|
8820
|
+
if (left.kind === "named" && right.kind === "named") {
|
|
8821
|
+
const leftDeclaration = project.typeById.get(left.typeId);
|
|
8822
|
+
const rightDeclaration = project.typeById.get(right.typeId);
|
|
8823
|
+
if (leftDeclaration?.kind === "interface" && rightDeclaration?.kind === "interface") {
|
|
8824
|
+
return true;
|
|
8825
|
+
}
|
|
8826
|
+
const classDeclaration = leftDeclaration?.kind === "class" ? leftDeclaration : rightDeclaration?.kind === "class" ? rightDeclaration : null;
|
|
8827
|
+
const interfaceDeclaration = leftDeclaration?.kind === "interface" ? leftDeclaration : rightDeclaration?.kind === "interface" ? rightDeclaration : null;
|
|
8828
|
+
if (classDeclaration !== null && interfaceDeclaration !== null) {
|
|
8829
|
+
return classDeclaration.sealed !== true;
|
|
8830
|
+
}
|
|
8831
|
+
}
|
|
8820
8832
|
return isNumeric(left) && isNumeric(right);
|
|
8821
8833
|
}
|
|
8822
8834
|
function isUnknown(type) {
|
|
@@ -24110,6 +24122,7 @@ function buildProjectGraph(documents) {
|
|
|
24110
24122
|
...interfaceTypeIds.length ? { interfaceTypeIds } : {},
|
|
24111
24123
|
...typeParameters.length ? { typeParameters } : {},
|
|
24112
24124
|
...classDeclaration?.modifiers.includes("abstract") ? { abstract: true } : {},
|
|
24125
|
+
...classDeclaration?.modifiers.includes("sealed") ? { sealed: true } : {},
|
|
24113
24126
|
location: location(info.uri, info.declaration.range),
|
|
24114
24127
|
selectionLocation: location(info.uri, info.declaration.nameRange)
|
|
24115
24128
|
};
|
|
@@ -24612,10 +24625,23 @@ function accessorBodyRange(source, bodyRange, keyword) {
|
|
|
24612
24625
|
continue;
|
|
24613
24626
|
}
|
|
24614
24627
|
if (depth !== 1 || token.text !== keyword) continue;
|
|
24615
|
-
|
|
24628
|
+
let openIndex = index + 1;
|
|
24629
|
+
if (tokens[openIndex]?.text === "(") {
|
|
24630
|
+
let parameterDepth = 1;
|
|
24631
|
+
for (let cursor = openIndex + 1; cursor < tokens.length; cursor++) {
|
|
24632
|
+
const candidate = tokens[cursor];
|
|
24633
|
+
if (candidate.text === "(") parameterDepth++;
|
|
24634
|
+
if (candidate.text === ")") parameterDepth--;
|
|
24635
|
+
if (parameterDepth !== 0) continue;
|
|
24636
|
+
openIndex = cursor + 1;
|
|
24637
|
+
break;
|
|
24638
|
+
}
|
|
24639
|
+
if (parameterDepth !== 0) return null;
|
|
24640
|
+
}
|
|
24641
|
+
const open = tokens[openIndex];
|
|
24616
24642
|
if (open?.text !== "{") return null;
|
|
24617
24643
|
let accessorDepth = 1;
|
|
24618
|
-
for (let cursor =
|
|
24644
|
+
for (let cursor = openIndex + 1; cursor < tokens.length; cursor++) {
|
|
24619
24645
|
const candidate = tokens[cursor];
|
|
24620
24646
|
if (candidate.text === "{") accessorDepth++;
|
|
24621
24647
|
if (candidate.text === "}") accessorDepth--;
|
|
@@ -31325,6 +31351,7 @@ function schemaClass(value, environment, field) {
|
|
|
31325
31351
|
`${field}.implementsInterfaceIds`
|
|
31326
31352
|
),
|
|
31327
31353
|
...value.declarationModifier === "abstract" ? { abstract: true } : {},
|
|
31354
|
+
...value.isSealed === true ? { sealed: true } : {},
|
|
31328
31355
|
...sourceLocation(value.source, environment, `${field}.source`),
|
|
31329
31356
|
typeParameters: records(
|
|
31330
31357
|
value.genericParameters ?? [],
|
|
@@ -31945,6 +31972,20 @@ function memberType(member, environment, visiting, field) {
|
|
|
31945
31972
|
nullable: false
|
|
31946
31973
|
};
|
|
31947
31974
|
}
|
|
31975
|
+
if (kind === "variant") {
|
|
31976
|
+
const variantClass = [...environment.classes.values()].find(
|
|
31977
|
+
(candidate) => candidate.name === NEO_VARIANT_TYPE_NAME
|
|
31978
|
+
);
|
|
31979
|
+
if (variantClass === void 0) return { ...unknownType(), nullable };
|
|
31980
|
+
return {
|
|
31981
|
+
kind: "named",
|
|
31982
|
+
typeId: string2(variantClass.id, `${field}.variantClass.id`),
|
|
31983
|
+
typeArguments: [
|
|
31984
|
+
manifestType2(member.targetType, environment, `${field}.targetType`)
|
|
31985
|
+
],
|
|
31986
|
+
nullable
|
|
31987
|
+
};
|
|
31988
|
+
}
|
|
31948
31989
|
if (kind === "generic") {
|
|
31949
31990
|
return typeParameter(
|
|
31950
31991
|
string2(member.genericParamId, `${field}.genericParamId`),
|
|
@@ -32487,6 +32528,7 @@ var init_project_schema_manifest = __esm({
|
|
|
32487
32528
|
"use strict";
|
|
32488
32529
|
init_project();
|
|
32489
32530
|
init_project_schema_contract_generated();
|
|
32531
|
+
init_language_spec();
|
|
32490
32532
|
}
|
|
32491
32533
|
});
|
|
32492
32534
|
|
|
@@ -46337,6 +46379,23 @@ var init_member_kinds_db_response = __esm({
|
|
|
46337
46379
|
});
|
|
46338
46380
|
|
|
46339
46381
|
// ../src/models/members/unordered-list-membership.ts
|
|
46382
|
+
function buildUnorderedListMembershipIndex(values) {
|
|
46383
|
+
const membersByContainerId = /* @__PURE__ */ new Map();
|
|
46384
|
+
for (const candidate of values) {
|
|
46385
|
+
const containerId = candidate.containerId;
|
|
46386
|
+
if (typeof containerId !== "string") continue;
|
|
46387
|
+
const bucket = membersByContainerId.get(containerId);
|
|
46388
|
+
if (bucket === void 0) {
|
|
46389
|
+
membersByContainerId.set(containerId, [candidate.id]);
|
|
46390
|
+
} else {
|
|
46391
|
+
bucket.push(candidate.id);
|
|
46392
|
+
}
|
|
46393
|
+
}
|
|
46394
|
+
for (const bucket of membersByContainerId.values()) {
|
|
46395
|
+
bucket.sort();
|
|
46396
|
+
}
|
|
46397
|
+
return membersByContainerId;
|
|
46398
|
+
}
|
|
46340
46399
|
function unorderedListEntryIds(values, listValue2, membershipIndex) {
|
|
46341
46400
|
if (!Array.isArray(listValue2.value)) return [];
|
|
46342
46401
|
if (membershipIndex !== void 0) {
|
|
@@ -49214,9 +49273,16 @@ function isProjectRecordKind(value) {
|
|
|
49214
49273
|
return false;
|
|
49215
49274
|
}
|
|
49216
49275
|
function isInternalRecordRelation(value) {
|
|
49217
|
-
if (!
|
|
49276
|
+
if (!isAuthoredInternalRecordRelation(value)) return false;
|
|
49218
49277
|
const relation = value;
|
|
49219
49278
|
if (!isString(relation.projectId)) return false;
|
|
49279
|
+
if (!isNumber(relation.createdAt)) return false;
|
|
49280
|
+
return isNumber(relation.updatedAt);
|
|
49281
|
+
}
|
|
49282
|
+
function isAuthoredInternalRecordRelation(value) {
|
|
49283
|
+
if (!isWithId(value)) return false;
|
|
49284
|
+
if (value.id.length === 0) return false;
|
|
49285
|
+
const relation = value;
|
|
49220
49286
|
if (!isString(relation.relationKind)) return false;
|
|
49221
49287
|
if (relation.relationKind.length === 0) return false;
|
|
49222
49288
|
if (!isProjectRecordKind(relation.sourceRecordKind)) return false;
|
|
@@ -49228,8 +49294,7 @@ function isInternalRecordRelation(value) {
|
|
|
49228
49294
|
if (relation.orderKey !== void 0 && (!isString(relation.orderKey) || relation.orderKey.length === 0)) {
|
|
49229
49295
|
return false;
|
|
49230
49296
|
}
|
|
49231
|
-
|
|
49232
|
-
return isNumber(relation.updatedAt);
|
|
49297
|
+
return true;
|
|
49233
49298
|
}
|
|
49234
49299
|
function isProjectVersionSemver(value) {
|
|
49235
49300
|
if (!isObject(value)) return false;
|
|
@@ -63881,9 +63946,11 @@ function makeEvaluatorLookups(members, values, options = {}) {
|
|
|
63881
63946
|
for (const a of members) attrMap.set(a.id, a);
|
|
63882
63947
|
const valMap = /* @__PURE__ */ new Map();
|
|
63883
63948
|
for (const v of values) valMap.set(v.id, v);
|
|
63949
|
+
const unorderedListMembership = buildUnorderedListMembershipIndex(values);
|
|
63884
63950
|
const lookups = {
|
|
63885
63951
|
memberById: (id2) => attrMap.get(id2) ?? null,
|
|
63886
|
-
valueById: (id2) => valMap.get(id2) ?? null
|
|
63952
|
+
valueById: (id2) => valMap.get(id2) ?? null,
|
|
63953
|
+
unorderedListEntryIds: (containerValueId) => unorderedListMembership.get(containerValueId) ?? []
|
|
63887
63954
|
};
|
|
63888
63955
|
if (options.includeValueGraphIndexes === true) {
|
|
63889
63956
|
return {
|
|
@@ -67830,9 +67897,24 @@ function resolveValueIfIdForMember(at, member, ctx) {
|
|
|
67830
67897
|
);
|
|
67831
67898
|
if (!row) return at;
|
|
67832
67899
|
ctx.valueDependencies?.add(row.id);
|
|
67900
|
+
if (isMemberListBase(member) && member.listKind === "unordered" && Array.isArray(row.value)) {
|
|
67901
|
+
return evaluatorUnorderedListEntryIds(row.id, ctx);
|
|
67902
|
+
}
|
|
67833
67903
|
const value = resolveLocalizedRowValueForMember(row, member, ctx);
|
|
67834
67904
|
return shouldUnwrapSingleLookupValue(member) ? unwrapSingleLookupValue(value, ctx) : value;
|
|
67835
67905
|
}
|
|
67906
|
+
function evaluatorUnorderedListEntryIds(containerValueId, ctx) {
|
|
67907
|
+
const runtimeRows = [...ctx.__runtimeSessionValues?.values() ?? []];
|
|
67908
|
+
const overlayRows = [...ctx.__valueOverlay?.values() ?? []];
|
|
67909
|
+
const localRows = [...runtimeRows, ...overlayRows];
|
|
67910
|
+
const shadowedIds = new Set(localRows.map((row) => row.id));
|
|
67911
|
+
const baseIds = ctx.vm.databaseVM?.unorderedListEntryIds?.(containerValueId) ?? ctx.vm.values.filter((row) => row.containerId === containerValueId).map((row) => row.id);
|
|
67912
|
+
const ids = new Set(baseIds.filter((id2) => !shadowedIds.has(id2)));
|
|
67913
|
+
for (const row of localRows) {
|
|
67914
|
+
if (row.containerId === containerValueId) ids.add(row.id);
|
|
67915
|
+
}
|
|
67916
|
+
return [...ids].sort();
|
|
67917
|
+
}
|
|
67836
67918
|
function shouldUnwrapSingleLookupValue(member) {
|
|
67837
67919
|
if (member === null) return false;
|
|
67838
67920
|
if (!isMemberLookup(member)) return false;
|
|
@@ -71974,7 +72056,7 @@ function initializerEvaluatorLookups(document) {
|
|
|
71974
72056
|
});
|
|
71975
72057
|
return lookups;
|
|
71976
72058
|
}
|
|
71977
|
-
function
|
|
72059
|
+
function buildInitializerRootValueWithLookups(document, lookups) {
|
|
71978
72060
|
const rootValue = {};
|
|
71979
72061
|
for (const { root, memberId } of projectRootMembersInDisplayOrder(
|
|
71980
72062
|
document.project
|
|
@@ -72014,7 +72096,7 @@ function evaluateMemberInitializer(args) {
|
|
|
72014
72096
|
databaseVM
|
|
72015
72097
|
},
|
|
72016
72098
|
thisValue: null,
|
|
72017
|
-
rootValue:
|
|
72099
|
+
rootValue: buildInitializerRootValueWithLookups(args.document, databaseVM),
|
|
72018
72100
|
saveStaticBindings: args.saveStaticBindings,
|
|
72019
72101
|
sessionStaticBindings: args.sessionStaticBindings,
|
|
72020
72102
|
...args.storedConstructionReplay === true ? {
|
|
@@ -81254,23 +81336,6 @@ function isPushIntentInternalRecordRelation(value, operation) {
|
|
|
81254
81336
|
}
|
|
81255
81337
|
return isInternalRecordRelation(value);
|
|
81256
81338
|
}
|
|
81257
|
-
function isAuthoredInternalRecordRelation(value) {
|
|
81258
|
-
if (!isObjectRecord5(value)) return false;
|
|
81259
|
-
if (!isNonEmptyString3(value.id)) return false;
|
|
81260
|
-
if (!isNonEmptyString3(value.relationKind)) return false;
|
|
81261
|
-
if (!isProjectRecordKind(value.sourceRecordKind)) return false;
|
|
81262
|
-
if (!isNonEmptyString3(value.sourceRecordId)) return false;
|
|
81263
|
-
if (!isProjectRecordKind(value.targetRecordKind)) return false;
|
|
81264
|
-
if (!isNonEmptyString3(value.targetRecordId)) return false;
|
|
81265
|
-
if (value.orderKey === void 0) return true;
|
|
81266
|
-
return isNonEmptyString3(value.orderKey);
|
|
81267
|
-
}
|
|
81268
|
-
function isObjectRecord5(value) {
|
|
81269
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
81270
|
-
}
|
|
81271
|
-
function isNonEmptyString3(value) {
|
|
81272
|
-
return typeof value === "string" && value.length > 0;
|
|
81273
|
-
}
|
|
81274
81339
|
var init_push_change_intent = __esm({
|
|
81275
81340
|
"src/commands/push-change-intent.ts"() {
|
|
81276
81341
|
"use strict";
|
|
@@ -94520,13 +94585,24 @@ function sortSeedRows(values) {
|
|
|
94520
94585
|
return 0;
|
|
94521
94586
|
});
|
|
94522
94587
|
}
|
|
94523
|
-
function
|
|
94588
|
+
function stampServerOwnedSourceCommitMetadata(args) {
|
|
94524
94589
|
if (!isObjectRecord2(args.rawDocument)) {
|
|
94525
94590
|
throw new ProjectSourceCommitVerificationError(
|
|
94526
94591
|
"Authoritative project document must be an object."
|
|
94527
94592
|
);
|
|
94528
94593
|
}
|
|
94529
94594
|
const raw = args.rawDocument;
|
|
94595
|
+
const project = raw.project;
|
|
94596
|
+
if (!isObjectRecord2(project) || typeof project.id !== "string") {
|
|
94597
|
+
throw new ProjectSourceCommitVerificationError(
|
|
94598
|
+
"Authoritative project document must contain a project id."
|
|
94599
|
+
);
|
|
94600
|
+
}
|
|
94601
|
+
if (project.id.length === 0) {
|
|
94602
|
+
throw new ProjectSourceCommitVerificationError(
|
|
94603
|
+
"Authoritative project document project id must not be empty."
|
|
94604
|
+
);
|
|
94605
|
+
}
|
|
94530
94606
|
const now = args.timestamp ?? Date.now();
|
|
94531
94607
|
if (!Number.isSafeInteger(now)) {
|
|
94532
94608
|
throw new ProjectSourceCommitVerificationError(
|
|
@@ -94542,6 +94618,11 @@ function stampServerOwnedSourceCommitTimestamps(args) {
|
|
|
94542
94618
|
if (change.operation === "delete") return change;
|
|
94543
94619
|
if (!isObjectRecord2(change.nextData)) return change;
|
|
94544
94620
|
const stamped = { ...change.nextData };
|
|
94621
|
+
if (change.recordKind === "project") {
|
|
94622
|
+
delete stamped.projectId;
|
|
94623
|
+
} else {
|
|
94624
|
+
stamped.projectId = project.id;
|
|
94625
|
+
}
|
|
94545
94626
|
if (change.operation === "create") {
|
|
94546
94627
|
stamped.createdAt = now;
|
|
94547
94628
|
stamped.updatedAt = now;
|
|
@@ -94698,7 +94779,7 @@ function prepareServerPreparationChanges(args) {
|
|
|
94698
94779
|
`${change.recordKind}:${change.recordId}`
|
|
94699
94780
|
)
|
|
94700
94781
|
}));
|
|
94701
|
-
const trustedChanges =
|
|
94782
|
+
const trustedChanges = stampServerOwnedSourceCommitMetadata({
|
|
94702
94783
|
rawDocument,
|
|
94703
94784
|
changes
|
|
94704
94785
|
});
|
|
@@ -108671,11 +108752,11 @@ function assertProjectFileAuthoringRecordIdentifiers(recordKind, data) {
|
|
|
108671
108752
|
if (recordKind !== "unity-texture-template" && recordKind !== "unity-audio-clip-template") {
|
|
108672
108753
|
return;
|
|
108673
108754
|
}
|
|
108674
|
-
if (!
|
|
108755
|
+
if (!isObjectRecord5(data) || typeof data.name !== "string") return;
|
|
108675
108756
|
const label = recordKind === "unity-texture-template" ? "Unity texture template name" : "Unity audio clip template name";
|
|
108676
108757
|
assertProjectFileAuthoringIdentifier(data.name, label);
|
|
108677
108758
|
}
|
|
108678
|
-
function
|
|
108759
|
+
function isObjectRecord5(value) {
|
|
108679
108760
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
108680
108761
|
}
|
|
108681
108762
|
var init_project_file_authoring_identifiers = __esm({
|
|
@@ -108686,12 +108767,13 @@ var init_project_file_authoring_identifiers = __esm({
|
|
|
108686
108767
|
});
|
|
108687
108768
|
|
|
108688
108769
|
// ../src/database/project-version-validation.ts
|
|
108689
|
-
function validateProjectRecordByKind(recordKind, data) {
|
|
108770
|
+
function validateProjectRecordByKind(recordKind, data, options = {}) {
|
|
108690
108771
|
if (recordKind === ProjectRecordKind.Project) {
|
|
108691
108772
|
if (isProject(data)) return;
|
|
108692
108773
|
}
|
|
108693
108774
|
if (recordKind === ProjectRecordKind.Member) {
|
|
108694
|
-
|
|
108775
|
+
const memberGuard = options.members === "authored-or-compiled" ? isAnyMemberAuthoredOrCompiled : isAnyMember;
|
|
108776
|
+
if (memberGuard(data)) return;
|
|
108695
108777
|
}
|
|
108696
108778
|
if (recordKind === ProjectRecordKind.Value) {
|
|
108697
108779
|
if (isMemberValue(data)) return;
|
|
@@ -111624,7 +111706,7 @@ var init_registry2 = __esm({
|
|
|
111624
111706
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
111625
111707
|
formatVersion: 3,
|
|
111626
111708
|
contractVersion: "3.13",
|
|
111627
|
-
cliVersion: "0.31.
|
|
111709
|
+
cliVersion: "0.31.17",
|
|
111628
111710
|
projectFileUploadBatchSize: 32,
|
|
111629
111711
|
documentRecords: {
|
|
111630
111712
|
member: {
|
|
@@ -118219,7 +118301,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
118219
118301
|
async function main() {
|
|
118220
118302
|
const args = parseArgs(process.argv.slice(2));
|
|
118221
118303
|
if (args.command === "--version") {
|
|
118222
|
-
console.log("0.31.
|
|
118304
|
+
console.log("0.31.17");
|
|
118223
118305
|
return;
|
|
118224
118306
|
}
|
|
118225
118307
|
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.31.
|
|
86
|
+
<!-- reviewed-through-cli: 0.31.17 -->
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -56,6 +56,11 @@ or narrowing guard before the next access.
|
|
|
56
56
|
|
|
57
57
|
Treat lookup-return values with the same nullable narrowing rules.
|
|
58
58
|
|
|
59
|
+
Runtime declaration patterns follow the possible runtime type, not only the
|
|
60
|
+
static declaration. An open Class value may match an otherwise unrelated
|
|
61
|
+
interface through a derived Class that implements it; a sealed Class with no
|
|
62
|
+
such relationship remains a compile-time impossible pattern.
|
|
63
|
+
|
|
59
64
|
A declaration pattern introduced by `is` stays available after a guard when
|
|
60
65
|
every path that falls through matched the pattern, including when the guard's
|
|
61
66
|
other paths return from a nested block:
|