@neocompose/cli 0.25.0 → 0.25.1
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,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.25.1] - 2026-08-09
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Stop `First`, `FirstOrDefault`, and collection `Contains` scans as soon as their result is known. Terminal scans now resolve and charge only visited entries, preserve list/dictionary order and value-reference identity, and avoid intermediate entry arrays (P55).
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Seed the owned rows for a field a newly declared member adds to a
|
|
12
|
+
row-backed class default, instead of refusing the push with "no existing
|
|
13
|
+
owned value row". Adding an entry to a row-backed _list_ default has always
|
|
14
|
+
minted its rows; a class field now takes the same path, so replacing a class
|
|
15
|
+
member (`Name = "Blue"` → `Kind = .Blue` across every default that sets it)
|
|
16
|
+
pushes without editing each default in the web editor first. An `@id` on the
|
|
17
|
+
new field is honoured when it names an existing row and, when it does not,
|
|
18
|
+
held to the same UUID v4 identity rule list entries follow.
|
|
19
|
+
- Carry only the new rows and the ancestors that reach them in a member value
|
|
20
|
+
seed. Naming every row the pass touched made the seed depend on which
|
|
21
|
+
constructions the materialization cache preserved that run — so a push and
|
|
22
|
+
its own trusted re-lowering disagreed — and handed back rows stripped of the
|
|
23
|
+
`constructorArgs` a seed row cannot carry, which then failed to project back
|
|
24
|
+
to source. Pushing a new row anywhere under `root.Assets` previously failed
|
|
25
|
+
with "Authored value row … is missing memberId".
|
|
26
|
+
- Drop a stored class body key whose member the push deletes, instead of
|
|
27
|
+
carrying it into a schema that no longer has it while the same push
|
|
28
|
+
tombstones the row it names.
|
|
29
|
+
- Treat a member value seed as pushable work on its own. Adding a row to an
|
|
30
|
+
unordered list moves no stored record — membership is the new row's
|
|
31
|
+
`containerId` — so `neo status` and `neo push` reported a clean working copy
|
|
32
|
+
and silently dropped it. `neo status` now reports pending seeds too.
|
|
33
|
+
- Accept a stored row that spells "no class" as an explicit `null`, and adopt
|
|
34
|
+
the declared storage partition for an unstamped row reached through its
|
|
35
|
+
owning slot, in constructed static value graph validation. Rows materialized
|
|
36
|
+
before their partition was stamped (object-tree `Enabled`, P41 §4.3) sit in
|
|
37
|
+
main under a partitioned parent and failed a push over data it never wrote. A
|
|
38
|
+
row already stamped for a different partition is still rejected.
|
|
39
|
+
|
|
3
40
|
## [0.25.0] - 2026-08-07
|
|
4
41
|
|
|
5
42
|
### Added
|
package/dist/neo.mjs
CHANGED
|
@@ -61613,11 +61613,16 @@ function evalFunction(fn, scope, ctx) {
|
|
|
61613
61613
|
}
|
|
61614
61614
|
return c.includes(target);
|
|
61615
61615
|
}
|
|
61616
|
-
|
|
61617
|
-
|
|
61618
|
-
|
|
61619
|
-
|
|
61620
|
-
|
|
61616
|
+
const targetReferenceId = typeof target === "string" ? target : findKnownRowIdByValueReference(target, ctx);
|
|
61617
|
+
let containsResolvedEntry = false;
|
|
61618
|
+
iterateCollection(c, ctx, (entry, _key, valueId) => {
|
|
61619
|
+
if (valueId !== null && valueId === targetReferenceId || jsEqual(entry, target)) {
|
|
61620
|
+
containsResolvedEntry = true;
|
|
61621
|
+
return 1 /* Break */;
|
|
61622
|
+
}
|
|
61623
|
+
return 0 /* Continue */;
|
|
61624
|
+
});
|
|
61625
|
+
return containsResolvedEntry;
|
|
61621
61626
|
}
|
|
61622
61627
|
case "decimalOp" /* decimalOp */: {
|
|
61623
61628
|
const info = fn.info;
|
|
@@ -61772,6 +61777,7 @@ function evalFunction(fn, scope, ctx) {
|
|
|
61772
61777
|
out[String(key)] = valueId ?? entry;
|
|
61773
61778
|
}
|
|
61774
61779
|
}
|
|
61780
|
+
return 0 /* Continue */;
|
|
61775
61781
|
});
|
|
61776
61782
|
return out;
|
|
61777
61783
|
}
|
|
@@ -61783,10 +61789,9 @@ function evalFunction(fn, scope, ctx) {
|
|
|
61783
61789
|
const sentinel = /* @__PURE__ */ Symbol("not-found");
|
|
61784
61790
|
let found = sentinel;
|
|
61785
61791
|
iterateCollection(c, ctx, (entry, key) => {
|
|
61786
|
-
if (found !== sentinel) return;
|
|
61787
61792
|
if (!innerFn) {
|
|
61788
61793
|
found = entry;
|
|
61789
|
-
return
|
|
61794
|
+
return 1 /* Break */;
|
|
61790
61795
|
}
|
|
61791
61796
|
consumeBudget(ctx, "workUnits", 1, "work unit");
|
|
61792
61797
|
const innerScope = pushParams(
|
|
@@ -61803,7 +61808,9 @@ function evalFunction(fn, scope, ctx) {
|
|
|
61803
61808
|
);
|
|
61804
61809
|
if (result.kind === "return" && result.value === true) {
|
|
61805
61810
|
found = entry;
|
|
61811
|
+
return 1 /* Break */;
|
|
61806
61812
|
}
|
|
61813
|
+
return 0 /* Continue */;
|
|
61807
61814
|
});
|
|
61808
61815
|
if (found !== sentinel) return found;
|
|
61809
61816
|
if (fn.type === "first" /* first */) {
|
|
@@ -61841,6 +61848,7 @@ function evalFunction(fn, scope, ctx) {
|
|
|
61841
61848
|
);
|
|
61842
61849
|
out.push(result.value);
|
|
61843
61850
|
}
|
|
61851
|
+
return 0 /* Continue */;
|
|
61844
61852
|
});
|
|
61845
61853
|
return out;
|
|
61846
61854
|
}
|
|
@@ -64304,6 +64312,7 @@ function snapshotCollectionMembership(collection, ctx) {
|
|
|
64304
64312
|
const valid = forEachRawCollectionEntry(collection, ({ raw }) => {
|
|
64305
64313
|
consumeBudget(ctx, "collectionVisits", 1, "collection visit");
|
|
64306
64314
|
membership.push(raw);
|
|
64315
|
+
return 0 /* Continue */;
|
|
64307
64316
|
});
|
|
64308
64317
|
if (valid) return membership;
|
|
64309
64318
|
throw new NSGetterRuntimeError(
|
|
@@ -64314,21 +64323,23 @@ function forEachRawCollectionEntry(c, callback) {
|
|
|
64314
64323
|
if (Array.isArray(c)) {
|
|
64315
64324
|
for (let key = 0; key < c.length; key += 1) {
|
|
64316
64325
|
const raw = c[key];
|
|
64317
|
-
callback({
|
|
64326
|
+
const control = callback({
|
|
64318
64327
|
raw,
|
|
64319
64328
|
key,
|
|
64320
64329
|
valueId: typeof raw === "string" ? raw : null
|
|
64321
64330
|
});
|
|
64331
|
+
if (control === 1 /* Break */) break;
|
|
64322
64332
|
}
|
|
64323
64333
|
return true;
|
|
64324
64334
|
}
|
|
64325
64335
|
if (typeof c === "object" && c !== null) {
|
|
64326
64336
|
for (const [key, raw] of Object.entries(c)) {
|
|
64327
|
-
callback({
|
|
64337
|
+
const control = callback({
|
|
64328
64338
|
raw,
|
|
64329
64339
|
key,
|
|
64330
64340
|
valueId: typeof raw === "string" ? raw : null
|
|
64331
64341
|
});
|
|
64342
|
+
if (control === 1 /* Break */) break;
|
|
64332
64343
|
}
|
|
64333
64344
|
return true;
|
|
64334
64345
|
}
|
|
@@ -64339,6 +64350,7 @@ function collectionEntries(c, ctx) {
|
|
|
64339
64350
|
forEachRawCollectionEntry(c, ({ raw }) => {
|
|
64340
64351
|
consumeBudget(ctx, "collectionVisits", 1, "collection visit");
|
|
64341
64352
|
entries.push(resolveValueIfId(raw, ctx));
|
|
64353
|
+
return 0 /* Continue */;
|
|
64342
64354
|
});
|
|
64343
64355
|
return entries;
|
|
64344
64356
|
}
|
|
@@ -64346,7 +64358,7 @@ function iterateCollection(c, ctx, callback) {
|
|
|
64346
64358
|
forEachRawCollectionEntry(c, ({ raw, key, valueId }) => {
|
|
64347
64359
|
consumeBudget(ctx, "collectionVisits", 1, "collection visit");
|
|
64348
64360
|
const entry = resolveValueIfId(raw, ctx);
|
|
64349
|
-
callback(entry, key, valueId);
|
|
64361
|
+
return callback(entry, key, valueId);
|
|
64350
64362
|
});
|
|
64351
64363
|
}
|
|
64352
64364
|
function pushParams(parent, parameters, positional, isList) {
|
|
@@ -78101,13 +78113,16 @@ var init_project_version_static_value_writes = __esm({
|
|
|
78101
78113
|
);
|
|
78102
78114
|
}
|
|
78103
78115
|
const normalizedExpected = normalizeMapKey(args.expectedMapKey);
|
|
78116
|
+
const normalizedStored = normalizeMapKey(value.mapKey);
|
|
78104
78117
|
if (this.createdValueIds.has(value.id)) {
|
|
78105
78118
|
this.visitedCreatedValueIds.add(value.id);
|
|
78106
78119
|
if (normalizedExpected === null) delete value.mapKey;
|
|
78107
78120
|
else value.mapKey = normalizedExpected;
|
|
78108
|
-
} else if (
|
|
78121
|
+
} else if (normalizedStored === null && normalizedExpected !== null) {
|
|
78122
|
+
value.mapKey = normalizedExpected;
|
|
78123
|
+
} else if (normalizedStored !== normalizedExpected) {
|
|
78109
78124
|
throw new Error(
|
|
78110
|
-
`${args.path} cannot bind value "${value.id}" from storage partition ${JSON.stringify(
|
|
78125
|
+
`${args.path} cannot bind value "${value.id}" from storage partition ${JSON.stringify(normalizedStored ?? "main")}; expected ${JSON.stringify(normalizedExpected ?? "main")}.`
|
|
78111
78126
|
);
|
|
78112
78127
|
}
|
|
78113
78128
|
if (args.graphValueIds.has(value.id)) {
|
|
@@ -78144,7 +78159,7 @@ var init_project_version_static_value_writes = __esm({
|
|
|
78144
78159
|
}
|
|
78145
78160
|
return;
|
|
78146
78161
|
}
|
|
78147
|
-
if (member.kind !== 7 /* Class */ && value.classId !== void 0) {
|
|
78162
|
+
if (member.kind !== 7 /* Class */ && value.classId !== void 0 && value.classId !== null) {
|
|
78148
78163
|
throw new Error(
|
|
78149
78164
|
`${path} value "${value.id}" has classId but the member is not Class.`
|
|
78150
78165
|
);
|
|
@@ -86434,6 +86449,7 @@ function buildValueLowerContext(state, manifest, options = {}) {
|
|
|
86434
86449
|
pendingValues: registry.pendingValues,
|
|
86435
86450
|
pendingLocalizedTexts: registry.pendingLocalizedTexts,
|
|
86436
86451
|
loweredMemberIdByValueId: /* @__PURE__ */ new Map(),
|
|
86452
|
+
storedClassSchemaMemberIds: /* @__PURE__ */ new Map(),
|
|
86437
86453
|
pendingBindingMembersByClassId: registry.pendingBindingMembersByClassId,
|
|
86438
86454
|
declaredConstructors: declaredConstructorIndex,
|
|
86439
86455
|
initAuthoredRowIds: seedInitAuthoredRowIds(
|
|
@@ -86657,14 +86673,12 @@ function lowerMemberDefaultSourcesV4(state, analysis, manifest, options = {}) {
|
|
|
86657
86673
|
(row) => !existingPendingValueIds.has(row.id)
|
|
86658
86674
|
);
|
|
86659
86675
|
if (pendingRows.length > 0) {
|
|
86660
|
-
const existingRows =
|
|
86661
|
-
|
|
86662
|
-
|
|
86663
|
-
|
|
86664
|
-
|
|
86665
|
-
|
|
86666
|
-
)
|
|
86667
|
-
);
|
|
86676
|
+
const existingRows = pendingSeedGraphRows({
|
|
86677
|
+
context,
|
|
86678
|
+
reconstructedBefore: existingReconstructedKeys,
|
|
86679
|
+
pendingRows,
|
|
86680
|
+
rootBody: lowered.value
|
|
86681
|
+
});
|
|
86668
86682
|
const bindingMembers = [
|
|
86669
86683
|
...context.pendingBindingMembersByClassId.values()
|
|
86670
86684
|
].filter(
|
|
@@ -87247,21 +87261,49 @@ function lowerRowBackedDefault(context, member, backed, baseData3, binding) {
|
|
|
87247
87261
|
`Default value ${binding.label}.${assignment.name} is constructor-projected and must be set through its named constructor argument.`
|
|
87248
87262
|
);
|
|
87249
87263
|
}
|
|
87264
|
+
const childValueMember = recursivePartialMember(member, childMember);
|
|
87265
|
+
const childSlice = assignmentSlices.get(assignment.name);
|
|
87250
87266
|
const existingId = isObjectRecord2(baseBody) ? baseBody[assignment.name] : void 0;
|
|
87251
|
-
const
|
|
87252
|
-
|
|
87267
|
+
const annotatedId = annotatedValue(assignment.value).id;
|
|
87268
|
+
const storedId = typeof existingId === "string" ? existingId : annotatedId;
|
|
87269
|
+
if (storedId !== null && storedId !== void 0) {
|
|
87270
|
+
if (typeof existingId === "string" || context.state[`value:${storedId}`] !== void 0) {
|
|
87271
|
+
body[assignment.name] = lowerValueRow(
|
|
87272
|
+
context,
|
|
87273
|
+
childValueMember,
|
|
87274
|
+
assignment.value,
|
|
87275
|
+
storedId,
|
|
87276
|
+
binding,
|
|
87277
|
+
environment,
|
|
87278
|
+
childSlice
|
|
87279
|
+
);
|
|
87280
|
+
continue;
|
|
87281
|
+
}
|
|
87282
|
+
if (!isPendingId(storedId) && !isUuidV4Id(storedId)) {
|
|
87283
|
+
context.loweringFailures.push({
|
|
87284
|
+
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.`,
|
|
87285
|
+
site: referenceSite(binding, assignment.value)
|
|
87286
|
+
});
|
|
87287
|
+
}
|
|
87288
|
+
}
|
|
87289
|
+
const placedId = sourceValueSymbol(context, assignment.value);
|
|
87290
|
+
if (placedId !== null) {
|
|
87253
87291
|
throw new Error(
|
|
87254
|
-
`Default value ${binding.label}.${assignment.name}
|
|
87292
|
+
`Default value ${binding.label}.${assignment.name} cannot place existing value ${placedId} into a new structural slot. Create the nested value inline so the atomic construction transaction can own it.`
|
|
87255
87293
|
);
|
|
87256
87294
|
}
|
|
87257
|
-
body[assignment.name] =
|
|
87295
|
+
body[assignment.name] = lowerSeedChild(
|
|
87258
87296
|
context,
|
|
87259
|
-
|
|
87297
|
+
childValueMember,
|
|
87260
87298
|
assignment.value,
|
|
87261
|
-
childId,
|
|
87262
87299
|
binding,
|
|
87300
|
+
`${binding.label}.${assignment.name}`,
|
|
87301
|
+
/* @__PURE__ */ new Map(),
|
|
87302
|
+
/* @__PURE__ */ new Map(),
|
|
87303
|
+
void 0,
|
|
87263
87304
|
environment,
|
|
87264
|
-
|
|
87305
|
+
void 0,
|
|
87306
|
+
childSlice
|
|
87265
87307
|
);
|
|
87266
87308
|
}
|
|
87267
87309
|
return {
|
|
@@ -87402,14 +87444,13 @@ function lowerStoredBinding(context, binding, memberValueIds, seeds) {
|
|
|
87402
87444
|
);
|
|
87403
87445
|
if (pendingRows.length > 0) {
|
|
87404
87446
|
const root = reconstructedOrStateValue(context, valueId);
|
|
87405
|
-
const existingRows =
|
|
87406
|
-
|
|
87407
|
-
|
|
87408
|
-
|
|
87409
|
-
|
|
87410
|
-
|
|
87411
|
-
|
|
87412
|
-
);
|
|
87447
|
+
const existingRows = pendingSeedGraphRows({
|
|
87448
|
+
context,
|
|
87449
|
+
reconstructedBefore: existingReconstructedKeys,
|
|
87450
|
+
pendingRows,
|
|
87451
|
+
rootBody: root.value,
|
|
87452
|
+
rootValueId: valueId
|
|
87453
|
+
});
|
|
87413
87454
|
const bindingMembers = [
|
|
87414
87455
|
...context.pendingBindingMembersByClassId.values()
|
|
87415
87456
|
].filter((pending) => !existingPendingBindingMemberIds.has(pending.id));
|
|
@@ -87444,6 +87485,105 @@ function memberValueId(memberId) {
|
|
|
87444
87485
|
function reconstructedOrStateValue(context, valueId) {
|
|
87445
87486
|
return context.reconstructed.get(`value:${valueId}`)?.fileFields ?? valueBase(context, valueId);
|
|
87446
87487
|
}
|
|
87488
|
+
function pendingSeedGraphRows(args) {
|
|
87489
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
87490
|
+
for (const [key, record3] of args.context.reconstructed) {
|
|
87491
|
+
if (args.reconstructedBefore.has(key)) continue;
|
|
87492
|
+
if (record3.recordKind !== "value") continue;
|
|
87493
|
+
if (record3.recordId === args.rootValueId) continue;
|
|
87494
|
+
candidates.set(record3.recordId, record3.fileFields);
|
|
87495
|
+
}
|
|
87496
|
+
const pendingIds = new Set(args.pendingRows.map((row) => row.id));
|
|
87497
|
+
const bodies = /* @__PURE__ */ new Map();
|
|
87498
|
+
for (const [id2, fields] of candidates) bodies.set(id2, fields.value);
|
|
87499
|
+
for (const row of args.pendingRows) bodies.set(row.id, row.value);
|
|
87500
|
+
const containedIds = /* @__PURE__ */ new Map();
|
|
87501
|
+
const addContained = (containerId, id2) => {
|
|
87502
|
+
if (typeof containerId !== "string") return;
|
|
87503
|
+
const siblings = containedIds.get(containerId);
|
|
87504
|
+
if (siblings === void 0) containedIds.set(containerId, [id2]);
|
|
87505
|
+
else siblings.push(id2);
|
|
87506
|
+
};
|
|
87507
|
+
for (const [id2, fields] of candidates) addContained(fields.containerId, id2);
|
|
87508
|
+
for (const row of args.pendingRows) addContained(row.containerId, row.id);
|
|
87509
|
+
const collectReferenced = (body, into) => {
|
|
87510
|
+
if (typeof body === "string") {
|
|
87511
|
+
if (bodies.has(body)) into.add(body);
|
|
87512
|
+
return;
|
|
87513
|
+
}
|
|
87514
|
+
if (Array.isArray(body)) {
|
|
87515
|
+
for (const entry of body) collectReferenced(entry, into);
|
|
87516
|
+
return;
|
|
87517
|
+
}
|
|
87518
|
+
if (!isObjectRecord2(body)) return;
|
|
87519
|
+
for (const entry of Object.values(body)) collectReferenced(entry, into);
|
|
87520
|
+
};
|
|
87521
|
+
const childIds = (id2) => {
|
|
87522
|
+
const children = new Set(containedIds.get(id2) ?? []);
|
|
87523
|
+
collectReferenced(bodies.get(id2), children);
|
|
87524
|
+
children.delete(id2);
|
|
87525
|
+
return children;
|
|
87526
|
+
};
|
|
87527
|
+
const reachesPending = /* @__PURE__ */ new Map();
|
|
87528
|
+
const visit = (id2) => {
|
|
87529
|
+
const settled = reachesPending.get(id2);
|
|
87530
|
+
if (settled !== void 0) return settled;
|
|
87531
|
+
reachesPending.set(id2, false);
|
|
87532
|
+
let reaches = pendingIds.has(id2);
|
|
87533
|
+
for (const childId of childIds(id2)) {
|
|
87534
|
+
if (visit(childId)) reaches = true;
|
|
87535
|
+
}
|
|
87536
|
+
reachesPending.set(id2, reaches);
|
|
87537
|
+
return reaches;
|
|
87538
|
+
};
|
|
87539
|
+
const roots = new Set(
|
|
87540
|
+
args.rootValueId === void 0 ? [] : containedIds.get(args.rootValueId) ?? []
|
|
87541
|
+
);
|
|
87542
|
+
collectReferenced(args.rootBody, roots);
|
|
87543
|
+
for (const id2 of roots) visit(id2);
|
|
87544
|
+
const rows = [];
|
|
87545
|
+
for (const [id2, fields] of candidates) {
|
|
87546
|
+
if (reachesPending.get(id2) !== true) continue;
|
|
87547
|
+
rows.push(
|
|
87548
|
+
staticValueSeedRow(fields, args.context.loweredMemberIdByValueId.get(id2))
|
|
87549
|
+
);
|
|
87550
|
+
}
|
|
87551
|
+
return rows;
|
|
87552
|
+
}
|
|
87553
|
+
function retainedStoredClassBody(context, storedClassId, baseBody) {
|
|
87554
|
+
const storedMemberIds = storedClassSchemaMemberIds(context, storedClassId);
|
|
87555
|
+
const body = {};
|
|
87556
|
+
for (const [key, childId] of Object.entries(baseBody)) {
|
|
87557
|
+
const storedMemberId = storedMemberIds.get(key);
|
|
87558
|
+
if (storedMemberId !== void 0 && !context.members.has(storedMemberId)) {
|
|
87559
|
+
continue;
|
|
87560
|
+
}
|
|
87561
|
+
body[key] = childId;
|
|
87562
|
+
}
|
|
87563
|
+
return body;
|
|
87564
|
+
}
|
|
87565
|
+
function storedClassSchemaMemberIds(context, classId) {
|
|
87566
|
+
const cached = context.storedClassSchemaMemberIds.get(classId);
|
|
87567
|
+
if (cached !== void 0) return cached;
|
|
87568
|
+
const memberIds = /* @__PURE__ */ new Map();
|
|
87569
|
+
let current = classId;
|
|
87570
|
+
const visited = /* @__PURE__ */ new Set();
|
|
87571
|
+
while (current !== null && !visited.has(current)) {
|
|
87572
|
+
visited.add(current);
|
|
87573
|
+
const data = stateData(context, "class", current);
|
|
87574
|
+
if (data === null) break;
|
|
87575
|
+
if (isObjectRecord2(data.schema)) {
|
|
87576
|
+
for (const [key, memberId] of Object.entries(data.schema)) {
|
|
87577
|
+
if (typeof memberId === "string" && !memberIds.has(key)) {
|
|
87578
|
+
memberIds.set(key, memberId);
|
|
87579
|
+
}
|
|
87580
|
+
}
|
|
87581
|
+
}
|
|
87582
|
+
current = stringOrNull(data.extendsClassId);
|
|
87583
|
+
}
|
|
87584
|
+
context.storedClassSchemaMemberIds.set(classId, memberIds);
|
|
87585
|
+
return memberIds;
|
|
87586
|
+
}
|
|
87447
87587
|
function staticValueSeedRow(value, loweredMemberId) {
|
|
87448
87588
|
const id2 = stringOrNull(value.id);
|
|
87449
87589
|
if (id2 === null) throw new Error("Authored value row is missing id.");
|
|
@@ -88195,7 +88335,11 @@ function lowerClassValue(context, member, expression, base, source, outerEnviron
|
|
|
88195
88335
|
String(base.id ?? member.name)
|
|
88196
88336
|
);
|
|
88197
88337
|
const baseBody = isObjectRecord2(base.value) ? base.value : {};
|
|
88198
|
-
const body =
|
|
88338
|
+
const body = retainedStoredClassBody(
|
|
88339
|
+
context,
|
|
88340
|
+
currentClassId,
|
|
88341
|
+
baseBody
|
|
88342
|
+
);
|
|
88199
88343
|
const assignmentSlices = objectInitializerSlices(authoredSlice);
|
|
88200
88344
|
if (materializedConstruction !== "preserve") {
|
|
88201
88345
|
lowerConstructorProjections(
|
|
@@ -100954,7 +101098,9 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
100954
101098
|
changes: status.changes,
|
|
100955
101099
|
binaryChanges: status.binaryChanges ?? []
|
|
100956
101100
|
});
|
|
100957
|
-
if (status.changes.length === 0
|
|
101101
|
+
if (status.changes.length === 0 && status.authoredValueSeeds.size === 0) {
|
|
101102
|
+
return status;
|
|
101103
|
+
}
|
|
100958
101104
|
const initConversions = status.initConversions ?? [];
|
|
100959
101105
|
if (initConversions.length > 0 && options.json !== true) {
|
|
100960
101106
|
for (const line of describeInitConversions(initConversions)) warn(line);
|
|
@@ -101059,7 +101205,7 @@ async function runPush(workspace, options, preparationOverride) {
|
|
|
101059
101205
|
const status = candidate.status;
|
|
101060
101206
|
const local = candidate.preparedLocal;
|
|
101061
101207
|
preparation?.stop();
|
|
101062
|
-
if (status.changes.length === 0) {
|
|
101208
|
+
if (status.changes.length === 0 && status.authoredValueSeeds.size === 0) {
|
|
101063
101209
|
if (options.json === true) {
|
|
101064
101210
|
console.log(
|
|
101065
101211
|
JSON.stringify({
|
|
@@ -101575,7 +101721,7 @@ async function prepareLocalCandidateV4(workspace, options = {}) {
|
|
|
101575
101721
|
let sourceHash;
|
|
101576
101722
|
let preparedLocal = null;
|
|
101577
101723
|
let documentStatus = status;
|
|
101578
|
-
if (status.changes.length > 0) {
|
|
101724
|
+
if (status.changes.length > 0 || status.authoredValueSeeds.size > 0) {
|
|
101579
101725
|
try {
|
|
101580
101726
|
documentStatus = pushOptions.dryRun ? cloneStatusForDryRun(status) : status;
|
|
101581
101727
|
preparedLocal = await prepareLocalPushArtifactsV4(
|
|
@@ -103116,7 +103262,7 @@ var init_registry2 = __esm({
|
|
|
103116
103262
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
103117
103263
|
formatVersion: 3,
|
|
103118
103264
|
contractVersion: "3.9",
|
|
103119
|
-
cliVersion: "0.25.
|
|
103265
|
+
cliVersion: "0.25.1",
|
|
103120
103266
|
projectFileUploadBatchSize: 32,
|
|
103121
103267
|
documentRecords: {
|
|
103122
103268
|
member: {
|
|
@@ -109811,7 +109957,12 @@ async function main() {
|
|
|
109811
109957
|
`${paintChangeKind(binary.action === "create" ? "create" : "update")} project-file bytes ${binary.symbol} (${binary.path}) \u2014 ${binary.action}`
|
|
109812
109958
|
);
|
|
109813
109959
|
}
|
|
109814
|
-
if (status.
|
|
109960
|
+
if (status.authoredValueSeeds.size > 0) {
|
|
109961
|
+
console.log(
|
|
109962
|
+
` ${paintChangeKind("create")} ${status.authoredValueSeeds.size} member value seed(s)`
|
|
109963
|
+
);
|
|
109964
|
+
}
|
|
109965
|
+
if (status.conflictedFiles.length === 0 && status.parseErrors.length === 0 && status.changes.length === 0 && status.authoredValueSeeds.size === 0 && (status.binaryChanges?.length ?? 0) === 0) {
|
|
109815
109966
|
console.log(`${sym.ok} Working copy is clean.`);
|
|
109816
109967
|
}
|
|
109817
109968
|
return;
|
package/package.json
CHANGED
|
@@ -41,11 +41,12 @@ Read the relevant specs in full:
|
|
|
41
41
|
- [P50 loops](https://github.com/ryanbliss/neo-compose-specs/blob/main/new-features/p50-neoscript-for-and-foreach-loops.md)
|
|
42
42
|
- [P51 switch](https://github.com/ryanbliss/neo-compose-specs/blob/main/new-features/p51-neoscript-switch-statements.md)
|
|
43
43
|
- [P52 try/catch](https://github.com/ryanbliss/neo-compose-specs/blob/main/new-features/p52-neoscript-try-catch-blocks.md)
|
|
44
|
+
- [P55 breakable collection iteration](https://github.com/ryanbliss/neo-compose-specs/blob/main/neoscript/p55-breakable-collection-iteration.md)
|
|
44
45
|
- [P60 delegate parameters and selector targeting](https://github.com/ryanbliss/neo-compose-specs/blob/main/new-features/p60-closure-parameters-and-selector-targeting.md)
|
|
45
46
|
- [P61 initializer materialization](https://github.com/ryanbliss/neo-compose-specs/blob/main/new-features/complete/p61-initializer-materialization.md)
|
|
46
47
|
- [P64 NeoScript unit testing and push hooks](https://github.com/ryanbliss/neo-compose-specs/blob/main/new-features/p64-neoscript-unit-testing-and-push-hooks.md)
|
|
47
48
|
|
|
48
|
-
P38–P44, P47–P52, P60–P61, and the initial P64 test/push-hook vertical slice
|
|
49
|
+
P38–P44, P47–P52, P55, P60–P61, and the initial P64 test/push-hook vertical slice
|
|
49
50
|
are implemented. P45 remains deliberately deferred; do not
|
|
50
51
|
build or teach runtime-child provenance. P46 is a hardening proposal, not an
|
|
51
52
|
authoring capability. P52's document header still says proposed, but try/catch
|
|
@@ -82,7 +83,7 @@ wrappers.
|
|
|
82
83
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
83
84
|
|
|
84
85
|
```html
|
|
85
|
-
<!-- reviewed-through-cli: 0.25.
|
|
86
|
+
<!-- reviewed-through-cli: 0.25.1 -->
|
|
86
87
|
```
|
|
87
88
|
|
|
88
89
|
The quoted version above is checked too, so this instruction cannot go stale
|