[GH-ISSUE #3310] [Bug] Noncomputed class method names create false resolved lexical reads #1182

Closed
opened 2026-10-15 18:31:48 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 14, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/3310

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

A noncomputed class method name creates a resolved lexical read when an outer variable has the same name. analyze-javascript-application retains that relationship in semantic Evidence, and trace-javascript-semantics reports forward influence from the variable into a method whose key never evaluates the variable. Both CLI commands exit successfully.

For const marker = "seed"; class Holder { marker() {} }, the noncomputed case returns status: "found", two traversed nodes, one traversed relation, one traversed function, and zero relevant unknowns. The relation is reads with resolution: "resolved" at sample.mjs, line 2, columns 15 through 21, exactly the noncomputed method name. The computed control, [marker]() {}, also retains one resolved read, at columns 16 through 22. Both forms were executed through the analysis and trace commands.

Overall trace coverage is partial in both runs. That does not make the false resolved edge a candidate or an unknown.

Reproduction

  1. Clone a clean checkout, select the reproduced baseline, install the locked dependencies, and build the runtime:
git clone https://github.com/morluto/rea.git rea-class-key-repro
cd rea-class-key-repro
git checkout 8dde6370d0809ad04cda3342d4e6f290f48aa063
npm ci
npm run build:cached
  1. From the repository root, create an isolated directory and configuration home, then write the complete two-line input file. The target is inert source text; no application code needs to run:
work="$(mktemp -d)"
mkdir -p "$work/app" "$work/home"
cat > "$work/app/sample.mjs" <<'JS'
const marker = "seed";
class Holder { marker() {} }
JS
  1. Analyze the application and save the returned Evidence:
env HOME="$work/home" node scripts/rea.mjs analyze-javascript-application "$work/app" --json > "$work/application.json"
  1. Use the returned marker binding node ID to create the complete trace input, retaining the application Evidence:
node --input-type=module - "$work" <<'JS'
import { readFileSync, writeFileSync } from 'node:fs';
const root = process.argv[2];
const application = JSON.parse(readFileSync(`${root}/application.json`, 'utf8'));
const binding = application.normalized_result.semantic_graph.nodes.find(
  node => node.kind === 'binding' && node.label === 'marker'
);
writeFileSync(`${root}/trace-input.json`, JSON.stringify({
  application,
  query: {
    seed: { kind: 'semantic-node', node_id: binding.node_id },
    direction: 'forward-influence',
    allowed_relations: ['reads']
  }
}));
JS
  1. Run the trace and print its status, summary, and relation locations:
env HOME="$work/home" node scripts/rea.mjs trace-javascript-semantics "$work/trace-input.json" --json > "$work/trace.json"
node --input-type=module - "$work/trace.json" <<'JS'
import { readFileSync } from 'node:fs';
const result = JSON.parse(readFileSync(process.argv[2], 'utf8')).normalized_result;
console.log(JSON.stringify({status: result.status, summary: result.summary}));
for (const relation of result.relations) {
  console.log(JSON.stringify({
    relation: relation.relation,
    resolution: relation.resolution,
    location: relation.evidence.location.value
  }));
}
JS
  1. Replace the noncomputed key with the computed control, then repeat steps 3 through 5. Analyze again and rebuild the trace input from the new Evidence:
cat > "$work/app/sample.mjs" <<'JS'
const marker = "seed";
class Holder { [marker]() {} }
JS

Expected behavior

The noncomputed key names a property and must not create a lexical reads edge from the outer binding. The computed control evaluates marker and must retain its real lexical read. The trace should preserve that distinction without requiring candidate-edge opt-in or excluding all read relationships.

docs/javascript-application-workflows.md:68 describes lexical definitions and reads, and docs/javascript-application-workflows.md:101 defines resolved relationships as uniquely identified static targets. src/domain/javascript/javascriptSemanticAnalysis.calls.test.ts:161 preserves real computed class-key references.

Impact and scope

Impact level: P2, supported. A valid class declaration produces a false resolved data dependency in retained semantic Evidence and in the public forward trace. This can misdirect an investigation when a local binding shares a class method name; the executed sample establishes that bounded input family.

Workaround status: unverified. No alternative REA query was verified to preserve all real lexical reads while removing only the false class-key relationship. Manual source inspection can identify this fixture's error but does not correct its stored graph.

REA version

6.4.0 (main at 8dde6370d0)

Runtime and platform

Node.js v26.10.0; macOS 27.0.1. Architecture was not recorded for this reproduction.

Target and artifact context

An extracted directory containing the two-line sample.mjs fixture, analyzed as inert JavaScript source text. The trace input contains the returned application Evidence and the actual outer marker binding node ID. No native analysis engine is needed, and no application code needs to run.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

Observed result fields and source spans:

Both CLI commands exit successfully.
Noncomputed key: status: "found"; two traversed nodes; one traversed relation; one traversed function; zero relevant unknowns.
Noncomputed key: reads, resolution: "resolved", sample.mjs, line 2, columns 15 through 21.
Computed control: one resolved read, sample.mjs, line 2, columns 16 through 22.
Overall trace coverage is partial in both runs.

Typed outcome or recovery expected

Repeat the two-line noncomputed fixture and confirm that no reads relation connects the outer binding to the method key. Repeat the computed control and retain its resolved read. A passing result must remove the false dependency without suppressing class bodies or actual computed-key evaluation.

Analysis or suspected cause

Source-derived reasoning: src/domain/javascript/javascriptSemanticProjection.ts:749 excludes noncomputed object keys but omits class keys. Its reference collector at src/domain/javascript/javascriptSemanticProjection.ts:174 feeds the resolved read projection in src/application/javascript/JavaScriptSemanticGraphBuilder.ts:627. This explains how the class key can become a resolved lexical read; the primary failure evidence is the successful CLI analysis and trace returning the noncomputed key as a resolved read.

Additional context

  • #2573, closed as completed, concerns false method-owned closure captures for computed keys; this report concerns false lexical reads for noncomputed class keys.
  • #3207, closed as completed, concerns local export references projected as writes; this report concerns a class key that should not enter lexical reference collection.
  • #2567, closed as completed, concerns member mutation targets classified as property reads; this report concerns noncomputed class names classified as lexical reads.
  • #2568, closed as completed, concerns unrelated read unknowns in callers traces; this report concerns a false resolved read in a forward-influence trace with zero relevant unknowns.
  • #822, closed as completed, concerns computed member identifiers fabricating Electron property names; this report concerns noncomputed class keys and lexical binding references.
  • #783, closed as completed, concerns empty-string property identity and method names; this report uses an ordinary nonempty key that becomes a false variable read.
  • #3261, open, concerns missing callable return shapes for identifier default exports; this report concerns an extra lexical relationship from a class method key.
Originally created by @coygeek on GitHub (Oct 14, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3310 ### 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 A noncomputed class method name creates a resolved lexical read when an outer variable has the same name. `analyze-javascript-application` retains that relationship in semantic Evidence, and `trace-javascript-semantics` reports forward influence from the variable into a method whose key never evaluates the variable. Both CLI commands exit successfully. For `const marker = "seed"; class Holder { marker() {} }`, the noncomputed case returns `status: "found"`, two traversed nodes, one traversed relation, one traversed function, and zero relevant unknowns. The relation is `reads` with `resolution: "resolved"` at `sample.mjs`, line 2, columns 15 through 21, exactly the noncomputed method name. The computed control, `[marker]() {}`, also retains one resolved read, at columns 16 through 22. Both forms were executed through the analysis and trace commands. Overall trace coverage is partial in both runs. That does not make the false resolved edge a candidate or an unknown. ### Reproduction 1. Clone a clean checkout, select the reproduced baseline, install the locked dependencies, and build the runtime: ```bash git clone https://github.com/morluto/rea.git rea-class-key-repro cd rea-class-key-repro git checkout 8dde6370d0809ad04cda3342d4e6f290f48aa063 npm ci npm run build:cached ``` 2. From the repository root, create an isolated directory and configuration home, then write the complete two-line input file. The target is inert source text; no application code needs to run: ```bash work="$(mktemp -d)" mkdir -p "$work/app" "$work/home" cat > "$work/app/sample.mjs" <<'JS' const marker = "seed"; class Holder { marker() {} } JS ``` 3. Analyze the application and save the returned Evidence: ```bash env HOME="$work/home" node scripts/rea.mjs analyze-javascript-application "$work/app" --json > "$work/application.json" ``` 4. Use the returned `marker` binding node ID to create the complete trace input, retaining the application Evidence: ```bash node --input-type=module - "$work" <<'JS' import { readFileSync, writeFileSync } from 'node:fs'; const root = process.argv[2]; const application = JSON.parse(readFileSync(`${root}/application.json`, 'utf8')); const binding = application.normalized_result.semantic_graph.nodes.find( node => node.kind === 'binding' && node.label === 'marker' ); writeFileSync(`${root}/trace-input.json`, JSON.stringify({ application, query: { seed: { kind: 'semantic-node', node_id: binding.node_id }, direction: 'forward-influence', allowed_relations: ['reads'] } })); JS ``` 5. Run the trace and print its status, summary, and relation locations: ```bash env HOME="$work/home" node scripts/rea.mjs trace-javascript-semantics "$work/trace-input.json" --json > "$work/trace.json" node --input-type=module - "$work/trace.json" <<'JS' import { readFileSync } from 'node:fs'; const result = JSON.parse(readFileSync(process.argv[2], 'utf8')).normalized_result; console.log(JSON.stringify({status: result.status, summary: result.summary})); for (const relation of result.relations) { console.log(JSON.stringify({ relation: relation.relation, resolution: relation.resolution, location: relation.evidence.location.value })); } JS ``` 6. Replace the noncomputed key with the computed control, then repeat steps 3 through 5. Analyze again and rebuild the trace input from the new Evidence: ```bash cat > "$work/app/sample.mjs" <<'JS' const marker = "seed"; class Holder { [marker]() {} } JS ``` ### Expected behavior The noncomputed key names a property and must not create a lexical `reads` edge from the outer binding. The computed control evaluates `marker` and must retain its real lexical read. The trace should preserve that distinction without requiring candidate-edge opt-in or excluding all read relationships. `docs/javascript-application-workflows.md:68` describes lexical definitions and reads, and `docs/javascript-application-workflows.md:101` defines resolved relationships as uniquely identified static targets. `src/domain/javascript/javascriptSemanticAnalysis.calls.test.ts:161` preserves real computed class-key references. ### Impact and scope Impact level: P2, supported. A valid class declaration produces a false resolved data dependency in retained semantic Evidence and in the public forward trace. This can misdirect an investigation when a local binding shares a class method name; the executed sample establishes that bounded input family. Workaround status: unverified. No alternative REA query was verified to preserve all real lexical reads while removing only the false class-key relationship. Manual source inspection can identify this fixture's error but does not correct its stored graph. ### REA version 6.4.0 (main at 8dde6370d0809ad04cda3342d4e6f290f48aa063) ### Runtime and platform Node.js v26.10.0; macOS 27.0.1. Architecture was not recorded for this reproduction. ### Target and artifact context An extracted directory containing the two-line `sample.mjs` fixture, analyzed as inert JavaScript source text. The trace input contains the returned application Evidence and the actual outer `marker` binding node ID. No native analysis engine is needed, and no application code needs to run. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence Observed result fields and source spans: ```text Both CLI commands exit successfully. Noncomputed key: status: "found"; two traversed nodes; one traversed relation; one traversed function; zero relevant unknowns. Noncomputed key: reads, resolution: "resolved", sample.mjs, line 2, columns 15 through 21. Computed control: one resolved read, sample.mjs, line 2, columns 16 through 22. Overall trace coverage is partial in both runs. ``` ### Typed outcome or recovery expected Repeat the two-line noncomputed fixture and confirm that no `reads` relation connects the outer binding to the method key. Repeat the computed control and retain its resolved read. A passing result must remove the false dependency without suppressing class bodies or actual computed-key evaluation. ### Analysis or suspected cause Source-derived reasoning: `src/domain/javascript/javascriptSemanticProjection.ts:749` excludes noncomputed object keys but omits class keys. Its reference collector at `src/domain/javascript/javascriptSemanticProjection.ts:174` feeds the resolved read projection in `src/application/javascript/JavaScriptSemanticGraphBuilder.ts:627`. This explains how the class key can become a resolved lexical read; the primary failure evidence is the successful CLI analysis and trace returning the noncomputed key as a resolved read. ### Additional context - [#2573](https://github.com/morluto/rea/issues/2573), closed as completed, concerns false method-owned closure captures for computed keys; this report concerns false lexical reads for noncomputed class keys. - [#3207](https://github.com/morluto/rea/issues/3207), closed as completed, concerns local export references projected as writes; this report concerns a class key that should not enter lexical reference collection. - [#2567](https://github.com/morluto/rea/issues/2567), closed as completed, concerns member mutation targets classified as property reads; this report concerns noncomputed class names classified as lexical reads. - [#2568](https://github.com/morluto/rea/issues/2568), closed as completed, concerns unrelated read unknowns in callers traces; this report concerns a false resolved read in a forward-influence trace with zero relevant unknowns. - [#822](https://github.com/morluto/rea/issues/822), closed as completed, concerns computed member identifiers fabricating Electron property names; this report concerns noncomputed class keys and lexical binding references. - [#783](https://github.com/morluto/rea/issues/783), closed as completed, concerns empty-string property identity and method names; this report uses an ordinary nonempty key that becomes a false variable read. - [#3261](https://github.com/morluto/rea/issues/3261), open, concerns missing callable return shapes for identifier default exports; this report concerns an extra lexical relationship from a class method key.
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#1182
No description provided.