@neocompose/cli 0.81.2 → 0.81.3

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,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.81.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 9bdbe4b: Preserve outer construction values after editing an inline child. Stored children at their virtual IDs keep the outer construction's omitted fields when their variant selection matches, and ToVariant applies in place without recording an independent applied layer.
8
+ - 45e1b8b: Keep nested generic constructions bound to their own type arguments. Root values such as `Box<Box<int>>` and `Box<List<Box<int>>>` now push and round-trip without constructor argument errors.
9
+ - b6bb4b8: Fix edits to deeply nested projected constructor arguments when a changed field is packed inside its parent. Reconciliation now protects the edit with the physical parent row's content hash.
10
+
3
11
  ## 0.81.2
4
12
 
5
13
  ### Patch Changes
package/dist/neo.mjs CHANGED
@@ -54564,7 +54564,7 @@ var init_registry = __esm({
54564
54564
  "../packages/manifest/schema-contract/registry.mjs"() {
54565
54565
  "use strict";
54566
54566
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
54567
- cliVersion: "0.81.2",
54567
+ cliVersion: "0.81.3",
54568
54568
  projectFileUploadBatchSize: 32,
54569
54569
  documentRecords: {
54570
54570
  member: {
@@ -84200,9 +84200,27 @@ function validateClassConstructorDescriptor(info, ctx, requireEveryRequiredField
84200
84200
  `Cannot construct abstract Class '${schemaClass2.name}'.`
84201
84201
  );
84202
84202
  }
84203
- const genericSlot = ctx.__constructionGenericSlots?.toReversed().find((slot) => slot.classId === classId) ?? ctx.__storedConstructionReplaySlot;
84204
- const slotArguments = genericSlot?.classId === classId ? genericSlot.classArguments : void 0;
84205
- const typeArguments = slotArguments === void 0 ? receiverClosedTypeArguments(info.schemaClassInfo.typeArguments, ctx) : void 0;
84203
+ const typeArguments = receiverClosedTypeArguments(
84204
+ info.schemaClassInfo.typeArguments,
84205
+ ctx
84206
+ );
84207
+ const matchesSlot = (slot) => {
84208
+ if (slot.classId !== classId) return false;
84209
+ if (typeArguments === void 0) return true;
84210
+ const env = cachedInstanceEnv(classId, slot.classArguments, ctx);
84211
+ return Object.entries(typeArguments).every(([parameterId, typeInfo]) => {
84212
+ const binding = env.get(parameterId);
84213
+ if (binding?.kind !== "member") return false;
84214
+ const member = evalMemberById(ctx.vm, binding.memberId);
84215
+ return member !== null && typeInfosInvariantlyEqual(
84216
+ runtimeTypeInfoForMember(member, env, ctx, /* @__PURE__ */ new Set()),
84217
+ typeInfo
84218
+ );
84219
+ });
84220
+ };
84221
+ const genericSlot = ctx.__constructionGenericSlots?.findLast(matchesSlot);
84222
+ const replaySlot = ctx.__storedConstructionReplaySlot;
84223
+ const slotArguments = genericSlot?.classArguments ?? (replaySlot !== void 0 && matchesSlot(replaySlot) ? replaySlot.classArguments : void 0);
84206
84224
  const descriptorCache = evaluatorValueGeneration(ctx).constructorDescriptors;
84207
84225
  const descriptorCacheKey = `${requireEveryRequiredField}:${ctx.storedConstructionReplay === true}:${JSON.stringify(slotArguments ?? typeArguments ?? null)}`;
84208
84226
  const cachedDescriptor = descriptorCache.get(info)?.get(descriptorCacheKey);
@@ -89386,20 +89404,6 @@ var init_variant_value_graph = __esm({
89386
89404
  }
89387
89405
  });
89388
89406
 
89389
- // ../packages/neoscript-runtime/src/declaration-default-source.ts
89390
- function declarationDefaultSource(id2, stored, resolveGraph) {
89391
- if (stored !== null && !isCollapseStampedInstanceRoot(stored)) return stored;
89392
- const graph = resolveGraph(id2);
89393
- return defaultSourceWithListeners(graph?.rowsById.get(id2) ?? stored, graph);
89394
- }
89395
- var init_declaration_default_source = __esm({
89396
- "../packages/neoscript-runtime/src/declaration-default-source.ts"() {
89397
- "use strict";
89398
- init_instance_provenance();
89399
- init_member_change_listeners();
89400
- }
89401
- });
89402
-
89403
89407
  // ../packages/models/src/members/stored-value-placement-index.ts
89404
89408
  function buildStoredValuePlacementIndex(args) {
89405
89409
  return createStoredValuePlacementTraversal(args)();
@@ -89779,6 +89783,20 @@ var init_stored_value_placement_index = __esm({
89779
89783
  }
89780
89784
  });
89781
89785
 
89786
+ // ../packages/neoscript-runtime/src/declaration-default-source.ts
89787
+ function declarationDefaultSource(id2, stored, resolveGraph) {
89788
+ if (stored !== null && !isCollapseStampedInstanceRoot(stored)) return stored;
89789
+ const graph = resolveGraph(id2);
89790
+ return defaultSourceWithListeners(graph?.rowsById.get(id2) ?? stored, graph);
89791
+ }
89792
+ var init_declaration_default_source = __esm({
89793
+ "../packages/neoscript-runtime/src/declaration-default-source.ts"() {
89794
+ "use strict";
89795
+ init_instance_provenance();
89796
+ init_member_change_listeners();
89797
+ }
89798
+ });
89799
+
89782
89800
  // ../packages/neoscript-runtime/src/listener-endpoint-projection.ts
89783
89801
  function projectListenerEndpoint(args) {
89784
89802
  const { descriptor } = args;
@@ -89859,6 +89877,14 @@ var init_overlay_readonly_map = __esm({
89859
89877
  });
89860
89878
 
89861
89879
  // ../packages/neoscript-runtime/src/virtual-instance-graph.ts
89880
+ function isMaterializedSpine(location3) {
89881
+ const stored = location3?.materializedRow;
89882
+ if (stored == null || location3?.parentId == null) return false;
89883
+ const virtual = location3.virtualRow;
89884
+ if (!isLiteralValueContent(stored) || !isLiteralValueContent(virtual))
89885
+ return false;
89886
+ return stored.id === virtual.id && (stored.instanceVariantId ?? null) === (virtual.instanceVariantId ?? null) && (stored.instanceVariantRowValueId ?? null) === (virtual.instanceVariantRowValueId ?? null) && (stored.instanceAppliedVariantId ?? null) === (virtual.instanceAppliedVariantId ?? null) && (stored.instanceAppliedVariantRowValueId ?? null) === (virtual.instanceAppliedVariantRowValueId ?? null);
89887
+ }
89862
89888
  function buildVirtualInstanceMaterializedIndex(args) {
89863
89889
  const rowsById = new Map(
89864
89890
  (args.materializedRows ?? args.document.values).map((row) => [row.id, row])
@@ -91103,6 +91129,7 @@ function resolveStoredInstanceGraphs(args) {
91103
91129
  if (next === void 0 || resolvedRootIds.has(next.root.id)) continue;
91104
91130
  resolvedRootIds.add(next.root.id);
91105
91131
  enqueueStoredRoots(stored.includeRoot(next.root, next.member));
91132
+ if (isMaterializedSpine(resolvedLocations.get(next.root.id))) continue;
91106
91133
  const graph = isMemberClassBase(next.member) ? args.resolveClassGraph?.(next.root, next.member) ?? resolveStoredClassValue({
91107
91134
  evaluateInitializer: args.evaluateInitializer,
91108
91135
  document,
@@ -93168,6 +93195,10 @@ function createHeadlessVirtualInstanceResolver(args) {
93168
93195
  graphByValueId.set(graph.instanceRootId, graph);
93169
93196
  };
93170
93197
  const expandRoot = (rootId, declaredMember) => {
93198
+ const containing = graphByValueId.get(rootId);
93199
+ if (containing !== void 0 && isMaterializedSpine(containing.locationsById.get(rootId))) {
93200
+ return expandRoot(containing.instanceRootId, void 0);
93201
+ }
93171
93202
  const cached = graphRowsByRootId.get(rootId);
93172
93203
  if (cached !== void 0) {
93173
93204
  const reads2 = readsByRootId.get(rootId);
@@ -93257,17 +93288,21 @@ function createHeadlessVirtualInstanceResolver(args) {
93257
93288
  recorder.recordValuePlacementRead();
93258
93289
  recorder.recordValueRead(receiverValueId);
93259
93290
  let placement = placements().get(receiverValueId) ?? null;
93291
+ const roots = [];
93260
93292
  while (placement !== null) {
93261
93293
  recorder.recordValueRead(placement.valueId);
93262
93294
  const raw = rawById.get(placement.valueId);
93263
93295
  if (raw !== void 0 && isLiteralValueContent(raw) && isStoredClassResolutionRoot(raw)) {
93264
- return expandRoot(
93265
- placement.valueId,
93266
- membersById.get(placement.memberId)
93267
- );
93296
+ roots.push(placement);
93268
93297
  }
93269
93298
  placement = placement.parentValueId === null ? null : placements().get(placement.parentValueId) ?? null;
93270
93299
  }
93300
+ let resolved = emptyRows;
93301
+ for (let index = roots.length - 1; index >= 0; index -= 1) {
93302
+ const root2 = roots[index];
93303
+ resolved = expandRoot(root2.valueId, membersById.get(root2.memberId));
93304
+ }
93305
+ if (roots.length > 0) return resolved;
93271
93306
  const root = rawById.get(receiverValueId);
93272
93307
  if (root !== void 0 && typeof root.classId === "string" && isStoredClassResolutionRoot(root)) {
93273
93308
  return expandRoot(receiverValueId, {
@@ -93302,7 +93337,7 @@ function createHeadlessVirtualInstanceResolver(args) {
93302
93337
  const known = graphByValueId.get(valueId);
93303
93338
  if (known?.instanceRootId === valueId) return known;
93304
93339
  const stored = rawById.get(valueId);
93305
- if (known !== void 0 && (stored === void 0 || !isStoredClassResolutionRoot(stored)))
93340
+ if (known !== void 0 && (stored === void 0 || !isStoredClassResolutionRoot(stored) || isMaterializedSpine(known.locationsById.get(valueId))))
93306
93341
  return known;
93307
93342
  virtualInstanceRowsForValue(valueId);
93308
93343
  return graphByValueId.get(valueId) ?? null;
@@ -94657,6 +94692,7 @@ var init_effective_value_reader = __esm({
94657
94692
  init_core();
94658
94693
  init_members();
94659
94694
  init_packed_value_encoding();
94695
+ init_stored_value_placement_index();
94660
94696
  init_read_class_member();
94661
94697
  init_initializer_materialization();
94662
94698
  init_evaluateInitializer();
@@ -94721,6 +94757,7 @@ var init_effective_value_reader = __esm({
94721
94757
  resolvedDocument;
94722
94758
  indexedDocument;
94723
94759
  materializedIndex;
94760
+ storedPlacements;
94724
94761
  graphCache;
94725
94762
  createNormalizer(rowIdentities) {
94726
94763
  return createTypedValueNormalizer(
@@ -94994,6 +95031,30 @@ var init_effective_value_reader = __esm({
94994
95031
  unorderedListEntryIds: unorderedListEntryIds2
94995
95032
  });
94996
95033
  }
95034
+ const materializedIndex = this.materializedIndex;
95035
+ this.storedPlacements ??= buildStoredValuePlacementIndex({
95036
+ ...this.readDocument,
95037
+ constructors: this.readDocument.constructors ?? [],
95038
+ indexedRows: {
95039
+ valuesById: this.materializedIndex.rowsById,
95040
+ unorderedListEntryIds: (id2) => materializedIndex.unorderedEntryIdsByContainerId.get(id2) ?? []
95041
+ },
95042
+ resolveStaticValueId: (memberId) => this.memberForId(memberId)?.valueId ?? null
95043
+ });
95044
+ const positions = this.storedPlacements.placementByValueId;
95045
+ let parentId = positions.get(valueId)?.parentValueId;
95046
+ while (parentId != null) {
95047
+ const position = positions.get(parentId);
95048
+ if (position === void 0) break;
95049
+ const parentMember = this.memberForId(position.memberId);
95050
+ if (parentMember !== null && isMemberClassBase(parentMember)) {
95051
+ const containingRows = this.resolveGraph(parentId, parentMember);
95052
+ if (isMaterializedSpine(this.locations.get(valueId)))
95053
+ return containingRows;
95054
+ break;
95055
+ }
95056
+ parentId = position.parentValueId;
95057
+ }
94997
95058
  const rows = resolveStoredInstanceGraphs({
94998
95059
  ...this.context,
94999
95060
  readRecorder: this.context.readTracking === void 0 ? void 0 : virtualReadRecorder(this.context.readTracking),
@@ -117871,6 +117932,7 @@ function* prepareServerOwnedSchemaCommitPasses(args) {
117871
117932
  });
117872
117933
  materializePreparedInstanceInitializers({
117873
117934
  document: args.document,
117935
+ physicalValues: args.document.physicalValues,
117874
117936
  prepared,
117875
117937
  contentHashHeads: args.contentHashHeads
117876
117938
  });
@@ -118190,6 +118252,7 @@ function materializePreparedInstanceInitializers(args) {
118190
118252
  args.contentHashHeads,
118191
118253
  "value"
118192
118254
  );
118255
+ let writeBaseHashFor;
118193
118256
  const owners = resolveSemanticOwnerMembersForValues(
118194
118257
  materializationScope.document,
118195
118258
  new Set(sites.keys()),
@@ -118330,7 +118393,14 @@ function materializePreparedInstanceInitializers(args) {
118330
118393
  const existing = existingValueById.get(created.id);
118331
118394
  if (existing !== void 0) {
118332
118395
  if (materializedValueRowsEqual(existing, created)) continue;
118333
- const contentHash = liveValueHashes().get(created.id);
118396
+ writeBaseHashFor ??= createValueWriteBaseHashResolver({
118397
+ document: args.document,
118398
+ physicalValues: args.physicalValues,
118399
+ prepared: args.prepared,
118400
+ contentHashHeads: args.contentHashHeads,
118401
+ source: "server-initializer-materialization"
118402
+ });
118403
+ const contentHash = writeBaseHashFor(created.id);
118334
118404
  if (contentHash === void 0) {
118335
118405
  throw new Error(
118336
118406
  `Cannot reconcile materialized initializer row "${created.id}": its live content hash is unavailable.`
@@ -118345,7 +118415,7 @@ function materializePreparedInstanceInitializers(args) {
118345
118415
  source: "server-initializer-materialization",
118346
118416
  sourceValueId: valueId
118347
118417
  }),
118348
- expectedBaseContentHash: contentHash
118418
+ ...contentHash === null ? {} : { expectedBaseContentHash: contentHash }
118349
118419
  });
118350
118420
  existingValueById.set(created.id, created);
118351
118421
  continue;
@@ -120278,7 +120348,7 @@ function valueIdsFromRows(explicitRows, sweepRows) {
120278
120348
  for (const row of sweepRows) ids.add(row.id);
120279
120349
  return ids;
120280
120350
  }
120281
- function createValueRecompileBaseHashResolver(args) {
120351
+ function createValueWriteBaseHashResolver(args) {
120282
120352
  const hashById = indexLiveContentHashesByRecordId(
120283
120353
  args.contentHashHeads,
120284
120354
  "value"
@@ -120323,7 +120393,7 @@ function createValueRecompileBaseHashResolver(args) {
120323
120393
  nextData: root,
120324
120394
  expectedBaseContentHash: rootHash,
120325
120395
  intent: createProjectVersionIntent("value.update", {
120326
- source: "server-neoscript-recompile"
120396
+ source: args.source
120327
120397
  })
120328
120398
  });
120329
120399
  }
@@ -120441,7 +120511,8 @@ function prepareServerOwnedValueInitializerBodies(args) {
120441
120511
  const currentById = new Map(
120442
120512
  args.document.values.map((value) => [value.id, value])
120443
120513
  );
120444
- const baseHashFor = createValueRecompileBaseHashResolver({
120514
+ const baseHashFor = createValueWriteBaseHashResolver({
120515
+ source: "server-neoscript-recompile",
120445
120516
  document: committedDocument,
120446
120517
  physicalValues: args.document.physicalValues,
120447
120518
  prepared: args.prepared,
@@ -120913,7 +120984,8 @@ function prepareServerOwnedDelegateValueBodies(args) {
120913
120984
  const currentById = new Map(
120914
120985
  args.document.values.map((value) => [value.id, value])
120915
120986
  );
120916
- const baseHashFor = createValueRecompileBaseHashResolver({
120987
+ const baseHashFor = createValueWriteBaseHashResolver({
120988
+ source: "server-neoscript-recompile",
120917
120989
  document: committedDocument,
120918
120990
  physicalValues: args.physicalValues,
120919
120991
  prepared: args.prepared,
@@ -201775,7 +201847,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
201775
201847
  async function main() {
201776
201848
  const args = parseArgs(process.argv.slice(2));
201777
201849
  if (args.command === "--version") {
201778
- console.log("0.81.2");
201850
+ console.log("0.81.3");
201779
201851
  return;
201780
201852
  }
201781
201853
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
@@ -25166,9 +25166,27 @@ function validateClassConstructorDescriptor(info, ctx, requireEveryRequiredField
25166
25166
  `Cannot construct abstract Class '${schemaClass2.name}'.`
25167
25167
  );
25168
25168
  }
25169
- const genericSlot = ctx.__constructionGenericSlots?.toReversed().find((slot) => slot.classId === classId) ?? ctx.__storedConstructionReplaySlot;
25170
- const slotArguments = genericSlot?.classId === classId ? genericSlot.classArguments : void 0;
25171
- const typeArguments = slotArguments === void 0 ? receiverClosedTypeArguments(info.schemaClassInfo.typeArguments, ctx) : void 0;
25169
+ const typeArguments = receiverClosedTypeArguments(
25170
+ info.schemaClassInfo.typeArguments,
25171
+ ctx
25172
+ );
25173
+ const matchesSlot = (slot) => {
25174
+ if (slot.classId !== classId) return false;
25175
+ if (typeArguments === void 0) return true;
25176
+ const env = cachedInstanceEnv(classId, slot.classArguments, ctx);
25177
+ return Object.entries(typeArguments).every(([parameterId, typeInfo]) => {
25178
+ const binding = env.get(parameterId);
25179
+ if (binding?.kind !== "member") return false;
25180
+ const member = evalMemberById(ctx.vm, binding.memberId);
25181
+ return member !== null && typeInfosInvariantlyEqual(
25182
+ runtimeTypeInfoForMember(member, env, ctx, /* @__PURE__ */ new Set()),
25183
+ typeInfo
25184
+ );
25185
+ });
25186
+ };
25187
+ const genericSlot = ctx.__constructionGenericSlots?.findLast(matchesSlot);
25188
+ const replaySlot = ctx.__storedConstructionReplaySlot;
25189
+ const slotArguments = genericSlot?.classArguments ?? (replaySlot !== void 0 && matchesSlot(replaySlot) ? replaySlot.classArguments : void 0);
25172
25190
  const descriptorCache = evaluatorValueGeneration(ctx).constructorDescriptors;
25173
25191
  const descriptorCacheKey = `${requireEveryRequiredField}:${ctx.storedConstructionReplay === true}:${JSON.stringify(slotArguments ?? typeArguments ?? null)}`;
25174
25192
  const cachedDescriptor = descriptorCache.get(info)?.get(descriptorCacheKey);
@@ -32604,6 +32622,14 @@ function materializeMemberDefaultValue(args) {
32604
32622
  }
32605
32623
 
32606
32624
  // ../packages/neoscript-runtime/src/virtual-instance-graph.ts
32625
+ function isMaterializedSpine(location) {
32626
+ const stored = location?.materializedRow;
32627
+ if (stored == null || location?.parentId == null) return false;
32628
+ const virtual = location.virtualRow;
32629
+ if (!isLiteralValueContent(stored) || !isLiteralValueContent(virtual))
32630
+ return false;
32631
+ return stored.id === virtual.id && (stored.instanceVariantId ?? null) === (virtual.instanceVariantId ?? null) && (stored.instanceVariantRowValueId ?? null) === (virtual.instanceVariantRowValueId ?? null) && (stored.instanceAppliedVariantId ?? null) === (virtual.instanceAppliedVariantId ?? null) && (stored.instanceAppliedVariantRowValueId ?? null) === (virtual.instanceAppliedVariantRowValueId ?? null);
32632
+ }
32607
32633
  function buildVirtualInstanceMaterializedIndex(args) {
32608
32634
  const rowsById = new Map(
32609
32635
  (args.materializedRows ?? args.document.values).map((row) => [row.id, row])
@@ -35156,6 +35182,10 @@ function createHeadlessVirtualInstanceResolver(args) {
35156
35182
  graphByValueId.set(graph.instanceRootId, graph);
35157
35183
  };
35158
35184
  const expandRoot = (rootId, declaredMember) => {
35185
+ const containing = graphByValueId.get(rootId);
35186
+ if (containing !== void 0 && isMaterializedSpine(containing.locationsById.get(rootId))) {
35187
+ return expandRoot(containing.instanceRootId, void 0);
35188
+ }
35159
35189
  const cached = graphRowsByRootId.get(rootId);
35160
35190
  if (cached !== void 0) {
35161
35191
  const reads2 = readsByRootId.get(rootId);
@@ -35245,17 +35275,21 @@ function createHeadlessVirtualInstanceResolver(args) {
35245
35275
  recorder.recordValuePlacementRead();
35246
35276
  recorder.recordValueRead(receiverValueId);
35247
35277
  let placement = placements().get(receiverValueId) ?? null;
35278
+ const roots = [];
35248
35279
  while (placement !== null) {
35249
35280
  recorder.recordValueRead(placement.valueId);
35250
35281
  const raw = rawById.get(placement.valueId);
35251
35282
  if (raw !== void 0 && isLiteralValueContent(raw) && isStoredClassResolutionRoot(raw)) {
35252
- return expandRoot(
35253
- placement.valueId,
35254
- membersById.get(placement.memberId)
35255
- );
35283
+ roots.push(placement);
35256
35284
  }
35257
35285
  placement = placement.parentValueId === null ? null : placements().get(placement.parentValueId) ?? null;
35258
35286
  }
35287
+ let resolved = emptyRows;
35288
+ for (let index = roots.length - 1; index >= 0; index -= 1) {
35289
+ const root2 = roots[index];
35290
+ resolved = expandRoot(root2.valueId, membersById.get(root2.memberId));
35291
+ }
35292
+ if (roots.length > 0) return resolved;
35259
35293
  const root = rawById.get(receiverValueId);
35260
35294
  if (root !== void 0 && typeof root.classId === "string" && isStoredClassResolutionRoot(root)) {
35261
35295
  return expandRoot(receiverValueId, {
@@ -35290,7 +35324,7 @@ function createHeadlessVirtualInstanceResolver(args) {
35290
35324
  const known = graphByValueId.get(valueId);
35291
35325
  if (known?.instanceRootId === valueId) return known;
35292
35326
  const stored = rawById.get(valueId);
35293
- if (known !== void 0 && (stored === void 0 || !isStoredClassResolutionRoot(stored)))
35327
+ if (known !== void 0 && (stored === void 0 || !isStoredClassResolutionRoot(stored) || isMaterializedSpine(known.locationsById.get(valueId))))
35294
35328
  return known;
35295
35329
  virtualInstanceRowsForValue(valueId);
35296
35330
  return graphByValueId.get(valueId) ?? null;
@@ -59559,7 +59593,7 @@ var INITIALIZER_KEY_PLACEHOLDER = new RegExp(
59559
59593
 
59560
59594
  // ../packages/manifest/schema-contract/registry.mjs
59561
59595
  var PROJECT_SCHEMA_CONTRACT = Object.freeze({
59562
- cliVersion: "0.81.2",
59596
+ cliVersion: "0.81.3",
59563
59597
  projectFileUploadBatchSize: 32,
59564
59598
  documentRecords: {
59565
59599
  member: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.81.2",
3
+ "version": "0.81.3",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -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.81.2 -->
12
+ <!-- reviewed-through-cli: 0.81.3 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -129,7 +129,7 @@ wrappers.
129
129
  The marker near the top of `SKILL.md` must exactly match the package version:
130
130
 
131
131
  ```html
132
- <!-- reviewed-through-cli: 0.81.2 -->
132
+ <!-- reviewed-through-cli: 0.81.3 -->
133
133
  ```
134
134
 
135
135
  The quoted version above is checked too, so this instruction cannot go stale
@@ -247,6 +247,9 @@ initializer as its default. Omitted fields remain virtual and resolve through
247
247
  the instance's recorded constructor or variant. They track later source-default
248
248
  edits until that field is explicitly overridden; resetting an override makes it
249
249
  virtual again.
250
+ Editing an inline child preserves the outer construction's call-site values for
251
+ its other fields. The child keeps that construction while its variant selection
252
+ matches; selecting a different variant gives it an independent recipe.
250
253
 
251
254
  Declare a lookup member as `Reference<T>`. `public Reference<Config> Config`
252
255
  selects one row and reads as `Config`. `public Set<Reference<Config>> Configs`
@@ -578,6 +581,12 @@ selection. Constructor arguments and member initializers must select compatible
578
581
  targets too. An `NPC` lookup cannot select from `List<Quest>`, even when its
579
582
  initializer is typed `NPC`; status reports the conflicting collection annotation.
580
583
 
584
+ Generic constructions can nest the same generic class, including through
585
+ collections, such as `Box<Box<int>>` or `Box<List<Box<int>>>`. Each `new` uses
586
+ its own type arguments during first push and stored replay. Editing a nested
587
+ constructor argument rebuilds its projected fields in place, including fields
588
+ stored inside a packed parent; push followed by pull leaves a clean checkout.
589
+
581
590
  Schema export retains a constructed default's generic arguments, including
582
591
  nested collection references. For example, a `NeoAnimationClip<ArmPart>`
583
592
  default constructs `new NeoAnimationClip<ArmPart>` and its frames reference