@neocompose/cli 0.9.0 → 0.9.2

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/neo.mjs +137 -14
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,20 @@
7
7
  - Document the final relation-only world layer-link contract and keep the
8
8
  format-4 Hello World corpus free of the retired value-side binding field.
9
9
 
10
+ ## [0.9.2] - 2026-07-24
11
+
12
+ ### Fixed
13
+
14
+ - Create idless list entries inside existing stored value graphs, including
15
+ nested class subtrees and references to files created by the same push.
16
+
17
+ ## [0.9.1] - 2026-07-24
18
+
19
+ ### Fixed
20
+
21
+ - Avoid synthesizing `partial: false` on member kinds that do not support the
22
+ field, so prospective animation validation accepts ordinary project members.
23
+
10
24
  ## [0.9.0] - 2026-07-23
11
25
 
12
26
  ### Added
package/dist/neo.mjs CHANGED
@@ -1235,6 +1235,7 @@ function memberDefaultApplies(field, type) {
1235
1235
  if (field === "collectionValueId") return type === 9;
1236
1236
  if (field === "dialogueGroupId") return type === 18;
1237
1237
  if (field === "templateId") return type === 11 || type === 12;
1238
+ if (field === "partial") return type === 7 || type === 21;
1238
1239
  return true;
1239
1240
  }
1240
1241
  function omitRedundantDeclarationOrder(recordKind, value) {
@@ -42083,6 +42084,7 @@ function lowerStaticValueSourcesV4(state, analysis, manifest) {
42083
42084
  );
42084
42085
  bindings.push({
42085
42086
  memberId,
42087
+ purpose: "stored",
42086
42088
  ownerClassId: sourceIdentityId(sourceClass, "class", sourceClass.name),
42087
42089
  initializer: declaration.initializer,
42088
42090
  source: declaration.source,
@@ -42124,12 +42126,14 @@ function buildValueLowerContext(state, manifest, options = {}) {
42124
42126
  ),
42125
42127
  staticValueIdsBySymbol: staticTargets,
42126
42128
  dialogueTargetsBySymbol: dialogueTargetsBySymbol(options.analysis),
42127
- projectFileIdsBySymbol: projectFileIdsBySymbol(state),
42129
+ projectFileIdsBySymbol: projectFileIdsBySymbol(state, options.analysis),
42128
42130
  mainLocale: projectMainLocaleFromState(state),
42129
42131
  valuePlacements: indexValuePlacements(state),
42130
42132
  parsedInitializers,
42131
42133
  reconstructed: /* @__PURE__ */ new Map(),
42132
42134
  pendingValues: /* @__PURE__ */ new Map(),
42135
+ pendingLocalizedTexts: /* @__PURE__ */ new Map(),
42136
+ loweredMemberIdByValueId: /* @__PURE__ */ new Map(),
42133
42137
  pendingBindingMembersByClassId: /* @__PURE__ */ new Map()
42134
42138
  };
42135
42139
  }
@@ -42166,6 +42170,7 @@ function lowerMemberDefaultSourcesV4(state, analysis, manifest) {
42166
42170
  if (member === void 0) continue;
42167
42171
  const binding = {
42168
42172
  memberId,
42173
+ purpose: "memberDefault",
42169
42174
  ownerClassId: sourceIdentityId(sourceClass, "class", sourceClass.name),
42170
42175
  initializer: declaration.initializer,
42171
42176
  source: declaration.source,
@@ -42379,13 +42384,75 @@ function lowerStoredBinding(context, binding, memberValueIds, seeds) {
42379
42384
  const valueId = annotatedId ?? currentValueId ?? pendingValueId(binding, binding.label);
42380
42385
  memberValueIds.set(binding.memberId, valueId);
42381
42386
  if (currentValueId === valueId) {
42387
+ const existingReconstructedKeys = new Set(context.reconstructed.keys());
42388
+ const existingPendingValueIds = new Set(context.pendingValues.keys());
42389
+ const existingPendingLocalizedTextIds = new Set(
42390
+ context.pendingLocalizedTexts.keys()
42391
+ );
42392
+ const existingPendingBindingMemberIds = new Set(
42393
+ [...context.pendingBindingMembersByClassId.values()].map(
42394
+ (pending) => pending.id
42395
+ )
42396
+ );
42382
42397
  lowerValueRow(context, member, expression, valueId, binding);
42398
+ const pendingRows = [...context.pendingValues.values()].filter(
42399
+ (row) => !existingPendingValueIds.has(row.id)
42400
+ );
42401
+ if (pendingRows.length > 0) {
42402
+ const root = reconstructedOrStateValue(context, valueId);
42403
+ const existingRows = [...context.reconstructed].filter(
42404
+ ([key, record3]) => key !== `value:${valueId}` && !existingReconstructedKeys.has(key) && record3.recordKind === "value"
42405
+ ).map(
42406
+ ([, record3]) => staticValueSeedRow(
42407
+ record3.fileFields,
42408
+ context.loweredMemberIdByValueId.get(record3.recordId)
42409
+ )
42410
+ );
42411
+ const bindingMembers = [
42412
+ ...context.pendingBindingMembersByClassId.values()
42413
+ ].filter((pending) => !existingPendingBindingMemberIds.has(pending.id));
42414
+ const localizedTexts = [...context.pendingLocalizedTexts.values()].filter(
42415
+ (text) => !existingPendingLocalizedTextIds.has(text.id)
42416
+ );
42417
+ seeds.set(binding.memberId, {
42418
+ value: root.value,
42419
+ classId: stringOrNull(root.classId),
42420
+ valueId,
42421
+ values: [...existingRows, ...pendingRows],
42422
+ ...bindingMembers.length === 0 ? {} : { bindingMembers },
42423
+ ...localizedTexts.length === 0 ? {} : { localizedTexts }
42424
+ });
42425
+ }
42383
42426
  return;
42384
42427
  }
42385
42428
  preserveReboundValue(context, currentValueId, valueId, binding);
42386
42429
  const seed = lowerStaticSeed(context, member, expression, binding, valueId);
42387
42430
  seeds.set(binding.memberId, { ...seed, valueId });
42388
42431
  }
42432
+ function reconstructedOrStateValue(context, valueId) {
42433
+ return context.reconstructed.get(`value:${valueId}`)?.fileFields ?? valueBase(context, valueId);
42434
+ }
42435
+ function staticValueSeedRow(value, loweredMemberId) {
42436
+ const id2 = stringOrNull(value.id);
42437
+ if (id2 === null) throw new Error("Authored value row is missing id.");
42438
+ if (loweredMemberId === void 0) {
42439
+ throw new Error(`Authored value row ${id2} is missing memberId.`);
42440
+ }
42441
+ return {
42442
+ id: id2,
42443
+ memberId: loweredMemberId,
42444
+ value: value.value,
42445
+ classId: stringOrNull(value.classId),
42446
+ ...typeof value.containerId === "string" ? { containerId: value.containerId } : {},
42447
+ ...isObjectRecord2(value.genericBindings) ? {
42448
+ genericBindings: Object.fromEntries(
42449
+ Object.entries(value.genericBindings).filter(
42450
+ (entry) => typeof entry[1] === "string"
42451
+ )
42452
+ )
42453
+ } : {}
42454
+ };
42455
+ }
42389
42456
  function preserveReboundValue(context, currentValueId, nextValueId, binding) {
42390
42457
  if (currentValueId === null || currentValueId === nextValueId) return;
42391
42458
  const base = valueBase(context, currentValueId);
@@ -42597,6 +42664,11 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
42597
42664
  valueId,
42598
42665
  value: expression.value
42599
42666
  });
42667
+ context.pendingLocalizedTexts.set(textId, {
42668
+ id: textId,
42669
+ valueId,
42670
+ value: expression.value
42671
+ });
42600
42672
  value = textId;
42601
42673
  } else {
42602
42674
  const lowered = lowerValueBody(
@@ -42644,6 +42716,7 @@ function lowerSeedChild(context, member, expression, source, path, rows, localiz
42644
42716
  return valueId;
42645
42717
  }
42646
42718
  function lowerValueRow(context, member, sourceExpression, expectedValueId, source, environment) {
42719
+ context.loweredMemberIdByValueId.set(expectedValueId, member.id);
42647
42720
  const { expression, id: id2 } = annotatedValue(sourceExpression);
42648
42721
  if (id2 !== null && id2 !== expectedValueId) {
42649
42722
  throw new Error(
@@ -43134,7 +43207,7 @@ function lowerListValue(context, member, expression, base, source, inheritedEnvi
43134
43207
  const environment = valueGenericEnvironment(base, inheritedEnvironment);
43135
43208
  const existingIds = existingListItemIds(context, member, base);
43136
43209
  const ids = [];
43137
- for (const element of expression.elements) {
43210
+ for (const [index, element] of expression.elements.entries()) {
43138
43211
  const symbolId = sourceValueSymbol(context, element);
43139
43212
  if (symbolId !== null) {
43140
43213
  if (!existingIds.has(symbolId)) {
@@ -43145,12 +43218,27 @@ function lowerListValue(context, member, expression, base, source, inheritedEnvi
43145
43218
  ids.push(symbolId);
43146
43219
  continue;
43147
43220
  }
43148
- const itemId = annotatedValue(element).id;
43149
- if (itemId === null) {
43150
- throw new Error(
43151
- `List ${member.name} contains an idless item. New list item creation is not implemented by this slice.`
43221
+ const annotatedItemId = annotatedValue(element).id;
43222
+ if (annotatedItemId === null) {
43223
+ if (source.purpose === "memberDefault") {
43224
+ throw new Error(
43225
+ `List ${member.name} contains an idless default item. New default list item creation is not implemented by this slice.`
43226
+ );
43227
+ }
43228
+ ids.push(
43229
+ lowerPendingListItem(
43230
+ context,
43231
+ entryMember,
43232
+ element,
43233
+ source,
43234
+ `${String(base.id)}[${index}]`,
43235
+ member.listKind === "unordered" ? stringOrNull(base.id) : void 0,
43236
+ environment
43237
+ )
43152
43238
  );
43239
+ continue;
43153
43240
  }
43241
+ const itemId = annotatedItemId;
43154
43242
  const child = valueBase(context, itemId);
43155
43243
  if (member.listKind === "unordered" && child.containerId !== base.id) {
43156
43244
  throw new Error(
@@ -43166,6 +43254,25 @@ function lowerListValue(context, member, expression, base, source, inheritedEnvi
43166
43254
  value: member.listKind === "unordered" ? [] : ids
43167
43255
  };
43168
43256
  }
43257
+ function lowerPendingListItem(context, member, expression, source, path, containerId, environment) {
43258
+ const rows = /* @__PURE__ */ new Map();
43259
+ const localizedTexts = /* @__PURE__ */ new Map();
43260
+ const valueId = lowerSeedChild(
43261
+ context,
43262
+ member,
43263
+ expression,
43264
+ source,
43265
+ path,
43266
+ rows,
43267
+ localizedTexts,
43268
+ containerId ?? void 0,
43269
+ environment
43270
+ );
43271
+ for (const text of localizedTexts.values()) {
43272
+ context.pendingLocalizedTexts.set(text.id, text);
43273
+ }
43274
+ return valueId;
43275
+ }
43169
43276
  function existingListItemIds(context, member, base) {
43170
43277
  if (member.listKind === "unordered") {
43171
43278
  const containerId = stringOrNull(base.id);
@@ -43699,6 +43806,7 @@ function indexSourceStaticTargets(targets, state, analysis, manifest, parsedInit
43699
43806
  annotatedValue(expression).id ?? current ?? pendingValueId(
43700
43807
  {
43701
43808
  memberId,
43809
+ purpose: "stored",
43702
43810
  initializer: declaration.initializer,
43703
43811
  source: declaration.source,
43704
43812
  label: symbol
@@ -43901,7 +44009,7 @@ function staticValueIdsBySymbol(state, manifest) {
43901
44009
  }
43902
44010
  return result;
43903
44011
  }
43904
- function projectFileIdsBySymbol(state) {
44012
+ function projectFileIdsBySymbol(state, analysis) {
43905
44013
  const files = Object.values(state).flatMap((record3) => {
43906
44014
  if (record3.recordKind !== "project-file" || !isObjectRecord2(record3.data))
43907
44015
  return [];
@@ -43910,12 +44018,21 @@ function projectFileIdsBySymbol(state) {
43910
44018
  return kind === "image" || kind === "audio" ? [{ stableId: record3.recordId, path: name, kind }] : [];
43911
44019
  });
43912
44020
  const symbols = assignDeterministicFileSymbols(files);
43913
- return new Map(
44021
+ const result = new Map(
43914
44022
  files.map((file) => [
43915
44023
  `${file.kind === "image" ? "Images" : "AudioClips"}.${symbols.get(file.stableId)}`,
43916
44024
  file.stableId
43917
44025
  ])
43918
44026
  );
44027
+ if (analysis !== void 0) {
44028
+ for (const declaration of projectFileDeclarationsV4(analysis)) {
44029
+ result.set(
44030
+ `${declaration.kind === "image" ? "Images" : "AudioClips"}.${declaration.symbol}`,
44031
+ declaration.recordId
44032
+ );
44033
+ }
44034
+ }
44035
+ return result;
43919
44036
  }
43920
44037
  function projectMainLocaleFromState(state) {
43921
44038
  const config = Object.values(state).find(
@@ -44662,17 +44779,18 @@ ${declarations.join("\n\n")}
44662
44779
  }
44663
44780
  function lowerProjectRootSourceV4(state, analysis, manifest) {
44664
44781
  const validated = validateProjectRootEnvelopeV4(state, analysis);
44665
- if (validated === null) return [];
44782
+ if (validated === null) {
44783
+ return { records: [], memberValueIds: /* @__PURE__ */ new Map(), seeds: /* @__PURE__ */ new Map() };
44784
+ }
44666
44785
  const { expectedIds, global, slots } = validated;
44667
44786
  const bindings = PROJECT_ROOT_SOURCE_SLOTS.map((expected, index) => ({
44668
44787
  memberId: expectedIds[index],
44788
+ purpose: "stored",
44669
44789
  initializer: slots[index].initializer,
44670
44790
  source: global.source,
44671
44791
  label: `root.${expected.name}`
44672
44792
  }));
44673
- return [
44674
- ...lowerStoredValueBindingsV4(state, manifest, bindings, { analysis }).records
44675
- ];
44793
+ return lowerStoredValueBindingsV4(state, manifest, bindings, { analysis });
44676
44794
  }
44677
44795
  function validateProjectRootEnvelopeV4(state, analysis) {
44678
44796
  const project = Object.values(state).find(
@@ -48184,7 +48302,10 @@ function computeWorkspaceStatus(workspace, options = {}) {
48184
48302
  }
48185
48303
  manifest = lowerProjectSchemaV4(baseManifest, analysis, {
48186
48304
  staticValueIdsBySymbol: staticValueIdsBySymbol2(workspace.state.records),
48187
- projectFileIdsBySymbol: projectFileIdsBySymbol(workspace.state.records),
48305
+ projectFileIdsBySymbol: projectFileIdsBySymbol(
48306
+ workspace.state.records,
48307
+ analysis
48308
+ ),
48188
48309
  rowBackedDefaultMemberIds: rowBackedDefaultMemberIdsV4(
48189
48310
  workspace.state.records
48190
48311
  )
@@ -48270,11 +48391,13 @@ function computeWorkspaceStatus(workspace, options = {}) {
48270
48391
  );
48271
48392
  staticValueSeeds = new Map([...staticValues.seeds, ...memberDefaults.seeds]);
48272
48393
  staticMemberValueIds = staticValues.memberValueIds;
48273
- const rootRecords = lowerProjectRootSourceV4(
48394
+ const rootValues = lowerProjectRootSourceV4(
48274
48395
  workspace.state.records,
48275
48396
  projectAnalysisV4,
48276
48397
  manifest
48277
48398
  );
48399
+ staticValueSeeds = new Map([...staticValueSeeds, ...rootValues.seeds]);
48400
+ const rootRecords = rootValues.records;
48278
48401
  const supplementalRecords = lowerSupplementalProjectSourcesV4(
48279
48402
  workspace.root,
48280
48403
  workspace.state.records,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",