@neocompose/cli 0.31.15 → 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,24 @@
|
|
|
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
|
+
|
|
3
22
|
## [0.31.15] - 2026-08-18
|
|
4
23
|
|
|
5
24
|
### 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) {
|
|
@@ -63887,9 +63946,11 @@ function makeEvaluatorLookups(members, values, options = {}) {
|
|
|
63887
63946
|
for (const a of members) attrMap.set(a.id, a);
|
|
63888
63947
|
const valMap = /* @__PURE__ */ new Map();
|
|
63889
63948
|
for (const v of values) valMap.set(v.id, v);
|
|
63949
|
+
const unorderedListMembership = buildUnorderedListMembershipIndex(values);
|
|
63890
63950
|
const lookups = {
|
|
63891
63951
|
memberById: (id2) => attrMap.get(id2) ?? null,
|
|
63892
|
-
valueById: (id2) => valMap.get(id2) ?? null
|
|
63952
|
+
valueById: (id2) => valMap.get(id2) ?? null,
|
|
63953
|
+
unorderedListEntryIds: (containerValueId) => unorderedListMembership.get(containerValueId) ?? []
|
|
63893
63954
|
};
|
|
63894
63955
|
if (options.includeValueGraphIndexes === true) {
|
|
63895
63956
|
return {
|
|
@@ -67836,9 +67897,24 @@ function resolveValueIfIdForMember(at, member, ctx) {
|
|
|
67836
67897
|
);
|
|
67837
67898
|
if (!row) return at;
|
|
67838
67899
|
ctx.valueDependencies?.add(row.id);
|
|
67900
|
+
if (isMemberListBase(member) && member.listKind === "unordered" && Array.isArray(row.value)) {
|
|
67901
|
+
return evaluatorUnorderedListEntryIds(row.id, ctx);
|
|
67902
|
+
}
|
|
67839
67903
|
const value = resolveLocalizedRowValueForMember(row, member, ctx);
|
|
67840
67904
|
return shouldUnwrapSingleLookupValue(member) ? unwrapSingleLookupValue(value, ctx) : value;
|
|
67841
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
|
+
}
|
|
67842
67918
|
function shouldUnwrapSingleLookupValue(member) {
|
|
67843
67919
|
if (member === null) return false;
|
|
67844
67920
|
if (!isMemberLookup(member)) return false;
|
|
@@ -71980,7 +72056,7 @@ function initializerEvaluatorLookups(document) {
|
|
|
71980
72056
|
});
|
|
71981
72057
|
return lookups;
|
|
71982
72058
|
}
|
|
71983
|
-
function
|
|
72059
|
+
function buildInitializerRootValueWithLookups(document, lookups) {
|
|
71984
72060
|
const rootValue = {};
|
|
71985
72061
|
for (const { root, memberId } of projectRootMembersInDisplayOrder(
|
|
71986
72062
|
document.project
|
|
@@ -72020,7 +72096,7 @@ function evaluateMemberInitializer(args) {
|
|
|
72020
72096
|
databaseVM
|
|
72021
72097
|
},
|
|
72022
72098
|
thisValue: null,
|
|
72023
|
-
rootValue:
|
|
72099
|
+
rootValue: buildInitializerRootValueWithLookups(args.document, databaseVM),
|
|
72024
72100
|
saveStaticBindings: args.saveStaticBindings,
|
|
72025
72101
|
sessionStaticBindings: args.sessionStaticBindings,
|
|
72026
72102
|
...args.storedConstructionReplay === true ? {
|
|
@@ -111630,7 +111706,7 @@ var init_registry2 = __esm({
|
|
|
111630
111706
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
111631
111707
|
formatVersion: 3,
|
|
111632
111708
|
contractVersion: "3.13",
|
|
111633
|
-
cliVersion: "0.31.
|
|
111709
|
+
cliVersion: "0.31.17",
|
|
111634
111710
|
projectFileUploadBatchSize: 32,
|
|
111635
111711
|
documentRecords: {
|
|
111636
111712
|
member: {
|
|
@@ -118225,7 +118301,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
118225
118301
|
async function main() {
|
|
118226
118302
|
const args = parseArgs(process.argv.slice(2));
|
|
118227
118303
|
if (args.command === "--version") {
|
|
118228
|
-
console.log("0.31.
|
|
118304
|
+
console.log("0.31.17");
|
|
118229
118305
|
return;
|
|
118230
118306
|
}
|
|
118231
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:
|