[GH-ISSUE #7525] [Bug] Anchored /static path constants disappear from the route inventory #4471

Closed
opened 2026-10-31 00:50:06 +00:00 by bsakaguchi · 0 comments
Owner

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

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

Analyzing a JavaScript directory with recognized Next runtime evidence, an explicit /static router configuration and an independent /static/help string yields only the /static route pattern. The standalone constant contributes no inferred candidate or occurrence, although its top-level application segment is already established by the configuration in the same file.

The command used was node scripts/rea.mjs analyze-javascript-application "$work/app" --json --filter-output 'normalized_result.route_inventory.routes,normalized_result.route_inventory.statistics,normalized_result.route_inventory.unknowns,normalized_result.route_inventory.coverage', with the inline fixture below. It exits 0 and reports complete parsing and candidate enumeration, no unknowns, and zero unanchored literals excluded. Replacing the static segment with reports yields both /reports and the low-confidence /reports/help candidate.

Reproduction

  1. Use the baseline source checkout with its existing compiled runtime and Node v24.22.1 on PATH. Run this block from the checkout root. It creates inert source fixtures and isolates REA's HOME/XDG state; it does not install or execute the referenced router or start a Next server.
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
mkdir -p "$work/app" "$work/home"
printf '%s\n' '{"name":"route-fixture","private":true,"type":"module"}' > "$work/app/package.json"
for prefix in static reports; do
  cat > "$work/app/routes.js" <<EOF
globalThis.TURBOPACK = [];
import {createBrowserRouter} from "react-router-dom";
export const router=createBrowserRouter([{path:"/$prefix",element:null}]);
const helpLink="/$prefix/help";
globalThis.helpLink=helpLink;
EOF
  printf '%s\n' "$prefix"
  HOME="$work/home" \
  XDG_CONFIG_HOME="$work/home/config" \
  XDG_DATA_HOME="$work/home/data" \
  XDG_CACHE_HOME="$work/home/cache" \
  XDG_STATE_HOME="$work/home/state" \
    node scripts/rea.mjs analyze-javascript-application "$work/app" --json \
      --filter-output 'normalized_result.route_inventory.routes,normalized_result.route_inventory.statistics,normalized_result.route_inventory.unknowns,normalized_result.route_inventory.coverage'
done
  1. Compare the two inventories: the first contains /static only; the second contains /reports and /reports/help. Both commands exit 0.

The two descendant fixtures were each analyzed once independently, then replayed using this block. Additional same-path and prefix controls are described below.

Expected behavior

An independent rooted constant under a structurally supported application segment should be eligible for the documented low-confidence generic route-constant interpretation. Recognized Next runtime evidence is present, and the constant is neither a computed fragment, a module reference nor a page-shaped path owned by Next interpretation. The route-inventory guide describes these admission rules without a blanket exclusion for a top-level static segment.

The constant should remain an inferred candidate with unknown classification and no reachability claim, as it does in the reports control. Application-route completeness should remain unknown.

Impact and scope

The observed failure removes an inferred route pattern and its supporting occurrence from an otherwise parsed source. Same-path controls also lose an independent constant occurrence when a structural declaration establishes /api/status, /assets/status, /static/status or /_next/status; each of those prefix cases was executed. Equivalent /reports/status constants are retained. The same-source examples retain one supporting source, so they establish occurrence loss rather than a reduced source count.

This is a bounded static-discovery defect. No real application's prevalence, reachable page count, browser capture, MCP result or production bundle was tested. No state loss, service outage or security effect was observed. NOT_ENOUGH_INFO: a practical workaround that preserves the original source evidence without changing the application or analyzer.

REA version

Exact node scripts/rea.mjs --version stdout: 6.8.0 followed by a newline.

Source baseline: 65f1c447344a423fa2785847dbcea1e9a9e2454a, using its already-built runtime. The prefix guard was also confirmed in that compiled runtime. No separate published-package comparison was performed.

Runtime and platform

Node.js v24.22.1; macOS 27.0.1, build 26A434; arm64. No browser or native analysis provider was started.

Target and artifact context

A minimal ESM directory containing package.json and one JavaScript source. The source supplies the recognized TURBOPACK runtime marker, an explicit router configuration, and a separate rooted literal whose value is read through a global assignment. These are static-analysis inputs; no Next installation or runtime behavior is asserted.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Selected facts from the observed CLI replies, omitting generated identities:

static:
  paths: ["/static"]
  mechanisms: [["nested-route-object"]]
  route_patterns: 1
  occurrences: 1
  unanchored_literals_excluded: 0
  unknowns: []

reports:
  paths: ["/reports", "/reports/help"]
  mechanisms: [["nested-route-object"], ["route-string-constant"]]
  route_patterns: 2
  occurrences: 2
  unanchored_literals_excluded: 0
  unknowns: []

Both inventories report source_parsing: "complete", candidate_enumeration: "complete" and application_routes: "unknown". The control's /reports/help has confidence: "low" and classification: "unknown".

Expected source: docs/javascript-route-inventory.md:104-110 describes Next runtime constants supported by structural/navigation application segments and the literal-ownership exclusions. The rest of that guide does not document an API/asset/static reserved-prefix exception. src/domain/javascript/javascriptRouteInventory.ts:336-341 also describes top-level-segment support without such an exception. The completed feature proposal #4772 includes absolute strings under the application's own top-level segments.

Failure source: src/domain/javascript/javascriptRouteScan.ts:822-853 rejects the four prefix names before the Next-runtime/root admission and constant emission. The built dist/domain/javascript/javascriptRouteScan.js:595 contains the same prefix check. src/domain/javascript/javascriptRouteInventory.ts:547-582 can only apply its application-root check to candidates already emitted by the scanner.

Evidence provenance: executed public CLI outputs and inspected baseline source/runtime. Local verification: reproduced. Reproduction completeness: complete for the static CLI workflow; no application execution or route reachability verification is claimed.

Typed outcome or recovery expected

Retain the independently supported literal as a low-confidence route-string-constant candidate and preserve its occurrence. If a prefix remains excluded by design, document that narrower contract explicitly; the current application-segment rule and positive control do not expose that exception.

Analysis or suspected cause

Source-derived: the scanner tests the normalized literal against ^/(?:_next|api|assets|static)(?:/|$) and skips it before considering recognized Next runtime evidence or same-source structural support. The later inventory cannot recover the skipped fact, and the exclusion does not increment its unanchored-literal count. Hypothesis: an overbroad noise filter suppresses legitimate application-segment candidates along with API and asset strings.

Additional context

Same-path controls used an explicit route and a separate constant with the identical /prefix/status value. Each of api, assets, static and _next produced one structural occurrence; reports produced two occurrences with both structural and constant mechanisms. Explicit Next-runtime api and reports controls gave the same contrast. These observations corroborate the prefix-specific rejection without asserting that every prefix is a valid Next page path.

Open/closed issue and PR searches considered #6642, #2805, #6516, #6349, feature #4772 and its merged PR #6019. They concern other route fields, provenance, legacy endpoints or the original feature; no matching prefix-filter omission or existing fix was found.

The separate cross-source-constant finding has a different closure check: an ordinary /reports/status constant in a second source must contribute its occurrence and source. This report reproduces with one source and recognized Next runtime evidence, so allowing cross-source support alone leaves the unconditional prefix rejection in place.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: The public static CLI omits an inferred pattern or supporting occurrence for particular application prefixes despite matching documented application-segment support. The demonstrated loss is bounded; no severe workflow outage or security effect was observed.
  • Workaround status: unverified
  • Workaround basis: No caller-side procedure was demonstrated that recovers the original candidate and source evidence without changing the analyzed source or the analyzer.
Originally created by @coygeek on GitHub (Oct 27, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7525 ### 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 Analyzing a JavaScript directory with recognized Next runtime evidence, an explicit `/static` router configuration and an independent `/static/help` string yields only the `/static` route pattern. The standalone constant contributes no inferred candidate or occurrence, although its top-level application segment is already established by the configuration in the same file. The command used was `node scripts/rea.mjs analyze-javascript-application "$work/app" --json --filter-output 'normalized_result.route_inventory.routes,normalized_result.route_inventory.statistics,normalized_result.route_inventory.unknowns,normalized_result.route_inventory.coverage'`, with the inline fixture below. It exits 0 and reports complete parsing and candidate enumeration, no unknowns, and zero unanchored literals excluded. Replacing the `static` segment with `reports` yields both `/reports` and the low-confidence `/reports/help` candidate. ### Reproduction 1. Use the baseline source checkout with its existing compiled runtime and Node v24.22.1 on PATH. Run this block from the checkout root. It creates inert source fixtures and isolates REA's HOME/XDG state; it does not install or execute the referenced router or start a Next server. ```sh work=$(mktemp -d) trap 'rm -rf "$work"' EXIT mkdir -p "$work/app" "$work/home" printf '%s\n' '{"name":"route-fixture","private":true,"type":"module"}' > "$work/app/package.json" for prefix in static reports; do cat > "$work/app/routes.js" <<EOF globalThis.TURBOPACK = []; import {createBrowserRouter} from "react-router-dom"; export const router=createBrowserRouter([{path:"/$prefix",element:null}]); const helpLink="/$prefix/help"; globalThis.helpLink=helpLink; EOF printf '%s\n' "$prefix" HOME="$work/home" \ XDG_CONFIG_HOME="$work/home/config" \ XDG_DATA_HOME="$work/home/data" \ XDG_CACHE_HOME="$work/home/cache" \ XDG_STATE_HOME="$work/home/state" \ node scripts/rea.mjs analyze-javascript-application "$work/app" --json \ --filter-output 'normalized_result.route_inventory.routes,normalized_result.route_inventory.statistics,normalized_result.route_inventory.unknowns,normalized_result.route_inventory.coverage' done ``` 2. Compare the two inventories: the first contains `/static` only; the second contains `/reports` and `/reports/help`. Both commands exit 0. The two descendant fixtures were each analyzed once independently, then replayed using this block. Additional same-path and prefix controls are described below. ### Expected behavior An independent rooted constant under a structurally supported application segment should be eligible for the documented low-confidence generic route-constant interpretation. Recognized Next runtime evidence is present, and the constant is neither a computed fragment, a module reference nor a page-shaped path owned by Next interpretation. The route-inventory guide describes these admission rules without a blanket exclusion for a top-level `static` segment. The constant should remain an inferred candidate with unknown classification and no reachability claim, as it does in the `reports` control. Application-route completeness should remain unknown. ### Impact and scope The observed failure removes an inferred route pattern and its supporting occurrence from an otherwise parsed source. Same-path controls also lose an independent constant occurrence when a structural declaration establishes `/api/status`, `/assets/status`, `/static/status` or `/_next/status`; each of those prefix cases was executed. Equivalent `/reports/status` constants are retained. The same-source examples retain one supporting source, so they establish occurrence loss rather than a reduced source count. This is a bounded static-discovery defect. No real application's prevalence, reachable page count, browser capture, MCP result or production bundle was tested. No state loss, service outage or security effect was observed. NOT_ENOUGH_INFO: a practical workaround that preserves the original source evidence without changing the application or analyzer. ### REA version Exact `node scripts/rea.mjs --version` stdout: `6.8.0` followed by a newline. Source baseline: `65f1c447344a423fa2785847dbcea1e9a9e2454a`, using its already-built runtime. The prefix guard was also confirmed in that compiled runtime. No separate published-package comparison was performed. ### Runtime and platform Node.js v24.22.1; macOS 27.0.1, build 26A434; arm64. No browser or native analysis provider was started. ### Target and artifact context A minimal ESM directory containing `package.json` and one JavaScript source. The source supplies the recognized `TURBOPACK` runtime marker, an explicit router configuration, and a separate rooted literal whose value is read through a global assignment. These are static-analysis inputs; no Next installation or runtime behavior is asserted. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence Selected facts from the observed CLI replies, omitting generated identities: ```text static: paths: ["/static"] mechanisms: [["nested-route-object"]] route_patterns: 1 occurrences: 1 unanchored_literals_excluded: 0 unknowns: [] reports: paths: ["/reports", "/reports/help"] mechanisms: [["nested-route-object"], ["route-string-constant"]] route_patterns: 2 occurrences: 2 unanchored_literals_excluded: 0 unknowns: [] ``` Both inventories report `source_parsing: "complete"`, `candidate_enumeration: "complete"` and `application_routes: "unknown"`. The control's `/reports/help` has `confidence: "low"` and `classification: "unknown"`. Expected source: `docs/javascript-route-inventory.md:104-110` describes Next runtime constants supported by structural/navigation application segments and the literal-ownership exclusions. The rest of that guide does not document an API/asset/static reserved-prefix exception. `src/domain/javascript/javascriptRouteInventory.ts:336-341` also describes top-level-segment support without such an exception. The completed feature proposal [#4772](https://github.com/morluto/rea/issues/4772) includes absolute strings under the application's own top-level segments. Failure source: `src/domain/javascript/javascriptRouteScan.ts:822-853` rejects the four prefix names before the Next-runtime/root admission and constant emission. The built `dist/domain/javascript/javascriptRouteScan.js:595` contains the same prefix check. `src/domain/javascript/javascriptRouteInventory.ts:547-582` can only apply its application-root check to candidates already emitted by the scanner. Evidence provenance: executed public CLI outputs and inspected baseline source/runtime. Local verification: reproduced. Reproduction completeness: complete for the static CLI workflow; no application execution or route reachability verification is claimed. ### Typed outcome or recovery expected Retain the independently supported literal as a low-confidence `route-string-constant` candidate and preserve its occurrence. If a prefix remains excluded by design, document that narrower contract explicitly; the current application-segment rule and positive control do not expose that exception. ### Analysis or suspected cause Source-derived: the scanner tests the normalized literal against `^/(?:_next|api|assets|static)(?:/|$)` and skips it before considering recognized Next runtime evidence or same-source structural support. The later inventory cannot recover the skipped fact, and the exclusion does not increment its unanchored-literal count. Hypothesis: an overbroad noise filter suppresses legitimate application-segment candidates along with API and asset strings. ### Additional context Same-path controls used an explicit route and a separate constant with the identical `/prefix/status` value. Each of `api`, `assets`, `static` and `_next` produced one structural occurrence; `reports` produced two occurrences with both structural and constant mechanisms. Explicit Next-runtime `api` and `reports` controls gave the same contrast. These observations corroborate the prefix-specific rejection without asserting that every prefix is a valid Next page path. Open/closed issue and PR searches considered [#6642](https://github.com/morluto/rea/issues/6642), [#2805](https://github.com/morluto/rea/issues/2805), [#6516](https://github.com/morluto/rea/issues/6516), [#6349](https://github.com/morluto/rea/issues/6349), feature #4772 and its merged [PR #6019](https://github.com/morluto/rea/pull/6019). They concern other route fields, provenance, legacy endpoints or the original feature; no matching prefix-filter omission or existing fix was found. The separate cross-source-constant finding has a different closure check: an ordinary `/reports/status` constant in a second source must contribute its occurrence and source. This report reproduces with one source and recognized Next runtime evidence, so allowing cross-source support alone leaves the unconditional prefix rejection in place. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: The public static CLI omits an inferred pattern or supporting occurrence for particular application prefixes despite matching documented application-segment support. The demonstrated loss is bounded; no severe workflow outage or security effect was observed. - Workaround status: unverified - Workaround basis: No caller-side procedure was demonstrated that recovers the original candidate and source evidence without changing the analyzed source or the analyzer.
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#4471
No description provided.