@neocompose/cli 0.24.1 → 0.24.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,40 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.24.3] - 2026-08-07
4
+
5
+ ### Fixed
6
+
7
+ - Close generic classes constructed by normal member-default evaluation from
8
+ the concrete member slot, so local candidate preparation no longer rejects
9
+ values such as `NeoAnimationSegmentFrame<int>` as open generics before
10
+ `neo test` can discover or execute tests.
11
+ - Key compiled spec artifacts by the prepared candidate document as well as
12
+ source, preventing stale pending class and enum IDs from leaking across
13
+ repeated `neo test` runs.
14
+
15
+ ### Changed
16
+
17
+ - Require full-project `neo test` validation in the bundled CLI development
18
+ guidance when evaluator or candidate-materialization behavior changes.
19
+
20
+ ## [0.24.2] - 2026-08-07
21
+
22
+ ### Fixed
23
+
24
+ - Compile selectors on newly authored nested track rows with the lexical class
25
+ that declares the clip, including idless rows, explicit UUID rows, and
26
+ default rows copied into an instance graph.
27
+ - Preserve same-pass default-row provenance and initializer-backed rows while
28
+ assembling authored seeds, instead of losing the source owner or replacing
29
+ an initializer with an undefined literal.
30
+ - Accept compiled selector delegates in trusted static-value graph validation,
31
+ so server preparation agrees with P60 track construction.
32
+
33
+ ### Changed
34
+
35
+ - Clarify in the bundled CLI skill that `this` in a track selector refers to
36
+ the class declaring the clip, not the nested track or a receiving instance.
37
+
3
38
  ## [0.24.1] - 2026-08-07
4
39
 
5
40
  ### Fixed
package/dist/neo.mjs CHANGED
@@ -53791,11 +53791,12 @@ function compileNSInitializer(code, ctx) {
53791
53791
  );
53792
53792
  }
53793
53793
  try {
53794
+ const { lexicalThisClass, ...compilerContext } = ctx;
53794
53795
  return compileStrict(
53795
53796
  `return
53796
53797
  ${code};`,
53797
53798
  createContext(
53798
- { ...ctx, thisClass: null },
53799
+ { ...compilerContext, thisClass: lexicalThisClass ?? null },
53799
53800
  {
53800
53801
  scriptKind: "initializer",
53801
53802
  returnTypeInfo: ctx.returnTypeInfo,
@@ -53968,6 +53969,37 @@ var init_compiler_adapter = __esm({
53968
53969
  });
53969
53970
 
53970
53971
  // ../src/database/compile-ns-property.ts
53972
+ function initializerReferencedIdentifiers(source) {
53973
+ let expression;
53974
+ try {
53975
+ expression = parseExpression(source);
53976
+ } catch {
53977
+ return /* @__PURE__ */ new Set();
53978
+ }
53979
+ const identifiers = /* @__PURE__ */ new Set();
53980
+ const pending = [expression];
53981
+ const visited = /* @__PURE__ */ new Set();
53982
+ while (pending.length > 0) {
53983
+ const value = pending.pop();
53984
+ if (value === null || typeof value !== "object" || visited.has(value)) {
53985
+ continue;
53986
+ }
53987
+ visited.add(value);
53988
+ if (Reflect.get(value, "kind") === "ident") {
53989
+ const name = Reflect.get(value, "name");
53990
+ if (typeof name === "string") identifiers.add(name);
53991
+ }
53992
+ for (const child of Object.values(value)) pending.push(child);
53993
+ }
53994
+ return identifiers;
53995
+ }
53996
+ function initializerReferencesLexicalThis(source) {
53997
+ return initializerReferencedIdentifiers(source).has("this");
53998
+ }
53999
+ function initializerReferencesAnyIdentifier(source, names) {
54000
+ const identifiers = initializerReferencedIdentifiers(source);
54001
+ return [...names].some((name) => identifiers.has(name));
54002
+ }
53971
54003
  function compileNSPropertyBodies(args) {
53972
54004
  if (args.member.kind !== 10 /* NSProperty */) return;
53973
54005
  if (isMemberNSPropertyContractBase(args.member)) return;
@@ -54221,6 +54253,7 @@ function compileValueRowInitializerBody(args) {
54221
54253
  constructors: args.constructors ?? [],
54222
54254
  returnTypeInfo,
54223
54255
  initializerName: args.member.name,
54256
+ lexicalThisClass: args.lexicalThisClass ?? null,
54224
54257
  argumentTypes: initializerArgumentTypes(
54225
54258
  args.initializerOwnerClass,
54226
54259
  args.constructors ?? []
@@ -54775,6 +54808,7 @@ var init_compile_ns_property = __esm({
54775
54808
  init_lookup_declared_type();
54776
54809
  init_compiler_adapter();
54777
54810
  init_compiler_adapter();
54811
+ init_src();
54778
54812
  NeoScriptBodyCompileError = class extends Error {
54779
54813
  memberId;
54780
54814
  memberName;
@@ -54797,6 +54831,41 @@ var init_compile_ns_property = __esm({
54797
54831
  });
54798
54832
 
54799
54833
  // ../src/database/value-row-owner-members.ts
54834
+ function valueIdsWithSourceChains(targetValueIds, valuesById) {
54835
+ const result = new Set(targetValueIds);
54836
+ for (const targetId of targetValueIds) {
54837
+ const visited = /* @__PURE__ */ new Set();
54838
+ let currentId = targetId;
54839
+ while (currentId !== null && !visited.has(currentId)) {
54840
+ visited.add(currentId);
54841
+ result.add(currentId);
54842
+ const sourceValueId = valuesById.get(currentId)?.sourceValueId;
54843
+ currentId = typeof sourceValueId === "string" ? sourceValueId : null;
54844
+ }
54845
+ }
54846
+ return result;
54847
+ }
54848
+ function initializerOwnerContext(document, valueId, rootOwners, valuesById) {
54849
+ const visited = /* @__PURE__ */ new Set();
54850
+ let currentId = valueId;
54851
+ let lexicalRoot = rootOwners.get(valueId);
54852
+ while (currentId !== null && !visited.has(currentId)) {
54853
+ visited.add(currentId);
54854
+ const sourceValueId = valuesById.get(currentId)?.sourceValueId;
54855
+ if (typeof sourceValueId !== "string") break;
54856
+ currentId = sourceValueId;
54857
+ lexicalRoot = rootOwners.get(sourceValueId) ?? lexicalRoot;
54858
+ }
54859
+ if (lexicalRoot === void 0) {
54860
+ return { ownerClass: null, lexicalThisClass: null };
54861
+ }
54862
+ const lexicalRootId = getField(lexicalRoot, "id");
54863
+ const ownerClass = typeof lexicalRootId === "string" ? findSchemaPlacement(lexicalRootId, document.classes)?.ownerClass ?? null : null;
54864
+ return {
54865
+ ownerClass,
54866
+ lexicalThisClass: lexicalRoot.isStatic === true ? null : ownerClass
54867
+ };
54868
+ }
54800
54869
  function isRecordValue(value) {
54801
54870
  if (value === null) return false;
54802
54871
  if (typeof value !== "object") return false;
@@ -60695,8 +60764,8 @@ function validateClassConstructorDescriptor(info, ctx, requireEveryRequiredField
60695
60764
  `Cannot construct abstract Class '${schemaClass2.name}'.`
60696
60765
  );
60697
60766
  }
60698
- const replaySlot = ctx.__storedConstructionReplayNestedSlots?.toReversed().find((slot) => slot.classId === classId) ?? ctx.__storedConstructionReplaySlot;
60699
- const classArguments2 = replaySlot?.classId === classId ? replaySlot.classArguments : void 0;
60767
+ const genericSlot = ctx.__constructionGenericSlots?.toReversed().find((slot) => slot.classId === classId) ?? ctx.__storedConstructionReplaySlot;
60768
+ const classArguments2 = genericSlot?.classId === classId ? genericSlot.classArguments : void 0;
60700
60769
  const instanceEnv = resolveInstanceEnv(
60701
60770
  classId,
60702
60771
  classArguments2,
@@ -61552,7 +61621,7 @@ function constructionInitEvaluator(ctx, createdValues, argumentScopes, construct
61552
61621
  };
61553
61622
  return (member, init, sourceValueId) => {
61554
61623
  const evaluate = (argumentValues = []) => {
61555
- if (ctx.storedConstructionReplay !== true || !isMemberClassBase(member) || Object.keys(member.classArguments ?? {}).length === 0) {
61624
+ if (!isMemberClassBase(member) || Object.keys(member.classArguments ?? {}).length === 0) {
61556
61625
  return evaluateInitializerInContext(
61557
61626
  init,
61558
61627
  member,
@@ -61562,8 +61631,8 @@ function constructionInitEvaluator(ctx, createdValues, argumentScopes, construct
61562
61631
  sourceValueId ?? null
61563
61632
  );
61564
61633
  }
61565
- const previousSlots = ctx.__storedConstructionReplayNestedSlots;
61566
- ctx.__storedConstructionReplayNestedSlots = [
61634
+ const previousSlots = ctx.__constructionGenericSlots;
61635
+ ctx.__constructionGenericSlots = [
61567
61636
  ...previousSlots ?? [],
61568
61637
  {
61569
61638
  classId: member.classId,
@@ -61580,7 +61649,7 @@ function constructionInitEvaluator(ctx, createdValues, argumentScopes, construct
61580
61649
  sourceValueId ?? null
61581
61650
  );
61582
61651
  } finally {
61583
- ctx.__storedConstructionReplayNestedSlots = previousSlots;
61652
+ ctx.__constructionGenericSlots = previousSlots;
61584
61653
  }
61585
61654
  };
61586
61655
  if (init.compiled === void 0) {
@@ -63335,7 +63404,11 @@ function evaluateMemberInitializer(args) {
63335
63404
  __constructedArgumentsByValue: /* @__PURE__ */ new WeakMap(),
63336
63405
  __createdStorageKeyDeclarations: args.storageKeyDeclarations ?? /* @__PURE__ */ new Map()
63337
63406
  };
63338
- const result = evaluateNSGetterWithEffects(compiled, ctx);
63407
+ const result = evaluateNSGetterWithEffects(
63408
+ compiled,
63409
+ ctx,
63410
+ args.argumentValues ?? []
63411
+ );
63339
63412
  const created = result.createdSessionValues ?? [];
63340
63413
  if (isMemberLookupBase(args.member)) {
63341
63414
  return encodeLookupInitializerResult(
@@ -63390,7 +63463,8 @@ function evaluateInitializerMaterialization(args) {
63390
63463
  document: args.document,
63391
63464
  createdValues,
63392
63465
  storageKeyDeclarations,
63393
- ...args.storedConstructionReplay === true ? { storedConstructionReplay: true } : {}
63466
+ ...args.storedConstructionReplay === true ? { storedConstructionReplay: true } : {},
63467
+ ...args.argumentValues === void 0 ? {} : { argumentValues: args.argumentValues }
63394
63468
  });
63395
63469
  return { evaluated, createdValues, storageKeyDeclarations };
63396
63470
  }
@@ -63399,7 +63473,8 @@ function materializeInitializerValue(args) {
63399
63473
  init: args.row.init,
63400
63474
  member: args.member,
63401
63475
  document: args.document,
63402
- ...args.storedConstructionReplay === true ? { storedConstructionReplay: true } : {}
63476
+ ...args.storedConstructionReplay === true ? { storedConstructionReplay: true } : {},
63477
+ ...args.argumentValues === void 0 ? {} : { argumentValues: args.argumentValues }
63403
63478
  });
63404
63479
  const {
63405
63480
  init: _init,
@@ -63414,6 +63489,9 @@ function materializeInitializerValue(args) {
63414
63489
  ...evaluated.constructorArgs === void 0 ? {} : { constructorArgs: structuredClone(evaluated.constructorArgs) }
63415
63490
  };
63416
63491
  const allCreated = [root, ...createdValues];
63492
+ for (const created of createdValues) {
63493
+ if (created.classId === void 0) delete created.classId;
63494
+ }
63417
63495
  stampCreatedValuesMapKey(allCreated, args.row.mapKey);
63418
63496
  storageKeyDeclarations.delete(root.id);
63419
63497
  applyDeclaredStorageKeyOverrides({
@@ -77011,6 +77089,12 @@ var init_project_version_static_value_writes = __esm({
77011
77089
  this.validateDialogueLookup(member, value, path);
77012
77090
  return;
77013
77091
  }
77092
+ if (isMemberDelegateBase(member)) {
77093
+ if (!isNSDelegateValue(value.value)) {
77094
+ throw new Error(`${path} must store a valid NeoDelegate value.`);
77095
+ }
77096
+ return;
77097
+ }
77014
77098
  if (isMemberClassBase(member)) {
77015
77099
  this.validateClass({ ...args, member, value });
77016
77100
  return;
@@ -80201,17 +80285,21 @@ function prepareServerOwnedValueInitializerBodies(args) {
80201
80285
  ...[...explicitRows.values()].map((row) => row.id),
80202
80286
  ...sweepRows.map((row) => row.id)
80203
80287
  ]);
80288
+ const valuesById = new Map(
80289
+ committedDocument.values.map((value) => [value.id, value])
80290
+ );
80291
+ const ownershipTargetIds = valueIdsWithSourceChains(targetIds, valuesById);
80204
80292
  const rootOwnerByValueId = /* @__PURE__ */ new Map();
80205
80293
  const ownerByValueId = resolveOwnerMembersForValues(
80206
80294
  committedDocument,
80207
- targetIds,
80295
+ ownershipTargetIds,
80208
80296
  void 0,
80209
80297
  rootOwnerByValueId
80210
80298
  );
80211
80299
  const currentValueById = new Map(
80212
80300
  args.document.values.map((value) => [value.id, value])
80213
80301
  );
80214
- const compileOne = (document, row) => {
80302
+ const compileOne = (document, row, documentValuesById) => {
80215
80303
  const member = ownerByValueId.get(row.id);
80216
80304
  if (member === void 0) {
80217
80305
  throw new Error(
@@ -80220,6 +80308,12 @@ function prepareServerOwnedValueInitializerBodies(args) {
80220
80308
  }
80221
80309
  const currentValue = currentValueById.get(row.id);
80222
80310
  const replaysStoredConstruction = isLiteralValueContent(currentValue) && (typeof currentValue.classId === "string" || currentValue.constructorArgs !== void 0);
80311
+ const ownerContext = initializerOwnerContext(
80312
+ document,
80313
+ row.id,
80314
+ rootOwnerByValueId,
80315
+ documentValuesById
80316
+ );
80223
80317
  compileValueRowInitializerBody({
80224
80318
  project: document.project,
80225
80319
  projectFiles: document.projectFiles,
@@ -80231,16 +80325,14 @@ function prepareServerOwnedValueInitializerBodies(args) {
80231
80325
  member,
80232
80326
  valueRow: row,
80233
80327
  valueId: row.id,
80234
- initializerOwnerClass: findSchemaPlacement(
80235
- rootOwnerByValueId.get(row.id)?.id ?? "",
80236
- document.classes
80237
- )?.ownerClass ?? null,
80328
+ initializerOwnerClass: ownerContext.ownerClass,
80329
+ lexicalThisClass: initializerReferencesLexicalThis(row.init.code) ? ownerContext.lexicalThisClass : null,
80238
80330
  ...replaysStoredConstruction ? { storedConstructionReplay: true } : {}
80239
80331
  });
80240
80332
  };
80241
80333
  for (const [index, row] of explicitRows) {
80242
80334
  const compiled = { ...row, init: { ...row.init } };
80243
- compileOne(committedDocument, compiled);
80335
+ compileOne(committedDocument, compiled, valuesById);
80244
80336
  const change = args.prepared[index];
80245
80337
  if (change === void 0) continue;
80246
80338
  args.prepared[index] = { ...change, nextData: compiled };
@@ -80255,14 +80347,14 @@ function prepareServerOwnedValueInitializerBodies(args) {
80255
80347
  for (const row of sweepRows) {
80256
80348
  const compiled = { ...row, init: { ...row.init } };
80257
80349
  try {
80258
- compileOne(committedDocument, compiled);
80350
+ compileOne(committedDocument, compiled, valuesById);
80259
80351
  } catch (postWriteError) {
80260
80352
  const current2 = currentById.get(row.id);
80261
80353
  if (current2 === void 0) throw postWriteError;
80262
80354
  const preWrite = initBackedValueRow(structuredClone(current2));
80263
80355
  if (preWrite === null) throw postWriteError;
80264
80356
  try {
80265
- compileOne(args.document, preWrite);
80357
+ compileOne(args.document, preWrite, currentValueById);
80266
80358
  } catch (preWriteError) {
80267
80359
  if (sameCompileFailure(preWriteError, postWriteError)) continue;
80268
80360
  }
@@ -82833,9 +82925,16 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
82833
82925
  if (initializers.length === 0) return document;
82834
82926
  const rootKinds = /* @__PURE__ */ new Map();
82835
82927
  const rootOwners = /* @__PURE__ */ new Map();
82928
+ const valuesById = new Map(
82929
+ document.values.map((value) => [value.id, value])
82930
+ );
82931
+ const ownershipTargetIds = valueIdsWithSourceChains(
82932
+ new Set(initializers.map(({ row }) => row.id)),
82933
+ valuesById
82934
+ );
82836
82935
  const owners = resolveOwnerMembersForValues(
82837
82936
  document,
82838
- new Set(initializers.map(({ row }) => row.id)),
82937
+ ownershipTargetIds,
82839
82938
  void 0,
82840
82939
  rootOwners,
82841
82940
  rootKinds
@@ -82879,10 +82978,24 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
82879
82978
  if (!classBelongsToAnimationFamily(document.classes, declaredClassId)) {
82880
82979
  continue;
82881
82980
  }
82882
- const rootOwner = rootOwners.get(row.id);
82883
- const rootOwnerId = Reflect.get(rootOwner ?? {}, "id");
82884
- const initializerOwnerClass = typeof rootOwnerId !== "string" ? null : findSchemaPlacement(rootOwnerId, document.classes)?.ownerClass ?? null;
82885
- const evaluate = initializerOwnerClass?.requiredConstructorId === void 0 || initializerOwnerClass.requiredConstructorId === null;
82981
+ const fallback = fallbackValues.get(row.id);
82982
+ const ownerContext = initializerOwnerContext(
82983
+ document,
82984
+ row.id,
82985
+ rootOwners,
82986
+ valuesById
82987
+ );
82988
+ const initializerOwnerClass = ownerContext.ownerClass;
82989
+ const requiredConstructor = initializerOwnerClass?.requiredConstructorId === void 0 || initializerOwnerClass.requiredConstructorId === null ? void 0 : (replayDocument.constructors ?? []).find(
82990
+ (constructor2) => constructor2.id === initializerOwnerClass.requiredConstructorId
82991
+ );
82992
+ const requiredArgumentNames = new Set(
82993
+ requiredConstructor?.argumentTypes.map((argument2) => argument2.name) ?? []
82994
+ );
82995
+ const evaluate = !initializerReferencesAnyIdentifier(
82996
+ code,
82997
+ requiredArgumentNames
82998
+ );
82886
82999
  let replay;
82887
83000
  try {
82888
83001
  replay = replayStoredConstructionV4({
@@ -82894,9 +83007,15 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
82894
83007
  compileDocumentBodies: !documentBodiesCompiled,
82895
83008
  compilationProject,
82896
83009
  initializerOwnerClass,
82897
- // A parameterized declaration is a template. Its arguments exist only
82898
- // at concrete construction sites, so validate the authored body here
82899
- // without fabricating values for the class header parameters.
83010
+ lexicalThisClass: ownerContext.lexicalThisClass,
83011
+ ...requiredConstructor === void 0 || !evaluate ? {} : {
83012
+ initializerArgumentValues: requiredConstructor.argumentTypes.map(
83013
+ () => null
83014
+ )
83015
+ },
83016
+ // A parameterized declaration is a template. Replay it only when this
83017
+ // row does not read those parameters; null placeholders satisfy the
83018
+ // unused compiler envelope without inventing authored values.
82900
83019
  evaluate
82901
83020
  });
82902
83021
  documentBodiesCompiled = true;
@@ -82907,7 +83026,6 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
82907
83026
  );
82908
83027
  }
82909
83028
  if (!evaluate) {
82910
- const fallback = fallbackValues.get(row.id);
82911
83029
  if (fallback !== void 0) values.set(row.id, fallback);
82912
83030
  }
82913
83031
  for (const [id2, value] of replay) {
@@ -83292,7 +83410,6 @@ var init_workspace_status_core = __esm({
83292
83410
  init_project_documents();
83293
83411
  init_animation_clips();
83294
83412
  init_classes();
83295
- init_inheritance();
83296
83413
  init_members();
83297
83414
  init_value_row_owner_members();
83298
83415
  init_project2();
@@ -83300,6 +83417,7 @@ var init_workspace_status_core = __esm({
83300
83417
  init_push_change_intent();
83301
83418
  init_initializer_replay();
83302
83419
  init_compiler_adapter();
83420
+ init_compile_ns_property();
83303
83421
  init_materialized_construction_cache();
83304
83422
  init_project_version_whole_graph_validation();
83305
83423
  }
@@ -84164,6 +84282,7 @@ function replayStoredConstructionV4(args) {
84164
84282
  // Instance calls are self-contained. Declaration calls inherit the class
84165
84283
  // header parameters that are in lexical scope at their source site.
84166
84284
  initializerOwnerClass: args.initializerOwnerClass ?? null,
84285
+ lexicalThisClass: initializerReferencesLexicalThis(args.code) ? args.lexicalThisClass ?? null : null,
84167
84286
  storedConstructionReplay: true,
84168
84287
  ...compilationProject === void 0 ? {} : { compilationProject }
84169
84288
  });
@@ -84185,7 +84304,8 @@ function replayStoredConstructionV4(args) {
84185
84304
  // explicit typed descriptor for evaluation that compiled the replay.
84186
84305
  member: compileMember,
84187
84306
  row: candidate,
84188
- storedConstructionReplay: true
84307
+ storedConstructionReplay: true,
84308
+ ...args.initializerArgumentValues === void 0 ? {} : { argumentValues: args.initializerArgumentValues }
84189
84309
  });
84190
84310
  break;
84191
84311
  } catch (error) {
@@ -84248,10 +84368,17 @@ function valueInitializerCompilationSites(document) {
84248
84368
  const cached = pulledValueInitializerCompilationSites.get(document);
84249
84369
  if (cached !== void 0) return cached;
84250
84370
  const rows = document.values.filter(isInitValueContent);
84371
+ const valuesById = new Map(
84372
+ document.values.map((value) => [value.id, value])
84373
+ );
84374
+ const ownershipTargetIds = valueIdsWithSourceChains(
84375
+ new Set(rows.map((row) => row.id)),
84376
+ valuesById
84377
+ );
84251
84378
  const rootOwners = /* @__PURE__ */ new Map();
84252
84379
  const owners = resolveOwnerMembersForValues(
84253
84380
  document,
84254
- new Set(rows.map((row) => row.id)),
84381
+ ownershipTargetIds,
84255
84382
  void 0,
84256
84383
  rootOwners
84257
84384
  );
@@ -84259,11 +84386,17 @@ function valueInitializerCompilationSites(document) {
84259
84386
  for (const row of rows) {
84260
84387
  const member = owners.get(row.id);
84261
84388
  if (member === void 0) continue;
84262
- const rootOwnerId = Reflect.get(rootOwners.get(row.id) ?? {}, "id");
84389
+ const ownerContext = initializerOwnerContext(
84390
+ document,
84391
+ row.id,
84392
+ rootOwners,
84393
+ valuesById
84394
+ );
84263
84395
  sites.set(row.id, {
84264
84396
  row,
84265
84397
  member,
84266
- ownerClass: typeof rootOwnerId !== "string" ? null : findSchemaPlacement(rootOwnerId, document.classes)?.ownerClass ?? null
84398
+ ownerClass: ownerContext.ownerClass,
84399
+ lexicalThisClass: ownerContext.lexicalThisClass
84267
84400
  });
84268
84401
  }
84269
84402
  pulledValueInitializerCompilationSites.set(document, sites);
@@ -84288,6 +84421,7 @@ function compilePulledValueInitializerBodyV4(document, valueId, compilationProje
84288
84421
  valueRow: site.row,
84289
84422
  valueId: String(Reflect.get(site.row, "id")),
84290
84423
  initializerOwnerClass: site.ownerClass,
84424
+ lexicalThisClass: site.lexicalThisClass,
84291
84425
  storedConstructionReplay: true,
84292
84426
  ...compilationProject === void 0 ? {} : { compilationProject }
84293
84427
  });
@@ -84444,7 +84578,6 @@ var init_initializer_replay = __esm({
84444
84578
  init_compile_ns_property();
84445
84579
  init_init_backed_value_materialization();
84446
84580
  init_value_row_owner_members();
84447
- init_inheritance();
84448
84581
  init_project_document_read();
84449
84582
  init_localization2();
84450
84583
  init_server_preparation_preflight();
@@ -85888,11 +86021,9 @@ function staticValueSeedRow(value, loweredMemberId) {
85888
86021
  if (loweredMemberId === void 0) {
85889
86022
  throw new Error(`Authored value row ${id2} is missing memberId.`);
85890
86023
  }
85891
- return {
86024
+ const fields = {
85892
86025
  id: id2,
85893
86026
  memberId: loweredMemberId,
85894
- value: value.value,
85895
- classId: stringOrNull(value.classId),
85896
86027
  ...typeof value.containerId === "string" ? { containerId: value.containerId } : {},
85897
86028
  ...isObjectRecord2(value.genericBindings) ? {
85898
86029
  genericBindings: Object.fromEntries(
@@ -85903,6 +86034,15 @@ function staticValueSeedRow(value, loweredMemberId) {
85903
86034
  } : {},
85904
86035
  ...typeof value.sourceValueId === "string" ? { sourceValueId: value.sourceValueId } : {}
85905
86036
  };
86037
+ const init = isObjectRecord2(value.init) ? value.init : null;
86038
+ if (init !== null && typeof init.code === "string") {
86039
+ return { ...fields, init: { code: init.code } };
86040
+ }
86041
+ return {
86042
+ ...fields,
86043
+ value: value.value,
86044
+ classId: stringOrNull(value.classId)
86045
+ };
85906
86046
  }
85907
86047
  function preserveReboundValue(context, currentValueId, nextValueId, binding) {
85908
86048
  if (currentValueId === null || currentValueId === nextValueId) return;
@@ -86300,14 +86440,24 @@ function materializedRowStamp(context, materialization) {
86300
86440
  if (materialization === void 0) return null;
86301
86441
  const rowId = materialization.rowId;
86302
86442
  if (rowId === null) return null;
86303
- const forwarded = valueData(context, rowId)?.sourceValueId;
86443
+ const forwarded = materializationSourceValueData(
86444
+ context,
86445
+ rowId
86446
+ )?.sourceValueId;
86304
86447
  return stringOrNull(forwarded) ?? rowId;
86305
86448
  }
86449
+ function materializationSourceValueData(context, valueId) {
86450
+ if (context.pendingValues.has(valueId)) return valueData(context, valueId);
86451
+ return context.reconstructed.get(`value:${valueId}`)?.fileFields ?? valueData(context, valueId);
86452
+ }
86306
86453
  function materializedChild(context, materialization, key) {
86307
86454
  if (materialization === void 0) return void 0;
86308
86455
  const rowId = defaultChildRowId(materialization.body, key);
86309
86456
  if (rowId === null) return { rowId: null, body: void 0 };
86310
- return { rowId, body: valueData(context, rowId)?.value };
86457
+ return {
86458
+ rowId,
86459
+ body: materializationSourceValueData(context, rowId)?.value
86460
+ };
86311
86461
  }
86312
86462
  function defaultChildRowId(body, key) {
86313
86463
  if (typeof key === "number") {
@@ -101396,7 +101546,7 @@ var init_registry2 = __esm({
101396
101546
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
101397
101547
  formatVersion: 3,
101398
101548
  contractVersion: "3.9",
101399
- cliVersion: "0.24.1",
101549
+ cliVersion: "0.24.3",
101400
101550
  projectFileUploadBatchSize: 32,
101401
101551
  documentRecords: {
101402
101552
  member: {
@@ -102927,7 +103077,7 @@ function preparedHookCandidate(workspace) {
102927
103077
  );
102928
103078
  }
102929
103079
  }
102930
- function compileSpec(workspace, document, absolutePath, projectSourceHash) {
103080
+ function compileSpec(workspace, document, absolutePath, projectCompilationHash2) {
102931
103081
  const scriptDocument = readDocumentArrays(document);
102932
103082
  const path = relative6(workspace.root, absolutePath).split(sep6).join("/");
102933
103083
  const source = readFileSync17(absolutePath, "utf8");
@@ -102937,12 +103087,12 @@ function compileSpec(workspace, document, absolutePath, projectSourceHash) {
102937
103087
  ".neo",
102938
103088
  "test-build",
102939
103089
  "v1",
102940
- projectSourceHash,
103090
+ projectCompilationHash2,
102941
103091
  `${sourceHash}.json`
102942
103092
  );
102943
103093
  try {
102944
103094
  const cached = JSON.parse(readFileSync17(artifactPath, "utf8"));
102945
- if (isRecord10(cached) && cached.version === 1 && cached.compilerRevision === NEOSCRIPT_COMPILER_REVISION && cached.projectSourceHash === projectSourceHash && cached.sourceHash === sourceHash && isRecord10(cached.action) && typeof cached.artifactSha256 === "string" && createHash10("sha256").update(JSON.stringify(cached.action)).digest("hex") === cached.artifactSha256 && cached.action.compilerRevision === NEOSCRIPT_COMPILER_REVISION && Array.isArray(cached.action.parameters) && Array.isArray(cached.action.instructions) && isRecord10(cached.action.typeInfo)) {
103095
+ if (isRecord10(cached) && cached.version === 1 && cached.compilerRevision === NEOSCRIPT_COMPILER_REVISION && cached.projectCompilationHash === projectCompilationHash2 && cached.sourceHash === sourceHash && isRecord10(cached.action) && typeof cached.artifactSha256 === "string" && createHash10("sha256").update(JSON.stringify(cached.action)).digest("hex") === cached.artifactSha256 && cached.action.compilerRevision === NEOSCRIPT_COMPILER_REVISION && Array.isArray(cached.action.parameters) && Array.isArray(cached.action.instructions) && isRecord10(cached.action.typeInfo)) {
102946
103096
  return {
102947
103097
  path,
102948
103098
  source,
@@ -102972,7 +103122,7 @@ function compileSpec(workspace, document, absolutePath, projectSourceHash) {
102972
103122
  `${JSON.stringify({
102973
103123
  version: 1,
102974
103124
  compilerRevision: NEOSCRIPT_COMPILER_REVISION,
102975
- projectSourceHash,
103125
+ projectCompilationHash: projectCompilationHash2,
102976
103126
  sourceHash,
102977
103127
  artifactSha256: createHash10("sha256").update(JSON.stringify(compiled.action)).digest("hex"),
102978
103128
  action: compiled.action
@@ -102981,6 +103131,9 @@ function compileSpec(workspace, document, absolutePath, projectSourceHash) {
102981
103131
  );
102982
103132
  return compiled;
102983
103133
  }
103134
+ function projectCompilationHash(projectSourceHash, document) {
103135
+ return createHash10("sha256").update(projectSourceHash).update("\0").update(JSON.stringify(document)).digest("hex");
103136
+ }
102984
103137
  function selectedSpecPaths(workspace, selectors) {
102985
103138
  const all = listProjectTestFilesV1(workspace.root);
102986
103139
  const relativePaths = new Map(
@@ -103856,6 +104009,10 @@ async function runTest(workspace, options, dependencies = {}) {
103856
104009
  }
103857
104010
  projectFingerprint = `sha256:${candidate.sourceHash}`;
103858
104011
  const rawDocument = documentRecord(candidate.document);
104012
+ const compilationHash = projectCompilationHash(
104013
+ candidate.sourceHash,
104014
+ rawDocument
104015
+ );
103859
104016
  phase = "select";
103860
104017
  let selectedPaths;
103861
104018
  try {
@@ -103873,7 +104030,7 @@ async function runTest(workspace, options, dependencies = {}) {
103873
104030
  }
103874
104031
  phase = "compile";
103875
104032
  specs = selectedPaths.map(
103876
- (path) => compileSpec(workspace, rawDocument, path, candidate.sourceHash)
104033
+ (path) => compileSpec(workspace, rawDocument, path, compilationHash)
103877
104034
  );
103878
104035
  let pattern = null;
103879
104036
  if (options.testNamePattern !== null) {
@@ -104066,10 +104223,14 @@ async function inspectNeoTestCompilation(workspace, dependencies = {}) {
104066
104223
  };
104067
104224
  }
104068
104225
  const document = documentRecord(candidate.document);
104226
+ const compilationHash = projectCompilationHash(
104227
+ candidate.sourceHash,
104228
+ document
104229
+ );
104069
104230
  const errors = [];
104070
104231
  for (const path of selectedPaths) {
104071
104232
  try {
104072
- compileSpec(workspace, document, path, candidate.sourceHash);
104233
+ compileSpec(workspace, document, path, compilationHash);
104073
104234
  } catch (error) {
104074
104235
  errors.push({
104075
104236
  file: relative6(workspace.root, path).split(sep6).join("/"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.24.1",
3
+ "version": "0.24.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.24.1 -->
12
+ <!-- reviewed-through-cli: 0.24.3 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -178,6 +178,11 @@ row-ID coupling selectors were introduced to remove. For new track rows, omit
178
178
  `@id` and let the successful push assign it. Preserve IDs already present on
179
179
  pulled rows.
180
180
 
181
+ A selector argument such as `this.SelectPants` is evaluated in the lexical
182
+ scope of the class that declares the clip. Here `this` is the `LegPart`, not
183
+ the nested track row or an outer object instance that later receives a copy of
184
+ the declaration default.
185
+
181
186
  Each track has `StartFrame`, `Direction` (`.Forward` or `.Reverse`), and a
182
187
  crop window `OffsetStartIndex`/`OffsetEndIndex`. Crop before reversing, then
183
188
  schedule on the owning clip. Content beyond the owning clip truncates. Reject
@@ -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.1 -->
85
+ <!-- reviewed-through-cli: 0.24.3 -->
86
86
  ```
87
87
 
88
88
  The quoted version above is checked too, so this instruction cannot go stale
@@ -115,5 +115,7 @@ npm run doctor
115
115
 
116
116
  Also run contract/corpus checks, Monaco/browser parity, VSIX packaging, and
117
117
  interactive sample no-op verification when the corresponding implementation
118
- surface changes. Run `npm run doctor` last; do not rerun successful suites only
119
- because doctor formatted files.
118
+ surface changes. Evaluator or candidate-materialization changes also require an
119
+ actual `neo test` run against the affected full-project candidate; focused
120
+ Vitest coverage does not replace that end-to-end command. Run `npm run doctor`
121
+ last; do not rerun successful suites only because doctor formatted files.