@neocompose/cli 0.36.3 → 0.36.4

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.36.4] - 2026-08-19
4
+
5
+ ### Fixed
6
+
7
+ - Keep computed static/root binding value identities derived from their member
8
+ ids, so post-push source rewriting never inserts an `@id` inside the
9
+ initializer expression.
10
+ - Validate assigned-id source rewriting during `neo push --dry-run`, and keep
11
+ materialized scalar bindings stable so a successful push is followed by a
12
+ clean `neo status` without changing the authored initializer expression.
13
+
3
14
  ## [0.36.3] - 2026-08-19
4
15
 
5
16
  ### Fixed
package/dist/neo.mjs CHANGED
@@ -99654,7 +99654,7 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
99654
99654
  `Value ${path} in ${source.label} writes @id(${JSON.stringify(unattachedId)}) on part of a computed expression rather than on the row. Parenthesize the expression so the annotation names the whole row.`
99655
99655
  );
99656
99656
  }
99657
- if (annotated.id === null && isPendingId(valueId) && !context.pendingValueIdentitySites.has(valueId)) {
99657
+ if (annotated.id === null && isPendingId(valueId) && pendingMemberValueMemberId(valueId) === null && !context.pendingValueIdentitySites.has(valueId)) {
99658
99658
  context.pendingValueIdentitySites.set(valueId, {
99659
99659
  id: valueId,
99660
99660
  uri: source.source.uri,
@@ -100258,6 +100258,16 @@ function lowerValueRow(context, member, sourceExpression, expectedValueId, sourc
100258
100258
  }
100259
100259
  indexInitAuthoredRowIds(context, code, source.label);
100260
100260
  const storedConstructorArgs = isObjectRecord2(base.constructorArgs) ? base.constructorArgs : null;
100261
+ if (resolvedMember.kind !== "class" && isLiteralValueContent(base)) {
100262
+ addReconstructed(
100263
+ context,
100264
+ "value",
100265
+ expectedValueId,
100266
+ valueFileFields(base),
100267
+ source.source
100268
+ );
100269
+ return expectedValueId;
100270
+ }
100261
100271
  const materializedClass = resolvedMember.kind === "class" && isObjectRecord2(base.value);
100262
100272
  const effectiveClassId = resolvedMember.kind === "class" ? stringOrNull(base.classId) ?? resolvedMember.classId : null;
100263
100273
  const materializedPlainClass = materializedClass && effectiveClassId !== null && context.classes.get(effectiveClassId)?.requiredConstructorId === void 0;
@@ -112353,6 +112363,13 @@ async function prepareLocalPushArtifactsV4(workspace, status, onPhase = () => vo
112353
112363
  );
112354
112364
  let preparedChanges = null;
112355
112365
  if (options.fullValidation) {
112366
+ onPhase("Verifying the assigned-id source rewrite\u2026");
112367
+ materializeAssignedSchemaIdsInAuthoredSource(
112368
+ workspace,
112369
+ pendingAssignment.assigned,
112370
+ status.pendingValueIdentitySites,
112371
+ true
112372
+ );
112356
112373
  onPhase("Verifying the complete source round trip\u2026");
112357
112374
  verifyProjectSourceCommitAgainstStateV4({
112358
112375
  projectId: workspace.config.projectId,
@@ -113182,17 +113199,7 @@ function rewriteFilesFromState(workspace, records2 = new Map(
113182
113199
  return { uri: file.path, kind, text: file.content };
113183
113200
  })
113184
113201
  );
113185
- const finalErrors = finalAnalysis.diagnostics.filter(
113186
- (diagnostic) => diagnostic.severity === "error" && !isPullRecoveryDiagnosticCode(diagnostic.code)
113187
- );
113188
- if (finalErrors.length > 0) {
113189
- throw new Error(
113190
- `Assigned-id source rewrite produced invalid source:
113191
- ${finalErrors.map(
113192
- (diagnostic) => ` ${diagnostic.uri}:${diagnostic.range.start.line + 1}:${diagnostic.range.start.character + 1} ${diagnostic.message}`
113193
- ).join("\n")}`
113194
- );
113195
- }
113202
+ assertAssignedIdSourceRewriteValid(finalAnalysis);
113196
113203
  writeProjectSourceAnalysisCacheV4(workspace.root, finalAnalysis);
113197
113204
  const emittedPaths = new Set(files.map((file) => file.path));
113198
113205
  for (const recordState of Object.values(workspace.state.records)) {
@@ -113218,7 +113225,20 @@ ${finalErrors.map(
113218
113225
  workspace.state.records[key] = nextState;
113219
113226
  }
113220
113227
  }
113221
- function materializeAssignedSchemaIdsInAuthoredSource(workspace, replacements, pendingValueIdentitySites = /* @__PURE__ */ new Map()) {
113228
+ function assertAssignedIdSourceRewriteValid(analysis) {
113229
+ const finalErrors = analysis.diagnostics.filter(
113230
+ (diagnostic) => diagnostic.severity === "error" && !isPullRecoveryDiagnosticCode(diagnostic.code)
113231
+ );
113232
+ if (finalErrors.length > 0) {
113233
+ throw new Error(
113234
+ `Assigned-id source rewrite produced invalid source:
113235
+ ${finalErrors.map(
113236
+ (diagnostic) => ` ${diagnostic.uri}:${diagnostic.range.start.line + 1}:${diagnostic.range.start.character + 1} ${diagnostic.message}`
113237
+ ).join("\n")}`
113238
+ );
113239
+ }
113240
+ }
113241
+ function materializeAssignedSchemaIdsInAuthoredSource(workspace, replacements, pendingValueIdentitySites = /* @__PURE__ */ new Map(), validateResult = false) {
113222
113242
  const pendingIdsByUri = /* @__PURE__ */ new Map();
113223
113243
  for (const pendingId2 of replacements.keys()) {
113224
113244
  if (!isPendingId(pendingId2)) continue;
@@ -113394,6 +113414,16 @@ function materializeAssignedSchemaIdsInAuthoredSource(workspace, replacements, p
113394
113414
  }
113395
113415
  preserved.set(uri, source);
113396
113416
  }
113417
+ if (validateResult && preserved.size > 0) {
113418
+ assertAssignedIdSourceRewriteValid(
113419
+ compileNeoProjectSources(
113420
+ inputs.map((input) => ({
113421
+ ...input,
113422
+ text: preserved.get(input.uri) ?? input.text
113423
+ }))
113424
+ )
113425
+ );
113426
+ }
113397
113427
  return preserved;
113398
113428
  }
113399
113429
  function sourceOffsetInsideInitializer(source, oneBasedLine, oneBasedColumn) {
@@ -114010,7 +114040,7 @@ var init_registry2 = __esm({
114010
114040
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
114011
114041
  formatVersion: 3,
114012
114042
  contractVersion: "3.14",
114013
- cliVersion: "0.36.3",
114043
+ cliVersion: "0.36.4",
114014
114044
  projectFileUploadBatchSize: 32,
114015
114045
  documentRecords: {
114016
114046
  member: {
@@ -120612,7 +120642,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
120612
120642
  async function main() {
120613
120643
  const args = parseArgs(process.argv.slice(2));
120614
120644
  if (args.command === "--version") {
120615
- console.log("0.36.3");
120645
+ console.log("0.36.4");
120616
120646
  return;
120617
120647
  }
120618
120648
  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.36.3",
3
+ "version": "0.36.4",
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.36.3 -->
12
+ <!-- reviewed-through-cli: 0.36.4 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -83,7 +83,7 @@ wrappers.
83
83
  The marker near the top of `SKILL.md` must exactly match the package version:
84
84
 
85
85
  ```html
86
- <!-- reviewed-through-cli: 0.36.3 -->
86
+ <!-- reviewed-through-cli: 0.36.4 -->
87
87
  ```
88
88
 
89
89
  The quoted version above is checked too, so this instruction cannot go stale