[GH-ISSUE #6679] [Bug] Excluded package manifests produce false internal reference dependencies #4059

Closed
opened 2026-10-31 00:46:26 +00:00 by bsakaguchi · 0 comments
Owner

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

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

When .gitignore excludes a package's existing package.json, import-reference-source treats that unexamined manifest as absent and records a false parsed internal dependency on the package index. Node resolves the same require("./pkg") to the manifest's declared main instead.

The ignored manifest is correctly recorded in exclusions; it is the dependency interpretation that loses uncertainty. Removing the exclusion makes REA select the declared main. A malformed-but-inventoried manifest correctly leaves selection unresolved, showing that unavailable manifest interpretation already has a modeled outcome.

Reproduction

The executed Python driver created separate disposable trees for four cases. Each contained:

main.cjs:
require("./pkg");

pkg/actual.cjs:
throw new Error("The package main must not execute");

pkg/index.js:
throw new Error("The package index must not execute");

Their remaining inputs were:

visible:  empty .gitignore; pkg/package.json = {"main":"actual.cjs"}
excluded: .gitignore = pkg/package.json followed by newline;
          pkg/package.json = {"main":"actual.cjs"}
invalid:  empty .gitignore; pkg/package.json = {invalid followed by newline
absent:   empty .gitignore; no pkg/package.json

For each tree, with isolated HOME/XDG/TMPDIR and its root as cwd, the driver invoked node REA_CHECKOUT/scripts/rea.mjs import-reference-source ROOT --json, followed by this native resolve-only control with ROOT as the argument:

const { createRequire } = require("node:module");
const path = require("node:path");
const root = process.argv[1];
try {
  console.log(path.relative(root,
    createRequire(path.join(root, "main.cjs")).resolve("./pkg")));
} catch (error) { console.log(error.code); }

All four CLI calls exited 0 with empty stderr and parse_failures: []. No fixture module was loaded. The final four-case fixture and assertions passed before drafting; no post-draft reproduction was performed.

Expected behavior

Keep the manifest excluded and preserve unresolved/unknown package-main selection. Exclusion establishes that the manifest was not examined, not that no manifest exists. Do not bypass the exclusion to read it, and do not assert the different index as a known dependency. Actual absence should continue permitting index fallback; the readable declared main should continue taking precedence.

Contract support is explicit: REA's architecture rule requires preserving omission and uncertainty rather than treating unresolved facts as absent. The package-main owner says unavailable manifest interpretation leaves selection unknown, and its implementation already distinguishes that outcome from no manifest. The CLI contract supports .gitignore exclusions. This is an uncertainty-preservation defect in supported behavior, not a request to index excluded content.

Impact and scope

P2: a valid import policy changes a known omitted input into a false internal dependency. The demonstrated case uses one root .gitignore rule and an ordinary relative CommonJS directory request. The graph's global state is correctly partial, but the individual relationship claims a resolved target. Other inventory evidence remains available. Natural frequency, other exclusion policies, MCP projection, and downstream comparison effects were not measured. No source bytes were mutated by REA.

REA version

CLI --version: 6.7.0; source revision a7f967cf240eba8309cbf4526b2fc6338a52a617, using the prepared compiled runtime and locked dependencies.

Runtime and platform

Node.js v24.22.1, Linux x86_64. No external analysis provider or third-party source was used.

Target and artifact context

Self-authored local CommonJS package with distinct main and index candidates. No Git repository is necessary; the importer applies the selected tree's root .gitignore directly.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Observed targets:

visible:  REA internal pkg/actual.cjs; Node pkg/actual.cjs
excluded: REA internal pkg/index.js;   Node pkg/actual.cjs
invalid:  REA unresolved pkg;          Node ERR_INVALID_PACKAGE_CONFIG
absent:   REA internal pkg/index.js;   Node pkg/index.js

The excluded case retained these exact facts together:

{
  "relationship": {"from_path":"main.cjs","to":"pkg/index.js","kind":"requires","resolution":"internal","parse_state":"parsed"},
  "exclusion": {"path":"pkg/package.json","entry_kind":"file","reason":"project-ignored","pattern":"pkg/package.json"}
}

pkg/actual.cjs and pkg/index.js both remained hashed entries. Evidence provenance: observed public CLI with native resolve-only controls. Local verification: reproduced. Reproduction completeness: complete for these inputs. Existing package-main CLI coverage includes readable and invalid manifests, but not an excluded manifest alongside available candidates.

Typed outcome or recovery expected

Retain the exclusion and both candidate hashes, while marking the affected directory relationship unresolved/unknown. Preserve the readable-main and genuinely absent-manifest controls. These are proposed restoration checks; no implementation was changed.

Analysis or suspected cause

Source-derived: readPackageMains builds its lookup only from reader entries. Excluded files do not become entries. The application workflow passes entries to the parser and stores exclusions separately; package-main selection receives no exclusion facts. The missing manifest lookup therefore follows the same index fallback as actual absence.

Additional context

Live open and closed searches found no report for an excluded manifest producing this false edge. Closed #3383 and #3896 concern readable manifests, which work in the visible control here. Open #4189 concerns a trailing-slash request; this request has no trailing slash. Open #5891 concerns ignored nested policies; this reproduction correctly applies a single root policy. No last-known-good revision was tested.

Prepared with AI assistance.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: The executed excluded-manifest case produces a definite dependency on a different file, while preserving the manifest's exclusion and the rest of the bounded historical inventory. No severe downstream harm was established.
  • Workaround status: unverified
  • Workaround basis: Admitting the manifest restores correct selection in the visible control, but changes the requested exclusion policy. No result-preserving REA workflow keeping that exclusion was verified.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6679 ## 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 When `.gitignore` excludes a package's existing `package.json`, `import-reference-source` treats that unexamined manifest as absent and records a false parsed internal dependency on the package index. Node resolves the same `require("./pkg")` to the manifest's declared main instead. The ignored manifest is correctly recorded in `exclusions`; it is the dependency interpretation that loses uncertainty. Removing the exclusion makes REA select the declared main. A malformed-but-inventoried manifest correctly leaves selection unresolved, showing that unavailable manifest interpretation already has a modeled outcome. ## Reproduction The executed Python driver created separate disposable trees for four cases. Each contained: ```text main.cjs: require("./pkg"); pkg/actual.cjs: throw new Error("The package main must not execute"); pkg/index.js: throw new Error("The package index must not execute"); ``` Their remaining inputs were: ```text visible: empty .gitignore; pkg/package.json = {"main":"actual.cjs"} excluded: .gitignore = pkg/package.json followed by newline; pkg/package.json = {"main":"actual.cjs"} invalid: empty .gitignore; pkg/package.json = {invalid followed by newline absent: empty .gitignore; no pkg/package.json ``` For each tree, with isolated HOME/XDG/TMPDIR and its root as cwd, the driver invoked `node REA_CHECKOUT/scripts/rea.mjs import-reference-source ROOT --json`, followed by this native resolve-only control with `ROOT` as the argument: ```js const { createRequire } = require("node:module"); const path = require("node:path"); const root = process.argv[1]; try { console.log(path.relative(root, createRequire(path.join(root, "main.cjs")).resolve("./pkg"))); } catch (error) { console.log(error.code); } ``` All four CLI calls exited 0 with empty stderr and `parse_failures: []`. No fixture module was loaded. The final four-case fixture and assertions passed before drafting; no post-draft reproduction was performed. ## Expected behavior Keep the manifest excluded and preserve unresolved/unknown package-main selection. Exclusion establishes that the manifest was not examined, not that no manifest exists. Do not bypass the exclusion to read it, and do not assert the different index as a known dependency. Actual absence should continue permitting index fallback; the readable declared main should continue taking precedence. Contract support is explicit: [REA's architecture rule](https://github.com/morluto/rea/blob/a7f967cf240eba8309cbf4526b2fc6338a52a617/AGENTS.md#L19-L21) requires preserving omission and uncertainty rather than treating unresolved facts as absent. The [package-main owner](https://github.com/morluto/rea/blob/a7f967cf240eba8309cbf4526b2fc6338a52a617/src/application/ReferenceSourceImportEntries.ts#L103-L106) says unavailable manifest interpretation leaves selection unknown, and [its implementation](https://github.com/morluto/rea/blob/a7f967cf240eba8309cbf4526b2fc6338a52a617/src/application/ReferenceSourceImportEntries.ts#L219-L234) already distinguishes that outcome from no manifest. The [CLI contract](https://github.com/morluto/rea/blob/a7f967cf240eba8309cbf4526b2fc6338a52a617/docs/cli.md#L378-L385) supports `.gitignore` exclusions. This is an uncertainty-preservation defect in supported behavior, not a request to index excluded content. ## Impact and scope P2: a valid import policy changes a known omitted input into a false internal dependency. The demonstrated case uses one root `.gitignore` rule and an ordinary relative CommonJS directory request. The graph's global state is correctly partial, but the individual relationship claims a resolved target. Other inventory evidence remains available. Natural frequency, other exclusion policies, MCP projection, and downstream comparison effects were not measured. No source bytes were mutated by REA. ## REA version CLI `--version`: `6.7.0`; source revision `a7f967cf240eba8309cbf4526b2fc6338a52a617`, using the prepared compiled runtime and locked dependencies. ## Runtime and platform Node.js `v24.22.1`, Linux x86_64. No external analysis provider or third-party source was used. ## Target and artifact context Self-authored local CommonJS package with distinct main and index candidates. No Git repository is necessary; the importer applies the selected tree's root `.gitignore` directly. ## Interface CLI ## Earliest failure stage Native analysis or reconstruction ## Relevant output or evidence Observed targets: ```text visible: REA internal pkg/actual.cjs; Node pkg/actual.cjs excluded: REA internal pkg/index.js; Node pkg/actual.cjs invalid: REA unresolved pkg; Node ERR_INVALID_PACKAGE_CONFIG absent: REA internal pkg/index.js; Node pkg/index.js ``` The excluded case retained these exact facts together: ```json { "relationship": {"from_path":"main.cjs","to":"pkg/index.js","kind":"requires","resolution":"internal","parse_state":"parsed"}, "exclusion": {"path":"pkg/package.json","entry_kind":"file","reason":"project-ignored","pattern":"pkg/package.json"} } ``` `pkg/actual.cjs` and `pkg/index.js` both remained hashed entries. Evidence provenance: observed public CLI with native resolve-only controls. Local verification: reproduced. Reproduction completeness: complete for these inputs. [Existing package-main CLI coverage](https://github.com/morluto/rea/blob/a7f967cf240eba8309cbf4526b2fc6338a52a617/tests/boundary/cli/referenceSourceDirectoryImports.test.ts#L72-L85) includes readable and invalid manifests, but not an excluded manifest alongside available candidates. ## Typed outcome or recovery expected Retain the exclusion and both candidate hashes, while marking the affected directory relationship unresolved/unknown. Preserve the readable-main and genuinely absent-manifest controls. These are proposed restoration checks; no implementation was changed. ## Analysis or suspected cause Source-derived: [readPackageMains](https://github.com/morluto/rea/blob/a7f967cf240eba8309cbf4526b2fc6338a52a617/src/application/ReferenceSourceImportEntries.ts#L108-L149) builds its lookup only from reader entries. Excluded files do not become entries. The [application workflow](https://github.com/morluto/rea/blob/a7f967cf240eba8309cbf4526b2fc6338a52a617/src/application/ReferenceSourceImport.ts#L205-L247) passes entries to the parser and stores exclusions separately; package-main selection receives no exclusion facts. The missing manifest lookup therefore follows the same index fallback as actual absence. ## Additional context Live open and closed searches found no report for an excluded manifest producing this false edge. Closed [#3383](https://github.com/morluto/rea/issues/3383) and [#3896](https://github.com/morluto/rea/issues/3896) concern readable manifests, which work in the visible control here. Open [#4189](https://github.com/morluto/rea/issues/4189) concerns a trailing-slash request; this request has no trailing slash. Open [#5891](https://github.com/morluto/rea/issues/5891) concerns ignored nested policies; this reproduction correctly applies a single root policy. No last-known-good revision was tested. Prepared with AI assistance. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: The executed excluded-manifest case produces a definite dependency on a different file, while preserving the manifest's exclusion and the rest of the bounded historical inventory. No severe downstream harm was established. - Workaround status: unverified - Workaround basis: Admitting the manifest restores correct selection in the visible control, but changes the requested exclusion policy. No result-preserving REA workflow keeping that exclusion was verified.
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#4059
No description provided.