RHEXA
Project description · As of 19 October 2026

RHEXA RHEXA

Retargetable Headless Executable Analyzer

Reverse engineering for AI agents: an agent asks a concrete question about a program, RHEXA answers it across several analysis techniques and backs every finding with evidence. Deep static analysis is handled by the Rhexa Engine, an independently developed, purely headless derivative of Ghidra that is built into RHEXA.

Phase 0 complete Engine without Swing UI Rename REA → RHEXA complete

Overview

RHEXA is one product built from two technology stacks in a single repository. The agent layer talks to AI agents, the engine analyses machine code. Both are connected through a versioned contract and can be built, tested and shipped independently.

AI agent or human Claude Code, other MCP clients, command line
↓ MCP (Model Context Protocol) or CLI
RHEXA agent layer TypeScript, Node.js · more than 200 tools · evidence ledger, investigations, sessions · runtime sources such as Frida, browser observation and process capture · own parsers for JavaScript, .NET, WebAssembly, EVM, firmware, SQLite, network captures
↓ JSON contract over a local socket
Rhexa Engine Java and C++ · derived from Ghidra 12.1.4 · decompiler, Sleigh processor models, loaders for ELF, PE, Mach-O and many more formats, analyzers · headless only

One analysis tool

Static binary analysis has exactly one deep analyser: the Rhexa Engine. Hopper, IDA, JEB, Cutter, Rizin and objdump are replaced step by step as soon as the engine demonstrably covers the capability in use.

Evidence, not claims

Every answer carries the artefact identity, engine and contract version, parameters and location. Observation, inference, hypothesis and open question stay separate; missing coverage is stated openly.

Headless and independent

The engine needs no user interface. It is built, tested and shipped in the repository and does not follow Ghidra by merging; security fixes are adopted individually and traceably.

Starting point

RHEXA does not start from scratch. It brings together two mature open source projects whose strengths complement each other, but each was built for a different purpose.

REA – the agent layer

morluto/rea · MIT licence · npm package rea-agents 6.5.0

"Reverse Engineer Anything" is an MCP server with a command line through which AI agents examine native programs, web and Electron applications, .NET, Android, firmware, WebAssembly and more. Imported at commit efbc486.

  • 207 tools in the MCP catalogue, about 300,000 lines of production and 186,000 lines of test code
  • Several deep analysers side by side: Ghidra, Hopper and IDA, plus objdump, Rizin, Cutter and JEB
  • Ghidra had to be installed separately; the bridge was compiled as a script with the Java compiler on every start
  • No reproducible proof that a change actually improves analyses
  • The Linux runs against real Ghidra were not part of CI and had silently outdated expectations

Ghidra – the analysis engine

National Security Agency · Apache License 2.0 · version 12.1.4 (8b6bbb8)

The software reverse engineering framework with one of the best freely available decompilers, processor models for dozens of architectures and extensive analysis modules. Imported as an unmodified source snapshot without Git history.

  • About 2.28 million lines of Java in 12,837 files, plus native C++ code for the decompiler and Sleigh
  • Built as a desktop tool: about 830,000 lines of Swing user interface with 240 plugins
  • Multi-user server, debugger, version control, graph and diff views that automated analysis does not need
  • Java 21 as the minimum version, build designed for Gradle 8.5
  • 153 known vulnerability findings in bundled third-party libraries, mostly in the server part

Why a separate derivative?

An AI agent does not need windows, it needs fast answers backed by evidence. Running headless, RHEXA uses only about 19 % of the engine classes. The rest costs start-up time, enlarges the attack surface and makes further development harder. With its own lean engine in the same repository, analysis and agent layer can be improved together, tested together and shipped as one product.

RHEXA is an independent project. It is not affiliated with the authors of REA or the National Security Agency and is neither supported nor endorsed by them. A name of its own is necessary because the Apache licence grants no rights to the name "Ghidra" and "REA" belongs to the original.

How it works

How RHEXA answers a question such as "Which function checks the licence key, and against which constant?"

Concept illustration: the RHEXA agent combines static analysis, runtime observation, decompilation and cross-references into evidence-backed insights.

Ask

The agent formulates a concrete analysis question and opens the target with open_binary. RHEXA determines format, architecture and the matching analysis path.

Analyse

The Rhexa Engine imports the program headless, recognises functions, references and data types and decompiles on demand. The target file itself is never modified.

Look selectively

Instead of loading whole inventories, the agent calls only the tools it needs: strings, procedures, pseudocode, memory contents. Tool schemas are loaded on demand.

Answer with evidence

Every result is recorded with its provenance in the evidence ledger. The answer names address, constant and location; what is unknown is marked as unknown.

Add runtime data

Where static analysis is not enough, RHEXA observes processes, browsers or Frida sessions and links the runtime evidence to the static model.

Measure

A reproducible benchmark checks every change for quality, tokens, cost, CPU and memory. An improvement that loses evidence does not count.

What is already better

Every change is a separate, traceable commit with a rationale and verification.

AreaBeforeNow
Test coverage of the agent layer90.8 % lines / 82.0 % branches97.1 % / 91.3 %
Dependenciespartly outdatedall npm packages and CI actions on the latest stable release
Vulnerability checksno baselinenpm: 690 packages, 0 findings · engine: regular OWASP scan
Vulnerability findings in the engine distribution153 (17 critical)12 (0 critical)
Java and buildJava 21, Gradle 8.5+, more than 2,000 Gradle warningsJava 25 (LTS), Gradle 9.8.1 with a verified checksum, legacy cleaned up
Engine scopecomplete desktop application with server and debuggerserver, 28 modules and about 1,450 GUI source files removed; GUI removal in progress
Proof of improvementsnonetask benchmark with baseline, comparison with tolerance
Agent missteps before opening a target7 per benchmark run0, median tokens −11 %
Verification runs against the enginenot in CI, partly with outdated expectations13 of 19 green against the self-build, dedicated engine CI

Changes compared with REA

  • Much broader test coverageCoverage raised by 6 and 9 percentage points, thresholds raised accordingly.
  • All dependencies currentnpm packages and GitHub Actions on the latest stable release, minimum Node.js version raised.
  • Vulnerability scanningnpm audit and OSV-Scanner with a time-limited allowance list.
  • Session lifecycle bug fixedReopening the same target started the engine early and could miss a changed source file. The bug exists in the original.
  • Reproducible task benchmarkFive analysis tasks with an answer key, an isolated agent, measurement of quality, tokens, cost, CPU and memory.
  • Better agent guidanceA hint in the server instructions removed all calls made before opening a target.
  • Verification scripts correctedThree outdated expectations in the Ghidra runs (MIPS attributes, rejection of truncated ELF files, CET jump instructions) that are also present in the original.

Changes compared with Ghidra 12.1.4

  • Ghidra Server removedMulti-user server including its service wrapper and outdated networking library removed.
  • Modern toolchainJava 25 as minimum version and bytecode target, Gradle 9.8.1, Gradle 10 legacy cleaned up in 32 build scripts.
  • GUI removal, wave 128 modules without relevance for headless analysis removed, including the debugger complex and diff and graph views; verified with verification runs, unit and integration tests.
  • Dedicated engine CIBuild, unit tests, coverage and vulnerability scanning run separately from the agent layer.
  • Safety net for the rebuild128 headless integration test classes with 1,832 tests, plus more than 8,000 unit tests, the agent layer's verification runs and the benchmark.

Measurements

MeasurementResult
Task benchmark (baseline)30 of 30 runs successful, no false claim
Task benchmark after the GUI removal30 of 30 runs successful, no false claim, cost as in the baseline (10.68 vs. 10.59 USD)
Task benchmark with compact result delivery (package B)30 of 30 runs successful, no false claim; tool responses −30%, 4.12 instead of 4.87 million tokens (−15.5%), 10.46 instead of 10.68 USD
Agent layer verification runs against the engine13 of 19 passed, none fails because of the engine; 6 need macOS, Windows or newer compilers
Engine unit tests (without UI)7,001 cases, 0 failures
Headless integration tests429 tests, 0 failures
Start-up analyzeHeadless (small ELF, no analysis, median)Ghidra 12.1.4: 4.81 s · RHEXA engine: 4.12 s (−14 %)
Engine classes loaded headless3,878 of 19,996

Measured on an AMD Ryzen 9 3900X running Linux against the engine self-build.

Roadmap

Two tracks run in parallel: the agent layer (TypeScript) and the engine (Java/C++). Gates separate the phases. A gate only passes if the benchmark loses no evidence and needs no more tokens. Time frames are planning ranges for a deliberately narrow first scope, not commitments.

Phases at a glance

Phase 0Oct 2026done
Working engine, hygiene, measurement
  • Self-build on Java 25 and Gradle 9.8.1, tests and coverage baseline
  • Vulnerability baselines for both stacks, Ghidra Server removed
  • Task benchmark with baseline, engine CI, session lifecycle bug fixed
Gate 0 passed; 6 verification runs for macOS, Windows and newer compilers follow.
GUI removalOct 2026done
Remove the Ghidra user interface completely
  • ✓ Upfront: Ghidra Server removed (vulnerability findings 153 → 12)
  • ✓ Wave 1: 28 modules without headless relevance removed (debugger, emulation, ByteViewer, diff and graph views)
  • ✓ Wave 2: about 1,450 unreachable source files and more than 200 GUI tests removed
  • ✓ Wave 3: 69 UI-free classes moved from the window modules into the UI-free base module
  • ✓ Wave 4: gateways decoupled: options and help references, colours and icons, task execution, prompts, script dialogs
  • ✓ Wave 5: edges from the headless core into the UI cut, window, help and theme frameworks and the tool layer deleted; the engine is headless only and starts 14 % faster
After every wave: verification runs, unit tests and headless integration tests green; final benchmark passed. Details per wave
Phase 1Dec 2026 – Jan 2027completed
New name and a fixed contract
  • Rename to RHEXA including engine branding (done)
  • Bridge to the engine as a real, tested engine module (done)
  • One shared, versioned contract checked by both stacks (done)
  • Leaner, task-oriented result delivery (done: tool responses −30%)
Gate 1 passed (20 October 2026): contract conformant on both sides, no Java compiler at runtime, the product is called RHEXA; benchmark 36 of 36 runs correct, tool responses −38%, cost −14%.
Phase 2Feb – Mar 2027in progress
Distribution
  • rhexa engine install with verified release archives per platform
  • Shorter start-up (class archive, leaner analysis profiles)
  • Replace the first external tools: objdump, Rizin, Cutter
  • ✓ Switch to the latest MCP revision 2026-07-28 done (older revision only as a transition; Claude Code already speaks the new one)
Gate 2: fresh install without a separate Ghidra, start-up time before/after documented, engine without Swing UI.
Phase 3Apr – May 2027planned
Consolidation and investigation record
  • Remove Hopper, IDA and JEB
  • Persistent investigation projects and persistent engine projects
Gate 3: a single deep analyser, investigations resume after a restart.
Phase 4Jun – Jul 2027planned
Evidence chains and types
  • Trace a feature end to end: user interface → native code → effect
  • Reconstructions with executable proof
  • Own analyzers in the engine, deeper type recovery
Gate 4: one evidence-backed chain, a type fixture with inheritance passes.
Phase 5Aug – Sep 2027planned
Version comparison, user interface, Windows
  • Semantic comparison of two builds
  • New, lean web interface (Thymeleaf), first as a status and monitoring view
  • Unified transport on Windows, integration of BSim and Function ID
Gate 5: two builds with known changes are matched correctly.
Phase 6from Oct 2027planned
Deepening
  • Event-based process observation
  • One domain module after a three- to five-day feasibility study
  • Evaluate the engine debugger as a runtime source, further toolchain upgrades

GUI removal in detail

Ghidra's Swing UI was removed in five waves. Every wave was secured by the agent layer's verification runs, the engine unit tests and a net of headless integration tests, and committed separately.

WaveContentScopeStatus
UpfrontGhidra Server and its service wrapper removedmodule, scripts, 21 tests; vulnerability findings 153 → 12done
Wave 1Modules without headless relevance: debugger complex, system emulation, ByteViewer, diff and graph views, screenshot generators28 modules; distribution 723 MBdone
Wave 2Source files not reachable from any headless path, determined from the class graph (jdeps), plus the tests of removed GUI featuresabout 1,450 production and more than 200 GUI test files; distribution 644 MBdone
Wave 3Move window-module classes the core uses that contain no UI themselves (settings, field locations, sort state, filter strategies, constants, task base types) into the UI-free base module Generic; Java packages stay the same. Swing building blocks are left for wave 469 classes and their tests; checked with 13 lanes, 7,643 unit and 1,512 headless integration testsdone
Wave 4Decouple the gateways through which the window framework comes along, in steps: 4a options and help references (done: options system and resource lookup UI-free, theme binding through an interface), 4b colours and icons (done: theme values through an interface, icon part of the data type helpers split off), 4c task execution (done: tasks, prompts and HTML helpers UI-free), 4d comment annotations, script headers and file filters (done), 4e script API dialogs (done; the tool layer follows with wave 5); pure UI parts go away with their windows in wave 5about 166 window-module classes that headless operation loads at run time todaydone
Wave 5Clean-up in steps: 5a decoupled infrastructure that hung on the UI by a single edge (server client, links, Ghidra URL protocol, prompts, theme values), 5b script API without the tool (GUI methods such as goTo, show, askValues removed, GUI-only scripts deleted), 5c cut edges (PDB symbol servers, version tracking API, service providers by name, annotation click handlers), 5d deleted the window, help and theme frameworks, the tool layer and the rest of the UI world (about 2,700 classes, 550 test files); what headless needs, such as SARIF import, Jython, the ISF server and 17 bundled scripts, was decoupled instead of deleted. Multi-user merge on check-in is gone (the Ghidra server had already been removed)start-up 4.81 s → 4.12 s (−14 %), class search 958 → 386 ms, module JARs 195 → 118; 13 verification runs, 7,001 unit and 429 headless integration tests greendone

Engine work packages

P0 = prerequisite, P1 = immediate benefit, P2 = deepening, P3 = later option.

G0 Engine working on its own on the LTS toolchain P0 done
Goal
A demonstrably building, tested engine state without the agent layer, as the starting point for integration.
Scope
Build on Java 25 and current Gradle, unit and integration tests with a per-module coverage baseline, raised bytecode target, dedicated engine CI, dependency and vulnerability scan.
Result
All steps done; the Ghidra Server was removed as well (153 → 12 findings).
T0 Bug when reopening a target P0 done
Finding
Reopening the same target started the engine immediately and could then miss a changed source file.
Result
Fixed in the session lifecycle with a reproduction test; the verification run passes against the self-build.
T1 Rename to RHEXA P0 done
Scope
Display name, rhexa command, MCP key, configuration file, package name, about 210 environment variables (old names remain valid for one release), documentation; engine branding (application name, archive and settings names, start scripts). Java packages stay unchanged.
Acceptance
RHEXA runs under its own name and does not collide with a parallel installation of the original.
Status
Name, rhexa command, MCP key, npm package rhexa-agents, configuration and documentation are switched, as are the RHEXA_* environment variables; set REA_* values keep working with a notice for one major version. The verification lanes are called verify:engine*. The engine is called Rhexa Engine and has its own archive (rhexaengine_…) and settings directory, so a parallel Ghidra keeps its settings. Internal prefixes (temporary directories, bridge class names) stay on purpose because they are not visible outside.
G1 Repository integration and guidelines P0 done
Scope
Licence documents describe the engine as a derivative work, own engine guidelines for provenance, individual upstream adoptions and security review, build integration into the repository tooling.
Acceptance
TypeScript checks stay unaffected by the Java part; licence documents name the engine.
Result
Licence documents describe Rhexa Engine as a derivative work under Apache 2.0. All 392 modified upstream files carry the change notice Apache 2.0 requires, and the engine CI checks this against the upstream tree. Engine guidelines cover provenance, adoptions and security review; npm run engine:build builds the engine from the repository tooling.
G2 Bridge as an engine module and shared contract source P0 done
Scope
The bridge becomes a compiled engine module tested with JUnit, split into dispatcher, serialiser and operation groups. The contract is maintained as JSON Schema, generating types for TypeScript and Java; a handshake checks the contract version.
Acceptance
All 28 operations run through the module, a deliberately mismatched schema makes both conformance tests fail, no Java compiler at runtime.
Status
The bridge is an engine module and runs pre-compiled with Rhexa Engine; a separately installed Ghidra still compiles it. Together with a converted Windows analyzer, no verification run loads the Java compiler any more. The bridge's 4,900 lines are split into protocol, dispatcher and eight operation groups, and 20 integration tests check the operations directly against an imported program. A versioned contract covering all 31 operations is generated from the agent layer's schemas; both sides check against it and against recorded responses of the real bridge, and the handshake refuses a foreign protocol version.
G3 Engine distribution and installation P0 in progress
Scope
Release archives per platform with a SHA-256 manifest, rhexa engine install|status|remove, diagnostic checks, a separate Ghidra only as a developer option.
Acceptance
On a fresh machine with Java 25, RHEXA delivers pseudocode after installation without further steps.
Status
Met for Linux x86-64: rhexa engine install downloads the engine from rhexa.janda.io, checks size and SHA-256 and installs it; rhexa decompile then returns pseudocode, and every analysis names the engine's origin. Archives for macOS and Windows follow.
G4 Start-up time and removal of the Swing UI P1 in progress
Starting point
Headless runs load 3,878 of 19,996 classes; the UI is entangled with the core in only about 165 places (settings, task monitors, options, colours).
Scope
In waves: remove unused modules, delete unreachable classes, move entangled core classes into a UI-free module, remove the window, help and theme frameworks, drop GUI-only libraries; reduce start-up time with a class archive and leaner analysis profiles.
Acceptance
After every wave, engine tests, verification runs and benchmark pass; class list and start-up time documented before and after.
G5 Provider consolidation P1 in progress
Order
objdump → Rizin single commands and Cutter (replaced by curated engine scripts) → Hopper → IDA → JEB. Debug sessions remain until G9.
Acceptance per step
Parity matrix documented, tools rebound to the engine or removed with a migration note, a separate release marked as a breaking change.
Status
objdump: the parity matrix is in place. The new tool inspect_object_file reads the header, sections, symbols and relocations of ELF, PE and Mach-O files straight from the original bytes through the engine's parser, paging large tables. DWARF compilation units and line tables are included; rhexa engine languages lists the engine's processor languages with their GNU names. disassemble_range lists whole sections or address ranges without decoding data as code. Every objdump operation has its counterpart and inspect_with_objdump is removed (a breaking change with a migration table). Mach-O chained fixups remain open. Rizin and Cutter: the parity matrix is in place. Free command lines are replaced by run_engine_script, a fixed, versioned catalog of engine scripts with validated parameters: raw_strings (every text sequence in the file bytes), instruction_search (regular expressions over instruction text), function_graph (basic blocks and edges) and cpp_classes (C++ classes with vtable, type info and methods). Every other command family already had an engine tool. execute_rizin_command and the Cutter bridge are removed (a breaking change with a migration table); Rizin debugger sessions stay until G9. Hopper comes next.
G6 Persistent engine projects P1 Phase 3
Scope
Own project format with a manifest (artefact hash, engine version, analysis profile, contract version), explicit open and save, invalidation when the artefact changes, a long-lived engine service holding several programs.
Acceptance
Investigations resume after a restart; a changed binary creates a new artefact version.
G7 Independent engine development P1 Phase 4
Scope
Developer documentation, own versioning scheme, own analyzers and loaders instead of script workarounds: repair of wrong no-return assumptions, MIPS soft-float, PSP, .NET NativeAOT.
Acceptance
An engine feature can be developed, tested and shipped without changing the agent layer.
G8 Windows unification P2 Phase 5
Scope
One transport path for all platforms; Windows loses its "read-only" special status.
G9 Engine debugger as a runtime source P3 Phase 6
Scope
Evaluate whether static and dynamic evidence can be merged in the same program model; decide only after a successful feasibility study.

Analysis work packages

A Reproducible task benchmarks P0 baseline available
Problem
A new feature or a shorter answer is no proof of better analysis.
Scope
Corpus of self-built programs with known solutions: find a function, explain a file write, detect a change between two builds, verify a static call dynamically, reimplement a function.
Next steps
Harder variants (stripped and optimised builds, indirect calls) so that quality gains become measurable too.
B Task-oriented, economical result delivery P0 done
Scope
Summaries first for inventory questions, reference evidence already read instead of sending it again, avoid duplicate serialisation; optionally hybrid search over symbols, full text and semantic search.
Acceptance
Fewer total tokens in the benchmark at the same answer quality.
Status
First step done: the opt-in profile RHEXA_MCP_RESULT_TEXT_PROFILE=compact delivers results without the duplicate copy and without the repeated analysis profile; the session keeps the complete evidence. rhexa setup sets it for Claude Code automatically. In the benchmark 30% smaller tool responses and 15.5% fewer tokens at the same quality (30 of 30 runs). A new task on a large statically linked program shows that agents reach the answer there by search rather than complete lists (6 of 6 correct), so separate inventory summaries are not needed.
C Persistent investigation projects P1 Phase 3
Scope
Named projects with automatic saving, a manifest, hypotheses and counter-evidence, resumption after a restart.
Acceptance
An investigation continues after a restart; contradictory evidence becomes visible.
D End-to-end tracing of a feature P1 Phase 4
Scope
A question such as "What happens on save?" becomes an evidence-backed chain from the user interface through native code to the effect, statically and at runtime.
Acceptance
A known fixture yields an evidence-backed chain, also under address space randomisation.
E Event-based process observation P1/P2 Phase 6
Scope
Platform adapters for process start, exit, re-execution and child processes.
Acceptance
Even very short-lived child processes are detected.
F Deeper native type and call analysis P1/P2 Phase 4
Scope
Structure layouts, argument types, function pointers and virtual calls, computed in the engine.
Acceptance
A self-built fixture with inheritance and function pointers is reconstructed correctly.
G Semantic version comparison P1/P2 Phase 5
Scope
"Which earlier findings and extension points must be rechecked after an update?" – matching renamed and moved functions across builds.
Acceptance
Two builds with known changes are matched correctly.
H From reconstruction to executable proof P1 Phase 4
Scope
Requirements on a reconstruction produce test harnesses and input corpora that compare original and reimplementation.
Acceptance
A deliberately wrong reconstruction is rejected.
I New analysis interface P2 Phase 5
Scope
Server-rendered web interface with Thymeleaf, first as a status and monitoring view for sessions, engine processes, providers and benchmark runs, then as a read-only view of the investigation record. No analysis of its own in the interface.
Acceptance
Every conclusion can be expanded down to its evidence; missing coverage is visible.

Optional domain modules

ModuleFirst scopePriority
GamesDetect engine and deployment form, inventory resources, classes and extension pointsP1 with a games focus
Java/SpringExamine one Spring Boot archive: REST routes, services, configuration referencesP1 with an enterprise focus
.NET/C#Link a decompiler export with unique member identitiesP2
ProtocolsStructure recurring messages in capturesP2
Security analysisProvenance-backed rules for risky API usage and data flowsP2/P3
Component provenanceTurn package metadata into a provenance report, SBOM exportP2
Symbolic analysisOne small pure function, one narrowly scoped questionP3

Principles

Decisions

  • Source base and toolchainGhidra 12.1.4, Java 25 (LTS), the current stable Gradle release.
  • One repository, two stacksEngine as a source copy in the repository, separate build, test and lint gates per stack.
  • NameRHEXA for product and engine; Java packages stay unchanged, attribution is retained.
  • One contractOne schema source, generated types and conformance tests for both sides.
  • No merging with upstreamSecurity fixes are watched and adopted individually with provenance.
  • HeadlessThe Swing UI goes away; a new interface is built only when needed.

Quality rules

  • Demonstrable benefitEvery package needs a concrete analysis case and measurable added value.
  • EvidenceArtefact identity, engine and contract version, parameters, location; facts, inferences, hypotheses and open questions kept apart.
  • Real runsNo support claim without a real run on the claimed platform.
  • Untrusted contentStrings and code from the target are data, never instructions to the agent.
  • No silent side effectsStatic analysis never executes the target; runtime actions and write effects are visible in the tool contract.
  • Engine changesA test in the affected module, an entry in the provenance record, no drop in coverage.

Risks and countermeasures

RiskCountermeasure
Missing upstream security fixesRegular review, individual adoption with provenance, own regression tests for importers
GUI removal makes later adoptions harderMove core classes, do not rewrite them; analyzers, loaders and processors stay unchanged
Loss of capability when removing providersParity matrix and gate before every removal, transition period, breaking-change note
Contract drifts apartOne schema source, generators, golden examples for both sides
Scope growsGates with benchmark; the analysis packages run independently of the engine work

Licence and attribution

Agent layer

Based on REA by morluto, published under the MIT licence. The original copyright notice is retained in all copies.

Rhexa Engine

Derived from Ghidra, published under the Apache License 2.0. Licence text, NOTICE file and all attributions are retained; every deviation is documented in engine/UPSTREAM.md. Ghidra logos are not used.