[GH-ISSUE #3909] [Bug] inventory assigns source-map relationships to directory entries #1519

Closed
opened 2026-10-16 21:06:34 +00:00 by bsakaguchi · 0 comments
Owner

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

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

rea inspect-artifact can emit a maps-source edge whose child is an ordinary directory. For a ZIP containing regular main.js and empty directory main.js.map/, inventory correctly represents the directory/container, then assigns its edge to the sibling JavaScript artifact. Its occurrence retains the archive parent, but the edge asserts an inapplicable source-map derivation. This is a source-supported output correctness defect; no runtime reproduction was run.

For the proposed input, the source derives entry_kind: "directory", artifact_kind: "container", artifact_format: "directory", and a verified virtual node for main.js.map. Its edge nevertheless has relation: "maps-source" and parent_artifact_id equal to the sibling main.js artifact ID instead of the archive root ID. The unique sibling has content identity, so no ambiguity limitation intervenes. Runtime output, exit status, frequency, and actual platform behavior were not observed.

Reproduction

These exact steps are proposed and unexecuted against the baseline below. No ZIP fixture or REA command was run in the supplied investigation.

work=$(mktemp -d /tmp/agent-work.XXXXXX)
python3 - "$work" <<'PYCODE'
import sys, zipfile
from pathlib import Path
path = Path(sys.argv[1]) / "directory-map.zip"
with zipfile.ZipFile(path, "w", compression=zipfile.ZIP_STORED) as archive:
    archive.writestr("main.js", b"export const answer = 42;\n")
    archive.writestr("main.js.map/", b"")
PYCODE
rea inspect-artifact "$work/directory-map.zip" --json

Read normalized_result.substeps[0].evidence.normalized_result. Locate the occurrence with logical_path == "main.js.map", its node through artifact_id, and its edge through occurrence_id. The input has two distinct normalized paths, no duplicate/prefix collision, encryption, or declared integrity mismatch, and a tiny stored payload within ZIP budgets. The trailing slash declares a directory. This operation needs no JavaScript execution or deep analysis engine.

Expected behavior

Preserve the parsed directory identity and represent the directory as contained by its archive. A directory is not a source map of the sibling JavaScript file. The producer explicitly gives directory entries artifact_format: "directory", a container/framework kind, and a virtual directory node. The graph contract defines edges as parent-child derivation relations. A regular source-map file remains a valid maps-source control.

Impact and scope

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: Public inventory returns an incorrect derivation relationship for a bounded valid directory-entry case. The occurrence still preserves the actual parent and directory identity; no data loss or execution effect is established.

REA version

Reviewed release: rea-agents-6.5.0, revision 3b79af28e80785afce9f5998d8f03289402a1847. The source review compared fetched main at cf0a38ad9774ee9acff3164052688f7a58a1c72c. The relevant producer, ZIP reader, scanner, and CLI behavior remained unchanged; a scanCanonical change only removed a legacy coverage field. Runtime/platform details are NOT_ENOUGH_INFO because REA and the fixture were not run. No last-known-good release was established.

Runtime and platform

REA runtime reproduction was not run. Runtime and platform details for any smaller premise checks are recorded in the version/environment field above. Real-provider versions and end-to-end output are NOT_ENOUGH_INFO because no provider was launched.

Target and artifact context

Stored ZIP containing regular main.js and an empty main.js.map/ directory; artifact inventory graph and occurrence parents.

Interface

CLI

Earliest failure stage

Artifact or evidence registration

Relevant output or evidence

The primary evidence is the supplied production-source proof for the fully specified ordinary ZIP input. Runtime reproduction was not run. The public path and admission guards below establish the public trigger.

src/cli/artifactCommands.ts:219-250 registers inspect-artifact, accepts the nonempty path, defaults integrity policy to fail, and dispatches through runProviderAnalysis. src/application/DirectAnalysis.ts:130-158,309-328 selects the artifact session, opens the target, and invokes the operation. src/composition/binary.ts:45-59 composes ArtifactProvider without deep engines. src/application/binary/BinarySessionOpen.ts:66-105 and src/application/BinaryTargetResolver.ts:174-201 admit the detected regular ZIP and its readable content identity. src/artifacts/ArtifactProviderMetadata.ts:11-61 advertises inspection; its host exclusion concerns asset catalogs. src/application/binary/BinarySession.ts:679-714 executes the admitted operation.

src/artifacts/ArtifactProvider.ts:100-102,329-403 parses integrity input, inventories the target, and wraps nested Evidence. src/artifacts/inventory/ArtifactInventory.ts:14-42 → scanCanonical.ts:66-128 → reader.ts:27-30 selects ZIP scanning. src/artifacts/ZipArtifactReader.ts:181-213,261-276 emits the trailing-slash entry as a directory. src/artifacts/ArtifactPaths.ts:22-41,44-86 normalizes its path and admits both distinct siblings.

src/artifacts/inventory/scanReader.ts:175-232,287-289 retains both occurrences and skips directory content reads without changing its type. Parent resolution at :115-120 finds no non-root ancestor. scanCanonical.ts:208-248 materializes directory identity, supplies archive-root parent pointers, and calls edge construction. Both directory and unique sibling now have non-null artifact IDs, so the suffix-only mapping branch assigns the wrong parent. ArtifactProvider.ts:354-386 embeds that inventory unchanged; DirectAnalysis.ts:466-496 returns it through CLI Evidence.

Typed outcome or recovery expected

For the exact ZIP, retain the directory's node, occurrence, and directory/container identity. Its edge must describe containment under the archive, rather than mapping from main.js. A control with an actual regular main.js.map must retain supported source mapping. Rejecting the input, omitting the directory, or reducing inventory coverage would not restore this contract. These are proposed checks, not executed results.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: Public inventory returns an incorrect derivation relationship for a bounded valid directory-entry case. The occurrence still preserves the actual parent and directory identity; no data loss or execution effect is established.
  • Workaround status: unverified
  • Workaround basis: A consumer can derive containment from retained parent_occurrence_id and directory type and ignore the inapplicable edge. This recovery was source-derived, not exercised through a downstream consumer.
Originally created by @coygeek on GitHub (Oct 15, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3909 ## 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 `rea inspect-artifact` can emit a `maps-source` edge whose child is an ordinary directory. For a ZIP containing regular `main.js` and empty directory `main.js.map/`, inventory correctly represents the directory/container, then assigns its edge to the sibling JavaScript artifact. Its occurrence retains the archive parent, but the edge asserts an inapplicable source-map derivation. This is a source-supported output correctness defect; no runtime reproduction was run. For the proposed input, the source derives `entry_kind: "directory"`, `artifact_kind: "container"`, `artifact_format: "directory"`, and a verified virtual node for `main.js.map`. Its edge nevertheless has `relation: "maps-source"` and `parent_artifact_id` equal to the sibling `main.js` artifact ID instead of the archive root ID. The unique sibling has content identity, so no ambiguity limitation intervenes. Runtime output, exit status, frequency, and actual platform behavior were not observed. ## Reproduction These exact steps are proposed and unexecuted against the baseline below. No ZIP fixture or REA command was run in the supplied investigation. ```sh work=$(mktemp -d /tmp/agent-work.XXXXXX) python3 - "$work" <<'PYCODE' import sys, zipfile from pathlib import Path path = Path(sys.argv[1]) / "directory-map.zip" with zipfile.ZipFile(path, "w", compression=zipfile.ZIP_STORED) as archive: archive.writestr("main.js", b"export const answer = 42;\n") archive.writestr("main.js.map/", b"") PYCODE rea inspect-artifact "$work/directory-map.zip" --json ``` Read `normalized_result.substeps[0].evidence.normalized_result`. Locate the occurrence with `logical_path == "main.js.map"`, its node through `artifact_id`, and its edge through `occurrence_id`. The input has two distinct normalized paths, no duplicate/prefix collision, encryption, or declared integrity mismatch, and a tiny stored payload within ZIP budgets. The trailing slash declares a directory. This operation needs no JavaScript execution or deep analysis engine. ## Expected behavior Preserve the parsed directory identity and represent the directory as contained by its archive. A directory is not a source map of the sibling JavaScript file. The producer explicitly gives directory entries `artifact_format: "directory"`, a container/framework kind, and a virtual directory node. The graph contract defines edges as parent-child derivation relations. A regular source-map file remains a valid `maps-source` control. ## Impact and scope - Impact level: P2 - Assessment status: supported - Impact basis: Public inventory returns an incorrect derivation relationship for a bounded valid directory-entry case. The occurrence still preserves the actual parent and directory identity; no data loss or execution effect is established. ## REA version Reviewed release: `rea-agents-6.5.0`, revision `3b79af28e80785afce9f5998d8f03289402a1847`. The source review compared fetched main at `cf0a38ad9774ee9acff3164052688f7a58a1c72c`. The relevant producer, ZIP reader, scanner, and CLI behavior remained unchanged; a scanCanonical change only removed a legacy coverage field. Runtime/platform details are `NOT_ENOUGH_INFO` because REA and the fixture were not run. No last-known-good release was established. ## Runtime and platform REA runtime reproduction was not run. Runtime and platform details for any smaller premise checks are recorded in the version/environment field above. Real-provider versions and end-to-end output are NOT_ENOUGH_INFO because no provider was launched. ## Target and artifact context Stored ZIP containing regular main.js and an empty main.js.map/ directory; artifact inventory graph and occurrence parents. ## Interface CLI ## Earliest failure stage Artifact or evidence registration ## Relevant output or evidence - Expected source: [src/artifacts/inventory/ArtifactGraphConstruction.ts:77-85](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/artifacts/inventory/ArtifactGraphConstruction.ts#L77-L85) and `:164-172` represent directory containers and virtual nodes; [src/domain/artifactGraph.ts:157-176](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/domain/artifactGraph.ts#L157-L176) defines derivation edges. `src/artifacts/inventory/ArtifactGraphConstruction.test.ts:68-126` uses a regular source-map file for truthful mapping relationships. - Failure source: [src/artifacts/inventory/ArtifactGraphConstruction.ts:296-350](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/artifacts/inventory/ArtifactGraphConstruction.ts#L296-L350) selects a unique sibling solely from the `.map` suffix and assigns it as parent; `:590-595` selects `maps-source` without an entry-kind guard. The directory already has content identity and passes the loop's guards. - Evidence provenance: static - Local verification: static-proof - Reproduction completeness: complete The primary evidence is the supplied production-source proof for the fully specified ordinary ZIP input. Runtime reproduction was not run. The public path and admission guards below establish the public trigger. `src/cli/artifactCommands.ts:219-250` registers `inspect-artifact`, accepts the nonempty path, defaults integrity policy to `fail`, and dispatches through `runProviderAnalysis`. `src/application/DirectAnalysis.ts:130-158,309-328` selects the artifact session, opens the target, and invokes the operation. `src/composition/binary.ts:45-59` composes `ArtifactProvider` without deep engines. `src/application/binary/BinarySessionOpen.ts:66-105` and `src/application/BinaryTargetResolver.ts:174-201` admit the detected regular ZIP and its readable content identity. `src/artifacts/ArtifactProviderMetadata.ts:11-61` advertises inspection; its host exclusion concerns asset catalogs. `src/application/binary/BinarySession.ts:679-714` executes the admitted operation. `src/artifacts/ArtifactProvider.ts:100-102,329-403` parses integrity input, inventories the target, and wraps nested Evidence. `src/artifacts/inventory/ArtifactInventory.ts:14-42` → `scanCanonical.ts:66-128` → `reader.ts:27-30` selects ZIP scanning. `src/artifacts/ZipArtifactReader.ts:181-213,261-276` emits the trailing-slash entry as a directory. `src/artifacts/ArtifactPaths.ts:22-41,44-86` normalizes its path and admits both distinct siblings. `src/artifacts/inventory/scanReader.ts:175-232,287-289` retains both occurrences and skips directory content reads without changing its type. Parent resolution at `:115-120` finds no non-root ancestor. `scanCanonical.ts:208-248` materializes directory identity, supplies archive-root parent pointers, and calls edge construction. Both directory and unique sibling now have non-null artifact IDs, so the suffix-only mapping branch assigns the wrong parent. `ArtifactProvider.ts:354-386` embeds that inventory unchanged; `DirectAnalysis.ts:466-496` returns it through CLI Evidence. ## Typed outcome or recovery expected For the exact ZIP, retain the directory's node, occurrence, and directory/container identity. Its edge must describe containment under the archive, rather than mapping from `main.js`. A control with an actual regular `main.js.map` must retain supported source mapping. Rejecting the input, omitting the directory, or reducing inventory coverage would not restore this contract. These are proposed checks, not executed results. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: Public inventory returns an incorrect derivation relationship for a bounded valid directory-entry case. The occurrence still preserves the actual parent and directory identity; no data loss or execution effect is established. - Workaround status: unverified - Workaround basis: A consumer can derive containment from retained parent_occurrence_id and directory type and ignore the inapplicable edge. This recovery was source-derived, not exercised through a downstream consumer.
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#1519
No description provided.