[GH-ISSUE #5195] [Bug] compare-application-versions reports unchanged module exports as removed and added #3187

Closed
opened 2026-10-31 00:37:39 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @rodricksz4h5 on GitHub (Oct 19, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/5195

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

compare-application-versions (and MCP compare_application_versions) reports every module export of an unchanged file as removed and added with match basis none, while coverage is complete-within-inputs. Because those export nodes never pair, the source modules that expose them fall to unknown even when they have an exact-module-source-digest match. This happens for any two versions that differ in any file, so in practice for every real comparison of a JavaScript package or Electron app whose files export anything.

#3188 fixed the same symptom for source modules; its reproduction used a file with no exports.

Reproduction

  1. Two copies of an app: package.json ("main": "src/main.js"), src/main.js (const util = require("./util.js"); module.exports = { start: () => util.greet() };), src/util.js (module.exports = { greet: () => 1 };). In the second copy change only package.json's version.
  2. rea analyze-javascript-application <dir> --json for each.
  3. rea compare-application-versions <file with {"left":…,"right":…}> --json.

Expected behavior

The exports of the byte-identical files, and the modules exposing them, are unchanged, as the source modules of byte-identical files already are after #3188.

Impact and scope

Every export of an unchanged file is reported as removed plus added, and modules become unknown, on every comparison where any file differs. Observed on each run, CLI and MCP (same domain function). Exports of edited files were not expected to pair and do not.

REA version

main 2e5171e3

Runtime and platform

Node 24.18.0, Linux (node:24.18.0-bookworm), REA built from source

Target and artifact context

Generated two-file CommonJS application directories

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

main 2e5171e3, the two copies above (REA built from source on Linux): summary {"unchanged":1,"added":3,"removed":3,"changed":2,"unknown":4}, coverage complete-within-inputs. Both exports are listed once removed and once added (basis none); both modules are unknown although each has an exact-module-source-digest match.

Analysis or suspected cause

Source-derived: addExportRelationship (src/application/javascript/JavaScriptModuleRelationships.ts) keys an export node with compositeKey([file.container_sha256, file.path, exportedName]), and container_sha256 is the digest of the whole application root, so the node id changes when any sibling changes. In src/domain/javascript/javascriptApplicationVersionKeys.ts, moduleSourceDigestKey pairs only nodes with a source_sha256 property (source modules), and semanticKey skips javascript-module, so no tier pairs export bindings.

Additional context

Searched issues and PRs (open and closed) for application version export comparisons; checked the files of all 568 open PRs: none changes moduleSourceDigestKey or export node identity (#2978, #2986, #2702, #2092, #4536, #4020 touch the same files for other reasons).

Originally created by @rodricksz4h5 on GitHub (Oct 19, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5195 ### Before submitting - [X] I searched the open and closed issues for a related report. - [X] I removed credentials, tokens, private paths, and sensitive target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior `compare-application-versions` (and MCP `compare_application_versions`) reports every module export of an unchanged file as `removed` and `added` with match basis `none`, while coverage is `complete-within-inputs`. Because those export nodes never pair, the source modules that expose them fall to `unknown` even when they have an `exact-module-source-digest` match. This happens for any two versions that differ in any file, so in practice for every real comparison of a JavaScript package or Electron app whose files export anything. #3188 fixed the same symptom for source modules; its reproduction used a file with no exports. ### Reproduction 1. Two copies of an app: `package.json` (`"main": "src/main.js"`), `src/main.js` (`const util = require("./util.js"); module.exports = { start: () => util.greet() };`), `src/util.js` (`module.exports = { greet: () => 1 };`). In the second copy change only `package.json`'s `version`. 2. `rea analyze-javascript-application <dir> --json` for each. 3. `rea compare-application-versions <file with {"left":…,"right":…}> --json`. ### Expected behavior The exports of the byte-identical files, and the modules exposing them, are `unchanged`, as the source modules of byte-identical files already are after #3188. ### Impact and scope Every export of an unchanged file is reported as removed plus added, and modules become `unknown`, on every comparison where any file differs. Observed on each run, CLI and MCP (same domain function). Exports of edited files were not expected to pair and do not. ### REA version main 2e5171e3 ### Runtime and platform Node 24.18.0, Linux (`node:24.18.0-bookworm`), REA built from source ### Target and artifact context Generated two-file CommonJS application directories ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence main 2e5171e3, the two copies above (REA built from source on Linux): `summary {"unchanged":1,"added":3,"removed":3,"changed":2,"unknown":4}`, coverage `complete-within-inputs`. Both exports are listed once `removed` and once `added` (basis `none`); both modules are `unknown` although each has an `exact-module-source-digest` match. ### Analysis or suspected cause Source-derived: `addExportRelationship` (`src/application/javascript/JavaScriptModuleRelationships.ts`) keys an export node with `compositeKey([file.container_sha256, file.path, exportedName])`, and `container_sha256` is the digest of the whole application root, so the node id changes when any sibling changes. In `src/domain/javascript/javascriptApplicationVersionKeys.ts`, `moduleSourceDigestKey` pairs only nodes with a `source_sha256` property (source modules), and `semanticKey` skips `javascript-module`, so no tier pairs export bindings. ### Additional context Searched issues and PRs (open and closed) for application version export comparisons; checked the files of all 568 open PRs: none changes `moduleSourceDigestKey` or export node identity (#2978, #2986, #2702, #2092, #4536, #4020 touch the same files for other reasons).
Author
Owner

@XinwangTao commented on GitHub (Oct 19, 2026):

Clear root-cause isolation. The container-level sha256 in the export node identity is the crux — a sibling change reshuffles every export node id, so byte-identical files' exports can never pair. Pairing exports by file-level digest + exported name (mirroring what #3188 did for source modules) should fix both the removed/added noise and the modules falling to unknown. Also nice that you checked the open PRs touching those files — that de-risks the fix. +1 to #5196.

<!-- gh-comment-id:6262701409 --> @XinwangTao commented on GitHub (Oct 19, 2026): Clear root-cause isolation. The container-level sha256 in the export node identity is the crux — a sibling change reshuffles every export node id, so byte-identical files' exports can never pair. Pairing exports by file-level digest + exported name (mirroring what #3188 did for source modules) should fix both the removed/added noise and the modules falling to unknown. Also nice that you checked the open PRs touching those files — that de-risks the fix. +1 to #5196.
Author
Owner

@matbrgz commented on GitHub (Oct 20, 2026):

Cross-referencing with sibling version comparison reports in Cluster AO: #4681 ([Bug] Application version comparison treats unresolved relationship targets as aligned) and #5406. Both isolate how export and endpoint node identities are paired during application diffing.

Consolidated under Cluster AO (Application Version Diffing & Endpoint Comparison Anomalies) in tracker #4330.

<!-- gh-comment-id:6291596059 --> @matbrgz commented on GitHub (Oct 20, 2026): Cross-referencing with sibling version comparison reports in **Cluster AO**: #4681 (`[Bug] Application version comparison treats unresolved relationship targets as aligned`) and #5406. Both isolate how export and endpoint node identities are paired during application diffing. Consolidated under **Cluster AO (Application Version Diffing & Endpoint Comparison Anomalies)** in tracker #4330.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3187
No description provided.