@neocompose/cli 0.24.7 → 0.24.9

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,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.24.9] - 2026-08-08
4
+
5
+ ### Fixed
6
+
7
+ - Build `neo test` execution documents from the server-prepared candidate and
8
+ compile every remaining authored initializer into evaluator-only IR. Tests
9
+ can now construct classes whose pending idless list rows capture lexical
10
+ selectors without requiring an earlier push.
11
+ - Index constructor-initializer ownership by class and member instead of
12
+ repeatedly scanning the project document. This reduces Neowyn's
13
+ initializer-owner walk from 87.8 ms to 24.9 ms median.
14
+
15
+ ## [0.24.8] - 2026-08-08
16
+
17
+ ### Fixed
18
+
19
+ - Preserve generated Generic-slot initializers while closing their concrete
20
+ type. `NeoAnimationSegmentFrame<int>(value: 60)` now materializes `Value` as
21
+ `60` instead of replacing the initializer with the Int binding's fallback
22
+ `0`, keeping local and server construction graphs identical.
23
+ - Keep constructor-pane preview graphs stable while runtime values change, and
24
+ invalidate each animation segment lane only from the value rows that its
25
+ getter actually reads. Direction changes update the affected leaves without
26
+ reconstructing the ephemeral character graph.
27
+
3
28
  ## [0.24.7] - 2026-08-08
4
29
 
5
30
  ### Fixed
package/dist/neo.mjs CHANGED
@@ -40044,6 +40044,9 @@ function substituteMember(member, env, members) {
40044
40044
  accessModifierKind: resolved.accessModifierKind,
40045
40045
  system: resolved.system ?? void 0
40046
40046
  };
40047
+ if (resolved.defaultValue !== void 0) {
40048
+ substituted.defaultValue = resolved.defaultValue;
40049
+ }
40047
40050
  const slotId = getOptionalString(member, "id");
40048
40051
  if (slotId !== void 0) {
40049
40052
  substituted.id = slotId;
@@ -54907,6 +54910,14 @@ function resolveOwnerMembersForValues(document, targetValueIds, additionalRoots,
54907
54910
  const resolved = /* @__PURE__ */ new Map();
54908
54911
  if (targetValueIds.size === 0) return resolved;
54909
54912
  const valuesById = new Map(document.values.map((value) => [value.id, value]));
54913
+ const membersById = new Map(
54914
+ document.members.map((member) => [member.id, member])
54915
+ );
54916
+ const classesById = new Map(
54917
+ document.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
54918
+ );
54919
+ const storedSchemaByClassId = /* @__PURE__ */ new Map();
54920
+ const defaultInstanceEnvByClassId = /* @__PURE__ */ new Map();
54910
54921
  const rowsByContainerId = /* @__PURE__ */ new Map();
54911
54922
  for (const value of document.values) {
54912
54923
  if (typeof value.containerId !== "string") continue;
@@ -54930,7 +54941,25 @@ function resolveOwnerMembersForValues(document, targetValueIds, additionalRoots,
54930
54941
  if (typeof memberId !== "string") return /* @__PURE__ */ new Map();
54931
54942
  const classId = declaringClassIdByMemberId.get(memberId);
54932
54943
  if (classId === void 0) return /* @__PURE__ */ new Map();
54933
- return resolveInstanceEnv(classId, void 0, document.classes);
54944
+ return defaultInstanceEnv(classId);
54945
+ }
54946
+ function defaultInstanceEnv(classId) {
54947
+ const cached = defaultInstanceEnvByClassId.get(classId);
54948
+ if (cached !== void 0) return cached;
54949
+ const created = resolveInstanceEnv(classId, void 0, document.classes);
54950
+ defaultInstanceEnvByClassId.set(classId, created);
54951
+ return created;
54952
+ }
54953
+ function storedSchema(classId) {
54954
+ const cached = storedSchemaByClassId.get(classId);
54955
+ if (cached !== void 0) return cached;
54956
+ const created = mergeStoredInstanceSchema(
54957
+ classId,
54958
+ document.classes,
54959
+ document.members
54960
+ );
54961
+ storedSchemaByClassId.set(classId, created);
54962
+ return created;
54934
54963
  }
54935
54964
  function searchRow(member, valueId, rootOwner, env, rootKind) {
54936
54965
  if (targetValueIds.has(valueId) && !resolved.has(valueId)) {
@@ -54969,16 +54998,10 @@ function resolveOwnerMembersForValues(document, targetValueIds, additionalRoots,
54969
54998
  if (isMemberClassBase(member)) {
54970
54999
  if (!isRecordValue(body.value)) return;
54971
55000
  const effectiveClassId = body.classId ?? member.classId;
54972
- const schemaClass2 = document.classes.find(
54973
- (candidate) => candidate.id === effectiveClassId
54974
- );
55001
+ const schemaClass2 = classesById.get(effectiveClassId);
54975
55002
  if (schemaClass2 === void 0) return;
54976
- const merged = mergeStoredInstanceSchema(
54977
- effectiveClassId,
54978
- document.classes,
54979
- document.members
54980
- );
54981
- const env = resolveInstanceEnv(
55003
+ const merged = storedSchema(effectiveClassId);
55004
+ const env = member.classArguments === void 0 || member.classArguments === null ? defaultInstanceEnv(effectiveClassId) : resolveInstanceEnv(
54982
55005
  effectiveClassId,
54983
55006
  member.classArguments,
54984
55007
  document.classes
@@ -54987,9 +55010,7 @@ function resolveOwnerMembersForValues(document, targetValueIds, additionalRoots,
54987
55010
  if (entry.memberId === null) continue;
54988
55011
  const childValueId = body.value[entry.schemaKey];
54989
55012
  if (childValueId === void 0) continue;
54990
- const childMember = document.members.find(
54991
- (candidate) => candidate.id === entry.memberId
54992
- );
55013
+ const childMember = membersById.get(entry.memberId);
54993
55014
  if (childMember === void 0) continue;
54994
55015
  const substituted = trySubstituteMember(childMember, env);
54995
55016
  if (substituted === null) continue;
@@ -54999,9 +55020,7 @@ function resolveOwnerMembersForValues(document, targetValueIds, additionalRoots,
54999
55020
  }
55000
55021
  if (isMemberDictionaryBase(member)) {
55001
55022
  if (!isRecordValue(body.value)) return;
55002
- const entryMemberRecord = document.members.find(
55003
- (candidate) => candidate.id === member.entryMemberId
55004
- );
55023
+ const entryMemberRecord = membersById.get(member.entryMemberId);
55005
55024
  if (entryMemberRecord === void 0) return;
55006
55025
  const entryEnv = overlayStamp(ambientEnv, body.genericBindings);
55007
55026
  const entryMember = trySubstituteMember(entryMemberRecord, entryEnv);
@@ -55012,9 +55031,7 @@ function resolveOwnerMembersForValues(document, targetValueIds, additionalRoots,
55012
55031
  return;
55013
55032
  }
55014
55033
  if (isMemberListBase(member)) {
55015
- const entryMemberRecord = document.members.find(
55016
- (candidate) => candidate.id === member.entryMemberId
55017
- );
55034
+ const entryMemberRecord = membersById.get(member.entryMemberId);
55018
55035
  if (entryMemberRecord === void 0) return;
55019
55036
  const entryEnv = overlayStamp(ambientEnv, body.genericBindings);
55020
55037
  const entryMember = trySubstituteMember(entryMemberRecord, entryEnv);
@@ -56638,7 +56655,8 @@ function evalMemberById(vm, id2) {
56638
56655
  if (vm.databaseVM?.memberById) return vm.databaseVM.memberById(id2);
56639
56656
  return vm.members.find((a) => a.id === id2) ?? null;
56640
56657
  }
56641
- function evalValueById(vm, id2, runtimeValues, overlayValues) {
56658
+ function evalValueById(ctx, id2, runtimeValues, overlayValues) {
56659
+ const vm = ctx.vm;
56642
56660
  const runtime = runtimeValues?.get(id2);
56643
56661
  if (runtime !== void 0) return runtime;
56644
56662
  const overlay = overlayValues?.get(id2);
@@ -56908,7 +56926,7 @@ function evaluatorOwnershipDistances(rowId, indexes) {
56908
56926
  }
56909
56927
  function resolveRuntimeReferenceRow(sourceValueId, ctx) {
56910
56928
  const direct = evalValueById(
56911
- ctx.vm,
56929
+ ctx,
56912
56930
  sourceValueId,
56913
56931
  ctx.__runtimeSessionValues,
56914
56932
  ctx.__valueOverlay
@@ -57347,7 +57365,7 @@ function finalizeConstructorAllocations(ctx, returnValue, ownsInvocationState, r
57347
57365
  if (scannedRows.has(valueId)) return;
57348
57366
  scannedRows.add(valueId);
57349
57367
  const row = evalValueById(
57350
- ctx.vm,
57368
+ ctx,
57351
57369
  valueId,
57352
57370
  ctx.__runtimeSessionValues,
57353
57371
  ctx.__valueOverlay
@@ -57357,7 +57375,7 @@ function finalizeConstructorAllocations(ctx, returnValue, ownsInvocationState, r
57357
57375
  const { id: argumentId, typeInfo } = argument2;
57358
57376
  if (groupByRowId.has(argumentId)) scanOwnedRow(argumentId);
57359
57377
  const argumentRow = evalValueById(
57360
- ctx.vm,
57378
+ ctx,
57361
57379
  argumentId,
57362
57380
  ctx.__runtimeSessionValues,
57363
57381
  ctx.__valueOverlay
@@ -58210,7 +58228,7 @@ function applyOverlayAssignment(target, targetTypeInfo, value, scope, ctx) {
58210
58228
  const existing2 = receiver[index];
58211
58229
  if (typeof existing2 === "string") {
58212
58230
  const row = evalValueById(
58213
- ctx.vm,
58231
+ ctx,
58214
58232
  existing2,
58215
58233
  ctx.__runtimeSessionValues,
58216
58234
  ctx.__valueOverlay
@@ -58247,7 +58265,7 @@ function applyOverlayAssignment(target, targetTypeInfo, value, scope, ctx) {
58247
58265
  const existing = object2[stringKey];
58248
58266
  if (typeof existing === "string") {
58249
58267
  const row = evalValueById(
58250
- ctx.vm,
58268
+ ctx,
58251
58269
  existing,
58252
58270
  ctx.__runtimeSessionValues,
58253
58271
  ctx.__valueOverlay
@@ -58297,7 +58315,7 @@ function applyOverlayStaticAssignment(memberId, value, ctx) {
58297
58315
  }
58298
58316
  if (!referenceAssignment && currentId !== null) {
58299
58317
  const row2 = evalValueById(
58300
- ctx.vm,
58318
+ ctx,
58301
58319
  currentId,
58302
58320
  ctx.__runtimeSessionValues,
58303
58321
  ctx.__valueOverlay
@@ -58803,7 +58821,7 @@ function evalStaticMember(memberId, ctx) {
58803
58821
  return null;
58804
58822
  }
58805
58823
  const row = evalValueById(
58806
- ctx.vm,
58824
+ ctx,
58807
58825
  targetId,
58808
58826
  ctx.__runtimeSessionValues,
58809
58827
  ctx.__valueOverlay
@@ -58813,6 +58831,7 @@ function evalStaticMember(memberId, ctx) {
58813
58831
  `Static member '${member.name}' is bound to missing value '${targetId}'.`
58814
58832
  );
58815
58833
  }
58834
+ ctx.valueDependencies?.add(row.id);
58816
58835
  return row.value;
58817
58836
  }
58818
58837
  function evalPointer(pointer, scope, ctx) {
@@ -59098,7 +59117,7 @@ function invokeDelegateValue(value, args, ctx, callSiteId) {
59098
59117
  let receiver = null;
59099
59118
  if (value.valueId !== null) {
59100
59119
  const row = evalValueById(
59101
- ctx.vm,
59120
+ ctx,
59102
59121
  value.valueId,
59103
59122
  ctx.__runtimeSessionValues,
59104
59123
  ctx.__valueOverlay
@@ -59225,7 +59244,7 @@ function delegateClosureLexicalThis(closure, ctx) {
59225
59244
  )) {
59226
59245
  if (ancestorId === closureRow.id) continue;
59227
59246
  const ancestor = evalValueById(
59228
- ctx.vm,
59247
+ ctx,
59229
59248
  ancestorId,
59230
59249
  ctx.__runtimeSessionValues,
59231
59250
  ctx.__valueOverlay
@@ -59371,7 +59390,7 @@ function runtimeParentGenericEnv(row, ctx, visited) {
59371
59390
  const result = /* @__PURE__ */ new Map();
59372
59391
  for (const link of evaluatorParentLinks(evaluatorIndexes(ctx), row.id)) {
59373
59392
  const parent = evalValueById(
59374
- ctx.vm,
59393
+ ctx,
59375
59394
  link.parentId,
59376
59395
  ctx.__runtimeSessionValues,
59377
59396
  ctx.__valueOverlay
@@ -60042,12 +60061,13 @@ function resolveAssetRuntimeMember(receiver, memberName, ctx) {
60042
60061
  function resolveValueIfId(at, ctx) {
60043
60062
  if (typeof at !== "string") return at;
60044
60063
  const row = evalValueById(
60045
- ctx.vm,
60064
+ ctx,
60046
60065
  at,
60047
60066
  ctx.__runtimeSessionValues,
60048
60067
  ctx.__valueOverlay
60049
60068
  );
60050
60069
  if (!row) return at;
60070
+ ctx.valueDependencies?.add(row.id);
60051
60071
  const member = memberForValueRow(row, ctx);
60052
60072
  const value = member === null ? resolveLocalizedRowValue(row, ctx) : resolveLocalizedRowValueForMember(row, member, ctx);
60053
60073
  return shouldUnwrapSingleLookupValue(member) ? unwrapSingleLookupValue(value, ctx) : value;
@@ -60055,12 +60075,13 @@ function resolveValueIfId(at, ctx) {
60055
60075
  function resolveValueIfIdForMember(at, member, ctx) {
60056
60076
  if (typeof at !== "string") return at;
60057
60077
  const row = evalValueById(
60058
- ctx.vm,
60078
+ ctx,
60059
60079
  at,
60060
60080
  ctx.__runtimeSessionValues,
60061
60081
  ctx.__valueOverlay
60062
60082
  );
60063
60083
  if (!row) return at;
60084
+ ctx.valueDependencies?.add(row.id);
60064
60085
  const value = resolveLocalizedRowValueForMember(row, member, ctx);
60065
60086
  return shouldUnwrapSingleLookupValue(member) ? unwrapSingleLookupValue(value, ctx) : value;
60066
60087
  }
@@ -60072,12 +60093,15 @@ function shouldUnwrapSingleLookupValue(member) {
60072
60093
  function unwrapSingleLookupValue(value, ctx) {
60073
60094
  if (Array.isArray(value) && value.length === 1 && typeof value[0] === "string") {
60074
60095
  const next = evalValueById(
60075
- ctx.vm,
60096
+ ctx,
60076
60097
  value[0],
60077
60098
  ctx.__runtimeSessionValues,
60078
60099
  ctx.__valueOverlay
60079
60100
  );
60080
- if (next) return next.value;
60101
+ if (next) {
60102
+ ctx.valueDependencies?.add(next.id);
60103
+ return next.value;
60104
+ }
60081
60105
  }
60082
60106
  return value;
60083
60107
  }
@@ -60118,7 +60142,7 @@ function resolveMemberForValueRow(row, ctx, visited) {
60118
60142
  }
60119
60143
  for (const link of evaluatorParentLinks(indexes, row.id)) {
60120
60144
  const parent = evalValueById(
60121
- ctx.vm,
60145
+ ctx,
60122
60146
  link.parentId,
60123
60147
  ctx.__runtimeSessionValues,
60124
60148
  ctx.__valueOverlay
@@ -60443,7 +60467,7 @@ function evalDeclaredListIndex(info, scope, ctx) {
60443
60467
  for (const valueId of collection) {
60444
60468
  if (typeof valueId !== "string") continue;
60445
60469
  const row = evalValueById(
60446
- ctx.vm,
60470
+ ctx,
60447
60471
  valueId,
60448
60472
  ctx.__runtimeSessionValues,
60449
60473
  ctx.__valueOverlay
@@ -61028,7 +61052,7 @@ function applyConstructorFields(args) {
61028
61052
  const trackedValueId = findKnownRowIdByValueReference(value, ctx);
61029
61053
  if (trackedValueId !== null && isMemberClassBase(member)) {
61030
61054
  const source = evalValueById(
61031
- ctx.vm,
61055
+ ctx,
61032
61056
  trackedValueId,
61033
61057
  ctx.__runtimeSessionValues,
61034
61058
  ctx.__valueOverlay
@@ -61139,7 +61163,7 @@ function bindConstructedDelegateTargets(rootId, ctx) {
61139
61163
  if (rowId === void 0 || visited.has(rowId)) continue;
61140
61164
  visited.add(rowId);
61141
61165
  const row = evalValueById(
61142
- ctx.vm,
61166
+ ctx,
61143
61167
  rowId,
61144
61168
  ctx.__runtimeSessionValues,
61145
61169
  ctx.__valueOverlay
@@ -61171,7 +61195,7 @@ function bindConstructedDelegateTargets(rootId, ctx) {
61171
61195
  indexes
61172
61196
  )) {
61173
61197
  const ancestor = evalValueById(
61174
- ctx.vm,
61198
+ ctx,
61175
61199
  ancestorId,
61176
61200
  ctx.__runtimeSessionValues,
61177
61201
  ctx.__valueOverlay
@@ -62318,7 +62342,7 @@ function constructDeclaredClassValueWithinFrame(descriptor, record3, info, scope
62318
62342
  }
62319
62343
  function assertOwnedValueAttachable(valueId, destination, destinationName2, ctx, reserveUntilPublished = false) {
62320
62344
  const row = evalValueById(
62321
- ctx.vm,
62345
+ ctx,
62322
62346
  valueId,
62323
62347
  ctx.__runtimeSessionValues,
62324
62348
  ctx.__valueOverlay
@@ -62364,7 +62388,7 @@ function currentOwnedValueAttachments(valueId, ctx) {
62364
62388
  found.set(attachment.identity, attachment);
62365
62389
  };
62366
62390
  const row = evalValueById(
62367
- ctx.vm,
62391
+ ctx,
62368
62392
  valueId,
62369
62393
  ctx.__runtimeSessionValues,
62370
62394
  ctx.__valueOverlay
@@ -62401,7 +62425,7 @@ function currentOwnedValueAttachments(valueId, ctx) {
62401
62425
  );
62402
62426
  for (const parentId of parentIds) {
62403
62427
  const parent = evalValueById(
62404
- ctx.vm,
62428
+ ctx,
62405
62429
  parentId,
62406
62430
  ctx.__runtimeSessionValues,
62407
62431
  ctx.__valueOverlay
@@ -62469,7 +62493,7 @@ function constructorArgumentStorage(valueId, ctx, visiting = /* @__PURE__ */ new
62469
62493
  if (visiting.has(valueId)) return null;
62470
62494
  visiting.add(valueId);
62471
62495
  const row = evalValueById(
62472
- ctx.vm,
62496
+ ctx,
62473
62497
  valueId,
62474
62498
  ctx.__runtimeSessionValues,
62475
62499
  ctx.__valueOverlay
@@ -62491,7 +62515,7 @@ function constructorArgumentStorage(valueId, ctx, visiting = /* @__PURE__ */ new
62491
62515
  const parentIds = /* @__PURE__ */ new Set();
62492
62516
  for (const owner of currentOwnedValueAttachments(valueId, ctx)) {
62493
62517
  if (evalValueById(
62494
- ctx.vm,
62518
+ ctx,
62495
62519
  owner.label,
62496
62520
  ctx.__runtimeSessionValues,
62497
62521
  ctx.__valueOverlay
@@ -62601,7 +62625,7 @@ function cloneConstructorArgumentGraph(args) {
62601
62625
  args.ctx
62602
62626
  );
62603
62627
  const child = evalValueById(
62604
- args.ctx.vm,
62628
+ args.ctx,
62605
62629
  childId,
62606
62630
  args.ctx.__runtimeSessionValues,
62607
62631
  args.ctx.__valueOverlay
@@ -62637,7 +62661,7 @@ function cloneConstructorArgumentGraph(args) {
62637
62661
  );
62638
62662
  }
62639
62663
  const child = evalValueById(
62640
- args.ctx.vm,
62664
+ args.ctx,
62641
62665
  childId,
62642
62666
  args.ctx.__runtimeSessionValues,
62643
62667
  args.ctx.__valueOverlay
@@ -62684,7 +62708,7 @@ function cloneConstructorArgumentGraph(args) {
62684
62708
  );
62685
62709
  }
62686
62710
  const child = evalValueById(
62687
- args.ctx.vm,
62711
+ args.ctx,
62688
62712
  childId,
62689
62713
  args.ctx.__runtimeSessionValues,
62690
62714
  args.ctx.__valueOverlay
@@ -62726,7 +62750,7 @@ function materializeConstructorArgumentValue(args) {
62726
62750
  }
62727
62751
  if (trackedValueId !== null) {
62728
62752
  const tracked = evalValueById(
62729
- args.ctx.vm,
62753
+ args.ctx,
62730
62754
  trackedValueId,
62731
62755
  args.ctx.__runtimeSessionValues,
62732
62756
  args.ctx.__valueOverlay
@@ -62909,7 +62933,7 @@ function assertConstructorClassValueAdmitted(args) {
62909
62933
  function constructorCollectionEntryValue(value, ctx, resolveStoredId) {
62910
62934
  if (!resolveStoredId || typeof value !== "string") return value;
62911
62935
  const row = evalValueById(
62912
- ctx.vm,
62936
+ ctx,
62913
62937
  value,
62914
62938
  ctx.__runtimeSessionValues,
62915
62939
  ctx.__valueOverlay
@@ -62959,7 +62983,7 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
62959
62983
  );
62960
62984
  }
62961
62985
  const source = evalValueById(
62962
- ctx.vm,
62986
+ ctx,
62963
62987
  sourceId3,
62964
62988
  ctx.__runtimeSessionValues,
62965
62989
  ctx.__valueOverlay
@@ -63024,7 +63048,7 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
63024
63048
  const childTypeInfo = sourceTypeInfo?.type === 5 /* Dictionary */ ? sourceTypeInfo.entryTypeInfo : void 0;
63025
63049
  if (childMember === null && childTypeInfo === void 0) continue;
63026
63050
  const child = evalValueById(
63027
- ctx.vm,
63051
+ ctx,
63028
63052
  childId,
63029
63053
  ctx.__runtimeSessionValues,
63030
63054
  ctx.__valueOverlay
@@ -63045,7 +63069,7 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
63045
63069
  clone.value = sourceRow.value.map((childId) => {
63046
63070
  if (typeof childId !== "string") return childId;
63047
63071
  const child = evalValueById(
63048
- ctx.vm,
63072
+ ctx,
63049
63073
  childId,
63050
63074
  ctx.__runtimeSessionValues,
63051
63075
  ctx.__valueOverlay
@@ -63075,7 +63099,7 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
63075
63099
  }
63076
63100
  if (constructorArgumentReferenceCounts.get(argument2.id) !== 1) continue;
63077
63101
  const argumentRow = evalValueById(
63078
- ctx.vm,
63102
+ ctx,
63079
63103
  argument2.id,
63080
63104
  ctx.__runtimeSessionValues,
63081
63105
  ctx.__valueOverlay
@@ -63452,21 +63476,17 @@ function initializerEvaluatorLookups(document) {
63452
63476
  });
63453
63477
  return lookups;
63454
63478
  }
63455
- function buildInitializerRootValue(document) {
63479
+ function buildInitializerRootValue(document, lookups) {
63456
63480
  const rootValue = {};
63457
- const memberById = new Map(
63458
- document.members.map((member) => [member.id, member])
63459
- );
63460
- const valueById = new Map(document.values.map((row) => [row.id, row]));
63461
63481
  for (const { root, memberId } of projectRootMembersInDisplayOrder(
63462
63482
  document.project
63463
63483
  )) {
63464
- const member = memberById.get(memberId);
63465
- if (member === void 0 || typeof member.valueId !== "string") {
63484
+ const member = lookups.memberById(memberId);
63485
+ if (member === null || typeof member.valueId !== "string") {
63466
63486
  rootValue[root.key] = null;
63467
63487
  continue;
63468
63488
  }
63469
- rootValue[root.key] = valueById.get(member.valueId)?.value ?? null;
63489
+ rootValue[root.key] = lookups.valueById(member.valueId)?.value ?? null;
63470
63490
  }
63471
63491
  return rootValue;
63472
63492
  }
@@ -63479,6 +63499,7 @@ function evaluateMemberInitializer(args) {
63479
63499
  args.init
63480
63500
  );
63481
63501
  }
63502
+ const databaseVM = initializerEvaluatorLookups(args.document);
63482
63503
  const ctx = {
63483
63504
  vm: {
63484
63505
  project: args.document.project,
@@ -63492,10 +63513,10 @@ function evaluateMemberInitializer(args) {
63492
63513
  interfaces: args.document.interfaces,
63493
63514
  localizedTexts: args.document.localizedTexts,
63494
63515
  localizationConfig: args.document.localizationConfig,
63495
- databaseVM: initializerEvaluatorLookups(args.document)
63516
+ databaseVM
63496
63517
  },
63497
63518
  thisValue: null,
63498
- rootValue: buildInitializerRootValue(args.document),
63519
+ rootValue: buildInitializerRootValue(args.document, databaseVM),
63499
63520
  saveStaticBindings: args.saveStaticBindings,
63500
63521
  sessionStaticBindings: args.sessionStaticBindings,
63501
63522
  ...args.storedConstructionReplay === true ? {
@@ -84127,6 +84148,7 @@ function assertServerPreparationSucceeds(args) {
84127
84148
  prepared
84128
84149
  );
84129
84150
  }
84151
+ return prepared;
84130
84152
  } catch (error) {
84131
84153
  throw locateBodyCompileFailure(error, args.sourceByRecord);
84132
84154
  }
@@ -84344,7 +84366,7 @@ function replayStoredConstructionV4(args) {
84344
84366
  "Construction replay cannot compile document bodies without a compiler project."
84345
84367
  );
84346
84368
  }
84347
- compilePulledProjectDocumentBodiesV4(document, compilationProject);
84369
+ compilePulledProjectDocumentForEvaluationV4(document, compilationProject);
84348
84370
  }
84349
84371
  const root = document.values.find((value) => value.id === args.valueId);
84350
84372
  if (root === void 0) {
@@ -84540,7 +84562,16 @@ function compilePulledValueInitializerBodyV4(document, valueId, compilationProje
84540
84562
  ...compilationProject === void 0 ? {} : { compilationProject }
84541
84563
  });
84542
84564
  }
84543
- function compilePulledProjectDocumentBodiesV4(document, compilationProject) {
84565
+ function compilePulledProjectDocumentForEvaluationV4(document, compilationProject) {
84566
+ const sharedCompilationProject = compilationProject ?? createNeoScriptCompilationProject({
84567
+ project: document.project,
84568
+ projectFiles: document.projectFiles,
84569
+ members: document.members,
84570
+ classes: document.classes,
84571
+ enums: document.enums,
84572
+ interfaces: document.interfaces,
84573
+ constructors: document.constructors ?? []
84574
+ });
84544
84575
  const compileArgs = {
84545
84576
  project: document.project,
84546
84577
  projectFiles: document.projectFiles,
@@ -84549,7 +84580,7 @@ function compilePulledProjectDocumentBodiesV4(document, compilationProject) {
84549
84580
  enums: document.enums,
84550
84581
  interfaces: document.interfaces,
84551
84582
  constructors: document.constructors ?? [],
84552
- compilationProject
84583
+ compilationProject: sharedCompilationProject
84553
84584
  };
84554
84585
  for (const constructor2 of compileArgs.constructors) {
84555
84586
  compileConstructorRecord({ ...compileArgs, constructor: constructor2 });
@@ -84569,6 +84600,20 @@ function compilePulledProjectDocumentBodiesV4(document, compilationProject) {
84569
84600
  thisClass: ownerClassByMemberId.get(member.id) ?? null
84570
84601
  });
84571
84602
  }
84603
+ for (const site of valueInitializerCompilationSites(document).values()) {
84604
+ if (isInitValueContent(site.row) && site.row.init.compiled !== void 0) {
84605
+ continue;
84606
+ }
84607
+ compileValueRowInitializerBody({
84608
+ ...compileArgs,
84609
+ member: site.member,
84610
+ valueRow: site.row,
84611
+ valueId: String(Reflect.get(site.row, "id")),
84612
+ initializerOwnerClass: site.ownerClass,
84613
+ lexicalThisClass: site.lexicalThisClass,
84614
+ storedConstructionReplay: true
84615
+ });
84616
+ }
84572
84617
  }
84573
84618
  function assertPulledConstructorsCompiled(document) {
84574
84619
  const uncompiled = (document.constructors ?? []).find(
@@ -100088,6 +100133,7 @@ async function prepareLocalPushArtifactsV4(workspace, status, onPhase = () => vo
100088
100133
  status.changes,
100089
100134
  localizedTextCreateEnvelopeConfig2(workspace, status.changes)
100090
100135
  );
100136
+ let preparedChanges = null;
100091
100137
  if (options.fullValidation) {
100092
100138
  onPhase("Verifying the complete source round trip\u2026");
100093
100139
  verifyProjectSourceCommitAgainstStateV4({
@@ -100104,7 +100150,7 @@ async function prepareLocalPushArtifactsV4(workspace, status, onPhase = () => vo
100104
100150
  onPhase(
100105
100151
  `Rehearsing server validation for ${transportChanges.length.toLocaleString("en-US")} change(s)\u2026`
100106
100152
  );
100107
- assertServerPreparationSucceeds({
100153
+ preparedChanges = assertServerPreparationSucceeds({
100108
100154
  workspace,
100109
100155
  changes: transportChanges,
100110
100156
  authoredValueSeeds: transportSeeds,
@@ -100119,7 +100165,8 @@ async function prepareLocalPushArtifactsV4(workspace, status, onPhase = () => vo
100119
100165
  transactionOperation,
100120
100166
  transportChanges,
100121
100167
  transportSeeds,
100122
- preparedFiles
100168
+ preparedFiles,
100169
+ preparedChanges
100123
100170
  };
100124
100171
  }
100125
100172
  async function prepareLocalCandidateV4(workspace, options = {}) {
@@ -100193,8 +100240,23 @@ async function prepareLocalCandidateV4(workspace, options = {}) {
100193
100240
  if (typeof baseId === "string") {
100194
100241
  records2.delete(`${change.recordKind}:${baseId}`);
100195
100242
  }
100243
+ }
100244
+ const candidateChanges = preparedLocal?.preparedChanges ?? documentStatus.changes.map((change) => ({
100245
+ recordKind: change.recordKind,
100246
+ recordId: change.recordId,
100247
+ operation: change.kind,
100248
+ nextData: change.nextData
100249
+ }));
100250
+ for (const change of candidateChanges) {
100196
100251
  records2.delete(`${change.recordKind}:${change.recordId}`);
100197
- if (change.nextData === void 0) continue;
100252
+ if (change.operation === "delete" || change.nextData === void 0) {
100253
+ continue;
100254
+ }
100255
+ if (!isObjectRecord2(change.nextData)) {
100256
+ throw new Error(
100257
+ `Prepared ${change.recordKind} record ${JSON.stringify(change.recordId)} has invalid data.`
100258
+ );
100259
+ }
100198
100260
  const nextId = typeof change.nextData.id === "string" ? change.nextData.id : change.recordId;
100199
100261
  records2.set(`${change.recordKind}:${nextId}`, {
100200
100262
  recordKind: change.recordKind,
@@ -100204,9 +100266,11 @@ async function prepareLocalCandidateV4(workspace, options = {}) {
100204
100266
  data: change.nextData
100205
100267
  });
100206
100268
  }
100269
+ const document = readPulledProjectDocumentV4(records2);
100270
+ compilePulledProjectDocumentForEvaluationV4(document);
100207
100271
  return {
100208
100272
  status,
100209
- document: readPulledProjectDocumentV4(records2),
100273
+ document,
100210
100274
  sourceHash,
100211
100275
  preparedLocal
100212
100276
  };
@@ -101660,7 +101724,7 @@ var init_registry2 = __esm({
101660
101724
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
101661
101725
  formatVersion: 3,
101662
101726
  contractVersion: "3.9",
101663
- cliVersion: "0.24.7",
101727
+ cliVersion: "0.24.9",
101664
101728
  projectFileUploadBatchSize: 32,
101665
101729
  documentRecords: {
101666
101730
  member: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.24.7",
3
+ "version": "0.24.9",
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.24.7 -->
12
+ <!-- reviewed-through-cli: 0.24.9 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -30,6 +30,9 @@ Those are not part of format 4.
30
30
  existed before the task began.
31
31
  4. Run `neo test` after NeoScript changes and `neo dialogue dryrun <ref>` after
32
32
  dialogue changes.
33
+ `neo test` compiles the complete pending candidate, including idless nested
34
+ construction rows, so tests must work before the first push; do not add IDs
35
+ or push merely to obtain compiled initializer bodies.
33
36
  5. Run `neo push --dry-run` before every real push. It performs the full local
34
37
  source emission, ID-assignment, transport-shape, hash, and repeat-verification path,
35
38
  then rehearses the server's preparation phase — schema-commit
@@ -127,6 +127,10 @@ Use `NeoAnimationSegment<T>` for a frame-indexed value lane. The shipped
127
127
  sprite specialization is `NeoSpriteAnimationSegment`, whose
128
128
  `NeoAnimationSegmentFrame<SpriteInfo>` rows each provide `Index` and
129
129
  `Value`. Sparse frame values hold until the next row or `Duration`.
130
+ Pass `Value` through the frame constructor (for example,
131
+ `new NeoAnimationSegmentFrame<int>(value: 60)`). The constructor argument is
132
+ the frame's authored value; it must not collapse to the concrete generic
133
+ binding's fallback while the segment is materialized.
130
134
 
131
135
  Use one polymorphic `NeoAnimationClip.Tracks` list:
132
136
 
@@ -82,7 +82,7 @@ wrappers.
82
82
  The marker near the top of `SKILL.md` must exactly match the package version:
83
83
 
84
84
  ```html
85
- <!-- reviewed-through-cli: 0.24.7 -->
85
+ <!-- reviewed-through-cli: 0.24.9 -->
86
86
  ```
87
87
 
88
88
  The quoted version above is checked too, so this instruction cannot go stale