[PR #3775] feat(native): static packer identification for PE and ELF #5890

Open
opened 2026-10-31 01:10:12 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/3775
Author: @Kizuno18
Created: 10/15/2026
Status: 🔄 Open

Base: main ← Head: feat/static-packer-identification


📝 Commits (4)

  • aff9524 feat(native): static packer identification for PE and ELF
  • afd4c83 Merge remote-tracking branch 'upstream/main' into feat/static-packer-identification
  • 453913b style: format NodeHttpRequestOwner after lint autofix
  • ca8b671 fix(native): harden packer readers against review findings

📊 Changes

32 files changed (+2797 additions, -138 deletions)

View changed files

📝 docs/binary-diagnostics.md (+64 -0)
➕ docs/specs/3413-static-packer-identification/spec.md (+65 -0)
📝 scripts/lib/catalog-builders.mjs (+10 -1)
📝 src/application/CapabilityInventory.ts (+1 -1)
📝 src/application/InvestigationProviders.ts (+7 -0)
➕ src/application/binaryDiagnostics/PackerIndicatorsPort.ts (+20 -0)
➕ src/application/binaryDiagnostics/PackerIndicatorsService.ts (+112 -0)
📝 src/cli/binaryDiagnosticsCommands.ts (+33 -0)
📝 src/cliCommandNames.ts (+1 -0)
📝 src/composition/binaryDiagnostics.ts (+6 -0)
📝 src/contracts/native/binaryDiagnosticsToolContracts.ts (+19 -0)
📝 src/contracts/toolEffects.test.ts (+2 -0)
📝 src/contracts/toolEffects.ts (+1 -0)
📝 src/domain/artifactOperationError.ts (+1 -0)
📝 src/domain/flutter/flutterBuildAnalysis.ts (+1 -1)
➕ src/domain/native/packerIndicators.ts (+126 -0)
➕ src/native/packer/ElfPackerReader.ts (+280 -0)
➕ src/native/packer/PackerIndicatorParser.test.ts (+390 -0)
➕ src/native/packer/PackerIndicatorParser.ts (+99 -0)
➕ src/native/packer/PackerIndicatorReview.test.ts (+247 -0)

...and 12 more files

📄 Description

Summary

Fixes #3413 (Part A only: static packer identification). Part B — producing a decompressed derived artifact with a caller-supplied upx -d — is not included. It waits for the maintainer answer to the scope question in #3413 and would be a separate follow-up PR. This PR does not close the Part B request.

REA had no packer signal. Callers had to infer packing from scattered hints (few imports, odd section names), and different runs reached different conclusions. This adds a read-only inspect_packer_indicators MCP tool and rea inspect-packer-indicators CLI command for PE32, PE32+, ELF32 and ELF64. It returns per-region facts, named indicators and a likely_packed / not_observed / unknown verdict as observed Evidence.

Problem and expected behavior

For an admitted PE or ELF, the issue asks for:

  • per-section raw/virtual size, flags and Shannon entropy;
  • known packer section names and magic (UPX0/UPX1, UPX!) with byte offsets;
  • import count and whether imports are limited to loader-style APIs;
  • entry point in a non-first or writable+executable section;
  • overlay presence and size;
  • a verdict with supporting facts and explicit limitations, where an empty result does not mean the file is unpacked.

All of these are in the report:

Field Content
regions PE sections, or ELF PT_LOAD segments followed by any section headers: virtual address (PE RVA), virtual size, file range, raw flags, R/W/X, entropy (null when no file bytes back the region)
entry_point address, containing region, file offset
signatures packer section names (UPX, ASPack, MPRESS, PECompact, Petite, NsPack, RLPack, kkrunchy, MEW) and magic (UPX!, UPX info string) with offsets; up to 16 offsets listed, plus magic_matches_total
imports PE: libraries, function/ordinal counts, loader-style APIs present, only_loader_style. An inconsistent directory is reported as unreadable, not partially decoded. ELF: not_applicable
overlay trailing bytes after headers/sections/segments, with entropy and any PE certificate-table range
indicators / verdict strong = known name or magic. supporting = entry outside the first PE section, entry in a W+X region, entry outside every region, high-entropy executable region (≥ 7.2 bits/byte over ≥ 1 KiB), executable virtual-only region (virtual ≥ 4× file size and ≥ 64 KiB), loader-only imports, ELF executable without section headers, non-certificate overlay. likely_packed = any strong or ≥ 2 supporting; unknown = 1 supporting or part of the image unexamined; otherwise not_observed

Change and scope

  • src/native/packer/: a tolerant PE reader and an ELF reader (both classes and byte orders), the shared indicator and verdict derivation, and a provider over the existing readStableArtifact snapshot. Packed layouts such as a zero-raw UPX0 or no ELF section headers are reported rather than rejected. Section ranges past EOF are clamped and listed as limitations.
  • PackerIndicatorsService validates input and cross-checks provider output (every range inside the snapshot, every region reference resolves, overlay ends at EOF) before creating Evidence. This follows PeResourcesService.
  • The stable-file failure mapping that used to be private to PeResourcesProvider moved to src/native/stableFileFailure.ts, and both providers now use it. Error behavior for inspect_pe_resources is unchanged, and its existing tests pass.
  • MCP registration reuses the registerPeResourcesTool path. The tool contract, effects (evidence: no launch, no writes, no network), capability inventory, catalog provider entry (rea-packer-indicators) and CLI command are added.
  • Docs: a new section in docs/binary-diagnostics.md and a spec at docs/specs/3413-static-packer-identification/spec.md.

Intentionally not included:

  • Part B (UPX extraction as a derived artifact).
  • Commercial protectors, emulation, OEP/IAT work.
  • ELF dynamic-symbol import heuristics and PE delay-load imports.
  • DOS MZ without a PE header.
  • RT_STRING/RT_VERSION decoding, which is already in flight in #2812/#2887.

Contract and boundary impact

  • Semantic owner and earliest changed stage: new domain schema src/domain/native/packerIndicators.ts, then the provider in src/native/packer/.
  • Contribution scope fit and linked maintainer decision: static identification only. The #2080 closing comment invites a detection-only proposal. The Part B scope decision is pending in #3413 and is not needed for this diff.
  • CLI and MCP/tool-catalog contract: new inspect_packer_indicators / inspect-packer-indicators. Input is path and max_file_bytes (default 64 MiB, max 512 MiB). No existing contract changes.
  • Provider, bridge, target-format, or platform compatibility: portable Node parser, with no external tool or engine.
  • Evidence, artifact, provenance, or reconstruction contract: Evidence subject is pe or elf with the snapshot SHA-256; confidence is observed, and limitations are copied into the Evidence. No derived artifacts.
  • Target selection, authority, upstream behavior, and cleanup details: explicit path only. Regular files only; symlinks are rejected; the snapshot is checked for identity.
  • Generated metadata, package, or installation impact: catalog builder adds the provider entry. metadata:check and mcp-catalog:check pass. No committed build outputs.

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/native/packer/PackerIndicatorParser.test.ts (12 tests):
      • entropy;
      • ordinary PE32/PE32+ → not_observed;
      • a UPX-shaped PE (empty RWX UPX0, high-entropy RWX UPX1 holding the entry, UPX! magic, loader-only imports) → likely_packed with exact offsets;
      • a single vs. double supporting-indicator verdict;
      • an overlay vs. a certificate-only overlay;
      • an unreadable import directory → unknown;
      • an ordinary ELF64 → not_observed;
      • UPX-shaped ELF64 and ELF32;
      • non-PE/ELF and truncated headers → format failure;
      • hostile section ranges.
    • src/native/packer/PackerIndicatorReview.test.ts (11 tests, each failing on the previous head 453913b7f): shared entropy work budget for overlapping headers; one high-entropy fact for an ELF segment and its section over the same bytes; PE import descriptor leaving its section → unreadable; extended ELF section numbering (e_shnum == 0); trailing PT_NOTE not reported as overlay; section names bounded by the string table and invalid e_shstrndx reported; executable derived from IMAGE_SCN_MEM_EXECUTE only; section-name match locations point at the name bytes; SizeOfHeaders padding not treated as overlay; truncated certificate table not treated as complete.
    • tests/boundary/filesystem/packerIndicators.test.ts: Evidence through the composed service; directory, symlink, malformed, missing and relative paths → typed input errors; budget and cancellation failures.
    • toolEffects.test.ts and localToolContracts.test.ts include the new tool.
  • Fixtures: all images are hand-built in PackerIndicators.fixture.ts from deterministic filler. No packed program or third-party binary is committed.
  • User-visible CLI output (hand-built UPX-shaped PE, abbreviated):
{
  "verdict": { "status": "likely_packed", "basis": "Known packer signature observed (packer_section_name, packer_magic)." },
  "indicators": ["packer_section_name", "packer_section_name", "packer_magic", "entry_outside_first_section",
                 "entry_in_writable_executable_region", "virtual_only_region", "high_entropy_executable_region",
                 "loader_style_imports_only"],
  "regions": [
    { "name": "UPX0", "raw": { "offset": 0, "bytes": 0 }, "virtual_size": 131072, "writable": true, "executable": true, "entropy": null },
    { "name": "UPX1", "raw": { "offset": 512, "bytes": 8704 }, "virtual_size": 12288, "writable": true, "executable": true, "entropy": 7.8136 }
  ],
  "signatures": { "magic": [{ "family": "upx", "value": "UPX!", "location": { "offset": 517, "bytes": 4 } }] },
  "entry_point": { "address": "0x21010", "region_index": 1, "file_offset": 528 }
}

The same command on an ordinary one-section PE returns {"status":"not_observed", ...}.

  • Remaining proof gaps:
    • Not yet checked against real upx --best output of a self-built PE and ELF, which is the verification suggested in the issue. Thresholds (7.2 bits/byte, 4×/64 KiB) are chosen conservatively and may need tuning on real samples.
    • No real Windows host run; none is needed, because the parser is portable.

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

After the review hardening commit ca8b671fb (Node 24.18.0, Linux x64):

  • npx tsc --noEmit -p .: passes.
  • npm run check:ci: passes.
  • npm run test:fast: 12384 passed, 9 skipped.
  • npx vitest run src/native/packer: 23 passed.

Earlier, on the initial head:

  • npx tsc --noEmit -p .: passes.
  • npm run build: passes.
  • npx vitest run src/native/packer tests/boundary/filesystem/packerIndicators.test.ts: 15 passed.
  • npx vitest run src/contracts tests/acceptance/tools/localToolContracts.test.ts tests/acceptance/applications/peResources.test.ts tests/boundary/filesystem tests/boundary/providers/artifactReadCleanupRetry.test.ts src/application/binaryDiagnostics: 2715 passed and 6 failed. All 6 failures are environmental and unrelated to this change:
    • zip is not installed;
    • ignored generated files docs/public/product-catalog.json and docs/verification/managed-conformance-manifest.json are absent from this checkout.
  • npx oxlint on changed paths: no errors. Some complexity/max-params warnings remain in the new readers, as is common elsewhere in the tree.
  • npm run verify:module-boundaries: passes.
  • npx knip: passes.
  • npm run metadata:check: passes.
  • npm run mcp-catalog:check: passes.
  • npx oxfmt on changed files: applied.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. This only adds a tool.
  • Real Hopper/Ghidra, browser, or OS coverage: not applicable (no provider involved). Linux x64 host.
  • Package or release metadata impact: new tool in the catalog.
  • Security, privacy, process, or containment review: bounded read of one regular file. No process launch, no writes, no network. Import walking is bounded (4096 libraries, 65536 functions, 512-byte names), and magic output is capped.

Author readiness

Human owner: @Kizuno18

  • 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/3775 **Author:** [@Kizuno18](https://github.com/Kizuno18) **Created:** 10/15/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feat/static-packer-identification` --- ### 📝 Commits (4) - [`aff9524`](https://github.com/morluto/rea/commit/aff9524a7dc87979645e4779f40c619014b2e5f9) feat(native): static packer identification for PE and ELF - [`afd4c83`](https://github.com/morluto/rea/commit/afd4c830a54e68c23d77402c2fc48b3503a055f3) Merge remote-tracking branch 'upstream/main' into feat/static-packer-identification - [`453913b`](https://github.com/morluto/rea/commit/453913b7fecf8a1a6f581813818e01d5a55cb400) style: format NodeHttpRequestOwner after lint autofix - [`ca8b671`](https://github.com/morluto/rea/commit/ca8b671fba45115535d0874597d6608bf6ac6eab) fix(native): harden packer readers against review findings ### 📊 Changes **32 files changed** (+2797 additions, -138 deletions) <details> <summary>View changed files</summary> 📝 `docs/binary-diagnostics.md` (+64 -0) ➕ `docs/specs/3413-static-packer-identification/spec.md` (+65 -0) 📝 `scripts/lib/catalog-builders.mjs` (+10 -1) 📝 `src/application/CapabilityInventory.ts` (+1 -1) 📝 `src/application/InvestigationProviders.ts` (+7 -0) ➕ `src/application/binaryDiagnostics/PackerIndicatorsPort.ts` (+20 -0) ➕ `src/application/binaryDiagnostics/PackerIndicatorsService.ts` (+112 -0) 📝 `src/cli/binaryDiagnosticsCommands.ts` (+33 -0) 📝 `src/cliCommandNames.ts` (+1 -0) 📝 `src/composition/binaryDiagnostics.ts` (+6 -0) 📝 `src/contracts/native/binaryDiagnosticsToolContracts.ts` (+19 -0) 📝 `src/contracts/toolEffects.test.ts` (+2 -0) 📝 `src/contracts/toolEffects.ts` (+1 -0) 📝 `src/domain/artifactOperationError.ts` (+1 -0) 📝 `src/domain/flutter/flutterBuildAnalysis.ts` (+1 -1) ➕ `src/domain/native/packerIndicators.ts` (+126 -0) ➕ `src/native/packer/ElfPackerReader.ts` (+280 -0) ➕ `src/native/packer/PackerIndicatorParser.test.ts` (+390 -0) ➕ `src/native/packer/PackerIndicatorParser.ts` (+99 -0) ➕ `src/native/packer/PackerIndicatorReview.test.ts` (+247 -0) _...and 12 more files_ </details> ### 📄 Description ## Summary Fixes #3413 (Part A only: static packer identification). **Part B — producing a decompressed derived artifact with a caller-supplied `upx -d` — is not included.** It waits for the maintainer answer to the scope question in #3413 and would be a separate follow-up PR. This PR does not close the Part B request. REA had no packer signal. Callers had to infer packing from scattered hints (few imports, odd section names), and different runs reached different conclusions. This adds a read-only `inspect_packer_indicators` MCP tool and `rea inspect-packer-indicators` CLI command for PE32, PE32+, ELF32 and ELF64. It returns per-region facts, named indicators and a `likely_packed` / `not_observed` / `unknown` verdict as `observed` Evidence. ## Problem and expected behavior For an admitted PE or ELF, the issue asks for: - per-section raw/virtual size, flags and Shannon entropy; - known packer section names and magic (`UPX0`/`UPX1`, `UPX!`) with byte offsets; - import count and whether imports are limited to loader-style APIs; - entry point in a non-first or writable+executable section; - overlay presence and size; - a verdict with supporting facts and explicit limitations, where an empty result does not mean the file is unpacked. All of these are in the report: | Field | Content | | --- | --- | | `regions` | PE sections, or ELF `PT_LOAD` segments followed by any section headers: virtual address (PE RVA), virtual size, file range, raw flags, R/W/X, entropy (`null` when no file bytes back the region) | | `entry_point` | address, containing region, file offset | | `signatures` | packer section names (UPX, ASPack, MPRESS, PECompact, Petite, NsPack, RLPack, kkrunchy, MEW) and magic (`UPX!`, UPX info string) with offsets; up to 16 offsets listed, plus `magic_matches_total` | | `imports` | PE: libraries, function/ordinal counts, loader-style APIs present, `only_loader_style`. An inconsistent directory is reported as `unreadable`, not partially decoded. ELF: `not_applicable` | | `overlay` | trailing bytes after headers/sections/segments, with entropy and any PE certificate-table range | | `indicators` / `verdict` | `strong` = known name or magic. `supporting` = entry outside the first PE section, entry in a W+X region, entry outside every region, high-entropy executable region (≥ 7.2 bits/byte over ≥ 1 KiB), executable virtual-only region (virtual ≥ 4× file size and ≥ 64 KiB), loader-only imports, ELF executable without section headers, non-certificate overlay. `likely_packed` = any strong or ≥ 2 supporting; `unknown` = 1 supporting or part of the image unexamined; otherwise `not_observed` | ## Change and scope - `src/native/packer/`: a tolerant PE reader and an ELF reader (both classes and byte orders), the shared indicator and verdict derivation, and a provider over the existing `readStableArtifact` snapshot. Packed layouts such as a zero-raw `UPX0` or no ELF section headers are reported rather than rejected. Section ranges past EOF are clamped and listed as limitations. - `PackerIndicatorsService` validates input and cross-checks provider output (every range inside the snapshot, every region reference resolves, overlay ends at EOF) before creating Evidence. This follows `PeResourcesService`. - The stable-file failure mapping that used to be private to `PeResourcesProvider` moved to `src/native/stableFileFailure.ts`, and both providers now use it. Error behavior for `inspect_pe_resources` is unchanged, and its existing tests pass. - MCP registration reuses the `registerPeResourcesTool` path. The tool contract, effects (`evidence`: no launch, no writes, no network), capability inventory, catalog provider entry (`rea-packer-indicators`) and CLI command are added. - Docs: a new section in `docs/binary-diagnostics.md` and a spec at `docs/specs/3413-static-packer-identification/spec.md`. Intentionally not included: - Part B (UPX extraction as a derived artifact). - Commercial protectors, emulation, OEP/IAT work. - ELF dynamic-symbol import heuristics and PE delay-load imports. - DOS MZ without a PE header. - RT_STRING/RT_VERSION decoding, which is already in flight in #2812/#2887. ## Contract and boundary impact - Semantic owner and earliest changed stage: new domain schema `src/domain/native/packerIndicators.ts`, then the provider in `src/native/packer/`. - Contribution scope fit and linked maintainer decision: static identification only. The #2080 closing comment invites a detection-only proposal. The Part B scope decision is pending in #3413 and is not needed for this diff. - CLI and MCP/tool-catalog contract: new `inspect_packer_indicators` / `inspect-packer-indicators`. Input is `path` and `max_file_bytes` (default 64 MiB, max 512 MiB). No existing contract changes. - Provider, bridge, target-format, or platform compatibility: portable Node parser, with no external tool or engine. - Evidence, artifact, provenance, or reconstruction contract: Evidence subject is `pe` or `elf` with the snapshot SHA-256; confidence is `observed`, and limitations are copied into the Evidence. No derived artifacts. - Target selection, authority, upstream behavior, and cleanup details: explicit path only. Regular files only; symlinks are rejected; the snapshot is checked for identity. - Generated metadata, package, or installation impact: catalog builder adds the provider entry. `metadata:check` and `mcp-catalog:check` pass. No committed build outputs. 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/native/packer/PackerIndicatorParser.test.ts` (12 tests): - entropy; - ordinary PE32/PE32+ → `not_observed`; - a UPX-shaped PE (empty RWX `UPX0`, high-entropy RWX `UPX1` holding the entry, `UPX!` magic, loader-only imports) → `likely_packed` with exact offsets; - a single vs. double supporting-indicator verdict; - an overlay vs. a certificate-only overlay; - an unreadable import directory → `unknown`; - an ordinary ELF64 → `not_observed`; - UPX-shaped ELF64 and ELF32; - non-PE/ELF and truncated headers → format failure; - hostile section ranges. - `src/native/packer/PackerIndicatorReview.test.ts` (11 tests, each failing on the previous head `453913b7f`): shared entropy work budget for overlapping headers; one high-entropy fact for an ELF segment and its section over the same bytes; PE import descriptor leaving its section → `unreadable`; extended ELF section numbering (`e_shnum == 0`); trailing `PT_NOTE` not reported as overlay; section names bounded by the string table and invalid `e_shstrndx` reported; executable derived from `IMAGE_SCN_MEM_EXECUTE` only; section-name match locations point at the name bytes; `SizeOfHeaders` padding not treated as overlay; truncated certificate table not treated as complete. - `tests/boundary/filesystem/packerIndicators.test.ts`: Evidence through the composed service; directory, symlink, malformed, missing and relative paths → typed input errors; budget and cancellation failures. - `toolEffects.test.ts` and `localToolContracts.test.ts` include the new tool. - Fixtures: all images are hand-built in `PackerIndicators.fixture.ts` from deterministic filler. No packed program or third-party binary is committed. - User-visible CLI output (hand-built UPX-shaped PE, abbreviated): ```json { "verdict": { "status": "likely_packed", "basis": "Known packer signature observed (packer_section_name, packer_magic)." }, "indicators": ["packer_section_name", "packer_section_name", "packer_magic", "entry_outside_first_section", "entry_in_writable_executable_region", "virtual_only_region", "high_entropy_executable_region", "loader_style_imports_only"], "regions": [ { "name": "UPX0", "raw": { "offset": 0, "bytes": 0 }, "virtual_size": 131072, "writable": true, "executable": true, "entropy": null }, { "name": "UPX1", "raw": { "offset": 512, "bytes": 8704 }, "virtual_size": 12288, "writable": true, "executable": true, "entropy": 7.8136 } ], "signatures": { "magic": [{ "family": "upx", "value": "UPX!", "location": { "offset": 517, "bytes": 4 } }] }, "entry_point": { "address": "0x21010", "region_index": 1, "file_offset": 528 } } ``` The same command on an ordinary one-section PE returns `{"status":"not_observed", ...}`. - Remaining proof gaps: - Not yet checked against real `upx --best` output of a self-built PE and ELF, which is the verification suggested in the issue. Thresholds (7.2 bits/byte, 4×/64 KiB) are chosen conservatively and may need tuning on real samples. - No real Windows host run; none is needed, because the parser is portable. 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 After the review hardening commit `ca8b671fb` (Node 24.18.0, Linux x64): - `npx tsc --noEmit -p .`: passes. - `npm run check:ci`: passes. - `npm run test:fast`: 12384 passed, 9 skipped. - `npx vitest run src/native/packer`: 23 passed. Earlier, on the initial head: - `npx tsc --noEmit -p .`: passes. - `npm run build`: passes. - `npx vitest run src/native/packer tests/boundary/filesystem/packerIndicators.test.ts`: 15 passed. - `npx vitest run src/contracts tests/acceptance/tools/localToolContracts.test.ts tests/acceptance/applications/peResources.test.ts tests/boundary/filesystem tests/boundary/providers/artifactReadCleanupRetry.test.ts src/application/binaryDiagnostics`: 2715 passed and 6 failed. All 6 failures are environmental and unrelated to this change: - `zip` is not installed; - ignored generated files `docs/public/product-catalog.json` and `docs/verification/managed-conformance-manifest.json` are absent from this checkout. - `npx oxlint` on changed paths: no errors. Some complexity/max-params warnings remain in the new readers, as is common elsewhere in the tree. - `npm run verify:module-boundaries`: passes. - `npx knip`: passes. - `npm run metadata:check`: passes. - `npm run mcp-catalog:check`: passes. - `npx oxfmt` on changed files: applied. ## Compatibility, safety, and release - Breaking changes or migration steps: none. This only adds a tool. - Real Hopper/Ghidra, browser, or OS coverage: not applicable (no provider involved). Linux x64 host. - Package or release metadata impact: new tool in the catalog. - Security, privacy, process, or containment review: bounded read of one regular file. No process launch, no writes, no network. Import walking is bounded (4096 libraries, 65536 functions, 512-byte names), and magic output is capped. ## Author readiness Human owner: @Kizuno18 - [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. - [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>
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#5890
No description provided.