[GH-ISSUE #6582] [Bug] decode-interface-builder silently drops symlinked nibs while reporting complete archive coverage #3972

Closed
opened 2026-10-31 00:45:41 +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/6582

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

Source-only finding; runtime reproduction NOT RUN. A bundle resource named Contents/Resources/Panel.nib that is a symlink to an otherwise valid in-bundle archive is enumerated as a symlink, then discarded before candidate and omission accounting. With no other regular .nib files, the source produces documents: [], an archive_decode facet with status: "complete", examined: 0, omitted: 0, and graph.truncated: false. It reports neither the skipped path nor the reader's known symlink limitation.

Reproduction

Actually performed: traced directory enumeration, archive selection, final coverage projection, and the public CLI/provider route; searched supplied open issues/PRs and live GitHub open/closed reports. No runtime reproduction was executed.

Proposed runtime steps, UNEXECUTED:

  1. Prepare an ordinary executable .app with an executable-resolving Contents/Info.plist and a valid compiled nib saved as Contents/Resources/Panel.data.
  2. Add a relative symlink Contents/Resources/Panel.nib pointing to Panel.data; leave no other .nib file. Both paths stay inside the fixture bundle.
  3. Run rea decode-interface-builder Fixture.app --json with default limits.
  4. Inspect documents, graph.coverage and graph.truncated for the source-derived result above. A proposed control replaces only the symlink in a disposable copy with regular archive bytes at Panel.nib.

Expected behavior

Preserve the known archive-shaped entry and report that it was not inspected, with incomplete/unknown archive coverage and its path. Following the symlink is not required to correct the false completeness claim. The documented workflow says unsupported archive forms remain explicit; the directory reader already preserves the entry kind and limitation.

Impact and scope

A valid archive reachable through a bundle symlink contributes no UI objects or connections, while the result supplies complete archive coverage and no omission count. The same selector is shared by CLI and MCP, and asset-catalog analysis also consumes this UI graph for resource keys. These are source-derived effects; real-app incidence, rendered UI behavior, and public runtime output were not measured. Inspecting a disposable bundle copy with the link replaced by bytes is a possible workaround, not an executed one.

REA version

rea-agents 6.7.0; source main at 46111dd091f2ae01baab9eb119b53b9bd309a05b (the supplied latest published release is also 6.7.0).

Runtime and platform

Source-only; runtime reproduction NOT RUN; no provider runtime run. Source inspection host: Linux x86_64; Node.js v26.12.1 was queried for environment identification only. No REA command, Apple tool, target process, dependency installation, or test suite was run.

Target and artifact context

Apple .app with an admitted executable, valid Info.plist, and an in-bundle relative symlink whose basename ends in .nib; the regular target has a different suffix.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Source proof, not captured runtime output:

Missing evidence: no generated fixture, CLI/MCP execution, Apple tool output, or real-app frequency measurement.

Typed outcome or recovery expected

Retain an explicit skipped archive path and a coverage gap rather than treating unexamined archive content as an empty complete inventory.

Analysis or suspected cause

The selector conflates a recognized but unread non-regular archive with an unrelated filename. It does not carry the directory reader's entry/limitation into coverage accounting.

Additional context

Open/closed GitHub searches included repo:morluto/rea nib symlink and repo:morluto/rea "interface builder" symlink. Related #5887 concerns structured asset-catalog join coverage after skipping a catalog; #6066 and PR #6074 concern exceptions after a regular nib was selected; closed #3914 concerns unrelated catalog filenames, and #2176 concerns missing resource-key projection. None reports this preselection omission of a nib. No known-good version was established.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: The source deterministically discards a recognized archive entry and emits complete archive coverage without its known omission. Consequential UI evidence is missing; runtime frequency remains unmeasured.
  • Workaround status: unverified
  • Workaround basis: Materializing the symlink target at the archive path in a disposable copy should enter the regular-file branch, but this was not executed and does not preserve the original bundle representation.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6582 ### 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 Source-only finding; runtime reproduction NOT RUN. A bundle resource named `Contents/Resources/Panel.nib` that is a symlink to an otherwise valid in-bundle archive is enumerated as a symlink, then discarded before candidate and omission accounting. With no other regular `.nib` files, the source produces `documents: []`, an `archive_decode` facet with `status: "complete"`, `examined: 0`, `omitted: 0`, and `graph.truncated: false`. It reports neither the skipped path nor the reader's known symlink limitation. ### Reproduction Actually performed: traced directory enumeration, archive selection, final coverage projection, and the public CLI/provider route; searched supplied open issues/PRs and live GitHub open/closed reports. No runtime reproduction was executed. Proposed runtime steps, UNEXECUTED: 1. Prepare an ordinary executable `.app` with an executable-resolving `Contents/Info.plist` and a valid compiled nib saved as `Contents/Resources/Panel.data`. 2. Add a relative symlink `Contents/Resources/Panel.nib` pointing to `Panel.data`; leave no other `.nib` file. Both paths stay inside the fixture bundle. 3. Run `rea decode-interface-builder Fixture.app --json` with default limits. 4. Inspect `documents`, `graph.coverage` and `graph.truncated` for the source-derived result above. A proposed control replaces only the symlink in a disposable copy with regular archive bytes at `Panel.nib`. ### Expected behavior Preserve the known archive-shaped entry and report that it was not inspected, with incomplete/unknown archive coverage and its path. Following the symlink is not required to correct the false completeness claim. The documented workflow says unsupported archive forms remain explicit; the directory reader already preserves the entry kind and limitation. ### Impact and scope A valid archive reachable through a bundle symlink contributes no UI objects or connections, while the result supplies complete archive coverage and no omission count. The same selector is shared by CLI and MCP, and asset-catalog analysis also consumes this UI graph for resource keys. These are source-derived effects; real-app incidence, rendered UI behavior, and public runtime output were not measured. Inspecting a disposable bundle copy with the link replaced by bytes is a possible workaround, not an executed one. ### REA version rea-agents 6.7.0; source main at `46111dd091f2ae01baab9eb119b53b9bd309a05b` (the supplied latest published release is also 6.7.0). ### Runtime and platform Source-only; runtime reproduction NOT RUN; no provider runtime run. Source inspection host: Linux x86_64; Node.js v26.12.1 was queried for environment identification only. No REA command, Apple tool, target process, dependency installation, or test suite was run. ### Target and artifact context Apple `.app` with an admitted executable, valid Info.plist, and an in-bundle relative symlink whose basename ends in `.nib`; the regular target has a different suffix. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence Source proof, not captured runtime output: - [Directory reader preserves symlinks and their explicit limitation](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/artifacts/DirectoryArtifactReader.ts#L453-L479). - [Candidate selection skips every non-file before counting candidates or omissions](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/artifacts/apple/InterfaceBuilderAnalysis.ts#L252-L281); `.nib` is a [recognized archive suffix](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/artifacts/apple/InterfaceBuilderAnalysis.ts#L733-L735). - [Final archive coverage depends only on recorded invalid/omitted archives](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/artifacts/apple/InterfaceBuilderAnalysis.ts#L332-L390); the discarded entry never enters those collections. - [CLI dispatch](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/cli/artifactCommands.ts#L180-L191) reaches the [production analyzer](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/artifacts/ArtifactProvider.ts#L224-L231). The [documented workflow](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/docs/native-investigation.md#L447-L463) calls for explicit unsupported forms. Missing evidence: no generated fixture, CLI/MCP execution, Apple tool output, or real-app frequency measurement. ### Typed outcome or recovery expected Retain an explicit skipped archive path and a coverage gap rather than treating unexamined archive content as an empty complete inventory. ### Analysis or suspected cause The selector conflates a recognized but unread non-regular archive with an unrelated filename. It does not carry the directory reader's entry/limitation into coverage accounting. ### Additional context Open/closed GitHub searches included `repo:morluto/rea nib symlink` and `repo:morluto/rea "interface builder" symlink`. Related #5887 concerns structured asset-catalog join coverage after skipping a catalog; #6066 and PR #6074 concern exceptions after a regular nib was selected; closed #3914 concerns unrelated catalog filenames, and #2176 concerns missing resource-key projection. None reports this preselection omission of a nib. No known-good version was established. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: The source deterministically discards a recognized archive entry and emits complete archive coverage without its known omission. Consequential UI evidence is missing; runtime frequency remains unmeasured. - Workaround status: unverified - Workaround basis: Materializing the symlink target at the archive path in a disposable copy should enter the regular-file branch, but this was not executed and does not preserve the original bundle representation.
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#3972
No description provided.