[GH-ISSUE #6105] [Bug] Explicit require of TypeScript declaration paths becomes unavailable #3736

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

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

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

The compiled analyze-javascript-application CLI marks an explicit require("./dep.d.ts") as unavailable, with resolved_path: null and candidate_path: "dep.d.ts", even though that exact declaration is inventoried and parsed. An import "./dep.d.ts" in the same artifact resolves to it.

The same asymmetry reproduces for .d.mts and .d.cts, in both ordinary static relationship edges and semantic module relationship edges. The analysis itself succeeds with no parse failures.

Reproduction

From a built source checkout at the revision below, create this inert fixture:

from pathlib import Path
p = Path("fixture")
p.mkdir()
(p / "main.cjs").write_text(
    'require("./dep.d.ts");\n'
    'require("./cfg.d.mts");\n'
    'require("./legacy.d.cts");\n'
)
(p / "main.mjs").write_text(
    'import "./dep.d.ts";\n'
    'import "./cfg.d.mts";\n'
    'import "./legacy.d.cts";\n'
)
(p / "fallback.cts").write_text('require("./only.js");\n')
for name in ("dep.d.ts", "cfg.d.mts", "legacy.d.cts", "only.d.ts"):
    (p / name).write_text('export declare const value: number;\n')

Run:

node scripts/rea.mjs analyze-javascript-application "$PWD/fixture" --json > result.json

I executed this CLI workflow once against those seven files. Inspect normalized_result.graph.edges, selecting relation: "imports"; the edge evidence location identifies main.cjs, main.mjs, or fallback.cts. Each request appears under both map-static-relationship and resolve-semantic-module-relationship extractor operations.

All three explicit requests from main.cjs report unavailable; the same three paths from main.mjs resolve. The fallback.cts control correctly retains only.d.ts as an unavailable candidate for ./only.js.

Expected behavior

An explicitly selected declaration path should retain its exact static source relationship identity consistently across require and import modes. Keep the genuine emitted-extension declaration fallback unavailable.

The documented source-link contract distinguishes explicit paths from declarations found only through emitted-extension fallback. Its exact-import half is also covered by the existing declaration ownership tests.

This expectation concerns static artifact identity. It does not establish that a declaration file can execute as a Node runtime module.

Impact and scope

P2: bounded evidence correctness failure. Explicit CommonJS declaration references point to unresolved module nodes instead of the selected inventoried source target. The exact candidate remains visible, so an analyst can manually correlate it with the inventory; no data loss, mutation, or analysis crash was observed.

Observed scope covers the three declaration suffixes in this synthetic directory. Frequency in real applications and downstream tracing effects were not measured. Changing the original require syntax to import changes the artifact and is only a diagnostic control, not a demonstrated workaround preserving source bytes.

REA version

Source revision 52415975942a4b9c53a817915b313ccc404f280e; package manifest version 6.7.0.

Runtime and platform

macOS 27.0.1 arm64, Node v26.12.0. Built CLI with checkout dependencies. No native provider or provider simulation was needed.

Target and artifact context

Synthetic seven-file JavaScript/TypeScript directory; three explicit declaration requests per loader mode and one emitted-extension fallback control. Static inspection only; target code was not executed.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

CLI exit status was 0. Statistics reported seven relevant files, seven parsed JavaScript files, and zero parse failures. Representative edge properties:

{
  "kind": "require",
  "specifier": "./dep.d.ts",
  "expression": null,
  "resolution_mode": "require",
  "resolved_path": null,
  "resolution_status": "unavailable",
  "candidate_path": "dep.d.ts"
}

Its evidence limitation includes:

The TypeScript declaration dep.d.ts is compile-time evidence and cannot identify a runtime module implementation.

The equivalent main.mjs edge has resolution_status: "resolved" and resolved_path: "dep.d.ts". Both outcomes were also observed on semantic module import edges. Assertions over all 14 import edges confirmed the same pattern for all three suffixes and preserved the unavailable fallback control.

Typed outcome or recovery expected

For an exact selected declaration, retain resolution_status: "resolved" and the exact artifact-relative resolved_path on the static source relationship, with normal inference/runtime-execution limitations. For require("./only.js") when only only.d.ts exists, continue to return unavailable with the declaration candidate.

Analysis or suspected cause

Source-derived: import-mode relative paths use the candidate owner that distinguishes exact paths from declaration fallbacks.

Require mode first enters resolveCandidate. Its file-candidate check downgrades a present file using a declaration-extension predicate that does not distinguish explicit requests from emitted fallbacks. That non-null outcome prevents the subsequent exact-candidate owner from being consulted.

The semantic module consumer retains the resulting unavailable status. The reproduction does not establish which declaration restrictions should apply to separate package-entrypoint or runtime-launch cases.

Additional context

Fetched main at d8a9673fc44fde4bd30ff98c241886e6683580ca leaves the relevant resolver, graph consumer, loader-mode owner, and documentation unchanged from the tested revision.

Issue #4382 and PR #4401 address template-literal extraction in historical-source imports. This case uses ordinary quoted literals in application analysis and reaches path resolution successfully, so that parser fix does not cover it. PRs #2642 and #2742 concern opaque inventory targets and Electron runtime entrypoints respectively. PR #4941 concerns runtime path bytes and application ownership; the failure reproduces after its merge. MCP was not independently exercised.

Originally created by @coygeek on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6105 ### 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 The compiled `analyze-javascript-application` CLI marks an explicit `require("./dep.d.ts")` as `unavailable`, with `resolved_path: null` and `candidate_path: "dep.d.ts"`, even though that exact declaration is inventoried and parsed. An `import "./dep.d.ts"` in the same artifact resolves to it. The same asymmetry reproduces for `.d.mts` and `.d.cts`, in both ordinary static relationship edges and semantic module relationship edges. The analysis itself succeeds with no parse failures. ### Reproduction From a built source checkout at the revision below, create this inert fixture: ```python from pathlib import Path p = Path("fixture") p.mkdir() (p / "main.cjs").write_text( 'require("./dep.d.ts");\n' 'require("./cfg.d.mts");\n' 'require("./legacy.d.cts");\n' ) (p / "main.mjs").write_text( 'import "./dep.d.ts";\n' 'import "./cfg.d.mts";\n' 'import "./legacy.d.cts";\n' ) (p / "fallback.cts").write_text('require("./only.js");\n') for name in ("dep.d.ts", "cfg.d.mts", "legacy.d.cts", "only.d.ts"): (p / name).write_text('export declare const value: number;\n') ``` Run: ```sh node scripts/rea.mjs analyze-javascript-application "$PWD/fixture" --json > result.json ``` I executed this CLI workflow once against those seven files. Inspect `normalized_result.graph.edges`, selecting `relation: "imports"`; the edge evidence location identifies `main.cjs`, `main.mjs`, or `fallback.cts`. Each request appears under both `map-static-relationship` and `resolve-semantic-module-relationship` extractor operations. All three explicit requests from `main.cjs` report unavailable; the same three paths from `main.mjs` resolve. The `fallback.cts` control correctly retains `only.d.ts` as an unavailable candidate for `./only.js`. ### Expected behavior An explicitly selected declaration path should retain its exact static source relationship identity consistently across require and import modes. Keep the genuine emitted-extension declaration fallback unavailable. The [documented source-link contract](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/docs/javascript-application-graph.md#L118-L125) distinguishes explicit paths from declarations found only through emitted-extension fallback. Its exact-import half is also covered by the [existing declaration ownership tests](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/application/javascript/JavaScriptArtifactPathResolution.test.ts#L3035-L3074). This expectation concerns static artifact identity. It does not establish that a declaration file can execute as a Node runtime module. ### Impact and scope P2: bounded evidence correctness failure. Explicit CommonJS declaration references point to unresolved module nodes instead of the selected inventoried source target. The exact candidate remains visible, so an analyst can manually correlate it with the inventory; no data loss, mutation, or analysis crash was observed. Observed scope covers the three declaration suffixes in this synthetic directory. Frequency in real applications and downstream tracing effects were not measured. Changing the original require syntax to import changes the artifact and is only a diagnostic control, not a demonstrated workaround preserving source bytes. ### REA version Source revision `52415975942a4b9c53a817915b313ccc404f280e`; package manifest version `6.7.0`. ### Runtime and platform macOS 27.0.1 arm64, Node v26.12.0. Built CLI with checkout dependencies. No native provider or provider simulation was needed. ### Target and artifact context Synthetic seven-file JavaScript/TypeScript directory; three explicit declaration requests per loader mode and one emitted-extension fallback control. Static inspection only; target code was not executed. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence CLI exit status was 0. Statistics reported seven relevant files, seven parsed JavaScript files, and zero parse failures. Representative edge properties: ```json { "kind": "require", "specifier": "./dep.d.ts", "expression": null, "resolution_mode": "require", "resolved_path": null, "resolution_status": "unavailable", "candidate_path": "dep.d.ts" } ``` Its evidence limitation includes: ```text The TypeScript declaration dep.d.ts is compile-time evidence and cannot identify a runtime module implementation. ``` The equivalent `main.mjs` edge has `resolution_status: "resolved"` and `resolved_path: "dep.d.ts"`. Both outcomes were also observed on semantic module import edges. Assertions over all 14 import edges confirmed the same pattern for all three suffixes and preserved the unavailable fallback control. ### Typed outcome or recovery expected For an exact selected declaration, retain `resolution_status: "resolved"` and the exact artifact-relative `resolved_path` on the static source relationship, with normal inference/runtime-execution limitations. For `require("./only.js")` when only `only.d.ts` exists, continue to return unavailable with the declaration candidate. ### Analysis or suspected cause Source-derived: [import-mode relative paths](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/application/javascript/JavaScriptArtifactPathResolution.ts#L382-L398) use [the candidate owner that distinguishes exact paths from declaration fallbacks](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/application/javascript/JavaScriptArtifactPathResolution.ts#L529-L552). Require mode first enters [resolveCandidate](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/application/javascript/JavaScriptArtifactPathResolution.ts#L1472-L1494). Its [file-candidate check](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/application/javascript/JavaScriptArtifactPathResolution.ts#L1626-L1646) downgrades a present file using [a declaration-extension predicate](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/application/javascript/JavaScriptArtifactPathResolution.ts#L1740-L1744) that does not distinguish explicit requests from emitted fallbacks. That non-null outcome prevents the subsequent exact-candidate owner from being consulted. The [semantic module consumer](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/application/javascript/JavaScriptModuleRelationships.ts#L283-L328) retains the resulting unavailable status. The reproduction does not establish which declaration restrictions should apply to separate package-entrypoint or runtime-launch cases. ### Additional context Fetched main at `d8a9673fc44fde4bd30ff98c241886e6683580ca` leaves the relevant resolver, graph consumer, loader-mode owner, and documentation unchanged from the tested revision. Issue #4382 and PR #4401 address template-literal extraction in historical-source imports. This case uses ordinary quoted literals in application analysis and reaches path resolution successfully, so that parser fix does not cover it. PRs #2642 and #2742 concern opaque inventory targets and Electron runtime entrypoints respectively. PR #4941 concerns runtime path bytes and application ownership; the failure reproduces after its merge. MCP was not independently exercised.
Author
Owner

@morluto commented on GitHub (Oct 23, 2026):

Resolved by github.com/morluto/rea@75daf0c7df. Explicit runtime require of exact declaration paths uses runtime-require resolution; declaration suffix classification is preserved. CLI and stdio MCP fixtures cover .d.ts/.d.mts/.d.cts and fallback controls. Validation: tests/acceptance/applications/javascriptModuleResolutionSemantics.test.ts passed in the recorded round2/3 execution; this review did not rerun tests. Coverage is limited to the cited control; no broader real-provider, Windows or performance claim.

<!-- gh-comment-id:6376113345 --> @morluto commented on GitHub (Oct 23, 2026): Resolved by https://github.com/morluto/rea/commit/75daf0c7df108f04ab41f34aec1a31d4a7ceb322. Explicit runtime require of exact declaration paths uses runtime-require resolution; declaration suffix classification is preserved. CLI and stdio MCP fixtures cover .d.ts/.d.mts/.d.cts and fallback controls. Validation: `tests/acceptance/applications/javascriptModuleResolutionSemantics.test.ts` passed in the recorded round2/3 execution; this review did not rerun tests. Coverage is limited to the cited control; no broader real-provider, Windows or performance claim.
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#3736
No description provided.