@neocompose/cli 0.21.1 → 0.21.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.21.2] - 2026-08-03
4
+
5
+ ### Fixed
6
+
7
+ - Canonical pull emits `@id` only for structurally ambiguous positions such
8
+ as list entries. Class fields, dictionary entries, and constructor arguments
9
+ recover their value rows from the owning value and role instead of exposing
10
+ redundant P61 creation or localization-link identities.
11
+ - Long and nested constructor calls emitted by `neo pull --reset` wrap at a
12
+ stable 88-column default with one named argument per indented line.
13
+
3
14
  ## [0.21.1] - 2026-08-03
4
15
 
5
16
  ### Fixed
package/dist/neo.mjs CHANGED
@@ -75392,7 +75392,6 @@ function buildValueEmitContext(records2, manifest) {
75392
75392
  )
75393
75393
  ),
75394
75394
  fileSymbols: projectFileSymbols(records2),
75395
- referencedValueIds: externallyReferencedValueIds(records2),
75396
75395
  localizedTextIds: /* @__PURE__ */ new Set(),
75397
75396
  constructionReplays: /* @__PURE__ */ new Map()
75398
75397
  };
@@ -79235,7 +79234,10 @@ function classValue(context, member, value, visited, targetTyped, outerEnvironme
79235
79234
  `${key} = ${emitValue(context, emittedChildMember, childId, {
79236
79235
  environment,
79237
79236
  definitionSite: !context.symbolsByValueId.has(childId),
79238
- writeIdentity: !context.symbolsByValueId.has(childId) && context.referencedValueIds.has(childId),
79237
+ // A class slot recovers this row from the owning value and schema key.
79238
+ // P61 creation metadata and localization back-pointers must not turn
79239
+ // that structural child into an explicitly identified source value.
79240
+ writeIdentity: false,
79239
79241
  visited
79240
79242
  })}`
79241
79243
  );
@@ -79245,7 +79247,7 @@ function classValue(context, member, value, visited, targetTyped, outerEnvironme
79245
79247
  ${fields.map((field) => indentNeoSourceNonEmptyLines(field, 2)).join(",\n")}
79246
79248
  }`;
79247
79249
  }
79248
- const constructor2 = storedConstruction !== null ? storedConstruction : projection.arguments.length > 0 ? `new ${name}(${projection.arguments.join(", ")})` : targetTyped ? "new()" : `new ${name}()`;
79250
+ const constructor2 = storedConstruction !== null ? storedConstruction : projection.arguments.length > 0 ? constructorCallSource(`new ${name}`, projection.arguments) : targetTyped ? "new()" : `new ${name}()`;
79249
79251
  return fields.length === 0 ? constructor2 : `${storedConstruction !== null || projection.arguments.length > 0 ? constructor2 : targetTyped ? "new()" : `new ${name}`} {
79250
79252
  ${fields.map((field) => indentNeoSourceNonEmptyLines(field, 2)).join(",\n")}
79251
79253
  }`;
@@ -79322,7 +79324,16 @@ function storedConstructorCallSource(context, schemaClass2, value, className, en
79322
79324
  cloneAggregateArguments
79323
79325
  )}`;
79324
79326
  });
79325
- return argumentsValue.length === 0 && targetTyped ? "new()" : `new ${className}(${argumentsValue.join(", ")})`;
79327
+ return argumentsValue.length === 0 && targetTyped ? "new()" : constructorCallSource(`new ${className}`, argumentsValue);
79328
+ }
79329
+ function constructorCallSource(callee, argumentsValue) {
79330
+ const inline = `${callee}(${argumentsValue.join(", ")})`;
79331
+ if (!argumentsValue.some((argument2) => argument2.includes("\n")) && inline.length <= CANONICAL_CONSTRUCTOR_INLINE_WIDTH) {
79332
+ return inline;
79333
+ }
79334
+ return `${callee}(
79335
+ ${argumentsValue.map((argument2) => `${indentNeoSourceNonEmptyLines(argument2, 2)},`).join("\n")}
79336
+ )`;
79326
79337
  }
79327
79338
  function storedValueConstructor(context, schemaClass2, constructorArgs) {
79328
79339
  const requiredId = schemaClass2.requiredConstructorId;
@@ -79419,7 +79430,14 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
79419
79430
  if (cloneAggregateArguments) {
79420
79431
  return storedAggregateCloneSource(context, type, value, environment);
79421
79432
  }
79422
- return storedTypedRowSource(context, type, value, environment, visited);
79433
+ return storedTypedRowSource(
79434
+ context,
79435
+ type,
79436
+ value,
79437
+ environment,
79438
+ visited,
79439
+ false
79440
+ );
79423
79441
  }
79424
79442
  case "interface":
79425
79443
  case "generic":
@@ -79433,7 +79451,14 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
79433
79451
  if (cloneAggregateArguments) {
79434
79452
  return storedAggregateCloneSource(context, type, value, environment);
79435
79453
  }
79436
- return storedTypedRowSource(context, type, value, environment, visited);
79454
+ return storedTypedRowSource(
79455
+ context,
79456
+ type,
79457
+ value,
79458
+ environment,
79459
+ visited,
79460
+ false
79461
+ );
79437
79462
  case "lookup":
79438
79463
  return referenceValue(
79439
79464
  context,
@@ -79552,7 +79577,7 @@ function storedSchemaTypeName(context, type, environment, valueId) {
79552
79577
  return "null";
79553
79578
  }
79554
79579
  }
79555
- function storedTypedRowSource(context, type, valueId, environment, visited) {
79580
+ function storedTypedRowSource(context, type, valueId, environment, visited, writeIdentity) {
79556
79581
  const symbol = context.symbolsByValueId.get(valueId);
79557
79582
  if (symbol !== void 0) return symbol;
79558
79583
  const row = context.values.get(valueId);
@@ -79575,32 +79600,34 @@ function storedTypedRowSource(context, type, valueId, environment, visited) {
79575
79600
  `Stored ${type.kind} constructor argument ${valueId} has no concrete class.`
79576
79601
  );
79577
79602
  }
79578
- return `@id(${quote4(valueId)})
79579
- ${classValue(
79580
- context,
79581
- {
79582
- id: `__constructor_arg__:${valueId}`,
79583
- name: "argument",
79584
- kind: 7 /* Class */,
79585
- classId,
79586
- classArguments: {},
79587
- partial: false
79588
- },
79589
- row,
79590
- visited,
79591
- false,
79592
- environment
79593
- )}`;
79603
+ return storedRowIdentitySource(
79604
+ valueId,
79605
+ writeIdentity,
79606
+ classValue(
79607
+ context,
79608
+ {
79609
+ id: `__constructor_arg__:${valueId}`,
79610
+ name: "argument",
79611
+ kind: 7 /* Class */,
79612
+ classId,
79613
+ classArguments: {},
79614
+ partial: false
79615
+ },
79616
+ row,
79617
+ visited,
79618
+ false,
79619
+ environment
79620
+ )
79621
+ );
79594
79622
  }
79595
79623
  if (type.kind === "list") {
79596
- if (row.value === null) return "null";
79624
+ if (row.value === null) {
79625
+ return storedRowIdentitySource(valueId, writeIdentity, "null");
79626
+ }
79597
79627
  const ids = Array.isArray(row.value) ? row.value.filter(
79598
79628
  (entry) => typeof entry === "string"
79599
79629
  ) : [...context.values].filter(([, candidate]) => candidate.containerId === valueId).map(([id2]) => id2).sort(compareCodePoints);
79600
- if (ids.length === 0) return `@id(${quote4(valueId)})
79601
- []`;
79602
- return `@id(${quote4(valueId)})
79603
- [
79630
+ const expression = ids.length === 0 ? "[]" : `[
79604
79631
  ${ids.map(
79605
79632
  (id2) => indentNeoSourceNonEmptyLines(
79606
79633
  storedTypedRowSource(
@@ -79608,22 +79635,26 @@ ${ids.map(
79608
79635
  type.entryType,
79609
79636
  id2,
79610
79637
  environment,
79611
- visited
79638
+ visited,
79639
+ true
79612
79640
  ),
79613
79641
  2
79614
79642
  )
79615
79643
  ).join(",\n\n")}
79616
79644
  ]`;
79645
+ return storedRowIdentitySource(valueId, writeIdentity, expression);
79617
79646
  }
79618
79647
  if (type.kind === "dictionary") {
79619
- if (row.value === null) return "null";
79620
- if (!isObjectRecord2(row.value)) return "{}";
79648
+ if (row.value === null) {
79649
+ return storedRowIdentitySource(valueId, writeIdentity, "null");
79650
+ }
79651
+ if (!isObjectRecord2(row.value)) {
79652
+ return storedRowIdentitySource(valueId, writeIdentity, "{}");
79653
+ }
79621
79654
  const entries = Object.entries(row.value).sort(
79622
79655
  ([left], [right]) => compareCodePoints(left, right)
79623
79656
  );
79624
- return entries.length === 0 ? `@id(${quote4(valueId)})
79625
- {}` : `@id(${quote4(valueId)})
79626
- {
79657
+ const expression = entries.length === 0 ? "{}" : `{
79627
79658
  ${entries.flatMap(
79628
79659
  ([key, id2]) => typeof id2 === "string" ? [
79629
79660
  indentNeoSourceNonEmptyLines(
@@ -79632,53 +79663,71 @@ ${entries.flatMap(
79632
79663
  type.entryType,
79633
79664
  id2,
79634
79665
  environment,
79635
- visited
79666
+ visited,
79667
+ false
79636
79668
  )}`,
79637
79669
  2
79638
79670
  )
79639
79671
  ] : []
79640
79672
  ).join(",\n")}
79641
79673
  }`;
79674
+ return storedRowIdentitySource(valueId, writeIdentity, expression);
79642
79675
  }
79643
79676
  if (type.kind === "lookup") {
79644
- return referenceValue(
79645
- context,
79646
- {
79647
- id: `__constructor_arg__:${valueId}`,
79648
- name: "argument",
79649
- kind: 9 /* Lookup */,
79650
- collectionMemberId: type.collectionMemberId,
79651
- collectionValueId: type.collectionValueId,
79652
- multiselect: false
79653
- },
79654
- row.value,
79655
- false
79677
+ return storedRowIdentitySource(
79678
+ valueId,
79679
+ writeIdentity,
79680
+ referenceValue(
79681
+ context,
79682
+ {
79683
+ id: `__constructor_arg__:${valueId}`,
79684
+ name: "argument",
79685
+ kind: 9 /* Lookup */,
79686
+ collectionMemberId: type.collectionMemberId,
79687
+ collectionValueId: type.collectionValueId,
79688
+ multiselect: false
79689
+ },
79690
+ row.value,
79691
+ false
79692
+ )
79656
79693
  );
79657
79694
  }
79658
79695
  if (type.kind === "dialogueLookup") {
79659
- return referenceValue(
79660
- context,
79661
- {
79662
- id: `__constructor_arg__:${valueId}`,
79663
- name: "argument",
79664
- kind: 18 /* DialogueLookup */,
79665
- multiselect: false
79666
- },
79667
- row.value,
79668
- true
79696
+ return storedRowIdentitySource(
79697
+ valueId,
79698
+ writeIdentity,
79699
+ referenceValue(
79700
+ context,
79701
+ {
79702
+ id: `__constructor_arg__:${valueId}`,
79703
+ name: "argument",
79704
+ kind: 18 /* DialogueLookup */,
79705
+ multiselect: false
79706
+ },
79707
+ row.value,
79708
+ true
79709
+ )
79669
79710
  );
79670
79711
  }
79671
- return storedConstructorArgumentSource(
79672
- context,
79673
- type,
79674
- row.value,
79675
- environment,
79676
- visited
79712
+ return storedRowIdentitySource(
79713
+ valueId,
79714
+ writeIdentity,
79715
+ storedConstructorArgumentSource(
79716
+ context,
79717
+ type,
79718
+ row.value,
79719
+ environment,
79720
+ visited
79721
+ )
79677
79722
  );
79678
79723
  } finally {
79679
79724
  visited.delete(valueId);
79680
79725
  }
79681
79726
  }
79727
+ function storedRowIdentitySource(valueId, writeIdentity, expression) {
79728
+ return `${writeIdentity ? `@id(${quote4(valueId)})
79729
+ ` : ""}${expression}`;
79730
+ }
79682
79731
  function storedVectorSource(value, name, keys) {
79683
79732
  if (!isObjectRecord2(value)) {
79684
79733
  throw new Error(`Stored ${name} constructor argument is not an object.`);
@@ -80001,7 +80050,9 @@ ${entries.flatMap(
80001
80050
  `${quote4(key)}: ${emitValue(context, entryMember, id2, {
80002
80051
  environment,
80003
80052
  definitionSite: !context.symbolsByValueId.has(id2),
80004
- writeIdentity: !context.symbolsByValueId.has(id2) && context.referencedValueIds.has(id2),
80053
+ // Dictionary keys, like class schema keys, recover entry
80054
+ // identity from the owning row. Only list entries need an id.
80055
+ writeIdentity: false,
80005
80056
  visited
80006
80057
  })}`,
80007
80058
  2
@@ -80215,33 +80266,6 @@ function projectFileSymbols(records2) {
80215
80266
  });
80216
80267
  return assignDeterministicFileSymbols(files);
80217
80268
  }
80218
- function externallyReferencedValueIds(records2) {
80219
- const counts = /* @__PURE__ */ new Map();
80220
- const visit = (value) => {
80221
- if (typeof value === "string") {
80222
- if (records2.has(`value:${value}`))
80223
- counts.set(value, (counts.get(value) ?? 0) + 1);
80224
- return;
80225
- }
80226
- if (Array.isArray(value)) {
80227
- value.forEach((entry) => visit(entry));
80228
- return;
80229
- }
80230
- if (isObjectRecord2(value)) {
80231
- for (const [childKey, child] of Object.entries(value)) {
80232
- if (childKey === "id") continue;
80233
- if (childKey === "sourceValueId") continue;
80234
- visit(child);
80235
- }
80236
- }
80237
- };
80238
- for (const record3 of records2.values()) {
80239
- if (!record3.deleted) visit(record3.data);
80240
- }
80241
- return new Set(
80242
- [...counts].filter(([, count]) => count > 1).map(([id2]) => id2)
80243
- );
80244
- }
80245
80269
  function projectMainLocale(records2) {
80246
80270
  const config = [...records2.values()].find(
80247
80271
  (record3) => !record3.deleted && record3.recordKind === "localization-config"
@@ -80330,7 +80354,7 @@ function memberDefaultBody(member) {
80330
80354
  if (!("value" in defaultValue)) return null;
80331
80355
  return defaultValue.value;
80332
80356
  }
80333
- var INFERRED_GENERIC_CLASS_PREFIX, MEMBER_KIND_DICTIONARY, MEMBER_KIND_LIST, MEMBER_KIND_CLASS;
80357
+ var INFERRED_GENERIC_CLASS_PREFIX, MEMBER_KIND_DICTIONARY, MEMBER_KIND_LIST, MEMBER_KIND_CLASS, CANONICAL_CONSTRUCTOR_INLINE_WIDTH;
80334
80358
  var init_value_sources = __esm({
80335
80359
  "src/project-source/value-sources.ts"() {
80336
80360
  "use strict";
@@ -80356,6 +80380,7 @@ var init_value_sources = __esm({
80356
80380
  MEMBER_KIND_DICTIONARY = 5;
80357
80381
  MEMBER_KIND_LIST = 6;
80358
80382
  MEMBER_KIND_CLASS = 7;
80383
+ CANONICAL_CONSTRUCTOR_INLINE_WIDTH = 88;
80359
80384
  }
80360
80385
  });
80361
80386
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.21.1",
3
+ "version": "0.21.2",
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.21.1 -->
12
+ <!-- reviewed-through-cli: 0.21.2 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -73,7 +73,7 @@ wrappers.
73
73
  The marker near the top of `SKILL.md` must exactly match the package version:
74
74
 
75
75
  ```html
76
- <!-- reviewed-through-cli: 0.21.1 -->
76
+ <!-- reviewed-through-cli: 0.21.2 -->
77
77
  ```
78
78
 
79
79
  The quoted version above is checked too, so this instruction cannot go stale