[PR #2799] [MERGED] fix(reverse): reconcile cleanup ownership and mutation diagnostics #5403

Closed
opened 2026-10-31 01:06:22 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2799
Author: @morluto
Created: 10/13/2026
Status: ✅ Merged
Merged: 10/13/2026
Merged by: @morluto

Base: main ← Head: codex/review-fixes-pr-2005


📝 Commits (10+)

  • eada258 feat(process): add owned debugger shutdown lifecycle
  • c6bea2e feat(reverse): add local inspection commands
  • cae5e3b merge: include owned debugger lifecycle prerequisite
  • 896e179 feat(gdb): add persistent debugger integration
  • faff3f2 feat(cutter): add Cutter bridge integration
  • 38c1c9b feat(rizin): add persistent debugger sessions
  • d549027 Merge remote-tracking branch 'origin/codex/pr1279-local-inspection' into feat/reverse-tools-coverage-gate
  • 8491f02 Merge remote-tracking branch 'origin/feat/owned-debugger-process-lifecycle' into feat/reverse-tools-coverage-gate
  • e36ca9d Merge remote-tracking branch 'origin/feat/cutter-pr1279' into feat/reverse-tools-coverage-gate
  • 8d637d7 Merge remote-tracking branch 'origin/feat/gdb-debugger-integration' into feat/reverse-tools-coverage-gate

📊 Changes

169 files changed (+32814 additions, -350 deletions)

View changed files

📝 .agents/skills/reverse-engineer-anything/SKILL.md (+43 -0)
📝 .github/workflows/ci.yml (+20 -0)
➕ .github/workflows/real-cutter.yml (+74 -0)
📝 .github/workflows/real-web-runtime.yml (+1 -1)
📝 .gitignore (+2 -0)
📝 README.md (+5 -0)
➕ bridge/cutter/rea_bridge.py (+816 -0)
📝 docs/architecture.mermaid (+13 -1)
📝 docs/readme/README_ar.md (+1 -1)
📝 docs/readme/README_de.md (+1 -1)
📝 docs/readme/README_es.md (+1 -1)
📝 docs/readme/README_fa.md (+1 -1)
📝 docs/readme/README_fr.md (+1 -1)
📝 docs/readme/README_id.md (+1 -1)
📝 docs/readme/README_it.md (+1 -1)
📝 docs/readme/README_ja.md (+1 -1)
📝 docs/readme/README_ko.md (+1 -1)
📝 docs/readme/README_pl.md (+1 -1)
📝 docs/readme/README_pt-BR.md (+1 -1)
📝 docs/readme/README_ru.md (+1 -1)

...and 80 more files

📄 Description

Fixes external-mutation cleanup failures that could permanently block analysis reopening or release analysis while a debugger writer remained. GDB/Rizin close recovery now belongs to the retained session owner; parent exit requires confirmed cleanup, with partial Evidence preserved. Rizin startup uses shared mutation admission and checks lifecycle state before publishing readiness. GDB also rechecks cancellation after its readiness yield. Both debugger status contracts expose observed decoding loss; Rizin command Evidence retains original and resolved launch paths as provenance, with current-target identity still unknown. The Ghidra admission guard reads the selected provider binding. Unrestricted commands now retire the active analysis instead of reopening it automatically: their protocol reply cannot prove background writers ended. Call open_binary explicitly after effects settle. Cleanup after failed detach can recover from captured PID/start-time identities and complete inferior inventories, with unknown, live, unreadable, or unsupported identities still retaining the owner. Rizin startup errors retain completed protocol frames and trailing partial diagnostics. Failed GDB startup Evidence propagates decoding loss in both raw and normalized results. Rizin command loss metadata follows only its collected frames, while session status stays cumulative. The queued-snapshot MCP workflow rejects saves after retirement, exports retained Evidence, and explicitly reopens before saving; it is now included in the reverse-tools lane and CI scope.

Cutter authenticates both peers before sending commands and authenticates responses. Timed-out commands retain bounded receipts by request ID until acknowledgement. Fresh clients recover terminal receipts before dispatch, while authenticated completion tokens preserve the original caller's cleanup proof after another caller acknowledges its receipt. The v2 handshake rejects older peers before command delivery. Discovery is bounded to 256 descriptor candidates and eight concurrent reads/probes; encoded command expansion is checked before transport dispatch. Response bytes are counted incrementally and collected into bounded pages, with one concatenation per completed frame. Concurrent cleanup callers share one receipt-recovery attempt. Poisoned-session rejections report not_started through the shared contract and MCP without creating a nonexistent cleanup owner. TypeScript-to-Python producer tests exercise the actual bridge protocol; they do not establish real Cutter/Qt behavior.

Objdump architecture queries are pathless and return subjectless Evidence; the CLI exposes list-objdump-architectures. The focused lane includes the owning BinarySession, snapshot, CLI, and Python producer suites. Coverage and mutation reports remain, but this PR no longer adds a perfect-score requirement. Existing repository-wide coverage thresholds remain unchanged. Stale mutation selectors, transient sandbox lock copying, translated documentation links, shared CI fixtures, and dependency notices are repaired. GDB sessions reject non-Linux hosts before launch because safe live-inferior descriptor verification is implemented only on Linux. CLI cleanup recovery preserves the producer's original completed Evidence; cancellation, timeout and unknown completion stay errors. Windows executable lookup resolves configured relative paths and quoted/relative PATH entries with Windows path semantics while preserving caller selections.

Continues #2005, originally authored by @dandgabr (Daniel Gonçalves Araujo), preserving the original commits and author attribution without squashing.

Validation: repository static checks (typecheck, lint, formatting, unused code, metadata, module boundaries, architecture guards), docs/license checks, focused reverse-tools tests with coverage, supplemental boundary tests, Python producer tests, and both Stryker dry runs. Full mutation scores and real GDB, Rizin, Cutter, and Windows native qualification remain unverified.

The final merged reverse-tools run passed 540 tests across 36 suites, with 23 platform skips, including CLI/MCP and Python producer boundaries. Six Windows path-semantics tests also passed using an injected filesystem. Repository static/docs checks and both mutation-runner dry runs passed; full mutation scores were not run. The two new real /proc Rizin identity cases were skipped on this macOS host and await Linux CI verification.

A parser-only benchmark used the actual AST-selected production frame methods to complete a 16 MiB frame in 256 chunks. Cold wall/CPU time was 154.5/352.1 ms before and 3.5/3.7 ms after; warm medians were 163.2/372.4 and 3.8/10.4 ms. Peak benchmark-process RSS, including transpilation and four runs, was 1,203,472 versus 253,952 KiB. Provider/transport, full process-family memory and model-token costs were not measured; no end-to-end speedup is claimed.

The aggregate contribution still includes pending integration scope tracked by #1959, #1960, and #1961. These fixes do not replace the required scope decisions or approve integration/deployment.

A separate frame-collector benchmark compared the former Cutter accumulation algorithm with the actual AST-selected replacement collector for a complete 16 MiB wire frame in 256 chunks. Cold wall/CPU was 475.2/503.5 ms before versus 2.2/2.4 ms after; warm medians were 446.7/463.9 versus 2.8/7.8 ms. Peak benchmark-process RSS, including transpilation and four runs, was 411,536 versus 187,824 KiB. Authentication, JSON parsing, transport, provider process-family costs and model tokens were not measured; this is not an end-to-end speedup claim.


🔄 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/2799 **Author:** [@morluto](https://github.com/morluto) **Created:** 10/13/2026 **Status:** ✅ Merged **Merged:** 10/13/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `codex/review-fixes-pr-2005` --- ### 📝 Commits (10+) - [`eada258`](https://github.com/morluto/rea/commit/eada258ea3145832a0ac0979739125b7e284ccab) feat(process): add owned debugger shutdown lifecycle - [`c6bea2e`](https://github.com/morluto/rea/commit/c6bea2e2b0c8000dff3ff2cc0668869273de00cf) feat(reverse): add local inspection commands - [`cae5e3b`](https://github.com/morluto/rea/commit/cae5e3b7746942d637af75258e0b6d8377faf20f) merge: include owned debugger lifecycle prerequisite - [`896e179`](https://github.com/morluto/rea/commit/896e1799b369c539d0253002a67f947810c11f15) feat(gdb): add persistent debugger integration - [`faff3f2`](https://github.com/morluto/rea/commit/faff3f22af5f044db04d9b2070a2608df38cf4f0) feat(cutter): add Cutter bridge integration - [`38c1c9b`](https://github.com/morluto/rea/commit/38c1c9b4d9afdd0848a7a5ee951eee0a5a787c93) feat(rizin): add persistent debugger sessions - [`d549027`](https://github.com/morluto/rea/commit/d549027129bbeac17746b25dd00ac0948f63b004) Merge remote-tracking branch 'origin/codex/pr1279-local-inspection' into feat/reverse-tools-coverage-gate - [`8491f02`](https://github.com/morluto/rea/commit/8491f0233faef1d3466effaea82866d99e21c4f5) Merge remote-tracking branch 'origin/feat/owned-debugger-process-lifecycle' into feat/reverse-tools-coverage-gate - [`e36ca9d`](https://github.com/morluto/rea/commit/e36ca9dd018d36bd3b5c39cb042eedeb5375bcd1) Merge remote-tracking branch 'origin/feat/cutter-pr1279' into feat/reverse-tools-coverage-gate - [`8d637d7`](https://github.com/morluto/rea/commit/8d637d7c211fe099b30cbfc0998886c428782493) Merge remote-tracking branch 'origin/feat/gdb-debugger-integration' into feat/reverse-tools-coverage-gate ### 📊 Changes **169 files changed** (+32814 additions, -350 deletions) <details> <summary>View changed files</summary> 📝 `.agents/skills/reverse-engineer-anything/SKILL.md` (+43 -0) 📝 `.github/workflows/ci.yml` (+20 -0) ➕ `.github/workflows/real-cutter.yml` (+74 -0) 📝 `.github/workflows/real-web-runtime.yml` (+1 -1) 📝 `.gitignore` (+2 -0) 📝 `README.md` (+5 -0) ➕ `bridge/cutter/rea_bridge.py` (+816 -0) 📝 `docs/architecture.mermaid` (+13 -1) 📝 `docs/readme/README_ar.md` (+1 -1) 📝 `docs/readme/README_de.md` (+1 -1) 📝 `docs/readme/README_es.md` (+1 -1) 📝 `docs/readme/README_fa.md` (+1 -1) 📝 `docs/readme/README_fr.md` (+1 -1) 📝 `docs/readme/README_id.md` (+1 -1) 📝 `docs/readme/README_it.md` (+1 -1) 📝 `docs/readme/README_ja.md` (+1 -1) 📝 `docs/readme/README_ko.md` (+1 -1) 📝 `docs/readme/README_pl.md` (+1 -1) 📝 `docs/readme/README_pt-BR.md` (+1 -1) 📝 `docs/readme/README_ru.md` (+1 -1) _...and 80 more files_ </details> ### 📄 Description Fixes external-mutation cleanup failures that could permanently block analysis reopening or release analysis while a debugger writer remained. GDB/Rizin close recovery now belongs to the retained session owner; parent exit requires confirmed cleanup, with partial Evidence preserved. Rizin startup uses shared mutation admission and checks lifecycle state before publishing readiness. GDB also rechecks cancellation after its readiness yield. Both debugger status contracts expose observed decoding loss; Rizin command Evidence retains original and resolved launch paths as provenance, with current-target identity still unknown. The Ghidra admission guard reads the selected provider binding. Unrestricted commands now retire the active analysis instead of reopening it automatically: their protocol reply cannot prove background writers ended. Call `open_binary` explicitly after effects settle. Cleanup after failed detach can recover from captured PID/start-time identities and complete inferior inventories, with unknown, live, unreadable, or unsupported identities still retaining the owner. Rizin startup errors retain completed protocol frames and trailing partial diagnostics. Failed GDB startup Evidence propagates decoding loss in both raw and normalized results. Rizin command loss metadata follows only its collected frames, while session status stays cumulative. The queued-snapshot MCP workflow rejects saves after retirement, exports retained Evidence, and explicitly reopens before saving; it is now included in the reverse-tools lane and CI scope. Cutter authenticates both peers before sending commands and authenticates responses. Timed-out commands retain bounded receipts by request ID until acknowledgement. Fresh clients recover terminal receipts before dispatch, while authenticated completion tokens preserve the original caller's cleanup proof after another caller acknowledges its receipt. The v2 handshake rejects older peers before command delivery. Discovery is bounded to 256 descriptor candidates and eight concurrent reads/probes; encoded command expansion is checked before transport dispatch. Response bytes are counted incrementally and collected into bounded pages, with one concatenation per completed frame. Concurrent cleanup callers share one receipt-recovery attempt. Poisoned-session rejections report `not_started` through the shared contract and MCP without creating a nonexistent cleanup owner. TypeScript-to-Python producer tests exercise the actual bridge protocol; they do not establish real Cutter/Qt behavior. Objdump architecture queries are pathless and return subjectless Evidence; the CLI exposes `list-objdump-architectures`. The focused lane includes the owning BinarySession, snapshot, CLI, and Python producer suites. Coverage and mutation reports remain, but this PR no longer adds a perfect-score requirement. Existing repository-wide coverage thresholds remain unchanged. Stale mutation selectors, transient sandbox lock copying, translated documentation links, shared CI fixtures, and dependency notices are repaired. GDB sessions reject non-Linux hosts before launch because safe live-inferior descriptor verification is implemented only on Linux. CLI cleanup recovery preserves the producer's original completed Evidence; cancellation, timeout and unknown completion stay errors. Windows executable lookup resolves configured relative paths and quoted/relative PATH entries with Windows path semantics while preserving caller selections. Continues #2005, originally authored by @dandgabr (Daniel Gonçalves Araujo), preserving the original commits and author attribution without squashing. Validation: repository static checks (typecheck, lint, formatting, unused code, metadata, module boundaries, architecture guards), docs/license checks, focused reverse-tools tests with coverage, supplemental boundary tests, Python producer tests, and both Stryker dry runs. Full mutation scores and real GDB, Rizin, Cutter, and Windows native qualification remain unverified. The final merged reverse-tools run passed 540 tests across 36 suites, with 23 platform skips, including CLI/MCP and Python producer boundaries. Six Windows path-semantics tests also passed using an injected filesystem. Repository static/docs checks and both mutation-runner dry runs passed; full mutation scores were not run. The two new real /proc Rizin identity cases were skipped on this macOS host and await Linux CI verification. A parser-only benchmark used the actual AST-selected production frame methods to complete a 16 MiB frame in 256 chunks. Cold wall/CPU time was 154.5/352.1 ms before and 3.5/3.7 ms after; warm medians were 163.2/372.4 and 3.8/10.4 ms. Peak benchmark-process RSS, including transpilation and four runs, was 1,203,472 versus 253,952 KiB. Provider/transport, full process-family memory and model-token costs were not measured; no end-to-end speedup is claimed. The aggregate contribution still includes pending integration scope tracked by #1959, #1960, and #1961. These fixes do not replace the required scope decisions or approve integration/deployment. A separate frame-collector benchmark compared the former Cutter accumulation algorithm with the actual AST-selected replacement collector for a complete 16 MiB wire frame in 256 chunks. Cold wall/CPU was 475.2/503.5 ms before versus 2.2/2.4 ms after; warm medians were 446.7/463.9 versus 2.8/7.8 ms. Peak benchmark-process RSS, including transpilation and four runs, was 411,536 versus 187,824 KiB. Authentication, JSON parsing, transport, provider process-family costs and model tokens were not measured; this is not an end-to-end speedup claim. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:06:22 +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#5403
No description provided.