[GH-ISSUE #7738] [Bug] trace_application_feature with direction "both" goes down from a shared container into its unrelated children #4630

Closed
opened 2026-10-31 00:51:37 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @jgt87 on GitHub (Oct 28, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/7738

Correction. The first version of this report said that direction: "both" returned the whole application graph of a synthetic build. In that fixture every chunk was linked into a ring of imports, so the whole graph was the correct answer there; it was not a fault. The fault is the smaller container case described below. The original text is in the edit history.

Before submitting

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

Area

JavaScript application workflows: trace_application_feature.

Observed behavior

With direction: "both", a trace that steps up a contains edge from a node into its container (a javascript-asset or the artifact root) then continues down into that container's other children. Parts of the application that are not related to the seed join the result.

In the repository's Notes example, seeded on the notes:export channel, the trace climbs from the feature's files to the artifact root and then goes down from the root into package.json. From the root it also reaches the package node, and through the package it reaches the Electron main entry. These nodes and edges are in the result only because of that step down from the root:

  • artifact:package.json, through artifact root -contains-> package.json
  • electron-main:main.js, through package -loads-> electron-main:main.js and electron-main:main.js -maps_to-> javascript-asset:main.js
Version both: nodes / edges incoming outgoing Source graph
rea-agents 6.8.0 (npm, Node.js 26.12.1) 32 / 44 10 / 14 1 / 0 32 / 44
main 6a226bd09 (source checkout, Node.js 24.22.1) 32 / 44 10 / 14 1 / 0 32 / 44

On both versions the both trace is the whole source graph. Its source modules are csv.js, main.js, preload.js and renderer.js, and it has 1 terminal path. The Notes example files did not change between the rea-agents-6.8.0 tag and 6a226bd09.

The example is small, so only two nodes and three edges are added here. In an application with several unrelated entry points or packages under one root, every sibling of a shared container joins the result.

Reproduction

From the repository root of a clean checkout (npm ci && npm run build), or with an installed rea:

rea analyze-javascript-application website/public/examples/notes-electron \
  --artifact-format directory --format json > notes.json
node -e 'const fs=require("fs"); fs.writeFileSync("trace.json", JSON.stringify({application: JSON.parse(fs.readFileSync("notes.json","utf8")), seed: {kind: "channel", value: "notes:export", match: "exact"}, direction: "both"}))'
rea trace-application-feature trace.json --format json > trace-out.json
node -e 'const t=JSON.parse(require("fs").readFileSync("trace-out.json","utf8")).normalized_result; console.log(t.summary.traced_nodes, t.summary.traced_edges, t.graph.nodes.map(n=>n.kind+":"+n.observations[0]?.label).filter(l=>/package.json|electron-main/.test(l)))'

From a source checkout, replace rea with node scripts/rea.mjs.

Observed output: 32 44 [ 'artifact:package.json', 'electron-main:main.js' ] (the label order can differ).

Expected behavior

A container that the trace reaches from one of its children through contains only leads further up its containment chain. It does not lead into its other children. Relationships across the feature in either direction are still followed, because a feature such as this one crosses them: the preload asset invokes the channel and the handler handles it.

For this example, the expected both result is 30 nodes and 41 edges, with the source modules csv.js, main.js, preload.js and renderer.js, and without artifact:package.json and electron-main:main.js. A build with that rule gives exactly this result.

Impact and scope

both is the default direction. Every application where the feature's files share a container with unrelated files is affected: one artifact root, one asset with several modules, or one package with several entry points. incoming and outgoing are not affected.

REA version

rea-agents 6.8.0 (npm) and upstream main at 6a226bd09.

Runtime and platform

Windows 11 Pro (10.0.26300).
6.8.0: global npm install, Node.js 26.12.1.
main: source checkout, Node.js 24.22.1.

Interface

CLI (rea trace-application-feature). The MCP tool trace_application_feature uses the same traversal.

Typed outcome or recovery expected

The same trace without the container's other children: 30 nodes and 41 edges for this example. PR #7743 proposes the change.

Originally created by @jgt87 on GitHub (Oct 28, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7738 > **Correction.** The first version of this report said that `direction: "both"` returned the whole application graph of a synthetic build. In that fixture every chunk was linked into a ring of imports, so the whole graph was the correct answer there; it was not a fault. The fault is the smaller container case described below. The original text is in the edit history. ### 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 JavaScript application workflows: `trace_application_feature`. ### Observed behavior With `direction: "both"`, a trace that steps up a `contains` edge from a node into its container (a `javascript-asset` or the artifact root) then continues down into that container's other children. Parts of the application that are not related to the seed join the result. In the repository's Notes example, seeded on the `notes:export` channel, the trace climbs from the feature's files to the artifact root and then goes down from the root into `package.json`. From the root it also reaches the package node, and through the package it reaches the Electron main entry. These nodes and edges are in the result only because of that step down from the root: - `artifact:package.json`, through `artifact root -contains-> package.json` - `electron-main:main.js`, through `package -loads-> electron-main:main.js` and `electron-main:main.js -maps_to-> javascript-asset:main.js` | Version | `both`: nodes / edges | `incoming` | `outgoing` | Source graph | | --- | --- | --- | --- | --- | | rea-agents 6.8.0 (npm, Node.js 26.12.1) | 32 / 44 | 10 / 14 | 1 / 0 | 32 / 44 | | main 6a226bd09 (source checkout, Node.js 24.22.1) | 32 / 44 | 10 / 14 | 1 / 0 | 32 / 44 | On both versions the `both` trace is the whole source graph. Its source modules are `csv.js`, `main.js`, `preload.js` and `renderer.js`, and it has 1 terminal path. The Notes example files did not change between the `rea-agents-6.8.0` tag and 6a226bd09. The example is small, so only two nodes and three edges are added here. In an application with several unrelated entry points or packages under one root, every sibling of a shared container joins the result. ### Reproduction From the repository root of a clean checkout (`npm ci && npm run build`), or with an installed `rea`: ```sh rea analyze-javascript-application website/public/examples/notes-electron \ --artifact-format directory --format json > notes.json node -e 'const fs=require("fs"); fs.writeFileSync("trace.json", JSON.stringify({application: JSON.parse(fs.readFileSync("notes.json","utf8")), seed: {kind: "channel", value: "notes:export", match: "exact"}, direction: "both"}))' rea trace-application-feature trace.json --format json > trace-out.json node -e 'const t=JSON.parse(require("fs").readFileSync("trace-out.json","utf8")).normalized_result; console.log(t.summary.traced_nodes, t.summary.traced_edges, t.graph.nodes.map(n=>n.kind+":"+n.observations[0]?.label).filter(l=>/package.json|electron-main/.test(l)))' ``` From a source checkout, replace `rea` with `node scripts/rea.mjs`. Observed output: `32 44 [ 'artifact:package.json', 'electron-main:main.js' ]` (the label order can differ). ### Expected behavior A container that the trace reaches from one of its children through `contains` only leads further up its containment chain. It does not lead into its other children. Relationships across the feature in either direction are still followed, because a feature such as this one crosses them: the preload asset `invokes` the channel and the handler `handles` it. For this example, the expected `both` result is 30 nodes and 41 edges, with the source modules `csv.js`, `main.js`, `preload.js` and `renderer.js`, and without `artifact:package.json` and `electron-main:main.js`. A build with that rule gives exactly this result. ### Impact and scope `both` is the default direction. Every application where the feature's files share a container with unrelated files is affected: one artifact root, one asset with several modules, or one package with several entry points. `incoming` and `outgoing` are not affected. ### REA version rea-agents 6.8.0 (npm) and upstream `main` at 6a226bd09. ### Runtime and platform Windows 11 Pro (10.0.26300). 6.8.0: global npm install, Node.js 26.12.1. main: source checkout, Node.js 24.22.1. ### Interface CLI (`rea trace-application-feature`). The MCP tool `trace_application_feature` uses the same traversal. ### Typed outcome or recovery expected The same trace without the container's other children: 30 nodes and 41 edges for this example. PR #7743 proposes the change.
Author
Owner

@jgt87 commented on GitHub (Oct 28, 2026):

Correction: the first version of this issue said that direction: "both" returned the whole application graph of a synthetic Vite-style build. That was not a fault. In that fixture every chunk was linked to the others by a ring of imports, so the whole graph really was reachable from the seed. The real fault is smaller: after a trace steps up a contains edge into a shared container, it also goes down into that container's other children. In the repository's Notes example, this adds package.json and the Electron main entry to the notes:export trace (32 nodes and 44 edges instead of 30 and 41). I have rewritten the body to describe and reproduce this case on 6.8.0 and on main. The original body is in the edit history.

<!-- gh-comment-id:6466942829 --> @jgt87 commented on GitHub (Oct 28, 2026): Correction: the first version of this issue said that `direction: "both"` returned the whole application graph of a synthetic Vite-style build. That was not a fault. In that fixture every chunk was linked to the others by a ring of imports, so the whole graph really was reachable from the seed. The real fault is smaller: after a trace steps up a `contains` edge into a shared container, it also goes down into that container's other children. In the repository's Notes example, this adds `package.json` and the Electron main entry to the `notes:export` trace (32 nodes and 44 edges instead of 30 and 41). I have rewritten the body to describe and reproduce this case on 6.8.0 and on main. The original body is in the edit history.
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#4630
No description provided.