@neocompose/cli 0.68.2 → 0.68.4
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 +14 -0
- package/dist/neo.mjs +429 -129
- package/dist/test-worker.mjs +2 -0
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +4 -3
- package/skills/neocompose-cli/references/cli-development.md +1 -1
- package/skills/neocompose-cli/references/declarations-and-construction.md +8 -0
- package/skills/neocompose-cli/references/values-identities-and-references.md +18 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.68.4] - 2026-10-05
|
|
4
|
+
|
|
5
|
+
- An empty header base clause such as `class Child(string name) : Base() { Name = name } {}` uses the base's member initializers when its declared constructors require arguments. The base block must settle remaining required members. Zero-argument and fully defaulted base constructors still run; required base constructors and declared `: base()` calls still require valid arguments. Fixes [#1186](https://github.com/ryanbliss/neo-compose/issues/1186). Use SDK 0.57.4 for matching Unity runtime behavior.
|
|
6
|
+
|
|
7
|
+
## [0.68.3] - 2026-10-05
|
|
8
|
+
|
|
9
|
+
- `neo push --dry-run` preserves valid authored UUID-v4 IDs on new nested member and dictionary values, including values named by local declarations. Previously, verification dropped the ID and failed with an internal "has no pending id assignment" error. Status and push report malformed new member-value IDs at the annotation, name the affected `Class.Member`, and suggest removing `@id` or providing an unused UUID v4 ([#1189](https://github.com/ryanbliss/neo-compose/issues/1189)).
|
|
10
|
+
|
|
11
|
+
- A stored nested class value can keep its UUID-v4 when moved between compatible empty fields on existing parents. Its old owning declaration must be removed in the same push. Unsafe ownership changes are refused with an explanation.
|
|
12
|
+
|
|
13
|
+
- Trusted verification resolves complete pending IDs inside initializer code, so `Reference<T>(key:)` can target a row created in the same push without confusing its ID with the containing value's ID.
|
|
14
|
+
|
|
15
|
+
- An override of a generic class's function passes the push-time animation check, including an override of an override, as in `class ClampedIntWatcher : MinIntWatcher` where `MinIntWatcher : ValueWatcher<int>`. Before, status warned and test and push stopped with "Prospective animation validation received an invalid member record … (\"Apply\")" in any project with animation classes.
|
|
16
|
+
|
|
3
17
|
## [0.68.2] - 2026-10-05
|
|
4
18
|
|
|
5
19
|
- Local initializer IDs may appear above the variable declaration. Formatting and pull move inline IDs there while preserving the stored row identity. Nested IDs remain on their expressions.
|
package/dist/neo.mjs
CHANGED
|
@@ -22862,6 +22862,11 @@ var init_project_source_variants = __esm({
|
|
|
22862
22862
|
});
|
|
22863
22863
|
|
|
22864
22864
|
// ../packages/neoscript-language/src/project-source-settlement.ts
|
|
22865
|
+
function requiredConstructorParameters(declaration) {
|
|
22866
|
+
if (declaration.headerParameters !== void 0)
|
|
22867
|
+
return declaration.headerParameters;
|
|
22868
|
+
return declaration.initBlocks.length > 0 ? [] : void 0;
|
|
22869
|
+
}
|
|
22865
22870
|
function buildNeoConstructionIndex(documents) {
|
|
22866
22871
|
const classes = /* @__PURE__ */ new Map();
|
|
22867
22872
|
const interfaceNames = /* @__PURE__ */ new Set();
|
|
@@ -22933,8 +22938,9 @@ function unsettledRequiredMembers(index, className, settledNames, typeArguments
|
|
|
22933
22938
|
function classConstructionContract(index, className) {
|
|
22934
22939
|
const declaration = index.classes.get(className)?.declaration;
|
|
22935
22940
|
if (!declaration) return null;
|
|
22936
|
-
|
|
22937
|
-
|
|
22941
|
+
const parameters = requiredConstructorParameters(declaration);
|
|
22942
|
+
if (parameters !== void 0) {
|
|
22943
|
+
return { kind: "required", parameters };
|
|
22938
22944
|
}
|
|
22939
22945
|
if (declaration.constructors.length > 0) {
|
|
22940
22946
|
return { kind: "declared", constructors: declaration.constructors };
|
|
@@ -22998,7 +23004,7 @@ function validateBaseConstruction(index, entry, diagnostics) {
|
|
|
22998
23004
|
}
|
|
22999
23005
|
for (const diagnostic of validateNeoConstructionSite(index, {
|
|
23000
23006
|
className: baseClause.type.name,
|
|
23001
|
-
site: "
|
|
23007
|
+
site: "headerBase",
|
|
23002
23008
|
typeArguments: baseClause.type.typeArguments.map(typeShape),
|
|
23003
23009
|
argumentNames: (baseClause.arguments ?? []).map(
|
|
23004
23010
|
(argument2) => argument2.name ?? null
|
|
@@ -23024,11 +23030,10 @@ function validateBaseConstruction(index, entry, diagnostics) {
|
|
|
23024
23030
|
}
|
|
23025
23031
|
}
|
|
23026
23032
|
function validateUnconstructedBase(entry, base, range2, diagnostics) {
|
|
23027
|
-
const parameters = base.declaration
|
|
23033
|
+
const parameters = requiredConstructorParameters(base.declaration);
|
|
23028
23034
|
if (parameters === void 0) {
|
|
23029
|
-
if (entry.declaration
|
|
23030
|
-
|
|
23031
|
-
pushBaseCall(entry, base, [], () => range2, diagnostics);
|
|
23035
|
+
if (requiredConstructorParameters(entry.declaration) === void 0) return;
|
|
23036
|
+
pushBaseCall(entry, base, [], () => range2, diagnostics, "headerBase");
|
|
23032
23037
|
return;
|
|
23033
23038
|
}
|
|
23034
23039
|
if (parameterListIsFullyDefaulted(parameters)) return;
|
|
@@ -23047,7 +23052,7 @@ function validateUnconstructedBase(entry, base, range2, diagnostics) {
|
|
|
23047
23052
|
function validateDeclaredBaseCalls(entry, base, diagnostics) {
|
|
23048
23053
|
for (const constructor2 of entry.declaration.constructors) {
|
|
23049
23054
|
const baseArguments = constructor2.baseArguments ?? [];
|
|
23050
|
-
if (constructor2.baseArguments === void 0 && base.declaration
|
|
23055
|
+
if (constructor2.baseArguments === void 0 && requiredConstructorParameters(base.declaration) !== void 0) {
|
|
23051
23056
|
continue;
|
|
23052
23057
|
}
|
|
23053
23058
|
pushBaseCall(
|
|
@@ -23062,13 +23067,13 @@ function validateDeclaredBaseCalls(entry, base, diagnostics) {
|
|
|
23062
23067
|
);
|
|
23063
23068
|
}
|
|
23064
23069
|
}
|
|
23065
|
-
function pushBaseCall(entry, base, argumentNames, rangeOf, diagnostics) {
|
|
23070
|
+
function pushBaseCall(entry, base, argumentNames, rangeOf, diagnostics, site = "base") {
|
|
23066
23071
|
const siteDiagnostics = [];
|
|
23067
23072
|
resolveInvokedConstructor(
|
|
23068
23073
|
base.declaration,
|
|
23069
23074
|
{
|
|
23070
23075
|
className: base.declaration.name,
|
|
23071
|
-
site
|
|
23076
|
+
site,
|
|
23072
23077
|
argumentNames,
|
|
23073
23078
|
initializerNames: []
|
|
23074
23079
|
},
|
|
@@ -23127,7 +23132,7 @@ function validateDeclaredConstructionPaths(index, entry, diagnostics) {
|
|
|
23127
23132
|
[]
|
|
23128
23133
|
).filter((member) => owned || member.declaringClassName === declaration.name);
|
|
23129
23134
|
if (outstanding.length === 0) return;
|
|
23130
|
-
if (declaration
|
|
23135
|
+
if (requiredConstructorParameters(declaration) !== void 0) {
|
|
23131
23136
|
const initBlock = declaration.initBlocks[0];
|
|
23132
23137
|
const assigned = assignedOnEveryPath(initBlock?.body.text ?? "{}");
|
|
23133
23138
|
const unsettled = filterUnassigned(outstanding, assigned);
|
|
@@ -23168,13 +23173,30 @@ function filterUnassigned(members, assigned) {
|
|
|
23168
23173
|
}
|
|
23169
23174
|
function declarationSettledMembers(index, entry) {
|
|
23170
23175
|
const settled = /* @__PURE__ */ new Set();
|
|
23171
|
-
const
|
|
23172
|
-
|
|
23173
|
-
for (const field of baseClause
|
|
23176
|
+
const declaration = entry.declaration;
|
|
23177
|
+
const baseClause = declaration.baseClause;
|
|
23178
|
+
for (const field of baseClause?.initializerFields ?? []) {
|
|
23174
23179
|
settled.add(field.name.toLowerCase());
|
|
23175
23180
|
}
|
|
23176
|
-
if (
|
|
23177
|
-
|
|
23181
|
+
if (baseClause === void 0 && requiredConstructorParameters(declaration) === void 0)
|
|
23182
|
+
return settled;
|
|
23183
|
+
const baseName = baseClause?.type.name ?? declaration.baseTypes[0]?.name;
|
|
23184
|
+
const base = baseName === void 0 ? void 0 : index.classes.get(baseName);
|
|
23185
|
+
if (base === void 0) return settled;
|
|
23186
|
+
if (!resolveInvokedConstructor(
|
|
23187
|
+
base.declaration,
|
|
23188
|
+
{
|
|
23189
|
+
className: base.declaration.name,
|
|
23190
|
+
site: "headerBase",
|
|
23191
|
+
argumentNames: (baseClause?.arguments ?? []).map(
|
|
23192
|
+
(argument2) => argument2.name ?? null
|
|
23193
|
+
),
|
|
23194
|
+
initializerNames: []
|
|
23195
|
+
},
|
|
23196
|
+
[]
|
|
23197
|
+
))
|
|
23198
|
+
return settled;
|
|
23199
|
+
for (const member of requiredMembersForClass(index, base.declaration.name)) {
|
|
23178
23200
|
settled.add(member.name.toLowerCase());
|
|
23179
23201
|
}
|
|
23180
23202
|
return settled;
|
|
@@ -23192,7 +23214,7 @@ function baseClauseRange(declaration, anchor) {
|
|
|
23192
23214
|
return baseClause.range;
|
|
23193
23215
|
}
|
|
23194
23216
|
function resolveInvokedConstructor(declaration, call, diagnostics) {
|
|
23195
|
-
const headerParameters = declaration
|
|
23217
|
+
const headerParameters = requiredConstructorParameters(declaration);
|
|
23196
23218
|
if (headerParameters !== void 0) {
|
|
23197
23219
|
if (call.argumentNames.length > 0) {
|
|
23198
23220
|
validateArgumentsAgainstParameters(
|
|
@@ -23228,7 +23250,7 @@ function resolveInvokedConstructor(declaration, call, diagnostics) {
|
|
|
23228
23250
|
const parameterless = declaration.constructors.some(
|
|
23229
23251
|
(constructor2) => parameterListIsFullyDefaulted(constructor2.parameters)
|
|
23230
23252
|
);
|
|
23231
|
-
if (parameterless || call.site
|
|
23253
|
+
if (parameterless || call.site !== "base") return parameterless;
|
|
23232
23254
|
diagnostics.push({
|
|
23233
23255
|
code: "base-requires-construction",
|
|
23234
23256
|
message: `The base call must pass arguments: '${declaration.name}' declares no parameterless constructor \u2014 candidates: ${describeConstructors(declaration)}.`,
|
|
@@ -23245,7 +23267,7 @@ function resolveInvokedConstructor(declaration, call, diagnostics) {
|
|
|
23245
23267
|
);
|
|
23246
23268
|
return true;
|
|
23247
23269
|
}
|
|
23248
|
-
if (call.site
|
|
23270
|
+
if (call.site !== "new") {
|
|
23249
23271
|
let positional = false;
|
|
23250
23272
|
call.argumentNames.forEach((name, index) => {
|
|
23251
23273
|
if (name !== null) return;
|
|
@@ -31690,7 +31712,7 @@ var init_registry = __esm({
|
|
|
31690
31712
|
"../packages/manifest/schema-contract/registry.mjs"() {
|
|
31691
31713
|
"use strict";
|
|
31692
31714
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
31693
|
-
cliVersion: "0.68.
|
|
31715
|
+
cliVersion: "0.68.4",
|
|
31694
31716
|
projectFileUploadBatchSize: 32,
|
|
31695
31717
|
documentRecords: {
|
|
31696
31718
|
member: {
|
|
@@ -79315,6 +79337,8 @@ function resolveBaseConstructorRecord(record6, ctx) {
|
|
|
79315
79337
|
);
|
|
79316
79338
|
if (resolution.kind === "resolved") return resolution.overload;
|
|
79317
79339
|
if (resolution.kind === "noMatch" && baseArguments.length === 0) {
|
|
79340
|
+
if (owningClass.requiredConstructorId === record6.id && evaluatorSchemaIndex(ctx).class(baseClassId)?.requiredConstructorId == null)
|
|
79341
|
+
return null;
|
|
79318
79342
|
throw new NSGetterRuntimeError(
|
|
79319
79343
|
`Constructor '${record6.id}' on '${owningClass.name}' must call ': base(...)': its base class declares constructors but none parameterless.`
|
|
79320
79344
|
);
|
|
@@ -88861,6 +88885,8 @@ function resolveBaseConstructorOverload(args, owner) {
|
|
|
88861
88885
|
);
|
|
88862
88886
|
if (resolution.kind === "resolved") return resolution.overload;
|
|
88863
88887
|
if (resolution.kind === "noMatch" && baseArguments.length === 0) {
|
|
88888
|
+
if (owner.requiredConstructorId === args.constructor.id && baseClass.requiredConstructorId == null)
|
|
88889
|
+
return null;
|
|
88864
88890
|
throw new Error(
|
|
88865
88891
|
`Constructor "${args.constructor.id}" must declare a base call: base class "${baseClass.name}" declares constructors but none parameterless \u2014 candidates: ${describeConstructorOverloads(candidates)}.`
|
|
88866
88892
|
);
|
|
@@ -116847,6 +116873,59 @@ var init_client_commit_preparation = __esm({
|
|
|
116847
116873
|
}
|
|
116848
116874
|
});
|
|
116849
116875
|
|
|
116876
|
+
// src/project-source/identity-rewriter.ts
|
|
116877
|
+
function createIdentityRewriter(assignments, onReplace) {
|
|
116878
|
+
if (assignments.size === 0) return (value) => value;
|
|
116879
|
+
const root = { children: /* @__PURE__ */ new Map() };
|
|
116880
|
+
for (const [source, replacement] of assignments) {
|
|
116881
|
+
let prefix = root;
|
|
116882
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
116883
|
+
const character = source[index];
|
|
116884
|
+
let child2 = prefix.children.get(character);
|
|
116885
|
+
if (child2 === void 0) {
|
|
116886
|
+
child2 = { children: /* @__PURE__ */ new Map() };
|
|
116887
|
+
prefix.children.set(character, child2);
|
|
116888
|
+
}
|
|
116889
|
+
prefix = child2;
|
|
116890
|
+
}
|
|
116891
|
+
prefix.replacement = replacement;
|
|
116892
|
+
}
|
|
116893
|
+
return (value) => {
|
|
116894
|
+
const exact = assignments.get(value);
|
|
116895
|
+
if (exact !== void 0) {
|
|
116896
|
+
onReplace?.(value);
|
|
116897
|
+
return exact;
|
|
116898
|
+
}
|
|
116899
|
+
const parts = [];
|
|
116900
|
+
let copiedThrough = 0;
|
|
116901
|
+
for (let start = 0; start < value.length; start += 1) {
|
|
116902
|
+
let prefix = root.children.get(value[start]);
|
|
116903
|
+
let replacement;
|
|
116904
|
+
let end = start;
|
|
116905
|
+
for (let index = start; prefix !== void 0; index += 1) {
|
|
116906
|
+
if (prefix.replacement !== void 0) {
|
|
116907
|
+
replacement = prefix.replacement;
|
|
116908
|
+
end = index + 1;
|
|
116909
|
+
}
|
|
116910
|
+
prefix = prefix.children.get(value[index + 1]);
|
|
116911
|
+
}
|
|
116912
|
+
if (replacement === void 0) continue;
|
|
116913
|
+
onReplace?.(value.slice(start, end));
|
|
116914
|
+
parts.push(value.slice(copiedThrough, start), replacement);
|
|
116915
|
+
copiedThrough = end;
|
|
116916
|
+
start = end - 1;
|
|
116917
|
+
}
|
|
116918
|
+
if (copiedThrough === 0) return value;
|
|
116919
|
+
parts.push(value.slice(copiedThrough));
|
|
116920
|
+
return parts.join("");
|
|
116921
|
+
};
|
|
116922
|
+
}
|
|
116923
|
+
var init_identity_rewriter = __esm({
|
|
116924
|
+
"src/project-source/identity-rewriter.ts"() {
|
|
116925
|
+
"use strict";
|
|
116926
|
+
}
|
|
116927
|
+
});
|
|
116928
|
+
|
|
116850
116929
|
// src/project-source/schema-source-validation.ts
|
|
116851
116930
|
function sourceDiagnosticMapper(analysis) {
|
|
116852
116931
|
const locations = /* @__PURE__ */ new Map();
|
|
@@ -124875,7 +124954,8 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
124875
124954
|
claim.message,
|
|
124876
124955
|
position.file,
|
|
124877
124956
|
position.line,
|
|
124878
|
-
position.column
|
|
124957
|
+
position.column,
|
|
124958
|
+
claim.code
|
|
124879
124959
|
)
|
|
124880
124960
|
);
|
|
124881
124961
|
}
|
|
@@ -125305,7 +125385,7 @@ function prospectiveAnimationDocumentV4(records2) {
|
|
|
125305
125385
|
let project;
|
|
125306
125386
|
const constructors = [];
|
|
125307
125387
|
const classes = [];
|
|
125308
|
-
const
|
|
125388
|
+
const memberData = [];
|
|
125309
125389
|
const values = [];
|
|
125310
125390
|
for (const record6 of candidates) {
|
|
125311
125391
|
if (record6.recordKind === "project") {
|
|
@@ -125325,16 +125405,7 @@ function prospectiveAnimationDocumentV4(records2) {
|
|
|
125325
125405
|
}
|
|
125326
125406
|
classes.push(record6.data);
|
|
125327
125407
|
} else if (record6.recordKind === "member") {
|
|
125328
|
-
|
|
125329
|
-
record6.data,
|
|
125330
|
-
memberRecords
|
|
125331
|
-
);
|
|
125332
|
-
if (!isMember(member)) {
|
|
125333
|
-
throw new Error(
|
|
125334
|
-
`Prospective animation validation received an invalid member record ${recordLabel(record6.data)}.`
|
|
125335
|
-
);
|
|
125336
|
-
}
|
|
125337
|
-
members.push(member);
|
|
125408
|
+
memberData.push(record6.data);
|
|
125338
125409
|
} else if (record6.recordKind === "value") {
|
|
125339
125410
|
if (!isMemberValue(record6.data)) {
|
|
125340
125411
|
throw new Error(
|
|
@@ -125345,6 +125416,22 @@ function prospectiveAnimationDocumentV4(records2) {
|
|
|
125345
125416
|
}
|
|
125346
125417
|
}
|
|
125347
125418
|
if (project === void 0) return null;
|
|
125419
|
+
const members = [];
|
|
125420
|
+
const inheritedCallables = [];
|
|
125421
|
+
for (const data of memberData) {
|
|
125422
|
+
const member = hydrateProspectiveMemberOverride(data, memberRecords);
|
|
125423
|
+
if (typeof data.extendsMemberId === "string" && member.returnTypeInfo !== void 0) {
|
|
125424
|
+
inheritedCallables.push(member);
|
|
125425
|
+
} else {
|
|
125426
|
+
members.push(validProspectiveMember(member));
|
|
125427
|
+
}
|
|
125428
|
+
}
|
|
125429
|
+
const closedCallables = inheritedCallables.map(
|
|
125430
|
+
(member) => validProspectiveMember(
|
|
125431
|
+
closeInheritedCallableSignature(member, classes, members)
|
|
125432
|
+
)
|
|
125433
|
+
);
|
|
125434
|
+
members.push(...closedCallables);
|
|
125348
125435
|
const classesById = new Map(
|
|
125349
125436
|
classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
|
|
125350
125437
|
);
|
|
@@ -125768,6 +125855,36 @@ function hydrateProspectiveMemberOverride(data, members) {
|
|
|
125768
125855
|
}
|
|
125769
125856
|
return hydrated;
|
|
125770
125857
|
}
|
|
125858
|
+
function validProspectiveMember(member) {
|
|
125859
|
+
if (!isMember(member)) {
|
|
125860
|
+
throw new Error(
|
|
125861
|
+
`Prospective animation validation received an invalid member record ${recordLabel(member)}.`
|
|
125862
|
+
);
|
|
125863
|
+
}
|
|
125864
|
+
return member;
|
|
125865
|
+
}
|
|
125866
|
+
function closeInheritedCallableSignature(member, classes, members) {
|
|
125867
|
+
if (typeof member.id !== "string") return member;
|
|
125868
|
+
const env = resolveDeclaringClassGenericEnv(member.id, classes);
|
|
125869
|
+
if (env.size === 0) return member;
|
|
125870
|
+
const close = (typeInfo) => substituteInheritedCallableTypeInfo(typeInfo, env, classes, members);
|
|
125871
|
+
const closed = { ...member };
|
|
125872
|
+
if (isNSFunctionReturnTypeInfo(member.returnTypeInfo)) {
|
|
125873
|
+
closed.returnTypeInfo = close(member.returnTypeInfo);
|
|
125874
|
+
}
|
|
125875
|
+
if (Array.isArray(member.argumentTypes)) {
|
|
125876
|
+
closed.argumentTypes = member.argumentTypes.map((argument2) => {
|
|
125877
|
+
if (!isNSFunctionArgumentTypeInfo(argument2)) return argument2;
|
|
125878
|
+
const { name, defaultValue } = argument2;
|
|
125879
|
+
return {
|
|
125880
|
+
...close(argument2),
|
|
125881
|
+
name,
|
|
125882
|
+
...defaultValue === void 0 ? {} : { defaultValue }
|
|
125883
|
+
};
|
|
125884
|
+
});
|
|
125885
|
+
}
|
|
125886
|
+
return closed;
|
|
125887
|
+
}
|
|
125771
125888
|
function resolveProspectiveMemberField(start, field, members) {
|
|
125772
125889
|
let current = start;
|
|
125773
125890
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -126149,6 +126266,8 @@ var init_workspace_status_core = __esm({
|
|
|
126149
126266
|
init_project_documents();
|
|
126150
126267
|
init_animation_clips();
|
|
126151
126268
|
init_classes();
|
|
126269
|
+
init_generics();
|
|
126270
|
+
init_neoscript_guards();
|
|
126152
126271
|
init_members();
|
|
126153
126272
|
init_value_row_owner_members();
|
|
126154
126273
|
init_constructors2();
|
|
@@ -126255,7 +126374,16 @@ ${blockingErrors.map((error) => error.message).join("\n")}` : `Trusted source lo
|
|
|
126255
126374
|
);
|
|
126256
126375
|
const usedAssignments = /* @__PURE__ */ new Set();
|
|
126257
126376
|
const positionless = positionIndependentAssignments(assignments);
|
|
126258
|
-
const
|
|
126377
|
+
const rewriteEmbedded = createIdentityRewriter(assignments, (id2) => {
|
|
126378
|
+
usedAssignments.add(id2);
|
|
126379
|
+
});
|
|
126380
|
+
const rewrite = (value) => rewritePending(
|
|
126381
|
+
value,
|
|
126382
|
+
assignments,
|
|
126383
|
+
usedAssignments,
|
|
126384
|
+
positionless,
|
|
126385
|
+
rewriteEmbedded
|
|
126386
|
+
);
|
|
126259
126387
|
const expectedChanges = status.changes.map((change) => {
|
|
126260
126388
|
const rewrittenData = change.nextData === void 0 ? void 0 : rewrite(change.nextData);
|
|
126261
126389
|
return {
|
|
@@ -126495,7 +126623,7 @@ function relocatedAssignment(pendingId2, assignments, byPosition, used) {
|
|
|
126495
126623
|
const relocatedVirtual = pendingVirtualValueId(relocatedRoot, sourceIdentity3);
|
|
126496
126624
|
return assignments.has(relocatedVirtual) ? relocatedVirtual : null;
|
|
126497
126625
|
}
|
|
126498
|
-
function rewritePending(value, assignments, used, positionless) {
|
|
126626
|
+
function rewritePending(value, assignments, used, positionless, rewriteEmbedded) {
|
|
126499
126627
|
if (typeof value === "string") {
|
|
126500
126628
|
const exact = assignments.get(value);
|
|
126501
126629
|
if (exact !== void 0) {
|
|
@@ -126518,28 +126646,23 @@ function rewritePending(value, assignments, used, positionless) {
|
|
|
126518
126646
|
);
|
|
126519
126647
|
}
|
|
126520
126648
|
if (!value.includes("__pending__:")) return value;
|
|
126521
|
-
|
|
126522
|
-
for (const [pendingId2, assignedId] of assignments) {
|
|
126523
|
-
if (!rewritten.includes(pendingId2)) continue;
|
|
126524
|
-
rewritten = rewritten.replaceAll(pendingId2, assignedId);
|
|
126525
|
-
used.add(pendingId2);
|
|
126526
|
-
}
|
|
126527
|
-
return rewritten;
|
|
126649
|
+
return rewriteEmbedded(value);
|
|
126528
126650
|
}
|
|
126529
126651
|
if (Array.isArray(value)) {
|
|
126530
126652
|
return value.map(
|
|
126531
|
-
(entry) => rewritePending(entry, assignments, used, positionless)
|
|
126653
|
+
(entry) => rewritePending(entry, assignments, used, positionless, rewriteEmbedded)
|
|
126532
126654
|
);
|
|
126533
126655
|
}
|
|
126534
126656
|
if (isObjectRecord2(value)) {
|
|
126535
126657
|
const result = {};
|
|
126536
126658
|
for (const [key, entry] of Object.entries(value)) {
|
|
126537
|
-
const rewrittenKey = key.startsWith("__pending__:") ? rewritePending(key, assignments, used, positionless) : key;
|
|
126659
|
+
const rewrittenKey = key.startsWith("__pending__:") ? rewritePending(key, assignments, used, positionless, rewriteEmbedded) : key;
|
|
126538
126660
|
result[rewrittenKey] = rewritePending(
|
|
126539
126661
|
entry,
|
|
126540
126662
|
assignments,
|
|
126541
126663
|
used,
|
|
126542
|
-
positionless
|
|
126664
|
+
positionless,
|
|
126665
|
+
rewriteEmbedded
|
|
126543
126666
|
);
|
|
126544
126667
|
}
|
|
126545
126668
|
return result;
|
|
@@ -126775,6 +126898,7 @@ var ProjectSourceCommitVerificationError, ABSENT_DIFFERENCE_VALUE;
|
|
|
126775
126898
|
var init_trusted_commit_verification = __esm({
|
|
126776
126899
|
"src/project-source/trusted-commit-verification.ts"() {
|
|
126777
126900
|
"use strict";
|
|
126901
|
+
init_identity_rewriter();
|
|
126778
126902
|
init_schema_source_validation();
|
|
126779
126903
|
init_projectRecordBuckets();
|
|
126780
126904
|
init_workspace_status_core();
|
|
@@ -128342,6 +128466,8 @@ function createValueLowerRegistryV4(options = {}) {
|
|
|
128342
128466
|
initAuthoredRowIds: /* @__PURE__ */ new Map(),
|
|
128343
128467
|
loweringFailures: [],
|
|
128344
128468
|
storedRowClaims: /* @__PURE__ */ new Map(),
|
|
128469
|
+
movedValueSites: /* @__PURE__ */ new Map(),
|
|
128470
|
+
storedMoveRoots: /* @__PURE__ */ new Map(),
|
|
128345
128471
|
placedStoredRowIds: /* @__PURE__ */ new Set(),
|
|
128346
128472
|
pendingValueIdentitySites: /* @__PURE__ */ new Map(),
|
|
128347
128473
|
initializerSites: /* @__PURE__ */ new Map(),
|
|
@@ -128468,6 +128594,7 @@ function buildValueLowerContext(state, manifest, options = {}) {
|
|
|
128468
128594
|
localizationConversionValueIds: registry.localizationConversionValueIds,
|
|
128469
128595
|
loweredMemberIdByValueId: /* @__PURE__ */ new Map(),
|
|
128470
128596
|
storedClassSchemaMemberIds: /* @__PURE__ */ new Map(),
|
|
128597
|
+
ordinaryMoveFields: /* @__PURE__ */ new Map(),
|
|
128471
128598
|
pendingBindingMembersByClassId: registry.pendingBindingMembersByClassId,
|
|
128472
128599
|
declaredConstructors: declaredConstructorIndex,
|
|
128473
128600
|
initAuthoredRowIds: seedInitAuthoredRowIds(
|
|
@@ -128481,6 +128608,8 @@ function buildValueLowerContext(state, manifest, options = {}) {
|
|
|
128481
128608
|
referenceObligations: registry.referenceObligations,
|
|
128482
128609
|
loweringFailures: registry.loweringFailures,
|
|
128483
128610
|
storedRowClaims: registry.storedRowClaims,
|
|
128611
|
+
movedValueSites: registry.movedValueSites,
|
|
128612
|
+
storedMoveRoots: registry.storedMoveRoots,
|
|
128484
128613
|
placedStoredRowIds: registry.placedStoredRowIds,
|
|
128485
128614
|
pendingValueIdentitySites: registry.pendingValueIdentitySites,
|
|
128486
128615
|
initializerSites: registry.initializerSites,
|
|
@@ -129131,6 +129260,21 @@ function drainValueReferenceObligationsV4(state, manifest, options) {
|
|
|
129131
129260
|
})
|
|
129132
129261
|
});
|
|
129133
129262
|
const failures = [];
|
|
129263
|
+
const movedRoots = /* @__PURE__ */ new Map();
|
|
129264
|
+
for (const [valueId, move] of options.registry.movedValueSites) {
|
|
129265
|
+
const placements = context.valuePlacements.placementsByValueId.get(valueId) ?? [];
|
|
129266
|
+
let message;
|
|
129267
|
+
if (placements.length !== 1) {
|
|
129268
|
+
message = `Value @id(${JSON.stringify(valueId)}) must have exactly one owning slot after a move; found ${placements.length}. Remove its declaration from the old parent before keeping the same ID on the new owner.`;
|
|
129269
|
+
} else if (singleSlotBindingRoot(context, valueId, movedRoots) !== move.rootValueId) {
|
|
129270
|
+
message = `Value @id(${JSON.stringify(valueId)}) cannot move: moves require one acyclic path under the same root or static binding, through non-overridden class fields with inherited storage and automatic distribution.`;
|
|
129271
|
+
} else continue;
|
|
129272
|
+
failures.push({
|
|
129273
|
+
code: "invalid-value-move",
|
|
129274
|
+
message,
|
|
129275
|
+
...composeReferenceSitePosition(move.site, options.sourceTextByUri)
|
|
129276
|
+
});
|
|
129277
|
+
}
|
|
129134
129278
|
for (const recorded of options.registry.loweringFailures) {
|
|
129135
129279
|
failures.push({
|
|
129136
129280
|
message: recorded.message,
|
|
@@ -129730,27 +129874,17 @@ function lowerRowBackedDefault(context, member, backed, baseData3, binding) {
|
|
|
129730
129874
|
const childValueMember = recursivePartialMember(member, childMember);
|
|
129731
129875
|
const childSlice = assignmentSlices.get(assignment.name);
|
|
129732
129876
|
const existingId = isObjectRecord2(baseBody) ? baseBody[assignment.name] : void 0;
|
|
129733
|
-
|
|
129734
|
-
|
|
129735
|
-
|
|
129736
|
-
|
|
129737
|
-
|
|
129738
|
-
|
|
129739
|
-
|
|
129740
|
-
|
|
129741
|
-
|
|
129742
|
-
|
|
129743
|
-
|
|
129744
|
-
childSlice
|
|
129745
|
-
);
|
|
129746
|
-
continue;
|
|
129747
|
-
}
|
|
129748
|
-
if (!isPendingId(storedId) && !isUuidV4Id(storedId)) {
|
|
129749
|
-
context.loweringFailures.push({
|
|
129750
|
-
message: `Default value ${binding.label}.${assignment.name} is annotated @id("${storedId}"), which names no existing row, and a new row's durable identity must be a UUID v4. Fix the id if it meant an existing row, or drop the @id to mint a fresh identity.`,
|
|
129751
|
-
site: referenceSite(binding, assignment.value)
|
|
129752
|
-
});
|
|
129753
|
-
}
|
|
129877
|
+
if (typeof existingId === "string") {
|
|
129878
|
+
body[assignment.name] = lowerValueRow(
|
|
129879
|
+
context,
|
|
129880
|
+
childValueMember,
|
|
129881
|
+
assignment.value,
|
|
129882
|
+
existingId,
|
|
129883
|
+
binding,
|
|
129884
|
+
environment,
|
|
129885
|
+
childSlice
|
|
129886
|
+
);
|
|
129887
|
+
continue;
|
|
129754
129888
|
}
|
|
129755
129889
|
const placedId = sourceValueSymbol(context, assignment.value);
|
|
129756
129890
|
if (placedId !== null) {
|
|
@@ -129782,6 +129916,7 @@ function lowerRowBackedDefault(context, member, backed, baseData3, binding) {
|
|
|
129782
129916
|
}
|
|
129783
129917
|
const entryMember = requiredMember(context, member.entryMemberId);
|
|
129784
129918
|
const existingIds = new Set(backed.body);
|
|
129919
|
+
const placedIds = /* @__PURE__ */ new Set();
|
|
129785
129920
|
const entrySlices = topLevelEntrySlices(binding.initializer, "[", "]");
|
|
129786
129921
|
const ids = expression.elements.map((element, index) => {
|
|
129787
129922
|
const symbolId = sourceValueSymbol(context, element);
|
|
@@ -129812,6 +129947,21 @@ function lowerRowBackedDefault(context, member, backed, baseData3, binding) {
|
|
|
129812
129947
|
entrySlices[index]
|
|
129813
129948
|
);
|
|
129814
129949
|
}
|
|
129950
|
+
if (!existingIds.has(itemId)) {
|
|
129951
|
+
context.storedRowClaims.set(itemId, {
|
|
129952
|
+
code: "invalid-value-move",
|
|
129953
|
+
message: `Value @id(${JSON.stringify(itemId)}) cannot move into another default list. Remove @id to create a new value.`,
|
|
129954
|
+
site: referenceSite(binding, element)
|
|
129955
|
+
});
|
|
129956
|
+
return itemId;
|
|
129957
|
+
}
|
|
129958
|
+
recordRepeatedRow(
|
|
129959
|
+
context,
|
|
129960
|
+
itemId,
|
|
129961
|
+
`Default list ${binding.label}`,
|
|
129962
|
+
referenceSite(binding, element),
|
|
129963
|
+
placedIds
|
|
129964
|
+
);
|
|
129815
129965
|
return lowerValueRow(
|
|
129816
129966
|
context,
|
|
129817
129967
|
entryMember,
|
|
@@ -129832,6 +129982,8 @@ function lowerRowBackedDefault(context, member, backed, baseData3, binding) {
|
|
|
129832
129982
|
const keyEnum = dictionaryKeyEnum(context, member);
|
|
129833
129983
|
const baseBody = backed.body;
|
|
129834
129984
|
const body = {};
|
|
129985
|
+
const existingIds = new Set(Object.values(baseBody));
|
|
129986
|
+
const placedIds = /* @__PURE__ */ new Set();
|
|
129835
129987
|
const entrySlices = topLevelEntrySlices(binding.initializer, "{", "}");
|
|
129836
129988
|
let entryIndex = 0;
|
|
129837
129989
|
for (const entry of expression.entries) {
|
|
@@ -129843,6 +129995,23 @@ function lowerRowBackedDefault(context, member, backed, baseData3, binding) {
|
|
|
129843
129995
|
`Default dictionary ${binding.label}[${JSON.stringify(key)}] has no existing owned value row. Creating new default rows from source is not implemented by this slice.`
|
|
129844
129996
|
);
|
|
129845
129997
|
}
|
|
129998
|
+
if (context.state[`value:${entryId}`] !== void 0 && !existingIds.has(entryId)) {
|
|
129999
|
+
context.storedRowClaims.set(entryId, {
|
|
130000
|
+
code: "invalid-value-move",
|
|
130001
|
+
message: `Value @id(${JSON.stringify(entryId)}) cannot move into another default dictionary. Remove @id to create a new value.`,
|
|
130002
|
+
site: referenceSite(binding, entry.value)
|
|
130003
|
+
});
|
|
130004
|
+
body[key] = entryId;
|
|
130005
|
+
entryIndex += 1;
|
|
130006
|
+
continue;
|
|
130007
|
+
}
|
|
130008
|
+
recordRepeatedRow(
|
|
130009
|
+
context,
|
|
130010
|
+
entryId,
|
|
130011
|
+
`Default dictionary ${binding.label}`,
|
|
130012
|
+
referenceSite(binding, entry.value),
|
|
130013
|
+
placedIds
|
|
130014
|
+
);
|
|
129846
130015
|
body[key] = lowerValueRow(
|
|
129847
130016
|
context,
|
|
129848
130017
|
entryMember,
|
|
@@ -130909,8 +131078,64 @@ function structuralMemberByParameterName(context, effectiveClass) {
|
|
|
130909
131078
|
function lowerSeedChild(context, member, expression, source, path, rows, localizedTexts, containerId, environment, authoredSlice) {
|
|
130910
131079
|
const symbolId = sourceValueSymbol(context, expression);
|
|
130911
131080
|
if (symbolId !== null) return symbolId;
|
|
130912
|
-
const
|
|
131081
|
+
const local = context.localValues.resolve(expression, source);
|
|
131082
|
+
const annotatedId = annotatedValue(local.expression).id;
|
|
131083
|
+
if (annotatedId !== null && !isPendingId(annotatedId) && context.state[`value:${annotatedId}`] === void 0 && member.owner.kind === "classMember" && !isUuidV4Id(annotatedId)) {
|
|
131084
|
+
const owner = context.classes.get(member.owner.classId)?.name;
|
|
131085
|
+
const name = owner === void 0 ? member.name : `${owner}.${member.name}`;
|
|
131086
|
+
context.loweringFailures.push({
|
|
131087
|
+
code: "invalid-new-value-id",
|
|
131088
|
+
message: `Value ${name} has @id(${JSON.stringify(annotatedId)}), which names no existing row. A new nested value requires a UUID v4. Remove @id to let Neo assign the value's identity, or provide a valid, unused UUID v4.`,
|
|
131089
|
+
site: referenceSiteAt(
|
|
131090
|
+
local.source,
|
|
131091
|
+
local.expression.kind === "annotated" ? local.expression.annotations.find((entry) => entry.name === "id")?.pos ?? local.expression.pos : local.expression.pos
|
|
131092
|
+
)
|
|
131093
|
+
});
|
|
131094
|
+
}
|
|
130913
131095
|
const valueId = annotatedId ?? context.structuralStoredIds.get(path) ?? pendingNestedValueId(source, path);
|
|
131096
|
+
if (!context.structuralConstruction && annotatedId !== null && context.state[`value:${annotatedId}`] !== void 0) {
|
|
131097
|
+
const failure = storedClassMoveFailure(
|
|
131098
|
+
context,
|
|
131099
|
+
member,
|
|
131100
|
+
annotatedId,
|
|
131101
|
+
path,
|
|
131102
|
+
containerId
|
|
131103
|
+
);
|
|
131104
|
+
if (failure !== null) {
|
|
131105
|
+
context.storedRowClaims.set(annotatedId, {
|
|
131106
|
+
code: "invalid-value-move",
|
|
131107
|
+
message: failure,
|
|
131108
|
+
site: referenceSite(local.source, local.expression)
|
|
131109
|
+
});
|
|
131110
|
+
return annotatedId;
|
|
131111
|
+
}
|
|
131112
|
+
const rootValueId = singleSlotBindingRoot(
|
|
131113
|
+
context,
|
|
131114
|
+
annotatedId,
|
|
131115
|
+
context.storedMoveRoots
|
|
131116
|
+
);
|
|
131117
|
+
if (rootValueId === null) {
|
|
131118
|
+
context.storedRowClaims.set(annotatedId, {
|
|
131119
|
+
code: "invalid-value-move",
|
|
131120
|
+
message: `Value @id(${JSON.stringify(annotatedId)}) cannot move: moves require an existing path to a root or static binding through non-overridden class fields with inherited storage and automatic distribution.`,
|
|
131121
|
+
site: referenceSite(local.source, local.expression)
|
|
131122
|
+
});
|
|
131123
|
+
return annotatedId;
|
|
131124
|
+
}
|
|
131125
|
+
context.movedValueSites.set(annotatedId, {
|
|
131126
|
+
site: referenceSite(local.source, local.expression),
|
|
131127
|
+
rootValueId
|
|
131128
|
+
});
|
|
131129
|
+
return lowerValueRow(
|
|
131130
|
+
context,
|
|
131131
|
+
member,
|
|
131132
|
+
expression,
|
|
131133
|
+
annotatedId,
|
|
131134
|
+
source,
|
|
131135
|
+
environment,
|
|
131136
|
+
authoredSlice
|
|
131137
|
+
);
|
|
131138
|
+
}
|
|
130914
131139
|
lowerSeedRow(
|
|
130915
131140
|
context,
|
|
130916
131141
|
member,
|
|
@@ -130926,6 +131151,99 @@ function lowerSeedChild(context, member, expression, source, path, rows, localiz
|
|
|
130926
131151
|
);
|
|
130927
131152
|
return valueId;
|
|
130928
131153
|
}
|
|
131154
|
+
function singleSlotBindingRoot(context, start, roots) {
|
|
131155
|
+
const placements = context.valuePlacements;
|
|
131156
|
+
const path = /* @__PURE__ */ new Set();
|
|
131157
|
+
let cursor = start;
|
|
131158
|
+
let root = null;
|
|
131159
|
+
while (!path.has(cursor)) {
|
|
131160
|
+
const cached = roots.get(cursor);
|
|
131161
|
+
if (cached !== void 0) {
|
|
131162
|
+
root = cached;
|
|
131163
|
+
break;
|
|
131164
|
+
}
|
|
131165
|
+
if (placements.memberIdsByBoundValueId.has(cursor)) {
|
|
131166
|
+
root = cursor;
|
|
131167
|
+
break;
|
|
131168
|
+
}
|
|
131169
|
+
path.add(cursor);
|
|
131170
|
+
const parents = placements.placementsByValueId.get(cursor) ?? [];
|
|
131171
|
+
const parent = parents[0];
|
|
131172
|
+
if (parents.length !== 1 || parent === void 0) break;
|
|
131173
|
+
if (parent.containerClassId === null) break;
|
|
131174
|
+
const key = `${parent.containerClassId}:${parent.schemaKey}`;
|
|
131175
|
+
let ordinary = context.ordinaryMoveFields.get(key);
|
|
131176
|
+
if (ordinary === void 0) {
|
|
131177
|
+
const member = classMemberByName(
|
|
131178
|
+
context,
|
|
131179
|
+
parent.containerClassId,
|
|
131180
|
+
parent.schemaKey
|
|
131181
|
+
);
|
|
131182
|
+
ordinary = member.overrideOf === null && member.storage === null && member.storageKey === null && member.distribution === null;
|
|
131183
|
+
context.ordinaryMoveFields.set(key, ordinary);
|
|
131184
|
+
}
|
|
131185
|
+
if (!ordinary) break;
|
|
131186
|
+
cursor = parent.containerValueId;
|
|
131187
|
+
}
|
|
131188
|
+
for (const id2 of path) roots.set(id2, root);
|
|
131189
|
+
return root;
|
|
131190
|
+
}
|
|
131191
|
+
function storedClassMoveFailure(context, member, valueId, path, containerId) {
|
|
131192
|
+
const refuse = (reason) => `Value @id(${JSON.stringify(valueId)}) cannot move: ${reason}. Remove @id to create a new value.`;
|
|
131193
|
+
if (!isUuidV4Id(valueId))
|
|
131194
|
+
return refuse("its identity is derived from its original placement");
|
|
131195
|
+
if (containerId !== void 0)
|
|
131196
|
+
return refuse("unordered-list membership is immutable");
|
|
131197
|
+
if (member.owner.kind !== "classMember")
|
|
131198
|
+
return refuse("the new owner is not a class member");
|
|
131199
|
+
if (member.kind !== "class")
|
|
131200
|
+
return refuse("only nested class values support moves");
|
|
131201
|
+
const base = valueBase(context, valueId);
|
|
131202
|
+
if (typeof base.containerId === "string")
|
|
131203
|
+
return refuse("unordered-list membership is immutable");
|
|
131204
|
+
if ((context.valuePlacements.memberIdsByBoundValueId.get(valueId)?.length ?? 0) > 0)
|
|
131205
|
+
return refuse("a root or static binding owns it");
|
|
131206
|
+
const placement = context.readStoredValuePlacements().placementByChildValueId.get(valueId);
|
|
131207
|
+
if (placement === void 0)
|
|
131208
|
+
return refuse("its old owning class slot could not be resolved");
|
|
131209
|
+
if (placement.source !== "body")
|
|
131210
|
+
return refuse("its old owner supplies it through a constructor");
|
|
131211
|
+
const parent = valueBase(context, placement.parentValueId);
|
|
131212
|
+
const targetParentId = path.slice(0, -(member.name.length + 1));
|
|
131213
|
+
if (context.state[`value:${targetParentId}`] === void 0)
|
|
131214
|
+
return refuse("the new parent is not an existing stored class value");
|
|
131215
|
+
const targetParent = valueBase(context, targetParentId);
|
|
131216
|
+
for (const row of [base, parent, targetParent]) {
|
|
131217
|
+
if (typeof row.sourceValueId === "string")
|
|
131218
|
+
return refuse("a projected value depends on its original owner");
|
|
131219
|
+
if (typeof row.mapKey === "string")
|
|
131220
|
+
return refuse("partitioned values cannot change ownership");
|
|
131221
|
+
if (isObjectRecord2(row.genericBindings) && Object.keys(row.genericBindings).length > 0)
|
|
131222
|
+
return refuse("generic value ownership cannot be changed");
|
|
131223
|
+
}
|
|
131224
|
+
if (typeof targetParent.instanceConstructorId === "string" || isObjectRecord2(targetParent.constructorArgs) && Object.keys(targetParent.constructorArgs).length > 0)
|
|
131225
|
+
return refuse("the new owner has constructor creation data");
|
|
131226
|
+
if (typeof parent.instanceConstructorId === "string" || isObjectRecord2(parent.constructorArgs) && Object.keys(parent.constructorArgs).length > 0)
|
|
131227
|
+
return refuse("its old owner has constructor creation data");
|
|
131228
|
+
const oldMember = placement.memberId === null ? void 0 : context.members.get(placement.memberId);
|
|
131229
|
+
if (oldMember?.kind !== "class")
|
|
131230
|
+
return refuse(
|
|
131231
|
+
"its old owner is not a class member containing a class value"
|
|
131232
|
+
);
|
|
131233
|
+
if (oldMember.storageKey !== member.storageKey)
|
|
131234
|
+
return refuse("the new member declares a different storage key");
|
|
131235
|
+
if (oldMember.distribution !== member.distribution)
|
|
131236
|
+
return refuse("the new member declares a different distribution");
|
|
131237
|
+
if (oldMember.storage !== member.storage)
|
|
131238
|
+
return refuse("the new member uses different storage");
|
|
131239
|
+
if (oldMember.classId !== member.classId)
|
|
131240
|
+
return refuse("the new member declares a different class type");
|
|
131241
|
+
if (Object.keys(oldMember.classArguments).length > 0)
|
|
131242
|
+
return refuse("generic member ownership cannot be changed");
|
|
131243
|
+
if (Object.keys(member.classArguments).length > 0)
|
|
131244
|
+
return refuse("the new member declares generic arguments");
|
|
131245
|
+
return null;
|
|
131246
|
+
}
|
|
130929
131247
|
function unorderedRowSubtreePath(valueId, path, containerId) {
|
|
130930
131248
|
if (containerId === void 0 || containerId === null) return path;
|
|
130931
131249
|
return valueId;
|
|
@@ -131174,7 +131492,8 @@ function lowerValueBody(context, member, expression, base, source, environment,
|
|
|
131174
131492
|
expression,
|
|
131175
131493
|
base,
|
|
131176
131494
|
source,
|
|
131177
|
-
environment
|
|
131495
|
+
environment,
|
|
131496
|
+
authoredSlice
|
|
131178
131497
|
);
|
|
131179
131498
|
default:
|
|
131180
131499
|
throw new Error(
|
|
@@ -132133,9 +132452,9 @@ function lowerListValue(context, member, expression, base, source, inheritedEnvi
|
|
|
132133
132452
|
value: member.listKind === "unordered" ? [] : ids
|
|
132134
132453
|
};
|
|
132135
132454
|
}
|
|
132136
|
-
function recordRepeatedRow(context, rowId, collection, site) {
|
|
132137
|
-
if (!
|
|
132138
|
-
|
|
132455
|
+
function recordRepeatedRow(context, rowId, collection, site, placedIds = context.placedStoredRowIds) {
|
|
132456
|
+
if (!placedIds.has(rowId)) {
|
|
132457
|
+
placedIds.add(rowId);
|
|
132139
132458
|
return;
|
|
132140
132459
|
}
|
|
132141
132460
|
context.loweringFailures.push({
|
|
@@ -132177,18 +132496,20 @@ function existingListItemIds(context, member, base) {
|
|
|
132177
132496
|
Array.isArray(base.value) ? base.value.filter((entry) => typeof entry === "string") : []
|
|
132178
132497
|
);
|
|
132179
132498
|
}
|
|
132180
|
-
function lowerDictionaryValue(context, member, expression, base, source, inheritedEnvironment) {
|
|
132499
|
+
function lowerDictionaryValue(context, member, expression, base, source, inheritedEnvironment, authoredSlice) {
|
|
132181
132500
|
if (expression.kind === "litNull")
|
|
132182
132501
|
return { ...valueFileFields(base), value: null };
|
|
132183
132502
|
if (expression.kind !== "litDict") {
|
|
132184
132503
|
throw new Error("Dictionary values require {...}.");
|
|
132185
132504
|
}
|
|
132186
132505
|
const baseBody = isObjectRecord2(base.value) ? base.value : {};
|
|
132506
|
+
const existingIds = new Set(Object.values(baseBody));
|
|
132187
132507
|
const keyEnum = dictionaryKeyEnum(context, member);
|
|
132188
132508
|
const entryMember = requiredMember(context, member.entryMemberId);
|
|
132189
132509
|
const environment = valueGenericEnvironment(base, inheritedEnvironment);
|
|
132190
132510
|
const body = {};
|
|
132191
|
-
|
|
132511
|
+
const entrySlices = authoredSlice === void 0 ? [] : topLevelEntrySlices(authoredSlice, "{", "}");
|
|
132512
|
+
for (const [entryIndex, entry] of expression.entries.entries()) {
|
|
132192
132513
|
const key = lowerDictionaryKey(entry.key, keyEnum, member.name);
|
|
132193
132514
|
const existingId = baseBody[key];
|
|
132194
132515
|
const symbolId = sourceValueSymbol(context, entry.value);
|
|
@@ -132208,6 +132529,15 @@ function lowerDictionaryValue(context, member, expression, base, source, inherit
|
|
|
132208
132529
|
`Dictionary ${member.name}[${JSON.stringify(key)}] has no existing row. New dictionary entries are not implemented by this slice.`
|
|
132209
132530
|
);
|
|
132210
132531
|
}
|
|
132532
|
+
if (context.state[`value:${valueId}`] !== void 0 && !existingIds.has(valueId)) {
|
|
132533
|
+
context.storedRowClaims.set(valueId, {
|
|
132534
|
+
code: "invalid-value-move",
|
|
132535
|
+
message: `Value @id(${JSON.stringify(valueId)}) cannot move into another dictionary. Remove @id to create a new value.`,
|
|
132536
|
+
site: referenceSite(source, entry.value)
|
|
132537
|
+
});
|
|
132538
|
+
body[key] = valueId;
|
|
132539
|
+
continue;
|
|
132540
|
+
}
|
|
132211
132541
|
recordRepeatedRow(
|
|
132212
132542
|
context,
|
|
132213
132543
|
valueId,
|
|
@@ -132220,7 +132550,8 @@ function lowerDictionaryValue(context, member, expression, base, source, inherit
|
|
|
132220
132550
|
entry.value,
|
|
132221
132551
|
valueId,
|
|
132222
132552
|
source,
|
|
132223
|
-
environment
|
|
132553
|
+
environment,
|
|
132554
|
+
dictionaryValueSlice(entrySlices[entryIndex])
|
|
132224
132555
|
);
|
|
132225
132556
|
}
|
|
132226
132557
|
return { ...valueFileFields(base), value: body };
|
|
@@ -133724,6 +134055,15 @@ function emitValue(context, member, valueId, options) {
|
|
|
133724
134055
|
);
|
|
133725
134056
|
return prefixFor(expression);
|
|
133726
134057
|
}
|
|
134058
|
+
function needsProspectiveValueIdentity(context, valueId, parentId, key) {
|
|
134059
|
+
if (pendingVirtualValueIdentity(valueId) !== null) return true;
|
|
134060
|
+
if (context.storedValueBase === void 0 || isPendingId(valueId))
|
|
134061
|
+
return false;
|
|
134062
|
+
if (typeof parentId !== "string")
|
|
134063
|
+
return !context.storedValueBase.has(valueId);
|
|
134064
|
+
const storedBody = context.storedValueBase.get(parentId)?.value;
|
|
134065
|
+
return !isObjectRecord2(storedBody) || storedBody[key] !== valueId;
|
|
134066
|
+
}
|
|
133727
134067
|
function emitValueBody(context, member, value, visited, targetTyped, environment) {
|
|
133728
134068
|
const kind = numberField(member, "kind");
|
|
133729
134069
|
const body = value.value;
|
|
@@ -133993,9 +134333,13 @@ function classValueBody(context, member, value, visited, targetTyped, outerEnvir
|
|
|
133993
134333
|
`${key} = ${emitValue(context, emittedChildMember, childId, {
|
|
133994
134334
|
environment,
|
|
133995
134335
|
definitionSite: !context.symbolsByValueId.has(childId),
|
|
133996
|
-
//
|
|
133997
|
-
|
|
133998
|
-
|
|
134336
|
+
// New and moved identities must survive repeat lowering against the old placement.
|
|
134337
|
+
writeIdentity: needsProspectiveValueIdentity(
|
|
134338
|
+
context,
|
|
134339
|
+
childId,
|
|
134340
|
+
value.id,
|
|
134341
|
+
key
|
|
134342
|
+
),
|
|
133999
134343
|
visited
|
|
134000
134344
|
})}`
|
|
134001
134345
|
);
|
|
@@ -135273,9 +135617,14 @@ ${entries.flatMap(
|
|
|
135273
135617
|
{
|
|
135274
135618
|
environment,
|
|
135275
135619
|
definitionSite: !context.symbolsByValueId.has(id2),
|
|
135276
|
-
//
|
|
135277
|
-
//
|
|
135278
|
-
writeIdentity:
|
|
135620
|
+
// Existing keys recover identity from their owning row;
|
|
135621
|
+
// new authored identities must survive repeat lowering.
|
|
135622
|
+
writeIdentity: needsProspectiveValueIdentity(
|
|
135623
|
+
context,
|
|
135624
|
+
id2,
|
|
135625
|
+
value.id,
|
|
135626
|
+
key
|
|
135627
|
+
),
|
|
135279
135628
|
visited
|
|
135280
135629
|
}
|
|
135281
135630
|
)}`,
|
|
@@ -137495,55 +137844,6 @@ var init_status_output = __esm({
|
|
|
137495
137844
|
}
|
|
137496
137845
|
});
|
|
137497
137846
|
|
|
137498
|
-
// src/project-source/identity-rewriter.ts
|
|
137499
|
-
function createIdentityRewriter(assignments) {
|
|
137500
|
-
if (assignments.size === 0) return (value) => value;
|
|
137501
|
-
const root = { children: /* @__PURE__ */ new Map() };
|
|
137502
|
-
for (const [source, replacement] of assignments) {
|
|
137503
|
-
let prefix = root;
|
|
137504
|
-
for (let index = 0; index < source.length; index += 1) {
|
|
137505
|
-
const character = source[index];
|
|
137506
|
-
let child2 = prefix.children.get(character);
|
|
137507
|
-
if (child2 === void 0) {
|
|
137508
|
-
child2 = { children: /* @__PURE__ */ new Map() };
|
|
137509
|
-
prefix.children.set(character, child2);
|
|
137510
|
-
}
|
|
137511
|
-
prefix = child2;
|
|
137512
|
-
}
|
|
137513
|
-
prefix.replacement = replacement;
|
|
137514
|
-
}
|
|
137515
|
-
return (value) => {
|
|
137516
|
-
const exact = assignments.get(value);
|
|
137517
|
-
if (exact !== void 0) return exact;
|
|
137518
|
-
const parts = [];
|
|
137519
|
-
let copiedThrough = 0;
|
|
137520
|
-
for (let start = 0; start < value.length; start += 1) {
|
|
137521
|
-
let prefix = root.children.get(value[start]);
|
|
137522
|
-
let replacement;
|
|
137523
|
-
let end = start;
|
|
137524
|
-
for (let index = start; prefix !== void 0; index += 1) {
|
|
137525
|
-
if (prefix.replacement !== void 0) {
|
|
137526
|
-
replacement = prefix.replacement;
|
|
137527
|
-
end = index + 1;
|
|
137528
|
-
}
|
|
137529
|
-
prefix = prefix.children.get(value[index + 1]);
|
|
137530
|
-
}
|
|
137531
|
-
if (replacement === void 0) continue;
|
|
137532
|
-
parts.push(value.slice(copiedThrough, start), replacement);
|
|
137533
|
-
copiedThrough = end;
|
|
137534
|
-
start = end - 1;
|
|
137535
|
-
}
|
|
137536
|
-
if (copiedThrough === 0) return value;
|
|
137537
|
-
parts.push(value.slice(copiedThrough));
|
|
137538
|
-
return parts.join("");
|
|
137539
|
-
};
|
|
137540
|
-
}
|
|
137541
|
-
var init_identity_rewriter = __esm({
|
|
137542
|
-
"src/project-source/identity-rewriter.ts"() {
|
|
137543
|
-
"use strict";
|
|
137544
|
-
}
|
|
137545
|
-
});
|
|
137546
|
-
|
|
137547
137847
|
// src/project-source/source-layout.ts
|
|
137548
137848
|
import { readFileSync as readFileSync9 } from "node:fs";
|
|
137549
137849
|
import { relative as relative4, sep as sep4 } from "node:path";
|
|
@@ -164838,7 +165138,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
164838
165138
|
async function main() {
|
|
164839
165139
|
const args = parseArgs(process.argv.slice(2));
|
|
164840
165140
|
if (args.command === "--version") {
|
|
164841
|
-
console.log("0.68.
|
|
165141
|
+
console.log("0.68.4");
|
|
164842
165142
|
return;
|
|
164843
165143
|
}
|
|
164844
165144
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/dist/test-worker.mjs
CHANGED
|
@@ -22401,6 +22401,8 @@ function resolveBaseConstructorRecord(record3, ctx) {
|
|
|
22401
22401
|
);
|
|
22402
22402
|
if (resolution.kind === "resolved") return resolution.overload;
|
|
22403
22403
|
if (resolution.kind === "noMatch" && baseArguments.length === 0) {
|
|
22404
|
+
if (owningClass.requiredConstructorId === record3.id && evaluatorSchemaIndex(ctx).class(baseClassId)?.requiredConstructorId == null)
|
|
22405
|
+
return null;
|
|
22404
22406
|
throw new NSGetterRuntimeError(
|
|
22405
22407
|
`Constructor '${record3.id}' on '${owningClass.name}' must call ': base(...)': its base class declares constructors but none parameterless.`
|
|
22406
22408
|
);
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
`@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
<!-- reviewed-through-cli: 0.68.
|
|
12
|
+
<!-- reviewed-through-cli: 0.68.4 -->
|
|
13
13
|
|
|
14
14
|
# Neo Compose CLI
|
|
15
15
|
|
|
@@ -63,8 +63,9 @@ opaque JSON or guessed syntax.
|
|
|
63
63
|
values, files, or other records. `@system` is reserved for platform-owned
|
|
64
64
|
system records; authoring it can make the record uneditable.
|
|
65
65
|
- Preserve existing `@id` annotations through rename, reorder, and file moves.
|
|
66
|
-
A
|
|
67
|
-
|
|
66
|
+
A copy must get a new ID. A stored nested class value may keep its UUID-v4
|
|
67
|
+
when moved between compatible empty fields on existing parents, provided
|
|
68
|
+
its old parent no longer declares it. See the identity reference for limits.
|
|
68
69
|
- Omit `@id` on new ordinary declarations and nested rows unless a same-push
|
|
69
70
|
structural reference genuinely requires an explicit UUID. A successful push
|
|
70
71
|
assigns the durable IDs and rewrites source.
|
|
@@ -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.68.
|
|
113
|
+
<!-- reviewed-through-cli: 0.68.4 -->
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -385,6 +385,14 @@ class Child(string name) : Base {
|
|
|
385
385
|
}
|
|
386
386
|
```
|
|
387
387
|
|
|
388
|
+
A header base clause with no arguments, such as `: Base()` or `: Base`,
|
|
389
|
+
runs a zero-argument or fully defaulted base constructor when available.
|
|
390
|
+
Otherwise, if the base has only declared constructors, it uses the member
|
|
391
|
+
initializers and base block without running a base constructor. The base block
|
|
392
|
+
must settle any remaining required members. A required base constructor cannot
|
|
393
|
+
be skipped. A declared constructor's `: base()` must call a base constructor
|
|
394
|
+
when the base declares one.
|
|
395
|
+
|
|
388
396
|
Bind generic base arguments explicitly when needed. Reject a subclass that
|
|
389
397
|
omits required base arguments or leaves any inherited required member
|
|
390
398
|
unsettled.
|
|
@@ -57,9 +57,19 @@ keys as quoted IDs when their option has been deleted.
|
|
|
57
57
|
|
|
58
58
|
## Identity rules
|
|
59
59
|
|
|
60
|
-
Preserve every existing ID through rename, reorder, and file moves. A
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
Preserve every existing ID through rename, reorder, and file moves. A copy
|
|
61
|
+
must get a new ID. A stored nested class value may keep its UUID-v4 when moved
|
|
62
|
+
to an empty, compatible class field on another existing parent. Remove its
|
|
63
|
+
old owning declaration in the same push. Both fields must declare the same
|
|
64
|
+
non-generic class and storage rules. The move must leave exactly one owning
|
|
65
|
+
path to the same root or static binding through ordinary class fields.
|
|
66
|
+
Both ownership paths must use inherited storage and automatic distribution;
|
|
67
|
+
member overrides are not supported for moves. Moving
|
|
68
|
+
projected values, constructor-owned slots, partitioned values, generic
|
|
69
|
+
instances, or unordered-list entries is refused. Moves into newly constructed
|
|
70
|
+
parents are also refused; omit the ID to create a new value there.
|
|
71
|
+
|
|
72
|
+
For a new ordinary record, omit
|
|
63
73
|
`@id` and let a successful real push assign and insert it. Dry-run and failed pushes
|
|
64
74
|
leave tracked source unchanged.
|
|
65
75
|
|
|
@@ -91,6 +101,11 @@ form, an author may assign a previously unseen UUID-v4 with `@id` to the new
|
|
|
91
101
|
row and reference it in the same edit. Reusing an existing ID means update, not
|
|
92
102
|
create. The server validates authored new IDs for UUID-v4 shape and uniqueness.
|
|
93
103
|
Prefer generated IDs unless the structural reference needs an ID immediately.
|
|
104
|
+
Dry-run preserves a valid authored UUID-v4 ID on a new nested member or dictionary
|
|
105
|
+
value, including one declared as a local initializer. An unknown malformed member
|
|
106
|
+
value ID is an error at its annotation; remove `@id` to let push assign the ID,
|
|
107
|
+
or supply an unused UUID v4. This does not change the derived identity of a
|
|
108
|
+
root/static binding or an existing projected value.
|
|
94
109
|
|
|
95
110
|
Do not invent IDs for structural rows whose identities derive from an owner
|
|
96
111
|
role. Do not add a separate root/static initializer ID. A constructor argument
|