[PR #7236] [MERGED] feat(ghidra): reuse existing projects through verified copies #7736

Closed
opened 2026-11-03 13:40:00 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/7236
Author: @gensokyo-dev
Created: 10/26/2026
Status: ✅ Merged
Merged: 10/26/2026
Merged by: @gensokyo-dev

Base: main ← Head: feat/1048-ghidra-existing-project


📝 Commits (10+)

  • 359f82c feat(ghidra): add existing-project launcher groundwork
  • f257ca4 feat(ghidra): bind read-only project reuse to selected content
  • f3cd478 test(ghidra): sample known local functions from a bounded inventory page
  • a542457 test(ghidra): compare exported functions by their stable identity
  • 9746ec7 docs(ghidra): document project provenance and bounded preparation
  • 5d237eb test(ghidra): exercise project staleness through public MCP
  • 314b0e0 fix(ghidra): report invalid program selection at its owning boundary
  • 9f8aabb docs(ghidra): record real project-reuse correctness and performance
  • 792525a docs(ghidra): distinguish Program readiness from analysis completion
  • bfd33f5 fix(ghidra): preserve reused project boundaries and historical evidence

📊 Changes

26 files changed (+2210 additions, -131 deletions)

View changed files

📝 .agents/skills/reverse-engineer-anything/references/native-and-artifacts.md (+14 -0)
📝 bridge/ghidra/ReaGhidraBridge.java (+18 -6)
📝 docs/installation.md (+62 -4)
📝 docs/mcp-contracts.md (+6 -0)
➕ experiments/analysis-efficiency/ghidra-project-reuse.md (+142 -0)
➕ experiments/analysis-efficiency/ghidra-project-reuse.mjs (+377 -0)
📝 src/application/SetupRegistrationEnvironment.ts (+2 -0)
📝 src/config/environment.ts (+32 -0)
➕ src/config/ghidraExistingProject.ts (+29 -0)
📝 src/config/parseConfig.ts (+10 -0)
📝 src/config/types.ts (+2 -0)
📝 src/ghidra/GhidraAnalysisProfile.ts (+19 -0)
📝 src/ghidra/GhidraClient.ts (+2 -0)
📝 src/ghidra/GhidraClientTypes.ts (+2 -1)
📝 src/ghidra/GhidraLauncher.ts (+171 -60)
➕ src/ghidra/GhidraProjectHistory.ts (+39 -0)
➕ src/ghidra/GhidraProjectSnapshot.ts (+279 -0)
📝 src/ghidra/GhidraProvider.behavior.test.ts (+109 -1)
📝 src/ghidra/GhidraProvider.ts (+70 -8)
📝 src/ghidra/GhidraProviderCapabilities.ts (+50 -2)

...and 6 more files

📄 Description

Summary

Fixes #1048 and #2147. Repeated Ghidra investigations can select an existing project instead of paying import and auto-analysis on every session. Builds on the launcher groundwork in #2150 by @akushonkamen and @morluto, preserving their attribution.

Change and scope

REA_GHIDRA_PROJECT_PATH selects an expanded .gpr marker; optional REA_GHIDRA_PROGRAM_NAME selects one exact root program (default: resolved executable filename). Shared CLI/MCP configuration and saved registrations use the same selection.

One provider owner fingerprints the selected .gpr/.rep pair with serial 64-KiB reads, copies only that pair into the owned runtime, and verifies copied content against the committed profile before launch. The engine runs -process -noanalysis -readOnly, skips repair scripts and exposes no database-edit capabilities. The bridge still validates the recorded import SHA against the admitted target. Source changes/mismatches fail explicitly; close/reopen resolves a new commitment.

Existing-project Evidence records caller/resolved paths, program and project content identity. Original analysis completeness/settings stay unknown; the authenticated bridge reports that origin with read-only capabilities and null completion. Fresh-import handshake semantics remain supported. Import overrides and Windows/special import profiles are rejected for this mode.

Scope decision: not applicable; existing static provider operations, owned helper processes/copies, no added target execution, injection or target mutation. The original database is read for copying/fingerprinting and is never opened/saved by Ghidra. No new installer or implicit persistent cache. Authored setup/contract/skill docs are updated; generated outputs remain ignored.

Executed validation

  • Focused Ghidra suites: 35 files, 958 passed / 4 platform skips, including copied-project identity, ignored sibling projects, stale content, configuration and strict origin/unknown-completion handshake cases.
  • Build, typecheck/lint, docs (9 cases), whole-repository formatting: passed with the updated main dependency lock.
  • Actual Linux x64 Ghidra 12.1.4 / JDK 21 CLI and SDK workflows passed. Full function inventory and two nonempty pseudocode results match fresh import by function identity; complete exported Evidence authenticates offline and source project/binary content stays unchanged.
  • Review regressions cover resolved executable names, unavailable Windows reuse, exact cancellation reasons, and shared /tmp parents. Actual Ghidra saved seed/analyzer reports reopen successfully as one immutable historical Evidence record linked from observations; a real project directly under /tmp also preserves identical facts and unchanged source content.
  • Real wrong-target digest and changed-after-open cases reject explicitly and clean up. Actual CLI decompilation matches MCP on the same selected project.
Completed investigation Fresh wall / family CPU Reuse wall / family CPU Fresh / reuse peak family GiB
ls, 652 functions 63.62 / 84.87 s 31.69 / 46.61 s 1.276 / 0.938
libcrypto, 14,338 functions 186.42 / 287.01 s 25.45 / 40.23 s 1.857 / 1.258

Matched rows use the same five-family catalog and complete task. A narrower executed ls pair removes the unused native family (97 tools), preserves facts, and uses 67,523 / 67,820 estimated full-wire tokens; the broader pair uses 85,151 / 85,448. Extra project provenance slightly increases response tokens. Estimates use cl100k_base; actual model usage is unmeasured. Preparation costs are separate: ls 36.17 s / 59.54 CPU s; crypto 231.76 s / 251.08 CPU s. Sequential shared-host samples do not establish a general speed ratio. All runs use 2-CPU affinity and an 8-GiB family guard; no OOM/guard or cleanup failure.

Full protocol, cold/warm calls, source revisions, heap settings, preparation, calibration receipts and limits: verification.

Baseline controls on main cd68181c9 and final feature bfd33f571 both produce the same 17 failures / 54 passes across six exact files: CLI advertised defaults (12), WorkBuddy/Trae paths, redirected-AppData uninstall, pcap ENOTDIR diagnostics and pwntools completed-read cleanup. Failure names and assertions match. Final-head CI run 40338086104 passed source tests, static checks, build/docs, Ghidra bridge compilation, Linux x64/arm64 and macOS arm64 packages, Windows capability/package tests, and Greptile review. Shard 7 reports 13 baseline failures; cancelled shard logs add the same WorkBuddy/pwntools baseline failures. Other cancelled coverage remains unverified. Readiness declarations stay unchecked.

Main subsequently fixed these failures. A local integration of final feature bfd33f571 with main 2b84efe0d built successfully and passed 248 tests across eight files, including both Ghidra boundary suites and all six baseline-control files. The authorized bypass applies to the old-baseline CI result, with current-main integration checked; no human-review attestation is made.

Real PE/Mach-O/macOS reuse and very large project trees remain unverified. Windows existing-project mode remains unsupported.

Author readiness

Human owner: @gensokyo-dev

  • 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.

The user explicitly authorized opening ready for review and bypassing this gate without an AI attestation of human review. Baseline CI failures, if any, will be attributed before applying the authorized bypass.


🔄 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/7236 **Author:** [@gensokyo-dev](https://github.com/gensokyo-dev) **Created:** 10/26/2026 **Status:** ✅ Merged **Merged:** 10/26/2026 **Merged by:** [@gensokyo-dev](https://github.com/gensokyo-dev) **Base:** `main` ← **Head:** `feat/1048-ghidra-existing-project` --- ### 📝 Commits (10+) - [`359f82c`](https://github.com/morluto/rea/commit/359f82c3be6407b6e0d8676f34d7d6f2ceba873c) feat(ghidra): add existing-project launcher groundwork - [`f257ca4`](https://github.com/morluto/rea/commit/f257ca4ae49893d8d2e9c8aceb986d199bea28ca) feat(ghidra): bind read-only project reuse to selected content - [`f3cd478`](https://github.com/morluto/rea/commit/f3cd478123a2645e5a7262d7de63b2b667e595de) test(ghidra): sample known local functions from a bounded inventory page - [`a542457`](https://github.com/morluto/rea/commit/a5424575aba6c373b00d07593a4071f6a4cf87cb) test(ghidra): compare exported functions by their stable identity - [`9746ec7`](https://github.com/morluto/rea/commit/9746ec7d932689924ac87ef51a1d4cad36f7d2de) docs(ghidra): document project provenance and bounded preparation - [`5d237eb`](https://github.com/morluto/rea/commit/5d237eb0c036658d9d69e7f99609c9a612434c92) test(ghidra): exercise project staleness through public MCP - [`314b0e0`](https://github.com/morluto/rea/commit/314b0e038d9c603f03d2974ef89d7dff540583c7) fix(ghidra): report invalid program selection at its owning boundary - [`9f8aabb`](https://github.com/morluto/rea/commit/9f8aabb293158662848a5ce42d7d6e93027b7801) docs(ghidra): record real project-reuse correctness and performance - [`792525a`](https://github.com/morluto/rea/commit/792525ae8e8ee035ee20f0650afd3bad38dbc431) docs(ghidra): distinguish Program readiness from analysis completion - [`bfd33f5`](https://github.com/morluto/rea/commit/bfd33f571e64438e399b159c675808d78d765208) fix(ghidra): preserve reused project boundaries and historical evidence ### 📊 Changes **26 files changed** (+2210 additions, -131 deletions) <details> <summary>View changed files</summary> 📝 `.agents/skills/reverse-engineer-anything/references/native-and-artifacts.md` (+14 -0) 📝 `bridge/ghidra/ReaGhidraBridge.java` (+18 -6) 📝 `docs/installation.md` (+62 -4) 📝 `docs/mcp-contracts.md` (+6 -0) ➕ `experiments/analysis-efficiency/ghidra-project-reuse.md` (+142 -0) ➕ `experiments/analysis-efficiency/ghidra-project-reuse.mjs` (+377 -0) 📝 `src/application/SetupRegistrationEnvironment.ts` (+2 -0) 📝 `src/config/environment.ts` (+32 -0) ➕ `src/config/ghidraExistingProject.ts` (+29 -0) 📝 `src/config/parseConfig.ts` (+10 -0) 📝 `src/config/types.ts` (+2 -0) 📝 `src/ghidra/GhidraAnalysisProfile.ts` (+19 -0) 📝 `src/ghidra/GhidraClient.ts` (+2 -0) 📝 `src/ghidra/GhidraClientTypes.ts` (+2 -1) 📝 `src/ghidra/GhidraLauncher.ts` (+171 -60) ➕ `src/ghidra/GhidraProjectHistory.ts` (+39 -0) ➕ `src/ghidra/GhidraProjectSnapshot.ts` (+279 -0) 📝 `src/ghidra/GhidraProvider.behavior.test.ts` (+109 -1) 📝 `src/ghidra/GhidraProvider.ts` (+70 -8) 📝 `src/ghidra/GhidraProviderCapabilities.ts` (+50 -2) _...and 6 more files_ </details> ### 📄 Description ## Summary Fixes #1048 and #2147. Repeated Ghidra investigations can select an existing project instead of paying import and auto-analysis on every session. Builds on the launcher groundwork in #2150 by @akushonkamen and @morluto, preserving their attribution. ## Change and scope `REA_GHIDRA_PROJECT_PATH` selects an expanded `.gpr` marker; optional `REA_GHIDRA_PROGRAM_NAME` selects one exact root program (default: resolved executable filename). Shared CLI/MCP configuration and saved registrations use the same selection. One provider owner fingerprints the selected `.gpr`/`.rep` pair with serial 64-KiB reads, copies only that pair into the owned runtime, and verifies copied content against the committed profile before launch. The engine runs `-process -noanalysis -readOnly`, skips repair scripts and exposes no database-edit capabilities. The bridge still validates the recorded import SHA against the admitted target. Source changes/mismatches fail explicitly; close/reopen resolves a new commitment. Existing-project Evidence records caller/resolved paths, program and project content identity. Original analysis completeness/settings stay unknown; the authenticated bridge reports that origin with read-only capabilities and null completion. Fresh-import handshake semantics remain supported. Import overrides and Windows/special import profiles are rejected for this mode. Scope decision: not applicable; existing static provider operations, owned helper processes/copies, no added target execution, injection or target mutation. The original database is read for copying/fingerprinting and is never opened/saved by Ghidra. No new installer or implicit persistent cache. Authored setup/contract/skill docs are updated; generated outputs remain ignored. ## Executed validation - Focused Ghidra suites: **35 files, 958 passed / 4 platform skips**, including copied-project identity, ignored sibling projects, stale content, configuration and strict origin/unknown-completion handshake cases. - Build, typecheck/lint, docs (9 cases), whole-repository formatting: passed with the updated main dependency lock. - Actual Linux x64 Ghidra 12.1.4 / JDK 21 CLI and SDK workflows passed. Full function inventory and two nonempty pseudocode results match fresh import by function identity; complete exported Evidence authenticates offline and source project/binary content stays unchanged. - Review regressions cover resolved executable names, unavailable Windows reuse, exact cancellation reasons, and shared `/tmp` parents. Actual Ghidra saved seed/analyzer reports reopen successfully as one immutable historical Evidence record linked from observations; a real project directly under `/tmp` also preserves identical facts and unchanged source content. - Real wrong-target digest and changed-after-open cases reject explicitly and clean up. Actual CLI decompilation matches MCP on the same selected project. | Completed investigation | Fresh wall / family CPU | Reuse wall / family CPU | Fresh / reuse peak family GiB | | --- | ---: | ---: | ---: | | ls, 652 functions | 63.62 / 84.87 s | 31.69 / 46.61 s | 1.276 / 0.938 | | libcrypto, 14,338 functions | 186.42 / 287.01 s | 25.45 / 40.23 s | 1.857 / 1.258 | Matched rows use the same five-family catalog and complete task. A narrower executed ls pair removes the unused native family (97 tools), preserves facts, and uses 67,523 / 67,820 estimated full-wire tokens; the broader pair uses 85,151 / 85,448. Extra project provenance slightly increases response tokens. Estimates use cl100k_base; actual model usage is unmeasured. Preparation costs are separate: ls 36.17 s / 59.54 CPU s; crypto 231.76 s / 251.08 CPU s. Sequential shared-host samples do not establish a general speed ratio. All runs use 2-CPU affinity and an 8-GiB family guard; no OOM/guard or cleanup failure. Full protocol, cold/warm calls, source revisions, heap settings, preparation, calibration receipts and limits: [verification](https://github.com/morluto/rea/blob/bfd33f571e64438e399b159c675808d78d765208/experiments/analysis-efficiency/ghidra-project-reuse.md). Baseline controls on main `cd68181c9` and final feature `bfd33f571` both produce the same **17 failures / 54 passes** across six exact files: CLI advertised defaults (12), WorkBuddy/Trae paths, redirected-AppData uninstall, pcap ENOTDIR diagnostics and pwntools completed-read cleanup. Failure names and assertions match. Final-head CI run [40338086104](https://github.com/morluto/rea/actions/runs/40338086104) passed source tests, static checks, build/docs, Ghidra bridge compilation, Linux x64/arm64 and macOS arm64 packages, Windows capability/package tests, and Greptile review. Shard 7 reports 13 baseline failures; cancelled shard logs add the same WorkBuddy/pwntools baseline failures. Other cancelled coverage remains unverified. Readiness declarations stay unchecked. Main subsequently fixed these failures. A local integration of final feature `bfd33f571` with main `2b84efe0d` built successfully and passed **248 tests across eight files**, including both Ghidra boundary suites and all six baseline-control files. The authorized bypass applies to the old-baseline CI result, with current-main integration checked; no human-review attestation is made. Real PE/Mach-O/macOS reuse and very large project trees remain unverified. Windows existing-project mode remains unsupported. ## Author readiness Human owner: @gensokyo-dev - [ ] 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. The user explicitly authorized opening ready for review and bypassing this gate without an AI attestation of human review. Baseline CI failures, if any, will be attributed before applying the authorized bypass. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-11-03 13:40:00 +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#7736
No description provided.