@neocompose/cli 0.58.0 → 0.58.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.58.1] - 2026-09-24
4
+
5
+ - Push writes `@id` on list entries nested inside a new computed row, such as the items of a list on a new `new Event(...) { ... }` entry, so `neo status` is clean afterwards. Before, those entries stayed without ids and status kept reporting changes.
6
+ - A new row that names a stored row's `@id`, such as a row moved or copied under a new parent, is an error that names the `@id`, in `neo status` and `neo push --dry-run` too. Before, dry run passed and push either failed with a base-hash-conflict or committed a row that still referenced the deleted original. Drop the `@id` to create a new row.
7
+ - Source that places one stored row twice, such as a list entry copied with its `@id` into the same or another list or dictionary, is an error. Before, the push stored the same row at two positions.
8
+ - A negative number after `@id`, such as `[@id("…") -3]`, parses as the annotated entry, and a push of a new list with negative entries writes its ids. Before, `@id` could not precede `-3`, so the push failed after the server had applied it.
9
+ - A stored enum value may be written `Direction.North` as well as `.North`. Before, `neo status` failed with "Enum member … requires contextual .Option values."
10
+ - A push that deletes a row and creates a new one with the same localized text, such as re-creating a part under a new parent, updates source after it commits. Before, it failed with "Localizable value references missing localized text" after the server had already applied it.
11
+
3
12
  ## [0.58.0] - 2026-09-24
4
13
 
5
14
  - **Behavior change:** NeoScript cell queries the CLI evaluates, such as in `neo test`, no longer return an object that has no placement tiles. Before, such an object answered for its origin cell. This matches the Unity SDK (0.43.0) and the web editor: `PlacementTiles` are the cells an object occupies, and without them it occupies none.
package/dist/neo.mjs CHANGED
@@ -3672,7 +3672,8 @@ var init_executable_parser = __esm({
3672
3672
  return {
3673
3673
  kind: "annotated",
3674
3674
  annotations,
3675
- expression: this.parsePostfix(),
3675
+ // Unary, so `@id("…") -3` annotates the negative entry.
3676
+ expression: this.parseUnary(),
3676
3677
  pos: at(t)
3677
3678
  };
3678
3679
  }
@@ -45372,17 +45373,12 @@ function lowerDictionaryKey(expression, keyEnum, path) {
45372
45373
  if (keyEnum === null) {
45373
45374
  throw new Error(`Dictionary ${path} requires string keys.`);
45374
45375
  }
45375
- let optionName;
45376
- if (expression.kind === "contextualEnum") {
45377
- optionName = expression.name;
45378
- } else if (expression.kind === "member" && expression.receiver.kind === "ident") {
45379
- if (expression.receiver.name !== keyEnum.name) {
45380
- throw new Error(
45381
- `Dictionary key at ${path} names enum ${JSON.stringify(expression.receiver.name)}, expected ${JSON.stringify(keyEnum.name)}.`
45382
- );
45383
- }
45384
- optionName = expression.name;
45385
- } else {
45376
+ const optionName = enumOptionSpelling(
45377
+ expression,
45378
+ keyEnum.name,
45379
+ `Dictionary key at ${path}`
45380
+ );
45381
+ if (optionName === null) {
45386
45382
  throw new Error(
45387
45383
  `Dictionary key at ${path} must be .Option, ${keyEnum.name}.Option, or a quoted option ID.`
45388
45384
  );
@@ -45395,6 +45391,17 @@ function lowerDictionaryKey(expression, keyEnum, path) {
45395
45391
  }
45396
45392
  return optionId;
45397
45393
  }
45394
+ function enumOptionSpelling(expression, enumName, subject) {
45395
+ if (expression.kind === "contextualEnum") return expression.name;
45396
+ if (expression.kind !== "member") return null;
45397
+ if (expression.receiver.kind !== "ident") return null;
45398
+ if (expression.receiver.name !== enumName) {
45399
+ throw new Error(
45400
+ `${subject} names enum ${JSON.stringify(expression.receiver.name)}, expected ${JSON.stringify(enumName)}.`
45401
+ );
45402
+ }
45403
+ return expression.name;
45404
+ }
45398
45405
  function emitDictionaryKey(key, options) {
45399
45406
  const name = options?.get(key)?.name;
45400
45407
  return name === void 0 ? quoteNeoString(key) : `.${name}`;
@@ -64310,9 +64317,9 @@ var init_dialogue_sources = __esm({
64310
64317
  if (typeof memberId !== "string") return null;
64311
64318
  const nameMember = this.members.get(memberId);
64312
64319
  if (nameMember?.kind !== 3) return null;
64313
- const childValueId = value.value[memberName];
64314
- if (typeof childValueId !== "string") return null;
64315
- const child = this.values.get(childValueId);
64320
+ const childValueId2 = value.value[memberName];
64321
+ if (typeof childValueId2 !== "string") return null;
64322
+ const child = this.values.get(childValueId2);
64316
64323
  if (typeof child?.value !== "string") return null;
64317
64324
  const localizedText = this.localizedTexts.get(child.value);
64318
64325
  const localeValues = isObjectRecord2(localizedText?.localeValues) ? localizedText.localeValues : null;
@@ -67652,13 +67659,13 @@ function resolveOwnerMembersForValues(document, targetValueIds, additionalRoots,
67652
67659
  const env = overlayStamp(instanceEnv, body.genericBindings);
67653
67660
  for (const entry of merged) {
67654
67661
  if (entry.memberId === null) continue;
67655
- const childValueId = body.value[entry.schemaKey];
67656
- if (childValueId === void 0) continue;
67662
+ const childValueId2 = body.value[entry.schemaKey];
67663
+ if (childValueId2 === void 0) continue;
67657
67664
  const childMember = membersById.get(entry.memberId);
67658
67665
  if (childMember === void 0) continue;
67659
67666
  const substituted = trySubstituteMember(childMember, env);
67660
67667
  if (substituted === null) continue;
67661
- searchRow(substituted, childValueId, rootOwner, env, rootKind);
67668
+ searchRow(substituted, childValueId2, rootOwner, env, rootKind);
67662
67669
  }
67663
67670
  return;
67664
67671
  }
@@ -67669,8 +67676,8 @@ function resolveOwnerMembersForValues(document, targetValueIds, additionalRoots,
67669
67676
  const entryEnv = overlayStamp(ambientEnv, body.genericBindings);
67670
67677
  const entryMember = trySubstituteMember(entryMemberRecord, entryEnv);
67671
67678
  if (entryMember === null) return;
67672
- for (const childValueId of Object.values(body.value)) {
67673
- searchRow(entryMember, childValueId, rootOwner, entryEnv, rootKind);
67679
+ for (const childValueId2 of Object.values(body.value)) {
67680
+ searchRow(entryMember, childValueId2, rootOwner, entryEnv, rootKind);
67674
67681
  }
67675
67682
  return;
67676
67683
  }
@@ -67688,9 +67695,9 @@ function resolveOwnerMembersForValues(document, targetValueIds, additionalRoots,
67688
67695
  return;
67689
67696
  }
67690
67697
  if (!Array.isArray(body.value)) return;
67691
- for (const childValueId of body.value) {
67692
- if (typeof childValueId !== "string") continue;
67693
- searchRow(entryMember, childValueId, rootOwner, entryEnv, rootKind);
67698
+ for (const childValueId2 of body.value) {
67699
+ if (typeof childValueId2 !== "string") continue;
67700
+ searchRow(entryMember, childValueId2, rootOwner, entryEnv, rootKind);
67694
67701
  }
67695
67702
  return;
67696
67703
  }
@@ -67811,14 +67818,14 @@ function findOwningMembersForValues(document, valueIds, additionalRoots, travers
67811
67818
  args.genericBindings
67812
67819
  );
67813
67820
  for (const entry of merged) {
67814
- const childValueId = args.record[entry.schemaKey];
67815
- if (childValueId === void 0) continue;
67821
+ const childValueId2 = args.record[entry.schemaKey];
67822
+ if (childValueId2 === void 0) continue;
67816
67823
  const childMember = membersById.get(entry.memberId);
67817
67824
  if (childMember === void 0) continue;
67818
67825
  queue.push({
67819
67826
  member: substituteMember(childMember, env, document.members),
67820
67827
  memberRecordId: childMember.id,
67821
- id: childValueId,
67828
+ id: childValueId2,
67822
67829
  parentValueId: args.parentValueId,
67823
67830
  env,
67824
67831
  // Descending through `Overrides` opens an override graph, and every
@@ -67978,11 +67985,11 @@ function findOwningMembersForValues(document, valueIds, additionalRoots, travers
67978
67985
  env,
67979
67986
  document.members
67980
67987
  );
67981
- for (const childValueId of Object.values(storedValue.value)) {
67988
+ for (const childValueId2 of Object.values(storedValue.value)) {
67982
67989
  queue.push({
67983
67990
  member: entryMember,
67984
67991
  memberRecordId: entryMemberRecord.id,
67985
- id: childValueId,
67992
+ id: childValueId2,
67986
67993
  // An entry inherits its collection's position: a Dictionary is not
67987
67994
  // itself a way into an override graph.
67988
67995
  insideAnimationOverrideGraph: current.insideAnimationOverrideGraph,
@@ -68002,11 +68009,11 @@ function findOwningMembersForValues(document, valueIds, additionalRoots, travers
68002
68009
  document.members
68003
68010
  );
68004
68011
  const childValueIds = listKindOf(current.member) === 1 /* Unordered */ ? (rowsByContainerId.get(storedValue.id) ?? []).map((row) => row.id) : isStringListValue(storedValue.value) ? storedValue.value : [];
68005
- for (const childValueId of childValueIds) {
68012
+ for (const childValueId2 of childValueIds) {
68006
68013
  queue.push({
68007
68014
  member: entryMember,
68008
68015
  memberRecordId: entryMemberRecord.id,
68009
- id: childValueId,
68016
+ id: childValueId2,
68010
68017
  // An entry inherits its collection's position: a List is not itself
68011
68018
  // a way into an override graph.
68012
68019
  insideAnimationOverrideGraph: current.insideAnimationOverrideGraph,
@@ -81750,16 +81757,16 @@ function createStoredValuePlacementTraversal(args, trackReferences = false) {
81750
81757
  if (settled === null || Object.hasOwn(value.value, settled.schemaKey)) {
81751
81758
  continue;
81752
81759
  }
81753
- const childValueId = value.constructorArgs[constructorActionParameterId(constructor2, index)];
81754
- if (typeof childValueId === "string") {
81755
- settledChildrenBySchemaKey.set(settled.schemaKey, childValueId);
81760
+ const childValueId2 = value.constructorArgs[constructorActionParameterId(constructor2, index)];
81761
+ if (typeof childValueId2 === "string") {
81762
+ settledChildrenBySchemaKey.set(settled.schemaKey, childValueId2);
81756
81763
  }
81757
81764
  }
81758
81765
  }
81759
81766
  for (const entry of storedSchema(classId)) {
81760
81767
  const childMember = membersById.get(entry.memberId);
81761
- const childValueId = value.value[entry.schemaKey] ?? settledChildrenBySchemaKey.get(entry.schemaKey);
81762
- if (childMember === void 0 || typeof childValueId !== "string") {
81768
+ const childValueId2 = value.value[entry.schemaKey] ?? settledChildrenBySchemaKey.get(entry.schemaKey);
81769
+ if (childMember === void 0 || typeof childValueId2 !== "string") {
81763
81770
  continue;
81764
81771
  }
81765
81772
  if (memberAccessOf(childMember) !== 0 /* Public */) continue;
@@ -81767,7 +81774,7 @@ function createStoredValuePlacementTraversal(args, trackReferences = false) {
81767
81774
  memberId: childMember.id,
81768
81775
  parentValueId: value.id,
81769
81776
  source: { kind: "classField", schemaKey: entry.schemaKey },
81770
- valueId: childValueId
81777
+ valueId: childValueId2
81771
81778
  });
81772
81779
  }
81773
81780
  continue;
@@ -81779,16 +81786,16 @@ function createStoredValuePlacementTraversal(args, trackReferences = false) {
81779
81786
  if (entryMember === void 0) continue;
81780
81787
  if (isMemberDictionaryBase(member)) {
81781
81788
  if (!isStringRecord4(value.value)) continue;
81782
- for (const [key, childValueId] of Object.entries(value.value)) {
81789
+ for (const [key, childValueId2] of Object.entries(value.value)) {
81783
81790
  queue.push({
81784
81791
  memberId: entryMember.id,
81785
81792
  parentValueId: value.id,
81786
81793
  source: {
81787
81794
  kind: "collectionEntry",
81788
81795
  containerMemberId: storedMember.id,
81789
- entry: { kind: "dict", key, valueId: childValueId }
81796
+ entry: { kind: "dict", key, valueId: childValueId2 }
81790
81797
  },
81791
- valueId: childValueId
81798
+ valueId: childValueId2
81792
81799
  });
81793
81800
  }
81794
81801
  continue;
@@ -81796,9 +81803,9 @@ function createStoredValuePlacementTraversal(args, trackReferences = false) {
81796
81803
  const entries = listKindOf(member) === 1 /* Unordered */ ? args.indexedRows === void 0 ? unorderedEntriesByContainerId.get(value.id) ?? [] : args.indexedRows.unorderedListEntryIds(value.id).flatMap((id2) => {
81797
81804
  const row = valuesById.get(id2);
81798
81805
  return row === void 0 ? [] : [row];
81799
- }) : Array.isArray(value.value) ? value.value.flatMap((childValueId) => {
81800
- if (typeof childValueId !== "string") return [];
81801
- const childValue = valuesById.get(childValueId);
81806
+ }) : Array.isArray(value.value) ? value.value.flatMap((childValueId2) => {
81807
+ if (typeof childValueId2 !== "string") return [];
81808
+ const childValue = valuesById.get(childValueId2);
81802
81809
  return childValue === void 0 ? [] : [childValue];
81803
81810
  }) : [];
81804
81811
  for (const [index, childValue] of entries.entries()) {
@@ -93979,8 +93986,8 @@ function findParentValues(valueId, values) {
93979
93986
  continue;
93980
93987
  }
93981
93988
  if (!isStringRecord6(value.value)) continue;
93982
- for (const [key, childValueId] of Object.entries(value.value)) {
93983
- if (childValueId === valueId) parents.push({ value, key });
93989
+ for (const [key, childValueId2] of Object.entries(value.value)) {
93990
+ if (childValueId2 === valueId) parents.push({ value, key });
93984
93991
  }
93985
93992
  }
93986
93993
  return parents;
@@ -96651,8 +96658,8 @@ function inspectClass(options, member) {
96651
96658
  options.index.members
96652
96659
  );
96653
96660
  if (!memberKindSupportsStorage(childMember.kind)) continue;
96654
- const childValueId = body[entry.schemaKey];
96655
- if (childValueId === void 0) {
96661
+ const childValueId2 = body[entry.schemaKey];
96662
+ if (childValueId2 === void 0) {
96656
96663
  if (isRequiredMember2(childMember) && !options.allowMissingRequiredClassFields) {
96657
96664
  fail(
96658
96665
  `${options.path} is missing required schema key "${entry.schemaKey}".`
@@ -96662,7 +96669,7 @@ function inspectClass(options, member) {
96662
96669
  }
96663
96670
  children.push({
96664
96671
  member: childMember,
96665
- valueId: childValueId,
96672
+ valueId: childValueId2,
96666
96673
  path: `${options.path}.${entry.schemaKey}`,
96667
96674
  genericEnv: environment,
96668
96675
  insideAnimationOverrideGraph: options.insideAnimationOverrideGraph || entersAnimationOverrideGraph(entry.memberId)
@@ -106731,10 +106738,10 @@ function repointedChildValueIds(document, change) {
106731
106738
  if (!isPlainRecord4(change.nextData)) return [];
106732
106739
  const after = change.nextData.value;
106733
106740
  if (!isPlainRecord4(after)) return [];
106734
- return Object.entries(before).flatMap(([schemaKey, childValueId]) => {
106735
- if (typeof childValueId !== "string") return [];
106736
- if (after[schemaKey] === childValueId) return [];
106737
- return [childValueId];
106741
+ return Object.entries(before).flatMap(([schemaKey, childValueId2]) => {
106742
+ if (typeof childValueId2 !== "string") return [];
106743
+ if (after[schemaKey] === childValueId2) return [];
106744
+ return [childValueId2];
106738
106745
  });
106739
106746
  }
106740
106747
  function authoredFieldsEqual(recordKind, base, next) {
@@ -115996,12 +116003,12 @@ function buildStoredValuePlacementIndexV4(records2) {
115996
116003
  const classId = typeof value.classId === "string" ? value.classId : null;
115997
116004
  const body = value.value;
115998
116005
  if (isObjectRecord2(body)) {
115999
- for (const [schemaKey, childValueId] of Object.entries(body)) {
116000
- if (typeof childValueId !== "string" || !values.has(childValueId)) {
116006
+ for (const [schemaKey, childValueId2] of Object.entries(body)) {
116007
+ if (typeof childValueId2 !== "string" || !values.has(childValueId2)) {
116001
116008
  continue;
116002
116009
  }
116003
116010
  add({
116004
- childValueId,
116011
+ childValueId: childValueId2,
116005
116012
  memberId: classId === null ? null : memberIdForSchemaKey(classId, schemaKey),
116006
116013
  parentValueId,
116007
116014
  schemaKey,
@@ -116029,8 +116036,8 @@ function buildStoredValuePlacementIndexV4(records2) {
116029
116036
  continue;
116030
116037
  }
116031
116038
  const parameterId = constructorActionParameterId(constructor2, index);
116032
- const childValueId = constructorArgs[parameterId];
116033
- if (typeof childValueId !== "string" || !values.has(childValueId) || !memberStoresAggregate(
116039
+ const childValueId2 = constructorArgs[parameterId];
116040
+ if (typeof childValueId2 !== "string" || !values.has(childValueId2) || !memberStoresAggregate(
116034
116041
  memberDataById.get(settled.memberId),
116035
116042
  value,
116036
116043
  memberDataById,
@@ -116041,7 +116048,7 @@ function buildStoredValuePlacementIndexV4(records2) {
116041
116048
  continue;
116042
116049
  }
116043
116050
  add({
116044
- childValueId,
116051
+ childValueId: childValueId2,
116045
116052
  memberId: settled.memberId,
116046
116053
  parentValueId,
116047
116054
  schemaKey: settled.schemaKey,
@@ -117766,16 +117773,7 @@ function computeWorkspaceStatus(workspace, options) {
117766
117773
  projectSources.push({ uri: relPath, source, kind: sourceKind });
117767
117774
  }
117768
117775
  if (conflictedFiles.length > 0) {
117769
- return {
117770
- changes: [],
117771
- conflictedFiles,
117772
- parseErrors,
117773
- parseWarnings,
117774
- reconstructed: /* @__PURE__ */ new Map(),
117775
- authoredValueSeeds: /* @__PURE__ */ new Map(),
117776
- binaryChanges: [],
117777
- binaryFiles: []
117778
- };
117776
+ return refusedStatus(conflictedFiles, parseErrors, parseWarnings);
117779
117777
  }
117780
117778
  const { records: loweringRecords, residency: packedResidency } = logicalValueBaseRecordsV4(loweringBaseRecords(workspace.state.records));
117781
117779
  const baseDocuments = schemaBaseDocuments(workspace);
@@ -117907,16 +117905,7 @@ function computeWorkspaceStatus(workspace, options) {
117907
117905
  1
117908
117906
  )
117909
117907
  );
117910
- return {
117911
- changes: [],
117912
- conflictedFiles,
117913
- parseErrors,
117914
- parseWarnings,
117915
- reconstructed: /* @__PURE__ */ new Map(),
117916
- authoredValueSeeds: /* @__PURE__ */ new Map(),
117917
- binaryChanges: [],
117918
- binaryFiles: []
117919
- };
117908
+ return refusedStatus(conflictedFiles, parseErrors, parseWarnings);
117920
117909
  }
117921
117910
  const sourceByKey = manifestRecordSources(manifest);
117922
117911
  const documents = projectSchemaManifestToDocuments(
@@ -118219,8 +118208,7 @@ function computeWorkspaceStatus(workspace, options) {
118219
118208
  if (reconstructed3.has(key)) continue;
118220
118209
  if (brokenFiles.has(recordFile)) continue;
118221
118210
  if (recordState.conflictServerHash === null) continue;
118222
- if (recordState.recordKind === "localized-text" && isLocalizedText(recordState.data) && recordState.data.memberSource !== void 0)
118223
- continue;
118211
+ if (isSharedMemberText(recordState)) continue;
118224
118212
  if (recordState.recordKind === "value") {
118225
118213
  deletedValueIds.add(recordState.recordId);
118226
118214
  }
@@ -118234,6 +118222,9 @@ function computeWorkspaceStatus(workspace, options) {
118234
118222
  casBaseHash: recordState.conflictServerHash !== void 0 ? recordState.conflictServerHash : recordState.contentHash
118235
118223
  });
118236
118224
  }
118225
+ const sourceTextByUri = new Map(
118226
+ sourceEntries.map((entry) => [entry.relPath, entry.source])
118227
+ );
118237
118228
  const referenceFailures = drainValueReferenceObligationsV4(
118238
118229
  prospectiveState,
118239
118230
  manifest,
@@ -118241,9 +118232,7 @@ function computeWorkspaceStatus(workspace, options) {
118241
118232
  registry: valueLowerRegistry,
118242
118233
  analysis: projectAnalysisV4,
118243
118234
  deletedValueIds,
118244
- sourceTextByUri: new Map(
118245
- sourceEntries.map((entry) => [entry.relPath, entry.source])
118246
- )
118235
+ sourceTextByUri
118247
118236
  }
118248
118237
  );
118249
118238
  for (const failure of referenceFailures) {
@@ -118260,16 +118249,7 @@ function computeWorkspaceStatus(workspace, options) {
118260
118249
  }
118261
118250
  reportPhase("record-diff-references", "Checking packed values\u2026");
118262
118251
  if (referenceFailures.length > 0) {
118263
- return {
118264
- changes: [],
118265
- conflictedFiles,
118266
- parseErrors,
118267
- parseWarnings,
118268
- reconstructed: /* @__PURE__ */ new Map(),
118269
- authoredValueSeeds: /* @__PURE__ */ new Map(),
118270
- binaryChanges: [],
118271
- binaryFiles: []
118272
- };
118252
+ return refusedStatus(conflictedFiles, parseErrors, parseWarnings);
118273
118253
  }
118274
118254
  const unanchoredValueDeletes = unanchoredValueDeleteIds({
118275
118255
  records: workspace.state.records,
@@ -118293,16 +118273,7 @@ function computeWorkspaceStatus(workspace, options) {
118293
118273
  "value-base-desync"
118294
118274
  )
118295
118275
  );
118296
- return {
118297
- changes: [],
118298
- conflictedFiles,
118299
- parseErrors,
118300
- parseWarnings,
118301
- reconstructed: /* @__PURE__ */ new Map(),
118302
- authoredValueSeeds: /* @__PURE__ */ new Map(),
118303
- binaryChanges: [],
118304
- binaryFiles: []
118305
- };
118276
+ return refusedStatus(conflictedFiles, parseErrors, parseWarnings);
118306
118277
  }
118307
118278
  parseWarnings.push(
118308
118279
  new SchemaSourceError(
@@ -118315,6 +118286,23 @@ function computeWorkspaceStatus(workspace, options) {
118315
118286
  )
118316
118287
  );
118317
118288
  }
118289
+ if (valueLowerRegistry.storedRowClaims.size > 0) {
118290
+ for (const claim of valueLowerRegistry.storedRowClaims.values()) {
118291
+ const position = composeReferenceSitePosition(
118292
+ claim.site,
118293
+ sourceTextByUri
118294
+ );
118295
+ parseErrors.push(
118296
+ new SchemaSourceError(
118297
+ claim.message,
118298
+ position.file,
118299
+ position.line,
118300
+ position.column
118301
+ )
118302
+ );
118303
+ }
118304
+ return refusedStatus(conflictedFiles, parseErrors, parseWarnings);
118305
+ }
118318
118306
  for (let index = changes.length - 1; index >= 0; index -= 1) {
118319
118307
  const change = changes[index];
118320
118308
  if (change === void 0 || change.kind !== "update") continue;
@@ -119501,6 +119489,21 @@ function summarizeFieldDiff(baseData3, nextData) {
119501
119489
  }
119502
119490
  return lines;
119503
119491
  }
119492
+ function isSharedMemberText(record6) {
119493
+ return record6.recordKind === "localized-text" && isLocalizedText(record6.data) && record6.data.memberSource !== void 0;
119494
+ }
119495
+ function refusedStatus(conflictedFiles, parseErrors, parseWarnings) {
119496
+ return {
119497
+ changes: [],
119498
+ conflictedFiles,
119499
+ parseErrors,
119500
+ parseWarnings,
119501
+ reconstructed: /* @__PURE__ */ new Map(),
119502
+ authoredValueSeeds: /* @__PURE__ */ new Map(),
119503
+ binaryChanges: [],
119504
+ binaryFiles: []
119505
+ };
119506
+ }
119504
119507
  var ANIMATION_DOCUMENT_RECORD_KINDS, ANIMATION_REPLAY_RECORD_KINDS, PROSPECTIVE_ANIMATION_RECORD_KINDS;
119505
119508
  var init_workspace_status_core = __esm({
119506
119509
  "src/project-source/workspace-status-core.ts"() {
@@ -121562,8 +121565,8 @@ function animationConstructorProjectionTargetValueIds(context, classId, value) {
121562
121565
  classId,
121563
121566
  projection.memberId
121564
121567
  );
121565
- const childValueId = schemaKey === null ? void 0 : value.value[schemaKey];
121566
- const childValue = typeof childValueId === "string" ? context.values.get(childValueId) : void 0;
121568
+ const childValueId2 = schemaKey === null ? void 0 : value.value[schemaKey];
121569
+ const childValue = typeof childValueId2 === "string" ? context.values.get(childValueId2) : void 0;
121567
121570
  const projectedMember = context.members.get(projection.memberId);
121568
121571
  if (childValue !== void 0 && projectedMember !== void 0 && numberField(projectedMember, "kind") === 9 /* Lookup */ && Array.isArray(childValue.value) && typeof childValue.value[0] === "string") {
121569
121572
  targetIds.push(childValue.value[0]);
@@ -121716,6 +121719,8 @@ function createValueLowerRegistryV4(options = {}) {
121716
121719
  referenceObligations: [],
121717
121720
  initAuthoredRowIds: /* @__PURE__ */ new Map(),
121718
121721
  loweringFailures: [],
121722
+ storedRowClaims: /* @__PURE__ */ new Map(),
121723
+ placedStoredRowIds: /* @__PURE__ */ new Set(),
121719
121724
  pendingValueIdentitySites: /* @__PURE__ */ new Map(),
121720
121725
  initializerReconciliations: /* @__PURE__ */ new Map()
121721
121726
  };
@@ -121848,6 +121853,8 @@ function buildValueLowerContext(state, manifest, options = {}) {
121848
121853
  ),
121849
121854
  referenceObligations: registry.referenceObligations,
121850
121855
  loweringFailures: registry.loweringFailures,
121856
+ storedRowClaims: registry.storedRowClaims,
121857
+ placedStoredRowIds: registry.placedStoredRowIds,
121851
121858
  pendingValueIdentitySites: registry.pendingValueIdentitySites,
121852
121859
  initializerReconciliations: registry.initializerReconciliations,
121853
121860
  materializedConstructorExpressions: registry.materializedConstructorExpressions,
@@ -121953,14 +121960,16 @@ function entrySliceRequiresEvaluation(entry, declaredConstructors2, entryClassNa
121953
121960
  }
121954
121961
  }
121955
121962
  function indexAuthoredRowIds(index, initSource, owner) {
121956
- const pattern = /@id\(\s*"((?:[^"\\]|\\.)*)"\s*\)/g;
121957
- let match = pattern.exec(initSource);
121958
- while (match !== null) {
121963
+ for (const authored of authoredRowIds(initSource)) {
121964
+ index.set(authored, owner);
121965
+ }
121966
+ }
121967
+ function* authoredRowIds(initSource) {
121968
+ for (const match of initSource.matchAll(
121969
+ /@id\(\s*"((?:[^"\\]|\\.)*)"\s*\)/g
121970
+ )) {
121959
121971
  const authored = match[1];
121960
- if (authored !== void 0 && authored.length > 0) {
121961
- index.set(authored, owner);
121962
- }
121963
- match = pattern.exec(initSource);
121972
+ if (authored !== void 0 && authored.length > 0) yield authored;
121964
121973
  }
121965
121974
  }
121966
121975
  function indexDeclaredInitializers(analysis) {
@@ -123537,7 +123546,8 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
123537
123546
  expressionPosition: {
123538
123547
  line: sourceExpression.pos.line,
123539
123548
  column: sourceExpression.pos.column
123540
- }
123549
+ },
123550
+ nestedListEntries: idlessNestedListEntries(context, expression)
123541
123551
  });
123542
123552
  }
123543
123553
  const code = initializerExpressionSlice(authoredSlice);
@@ -123653,9 +123663,9 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
123653
123663
  );
123654
123664
  }
123655
123665
  const childPath = `${path}.${schemaKey}`;
123656
- const childValueId = pendingNestedValueId(source, childPath);
123657
- if (rows.has(childValueId)) {
123658
- throw new Error(`Value construction reuses identity ${childValueId}.`);
123666
+ const childValueId2 = pendingNestedValueId(source, childPath);
123667
+ if (rows.has(childValueId2)) {
123668
+ throw new Error(`Value construction reuses identity ${childValueId2}.`);
123659
123669
  }
123660
123670
  if (projectedMember.kind === "lookup") {
123661
123671
  if (argument2.kind !== "litString") {
@@ -123853,6 +123863,13 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
123853
123863
  registerSeedRow(context, rows, row, source, sourceExpression);
123854
123864
  return row;
123855
123865
  }
123866
+ function* storedRowIdsRecreatedBy(context, row) {
123867
+ if (context.state[`value:${row.id}`] !== void 0) yield row.id;
123868
+ if (row.nodeType !== "initializer") return;
123869
+ for (const authored of authoredRowIds(row.code)) {
123870
+ if (context.state[`value:${authored}`] !== void 0) yield authored;
123871
+ }
123872
+ }
123856
123873
  function registerSeedRow(context, rows, row, source, expression) {
123857
123874
  if (rows.has(row.id)) {
123858
123875
  throw new Error(`Value construction reuses identity ${row.id}.`);
@@ -123865,6 +123882,15 @@ function registerSeedRow(context, rows, row, source, expression) {
123865
123882
  rows.set(row.id, row);
123866
123883
  return;
123867
123884
  }
123885
+ if (!context.structuralConstruction) {
123886
+ for (const storedId of storedRowIdsRecreatedBy(context, row)) {
123887
+ if (context.storedRowClaims.has(storedId)) continue;
123888
+ context.storedRowClaims.set(storedId, {
123889
+ message: `Value ${source.label} names existing row @id(${JSON.stringify(storedId)}) inside a new row. A row keeps its parent: drop the @id to create a new row.`,
123890
+ site: referenceSite(source, expression)
123891
+ });
123892
+ }
123893
+ }
123868
123894
  rows.set(row.id, row);
123869
123895
  context.pendingValues.set(row.id, row);
123870
123896
  if (row.containerId !== void 0) {
@@ -124781,8 +124807,8 @@ function lowerConstructorProjections(context, schemaClass2, expression, base, ba
124781
124807
  argument: argument2,
124782
124808
  argumentIndex
124783
124809
  } of resolved) {
124784
- const childValueId = baseBody[schemaKey];
124785
- if (typeof childValueId !== "string") {
124810
+ const childValueId2 = baseBody[schemaKey];
124811
+ if (typeof childValueId2 !== "string") {
124786
124812
  throw new Error(
124787
124813
  `Class value ${String(base.id)}.${schemaKey} has no existing structural row.`
124788
124814
  );
@@ -124793,27 +124819,27 @@ function lowerConstructorProjections(context, schemaClass2, expression, base, ba
124793
124819
  `Class value ${String(base.id)}.${schemaKey} requires a value-row id string literal.`
124794
124820
  );
124795
124821
  }
124796
- const projectedBase = valueBase(context, childValueId);
124822
+ const projectedBase = valueBase(context, childValueId2);
124797
124823
  addReconstructed(
124798
124824
  context,
124799
124825
  "value",
124800
- childValueId,
124826
+ childValueId2,
124801
124827
  { ...valueFileFields(projectedBase), value: [argument2.value] },
124802
124828
  source.source
124803
124829
  );
124804
- body[schemaKey] = childValueId;
124830
+ body[schemaKey] = childValueId2;
124805
124831
  continue;
124806
124832
  }
124807
124833
  lowerValueRow(
124808
124834
  context,
124809
124835
  projectedMember,
124810
124836
  argument2,
124811
- childValueId,
124837
+ childValueId2,
124812
124838
  source,
124813
124839
  environment,
124814
124840
  argumentSlices[argumentIndex]
124815
124841
  );
124816
- body[schemaKey] = childValueId;
124842
+ body[schemaKey] = childValueId2;
124817
124843
  }
124818
124844
  }
124819
124845
  function classInheritanceChain(classes, classId) {
@@ -125324,6 +125350,12 @@ function lowerListValue(context, member, expression, base, source, inheritedEnvi
125324
125350
  );
125325
125351
  continue;
125326
125352
  }
125353
+ recordRepeatedRow(
125354
+ context,
125355
+ itemId,
125356
+ `List ${member.name}`,
125357
+ referenceSite(source, element)
125358
+ );
125327
125359
  const child = valueBase(context, itemId);
125328
125360
  if (member.listKind === "unordered" && child.containerId !== base.id) {
125329
125361
  throw new Error(
@@ -125347,6 +125379,16 @@ function lowerListValue(context, member, expression, base, source, inheritedEnvi
125347
125379
  value: member.listKind === "unordered" ? [] : ids
125348
125380
  };
125349
125381
  }
125382
+ function recordRepeatedRow(context, rowId, collection, site) {
125383
+ if (!context.placedStoredRowIds.has(rowId)) {
125384
+ context.placedStoredRowIds.add(rowId);
125385
+ return;
125386
+ }
125387
+ context.loweringFailures.push({
125388
+ message: `${collection} places existing row @id(${JSON.stringify(rowId)}), which source already places elsewhere. A row has one position: drop the @id on the copy to create a new row.`,
125389
+ site
125390
+ });
125391
+ }
125350
125392
  function lowerPendingListItem(context, member, expression, source, path, containerId, environment, authoredSlice) {
125351
125393
  const rows = /* @__PURE__ */ new Map();
125352
125394
  const localizedTexts = /* @__PURE__ */ new Map();
@@ -125414,6 +125456,12 @@ function lowerDictionaryValue(context, member, expression, base, source, inherit
125414
125456
  `Dictionary ${member.name}[${JSON.stringify(key)}] has no existing row. New dictionary entries are not implemented by this slice.`
125415
125457
  );
125416
125458
  }
125459
+ recordRepeatedRow(
125460
+ context,
125461
+ valueId,
125462
+ `Dictionary ${member.name}`,
125463
+ referenceSite(source, entry.value)
125464
+ );
125417
125465
  body[key] = lowerValueRow(
125418
125466
  context,
125419
125467
  entryMember,
@@ -125485,14 +125533,20 @@ function lowerEnum2(context, member, expression) {
125485
125533
  throw new Error(`Enum member ${member.name} requires [...].`);
125486
125534
  const options = context.enumOptions.get(member.enumId);
125487
125535
  if (options === void 0) throw new Error(`Unknown enum ${member.enumId}.`);
125536
+ const enumName = context.enumNames.get(member.enumId);
125537
+ if (enumName === void 0) {
125538
+ throw new Error(`Enum ${member.enumId} has no manifest name.`);
125539
+ }
125540
+ const subject = `Enum member ${member.name}`;
125488
125541
  return elements.map((entry) => {
125489
- if (entry.kind !== "contextualEnum") {
125542
+ const optionName = enumOptionSpelling(entry, enumName, subject);
125543
+ if (optionName === null) {
125490
125544
  throw new Error(
125491
- `Enum member ${member.name} requires contextual .Option values.`
125545
+ `${subject} requires .Option or ${enumName}.Option values.`
125492
125546
  );
125493
125547
  }
125494
- const id2 = options.get(entry.name);
125495
- if (id2 === void 0) throw new Error(`Enum has no option ${entry.name}.`);
125548
+ const id2 = options.get(optionName);
125549
+ if (id2 === void 0) throw new Error(`Enum has no option ${optionName}.`);
125496
125550
  return id2;
125497
125551
  });
125498
125552
  }
@@ -126078,17 +126132,17 @@ function indexValuePlacements(state, options = {}) {
126078
126132
  }
126079
126133
  const body = isObjectRecord2(row.body) ? row.body : null;
126080
126134
  if (body === null) continue;
126081
- for (const [memberName, childValueId] of Object.entries(body)) {
126082
- if (typeof childValueId !== "string") continue;
126083
- const placementKey = `${memberName}:${childValueId}`;
126135
+ for (const [memberName, childValueId2] of Object.entries(body)) {
126136
+ if (typeof childValueId2 !== "string") continue;
126137
+ const placementKey = `${memberName}:${childValueId2}`;
126084
126138
  if (!containerBodyByPlacement.has(placementKey)) {
126085
126139
  containerBodyByPlacement.set(placementKey, body);
126086
126140
  }
126087
126141
  const placed = mutablePlacedValueIds.get(memberName) ?? /* @__PURE__ */ new Set();
126088
- placed.add(childValueId);
126142
+ placed.add(childValueId2);
126089
126143
  mutablePlacedValueIds.set(memberName, placed);
126090
126144
  const placement = {
126091
- valueId: childValueId,
126145
+ valueId: childValueId2,
126092
126146
  schemaKey: memberName,
126093
126147
  containerValueId: row.id,
126094
126148
  containerClassId: row.classId
@@ -126096,9 +126150,9 @@ function indexValuePlacements(state, options = {}) {
126096
126150
  const byKey = placementsBySchemaKey.get(memberName) ?? [];
126097
126151
  byKey.push(placement);
126098
126152
  placementsBySchemaKey.set(memberName, byKey);
126099
- const byValue = placementsByValueId.get(childValueId) ?? [];
126153
+ const byValue = placementsByValueId.get(childValueId2) ?? [];
126100
126154
  byValue.push(placement);
126101
- placementsByValueId.set(childValueId, byValue);
126155
+ placementsByValueId.set(childValueId2, byValue);
126102
126156
  }
126103
126157
  }
126104
126158
  const valueIdByMemberId = /* @__PURE__ */ new Map();
@@ -126569,6 +126623,68 @@ function fileTargetId(context, expression, registry) {
126569
126623
  }
126570
126624
  return null;
126571
126625
  }
126626
+ function idlessNestedListEntries(context, expression) {
126627
+ const entries = [];
126628
+ let spellable = true;
126629
+ const visit = (node, path) => {
126630
+ const { expression: unwrapped } = annotatedValue(node);
126631
+ if (unwrapped.kind === "new") {
126632
+ for (const field of unwrapped.initializer ?? []) {
126633
+ visit(field.value, [...path, field.name]);
126634
+ }
126635
+ return;
126636
+ }
126637
+ if (unwrapped.kind === "litDict") {
126638
+ for (const entry of unwrapped.entries) {
126639
+ if (entry.key.kind === "litString") {
126640
+ visit(entry.value, [...path, entry.key.value]);
126641
+ continue;
126642
+ }
126643
+ const before = entries.length;
126644
+ visit(entry.value, path);
126645
+ if (entries.length > before) spellable = false;
126646
+ }
126647
+ return;
126648
+ }
126649
+ if (unwrapped.kind !== "litList") return;
126650
+ unwrapped.elements.forEach((element, index) => {
126651
+ const entryPath = [...path, index];
126652
+ if (annotatedValue(element).id === null && sourceValueSymbol(context, element) === null) {
126653
+ const start = stampableEntryStart(element);
126654
+ if (start === null) spellable = false;
126655
+ else {
126656
+ entries.push({
126657
+ path: entryPath,
126658
+ expressionPosition: { line: start.line, column: start.column }
126659
+ });
126660
+ }
126661
+ }
126662
+ visit(element, entryPath);
126663
+ });
126664
+ };
126665
+ visit(expression, []);
126666
+ return spellable ? entries : null;
126667
+ }
126668
+ function stampableEntryStart(expression) {
126669
+ switch (expression.kind) {
126670
+ case "member":
126671
+ case "index":
126672
+ return stampableEntryStart(expression.receiver);
126673
+ case "call":
126674
+ return stampableEntryStart(expression.callee);
126675
+ case "force":
126676
+ return stampableEntryStart(expression.operand);
126677
+ case "binary":
126678
+ case "coalesce":
126679
+ case "conditional":
126680
+ case "is":
126681
+ case "lambda":
126682
+ case "annotated":
126683
+ return null;
126684
+ default:
126685
+ return expression.pos;
126686
+ }
126687
+ }
126572
126688
  function memberPath2(expression) {
126573
126689
  if (expression.kind === "ident") return expression.name;
126574
126690
  if (expression.kind !== "member") return null;
@@ -128005,10 +128121,10 @@ function constructorProjectionSource(context, classId, body, visited, environmen
128005
128121
  classId,
128006
128122
  projection.memberId
128007
128123
  );
128008
- const childValueId = schemaKey === null ? void 0 : body[schemaKey];
128009
- const childValue = typeof childValueId === "string" ? context.values.get(childValueId) : void 0;
128124
+ const childValueId2 = schemaKey === null ? void 0 : body[schemaKey];
128125
+ const childValue = typeof childValueId2 === "string" ? context.values.get(childValueId2) : void 0;
128010
128126
  const projectedMember = context.members.get(projection.memberId);
128011
- if (schemaKey === null || typeof childValueId !== "string" || childValue === void 0 || projectedMember === void 0) {
128127
+ if (schemaKey === null || typeof childValueId2 !== "string" || childValue === void 0 || projectedMember === void 0) {
128012
128128
  throw new Error(
128013
128129
  `Class ${context.manifestClasses.get(classId)?.name ?? classId} constructor projection ${projection.parameterName} has no stored projected value.`
128014
128130
  );
@@ -128023,7 +128139,7 @@ function constructorProjectionSource(context, classId, body, visited, environmen
128023
128139
  `Class ${context.manifestClasses.get(classId)?.name ?? classId} constructor projection ${projection.parameterName} requires exactly one referenced value.`
128024
128140
  );
128025
128141
  }
128026
- visited.add(childValueId);
128142
+ visited.add(childValueId2);
128027
128143
  targetValueIds.push(targetIds[0]);
128028
128144
  argumentsValue.push(
128029
128145
  `${projection.parameterName}: ${quote5(targetIds[0])}`
@@ -128034,7 +128150,7 @@ function constructorProjectionSource(context, classId, body, visited, environmen
128034
128150
  `${projection.parameterName}: ${emitValue(
128035
128151
  context,
128036
128152
  projectedMember,
128037
- childValueId,
128153
+ childValueId2,
128038
128154
  {
128039
128155
  definitionSite: true,
128040
128156
  writeIdentity: false,
@@ -133949,7 +134065,10 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
133949
134065
  workspace,
133950
134066
  replacements.exact,
133951
134067
  localStatus.pendingValueIdentitySites,
133952
- { sourceSnapshot: localStatus.sourceSnapshot }
134068
+ {
134069
+ sourceSnapshot: localStatus.sourceSnapshot,
134070
+ committedValueAtPath: committedValueAtPathReader(nextRecords)
134071
+ }
133953
134072
  );
133954
134073
  const localRecords = rewriteReconstructedRecords(
133955
134074
  localStatus.reconstructed,
@@ -133977,7 +134096,8 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
133977
134096
  for (const [key, state] of Object.entries(nextRecords)) {
133978
134097
  const prior = previousRecords[key];
133979
134098
  const local = localRecords.get(key);
133980
- if (local === void 0 && prior?.file !== void 0) continue;
134099
+ if (local === void 0 && prior?.file !== void 0 && !isSharedMemberText(state))
134100
+ continue;
133981
134101
  const submitted = submittedByKey.get(key);
133982
134102
  const emitData = local === void 0 ? state.data : changedKeys.has(key) && submitted !== void 0 ? mergeCommittedRecordWithLaterLocalEdits(
133983
134103
  state.recordKind,
@@ -134516,12 +134636,10 @@ function materializeAssignedSchemaIdsInAuthoredSource(workspace, replacements, p
134516
134636
  entry.identity.source.range.start.line,
134517
134637
  entry.identity.source.range.start.character
134518
134638
  );
134519
- const indentation = sourceIndentationAt(source, start);
134520
- const newline = source.includes("\r\n") ? "\r\n" : "\n";
134521
134639
  edits.push({
134522
134640
  start,
134523
134641
  end: start,
134524
- text: `@id(${JSON.stringify(assignedId)})${newline}${indentation}`
134642
+ text: idStampText(source, start, assignedId)
134525
134643
  });
134526
134644
  } else {
134527
134645
  const quotedPendingId = JSON.stringify(pendingId2);
@@ -134559,15 +134677,18 @@ function materializeAssignedSchemaIdsInAuthoredSource(workspace, replacements, p
134559
134677
  site.expressionPosition.column
134560
134678
  );
134561
134679
  if (expressionOffset === null) continue;
134562
- const insertion = initializerOffset + expressionOffset;
134563
- const indentation = sourceIndentationAt(source, insertion);
134564
- const newline = source.includes("\r\n") ? "\r\n" : "\n";
134565
- const edits = editsByUri.get(site.uri) ?? [];
134566
- edits.push({
134567
- start: insertion,
134568
- end: insertion,
134569
- text: `@id(${JSON.stringify(assignedId)})${newline}${indentation}`
134680
+ const stamp = (offset, id2) => ({
134681
+ start: offset,
134682
+ end: offset,
134683
+ text: idStampText(source, offset, id2)
134570
134684
  });
134685
+ const entryStamps = options.committedValueAtPath === void 0 ? [] : nestedListEntryStamps(site, assignedId, options.committedValueAtPath);
134686
+ if (entryStamps === null) continue;
134687
+ const edits = editsByUri.get(site.uri) ?? [];
134688
+ edits.push(stamp(initializerOffset + expressionOffset, assignedId));
134689
+ for (const entry of entryStamps) {
134690
+ edits.push(stamp(initializerOffset + entry.offset, entry.id));
134691
+ }
134571
134692
  editsByUri.set(site.uri, edits);
134572
134693
  const handled = handledByUri.get(site.uri) ?? /* @__PURE__ */ new Set();
134573
134694
  handled.add(pendingId2);
@@ -134601,6 +134722,49 @@ function materializeAssignedSchemaIdsInAuthoredSource(workspace, replacements, p
134601
134722
  }
134602
134723
  return preserved;
134603
134724
  }
134725
+ function nestedListEntryStamps(site, rowId, committedValueAtPath) {
134726
+ if (site.nestedListEntries === null) return null;
134727
+ const stamps = [];
134728
+ for (const entry of site.nestedListEntries) {
134729
+ const id2 = committedValueAtPath(rowId, entry.path);
134730
+ if (id2 === null) return null;
134731
+ const offset = sourceOffsetInsideInitializer(
134732
+ site.initializer,
134733
+ entry.expressionPosition.line,
134734
+ entry.expressionPosition.column
134735
+ );
134736
+ if (offset === null) return null;
134737
+ if (precedingNonWhitespace(site.initializer, offset) === "(") return null;
134738
+ stamps.push({ offset, id: id2 });
134739
+ }
134740
+ return stamps;
134741
+ }
134742
+ function precedingNonWhitespace(text, offset) {
134743
+ let index = offset - 1;
134744
+ while (index >= 0 && /\s/u.test(text[index] ?? "")) index -= 1;
134745
+ return text[index];
134746
+ }
134747
+ function committedValueAtPathReader(records2) {
134748
+ let rows;
134749
+ return (rootId, path) => {
134750
+ rows ??= storedValueRowsByIdV4(Object.values(records2));
134751
+ let id2 = rootId;
134752
+ for (const key of path) {
134753
+ const next = childValueId(rows.get(id2)?.value, key);
134754
+ if (next === null) return null;
134755
+ id2 = next;
134756
+ }
134757
+ return id2;
134758
+ };
134759
+ }
134760
+ function childValueId(body, key) {
134761
+ if (typeof key === "number") {
134762
+ const entry = Array.isArray(body) ? body[key] : void 0;
134763
+ return typeof entry === "string" ? entry : null;
134764
+ }
134765
+ const child = isObjectRecord2(body) ? body[key] : void 0;
134766
+ return typeof child === "string" ? child : null;
134767
+ }
134604
134768
  function sourceOffsetInsideInitializer(source, oneBasedLine, oneBasedColumn) {
134605
134769
  if (oneBasedLine < 1 || oneBasedColumn < 1) return null;
134606
134770
  let offset = 0;
@@ -134630,9 +134794,13 @@ function sourceOffsetAt2(source, line, character) {
134630
134794
  }
134631
134795
  return Math.min(offset + character, source.length);
134632
134796
  }
134633
- function sourceIndentationAt(source, offset) {
134797
+ function idStampText(source, offset, id2) {
134798
+ const annotation2 = `@id(${JSON.stringify(id2)})`;
134634
134799
  const lineStart = source.lastIndexOf("\n", Math.max(0, offset - 1)) + 1;
134635
- return /^[\t ]*/u.exec(source.slice(lineStart, offset))?.[0] ?? "";
134800
+ const prefix = source.slice(lineStart, offset);
134801
+ if (!/^[\t ]*$/u.test(prefix)) return `${annotation2} `;
134802
+ const newline = source.includes("\r\n") ? "\r\n" : "\n";
134803
+ return `${annotation2}${newline}${prefix}`;
134636
134804
  }
134637
134805
  async function buildPostPushCompileSchema(workspace, status) {
134638
134806
  const byKind = /* @__PURE__ */ new Map();
@@ -136574,8 +136742,7 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
136574
136742
  baseState.data,
136575
136743
  mainLocale
136576
136744
  );
136577
- const locallyDeleted = hasBaseline && baseState.file !== void 0 && local === void 0 && // Member-owned texts survive losing their last inline source reference.
136578
- !(serverRecord.recordKind === "localized-text" && isLocalizedText(baseState.data) && baseState.data.memberSource !== void 0);
136745
+ const locallyDeleted = hasBaseline && baseState.file !== void 0 && local === void 0 && !isSharedMemberText(baseState);
136579
136746
  if (!serverChanged) {
136580
136747
  plans.set(key, {
136581
136748
  emitData: locallyDeleted ? void 0 : local === void 0 ? serverRecord.data : mergeProjectDocumentRecord(
@@ -137303,7 +137470,6 @@ var init_pull = __esm({
137303
137470
  "src/commands/pull.ts"() {
137304
137471
  "use strict";
137305
137472
  init_push();
137306
- init_localization2();
137307
137473
  init_source_layout();
137308
137474
  init_project_read_base();
137309
137475
  init_document();
@@ -140444,7 +140610,7 @@ var init_registry2 = __esm({
140444
140610
  "schema-contract/registry.mjs"() {
140445
140611
  "use strict";
140446
140612
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
140447
- cliVersion: "0.58.0",
140613
+ cliVersion: "0.58.1",
140448
140614
  projectFileUploadBatchSize: 32,
140449
140615
  documentRecords: {
140450
140616
  member: {
@@ -144977,8 +145143,8 @@ function collectClassInstances(document, targetClassId, memberById2, valueById,
144977
145143
  const schema = schemaClass2 !== void 0 && isObjectRecord2(schemaClass2.schema) ? schemaClass2.schema : {};
144978
145144
  const instanceValue = valueRecord.value;
144979
145145
  if (isObjectRecord2(instanceValue)) {
144980
- for (const [key, childValueId] of Object.entries(instanceValue)) {
144981
- walk(schema[key], childValueId);
145146
+ for (const [key, childValueId2] of Object.entries(instanceValue)) {
145147
+ walk(schema[key], childValueId2);
144982
145148
  }
144983
145149
  }
144984
145150
  return;
@@ -144986,8 +145152,8 @@ function collectClassInstances(document, targetClassId, memberById2, valueById,
144986
145152
  if (memberKind === 6) {
144987
145153
  const entries = valueRecord.value;
144988
145154
  if (Array.isArray(entries)) {
144989
- for (const childValueId of entries) {
144990
- walk(member.entryMemberId, childValueId);
145155
+ for (const childValueId2 of entries) {
145156
+ walk(member.entryMemberId, childValueId2);
144991
145157
  }
144992
145158
  }
144993
145159
  return;
@@ -144995,8 +145161,8 @@ function collectClassInstances(document, targetClassId, memberById2, valueById,
144995
145161
  if (memberKind === 5) {
144996
145162
  const entries = valueRecord.value;
144997
145163
  if (isObjectRecord2(entries)) {
144998
- for (const childValueId of Object.values(entries)) {
144999
- walk(member.entryMemberId, childValueId);
145164
+ for (const childValueId2 of Object.values(entries)) {
145165
+ walk(member.entryMemberId, childValueId2);
145000
145166
  }
145001
145167
  }
145002
145168
  }
@@ -147012,10 +147178,10 @@ function dryrunOwnership(document, valueById, saveBindings = /* @__PURE__ */ new
147012
147178
  const childMemberByKey = new Map(
147013
147179
  storageResolver.mergedSchema(classId).map((entry) => [entry.schemaKey, entry.memberId])
147014
147180
  );
147015
- for (const [key, childValueId] of Object.entries(value.value)) {
147181
+ for (const [key, childValueId2] of Object.entries(value.value)) {
147016
147182
  const childMemberId = childMemberByKey.get(key);
147017
- if (childMemberId !== void 0 && typeof childValueId === "string") {
147018
- walkOwnedGraph([...memberPath3, childMemberId], childValueId);
147183
+ if (childMemberId !== void 0 && typeof childValueId2 === "string") {
147184
+ walkOwnedGraph([...memberPath3, childMemberId], childValueId2);
147019
147185
  }
147020
147186
  }
147021
147187
  return;
@@ -147024,9 +147190,9 @@ function dryrunOwnership(document, valueById, saveBindings = /* @__PURE__ */ new
147024
147190
  if (unorderedList && (Array.isArray(value.value) || includeHistoricalNullLists && membership.has(valueId))) {
147025
147191
  const entryMemberId = storageResolver.resolvedEntryMemberId(memberId);
147026
147192
  if (entryMemberId === void 0) return;
147027
- for (const childValueId of membership.get(valueId) ?? []) {
147028
- if (typeof childValueId === "string") {
147029
- walkOwnedGraph([...memberPath3, entryMemberId], childValueId);
147193
+ for (const childValueId2 of membership.get(valueId) ?? []) {
147194
+ if (typeof childValueId2 === "string") {
147195
+ walkOwnedGraph([...memberPath3, entryMemberId], childValueId2);
147030
147196
  }
147031
147197
  }
147032
147198
  return;
@@ -147035,9 +147201,9 @@ function dryrunOwnership(document, valueById, saveBindings = /* @__PURE__ */ new
147035
147201
  const entryMemberId = storageResolver.resolvedEntryMemberId(memberId);
147036
147202
  if (entryMemberId === void 0) return;
147037
147203
  const childIds = Array.isArray(value.value) ? value.value : Object.values(value.value);
147038
- for (const childValueId of childIds) {
147039
- if (typeof childValueId === "string") {
147040
- walkOwnedGraph([...memberPath3, entryMemberId], childValueId);
147204
+ for (const childValueId2 of childIds) {
147205
+ if (typeof childValueId2 === "string") {
147206
+ walkOwnedGraph([...memberPath3, entryMemberId], childValueId2);
147041
147207
  }
147042
147208
  }
147043
147209
  }
@@ -148265,7 +148431,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
148265
148431
  async function main() {
148266
148432
  const args = parseArgs(process.argv.slice(2));
148267
148433
  if (args.command === "--version") {
148268
- console.log("0.58.0");
148434
+ console.log("0.58.1");
148269
148435
  return;
148270
148436
  }
148271
148437
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.58.0",
3
+ "version": "0.58.1",
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.58.0 -->
12
+ <!-- reviewed-through-cli: 0.58.1 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -63,6 +63,8 @@ opaque JSON or guessed syntax.
63
63
  values, files, or other records. `@system` is reserved for platform-owned
64
64
  system records; authoring it can make the record uneditable.
65
65
  - Preserve existing `@id` annotations through rename, reorder, and file moves.
66
+ A new row cannot reuse a stored row's `@id`, including inside a new parent:
67
+ author the new row without it.
66
68
  - Omit `@id` on new ordinary declarations and nested rows unless a same-push
67
69
  structural reference genuinely requires an explicit UUID. A successful push
68
70
  assigns the durable IDs and rewrites source.
@@ -97,7 +97,7 @@ wrappers.
97
97
  The marker near the top of `SKILL.md` must exactly match the package version:
98
98
 
99
99
  ```html
100
- <!-- reviewed-through-cli: 0.58.0 -->
100
+ <!-- reviewed-through-cli: 0.58.1 -->
101
101
  ```
102
102
 
103
103
  The quoted version above is checked too, so this instruction cannot go stale
@@ -57,9 +57,11 @@ keys as quoted IDs when their option has been deleted.
57
57
 
58
58
  ## Identity rules
59
59
 
60
- Preserve every existing ID through rename, reorder, and file moves. For a new
61
- ordinary record, omit `@id` and let a successful real push assign and insert
62
- it. Dry-run and failed pushes leave tracked source unchanged.
60
+ Preserve every existing ID through rename, reorder, and file moves. A new row
61
+ cannot reuse a stored row's `@id`, including inside a new parent, and source
62
+ cannot place one stored row in two collection positions. For a new ordinary record, omit
63
+ `@id` and let a successful real push assign and insert it. Dry-run and failed pushes
64
+ leave tracked source unchanged.
63
65
 
64
66
  Nested class/list rows remain independently addressable and keep inline IDs:
65
67