[GH-ISSUE #7380] [Bug] Electron IPC pairing drops to zero when a container has module gaps #4387

Closed
opened 2026-10-31 00:49:25 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @akshad-exe on GitHub (Oct 27, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/7380

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

On clean main at bfdde7ee4 (and f87826650), the Electron boundary fixture test fails:

tests/boundary/filesystem/javascript-applications/electronApplicationAnalysis.test.ts > "maps windows, preload, contextBridge, IPC, validations, utility, and native boundaries without execution" at tests/boundary/filesystem/javascript-applications/electronApplicationAnalysis.test.ts:44.

- "ambiguous_renderer_transmissions": 1,
+ "ambiguous_renderer_transmissions": 7,
- "paired_renderer_transmissions": 4,
+ "paired_renderer_transmissions": 0,
- "unpaired_literal_renderer_transmissions": 1,
+ "unpaired_literal_renderer_transmissions": 0,

No renderer transmission pairs with its handler, and rea:missing is reported ambiguous instead of unpaired. This is a local, source-built observation; CI did not report it because the shard that owns this file was cancelled on the inspected runs.

Reproduction

  1. Check out bfdde7ee4 in a worktree and build (npm ci, npm run build:cached).
  2. Run ./node_modules/.bin/vitest run --project boundary tests/boundary/filesystem/javascript-applications/electronApplicationAnalysis.test.ts with Node 24.22.1.
  3. Observe the summary mismatch above. Reproduced 3/3 runs, with TMPDIR on the home filesystem and with the default /tmp.

The fixture is tests/fixtures/electronBoundaryApplication.ts: one package.json with main: "main.js", plus preload.js and renderer/renderer.js.

Expected behavior

The fixture's preload.js and renderer/renderer.js belong to the only application root in the container, so their literal ipcRenderer.invoke/send calls should pair with the same app's ipcMain.handle/on handlers, which is what the test expects. This matches the documented ownership rule in applicationRootPath: inventoried ancestor packages are candidates, and only multiple candidates stay unknown.

Impact and scope

Observed: IPC pairing and join-electron-wrapper-paths joins disappear for this fixture, so all renderer transmissions become ambiguous. Source-derived reasoning indicates the same happens for ordinary directory apps:

  • require("electron") (and other bare specifiers that do not resolve to an inventoried file) records the referencing file in applicationModuleGapSources via addReference.
  • applicationRootPath then returns null for every file in that container without proven entry roots (src/application/javascript/JavaScriptArtifactGraphContext.ts:131-135), which covers preload scripts and HTML-referenced renderer scripts.
  • createElectronIpcContext treats a null owner as uncertain, so no transmission can pair (src/application/javascript/ElectronBoundaryAnalysis.ts:83-97).

No real Electron application was run, so real-app impact and frequency are unverified. Severity, evidence-integrity effects, and whether other ownership consumers are affected are unknown.

REA version

Source revision bfdde7ee4; also reproduced at f87826650.

Runtime and platform

Node 24.22.1; Linux x64; no provider involved.

Target and artifact context

JavaScript/Electron directory fixture (app-style directory with one manifest), not a real application.

Interface

CLI

Earliest failure stage

Artifact or evidence registration

Relevant output or evidence

Command actually run:

TMPDIR=<home-fs dir> ./node_modules/.bin/vitest run --project boundary \
  tests/boundary/filesystem/javascript-applications/electronApplicationAnalysis.test.ts

Source references:

  • src/application/javascript/JavaScriptArtifactGraphContext.ts:117-161 — applicationRootPath, including the early return null for containers with module gaps.
  • src/application/javascript/ElectronBoundaryAnalysis.ts:55-106 — createElectronIpcContext requires a proven owner.
  • src/application/javascript/JavaScriptArtifactGraphFindings.ts:87-102 — possible owners are seeded from gap sources.
  • aa253bd13 ("fix(electron): scope IPC pairing to application ownership") made pairing require owners; the null-returning rule predates it (e9fc8fb30).

Temporary instrumentation on the fixture (removed before reporting) showed, for preload.js:

{"path":"preload.js","entry":[],"possible":[""],"gaps":["main.js","preload.js","utility/worker.js"]}

Missing evidence: no real-app run, no CI job that executed this file, and no history bisect beyond identifying the two commits above.

Typed outcome or recovery expected

Not applicable; this is a projection result, not a typed error.

Analysis or suspected cause

Source-derived: the gap check in applicationRootPath is broader than the ambiguity it is meant to represent. When the container's only possible root is the source's own ancestor package root, ownership is not ambiguous, but the function returns null before computing those ancestor candidates. aa253bd13 did not introduce the null, it only made IPC pairing consume it, which is why the failure appears now.

Hypothesis (unverified): excluding resolved-external specifiers such as electron from applicationModuleGapSources, or comparing possible roots against the ancestor-package candidates instead of requiring proven entry roots, restores pairing without weakening the documented distinct-owner and unknown-owner cases. Either change needs a check against the cases in tests/boundary/cli/electronScopedIpc.test.ts.

Additional context

Last known good: before aa253bd13, the test passed because classifyElectronIpcPairings paired literal channels without consulting ownership. First known bad: aa253bd13.

Proposed checks (not run): the fixture above, the three ownership cases in tests/boundary/cli/electronScopedIpc.test.ts, and a single-root variant of the same fixture once the fix is chosen.

Originally created by @akshad-exe on GitHub (Oct 27, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7380 ### 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 On clean `main` at `bfdde7ee4` (and `f87826650`), the Electron boundary fixture test fails: `tests/boundary/filesystem/javascript-applications/electronApplicationAnalysis.test.ts` > "maps windows, preload, contextBridge, IPC, validations, utility, and native boundaries without execution" at `tests/boundary/filesystem/javascript-applications/electronApplicationAnalysis.test.ts:44`. ``` - "ambiguous_renderer_transmissions": 1, + "ambiguous_renderer_transmissions": 7, - "paired_renderer_transmissions": 4, + "paired_renderer_transmissions": 0, - "unpaired_literal_renderer_transmissions": 1, + "unpaired_literal_renderer_transmissions": 0, ``` No renderer transmission pairs with its handler, and `rea:missing` is reported ambiguous instead of unpaired. This is a local, source-built observation; CI did not report it because the shard that owns this file was cancelled on the inspected runs. ### Reproduction 1. Check out `bfdde7ee4` in a worktree and build (`npm ci`, `npm run build:cached`). 2. Run `./node_modules/.bin/vitest run --project boundary tests/boundary/filesystem/javascript-applications/electronApplicationAnalysis.test.ts` with Node 24.22.1. 3. Observe the summary mismatch above. Reproduced 3/3 runs, with `TMPDIR` on the home filesystem and with the default `/tmp`. The fixture is `tests/fixtures/electronBoundaryApplication.ts`: one `package.json` with `main: "main.js"`, plus `preload.js` and `renderer/renderer.js`. ### Expected behavior The fixture's `preload.js` and `renderer/renderer.js` belong to the only application root in the container, so their literal `ipcRenderer.invoke`/`send` calls should pair with the same app's `ipcMain.handle`/`on` handlers, which is what the test expects. This matches the documented ownership rule in `applicationRootPath`: inventoried ancestor packages are candidates, and only multiple candidates stay unknown. ### Impact and scope Observed: IPC pairing and `join-electron-wrapper-paths` joins disappear for this fixture, so all renderer transmissions become ambiguous. Source-derived reasoning indicates the same happens for ordinary directory apps: - `require("electron")` (and other bare specifiers that do not resolve to an inventoried file) records the referencing file in `applicationModuleGapSources` via `addReference`. - `applicationRootPath` then returns `null` for every file in that container without proven entry roots (`src/application/javascript/JavaScriptArtifactGraphContext.ts:131-135`), which covers preload scripts and HTML-referenced renderer scripts. - `createElectronIpcContext` treats a `null` owner as uncertain, so no transmission can pair (`src/application/javascript/ElectronBoundaryAnalysis.ts:83-97`). No real Electron application was run, so real-app impact and frequency are unverified. Severity, evidence-integrity effects, and whether other ownership consumers are affected are unknown. ### REA version Source revision `bfdde7ee4`; also reproduced at `f87826650`. ### Runtime and platform Node 24.22.1; Linux x64; no provider involved. ### Target and artifact context JavaScript/Electron directory fixture (`app`-style directory with one manifest), not a real application. ### Interface CLI ### Earliest failure stage Artifact or evidence registration ### Relevant output or evidence Command actually run: ``` TMPDIR=<home-fs dir> ./node_modules/.bin/vitest run --project boundary \ tests/boundary/filesystem/javascript-applications/electronApplicationAnalysis.test.ts ``` Source references: - `src/application/javascript/JavaScriptArtifactGraphContext.ts:117-161` — `applicationRootPath`, including the early `return null` for containers with module gaps. - `src/application/javascript/ElectronBoundaryAnalysis.ts:55-106` — `createElectronIpcContext` requires a proven owner. - `src/application/javascript/JavaScriptArtifactGraphFindings.ts:87-102` — possible owners are seeded from gap sources. - `aa253bd13` ("fix(electron): scope IPC pairing to application ownership") made pairing require owners; the `null`-returning rule predates it (`e9fc8fb30`). Temporary instrumentation on the fixture (removed before reporting) showed, for `preload.js`: ``` {"path":"preload.js","entry":[],"possible":[""],"gaps":["main.js","preload.js","utility/worker.js"]} ``` Missing evidence: no real-app run, no CI job that executed this file, and no history bisect beyond identifying the two commits above. ### Typed outcome or recovery expected Not applicable; this is a projection result, not a typed error. ### Analysis or suspected cause Source-derived: the gap check in `applicationRootPath` is broader than the ambiguity it is meant to represent. When the container's only possible root is the source's own ancestor package root, ownership is not ambiguous, but the function returns `null` before computing those ancestor candidates. `aa253bd13` did not introduce the `null`, it only made IPC pairing consume it, which is why the failure appears now. Hypothesis (unverified): excluding resolved-external specifiers such as `electron` from `applicationModuleGapSources`, or comparing possible roots against the ancestor-package candidates instead of requiring proven entry roots, restores pairing without weakening the documented distinct-owner and unknown-owner cases. Either change needs a check against the cases in `tests/boundary/cli/electronScopedIpc.test.ts`. ### Additional context Last known good: before `aa253bd13`, the test passed because `classifyElectronIpcPairings` paired literal channels without consulting ownership. First known bad: `aa253bd13`. Proposed checks (not run): the fixture above, the three ownership cases in `tests/boundary/cli/electronScopedIpc.test.ts`, and a single-root variant of the same fixture once the fix is chosen.
Author
Owner

@gensokyo-dev commented on GitHub (Oct 29, 2026):

The reported regression no longer reproduces on current main d157560d40. Executed:

npm run test:focused -- tests/boundary/filesystem/javascript-applications/electronApplicationAnalysis.test.ts tests/boundary/cli/electronScopedIpc.test.ts

Both files passed: 20 tests, including the exact failing fixture, proven-owner pairing, distinct/shared unknown owners, scoped handlers, and unexamined external-package effects through CLI and stdio MCP. The existing shared handling now distinguishes Electron/builtins from unexamined package effects; #7950 retains the latter as unknown. No ownership guard was weakened and no new code change is needed for this report.

Scope: these are the repository fixture and public-adapter regressions on Linux x64 / Node 24.22.1, not real-Electron execution or a claim that every module-gap scenario can be paired.

<!-- gh-comment-id:6488980720 --> @gensokyo-dev commented on GitHub (Oct 29, 2026): The reported regression no longer reproduces on current main d157560d402fbd1b54069ff59039dcde73e4a7e1. Executed: ``` npm run test:focused -- tests/boundary/filesystem/javascript-applications/electronApplicationAnalysis.test.ts tests/boundary/cli/electronScopedIpc.test.ts ``` Both files passed: 20 tests, including the exact failing fixture, proven-owner pairing, distinct/shared unknown owners, scoped handlers, and unexamined external-package effects through CLI and stdio MCP. The existing shared handling now distinguishes Electron/builtins from unexamined package effects; [#7950](https://github.com/morluto/rea/pull/7950) retains the latter as unknown. No ownership guard was weakened and no new code change is needed for this report. Scope: these are the repository fixture and public-adapter regressions on Linux x64 / Node 24.22.1, not real-Electron execution or a claim that every module-gap scenario can be paired.
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#4387
No description provided.