[PR #4790] [CLOSED] fix: prevent source maps targeting directories #6410

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

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/4790
Author: @udaydomadiya08
Created: 10/17/2026
Status: ❌ Closed

Base: main ← Head: fix/source-map-directory-target


📝 Commits (1)

  • acc1b92 fix: prevent source maps targeting directories

📊 Changes

3 files changed (+212 additions, -4 deletions)

View changed files

📝 src/artifacts/inventory/ArtifactGraphConstruction.test.ts (+132 -3)
📝 src/artifacts/inventory/ArtifactGraphConstruction.ts (+8 -1)
📝 tests/boundary/providers/native/artifactProvider.directoryInventory.test.ts (+72 -0)

📄 Description

Summary

Fixes #4212

Prevents source map artifacts (.map) from linking to directory containers via relation: "maps-source", ensuring source maps only target genuine source files and fall back truthfully to parent containment.

Problem and expected behavior

When constructing artifact graph edges (createArtifactEdges in src/artifacts/inventory/ArtifactGraphConstruction.ts), a source map derives its target source path by trimming the .map suffix (e.g., main.js.map -> main.js). It then queries byPath.get(sourcePath).

Previously, byPath.get(sourcePath) returned any occurrence matching that path, including directory containers (artifact_kind === "container", entry_kind === "directory"). When a directory shared the name of a script (such as main.js/), the graph builder treated the directory as mappedSource and created a relation: "maps-source" edge pointing to the directory. A directory is a container boundary, not source code, and must never be the target of a source map.

Expected behavior:

  • A source map must only map genuine source-file occurrences (entry_kind === "file" / non-container).
  • When a sibling directory shares the base name of a source map, it must be ignored as a source candidate.
  • If no genuine source file exists at that path, the source map falls back to parent containment (relation: "contains").
  • Parent and child containment for directory containers and their children must remain intact.

Change and scope

In src/artifacts/inventory/ArtifactGraphConstruction.ts:

  • Filter sourceCandidates retrieved from byPath.get(sourcePath) to exclude directory containers:
    const sourceCandidates =
      sourcePath === undefined
        ? []
        : (byPath.get(sourcePath) ?? []).filter(
            (candidate) =>
              candidate.artifact_kind !== "container" &&
              candidate.entry_kind !== "directory",
          );
    
  • If no valid source file candidates exist, mappedSource is undefined, so no maps-source edge or false ambiguity limitation is emitted. The source map is instead linked to its owning parent container via relation: "contains".

Contract and boundary impact

  • Semantic owner and earliest changed stage: createArtifactEdges in src/artifacts/inventory/ArtifactGraphConstruction.ts.
  • Contribution scope fit and linked maintainer decision: Fix within existing artifact inventory boundary.
  • CLI and MCP/tool-catalog contract: Unchanged; graph structure reflects truthful containment.
  • Provider, bridge, target-format, or platform compatibility: Fully compatible; affects all artifact inventory graphs containing source maps alongside directories.
  • Evidence, artifact, provenance, or reconstruction contract: Preserves container containment and prevents invalid source map edges.
  • Target selection, authority, upstream behavior, and cleanup details: Not applicable.
  • Generated metadata impact: None.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

  • Tests added or updated:
    • src/artifacts/inventory/ArtifactGraphConstruction.test.ts:
      • resolves parent containment when a directory is named like a source file: verifies parent ownership resolution preserves containment for directory main.js, its child, and sibling main.js.map.
      • keeps a directory named like a source file contained by its parent and avoids maps-source edges: verifies directory app/main.js is contained by app, child app/main.js/child.js is contained by app/main.js, and app/main.js.map is contained by app (not mapped to app/main.js).
      • links a source map to a genuine source file named main.js: verifies genuine source file continues to link via relation: "maps-source".
    • tests/boundary/providers/native/artifactProvider.directoryInventory.test.ts:
      • does not map a source map to a directory container and preserves parent/child containment: boundary test using ArtifactProvider validating end-to-end directory inventory behavior.
  • Base reproduction: On the base revision, createArtifactEdges created maps-source with parent_artifact_id set to the directory's artifact ID.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • git diff --check — Clean (0 errors).
  • npm run test:focused -- src/artifacts/inventory/ArtifactGraphConstruction.test.ts tests/boundary/providers/native/artifactProvider.directoryInventory.test.ts — 30/30 passed.
  • npm run check:fast — 2/2 tasks passed (turbo run typecheck lint).
  • npx turbo run typecheck lint --force --output-logs=errors-only — 2/2 tasks passed without cache.
  • npm run docs:check — 6/6 tasks passed (all doc facts and catalog checks).

Compatibility, safety, and release

  • Breaking changes or migration steps: None.
  • Real Hopper/Ghidra, browser, or OS coverage: Not applicable (pure artifact graph construction).
  • Package or release metadata impact: None.
  • Security, privacy, process, or containment review: Corrects graph edges to prevent invalid relationship derivation.

Author readiness

Human owner: @udaydomadiya08

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/4790 **Author:** [@udaydomadiya08](https://github.com/udaydomadiya08) **Created:** 10/17/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/source-map-directory-target` --- ### 📝 Commits (1) - [`acc1b92`](https://github.com/morluto/rea/commit/acc1b925152c262ee33b8d9e6761893b7934542a) fix: prevent source maps targeting directories ### 📊 Changes **3 files changed** (+212 additions, -4 deletions) <details> <summary>View changed files</summary> 📝 `src/artifacts/inventory/ArtifactGraphConstruction.test.ts` (+132 -3) 📝 `src/artifacts/inventory/ArtifactGraphConstruction.ts` (+8 -1) 📝 `tests/boundary/providers/native/artifactProvider.directoryInventory.test.ts` (+72 -0) </details> ### 📄 Description ## Summary Fixes #4212 Prevents source map artifacts (`.map`) from linking to directory containers via `relation: "maps-source"`, ensuring source maps only target genuine source files and fall back truthfully to parent containment. ## Problem and expected behavior When constructing artifact graph edges (`createArtifactEdges` in `src/artifacts/inventory/ArtifactGraphConstruction.ts`), a source map derives its target source path by trimming the `.map` suffix (e.g., `main.js.map` -> `main.js`). It then queries `byPath.get(sourcePath)`. Previously, `byPath.get(sourcePath)` returned any occurrence matching that path, including directory containers (`artifact_kind === "container"`, `entry_kind === "directory"`). When a directory shared the name of a script (such as `main.js/`), the graph builder treated the directory as `mappedSource` and created a `relation: "maps-source"` edge pointing to the directory. A directory is a container boundary, not source code, and must never be the target of a source map. Expected behavior: - A source map must only map genuine source-file occurrences (`entry_kind === "file"` / non-container). - When a sibling directory shares the base name of a source map, it must be ignored as a source candidate. - If no genuine source file exists at that path, the source map falls back to parent containment (`relation: "contains"`). - Parent and child containment for directory containers and their children must remain intact. ## Change and scope In `src/artifacts/inventory/ArtifactGraphConstruction.ts`: - Filter `sourceCandidates` retrieved from `byPath.get(sourcePath)` to exclude directory containers: ```typescript const sourceCandidates = sourcePath === undefined ? [] : (byPath.get(sourcePath) ?? []).filter( (candidate) => candidate.artifact_kind !== "container" && candidate.entry_kind !== "directory", ); ``` - If no valid source file candidates exist, `mappedSource` is `undefined`, so no `maps-source` edge or false ambiguity limitation is emitted. The source map is instead linked to its owning parent container via `relation: "contains"`. ## Contract and boundary impact - Semantic owner and earliest changed stage: `createArtifactEdges` in `src/artifacts/inventory/ArtifactGraphConstruction.ts`. - Contribution scope fit and linked maintainer decision: Fix within existing artifact inventory boundary. - CLI and MCP/tool-catalog contract: Unchanged; graph structure reflects truthful containment. - Provider, bridge, target-format, or platform compatibility: Fully compatible; affects all artifact inventory graphs containing source maps alongside directories. - Evidence, artifact, provenance, or reconstruction contract: Preserves container containment and prevents invalid source map edges. - Target selection, authority, upstream behavior, and cleanup details: Not applicable. - Generated metadata impact: None. Expected effects: - [x] Read existing files or captured data. - [ ] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage - Tests added or updated: - `src/artifacts/inventory/ArtifactGraphConstruction.test.ts`: - `resolves parent containment when a directory is named like a source file`: verifies parent ownership resolution preserves containment for directory `main.js`, its child, and sibling `main.js.map`. - `keeps a directory named like a source file contained by its parent and avoids maps-source edges`: verifies directory `app/main.js` is contained by `app`, child `app/main.js/child.js` is contained by `app/main.js`, and `app/main.js.map` is contained by `app` (not mapped to `app/main.js`). - `links a source map to a genuine source file named main.js`: verifies genuine source file continues to link via `relation: "maps-source"`. - `tests/boundary/providers/native/artifactProvider.directoryInventory.test.ts`: - `does not map a source map to a directory container and preserves parent/child containment`: boundary test using `ArtifactProvider` validating end-to-end directory inventory behavior. - Base reproduction: On the base revision, `createArtifactEdges` created `maps-source` with `parent_artifact_id` set to the directory's artifact ID. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - `git diff --check` — Clean (0 errors). - `npm run test:focused -- src/artifacts/inventory/ArtifactGraphConstruction.test.ts tests/boundary/providers/native/artifactProvider.directoryInventory.test.ts` — 30/30 passed. - `npm run check:fast` — 2/2 tasks passed (`turbo run typecheck lint`). - `npx turbo run typecheck lint --force --output-logs=errors-only` — 2/2 tasks passed without cache. - `npm run docs:check` — 6/6 tasks passed (all doc facts and catalog checks). ## Compatibility, safety, and release - Breaking changes or migration steps: None. - Real Hopper/Ghidra, browser, or OS coverage: Not applicable (pure artifact graph construction). - Package or release metadata impact: None. - Security, privacy, process, or containment review: Corrects graph edges to prevent invalid relationship derivation. ## Author readiness Human owner: @udaydomadiya08 - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [ ] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:14:15 +00:00
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#6410
No description provided.