[PR #1969] [CLOSED] fix(artifacts): propose probes from the contents of inspected app bundles #4940

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

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1969
Author: @thefolahan
Created: 10/11/2026
Status: ❌ Closed

Base: main ← Head: fix/inspect-artifact-bundle-probes


📝 Commits (10+)

  • fd4f2fe fix(artifacts): propose probes from the contents of inspected app bundles
  • 7eece9b fix(artifacts): count only readable JavaScript sources as bundle members
  • 5b7c7e1 fix(artifacts): share script classification and retain plist link probes
  • 22ee275 fix(artifacts): share JavaScript acquisition classification
  • 948f272 fix(artifacts): retain occurrence identity when proposing direct probes
  • e283e62 fix(artifacts): sync occurrence probe fix with captured main
  • e364692 fix(artifacts): align Harmony runtime families
  • 9597916 test(artifacts): expect native probes before managed probes
  • 1e2ade3 Merge commit '8fef2aa64e' into HEAD
  • aaede83 Merge branch 'main' into fix/inspect-artifact-bundle-probes

📊 Changes

7 files changed (+307 additions, -18 deletions)

View changed files

📝 src/artifacts/inventory/ArtifactGraphConstruction.ts (+2 -1)
📝 src/artifacts/javascript/JavaScriptArtifactFiles.ts (+4 -14)
📝 src/domain/artifactInspection.ts (+81 -1)
📝 src/domain/harmony/harmonyApplication.ts (+4 -1)
📝 src/domain/javascript/javascriptArtifactFiles.ts (+19 -0)
📝 tests/boundary/filesystem/harmony/application.test.ts (+1 -1)
➕ tests/boundary/providers/native/artifactProvider.directoryProbes.test.ts (+196 -0)

📄 Description

Summary

inspect_artifact on a native macOS app bundle proposes analyze_javascript_application as its only next probe, even when the bundle contains no JavaScript at all. Directory probes now follow the member formats that the inventory actually observed. No issue is linked; I found this while running REA 6.4.0 on two of my own Swift apps and searched open and closed issues and PRs before opening this.

Problem and expected behavior

probesFor in src/domain/artifactInspection.ts chose probes from root_format alone, and "directory" shared the JavaScript branch with asar and javascript-bundle. Because inspect_artifact only admits app bundles as directories (a plain directory is refused with "open_binary accepts files and macOS app bundles"), every native .app was told to run the JavaScript analyzer and was never pointed at open_binary or inspect_plist.

Smallest trigger: any SwiftUI app bundle.

$ rea inspect-artifact Vigil.app --format json   # Contents/MacOS/Vigil and Contents/Helpers/vigil are universal Mach-O
next_probes: [analyze_javascript_application]

Expected: the probes match the bundle's members, so open_binary and inspect_plist, plus analyze_javascript_application only when the bundle holds an ASAR or bundled scripts (Electron).

Change and scope

For a directory root, probesFor now collects the artifact_format of every inventory occurrence and reuses the existing per format probes (renamed probesForFormat, unchanged otherwise) in a fixed order: ASAR and JavaScript, then Mach-O and ELF, then PE, then plist. Repeated operations are kept once, so open_binary keeps the general native rationale when a bundle holds both Mach-O and PE members. Non directory roots behave exactly as before.

Following review: classifyArtifactPath now names the same JavaScript source extensions the analyzer reads (.cts, .mts, .jsx, .ts, .tsx in addition to .cjs, .mjs, .js), so a bundle holding only TypeScript sources still gets the JavaScript probe; and directory probes ignore symlink occurrences, which the inventory and analyzers never follow.

Not included: no new probe operations, no schema change, and no change to hypotheses.

Contract and boundary impact

  • Semantic owner and earliest changed stage: src/domain/artifactInspection.ts, probe derivation after inventory.
  • CLI and MCP/tool-catalog contract: none; next_probes and unexplored_branches keep their schema, only their values for directory roots change.
  • Provider, bridge, target-format, or platform compatibility: none.
  • Evidence, artifact, provenance, or reconstruction contract: inventory occurrences for .cts, .mts, .jsx, .ts and .tsx paths now carry artifact_kind: javascript and artifact_format: javascript-bundle instead of resource and file, matching what the JavaScript analyzer already reads. No schema change.
  • Process execution, authorization, cleanup, or containment impact: none.
  • Generated metadata, package, or installation impact: none.

Evidence and regression coverage

  • Tests added or updated: tests/boundary/providers/native/artifactProvider.directoryProbes.test.ts runs inspect_artifact through the direct analysis workflow on a minimal native bundle (arm64 mach_header_64 plus Info.plist) and on an Electron style bundle (the same plus Contents/Resources/app.asar), on a bundle whose only scripts are TypeScript, and on a bundle whose only .js member is a symlink. Unexplored branches are checked to carry the same probes.
  • Base reproduction or other evidence: the first two tests fail on the base revision (it returns only analyze_javascript_application); the TypeScript test fails without the classifier change and the symlink test fails without the symlink filter. All four pass with this change.
  • User-visible CLI/MCP output: on real universal Swift bundles (Vigil.app and API Pilot.app, macOS 27.0.1), next_probes changes from ["analyze_javascript_application"] to ["open_binary", "inspect_plist"].
  • Remaining proof gaps: no real Electron app bundle was inspected; the Electron case is covered by the fixture only.

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

  • npx vitest run tests/boundary/providers/native/artifactProvider.directoryProbes.test.ts: 4 passed; each test fails when its corresponding fix is reverted.
  • npx vitest run over every test file whose path mentions artifact, javascript, inventory, electron, asar, bundle, comparison or evidence (251 files): 2852 passed, 4 failed, 41 skipped. The 4 failures are in tests/boundary/inspector/javascriptRuntimeObservation.test.ts and javascriptRuntimeTargetLocations.test.ts and fail identically on unmodified b777e5d in my environment, so they are unrelated to this change.
  • npm run check:fast: typecheck and lint passed.
  • npm run verify:test-discovery: discovered all test files exactly once.
  • oxfmt --check src tests: passed.

Compatibility, safety, and release

  • Breaking changes or migration steps: none.
  • Real Hopper/Ghidra, browser, or OS coverage: macOS 27.0.1 on Apple silicon, Node 24.21.0; no native provider was needed or run, since inspect_artifact is provider neutral.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: no new process execution or file access; the change only reads inventory occurrences already in memory.

Review checklist

  • This PR addresses a concrete problem or an agreed enhancement.
  • 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/1969 **Author:** [@thefolahan](https://github.com/thefolahan) **Created:** 10/11/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/inspect-artifact-bundle-probes` --- ### 📝 Commits (10+) - [`fd4f2fe`](https://github.com/morluto/rea/commit/fd4f2fe57ccb933fafc6d413616e7ea4fd83aef6) fix(artifacts): propose probes from the contents of inspected app bundles - [`7eece9b`](https://github.com/morluto/rea/commit/7eece9bc7ec91ca522e2835ad92290b75e593e42) fix(artifacts): count only readable JavaScript sources as bundle members - [`5b7c7e1`](https://github.com/morluto/rea/commit/5b7c7e1db22139bcdf38b849e12f33dd2b934490) fix(artifacts): share script classification and retain plist link probes - [`22ee275`](https://github.com/morluto/rea/commit/22ee275271d911ff27aa7f5717ad025d57e945d9) fix(artifacts): share JavaScript acquisition classification - [`948f272`](https://github.com/morluto/rea/commit/948f2728915dcc54e41d67dad75a99257e037bf9) fix(artifacts): retain occurrence identity when proposing direct probes - [`e283e62`](https://github.com/morluto/rea/commit/e283e621df07277522ad45c212ec320cd435bf0e) fix(artifacts): sync occurrence probe fix with captured main - [`e364692`](https://github.com/morluto/rea/commit/e364692ab720cbacb24498ea1149f2135c8d0a05) fix(artifacts): align Harmony runtime families - [`9597916`](https://github.com/morluto/rea/commit/959791601bd6aeaeecf2b6546687deb298b63049) test(artifacts): expect native probes before managed probes - [`1e2ade3`](https://github.com/morluto/rea/commit/1e2ade30bac59e96ce776988a4ae70462c60ed4b) Merge commit '8fef2aa64ec1ee742e8b70b825938d30a0ea7319' into HEAD - [`aaede83`](https://github.com/morluto/rea/commit/aaede83264ee2df454b4293977571100dd743832) Merge branch 'main' into fix/inspect-artifact-bundle-probes ### 📊 Changes **7 files changed** (+307 additions, -18 deletions) <details> <summary>View changed files</summary> 📝 `src/artifacts/inventory/ArtifactGraphConstruction.ts` (+2 -1) 📝 `src/artifacts/javascript/JavaScriptArtifactFiles.ts` (+4 -14) 📝 `src/domain/artifactInspection.ts` (+81 -1) 📝 `src/domain/harmony/harmonyApplication.ts` (+4 -1) 📝 `src/domain/javascript/javascriptArtifactFiles.ts` (+19 -0) 📝 `tests/boundary/filesystem/harmony/application.test.ts` (+1 -1) ➕ `tests/boundary/providers/native/artifactProvider.directoryProbes.test.ts` (+196 -0) </details> ### 📄 Description ## Summary `inspect_artifact` on a native macOS app bundle proposes `analyze_javascript_application` as its only next probe, even when the bundle contains no JavaScript at all. Directory probes now follow the member formats that the inventory actually observed. No issue is linked; I found this while running REA 6.4.0 on two of my own Swift apps and searched open and closed issues and PRs before opening this. ## Problem and expected behavior `probesFor` in `src/domain/artifactInspection.ts` chose probes from `root_format` alone, and `"directory"` shared the JavaScript branch with `asar` and `javascript-bundle`. Because `inspect_artifact` only admits app bundles as directories (a plain directory is refused with "open_binary accepts files and macOS app bundles"), every native `.app` was told to run the JavaScript analyzer and was never pointed at `open_binary` or `inspect_plist`. Smallest trigger: any SwiftUI app bundle. ```text $ rea inspect-artifact Vigil.app --format json # Contents/MacOS/Vigil and Contents/Helpers/vigil are universal Mach-O next_probes: [analyze_javascript_application] ``` Expected: the probes match the bundle's members, so `open_binary` and `inspect_plist`, plus `analyze_javascript_application` only when the bundle holds an ASAR or bundled scripts (Electron). ## Change and scope For a directory root, `probesFor` now collects the `artifact_format` of every inventory occurrence and reuses the existing per format probes (renamed `probesForFormat`, unchanged otherwise) in a fixed order: ASAR and JavaScript, then Mach-O and ELF, then PE, then plist. Repeated operations are kept once, so `open_binary` keeps the general native rationale when a bundle holds both Mach-O and PE members. Non directory roots behave exactly as before. Following review: `classifyArtifactPath` now names the same JavaScript source extensions the analyzer reads (`.cts`, `.mts`, `.jsx`, `.ts`, `.tsx` in addition to `.cjs`, `.mjs`, `.js`), so a bundle holding only TypeScript sources still gets the JavaScript probe; and directory probes ignore symlink occurrences, which the inventory and analyzers never follow. Not included: no new probe operations, no schema change, and no change to hypotheses. ## Contract and boundary impact - Semantic owner and earliest changed stage: `src/domain/artifactInspection.ts`, probe derivation after inventory. - CLI and MCP/tool-catalog contract: none; `next_probes` and `unexplored_branches` keep their schema, only their values for directory roots change. - Provider, bridge, target-format, or platform compatibility: none. - Evidence, artifact, provenance, or reconstruction contract: inventory occurrences for `.cts`, `.mts`, `.jsx`, `.ts` and `.tsx` paths now carry `artifact_kind: javascript` and `artifact_format: javascript-bundle` instead of `resource` and `file`, matching what the JavaScript analyzer already reads. No schema change. - Process execution, authorization, cleanup, or containment impact: none. - Generated metadata, package, or installation impact: none. ## Evidence and regression coverage - Tests added or updated: `tests/boundary/providers/native/artifactProvider.directoryProbes.test.ts` runs `inspect_artifact` through the direct analysis workflow on a minimal native bundle (arm64 `mach_header_64` plus `Info.plist`) and on an Electron style bundle (the same plus `Contents/Resources/app.asar`), on a bundle whose only scripts are TypeScript, and on a bundle whose only `.js` member is a symlink. Unexplored branches are checked to carry the same probes. - Base reproduction or other evidence: the first two tests fail on the base revision (it returns only `analyze_javascript_application`); the TypeScript test fails without the classifier change and the symlink test fails without the symlink filter. All four pass with this change. - User-visible CLI/MCP output: on real universal Swift bundles (Vigil.app and API Pilot.app, macOS 27.0.1), `next_probes` changes from `["analyze_javascript_application"]` to `["open_binary", "inspect_plist"]`. - Remaining proof gaps: no real Electron app bundle was inspected; the Electron case is covered by the fixture only. 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 - `npx vitest run tests/boundary/providers/native/artifactProvider.directoryProbes.test.ts`: 4 passed; each test fails when its corresponding fix is reverted. - `npx vitest run` over every test file whose path mentions artifact, javascript, inventory, electron, asar, bundle, comparison or evidence (251 files): 2852 passed, 4 failed, 41 skipped. The 4 failures are in `tests/boundary/inspector/javascriptRuntimeObservation.test.ts` and `javascriptRuntimeTargetLocations.test.ts` and fail identically on unmodified `b777e5d` in my environment, so they are unrelated to this change. - `npm run check:fast`: typecheck and lint passed. - `npm run verify:test-discovery`: discovered all test files exactly once. - `oxfmt --check src tests`: passed. ## Compatibility, safety, and release - Breaking changes or migration steps: none. - Real Hopper/Ghidra, browser, or OS coverage: macOS 27.0.1 on Apple silicon, Node 24.21.0; no native provider was needed or run, since `inspect_artifact` is provider neutral. - Package or release metadata impact: none. - Security, privacy, process, or containment review: no new process execution or file access; the change only reads inventory occurrences already in memory. ## Review checklist - [x] This PR addresses a concrete problem or an agreed enhancement. - [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. - [x] 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 00:57:10 +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#4940
No description provided.