Compare commits

..
Author SHA1 Message Date
N0zoM1z0 10097f6ae6 fix(javascript): retain cancellation during ownership preparation 2026-10-11 07:39:47 +08:00
N0zoM1z0 32b56f188e test(javascript): verify cleanup retention and repeated source paths 2026-10-11 07:07:21 +08:00
N0zoM1z0 8a13d920bb fix(javascript): isolate source analysis and retain bounded partial evidence 2026-10-11 07:04:24 +08:00
N0zoM1z0 e5d8179c29 test(javascript): consume decoded module and static facts 2026-10-11 07:02:44 +08:00
N0zoM1z0 78f9da9a6a refactor(javascript): validate transferable file projections 2026-10-11 07:02:44 +08:00
morluto 1b527f4898 fix(ci): share runtime fixtures and allow modest duplication headroom 2026-10-11 06:53:20 +08:00
YsopwnableandGitHub b09dd333ab fix(tests): separate Copilot model IDs from wire models (#1647)
* fix(tests): separate Copilot model IDs from wire models

* fix(tests): inspect parsed reference import diagnostics
2026-10-11 06:52:45 +08:00
morluto 60fbb2f06e fix(install): share arguments between the plan and npm execution
Include the Linux user prefix in the planned command. Build the install
arguments once and shell-escape the printed arguments so paths with spaces
or metacharacters remain reusable. Cover dry-run admission, exact argument
round-trip and the unprefixed macOS command with native Bash 3.2.

Refs: #1417
2026-10-11 06:41:51 +08:00
morlutoandFazmin 8b4c96e6c6 fix(cli): preserve native option descriptions in help
Keep the optional address description visible to incur and describe the actual
bundle plist default and absolute-path support. Extend the existing command
help sweep instead of traversing the inventory a second time.

Refs: #1418
Co-authored-by: Fazmin <fazmin.nizam@gmail.com>
2026-10-11 06:41:46 +08:00
morluto 95a77b6e25 fix(web)!: retain capture read cleanup through export
BREAKING CHANGE: WebScriptExportError accepts error context and residual paths in an options object.
2026-10-11 06:30:56 +08:00
morluto 67966c69a5 fix(setup): retain client configuration cleanup owners 2026-10-11 06:30:56 +08:00
morluto 279c942fe1 refactor(reference): consolidate Git metadata cleanup 2026-10-11 06:30:56 +08:00
morlutoandGitHub 54e2890b30 fix(ci): check decoded reference paths and restore formatting (#1648)
* style(browser): format cached SVG ancestry check

* fix(tests): assert decoded reference-source error paths
2026-10-11 06:29:26 +08:00
0f605bca09 fix(browser): report SVG xlink:href links in dom_urls (#1602)
* fix(browser): report SVG xlink:href links in dom_urls

DOM snapshots have no namespace URI, so SVG context is an svg ancestor
outside foreignObject. When href is missing, report xlink:href as href
with the same base URL and origin policy.

Fixes #1586

* fix(browser): cache SVG ancestry during DOM capture

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-11 06:23:07 +08:00
Immanuel TikhonovandGitHub 423b11c8ef fix(javascript): preserve trailing slash in package directory requests (#1615) 2026-10-11 06:23:05 +08:00
FengandGitHub 52331ab637 fix(setup): preserve configured MCP server environment (#1607)
* fix(setup): preserve configured MCP server environment

* fix(setup): validate retained server environment before writes
2026-10-11 06:23:02 +08:00
akushonkamenandGitHub 3e931a7e35 fix(browser): fold loopback spellings into one attach admission key (#1604)
A CDP endpoint serves every loopback stack on one port, but the attach
admission key was built from the endpoint origin string, so scenarios
attaching through http://127.0.0.1:PORT and http://[::1]:PORT produced
two lease keys, passed admission in parallel and the browser rejected
the second client. Collapse literal loopback hostnames to one identity
in the lease key (port and target still partition it) without touching
endpoint validation.

Validation: npx vitest run src/browser/PlaywrightScenarioBrowser.test.ts (9 passed; the two new loopback tests failed before the fix), npx vitest run src/browser src/domain (1745 passed, 2 failed, both failing on pristine main), npm run test:fast (3896 passed, 12 failed, 7 skipped; the failure set is identical on pristine main at 3894 passed), plus typecheck, oxlint, oxfmt and resolved module-boundary verification.
2026-10-11 06:22:59 +08:00
AdolaniumandGitHub 6edd5cf045 fix(browser): keep declared scenario secrets out of redacted evidence (#1590)
A redaction marker such as [REDACTED:password] can contain the secret it replaced, and the byte replacer never scanned the marker it inserted. Cookie names, domains, paths, and storage keys were also stored raw. Choose a marker that does not contain a declared spelling, drop the result when a spelling remains, and redact storage identity fields.
2026-10-11 06:22:57 +08:00
1a6ccec636 fix(browser): skip Windows Electron signals without verified lineage (#1588)
capture_electron_scenario called taskkill on the recorded leader PID before lineage could be verified. On Windows the process table is empty, so that proof never arrives and the signal still ran. Refuse the cleanup without signaling. A verified lineage still terminates the leader and its descendants.

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-11 06:22:54 +08:00
Luis ArayaandGitHub afc9d819aa test(android): preserve reason in JADX cleanup-failure teardown poll (#1639) 2026-10-11 06:22:51 +08:00
Luis ArayaandGitHub 7b3011b41e fix(tests): bind HOME in native client and deepseek verifiers (#1638) 2026-10-11 06:22:48 +08:00
6849ecf70a docs(installation): clarify that npm 6.3.0 excludes automatic pi and hermes setup (#1637)
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-11 06:22:37 +08:00
morluto 926c2d6ba7 test(ghidra): preserve metadata in interior-label fixture
Place the imported control label inside a valid multi-byte NOP instead of suppressing Mach-O function-start metadata. Encode the supported ARM64 and x86-64 instructions explicitly and retain the load dependency so the control remains past the function entry. Assert that Ghidra imports a label and no procedure at the control address before checking name rejection and address containment.

Two real arm64 Ghidra 12.1.4 imports confirmed both fixture strategies produce labels; only default linking retains LC_FUNCTION_STARTS. The full native-value CLI/MCP verifier passed with 349 successful and 52 expected rejected boundary calls, including imported aliases, complete exports, and startup cancellation cleanup. Host ARM64 and Apple x86-64 fixture compilation passed; x86 provider execution remains unverified.
2026-10-11 06:10:10 +08:00
morluto c7345512ea perf(native): index admitted value-trace nodes
Replace a graph-wide node scan for each parameter use with membership in the set of admitted node IDs. Preserve node-budget omission, pagination, and existing ID-collision behavior.

Flameox profiles identify the eliminated scan. Six-run medians on a bounded synthetic four-procedure workload improved from 2538.17 ms to 220.32 ms (11.52x); full JSON responses have identical SHA-256 4071fc7ec17be01e6a23d53814a47b3b1bb0ebd80099d21ef8431da487801725. This measures production trace composition with a synthetic provider, not real Ghidra target speed.

External design research through DeepWiki was checked against Ghidra 12.1.4 DataGraph: https://github.com/NationalSecurityAgency/ghidra/blob/8b6bbb857accdfa20dc5b2f5dea471178c2e9fbc/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/graphanalysis/DataGraph.java
2026-10-11 06:10:10 +08:00
morluto 53e7fadbd0 fix(reference)!: retain source and metadata cleanup owners
Require a caller-owned artifact resource scope for source traversal and Git metadata reads. Preserve cancellation, filesystem reasons, partial entries and bytes, and cleanup observations through import and the CLI. Transfer exact failed file owners at regular-file admission and close boundaries, including multiple failures encountered by Git reference resolution.

Validation: 169 focused tests passed across 26 files; two Windows-only cases skipped. Build, typecheck, lint, formatting, knip, architecture guards, discovery and docs checks passed.

BREAKING CHANGE: Reference source readers and imports require an ArtifactResourceScope. VCS metadata reads return Result, and CLI import failures include observed details and partial evidence.
2026-10-11 06:10:10 +08:00
morluto 215001a1ce refactor(filesystem): share directory cleanup ownership
Reuse the existing directory close state machine for artifact and reference readers. ArtifactResourceScope can retain the exact directory owner when cleanup fails.
2026-10-11 06:10:10 +08:00
YsopwnableandGitHub 9515d2fcd3 fix(tests): verify Qwen skills through an isolated native home (#1646) 2026-10-11 06:05:57 +08:00
YsopwnableandGitHub ac9677bd6c fix(test): preserve Ghidra interior-label controls on Mach-O (#1640)
* fix(test): preserve Ghidra interior-label controls on Mach-O

* test: preserve selector semantics and accept signaled fixture exits

* test(javascript): exercise deep returns through the public CLI
2026-10-11 05:45:00 +08:00
morluto 69fe5b6010 perf(javascript): index structured observations by path
Build package, JSON-module and source-map indexes once instead of rescanning every observation list per file. Preserve first-observation lookup semantics when paths repeat and share each JSON lookup with the file projection.

Validation: duplicate-observation consumer regression and reconstruction suites. Flameox captured before/after CPU profiles on 3,000 JSON files; the complete CLI output stayed byte-identical. Exploratory samples do not establish an end-to-end timing improvement.
2026-10-11 05:33:21 +08:00
morluto 684199ba0b fix(javascript)!: retain nested artifact readers in caller scopes
Require the caller artifact resource scope when reading JavaScript artifacts. Transfer failed nested ASAR cleanup to that scope so later work retries the same owner before admission. Preserve traversal failures and attempt every remaining iterator during unwind.

Validation: reconstruction, integrity, content identity, cancellation and nested-reader cleanup boundary checks.

BREAKING CHANGE: readJavaScriptArtifactFiles now requires ArtifactResourceScope as its third argument; the optional abort signal is fourth.
2026-10-11 05:33:15 +08:00
morluto a17e257f43 fix(artifacts): preserve failures while unwinding nested traversals
Finish every remaining iterator from inner to outer, retaining cleanup observations without replacing the original traversal failure. A real nested ASAR regression reproduces the previous integrity-error masking.
2026-10-11 05:33:14 +08:00
morluto 5502ca9c97 fix(artifacts): retain reader owners after cleanup failures
Keep directory handles under explicit close ownership and retain ZIP and Mach-O admission owners when initialization or cleanup fails. Preserve cancellation and primary failure details, and avoid false successful release after native handle invalidation.

Validation: filesystem ownership, FIFO, archive and reconstruction boundary checks; static and architecture checks; real macOS CLI/MCP bundle workflows. Windows native behavior was not verified.
2026-10-11 05:33:05 +08:00
morluto be75ed5e4b fix(publication)!: retain cleanup owners across export workflows
Require an ArtifactResourceScope for web script exports and share its lifetime with CLI or MCP shutdown. Retain setup-failed output trees in firmware and Wakaru providers. Preserve completed publications when descriptor cleanup fails, returning the full result after a successful retry or as a partial observation while cleanup remains unresolved.
2026-10-11 05:17:10 +08:00
morluto 3f8c51e9b5 fix(artifacts): retain output ownership through publication failures 2026-10-11 05:17:10 +08:00
morluto e0e49e9dd5 fix(artifacts)!: keep streamed reads within descriptor ownership
Use bounded positional reads for unpacked ASAR members and borrowed Mach-O slices so destroying a stream cannot bypass its descriptor owner. Retain uncertain ASAR closes and preserve borrowed sources after cancellation.

BREAKING CHANGE: Injected ASAR unpacked handles expose fd and read instead of createReadStream.
2026-10-11 05:17:10 +08:00
morluto be6272f261 fix(artifacts)!: preserve descriptor cleanup authority
Keep rejected closes unresolved after descriptor invalidation and share concurrent close attempts. Preserve primary admission failures and transfer the exact failed handle owner into inventory scopes.

BREAKING CHANGE: ArtifactResourceScope file-handle owners require OwnedFileHandle. Root inventory sources retain their single cleanup owner.
2026-10-11 05:17:10 +08:00
clydeandGitHub 32d13c431e test(javascript): retain resource ownership in deep-return fixture (#1644) 2026-10-11 05:16:03 +08:00
morluto 0fa0b04628 fix(electron): check Windows lineage before process cleanup
Return an unverified cleanup failure before invoking numeric process-tree termination when owned lineage is unavailable. Preserve the partial capture and existing cleanup diagnostics.

Exercise the provider capture boundary with stable application-state observations; assert no Windows cleanup call and retained partial Evidence. Source tests pass; native Windows behavior was not verified.
2026-10-11 04:43:02 +08:00
morluto ffe0574e17 fix(artifacts)!: retain cleanup owners through client shutdown
Keep failed reader, root descriptor, and output-tree cleanup with the caller. Drain admitted work before close, retry the same retained owners, and block new resource work while cleanup is incomplete. Preserve primary failures and complete inventory observations.

Thread ownership through JavaScript reconstruction, the CLI's one-shot scope, MCP server shutdown, verifier scripts, and test fixtures. Remove redundant ownership flags and the unused validated test wrapper.

Validate with 850 passing focused tests across 90 suites (two skipped), targeted classification and cleanup retries, static and unused-code checks, and real macOS CLI/MCP directory, ZIP, and DMG workflows. Native Windows and deep-analysis providers were not verified.

BREAKING CHANGE: Direct artifact inventory/extraction and JavaScript analysis APIs require an explicit caller-owned ArtifactResourceScope. CLI and MCP input contracts are unchanged.
2026-10-11 04:43:02 +08:00
morluto 87d5ec93d5 perf(javascript): index native Evidence links by observed digest
Build each side's digest-to-Evidence index once instead of scanning native observations for every comparison item. Retain every exact match and avoid linking subjectless Evidence to nodes lacking content identity.

Comparison and relationship regressions pass. Isolated alternating unprofiled runs at 2,000 nodes and observations per side have conventional medians 379.924 ms before and 246.466 ms after; the complete 4,000-item outputs match byte-for-byte. Timings are bounded workload evidence, not whole-suite performance.

Flameox profile: flameox://evidence/7dca714833dc3d254a75704670a81de656b4b31d4b77a72236eecb82459b3d86
2026-10-11 04:43:02 +08:00
morluto f1c58cc53f fix(reference): reject FIFO replacements without blocking
Use the shared nonblocking, no-follow regular-file opener at the source-read boundary and report a nonregular replacement as changed. Keep descriptor identity and extent checks.

The compiled subprocess regression timed out on the baseline and completes without a FIFO writer after this change. Reference reader failure, capacity, cancellation, and import checks pass.
2026-10-11 04:43:02 +08:00
morluto 6636045c9c fix(reference): match exclusions against observed entry kinds
Inspect each entry without following links before applying directory-only patterns. Retain the winning rule and original entry path while pruning excluded directories before reading their children.

Validate directory exclusions, negation, symlinks, explicit secret rules, and compiled CLI provenance alongside reference reader failure and cancellation coverage.
2026-10-11 04:43:02 +08:00
YsopwnableandGitHub b74d9a1bb2 fix(onboarding): isolate client homes and clarify npm release support (#1627)
Bind HOME and USERPROFILE in disposable native client verifiers, exercise default personal skill discovery, and clarify automatic Pi/Hermes setup availability in the checked npm release.

Validation: integrated build/static/docs checks, repeated native client workflows, real Codex-backed client trials and two independent cold-npx Codex installs. All 19 CI checks passed on a7ba07ba. Other model providers, platforms and deep-analysis engines retain their explicit verification TODOs.
2026-10-11 04:37:31 +08:00
6e0d5d64d3 feat(ghidra): admit set_address_name and set_addresses_names (#1635)
* feat(ghidra): admit set_address_name and set_addresses_names

Ghidra sessions rejected the existing naming tools with "operation is not declared by this provider", so agents had to use annotate_native_function, which returns a complete function dossier per rename and cannot name data addresses.

The Java bridge now names a local function entry (namespace-aware, like annotate_native_function) or creates/renames the primary label at any other mapped address, verifying readback. set_addresses_names applies each address in its own transaction and reports per-address booleans. Both are mutating capabilities: excluded from read-only (Windows P0) handshakes and from snapshot replay.

* fix(ghidra): normalize qualified symbol names and reject empty leaves

Share namespace-aware leaf normalization across functions and primary labels. Invalid qualified leaves now return false for naming operations without marking the provider unavailable; function annotations retain typed invalid-input errors.

Extend real CLI/MCP namespace verification with namespaced globals, readback replay, failed-name rollback, mixed batches, and capability checks.

Validation: 75 focused tests and npm run check pass. Ghidra 12.1.4/JDK 21 namespace verification passes on macOS arm64 with unchanged source bytes and complete cleanup. The full host lane passes this workflow before the existing entry-alias fixture fails because the compiler places its interior label at the function entry.

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-11 04:35:38 +08:00
YsopwnableandGitHub d6f698d8af fix(ghidra): admit carved MIPS ELF with incomplete section tables (#1629)
* fix(ghidra): inspect carved MIPS ABI declarations without missing sections

* test: share filesystem fixtures and cleanup assertions
2026-10-11 04:33:05 +08:00
morluto bbd01923e9 fix(artifacts): own DMG readers before attachment
Make inventory reader construction synchronous and DMG attachment lazy, so the inventory registers its reader before native operations start. Share initialization, reject work after close, wait for an in-flight attach before cleanup, and preserve retryable close state.

Cover failed-attach inventory cleanup, concurrent initialization, close-before-use, and close-during-attach alongside existing ownership, cancellation, and integrity cases. Session-level retention after inventory cleanup failure remains a separate concern.
2026-10-11 04:15:26 +08:00
morluto 5a77a962ec perf(reference): size read buffers from admitted file lengths
Use the descriptor size to bound each allocation, with a one-byte EOF probe, and stop on observed growth. Retain short-read, cancellation, and final identity validation.

A 2,001-file benchmark requests 4,200,307 bytes instead of 266,469,376 with the same captured-byte digest. Flameox shows filesystem waits dominate, so this is an allocation reduction without a CPU speedup claim.
2026-10-11 04:15:26 +08:00
morluto 6585293c56 fix(reference)!: preserve exclusion rule provenance
Record the exact matching pattern and distinguish project, default, caller, and configured-sensitive exclusions without changing ignore ordering. Include that provenance in graph commitments and validate the contract through compiled CLI and MCP consumers.

BREAKING CHANGE: Pattern-based reference graph exclusions require pattern and distinguish project-ignored and default-ignored reasons. Re-import saved graphs that omit matching patterns.
2026-10-11 04:15:26 +08:00
YsopwnableandGitHub be44b5098e test(javascript): share semantic graph fixtures (#1631) 2026-10-11 04:05:35 +08:00
morluto 6db97d5162 perf(javascript): remove duplicate workflow Evidence snapshots
Pass typed workflow results directly to createEvidence, which validates generic JSON and takes the owned snapshot. Remove the extra generic parse and full result clone from all five workflow helpers; domain producers retain their specific schema validation.

Flameox confirmed JSON validation and copying costs. Alternating warm runs creating Evidence for a valid 2,001-node trace reduced median boundary time from 15.94 ms to 11.20 ms over 120 samples per variant, with identical output digests and independent mutable-input snapshots. This does not measure end-to-end workflow latency.

Validation: 39 focused CLI, SDK MCP and filesystem workflow tests and 17 Evidence tests passed; build, static and documentation checks passed. No deep analysis providers were exercised for this change.
2026-10-11 03:56:59 +08:00
morluto 39da0b150b fix(artifacts): bind member reads to emitted metadata
Reject Mach-O and ZIP entries whose metadata no longer matches the reader inventory, preventing a sibling adapter key from selecting bytes under another entry. Reuse the existing ASAR metadata snapshot and equality rules and read Mach-O ranges from owned records.

Move the real system-lipo test to the provider boundary suite, release its reader, and derive slice expectations from the host FAT table.

Validation: 68 focused artifact, ASAR and MCP tests plus ZIP cancellation passed. Real macOS lipo was exercised against /bin/ls; Ghidra, IDA and other deep providers were not run. Static, docs, architecture and test discovery checks passed.
2026-10-11 03:53:50 +08:00
morluto 3967cfa43e fix(reference): distinguish root access failures from invalid input
Share root filesystem failure classification between import preflight and traversal. Missing roots remain invalid selections; permission and I/O errors retain their reason and reach the CLI as execution failures. Preserve cancellation priority and expose unexpected exceptions.

Validation: compiled CLI permission regression, direct reader error details, import/traversal and unreadable-directory boundaries passed. Windows-only cases were skipped on macOS; static, architecture and documentation checks passed.
2026-10-11 03:53:50 +08:00
morluto 2014ee7d68 perf(javascript): compare scalar semantic query seeds directly
Avoid repeatedly canonicalizing scalar seeds for every literal node. Valid literal metadata without a scalar value now remains unmatched instead of throwing.

Flameox identified canonicalization as the hotspot. Alternating warm query benchmarks over 2,002 nodes reduced the 35.5 KB seed median from 36.34 ms to 0.158 ms; a short seed improved from 0.304 ms to 0.128 ms with identical result digests. These measurements cover the query function, not end-to-end analysis.

Validation: 38 domain query/traversal tests and focused compiled CLI/MCP consumers; static, architecture and documentation checks passed.
2026-10-11 03:53:50 +08:00
YsopwnableandGitHub 5100a1a1a5 test(clients): verify Copilot compact schema workflows (#1624) 2026-10-11 03:43:24 +08:00
morluto de0d341524 fix(artifacts): retain unpacked ASAR handles after close failures
Own unpacked FileHandles until closure succeeds, deduplicate in-flight closure, and retain cleanup resources for retry without replacing the original read or identity failure. Attempt handle and snapshot cleanup independently and retain failed snapshots.

Consolidate unpacked admission, identity checking, cancellation and stream setup, removing the redundant same-handle stat. Cover stat and identity failures, post-stat cancellation, combined cleanup failure/retry, and stream completion/cancellation with real file descriptors.

Validation: 32 ASAR boundary tests, artifact extraction and SDK MCP consumers, check:fast. Native Windows descriptor inspection and real-provider workflows were not verified.
2026-10-11 03:36:36 +08:00
morluto d1f04512af refactor(javascript): remove redundant semantic query passes
Use resolved seeds directly, retain one list of relevant unknowns, and stop sorting adjacency used only for complete reachability. Preserve canonical graph-array output order and candidate coverage scans.

Validation: 37 query and traversal tests, public JavaScript reconstruction and invalid-Evidence consumers, check:fast. No real-browser or deep-provider workflow verified.
2026-10-11 03:36:35 +08:00
morluto 514df0918c fix(analysis-view): preserve inline Evidence error paths
Project authenticated inline Evidence failures at source.evidence while retaining their reasons and messages. Supply the matching request root to input issue projection so nested values remain identifiable.

Validation: both service entrypoints and SDK MCP integrity regressions, advertised-schema consumer suite, check:fast and architecture guards. No real-provider verification.
2026-10-11 03:36:35 +08:00
morluto 8fb79c67ee perf(evidence): remove disposable ledger work from standalone import
Count already-validated records and unknown revisions without reimporting, sealing, and exporting a temporary empty ledger. Keep canonical integrity checks at the file boundary and verify counts and malformed bundles through the compiled CLI.

Validation: Evidence file and CLI consumer suites; check:fast; Flameox CPU profiles and alternating 3.8 MB import benchmark (315.8 ms to 102.5 ms warm median, identical result digests). No real-provider workflow changed or verified.
2026-10-11 03:36:35 +08:00
clydeandGitHub 6a41a29963 fix(apple): preserve directory requirements in dylib paths (#1623) 2026-10-11 03:30:27 +08:00
YsopwnableandGitHub c12a532b9c perf(evm): avoid repeated cleanup diagnostics (#1622)
Retain the original owned-command cleanup failure and one captured-output copy while preserving cleanup resources, truncation and retry semantics.

Verify socket release after cancelled CDP cleanup while retaining the independent detach regression.

Validation: 167 tests across 13 files, all eight local gates, real small Chrome/EVM CLI and pinned-SDK MCP controls, and 20/20 exact-head CI checks.
2026-10-11 03:28:16 +08:00
YsopwnableandGitHub b28c0337fc perf(javascript): reduce retained semantic analysis allocations (#1601)
Reduce retained semantic allocations and memoize lexical scope ancestry while preserving semantic identities. Refs #1065 and #1563; the complete-directory memory failure remains open.
2026-10-11 03:20:05 +08:00
morluto f4e437e544 refactor(artifacts): remove unused extraction inventory indexes
Derive needed artifact IDs directly from selected occurrences. Keep the node lookup local to selection, drop the unread occurrence map and collector helpers, and pass only manifest and selected integrity metadata to materialization.

Validation: existing extraction completeness, identity, unsupported-format, packed/unpacked ASAR, and public MCP workflows pass. Nested archive selection and equal-content occurrence coverage remain intact. This is a structural simplification; no throughput improvement is claimed.
2026-10-11 03:19:29 +08:00
morluto 8ba0a887ff refactor(javascript): bind application links only at graph finish
Remove the empty application-node index from incremental projection state. The completed application graph now owns the only binding pass, and indexing returns the map directly instead of a wrapper.

Validation: 76 builder/composition tests and 19 filesystem, CLI-output, and SDK MCP trace boundary tests pass. Identity budgets and streaming/full-projection parity remain covered; no throughput improvement is claimed.
2026-10-11 03:19:29 +08:00
morluto f9ea9a9268 fix(process)!: bound terminal buffers before capture
Validate columns × (rows + scrollback) against a 1,000,000-cell xterm working-buffer budget, including every resize with the selected scrollback. Document the budget in the advertised MCP input and process-capture guide; never clamp caller dimensions.

Validation: default/exact-boundary schema cases, prelaunch MCP rejection, compiled CLI capture, terminal rendering, normalization, cancellation, and lifecycle checks pass on macOS. This is resource admission, not a measured serializer throughput improvement; Linux-only and real deep-analysis providers were not exercised.

BREAKING CHANGE: process scenarios whose initial or resized terminal exceeds 1,000,000 combined visible-plus-scrollback cells are now rejected before launch.
2026-10-11 03:19:29 +08:00
morluto 78778d91a4 fix(artifacts): retain output identity through cleanup retries
Track created directory and file identities before materializing or removing output. Refuse displaced paths and untracked entries, preserve completed cleanup work across permission failures, and prevent publication once rollback starts. Group cleanup files once per attempt instead of rescanning them for every directory.

Validation: root, nested-parent, and file symlink replacement; untracked-entry retention; real POSIX permission failure and retry; extraction integrity and CLI/MCP consumers pass. Path identity revalidation cannot eliminate syscall-boundary pathname races in portable Node. Windows behavior was simulated; native Windows and Linux-only publication providers were not exercised.
2026-10-11 03:19:29 +08:00
morluto d510f3e928 perf(browser): share JSON shape paths across repeated array rows
Accumulate observations once per structural path instead of allocating and serializing a path for every payload value. Remove the CDP body-shape wrapper and retain primitive, empty-array, and literal-property semantics.

Validation: CDP capture/comparison regressions and CLI/MCP boundary checks pass; 1,507 differential cases match the previous implementation. A 2.5 MB repeated-row workload improves from 105.0 ms to 14.6 ms warm median across alternating runs. Real browser providers were not exercised.
2026-10-11 03:19:29 +08:00
YsopwnableandGitHub 043fd2579d fix(firmware): recover after workspace removal failures (#1616) 2026-10-11 03:16:34 +08:00
YsopwnableandGitHub a761981897 test: remove module and timestamp assumptions from boundary fixtures (#1621) 2026-10-11 03:15:44 +08:00
YsopwnableandGitHub 2653b194b6 feat(skills)!: improve Codex onboarding and task recovery (#1613)
Guide task-centered recovery from observed client, registration, PATH and
provider blockers. Install the recovery reference, document exact JavaScript
module selectors, and require clarification before searching for an unnamed
app. Validate public setup in isolated Codex accounts and preserve failed
or unrecognized tool outcomes in the existing evaluator.

Refs: #1587

BREAKING CHANGE: Optional verify:agent reports now use schemaVersion 4.
Consumers must accept expectedFirstTool: null and targetClarificationPassed
for missing-target scenarios. Production CLI/MCP contracts are unchanged.
2026-10-11 03:13:56 +08:00
YsopwnableandGitHub 16d9c5adef fix(ci): preserve cleanup boundaries and bounded failure assertions (#1618)
Interrupt optional CDP domain shutdown on caller cancellation while preserving an independent bounded detach attempt. Retain original overflow and cleanup failures, verify workspace recovery, preserve user skill files, and reject another unverified firmware worker.

Validation: 149 integrated tests; repeated 64 affected boundary tests; full local check. Standalone CI includes real Chrome CLI/stdio MCP and real Web runtime checks.

Refs #1613
2026-10-11 02:54:12 +08:00
morluto b582b6ecb4 fix(managed): enforce module identity before joining token facts
Validate declared artifact and MVID scopes at managed Evidence admission, and reject conflicting known module declarations across graph inputs. Join boundary tokens to members only under matching known MVID scopes; preserve facts and report partial coverage when scope is unknown.

Prefer an observed MVID-bearing declaration with its supplying Evidence. Normalize GUID casing for module node identity while preserving original strings in observations.

Validation: 285 tests across 34 focused suites passed, followed by the final 12-test managed graph suite and managed CLI/MCP regressions. check:fast and architecture guards passed; no real native providers were run.
2026-10-11 02:52:11 +08:00
morluto ba056e08a4 fix(providers): bound launcher diagnostics without losing byte counts
Give Ghidra and Hopper an 8 MiB aggregate retained-output budget while continuing to drain their process pipes. Expose total observed bytes at the supervisor boundary and retained bytes plus explicit truncation in provider diagnostics.

Redact known transport tokens even when the retained prefix ends inside one, preserving adjacent caller path/query evidence. Existing partial-launch and cleanup ownership remain intact.

Validation: 285 tests across 34 focused suites passed; the final cutoff-fixture refinement passed all 31 Ghidra/Hopper diagnostic tests. check:fast and architecture guards passed. Provider fixtures use real child processes; real Ghidra/Hopper applications were not verified.
2026-10-11 02:50:06 +08:00
morluto cb13a27bfa perf(artifacts): reuse the admitted ASAR header size
Use the header size already validated against the owned archive snapshot instead of asking the ASAR SDK to read and allocate its raw header again.

Validation: ASAR freshness, containment, streaming-allocation, and MCP extraction suites passed within the 285-test focused run. check:fast and architecture guards passed.
2026-10-11 02:49:05 +08:00
morluto 3d79903fb1 perf(browser): normalize precise coverage once by script identity
Pass validated coverage into normalization and index retained sources by script ID instead of scanning them for every script. Preserve source revalidation, UTF-16 bounds, nested counts, and unavailable-source uncertainty.

Validation: 285 tests across 34 focused suites, check:fast, and architecture guards passed. Flameox-guided 8,000-script normalization benchmark improved from 101.6 ms to 5.5 ms median with identical full-result digests; this is normalization CPU, not end-to-end browser timing.
2026-10-11 02:48:59 +08:00
morluto dce81ca400 perf(javascript): count candidate relevance without a second adjacency
Scan eligible candidate relations directly for query ambiguity instead of allocating and sorting another traversal index. Preserve direction, relation filters and cycle handling.

Semantic graph and builder suites plus public application workflow CLI tests passed. Full query outputs matched on a generated 20000-node graph; the single repeated-query timing run is indicative only.
2026-10-11 02:32:11 +08:00
morluto bb764d26bd perf(artifacts): stop parsing parent paths after a missing branch
Walk delimiter-terminated parent segments lazily instead of splitting full paths before discovering that no deeper observed parent exists. Preserve canonical paths and observed ancestry.

Verified real ZIP inventory with multiple 30000-component siblings and the full entry-order suite. A 96-member deep ZIP benchmark retained an identical full inventory digest and reduced median scan time from 517.5 to 464.5 ms across five measured inventories.
2026-10-11 02:32:04 +08:00
morluto acd8d86898 perf(android): validate prerequisites once per retained JADX session
Resolve current paths and JVM options and rehash source identities for each request. Probe Java modules and engine capabilities only when creating a new session; remove the superseded full configuration resolver.

Focused configuration, session retirement, cancellation, cleanup and Android MCP boundaries passed. The 34-operation retained session now performs one prerequisite probe. Protocol fixtures do not establish real JADX or JDK performance.
2026-10-11 02:31:57 +08:00
morluto e6d0b3993d perf(process): batch liveness rechecks within ownership phases
Recheck unreadable token and identity observations against one fresh live process snapshot per phase. Preserve token mismatches, fail closed on inspection errors, and retain liveness failure diagnostics.

Validated with focused process ownership, native capture, CLI and MCP boundaries. An eight-member injected-unreadable workload using native ps reduced snapshots from nine to two with equivalent failures; real permission-denied provider behavior was not exercised.
2026-10-11 02:31:07 +08:00
morluto 92a901e0db perf(process): share settlement probes across captured groups 2026-10-11 02:21:50 +08:00
morluto cef6d6d3c4 perf(artifacts): reuse trie membership for case-folded siblings 2026-10-11 02:21:40 +08:00
morluto bd972bf80b perf(javascript): reuse capture completeness during load classification 2026-10-11 02:21:35 +08:00
morluto ac9709a80a perf(reconstruction): index semantic evidence contexts per derivation 2026-10-11 02:21:28 +08:00
morluto d1e6fe2eca test(artifacts): close owned Mach-O readers after each case 2026-10-11 02:11:13 +08:00
morluto a147ecd4b4 perf(artifacts): index observed parents for deep archive paths 2026-10-11 02:10:50 +08:00
morluto 22fdcb8ab7 perf(process): share batched token observation across ownership checks 2026-10-11 02:10:44 +08:00
morluto b22d817073 perf(process): batch ownership tokens during rooted cleanup
Use the host bulk token reader for each cleanup validation while preserving identity checks before and after token reads. Fall back for unsupported readers or omitted rows, retain explicit unavailable observations, and preserve batch and individual failures. Source ownership regressions and real owned-process boundary tests pass; a warm Darwin validation probe reduced median time from 90 ms to 52 ms.
2026-10-11 01:59:30 +08:00
morluto 3d876c5c1a perf(javascript): validate semantic factory inputs once
Construct typed semantic records directly from cloned, normalized input and derived commitments instead of reparsing the same fields. Keep full graph integrity validation and verify caller mutation isolation. Four alternating cold runs preserved complete result digests while median projection time fell about 8 percent and 17 percent for the two 20,000-node capacity workloads.
2026-10-11 01:54:46 +08:00
morluto cf346368c4 perf(javascript): reuse graph buckets and query indexes
Append overlapping observations to node buckets instead of recopying groups, and share one node index across semantic seed admission and traversal. Preserve merged provenance and absent-seed behavior.
2026-10-11 01:54:36 +08:00
morluto e52c0a72c5 fix(browser): retain incomplete WebMCP replay coverage
Mark malformed WebMCP event envelopes, tool lists and entries as invalid protocol values while preserving valid siblings and out-of-scope classifications. Verify toolsAdded and toolsRemoved replay uncertainty through CDP discovery and capture comparison.
2026-10-11 01:54:26 +08:00
morluto 999e3e2098 fix(android): cancel admitted snapshot copies with their operation
Forward caller and timeout cancellation through engine and APK snapshots, release stream handles before removing partial output, and retain the existing root cleanup authority. Verify cancellation after destination bytes appear with a sparse filesystem fixture.
2026-10-11 01:54:20 +08:00
dakjdakdandYsopwnable c1217e711b fix(javascript): retain runtime scope in bundled module relationships 2026-10-11 01:36:12 +08:00
morluto 0d89978333 fix(android): release snapshot streams before closing file handles
Retain both non-auto-closing copy streams and destroy them after verification, before awaiting their FileHandle closure. This releases stream-held descriptor references on success and failure instead of deadlocking Android snapshot cleanup.

Validation: all 33 JADX subprocess integration tests passed on macOS with Node 24.18.0; check:fast and formatting passed. No real JADX provider execution or Linux/Windows verification was performed locally.
2026-10-11 01:12:48 +08:00
morluto 11e3fae697 fix(ci): repair boundary regressions and evidence assertions
Detach cancelled CDP sessions within the cleanup budget and retain event-finalization failures across retries. Honor Git filesystem encodings and exclude the promise-API probe from source-read failures.

Align existing integration regressions with retained process resources, filesystem-order-independent truncation, owned skill files, explicit native access facts and streamed JSON errors.

Validation: 132 acceptance tests passed (2 skipped), 83 affected boundary tests passed, Git/JSON/CLI boundary regressions passed, check:ci, docs:check and test discovery passed. Local verification used Node 24.18.0 on macOS; cross-platform CI remains pending.
2026-10-11 01:00:30 +08:00
morluto 603d04ee3a fix(ci): repair format gate and pin maintenance skill destinations
format:check failed on ApktoolProvider; existingMaintenanceScope now
returns skillDestinations (consumed by maintenance planning), so pin
the field in the exact-shape scope assertions.
2026-10-11 00:33:36 +08:00
morluto 472f313232 refactor(native): match UI controls by explicit object identity 2026-10-11 00:28:39 +08:00
morluto 1f7e279aa2 fix(adb): retain rollback ownership and cancelled acquisition facts 2026-10-11 00:28:39 +08:00
morluto db8ccaa251 fix(android): bind JADX snapshots and hashes to admitted sources 2026-10-11 00:28:25 +08:00
morluto 5daff4d67e fix(artifacts): retain Mach-O source identity through inventory 2026-10-11 00:28:25 +08:00
morluto a9fd1aecae fix(application): verify configuration and reference input reads 2026-10-11 00:28:24 +08:00
morluto abb8e81d3a fix(filesystem): bound and verify admitted file and JSON reads 2026-10-11 00:28:24 +08:00
YsopwnableandGitHub 6d8f95e38d fix(clients): preserve portable MCP schemas in native workflows (#1580)
* test(clients): verify native Command Code workflows

* docs: synchronize Italian provider guide links

* fix(contracts): make ADB identifier patterns portable

* fix(contracts): preserve portable ADB patterns after formatting
2026-10-11 00:09:43 +08:00
morluto c1b5ccf0a4 refactor(server): admit complete evidence workflows and share handlers
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:24 +08:00
morluto 5f30ea6ff2 fix(engines): serialize JEB acquisition and respect IDA cancellation
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:23 +08:00
morluto d438675677 fix(process): retain capture resources and bound filesystem snapshots
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:23 +08:00
morluto a84dea5500 fix(apktool): join active work and retain cleanup authority
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:22 +08:00
morluto 2a66ec9094 fix(browser): retain startup owners and coordinate retryable close
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:22 +08:00
morluto d1235fadc9 fix(providers): retain worker cleanup owners through shutdown
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:21 +08:00
morluto a01148553e fix(setup): preserve recovery backups and retain installer cleanup
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:21 +08:00
morluto a6f76f5da9 fix(graphs): separate source identities from display representations
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:20 +08:00
morluto 2ca3ad2386 fix(reference): preserve exact paths and unify symlink lookup
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:20 +08:00
morluto 5d0a883605 fix(native): bound metadata projection and compact Mach-O bind runs
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:19 +08:00
morluto 0f0d6e4d43 fix(managed): budget decoding before representation expansion
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:19 +08:00
morluto 6d4cefc4f7 fix(artifacts): admit bounded reads and preserve source identity
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:18 +08:00
morluto 2a0b58e440 refactor(cleanup): share failure composition and retain native UI owners
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:18 +08:00
morluto 6543405252 fix(adb): escape portable patterns for unicodeSets consumers 2026-10-10 23:40:37 +08:00
morluto cca7bf0022 fix(ci): repair option alias, pattern portability, and Italian doc links 2026-10-10 23:34:57 +08:00
morluto bb742110a4 fix(ghidra): build bridge script paths with the target platform syntax 2026-10-10 23:22:44 +08:00
morluto a97bd5ed29 fix(ci): share provider workflows to restore static gates 2026-10-10 23:15:02 +08:00
Jay-Alexander ElliotGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
bddddccdee feat(native): admit bounded MIPS ELF analysis through Ghidra (#1362)
* feat(native): admit bounded MIPS ELF analysis through Ghidra

Retain MIPS ELF identity and interpretation through Evidence and snapshots.
Keep provider admission bounded to ELF32 ET_EXEC o32 MIPS32r2, without
implicitly widening Hopper, IDA or Windows P0 coverage. Add source-owned
fixtures and an optional real-provider verifier; real Ghidra verification
remains pending in this contribution environment.

Refs #718

* fix(ghidra): bound MIPS floating-point mode admission

Reject explicit EF_MIPS_FP64 and EF_MIPS_NAN2008 declarations until their
semantics have a real-provider verification lane. Add PSP PRX/Allegrex,
o64/EABI and floating-point-mode refusal regressions. Document that the
header gate is not a full .MIPS.abiflags check and advance the profile lane
identity to invalidate older interpretation bindings.

Validation: 24 standalone checks against the transpiled production profile
module passed; the two new flag cases failed before this change. Clang 17
and LLD compiled the source-owned fixture for both endian targets. The
complete Vitest/typecheck suite and real Ghidra verification remain pending.

Refs morluto/rea#718; PSP support remains follow-up morluto/rea#1330.

* fix(native): validate MIPS ABI records before Ghidra admission

Read bounded ELF32 PT_MIPS_ABIFLAGS and SHT_MIPS_ABIFLAGS records through
the already-open target handle. Preserve declared ABI fields, reject
conflicting/duplicate/truncated records, and keep missing records unknown.
Wire inspection into target resolution before provider selection. Require
compatible declarations for the deliberately narrow Ghidra lane and bind
all ABI fields into profile identity (v3) for snapshot invalidation.

Clang 17 produced eight source-owned fixtures spanning both byte orders
and FPXX/FP32/FP64/soft-float modes with identical ELF header flags. The
new reader and policy distinguish them. 24 focused regression test bodies
passed after TypeScript transpilation using node:test in place of Vitest;
strict isolated TypeScript checking of the reader and target/result types
passed. These are limited checks, not full Vitest/project typechecking or
real-Ghidra verification, which remain pending.

Advances morluto/rea#718. PSP/Allegrex remains morluto/rea#1330 follow-up.

* fix(native): repair MIPS integration boundaries and test resolver behavior

Keep ELF targets out of Hopper Mach-O preparation and scope existing PE fixture types correctly. Move ABI tests into the filesystem boundary lane, use shared cleanup, add resolver regressions, apply the pinned formatter, and register the real MIPS verifier through the existing package-command pattern. Validated with repository-pinned Node/npm, check:ci, actual focused Vitest, discovery and docs:check. Real Ghidra conformance remains pending.

* fix(test): honor caller-selected JDK in real MIPS verification

* test(native): strengthen MIPS Ghidra conformance

Cross-check the source-owned fixture with bounded GNU readelf inspection, compare production ELF/ABI interpretation and independent symbol addresses, and verify effective Ghidra language/compiler identity through existing public operations. Add a source-owned fixed-encoding probe for immediate and conditional branch checks plus global/string byte assertions.

Add 16 assertion/producer-boundary regression cases without widening production admission, changing provider contracts, or introducing proprietary dependencies. Local focused suite: 99 passed, one existing root-permission test skipped. Typecheck, lint/module boundaries, formatting and 700-file discovery pass; full hosted checks and real Ghidra verification remain pending for this checkpoint.

* fix(ghidra): preserve native-tool architecture checks after MIPS integration

The conflict-free upstream merge failed TypeScript compilation because includes on the union of MIPS-only and other architecture arrays requires never. Use equality-based membership without casts or changing accepted native hosts. Extend the existing native-decompiler rejection table with a MIPS executable at a Linux x64 tool path; retain upstream FAT and unknown-header behavior. Hosted verification follows this commit; no success is claimed yet.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-10-10 23:04:27 +08:00
96fd98cce0 feat(apktool): decode Android resource tables through a caller-supplied launcher (#1556)
* feat(apktool): decode Android resource tables through a caller-supplied launcher

Add an Apktool family with two operations over the caller's apktool
launcher (REA_APKTOOL_COMMAND, absolute, or apktool on PATH):

- inspect_apktool_client: resolved launcher, selection source, and
  version; decodes nothing.
- decode_android_resources: apktool d --no-src in a provider-owned
  workspace that is removed before the result returns. Projects the
  decoded AndroidManifest.xml (bounded at 512 KiB), apktool.yml version
  and SDK facts exactly as printed, string resources verbatim (default or
  one locale, bounded at 2000 entries, nested-markup entries counted as
  unparsed), available string locales, and the decoded file count with a
  hard cap. The target APK is digested with SHA-256 before decoding so
  Evidence binds the observation to the exact input.

Smali production is skipped by design: Java-source recovery belongs to
the JADX family. Workspace cleanup happens before results return; an
unremovable workspace is named in the limitations instead of abandoned.

Verified against apktool 2.7.0-dirty (Debian packaging) on Linux with
OpenJDK 25 against a signed aapt2-built probe APK with two resource
locales: launcher version, on-disk digest agreement, metadata projection,
manifest package agreement, and both string tables (default and de).
Parser goldens come from the same decode. READMEs carry the new
'Android resources' row in every supported language.

* fix(apktool): own snapshots and bound decoded resource reads

* docs(apktool): describe owned resources and bounded projection

---------

Co-authored-by: REA Contributor <contributor@rea.tools>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:04:12 +08:00
749e58772a feat(jeb): add JEB engine provider over its MCP interface (#1536)
* feat(jeb): add JEB engine provider over its MCP interface

Add a bring-your-own JEB provider that serves project, unit, and
decompilation inspection from a caller-started JEB client speaking MCP
(streamable HTTP, selected with REA_JEB_MCP_URL). Expose four provider-neutral
operations through shared CLI/MCP workflows: inspect_jeb_client,
open_jeb_project, list_jeb_units, and decompile_jeb_item, each returning
Evidence with engine identity, endpoint, and preserved refusal reasons.

The adapter keeps JEB's envelope semantics: success fields are parsed
format-aware at the boundary, message-only refusals become unsupported-target
errors with the engine's own reason, transport failures become availability
failures with recovery guidance, and unit pagination derives coverage from the
engine's 100-item page cap. Explicit unknowns (implicitly selected unit,
omitted filters) are reported instead of guessed.

Verified against a real JEB 5.48.0 licensed build serving jeb-mcp-server 1.3.0
headless: client inspection, unit listing, and method decompilation were
exercised through the CLI, MCP boundary, and scripts/verify-jeb.mjs.
JEB 5.48.0 headless instances do not advertise open_project; the refusal is
preserved and documented.

* fix(jeb): verify against a real signed APK and fix CLI option surface

Verify the provider against a locally built, v1/v2/v3-signed probe APK
(binary manifest, classes.dex with a launcher activity) on JEB 5.48.0: the
full unit tree (apk, manifest, three certificate units, dex bytecode,
decompiler), wildcard-filtered and paginated unit listing with derived
coverage, parent-restricted listing, and launcher-activity method
decompilation through both CLI and MCP, including dexdec's inline
constant folding of the probe's obfuscated tag.

Move list-jeb-units filter/pagination and decompile-jeb-item unit selection
from positional arguments to options; the MCP schemas are unchanged.

* fix(jeb): preserve engine refusals through the real MCP boundary

Testing against the published Signal 8.30.3 universal APK exposed a boundary
bug the scripted provider tests missed: decodeJebToolResult raised a protocol
error for isError results before the provider could map JEB's
{success:false, message} envelope, so real engine refusals surfaced as
unreadable output instead of the engine's own reason. Decode refusal
envelopes like any structured result and let the provider preserve the
reason; cover the decoder directly, including contentless and unparseable
results.

Signal verification: full 109 MB R8/Kotlin/Compose APK with four signature
schemes and native arm64 ELF units parsed; MainActivity.onCreate and R8
synthetic lambdas decompiled through CLI and MCP; paginated, filtered, and
parent-restricted unit listing; refusal path confirmed on the live engine.

* docs(jeb): record Flutter Gallery verification on the real-engine lane

Verify the provider against the official Flutter Gallery 2.9.2 release APK
(112 MB): per-ABI libapp.so Dart AOT snapshot images analyzed as native code
with 75k methods on arm64, snapshot internals and wrapper methods decompiled
through both CLI and MCP with explicit unit selection, decoded manifest, and
filtered native-library unit discovery. Note that JEB 5.48.0 headless does
not expose the dedicated Dart snapshot processor or run_script; both remain
GUI-only engine surfaces.

* docs(jeb): translate the README JEB row for every supported language

The JEB row was inserted in English across all translated READMEs; each now
carries its own label, capability summary, requirements, and guide link
following that language's Android-row conventions.

* fix(jeb): enforce local endpoints and preserve cancellation

* fix(jeb): refuse redirects across the local MCP boundary

---------

Co-authored-by: REA Contributor <contributor@rea.tools>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:03:27 +08:00
ded59689ce fix(javascript): accept the Wakaru 1.x release line and verify 1.14.0 (#1540)
* fix(javascript): accept the Wakaru 1.x release line and verify 1.14.0

Exact --version equality rejected every Wakaru build except 1.13.0, and
strict report schemas rejected any added field, so each upstream release
broke recovery until REA re-pinned. Wakaru now documents that --version,
--json and provenance.json change only by addition within a major version.

Admit ^1.13.0 with the verified/compatible split used for Binwalk and
Unblob, report the observed version instead of the pinned constant, and
add a limitation for unverified releases. Parse reports with loose
objects and keep the reported module status as a string; path, identity,
range and file-set checks stay exact.

Move the audited pin, submodule, CI binary and verifier to 1.14.0, and
document where to get the binary from the refusal message.

* fix(javascript): project known Wakaru warning fields

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:02:15 +08:00
0363e5a8e1 fix(reference): join internal symlink targets with the inventory NFC normalizer (#1535)
* fix(reference): join internal symlink targets with the inventory NFC normalizer

checkSymlinks resolved an internal symlink target with bare
posix.normalize and looked the result up in the inventoried path set.
A target that a filesystem reports in NFD (macOS readlink commonly
does) joined to an NFD spelling while the inventory holds NFC, so
validation reported "Internal symlink target must resolve to an
inventoried entry" for a target the inventory actually contains.

Route the join through normalizeJoinedLogicalPath, the same inventory
identity normalizer #1513 applied to the runtime, HTML/module, and
import joins from #1488. The feature-seed NFKC query fold stays a
query.

Refs #1488

* fix(reference): preserve source spelling during symlink lookup

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:02:10 +08:00
905e4866c4 feat(artifacts): inspect PE resource identities and payload ranges (#1482)
* feat(artifacts): inspect PE resource identities and payload ranges

* fix(artifacts): reject header payloads overlapping PE sections

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:02:06 +08:00
f6009d0077 fix(browser): keep the first DOM attribute when the name is repeated (#1516)
* fix(browser): keep the first DOM attribute when the name is repeated

When an element in a captured DOM tree carries duplicate attribute
declarations (e.g. repeated href, action, or src), domMetadata folded
the attributes into a Map using pairs.set(), overwriting earlier
declarations with the last one.

HTML specifies that the first declaration is kept when an attribute
name is repeated. This aligns domMetadata and attribute_names to retain
the first occurrence case-insensitively, matching HTML and ensuring that
attribute_names and dom_urls reflect the same attributes.

Fixes #1496

* fix(browser): preserve case-sensitive DOM attribute names

* test(browser): align repeated attribute coverage with deduplication

---------

Co-authored-by: taljeri <318237806+taljeri@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:02:00 +08:00
4d8d76b253 fix(electron): support packaged app.asar pages and rewritten unpacked companions (#1400)
* fix(electron): resolve pages served from inside app.asar

Packaged Electron applications load their renderer pages from file URLs
inside app.asar. The host filesystem cannot stat those paths, so
list_electron_targets excluded every such page as unsupported_url and
inspect_electron_page could not select it.

Resolve these URLs the way Electron's file protocol does: the first .asar
path component that is a regular file is the archive, and the remainder
must name a regular file in its header. Directories, links, and missing
members stay rejected. Parsed headers are cached by archive identity.

* fix(artifacts): extract and explain rewritten ASAR unpacked companions

Packaging tools commonly sign or strip .asar.unpacked native binaries after
writing the archive header, so their declared hashes no longer match.
analyze_javascript_application already accepts integrity_policy, but
extract_artifact did not, and inspect_artifact and extract_artifact still
told callers to "get a fresh copy", which cannot help for a shipped app.

- Accept integrity_policy on extract_artifact (MCP and CLI). The default
  still fails closed; record-and-continue writes the observed bytes and
  returns the extracted files' integrity_contradictions records.
- Name the unpacked entry and the post-packaging cause in integrity
  failures, and point every operation that accepts integrity_policy at
  record-and-continue.
- Report an active unpacked entry whose companion file is absent as
  unavailable with its logical path instead of a format failure.
- Share one integrity_policy schema across the inventory, extraction, and
  JavaScript application inputs.

* fix(electron): bound ASAR headers before allocation

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:01:54 +08:00
162f9bf7ff fix(ghidra): clear wrong no-return flags before serving a session (#1419)
* fix(ghidra): clear wrong no-return flags before serving a session

Auto-analysis can flag ordinary functions as no-return (stream readers,
__cxa_guard_acquire, ...). Their callers then end at the call and the
decompiler truncates them. Run a postScript before the bridge that clears the
flag on functions containing a real RET and re-disassembles the call sites that
were terminators.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(ghidra): refit in place and scope no-return call-site repair

Keep function types by refitting the owning functions with fixupFunctionBody
instead of removing and recreating them. Only redo call sites whose callee was
actually cleared (including thunks to it), skip sites followed by a function
start or x86 padding so real end calls do not run on, and always log the result.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(ghidra): constrain no-return repair to admitted return evidence

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:01:50 +08:00
fef6f73064 feat(adb): complete ADB device support for Android reverse engineering (#1552)
* feat(adb): acquire installed APK sets from connected Android devices

Add a read-only ADB device-acquisition family over the caller's adb binary:
inspect_adb_client, list_adb_devices, inspect_adb_device, list_adb_packages,
and pull_adb_package, exposed through the CLI and MCP with shared admission,
Evidence provenance (binary, version, serial, transport), and fixed argv
vectors that never reach a shell.

pull_adb_package acquires the complete split set reported by pm path into a
package-named directory that must not exist, digesting every file with
SHA-256 and keeping per-file failure reasons and partial coverage. Device
kind is reported as an inference with its basis; getprop whitelisting keeps
build identity bounded. REA installs nothing and never manages devices or
emulators; the first device query may start the caller's local adb server,
recorded when observed.

Verified against adb 34.0.5 on Linux with an Android 14 (API 34) x86_64
emulator: full 224-package inventory, a real two-APK split set pulled with
byte-exact digests, and a 73.9 MB system-package pull. npm run verify:adb
records the lane; parser goldens come from the same device. READMEs carry
the new row in every supported language.

* feat(adb): complete the adb surface with observation, transfer, and lifecycle tools

Extend the ADB family from five to twenty-four operations, all through
fixed adb argument vectors with no shell exposure:

Observation: read_adb_logcat (bounded dump, count/buffer/pid), inspect_adb_package
(dumpsys package projection), list_adb_processes (ps -A), list_adb_directory
(ls -la with kinds and symlink targets), list_adb_features (hex GL versions),
list_adb_services (AIDL slash-suffixed names), inspect_adb_display (wm size and
density), inspect_adb_window (focus declarations), read_adb_setting (device-side
nulls reported as such), capture_adb_screen (exec-out screencap with PNG
dimensions), collect_adb_bugreport (digested device archive).

Transfer and search: pull_adb_file and push_adb_file (device-side sha256sum
verification, explicit overwrite authority), resolve_adb_packages (substring
package search with exact-match flag — the find step of an easy get).

Lifecycle for dynamic analysis, each declaring mutatesTarget:
install_adb_package and uninstall_adb_package preserving the device's
Success/Failure verdict, start_adb_app (resolve-activity then am start -W),
start_adb_activity (typed extras as --es/--ez/--ei/--el/--ef), and stop_adb_app
(am force-stop).

Verified end-to-end against adb 34.0.5 on Linux with an Android 14 (API 34)
x86_64 emulator: 287 services, 92 features, split-set pulls with byte-exact
digests, verified push/pull roundtrip, sized screen capture, and the full
install → resolve → start → observe-in-ps → force-stop → uninstall lifecycle.
Fixed a v-mode regex incompatibility in the settings key pattern and added
argument descriptions required by the CLI catalog audit.

* fix(adb): quote remote shell operands and protect captured output

* test(adb): cover bugreport destinations containing spaces

---------

Co-authored-by: REA Contributor <contributor@rea.tools>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:01:24 +08:00
YsopwnableandGitHub efd81f9776 test(clients): verify native Grok Build workflows (#1571) 2026-10-10 22:59:43 +08:00
5156ba44c5 feat(native): return a retained summary view of binary layouts on request (#1570)
inspect_binary_layout accepts the same optional detail input as
analyze_javascript_application. The default complete delivery is
unchanged; detail "summary" retains the complete layout Evidence in the
session and returns its inspect_analysis_view summary, whose
parent_evidence_id selects sections, symbols, mitigations or linkage
later. Both tools share one detail schema and output projection.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:57:42 -07:00
c19e15a2b3 feat(javascript): return a retained summary view on request (#1568)
analyze_javascript_application returns the complete application graph
inline, which repeats tens of kilobytes even for a few source lines and
exceeds the default 10 MiB MCP frame for a 300-function source file.

The new optional detail input keeps complete delivery by default. With
detail "summary" the server records the complete analysis Evidence in
the session and returns its inspect_analysis_view summary, whose
parent_evidence_id lets callers page modules, select items, or pass the
retained reference to application workflows. A server without Evidence
retention refuses summary detail with capability_unavailable rather
than returning a summary whose analysis cannot be reached.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:37:37 -07:00
ClaudeandYsopwnable 649661dc8b fix(javascript): stop reading media preload attributes as Electron preloads
HTML audio and video elements have their own `preload` attribute ("none",
"metadata", "auto"). A React renderer compiles `<audio preload="metadata">`
to `jsx("audio", { preload: "metadata" })`, and the `property:preload`
heuristic reported it as an Electron preload script named `metadata`.

Skip `preload` properties in the props object of a call whose first
argument is the static tag `audio` or `video`. The callee is not checked,
because minified element factories have arbitrary names.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XPY2GmufMNGQKoEgRUx1pd
2026-10-10 22:12:56 +08:00
YsopwnableandGitHub e4cc0f09de fix(setup): reject invalid OMP profiles before fallback writes (#1562) 2026-10-10 22:11:14 +08:00
a53689c55d fix(mcp): stop advertising complete Evidence in input examples (#1560)
Hosts forward every tool's input schema to the model on each request.
Seventeen tools advertised a canonical example that embedded a complete
producer Evidence record, up to 22 KB each, accounting for 116 KB of the
450 KB of advertised input schemas.

Advertised examples now show an embedded Evidence record as its exact
retained-evidence reference when the canonical input accepts one, and
omit an example that can only carry inline Evidence. Canonical contract
examples, their executable tests, and validation are unchanged.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:10:38 -07:00
morluto 2d426c924c fix(native): format runtime convention guard 2026-10-10 21:50:55 +08:00
a929c9f714 fix(mobile): bound framework conventions to path segments (#1506)
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 21:42:03 +08:00
YsopwnableandGitHub 8c47a9ce4b fix(javascript): yield during receiver and reference classification (#1557) 2026-10-10 21:40:16 +08:00
de619bd334 fix(ida): canonicalize the headless workspace root before opening (#1481)
On macOS the default workspace root is os.tmpdir() under /var/folders,
and /var is a symlink to /private/var. idalib-mcp reports the canonical
input path from idb_open/idb_list, while REA compared it against the
uncanonicalized private copy with normalize(), so every headless IDA
analysis failed its identity check (surfacing as unreadable_output) and
the spawned idalib worker was never released.

Resolve the workspace root with realpath() when allocating the private
workspace so the input path REA sends already matches what upstream
reports.

Co-authored-by: Xingchuan Ma <xingchuan.ma@msn.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 21:39:33 +08:00
24d9337649 fix(native): preserve compact reference provenance (#1438)
Co-authored-by: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com>
2026-10-10 21:39:28 +08:00
2ec93ba166 docs: celebrate 60,000 GitHub stars 🎉 (#1559)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:31:58 -07:00
afdaf98117 fix(hopper): treat a directory launcher path as missing (#1426)
`HOPPER_LAUNCHER_PATH` availability was decided by an `X_OK` access check
alone, which a searchable directory also passes. Pointing it at the
`Hopper Disassembler.app` bundle instead of its launcher made `rea providers`
report Hopper as available and `rea doctor` report it healthy, while analysis
then failed with an unrelated `version_unresolved` rejection.

Require a regular file in both the provider availability probe and the
doctor executable probe, matching the Ghidra launcher check. A directory now
reports `executable_missing`, and doctor reports `config_drift` with its
existing HOPPER_LAUNCHER_PATH remediation.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 21:31:26 +08:00
944981d8d5 docs: correct stale logging, Ghidra host, and example path statements (#1420)
- CONTRIBUTING: CLI logs go to stderr, not stdout. `createLogger` writes every
  mode to fd 2 so protocol and `--json` stdout stay parseable.
- Get started: Ghidra supports Linux arm64 (`GhidraInstallation` maps
  `linux.arm64`), as installation.md already states.
- Browser guide: drop the caption claiming the hosted request path carries a
  `/rea/` prefix. The guide now targets rea.tools, where the example is served
  at `/examples/notes-web/`, as the evidence table above it shows.
- JavaScript workflows: six CLI commands accept inline JSON or a JSON file,
  not five; `inspect-analysis-view` was added after the sentence was written.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 21:29:31 +08:00
b32a11e1a7 docs: correct host requirements in the README analysis tables (#1422)
- EVM bytecode and recorded crashes: state the Linux x64 host requirement.
  `EvmoleInterfaceProvider` and `PwntoolsDecoder` refuse every other host
  with `capability_unavailable`, but only the neighbouring offline ELF layout
  row said so.
- Translations: Android analysis has supported Windows x64 since 6.2.0
  (#1276), which updated only the English table; 16 translations still said
  Linux/macOS.

Translated cells reuse each README's own wording: the recorded-crash cell
copies that file's ELF-row pwntools phrase, and the EVM and Android cells
follow the construction the same table already uses for host platforms.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 21:29:03 +08:00
0e19db9fce fix(javascript): unify package resolution and resolve exact exports subpaths (#1424)
* fix(javascript): resolve exact package export subpaths

Bare module specifiers with subpaths now resolve against the selected
package's exports map instead of staying external. An exact subpath key
selects its target through the existing condition, array, and null
semantics, and the selected target resolves as one exact file with no
extension or index fallback. A declared exports map encapsulates every
other subpath lookup, and packages without an exports map keep legacy
file and directory-index resolution.

Package-private import aliases remain external pending a separate
increment (#1365).

Verification: npm run check:fast; focused and full
src/application/javascript source tests on Windows;
verify:test-discovery; docs:check. Four pre-existing failures in
JavaScriptFileUrlPaths and JavaScriptModuleSpecifierPaths reproduce on
unmodified main on Windows because their fixtures write file names
containing '?'.

* fix(javascript): unify package path resolution

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 21:26:02 +08:00
YsopwnableandGitHub 66a9ad58fc test(clients): verify native GitHub Copilot CLI integration (#1555) 2026-10-10 21:23:11 +08:00
4b985e5021 fix(artifacts): take nested container families from bytes (#1553)
Inventory gave nested members a ZIP or ASAR family from their path
suffix. Byte classification replaced it only for ZIP magic, so text named
`.apk` or `.asar` stayed a container, and encrypted entries and symlinks
kept the suffix guess. A filesystem `.asar` without an ASAR header failed
the whole inventory as a malformed archive.

Nested ZIP families now follow ZIP magic and ASAR follows its header
pickle, shared with root classification. An unread member named like a
container has an unknown format and a limitation naming the suffix. ASAR
expansion requires the header.

The Android projection adds a limitation when no root AndroidManifest.xml
was observed, and its rejection names the observed root format.

Fixes #1491

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:17:40 -07:00
Rudy CelekliandYsopwnable c8fd2f152b fix(apple): scope keyed archive traversal to the selection
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-10 21:17:35 +08:00
morluto 02ef2b1c41 docs(zh): rename title to 逆向一切 2026-10-10 21:10:30 +08:00
morluto 961471205c fix(docs): format Italian README tables 2026-10-10 21:08:41 +08:00
a6d6e595f3 docs: add Italian (it) README translation (#1455)
* docs: add Italian (it) README translation

Adds README_it.md (full Italian translation of the English README) and updates the language nav bar in all existing READMEs to include the new [Italiano] link, appended at the end of the bar (after Bahasa Indonesia) to match the repository's convention for adding new languages.

Rebuilt on top of current main to resolve the merge conflict caused by the recently added Bahasa Indonesia (README_id.md) translation.

Closes #1453

* docs: fix Italian README showcase anchors

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 21:03:39 +08:00
N0zoM1z0 9ffc6210a4 test(javascript): remove duplicate escaped-receiver cases 2026-10-10 20:53:47 +08:00
GeekwolfandYsopwnable b973b1b1ec test(javascript): cover returned object scaling 2026-10-10 20:53:47 +08:00
GeekwolfandYsopwnable 47947eb01c perf(javascript): index returned object targets 2026-10-10 20:53:47 +08:00
YsopwnableandGitHub 2d99e1e3b2 test(ghidra): preserve Node heap options in adapter verification (#1550) 2026-10-10 20:27:45 +08:00
5d6eeb22fb fix(javascript): yield during the largest AST traversals (#1545)
After #1542 the longest event-loop blocks on large bundles were single AST
traversals inside one analyzer: member-mutation collection with its
fixpoint, static source analysis, and function fingerprints, each about
one second on Obsidian's 3.7 MB app.js.

- traverseJavaScriptAstSteps yields every 1,024 visited nodes with the
  same visit order; traverseJavaScriptAst drains it, so every existing
  caller is unchanged.
- Member mutations, static analysis and fingerprints run as steps. The
  member-mutation fixpoint yields every 64 references, and fingerprints
  yield between callables.
- The now-unused synchronous member-mutation and fingerprint wrappers are
  removed.

Graph IDs and complete result digests match main on three inputs,
including obsidian.asar. Over two runs there, the longest block falls
from about 920 ms to 740 ms, the second from 860 to 595 ms, and blocks
over 250 ms from 27 to 18, with total time within 1.5%.

Refs #1462

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 20:27:41 +08:00
N0zoM1z0 e964a06b83 fix(website): preserve template-owned HTML formatting 2026-10-10 20:27:01 +08:00
N0zoM1z0 5aa30b8b86 chore(website): simplify maintenance and detect documentation drift 2026-10-10 20:27:01 +08:00
YsopwnableandGitHub 8c7569aca7 test(clients): verify native Claude Code integration (#1549) 2026-10-10 20:16:41 +08:00
YsopwnableandGitHub 539a0f95b5 test(clients): verify native OpenCode integration (#1546) 2026-10-10 19:51:30 +08:00
N0zoM1z0 c73cf0ab76 fix(verification): reuse shared output schemas in Electron checks 2026-10-10 19:29:16 +08:00
PeterandYsopwnable aa7008f8a5 fix: reuse validators for identical output schemas 2026-10-10 19:29:16 +08:00
PeterandYsopwnable 1887e1120e fix: reuse validators for identical output schemas 2026-10-10 19:29:16 +08:00
ca7ef69c0c fix(javascript): yield inside semantic analysis and large projection passes (#1542)
* fix(javascript): yield inside semantic analysis and large projection passes

After #1525 the longest event-loop blocks were single stages on very large
files: semantic analysis of Obsidian's 3.7 MB app.js ran 5.8 s in one piece,
and its object projection 1.8 s.

- analyzeParsedJavaScriptSemanticsSteps yields between the analysis phases
  and between the eight derived collectors; the synchronous function drains
  it, so results are unchanged.
- Per-file analysis yields between open-receiver classification and static
  analysis and drives the semantic steps.
- Semantic node creation, definitions and references, and the object and
  frontier passes yield every 64 items. Node creation keeps source order,
  which the per-file node budget depends on.

On obsidian.asar the longest block falls from 5,355 ms to 907 ms with the
same total time (40.6 s to 39.5 s). Graph IDs and complete result digests
match main on five inputs. Remaining blocks up to about 0.9 s are single
AST traversal passes inside the analyzers.

Refs #1462

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(javascript): drop the unused synchronous derived-semantics wrapper

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 04:20:50 -07:00
YsopwnableandGitHub b9c439831d test(clients): verify native Gemini CLI integration (#1541) 2026-10-10 19:17:55 +08:00
YsopwnableandGitHub bace2c5a4f fix(javascript): avoid argument limits when expanding escaped receivers 2026-10-10 19:11:00 +08:00
N0zoM1z0 3cd80cbb88 test(process): prepare SDK validation before cancellation timing 2026-10-10 18:54:57 +08:00
N0zoM1z0 6cd5ea0fb2 fix(process): coalesce delayed capture progress
Retain one pending intermediate observation and drop stale live status before terminal cleanup. Preserve monotonic counts and final delivery while an observer is slow or rejects an update.

Verify the send rate at its controlled-clock owner and lifecycle notification density at the CLI/MCP boundary, where receive timestamps include buffering and scheduling.
2026-10-10 18:54:57 +08:00
Cursor AgentandYsopwnable 706bba6e13 feat(process): report live capture progress through CLI and MCP
Long captures emitted only a final result, so a quiet child looked idle.
Pass the shared rate-limited progress reporter through the capture lifecycle
and report the observed phase, elapsed time, and collected-unit counts.
CLI writes those lines to stderr; MCP forwards them only when the client
supplied a progress token. Final Evidence on stdout keeps its shape.
2026-10-10 18:54:57 +08:00
YsopwnableandGitHub 9964af6b79 fix(ci): synchronize browser fixture events before inspection (#1534) 2026-10-10 18:44:49 +08:00
YsopwnableandGitHub 3059d8a40f test(clients): verify native DeepSeek Harness integration (#1524)
* test(clients): verify native DeepSeek Harness integration

* fix(ci): avoid load-sensitive escape regression timing
2026-10-10 18:29:00 +08:00
86b223b33e fix(setup): follow and validate Hermes sticky profiles (#1528)
* fix: follow Hermes sticky profile for setup paths

* test: cover Hermes sticky profile paths

* fix: honor Hermes profiles with home overrides

* style: format Hermes profile lookup

* style: format Hermes profile tests

* fix(ci): avoid load-sensitive escape regression timing

* fix(setup): validate Hermes sticky profile identity

---------

Co-authored-by: N0zoM1z0 <1705004398@qq.com>
2026-10-10 18:19:51 +08:00
92741187ec docs: list all supported clients in the REA skill (#1523)
docs: include all supported clients in the REA skill

Co-authored-by: Ysopwnable <161784452+N0zoM1z0@users.noreply.github.com>
2026-10-10 18:18:26 +08:00
5fdb0636b4 fix(javascript): yield during per-file projection and graph construction (#1525)
analyze_javascript_application ran several long phases with no event-loop
turn, so MCP ping and cancellation waited: each file's parse, analysis and
semantic projection; building every application node and relationship
before the application graph's first sealing step; and whole-graph schema
parses inside both immutable graph factories.

- Each file runs as steps (parse, static analysis, semantic analysis, then
  each projection pass), driven by the existing time-sliced checkpoint.
- Application graph input construction yields between phases, per module
  link and per file of findings.
- The pipeline transfers its privately built graph inputs to new sealing
  steps that validate the graph's own fields synchronously and elements,
  content checks and the digest in steps. The public copying factories
  keep their synchronous capture.

Results are unchanged: graph IDs and the complete result digest match main
on five inputs including Obsidian's 23 MB obsidian.asar. On the issue's
1,200-function fixture the longest event-loop block falls from about
290 ms to 90 ms, and ping after abort from up to 286 ms to at most 56 ms.
On obsidian.asar it falls from 10.9 s to 5.4 s; the rest is one analyzer
stage of a single very large file.

Refs #1462

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com>
2026-10-10 03:14:37 -07:00
N0zoM1z0 72b3209f3a docs(website): explain autonomy and oracle lessons in Touhou reconstruction 2026-10-10 18:09:13 +08:00
YsopwnableandGitHub f9ce32b474 test(javascript): verify escaped receivers through CLI and MCP 2026-10-10 17:50:36 +08:00
46c9cba03a fix(javascript): expand an escaped receiver's methods once (#1495) (#1517)
Since #1471, escaping an object also escapes every method's results. Each
call through the object escapes it as the receiver, and each escape
re-expanded all of its methods. N methods returning one shared object,
each called once, did N times N work: 2,000 calls took 3.0 s of semantic
analysis and 4,000 took 12 s.

Expansion below references depends only on syntax, so escapes now reuse
it per expression and path. Identifiers that resolve to the same binding
and path collapse to one, because the escape walk treats them alike.
Every escape site is still recorded. The semantic IR is byte-identical
on 50 sources, and the issue's case takes 253 ms at 2,000 and 638 ms at
4,000.

Closes #1495

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 02:16:30 -07:00
b4db35f092 fix: bind identity and coverage to the producing rule (#1513)
* fix: bind identity and coverage to the producing rule

Logical paths, container families, examined bytes, path-segment conventions, destination collisions, file-id leases, Mach-O CPU selection, and firmware cleanup now follow the observation that owns each rule.

* fix: fail unmatched Mach-O slices and keep firmware roots independent

A fat target whose architecture lipo did not list now stops before slice tools run. Chained fixups still count unread LC_DYLD_INFO rebase bytes, and a firmware cleanup failure no longer blocks the next workspace.

* test: cover path identity and runtime families at the projection boundary

NFC joins and segment conventions are now asserted by the path resolver, the Apple projection, and a real APK inventory instead of helper unit tests.

* test: expect unread dyld rebase bytes in the Apple dispatch fixture

The legacy LC_DYLD_INFO fixture keeps a rebase range this reader does not decode, so the public CLI and MCP check now requires that partial coverage beside the bind opcodes.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-10-10 17:14:47 +08:00
7a56fe6260 fix(setup): honor active client configuration and skill roots (#1504)
* refactor(setup): resolve skill destinations per client

* fix(setup): honor active client configuration and skill roots

* fix(setup): validate effective client scopes and Gemini trust

* fix(setup): treat empty OpenCode overrides as unset

An empty OPENCODE_CONFIG_DIR now stays on the XDG directory, and doctor
and setup inspect global OpenCode files when a custom directory is absent.
Uninstall reports one status per client so a missing earlier layer does
not hide a removed registration.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-10-10 17:03:43 +08:00
YsopwnableandGitHub b25922e4e8 test(clients): verify native Qwen Pi and Hermes workflows (#1511) 2026-10-10 16:59:32 +08:00
b6ad1f2c3d feat(mcp): compact input schema profile for size-capped providers (kimi-cli/Moonshot) (#1514)
* feat(mcp): add compact input schema profile for size-capped providers

Moonshot's function-calling API rejects a request while any single tool
parameters schema exceeds its literal serialized size cap, so clients
such as kimi-cli fail every request while the default catalog is
attached (#1484).

Add an opt-in REA_MCP_INPUT_SCHEMA_PROFILE=compact server presentation.
Each advertised input schema is rendered within a 13,312-byte budget,
measured to sit below the observed provider cap: annotation prose
(nested descriptions, examples, defaults, titles) is dropped, repeated
annotation-free subschemas are shared through schema-local $defs/$ref
references the provider validates without expansion, and the three
structurally oversized schemas are advertised in a documented reduced
form. The canonical catalog, tool set, output schemas, and server-side
canonical validation are unchanged; the default full profile is
byte-identical to today's advertisement.

Boundary tests pin every compact schema to the budget, keep them valid
JSON Schema that still accepts every canonical example, hold reduced
presentations at three or fewer, and verify canonical rejection still
guards a permissive advertisement. Verified against the real Moonshot
API through kimi-cli: prompts succeed with the compact catalog attached
where the default catalog fails every request with 400.

* fix(mcp): preserve compact schemas through Kimi conversion

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 16:58:43 +08:00
N0zoM1z0 2b6f14f528 fix(process)!: version literal scenario replacement semantics
Keep caller-selected replacement text literal with a callback, preserving
empty-search positions instead of changing their split/join behavior.
Commit the replacement interpretation for captures using custom patterns so
legacy records cannot report this producer correction as a target change.

BREAKING CHANGE: Captures with custom normalization patterns use
literal-replacements-v1 and cannot be compared with legacy unversioned
pattern captures. Capture both sides with the same replacement semantics;
legacy captures remain readable and captures without patterns are unaffected.
2026-10-10 16:57:06 +08:00
openhandsandYsopwnable f51503ef1c fix(process): normalize scenario replacements literally
capture_process_scenario declares normalization patterns as literal text, but\nreplaceAll expands \$&\, \$\`, and \$1\ in the replacement as a replacement\npattern. A caller normalizing text that contains a dollar sign silently gets\nduplicated, spliced, or dropped content in the recorded Evidence instead of\nthe requested literal replacement.\n\nUse split/join, which is literal on both sides and is already the idiom used\nfor exact-literal scenario rules in browserScenarioNormalization.ts.
2026-10-10 16:57:06 +08:00
2bf812772d fix(apple): bound binary plist expansion before decoding keyed archives (#1515)
inspect_keyed_archive passed caller-selected binary plists straight to
plist.parseBinary, which recurses on every object reference and copies
shared containers. A 484-byte archive of forty nested [next, next] arrays
grew the process past 4 GB until it died with no result, which would also
end an MCP server. A 125-byte self-referencing array overflowed the stack
and was reported as an artifact too large to process.

The iterative reference walk that already guards decode_interface_builder
now runs first, with an 8x keyed-archive decode budget. Over-budget depth
or expansion is a limit; a reference cycle is a malformed archive. Its
"decoder" bounds admit the same layouts plist.parseBinary reads, so
accepted archives stay accepted. Interface Builder behavior is unchanged.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 01:44:46 -07:00
a936303723 fix(json): name a leading byte-order mark in rejected JSON input (#1510)
Strict JSON file inputs reject a leading UTF-8 byte-order mark, but the
diagnostic was the parser's own message, which quotes the invisible U+FEFF
as the unexpected token: Unexpected token '', "{"invento"... is not
valid JSON. Editors such as Windows PowerShell 5.1 write that mark by
default, and nothing in the message showed it.

CLI JSON files (whole and streamed), Evidence and snapshot JSON files, and
process scenario files now report that the input begins with a UTF-8
byte-order mark and how to save it. Acceptance is unchanged.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 01:37:41 -07:00
93ca276921 fix(browser): accept HAR files that begin with a byte-order mark (#1509)
HAR 1.2 lets writers emit a UTF-8 byte-order mark and requires readers to
ignore it. The decoder passed ignoreBOM: true to TextDecoder, which keeps
the mark in the decoded text, so a BOM-prefixed export failed as "HAR is
malformed JSON." Decoding now uses the default, which skips one leading
mark. The artifact digest still covers the selected file bytes.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 01:31:31 -07:00
911323c5dd fix(native): page every retained function dossier collection (#1507)
inspect_analysis_view is the recovery path when an analyze_function
dossier exceeds the MCP response budget, but its native facets covered
only procedure, pseudocode, assembly, callers/callees, references, and
value flow. Basic blocks, comments, unresolved calls, referenced strings
and names, and the native API record could not be read from retained
Evidence at all; basic blocks grow with the function just like assembly.

These are now facets: collections page by rows, and native_api is a
singleton. A dossier without an unresolved_calls record reports "not
recorded" rather than the value-flow failure reason.

Refs #1247 and #1065.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 01:31:15 -07:00
f63f12d8ff docs: align the Indonesian README with the other translations (#1512)
Keep the Bahasa Indonesia onboarding text from #1508, and fix the formatting
that left it outside the shared README layout: drop the leading space, point
in-page links at the translated headings, align the analysis table, and link
Bahasa Indonesia from every language selector.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Dev Cee <24010110166@universitasbumigora.ac.id>
2026-10-10 16:26:52 +08:00
983b070d4d fix(artifacts): record each case collision once at its diverging segment (#1505)
Inventory paired every path under one case spelling with every path under
each other spelling and listed all of them on each occurrence. An archive
with Foo/ and foo/ subtrees of N files each produced N-entry lists on 2N
occurrences: 4,000 such ZIP members yielded a 120 MB inspect_artifact
result and close to 1 GB of memory. The trie walks also recursed once per
path component, so a ZIP name with tens of thousands of components threw
RangeError.

A collision is now recorded at the segment where spellings diverge and
shared down that subtree by an iterative walk. Each occurrence names the
colliding prefix and the first other spelling, plus a count of further
spellings, each of which is its own occurrence.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 01:16:16 -07:00
9e22da845b feat(setup): add native Pi client support (#1376)
* feat(setup): add native Pi client support

* fix(setup): isolate invalid Pi agent directory overrides

Keep malformed Pi path evidence on its client entry so unrelated selected clients can complete setup and doctor. Preserve explicit Pi rejection and block filesystem operations rather than falling back to another directory.

* fix(setup): parse Pi configuration as strict JSON

Pi's installed MCP loader reads mcp.json with a bare JSON.parse and no
BOM tolerance, so comments, trailing commas, a BOM, or an empty existing
file yield loader errors and no servers. Parsing the Pi dialect with
objectSchema.parse(JSON.parse(text)) before the shared empty/JSONC
shortcut rejects those files at every mutation boundary instead of
reporting configured registrations Pi cannot load. A missing file still
initializes a fresh strict-JSON document, other dialects keep their
JSONC/BOM/empty tolerance, and malformed files are never rewritten.

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 16:10:39 +08:00
f970b886aa feat: add Hermes as a supported MCP client (#1403)
* feat: add Hermes as a supported MCP client

Hermes Agent reads stdio MCP servers from `mcp_servers.<name>` in
`config.yaml`. REA had no Hermes client, so setup could not register it and
Hermes users had to wire the server up by hand.

- SupportedClients: add the `hermes` format and client definition, resolving
  the config path from HERMES_HOME, else the platform default that Hermes's own
  resolver uses (LOCALAPPDATA/hermes on Windows, ~/.hermes elsewhere), including
  HERMES_DATA_DIR_SUFFIX.
- ClientConfigurationDocument: parse and serialize Hermes YAML, upserting the
  rea entry into the parsed document so user comments and unrelated settings are
  preserved; emit `enabled: true` since Hermes connects entries unless disabled.
- ClientRegistrationStatus: forward the Hermes location variables so status
  checks resolve the same path as setup.
- Tests: cover path resolution on both platforms and the register/read/uninstall
  round trip, and clear the Hermes location variables between tests.

- delilah 🌸

* docs: document the Hermes client and its config path

- delilah 🌸

* refactor(setup): resolve skill destinations per client

* fix(setup): install Hermes skills in the active profile

* fix(setup): identify each client skill action uniquely

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 16:03:25 +08:00
a0e5e9db2b perf(artifacts)!: name each edge's child through its occurrence (#1493)
Every inventory edge is created from one occurrence and copied that
occurrence's artifact_id and logical_path as child_artifact_id and
logical_path. Edges now keep the occurrence_id reference alone. Edge IDs
still hash the same child and path, read from the occurrence, so they are
unchanged; validation and artifact comparison read the occurrence too.

inspect_artifact output: Transmission.app 1.10 MB to 0.97 MB, Visual
Studio Code.app 15.37 MB to 13.48 MB.

BREAKING CHANGE: Artifact inventory edges no longer include
child_artifact_id or logical_path; read them from the occurrence named by
occurrence_id. The graph commitment changes, so inventory Evidence
recorded by earlier versions no longer validates.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:58:05 -07:00
1f692c83e2 perf(artifacts): stop repeating every artifact path as Evidence locations (#1492)
inventory_artifact, inspect_artifact, and extract_artifact copied each
occurrence or extracted file path into Evidence locations, although the
result already names every one. inspect_artifact did so twice, in its own
Evidence and in the nested inventory Evidence. Like other whole-target
Evidence, these now report no locations.

Visual Studio Code.app: inspect_artifact 15.37 MB to 13.07 MB,
extract_artifact 1.40 MB to 1.06 MB.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:47:51 -07:00
YsopwnableandGitHub 782e0147cd fix(javascript): retain returned-reference mutation uncertainty (#1471) 2026-10-10 15:46:24 +08:00
9defed9725 perf(mcp): stop advertising placeholder input descriptions (#1479)
Input schema presentation gave every undescribed property a generic
"Value for <name>." sentence. That only restates the property name, yet
it covered 1,958 properties: 70 KB of the 522 KB of advertised input
schemas that clients load into model context. Authored descriptions,
referenced descriptions, and the name-pattern sentences that add meaning
(maximums, digests, paths, Evidence IDs) remain; other properties now
advertise no description.

The schema validity test now rejects placeholder descriptions instead of
requiring a description on every property.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:32:29 -07:00
5f6bb7a5ba perf(apple): state each NIB object's class, label, and ID once (#1477)
The NIBArchive projection synthesizes customClass, label, and objectID so
its records share the ibtool dictionary parser. The parser then returned
those values as class_name, name, and the object ID, and the graph node
kept the synthesized copies in attributes as well. Attributes now omit a
key whose value its canonical field already carries; differing authored
values stay. Transmission.app decode_interface_builder output shrinks
from 6.45 MB to 6.14 MB.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:31:00 -07:00
morluto 2596f8da14 test(android): retry verified cleanup during fixture teardown 2026-10-10 15:29:42 +08:00
morluto b12d0c6361 test(artifacts): respect destination filesystem case sensitivity 2026-10-10 15:29:42 +08:00
N0zoM1z0 cbcba2902d docs(website): align Blog community links with the site 2026-10-10 15:28:13 +08:00
N0zoM1z0 07d416505c docs(website): finalize the Touhou essay for publication 2026-10-10 15:28:13 +08:00
N0zoM1z0 3ea0233342 docs(website): simplify the Blog introduction 2026-10-10 15:28:13 +08:00
N0zoM1z0 cf6957e796 feat(website): link the Blog from the homepage introduction 2026-10-10 15:28:13 +08:00
N0zoM1z0 ed200a2302 docs(website): emphasize the reconstruction essay takeaways 2026-10-10 15:28:13 +08:00
N0zoM1z0 7df2050606 docs(website): write the Touhou reconstruction essay 2026-10-10 15:28:13 +08:00
N0zoM1z0 130ffdf6bc docs(website): outline the Touhou reconstruction workflow 2026-10-10 15:28:13 +08:00
N0zoM1z0 b09d02d93c feat(website): add a blog for methods and project notes 2026-10-10 15:28:13 +08:00
1f0775684b fix(artifacts): keep case-distinct archive names in inventory (#1480)
ZIP member names are case-sensitive. Inventory was folding them with a
filesystem case rule, so shrunk APKs never became evidence for the Android
application graph. Logical registration now keeps both spellings and records
an English Unicode case-folding limitation. Extraction fails only when the
destination directory already holds the other spelling.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-10-10 15:21:16 +08:00
7296f2b5bf perf(javascript)!: stop repeating the semantic identifier strategy per fact (#1474)
Every semantic graph node and relation carried an identifier_strategy
object whose schema admits exactly one value per record type. The
constant made up about 9% of analyze_javascript_application output
(Obsidian app.asar: 12.04 MB to 10.96 MB), and semantic traces repeated
it on every returned fact.

The node_id and relation_id schema descriptions now state how each
identifier is derived.

BREAKING CHANGE: Semantic graph nodes and relations no longer include
identifier_strategy, and relation IDs no longer hash that constant.
Evidence recorded by earlier versions does not validate against the new
semantic graph schema.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:13:34 -07:00
3c7b176a3d perf(artifacts): deliver the inspected artifact graph once (#1473)
inspect_artifact nested the complete inventory Evidence and then restated
every artifact node and occurrence as an observation and every edge as a
derived relationship. No caller reads those copies; comparison and tests
use the nested inventory Evidence. On Transmission.app the result shrinks
from 2.46 MB to 1.10 MB.

Observations keep the root manifest and integrity findings.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:12:17 -07:00
aa23ec883f feat(clients): register Qwen Code during setup (#1415)
* feat(clients): register Qwen Code during setup

* fix(clients): honor Qwen home and shared skill discovery

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 15:12:09 +08:00
keemsisiandGitHub 934ffd28d1 perf(javascript): derive the application graph ID once
createJavaScriptApplicationGraph hashed the whole graph to derive its
graph_id, then parsed it with the public schema, whose invariant check
hashed the same content again to verify that ID. Validate the content
with every other invariant first, then derive graph_id once from the
validated copy. The public schema still verifies graph_id for stored
and untrusted graphs, and created graphs are unchanged.
2026-10-10 15:09:18 +08:00
79f6756239 docs(website): link the Discord community and REA on X (#1469)
Add an X link beside the GitHub and Discord header icons on every content
page, name the footer links "Join the community" and "Follow us on X", and
close the homepage with a "Join the community" section.

On narrow screens, pad the footer so the floating Top link no longer
covers its last row of links.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:00:09 +08:00
YsopwnableandGitHub 78e1308f49 docs(process): clarify normalized terminal line representation 2026-10-10 14:58:15 +08:00
YsopwnableandGitHub 4e3d335439 test(android): retain incomplete cleanup failure reasons (#1443)
Include the full stop disposition in the fixture assertion message, so incomplete owned teardown retains its typed reason in Vitest failure reporters. Preserve the existing cleanup requirement without retries or relaxed ownership checks.

Seven process-boundary tests, full serial typecheck/lint/duplication/format checks, and 19 final-head CI checks pass after integrating the combined-main fixture fix. A controlled failure-rendering probe verifies that the explicit message preserves the reason. The original CI cleanup failure remains unreproduced; this is diagnostic work with a synthetic JADX producer, not a root-cause or real-engine fix.

Refs #1441, #1446, #1448, #1065.
2026-10-10 14:37:49 +08:00
YsopwnableandGitHub ea92328775 fix(mcp): validate doctor probe against its discovered output contract (#1461)
Validate the target-free probe against the named definition discovered from the complete production catalog. Preserve initialized server and inventory observations when the SDK rejects the probe, and retain the schema failure reason, absolute deadline and owned-child cleanup.

The negative stdio replay regression fails on original main and passes the fix; actual production-boundary fault injection confirms rejection. Nine doctor/help tests, serial full static checks and real small-target CLI/MCP parity pass. Successful doctor reports remain byte-identical. No performance or model-token reduction is claimed.

Closes #1454. Refs #1065, #723, #1433.
2026-10-10 14:33:57 +08:00
morlutoandGitHub 28d3cb545c Merge pull request #1463 from morluto/codex/fix-skill-source-discovery
fix(skills): expose authored skill to repository discovery
2026-10-10 14:28:42 +08:00
b118f04492 perf(apple): stop repeating the archive path in Interface Builder evidence (#1460)
Every Interface Builder node and edge evidence record prefixed its
description with the archive's relative path, which artifact_path in the
same record already states. Bundles carry thousands of objects across
localized nibs, so the repeated path made up 6-10% of
decode_interface_builder output (XLD: 7.38 MB to 6.62 MB).

Descriptions now name only the decoded item, such as "object 81" or
"outlet o_quality".

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 23:21:24 -07:00
ef96657d6b perf(javascript): hash each semantic evidence context once (#1457)
The semantic graph's evidence-context registry canonicalized the full
provenance context three times for every node, relation, unknown and
fingerprint: once to hash its ID and twice more to compare against the
stored row. A file has only a few distinct contexts, so nearly all of
that work repeated a known answer.

Interning now keys contexts by their canonical text. Each fact
canonicalizes once, and only a new context is hashed and checked for a
digest collision. IDs and output are unchanged; Obsidian's 334 MB
Evidence is byte-identical and analysis drops from about 47.0 s to
44.4 s.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 23:21:07 -07:00
morluto 696fb834b8 fix(skills): expose authored skill to repository discovery 2026-10-10 14:20:22 +08:00
2781cad201 perf(process): stop padding rendered terminal lines to full width (#1450)
Rendered frames padded every visible row with trailing spaces to the
terminal width. Blank rows cost a full row each and every frame repeats
them, so the padding made up 14-39% of capture Evidence (2 KB of sparse
output produced 228 KB). The padding carried no information: columns is
recorded and serialized_state keeps the exact terminal state.

Lines are now trimmed after normalization, so line.padEnd(columns)
restores the previous value. The comparison contract commits
rendered_line_format so older padded captures do not compare as the
same contract.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 23:18:13 -07:00
YsopwnableandGitHub c89c8f5318 docs(mcp): record real Windows first-query recovery 2026-10-10 14:05:56 +08:00
1ec490f361 fix(javascript): stop replaying earlier writes for each object property write
Repeated property writes to one object made member-mutation collection
cubic. Each write evaluated its target binding to rule out a primitive,
and every evaluation folded all earlier mutation paths, copying every
slot once per path. 2,000 writes to one object took 27 s and 4,000 took
203 s.

- A recorded write always leaves a non-primitive binding value, so only
  the first write to a binding needs the primitive check.
- Apply mutation paths per slot in one pass with the same ordering
  semantics instead of one full slot copy per path.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com>
2026-10-10 14:04:31 +08:00
YsopwnableandGitHub 66863b609f test(javascript): reuse comparison node fixtures
Use the established typed graph fixture constructor while retaining right-hand comparison provenance assertions. Restore the unchanged duplicate-code gate on combined main.

Closes #1446. Refs #1434, #1443, #1065.
2026-10-10 14:02:02 +08:00
morlutoandGitHub 817efaca9a Merge pull request #1391 from marnixpluim/fix/electron-import-aliases
fix(javascript): recognize Electron APIs through renamed bindings
2026-10-10 13:57:24 +08:00
morluto 0d2082d36b fix(javascript): recognize unchanged var and let Electron aliases 2026-10-10 13:56:40 +08:00
morlutoandGitHub f1231d4a2c Merge pull request #1382 from BaaRai/fix/cross-branch-multiblock-callee
fix(ghidra): keep the cross-format branch callee multi-block
2026-10-10 13:50:51 +08:00
morlutoandGitHub a957f397ad Merge pull request #1303 from kvalls/codex/windows-ghidra-native-dlls
feat(ghidra): support native PE DLLs on Windows
2026-10-10 13:50:11 +08:00
YsopwnableandGitHub e09cfe9b59 fix(javascript): invalidate references stored through property targets (#1445)
* fix(javascript): invalidate references stored through property targets

* refactor(javascript): share rest keys and return-shape fixtures
2026-10-10 13:47:15 +08:00
morluto ea1dbda1c7 test(ghidra): share result projection client setup 2026-10-10 13:47:06 +08:00
morluto 7633dd8d5d fix(ghidra): publish Windows verification success after cleanup 2026-10-10 13:43:01 +08:00
morluto 941dc425ca chore: merge main into Windows DLL support branch 2026-10-10 13:42:54 +08:00
33b9b31a6f perf(javascript): index change-graph nodes once per comparison
Resolve each compared graph node through a per-side index while preserving right-hand evidence selection and complete comparison results.

Refs #1065.

Co-authored-by: keemsisi <7439375+keemsisi@users.noreply.github.com>
2026-10-10 13:21:13 +08:00
Kaoru0822andGitHub eeb83f6581 perf(cli): defer Playwright and isomorphic-git until a command needs them
Load browser composition after CLI scenario validation and load Git support only for local reference trees with Git metadata. Preserve default outputs and actual command behavior.

Refs #1065.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-10 13:16:44 +08:00
YsopwnableandGitHub bb6fa1c6f5 docs(process): verify independent full-report hashing budgets (#1440) 2026-10-10 13:13:05 +08:00
YsopwnableandGitHub ce16f7bc95 test(native): verify macOS provenance through real CLI and MCP
Verify five native operations through the public CLI and real SDK stdio MCP using a source-built macOS fixture. Retain normalized provenance, response parity and unchanged input bytes.

Refs #1430, #1065, #723.
2026-10-10 13:05:12 +08:00
YsopwnableandGitHub 0a14ca41b4 fix(javascript): preserve effects through yielded array references (#1437) 2026-10-10 13:00:11 +08:00
YsopwnableandGitHub dc5af6d68f perf(mcp): reuse output validators across catalog refreshes (#1433)
Advertise content- and dialect-bound identities for self-contained output schemas so the SDK can reuse unchanged Ajv validators after complete tools/list refreshes. Preserve explicit IDs and relative reference bases.

Verify changed schemas, availability transitions, reconnects, numeric and selector constraints, explicit IDs, relative references, and advertised dialects through the pinned SDK boundaries.

Refs #1065, #723
2026-10-10 12:49:09 +08:00
0b9815b6e7 docs(skill): save CLI application Evidence and read a summary view (#1429)
The skill's CLI fallback printed the complete application Evidence to
stdout. A real ASAR produces hundreds of megabytes (334 MB for Obsidian),
which an agent then reads into its context. Save the Evidence to a file
and project a summary or module page with inspect-analysis-view instead.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 21:38:52 -07:00
6375ccaf04 perf(native): record macOS command provenance once in its Evidence (#1430)
inspect_macho, inspect_signature, inspect_plist, list_architectures and
demangle_swift already return their command provenance inside the
normalized result. The provider also copied the same array into
raw_result, so every response carried it twice. raw_result now stays
null, as docs/mcp-contracts.md describes for results without a distinct
provider representation.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 21:35:50 -07:00
c29931ce81 fix(javascript): scan direct returns without recursive stack growth
Use the shared AST child enumeration with an explicit stack, preserving return order and nested callable boundaries.

Refs #1065.

Co-authored-by: rudycelekli <47457359+rudycelekli@users.noreply.github.com>
Co-authored-by: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com>
2026-10-10 12:25:00 +08:00
YsopwnableandGitHub f4a0c1ce95 fix(javascript)!: avoid event payload copies in graph metadata (#1427)
Share the canonical string identity rule with endpoint projection, scope event keys to each emitter, and keep complete event/listener names in properties. Verify real CLI and stdio MCP with large names, registration/removal, distinct emitters, exact name seeds, reserved-prefix values, and unresolved dynamic names.

BREAKING CHANGE: New analyses use digest-based IDs for long or reserved-prefix event names and shorter event/listener display labels. Select IDs from the parent graph and read exact names from event_name properties. Stored graphs and their original IDs remain accepted for semantic tracing.
2026-10-10 12:20:05 +08:00
a9ee2360fd feat(native): inspect oversized retained function dossiers via bounded views
Add caller-selected native dossier facets with preserved Evidence identity, provenance, unknowns and transport recovery.

Refs #1247 and #1065.

Co-authored-by: jhuang-tw <77732008+jhuang-tw@users.noreply.github.com>
Co-authored-by: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com>
2026-10-10 12:18:50 +08:00
YsopwnableandGitHub 4d95f2b2e7 fix(validation): retain unmatched union correction details
Preserve actionable field paths and schema-declared variants for unknown or missing discriminators.

Closes #1421. Refs #1065.
2026-10-10 12:15:11 +08:00
28595276fa fix(javascript): bound member-mutation paths through reassignment loops
Fixes #1401. Refs #1065. Preserve exact member facts and equal-depth write effects while bounding the observed reassignment-loop expansion.

Validated with the JavaScript semantic/application suite, focused alias regressions, full static checks, real compiled CLI and SDK MCP Notion workflows, and all 20 checks on the final PR head.

Co-Authored-By: Marnix Pluim <286664873+marnixpluim@users.noreply.github.com>
Co-Authored-By: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-10 12:03:13 +08:00
YsopwnableandGitHub 98022a8352 fix(javascript)!: avoid endpoint payload copies in graph metadata (#1423)
Keep exact endpoint observations and request properties while using compact display labels and collision-safe canonical value digests for long artifact-local endpoint keys. Verify real CLI/stdio MCP tracing and version comparison without truncating evidence.

BREAKING CHANGE: New analyses use compact endpoint labels and digest-based IDs for long or reserved-prefix endpoint keys. Select IDs from the parent graph and read full values from endpoint properties. Previously stored graphs retain their original identities and remain valid workflow inputs.
2026-10-10 12:02:24 +08:00
YsopwnableandGitHub 81cdafc132 docs: celebrate 50,000 GitHub stars 🎉 2026-10-10 03:45:42 +00:00
YsopwnableandGitHub 4d8ef3f350 perf(javascript): aggregate semantic family coverage once (#1410)
Reduce repeated semantic relation and unknown family scans while preserving exact complete Evidence and coverage.
2026-10-10 11:30:42 +08:00
ca3131b36c perf(cli): write compact JSON when output is not a terminal (#1413)
`--json` / `--format json` always indented its streamed result. Agents and
scripts read REA through pipes and redirects, where indentation carries no
information: on real application results it added 16-45% model tokens
(o200k proxy) and 25-73% bytes. The skill's CLI fallback uses `--json`.

Indent only when stdout is a TTY, as `gh --json` does; piped or redirected
JSON is compact. The JSON value, `jsonl`, `--filter-output`,
`--full-output` and the token-window paths are unchanged. `jq .` restores
indentation for files.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:29:48 -07:00
YsopwnableandGitHub de8fc67195 fix(javascript): retain shorter literal metadata encodings (#1408)
Choose the shorter complete JSON or digest key and string display label.
Short values keep their existing identities and labels, while large values
retain the payload-copy reduction without an arbitrary truncation limit.
2026-10-10 11:23:47 +08:00
YsopwnableandGitHub 8550913cda fix(javascript)!: stop copying literals into semantic metadata (#1407)
Commit literal values with canonical JSON SHA-256 in semantic role keys
and use a type label for strings. Preserve complete values, provenance and
literal queries while avoiding two payload copies in each string node.

Verify real compiled CLI/default stdio MCP, typed union seeds, empty
strings and trace continuation with a large source-owned fixture.

Refs #723

BREAKING CHANGE: Newly produced semantic literal node IDs use
value-sha256 role keys, and string labels read "string literal". Read exact
values from properties.value and obtain node IDs from the selected parent
graph. Previously stored Evidence and its original IDs remain valid.
2026-10-09 20:00:53 -07:00
1f0f728c63 perf(hopper): stop repeating Hopper replies as raw_result (#1405)
HopperProvider passed the bridge reply as rawResult and, for every
operation except address_to_file_offset, the same object as the result.
Every Hopper Evidence record (decompilation, procedure and string
listings, xrefs, ...) therefore carried its complete result twice, and
an MCP response four times counting its text copy.

raw_result is now null unless REA transformed the reply, which only the
file-offset mapping does; that case keeps Hopper's original reply.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:00:35 -07:00
7623e21ff0 perf(native): record pwntools diagnostics once in their Evidence (#1404)
inspect_binary_layout and inspect_recorded_crash passed the decoded report
as both result and rawResult, so every Evidence record carried the whole
report twice (and an MCP response four times, counting its text copy).
The decoded report is the only representation, so raw_result is now null,
as for other single-representation operations.

The real pwntools verifiers asserted the duplicate; they now assert null.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:00:11 -07:00
499e2f54ef perf(evidence): stop copying normalized results into raw_result (#1402)
createAnalysisExecution defaulted an omitted rawResult to a second
complete copy of the result. Every caller that had no distinct provider
representation therefore doubled its Evidence: decode_interface_builder,
inspect_keyed_archive, inspect_asset_catalog, trace_dylib_resolution,
inspect_native_dispatch_metadata, observe_native_calls,
observe_native_ui/capture_native_ui_scenario (including screenshots), and
small Ghidra/IDA lifecycle records. Sibling operations of the same
providers already recorded null.

An omitted rawResult now records null. Normalized results are unchanged.
MCP responses repeat Evidence in text and structured content, so each
response and its share of the 10 MiB transport budget shrink by the same
half; e.g. trace_dylib_resolution on a real app bundle drops from
3,217,119 to 1,612,524 bytes per representation.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 19:52:54 -07:00
6875d4a64c fix(cli): accept JSON files for web capture and screenshot comparisons (#1397)
compare-web-captures and compare-web-screenshots parsed their arguments as
inline JSON only, unlike every other JSON-input command. Screenshot
artifacts and scenario captures embed base64 PNG bytes, so a typical
viewport screenshot exceeds the command-line length limit (128 KiB per
argument on Linux, 1 MiB total on macOS) and could not be compared from
the CLI at all, while MCP accepts it. A file path was reported as
malformed JSON, and screenshot schema failures returned no issues.

Each argument now accepts inline JSON or a JSON file path through
parseCliJsonInput; file failures keep its path diagnostics, malformed
inline JSON keeps the field issue, and screenshot validation reports
projected schema issues. The tests share one CLI JSON process fixture.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 19:29:42 -07:00
2b6e9ec03f fix(browser): classify selected web trace file failures by cause (#1396)
trace_web_module_imports and trace_web_source_location reported a missing
or non-file manifest, source map or import map as artifact_operation_failed
("Artifact could not be read or written" / "unsafe or conflicting internal
path"). These are caller selections: report ENOENT/ENOTDIR and non-regular
files as invalid input on the selected field, and EACCES/EPERM as a host
access denial. A missing manifest-derived source file stays an artifact fault.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 19:29:31 -07:00
498cec042a fix(cli): stop advertising multi-letter single-dash option aliases (#1395)
Incur's `alias` map registers one-letter short flags and already accepts
kebab-case spellings of camelCase options. Twenty options registered their
kebab-case long name as an "alias", so help and completions advertised
flags such as `-case-sensitive` and `-relative-path` that the parser reads
as stacked short flags and rejects with "Unknown flag: -c".

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 19:29:20 -07:00
Minghang ChamlingandGitHub 5fc4d792ca fix(javascript): handle oversized inline source maps (#1386)
* fix(javascript): handle oversized inline source maps

* fix(javascript): avoid source map directive regex overflow
2026-10-10 10:24:38 +08:00
Claude e4a8e0b728 fix(javascript): recognize Electron APIs through renamed bindings
Electron recognition matched callee spellings, so a bundler rename such as
esbuild's `import { ipcMain as ipcMain2 } from "electron"`, or a destructured
`const { contextBridge: bridge } = require("electron")`, hid every IPC
handler, BrowserWindow, contextBridge and utility process behind it.

Resolve each call and construction root lexically to its Electron import or
require origin, and classify the callee under that export's name. Shadowed
locals keep their own meaning.

On Hermes Desktop v0.21.6, whose main process is one esbuild ESM bundle,
recognized main IPC handlers rise from 1 to 204, BrowserWindow constructions
from 0 to 11, and paired renderer transmissions from 1 to 201.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XPY2GmufMNGQKoEgRUx1pd
2026-10-10 00:44:32 +00:00
GRAB Racem e17290cd2a ci: re-run the suite on the corrected main checkpoint
b8a8190b restored the guarded-mutation uncertainty the failing test
encodes, so the shard should pass against the new merge base.
2026-10-10 02:34:52 +02:00
GRAB Racem 40f632a155 ci: re-run the suite after the main-branch shard flake
The failed shard is the JavaScriptSemanticGraphBuilder short-circuit
mutation test, which also failed on main run 38003459598 at the same
base commit (08ec2bf8) before this branch started CI, and passed on
main run 38003459600 minutes later at the same commit.
2026-10-10 02:06:15 +02:00
morluto 7aa4d768eb chore(release): sync corrected 6.3 checkpoint 2026-10-10 07:57:04 +08:00
morlutoandGitHub 74cf9e1401 Merge pull request #1383 from morluto/release-please--branches--release/6.3.0--components--rea-agents
chore(release/6.3.0): release rea-agents 6.3.0
2026-10-10 07:56:11 +08:00
morluto bf58eac4ef docs(release): restore complete 6.3 migration and ancestry notes 2026-10-10 07:42:17 +08:00
github-actions[bot]andGitHub 565f2efa03 chore(release/6.3.0): release rea-agents 6.3.0 2026-10-09 23:41:35 +00:00
morluto b8a8190b2f fix(javascript): retain conditional mutation ordering uncertainty 2026-10-10 07:40:25 +08:00
GRAB Racem e10c934d5a fix(ghidra): keep the cross-format branch callee multi-block
The cross-format oracle requires a callee whose recovered control flow
has more than one basic block, and rea_cross_branch provided it through
a symmetric if/else of tail calls. Clang 21 folds that shape into a
conditional negate plus one tail branch, a single basic block, so the
lane rejected a correct Ghidra analysis of the fixture.

Give the branch a loop whose trip count depends on a volatile global:
no compiler can eliminate the backedge, and the callee stays multi-block
at every optimization level on every toolchain.
2026-10-10 01:36:11 +02:00
github-actions[bot]GitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
08ec2bf82f chore(main): release rea-agents 6.3.0 (#1341)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-10-10 07:14:55 +08:00
morluto 001851fde6 fix(javascript): preserve capture-time guards and ordering 2026-10-10 07:13:48 +08:00
39dabd0608 fix(mcp): advertise object roots for union input schemas (#1373)
* fix(mcp): advertise object roots for union input schemas

Anthropic tool input schemas reject anyOf, oneOf, and allOf at the root.
Since 63bf9140 removed root flattening, compare_web_captures,
inspect_web_page, inspect_electron_page, and
project_managed_application_graph advertised root unions: Claude Desktop
disabled compare_web_captures and Claude Code exposed the tools without
parameters.

Present a root union of plain-reference object branches as one strict
object with the union of properties, shared required fields, a
minProperties bound, and a description of the accepted input groups. The
canonical Zod union still validates every call, so mixed input groups are
rejected before the handler runs. Branches whose reference siblings cannot
be merged keep their root alternatives.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(browser): keep comparison input boundary within lint limits

Express advertised and runtime expectations as one case table so the
boundary test stays under the 150-line function limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(mcp): preserve input group dependencies in object schemas

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 07:03:12 +08:00
BaaRaiandGitHub 73a664bc78 fix(ghidra): verify dense jump tables on an optimized fixture (#1374)
The dense jump-table oracles (inspect-native-api CLI and the
analyze_function dossier) ran against the -O0 debug fixture, which
assumes the host compiler lowers dense switches to tables at -O0. GCC 16
and later expand them as compare chains instead, so on those hosts the
lane rejected a correct provider and Ghidra build with empty
jump_tables.

Build the same inventory source once more at -O2 as a dedicated
jump-table variant, run both strict dense oracles there, and keep the
debug dossier at its complete generic shape. The dedicated switch lane
already compiles at -O2 for the same reason.
2026-10-10 06:58:29 +08:00
355a292198 fix(javascript): preserve uncertainty after references escape to calls (#1292)
* fix(javascript): preserve uncertainty after references escape to calls

* fix(javascript): track iterator root escapes and preserve static captures

* fix(javascript): scope comparison unknowns to their evidence

* fix(javascript): track parameter origins at function body entry

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 06:53:42 +08:00
Akshit KhokhaniandGitHub d0e606930a fix(javascript): honor module-sync package exports (#1361) 2026-10-10 06:49:43 +08:00
You WishandGitHub a9f5dad5a8 fix(javascript): resolve exported callables through lexical bindings (#1351)
* fix(javascript): resolve exported callables through lexical bindings

* fix(javascript): preserve export scope and hoisted writes

* test(javascript): consolidate export binding assertions

* fix(javascript): account for skipped initializers and loop binding writes

* fix(javascript): preserve parameters copied into body variables
2026-10-10 06:39:56 +08:00
You WishandGitHub 1c0cc8a675 fix(snapshot): preserve complete investigation revision histories (#1354)
Select residual unknown histories as complete units and retain referenced registry mutation Evidence regardless of the active target at edit time. Prune incompatible dependency histories atomically instead of retaining stale dispositions.

Verify public MCP save/read/reopen for verified, withdrawn, and out-of-scope resolutions, and document target scope rules.
2026-10-10 06:39:29 +08:00
f504c2a351 fix(javascript): decline source-map UNC references with an unusable host (#1372)
* fix(javascript): decline source-map UNC references with an unusable host

A source map can name a Windows share whose host a file URL cannot carry,
such as `\\bad host\share\a.js`. On the Node builds `engines` admits,
`pathToFileURL(path, { windows: true })` fails a native assertion and calls
`abort()` on Node 22.19-22.22, 24.11-24.15 and 26.0, so the process dies
with exit 134 instead of declining the reference. Node 22.23 and 24.16 raise
`ERR_INVALID_URL` instead, and older builds silently drop the host, so the
same reference resolves three different ways depending on the runtime.

Validate the UNC host before handing the path to Node. A host carrying a
forbidden host code point, a percent escape or nothing at all now resolves as
`unresolved` on every admitted build, and `npm test` passes the existing
`\\bad host\share\a.js` row everywhere. Well-formed UNC hosts and
drive-letter paths are untouched.

* fix(javascript): validate UNC hosts through IDNA before conversion

Reject Unicode source-map UNC hosts that URL/IDNA processing cannot use or normalizes to an empty hostname before calling Windows pathToFileURL. Keep the original source identity and preserve usable normalized hosts.

Exercise the built reference resolver in owned subprocesses, including U+00AD and U+200C as source names and source roots. The original PR implementation aborts under Node 22.22.2; the new regression isolates those signals from the test runner. Add this test to the existing Node 22 Windows CI step.

Validation: 64 focused tests pass on Node 22.22.2 and 24.18.0; npm run check and test discovery pass. Local verification ran on macOS; Windows verification remains with CI.

---------

Co-authored-by: Yi-111-a <yi-111-a@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 06:38:47 +08:00
You WishandGitHub f91f2798b4 fix(process): keep unobserved file contents unknown (#1358) 2026-10-10 06:36:35 +08:00
keemsisiandGitHub 037709a52c perf(javascript): validate the version change graph once (#1370)
compareJavaScriptApplicationVersions built the change graph with
createJavaScriptApplicationGraph, which validates it and re-derives
every node, observation, edge and graph ID, then parsed the result
with a schema that embeds the full graph schema, repeating all of
that work. Seal the change graph with the owned immutable factory and
accept that exact sealed graph in the result parse, as owned analysis
results already do. Items, coverage and the public result schema are
unchanged; output is byte-identical.
2026-10-10 06:34:21 +08:00
morluto 810107a2ad fix(cli): stream JSON results at the shared command boundary
Route ordinary CLI results through the bounded JSON writer after command registration, including managed member inspection. Remove JavaScript-specific output plumbing while preserving filters, envelopes, cancellation, and failure exits.

Measure formatted UTF-16 expansion before Incur token counting and return resource_constraint above the runtime string limit, with recovery guidance.

Validate output above the real V8 string limit by SHA-256 and exercise the compiled managed provider. Clean-worktree validation: npm run check; 76 focused tests passed, with 2 optional-provider skips; test discovery passed.

Fixes #1371.
2026-10-10 06:23:26 +08:00
morluto ecc67cab2d ci: enforce architecture guards with portable checkout paths 2026-10-10 06:20:28 +08:00
morluto 4bcea1aa76 fix(javascript): retain array identity after length mutations
Keep unknown element coverage on arrays whose length may have changed, preserving intrinsic length presence and subsequent slot mutations through semantic graph and export-return consumers.
2026-10-10 06:20:28 +08:00
morluto 4951a897c5 fix(browser)!: preserve payload shapes and WebMCP declarations
Retain primitive and nested array types with typed paths, and compare only mutually observed body shapes while preserving selected coverage uncertainty. Return full untrusted WebMCP input declarations with canonical digests, without resolving references or invoking tools.

BREAKING CHANGE: JSON shape paths now contain typed property and array-element segments. WebMCP input_schema_shape is replaced by input_schema and input_schema_sha256, retaining declared examples and defaults.
2026-10-10 06:20:28 +08:00
morluto d79317cda0 fix(artifacts): bind ASAR interpretation to owned snapshots
Verify captured container bytes against their inventoried digest before listing or reading packed members. Isolate per-reader ASAR metadata, preserve original unpacked companions, and retain complete inventories when snapshot cleanup fails.
2026-10-10 06:20:28 +08:00
BaaRaiandGitHub bf934d5592 fix(hopper): probe interior navigation from multi-byte instructions (#1285)
The real-Hopper navigation probe derived its interior coordinate as
anchor + 1, which assumes the fixture procedure's first instruction is
longer than one byte. Host toolchains without endbr64-style prologue
padding (Kali gcc 16, or any build with -fcf-protection=none) compile
rea_entry to start with the one-byte push rbp, so anchor + 1 is itself
an instruction boundary: goto_address correctly observes that boundary
and the boundary-contract run rejects a correct bridge.

Advance the probe to the first instruction followed by a coordinate gap
larger than one byte and derive the interior-coordinate assertions from
that instruction, so the probed coordinate is never an analyzed-object
boundary on either prologue encoding.
2026-10-10 06:07:01 +08:00
morluto 392f1f3107 refactor: consolidate boundary semantics and prune redundant tests
Share parser modes and collision-free composite keys, enforce architecture guards, and consolidate redundant unit assertions into filesystem, CLI, MCP, and producer-backed workflows. Preserve concurrent upstream boundary fixes and exclude legacy Objective-C class-name bookkeeping labels.

Validation: source/composition suites (3358 passing), focused canonical digest and MCP checks, typecheck/lint, Knip, formatting, architecture guards, and real Foundation archive and Apple legacy simulator CLI/MCP verification. No real Hopper, Ghidra, or IDA verification claim.
2026-10-10 05:56:01 +08:00
morluto 077d6c407b docs: correct MCP error and capture import guidance 2026-10-10 05:41:52 +08:00
morluto 7a0c800851 docs: remove retired architecture and migration artifacts 2026-10-10 05:41:45 +08:00
morluto 7738c1f6a9 docs: add repository-local REA tool design skill 2026-10-10 05:30:02 +08:00
morluto 5d79387505 docs: prune repeated contributor and tool design instructions 2026-10-10 05:28:13 +08:00
morluto ba4422296d docs: consolidate agent guidance around ownership and boundaries 2026-10-10 05:22:35 +08:00
morluto 614fb7681e fix(evidence): order canonical projections independently of locale 2026-10-10 05:13:53 +08:00
morluto 0f10499245 refactor(javascript): share Babel child traversal 2026-10-10 05:13:53 +08:00
morluto 617cd84d27 fix(browser): retain malformed redirect diagnostics 2026-10-10 05:13:53 +08:00
morluto abf5e243c4 fix(update): preserve disabled client registrations 2026-10-10 05:13:53 +08:00
morluto 5aa200285a fix(artifacts): infer legacy Mach-O simulator platforms 2026-10-10 05:13:53 +08:00
morluto 5751f5caac fix(artifacts): preserve archive facts and Unicode path identity 2026-10-10 05:13:53 +08:00
morluto 70bad53847 fix(native): distinguish symbol definitions from metadata 2026-10-10 05:13:53 +08:00
morluto 890bb66b35 fix(ida): compare admitted document paths consistently 2026-10-10 05:13:53 +08:00
YsopwnableandGitHub 53ed942a85 fix(mcp): preserve JavaScript workflow identity validation (#1366)
Preserve canonical distinct-source and unique-native-observation refinements after resolving inline or retained JavaScript workflow inputs. The shared application entry points now return structured invalid_request errors before graph parsing and computation, avoiding another complete graph capture.

Six focused tests, actual compiled CLI/SDK stdio workflows, JSON Schema dialect checks, static/document checks, and a real Notion ASAR analysis/recovery/trace/close workflow passed. All 20 final-head checks, including real JavaScript recovery, passed. Native-provider acceptance is not claimed for this provider-neutral validation change.

Fixes #1364
Refs #1065
2026-10-10 05:11:38 +08:00
YsopwnableandGitHub 6ce3288f3b fix(cli): stream JSON inputs beyond the whole-document string limit (#1360)
Stream large CLI JSON files through a strict UTF-8 decoder and standard JSON parser using the same admitted regular-file handle. Preserve native parsing for small inputs, typed malformed-input/resource/access-denied errors, cancellation, and complete Evidence.

Verified with focused public CLI regressions, a 768 MB whitespace-padded valid request, and the Windows native decoder boundary. Individual strings and the assembled object graph remain subject to native runtime limits. All 27 final-head checks passed.

Refs #1331
2026-10-10 04:53:09 +08:00
Dery FerdikaandGitHub 3728c8267b fix(ghidra): reject a native decompiler built for another host (#1280)
Reject positively identified foreign-only Ghidra decompiler binaries and non-regular native prerequisites before provider startup, while retaining unknown classifications for incomplete or unrecognized headers.

Verified with 54 focused tests and real Linux Ghidra CLI/MCP admission, decompilation, cleanup, wrong-host PE rejection, and non-blocking FIFO rejection. All 19 final-head checks passed.

Fixes #1192

Co-authored-by: Dery Ferdika <114888155+DeryFerd@users.noreply.github.com>
2026-10-10 04:52:25 +08:00
f39e71ce18 fix(skill): pin packaged commands to the shipping package version (#1346)
Fixes #1338.

Use canonical product identity for bundled command versions and keep build-cache fixtures aligned. Verified 10 focused tests, actual CLI installation/repair/uninstall scenarios and all 19 final-head CI checks.

Co-authored-by: Yi-111-a <97448247+Yi-111-a@users.noreply.github.com>
2026-10-10 04:47:10 +08:00
morluto 048b79878c test(native): retain trace diagnostics when observed hits differ 2026-10-10 04:39:17 +08:00
morluto 7ad353fa8b fix(native): retain LLDB cleanup ownership through client close 2026-10-10 04:35:03 +08:00
morluto 0bfb6e00ab test(filesystem): bound FIFO regressions at consumers 2026-10-10 04:23:03 +08:00
morluto 5291bca108 refactor(artifacts): remove unused root classifier 2026-10-10 04:16:29 +08:00
morluto 7829b1aeef fix(filesystem): reject unstable artifact targets 2026-10-10 04:14:54 +08:00
morluto 66a20a2597 test(managed): include shared dossier fixture in artifact inputs 2026-10-10 04:09:45 +08:00
morluto 5b3715ef82 docs: correct README setup and runtime guidance 2026-10-10 04:08:05 +08:00
morluto 37fcea78ce fix(cli): avoid duplicate primary cleanup diagnostics 2026-10-10 04:02:41 +08:00
morluto ac356c46ad test(javascript): share semantic graph test facts 2026-10-10 04:02:41 +08:00
morluto ca9010936a test(package): share validated native dossier fixtures 2026-10-10 04:02:40 +08:00
morluto 5d32e42529 test(cli): remove duplicate malformed JSON assertion 2026-10-10 03:53:12 +08:00
morluto 79d5b9a826 test(process): report cleanup details on cancellation failures 2026-10-10 03:52:35 +08:00
morluto 961c3c3de7 test(android): allow provider readiness under load 2026-10-10 03:52:35 +08:00
morluto d761d7358b test(ghidra): allow rollback tests to reach spawned process 2026-10-10 03:52:35 +08:00
morluto 006b295f1d refactor(javascript): parse runtime evidence into one verified owner 2026-10-10 03:52:35 +08:00
morluto 415145d04f fix(process)!: retain per-file digest open failures
BREAKING CHANGE: Filesystem digest omission entries now require system_code; budget and changed-file omissions use null, and unavailable-file omissions preserve the operating-system error code.
2026-10-10 03:52:35 +08:00
morluto f62b44971d fix(mcp): advertise primitive semantic literal seeds 2026-10-10 03:52:35 +08:00
morluto 218c13160e fix: report malformed application evidence as input errors 2026-10-10 03:52:35 +08:00
morluto 55a46f7c71 fix(javascript): resolve query-only HTML references to their document 2026-10-10 03:52:35 +08:00
morluto 08daf056cc fix(cli): classify JSON input permission denials 2026-10-10 03:52:35 +08:00
morluto a4ba8aecd5 fix(contracts)!: require observed provider output metadata
Reject omitted segment bounds, procedure classification and body facts, unresolved-call observations, dossier facets, and Ghidra parameter flow metadata. Providers emit explicit nulls for unsupported facets. Verify those unknowns in the real Hopper workflow.

BREAKING CHANGE: Provider analysis outputs must explicitly supply metadata previously repaired with defaults; unsupported nullable facets must be reported as null.
2026-10-10 03:52:13 +08:00
morluto e3bbb9ac45 refactor(javascript)!: share semantic evidence at fact construction
Intern shared provenance in a graph-scoped context registry while retaining exact locations on every fact. Semantic traces carry their referenced context subset, and portable graph validation rejects stale or dangling commitments.

BREAKING CHANGE: Semantic graph facts now store evidence context IDs and locations. Graph and semantic trace results require an inline evidence_contexts table.
2026-10-10 03:52:13 +08:00
YsopwnableandGitHub 9c4a68bc19 fix(json): preserve runtime limits across JSON file readers (#1350)
* fix(cli): preserve runtime JSON string-limit diagnostics

* test(json): check actionable oversized Evidence recovery

* fix(json): decode large UTF-8 inputs by character length

* test(json): reject truncated UTF-8 after large input decode
2026-10-09 19:39:35 +00:00
morluto 750fb65650 refactor(artifacts): test inventory changes at materialization boundary 2026-10-10 02:49:46 +08:00
morluto e36afa112f docs(contracts)!: explain canonical URL and skill metadata ownership
BREAKING CHANGE: source-map URLs now live in target observations selected by declared_url_sha256, and doctor skill identity no longer emits installed_catalog_digest. Use the documented observation join and identity.skill.state instead.
2026-10-10 02:49:46 +08:00
morluto a959a8309d test(json): remove assertions covered by CLI output consumers 2026-10-10 02:49:46 +08:00
morluto c867bcd0aa test(javascript): share primitive expansion producer fixtures 2026-10-10 02:49:46 +08:00
morluto 449d57075e refactor(javascript)!: remove obsolete scope truncation statistic
BREAKING CHANGE: remove the never-incremented truncated_scopes statistic from JavaScript application analysis results and schemas.
2026-10-10 02:49:46 +08:00
morluto b4a19193fe fix(setup): install the skill for Claude Code 2026-10-10 02:49:46 +08:00
morluto ed8fcae94b fix(javascript): store source map URLs once 2026-10-10 02:49:46 +08:00
morluto 7915ee5178 feat(javascript): record Electron integrity mismatches 2026-10-10 02:49:46 +08:00
morluto f0dc233d64 fix(setup): recognize supported Nobara hosts 2026-10-10 02:49:46 +08:00
morluto f7cf4c890d fix(cli): classify oversized JSON inputs 2026-10-10 02:49:46 +08:00
morluto db171be6e5 fix(javascript): preserve agreeing module provenance 2026-10-10 02:49:46 +08:00
2793672ee2 fix(skill): pin packaged commands to the shipping package version
The generated skill rewrote `rea-agents@latest` to the version it ships with, so a pinned install no longer needs a local edit that `doctor --skill` reports as stale.

Co-Authored-By: OpenCode <opencode@opencode.ai>
2026-10-10 02:49:46 +08:00
LucienandGitHub 1ac8389c5c test(artifacts): verify extraction races with real filesystem changes
Co-authored-by: dakjdakd <164857476+dakjdakd@users.noreply.github.com>
2026-10-10 02:38:33 +08:00
LucienandGitHub f6cfbfcc55 fix(browser): release attached viewport overrides without resizing the external page
Co-authored-by: dakjdakd <164857476+dakjdakd@users.noreply.github.com>
2026-10-10 02:33:56 +08:00
YsopwnableandGitHub 6c9161d617 docs: explain CI scope and native runner reuse (#1348) 2026-10-09 18:28:43 +00:00
YsopwnableandGitHub d5cb8aee06 fix(ci): scope verification and reuse native runners (#1344)
* fix(ci): scope documentation checks and cancel superseded runs

* ci: reuse package runners for native Inspector checks

* test(ci): share deterministic workflow Git fixtures
2026-10-09 18:22:03 +00:00
You WishandGitHub 1c123493a2 fix(hopper): allow restart after verified owned-provider shutdown
Co-authored-by: YouWish <29498139+Y0UW1SH@users.noreply.github.com>
2026-10-10 02:12:33 +08:00
keemsisiandGitHub b1e85ad711 perf(javascript): index version relationships once per comparison (#1347)
relationshipSignature rebuilt a node map and scanned every graph edge
for each side of each matched pair, so comparison cost grew as
pairs x (nodes + edges). Build node and adjacency indexes once per
graph in ItemContext; signatures, sorting and output are unchanged.
At 4000 matched modules, end-to-end compare: 5.7s -> 2.9s (2 edges
per node) and 10.4s -> 5.8s (6 edges per node); 8000: 3.3x and 2.5x.
Output JSON is byte-identical on the base commit.
2026-10-10 02:07:30 +08:00
3f59a84bd1 fix(contracts): advertise NUL with a portable hex escape
Use the equivalent hex NUL spelling in named public contracts while preserving current path and reserved-name validation. Verify converted JSON Schema and real stdio catalog consumers.

Closes #1329

Co-authored-by: Yi-111-a <97448247+Yi-111-a@users.noreply.github.com>
2026-10-10 01:54:42 +08:00
You WishandGitHub 5f16124a31 fix(files): reject nonregular capture and JSON inputs
Verify selected files through a nonblocking opened handle before reading. Preserve regular-file symlinks and return actionable CLI/MCP diagnostics without publishing output.

Co-authored-by: YouWish <29498139+Y0UW1SH@users.noreply.github.com>
2026-10-10 01:49:54 +08:00
morluto cfce91d418 fix(browser): serialize attached scenarios through cleanup settlement 2026-10-10 01:45:01 +08:00
morluto 4940a867e2 test(process): use owned CLI and workspace fixtures 2026-10-10 01:45:01 +08:00
morluto 74be52611e test(process): publish capture readiness atomically 2026-10-10 01:45:01 +08:00
morluto 377df715ea refactor(reference): simplify malformed UTF-8 handling 2026-10-10 01:45:01 +08:00
morluto 5a61562dc2 test(browser): report redirect status cases independently 2026-10-10 01:45:01 +08:00
morluto 96b2b245fd test(javascript): verify distinct module origins through reconstruction 2026-10-10 01:45:01 +08:00
morluto 41a228c1b0 fix(electron): preserve unrepresentable numeric option evidence 2026-10-10 01:45:01 +08:00
morluto 3e19875c7f fix(javascript): retain unresolved value frontiers in provenance queries 2026-10-10 01:45:01 +08:00
morluto b628bba1fa refactor(javascript): normalize erased expression syntax once 2026-10-10 01:45:01 +08:00
morluto cfb12e47dc fix(artifacts): validate only active extraction entries 2026-10-10 01:45:00 +08:00
ACandmorluto 7a4f2685d4 fix(javascript): reject invalid package exports configurations 2026-10-10 01:45:00 +08:00
ACandmorluto 2b4abbf1cc fix(javascript): distinguish prefix-only builtins from packages 2026-10-10 01:45:00 +08:00
Rudy Celekliandmorluto 9367dc13bd test(browser): avoid duplicating source-map listener setup
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-10 01:45:00 +08:00
Rudy Celekliandmorluto 82bbe74333 fix(browser): follow only HTTP redirect statuses for source maps
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-10 01:45:00 +08:00
Rudy Celekliandmorluto f166a2ae15 fix(reference): report malformed UTF-8 before import parsing
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-10 01:45:00 +08:00
Rudy Celekliandmorluto 9055bd695b fix(javascript): avoid positive-zero evidence for signed zero 2026-10-10 01:45:00 +08:00
Rudy Celekliandmorluto 2bd7de6f8c fix(javascript): retain distinct module provenance path components 2026-10-10 01:45:00 +08:00
Rudy Celekliandmorluto e995b19f83 fix(javascript): preserve semantic evidence through satisfies 2026-10-10 01:45:00 +08:00
Rudy Celekliandmorluto 4896adcd0f fix(javascript): parse declaration artifacts in ambient mode 2026-10-10 01:45:00 +08:00
dakjdakdandmorluto a0523b375e fix(browser): retain attached scenario emulation until cleanup 2026-10-10 01:45:00 +08:00
dakjdakdandmorluto 5e8fb531e2 fix(artifacts): reject incomplete inventoried extraction 2026-10-10 01:45:00 +08:00
YsopwnableandGitHub 3edb2172de Merge pull request #1334 from morluto/docs/celebrate-40000-stars
docs: celebrate 40,000 GitHub stars 🎉
2026-10-10 01:35:02 +08:00
YsopwnableandGitHub 8c1bec42ba chore(release): sync 6.2.0 checkpoint into main (#1340)
Preserve the published 6.2.0 tag ancestry and main's later implementation changes.
2026-10-10 01:31:46 +08:00
N0zoM1z0 0c3aa98a3e chore(release): sync 6.2.0 checkpoint into main 2026-10-09 17:13:44 +00:00
morluto 8c96baab80 refactor(catalog): import CLI metadata from its owner 2026-10-10 00:49:14 +08:00
morluto 4144e454f3 refactor: remove single-use forwarding helpers 2026-10-10 00:49:14 +08:00
morluto 070339af50 refactor(process): remove duplicate observation and trace entry points 2026-10-10 00:49:14 +08:00
morluto d1983a4576 refactor(browser): open scenario sessions without a factory wrapper 2026-10-10 00:49:14 +08:00
morluto 87f0051496 refactor(providers): use canonical artifact and managed identities 2026-10-10 00:49:14 +08:00
N0zoM1z0 5ecc98a5ea docs: celebrate 40,000 GitHub stars 🎉 2026-10-09 16:43:35 +00:00
1b73b5ab4b fix(native): refuse to list architectures of non-Mach-O targets (#1325)
list_architectures ran lipo on every admitted target. For a PE DLL, ELF
binary or plist, lipo's refusal surfaced as execution_failure with
"Retry once; if it continues, run rea doctor", which neither can fix.
Refuse non-Mach-O targets as capability_unavailable before running
lipo, as inspect_macho already does.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:41:03 -07:00
56598beb4e perf(json): encode streamed JSON iteratively (#1322)
The streamed JSON encoder delegated every token through one recursive
generator per nesting level and yielded each token separately. Writing
analyze-javascript-application output for Typora (873 MB) spent 22 of
66 s there. Encode with an explicit stack into bounded 16 KiB parts:
identical bytes, 3-6x faster encoding, and the same laziness, error
and surrogate-pair guarantees.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:40:45 -07:00
morluto d83cbd2abf test: share snapshot replay and managed graph fixtures 2026-10-10 00:35:17 +08:00
morluto a27794c246 fix(artifacts): retain DMG ownership through uncertain attachment 2026-10-10 00:35:17 +08:00
morluto 35f121f4ac fix: retain completed observations when later analysis steps fail 2026-10-10 00:35:17 +08:00
morluto e11f4d371a fix(mcp): admit composed analysis through result bookkeeping 2026-10-10 00:35:17 +08:00
morluto e64678e8f9 fix(mcp): retry failed shutdown resources and retain failure reasons 2026-10-10 00:35:17 +08:00
morluto 25711ad259 test: exercise source test selection through Git and Vitest 2026-10-10 00:35:17 +08:00
morluto f3c4a332f7 fix(targets): cancel resolution before provider admission 2026-10-10 00:35:17 +08:00
morluto 44c92f88c5 refactor: remove obsolete source exclusions and identity wrapper 2026-10-10 00:35:17 +08:00
morluto 07675f78c6 fix(ghidra): retain process ownership after failed launch rollback 2026-10-10 00:35:17 +08:00
morluto cc7b5af077 fix(managed): bind graph facts to their source Evidence 2026-10-10 00:35:17 +08:00
morluto b112d44a39 fix(native)!: preserve unknown Objective-C metadata
BREAKING CHANGE: Objective-C attribute tokens now contain only name and value. Properties report nullable atomicity and readonly facts; class flags, ivar counts, and method requirement flags are nullable when unobserved.
2026-10-10 00:35:16 +08:00
github-actions[bot]GitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>N0zoM1z0
a64851f259 chore(release/6.2.0): release rea-agents 6.2.0 (#1305)
* chore(release/6.2.0): release rea-agents 6.2.0

* docs(release): complete 6.2 breaking migration notes

* fix(dev): allow formatter-ignored staged files

* docs(release): include all unreleased mainline entries

* docs(release): note ignored-file hook repair

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: N0zoM1z0 <1705004398@qq.com>
2026-10-09 16:17:20 +00:00
morluto e10f1f0901 docs: keep license sections text-only 2026-10-10 00:09:46 +08:00
5d16be2a71 test: share the client registration command to restore the jscpd gate (#1317)
After #1301 merged, main's duplicated-line share rose to 2.503%, over
jscpd's 2.5% threshold, so Static checks fail on every PR. The new OMP
test repeated the dialect test's imports and npx registration command.
Export that command from the shared client test fixture instead.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:09:08 -07:00
morluto ccfbe87e98 docs: align translated README artwork and layout 2026-10-10 00:03:14 +08:00
morluto 4b8e744d90 docs: add README artwork and refine closing sections 2026-10-10 00:00:41 +08:00
8b4c359135 feat(setup): register OMP during setup (#1301)
* feat(setup): register OMP during setup

Add OMP (oh-my-pi) as a setup, doctor and uninstall client. Setup writes
a type: stdio entry to the user-level agent mcp.json that OMP reads,
following PI_CONFIG_DIR, an absolute PI_CODING_AGENT_DIR and the
OMP_PROFILE/PI_PROFILE named profile. It removes rea from OMP's
disabledServers denylist, which would otherwise hide the registration,
and doctor reports a listed registration as stale.

Closes #1257

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(setup): honor OMP's enabledServers allowlist in doctor

OMP's user enabledServers allowlist forces an entry with enabled: false
on, unless disabledServers also lists it. Doctor reported such a working
registration as stale. Also format the FAQ client list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(setup): keep OMP's allowlisted entry in update maintenance

rea update skipped an owned OMP entry with enabled: false even when
OMP's enabledServers allowlist runs it. Apply the same forced-enable rule
as doctor. Share the client-location environment reset across the client
tests instead of repeating it in each file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:51:12 -07:00
morluto 24673aaae4 test(mcp): remove arbitrary schema inventory thresholds 2026-10-09 23:35:19 +08:00
morluto 765e809e36 refactor: use canonical implementations and types directly
Remove forwarding wrappers and shadow aliases, migrate callers and verification scripts to their owners, and share one exhaustive semantic resource-bound projection.
2026-10-09 23:35:19 +08:00
morluto 3283a45d09 refactor(captures)!: require canonical producer metadata
Require process retention accounting, browser network transaction identity, and all web comparison dimensions. Remove obsolete omission repairs and derive completeness from the owning producer facts.

BREAKING CHANGE: Historical captures without current producer accounting or transaction identity, and web diffs missing accessibility or storage dimensions, are rejected.
2026-10-09 23:35:19 +08:00
morluto dea3498b2b fix(inspector): retain observations after capture failures 2026-10-09 23:35:19 +08:00
YsopwnableandGitHub c267e99227 docs: explain 6.2 contract and saved-data migration (#1304) 2026-10-09 15:31:11 +00:00
YsopwnableandGitHub 4bb4c6fe6d test(apple): verify compiled Mach-O root occurrence facts (#1300)
test(artifacts): verify compiled Mach-O roles and permissions

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-09 15:24:53 +00:00
kvalls be6863e9a1 feat(ghidra): support native PE DLLs on Windows 2026-10-09 16:11:13 +01:00
You WishandGitHub 411498d45f fix(electron): resolve effective preload after option overrides (#1286) 2026-10-09 08:05:00 -07:00
Kaoru0822andGitHub c3fc6c3aed Merge pull request #1297 from morluto/fix/ghidra-session-root-stability
fix(ghidra): use dot-free private session paths
2026-10-09 07:59:06 -07:00
Kaoru0822andGitHub 1f099a6fc0 Merge pull request #1299 from morluto/fix/schema-patterns-without-lookaround
fix(mcp): advertise input patterns without look-around
2026-10-09 07:58:51 -07:00
Kaoru0822andGitHub 701d90aba4 Merge pull request #1298 from morluto/test/artifacts-direct-macho-root-kind
test(artifacts): pin per-occurrence roles for direct Mach-O roots and shared bytes
2026-10-09 07:54:24 -07:00
Kaoru0822andClaude Opus 5.5 a8701eaf48 fix(mcp): advertise input patterns without look-around
trace_dylib_resolution roots and capture_process_scenario environment
names still advertised negative look-ahead patterns. RE2 and Rust schema
validators reject look-around, so a client using one refuses the whole
tools request, as #1282 reported for the NUL escape. Spell both
constraints as equivalent look-around-free patterns and assert that no
advertised pattern uses look-around or backreferences.

Closes #1282

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:49:22 +00:00
morluto ad59531a96 refactor: remove forwarding exports and redundant aliases 2026-10-09 22:46:09 +08:00
morluto 69c3b32a21 test(mcp): read bundle failures from public error content 2026-10-09 22:46:09 +08:00
morluto 5f749c2096 fix(mcp): only recommend exporting retained evidence 2026-10-09 22:46:09 +08:00
morluto 76b214e45f fix(windows): retain unsettled jobs for cleanup retry 2026-10-09 22:46:09 +08:00
morluto 614e0c2e74 fix(browser): retain scenario observations across failures 2026-10-09 22:46:08 +08:00
morluto 73e98b2516 fix(javascript): preserve alias and container uncertainty 2026-10-09 22:46:08 +08:00
YsopwnableandGitHub 99f257bbf0 Merge pull request #1296 from morluto/feat/website-seo-metadata
feat(website): add search metadata and automatic sitemap
2026-10-09 22:43:41 +08:00
Kaoru0822andClaude Opus 5.5 b9e29c52d4 test(artifacts): pin per-occurrence roles for direct Mach-O roots and shared bytes
Both reported failures were fixed by 63bf9140, which moved kind and
executable facts from content nodes to occurrences, but neither
reproduction had a regression test. Pin the direct-file Mach-O root kind
and permission against its bundle occurrence, and the Apple JavaScript
component and runtime family next to byte-identical text resources.

Refs #1234
Refs #1235

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:39:51 +00:00
N0zoM1z0 1c3766a8bc test(ghidra): preserve selected verification resource limits 2026-10-09 14:37:06 +00:00
Kaoru0822andGitHub 098d76900e Merge pull request #1291 from morluto/fix/process-port-normalization-sentence-period
fix(process): normalize ports that end a sentence
2026-10-09 07:34:54 -07:00
Kaoru0822andGitHub 2ddd9456cd Merge pull request #1295 from morluto/fix/javascript-html-url-whitespace-admission
fix(javascript): reject encoded separators joined by HTML URL whitespace
2026-10-09 07:34:39 -07:00
N0zoM1z0 43405f9ffe Merge remote-tracking branch 'origin/main' into feat/website-seo-metadata 2026-10-09 22:33:04 +08:00
Kaoru0822andGitHub 6020a0b368 Merge pull request #1294 from morluto/test/process-contract-rejections-concurrent
test(process): check malformed capture choices concurrently
2026-10-09 07:31:08 -07:00
Kaoru0822andGitHub fe34ec2ef3 Merge pull request #1288 from morluto/fix/mcp-error-text-budget
fix(mcp): measure tool errors against their text-only delivery
2026-10-09 07:30:48 -07:00
Kaoru0822andClaude Opus 5.5 ad813e473b fix(process): treat non-ASCII letters as port continuations
\w is ASCII-only even with the u flag, so "port: 8080.β" was treated as
a sentence-ending port. Use Unicode letter and number classes for the
port boundary checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:28:19 +00:00
N0zoM1z0 1e341973cf test(ghidra): size oversized annotations for canonical delivery 2026-10-09 14:21:38 +00:00
Kaoru0822andGitHub 69833fb0d0 Merge pull request #1293 from morluto/fix/process-capture-terminal-byte-accounting
fix(process): validate terminal byte totals against retained frames
2026-10-09 07:20:08 -07:00
Kaoru0822andClaude Opus 5.5 184ed970b9 fix(process): keep ports before a chunk-final period
PTY chunks are normalized independently. A period that ends a chunk may
begin a decimal continued in the next chunk ("port: 80." then "5"), so
leave such a port unnormalized instead of masking the decimal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:19:37 +00:00
N0zoM1z0 8c9c5550d0 Merge remote-tracking branch 'origin/main' into feat/website-seo-metadata 2026-10-09 22:19:04 +08:00
Kaoru0822andClaude Opus 5.5 fb57c8643f fix(javascript): reject encoded separators joined by HTML URL whitespace
#1287 removes URL tabs and newlines from an HTML script URL before
percent-decoding. A declaration such as %2<newline>fapp.js passed the
raw admission check and then decoded to a separator, resolving to a
file the encoded-separator rule must refuse. Apply canonical path
admission again to the parsed URL text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:18:39 +00:00
Kaoru0822andClaude Opus 5.5 48de11ce2e test(process): check malformed capture choices concurrently
The malformed process-choice acceptance test spawned 26 CLI processes one
after another. On CI it took 45-59 s against its 60 s deadline and timed
out on unrelated PRs. Run the independent cases concurrently, each with
its own scenario file; every assertion is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:17:27 +00:00
Kaoru0822andGitHub b80bd2db96 Merge pull request #1289 from morluto/fix/ghidra-address-verifier-error-envelope
fix(ghidra): stop dereferencing the removed error payload in address verification
2026-10-09 07:14:32 -07:00
Kaoru0822andGitHub d601b8016e Merge pull request #1287 from morluto/fix/javascript-html-script-url-decoding
fix(javascript): resolve HTML script URLs after URL whitespace and percent decoding
2026-10-09 07:13:13 -07:00
Kaoru0822andClaude Opus 5.5 39eb0587c9 fix(process): validate terminal byte totals against retained frames
parseProcessCapture accepted terminal retention accounting that its
retained frames contradict: any retained_bytes within budget, and
observed_bytes above retained_bytes with no omitted frame. A malformed
capture could therefore report truncated: false while its terminal
evidence was incomplete. Recompute retained raw and rendered bytes from
the frames, and require equal observed and retained bytes when no frame
was omitted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:12:05 +00:00
Kaoru0822andClaude Opus 5.5 db98a51dd1 fix(process): normalize ports that end a sentence
Contextual port normalization refused any port followed by a period, so
common log lines such as "Listening on port: 8080." or
"http://localhost:8080." kept their run-specific port and equivalent
captures compared as changed. Accept a sentence-ending period while
still refusing a period that continues a decimal, version, or host name,
and bump the committed port-normalization version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:06:41 +00:00
Kaoru0822andClaude Opus 5.5 59fbaa2d33 fix(ghidra): stop dereferencing the removed error payload in address verification
Since #1277 an MCP tool error carries no structuredContent, so the real
Ghidra address-boundary verifier threw a TypeError on its first expected
rejection and never checked the remaining representations or the
alias-preservation control. Assert that the error carries no structured
payload instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:04:35 +00:00
Kaoru0822andClaude Opus 5.5 7b51121f7c fix(mcp): measure tool errors against their text-only delivery
Since #1277 an error result reaches the client without structuredContent,
but toErrorToolResult and the transport recovery still budgeted it as
structured JSON plus escaped text. An error whose text fit between about
half and all of the response budget was replaced by resource_constraint,
and without Evidence retention the original diagnostic was lost.

Count only the escaped text for errors. The boundary, process-global and
real Ghidra large-result probes now use diagnostics that exceed the
text-only budget.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:03:12 +00:00
YsopwnableandGitHub 33bf585185 fix(process): localize capture truncation diagnostics (#1284)
Report per-source capture coverage and existing file-hash omissions while preserving comparable observations in unaffected dimensions. Keep legacy truncated captures conservative and retain known partial trace events.

Closes #1250
Partially addresses #1251; independent hashing remains out of scope.
2026-10-09 21:56:43 +08:00
N0zoM1z0 f61673fa99 Merge remote-tracking branch 'origin/main' into fix/ghidra-session-root-stability 2026-10-09 13:54:37 +00:00
YsopwnableandGitHub 7e96f25f8b fix(mcp): deliver typed errors without invalid structured output (#1277)
* fix(mcp): deliver tool errors within advertised schema contracts

Retain complete typed JSON error content while omitting non-conforming
structured errors at the public transport boundary. Recover oversized
diagnostics into Evidence before removing their private structured carrier.
Update schema-validated client readers and cover actual stdio delivery.

Closes #1261

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)

* test(mcp): read typed errors in canonical Evidence regressions

* test(mcp): validate public error diagnostics in acceptance workflows
2026-10-09 13:54:32 +00:00
Kaoru0822andClaude Opus 5.5 502528c58d fix(javascript): resolve HTML script URLs after URL whitespace and percent decoding
An HTML script src or base href with percent-encoded letters or
surrounding whitespace was looked up literally, so an inventoried script
was reported as not-found. Apply HTML attribute and URL parser
whitespace handling, then percent-decode the path as the URL standard
does. Encoded dot and separator bytes are still rejected, and paths that
decode to NUL or non-UTF-8 bytes are rejected explicitly.

Closes #1236

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:52:55 +00:00
N0zoM1z0 bb8ff2cfba docs(website): explain SEO maintenance and indexing follow-up
Document the Python preview environment, automatic sitemap updates, canonical URLs, generated sharing card and Search Console checks after publication. Apply the website's clear, concise writing standard to search and sharing metadata.
2026-10-09 21:47:08 +08:00
N0zoM1z0 b8851cb977 feat(website): add search metadata and automatic sitemap
Prefer rea.tools in page canonicals and search listings. Generate the sitemap from current HTML indexing directives and render a shared PNG preview from SVG before verification and manual deployment.

Refs #1283
2026-10-09 21:46:05 +08:00
N0zoM1z0 2060a6d7f3 Merge branch 'fix/mcp-error-schema-delivery' into fix/ghidra-session-root-stability 2026-10-09 13:42:28 +00:00
N0zoM1z0 09058ebc4a test(mcp): validate public error diagnostics in acceptance workflows 2026-10-09 13:42:08 +00:00
N0zoM1z0 1e83d270c2 test(ghidra): use host-native absolute session root fixtures 2026-10-09 13:20:49 +00:00
YsopwnableandGitHub 0c6852b392 docs(ghidra): explain supported heap and CPU controls (#1278)
Explain consumed heap settings, owned JVM environment overrides, CPU affinity and memory measurements in the Ghidra setup guide.

Closes #1255
2026-10-09 21:20:33 +08:00
felipeatpandN0zoM1z0 a8b8288396 fix: keep the Ghidra session root free of dot-prefixed path elements
Ghidra validates every project path element with NamingUtilities.checkName and aborts the headless analyzer on any element starting with '.', so an inherited TMPDIR such as ~/.cache/<tool> failed every Ghidra operation with a generic analysis failure. Select the session root through a helper that prefers the inherited base, then a dot-free platform temp directory, then the nearest dot-free ancestor.
2026-10-09 13:10:30 +00:00
N0zoM1z0 5486860673 Merge remote-tracking branch 'origin/main' into fix/mcp-error-schema-delivery 2026-10-09 13:06:26 +00:00
YsopwnableandGitHub f085589957 fix(ci): pass selected environment to Windows Ghidra fixture (#1281) 2026-10-09 13:05:54 +00:00
N0zoM1z0 fd46cff017 test(mcp): read typed errors in canonical Evidence regressions 2026-10-09 13:03:28 +00:00
morluto d6d1cd2485 test: remove duplicate workflow examples and self assertions 2026-10-09 21:01:53 +08:00
morluto af7a439633 fix(windows): retain runtime authority after cleanup failure 2026-10-09 21:01:53 +08:00
morluto 81b70bc358 fix(managed): preserve literal library names during native matching 2026-10-09 21:01:52 +08:00
morluto 5eb0049a9f fix(process): retain known events from incomplete captures 2026-10-09 21:01:52 +08:00
morluto b7b4333703 fix(reference)!: represent unreadable symlink targets explicitly
BREAKING CHANGE: Historical source symlinks with unreadable or unknown target_state require target: null. Placeholder target strings are rejected.
2026-10-09 21:01:52 +08:00
morluto 0696bde266 fix(providers): preserve observations and primary cleanup failures 2026-10-09 21:01:52 +08:00
morluto 88640f60fe fix(browser): retain scenario resources until cleanup succeeds 2026-10-09 21:01:52 +08:00
N0zoM1z0 7bf63ed7f8 chore: integrate canonical Evidence changes for MCP error delivery 2026-10-09 12:43:17 +00:00
YsopwnableandGitHub 636b245f1b fix(android): support owned JADX stdio on Windows (#1276)
Support owned JADX stdio on Windows x64, preserve protocol input errors through cancellation, and verify native stdin and Android CLI/MCP lifecycle on the real Windows host.

Closes #1262
2026-10-09 20:34:42 +08:00
morluto b71a591a60 test: consolidate redundant assertions into boundary workflows
Remove getter, enum, cloned-projection, cache-identity, and obsolete profile assertions along with the shadow JSON Schema engine and dead test-only APIs. Retain producer, filesystem, SDK, lifecycle, integrity, and malformed-format coverage.

Document the priority of real end-to-end workflows, boundary integration, and producer goldens.
2026-10-09 20:26:46 +08:00
N0zoM1z0 da606ff777 fix(mcp): deliver tool errors within advertised schema contracts
Retain complete typed JSON error content while omitting non-conforming
structured errors at the public transport boundary. Recover oversized
diagnostics into Evidence before removing their private structured carrier.
Update schema-validated client readers and cover actual stdio delivery.

Closes #1261

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-09 12:26:27 +00:00
morluto 2f02eff988 fix(managed): separate metadata and signature completeness 2026-10-09 20:18:52 +08:00
morluto 5510b27d7f refactor(domain)!: remove obsolete comparison representations
Compare complete function dossiers directly, remove unreachable truncation and collection wrappers, and preserve deterministic Unicode ordering. Require real external reference targets instead of display placeholders.

BREAKING CHANGE: function comparison results no longer advertise the unreachable truncated state or counter.
2026-10-09 20:18:52 +08:00
morluto 475a0f84da fix(javascript)!: preserve property paths and uncertain slot presence
Use one explicit object/array slot model and JSON-pointer property identity across mutation analysis, return projection, and semantic graphs. Require observed presence for discriminants and resolve writes only through retained object or array receivers.

BREAKING CHANGE: projected return fields require explicit presence and semantic object operations carry full property paths.
2026-10-09 20:18:52 +08:00
morluto 63bf91405c refactor!: enforce canonical evidence and provider boundaries
Deliver complete Evidence directly through MCP with required nullable analysis profiles and immutable per-server delivery settings. Bind selected environments at construction and require typed cleanup outcomes with retained retry ownership.

Remove test-only routing, duplicate session and snapshot metadata, producer-field repairs, and ambiguous provider arguments. Separate artifact byte identity from occurrence classification and retain typed source-map and partial native facts across CLI, MCP, and verifier consumers.

BREAKING CHANGE: obsolete Evidence envelopes, session aliases, incomplete snapshots, and missing normalized producer facts are no longer accepted.
2026-10-09 20:18:52 +08:00
morluto 2a7746998d fix(process)!: require current captures and preserve cleanup failures
Remove v3 capture conversion and require explicit executable identity and event journals. Preserve cancellation, execution diagnostics, snapshots, and cleanup outcomes from preparation through CLI delivery.
2026-10-09 20:12:07 +08:00
morluto abc4f47683 build: separate runtime artifacts and supervise command ownership 2026-10-09 20:11:17 +08:00
YsopwnableandGitHub c8544b1574 fix(process): preserve unknown filesystem absence in partial captures
Separate exhausted path enumeration from hash coverage and preserve known
effects outside incomplete roots or unfollowed symlink subtrees. Return
explicit unknown effects through capture Evidence and comparison workflows.

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-09 12:09:24 +00:00
YsopwnableandGitHub 4578647c59 Merge pull request #1272 from morluto/docs/website-calculator-continuation
docs(website): continue the Calculator example with reconstruction
2026-10-09 19:57:38 +08:00
morluto cc39fc53b8 feat(website): add Discord link beside GitHub badge 2026-10-09 19:54:34 +08:00
YsopwnableandGitHub 13c3b68730 Merge pull request #1270 from morluto/fix/batch-procedure-identity
fix(native): distinguish batch selectors from resolved entries
2026-10-09 19:39:48 +08:00
N0zoM1z0 18a1e8cd0e docs(website): continue the Calculator example with reconstruction 2026-10-09 19:38:17 +08:00
N0zoM1z0 933fcb33c1 test(native): assert batch identity in production registration 2026-10-09 19:27:27 +08:00
YsopwnableandGitHub f6fe575094 fix(process): await cleanup on CLI and MCP cancellation
Propagate CLI interrupts to capture and interrupt post-exit settlement
without cancelling owned-resource cleanup or discarding prior observations.

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-09 11:26:41 +00:00
N0zoM1z0 8342e3a78f chore: merge current main into batch identity fix 2026-10-09 19:13:13 +08:00
N0zoM1z0 bfaa5a6c2c fix(native): distinguish batch selectors from resolved entries 2026-10-09 19:09:30 +08:00
YsopwnableandGitHub b189c3ceb1 Merge pull request #1268 from morluto/fix/ghidra-return-flow
fix(ghidra): preserve decoded return flow evidence
2026-10-09 19:04:47 +08:00
N0zoM1z0 bcc8a773e2 fix(ghidra): preserve decoded return flow evidence 2026-10-09 18:53:28 +08:00
YsopwnableandGitHub 6cc817e8bd Merge pull request #1266 from morluto/feat/website-apk-showcase
feat(website): add an Android showcase and clearer project prompts
2026-10-09 18:46:52 +08:00
keemsisiandGitHub 9426c3f1bb perf(hopper): resolve string search records once per query (#1229)
* perf(hopper): resolve string search records once per query

search_strings called _string_inventory(document) once per match, and each
call sorts every string address and rebuilds the record dict, so a query cost
O(matches x strings log strings). Resolve the inventory once per search.
Warm search, 50% matches, fake document, best of 7: 1000 strings 186 -> 0.5 ms,
4000 strings 3161 -> 2.1 ms, 8000 strings 13121 -> 4.9 ms; output byte-identical.

* perf(hopper): skip record resolution for empty string searches

Resolving the full string inventory for a query with no matches added a sort
of every string address that the previous code never performed. Return early
when nothing matches. Zero-match search on a warm document, best of 7:
64000 strings 35.9 ms before this change, 4.0 ms after (main: 3.9 ms).
2026-10-09 18:39:19 +08:00
N0zoM1z0 5691606aa9 fix(website): clarify Android host and JDK requirements 2026-10-09 18:31:22 +08:00
45e3edc17f feat(javascript): report observed export property presence (#1160)
* feat(javascript): report observed export property presence

Extend compare_javascript_export_shapes so each retained return variant
lists observed property names and each change reports presence independently
of value resolution. Complete parent coverage classifies one-sided names as
added or removed even when static values stay unknown.

Fixes #725

* test(javascript): match unknown export-shape values by availability

Nested availability objects include a reason when values stay unresolved.
Assert availability through objectContaining so presence-only added and
removed rows still verify unknown values.

* fix(javascript): preserve uncertain export property presence and locations

* fix(javascript): normalize presence and preserve local property coverage

* fix(javascript): require present discriminants for return pairing

* fix(javascript): normalize retained shapes before comparison

* refactor(javascript): share return projection with executable examples

* fix(javascript): localize uncertainty for missing mutated slots

* fix(javascript): bind advertised export examples to exact artifacts

* fix(javascript): keep uncertain property flow as candidates

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-09 18:30:31 +08:00
YsopwnableandGitHub 04aef6df33 Merge pull request #1265 from morluto/fix/snapshot-receipt-counts
fix(snapshot): report query workflow and Evidence counts separately
2026-10-09 18:29:02 +08:00
YsopwnableandGitHub 552634d634 Merge pull request #1264 from morluto/perf/snapshot-materialization
perf(snapshot): avoid redundant result copies and serialization
2026-10-09 18:19:59 +08:00
N0zoM1z0 0e779533a9 fix(snapshot): report query workflow and Evidence counts separately 2026-10-09 18:13:50 +08:00
YsopwnableandGitHub c5c75c38c3 Merge pull request #1263 from morluto/fix/process-normalization-fidelity
fix(process): preserve numeric output and original PTY evidence
2026-10-09 18:07:22 +08:00
N0zoM1z0 569d2bc6b9 perf(snapshot): avoid redundant result copies and serialization 2026-10-09 18:07:21 +08:00
889fb374df fix(javascript): match source-map originals that name parent directories (#1215)
* fix(javascript): match source-map originals that name parent directories

* fix(javascript): resolve parent segments against the source map's directory

* fix(javascript): resolve source originals against their map location

* fix(javascript): preserve URI and empty source map path semantics

* fix(javascript): separate source URL paths from opaque URI payloads

* fix(javascript): preserve filesystem names during URI classification

* style(javascript): format source URI presence guard

* fix(javascript): resolve source map references with URL semantics

* fix(javascript): preserve literal UNC source map paths

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-09 18:04:25 +08:00
YsopwnableandGitHub 24a3aa08d1 fix(session): retain failed provider cleanup for lifecycle retries (#1260)
Retire inactive clients until cleanup succeeds and block replacement startup
while owned resources remain. Preserve startup/cancellation failures alongside
cleanup diagnostics and retain explicit document choices across retries.

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-09 17:56:17 +08:00
N0zoM1z0 00d8e44cbf fix(process): preserve numeric output and original PTY evidence 2026-10-09 17:55:28 +08:00
N0zoM1z0 3fb9ffaa4d docs(website): invite deeper projects and reader feedback 2026-10-09 17:48:59 +08:00
Kaoru0822andGitHub db0afce5f3 Merge pull request #1259 from morluto/fix/cli-json-input-read-cause
fix(cli): list the read failure cause for an unreadable JSON input file
2026-10-09 02:47:42 -07:00
Kaoru0822andGitHub 5612496f6d Merge pull request #1258 from morluto/fix/inspect-plist-default-remediation
fix(native): name the plist selection that works when Info.plist is missing
2026-10-09 02:47:30 -07:00
Kaoru0822andGitHub fe5291e916 Merge pull request #1239 from morluto/fix/javascript-input-selection-errors
fix(javascript): classify application input selection failures by cause
2026-10-09 02:47:09 -07:00
Kaoru0822andGitHub d4a598e936 Merge pull request #1256 from morluto/fix/evidence-file-selection-code
fix(errors): report caller-selected evidence path failures as invalid input
2026-10-09 02:46:04 -07:00
Kaoru0822andGitHub ddaa18301a Merge pull request #1240 from morluto/fix/web-script-export-capture-selection
fix(browser): classify export-web-scripts capture selection failures by cause
2026-10-09 02:45:47 -07:00
morluto d6832c3632 docs: require focused brittleness cleanup and executable examples 2026-10-09 17:41:14 +08:00
Kaoru0822andClaude Opus 5.5 9b6950373c fix(native): name the CLI flag that selects another plist
rea inspect-plist takes the target as its positional path and selects a
plist with --relative-path, so "Pass path" pointed CLI callers at the
wrong argument. Name the MCP path input and the CLI flag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:32:24 +00:00
Kaoru0822andClaude Opus 5.5 6020df53d9 fix(cli): list the read failure cause for an unreadable JSON input file
A CLI workflow given a JSON input file that cannot be read (missing, a
directory, or permission denied) returned invalid_request with
input_reason "read-failed" but no details. The remediation "Correct the
listed arguments and retry." therefore listed nothing, and the system
error that separates a typo from a permission denial was dropped.

Add an invalid_value issue naming the system error code and the path.
The envelope, code and input_reason are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:30:15 +00:00
Kaoru0822andClaude Opus 5.5 a6fdf426bd fix(native): name the plist selection that works when Info.plist is missing
inspect_plist on a target without a readable default Contents/Info.plist
(for example a bare Mach-O) reported the generic "This analysis is
unavailable for the current target. Choose another analysis or target."
as message and remediation. The specific reason, including "Pass path to
inspect another plist", appeared only in details.reason, although
selecting another plist in the same target is the available workflow.

Pass that reason as the refusal's user message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:26:18 +00:00
Kaoru0822andClaude Opus 5.5 db177c91b8 fix(errors): report caller-selected evidence path failures as invalid input
An EvidenceFileError for a missing evidence file, a selected path that is
not a regular file, or an output that already exists projected code and
category execution_failure. The message already told the caller to
correct the path, but agents branching on code or category saw a tool
failure.

Project those three reasons as invalid_request with category
invalid_input. An unreadable file (io) and invalid JSON keep their
codes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:23:00 +00:00
Kaoru0822andClaude Opus 5.5 d186ca7e41 test(javascript): expect the invalid input_path code in the streamed CLI failure test
The acceptance test uses a missing input path only to produce a streamed
JSON failure with a nonzero exit. The missing path is now an invalid
input_path rather than an artifact io failure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:20:16 +00:00
YsopwnableandGitHub aa5750c263 fix(mcp): emit portable Unicode NUL patterns (#1230)
Preserve NUL rejection while avoiding the short escape rejected by strict
schema consumers. Guard the entire advertised input/output catalog and all
three JavaScript regexp modes.

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-09 17:18:17 +08:00
Kaoru0822andClaude Opus 5.5 8c5e34cd37 fix(browser): classify export-web-scripts capture selection failures by cause
export_web_scripts reported a missing capture, a directory selected as
the capture, and an unreadable capture as an artifact io failure ("Script
export failed for <capture> -> <output>: ENOENT ..."), unlike its sibling
inspect_web_network_capture, which already reports these as invalid
input or access_denied.

Read the selected capture in its own step: ENOENT, ENOTDIR and EISDIR
become an invalid capture_path issue, and EACCES or EPERM becomes
access_denied. Failures while writing the export keep their existing
classification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:16:59 +00:00
N0zoM1z0 0270dd5739 feat(website): add an Aegis APK code-generation showcase 2026-10-09 17:15:07 +08:00
Kaoru0822andClaude Opus 5.5 0a14bbbf05 fix(javascript): classify application input selection failures by cause
analyze_javascript_application reported every input-selection problem as
an artifact fault:

- a missing input path: "Artifact could not be read or written", with no
  path or reason;
- an unreadable selected directory: the same generic io failure;
- a regular file that is neither a directory nor an .asar, and a
  --artifact-format that contradicts the selection: "Artifact is invalid
  or has changed. Get a fresh copy and try again."

Report a missing path as an invalid input_path, an unreadable selection
as access_denied, a non-directory non-.asar file as unsupported_target
with the accepted inputs as remediation, and a contradicting format as an
invalid format with the observed kind as expected value. Failures inside
a selected artifact keep their existing classification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:13:17 +00:00
N0zoM1z0 f6f5c16097 docs(website): introduce the worked homepage examples 2026-10-09 16:52:45 +08:00
Kaoru0822andGitHub f4c99ab8a5 Merge pull request #1228 from morluto/fix/keyed-archive-host-remediation
fix(artifacts): name only host-available workflows for non-archive plists
2026-10-09 01:48:51 -07:00
954badbaaa refactor(schemas): share portable identifier and base64 patterns (#1227)
* refactor(schemas): share identifier and canonical base64 patterns

* test: hold the offset datetime schema to the validator it replaces

The module documents that its accepted set matches z.string().datetime({ offset: true }), and nothing in the suite checked that claim. Adds table-driven accept and reject cases (leap years including the 1900/2000 century pair, month, day, hour and offset ranges, fractional and omitted seconds, missing offset, basic format) plus a differential assertion that classifies every case exactly as the replaced validator does, and asserts the emitted pattern compiles under u and v while the replaced pattern does not compile under v.

---------

Co-authored-by: felipeatp <felipe.troncosopt@gmail.com>
2026-10-09 16:47:09 +08:00
Kaoru0822andClaude Opus 5.5 22958558ea fix(artifacts): name only host-available workflows for non-archive plists
inspect_keyed_archive runs on every host, but its remediation for an
ordinary property list pointed to inspect_plist, which only macOS
supports. On Linux that sent callers to a workflow the capability layer
rejects.

The domain error now names what the file is. The artifact reader picks
the remediation from the provider's host: inspect_plist on macOS, and
elsewhere the selection of an NSKeyedArchiver archive, with a note that
inspect_plist requires macOS. decode_interface_builder, which is
portable, stays the NIBArchive remediation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:40:45 +00:00
Kaoru0822andGitHub fef38e4d22 Merge pull request #1226 from morluto/fix/keyed-archive-kind-refusal
fix(artifacts): report non-archive keyed-archive selections as unsupported targets
2026-10-09 01:37:29 -07:00
Kaoru0822andGitHub 136d4aab18 Merge pull request #1225 from morluto/fix/exec-stop-timeout-validation
fix(process): refuse malformed timeouts for stoppable commands
2026-10-09 01:33:25 -07:00
Kaoru0822andGitHub 68cb02fe8b Merge pull request #1224 from morluto/fix/adapter-host-refusal-messages
fix: name host and tool requirements in optional adapter refusals
2026-10-09 01:33:15 -07:00
Kaoru0822andClaude Opus 5.5 8c5088c8cd fix(artifacts): report non-archive keyed-archive selections as unsupported targets
inspect_keyed_archive reported a selected ordinary property list or a
compiled NIBArchive as a damaged artifact: "Artifact is invalid or has
changed. Get a fresh copy and try again." The file is intact; it is
another kind of file, and the workflow that reads it (inspect_plist or
decode_interface_builder) appeared only in details.detail.

Report a NIBArchive, or a plist whose $archiver is not NSKeyedArchiver,
as unsupported_target with that workflow as the remediation. An
NSKeyedArchiver archive that fails to decode stays a format failure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:28:21 +00:00
Kaoru0822andClaude Opus 5.5 3d328193d6 fix(process): apply one timeout rule to both execFileOutput modes
Node's execFile timeout contract differs by supported runtime: Node 22
and 24 accept any non-negative integer (their timers clamp anything
above 2^31-1 to 1 ms), while Node 26 caps it at Number.MAX_SAFE_INTEGER.
Mirroring either left stoppable and plain commands disagreeing on one
runtime. Validate a safe non-negative integer before spawning in both
modes, so every supported runtime gives the same answer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:22:09 +00:00
felipeatpandGitHub f0da05f67f fix: emit v-mode-compatible patterns for tool schemas (#1220)
* fix: emit v-mode-compatible patterns for tool schemas

Character classes in emitted patterns carried unescaped '-', '/' and '['. Annex-B and u-mode accept them, so REA's own Zod validation (u) and every u-based validator never saw a defect, but v-mode rejects ClassSetSyntaxCharacters and Ruby rejects [^s[]]. With 6.1.0 tools/list, 117 pattern fields across 11 tools were rejected under v.

The characters are escaped as \x2d, \x2f, \x5b and \x5d rather than \-/\//\[, because oxlint --fix removes an escaped '-' inside a character class as a useless escape, so an escape-only change does not survive the pre-commit hook. \x2d-style escapes are valid under Annex B, u and v, are matched identically, and are not useless-escape candidates.

22 pattern literals in 18 files are touched; no other token changes.

* fix: replace the Zod offset pattern and guard the advertised catalog

The offset datetime site projected Zod's offset class as [ +- ], which no escape in this repository's sources can reach, so evaluate_reconstruction_coverage stayed unreachable for exactly the clients this change targets. It now uses offsetDateTimeSchema in src/domain/offsetDateTime.ts: the same accepted set with the offset class escaped as [ +\x2d ].

Adds tests/boundary/mcp/advertisedPatternsVMode.test.ts, which performs the real tools/list projection, traverses every advertised input and output schema, compiles each pattern under v, and asserts the inventory it walked so a silent traversal collapse fails instead of passing vacuously.
2026-10-09 16:20:57 +08:00
Jay HemnaniandGitHub 01174c4a81 fix(javascript): report located sources with differing digests as modified (#1216) 2026-10-09 16:20:42 +08:00
Kaoru0822andClaude Opus 5.5 6489d58851 fix(javascript): keep Wakaru version stderr out of the refusal message
The version-mismatch reason ends with the tool's complete stderr, which
is too long for a caller-facing message. The message now names the
expected and reported version and exit code; details.reason keeps the
stderr.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:16:45 +00:00
Kaoru0822andClaude Opus 5.5 59c91c88fe fix(process): refuse malformed timeouts for stoppable commands
Since a stoppable command keeps its own deadline, execFile no longer
validated its timeout. A negative, NaN, fractional or infinite value
then started the command with no deadline (or one setTimeout coerced)
instead of failing with ERR_OUT_OF_RANGE as execFile does.

Apply execFile's unsigned-integer contract before spawning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:15:03 +00:00
c89b3a00dc test(artifacts): read /bin/ls slice layout from its FAT table (#1223)
The real-lipo slice test pinned the byte offsets and sizes of one macOS
release's /bin/ls, so it failed on any host whose /bin/ls differs
(macOS 26.7.1: x86_64 48128 bytes, arm64e 88672, versus the pinned 48112
and 89088). Read the expected layout from the binary's FAT header
instead.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 16:12:27 +08:00
Kaoru0822andClaude Opus 5.5 170d0bf9e2 fix: name host and tool requirements in optional adapter refusals
Host and tool-configuration refusals from the pwntools, EVMole, firmware,
mitmproxy, Wakaru, LLDB and xcrun adapters carried no userMessage, so CLI
and MCP callers saw the generic "This analysis is unavailable for the
current target. Choose another analysis or target." as both message and
remediation. Choosing another target cannot satisfy a Linux-only profile
or an unset REA_*_COMMAND. The actual requirement appeared only in
details.reason.

Pass each refusal's reason as its userMessage, as the adapters' other
configuration refusals (EVMole limits, JADX, pwndbg) already do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:12:25 +00:00
6935dc7fe1 fix(ghidra): classify modern Swift manglings in swift type analysis (#1208)
* fix(ghidra): classify modern Swift manglings in swift type analysis

Categorize modern Swift 4.2+ manglings ($s, _$s) instead of dropping them
in analyze_swift_types. The classifier only accepted the legacy _Tt marker,
so procedure names reported by current providers produced an empty inventory.
Legacy _Tt families and behavior are unchanged. Fixes #1187.

* fix(swift): retain provider aliases and category unknowns

---------

Co-authored-by: Saim Shafique <sx4imm@gmail.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-09 16:10:55 +08:00
Kaoru0822andGitHub 04a516b1e3 Merge pull request #1222 from morluto/fix/ghidra-relative-java-probe
fix(ghidra): do not run Java from a relative JAVA_HOME in doctor and setup
2026-10-09 01:04:53 -07:00
Kaoru0822andGitHub 4b38d18995 Merge pull request #1221 from morluto/fix/exec-stop-signal-timeout
fix(process): stop timed-out commands with the caller's stop signal
2026-10-09 01:04:21 -07:00
Kaoru0822andClaude Opus 5.5 c3f169823f fix(ghidra): do not run Java from a relative JAVA_HOME in doctor and setup
The installation inspection rejected a relative JAVA_HOME, but only after
it had already probed `<JAVA_HOME>/bin/java` with spawnSync. `rea doctor`
and `rea setup` therefore ran whatever `jdk/bin/java` (or `bin/java` for
an empty JAVA_HOME) the current directory held, while reporting the
setting as rejected.

Skip the probe when JAVA_HOME is not absolute on the inspected platform.
The configuration check still reports the rejection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 07:59:38 +00:00
Kaoru0822andClaude Opus 5.5 063de5014f fix(process): stop timed-out commands with the caller's stop signal
execFileOutput forwarded stopSignal only together with an AbortSignal, so
a caller with just a timeout (the native UI helper's swiftc build) still
got Node's SIGTERM. When the timeout did send the stop signal, nothing
killed a process that ignored it, and a process that exited cleanly
after the signal resolved as a success.

A stoppable command now owns its timeout: it sends the stop signal,
kills the process after the grace period, and rejects with ETIMEDOUT
and killed: true.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 07:57:14 +00:00
morluto e6905c18e0 fix(website): identify publication verifier requests 2026-10-09 15:46:20 +08:00
YsopwnableandGitHub 9405bd660d fix(javascript): allow cancellation during semantic graph commitment (#1218)
Move whole-graph commitment and batched integrity checks into owned domain steps while retaining eager input capture, canonical IDs, full validation and completion-only immutable proofs.

Verified complete real Notion identity parity and actual stdio MCP cancellation, Evidence retention and connection reuse.

Refs #1065.
2026-10-09 15:15:17 +08:00
27a9ceade7 fix!: restore caching, preserve failures, and verify fixture claims (#1211)
Restore profile-bound Ghidra snapshot reuse, preserve direct-analysis results through cleanup failures, and grade configured agent fixture claims against returned evidence.

Register the compiled agent-evaluation fixture entry for static analysis.

Co-authored-by: YouWish <29498139+Y0UW1SH@users.noreply.github.com>
Co-authored-by: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com>
2026-10-09 14:49:09 +08:00
YsopwnableandGitHub c399670653 docs: keep the 30k milestone in Star History (#1217) 2026-10-09 14:45:59 +08:00
YsopwnableandGitHub 863674b2e9 feat(website): add homepage navigation and faster reading paths (#1213)
feat(website): add homepage navigation and faster reading paths
2026-10-09 14:33:47 +08:00
YsopwnableandGitHub c2d8146f94 docs: clarify REA has no affiliated cryptocurrency or token (#1214) 2026-10-09 14:25:32 +08:00
N0zoM1z0 c94f06d98f feat(website): add homepage navigation and faster reading paths 2026-10-09 14:03:00 +08:00
Kaoru0822andGitHub 5b769d3a78 Merge pull request #1201 from morluto/fix/ghidra-runtime-cleanup-retry
fix(ghidra): keep and name a runtime directory that close could not remove
2026-10-08 22:49:12 -07:00
Kaoru0822andGitHub 6987cb066a Merge pull request #1207 from morluto/docs/celebrate-30000-stars
docs: celebrate 30,000 GitHub stars 🎉
2026-10-08 22:48:54 -07:00
YsopwnableandGitHub 7e9c91199e fix(cli): resolve xrefs symbol selectors after address validation (#1209)
* fix(cli): resolve xrefs symbol selectors after address validation

* style(cli): format xrefs fallback call
2026-10-09 13:28:48 +08:00
N0zoM1z0 9db1fd0bd7 docs: thank feature request contributors 2026-10-09 13:02:26 +08:00
YsopwnableandGitHub 796b65e1cd ci(website): allow explicitly requested Pages-only publication (#1205)
ci(website): allow explicitly requested Pages-only publication
2026-10-09 13:00:26 +08:00
N0zoM1z0 beca9977eb docs: celebrate 30,000 GitHub stars 🎉 2026-10-09 12:58:16 +08:00
YsopwnableandGitHub 6051cb2c0c fix(setup): preserve initial backups and Codex comments (#1204) 2026-10-09 12:57:00 +08:00
N0zoM1z0 864160d885 ci(website): allow explicitly requested Pages-only publication 2026-10-09 12:46:17 +08:00
db675f1d52 feat(mcp): select views of retained analysis results (#1180)
Add explicit summary, facet, item and paged views of retained analysis Evidence without repeating analysis. Preserve captured observations, graph validation, artifact identity, coverage and complete default results.

Fixes #1050

Verified with focused source, CLI, pinned-SDK schema and MCP tests, serial static checks, and one complete native Windows Notion ASAR workflow. Real Hopper/Ghidra verification was not performed for this provider-independent projection change.

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
2026-10-09 12:45:48 +08:00
911152a04d fix(cli): complete cleanup after relayed interrupts (#1202)
* fix: Handle relayed SIGINT gracefully in withProcessCancellation

Changes `process.once` to `process.on` for SIGINT in `DirectAnalysis.ts`.
When REA is launched via npx, a single process-group SIGINT triggers two
SIGINT events (one direct, one relayed). Previously, the first event would
consume the handler and the second would abruptly terminate the Node process,
abandoning Ghidra resource cleanup.

This change ensures subsequent SIGINTs idempotently request cancellation
without crashing the process, matching the behaviour of `withCommandCancellation`.

* fix(cli): keep termination guards through provider cleanup

* test(cli): exercise repeated analysis signals on macOS

---------

Co-authored-by: N0zoM1z0 <1705004398@qq.com>
2026-10-09 12:45:23 +08:00
YsopwnableandGitHub 0fec65d06b feat(website): add beginner examples and synchronized publishing (#1203)
feat(website): add beginner examples and synchronized publishing
2026-10-09 12:41:51 +08:00
Kaoru0822andGitHub cf415619ca Merge pull request #1194 from morluto/fix/darwin-helper-compile-tmpdir
fix(process): stop cancelled Swift helper builds before removing their files
2026-10-08 21:21:32 -07:00
Kaoru0822andGitHub cfb49eb8a8 Merge pull request #1198 from morluto/fix/ghidra-extension-unsupported-host
fix(ghidra): report NativeAOT host and target refusals as unsupported, not failures
2026-10-08 21:21:18 -07:00
Kaoru0822andGitHub 8998438c23 Merge pull request #1200 from morluto/fix/doctor-setup-relative-provider-paths
fix(ghidra): reject relative installation and Java paths in doctor and setup
2026-10-08 21:21:04 -07:00
Kaoru0822andGitHub c3acc34475 Merge pull request #1199 from morluto/fix/config-error-names-setting
fix(config): name the rejected setting and its constraint in configuration errors
2026-10-08 21:20:48 -07:00
N0zoM1z0 761881cec3 ci(website): publish Cloudflare and Pages from one artifact 2026-10-09 12:19:38 +08:00
Kaoru0822andClaude Opus 5.5 b79d379c25 fix(ghidra): keep and name a runtime directory that close could not remove
When removing Ghidra's private runtime directory failed, close_binary
reported only a generic `provider-client` resource, and a later close,
after the permission was restored, returned success while the directory
and its contents remained. The client dropped its reference to the root
before removing it, and PrivateRuntimeRoot cached the rejected removal.

Keep each runtime or socket root until its removal succeeds, report a
failure as a ProviderCleanupError naming the leftover paths, let
PrivateRuntimeRoot retry a failed removal, and pass such typed cleanup
failures through closeAnalysisClient instead of replacing them.

Fixes #1190

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 04:19:10 +00:00
YsopwnableandGitHub 6fbdbd6820 fix(ghidra): resolve secondary symbols at function entries (#1195)
* fix(ghidra): resolve secondary symbols at function entries

* test(ghidra): derive interior bytes from decoded instructions
2026-10-09 12:19:07 +08:00
Kaoru0822andClaude Opus 5.5 53568568bf fix(ghidra): reject relative installation and Java paths in doctor and setup
A relative GHIDRA_INSTALL_DIR (or JAVA_HOME) that resolved from the current
directory passed doctor's Ghidra inspection, so doctor reported a healthy
provider and setup wrote the relative path into the MCP registration, but
REA's configuration parser rejects relative paths, so `providers`,
`capabilities` and the registered MCP server all failed.

The installation inspection's configuration check now applies the same
absolute-path rule, judged by the inspected platform's path syntax, and
names the relative setting. Doctor reports the provider unavailable with
that reason, and setup, which registers only an available inspection's
environment, no longer writes the path.

Fixes #1183

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 04:13:40 +00:00
Kaoru0822andGitHub f36c10f9e8 Merge pull request #1197 from morluto/fix/target-admission-access-denied
fix(domain): report target read-permission denials as access_denied
2026-10-08 21:13:32 -07:00
Kaoru0822andGitHub d39a450bdf Merge pull request #1196 from morluto/fix/target-truncated-headers
fix(native): refuse truncated executable headers at target admission
2026-10-08 21:13:15 -07:00
Kaoru0822andGitHub 98b07d07dd Merge pull request #1182 from morluto/fix/doctor-hopper-discovery-readonly
fix(doctor): find the Homebrew Hopper cask without writing Homebrew caches
2026-10-08 21:13:00 -07:00
Kaoru0822andClaude Opus 5.5 f198993f41 fix(ghidra): keep the NativeAOT target refusal's own recovery advice
An unsupported-target error always projected the generic "select a target"
remediation, which hid the adapter's available workflows (omit
REA_GHIDRA_NATIVEAOT_JAR for ordinary analysis, or use
inspect_managed_artifact). AnalysisUnsupportedTargetError accepts a
refusal-specific remediation, as AnalysisResourceConstraintError does, and
the NativeAOT refusal supplies its reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 04:09:50 +00:00
N0zoM1z0 54c0ed42aa chore: merge main before website publication 2026-10-09 12:09:29 +08:00
Kaoru0822andClaude Opus 5.5 0a0244db42 fix(config): name the rejected setting and its constraint in configuration errors
Every configuration failure projected the same message, "REA configuration
is invalid. Run `rea doctor` and fix the reported setting.", with no
details. The environment parser discarded the issue that names the variable
(for example `REA_GHIDRA_NATIVEAOT_JAR must be absolute`), and doctor can
report healthy for that environment, so neither the CLI, the MCP startup
message, nor doctor told callers which setting to correct.

ConfigurationError now carries the rejected settings and their constraints
(never their values). The projection names them in its message, lists them
in `details.settings`, and asks the caller to correct those settings where
REA is started. Errors without a named setting keep the previous message.

Fixes #1184

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 04:08:43 +00:00
Kaoru0822andClaude Opus 5.5 9f5dc52be8 fix(hopper): keep the OS error when the FAT64 source cannot be reopened
resolveHopperMachOImage built its BinaryTargetError without the open
failure as its cause, so a target that became unreadable after admission
still projected as `target_unavailable` instead of `access_denied`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 04:04:42 +00:00
Kaoru0822andClaude Opus 5.5 42c276af1e fix(ghidra): report NativeAOT host and target refusals as unsupported, not failures
With REA_GHIDRA_NATIVEAOT_JAR set on a host other than Linux, Ghidra
analysis was refused before Ghidra started, as intended, but the refusal
was a ProviderAdapterError: `execution_failure` with advice to retry and
run doctor, neither of which can change the host.

Adapters now say whether a refusal concerns the host or the target. A host
refusal is `capability_unavailable` whose message and remediation are the
adapter's reason (omit the JAR for ordinary analysis); a target refusal is
`unsupported_target` with the target path. Missing or malformed JARs on a
supported host remain provider failures.

Fixes #1185

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 04:03:10 +00:00
N0zoM1z0 291bc6fb70 feat(website): show manual analysis beside a one-prompt workflow 2026-10-09 12:02:58 +08:00
Kaoru0822andClaude Opus 5.5 facaae865a test(native): build the .app fixture executable with a complete Mach-O header
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 03:59:19 +00:00
Kaoru0822andClaude Opus 5.5 d0ff57a45c fix(domain): report target read-permission denials as access_denied
Opening a target the current user cannot read returned
`target_unavailable`, the same code as a missing target, although the
reason named EACCES. Clients that branch on the error code could not choose
read-access recovery, contrary to the boundary contract that separates host
permission denial from unavailable targets.

A BinaryTargetError whose cause is an OS EACCES or EPERM now records that
system code and projects as `access_denied` with `system_code`, the
filesystem-read boundary, and read-access remediation, while keeping its
specific reason and path. This covers target files, app bundle paths and
Info.plist reads, and selected plist reads, since every site passes the OS
error as the cause.

Fixes #1188

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 03:56:38 +00:00
Kaoru0822andClaude Opus 5.5 0b04d384cc fix(native): refuse truncated executable headers at target admission
Target admission accepted a thin Mach-O after reading only its magic and
CPU type, so a 12-byte prefix opened as a valid arm64 executable and the
first provider query failed as a generic execution failure. ELF headers
were likewise accepted after 20 bytes, and a FAT file whose selected slice
lies beyond its end was admitted.

Require the complete fixed header (Mach-O 28 or 32 bytes, ELF 52 or 64),
Mach-O load commands that fit in the file, and a selected FAT slice within
the file, checking commitments against the file size rather than the
probed prefix. Each refusal names the failed constraint.

Fixes #1189

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 03:51:37 +00:00
Kaoru0822andGitHub e6abaefbbc Merge pull request #1179 from morluto/fix/session-client-metadata-2025
fix(server): report 2025-era client identity and features in binary_session
2026-10-08 20:51:34 -07:00
Kaoru0822andGitHub f5539cfc2f Merge pull request #1178 from morluto/fix/codex-toml-preserve-comments
fix(setup): keep Codex TOML comments when adding or removing REA
2026-10-08 20:51:15 -07:00
2a620c06cd fix(javascript): resolve package exports targets only to the exact file (#1181)
A selected package exports target names one file, and Node tries no
extension or directory index for it. REA still resolved it like a relative
specifier, so `exports: "./file"` with only `file.js` present, or
`"./folder"` with only `folder/index.js`, reported a resolved import that
Node rejects under both import and require.

Resolve an exports target only to its exact file and otherwise report
not-found with a limitation naming the target. Legacy main entries keep
their extension and index fallbacks.

Fixes #1174

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:49:32 +08:00
N0zoM1z0 e750c262fb feat(website): clarify reverse engineering and showcase goals 2026-10-09 11:46:06 +08:00
Kaoru0822andClaude Opus 5.5 c717204795 fix(process): stop cancelled Swift helper builds before removing their files
Cancelling the macOS process-ownership helper build left swiftc object files
in TMPDIR. Node's execFile sends SIGTERM on abort and rejects before the
child exits, and swift-driver runs each frontend job in its own process
group: on SIGTERM the driver exits while a job keeps writing, so REA removed
its root while objects were still being written outside and inside it.

Add an opt-in `stopSignal` to execFileOutput that stops the process with the
caller's signal on abort or timeout and settles only after it exits. Swift
helper builds stop swiftc with SIGINT, on which swift-driver stops its jobs
and deletes their objects, and point TMPDIR inside the root cleanup removes.

Fixes #1173

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 03:43:43 +00:00
YsopwnableandGitHub e1afbc1914 perf(mcp): reuse input schemas without losing caller guidance (#1162) 2026-10-09 11:38:07 +08:00
Kaoru0822andClaude Opus 5.5 a503376b2f fix(doctor): find the Homebrew Hopper cask without writing Homebrew caches
`rea doctor`, documented as strictly read-only, ran
`brew --prefix --cask hopper-disassembler` when Hopper was not in a
standard location. Current Homebrew rejects that option combination, but
any brew command naming a cask first fetches the cask API, so each doctor
run wrote about 600 files (36 MB) into the user's Homebrew cache.

Ask brew only for its Caskroom, which brew answers without loading the
cask API, and read the application directory Homebrew recorded in the
Hopper cask's install receipt.

Fixes #1165

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 03:28:25 +00:00
Kaoru0822andGitHub 4fb2f3e6ed Merge pull request #1177 from morluto/fix/uninstall-preflight-client-config
fix(setup): stop uninstall before removals when a client config is unsafe
2026-10-08 20:22:34 -07:00
Kaoru0822andGitHub d8e314cb24 Merge pull request #1176 from morluto/fix/session-availability-active-target
fix(session): require an open target for session-bound native and artifact tools
2026-10-08 20:22:23 -07:00
N0zoM1z0 19c52f5e3f feat(website): lead with the playable dinosaur example 2026-10-09 11:21:18 +08:00
Kaoru0822andClaude Opus 5.5 b8312fa8d1 fix(server): report 2025-era client identity and features in binary_session
binary_session read the client's identity, protocol revision, and
capabilities only from the 2026-era per-request envelope. A 2025-era
connection sends none, so every such client was reported as `client: null`
with no negotiated protocol and no features, although it declared them in
`initialize`.

When a request carries no envelope, read the values the SDK keeps from the
connection's initialize handshake. An envelope still takes precedence.

Fixes #1167

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 03:20:43 +00:00
Kaoru0822andClaude Opus 5.5 fd975c75fa fix(setup): stop remaining uninstall removals after a client fails
A configuration that passes the preflight can still fail when uninstall
rereads it to edit, for example when it changes concurrently. Rereading
keeps that edit from overwriting the newer file; stopping at the failure
keeps later clients, the skill, and REA data from being removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 03:17:11 +00:00
Kaoru0822andClaude Opus 5.5 e9c48a61e4 fix(setup): keep Codex TOML comments when adding or removing REA
Setup and uninstall rewrote the whole Codex config.toml with a fresh TOML
serializer, which dropped every comment and respelled unrelated values,
although the plan promises to preserve unrelated configuration. Grok Build
already edited only REA's server tables.

Share that table editor with Codex, without Grok's root
disabled_mcp_servers handling, keep the original final line break, and
fall back to the full rewrite only when the edited text would not parse to
the requested document.

Fixes #1163

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 03:15:18 +00:00
b4927a0a4f fix(cli): advertise defaulted inputs as optional in --schema and help (#1175)
Incur derives `--schema`, the `--llms` manifests, and help synopses from
Zod's output view, where a defaulted field always has a value, so every
defaulted argument and option was listed as required even though the CLI
accepts its omission. Wrap each field that fills an omitted value as
optional after registration, keeping its default, constraints, metadata,
and parsed value.

Fixes #1169

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:11:11 +08:00
Kaoru0822andClaude Opus 5.5 5cc841d5c1 fix(setup): stop uninstall before removals when a client config is unsafe
The installation guide says malformed client configuration stops
`rea uninstall`, but uninstall reported that client as failed and still
removed other clients' registrations, the bundled skill, and with
--purge-data REA's cache and state.

Inspect every client configuration first, using the conditions setup
already treats as blocking (unsafe path, unreadable file, malformed
document), and stop before any removal when one fails. Purge paths that are
symbolic links are still retained and reported per item, as the guide now
states.

Fixes #1164

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 03:07:40 +00:00
N0zoM1z0 11b9f0346c feat(website): explain REA with Calculator and a playable dinosaur lab 2026-10-09 11:06:05 +08:00
Kaoru0822andClaude Opus 5.5 cf77d073fc fix(session): require an open target for session-bound native and artifact tools
binary_session reported native and artifact operations available whenever
their provider declared them, although these operations run on the active
target: in a closed session every call failed with target_unavailable, and
Mach-O-only operations stayed available with a ZIP or ELF target open.

Report target_required for every session-bound contract kind in a closed
session, and target_unsupported for Mach-O-only operations unless the open
target is a Mach-O executable. A host limitation is reported before target
selection, since opening a target cannot fix it; composed operations keep
deciding from their requirements.

Fixes #1166

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 03:02:40 +00:00
Kaoru0822andGitHub de5bfec79f Merge pull request #1172 from morluto/fix/macho-arm64e-variant-slices
fix(artifacts): match lipo arm64e variant names to their FAT slices
2026-10-08 19:42:05 -07:00
Kaoru0822andGitHub 37025cc09f Merge pull request #1171 from morluto/fix/extraction-preflight-cancellation
fix(artifacts): keep cancellation and the caller path in extraction refusals
2026-10-08 19:38:56 -07:00
Kaoru0822andClaude Opus 5.5 0b32577a90 fix(artifacts): match lipo arm64e variant names to their FAT slices
Newer lipo names arm64e ABI variants `arm64e.<variant>`: `arm64e.v1` for
pointer-auth ABI version 1 on freshly built universal binaries, and
`arm64e.x1` on recent macOS system binaries such as /bin/ls. The
structural FAT parser names the same slice `arm64e`, so the exact name
comparison failed and inspect_artifact reported a valid, unmodified
universal binary as an integrity mismatch ("Artifact is invalid or has
changed").

Accept `arm64e.<variant>` for an `arm64e` FAT slice. Offset, size, CPU
type, subtype (including the pointer-auth version bits when lipo prints
them) and alignment are still compared field by field. The slice keeps
lipo's name in its logical path.

Fixes #1168

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 02:37:03 +00:00
Kaoru0822andClaude Opus 5.5 eacf8461da fix(artifacts): keep cancellation and the caller path in extraction refusals
Two follow-ups to #1161 from its post-merge review:

- The new format preflight ran before scanArtifactInventory, which was
  the first cancellation check. An already-cancelled extraction of a
  DMG or PKG therefore reported unsupported_target instead of
  cancellation. Check the signal before the preflight.
- The unsupported-format and encrypted-entry refusals reported the
  realpath. When the caller selected the target through a symlink,
  junction, or other alias, the diagnostic named a different path.
  Report the caller's input path; I/O still uses the canonical path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 02:33:16 +00:00
Kaoru0822andGitHub b34bdcdb28 Merge pull request #1161 from morluto/fix/artifact-unsupported-target-errors
fix(artifacts): report wrong target kinds as unsupported targets
2026-10-08 19:30:54 -07:00
Kaoru0822andClaude Opus 5.5 de43da71ae fix(artifacts): report encrypted archive entries as unsupported extraction
extract_artifact on a ZIP containing a password-protected entry failed
the whole extraction with "Artifact is invalid or has changed. Get a
fresh copy" and named only an opaque occurrence ID. The archive was
intact; REA does not decrypt entries, so complete extraction is
unsupported for this target.

Raise AnalysisUnsupportedTargetError naming the encrypted entry's path.
Other unextractable occurrences keep their format failure but now name
the logical path alongside the occurrence ID.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 02:23:44 +00:00
Kaoru0822andGitHub 6a1e558db3 Merge pull request #1159 from morluto/fix/dylib-resolution-root-input-errors
fix(apple): report unusable dylib-resolution roots as invalid input
2026-10-08 19:23:22 -07:00
Kaoru0822andClaude Opus 5.5 8e74c9c62f fix(artifacts): refuse unsupported extraction formats before scanning
extract_artifact on a format without an extraction reader, such as a
DMG, first ran the full inventory scan (mounting the image) and then
failed with an `unavailable` artifact failure: "Check artifact support
and required tools". The target format, not the host, is unsupported.

Check the format before any inventory or output work and raise
AnalysisUnsupportedTargetError, which the provider now keeps, as it does
for the other target-kind checks in this PR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 02:21:22 +00:00
Kaoru0822andClaude Opus 5.5 44d5b4b25e test(artifacts): assert asset-catalog target refusal only on macOS
Outside Darwin the session reports inspect_asset_catalog as unavailable
on the host before the provider checks the target kind, so the Linux
test shards would see capability_unavailable rather than
unsupported_target.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 02:21:21 +00:00
Kaoru0822andClaude Opus 5.5 637bcb5e41 fix(artifacts): report wrong target kinds as unsupported targets
decode_interface_builder, inspect_asset_catalog, inspect_keyed_archive
and trace_dylib_resolution refused a target of the wrong kind (for
example a plain Mach-O for the asset catalog, or a plist for dyld
tracing) as an `unavailable` artifact failure: "Artifact processing is
unavailable for the current target or host. Check artifact support and
required tools." Nothing was missing on the host; the operation does not
support that kind of target.

Raise AnalysisUnsupportedTargetError for these checks and let
translateFailure keep it. The result is now `unsupported_target`, naming
the operation, the target path and the requirement, with advice to pick
a supported target or another operation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 02:16:57 +00:00
YsopwnableandGitHub 33d5ae0b52 fix(hopper): reserve Linux demo application before launch (#1158)
* test(hopper): give locals oracle explicit stack storage

* fix(hopper): reserve Linux demo application before launch

* fix(hopper): serialize stale lease recovery
2026-10-09 10:14:25 +08:00
Kaoru0822andClaude Opus 5.5 24a30fd91c fix(apple): report unusable dylib-resolution roots as invalid input
trace_dylib_resolution blamed the artifact for the caller's root
selection. A missing root, a directory, or a symlink leading outside the
bundle got "Artifact contains an unsafe or conflicting internal path ...
correct the artifact". A non-Mach-O file such as Contents/Info.plist got
"Artifact is invalid or has changed. Get a fresh copy". Any schema
failure, including a bad architecture, was reported as "roots must be
normalized paths".

Report a caller-selected root that cannot be traced as an
invalid_request issue on roots[i] with the failed constraint, and
project schema failures through their real issues. The normalized-path
rule now carries a readable message. Roots REA derives itself (bundle
executables or the active target) keep reporting artifact failures.
This matches what #1070 did for inspect_keyed_archive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 02:12:58 +00:00
b620e2a2bd fix(javascript): omit self-referential static references with disclosure (#1157)
* fix(javascript): omit self-referential static references with disclosure

A bundled module that requires its own key (`r(50)` inside webpack
module 50) resolved, through the static-reference composer, to its own
module node. The resulting self-referential imports edge failed result
validation and lost the entire analysis ("Result schema rejected 1
issue ... (custom)"). This is the same invariant as #1146; #1152 fixed
the bundler async-chunk composer, and this is the remaining adjacent
composer.

Skip a reference whose resolved target is its own source, count it, and
disclose the omission the way #1152 discloses async-chunk references.
Sibling requires are kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(javascript): share the self-reference omission disclosure

The self-import (#1130), async-chunk (#1152) and static-reference
disclosures repeated one sentence template in three composers, and the
new test repeated the analyze-and-check sequence of its neighbour. That
put jscpd at its 2.5% threshold. Share the template through
selfReferenceOmissions with identical wording, and share one test helper
for the graph-wide self-reference invariants.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:01:59 +08:00
58a91f03d7 fix(artifacts): recheck failed DMG detaches before reporting cleanup failure (#1155)
* fix(artifacts): recheck failed DMG detaches before reporting cleanup failure

NativeDmgArtifactReader.close() detached each device once and, when a
detach failed, asked `hdiutil info` once whether the device was still
attached. On APFS images, detaching the synthesized container ejects the
image disk too. `hdiutil info` can still list that ejected device
briefly, and a just-read volume can report busy. Either way a real
cleanup succeeded but close() reported "DMG detach or mount-root cleanup
failed" and kept the mount root.

macOS CI hit this intermittently in verify:macos-bundle: `hdiutil
detach /dev/disk23` failed with "No such file or directory" (already
ejected) and the device was still counted as attached. The #1103
review also raised the missing recheck.

After the first pass, recheck the remaining devices up to three times
with 250/500/1000 ms settle delays. Drop any that hdiutil no longer
lists, retry the detach of any still listed, and fail only for devices
that stay attached. The host seam gains an optional delay so tests run
without real waits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(artifacts): share DMG detach fixtures to stay under the duplication gate

The new busy-device and recheck cases copied the fake hdiutil host and
the APFS close sequence from neighbouring tests, which pushed jscpd to
its 2.5% threshold in Static checks. Share one single-device host
between the busy and retained-attachment cases and one APFS close
helper between the ejected-device cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:01:52 +08:00
N0zoM1z0 5160d9b717 feat(website): explain REA through a first investigation 2026-10-09 10:00:22 +08:00
089bbf58f3 fix(cli): cancel routed JavaScript analysis in rea analyze (#1156)
`rea analyze PATH` routes a JavaScript directory or ASAR to the same
static analysis as `rea analyze-javascript-application`, but it passed
no signal and was not wrapped in withCommandCancellation. On SIGINT the
process was killed with no output (signal SIGINT, empty stdout).
The dedicated command returns a typed `cancelled` result and exits 130.
The #1098 review raised this route.

Decide the route first. A JavaScript target now runs exactly like the
dedicated command: cancellation wraps logging, so the cancelled exit
code is not replaced by the logged failure status. The binary route is
unchanged and keeps its own SIGINT handling in runDirectAnalysis.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:48:10 +08:00
YsopwnableandGitHub 72201668ed fix(javascript): preserve graphs with async chunk self-references (#1152) 2026-10-09 09:37:37 +08:00
Kaoru0822andGitHub 84094af54a Merge pull request #1151 from morluto/docs/readme-french
docs: add French README translation
2026-10-08 18:34:31 -07:00
YsopwnableandGitHub 16624f1324 fix(evidence): cancel exports before atomic publication 2026-10-09 09:29:22 +08:00
Kaoru0822andClaude Opus 5.5 9664b2b101 docs: add French README translation
Adds README_fr.md, translated from the current English README with the
same commands, links, heading structure and FAQ entries. Links Français
from every README language selector and registers it in the README
consistency matrix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:21:53 +00:00
morluto 2609352eef chore(release): preserve concurrent main updates 2026-10-09 09:17:44 +08:00
morluto 90f532feb1 chore(release): sync published 6.1.0 checkpoint 2026-10-09 09:16:40 +08:00
YsopwnableandGitHub e9ebfb94ef fix(android): validate engine archive prerequisites (#1145)
* fix(android): validate engine archive prerequisites

* fix(android): bound engine metadata reads before allocation
2026-10-09 09:15:33 +08:00
Andrew BarnesandGitHub 13935077ba fix(browser): report Windows HAR heap exhaustion (#1147)
Recognize exit code 134 without a signal when the HAR decoder reports
V8 heap exhaustion. Preserve the observed termination in the memory
failure and cover Windows, POSIX, and unrelated decoder failures.
2026-10-09 09:13:00 +08:00
github-actions[bot]GitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
ae9aaee16b chore(release/6.1.0): release rea-agents 6.1.0 (#1144)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-10-09 08:51:58 +08:00
morluto cdddfddf49 fix(release): publish reviewed release PR merges 2026-10-09 08:47:00 +08:00
YsopwnableandGitHub 441813c070 perf(mcp): share repeated output schema definitions 2026-10-09 08:46:59 +08:00
morluto c12bad7f13 fix(release): publish reviewed release PR merges 2026-10-09 08:44:47 +08:00
github-actions[bot]GitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>morluto
70e5c24718 chore(main): release rea-agents 6.1.0 (#1106)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-09 08:15:17 +08:00
morluto 283c82f68c revert(test): remove duplicated application workflow acceptance tests
Commit 5ac3dc96 re-added application workflow scenarios under tests/acceptance/applications that are already covered under tests/boundary (mcp, filesystem, process) via the shared tests/fixtures/applicationMcpHarness.js fixture, per the boundary classification in 0e0b386d. The duplicates added no new coverage and pushed the jscpd duplication gate over its 2.5% threshold, failing CI static checks.
2026-10-09 08:03:13 +08:00
morluto c29d85a7db chore: clarify local Cloudflare ignore comment and wrap website deploy note 2026-10-09 08:00:11 +08:00
morluto b7d803dd10 fix(cli): drive mcp doctor help from a single option schema
Parses rea mcp doctor arguments against one zod option schema that is also the help renderer's source of truth, answering --help/-h in any position without starting a diagnostic session and keeping actionable errors for unknown options and invalid formats. Updates the landed help assertion to the schema-rendered format list and adds boundary coverage for help positioning and --format edge cases.
2026-10-09 08:00:07 +08:00
morluto 5ac3dc96f0 test(acceptance): add application workflow MCP parity harness and scenarios
Adds an owned in-memory MCP harness plus acceptance coverage for trace/compare/export-shape workflows over inline and recorded Evidence, including rejection of mismatched evidence references and spoofed providers. All 16 scenarios pass on the current base.
2026-10-09 08:00:00 +08:00
morluto 96af2fa744 fix(browser): preserve captures when response bodies are unavailable 2026-10-09 07:47:34 +08:00
morluto 67756dacc0 fix(ci): align diagnostic regressions and format merged changes 2026-10-09 07:45:49 +08:00
morluto 80c3d36dfa fix(ghidra): preserve POSIX runtime paths with spaces 2026-10-09 07:29:17 +08:00
morluto c715af8058 fix(android): report actual provider readiness 2026-10-09 07:29:17 +08:00
morluto 55c9ce26d1 test(cli): verify self-import parity and cleanup 2026-10-09 07:29:16 +08:00
morluto a69b8337ab fix(cli): support MCP doctor help 2026-10-09 07:29:16 +08:00
morluto 1d9b96a9c4 fix(cli): preserve web cancellation exit status 2026-10-09 07:29:15 +08:00
morluto 3e598b2d38 fix(ghidra): admit Linux arm64 with matching native tools 2026-10-09 07:29:15 +08:00
morluto 1f79002497 docs: clarify contribution scope and cosmetic suggestions 2026-10-09 07:28:47 +08:00
d84bc8f11a feat(ghidra): make the startup deadline configurable (#974)
* feat(ghidra): make the startup deadline configurable

Large binaries (an 8 MB PE with about 20,000 functions) need more than the
fixed 330 s for import and full auto-analysis, so every first request timed
out. REA_GHIDRA_STARTUP_TIMEOUT_MS overrides the deadline in milliseconds;
absent, empty or invalid values keep the 330 s default.

* docs(ghidra): document REA_GHIDRA_STARTUP_TIMEOUT_MS

* fix(ghidra): parse startup deadlines through runtime configuration

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-09 07:21:36 +08:00
65a809a0da fix(process): avoid cold ownership helper deadline exhaustion (#1139)
* fix(process): avoid cold ownership helper deadline exhaustion

Fixes #1137.

* test(process): fix cold ownership test deadlines and cleanup

* fix(process): isolate Swift cache overrides and retain diagnostics

* test(electron): assert blank path rejection without trim assumptions

---------

Co-authored-by: Chris <Chis@RICH-13918M.local>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-09 07:18:07 +08:00
morlutoandRudy Mizrahi Celekli 4034883e98 fix(artifacts): preserve keyed archive integer precision
Integrate the numeric precision correction from #1135 with complete supplemental
metadata handling. Keep decoded numbers with an explicit limitation for mixed XML
content or unclassified integer text, rather than assigning another literal's
exact decimal. Project nonnumeric UID and CF$UID dictionary values recursively
while preserving numeric references, graph identity and original byte digests.

Add filesystem, built CLI and MCP regressions for the review findings, adjacent
XML representations and numeric reference controls. Retain the original native
Foundation qualification fixtures and verifier.

Verification: 84 focused tests; npm run check; npm run docs:check;
npm run verify:test-discovery; npm run verify:keyed-archive (real Foundation,
CLI and stdio MCP). No real Hopper or Ghidra verification was needed or run.

Co-authored-by: Rudy Mizrahi Celekli <47457359+rudycelekli@users.noreply.github.com>
Signed-off-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-09 07:13:32 +08:00
1d7115b7b4 fix(javascript): omit self-referential import edges with disclosure (#1130)
* fix(javascript): omit self-referential import edges with disclosure

A specifier that resolves back to the importing module itself produced an
imports edge from a module to itself, which the application graph schema
forbids; one such specifier failed result validation and lost the whole
analysis. Skip those edges at composition time and disclose the omission
count in the graph limitations.

Fixes #1129

* test(javascript): verify self-import behavior through the compiled CLI

---------

Co-authored-by: BaaRai <baarai@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-09 07:10:38 +08:00
c1d0002470 test(browser): pin DOM and source-map URL policy classifications (#1120)
* test(browser): pin DOM and source-map URL policy classifications

Cover the unsupported DOM scope, credentialed destinations, and the source-map fetcher's pre-request filtering of credentials, other origins and non-http(s) URLs, so a later vocabulary unification can show exactly what changes.

Refs #829

* test(browser): assert exact sanitized credentialed DOM URL

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-09 06:57:40 +08:00
e8939ca220 fix(hopper): enforce caller-supplied request deadlines (#1119)
* fix(hopper): enforce caller-supplied request deadlines

* fix(hopper): correct idle deadline state and name timeout bound

Zero-ms deadlines never enter the FIFO, so report providerState
not_started instead of busy; the busy wording tells callers to wait
for an active request that does not exist. Name the Node timer
ceiling once and reuse it in validation and the error message.

* fix(hopper): enforce elapsed deadlines before dispatch and replies

* fix(hopper): distinguish unsent requests in timeout diagnostics

* test(hopper): exercise request deadlines against native Hopper

---------

Co-authored-by: Vilmer Frost <frost.vilmer@gmail.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-09 06:52:07 +08:00
329cf206d1 fix(hopper): preserve owned basic-block endpoint instructions (#1118)
* fix(hopper): preserve owned basic-block endpoint instructions

* test(hopper): share probe runner and restore fixture hashability

Reuse one probe helper with the facade test's execFile options
(encoding, timeout, maxBuffer) instead of repeating the invocation.
Give the fixture Block a hash consistent with its equality so the
equality-based ownership doubles stay hashable.

* fix(hopper): align owned instruction walks with normalized block ranges

---------

Co-authored-by: Vilmer Frost <frost.vilmer@gmail.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-09 06:51:53 +08:00
morluto 2b27515476 fix(process): stabilize native capture and ownership prerequisites 2026-10-09 06:49:02 +08:00
morluto 44fd18305f fix(capture): retain Electron observations and HAR resource failures 2026-10-09 06:49:02 +08:00
morluto 6c13fc8e0a fix(android): report startup and selector failure causes 2026-10-09 06:49:02 +08:00
morluto 70e8a8f860 fix(contracts): preserve local inputs and comparison uncertainty 2026-10-09 06:49:02 +08:00
morlutoandArad Ashkan 7a7460f04f docs: add Persian README translation with full language navigation
Adds README_fa.md (Persian/Farsi) contributed via PR #1140, keeps onboarding commands, links, and structure aligned with English, links فارسی from every translated selector, and registers fa in the readme consistency matrix.

Co-authored-by: Arad Ashkan <65897590+AradAshkan@users.noreply.github.com>
2026-10-09 06:44:02 +08:00
morluto b3f1b4e822 fix(mcp): retain oversized errors before transport delivery 2026-10-09 06:39:12 +08:00
morluto 480b16b9c1 fix(ghidra): parse long procedure selectors without recursion 2026-10-09 06:39:12 +08:00
morluto e762e32afb refactor(browser): charge source-map records before retention 2026-10-09 06:32:10 +08:00
morluto f7366a517f fix(verify): close both sides of the browser proxy 2026-10-09 06:32:10 +08:00
morluto faf209e50d fix(browser): bound script metadata and preserve omissions 2026-10-09 06:32:10 +08:00
morluto 0a0174b9ac fix(browser): validate and bound source-map evidence 2026-10-09 06:32:10 +08:00
morluto e1df5e8555 fix(apple): account for repeated archive projections 2026-10-09 06:32:10 +08:00
morluto d575a7340b fix(apple): decode bundle plist bytes before executable lookup 2026-10-09 06:32:09 +08:00
morluto 6495171812 fix(javascript): classify direct defaults and argv elements 2026-10-09 06:32:09 +08:00
morluto 14b19a0b8a fix(native): resample tool identity for each invocation 2026-10-09 06:32:09 +08:00
9fd65ce071 fix(setup): treat empty client config files as new documents (#1117)
* fix(setup): treat empty client config files as new documents

An empty MCP config file (for example Antigravity's mcp_config.json, which
the client can create with zero bytes) was reported as malformed, which
blocked rea setup from configuring every other detected agent. Parse a
whitespace- or BOM-only JSON/JSONC file as an empty document and write a
fresh document over it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(setup): use explicit unicode escape for BOM-only empty config case

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-09 06:30:46 +08:00
567a82f8d4 fix(update): accept npm 12 release metadata (#1138)
* fix(update): accept npm 12 release metadata

(cherry picked from commit aa400d18c95e36029c5c654c396ec66924e1358f)

* fix(update): classify npm release metadata without a spawn mock

Keep the npm 11 string and npm 12 one-element array accepted by the
cherry-picked lookup, and separate invalid metadata from a failed
registry command.

---------

Co-authored-by: Dapo Olaomo <penielgold@gmail.com>
2026-10-09 06:29:29 +08:00
morluto 82626c4499 fix(hopper): bind file mappings to verified source bytes
Read source digests, FAT tables and embedded headers from one opened source stream before translating native offsets. Preserve native mapping observations through changed, missing, nonregular and access-denied source failures; keep filesystem work outside the Hopper API thread.

Exercise source drift, relocated slices, missing files, permissions and recovery through real Hopper CLI/MCP verification for thin, FAT32 and FAT64 inputs.
2026-10-09 06:13:41 +08:00
morluto ae06dcf83f test: prune resource-recovery wording assertions 2026-10-09 06:13:41 +08:00
08561e0eb7 feat(clients): register Grok Build and Grok Bot during setup (#1134)
* feat(clients): register Grok Build and Grok Bot during setup

Detect both clients and install the local REA MCP registration the same
way setup already handles the other agents. Grok Build edits only the
REA tables in its TOML config and sets startup_timeout_sec to 30. Grok
Bot writes the mcpServers.rea entry into mcp.json. That file is the
registration to add to the signed-in account; setup does not call the
account API.

Filed by Grok.

* fix(clients): clear a disabled Grok Build registration during setup

Grok Build keeps a server suppressed when its name stays in
disabled_mcp_servers, and setup was treating that file as already aligned.
Setup now removes only that name, doctor reports the registration stale until
it is gone, and uninstall keeps comments in an inline table whose only server
was REA. Split the lifecycle suite and reflow the get-started page so static
checks pass.

* fix(verify): check packed Hopper search as literal-only

The package verifier still called a regex probe that main deleted. The
native bridge refuses regex and joins string hits with typed records, so
the restored probe stubs that inventory and the check asserts the literal
matches and the regex refusal. The new README translations also name
Grok Build and Grok Bot.

* fix(clients): stop treating a Grok Bot data directory as registered

Grok Bot stores connectors in the signed-in account and runs them on its
hosted computer. Setup no longer writes mcp.json or reports that file as
aligned. Doctor and setup tell the caller to add the server from the
Grok Bot chat.

* fix(clients): drop multiline Grok disable-list entries

Decode disabled_mcp_servers strings with the document parser so a
multiline basic or literal string that loads as rea is removed.

---------

Co-authored-by: Grok <eugene.ray@gmail.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-09 06:08:29 +08:00
morluto 0639a541a3 fix(mcp): preserve retained evidence on oversized delivery 2026-10-09 05:55:55 +08:00
morluto 826583dd43 fix(verify): remove stale mocked bridge package probe 2026-10-09 05:54:10 +08:00
morluto c3136064c7 fix(cli): accept exact native names through explicit selectors 2026-10-09 05:46:16 +08:00
morluto 2a4979b7cd docs: move Portuguese toward the end of language navigation 2026-10-09 05:35:05 +08:00
morluto a61491ad00 docs: add ten README translations and expand language navigation 2026-10-09 05:33:36 +08:00
morluto 2847311a57 fix(hopper): normalize native block endpoints and retain terminal evidence 2026-10-09 05:31:49 +08:00
morluto 4458128a84 fix(ghidra): make qualified function renames idempotent 2026-10-09 05:27:39 +08:00
morluto 34f7c4fd66 fix(docs): validate translated links to canonical product facts 2026-10-09 05:15:23 +08:00
morluto 67252b23b9 perf(javascript): index configuration and module lookups 2026-10-09 05:15:23 +08:00
morluto 02d0702761 fix(electron): bound hook retention and report dropped coverage 2026-10-09 05:15:23 +08:00
morluto e714fb027a fix(inspector): bound retained metadata and preserve cancellation 2026-10-09 05:15:23 +08:00
morluto f983c718c3 fix(browser): bound aggregate source-map decoding before expansion 2026-10-09 05:15:23 +08:00
morluto 3d450a29fc fix(application): budget bridge candidate projection by bytes 2026-10-09 05:15:23 +08:00
morluto 73b09f4c5c fix(managed): bind inspection evidence to artifact identity 2026-10-09 05:15:23 +08:00
morluto dbcf8c3391 fix(apple): budget Interface Builder decoding and projection 2026-10-09 05:15:23 +08:00
morluto f2e9c491ea fix(native): share command supervision and retain failure output 2026-10-09 05:15:23 +08:00
morluto 4a45c14742 fix(firmware): reject malformed UTF-8 producer reports 2026-10-09 05:15:23 +08:00
morluto 2b86ea9c7c docs: require partial native facts at provider boundaries 2026-10-09 05:12:36 +08:00
morluto f201b04fbb fix(hopper)!: isolate regex matching from the native API thread
BREAKING CHANGE: Hopper regex mode uses ECMAScript Unicode syntax instead of Python re. Matching runs in a cancellable worker with a five-second deadline; literal mode keeps Unicode casefold matching.
2026-10-09 05:12:36 +08:00
morluto 246170238e fix(hopper): preserve partial native call and string evidence 2026-10-09 05:12:36 +08:00
morluto 0a49d5bfb9 fix(hopper): load verified FAT64 slices with native Mach-O semantics 2026-10-09 05:12:36 +08:00
morluto 458771cb58 fix(hopper): preserve launcher evidence on readiness timeout 2026-10-09 05:12:36 +08:00
morluto 7d7b3f961a fix(hopper): preserve typed string values and verify real searches 2026-10-09 05:12:36 +08:00
morluto 35f1ddd6bc fix(hopper): resolve FAT loaders and original file coordinates 2026-10-09 05:12:36 +08:00
morluto b2d5bc1109 fix(hopper): validate annotation destinations and symbol extents 2026-10-09 05:12:36 +08:00
morluto 704fa7699c fix(ghidra): preserve source failures and snapshot ownership 2026-10-09 05:10:36 +08:00
morluto 2f59287f1a feat(website): add GitHub link with live star count 2026-10-09 04:55:51 +08:00
morluto d83f0983d5 docs: align translated READMEs and website links with English 2026-10-09 04:55:43 +08:00
morluto 1136ea8810 test(session): preserve live binding after cancelled switches 2026-10-09 04:43:19 +08:00
morluto e44cb45908 fix(session): serialize snapshot lifecycle with admitted requests 2026-10-09 04:37:43 +08:00
morluto 8d39eae6b9 chore(website): configure Cloudflare hosting for rea.tools 2026-10-09 04:29:57 +08:00
morluto 09d7b9bab5 test(process): cover argv rewrites in native ownership inspection 2026-10-09 04:12:49 +08:00
morluto 9a70fb482c test(process): distinguish native startup from producer verification 2026-10-09 04:12:49 +08:00
morluto f591e37a1e test(artifacts): retire simulated mounts after detach failures 2026-10-09 04:12:49 +08:00
morluto a0784c0d2c test(process): retire native caches at worker teardown 2026-10-09 04:12:49 +08:00
morluto 96d3cafb07 fix(browser): bind correlated replies to their selected session 2026-10-09 04:12:49 +08:00
morluto ee043e2cbf fix(verify): report final success only after resource cleanup 2026-10-09 04:12:49 +08:00
morluto 3eb7dbdc16 fix(verify): isolate package archives and published canary caches 2026-10-09 04:12:49 +08:00
morluto 90b06db6c0 test(process): expose unavailable capture and unexpected teardown failures 2026-10-09 04:12:49 +08:00
morluto 6b92002597 fix(browser): preserve command failures and reject malformed replies 2026-10-09 04:12:48 +08:00
morluto bc4aa46d7c fix(ghidra): recover regex stack exhaustion without losing annotations 2026-10-09 03:54:11 +08:00
morluto 549effa056 fix(ghidra): resolve exact external function entries 2026-10-09 03:54:02 +08:00
morluto dcae3c6c14 fix(ghidra): reject address truncation before reads and edits 2026-10-09 03:53:28 +08:00
morluto 84a17d5519 fix(ghidra): preserve function references and snapshot boundaries
Collect references from the complete owned function body and exact entry,
including instruction-interior destinations and embedded-data sources.
Bind the corrected semantics to the analysis profile so legacy snapshots
cannot replay incomplete results. Preserve snapshot mismatch reasons and
recovery advice through CLI and MCP without disturbing live sessions.

Return exact entry candidates for ambiguous function names. Expand the
real-provider regression workflow and replace redundant parser assertions
with malformed-output coverage through the pinned MCP client.

Verified with Ghidra 12.1.4 on macOS arm64: full host-native lane, real
CLI/MCP boundary probes, 30 focused tests, and typecheck/lint.
2026-10-09 03:19:47 +08:00
morluto 017297c40c test(browser): reject unmodeled CDP commands in protocol fixtures 2026-10-09 03:13:53 +08:00
morluto ffd9611308 test: consolidate failure guards and trim unused fixture APIs 2026-10-09 03:13:43 +08:00
morluto 81ae838567 refactor(config): prune unused format wrappers and launcher export 2026-10-09 03:13:27 +08:00
YsopwnableandGitHub d1c904bac7 fix(build): exclude the test-only generated catalog from packages (#1116) 2026-10-09 03:02:07 +08:00
morluto 8f9da25164 test(mcp): serialize real process capture and report unavailable authority 2026-10-09 02:58:03 +08:00
morluto fe48e779c2 test(setup): scope removal regression to its fixture client 2026-10-09 02:58:03 +08:00
morluto 9a5b077899 test(process): retain cancellation checks under unverified host cleanup 2026-10-09 02:58:03 +08:00
morluto 9588482bfe docs(testing): prioritize real workflows and distinct regressions 2026-10-09 02:58:03 +08:00
morluto 0e0b386dc3 test: classify application scenarios by their actual boundaries 2026-10-09 02:58:03 +08:00
morluto a1b7d40bb0 test: remove duplicate result assertions before throwing guards 2026-10-09 02:58:03 +08:00
morluto 5945915f91 test: prune redundant cases and promote configuration lifecycle coverage 2026-10-09 02:58:03 +08:00
morluto bef234d6ce fix(ghidra): preserve Unicode boundaries without breaking sessions
Validate native annotation text before mutation and escape surrogate code units in Java bridge JSON replies. Reject unsupported text with field and index diagnostics while preserving supported Unicode and line endings.

Probe real CLI/MCP annotation, transport, mapping, rollback and cleanup behavior; replace seven redundant unit tests with E2E and SDK boundary coverage.
2026-10-09 02:50:33 +08:00
morluto 64717ad7da test(hopper): cover real boundary failures and CLI parity 2026-10-09 02:44:28 +08:00
morluto d830cb79b3 fix(analysis): resolve procedure identities and preserve literal queries 2026-10-09 02:42:39 +08:00
morluto f2e22e13a6 fix(hopper): preserve native navigation and annotation semantics 2026-10-09 02:42:39 +08:00
YsopwnableandGitHub b743bd20a0 fix(hopper): verify lease cleanup and repair the macOS test lane (#1111)
* fix(hopper): distinguish shared lease roots from leaked sessions

* fix(ci): follow the moved process CLI regression tests
2026-10-09 02:41:34 +08:00
YsopwnableandGitHub ec6db0f063 perf(javascript): reuse validated immutable graphs (#1112)
* perf(javascript): reuse validated immutable graphs

* fix(ci): follow the moved process CLI boundary test
2026-10-09 02:40:21 +08:00
morluto 1f5be750bc fix(ghidra): harden location resolution and provider lifecycle
Preserve boundary diagnostics, resolve procedure names before bare hex addresses, and launch the inspected JVM directly on macOS for verifiable startup cancellation. Keep private socket paths within host limits and retain ownership when cleanup is incomplete.

Exercise the fixes through real CLI/MCP Ghidra workflows and provider-boundary integration tests, replacing redundant unit coverage.
2026-10-09 02:38:07 +08:00
morluto e2fc2493b6 fix(process): retain ownership after incomplete cleanup 2026-10-09 02:37:47 +08:00
morluto be783efaba fix(release): always bump minor for releases 2026-10-09 02:15:30 +08:00
morluto 7005166f58 test(hopper): verify real boundaries and prune redundant happy paths 2026-10-09 02:05:58 +08:00
morluto 2f71375efc fix(hopper)!: bind analysis to the active target and correct boundary contracts
Preserve native document identity, nullable bookmark labels, address diagnostics, segment-end byte prefixes, and verified file mappings. Validate batch rename addresses before mutation.

BREAKING CHANGE: remove set_current_document. Use open_binary to switch targets; document arguments are scoped to the active target.
2026-10-09 02:05:31 +08:00
YsopwnableandGitHub 34cc9259c1 fix(process): derive executable names from the capture host (#1108) 2026-10-09 02:02:24 +08:00
Rudy Mizrahi CelekliandGitHub 8b08ec0af9 fix(browser): compose nested source-map column offsets (#1109)
* test(browser): verify native nested source-map coordinates

Qualify valid compiler-produced nested index maps through actual owned Chrome and the built public analyze-web-bundle CLI. Preserve same-line and zero-column controls, physical UTF-16 mapping positions and the independently correct dedicated decoder control. No production or workflow changes.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

* test(browser): retain native source-map failure receipts

Serialize the already-created phase and proof fields for failed native source-map owners. Preserve all producer inputs, scenarios, commands and assertions; first native two-failure/two-control evidence remains unchanged.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

* test(browser): preserve nested source-map boundary contracts

Qualify ordinary maps, nested offsets, sibling clipping, parent gaps, empty sections and deeper composition against the actual browser fetcher. Compare the existing dedicated decoder only for its valid non-overlapping profile. Preserve the four frozen compiler/Chrome/public CLI scenarios.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

* fix(browser): compose nested source-map column offsets

Normalize indexed sections to absolute leaf offsets before upstream flattening. Apply enclosing column offsets only for same-line child sections and retain parent clipping boundaries for gaps and empty sections. Preserve raw map evidence, source identities, transport budgets and the dedicated decoder profile.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

---------

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>
2026-10-09 02:01:29 +08:00
morluto 82560ebf59 test(process): serialize real CLI capture boundaries 2026-10-09 01:55:12 +08:00
morluto 8a4c4b657f test(process): report the cause of terminal capture failures 2026-10-09 01:55:12 +08:00
morluto 1d0baa352f fix(native): preserve bridge failure types during cleanup 2026-10-09 01:55:12 +08:00
morluto 7c323870c2 fix(native): bound retained observations and preserve failure evidence 2026-10-09 01:55:12 +08:00
morluto d6cc9ca3a6 fix(javascript): preserve lexical open and exact template semantics 2026-10-09 01:55:12 +08:00
morlutoandGitHub fe297e56e8 fix(apple): classify empty dyld settings by consumer semantics (#1110) 2026-10-09 01:54:32 +08:00
YsopwnableandGitHub 1e63144390 ci: run signature target binding regressions on native macOS (#1107) 2026-10-09 01:53:40 +08:00
YsopwnableandGitHub cd756b07d5 fix(hopper): report launcher failures before bridge timeout (#1105)
* fix(hopper): report launcher failures before bridge timeout

* fix(hopper): separate helper ownership from GUI lifetime
2026-10-09 01:51:45 +08:00
morlutoandGitHub 7914e36ab9 fix(apple): validate dylib candidates and preserve search uncertainty (#1100)
* fix(apple): validate dylib candidates and preserve search uncertainty

* fix(apple): scope embedded dyld uncertainty by search phase

* fix(apple): scope dyld prefixes to eligible paths and platforms

* fix(apple): ignore embedded process settings on library roots
2026-10-09 01:43:52 +08:00
Rudy Mizrahi CelekliandGitHub 3b2ec69c54 fix(apple): report missing keyed archive hierarchy references (#1104)
* test(apple): qualify malformed native hierarchy references

Freeze actual Foundation/AppKit producer, single-slot positive UID mutation and real optional nil control at filesystem and compiled CLI boundaries. Preserve original raw-byte evidence and existing CI.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

* fix(apple): report missing keyed archive hierarchy references

Preserve known hierarchy objects and links while reporting unresolved nonnil object-table references as partial coverage. Retain archived nil semantics and original byte evidence.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

---------

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>
2026-10-09 01:31:53 +08:00
YsopwnableandGitHub 4bb056bbb5 fix(artifacts): retain failed DMG cleanup state and diagnostics (#1103) 2026-10-09 01:28:42 +08:00
morlutoandGitHub c789af04b7 fix(native): bind signature observations to registered target versions (#1099)
* fix(native): bind signature observations to registered target versions

* fix(native): preserve target drift and cancellation across signature captures

* fix(native): inspect signatures from a verified byte snapshot
2026-10-09 01:27:26 +08:00
morluto acb3e0f2e5 fix(release): restore automatic release proposals on main 2026-10-09 01:25:36 +08:00
Rudy Mizrahi CelekliandGitHub 3db46813f8 fix(javascript): parse plain TypeScript artifact dialects (#1102)
* test(javascript): reproduce TypeScript source dialect loss

Add native directory/ASAR and built public CLI owners with actual locked native TypeScript syntax/emit and independent Babel source-range oracles. Production and every workflow remain unchanged.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

* test(javascript): admit isolated native compiler inputs

Use the actual TypeScript7 producer-requested --ignoreConfig flag when supplying isolated source filenames. Preserve every graph input, owning assertion, control and production file.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

* fix(javascript): parse plain TypeScript artifacts without JSX

Select the plain .ts dialect using the artifact source path so valid angle-bracket assertions retain syntax-derived graph facts. Preserve existing JSX defaults and all other dialects. Document the inert artifact parser contract.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

---------

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>
2026-10-09 01:24:47 +08:00
YsopwnableandGitHub cc0ee2edc6 fix(javascript): honor cancellation before evidence publication (#1098) 2026-10-09 01:15:50 +08:00
f8e143a3bc fix(apple): decode Interface Builder XML byte encodings (#1095)
* test(apple): qualify native Interface Builder XML encodings

Exercise actual AppKit/Foundation XML archive representations through filesystem and compiled CLI consumers. Preserve independent UID/hierarchy and original-byte provenance oracles.

Tests-only candidate qualification on unchanged native Apple CI; no production or workflow changes.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

* fix(apple): share BOM-aware Interface Builder XML decoding

Reuse the existing fatal BOM-aware XML plist decoder for Interface Builder archives. Preserve original serialized-byte digests, binary decoding, and frozen native producer/consumer tests.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

* fix(apple): reject unsupported XML encoding declarations

---------

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>
Co-authored-by: N0zoM1z0 <1705004398@qq.com>
2026-10-09 01:11:49 +08:00
Kaoru0822andGitHub ae0630a619 Merge pull request #1097 from morluto/fix/web-runtime-script-initiators
fix(browser): treat module-import initiator positions as script positions
2026-10-08 10:00:21 -07:00
YsopwnableandGitHub 81b5104276 fix(analysis): bind overview document identity to the active target (#1094)
* fix(analysis): bind overview document identity to the active target

* fix(analysis): refresh legacy overview snapshot results
2026-10-09 00:57:28 +08:00
morluto 4a1837d9d5 fix(javascript): bound primitive string growth and repeated evaluation 2026-10-09 00:49:31 +08:00
morluto 770d2f60aa test(workflows): verify residual questions in CLI snapshots 2026-10-09 00:49:31 +08:00
morluto eb89a16d9b fix(process): identify unknown live processes in cleanup diagnostics 2026-10-09 00:49:31 +08:00
morluto bfb7776006 fix(release): publish prereleases under the next npm tag 2026-10-09 00:49:30 +08:00
morluto 4b1066501b refactor(setup): validate formats through canonical configuration 2026-10-09 00:49:30 +08:00
morluto 8b01e0cc89 fix(providers): validate ELF versions and preserve probe cancellation 2026-10-09 00:49:30 +08:00
morluto 915855e75c fix(native): supervise LLDB and preserve bounded capture uncertainty 2026-10-09 00:49:30 +08:00
morluto 488f448ae2 fix(apple): derive dispatch coverage from located decode facts 2026-10-09 00:49:30 +08:00
morluto 15f92f2988 fix(apple): validate physical slices and dylib platform compatibility 2026-10-09 00:49:30 +08:00
morluto 16f4609d68 fix(javascript): bound semantic expansion and resolve lexical receivers 2026-10-09 00:49:30 +08:00
morluto eaf5734083 fix(browser): bound source-map fetches and retain predecessor requests 2026-10-09 00:49:30 +08:00
morluto 135d102f9d refactor(artifacts): centralize stable inventory identities 2026-10-09 00:49:30 +08:00
morluto d4c2c3c18f fix(target): preserve app bundle filesystem failure reasons 2026-10-09 00:49:30 +08:00
morluto 17809caacd fix(managed): match exact method bytes without decoded signatures 2026-10-09 00:49:30 +08:00
morluto 0136ee8c22 fix(workflows): retain residual unknowns through CLI and MCP 2026-10-09 00:49:30 +08:00
morluto 65a6288257 refactor(input): share schema issue error construction 2026-10-09 00:49:30 +08:00
Kaoru0822andClaude Opus 5.5 99d31ee24a fix(browser): treat module-import initiator positions as script positions
An empty script_id also marks a script-type initiator, such as a module
import, whose url is the importing script file. Its position is a real
script position without a session-script association. The previous
wording called every empty-ID callsite parser markup with "no script
position" and excluded it from the external-script conversion. Describe
the empty ID as a missing session-script association, which only rules
out joining captured source or resource_start, and keep the
external-script conversion for script-file positions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 16:44:25 +00:00
3c157b4ec6 fix(browser): keep initiator callsites out of script coordinate guidance (#1096)
observe_web_execution also derives callsites from a request's reported
initiator, such as an image the parser found in HTML or a module import,
with an empty script_id. Those positions point into the initiating
resource, not a script, so the "script's enclosing resource" wording and
source-map conversion did not apply to them. Describe the coordinates as
relative to the resource named by url, explain empty script IDs, and
limit the documented conversion to positions with a script_id.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:43:03 +08:00
c1b370ce0d fix(javascript): retain NodeNext artifact source facts (#1087)
* test(javascript): reproduce omitted NodeNext artifact sources

Tests only: qualify current .mts/.cts artifact selection through real directory and ASAR reconstruction and the built public CLI.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

* fix(javascript): retain NodeNext artifact source facts

Read .mts and .cts artifact files through the existing inert TypeScript parser, preserving selected file identities and analysis facts in directory and ASAR inputs. Document source selection and format the existing regression assertion.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

---------

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>
Co-authored-by: N0zoM1z0 <1705004398@qq.com>
2026-10-09 00:39:39 +08:00
5a67c7fc54 fix(hopper): diagnose MCP provider failures with stage, state, and request context (#1044)
* fix(hopper): diagnose MCP provider failures with stage, state, and request context

* fix(hopper): retain health at the actual provider lifecycle boundary

* test(hopper): distinguish socket loss from later observed process exit

* test(hopper): cover observed exit separately from socket-first replies

---------

Co-authored-by: N0zoM1z0 <1705004398@qq.com>
2026-10-09 00:33:56 +08:00
b5c2954ad6 fix(domain): order canonical paths by code point, not UTF-16 unit (#1034)
compareCodePoints documented a Unicode code-point comparison but used
</> operators, which compare UTF-16 code units. For astral code points
(above U+FFFF) the lead surrogate 0xD800-0xDBFF is numerically below the
BMP tail U+E000-U+FFFF, so those characters sorted before it.

Delegate to the existing compareUnicodeCodePoints, which the domain
already uses elsewhere, so the two canonical comparators agree. All call
sites use only the sign, so sort and '< 0' checks are unaffected.

Adds the missing regression coverage for canonicalOrdering.

Co-authored-by: TahsinArafat <TahsinArafat@users.noreply.github.com>
Co-authored-by: N0zoM1z0 <1705004398@qq.com>
2026-10-09 00:26:25 +08:00
6218d289e2 fix(browser): advertise zero-based units for runtime source coordinates (#1085)
* fix(browser): advertise zero-based units for runtime source coordinates

inspect_web_event_listeners and observe_web_execution return CDP
callsite, listener and resource_start line_number/column_number values
unchanged: zero-based lines and UTF-16 columns. Neither the advertised
output schema nor docs/web-runtime.md said so. trace_web_source_location
takes one-based lines, so a caller chaining a listener location into it
lands one line early.

Describe the units on the shared schema fields, which reach both tools'
advertised output schemas, and document the conversion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(browser): describe runtime positions relative to the enclosing resource

For an inline <script>, CDP reports listener and callsite positions
relative to the HTML document, and resource_start is where the script
text starts in that document. A real headless Chromium 155 page showed
this: a listener on HTML line 6 came back as line_number 5, with
resource_start {3, 8}. Describe all positions as relative to the
enclosing resource. Document that inline-script positions must have
resource_start subtracted, plus one added to the line, before
trace_web_source_location.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(browser): clarify runtime-to-source coordinate conversion

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: N0zoM1z0 <1705004398@qq.com>
2026-10-09 00:22:18 +08:00
Rudy Mizrahi CelekliandGitHub 23862af1b5 fix(javascript): preserve HTML carriage return source ranges (#1092)
* test(javascript): reproduce HTML carriage return source coordinates

Compare actual resolved and unresolved artifact graph evidence with parse5 source locations across HTML line terminators and UTF-16 columns. Exercise both public built CLI analysis commands. Tests only; production and workflows unchanged.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

* fix(javascript): preserve HTML carriage return source ranges

Treat LF, CRLF, and bare CR as HTML line endings when projecting actual script opening-tag offsets to retained source ranges. Preserve UTF-16 column semantics and document the source-coordinate contract.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

---------

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>
2026-10-09 00:15:24 +08:00
e94be95c66 test(artifacts): verify native directory identity on supported Windows runtimes (#1069)
* fix(artifacts): guard Windows device 0 in directory open integrity check

On Windows, Node.js fs.lstat reports dev as 0 without opening a handle. When DirectoryArtifactReader.open inspects the opened handle using handle.stat(), stat.dev is populated with the volume serial number.

Consequently, the TOCTOU check observed.dev !== entry.sourceIdentity.device evaluated to true on Windows for every regular file, throwing an ArtifactReaderFailure integrity error.

Relax the device comparison when running on Windows or when the inventoried device is 0, while maintaining strict inode verification to ensure the target has not been replaced.

* test(artifacts): verify native directory identity without device bypasses

---------

Co-authored-by: N0zoM1z0 <1705004398@qq.com>
2026-10-09 00:11:28 +08:00
Rudy Mizrahi CelekliandGitHub 83defc054b fix(javascript): preserve original BOM source coordinates (#1093)
* test(javascript): reproduce BOM source range drift

Compare original UTF-8 source bytes and their retained digests with direct Babel and parse5 source-location oracles through actual directory and ASAR artifact reconstruction and both built public CLI analysis commands. Preserve no-BOM, structured-BOM and invalid UTF-8 controls. Tests only; production and workflows unchanged.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

* fix(javascript): preserve original BOM source coordinates

Retain the initial UTF-8 BOM for JavaScript and HTML source text so graph ranges refer to the original digest-bound bytes. Preserve structured-text BOM handling and fatal UTF-8 decoding.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

* style(javascript): format BOM decoder option

Apply the locked Oxfmt line wrapping to the approved decoder option; no behavior or test changes.

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>

---------

Signed-off-by: Rudy Celekli <rudy@gradiahq.com>
2026-10-09 00:09:55 +08:00
eb69763d27 fix(process): name the reason two captures cannot be compared (#1080)
* fix(process): name the reason two captures cannot be compared

compare-process-captures rejected captures whose comparison contracts
differ, but the reason never reached the caller. The CLI printed
"Process command could not complete... run `rea doctor`". MCP wrapped
the error in an AnalysisInputError with no issues ("Analysis input is
invalid. Check the arguments"). A stale capture under
max_capture_age_ms got the same treatment.

Throw typed input issues that name the differing contract fields, or
the stale side with its completion time and age, and let
runDerivedOperation pass AnalysisInputError through unchanged. Document
what the comparison contract covers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(process): report CLI trace-spec issues under the MCP input path

The CLI reported an invalid trace specification under operation
"compare-process-captures" with root-relative issue paths such as
["events"]. MCP reports the same input as compare_process_captures with
paths under trace_spec. Use the canonical operation name and prefix
trace_spec so both surfaces describe the same input identically.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(process): name the side and constraint for unusable capture Evidence

Adjacent compare_process_captures failures still lost their reason.
Over MCP, Evidence from another workflow, tampered Evidence and an
invalid capture result all became "Evidence is invalid or has changed".
The CLI said only "Capture evidence is malformed".

Parse each side separately. Evidence from another workflow is an input
issue on left or right that names the operation and predicate it has.
Tampered Evidence and invalid capture results stay integrity
mismatches, and their message now carries the validation detail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:04:35 +08:00
289aef6838 fix(workflows): keep caller-input details in workflow input errors (#1089)
* fix(managed): keep caller-input details in managed workflow errors

The managed workflows wrapped every rejected input as
`new AnalysisInputError(op, { cause })` with no issues. The projected
result said "Correct the listed arguments and retry" and listed nothing:

- `rea import-managed-reconstruction`,
  `rea project-managed-application-graph` and
  `rea verify-managed-native-boundaries` lost every schema issue for
  malformed JSON;
- domain checks such as a reconstruction text hash mismatch, or Evidence
  from the wrong operation, lost their message on CLI and MCP;
- `rea compare-managed-members` with a missing file did not say which
  path failed.

Add managedInputError, which projects Zod issues with their paths and
keeps a domain TypeError's message, as the JavaScript workflows already
do. Return the BinaryTargetError from an unopenable comparison path
unchanged, with details.path, as every other path-based command does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(managed): keep nested Evidence schema issues off request paths

A ZodError raised after the request parsed comes from a nested
Evidence result, so its issue paths are relative to that result.
Projecting it against the whole request reported, for example,
artifact.sha256 as a missing request field. Keep request-relative
projection for the raw request's schema failures. Report nested schema
failures as root issues whose message names the nested location.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(managed): type the malformed nested Evidence fixture

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(workflows): keep input details in the remaining workflow services

Inventory projection (project_android_application_graph and
project_apple_application_graph), build_reconstruction_obligation_ledger
and evaluate_reconstruction_coverage had the same issue-less
`AnalysisInputError({ cause })` as the managed services. For example,
evaluating coverage for an unknown boundary returned "Correct the listed
arguments" with no issues, dropping "Unknown reconstruction boundary: X"
on CLI and MCP.

Move the helpers to src/application/workflowInputError.ts and use them
for these services: requestInputError for raw request schema failures,
workflowInputError for nested schema and domain constraint failures.
Classification is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:56:19 +08:00
1986 changed files with 177701 additions and 35751 deletions
+20
View File
@@ -0,0 +1,20 @@
---
name: rea-tool-design
description: Design or change REA investigation tools, CLI/MCP contracts, provider capabilities, and Evidence semantics.
---
# REA tool design
Use the [tool-design guide](../../../docs/tool-design.md) for tool boundaries,
contract semantics, provider ownership, and discoverability. Inspect the current
contract and nearest existing tool relevant to the analyst question; source,
documentation, and live catalogs may describe different versions.
For a design request, return the proposed boundary, input/result shape, Evidence
semantics, nearest alternative, and verification approach. Implement when
requested, preserving the user's scope and existing authorization.
For implementation or verification, consult [testing](../../../docs/testing.md)
for the affected consumer and provider lanes, and
[contributing](../../../CONTRIBUTING.md) for generated-file ownership. Read
provider/workflow guides only as the task requires.
@@ -2,7 +2,7 @@
name: reverse-engineer-anything
description: Reverse engineer native, managed, Electron/JavaScript, packaged, firmware, and browser targets with REA. Use shipped-artifact or requested runtime evidence to explain features, compare versions, decompile code, or guide a reconstruction. Skip REA for ordinary source-repository architecture analysis.
metadata:
version: "33"
version: "37"
---
# REA
@@ -25,48 +25,18 @@ a skill installed from repository main may describe capabilities absent from
an older npm release. Keep complete inline Evidence when that server does not
advertise retained references.
When tools are absent or registration is stale:
If tools are absent, a call is blocked by the client, or a required provider is
unavailable, read [connection and recovery](references/connection-and-recovery.md).
Diagnose the observed blocker, continue useful supported work, and resume the
original task after repair. Client approval, shell PATH, registration and engine
availability have different remedies; avoid repeating setup for all of them.
1. Diagnose without changing files. For Codex, run
`npx -y rea-agents@latest doctor --client codex --json`. Substitute the current
supported client: `claude_code`, `claude_desktop`, `codex`, `cursor`,
`gemini_cli`, `windsurf`, `devin`, `opencode`, `antigravity`, `copilot_cli`,
`commandcode`, or `vscode`. If the client is unknown, use `doctor --json` and
inspect its registration results before choosing a setup scope.
2. Distinguish the reason. Missing, malformed, or stale registration needs a
scoped configuration repair. An aligned registration with no tools in the
active session needs a restart/reconnection; doctor cannot prove that the
current agent has connected. A missing provider affects only tasks requiring
that provider: static JavaScript inspection needs neither Hopper nor Ghidra,
and Android inspection has separate bring-your-own JADX/Java prerequisites.
3. For a configuration repair, prepare the read-only plan:
`npx -y rea-agents@latest setup --client codex --dry-run --json`.
Use the current client's ID, show its exact proposed paths, backups, and
changes, and obtain approval before setup writes configuration or installs
Hopper. Setup normally installs the matching bundled skill too; include that
replacement in the reviewed plan. After approval, apply the same scope with
`npx -y rea-agents@latest setup --client codex --yes`. Add `--install-hopper`
only if that separate installation was needed and explicitly approved.
4. Restart/reconnect the affected agent. Verify that REA tools actually appear
in the session, then resume the original investigation. If they remain
absent, inspect the client's MCP launch error rather than repeating setup.
REA setup never installs or upgrades Node.js, npm, Homebrew, Java, Ghidra, IDA,
JADX, Binwalk, or Unblob. Use existing prerequisites; do not install unrelated
software to repair
MCP registration. For an unsupported client, use manual stdio registration
with a version-pinned `rea-agents` package or continue through the CLI.
A concrete CLI fallback for an operator-supplied JavaScript tree or ASAR is:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
No MCP registration or native engine is required. Read the returned Evidence,
graph, limitations, and unknowns with the same care as an MCP result; the CLI
returns the Evidence record directly. This fallback does not establish that
MCP is configured. Native CLI tasks still require their selected engine.
Prefer an existing `rea` CLI. When none is installed and REA package acquisition
is within the authorized scope, use `npx -y rea-agents@latest` in its place.
Configuration repair starts with a read-only setup plan; show paths, backups and
skill replacement before applying authorized changes. Preserve existing approval
and target-execution boundaries. REA setup never installs or upgrades unrelated
software, including Node.js, npm, Homebrew, Java, Ghidra, IDA, JADX, Binwalk or Unblob.
## Route the target first
@@ -112,6 +82,9 @@ explicit path or endpoint and do not need it.
Historical PIDs do not select live processes. Request `include_debugger_context`
only when core-only mapping candidates help; see the
[recorded crash guide](https://github.com/morluto/rea/blob/main/docs/recorded-crashes.md).
- PE resource type/name/language trees and static icon group references:
`inspect_pe_resources` with an explicit path. This portable operation requires
no active target or engine; opaque payloads retain file ranges and SHA-256.
- Native executable, library, or analysis database: `open_binary`, then
use focused analysis tools directly; call `binary_overview` when metadata or
inventory context is useful and available from the selected provider.
@@ -128,9 +101,11 @@ after opening; IDA does not supply `binary_overview`. Consult session availabili
when composing broader workflows. Modern direct callers and unsupported dossier
facets remain unknown; live IDA results are not replayed from snapshots.
If the app is missing, ask which app to inspect. Resolve a human-readable app
name to one clear installed artifact when possible; ask only when matches are
ambiguous. Never choose an example app on the user's behalf.
If the user says only "my app" without a name, path, or target already selected
for this task, ask which app before searching for artifacts. Paths in unrelated
saved reports and nearby test fixtures do not select the user's target. Resolve
an actual human-readable app name to one clear installed artifact when possible;
ask when matches are ambiguous. Never choose an example app on the user's behalf.
In a target-free session, use `open_binary` to bind any archive/package or
native target whose analysis tool operates on the active target. Do not call an
@@ -141,15 +116,32 @@ list stays complete; availability depends on the operation, target, and host.
## Work summary-first
Start with the default result and use its inline Evidence and graph context.
Do not repeat an identical tool call. Make a focused follow-up only when the
For a JavaScript application or ELF layout whose size is unknown or large,
call `analyze_javascript_application` or `inspect_binary_layout` with
`"detail": "summary"`, then inspect the retained `parent_evidence_id` with
`inspect_analysis_view`.
Page module identities and select the returned `node_id` before requesting an
item; a single file path can represent several graph roles. Do not repeat an
identical analysis or rejected call without a changed input or resolved blocker.
Recheck session state when a lifecycle change makes that status useful.
Make a focused follow-up only when the
returned result leaves a specific question unanswered.
If MCP reports `resource_constraint` with `details.resource: "transport"`, use
its reported same-session Evidence reference with a focused application tool,
or call `export_evidence_bundle` to write the complete session to a selected
path. The analysis remains complete in the ledger; avoid repeating it merely
to request the same oversized response. Complete CLI JSON output also streams
without a single MCP frame.
If MCP reports `resource_constraint` with `details.resource: "transport"`, call
`inspect_analysis_view` with its reported same-session Evidence reference for a
summary, one section/module, or a stable page. Use `trace_application_feature`
once a seed is known, or call `export_evidence_bundle` to write the complete
session to a selected path. The analysis remains complete in the ledger; avoid
repeating it merely to request the same oversized response. Complete CLI JSON
output also streams without a single MCP frame.
A client can also truncate a successful tool result without a REA transport
error. Treat that preview as incomplete; use the retained parent ID for smaller
views or export when the full record is needed. Do not parse the preview as
canonical JSON or repeat the producer. For JavaScript, read the
[module-view and trace recipes](references/javascript-applications.md) before
drilling into a large graph; a broad bidirectional trace can expand unrelated
containment relationships even after summary analysis.
Every conclusion must distinguish observations, inferences, and unknowns. Cite
Evidence IDs, preserve limitations and incomplete coverage, and never imply
@@ -158,7 +150,9 @@ target and lifecycle; do not broaden the target or action beyond those fields.
Within the user's requested investigation, call available analysis tools
directly. REA does not require permission grants or per-call approval flags.
Follow the declared request scope and the host's actual access requirements.
The agent client can independently require approval. Follow the declared request
scope and the host's actual access requirements; use the recovery guide for an
observed client-policy rejection.
## Plan broader investigations
@@ -19,9 +19,12 @@ can select Java. REA setup does not install or configure that JAR, and doctor
provider scopes cover Hopper/Ghidra rather than JADX. Use existing tools and
report missing prerequisites for the Android task specifically.
Real verification covers Linux. macOS has the POSIX launch boundary but no
claimed real-provider verification; Windows is unsupported. Calls use one
worker, a bounded JVM heap, and provider deadlines. The APK is never launched,
Linux and macOS use the POSIX owned-process boundary. Windows x64 requires the
matching bundled native controls and uses an owned Job Object with bidirectional
stdio. A full JDK, including `jdk.compiler`, is required on every host; Windows
`JAVA_HOME` selects `bin\java.exe`. Consult the Android guide for actual host
verification coverage. Calls use one worker and provider deadlines; optional
`REA_JADX_HEAP_MIB` selects the JVM heap. The APK is never launched,
and no emulator is required.
Manifest entries and decompiled text are static observations, not execution or
@@ -0,0 +1,127 @@
# Connection and task recovery
Read this guide only for an observed connection, command, approval or provider
blocker. Keep the user's target and question in view. Explain what prevented the
operation and the next useful step; after repair, continue the investigation.
Commands below use an installed `rea`. If none is available, use the package
invocation in `SKILL.md` when acquiring REA is authorized. Follow the connected
server's schemas and the installed CLI's help rather than assuming repository
main and an older release expose the same arguments.
## Choose the remedy from the observed failure
| Observation | Meaning and next step |
| --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| No REA tools in the active session | Inspect registration with `rea doctor --client codex --json`. A skill installation alone does not register MCP. |
| Missing, malformed or stale registration | Prepare a scoped setup plan; apply only authorized changes with backups. |
| Aligned registration, but no connected tools | Restart/reconnect the client. Doctor checks registration; it cannot establish the current agent's connection. Inspect the client's launch error if reconnection fails. |
| `MCP tool call requires approval, but approval policy is never` | Codex rejected the call before REA executed it. Do not install an engine or repeat setup to solve this client-policy decision. See the approval section below. |
| REA returns `provider_unavailable` or an unavailable tool entry | Read that operation's provider diagnostics or `binary_session.result.tool_availability`. Resolve only the prerequisite needed for the task; a complete tool catalog does not imply every operation is available. |
| `rea` is missing in a child shell, or Node is incompatible | Inspect the actual shell PATH and launcher/runtime. A prefix installation may be absent from a login shell's PATH; this does not establish a broken MCP registration. |
If the client cannot launch its shell/sandbox helper or read the installed skill,
inspect its launch diagnostic. For example, Codex can refuse helper aliases when
CODEX_HOME is under `/tmp`; use an authorized profile outside the OS temporary
directory. REA setup cannot repair the client's executor. Preserve the sandbox
instead of silently disabling it to make an analysis command work.
Static JavaScript and ordinary ZIP inventory need neither Hopper nor Ghidra.
HAR inspection is offline and does not require a live browser. Native
decompilation, Android analysis and firmware extraction have their own
bring-your-own prerequisites. Use supported inventory/static evidence when it
answers part of the question, and name the unavailable evidence separately.
Do not substitute another target. Label observations from ordinary shell tools
as such; only actual REA output supplies REA Evidence.
## Repair registration when needed
For Codex:
```bash
rea doctor --client codex --json
rea setup --client codex --dry-run --json
```
Use the current supported client's ID: `claude_code`, `claude_desktop`, `codex`,
`cursor`, `gemini_cli`, `windsurf`, `devin`, `opencode`, `antigravity`,
`copilot_cli`, `commandcode`, `qwen_code`, `vscode`, `grok_build`, `omp`, `pi`,
`hermes`, or `grok_bot`. If unknown, inspect `doctor --json` before choosing a
scope. `grok_bot` uses a chat registration step rather than local `mcp.json`.
For unsupported clients, use version-pinned manual stdio registration or CLI.
Show the plan's exact paths, backups, changes and bundled-skill replacement.
Obtain approval for writes when that concrete scope is not already authorized,
then apply the same scope with `rea setup --client codex --yes`. Add
`--install-hopper` only when separately needed and explicitly approved. Do not
install or upgrade unrelated prerequisites. Restart/reconnect, verify tools
actually appear, and resume the original task. If they remain absent, inspect
the launch failure rather than looping through setup.
## Codex tool approval is separate from REA readiness
REA tools have no permission-grant handshake. Codex can still require approval
because an operation creates owned resources, launches a helper or has cleanup
effects. An advertised tool or successful doctor result does not override that
client policy. `workspace-write` alone does not resolve an MCP approval
rejection, and `approval_policy = "never"` does not mean every MCP tool is
preapproved.
When interactive approval is available, use the client's approval flow for the
requested operation. In an unattended run, continue through an authorized CLI
workflow if the execution environment permits it, or report the blocked
operation and the approval needed to proceed. Do not retry the same rejected
call, silently broaden approvals, or rewrite MCP effects as read-only.
For an operator who explicitly wants to preapprove named operations in a
disposable Codex profile, current Codex supports per-tool configuration. For
example, opening and closing an analysis session can be scoped independently:
```toml
[mcp_servers.rea.tools.open_binary]
approval_mode = "approve"
[mcp_servers.rea.tools.close_binary]
approval_mode = "approve"
```
Use the actual server ID and only the operations whose effects were approved;
this example does not approve inspection, extraction or runtime execution.
Show the proposed config edit and preserve unrelated entries and backups before
writing. Managed policy can constrain client settings. Consult the
[Codex configuration reference](https://learn.chatgpt.com/docs/config-file/config-reference)
for the installed client's supported settings. This is an optional recovery
choice, not a prerequisite for every REA task.
## Continue through an installed CLI
Check the command environment only if the launcher fails:
```bash
command -v rea
command -v node
node --version
rea --version
```
Use the public launcher at its known installation path with a supported existing
Node on PATH when the child shell loses a prefix installation. Avoid internal
`dist/cli.js` entrypoints or global toolchain changes. MCP may have its own valid
launcher even when a shell cannot resolve `rea`.
For a user-supplied JavaScript tree or ASAR, select output files in the authorized
workspace and save complete Evidence before reading a view:
```bash
rea analyze-javascript-application /absolute/path/to/app --json > app-evidence.json
jq -c '{source: {kind: "inline", evidence: .}, view: {kind: "summary"}}' app-evidence.json > app-view.json
rea inspect-analysis-view app-view.json
```
These commands do not register MCP or install an analysis engine. CLI JavaScript
JSON is complete and can be very large; redirect it rather than loading it into
context. Use an existing JSON processor if `jq` is absent, without installing
one just for this recipe. Inspect a module page or item using the same inline
source and the [JavaScript recipes](javascript-applications.md). Preserve graph
coverage, limitations and unknowns. Native CLI analysis still requires its
selected engine, and all CLI operations retain the host's execution permissions.
@@ -1,11 +1,15 @@
# Evidence, comparison, and verification workflows
REA returns Evidence with each result. Read that result directly, cite its
Evidence ID when another tool or your explanation needs a stable reference, and
preserve authority, limitations, coverage, and residual unknowns. If a result
Evidence-producing tools return the complete Evidence record directly in MCP
`structuredContent` and CLI JSON. Read `normalized_result` for operation data,
and cite `evidence_id` when another tool or your explanation needs a stable
reference. Preserve authority, limitations, coverage, and residual unknowns. If a result
is incomplete or paginated, continue only when the remaining data matters to
the task; do not fetch a bundle or resource merely to read a result already
returned inline.
returned inline. When complete `inspect_binary_layout` or
`analyze_javascript_application` Evidence is already retained, call
`inspect_analysis_view` for a summary, one section/symbol/module, or a stable
page instead of repeating the producer.
Use `record_unknown` to track unresolved questions in the user's investigation
and name the authority or environment still required. Supply supporting and
@@ -0,0 +1,149 @@
# JavaScript and Electron application artifacts
Use `analyze_javascript_application` directly on the operator-supplied ASAR or
extracted tree. When size is unknown or large and the connected schema advertises
`detail`, request `detail: "summary"`. This returns an `inspect_analysis_view`
Evidence record with a distinct ID and a `normalized_result.parent_evidence_id`
for the complete retained application analysis. Source-map contents are part of
that static analysis. Read findings, coverage, limitations and unknowns, then
follow a specific unanswered question. Older servers without `detail` return
the complete application Evidence inline when it fits.
When the connected schema advertises `max_heap_mb` and `analysis_timeout_ms`,
these select the isolated source analyzer's old-space heap and per-source
deadline. Defaults are 1024 MiB and 300000 ms. They do not change the MCP
process heap. Resource-limited analyses preserve completed static facts and
report partial semantic coverage with specific unknown scopes; this does not
mean the source is malformed. Inspect those limits before retrying a source.
When expanded relationships exceed the parent's available memory, inspect the
file's modules item view for retained `static_analysis` and
`semantic_module_analysis`. Their facts remain available even when graph links
are unknown. Cumulative result exhaustion can stop analysis before every file
is examined; the inventory and remaining unknown scopes distinguish that case.
Timeout or cancellation after source analysis begins retains partial Evidence
in the same session. A returned `error.details.partial_observation` reference
can be supplied directly to `inspect_analysis_view`. If the SDK cancels locally, retrieve its recorded ID from
the Evidence bundle before inspecting the partial analysis.
## Read a module without repeating analysis
Use the actual returned parent ID, on the same connection, as `source.evidence_id`.
The following IDs are placeholders to replace with returned values. When the
module's node ID is not already known, page identities before selecting an item.
Pages return only node IDs, paths and roles; choose a useful page size and follow
`coverage.next_offset` when another page matters:
```json
{
"source": {
"kind": "retained-evidence",
"evidence_id": "ev_ACTUAL_PARENT_ID"
},
"view": { "kind": "page", "collection": "modules", "offset": 0, "limit": 16 }
}
```
Select the relevant page entry by its exact `node_id` and recorded role:
```json
{
"source": {
"kind": "retained-evidence",
"evidence_id": "ev_ACTUAL_PARENT_ID"
},
"view": {
"kind": "item",
"collection": "modules",
"selector": { "node_id": "jag_node_ACTUAL_NODE_ID" }
}
}
```
Module pages include asset, bundled and source module roles, so one path can
identify several entries. Use `selector.path` only when uniqueness is established;
the returned node ID avoids needing a complete inventory to prove uniqueness. On ambiguity,
select the matching node ID from the page or the error's candidates. Follow
`next_offset` when another page matters. An item exposes that module node's
recorded observations, identity, hashes, exports and source ranges; it does not
include every child syntax observation, related edge or original source file.
An absent item fact is not evidence of absence from the whole application.
## Trace only the remaining question
Use `trace_application_feature` on the parent application Evidence for one
literal node ID, route, string, API, IPC channel, module, or native export.
Select `incoming` for relationships leading to the seed, `outgoing` for those
leaving it, and `both` when the question needs both. Trace traversal includes
containment relationships, so even a narrow seed can expand many nodes; a
bidirectional trace can reach unrelated sibling modules. A module item or page
is preferable when its observations already answer the question. Do not treat
all reached nodes as participants in the feature.
Reuse retained parent Evidence when the server advertises it, or supply complete
Evidence inline. Include Hopper or Ghidra Evidence only when its artifact digest
matches exactly.
## Recover an oversized display
An oversized response reports `resource_constraint` and
`details.resource: "transport"`. Reuse
`details.reported_limits.evidence_reference` with `inspect_analysis_view` for a
summary, one module, or a stable page of module identities.
`export_evidence_bundle` writes the complete canonical session to a
caller-selected file. These workflows keep the original Evidence and coverage;
a broad follow-up can also exceed framing.
A client can truncate a successful result inside its text envelope without a
REA `resource_constraint`. Treat a truncation notice or incomplete JSON as a
display limitation; do not claim the full record was examined. Reuse the known
parent ID for smaller views, or export complete Evidence to a selected file
while the session remains open. If the parent ID was lost from the preview,
use the prior analysis summary or explicit ledger entries to recover it; do
not invent an ID or rerun analysis just to reproduce the same display.
BrowserWindow preferences, preload and contextBridge surfaces, IPC
registrations, utility processes, and native binding requests are static syntax
observations. Only a unique exact literal IPC channel match supports an inferred
pairing. Dynamic or ambiguous channels remain unresolved. A requested `.node`
member is not a verified native export. Never claim runtime reachability,
registration, defaults, or policy enforcement from static analysis.
For version comparison, analyze each version once, then call
`compare_application_versions`. Accept only its digest, source-map, structural
fingerprint, or non-module semantic matches. Module ordinals and minified names
are not persistent identity. Report added or removed only with complete
opposite-side coverage; otherwise report unknown.
When the question asks how one exact exported callable's returned object shape
changed, analyze each version once and then call
`compare_javascript_export_shapes` with explicit module paths and export names.
Use the returned IDs on the same connection, or complete inline Evidence
records, from both analysis calls. Accept variant
pairing only through the tool's unique exact literal discriminant. Read
`property_inventories` and each change's `presence` before treating `unknown` as
"the name was not observed": inventories list observed property names even when
values stay unknown, with a `source_range` for each paired or unpaired variant.
Array holes and mutation-invalidated slots are not observed properties.
Complete parent coverage reports presence-only
`added`/`removed` independently of unresolved values. Cite the
comparison Evidence and report JSON Pointer changes; dynamic values, ambiguous
variants, and incomplete parent-property coverage stay unknown. This is static
inference, not runtime behavior. When runtime semantics are needed, run
behavioral probes against the relevant application versions and capture them
through the available browser, Electron, or process workflows.
## Reusing application Evidence
When advertised by the connected server, application trace and compare tools
accept complete inline Evidence or
`{"kind":"retained-evidence","evidence_id":"ev_<64 lowercase hex characters>"}`
for their application input (`application`, or `left`/`right`). `inspect_analysis_view`
uses the same retained-reference form in `source`, or portable inline Evidence,
to project a summary, module page, or one module with its recorded observations. This notation is
a template: replace it with the actual returned ID. Versions before 4.1.0 accept only full
inline Evidence. Use the exact ID
returned by the producer on the same MCP connection. Resolution does not run
analysis or select a provider; findings remain inline. Native observation
arrays still take full Evidence. `close_binary` clears retained references;
export a bundle before closing, or supply portable inline Evidence in another
connection. A missing reference includes its ID and recovery guidance.
@@ -16,6 +16,15 @@ Requested unavailable context fails with setup guidance. See
[recorded crashes](https://github.com/morluto/rea/blob/main/docs/recorded-crashes.md)
for exact upstream profiles, bounds and verification coverage.
## Offline ELF layout
Use `inspect_binary_layout` with an explicit local ELF path for file-backed
sections, symbols, relocations, linkage names, and static mitigation inferences
without opening a disassembler target. When that complete record is already
retained, call `inspect_analysis_view` for a summary, mitigations or linkage
facet, one section or symbol, or a stable page. Do not re-run the decoder to
read a single object.
## Native targets
After `open_binary`, use focused search, procedure, or function tools directly.
@@ -25,6 +34,15 @@ cross-references. Addresses and recovered pseudocode are analysis observations,
not original source. Provider unavailability and unsupported metadata remain
unknown rather than false.
For a completed `analyze_function` dossier, use `inspect_analysis_view` with
`view: {kind: "native", facet: "value_flow_operations", offset: 0, limit: 32}`
and the exact retained Evidence ID to read selected facts without reanalysis.
Native facets also include procedure, pseudocode, assembly, basic blocks,
comments, callers/callees, references, unresolved calls, referenced strings and
names, the native API record, and value-flow summaries. Pseudocode offsets and limits count UTF-16
code units; use the returned `next_offset` for continuation. Provider limitations
and unavailable facts remain explicit; the complete parent Evidence is retained.
To see which functions or Objective-C methods a Mach-O actually calls in one
run, use `observe_native_calls` with explicit breakpoints and a bounded
`duration_ms`/`max_events`. It launches a new process under LLDB, so the target
@@ -51,6 +69,15 @@ use inclusive ends and can contain gaps. Do not treat the enclosing span as code
For packed targets, retain the original and separately derived artifact identities;
decompiling an unpacking stub does not recover the unpacked program.
When reading Objective-C dispatch metadata, distinguish class implementation
methods from protocol requirements: class methods report null requirement
flags, while decoded protocol declarations retain required and optional facts.
Property attributes remain raw name/value tokens; use the property's
`atomicity` field for the decoded `N` marker or the default atomic behavior.
Null class/meta flags, ivar counts, atomicity, or read-only values mean the
selected provider did not establish that fact. Symbol names alone do not prove
that a class is a root class or has no ivars.
## Managed PE/CLI
Start with `inspect_managed_artifact`. REA's canonical managed inspection is
@@ -125,4 +152,16 @@ context. PSP/stack/device state remains unmodeled. See [DOS guide](https://githu
### Function annotations in Ghidra
Use `annotate_native_function` for one function name and/or entry comments, with at least one explicit change. Review its annotation readback and refreshed dossier inline. Changes are atomic and session-scoped; empty comments clear them, omitted fields preserve them. Later MCP calls observe edits until close. CLI `annotate-native-function` returns the updated analysis before discarding the session. Original executable bytes are unchanged; edits invalidate immutable snapshots. Windows P0 does not admit database mutations.
Use `annotate_native_function` for one function name and/or entry comments, with at least one explicit change. Review its annotation readback and refreshed dossier inline. Changes are atomic and session-scoped; empty comments clear them, omitted fields preserve them. Later MCP calls observe edits until close. CLI `annotate-native-function` returns the updated analysis before discarding the session. Original executable bytes are unchanged; edits invalidate immutable snapshots. Windows P0 does not admit database mutations. For naming only, `set_address_name` / `set_addresses_names` also work with Ghidra: they name function entries or data addresses (primary labels) and return compact per-address success booleans instead of a dossier.
## Offline PE resource inventory
Use `inspect_pe_resources` with an absolute `path`, or
`rea inspect-pe-resources ./selected.exe --json`, for portable PE32/PE32+
resource inspection without opening a native target. Preserve returned Evidence:
type/name/language IDs and UTF-16 names, original directory/data/payload ranges,
code pages, payload hashes and static icon-group references. Same-language icon
resolution is explicit; missing references and size mismatch remain visible.
Other payloads are opaque, and this operation does not decode images or simulate
Windows resource loading. Consult the budgets and supported tree profile in
[offline binary diagnostics](https://github.com/morluto/rea/blob/main/docs/binary-diagnostics.md).
+4 -2
View File
@@ -28,7 +28,7 @@ intentionally not included. -->
- Provider, bridge, target-format, or platform compatibility:
- Evidence, artifact, provenance, or reconstruction contract:
- Process execution, authorization, cleanup, or containment impact:
- Generated metadata (`docs/public/product-catalog.json`), package, or installation impact (CI generates and validates ignored catalogs and `skills/`; edit authored instructions in `skill-src/` and never commit build outputs):
- Generated metadata (`docs/public/product-catalog.json`), package, or installation impact (CI generates and validates ignored catalogs and `skills/`; edit authored instructions in `.agents/skills/reverse-engineer-anything/` and never commit build outputs):
## Evidence and regression coverage
@@ -61,7 +61,8 @@ limits, security/privacy/containment implications, and meaningful proof gaps. --
- Breaking changes or migration steps:
<!-- For ! / BREAKING CHANGE: show a previously valid call/configuration,
its new behavior and migration, and why compatibility/deprecation cannot
preserve it. Compatible fixes/additions should use patch/minor semantics.
preserve it. Every release increments minor, including breaking changes;
keep breaking markers and migration notes so callers can assess compatibility.
See docs/releasing.md. -->
- Real Hopper/Ghidra, browser, or OS coverage:
- Package or release metadata impact:
@@ -69,6 +70,7 @@ limits, security/privacy/containment implications, and meaningful proof gaps. --
## Review checklist
- [ ] This PR addresses a concrete problem or an agreed enhancement.
- [ ] The PR has one focused outcome and the title follows `type(scope): outcome`.
- [ ] Related issue is linked, or the reason for not linking one is stated above.
- [ ] Tests cover changed observable behavior and meaningful failure paths.
+49 -51
View File
@@ -8,7 +8,9 @@ on:
concurrency:
group: ci-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
# The latest main push verifies the full tree, including earlier changes.
# Publication uses its own release workflow and concurrency group.
cancel-in-progress: true
env:
HUSKY: "0"
@@ -47,15 +49,22 @@ jobs:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
if [[ "${{ github.event_name }}" != "pull_request" ]]; then
if [[ "${GITHUB_EVENT_NAME}" != "pull_request" ]]; then
echo "required=true" >> "${GITHUB_OUTPUT}"
elif git diff --quiet "${BASE_SHA}" "${HEAD_SHA}" -- \
# Compare the PR's changes, excluding unrelated updates on its base.
elif git diff --quiet "${BASE_SHA}...${HEAD_SHA}" -- \
. \
':(exclude)docs/**' \
':(top,exclude,glob)README*.md' \
':(exclude)AGENTS.md' \
':(exclude)CONTRIBUTING.md'; then
echo "required=false" >> "${GITHUB_OUTPUT}"
else
diff_status=$?
# A failed comparison must fail classification, not report a scope.
if [[ "${diff_status}" -ne 1 ]]; then
exit "${diff_status}"
fi
echo "required=true" >> "${GITHUB_OUTPUT}"
fi
@@ -102,8 +111,12 @@ jobs:
with:
name: rea-dist
path: dist
- name: Generate projections from downloaded build
run: npm run build:projections
- name: Generate test artifacts from the downloaded runtime
run: |
node scripts/generate-mcp-tool-catalog.mjs
node scripts/generate-skill-metadata.mjs
node scripts/generate-product-catalog.mjs
node scripts/generate-completion-ledger.mjs
- run: npm run test:ci:shard:run -- --shard=${{ matrix.shard }}
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
@@ -298,7 +311,7 @@ jobs:
- run: npm run verify:windows-native:artifact
- run: npm run verify:package
- name: Verify real Node Inspector discovery and observation
if: matrix.platform == 'darwin'
timeout-minutes: 10
run: npm run verify:inspector
apple-artifacts:
@@ -317,6 +330,8 @@ jobs:
- run: npm run verify:keyed-archive
- run: npm run verify:asset-catalog
- run: npm run verify:macos-bundle
- name: Legacy simulator platform verification
run: npm run verify:legacy-simulator
- name: Native installer and compiled NIB hierarchy regressions
run: npm run test:focused -- tests/boundary/filesystem/installScript.test.ts tests/boundary/filesystem/nibNativeHierarchy.test.ts tests/boundary/filesystem/interfaceBuilderBundle.test.ts
- name: Real binary metadata and Interface Builder integration
@@ -325,10 +340,12 @@ jobs:
run: npm run test:focused -- tests/boundary/cli/nativePlistCli.test.ts tests/boundary/cli/nativePlistPrototypeKeyCli.test.ts tests/boundary/cli/nativePlistSelectionFailureCli.test.ts
- name: Native Swift demangling CLI and MCP regressions
run: npm run test:focused -- tests/boundary/cli/nativeDemangleCli.test.ts tests/boundary/mcp/nativeDemangleMcp.test.ts
- name: Native signature target binding and CLI/MCP recovery regressions
run: npm run test:focused -- tests/boundary/providers/native/nativeSignatureTargetBinding.test.ts tests/boundary/cli/nativeSignatureCli.test.ts tests/boundary/mcp/nativeSignatureTargetBindingMcp.test.ts
- name: Process filesystem snapshot descriptor regressions
run: npm run test:focused -- src/process/capture/FilesystemSnapshot.test.ts
- name: Native Darwin ownership and process cleanup regressions
run: npm run test:focused -- tests/boundary/process/darwinProcessRunTokenReader.test.ts tests/boundary/process/processCaptureLifecycle.test.ts tests/boundary/cli/processCli.test.ts tests/boundary/mcp/sessionMcp.test.ts
run: npm run test:focused -- tests/boundary/process/darwinProcessRunTokenReader.test.ts tests/boundary/process/directAnalysisSignals.test.ts tests/boundary/process/processCaptureLifecycle.test.ts tests/boundary/process/processCli.test.ts tests/boundary/mcp/sessionMcp.test.ts
reconstruction-readiness:
name: Reconstruction readiness
@@ -359,48 +376,6 @@ jobs:
if-no-files-found: error
retention-days: 30
javascript-runtime-observation:
name: JavaScript runtime observation (${{ matrix.os }})
needs: changes
if: github.event_name == 'push' || needs.changes.outputs.code == 'true'
strategy:
fail-fast: false
max-parallel: 2
matrix:
include:
- os: ubuntu-latest
platform: linux
architecture: x64
- os: ubuntu-24.04-arm
platform: linux
architecture: arm64
- os: windows-latest
platform: win32
architecture: x64
runs-on: ${{ matrix.os }}
timeout-minutes: 10
env:
NODE_OPTIONS: "--max-old-space-size=1024"
UV_THREADPOOL_SIZE: "2"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: npm
- name: Verify native runtime identity
env:
EXPECTED_CI_PLATFORM: ${{ matrix.platform }}
EXPECTED_CI_ARCHITECTURE: ${{ matrix.architecture }}
run: >-
node -e "const assert = require('node:assert/strict');
assert.equal(process.platform, process.env.EXPECTED_CI_PLATFORM);
assert.equal(process.arch, process.env.EXPECTED_CI_ARCHITECTURE);
console.log(JSON.stringify({ platform: process.platform, architecture: process.arch, node: process.version }));"
- run: npm ci
- name: Verify real Node Inspector discovery and observation
run: npm run verify:inspector
windows-curated:
name: Windows capability and package lane
needs: [changes, windows-native-build]
@@ -442,14 +417,14 @@ jobs:
tests/boundary/filesystem/binaryTarget.test.ts
tests/boundary/filesystem/safeOutputTree.test.ts
tests/boundary/providers/native/artifactProvider.archiveSafety.test.ts
tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts
tests/boundary/filesystem/setupUnavailableProvider.test.ts
tests/boundary/filesystem/windowsNpxRegistration.test.ts
src/application/ClientRegistrationIdentity.test.ts
tests/boundary/filesystem/webScriptManifestPaths.test.ts
tests/boundary/process/ProcessEvidence.host.test.ts
tests/acceptance/webModuleCli.test.ts
tests/acceptance/webSourceLocationCli.test.ts
tests/boundary/cli/referenceSourceImportStatus.test.ts
src/cliReferenceSourceImportStatus.test.ts
tests/boundary/filesystem/asarInventoryFreshness.test.ts
tests/composition/javascript-applications/javascriptArtifactReconstruction.test.ts
tests/conformance/providers/ghidra/windowsCapabilities.test.ts
@@ -457,6 +432,7 @@ jobs:
tests/boundary/providers/ghidra/ghidraTransport.test.ts
tests/boundary/providers/ghidra/ghidraTargetSnapshot.test.ts
tests/boundary/providers/ghidra/ghidraLauncher.test.ts
tests/boundary/providers/hopper/hopperClient.cleanupRetry.test.ts
src/windows/WindowsNativeLoader.test.ts
src/windows/WindowsOwnedProcess.test.ts
src/ghidra/GhidraLauncherEnvironment.test.ts
@@ -468,7 +444,29 @@ jobs:
tests/process-global/updateMaintenance.test.ts
tests/conformance/providers/ghidra/realGhidraWindowsWorkflow.test.ts
- run: npm run verify:windows-native
- name: Verify real Node Inspector discovery and observation
timeout-minutes: 10
env:
NODE_OPTIONS: "--max-old-space-size=1024"
UV_THREADPOOL_SIZE: "2"
run: npm run verify:inspector
- run: npm run verify:package:windows
- name: Verify native directory identity on Node 24
run: >-
npx vitest run --coverage.enabled=false
tests/boundary/filesystem/directoryArtifactReaderOpen.test.ts
tests/boundary/filesystem/javascriptPackagePrecedence.test.ts
tests/boundary/filesystem/javascriptArtifactContentIdentity.test.ts
- uses: actions/setup-node@v4
with:
node-version: 22.19.0
- name: Verify native path boundaries on Node 22
run: >-
npx vitest run --coverage.enabled=false
tests/boundary/filesystem/directoryArtifactReaderOpen.test.ts
tests/boundary/filesystem/javascriptPackagePrecedence.test.ts
tests/boundary/filesystem/javascriptArtifactContentIdentity.test.ts
tests/boundary/process/sourceMapUncHosts.test.ts
- uses: actions/upload-artifact@v4
if: always()
with:
+20
View File
@@ -64,6 +64,14 @@ jobs:
env:
REA_ANALYSIS_PROVIDER: ghidra
run: npm run verify:ghidra:windows -- --x86 | Tee-Object -FilePath windows-ghidra-x86-proof.log
- name: Verify native x64 DLL Windows Ghidra operations
env:
REA_ANALYSIS_PROVIDER: ghidra
run: npm run verify:ghidra:windows -- --dll | Tee-Object -FilePath windows-ghidra-dll-proof.log
- name: Verify native x86 DLL Windows Ghidra operations
env:
REA_ANALYSIS_PROVIDER: ghidra
run: npm run verify:ghidra:windows -- --x86 --dll | Tee-Object -FilePath windows-ghidra-x86-dll-proof.log
- name: Verify ordinary-user CLI and MCP operations
env:
REA_ANALYSIS_PROVIDER: ghidra
@@ -72,6 +80,14 @@ jobs:
env:
REA_ANALYSIS_PROVIDER: ghidra
run: npm run verify:ghidra:windows:package -- --x86 | Tee-Object -FilePath windows-ghidra-x86-package-proof.log
- name: Verify ordinary-user x64 DLL CLI and MCP operations
env:
REA_ANALYSIS_PROVIDER: ghidra
run: npm run verify:ghidra:windows:package -- --dll | Tee-Object -FilePath windows-ghidra-dll-package-proof.log
- name: Verify ordinary-user x86 DLL CLI and MCP operations
env:
REA_ANALYSIS_PROVIDER: ghidra
run: npm run verify:ghidra:windows:package -- --x86 --dll | Tee-Object -FilePath windows-ghidra-x86-dll-package-proof.log
- uses: actions/upload-artifact@v4
if: always()
with:
@@ -81,4 +97,8 @@ jobs:
windows-ghidra-package-proof.log
windows-ghidra-x86-proof.log
windows-ghidra-x86-package-proof.log
windows-ghidra-dll-proof.log
windows-ghidra-x86-dll-proof.log
windows-ghidra-dll-package-proof.log
windows-ghidra-x86-dll-package-proof.log
retention-days: 30
@@ -56,9 +56,9 @@ jobs:
shell: bash
run: |
mkdir -p "$RUNNER_TEMP/rea-wakaru"
curl --fail --location --retry 3 https://github.com/pionxzh/wakaru/releases/download/v1.13.0/wakaru-linux-x64.tar.gz -o "$RUNNER_TEMP/rea-wakaru/release.tar.gz"
curl --fail --location --retry 3 https://github.com/pionxzh/wakaru/releases/download/v1.14.0/wakaru-linux-x64.tar.gz -o "$RUNNER_TEMP/rea-wakaru/release.tar.gz"
tar -xzf "$RUNNER_TEMP/rea-wakaru/release.tar.gz" -C "$RUNNER_TEMP/rea-wakaru" wakaru
printf '%s %s\n' e8c7ca052974604197389f6ace7464e4dd24dce64e2730971521bd6606ec9c9e "$RUNNER_TEMP/rea-wakaru/wakaru" | sha256sum --check
printf '%s %s\n' 664fa06782a61eda7ed15885134b52525fd565dd77607e642062ceb6cd927c38 "$RUNNER_TEMP/rea-wakaru/wakaru" | sha256sum --check
- name: Install isolated fixture compilers
run: npm install --prefix "$RUNNER_TEMP/rea-fixture-compilers" --ignore-scripts --no-audit --no-fund esbuild@0.25.10 webpack@5.101.3
- run: npm run build:cached
+97 -8
View File
@@ -1,6 +1,11 @@
name: Release
on:
push:
branches: [main]
pull_request:
branches: [main]
types: [closed]
workflow_dispatch:
inputs:
release_branch:
@@ -18,12 +23,89 @@ env:
HUSKY: "0"
concurrency:
group: release-${{ inputs.release_branch }}
group: release-${{ inputs.release_branch || github.event.pull_request.merge_commit_sha || github.ref_name }}
cancel-in-progress: false
jobs:
release-proposal:
name: Update release proposal
if: github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: googleapis/release-please-action@v4
with:
token: ${{ secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }}
target-branch: main
skip-github-release: true
merged-release:
name: Release reviewed main merge
if: >-
github.event_name == 'pull_request' && github.event.pull_request.merged == true &&
github.event.pull_request.head.repo.full_name == github.repository &&
startsWith(github.event.pull_request.head.ref, 'release-please--branches--main--')
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
outputs:
release_created: ${{ steps.release.outputs.release_created }}
sha: ${{ steps.release.outputs.sha }}
steps:
- name: Check out reviewed release merge
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.merge_commit_sha }}
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-node@v6
with:
node-version-file: .nvmrc
package-manager-cache: false
- run: npm ci
- name: Validate reviewed merge before release creation
env:
SOURCE_SHA: ${{ github.event.pull_request.merge_commit_sha }}
run: |
if [[ "${SOURCE_SHA}" != "${GITHUB_SHA}" ]]; then
echo "The reviewed merge differs from the workflow source; refusing mismatched publication provenance." >&2
exit 1
fi
node scripts/verify-release-checkpoint.mjs \
--phase publish --release-branch main --source-sha "$SOURCE_SHA"
- uses: googleapis/release-please-action@v4
id: release
with:
token: ${{ secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }}
target-branch: main
skip-github-release: false
skip-github-pull-request: true
- name: Bind publication to the reviewed merge
env:
RELEASE_CREATED: ${{ steps.release.outputs.release_created }}
RELEASE_SHA: ${{ steps.release.outputs.sha }}
SOURCE_SHA: ${{ github.event.pull_request.merge_commit_sha }}
run: |
if [[ "${RELEASE_CREATED}" != true ]]; then
echo "Release Please did not create a release for the reviewed merge. Check its pending label and release metadata; for a partial publication, re-run failed jobs in the original run." >&2
exit 1
fi
if [[ "${RELEASE_SHA}" != "${SOURCE_SHA}" ]]; then
echo "The tagged release differs from the reviewed merge; refusing mismatched publication provenance. The GitHub release already exists; do not create another release as a retry." >&2
exit 1
fi
release-please:
name: Release Please
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: write
@@ -176,8 +258,11 @@ jobs:
publish:
name: Publish to npm
needs: release-please
if: inputs.phase == 'publish' && needs.release-please.outputs.release_created == 'true'
needs: [merged-release, release-please]
if: >-
always() && !cancelled() &&
((needs.merged-release.result == 'success' && needs.merged-release.outputs.release_created == 'true') ||
(needs.release-please.result == 'success' && inputs.phase == 'publish' && needs.release-please.outputs.release_created == 'true'))
runs-on: ubuntu-latest
permissions:
contents: read
@@ -185,7 +270,7 @@ jobs:
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.release-please.outputs.sha }}
ref: ${{ needs.merged-release.outputs.sha || needs.release-please.outputs.sha }}
persist-credentials: false
- uses: actions/setup-node@v6
@@ -213,7 +298,8 @@ jobs:
if [ "${published_version}" = "\"${version}\"" ]; then
echo "rea-agents@${version} is already published; verifying the existing package."
else
npm publish --access public
tag="$(node scripts/release-npm-tag.mjs "${version}")"
npm publish --access public --tag "${tag}"
fi
- name: Verify published CLI from npm
@@ -247,8 +333,11 @@ jobs:
publish-mcp:
name: Publish to MCP Registry
needs: [release-please, publish]
if: inputs.phase == 'publish' && needs.release-please.outputs.release_created == 'true' && needs.publish.result == 'success'
needs: [merged-release, release-please, publish]
if: >-
always() && !cancelled() && needs.publish.result == 'success' &&
((needs.merged-release.result == 'success' && needs.merged-release.outputs.release_created == 'true') ||
(needs.release-please.result == 'success' && inputs.phase == 'publish' && needs.release-please.outputs.release_created == 'true'))
runs-on: ubuntu-latest
permissions:
contents: read
@@ -256,7 +345,7 @@ jobs:
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.release-please.outputs.sha }}
ref: ${{ needs.merged-release.outputs.sha || needs.release-please.outputs.sha }}
persist-credentials: false
- name: Verify package and registry metadata versions
+15 -7
View File
@@ -5,8 +5,7 @@ on:
branches: [main, "release/*"]
paths:
- "website/**"
- "scripts/verify-website.py"
- "scripts/prepare-website.py"
- "scripts/*website*.py"
- ".github/workflows/**"
workflow_dispatch:
@@ -21,11 +20,20 @@ jobs:
check:
name: Website checks
runs-on: ubuntu-latest
timeout-minutes: 5
timeout-minutes: 10
steps:
- name: Check out the repository
uses: actions/checkout@v4
- name: Prepare the example download
run: python3 scripts/prepare-website.py
- name: Check website links and publishing configuration
run: python3 scripts/verify-website.py
- name: Set up Python for website assets
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
cache-dependency-path: website/requirements.txt
- name: Install sharing-image dependencies
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends -y libcairo2 fonts-dejavu-core
python3 -m pip install -r website/requirements.txt
- name: Check shared HTML, links, assets and contributor workflows
run: python3 scripts/website.py check
+136 -6
View File
@@ -2,6 +2,15 @@ name: Publish REA website
on:
workflow_dispatch:
inputs:
target:
description: Publish both hosts, or Pages while configuring Cloudflare
type: choice
required: true
default: both
options:
- both
- pages
permissions:
contents: read
@@ -14,17 +23,56 @@ jobs:
prepare:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
timeout-minutes: 5
timeout-minutes: 10
permissions:
contents: read
pages: read
steps:
- name: Validate the publication target
env:
PUBLISH_TARGET: ${{ inputs.target }}
run: |
case "$PUBLISH_TARGET" in
both|pages) ;;
*) echo "::error::Unknown publication target: $PUBLISH_TARGET"; exit 1 ;;
esac
- name: Require Cloudflare publishing credentials
if: inputs.target == 'both'
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
run: |
if [[ -z "$CLOUDFLARE_API_TOKEN" || -z "$CLOUDFLARE_ACCOUNT_ID" ]]; then
echo "::error::Set CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID in repository Actions secrets before publishing."
exit 1
fi
- name: Check out the repository
uses: actions/checkout@v4
- name: Prepare the example download
run: python3 scripts/prepare-website.py
- name: Check website links and publishing configuration
run: python3 scripts/verify-website.py
- name: Set up Python for website assets
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
cache-dependency-path: website/requirements.txt
- name: Install sharing-image dependencies
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends -y libcairo2 fonts-dejavu-core
python3 -m pip install -r website/requirements.txt
- name: Check shared HTML, links, assets and contributor workflows
run: python3 scripts/website.py check
- name: Record the published commit
run: |
python3 - <<'PY'
import json
import os
from pathlib import Path
Path("website/public/deployment.json").write_text(
json.dumps({"commit": os.environ["GITHUB_SHA"]}) + "\n",
encoding="utf-8",
)
PY
- name: Configure Pages
uses: actions/configure-pages@v5
- name: Upload the website
@@ -35,14 +83,96 @@ jobs:
deploy:
needs: prepare
runs-on: ubuntu-latest
timeout-minutes: 5
timeout-minutes: 15
permissions:
contents: read
actions: read
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Check out publishing configuration
if: inputs.target == 'both'
uses: actions/checkout@v4
- name: Set up Node.js for Wrangler
if: inputs.target == 'both'
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
- name: Download the verified website
if: inputs.target == 'both'
uses: actions/download-artifact@v4
with:
name: github-pages
path: ${{ runner.temp }}/website-archive
- name: Extract the shared publishing artifact
if: inputs.target == 'both'
run: |
mkdir -p "$RUNNER_TEMP/rea-website-public"
tar -xf "$RUNNER_TEMP/website-archive/artifact.tar" -C "$RUNNER_TEMP/rea-website-public"
- name: Publish the website to Cloudflare
if: inputs.target == 'both'
uses: cloudflare/wrangler-action@v4
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
wranglerVersion: "4.149.0"
packageManager: npm
command: deploy --cwd website --env production --assets "${{ runner.temp }}/rea-website-public"
- name: Publish to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
- name: Verify the selected published revisions
env:
PAGES_URL: ${{ steps.deployment.outputs.page_url }}
PUBLISH_TARGET: ${{ inputs.target }}
run: |
python3 -u - <<'PY'
import json
import os
import sys
import time
from urllib.error import URLError
from urllib.parse import urljoin
from urllib.request import Request, urlopen
expected = os.environ["GITHUB_SHA"]
pages_url = os.environ["PAGES_URL"]
if not pages_url:
sys.exit("GitHub Pages returned no published URL.")
target = os.environ["PUBLISH_TARGET"]
if target not in ("both", "pages"):
sys.exit("Unknown publication target: " + target)
hosts = {"GitHub Pages": pages_url}
if target == "both":
hosts["Cloudflare"] = "https://rea.tools/"
pending = dict(hosts)
for attempt in range(24):
for name, base in list(pending.items()):
url = urljoin(base, "deployment.json") + "?commit=" + expected
try:
request = Request(url, headers={
"Cache-Control": "no-cache",
"User-Agent": "REA-Website-Verifier/1.0 (+https://github.com/morluto/rea)",
})
with urlopen(request, timeout=10) as response:
actual = json.load(response).get("commit")
if actual == expected:
print(f"{name} serves {expected}: {base}")
del pending[name]
else:
print(f"Waiting for {name}: observed revision {actual}")
except (URLError, TimeoutError, ValueError) as error:
print(f"Waiting for {name}: {error}")
if not pending:
break
if attempt < 23:
time.sleep(5)
if pending:
sys.exit("Could not verify published revision on: " + ", ".join(pending))
with open(os.environ["GITHUB_STEP_SUMMARY"], "a", encoding="utf-8") as summary:
links = " and ".join(f"[{name}]({url})" for name, url in hosts.items())
summary.write(f"Published commit `{expected}` to {links}.\n")
PY
+11 -3
View File
@@ -49,12 +49,20 @@ Thumbs.db
# Generated website download
/website/public/examples/notes-example.zip
/website/public/deployment.json
/website/public/sitemap.xml
/website/public/assets/social-card.png
/website/.venv/
# Build-generated MCP tool catalog (regenerated by `npm run build`; never commit)
src/generatedMcpToolCatalog.ts
# Local Cloudflare development state
/website/.wrangler/
/website/.dev.vars*
/website/.env*
!/website/.dev.vars.example
!/website/.env*.example
# Derived catalogs, portable conformance projections, and packaged skill bundles
# (regenerated from this checkout by `npm run build:cached`; never commit)
# (regenerated by `npm run docs:generate`; never commit)
/skills/
/docs/public/product-catalog.json
/docs/verification/managed-conformance-manifest.json
+2 -2
View File
@@ -1,6 +1,6 @@
{
"_comment": "Test files are intentionally NOT excluded: the gate used to report zero clones because it skipped **/*.test.ts, hiding all test-tree duplication. Current actual is ~2.4% lines across src+ and tests/, down from 3.4% when tests were included. Lower this as duplication is removed.",
"threshold": 2.5,
"_comment": "Test files are intentionally NOT excluded: the gate used to report zero clones because it skipped **/*.test.ts, hiding all test-tree duplication. Current actual is ~2.47% lines across src+ and tests/, down from 3.4% when tests were included. The 2.6% limit leaves modest headroom for ordinary changes; lower it as duplication is removed.",
"threshold": 2.6,
"reporters": ["consoleFull"],
"ignore": [
"node_modules/**",
+1 -1
View File
@@ -1,3 +1,3 @@
{
".": "6.0.0"
".": "6.3.0"
}
+25 -84
View File
@@ -1,108 +1,49 @@
# Repository Guidelines
## Product Direction
## Product and Authority
REA exposes reverse-engineering tools through a CLI and MCP server. Hopper, the bring-your-own Ghidra adapter, and the bring-your-own IDA MCP adapter are operation-capable deep binary-analysis providers. Ghidra is supported on Linux x64 and macOS x64/arm64 with matching native decompiler tools, and has an experimental Windows x64 P0 boundary for approved native x86 and x86-64 PE applications; on Linux and macOS it supplies inventory, function analysis, and atomic function annotation edits in an ephemeral database, without modifying executable bytes or controlling a GUI. Windows P0 has no mutation authority. IDA adapts upstream legacy attached GUI and modern headless database-supervisor profiles for live read-only analysis; initial real verification covers Windows, and an attached GUI database is never saved or closed. Keep provider-specific code out of the domain and application layers.
REA is a local-only reverse-engineering tool with shared CLI/MCP workflows. Distinguish observations, derivations, inferences, and unknowns; preserve Evidence provenance and session semantics through both adapters. Provider support and setup live in [README.md](README.md#choosing-a-deep-analysis-provider) and its linked guides.
Prioritize:
Ghidra uses ephemeral databases without modifying executable bytes or controlling a GUI; Windows Ghidra P0 has no mutation authority. IDA analysis is read-only; never save or close an attached GUI database.
- tool results that distinguish observations, inferences, and unknowns;
- equivalent behavior through the CLI and MCP;
- additive, idempotent configuration with backups;
- end-to-end tests for packaged artifacts and real Hopper/Ghidra claims.
Configuration changes must be additive and idempotent, with backups. Installers must not install or upgrade unrelated software, including Homebrew, Node.js, npm, Java, or Ghidra. Ghidra and IDA are bring-your-own. `rea setup` must show its planned changes and require approval before writing files or installing Hopper.
Installers must not install or upgrade Homebrew, Node.js, npm, Java, Ghidra, or other unrelated software. Ghidra is bring-your-own. `rea setup` must print its planned changes and require approval before writing files or installing Hopper.
Preserve caller-selected inputs and local evidence, including output, URLs, paths, digests, and metadata. Redact transport authentication credentials and explicitly marked sensitive values; do not infer secrecy from names or text patterns. Do not persist the ambient environment merely because a child inherits it.
REA is a local-only tool. Preserve caller-selected inputs, captured output, URLs, paths, digests, mismatch locations, and analysis metadata. Do not guess that local evidence is secret from environment-variable names, argument names, or text patterns. Redact transport authentication credentials and values the caller explicitly marks sensitive; do not persist the entire ambient environment merely because a child inherits it.
## Architecture and Cleanup
## Project Structure & Module Organization
Dependencies flow inward: domain semantics and contracts, provider adapters, shared application workflows, then CLI/MCP adapters. Keep engine protocols and provider-specific code out of domain/application layers. See [docs/architecture.mermaid](docs/architecture.mermaid) when changing composition.
REA is a layered ESM TypeScript application. Dependencies flow inward from pure domain logic through contracts, providers, application workflows, and CLI/MCP adapters. See [docs/architecture.mermaid](docs/architecture.mermaid) for the component map.
Give each interpretation and resource a clear owner. Preserve identity, omission, uncertainty, and source evidence across boundaries. Retain ownership of resources whose cleanup failed. Reuse `src/process/` supervision and identity primitives; a PID and executable path alone do not establish ownership after exit or reuse.
- `src/domain/` owns pure provider-neutral semantics; `src/contracts/` owns caller-visible schemas and the canonical tool inventory.
- `src/hopper/`, `src/ghidra/`, `src/ida/`, `src/browser/`, `src/inspector/`, `src/native/`, `src/artifacts/`, and `src/dotnet/` own provider-specific boundaries. Keep provider protocols out of domain and application code.
- `src/application/` composes shared CLI/MCP workflows, including Evidence provenance, unknowns, and eligible snapshot bindings; `src/server/` translates MCP requests; `src/cli.ts` and `src/main.ts` are the CLI and MCP entry points.
- `src/process/` owns shared process lifecycle primitives, not provider wire protocols. Reuse its supervision and identity primitives before adding provider-local lifecycle code; a PID and executable pathname alone do not establish ownership after exit or reuse. `bridge/` contains provider-side adapters.
- `tests/` contains unit, composition, boundary, acceptance, and conformance tests. `scripts/verify-*` and capability directories under `scripts/verify/` contain real-toolchain checks.
- `docs/public/product-catalog.json`, `docs/verification/managed-conformance-*.json`, and `skills/` are ignored build outputs. Update source contracts and authored instructions in `skill-src/`, then run `npm run build:cached`; never commit derived catalog digests or portable conformance projections.
- `src/generatedMcpToolCatalog.ts` is build-generated and gitignored. Never commit it; resolve any trace of it in merges by deleting it and running `npm run build:cached`.
Assess brittleness in touched code during implementation, debugging, review, and maintenance. Fix the producing representation or ownership rule before adding downstream repairs. Normalize once at the owning boundary using format-aware parsers. Remove superseded representations, aliases, wrappers, and redundant tests after verifying affected consumers. Introduce abstractions only when they remove observed complexity.
## Build, Test, and Development Commands
Parse unknown boundary values and model expected failures with the tagged error algebra and `Result`. Preserve partial facts and meaningful failure reasons. Keep identity and lookup values separate from display formatting; preserve source values and explicit unknowns when normalization loses information. Absolute paths, file URLs, and HTTP paths have different semantics.
- `npm ci`: install the locked dependencies.
- `npm run build:cached`: build the CLI and MCP server.
- `npm run test:local`: run changed source tests without building; pass exact source test paths to run them regardless of Git status.
- `npm run test:focused -- PATH...`: run exact test files; build first for boundary, acceptance, or process-global tests.
- `npm run check:changed`: run cached static checks and source tests affected since the branch merge base (default `origin/main`).
- `npm run check:fast`: run cached typecheck and lint checks.
- `npm run check:pr`: opt into the complete local deterministic gate and generated-document checks for broad changes; CI owns full coverage. Routine iterations need focused tests and relevant checks, not the whole gate each time.
- `npm run docs:check`: build and validate generated documents for the current checkout; `npm run docs:generate` regenerates them. CI retains ignored outputs as artifacts and does not push snapshot commits to feature branches.
- For provider-dependent changes, see [docs/testing.md](docs/testing.md) and run the matching real-provider verification.
- Keep each verification lane's prerequisites limited to the claim it checks. Use host-native fixtures for host/provider acceptance; put optional cross-target formats and their external toolchains in a separate lane. Preflight required commands and report the missing dependency and lane clearly.
Validate advertised JSON Schemas after SDK conversion against their declared dialect and actual clients. Bind handlers to named contracts with exact types; catalog ordering must never select an operation or schema.
See [docs/testing.md](docs/testing.md) for test scopes and verification lanes and [CONTRIBUTING.md](CONTRIBUTING.md) for contribution checks. Pre-commit formats and lints staged source; pre-push runs `npm run check:fast`.
## Development
## Configuration & Environment Variables
Use [.nvmrc](.nvmrc) and `package.json#packageManager` for the pinned toolchain. Cursor Cloud may place older Node.js first on `PATH`; environment setup installs the pinned toolchain under `/usr/local/bin`.
Configuration is parsed and validated by `src/config.ts` and `src/config/`. Keep user-facing setup and provider configuration in [README.md](README.md) and the relevant guide under `docs/`; do not maintain a second environment-variable catalogue here.
- `npm ci`: install locked dependencies.
- `npm run build:cached`: build the runtime and packaged skill.
- `npm run test:local -- PATH...`: source tests without building.
- `npm run test:focused -- PATH...`: exact tests with their required artifacts.
- `npm run check:fast`: cached typecheck/lint and the pre-push check.
- `npm run docs:check`: validate generated documentation.
## Coding Style & Naming Conventions
Use relevant checks for the change. The complete local gate, `npm run check:pr`, is optional for broad changes or CI diagnosis. See [CONTRIBUTING.md](CONTRIBUTING.md) for development, generated-file ownership, and release conventions.
Use ESM TypeScript, two-space indentation, and the committed Oxfmt configuration. Keep compiler strictness intact (`strict`, `exactOptionalPropertyTypes`, `noUncheckedIndexedAccess`, `verbatimModuleSyntax`). Use `camelCase` for values/functions, `PascalCase` for classes/types, and `UPPER_SNAKE_CASE` for constants. Parse unknown values at every MCP, environment, and subprocess boundary. Avoid `any`, unchecked casts, non-null assertions, import-time I/O, and floating promises. Exported APIs require concise JSDoc. Model expected failures with the tagged error algebra and `Result`, not broad exception wrappers.
`docs/public/product-catalog.json`, `docs/verification/managed-conformance-*.json`, and `skills/` are ignored outputs. Edit source contracts and `.agents/skills/reverse-engineer-anything/`, then regenerate as needed. `.cache/mcp-tool-catalog.json` is test metadata; runtime builds and source checking do not consume it. Never commit binaries, provider project documents, credentials, `dist/`, `node_modules/`, or local planning artifacts.
## Boundary Contracts
## Tool and Test Changes
Treat a boundary as a contract between the producer's actual representation and the consumer's required meaning. When implementing or auditing a boundary, trace the value through parsing, normalization, authorization, serialization, and the CLI/MCP result. Establish affected callers from their code paths; similar tool names or workflows do not prove that they share a schema or failure mode.
For tool design, follow [docs/tool-design.md](docs/tool-design.md): start from the analyst question, reuse existing contracts, preserve caller choices, and return useful evidence inline. Limits must follow real format, protocol, authority, or resource constraints. Account for representation expansion before allocation; derive completeness from examined coverage.
When changing boundary behavior, inspect adjacent input representations, failure paths, and affected callers, and correct the underlying assumption across those cases.
For test changes or provider claims, use [docs/testing.md](docs/testing.md). Prefer real public CLI/MCP workflows, then production-boundary integration, then producer goldens. Keep module tests for distinct semantics stronger workflows cannot reliably reproduce. Preserve malformed-input, cancellation, cleanup, permission, capacity, and target-identity coverage when pruning. Report unverified coverage explicitly; simulated providers do not establish real-provider behavior.
Keep portable evidence and scenario validation distinct from host-native execution checks. Absolute filesystem paths, file URLs, and HTTP paths have different semantics; do not substitute one platform's syntax for the domain concept. Interpret provider metadata according to its documented or observed producer behavior. Keep values used for identity, provenance, matching, and path resolution separate from display formatting. When normalization loses information, preserve the source value and an explicit unknown; display placeholders must not feed back into lookup or selection.
Preserve meaningful failure reasons through application and adapter layers. Malformed input is distinct from an unsupported target, unavailable provider, or host operating-system permission denial. Diagnostics should identify the failed constraint and the target or lifecycle request it applies to. Recovery advice must address that reason and point to an available workflow; generic catches must not erase actionable validation details. Preserve collected observations on execution failure independently of whether cleanup succeeds.
Leave meaningful target, action, capture, and output choices to the agent. A selected operation already expresses intent; do not require approval booleans or repeated permission declarations. Trace each setting to its consumer: remove ignored options and single-value confirmations, derive built-in lifecycle behavior, and supply defaults for omitted optional metadata. Report actual effects and limitations where they help interpret results rather than asking callers to restate them.
Verify the representation consumed at the next boundary. Internal validator success does not establish JSON Schema validity or client compatibility: validate advertised input and output schemas against their declared dialect after SDK conversion, and keep generated contracts aligned. Use representative producer data and regressions that exercise the failed behavior. Platform and provider support claims require the corresponding real workflow; package startup, capability probes, and mock transport tests establish only their narrower claims. Report unverified coverage explicitly.
Bind tool handlers to named contracts, preserving their exact input and output types. Catalog ordering is presentation metadata; changing that order must not select a different schema or operation for an existing handler.
## Designing MCP Tools
Start from the analyst question and desired result, not a provider API. Before adding a tool, inspect the existing contract and its nearest alternative.
Let agents compose experiments with ordinary commands, scripts, and local fixture servers. REA tools should perform the requested inspection or capture and return evidence. A custom orchestration language, replay engine, or separate prepare/execute plan needs an observed requirement that those primitives cannot satisfy. A plan-only tool without an executor does not establish runtime behavior; expose the useful inspection directly.
- Prefer reusable, composable primitives: inspect one explicit object or
relationship and return evidence that can support different analyst
questions. Compose primitives into a workflow only for a recurring outcome
that benefits from joining evidence sources; keep one-application or
business-domain interpretations out of general tool contracts.
- Use **inspect/search** tools for facts about a target or candidate set; use **trace** tools for relationships; use **compare** tools for explicitly paired inputs.
- Add a **workflow** when observed agent use shows a repeated sequence that REA can compose without losing analyst control. Return useful results inline so callers can choose their next action.
- Use **observe/capture** only when runtime activity is required, and declare authority and lifecycle effects in the contract.
- Extend an existing tool when intent and result contract are unchanged. Add a tool for a distinct analyst outcome or materially different authority.
- Keep caller-facing names and results provider-neutral. Put engine-specific behavior in provider adapters and report each provider's exact coverage.
- Keep results complete by default. Add a limit only when it follows from a real format, protocol, authority, or resource-safety constraint; explain truncation and unsupported facets. Account for representation expansion and products of independently bounded dimensions before allocating or retaining output. Derive facet completeness from what was examined and exhausted, not an empty failure list. Keep observed, derived, inferred, and unknown results distinct.
- Include artifact identity, source locations, Evidence references, actionable errors, and relevant limitations when they affect conclusions. Return the evidence needed for the next analysis inline rather than requiring a resource or identifier lookup.
- Implement shared application workflows behind CLI and MCP adapters. Update canonical contracts and generated catalog together.
See [docs/tool-design.md](docs/tool-design.md) for the design checklist. When usability or tool selection changes, evaluate representative CLI/MCP tasks as well as schema and transport behavior.
## Testing Guidelines
Name tests `*.test.ts`. Use Vitest and production seams (`tests/fixtures/`) rather than module mocks. Domain tests assert pure behavior; adapter tests use fake launcher/socket seams; MCP tests connect with the client SDK version pinned in `package.json`. Preserve the canonical tool inventory defined by `TOOL_CONTRACTS` and verified through `CATALOG_IDENTITY` and generated product metadata. Cover malformed input, cancellation, lifecycle cleanup, and actual format, protocol, host-permission, and target-identity boundaries. Do not add tests that merely freeze arbitrary caps or prescribed call sequences. Real Hopper, Ghidra, browser, managed conformance, and any real managed-tool claims cannot be replaced by mocks; use the corresponding `verify:*` command.
Keep tool catalogs complete and self-describing; prefer capability- and session-scoped availability over schema truncation. Serialized bytes alone do not measure agent usability or model context cost.
## Cursor Cloud specific instructions
Development requires Node.js 24.18.0 and npm 11.16.0 (`.nvmrc` and `packageManager`). The Cloud Agent image places an older `node` on `PATH` ahead of a normal install. Environment setup installs the pinned toolchain under `/usr/local` and prepends `/usr/local/bin` for login shells. Confirm `node -v` is `v24.18.0` before installing dependencies.
`npm ci` installs locked dependencies. `npm run build:cached` produces the CLI and MCP server. `npm run check:fast` is the pre-push typecheck and lint. Hopper, Ghidra, and IDA are optional bring-your-own providers. JavaScript analysis and the deterministic Vitest suites do not need them. `rea doctor` reports those engines as missing until they are configured.
## Commit & Pull Request Guidelines
Use Conventional Commit subjects because Release Please derives versions and changelogs from them. Examples: `feat: add historical source import`, `fix(process): stop timers after exit`, and `docs: update architecture`. Use `!` or a `BREAKING CHANGE:` footer for breaking changes. Pull request titles must follow the same format because squash merges use the title as the release commit. Pull requests should describe contract or behavior changes, list verification commands, link issues, and include sanitized MCP examples when schemas change. State whether real Hopper/Ghidra verification was performed. Never commit binaries, Hopper or Ghidra project documents, credentials, `dist/`, `node_modules/`, or local planning artifacts (e.g. `.codex/`).
Use Conventional Commit subjects and PR titles. Mark breaking changes with `!` or a `BREAKING CHANGE:` footer. Describe behavior changes, relevant validation, and real-provider verification scope.
<!-- BEGIN:turborepo-agent-rules -->
+634
View File
@@ -1,5 +1,639 @@
# Changelog
## [6.3.0](https://github.com/morluto/rea/compare/rea-agents-6.2.0...rea-agents-6.3.0) (2026-10-09)
### ⚠ BREAKING CHANGES
* **captures:** Historical captures without current producer accounting or transaction identity, and web diffs missing accessibility or storage dimensions, are rejected. Preserve original captures and recapture with the current producer; update comparison consumers to include every dimension rather than synthesizing missing observations. See the [process capture guide](docs/process-capture.md) and [browser scenario contract](docs/browser-scenario-contract.md). ([3283a45](https://github.com/morluto/rea/commit/3283a45d09457c79e3adadb50a48620926d4bc5b))
* **browser:** JSON shape paths now contain typed property and array-element segments. WebMCP input_schema_shape is replaced by input_schema and input_schema_sha256, retaining declared examples and defaults.
* **process:** Filesystem digest omission entries now require system_code; budget and changed-file omissions use null, and unavailable-file omissions preserve the operating-system error code.
* **contracts:** Provider analysis outputs must explicitly supply metadata previously repaired with defaults; unsupported nullable facets must be reported as null.
* **javascript:** Semantic graph facts now store evidence context IDs and locations. Graph and semantic trace results require an inline evidence_contexts table.
* **contracts:** source-map URLs now live in target observations selected by declared_url_sha256, and doctor skill identity no longer emits installed_catalog_digest. Use the documented observation join and identity.skill.state instead.
* **javascript:** remove the never-incremented truncated_scopes statistic from JavaScript application analysis results and schemas.
* **native:** Objective-C attribute tokens now contain only name and value. Properties report nullable atomicity and readonly facts; class flags, ivar counts, and method requirement flags are nullable when unobserved.
### Features
* **setup:** register OMP during setup ([#1301](https://github.com/morluto/rea/pull/1301)) ([8b4c359](https://github.com/morluto/rea/commit/8b4c3591358ee59297d8298ede1b63d08459d817))
* **javascript:** record Electron integrity mismatches ([7915ee5](https://github.com/morluto/rea/commit/7915ee51781878ed67e094259924b6e6f3093b3f))
### Bug Fixes
* **inspector:** retain observations after capture failures ([dea3498](https://github.com/morluto/rea/commit/dea3498b2b8d919606eefc4fd62f6ebcbbe5ed30))
* **artifacts:** bind ASAR interpretation to owned snapshots ([d79317c](https://github.com/morluto/rea/commit/d79317cda0bbe8240eb7e25b0a5de90dcffca5fa))
* **artifacts:** infer legacy Mach-O simulator platforms ([5aa2002](https://github.com/morluto/rea/commit/5aa200285ab066e48b37b716495936e6e2a963fd))
* **artifacts:** preserve archive facts and Unicode path identity ([5751f5c](https://github.com/morluto/rea/commit/5751f5caac86c770123ae739a4e4101a72b0989c))
* **artifacts:** reject incomplete inventoried extraction ([5e8fb53](https://github.com/morluto/rea/commit/5e8fb531e255a4a04fc053c54096f66d5c84cde3))
* **artifacts:** retain DMG ownership through uncertain attachment ([a27794c](https://github.com/morluto/rea/commit/a27794c246b3f11d7f92ae7f6d276718190ab731))
* **artifacts:** validate only active extraction entries ([cfb12e4](https://github.com/morluto/rea/commit/cfb12e47dc241f057be93a00892f7d7361d6119d))
* **browser:** follow only HTTP redirect statuses for source maps ([82bbe74](https://github.com/morluto/rea/commit/82bbe743336244d398e67512659ea6943d43a4a4))
* **browser:** preserve payload shapes and WebMCP declarations ([4951a89](https://github.com/morluto/rea/commit/4951a897c53bb6882300c5d7a9660a3f43e374f5))
* **browser:** release attached viewport overrides without resizing the external page ([f6cfbfc](https://github.com/morluto/rea/commit/f6cfbfcc554ff24173dd7ad5333e8e26ab9c962d))
* **browser:** retain attached scenario emulation until cleanup ([a0523b3](https://github.com/morluto/rea/commit/a0523b375eb3147f1d2d1e7eb10a2f4546f5d0fc))
* **browser:** retain malformed redirect diagnostics ([617cd84](https://github.com/morluto/rea/commit/617cd84d27d100e7cc3cd4b5721dea4a996c9775))
* **browser:** serialize attached scenarios through cleanup settlement ([cfce91d](https://github.com/morluto/rea/commit/cfce91d418fbcde4a9ef283a61549279751854e7))
* **ci:** scope verification and reuse native runners ([#1344](https://github.com/morluto/rea/issues/1344)) ([d5cb8ae](https://github.com/morluto/rea/commit/d5cb8aee063065a48233458e04771635167825c8))
* **cli:** avoid duplicate primary cleanup diagnostics ([37fcea7](https://github.com/morluto/rea/commit/37fcea78cecbeeadd869e9a3d77dd133ed264a0a))
* **cli:** classify JSON input permission denials ([08daf05](https://github.com/morluto/rea/commit/08daf056cc8e4d092f9592574d09d5182457b7bc))
* **cli:** classify oversized JSON inputs ([f7cf4c8](https://github.com/morluto/rea/commit/f7cf4c890d4b9c70b1f56e6c627b44a59e58fd73))
* **cli:** stream JSON inputs beyond the whole-document string limit ([#1360](https://github.com/morluto/rea/issues/1360)) ([6ce3288](https://github.com/morluto/rea/commit/6ce3288f3bd65a886e47905455ed5c9b661015e6)), closes [#1331](https://github.com/morluto/rea/issues/1331)
* **cli:** stream JSON results at the shared command boundary ([810107a](https://github.com/morluto/rea/commit/810107a2ad15cc52afd6662aec24d231d8c77225))
* **contracts:** advertise NUL with a portable hex escape ([3f59a84](https://github.com/morluto/rea/commit/3f59a84bd1039763bb349894542601ed78be2033)), closes [#1329](https://github.com/morluto/rea/issues/1329)
* **contracts:** require observed provider output metadata ([a4ba8ae](https://github.com/morluto/rea/commit/a4ba8aecd507637b6261026afc17f79516840d50))
* **electron:** preserve unrepresentable numeric option evidence ([41a228c](https://github.com/morluto/rea/commit/41a228c1b01a89127858b1706879ede08a81deaf))
* **evidence:** order canonical projections independently of locale ([614fb76](https://github.com/morluto/rea/commit/614fb7681ee9e4eba7219c1ee9e90d6a85d78095))
* **files:** reject nonregular capture and JSON inputs ([5f16124](https://github.com/morluto/rea/commit/5f16124a31fa4a82bd03037506809d6be959d768))
* **filesystem:** reject unstable artifact targets ([7829b1a](https://github.com/morluto/rea/commit/7829b1aeef8f43f186be2d2adbd6c67541306a7a))
* **ghidra:** reject a native decompiler built for another host ([#1280](https://github.com/morluto/rea/issues/1280)) ([3728c82](https://github.com/morluto/rea/commit/3728c8267b4fb6da78cbae42a2a6cbddff80ea84)), closes [#1192](https://github.com/morluto/rea/issues/1192)
* **ghidra:** retain process ownership after failed launch rollback ([07675f7](https://github.com/morluto/rea/commit/07675f78c66ce9e8706e808d417265e18ba9f3a5))
* **ghidra:** verify dense jump tables on an optimized fixture ([#1374](https://github.com/morluto/rea/issues/1374)) ([73a664b](https://github.com/morluto/rea/commit/73a664bc78ee618045a2733b8714821281f77403))
* **hopper:** allow restart after verified owned-provider shutdown ([1c12349](https://github.com/morluto/rea/commit/1c123493a21cc579ba7532c40e7ef30df45db3e8))
* **hopper:** probe interior navigation from multi-byte instructions ([#1285](https://github.com/morluto/rea/issues/1285)) ([bf934d5](https://github.com/morluto/rea/commit/bf934d5592e707ba5e7769043de3a430ed8d4923))
* **ida:** compare admitted document paths consistently ([890bb66](https://github.com/morluto/rea/commit/890bb66b35d5f9f8ee54ff0049bf7dc7b82b2480))
* **javascript:** avoid positive-zero evidence for signed zero ([9055bd6](https://github.com/morluto/rea/commit/9055bd695b75f72fb1b8a538d1485d30c0b0ee0b))
* **javascript:** decline source-map UNC references with an unusable host ([#1372](https://github.com/morluto/rea/issues/1372)) ([f504c2a](https://github.com/morluto/rea/commit/f504c2a351027f17ac353fba2d7cfc3505ee17d6))
* **javascript:** distinguish prefix-only builtins from packages ([2b4abbf](https://github.com/morluto/rea/commit/2b4abbf1ccb6dd6ad1248cf48e381df0842542c1))
* **javascript:** honor module-sync package exports ([#1361](https://github.com/morluto/rea/issues/1361)) ([d0e6069](https://github.com/morluto/rea/commit/d0e606930acb701790c286340226b1e3e7060b4f))
* **javascript:** parse declaration artifacts in ambient mode ([4896adc](https://github.com/morluto/rea/commit/4896adcd0f9316034e83129685ed3807ade6f3ea))
* **javascript:** preserve agreeing module provenance ([db171be](https://github.com/morluto/rea/commit/db171be6e570fd1261a30d711e4da2d17de85a93))
* **javascript:** preserve capture-time guards and ordering ([001851f](https://github.com/morluto/rea/commit/001851fde6f972e6ebd01fddccdff4c645a85f63))
* **javascript:** preserve semantic evidence through satisfies ([e995b19](https://github.com/morluto/rea/commit/e995b19f834ba78faa294f5959fd3ad8a97290ca))
* **javascript:** preserve uncertainty after references escape to calls ([#1292](https://github.com/morluto/rea/issues/1292)) ([355a292](https://github.com/morluto/rea/commit/355a292198bf58245c67ae315fdb4f77e62769cc))
* **javascript:** reject invalid package exports configurations ([7a4f268](https://github.com/morluto/rea/commit/7a4f2685d41b134507331c322f0f5da8e1f6c3f4))
* **javascript:** resolve exported callables through lexical bindings ([#1351](https://github.com/morluto/rea/issues/1351)) ([a9f5dad](https://github.com/morluto/rea/commit/a9f5dad5a8f196c88f6305d8d958b355cc0b52c2))
* **javascript:** resolve query-only HTML references to their document ([55a46f7](https://github.com/morluto/rea/commit/55a46f7c7176075c9edda4fe61ed995f2ceadf6a))
* **javascript:** retain array identity after length mutations ([4bcea1a](https://github.com/morluto/rea/commit/4bcea1aa76e3e7ca665197181739c5e27a62c40a))
* **javascript:** retain conditional mutation ordering uncertainty ([b8a8190](https://github.com/morluto/rea/commit/b8a8190b2f30e377eee2d69d1ba31ea454fa70b9))
* **javascript:** retain distinct module provenance path components ([2bd7de6](https://github.com/morluto/rea/commit/2bd7de6f8ca62fc1d48334cfa7fdced461b7b153))
* **javascript:** retain unresolved value frontiers in provenance queries ([3e19875](https://github.com/morluto/rea/commit/3e19875c7fa9c61cff655bbe6046ddc4ab558533))
* **javascript:** store source map URLs once ([ed8fcae](https://github.com/morluto/rea/commit/ed8fcae94b699b62b44162f880faa077a36c455d))
* **json:** preserve runtime limits across JSON file readers ([#1350](https://github.com/morluto/rea/issues/1350)) ([9c4a68b](https://github.com/morluto/rea/commit/9c4a68bc19a0f7d39557e3cc039f5877f6550f63))
* **managed:** bind graph facts to their source Evidence ([cc7b5af](https://github.com/morluto/rea/commit/cc7b5af0777fc68ebba10ec061244729ebf2357d))
* **mcp:** admit composed analysis through result bookkeeping ([e11f4d3](https://github.com/morluto/rea/commit/e11f4d371abaa8cb65ebf7b94fa216329fd78d88))
* **mcp:** advertise object roots for union input schemas ([#1373](https://github.com/morluto/rea/issues/1373)) ([39dabd0](https://github.com/morluto/rea/commit/39dabd0608ed9617d60f16ece05993089f24ff38))
* **mcp:** advertise primitive semantic literal seeds ([f62b449](https://github.com/morluto/rea/commit/f62b44971deee0e99df6fcf32758c8e5592400ed))
* **mcp:** preserve JavaScript workflow identity validation ([#1366](https://github.com/morluto/rea/issues/1366)) ([53ed942](https://github.com/morluto/rea/commit/53ed942a85f51ff9f0e4f01cbb53359df476071d)), closes [#1364](https://github.com/morluto/rea/issues/1364) [#1065](https://github.com/morluto/rea/issues/1065)
* **mcp:** retry failed shutdown resources and retain failure reasons ([e64678e](https://github.com/morluto/rea/commit/e64678e8f9768dd819d8f5f12cc844a6660ff2c5))
* **native:** distinguish symbol definitions from metadata ([70bad53](https://github.com/morluto/rea/commit/70bad53847b0e14489acee73d204ff645e1adfcd))
* **native:** preserve unknown Objective-C metadata ([b112d44](https://github.com/morluto/rea/commit/b112d44a3961939881779c81a57e7a3f9d1372f7))
* **native:** refuse to list architectures of non-Mach-O targets ([#1325](https://github.com/morluto/rea/issues/1325)) ([1b73b5a](https://github.com/morluto/rea/commit/1b73b5ab4bc75bd424e643de8e49f142ffa2b336))
* **native:** retain LLDB cleanup ownership through client close ([7ad353f](https://github.com/morluto/rea/commit/7ad353fa8b3f07e14face80336678d23cc7c6507))
* **process:** keep unobserved file contents unknown ([#1358](https://github.com/morluto/rea/issues/1358)) ([f91f279](https://github.com/morluto/rea/commit/f91f2798b4dc6adb61b3ffe28a24a5d55adbd6ff))
* **process:** retain per-file digest open failures ([415145d](https://github.com/morluto/rea/commit/415145d04f09a15cbfb7dda8ea9dc363a77f9bf0))
* **reference:** report malformed UTF-8 before import parsing ([f166a2a](https://github.com/morluto/rea/commit/f166a2ae15b072216173a51a8f5cad930a858366))
* report malformed application evidence as input errors ([218c131](https://github.com/morluto/rea/commit/218c13160ec0ed7116d6633fc76559ec39dae4d7))
* retain completed observations when later analysis steps fail ([35f121f](https://github.com/morluto/rea/commit/35f121f4acac821e848c485fb82a2c42f51f6ea1))
* **setup:** install the skill for Claude Code ([b4a1919](https://github.com/morluto/rea/commit/b4a19193fe3baf9075f8ac419517021ea0c71ea3))
* **setup:** recognize supported Nobara hosts ([f0dc233](https://github.com/morluto/rea/commit/f0dc233d64de4c215c453c346e516b7622713e95))
* **skill:** pin packaged commands to the shipping package version ([2793672](https://github.com/morluto/rea/commit/2793672ee2a575f97a8011c7fec5288098cdd5d1))
* **skill:** pin packaged commands to the shipping package version ([#1346](https://github.com/morluto/rea/issues/1346)) ([f39e71c](https://github.com/morluto/rea/commit/f39e71ce1897bb5c704b33a8b0049567f11e3a13))
* **snapshot:** preserve complete investigation revision histories ([#1354](https://github.com/morluto/rea/issues/1354)) ([1c0cc8a](https://github.com/morluto/rea/commit/1c0cc8a6753b5ac781b28ebb1832f3a6a1771a68))
* **targets:** cancel resolution before provider admission ([f3c4a33](https://github.com/morluto/rea/commit/f3c4a332f7bd198bd67f0187bc2a85c7b31bb960))
* **update:** preserve disabled client registrations ([abf5e24](https://github.com/morluto/rea/commit/abf5e243c4d2cae03404b6e1fb1ccc77be917b53))
### Performance Improvements
* **javascript:** index version relationships once per comparison ([#1347](https://github.com/morluto/rea/issues/1347)) ([b1e85ad](https://github.com/morluto/rea/commit/b1e85ad711743a594c572dbd5b0d5cb664e2a502))
* **javascript:** validate the version change graph once ([#1370](https://github.com/morluto/rea/issues/1370)) ([037709a](https://github.com/morluto/rea/commit/037709a52c0824f4d2bbee90d8e2642b2d88d364))
* **json:** encode streamed JSON iteratively ([#1322](https://github.com/morluto/rea/issues/1322)) ([56598be](https://github.com/morluto/rea/commit/56598beb4e82968a313deb9efdf4b98db5bd1f4f))
### Code Refactoring
* use canonical implementations and types directly ([765e809](https://github.com/morluto/rea/commit/765e809e366eff21b4b9c224f1a813ad64245ea3))
* **artifacts:** remove unused root classifier ([5291bca](https://github.com/morluto/rea/commit/5291bca108af781214572fac709f9808bb8aa4db))
* **artifacts:** test inventory changes at materialization boundary ([750fb65](https://github.com/morluto/rea/commit/750fb6565052e9eaad40b946b6a284d0730d14f8))
* **browser:** open scenario sessions without a factory wrapper ([d1983a4](https://github.com/morluto/rea/commit/d1983a45767bfcdc020652f48109a78a3f9fa590))
* **catalog:** import CLI metadata from its owner ([8c96baa](https://github.com/morluto/rea/commit/8c96baab80dc258d31ca1632d761fffb11dbaaae))
* consolidate boundary semantics and prune redundant tests ([392f1f3](https://github.com/morluto/rea/commit/392f1f310733f2c365da7bc57a1154cf10ec4ba0))
* **javascript:** normalize erased expression syntax once ([b628bba](https://github.com/morluto/rea/commit/b628bba1fa65fd3b51363bf4b745f0afc57e1dba))
* **javascript:** parse runtime evidence into one verified owner ([006b295](https://github.com/morluto/rea/commit/006b295f1de19fd5351832cf52d98a202a5cd5cd))
* **javascript:** remove obsolete scope truncation statistic ([449d570](https://github.com/morluto/rea/commit/449d57075eec71b2f064af8877c50cbbde30a283))
* **javascript:** share Babel child traversal ([0f10499](https://github.com/morluto/rea/commit/0f10499245ec2fab8823f116caf34450b3a7385b))
* **javascript:** share semantic evidence at fact construction ([e3bbb9a](https://github.com/morluto/rea/commit/e3bbb9ac453da8d15f3b32511180451613710616))
* **process:** remove duplicate observation and trace entry points ([070339a](https://github.com/morluto/rea/commit/070339af50a50a0f23e82db859e761c53277ee79))
* **providers:** use canonical artifact and managed identities ([87f0051](https://github.com/morluto/rea/commit/87f0051496aff1b05ab24d6b63f79884f4ca9b8f))
* **reference:** simplify malformed UTF-8 handling ([377df71](https://github.com/morluto/rea/commit/377df715ea5b2523cd6c1084fdc286eb8a056182))
* remove obsolete source exclusions and identity wrapper ([44c92f8](https://github.com/morluto/rea/commit/44c92f88c51841735741811a68cc89fde14efa80))
* remove single-use forwarding helpers ([4144e45](https://github.com/morluto/rea/commit/4144e454f385c372d29e301e6bb959092c606a6e))
### Documentation
* keep license sections text-only ([e10f1f0](https://github.com/morluto/rea/commit/e10f1f0901fa56fb4443837cf9528b31a12e140e))
* align translated README artwork and layout ([ccfbe87](https://github.com/morluto/rea/commit/ccfbe87e984e456e12c66d0d2fe6d5a559d09518))
* add README artwork and refine closing sections ([4b8e744](https://github.com/morluto/rea/commit/4b8e744d90579e353371649047215c4e4be7a5f6))
* add repository-local REA tool design skill ([7738c1f](https://github.com/morluto/rea/commit/7738c1f6a9ccf1ec9868ef832f154abe9ba5eebd))
* celebrate 40,000 GitHub stars 🎉 ([3edb217](https://github.com/morluto/rea/commit/3edb2172def0e0bd9076f23148f0c41cd2f341a3))
* celebrate 40,000 GitHub stars 🎉 ([5ecc98a](https://github.com/morluto/rea/commit/5ecc98a5eac4c10d33e9c418b9ffae61c68e3ef2))
* consolidate agent guidance around ownership and boundaries ([ba44222](https://github.com/morluto/rea/commit/ba4422296dc409d49836f25642555e00463bfe3b))
* **contracts:** explain canonical URL and skill metadata ownership ([e36afa1](https://github.com/morluto/rea/commit/e36afa112fd7b7ab5a925ca452de93b68f12a6ab))
* correct MCP error and capture import guidance ([077d6c4](https://github.com/morluto/rea/commit/077d6c407b3ea7443a7277ae0e5531b3927dd742))
* correct README setup and runtime guidance ([5b3715e](https://github.com/morluto/rea/commit/5b3715ef825a30150b02d3f1bb7d40dd89453018))
* explain CI scope and native runner reuse ([#1348](https://github.com/morluto/rea/issues/1348)) ([6c9161d](https://github.com/morluto/rea/commit/6c9161d61745e242643f224ce49e7468143a15f3))
* prune repeated contributor and tool design instructions ([5d79387](https://github.com/morluto/rea/commit/5d79387505ebae1ec8d800ee3ffd901920a9d8be))
* remove retired architecture and migration artifacts ([7a0c800](https://github.com/morluto/rea/commit/7a0c80085128e6329ca2e4f54f3539f3245c57d1))
### Tests
* share the client registration command to restore the jscpd gate ([#1317](https://github.com/morluto/rea/pull/1317)) ([5d16be2](https://github.com/morluto/rea/commit/5d16be2a7185db8b70a5fcbc5f5e1be63297f2c8))
* **mcp:** remove arbitrary schema inventory thresholds ([24673aa](https://github.com/morluto/rea/commit/24673aaae497ca4ef0902544c0cd69817f5424ed))
* **android:** allow provider readiness under load ([961c3c3](https://github.com/morluto/rea/commit/961c3c3de79ec44d608d011eb3fa3d6bd645cf6a))
* **artifacts:** verify extraction races with real filesystem changes ([1ac8389](https://github.com/morluto/rea/commit/1ac8389c5c1f75faf8d7f2f3faf2f24febad5fea))
* **browser:** avoid duplicating source-map listener setup ([9367dc1](https://github.com/morluto/rea/commit/9367dc13bd8d2732d36d5376b5de170c9f4af424))
* **browser:** report redirect status cases independently ([5a61562](https://github.com/morluto/rea/commit/5a61562dc200120c7b8020854085c17b8203e95d))
* **cli:** remove duplicate malformed JSON assertion ([5d32e42](https://github.com/morluto/rea/commit/5d32e4252941e93065cadd83b9f02aa6427544d8))
* exercise source test selection through Git and Vitest ([25711ad](https://github.com/morluto/rea/commit/25711ad2590af136dfb301839dddd6d30971ba76))
* **filesystem:** bound FIFO regressions at consumers ([0bfb6e0](https://github.com/morluto/rea/commit/0bfb6e00abae1e67a96e548d64954bb21861f621))
* **ghidra:** allow rollback tests to reach spawned process ([d761d73](https://github.com/morluto/rea/commit/d761d7358b45fe0724b182a206241fd605f338b0))
* **javascript:** share primitive expansion producer fixtures ([c867bcd](https://github.com/morluto/rea/commit/c867bcd0aadd63473865f9a328459e0db3c89565))
* **javascript:** share semantic graph test facts ([ac356c4](https://github.com/morluto/rea/commit/ac356c46ad6a17c8864bc5d350984786db62d2f5))
* **javascript:** verify distinct module origins through reconstruction ([96b2b24](https://github.com/morluto/rea/commit/96b2b245fdefc9c78f5dcf6ce054232b51f7c117))
* **json:** remove assertions covered by CLI output consumers ([a959a83](https://github.com/morluto/rea/commit/a959a8309db79fbee6477efd7ee541615e625627))
* **managed:** include shared dossier fixture in artifact inputs ([66a20a2](https://github.com/morluto/rea/commit/66a20a2597b5daebc0a292361aa62a78b7df6e7d))
* **native:** retain trace diagnostics when observed hits differ ([048b798](https://github.com/morluto/rea/commit/048b79878c70c594789909082499dc675472b63a))
* **package:** share validated native dossier fixtures ([ca90109](https://github.com/morluto/rea/commit/ca9010936a934a49fbc6cf69eb1d7fc2242b6da9))
* **process:** publish capture readiness atomically ([74be526](https://github.com/morluto/rea/commit/74be52611e66f680ef1919d521fc3c304bc2326e))
* **process:** report cleanup details on cancellation failures ([79d5b9a](https://github.com/morluto/rea/commit/79d5b9a826b9204c1ef59b0a5c5ec83e7a2f2bec))
* **process:** use owned CLI and workspace fixtures ([4940a86](https://github.com/morluto/rea/commit/4940a867e2e56cbb974bfa321008a8f35db47d52))
* share snapshot replay and managed graph fixtures ([d83cbd2](https://github.com/morluto/rea/commit/d83cbd2abf1bbf15beef990f5353457fdbaaeb8e))
### Continuous Integration
* enforce architecture guards with portable checkout paths ([ecc67ca](https://github.com/morluto/rea/commit/ecc67cab2d85cacda245890ffe84b80ac395d79e))
## [6.2.0](https://github.com/morluto/rea/compare/rea-agents-6.1.0...rea-agents-6.2.0) (2026-10-09)
### ⚠ BREAKING CHANGES
Read the [6.1 to 6.2 migration guide](docs/migration-6.2.md) before upgrading. REA's `always-bump-minor` policy includes breaking changes; 6.2 is not a backward-compatibility promise. Preserve original saved files and regenerate missing observations rather than fabricating identities or facts.
* **MCP / Evidence / snapshots / artifacts:** Success results are direct canonical Evidence; read `normalized_result` rather than the old `result`/`evidence` wrapper. Evidence requires nullable `analysis_profile`, session provider aliases are removed, snapshots require complete profile-bound query records, and artifact roles/permissions belong to occurrences. Recreate incompatible saved data; adding fields without recomputing their semantic identity is invalid. ([63bf914](https://github.com/morluto/rea/commit/63bf91405cf97b114a84f337fb1272d98a267999))
* **Process captures:** Legacy v3 conversion is removed. Explicit executable identity and `event_journal` are required; retain old captures and recapture when current comparisons are needed instead of inventing launch identity or event order. ([2a77469](https://github.com/morluto/rea/commit/2a7746998d47446c4db6d4f524e0f183d6803f3f))
* **Cleanup and evaluation:** A one-shot analysis reports cleanup failure while preserving the completed observation or primary diagnostic. Handle `cleanup_incomplete` and retained observations/resources. Configured agent-evaluation fixtures require Evidence-backed correctness, not routing or answer wording alone. ([#1211](https://github.com/morluto/rea/pull/1211), [27a9cea](https://github.com/morluto/rea/commit/27a9ceade7232c1c9a24dc7d454ae060948183a1))
* **JavaScript:** Return-field projections require explicit presence; export-shape changes carry both sides' presence and property inventory coverage. Semantic object operations retain complete `property_path` segments. Regenerate old analysis and distinguish unknown values from unknown presence. ([475a0f8](https://github.com/morluto/rea/commit/475a0f84dac63d710e032bc7f731c1a3bda624ec))
* **Function comparisons:** Remove the unreachable `truncated` dimension state and `summary.truncated` counter; update enum and display consumers while retaining explicit `unknown` facts. ([5510b27](https://github.com/morluto/rea/commit/5510b27d7f863a3df26212fba4a59f8df0da3712))
* **Historical sources:** Unreadable/unknown symlink targets require `target: null`; external targets retain the observed absolute target. Reimport graphs containing display placeholders such as `<outside-root>` and handle nullable targets. ([b7b4333](https://github.com/morluto/rea/commit/b7b433370310c3ffe33d5027d8393151d5e862da))
### Features
* **javascript:** report observed export property presence ([#1160](https://github.com/morluto/rea/issues/1160)) ([45e3edc](https://github.com/morluto/rea/commit/45e3edc17f48954c89d8db86f7313c479bd39344))
* **mcp:** select views of retained analysis results ([#1180](https://github.com/morluto/rea/issues/1180)) ([db675f1](https://github.com/morluto/rea/commit/db675f1d52acda62b6f57b5a8773532f49b259e7))
* **website:** add an Aegis APK code-generation showcase ([0270dd5](https://github.com/morluto/rea/commit/0270dd5739480acced62e045b5890ec0ebde2631))
* **website:** add an Android showcase and clearer project prompts ([6cc817e](https://github.com/morluto/rea/commit/6cc817e8bd377b064b3568ef1eacb27eaefcb4c1))
* **website:** add beginner examples and synchronized publishing ([0fec65d](https://github.com/morluto/rea/commit/0fec65d06b2f5431e704c472e53015d4b3cc967c))
* **website:** add beginner examples and synchronized publishing ([#1203](https://github.com/morluto/rea/issues/1203)) ([0fec65d](https://github.com/morluto/rea/commit/0fec65d06b2f5431e704c472e53015d4b3cc967c))
* **website:** add Discord link beside GitHub badge ([cc39fc5](https://github.com/morluto/rea/commit/cc39fc53b829a349ae199823472990a53014c507))
* **website:** add homepage navigation and faster reading paths ([863674b](https://github.com/morluto/rea/commit/863674b2e92dd7c699768db82d521ccc88b7ebe4))
* **website:** add homepage navigation and faster reading paths ([c94f06d](https://github.com/morluto/rea/commit/c94f06d98f895eb8b6c5ffa5e999ef1d4bb5eea2))
* **website:** add homepage navigation and faster reading paths ([#1213](https://github.com/morluto/rea/issues/1213)) ([863674b](https://github.com/morluto/rea/commit/863674b2e92dd7c699768db82d521ccc88b7ebe4))
* **website:** add search metadata and automatic sitemap ([99f257b](https://github.com/morluto/rea/commit/99f257bbf03c27327e5e0a232fefd3c792acd5bc))
* **website:** add search metadata and automatic sitemap ([b8851cb](https://github.com/morluto/rea/commit/b8851cb977cfdd608798d32bf5877f645b960831)), closes [#1283](https://github.com/morluto/rea/issues/1283)
* **website:** clarify reverse engineering and showcase goals ([e750c26](https://github.com/morluto/rea/commit/e750c262fbf37100369ab25bf8659daa1a2c4cc7))
* **website:** explain REA through a first investigation ([5160d9b](https://github.com/morluto/rea/commit/5160d9b717d0207a357c754bdf72e215e59d19d1))
* **website:** explain REA with Calculator and a playable dinosaur lab ([11b9f03](https://github.com/morluto/rea/commit/11b9f0346cf5413045b41ff552a024e11ba46ccc))
* **website:** lead with the playable dinosaur example ([19c52f5](https://github.com/morluto/rea/commit/19c52f5e3f42fb754fc154bbd16552c5111df0c5))
* **website:** show manual analysis beside a one-prompt workflow ([291bc6f](https://github.com/morluto/rea/commit/291bc6fb70f47d28d23440f03a8a7fa49eb9a391))
### Bug Fixes
* **dev:** accept formatter-ignored staged documentation without failing the commit hook; malformed JSON remains rejected. ([bd2db2f](https://github.com/morluto/rea/commit/bd2db2f0fa495fb08dea443cd16d7683d4b86e6a))
* **release:** publish reviewed release-PR merges from their exact reviewed source. ([c12bad7](https://github.com/morluto/rea/commit/c12bad7f139431fc0db7a8b7c9db1eab95f96dc2))
* **android:** support owned JADX stdio on Windows ([#1276](https://github.com/morluto/rea/issues/1276)) ([636b245](https://github.com/morluto/rea/commit/636b245f1badf2a7ecfa63c6e2378ac2f7673cc3)), closes [#1262](https://github.com/morluto/rea/issues/1262)
* **android:** validate engine archive prerequisites ([#1145](https://github.com/morluto/rea/issues/1145)) ([e9ebfb9](https://github.com/morluto/rea/commit/e9ebfb94eff0699b1ea84bba000c4467fa1cb998))
* **apple:** report unusable dylib-resolution roots as invalid input ([6a1e558](https://github.com/morluto/rea/commit/6a1e558db3ec2b69561e91ea817f1c2065dfc676))
* **apple:** report unusable dylib-resolution roots as invalid input ([24a30fd](https://github.com/morluto/rea/commit/24a30fd91c144b7f2533e5f5de8c91268773519c))
* **artifacts:** keep cancellation and the caller path in extraction refusals ([37025cc](https://github.com/morluto/rea/commit/37025cc09f12d49f46e61eedc3564c710089146b))
* **artifacts:** keep cancellation and the caller path in extraction refusals ([eacf846](https://github.com/morluto/rea/commit/eacf8461dad6bab11a3d5438e6db001a10f33a9b))
* **artifacts:** match lipo arm64e variant names to their FAT slices ([de5bfec](https://github.com/morluto/rea/commit/de5bfec79fe862816350b2deeb42a12c0734d855))
* **artifacts:** match lipo arm64e variant names to their FAT slices ([0b32577](https://github.com/morluto/rea/commit/0b32577a90aef97e36adf2a7af4f3eccd5d82357)), closes [#1168](https://github.com/morluto/rea/issues/1168)
* **artifacts:** name only host-available workflows for non-archive plists ([f4c99ab](https://github.com/morluto/rea/commit/f4c99ab8a53806dd57dc24b3d5a600905bcb4686))
* **artifacts:** name only host-available workflows for non-archive plists ([2295855](https://github.com/morluto/rea/commit/22958558eafdfccf71a7d5bbbcf360574a6b2e3c))
* **artifacts:** recheck failed DMG detaches before reporting cleanup failure ([#1155](https://github.com/morluto/rea/issues/1155)) ([58a91f0](https://github.com/morluto/rea/commit/58a91f03d72162849991caf537ab058ccc918594))
* **artifacts:** refuse unsupported extraction formats before scanning ([8e74c9c](https://github.com/morluto/rea/commit/8e74c9c62fb44556b90f20bb6c12771ac05a18f2))
* **artifacts:** report encrypted archive entries as unsupported extraction ([de43da7](https://github.com/morluto/rea/commit/de43da71ae982dd0f3d7b5ae49c914729db3a6ec))
* **artifacts:** report non-archive keyed-archive selections as unsupported targets ([fef38e4](https://github.com/morluto/rea/commit/fef38e4d22ee859ec43fb591d53e8b9973c69958))
* **artifacts:** report non-archive keyed-archive selections as unsupported targets ([8c5088c](https://github.com/morluto/rea/commit/8c5088c8cdf32a9f96f6c479c6e70a71fa360168))
* **artifacts:** report wrong target kinds as unsupported targets ([b34bdcd](https://github.com/morluto/rea/commit/b34bdcdb2877be394c59c9cbf70269dc1841ff78))
* **artifacts:** report wrong target kinds as unsupported targets ([637bcb5](https://github.com/morluto/rea/commit/637bcb5e4182b6c60e922b18688642d8e1008e90))
* **browser:** classify export-web-scripts capture selection failures by cause ([ddaa183](https://github.com/morluto/rea/commit/ddaa18301ab9c67e7a6f7ce66076075e8a4d5017))
* **browser:** classify export-web-scripts capture selection failures by cause ([8c5e34c](https://github.com/morluto/rea/commit/8c5e34cd379392ca40f651ca5eeb6a947b44aa33))
* **browser:** report Windows HAR heap exhaustion ([#1147](https://github.com/morluto/rea/issues/1147)) ([1393507](https://github.com/morluto/rea/commit/13935077ba039f6e342f9c11ab5eea935a335ae6))
* **browser:** retain scenario observations across failures ([614e0c2](https://github.com/morluto/rea/commit/614e0c2e74819bb5e3ef3d2e16ff31ee6cab76ae))
* **browser:** retain scenario resources until cleanup succeeds ([88640f6](https://github.com/morluto/rea/commit/88640f60fe566edbe2320688df62c7ef46c4c61c))
* **ci:** pass selected environment to Windows Ghidra fixture ([#1281](https://github.com/morluto/rea/issues/1281)) ([f085589](https://github.com/morluto/rea/commit/f085589957922eaf421db814399e88e415712050))
* **cli:** advertise defaulted inputs as optional in --schema and help ([#1175](https://github.com/morluto/rea/issues/1175)) ([b4927a0](https://github.com/morluto/rea/commit/b4927a0a4fa7e8935b101d214b396bfa78208281)), closes [#1169](https://github.com/morluto/rea/issues/1169)
* **cli:** cancel routed JavaScript analysis in rea analyze ([#1156](https://github.com/morluto/rea/issues/1156)) ([089bbf5](https://github.com/morluto/rea/commit/089bbf58f3561e3f465c544bbcf8c307287b1256))
* **cli:** complete cleanup after relayed interrupts ([#1202](https://github.com/morluto/rea/issues/1202)) ([911152a](https://github.com/morluto/rea/commit/911152a04d3aeb0d361141a8d54959009b269e49))
* **cli:** list the read failure cause for an unreadable JSON input file ([db0afce](https://github.com/morluto/rea/commit/db0afce5f344268271c59acee04e96f986c5619a))
* **cli:** list the read failure cause for an unreadable JSON input file ([6020df5](https://github.com/morluto/rea/commit/6020df53d9cd44845cf3b6b416db2d7802925578))
* **cli:** resolve xrefs symbol selectors after address validation ([#1209](https://github.com/morluto/rea/issues/1209)) ([7e9c911](https://github.com/morluto/rea/commit/7e9c91199ecd133d26a51cb33b6e63e1f942df7e))
* **config:** name the rejected setting and its constraint in configuration errors ([c3acc34](https://github.com/morluto/rea/commit/c3acc34475ca22387ea674839acfa1891b0b9f66))
* **config:** name the rejected setting and its constraint in configuration errors ([0a0244d](https://github.com/morluto/rea/commit/0a0244db4212bc1f59dec4b925fa90b3b473136a)), closes [#1184](https://github.com/morluto/rea/issues/1184)
* **doctor:** find the Homebrew Hopper cask without writing Homebrew caches ([98b07d0](https://github.com/morluto/rea/commit/98b07d07ddd20bea2c3bdf8d55ac2776a263bcf4))
* **doctor:** find the Homebrew Hopper cask without writing Homebrew caches ([a503376](https://github.com/morluto/rea/commit/a503376b2f9d9ba14d1602e58e0e93059e9d9181)), closes [#1165](https://github.com/morluto/rea/issues/1165)
* **domain:** report target read-permission denials as access_denied ([f36c10f](https://github.com/morluto/rea/commit/f36c10f9e8dc45a298d668e608f8e945bde487cf))
* **domain:** report target read-permission denials as access_denied ([d0ff57a](https://github.com/morluto/rea/commit/d0ff57a45c8da8938e7ae16d00bfd5ec63310af3)), closes [#1188](https://github.com/morluto/rea/issues/1188)
* **electron:** resolve effective preload after option overrides ([#1286](https://github.com/morluto/rea/issues/1286)) ([411498d](https://github.com/morluto/rea/commit/411498d45f860eba2fbc9d7051af20237b7a4cb1))
* emit v-mode-compatible patterns for tool schemas ([#1220](https://github.com/morluto/rea/issues/1220)) ([f0da05f](https://github.com/morluto/rea/commit/f0da05f67fff1411cf2f7a48a752ee7b348c71ff))
* **errors:** report caller-selected evidence path failures as invalid input ([d4a598e](https://github.com/morluto/rea/commit/d4a598e93649607dd293a9c81bbf79c211bc8dd4))
* **errors:** report caller-selected evidence path failures as invalid input ([db177c9](https://github.com/morluto/rea/commit/db177c91b83adb0c3edc4f9f6f06e31ac7523d53))
* **evidence:** cancel exports before atomic publication ([16624f1](https://github.com/morluto/rea/commit/16624f1324e156d14025b2c346596c9781c07488))
* **ghidra:** classify modern Swift manglings in swift type analysis ([#1208](https://github.com/morluto/rea/issues/1208)) ([6935dc7](https://github.com/morluto/rea/commit/6935dc7fe1258b340bb9cdfb8cecae66ef7bc0d4))
* **ghidra:** do not run Java from a relative JAVA_HOME in doctor and setup ([04a516b](https://github.com/morluto/rea/commit/04a516b1e369f7e57e08d0653cc08292ac497e07))
* **ghidra:** do not run Java from a relative JAVA_HOME in doctor and setup ([c3f1698](https://github.com/morluto/rea/commit/c3f169823f690371ecfdd2d1b3b07a5749438cf1))
* **ghidra:** keep and name a runtime directory that close could not remove ([5b769d3](https://github.com/morluto/rea/commit/5b769d3a781c645ed8885e4fabf01a00f0bbc89b))
* **ghidra:** keep and name a runtime directory that close could not remove ([b79d379](https://github.com/morluto/rea/commit/b79d379c25bcc8ed61571c41a94b912b5704a067)), closes [#1190](https://github.com/morluto/rea/issues/1190)
* **ghidra:** keep the NativeAOT target refusal's own recovery advice ([f198993](https://github.com/morluto/rea/commit/f198993f418e6aaa9755e7e6413abcb27c6cd684))
* **ghidra:** preserve decoded return flow evidence ([b189c3c](https://github.com/morluto/rea/commit/b189c3ceb175dd9fa089eada9e9ca54e76307cb3))
* **ghidra:** preserve decoded return flow evidence ([bcc8a77](https://github.com/morluto/rea/commit/bcc8a773e2a714e4899755b786a4fef1539bbace))
* **ghidra:** reject relative installation and Java paths in doctor and setup ([8998438](https://github.com/morluto/rea/commit/8998438c23aa19e68f4ffa7574c5d341aa419165))
* **ghidra:** reject relative installation and Java paths in doctor and setup ([5356856](https://github.com/morluto/rea/commit/53568568bf32b36274ba3a532f1e2cfb2daed271)), closes [#1183](https://github.com/morluto/rea/issues/1183)
* **ghidra:** report NativeAOT host and target refusals as unsupported, not failures ([cfb49eb](https://github.com/morluto/rea/commit/cfb49eb8a88fc51f460907024c51e05a2f272502))
* **ghidra:** report NativeAOT host and target refusals as unsupported, not failures ([42c276a](https://github.com/morluto/rea/commit/42c276af1ec02473a7b6700a31292aae9e53d53e)), closes [#1185](https://github.com/morluto/rea/issues/1185)
* **ghidra:** resolve secondary symbols at function entries ([#1195](https://github.com/morluto/rea/issues/1195)) ([6fbdbd6](https://github.com/morluto/rea/commit/6fbdbd682038d012b04f0fe92c470cf1789fb101))
* **ghidra:** stop dereferencing the removed error payload in address verification ([b80bd2d](https://github.com/morluto/rea/commit/b80bd2db966731fd3cfddfff7e92704053dbe955))
* **ghidra:** stop dereferencing the removed error payload in address verification ([59fbaa2](https://github.com/morluto/rea/commit/59fbaa2d33359216534407f99f49705ac04a3426))
* **ghidra:** use dot-free private session paths ([c3fc6c3](https://github.com/morluto/rea/commit/c3fc6c3aedc202e8ade015c4039a63e9f91cac6d))
* **hopper:** keep the OS error when the FAT64 source cannot be reopened ([9f5dc52](https://github.com/morluto/rea/commit/9f5dc52be8420fb5e874595d63312bf80d07a3a2))
* **hopper:** reserve Linux demo application before launch ([#1158](https://github.com/morluto/rea/issues/1158)) ([33d5ae0](https://github.com/morluto/rea/commit/33d5ae0b52b8684634ecf14d4e9469968c69d462))
* **javascript:** allow cancellation during semantic graph commitment ([#1218](https://github.com/morluto/rea/issues/1218)) ([9405bd6](https://github.com/morluto/rea/commit/9405bd660def9946afaa5fcc1d99921a816911bf))
* **javascript:** classify application input selection failures by cause ([fe5291e](https://github.com/morluto/rea/commit/fe5291e9166977a6ebbfa6ffcf7850af57192b34))
* **javascript:** classify application input selection failures by cause ([0a14bbb](https://github.com/morluto/rea/commit/0a14bbbf05e0e61c98e06326fe7136e52fa4fb3c))
* **javascript:** keep Wakaru version stderr out of the refusal message ([6489d58](https://github.com/morluto/rea/commit/6489d58851d055fd7ce621000d960bb42a0e4ce0))
* **javascript:** match source-map originals that name parent directories ([#1215](https://github.com/morluto/rea/issues/1215)) ([889fb37](https://github.com/morluto/rea/commit/889fb374df0f8986f49e9d61b0fefd536327f781))
* **javascript:** omit self-referential static references with disclosure ([#1157](https://github.com/morluto/rea/issues/1157)) ([b620e2a](https://github.com/morluto/rea/commit/b620e2a2bdcf3683b494d137bc409813735d5572))
* **javascript:** preserve alias and container uncertainty ([73e98b2](https://github.com/morluto/rea/commit/73e98b2516dd792ea7b510aeed6b71f384bea21d))
* **javascript:** preserve graphs with async chunk self-references ([#1152](https://github.com/morluto/rea/issues/1152)) ([7220166](https://github.com/morluto/rea/commit/72201668ed88c2cc822a07c08cf35a1e5ba88f35))
* **javascript:** preserve property paths and uncertain slot presence ([475a0f8](https://github.com/morluto/rea/commit/475a0f84dac63d710e032bc7f731c1a3bda624ec))
* **javascript:** reject encoded separators joined by HTML URL whitespace ([2ddd945](https://github.com/morluto/rea/commit/2ddd9456cd405f081784a4b3cb02cb77cd90fbd6))
* **javascript:** reject encoded separators joined by HTML URL whitespace ([fb57c86](https://github.com/morluto/rea/commit/fb57c8643fb8b4733cbac9090ef58fd13a3b5347))
* **javascript:** report located sources with differing digests as modified ([#1216](https://github.com/morluto/rea/issues/1216)) ([01174c4](https://github.com/morluto/rea/commit/01174c4a81fea109ae712ea1a746a83996f928ac))
* **javascript:** resolve HTML script URLs after URL whitespace and percent decoding ([d601b80](https://github.com/morluto/rea/commit/d601b8016eaeb2955cea4e4c0aca10d17e7d12a7))
* **javascript:** resolve HTML script URLs after URL whitespace and percent decoding ([502528c](https://github.com/morluto/rea/commit/502528c58df54c7b34eefdb5837f36e58f473405)), closes [#1236](https://github.com/morluto/rea/issues/1236)
* **javascript:** resolve package exports targets only to the exact file ([#1181](https://github.com/morluto/rea/issues/1181)) ([2a620c0](https://github.com/morluto/rea/commit/2a620c06cdcaa32844c4a80aeb3df1793f1ce09e)), closes [#1174](https://github.com/morluto/rea/issues/1174)
* keep the Ghidra session root free of dot-prefixed path elements ([a8b8288](https://github.com/morluto/rea/commit/a8b8288396cf2e053db768ef03f4db756aa8f71e))
* **managed:** preserve literal library names during native matching ([81b70bc](https://github.com/morluto/rea/commit/81b70bc358031686c9d7afd049f21719c67a9525))
* **managed:** separate metadata and signature completeness ([2f02eff](https://github.com/morluto/rea/commit/2f02eff9887fc715c33f5d8770a6e6191ba70ca9))
* **mcp:** advertise input patterns without look-around ([1f099a6](https://github.com/morluto/rea/commit/1f099a6fc00b08fb0283dcabc5a238025d4c4c8b))
* **mcp:** advertise input patterns without look-around ([a8701ea](https://github.com/morluto/rea/commit/a8701eaf489692449739d5b2490502b1a14951c5)), closes [#1282](https://github.com/morluto/rea/issues/1282)
* **mcp:** deliver tool errors within advertised schema contracts ([da606ff](https://github.com/morluto/rea/commit/da606ff77718d9a3b10426fcf68c098138e6dcfa)), closes [#1261](https://github.com/morluto/rea/issues/1261)
* **mcp:** deliver typed errors without invalid structured output ([#1277](https://github.com/morluto/rea/issues/1277)) ([7e96f25](https://github.com/morluto/rea/commit/7e96f25f8b1380a13a086a68f8d5a70380468151))
* **mcp:** emit portable Unicode NUL patterns ([#1230](https://github.com/morluto/rea/issues/1230)) ([aa5750c](https://github.com/morluto/rea/commit/aa5750c263632d98d626c5ca3b985bb1519d2395))
* **mcp:** measure tool errors against their text-only delivery ([fe34ec2](https://github.com/morluto/rea/commit/fe34ec2ef3e2968eeb06f64a1a0fdb8b825f56c4))
* **mcp:** measure tool errors against their text-only delivery ([7b51121](https://github.com/morluto/rea/commit/7b51121f7cee21a5938f10ac3b5762e0bb41a58d))
* **mcp:** only recommend exporting retained evidence ([5f749c2](https://github.com/morluto/rea/commit/5f749c2096af2617d4b6b387ff19c13001af8e54))
* name host and tool requirements in optional adapter refusals ([68cb02f](https://github.com/morluto/rea/commit/68cb02fe8b123b9a0778c0065c13a15bcf0e577d))
* name host and tool requirements in optional adapter refusals ([170d0bf](https://github.com/morluto/rea/commit/170d0bf9e2d45b2512ad556c02f31bdc81ea03ca))
* **native:** distinguish batch selectors from resolved entries ([13c3b68](https://github.com/morluto/rea/commit/13c3b68730df80330fd867d921dea38770d5f880))
* **native:** distinguish batch selectors from resolved entries ([bfaa5a6](https://github.com/morluto/rea/commit/bfaa5a6c2c0ddc9e6fcf16cd11ad06f24db174a2))
* **native:** name the CLI flag that selects another plist ([9b69503](https://github.com/morluto/rea/commit/9b6950373cfaa1a2c0d28287bfadd4a421afb9e9))
* **native:** name the plist selection that works when Info.plist is missing ([5612496](https://github.com/morluto/rea/commit/5612496f6d34a462dcd0fb69fa38337592e2f72d))
* **native:** name the plist selection that works when Info.plist is missing ([a6fdf42](https://github.com/morluto/rea/commit/a6fdf426bd98c8cf7b7a7f589208d3193784062f))
* **native:** refuse truncated executable headers at target admission ([d39a450](https://github.com/morluto/rea/commit/d39a450bdfac425962c3a6a6f47b45600057a230))
* **native:** refuse truncated executable headers at target admission ([0b04d38](https://github.com/morluto/rea/commit/0b04d384cca4f22f271d60bcfe67f79cab89c8de)), closes [#1189](https://github.com/morluto/rea/issues/1189)
* **process:** apply one timeout rule to both execFileOutput modes ([3d32819](https://github.com/morluto/rea/commit/3d328193d69a63a355644c51bfb70f524d99bca9))
* **process:** await cleanup on CLI and MCP cancellation ([f6fe575](https://github.com/morluto/rea/commit/f6fe575094658e99ced78d45f385633fbfaaae32))
* **process:** keep ports before a chunk-final period ([184ed97](https://github.com/morluto/rea/commit/184ed970b9021552a5454ced20d202d10cabcbb8))
* **process:** localize capture truncation diagnostics ([#1284](https://github.com/morluto/rea/issues/1284)) ([33bf585](https://github.com/morluto/rea/commit/33bf585185ffcaea63d658e2d3145c900a680485))
* **process:** normalize ports that end a sentence ([098d769](https://github.com/morluto/rea/commit/098d76900effdbc682b0f97bcde7f8711380ecea))
* **process:** normalize ports that end a sentence ([db98a51](https://github.com/morluto/rea/commit/db98a51dd1750b09b3905e18efac526f7ebf90f7))
* **process:** preserve numeric output and original PTY evidence ([c5c75c3](https://github.com/morluto/rea/commit/c5c75c38c3a4ff0153513b8f8ad600d8a5bacc09))
* **process:** preserve numeric output and original PTY evidence ([00d8e44](https://github.com/morluto/rea/commit/00d8e44cbf82caa51709c2e0857fbaa69ea329b7))
* **process:** preserve unknown filesystem absence in partial captures ([c8544b1](https://github.com/morluto/rea/commit/c8544b1574a32838da6d4ed40f2b72582edb60dd))
* **process:** refuse malformed timeouts for stoppable commands ([136d4aa](https://github.com/morluto/rea/commit/136d4aab18d822f0f908096b8acfac556ef1873b))
* **process:** refuse malformed timeouts for stoppable commands ([59c91c8](https://github.com/morluto/rea/commit/59c91c88fe88210b4b22b9f1365a16567513da4a))
* **process:** require current captures and preserve cleanup failures ([2a77469](https://github.com/morluto/rea/commit/2a7746998d47446c4db6d4f524e0f183d6803f3f))
* **process:** retain known events from incomplete captures ([5eb0049](https://github.com/morluto/rea/commit/5eb0049a9f502b404f30e48c3fe3430a942bb0b5))
* **process:** stop cancelled Swift helper builds before removing their files ([cf41561](https://github.com/morluto/rea/commit/cf415619cadcfcb18cda59a54b26c9d164f750a4))
* **process:** stop cancelled Swift helper builds before removing their files ([c717204](https://github.com/morluto/rea/commit/c7172047951e7dbb9df58b57ff1b43ac9bd47909)), closes [#1173](https://github.com/morluto/rea/issues/1173)
* **process:** stop timed-out commands with the caller's stop signal ([4b38d18](https://github.com/morluto/rea/commit/4b38d1899566089d19b9fd137202f7d86b62fc6f))
* **process:** stop timed-out commands with the caller's stop signal ([063de50](https://github.com/morluto/rea/commit/063de5014f19e85c38b6bec5984de4f38e71adaa))
* **process:** treat non-ASCII letters as port continuations ([ad813e4](https://github.com/morluto/rea/commit/ad813e473b094ab0d3ab30798b7d252e2f4beb94))
* **process:** validate terminal byte totals against retained frames ([69833fb](https://github.com/morluto/rea/commit/69833fb0d0fe9b320b5745a992822342f2c54a92))
* **process:** validate terminal byte totals against retained frames ([39eb058](https://github.com/morluto/rea/commit/39eb0587c95ad028bb961c539ad1f326a1e8d81c))
* **providers:** preserve observations and primary cleanup failures ([0696bde](https://github.com/morluto/rea/commit/0696bde2660bb5d6538d8c01da15aa023312aa9f))
* **reference:** represent unreadable symlink targets explicitly ([b7b4333](https://github.com/morluto/rea/commit/b7b433370310c3ffe33d5027d8393151d5e862da))
* restore caching, preserve failures, and verify fixture claims ([#1211](https://github.com/morluto/rea/issues/1211)) ([27a9cea](https://github.com/morluto/rea/commit/27a9ceade7232c1c9a24dc7d454ae060948183a1))
* **server:** report 2025-era client identity and features in binary_session ([e6abaef](https://github.com/morluto/rea/commit/e6abaefbbc2bd81a6be34cbe71b87be801158c16))
* **server:** report 2025-era client identity and features in binary_session ([b8312fa](https://github.com/morluto/rea/commit/b8312fa8d184ba9f422d1f5592fb41e49811544a)), closes [#1167](https://github.com/morluto/rea/issues/1167)
* **session:** require an open target for session-bound native and artifact tools ([d8e314c](https://github.com/morluto/rea/commit/d8e314cb24e7a4a494347e45474234e0aad74ad1))
* **session:** require an open target for session-bound native and artifact tools ([cf77d07](https://github.com/morluto/rea/commit/cf77d073fc06ab95ce4181c30d68b1346e990b64)), closes [#1166](https://github.com/morluto/rea/issues/1166)
* **session:** retain failed provider cleanup for lifecycle retries ([#1260](https://github.com/morluto/rea/issues/1260)) ([24a3aa0](https://github.com/morluto/rea/commit/24a3aa08d1f69e25b441f086300ba3082d860a35))
* **setup:** keep Codex TOML comments when adding or removing REA ([f5539cf](https://github.com/morluto/rea/commit/f5539cfc2f6c0daf6c275fc97f3351e2cf89b2c3))
* **setup:** keep Codex TOML comments when adding or removing REA ([e9c48a6](https://github.com/morluto/rea/commit/e9c48a61e4c2c05c5b77ef4a815c5b2a65a9337e)), closes [#1163](https://github.com/morluto/rea/issues/1163)
* **setup:** preserve initial backups and Codex comments ([#1204](https://github.com/morluto/rea/issues/1204)) ([6051cb2](https://github.com/morluto/rea/commit/6051cb2c0c723d88dc43ee5ef8a96971bf84d49e))
* **setup:** stop remaining uninstall removals after a client fails ([fd975c7](https://github.com/morluto/rea/commit/fd975c75fa353840e6e887232ca68496cf8705ea))
* **setup:** stop uninstall before removals when a client config is unsafe ([4fb2f3e](https://github.com/morluto/rea/commit/4fb2f3e6ed0233505eada3cddeeff0ea0bfc6fe5))
* **setup:** stop uninstall before removals when a client config is unsafe ([5cc841d](https://github.com/morluto/rea/commit/5cc841d5c154f692bdc257e106cc4b212dc19dc0)), closes [#1164](https://github.com/morluto/rea/issues/1164)
* **snapshot:** report query workflow and Evidence counts separately ([04aef6d](https://github.com/morluto/rea/commit/04aef6df331634238cfc61f320ba4a4e720750a4))
* **snapshot:** report query workflow and Evidence counts separately ([0e77953](https://github.com/morluto/rea/commit/0e779533a9108a550b4d10dcb3920f91c7d48989))
* **website:** clarify Android host and JDK requirements ([5691606](https://github.com/morluto/rea/commit/5691606aa948bddc641e3ecbccf5375a12b65924))
* **website:** identify publication verifier requests ([e6905c1](https://github.com/morluto/rea/commit/e6905c18e09c41e04525fb1a84575483df789204))
* **windows:** retain runtime authority after cleanup failure ([af7a439](https://github.com/morluto/rea/commit/af7a43963351c655eb86197bf52ae798a04e9c22))
* **windows:** retain unsettled jobs for cleanup retry ([76b214e](https://github.com/morluto/rea/commit/76b214e45fa05fe723e216894327185b9b4e6f53))
### Performance Improvements
* **mcp:** share repeated output schema definitions. ([441813c](https://github.com/morluto/rea/commit/441813c0708dbee82ef554c91e973ae02964bf2e))
* **hopper:** resolve string search records once per query ([#1229](https://github.com/morluto/rea/issues/1229)) ([9426c3f](https://github.com/morluto/rea/commit/9426c3f1bbb94711d8b33097e604b9b8ed853b5e))
* **mcp:** reuse input schemas without losing caller guidance ([#1162](https://github.com/morluto/rea/issues/1162)) ([e1afbc1](https://github.com/morluto/rea/commit/e1afbc1914cc7ff90265313e942f34ea4a58a4fc))
* **snapshot:** avoid redundant result copies and serialization ([552634d](https://github.com/morluto/rea/commit/552634d634655a722b2204cfbc4b29f6d442c294))
* **snapshot:** avoid redundant result copies and serialization ([569d2bc](https://github.com/morluto/rea/commit/569d2bc6b9f600114267a4c69f8400393ea1bc2f))
### Code Refactoring
* **domain:** remove obsolete comparison representations ([5510b27](https://github.com/morluto/rea/commit/5510b27d7f863a3df26212fba4a59f8df0da3712))
* enforce canonical evidence and provider boundaries ([63bf914](https://github.com/morluto/rea/commit/63bf91405cf97b114a84f337fb1272d98a267999))
* remove forwarding exports and redundant aliases ([ad59531](https://github.com/morluto/rea/commit/ad59531a960a0c51ef6857fa1391270dda0fa7a4))
* **schemas:** share portable identifier and base64 patterns ([#1227](https://github.com/morluto/rea/issues/1227)) ([954badb](https://github.com/morluto/rea/commit/954badbaaadd24a210190ce3015e40c23d327567))
### Documentation
* add French README translation ([84094af](https://github.com/morluto/rea/commit/84094af54a4e0a6247445e59abff27bc4eca361b))
* add French README translation ([9664b2b](https://github.com/morluto/rea/commit/9664b2b101fe4ac334b2911f9210b50d58d90a89))
* celebrate 30,000 GitHub stars 🎉 ([6987cb0](https://github.com/morluto/rea/commit/6987cb066a5aa5e51480bb06a93a758e6f67cd1e))
* celebrate 30,000 GitHub stars 🎉 ([beca997](https://github.com/morluto/rea/commit/beca9977eb2b18fc7b9844cff0ca70004b6ff21a))
* clarify REA has no affiliated cryptocurrency or token ([#1214](https://github.com/morluto/rea/issues/1214)) ([c2d8146](https://github.com/morluto/rea/commit/c2d8146f94c7533eb87681c2405e93bdfef21b59))
* explain 6.2 contract and saved-data migration ([#1304](https://github.com/morluto/rea/issues/1304)) ([c267e99](https://github.com/morluto/rea/commit/c267e9922751c03df312655ebd623de1b480215c))
* **ghidra:** explain supported heap and CPU controls ([#1278](https://github.com/morluto/rea/issues/1278)) ([0c6852b](https://github.com/morluto/rea/commit/0c6852b392b34319a6fd2c6dffcac10cee51ab94)), closes [#1255](https://github.com/morluto/rea/issues/1255)
* keep the 30k milestone in Star History ([#1217](https://github.com/morluto/rea/issues/1217)) ([c399670](https://github.com/morluto/rea/commit/c399670653884673158f314ed38260aef74da593))
* require focused brittleness cleanup and executable examples ([d6832c3](https://github.com/morluto/rea/commit/d6832c3632847cf3e62d4082b4b8b8d9af554633))
* thank feature request contributors ([9db1fd0](https://github.com/morluto/rea/commit/9db1fd0bd7b17ed1dd21b9c72dabfa4ec6c23a3f))
* **website:** continue the Calculator example with reconstruction ([4578647](https://github.com/morluto/rea/commit/4578647c59a7487bce597a65be6eab8be0412e84))
* **website:** continue the Calculator example with reconstruction ([18a1e8c](https://github.com/morluto/rea/commit/18a1e8cd0efe14c06fd14aabe0c318d2ae390f78))
* **website:** explain SEO maintenance and indexing follow-up ([bb8ff2c](https://github.com/morluto/rea/commit/bb8ff2cfba638ee3a77f951c01e98340c757f525))
* **website:** introduce the worked homepage examples ([f6f5c16](https://github.com/morluto/rea/commit/f6f5c160979624cdcb33928f1a77cf000de403d4))
* **website:** invite deeper projects and reader feedback ([3fb9ffa](https://github.com/morluto/rea/commit/3fb9ffaa4d67685412873cbd3101c64fabbeaff3))
### Tests
* **apple:** verify compiled Mach-O root occurrence facts ([#1300](https://github.com/morluto/rea/issues/1300)) ([4bb4c6f](https://github.com/morluto/rea/commit/4bb4c6fe6d34525c7665a9d38b584b026dd5cdd9))
* **artifacts:** assert asset-catalog target refusal only on macOS ([44d5b4b](https://github.com/morluto/rea/commit/44d5b4b25e0831769c1bd4e5426ef498d0bd3c74))
* **artifacts:** pin per-occurrence roles for direct Mach-O roots and shared bytes ([701d90a](https://github.com/morluto/rea/commit/701d90aba48aaf4f23e1a73e46ebf9968fb85293))
* **artifacts:** pin per-occurrence roles for direct Mach-O roots and shared bytes ([b9e29c5](https://github.com/morluto/rea/commit/b9e29c52d483704c64cd88f87eaa117066288602)), closes [#1234](https://github.com/morluto/rea/issues/1234) [#1235](https://github.com/morluto/rea/issues/1235)
* **artifacts:** read /bin/ls slice layout from its FAT table ([#1223](https://github.com/morluto/rea/issues/1223)) ([c89b3a0](https://github.com/morluto/rea/commit/c89b3a00dce8df36ddb696b59c80e1adc6aceac1))
* **artifacts:** verify compiled Mach-O roles and permissions ([4bb4c6f](https://github.com/morluto/rea/commit/4bb4c6fe6d34525c7665a9d38b584b026dd5cdd9))
* consolidate redundant assertions into boundary workflows ([b71a591](https://github.com/morluto/rea/commit/b71a591a60e3fa5333889e3cf97e05f4ae03c686))
* **ghidra:** preserve selected verification resource limits ([1c3766a](https://github.com/morluto/rea/commit/1c3766a8bcc8a2b6af679cdaa92a73fec42b3372))
* **ghidra:** size oversized annotations for canonical delivery ([1e34197](https://github.com/morluto/rea/commit/1e341973cfad1dbf06755f3a086ffc23d42a723c))
* **ghidra:** use host-native absolute session root fixtures ([1e83d27](https://github.com/morluto/rea/commit/1e83d270c2098b1bcb59591698a257a05d2296fc))
* **javascript:** expect the invalid input_path code in the streamed CLI failure test ([d186ca7](https://github.com/morluto/rea/commit/d186ca7e41928fc2748de2631f5cb43115776571))
* **mcp:** read bundle failures from public error content ([69c3b32](https://github.com/morluto/rea/commit/69c3b32a21c90ea96194fb695f7b58992e8b3714))
* **mcp:** read typed errors in canonical Evidence regressions ([fd46cff](https://github.com/morluto/rea/commit/fd46cff017f0110aaab1216764cf01a71b341766))
* **mcp:** validate public error diagnostics in acceptance workflows ([09058eb](https://github.com/morluto/rea/commit/09058ebc4a68c76d865a92dbddb65811ba8344f7))
* **native:** assert batch identity in production registration ([933fcb3](https://github.com/morluto/rea/commit/933fcb33c1fa1eae109228b89c1200abb7745eb8))
* **native:** build the .app fixture executable with a complete Mach-O header ([facaae8](https://github.com/morluto/rea/commit/facaae865af243656ab8f557aeb42f5909748f2b))
* **process:** check malformed capture choices concurrently ([6020a0b](https://github.com/morluto/rea/commit/6020a0b3683ce16e1441963473605f870c247e29))
* **process:** check malformed capture choices concurrently ([48de11c](https://github.com/morluto/rea/commit/48de11ce2e5af9810fc97d1c2f89df56bf3a3d4d))
* remove duplicate workflow examples and self assertions ([d6d1cd2](https://github.com/morluto/rea/commit/d6d1cd248506015b59a2abdbbb84e3dbd02388fc))
### Continuous Integration
* **website:** allow explicitly requested Pages-only publication ([796b65e](https://github.com/morluto/rea/commit/796b65e1cd15f3cf819396716320db007655ee3f))
* **website:** allow explicitly requested Pages-only publication ([864160d](https://github.com/morluto/rea/commit/864160d8858fad3c0afebff81c31b090a1ebf823))
* **website:** allow explicitly requested Pages-only publication ([#1205](https://github.com/morluto/rea/issues/1205)) ([796b65e](https://github.com/morluto/rea/commit/796b65e1cd15f3cf819396716320db007655ee3f))
* **website:** publish Cloudflare and Pages from one artifact ([761881c](https://github.com/morluto/rea/commit/761881cec33b18d7228bae5e2093e5d44b96ceb1))
## [6.1.0](https://github.com/morluto/rea/compare/rea-agents-6.0.0...rea-agents-6.1.0) (2026-10-09)
### ⚠ BREAKING CHANGES
* **hopper:** Hopper regex mode uses ECMAScript Unicode syntax instead of Python re. Matching runs in a cancellable worker with a five-second deadline; literal mode keeps Unicode casefold matching.
* **hopper:** remove set_current_document. Use open_binary to switch targets; document arguments are scoped to the active target.
### Features
* **clients:** register Grok Build and Grok Bot during setup ([#1134](https://github.com/morluto/rea/issues/1134)) ([08561e0](https://github.com/morluto/rea/commit/08561e0eb7a4a01a256f3693a97061fbea7fb8fa))
* **ghidra:** make the startup deadline configurable ([#974](https://github.com/morluto/rea/issues/974)) ([d84bc8f](https://github.com/morluto/rea/commit/d84bc8f11abd6cbf5612daf5c8f7e1805d23c16e))
* **website:** add GitHub link with live star count ([2f59287](https://github.com/morluto/rea/commit/2f59287f1a1794a68102a45c61cc657659fa5de6))
### Bug Fixes
* **analysis:** bind overview document identity to the active target ([#1094](https://github.com/morluto/rea/issues/1094)) ([81b5104](https://github.com/morluto/rea/commit/81b51042767ad75310bad1a7a9faf954339841c0))
* **analysis:** resolve procedure identities and preserve literal queries ([d830cb7](https://github.com/morluto/rea/commit/d830cb79b305e6d4d255f8080de69ca668cbe0af))
* **android:** report actual provider readiness ([c715af8](https://github.com/morluto/rea/commit/c715af80587f808de816d3add6a6f989437ab66a))
* **android:** report startup and selector failure causes ([6c13fc8](https://github.com/morluto/rea/commit/6c13fc8e0a318ebe7be6b038089b350d99f8e286))
* **apple:** account for repeated archive projections ([e1df5e8](https://github.com/morluto/rea/commit/e1df5e85551125b27ef0debb7573de5507b149e1))
* **apple:** budget Interface Builder decoding and projection ([dbcf8c3](https://github.com/morluto/rea/commit/dbcf8c33915d924fdbc881bf2cf9676587f3b96f))
* **apple:** classify empty dyld settings by consumer semantics ([#1110](https://github.com/morluto/rea/issues/1110)) ([fe297e5](https://github.com/morluto/rea/commit/fe297e56e804130dd49cc0a95fcf2d115c183ae3))
* **apple:** decode bundle plist bytes before executable lookup ([d575a73](https://github.com/morluto/rea/commit/d575a7340bb19b84733c79b14de9f4df7181c6b3))
* **apple:** decode Interface Builder XML byte encodings ([#1095](https://github.com/morluto/rea/issues/1095)) ([f8e143a](https://github.com/morluto/rea/commit/f8e143a3bcd20ddcc0d76d90e73e238d456fe5a3))
* **apple:** derive dispatch coverage from located decode facts ([488f448](https://github.com/morluto/rea/commit/488f448ae27fd62904967ec1e0ab072e834a9822))
* **apple:** keep skipped catalog entries from reading as absence ([a079af2](https://github.com/morluto/rea/commit/a079af297bb454417dfd3d89b0037397554ad83e))
* **apple:** report apps without asset catalogs as empty inventories ([e2f0378](https://github.com/morluto/rea/commit/e2f03786f496ed742572acd87f47270c958171ec))
* **apple:** report apps without asset catalogs as empty inventories ([79e5a39](https://github.com/morluto/rea/commit/79e5a3923db896323c0491e31004214856529b74))
* **apple:** report missing keyed archive hierarchy references ([#1104](https://github.com/morluto/rea/issues/1104)) ([3b2ec69](https://github.com/morluto/rea/commit/3b2ec69c54fc9cf65bf8441edbb96e9619c3a37e))
* **apple:** validate dylib candidates and preserve search uncertainty ([#1100](https://github.com/morluto/rea/issues/1100)) ([7914e36](https://github.com/morluto/rea/commit/7914e36ab9adbbf591a6e1f3fafcb2e17f55d667))
* **apple:** validate physical slices and dylib platform compatibility ([15f92f2](https://github.com/morluto/rea/commit/15f92f298891c8b16d7d13c78cb6ca66cb90cd85))
* **application:** budget bridge candidate projection by bytes ([3d450a2](https://github.com/morluto/rea/commit/3d450a29fc91cef3e06ffce9a925ac70dcb24272))
* **artifacts:** preserve keyed archive integer precision ([4034883](https://github.com/morluto/rea/commit/4034883e9860a97edee03260fab59f9229debfa6))
* **artifacts:** report keyed-archive selection mistakes as invalid input ([5a55d5b](https://github.com/morluto/rea/commit/5a55d5b1c6aefb4a4e5df63ec43b7e2fc0a7d385))
* **artifacts:** report keyed-archive selection mistakes as invalid input ([25fb6d3](https://github.com/morluto/rea/commit/25fb6d32a325d88bb0f4e05e16f5f82e4f91c5ca))
* **artifacts:** retain failed DMG cleanup state and diagnostics ([#1103](https://github.com/morluto/rea/issues/1103)) ([4bb056b](https://github.com/morluto/rea/commit/4bb056bbb5b735e214ed8d725aa3de1c06fb0dc9))
* **browser:** advertise zero-based units for runtime source coordinates ([#1085](https://github.com/morluto/rea/issues/1085)) ([6218d28](https://github.com/morluto/rea/commit/6218d289e241715d0868004caafe15b5c4758450))
* **browser:** bind correlated replies to their selected session ([96d3caf](https://github.com/morluto/rea/commit/96d3cafb0725881b6cdab0e2185104957dc69f71))
* **browser:** bound aggregate source-map decoding before expansion ([f983c71](https://github.com/morluto/rea/commit/f983c718c33789ee40aec43f84315f6b53e95bde))
* **browser:** bound script metadata and preserve omissions ([faf209e](https://github.com/morluto/rea/commit/faf209e50d9faab03a185c1f044de3582552d11e))
* **browser:** bound source-map fetches and retain predecessor requests ([eaf5734](https://github.com/morluto/rea/commit/eaf57340831a753faec58246290f9502d159b6b1))
* **browser:** compose nested source-map column offsets ([#1109](https://github.com/morluto/rea/issues/1109)) ([8b08ec0](https://github.com/morluto/rea/commit/8b08ec0af936405fd20db25f941e2ae6318c5145))
* **browser:** keep initiator callsites out of script coordinate guidance ([#1096](https://github.com/morluto/rea/issues/1096)) ([3c157b4](https://github.com/morluto/rea/commit/3c157b4ec6297e6737bd3c2ec3dc520c7403402f))
* **browser:** normalize selected script manifest roots on Windows ([#1078](https://github.com/morluto/rea/issues/1078)) ([b49beb4](https://github.com/morluto/rea/commit/b49beb42d7a97f73d052a27fb99673b1bd0d3d39))
* **browser:** preserve captures when response bodies are unavailable ([96af2fa](https://github.com/morluto/rea/commit/96af2fa7444a3777d51ff46202ef563146929dbd))
* **browser:** preserve command failures and reject malformed replies ([6b92002](https://github.com/morluto/rea/commit/6b92002597d34555c32ebf24b9db6e4c17c0a08d))
* **browser:** treat module-import initiator positions as script positions ([ae0630a](https://github.com/morluto/rea/commit/ae0630a619ee2c98a68e65ca44bf0b93424e2f8e))
* **browser:** treat module-import initiator positions as script positions ([99d31ee](https://github.com/morluto/rea/commit/99d31ee24ad060babace9eca3325858418e0f55a))
* **browser:** validate and bound source-map evidence ([0a0174b](https://github.com/morluto/rea/commit/0a0174b9ac8a73b61094e857a2950f4e5a06f544))
* **build:** exclude the test-only generated catalog from packages ([#1116](https://github.com/morluto/rea/issues/1116)) ([d1c904b](https://github.com/morluto/rea/commit/d1c904bac7977d44b06bf2f823587baedcc88b9e))
* **build:** make catalogs and packaged skills generated outputs ([#1086](https://github.com/morluto/rea/issues/1086)) ([e613405](https://github.com/morluto/rea/commit/e6134056cf519410160a196363f8a04f0729324e))
* **capture:** retain Electron observations and HAR resource failures ([44fd183](https://github.com/morluto/rea/commit/44fd18305fa5a8893ebb5b952099fdf45dbd6e55))
* **ci:** align diagnostic regressions and format merged changes ([67756da](https://github.com/morluto/rea/commit/67756dacc0d435a61d2d0c403412151769da028f))
* **ci:** restore generated shard inputs and cleanup assertions ([5f93b4b](https://github.com/morluto/rea/commit/5f93b4b125e78f088a2349a178e60f8c0af3e1a2))
* **cli:** accept exact native names through explicit selectors ([c313606](https://github.com/morluto/rea/commit/c3136064c7f8f72b2f6c6799ec41ea6424111bb7))
* **cli:** drive mcp doctor help from a single option schema ([b7d803d](https://github.com/morluto/rea/commit/b7d803dd10c7ef8bb73f81f5e893168af8ea86e6))
* **cli:** preserve blank JSON paths for input validation ([#1068](https://github.com/morluto/rea/issues/1068)) ([3dcb732](https://github.com/morluto/rea/commit/3dcb732da33f6ceef597506b14a4536f1c9aff96))
* **cli:** preserve web cancellation exit status ([1d9b96a](https://github.com/morluto/rea/commit/1d9b96a9c497694592137cf95bea2af0a190abe7))
* **cli:** support MCP doctor help ([a69b833](https://github.com/morluto/rea/commit/a69b8337ab38707aaad2ac2fedb652f05afeb71c))
* **contracts:** preserve local inputs and comparison uncertainty ([70e8a8f](https://github.com/morluto/rea/commit/70e8a8f86060496452ccbc1a49b39822efef4113))
* **docs:** validate translated links to canonical product facts ([34f7c4f](https://github.com/morluto/rea/commit/34f7c4fd661e07db66c560a4d54272b0163a52b6))
* **domain:** order canonical paths by code point, not UTF-16 unit ([#1034](https://github.com/morluto/rea/issues/1034)) ([b5c2954](https://github.com/morluto/rea/commit/b5c2954ad67f0280732df043d5d9702f3d202819))
* **domain:** preserve prototype-named JSON members through Evidence boundaries ([#1049](https://github.com/morluto/rea/issues/1049)) ([40e18b2](https://github.com/morluto/rea/commit/40e18b2e37f2be11f452606c2d875981b03ad03e))
* **domain:** reject excessive JSON depth with actionable diagnostics ([#1029](https://github.com/morluto/rea/issues/1029)) ([bfbfc73](https://github.com/morluto/rea/commit/bfbfc7330aa7175018de04f1d099b8d4aeec3bd1))
* **electron:** bound hook retention and report dropped coverage ([02d0702](https://github.com/morluto/rea/commit/02d07027617a5df014f92a351aa9418aade6f06f))
* **evidence:** name the failed constraint when a bundle is rejected ([82a1a52](https://github.com/morluto/rea/commit/82a1a525d7aa725d939926ba953434fbf5db0ab0))
* **evidence:** name the failed constraint when a bundle is rejected ([cf96ceb](https://github.com/morluto/rea/commit/cf96ceb2119f52f61a621d2a790b7c8804c65595))
* **evidence:** report missing evidence files instead of permission advice ([e8b92a4](https://github.com/morluto/rea/commit/e8b92a40c003a5e6ce3cefe4ad18392d39759653))
* **evidence:** report missing evidence files instead of permission advice ([89252f1](https://github.com/morluto/rea/commit/89252f1f35de91494bd49460b1645d8c09cc6d33))
* **evidence:** require a complete record before the single-record hint ([38bbb65](https://github.com/morluto/rea/commit/38bbb656da2659088e30a1ca3e4434b2f65bab32))
* **firmware:** reject malformed UTF-8 producer reports ([4a45c14](https://github.com/morluto/rea/commit/4a45c14742e6868f687cead2ddf736c3f7c49acd))
* **ghidra:** admit Linux arm64 with matching native tools ([3e598b2](https://github.com/morluto/rea/commit/3e598b2d38a728cd9fd4a359741500a021ba9d3a))
* **ghidra:** harden location resolution and provider lifecycle ([1f5be75](https://github.com/morluto/rea/commit/1f5be750bced759339183945488cea352b18f28b))
* **ghidra:** make qualified function renames idempotent ([4458128](https://github.com/morluto/rea/commit/4458128a845c1448140b44d6e62d6ccfe611d37c))
* **ghidra:** parse long procedure selectors without recursion ([480b16b](https://github.com/morluto/rea/commit/480b16b9c151e1d4bfbca8b49a0668d74ceaa400))
* **ghidra:** preserve function references and snapshot boundaries ([84a17d5](https://github.com/morluto/rea/commit/84a17d55199b1b46493aea6bf4e41029a3b200fc))
* **ghidra:** preserve POSIX runtime paths with spaces ([80c3d36](https://github.com/morluto/rea/commit/80c3d36dfa2597f34fdeb69e0ba75277ee50c85c))
* **ghidra:** preserve source failures and snapshot ownership ([704fa76](https://github.com/morluto/rea/commit/704fa7699ca183d5d5e0518a6fcdbb953ec35a10))
* **ghidra:** preserve Unicode boundaries without breaking sessions ([bef234d](https://github.com/morluto/rea/commit/bef234d6ce63cd296a654400443fcdbbcd44d7de))
* **ghidra:** recover regex stack exhaustion without losing annotations ([bc4aa46](https://github.com/morluto/rea/commit/bc4aa46d7c3960a1f325523e48aed2089b176e84))
* **ghidra:** reject address truncation before reads and edits ([dcae3c6](https://github.com/morluto/rea/commit/dcae3c6c148582d235f5650aace6f9744eeb153c))
* **ghidra:** resolve exact external function entries ([549effa](https://github.com/morluto/rea/commit/549effa056729e5f9239d9ed7864537a9c49e421))
* **hopper:** bind analysis to the active target and correct boundary contracts ([2f71375](https://github.com/morluto/rea/commit/2f71375efc517bb9e6f9800f8e8a6849766bc893))
* **hopper:** bind file mappings to verified source bytes ([82626c4](https://github.com/morluto/rea/commit/82626c4499a53c227187575d40a845fadd5318e2))
* **hopper:** diagnose MCP provider failures with stage, state, and request context ([#1044](https://github.com/morluto/rea/issues/1044)) ([5a67c7f](https://github.com/morluto/rea/commit/5a67c7fc540c494371de76dcdf353923656993d3))
* **hopper:** enforce caller-supplied request deadlines ([#1119](https://github.com/morluto/rea/issues/1119)) ([e8939ca](https://github.com/morluto/rea/commit/e8939ca2208bc41454b73b90a32418714e6a2969))
* **hopper:** isolate regex matching from the native API thread ([f201b04](https://github.com/morluto/rea/commit/f201b04fbbb29591b0d2bb3f3b24636526e4ec4e))
* **hopper:** load verified FAT64 slices with native Mach-O semantics ([0a49d5b](https://github.com/morluto/rea/commit/0a49d5bfb931124d3d398dfbd64e9f6ae8a01405))
* **hopper:** normalize native block endpoints and retain terminal evidence ([2847311](https://github.com/morluto/rea/commit/2847311a579ce2da4c8ded4d89fcdd01545e6da5))
* **hopper:** preserve launcher evidence on readiness timeout ([458771c](https://github.com/morluto/rea/commit/458771cb583e38b848b3d8c58595d163143ff50a))
* **hopper:** preserve native navigation and annotation semantics ([f2e22e1](https://github.com/morluto/rea/commit/f2e22e13a6956985bd65a2d75e4db7e3128cce81))
* **hopper:** preserve owned basic-block endpoint instructions ([#1118](https://github.com/morluto/rea/issues/1118)) ([329cf20](https://github.com/morluto/rea/commit/329cf206d1111c051733c7115cabff4b46722deb))
* **hopper:** preserve partial native call and string evidence ([2461702](https://github.com/morluto/rea/commit/246170238ebb8669a20b57b559b03cfc26ee1b8c))
* **hopper:** preserve typed string values and verify real searches ([7d7b3f9](https://github.com/morluto/rea/commit/7d7b3f961af2dc9b7572e91aaec29e6c4eccf9d5))
* **hopper:** report launcher failures before bridge timeout ([#1105](https://github.com/morluto/rea/issues/1105)) ([cd756b0](https://github.com/morluto/rea/commit/cd756b07d5b9c06e085d778e9f1c4fc9bd403219))
* **hopper:** resolve FAT loaders and original file coordinates ([35f1ddd](https://github.com/morluto/rea/commit/35f1ddd6bc77588b9971961cd70968a815aae266))
* **hopper:** validate annotation destinations and symbol extents ([b2d5bc1](https://github.com/morluto/rea/commit/b2d5bc110914f2ad42d17bc739d5f37c1b0f0a4d))
* **hopper:** verify lease cleanup and repair the macOS test lane ([#1111](https://github.com/morluto/rea/issues/1111)) ([b743bd2](https://github.com/morluto/rea/commit/b743bd20a0cbc39728e2e822fa75c013d87e1730))
* **inspector:** bound retained metadata and preserve cancellation ([e714fb0](https://github.com/morluto/rea/commit/e714fb027afdf11bfbb0838722523d3fa9ebf244))
* **install:** guard empty prefix_args expansion on macOS Bash 3.2 under set -u ([#1061](https://github.com/morluto/rea/issues/1061)) ([68b9fa4](https://github.com/morluto/rea/commit/68b9fa489b0c07f580633785ec61c17fa20b5083))
* **javascript:** bound primitive string growth and repeated evaluation ([4a1837d](https://github.com/morluto/rea/commit/4a1837d9d52b1a6454469e2dc63eeb8d716fb296))
* **javascript:** bound semantic expansion and resolve lexical receivers ([16f4609](https://github.com/morluto/rea/commit/16f4609d689445c05a0befc744fce7e72f7047ec))
* **javascript:** classify direct defaults and argv elements ([6495171](https://github.com/morluto/rea/commit/649517181268a0b729970b7cbbda15e04b199e32))
* **javascript:** honor cancellation before evidence publication ([#1098](https://github.com/morluto/rea/issues/1098)) ([cc0ee2e](https://github.com/morluto/rea/commit/cc0ee2edc60dda42d7b7cfb2c08e39b0b736b5e9))
* **javascript:** omit self-referential import edges with disclosure ([#1130](https://github.com/morluto/rea/issues/1130)) ([1d7115b](https://github.com/morluto/rea/commit/1d7115b7b470719a32e477ca3cbb681f0ad408b8))
* **javascript:** parse plain TypeScript artifact dialects ([#1102](https://github.com/morluto/rea/issues/1102)) ([3db4681](https://github.com/morluto/rea/commit/3db46813f80f84504c5b87c73a4bece82a8fdc5e))
* **javascript:** preserve HTML carriage return source ranges ([#1092](https://github.com/morluto/rea/issues/1092)) ([23862af](https://github.com/morluto/rea/commit/23862af1b57413e09abf394f6e4f8369f6355d5a))
* **javascript:** preserve lexical open and exact template semantics ([d6cc9ca](https://github.com/morluto/rea/commit/d6cc9ca3a6e92604c837f61c193baf5abedaabc8))
* **javascript:** preserve original BOM source coordinates ([#1093](https://github.com/morluto/rea/issues/1093)) ([83defc0](https://github.com/morluto/rea/commit/83defc054b69e94da888d70bb3b05d835e1bf74d))
* **javascript:** retain NodeNext artifact source facts ([#1087](https://github.com/morluto/rea/issues/1087)) ([c1b370c](https://github.com/morluto/rea/commit/c1b370ce0dfcbd5725cf6aebe23b022dfc75ac84))
* **javascript:** use Node legacy package entry fields ([1706005](https://github.com/morluto/rea/commit/170600541bf44f2a63731e8b3d42aae3cbb8d6b3))
* **managed:** bind inspection evidence to artifact identity ([73b09f4](https://github.com/morluto/rea/commit/73b09f4c5c511ce80baa0c89717181bbe0ecba8f))
* **managed:** match exact method bytes without decoded signatures ([17809ca](https://github.com/morluto/rea/commit/17809caacd0f44fcc7c1af42932ea655489d64ae))
* **mcp:** flatten root union input schemas ([#1062](https://github.com/morluto/rea/issues/1062)) ([6a7650e](https://github.com/morluto/rea/commit/6a7650e93cba9169baad95d2c52b11351ae39d0e))
* **mcp:** preserve retained evidence on oversized delivery ([0639a54](https://github.com/morluto/rea/commit/0639a541a3b712940119f59e8189bc962b267726))
* **mcp:** retain complete application results across response limits ([a1ed423](https://github.com/morluto/rea/commit/a1ed4232de635d4acc0dd9eb293e309a29d03e80))
* **mcp:** retain oversized errors before transport delivery ([b3f1b4e](https://github.com/morluto/rea/commit/b3f1b4e822aec5626d1952a88f50c7520dc265d3))
* **metadata:** stop schema changes churning generated skill evidence ([#1075](https://github.com/morluto/rea/issues/1075)) ([d52f66d](https://github.com/morluto/rea/commit/d52f66d62a93ec09cccdf53e64e3ccd24d16e520))
* **native:** bind signature observations to registered target versions ([#1099](https://github.com/morluto/rea/issues/1099)) ([c789af0](https://github.com/morluto/rea/commit/c789af04b76c0e76a522a5dece34f461288f5ecd))
* **native:** bound retained observations and preserve failure evidence ([7c32387](https://github.com/morluto/rea/commit/7c323870c2dcab78654ee7a80128b06affdf2bbe))
* **native:** preserve bridge failure types during cleanup ([1d0baa3](https://github.com/morluto/rea/commit/1d0baa352fc76d1760abbe29a3cc80fa17296916))
* **native:** resample tool identity for each invocation ([14b19a0](https://github.com/morluto/rea/commit/14b19a0b8a5af401212c552173e761eac53bfe46))
* **native:** share command supervision and retain failure output ([f2e9c49](https://github.com/morluto/rea/commit/f2e9c491ea00bf79d5665102d95a3339b63cfe4f))
* **native:** supervise LLDB and preserve bounded capture uncertainty ([915855e](https://github.com/morluto/rea/commit/915855e75ca3fe3b1b54978ace6bbe10d1973f64))
* **process:** avoid cold ownership helper deadline exhaustion ([#1139](https://github.com/morluto/rea/issues/1139)) ([65a809a](https://github.com/morluto/rea/commit/65a809a0da0555aa8eeafbc2ec2559517471be02))
* **process:** derive executable names from the capture host ([#1108](https://github.com/morluto/rea/issues/1108)) ([34cc925](https://github.com/morluto/rea/commit/34cc9259c1076a0d9575a87679befca692ec86c2))
* **process:** identify unknown live processes in cleanup diagnostics ([eb89a16](https://github.com/morluto/rea/commit/eb89a16d9bc51b65dcc75e05f8492de894320753))
* **process:** name the reason two captures cannot be compared ([#1080](https://github.com/morluto/rea/issues/1080)) ([eb69763](https://github.com/morluto/rea/commit/eb69763d27e29fe3247c008925016e4c73cb6abe))
* **process:** preserve observations after successful cleanup ([2af12a1](https://github.com/morluto/rea/commit/2af12a18a36bb80fb7d91ef4c8009212750daa0a))
* **process:** retain ownership after incomplete cleanup ([e2fc249](https://github.com/morluto/rea/commit/e2fc2493b6a59f0663495d277c0cfec1aeb25a7a))
* **process:** stabilize native capture and ownership prerequisites ([2b27515](https://github.com/morluto/rea/commit/2b2751547662f8cb142f96d91eff50388a1ecb31))
* **process:** stop failing captures on tokens macOS cannot expose ([#1057](https://github.com/morluto/rea/issues/1057)) ([5547c1e](https://github.com/morluto/rea/commit/5547c1e697af8c2e1c771abe5344d10b7c1cd340))
* **providers:** validate ELF versions and preserve probe cancellation ([8b01e0c](https://github.com/morluto/rea/commit/8b01e0cc8904b512b517b4471ef2150f40c98f0d))
* **release:** always bump minor for releases ([be783ef](https://github.com/morluto/rea/commit/be783efaba62dc76c5d8d42229869a32afdb302a))
* **release:** publish prereleases under the next npm tag ([bfb7776](https://github.com/morluto/rea/commit/bfb7776006303c6164dba2f22b8e81fdb7c20beb))
* **release:** publish reviewed release PR merges ([cdddfdd](https://github.com/morluto/rea/commit/cdddfddf495ffd172f62a6a801f7697fe502847e))
* **release:** recognize conventional titles in GitHub merge commits ([f5009ed](https://github.com/morluto/rea/commit/f5009ed55f081939409808870458162991f836ca))
* **release:** restore automatic release proposals on main ([acb3e0f](https://github.com/morluto/rea/commit/acb3e0f2e5b38a9c97df7ed78c8e6e5f38bfa08f))
* **release:** validate frozen checkpoint versions and breaking notes ([8a31508](https://github.com/morluto/rea/commit/8a31508c8958800364e255540ded1586298d7008))
* **release:** validate frozen checkpoint versions and breaking notes ([60825fb](https://github.com/morluto/rea/commit/60825fb44751c9482bdf4cafdac3599da7c82d45)), closes [#1063](https://github.com/morluto/rea/issues/1063)
* select Node legacy package entry fields for import and require ([#1035](https://github.com/morluto/rea/issues/1035)) ([1706005](https://github.com/morluto/rea/commit/170600541bf44f2a63731e8b3d42aae3cbb8d6b3))
* **session:** serialize snapshot lifecycle with admitted requests ([e44cb45](https://github.com/morluto/rea/commit/e44cb45908af8d3902e0db044e0cf7b86cdd7ed0))
* **setup:** launch Windows npx registrations through cmd.exe ([#1072](https://github.com/morluto/rea/issues/1072)) ([ef30343](https://github.com/morluto/rea/commit/ef30343154d64d78b620d41c37457eee5d99fc71))
* **setup:** treat empty client config files as new documents ([#1117](https://github.com/morluto/rea/issues/1117)) ([9fd65ce](https://github.com/morluto/rea/commit/9fd65ce0711ce9257aee15e62a5ecf9832960035))
* **snapshot:** retain MCP workflow replay bindings ([5e1afe4](https://github.com/morluto/rea/commit/5e1afe454f2f283eeeea4532d07a9bdbea8bd51e))
* **target:** preserve app bundle filesystem failure reasons ([d4c2c3c](https://github.com/morluto/rea/commit/d4c2c3c18f691d04526fe38867347faa2530861d))
* **update:** accept npm 12 release metadata ([#1138](https://github.com/morluto/rea/issues/1138)) ([567a82f](https://github.com/morluto/rea/commit/567a82f8d4feb629a7c10d2cc9180377eb1f6f66))
* **verify:** close both sides of the browser proxy ([f7366a5](https://github.com/morluto/rea/commit/f7366a517ff0545f01df6202b1ed3231d9dd3b4a))
* **verify:** isolate package archives and published canary caches ([3eb7dbd](https://github.com/morluto/rea/commit/3eb7dbdc1689737b44cc4ff044bcb1a311511969))
* **verify:** remove stale mocked bridge package probe ([826583d](https://github.com/morluto/rea/commit/826583dd43fc918c70a87dfe148c2fdbc8612f3b))
* **verify:** report final success only after resource cleanup ([ee043e2](https://github.com/morluto/rea/commit/ee043e2cbf30152c60b403fff050a0fc848a3286))
* **workflows:** keep caller-input details in workflow input errors ([#1089](https://github.com/morluto/rea/issues/1089)) ([289aef6](https://github.com/morluto/rea/commit/289aef6838e424c14f331a9905020079e6b7539b))
* **workflows:** retain residual unknowns through CLI and MCP ([0136ee8](https://github.com/morluto/rea/commit/0136ee8c22300ed351af5eab6329ab4d271b5bb6))
### Performance Improvements
* **mcp:** advertise each tool JSON Schema once per target ([#1059](https://github.com/morluto/rea/issues/1059)) ([5ccb924](https://github.com/morluto/rea/commit/5ccb9241be15bb6a19b99fbbfb27ff3356ba157b))
* **build:** avoid duplicate documentation generation ([c701376](https://github.com/morluto/rea/commit/c701376777212ec9acfd10c97f45b1eaf0c885c6))
* **javascript:** index configuration and module lookups ([67252b2](https://github.com/morluto/rea/commit/67252b23b9e35e9526fed7842dab47a2c7c9fe5f))
* **javascript:** reuse validated immutable graphs ([#1112](https://github.com/morluto/rea/issues/1112)) ([ec6db0f](https://github.com/morluto/rea/commit/ec6db0f0630c4b0b35f0db84c0030784c1aa58a6))
### Code Refactoring
* **artifacts:** centralize stable inventory identities ([135d102](https://github.com/morluto/rea/commit/135d102f9df844d70d352870afce80f67c0ae96f))
* **browser:** charge source-map records before retention ([e762e32](https://github.com/morluto/rea/commit/e762e32afbba3fd32532fd42a3f4fdcd05252ad3))
* **config:** prune unused format wrappers and launcher export ([81ae838](https://github.com/morluto/rea/commit/81ae8385679ef10b95d34d0f0b5ba11732ac86b5))
* **input:** share schema issue error construction ([65a6288](https://github.com/morluto/rea/commit/65a6288257e4c3cab9adb53b0f9123ef567b61bd))
* **setup:** validate formats through canonical configuration ([4b10665](https://github.com/morluto/rea/commit/4b1066501b379107b2375e270f386fc9855a85c1))
### Documentation
* add Persian README translation with full language navigation ([7a7460f](https://github.com/morluto/rea/commit/7a7460f04f3cfd7e365d70ff891bdd0c474901b6))
* add ten README translations and expand language navigation ([a61491a](https://github.com/morluto/rea/commit/a61491ad00b21e912e16f68bff829927aed6e16f))
* align translated READMEs and website links with English ([d83f098](https://github.com/morluto/rea/commit/d83f0983d5aa18d29d95d24c4ccb3928be6f29f5))
* celebrate 20,000 GitHub stars 🎉 ([#1079](https://github.com/morluto/rea/issues/1079)) ([9455e7c](https://github.com/morluto/rea/commit/9455e7c8bc9d5c4a9a1fc9077aa15007ad80997e))
* check surrounding cases when changing boundaries ([46d195e](https://github.com/morluto/rea/commit/46d195e8a48b710fc355e84cb6b79461b9c39005))
* clarify contribution scope and cosmetic suggestions ([1f79002](https://github.com/morluto/rea/commit/1f7900249783956070af49c10f86002a0dfdc42b))
* clarify evidence ownership and verification guidance ([a9e00b8](https://github.com/morluto/rea/commit/a9e00b83f37651a8dd241375615b248062e04227))
* move Portuguese toward the end of language navigation ([2a4979b](https://github.com/morluto/rea/commit/2a4979b7cdc1a517865573d6c36654c022347d0a))
* move star milestone into history sections across readmes ([6e6ff7b](https://github.com/morluto/rea/commit/6e6ff7bd2eabb668602258ad5e31eb758b31f823))
* require partial native facts at provider boundaries ([2b86ea9](https://github.com/morluto/rea/commit/2b86ea9c7cd3cfc2141a021f8b531dbc84395c81))
* require surrounding boundary checks for review fixes ([9833c94](https://github.com/morluto/rea/commit/9833c94656e1d54e7711dc483bf8091ced14234f))
* **testing:** prioritize real workflows and distinct regressions ([9588482](https://github.com/morluto/rea/commit/9588482bfeeea869d7274d27fb96bac70278dd42))
* **website:** add a CTF showcase and FAQ ([#1077](https://github.com/morluto/rea/issues/1077)) ([a4d77f0](https://github.com/morluto/rea/commit/a4d77f0ff0242b7ab891030d2ffa09a4b4bc1c3c))
### Tests
* **acceptance:** add application workflow MCP parity harness and scenarios ([5ac3dc9](https://github.com/morluto/rea/commit/5ac3dc96f064e691b357aeddc11fa76b7b4d66d1))
* **artifacts:** retire simulated mounts after detach failures ([f591e37](https://github.com/morluto/rea/commit/f591e37a1e45d9b7179ed788c4e7ee77a708c6b0))
* **artifacts:** verify native directory identity on supported Windows runtimes ([#1069](https://github.com/morluto/rea/issues/1069)) ([e94be95](https://github.com/morluto/rea/commit/e94be95c66515fa6fba2a46e4b29850d34141fef))
* **browser:** pin DOM and source-map URL policy classifications ([#1120](https://github.com/morluto/rea/issues/1120)) ([c1d0002](https://github.com/morluto/rea/commit/c1d0002470dc2b6bde73e4ffe438e734dbb24d8d))
* **browser:** reject unmodeled CDP commands in protocol fixtures ([017297c](https://github.com/morluto/rea/commit/017297c40c0c38b9d9c17f5194f0f4c51748f0c3))
* classify application scenarios by their actual boundaries ([0e0b386](https://github.com/morluto/rea/commit/0e0b386dc35bdee1174df9a2d718e0f3e5793666))
* **cli:** verify self-import parity and cleanup ([55c9ce2](https://github.com/morluto/rea/commit/55c9ce26d1b52f359a21512103088048f9aa7492))
* consolidate failure guards and trim unused fixture APIs ([ffd9611](https://github.com/morluto/rea/commit/ffd9611308c91b894a7b0d27f331238f5117dacf))
* **hopper:** cover real boundary failures and CLI parity ([64717ad](https://github.com/morluto/rea/commit/64717ad7daa3152eeb718b4eb5fdcc77f1d76542))
* **hopper:** verify real boundaries and prune redundant happy paths ([7005166](https://github.com/morluto/rea/commit/7005166f5878737fb7b3c7ec4e3d2ee5f4dcce30))
* **mcp:** serialize real process capture and report unavailable authority ([8f9da25](https://github.com/morluto/rea/commit/8f9da251647beb530f6851c9dad5040b19a50a35))
* **process:** cover argv rewrites in native ownership inspection ([09d7b9b](https://github.com/morluto/rea/commit/09d7b9bab53ae968502fd6e19df694cca8cab817))
* **process:** distinguish native startup from producer verification ([9a70fb4](https://github.com/morluto/rea/commit/9a70fb482c974658088167c9d279bd70159e5dc8))
* **process:** expose unavailable capture and unexpected teardown failures ([90b06db](https://github.com/morluto/rea/commit/90b06db6c0b2c5863f292f63a226a5c5678a86ac))
* **process:** report the cause of terminal capture failures ([8a4c4b6](https://github.com/morluto/rea/commit/8a4c4b657fe3b0c249dd2e2147f6960361684c59))
* **process:** retain cancellation checks under unverified host cleanup ([9a5b077](https://github.com/morluto/rea/commit/9a5b0778993102460e333de6cad3ba85383c10be))
* **process:** retire native caches at worker teardown ([a0784c0](https://github.com/morluto/rea/commit/a0784c0d2cb70c48ecfeb0be23c6d68de5ee5be1))
* **process:** serialize real CLI capture boundaries ([82560eb](https://github.com/morluto/rea/commit/82560ebf593a7dfc704698ee312e4d8f1629be8f))
* prune redundant cases and promote configuration lifecycle coverage ([5945915](https://github.com/morluto/rea/commit/5945915f91adf85de91e16b69534bc3ed1d1b69a))
* prune resource-recovery wording assertions ([ae06dcf](https://github.com/morluto/rea/commit/ae06dcf83f65b06abb390d2e0b0ea33543278d6e))
* remove duplicate result assertions before throwing guards ([a1b7d40](https://github.com/morluto/rea/commit/a1b7d40bb0212cdfdddd770a1bccbed097601e0a))
* **session:** preserve live binding after cancelled switches ([1136ea8](https://github.com/morluto/rea/commit/1136ea881029eab59ffb0834149e86a6aff69e3b))
* **setup:** scope removal regression to its fixture client ([fe48e77](https://github.com/morluto/rea/commit/fe48e779c264745d28b5a819e51c06e6b5bd2776))
* **workflows:** verify residual questions in CLI snapshots ([770d2f6](https://github.com/morluto/rea/commit/770d2f60aa948cfdb61c71304be2f3e35f673840))
### Continuous Integration
* run signature target binding regressions on native macOS ([#1107](https://github.com/morluto/rea/issues/1107)) ([1e63144](https://github.com/morluto/rea/commit/1e63144390070f569998271fafd1459788ef3265))
## [6.0.0](https://github.com/morluto/rea/compare/rea-agents-5.0.0...rea-agents-6.0.0) (2026-10-08)
+99 -92
View File
@@ -1,16 +1,30 @@
# Contributing to REA
REA welcomes focused bug fixes, documentation improvements, tests, and reverse-engineering workflow enhancements. Open an issue before a large contract or architecture change so its scope can be agreed before implementation.
REA welcomes focused bug fixes, documentation improvements, tests, and reverse-engineering workflows. For large contract or architecture changes, explain the intended scope and link the relevant issue or design discussion.
For capability organization and provider composition, follow the incremental
[migration guide](docs/capability-migration.md). Run `npm run verify:test-discovery`
after adding or moving tests.
## Choosing a contribution
Explain the concrete problem, keep related corrections together, and report
verification and unavailable coverage. Contributions should justify their review
and maintenance cost. Keep cosmetic polish with useful fixes; confusing or
incorrect user instructions warrant standalone corrections. Collect other
cosmetic-only suggestions in an issue rather than separate PRs.
For capability organization and provider composition, use the
[architecture map](docs/architecture.mermaid). Production factories in
`src/composition/` construct fresh providers without starting engines or acquiring
targets; optional adapter failures must preserve successful peers. Run
`npm run verify:test-discovery` after adding or moving tests. Resolved import
boundaries are checked by `npm run verify:module-boundaries`, included in lint.
When adding or changing an MCP tool, follow the [tool design guide](docs/tool-design.md) and preserve the canonical contracts and generated catalog.
## Development setup
REA development requires Node.js 24.18.x and npm 11.16.x (pinned toolchain via `nvm use`; the supported runtime range is Node.js ^22.19 || ^24.11 || >=26, as the README badge states). Real-Hopper verification additionally requires either macOS 12+ or an officially supported Linux host (Ubuntu 24.04+, Fedora 41+, 64-bit Arch, or CachyOS) and an installed Hopper application. Linux demo verification uses its own private Xvfb display and does not require a desktop session. Run `nvm use` before installing dependencies.
Use the development toolchain pinned in `.nvmrc` and
`package.json#packageManager`. Run `nvm use` before installing dependencies;
installed-package runtime support is documented in
[installation](docs/installation.md#start-setup).
```bash
npm ci
@@ -19,12 +33,14 @@ npm run check:fast
`npm ci` installs the exact dependencies and prepares the Husky hooks without
building the project. Run `npm run build:cached` when you need the standalone
CLI or MCP server; `npm run build` remains the uncached compiler leaf used by
Turbo. Turbo caches deterministic builds and static checks across Git
worktrees. After a package, lockfile, or managed-skill version change, run
CLI or MCP server; it compiles the runtime and bundles the authored skill.
`npm run build` forces those tasks to rerun. Neither command generates test
catalogs, documentation projections, or managed verification evidence. Turbo
caches deterministic builds and static checks across Git worktrees. After a package, lockfile, or managed-skill version change, run
`npm run metadata:generate` before building.
Keep dependencies flowing inward through the existing domain, contracts, provider, application, server, and adapter layers. Parse unknown values at process and protocol boundaries, model expected failures with `Result`, and preserve the canonical tool inventory defined by `TOOL_CONTRACTS` unless a deliberate contract change updates every verifier, generated catalog artifact, and snapshot. Keep tool discovery complete and report capability- and session-scoped availability through `binary_session`.
Repository invariants live in [AGENTS.md](AGENTS.md). Keep provider-specific
protocols in adapters and shared CLI/MCP workflows in the application layer.
## Documentation website
@@ -39,113 +55,104 @@ use `npm run docs:generate`; `docs:build` generates them before building the web
Pull requests run `npm run docs:check`. `.github/workflows/pages.yml` is a
manual VitePress build and does not publish. The public site at
<https://morluto.github.io/rea/> is published only by the manual website
workflow on `main`. The repository's **Settings → Pages → Build and
deployment → Source** must be set to **GitHub Actions** before the first
deployment.
<https://rea.tools/> serves `website/public/` through Cloudflare Workers. See
the [website README](website/README.md#cloudflare-workers) for previews and
manual deployments.
The separate GitHub Pages host uses only the manual
`.github/workflows/website-pages.yml` workflow on `main`. The repository's
**Settings → Pages → Build and deployment → Source** must be set to
**GitHub Actions** before deploying there.
## Development feedback and PR verification
For an ordinary edit, run the relevant regression and cached static checks:
Select checks for the behavior changed. For a source edit:
```bash
npm run test:focused -- src/config.test.ts
npm run check:fast
```
`test:local` selects dirty source tests without building; explicit source test
paths run even on a clean tree. `check:changed` adds source tests affected since
the branch merge base with `origin/main`. Use `npm run test:changed -- --base
REVISION` to choose another base. Changed-test selection follows the import
graph and is feedback, not complete correctness evidence. Inspect relevant
boundary and provider behavior explicitly; see [docs/testing.md](docs/testing.md).
`test:local` runs source tests without building. `check:changed` combines cached
static checks with source tests affected since the merge base with `origin/main`.
Import-graph selection can miss runtime registration, bridges, and generated data;
select relevant boundary tests explicitly. See [testing](docs/testing.md#developer-commands)
for commands, test placement, pruning, and real-provider prerequisites.
Before handing off a PR, run the relevant tests, `npm run check`, and
`npm run docs:check` when contracts or generated metadata change. Record which
checks ran. CI owns complete deterministic tests and aggregate coverage. Use
`npm run check:pr` for a deliberate full local gate on broad changes or when
investigating CI failures; it is not required after each edit, rebase, or push.
Packaging, setup, installation, or distribution changes also require
`npm run verify:package` and `npm pack --dry-run`. Provider behavior changes
require the matching real-provider `verify:*` lane.
Before requesting review, run relevant tests and `npm run check`; add
`npm run docs:check` when contracts or generated metadata change. Record the
checks and unavailable coverage. CI owns the full deterministic suite and
coverage. `npm run check:pr` is an optional full local gate for broad changes or
CI diagnosis. Packaging/setup/distribution changes additionally require
`npm run verify:package` and `npm pack --dry-run`; provider changes require the
matching real-provider lane. State which host/provider workflows ran.
`check:fast` runs cached typecheck and lint, reporting diagnostics on failure.
`check` adds formatting, dead-code, and package-metadata freshness checks.
Formatting uses Oxfmt and the committed `.oxfmtrc.json`; generated sources use
the same configuration. Pre-commit formats and lints staged files; pre-push runs
`check:fast`.
`docs:check` builds and validates generated metadata for the current checkout.
The product catalog (`docs/public/product-catalog.json`), portable managed
conformance projections (`docs/verification/managed-conformance-*.json`), and
packaged skill (`skills/`) are ignored build outputs. Edit skill instructions
and references in `skill-src/`; the build adds catalog-dependent metadata to
the packaged copy without rewriting authored files. The generated manifest
commits to that exact packaged skill bundle. It is a portable projection of
the deterministic managed verifier, not a record of optional real-provider runs.
CI validates these outputs and retains them as artifacts instead of pushing
generated-only commits onto feature branches. Reviewed source metadata such as
`src/generatedPackageMetadata.ts` and `docs/error-contract.schema.json` remains
tracked and checked for freshness. Do not commit ignored generated outputs.
The build-generated product catalog contains documented facts and their provider
identity, rather than full runtime schema hashes. The managed skill contains
instructions and inventory metadata; doctor compares its installed files with
the canonical bundle. Schema-only fixes should not change these outputs or the
skill commitment in the conformance manifest. Runtime schema identity remains
available through doctor and `binary_session`.
Real-provider execution remains uncached; deterministic builds use Turbo.
Pre-commit formats and lints staged files; pre-push runs `check:fast`.
Local `npm test` runs every deterministic Vitest project without coverage or
retries. CI runs four coverage shards and merges JUnit and timing reports.
CI cancels superseded PR runs and skips package, Windows, and full test lanes
for documentation-only PRs. Coverage thresholds remain in `vitest.config.ts`.
### Generated files and command ownership
Tests that need a temporary directory must use
`createTestTempDirectory` from `tests/fixtures/temporaryDirectory.ts`. The
helper binds exact-path, awaited cleanup to the current Vitest case, including
failure and timeout completion. Run `npm run verify:test-temp-hygiene` to build
REA, execute the complete suite under a fresh `TMPDIR`, and reject any remaining
REA-owned temporary path. Never add a glob cleanup for shared `/tmp/rea-*`
content.
`docs:generate` prepares documentation and portable managed evidence;
`evidence:generate` prepares only the managed commitment and its runtime/skill
dependencies. The ignored outputs are `docs/public/product-catalog.json`,
`docs/verification/managed-conformance-*.json`, and `skills/`. Edit authored
skill instructions in `.agents/skills/reverse-engineer-anything/`, where Skills
can discover the public bundle directly from a clean checkout. `verify:package`
installs that bundle with Skills 1.7.2 using default repository-root discovery
and checks every installed file, alongside the packaged setup checks.
CI validates generated outputs and retains them as artifacts; do not commit
them. Reviewed source metadata, including
`src/generatedPackageMetadata.ts` and `docs/error-contract.schema.json`, remains
tracked and checked for freshness.
Set `REA_LOG_LEVEL` to `trace`, `debug`, `info`, `warn`, `error`, `fatal`, or
`silent` to control structured JSON diagnostics. MCP mode defaults to `info` and
always writes logs to stderr so the stdio protocol remains intact. One-shot CLI
logging is opt-in and writes to stdout when a level is configured, preserving
machine-readable command output by default. Request arguments, bridge
authentication tokens, and environment data are redacted.
The packaged skill contains instructions and inventory metadata, not runtime
schema hashes. Its conformance commitment covers that exact bundle and portable
verification; it does not attest optional real-provider runs. Schema-only changes
should not alter that commitment. Doctor and `binary_session` expose runtime
schema identity.
Changes that claim real Hopper behavior must also be tested against the
source-owned, digest-bound conformance manifest. The verifier builds the
platform-native fixtures before starting Hopper:
Build/generation commands hold a SQLite transaction around the entire Turbo
graph, including cache restoration. `.cache/rea-command-locks/` databases identify
locks, not stale files; never remove them while commands run. POSIX cancellation
retains process-group ownership until settlement; Windows waits for completion.
Real-provider execution is uncached.
```bash
npm run verify:hopper
```
### Temporary files and diagnostics
On a self-hosted Linux runner with the setup-installed Xvfb dependencies, use:
Tests use `createTestTempDirectory` from `tests/fixtures/temporaryDirectory.ts`
for exact-path, awaited cleanup, including failures and timeouts.
`npm run verify:test-temp-hygiene` runs the suite under a fresh `TMPDIR` and
rejects remaining REA-owned paths. Never glob-clean shared `/tmp/rea-*` content.
```bash
npm run verify:hopper:linux
```
`REA_LOG_LEVEL` selects `trace`, `debug`, `info`, `warn`, `error`, `fatal`, or
`silent`. Logs go to stderr: MCP defaults to `info`, and one-shot CLI logging
is opt-in, so stdout carries only protocol messages and command results.
Request arguments, bridge tokens, and environment data are redacted from
diagnostic logs.
Set `REA_HOPPER_CONFORMANCE_MANIFEST_PATH` only to verify another source-built
manifest. The normal commands use `build/conformance/manifest.json`; generated
fixtures and manifests remain ignored and must not be committed.
## Real Hopper changes
The macOS and Linux real-Hopper workflows remain separate so a successful mock or package test cannot be reported as platform-runtime proof. Pull requests changing setup, launch, bridge, or Hopper behavior must state which real workflows ran and why either workflow was unavailable.
Run `npm run verify:hopper` on a supported macOS host or
`npm run verify:hopper:linux` on the supported Linux demo runner. These build
native fixtures and verify the installed engine through CLI/MCP; package or
simulated-provider checks do not establish engine behavior. See
[real-toolchain verification](docs/testing.md#end-to-end-integration-and-golden-evidence)
for prerequisites and scope, and [Hopper setup](docs/installation.md#hopper)
for supported hosts and unattended startup.
Describe the behavior change and verification performed in the pull request. Never commit binaries, Hopper documents, credentials, `dist/`, `node_modules/`, or local planning artifacts.
Use the default `build/conformance/manifest.json` unless explicitly verifying
another source-built manifest with `REA_HOPPER_CONFORMANCE_MANIFEST_PATH`.
Generated fixtures and manifests remain ignored.
## Maintainer release checklist
Use the [checkpoint release guide](docs/releasing.md). Releases start from an
explicit `release/VERSION` branch cut at a recorded commit. Manually prepare
the bot PR, wait for its exact-head CI and review, merge into that frozen
branch, and manually publish through the official Release workflow. Main
pushes do not update release PRs or publish packages. Both publishers build
the exact SHA tagged by Release Please.
Use the [release guide](docs/releasing.md). Main pushes automatically refresh a
Release Please PR with the next version and changelog. Review its migration
notes, wait for the current CI checks to pass, and merge it into main to publish.
The Release workflow validates and tags that merge; both publishers build its
exact SHA. Ordinary main pushes cannot publish packages. An optional manual
`release/VERSION` checkpoint retains explicit preparation and publication.
Keep new implementation commits on main for the next release. The workflow
owns packaged-artifact verification, npm publication, the published CLI/MCP
canary, and MCP Registry publication. Sync release metadata back to main after
publication; see the guide for partial-publication recovery and verification.
canary, and MCP Registry publication. Sync manual checkpoint metadata back to
main after publication; see the guide for recovery and verification.
+41 -36
View File
@@ -1,6 +1,6 @@
<div align="center">
**English** · [简体中文](README_zh.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [العربية](README_ar.md)
**English** · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA: Reverse Engineer Anything
@@ -11,14 +11,14 @@
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js 22+](https://img.shields.io/badge/Node.js-22.19%2B-339933?style=flat-square&logo=nodedotjs&logoColor=white)](https://nodejs.org/)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#what-you-can-analyze)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[Website](https://morluto.github.io/rea/) · [Guides](https://morluto.github.io/rea/guides/) · [Showcases](https://morluto.github.io/rea/showcase/)**
**[Website](https://rea.tools/) · [Guides](https://rea.tools/guides/) · [Showcases](https://rea.tools/showcase/)**
[Quick start](#quick-start) · [How REA works](#how-rea-works) · [What you can analyze](#what-you-can-analyze) · [Showcases](#showcases) · [FAQ](#faq) · [Documentation](#documentation)
@@ -28,7 +28,7 @@
<img src="docs/assets/rea-hopper-analysis.png" alt="REA launching its analysis bridge inside Hopper while inspecting a native binary" width="1200" />
<br />
<br /><br />
<table aria-label="REA community">
<tr>
@@ -52,9 +52,9 @@ See a feature in an app that you want in your own product? Ask your agent to inv
REA connects your agent to tools for inspecting native binaries, JavaScript and Electron apps, .NET assemblies, and websites. You can also use the same tools from your terminal. Analysis runs locally, and results include the evidence and limitations behind each conclusion.
Setup registers REA with your agent and installs matching workflow instructions. Native analysis can use an existing Hopper or Ghidra installation; setup can optionally install Hopper with approval. Static JavaScript analysis needs neither engine.
Setup registers REA with your agent and installs matching workflow instructions. Native analysis can use an existing Hopper, Ghidra, or IDA installation; setup can optionally install Hopper with approval. Static JavaScript analysis needs no native analysis engine.
> **[Visit the REA website](https://morluto.github.io/rea/)** for setup instructions, illustrated guides, and real case studies.
> **[Visit the REA website](https://rea.tools/)** for setup instructions, illustrated guides, and real case studies.
## Quick start
@@ -70,7 +70,7 @@ Choose your agents, review the proposed changes, and approve them. Setup adds
REA's MCP server and matching workflow instructions, with backups of existing
configuration. Restart your agent afterward.
Setup supports Claude Code, Codex, Cursor, Gemini CLI and
Setup supports Claude Code, Codex, Cursor, Gemini CLI, Grok Build and
[other agents](docs/installation.md#supported-agents). See
[installation and setup](docs/installation.md) for provider configuration and
manual MCP registration.
@@ -149,15 +149,18 @@ Additional tools and host support depend on the target:
| Target | What REA returns | Requirements and guide |
| ---------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra or IDA; [native analysis](https://morluto.github.io/rea/guides/native/) |
| Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra or IDA; [native analysis](https://rea.tools/guides/native/) |
| Offline ELF layout | Sections, segments, original symbols/relocations and static mitigation candidates | Caller-supplied pwntools on Linux x64; [binary diagnostics](docs/binary-diagnostics.md) |
| EVM bytecode | Dispatch selectors, byte offsets, inferred arguments and mutability | Local raw/hex carrier; [offline EVM guide](docs/evm-bytecode.md) |
| Recorded Linux crashes | Raw notes, every recorded thread's registers/signals and optional mapping candidates | Caller-supplied pwntools; optional GDB/pwndbg; [recorded crashes](docs/recorded-crashes.md) |
| JavaScript / Electron | Modules, imports, source maps, routes, IPC and native add-on relationships | Node.js and npm; [application analysis](https://morluto.github.io/rea/guides/javascript/) |
| Websites | Page structure, scripts, network observations and requested screenshots | A Chrome-family browser; [browser analysis](https://morluto.github.io/rea/guides/browser/) |
| EVM bytecode | Dispatch selectors, byte offsets, inferred arguments and mutability | Local raw/hex carrier on Linux x64; [offline EVM guide](docs/evm-bytecode.md) |
| Recorded Linux crashes | Raw notes, every recorded thread's registers/signals and optional mapping candidates | Caller-supplied pwntools on Linux x64; optional GDB/pwndbg; [recorded crashes](docs/recorded-crashes.md) |
| JavaScript / Electron | Modules, imports, source maps, routes, IPC and native add-on relationships | Node.js and npm; [application analysis](https://rea.tools/guides/javascript/) |
| Websites | Page structure, scripts, network observations and requested screenshots | A Chrome-family browser; [browser analysis](https://rea.tools/guides/browser/) |
| Saved network captures | Requests, responses, exposed payloads and source locations | HAR; mitmdump on Linux for native mitmproxy captures; [capture guide](docs/web-network-captures.md) |
| .NET assemblies | Metadata, CIL instructions, declared native dependencies and build comparisons | Static inspection; [managed-code guide](docs/managed-code-analysis.md) |
| Android APKs | Manifest declarations, classes, decompiled methods and references | Headless JADX and a full JDK on Linux/macOS; [Android guide](docs/android-analysis.md) |
| .NET assemblies | Metadata, CIL instructions, declared native dependencies and build comparisons | None (static only); [managed-code guide](docs/managed-code-analysis.md) |
| Android APKs | Manifest declarations, classes, decompiled methods and references | Headless JADX and a full JDK on Linux/macOS/Windows x64; [Android guide](docs/android-analysis.md) |
| Android devices | Devices, packages, processes, logs, dumps, screen captures, and APK/file transfers | Caller-supplied adb (emulator or hardware); [ADB guide](docs/adb-device-analysis.md) |
| JEB projects | Engine-backed project units, artifact digests and type/method pseudo-code | A caller-started JEB client serving MCP, selected with REA_JEB_MCP_URL; [JEB guide](docs/jeb-analysis.md) |
| Android resources | Decoded manifest, string tables, locales and version facts | Caller-supplied Apktool launcher; [resource guide](docs/apktool-resource-analysis.md) |
| Firmware | Regions, extraction results and native-analysis handoffs | Binwalk / Unblob on Linux; [firmware guide](docs/firmware-analysis.md) |
| Packages and resources | File inventories, digests, plists, Apple bundle anatomy and extracted resources | [Artifact and JavaScript guide](docs/javascript-artifact-reconstruction.md), [Apple applications](docs/apple-application-analysis.md) |
| Process behavior | Terminal output, interactions, exit and filesystem observations, and run comparisons | Linux/macOS with a native PTY; [process capture](docs/process-capture.md) |
@@ -173,19 +176,23 @@ Native formats and host support vary by provider. See
[IDA guide](docs/ida-provider.md), and
[experimental Windows Ghidra support](docs/windows-ghidra-p0.md).
Ghidra also supports [16-bit DOS analysis](docs/ghidra-dos.md).
For large binaries, raise its startup deadline with
`REA_GHIDRA_STARTUP_TIMEOUT_MS`.
For provider selection, see the [CLI guide](docs/cli.md#choose-a-provider).
Check [release availability](docs/installation.md#released-package-and-main)
for features added since the latest npm release.
## Showcases
[![Illustrations of the DX-Ball sound-pan, Notion clipboard-bridge, and TH04 bullet-ring showcases](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: reconstruct a sound-pan calculation
Follow a sound call into its position-to-pan helper, inspect the instructions,
and turn incomplete pseudocode into C. The reconstruction passes 3,205
original-x86 cases and reproduces all 63 compiled function bytes.
[Read the case study](https://morluto.github.io/rea/showcase/dx-ball/) ·
[Read the case study](https://rea.tools/showcase/dx-ball/) ·
[Reconstruction repository](https://github.com/N0zoM1z0/dx-ball)
### Notion: trace the Electron clipboard bridge
@@ -193,7 +200,7 @@ original-x86 cases and reproduces all 63 compiled function bytes.
Find the renderer's clipboard API, follow it through preload and IPC into the
main process, and inspect the rich clipboard format.
[Read the case study](https://morluto.github.io/rea/showcase/notion/)
[Read the case study](https://rea.tools/showcase/notion/)
### TH04: recover a DOS bullet-ring calculation
@@ -201,7 +208,7 @@ Inspect the original PC-98 game's 16-bit instructions, recover the fixed and
aimed angle calculations, and compare the reconstructed C++ with the
historical compiler output.
[Read the case study](https://morluto.github.io/rea/showcase/th04/) ·
[Read the case study](https://rea.tools/showcase/th04/) ·
[Reconstruction repository](https://github.com/N0zoM1z0/th04)
If you've used REA on something interesting, we'd love to see it. Share your
@@ -241,7 +248,7 @@ ask you to choose demo mode or activate your license. See
<details>
<summary><strong>What does installing the skill from skills.sh do?</strong></summary>
The skill supplies investigation instructions for your agent. Use `rea setup`
The skill supplies investigation instructions for your agent. Use `npx rea-agents setup`
to register REA's MCP server and install the matching instructions, then restart
your agent. See [skill-only installation](docs/installation.md#skill-only-installation).
@@ -289,37 +296,23 @@ with your REA version, target type, steps to reproduce and error output.
## Documentation
Start with the website's [worked guides](https://morluto.github.io/rea/guides/).
Start with the website's [worked guides](https://rea.tools/guides/).
For exact options, prerequisites and result contracts:
- [Installation and setup](docs/installation.md): agent registration, provider configuration, updates and uninstall.
- [Readiness and troubleshooting](docs/installation.md#check-readiness-for-your-task): diagnose one agent or analysis engine.
- [CLI and Evidence](docs/cli.md): commands, provider selection, snapshots, import/export and exit statuses.
- [MCP contracts](docs/mcp-contracts.md) and [agent prompts](docs/mcp-prompts.md): tool results, sessions and guided investigations.
- [Tool catalog](docs/mcp-contracts.md#generated-catalog): build-generated inventory of tools, providers and CLI commands.
- [Tool catalog](docs/mcp-contracts.md#generated-catalog): generated inventory of tools, providers and CLI commands.
- [Roadmap](docs/roadmap.md): planned work and capability trackers.
Report vulnerabilities through [SECURITY.md](SECURITY.md).
## Contributing
We'd love your help with REA! [Open an issue](https://github.com/morluto/rea/issues) to
report a bug or suggest a feature, or [send a pull request](https://github.com/morluto/rea/pulls)
to improve the code or docs.
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and checks,
[testing](docs/testing.md) for verification lanes, and the
[architecture map](docs/architecture.mermaid) for the project structure.
## Project links
[Website](https://morluto.github.io/rea/) · [npm](https://www.npmjs.com/package/rea-agents) · [skills.sh](https://skills.sh/morluto/rea/reverse-engineer-anything) · [Issues](https://github.com/morluto/rea/issues) · [Security](SECURITY.md)
## Star history
🎉 **20,000 GitHub stars — thank you!**
🎉 **60,000 GitHub stars — thank you!**
Thanks to everyone using REA, reporting bugs, testing builds, and contributing fixes.
Thanks to everyone using REA, reporting bugs, requesting features, testing builds, and contributing fixes.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
@@ -333,6 +326,18 @@ Thanks to everyone using REA, reporting bugs, testing builds, and contributing f
REA provides tools for lawful reverse-engineering research, analysis, and reconstruction. You are responsible for obtaining any required authorization and complying with applicable laws. The project does not endorse illegal or unauthorized use.
REA is an open-source software project. We have not issued or endorsed any cryptocurrency or token. Tokens using the REA name are not affiliated with the project.
## Contributing
We'd love your help with REA! [Open an issue](https://github.com/morluto/rea/issues) to
report a bug or suggest a feature, or [send a pull request](https://github.com/morluto/rea/pulls)
to improve the code or docs.
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and checks,
[testing](docs/testing.md) for verification lanes, and the
[architecture map](docs/architecture.mermaid) for the project structure.
## License
[MIT](LICENSE)
+175 -242
View File
@@ -1,355 +1,288 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · **العربية**
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · **العربية** · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA: اعكس هندسة أي شيء
# REA: هندسة عكسية لأي شيء
### وسيط MCP واحد للهندسة العكسية عبر الملفات التنفيذية والتطبيقات وسلوك وقت التشغيل.
### خادم MCP واحد للهندسة العكسية للملفات الثنائية والتطبيقات والسلوك أثناء التشغيل.
**اعثر على ميزة تعجبك. افهم آلية عملها. ابنها بالطريقة التي تريدها.**
**وجدت ميزة تعجبك؟ افهم طريقة عملها حتى مستوى الشيفرة الثنائية.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](#منصة-أدوات-التحقيق)
[![Node.js 22+](https://img.shields.io/badge/Node.js-22.19%2B-339933?style=flat-square&logo=nodedotjs&logoColor=white)](https://nodejs.org/)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[الموقع (بالإنجليزية)](https://morluto.github.io/rea/) · [أدلة الاستخدام](https://morluto.github.io/rea/guides/) · [دراسة حالة DX-Ball](https://morluto.github.io/rea/showcase/dx-ball/)**
**[الموقع](https://rea.tools/) · [الأدلة](https://rea.tools/guides/) · [دراسات الحالة](https://rea.tools/showcase/)**
[البدء السريع](#البدء-السريع) · [حالة الدعم](#حالة-الدعم) · [من الملف التنفيذي إلى السلوك](#من-الملف-التنفيذي-إلى-السلوك) · [منصة أدوات التحقيق](#منصة-أدوات-التحقيق) · [خطة العمل](#خطة-العمل) · [كيف يعمل؟](#كيف-يعمل)
[البدء السريع](#البدء-السريع) · [كيف يعمل REA](#كيف-يعمل-rea) · [ما الذي يمكنك تحليله](#ما-الذي-يمكنك-تحليله) · [دراسات الحالة](#دراسات-الحالة) · [الأسئلة الشائعة](#الأسئلة-الشائعة) · [التوثيق](#التوثيق)
<table aria-label="REA community">
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA يشغّل جسر التحليل داخل Hopper لفحص ملف ثنائي للشيفرة الأصلية" width="1200" />
<br /><br />
<table aria-label="مجتمع REA">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>انضم إلى مجتمع الهندسة العكسية</strong>
</a><br />
<sub>Discord · أسئلة وأجوبة · شارك أعمالك</sub>
<sub>Discord · أسئلة وأجوبة · مشاركة النتائج</sub>
</td>
</tr>
</table>
<br />
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA يشغّل جسر التحليل داخل Hopper لفحص ملف تنفيذي أصلي" width="1200" />
</div>
---
هل وجدت في تطبيق ميزة تريدها في منتجك؟ اطلب من وكيلك استقصاءها باستخدام REA. يستطيع فحص التطبيق من دون شيفرته المصدرية، وشرح طريقة عمل الميزة وعرض الأدلة، ثم بناء نسخة تناسب مشروعك.
هل وجدت في تطبيق ميزة تريد إضافتها إلى منتجك؟ اطلب من وكيلك استقصاءها باستخدام REA. يستطيع فحص التطبيق من دون شيفرته المصدرية، وشرح طريقة عمل الميزة وعرض الأدلة، ثم بناء نسخة تناسب مشروعك.
يوفر REA أدوات لتحليل الملفات التنفيذية الأصلية وتطبيقات JavaScript وElectron وتجميعات .NET والمواقع. يمكنك استخدامها من وكيلك أو من الطرفية. يعمل التحليل محليًا، وتتضمن النتائج الأدلة والقيود.
يربط REA وكيلك بأدوات لفحص الملفات الثنائية للشيفرة الأصلية، وتطبيقات JavaScript وElectron، وتجميعات .NET، والمواقع. يمكنك أيضًا استخدام الأدوات نفسها من الطرفية. يجري التحليل محليًا، وتتضمن النتائج الأدلة والقيود التي تستند إليها كل خلاصة.
يضبط Setup إعدادات الوكيل ويربطه بتثبيت موجود من Hopper أو Ghidra، ويثبّت سير عمل REA الموجّه. ويمكنه تثبيت Hopper بعد موافقتك. ولا يحتاج التحليل الثابت لتطبيقات JavaScript إلى أي محرك.
يسجّل الإعداد REA لدى وكيلك ويثبّت تعليمات سير العمل المطابقة. يمكن لتحليل الشيفرة الأصلية استخدام تثبيت موجود من Hopper أو Ghidra؛ ويمكن للإعداد أيضًا تثبيت Hopper اختياريًا بعد موافقتك. لا يحتاج التحليل الثابت لـ JavaScript إلى أي من المحركين.
## اطلب من وكيلك مباشرة
بعد [الإعداد](#البدء-السريع)، أعد تشغيل الوكيل ثم اطلب:
```text
استقصِ طريقة عمل البحث في تطبيق Notes، واعرض الأدلة، ثم ابنِ ميزة مشابهة لمشروعي.
```
استبدل Notes بالتطبيق الذي تريد فهمه، أو اطلب نظرة عامة أولًا.
## من الملف التنفيذي إلى السلوك
| فك الترجمة | الفهم | إعادة الإنشاء |
| ---------------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------ |
| استخرج الشيفرة شبه المصدرية، والتعليمات، والسلاسل النصية، والرموز | تتبع تدفق التحكم والمراجع المتبادلة والاستدعاءات والأنواع | حوّل ما تعلمه الوكيل إلى ميزة تناسب تقنياتك وواجهتك ومتطلباتك |
يوضح REA كيف وصل إلى نتائجه. وهو لا يدّعي استعادة الشيفرة المصدرية الأصلية أو استنساخ التطبيق تلقائيًا.
## لماذا REA؟
| | |
| ------------------------ | ---------------------------------------------------------------------------- |
| **مصمم للوكلاء** | اسأل عما يفعله التطبيق ودع الوكيل يفحصه بدلًا من التخمين. |
| **CLI وMCP** | استخدم قدرات الهندسة العكسية نفسها من الطرفية أو الوكيل. |
| **إعداد موجّه** | اضبط وكيلك، واربط أداة تحليل موجودة، أو ثبّت Hopper بموافقتك. |
| **من الفهم إلى الشيفرة** | افهم الميزة ثم ابنِ نسختك الخاصة في جلسة البرمجة نفسها. |
| **محلي حسب التصميم** | يجري التحليل على مضيفك المحلي المدعوم، ولا يرفع REA التطبيق إلى خدمة مستضافة. |
| **يحافظ على السياق** | استقصِ عدة تطبيقات دون بدء التحليل من جديد عند كل سؤال. |
> **[زر موقع REA](https://rea.tools/)** للاطلاع على تعليمات الإعداد والأدلة المصوّرة ودراسات الحالة الفعلية.
## البدء السريع
### تشغيل الإعداد (موصى به)
### إعداد وكيلك
اربط REA بوكيلك:
بعد تثبيت Node.js وnpm، نفّذ:
```bash
npx rea-agents setup
```
يعرض Setup أولاً قائمة متعددة الاختيار للوكلاء الذين تريد ربطهم. تكون تسجيلات REA الموجودة محددة افتراضياً، ولا يؤدي اكتشاف عميل جديد وحده إلى تحديده؛ ويمكنك اختيار عميل غير مهيأ. راجع المسارات والتغييرات المحددة قبل الموافقة. يثبت Setup سير عمل REA للوكلاء المحددين افتراضياً. Hopper خيار منفصل يتطلب موافقة مستقلة، ويمكن أيضاً حفظ مسارات تثبيت Ghidra الموجودة.
اختر الوكلاء، وراجع التغييرات المقترحة، ثم وافق عليها. يضيف الإعداد خادم MCP الخاص بـ REA وتعليمات سير العمل المطابقة، مع الاحتفاظ بنسخ احتياطية من الإعدادات الموجودة. أعد تشغيل وكيلك بعد ذلك.
يعرض التغييرات قبل تطبيقها وينشئ نسخة احتياطية من الإعدادات الموجودة. راجع [دليل التثبيت والإعداد](docs/installation.md) للمتطلبات والخيارات الإضافية.
يدعم الإعداد Claude Code وCodex وCursor وGemini CLI وGrok Build و[وكلاء آخرين](docs/installation.md#supported-agents). راجع [التثبيت والإعداد](docs/installation.md) لتهيئة موفّري التحليل وتسجيل MCP يدويًا.
### الاستخدام مع وكيل
### اطلب من وكيلك
بعد الإعداد، أعد تشغيل الوكيل واشرح التطبيق أو الميزة التي تريد استقصاءها. يدعم REA Claude Code وClaude Desktop وCodex وCursor وGemini CLI وWindsurf وDevin وOpenCode وAntigravity وGitHub Copilot CLI وCommand Code وVS Code. تكون تسجيلات REA الموجودة محددة افتراضياً، ويجب اختيار العملاء المكتشفين الآخرين يدوياً. يمكن للوكلاء الآخرين استخدام إعداد MCP أدناه.
يمكن تشغيل Hopper في الوضع التجريبي. إذا ظهرت رسالة عند التشغيل الأول، فاختر التجربة أو أدخل ترخيصًا موجودًا.
### مهارة مساعد البرمجة (اختياري)
أضف المهارة إلى مساعد البرمجة للحصول على سياق أغنى:
```bash
npx skills add morluto/rea --skill reverse-engineer-anything
```text
استقصِ طريقة عمل البحث في تطبيق Notes، واعرض الأدلة، ثم ابنِ ميزة مشابهة لمشروعي.
```
توفر المهارة سير عمل التحقيق في REA. نفّذ الإعداد أعلاه لربط REA بالوكيل وضبط أدوات التحليل. يثبّت الإعداد افتراضيًا مهارة مطابقة للإصدار؛ وهذا الأمر يثبّت نسخة المستودع.
استبدل Notes بالتطبيق المستهدف وحدّد الميزة التي تريد فهمها.
لشجرة JavaScript/Electron المستخرجة أو ملف ASAR، لا يلزم إعداد MCP ولا محرك أصلي:
### استخدام الطرفية
افحص مجلد تطبيق JavaScript/Electron بعد فك حزمه، أو ملف ASAR:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
استبدل المسار بهدفك (مثل `"D:/apps/example"` على Windows). يدعم سير العمل الثابت هذه المسارات، بينما يتطلب التحليل الأصلي محركه الخاص.
تتضمن النتيجة الوحدات وعمليات الاستيراد وحدود Electron والأدلة المتعلقة بها. استبدل المسار بمسار هدفك، مثل `"D:/apps/example"` على Windows.
### تثبيت أمر rea
ثبت واجهة سطر الأوامر:
```bash
curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash
```
يجب تثبيت Node.js وnpm مسبقًا. عند تشغيله من طرفية، يثبت البرنامج `rea` ويبدأ الإعداد.
يمكنك بدلًا من ذلك التثبيت باستخدام npm ثم تشغيل الإعداد:
لتثبيت أمر `rea` للاستخدام المعتاد:
```bash
npm install --global rea-agents
rea setup
rea --help
```
### المتطلبات
لتحليل الشيفرة الأصلية، هيّئ موفّرًا أولًا. راجع [دليل CLI وEvidence](docs/cli.md) لأوامر تحليل الشيفرة الأصلية، واختيار الموفّر، واللقطات، والاستخدام في السكربتات.
- macOS 12 أو أحدث
- Ubuntu 24.04+ أو Fedora 41+ أو Arch Linux بنواة 64 بت أو CachyOS
- Node.js 22.x (>=22.19) أو 24.x (>=24.11) أو 26+ وnpm
### تحديث REA
يتطلب تحليل الملفات التنفيذية الأصلية Hopper أو Ghidra. Hopper برنامج منفصل، وللوضع التجريبي قيود يحددها المورّد، لكن الترخيص المدفوع ليس إلزاميًا.
يتطور REA بسرعة، وتتضمن الإصدارات الجديدة إصلاحات متكررة للأخطاء. حافظ على تحديث نسختك.
يدعم Ghidra نظامي Linux x64 وmacOS x64/arm64. ثبت Ghidra 12.1.x وJDK الكامل بنواة 64 بت الذي يعلنه ذلك التثبيت (`application.java.min` حتى `application.java.max`) بصورة منفصلة، ثم اضبط REA لاستخدامهما. تتطلب إصدارات 12.1 الحالية JDK 21 أو أحدث ولا تحدد حدًا أعلى. جرى التحقق من الجسر مع Ghidra 12.1.4 وJDK 21. يحتاج macOS أيضًا إلى أداة فك الترجمة الأصلية المطابقة لمعمارية الجهاز.
يستطيع Setup التحقق من التثبيت وحفظ المسارات؛ ولا يثبت أو يحدّث Ghidra أو Java أو Node.js أو npm أو Homebrew.
يتضمن فرع main والحزمة npm 4.1.0 دعمًا تجريبيًا لـ Windows x64 Ghidra P0 لتطبيقات PE الأصلية x86-64 (غير المُدارة وغير DLL) على NTFS محلي، مع ضوابط Job Object وقوائم DACL الخاصة وقبول المسارات المجمّعة. تحقق من [حد الإصدار](docs/installation.md#released-package-and-main) قبل توقع ذلك من حزمة npm أقدم. راجع [دليل Windows Ghidra P0](docs/windows-ghidra-p0.md) للمتطلبات والنطاق الموثق.
### تشخيص المشكلات
يشخّص `npx -y rea-agents@latest doctor` الجهاز والاعتماديات وأدوات التحليل وإعدادات الوكيل من دون تغييرها. أضف `--json` للحصول على تشخيص منظم.
على Linux، يفضّل REA الملف التنفيذي `/opt/hopper/bin/Hopper`، وإذا لم يكن متاحًا يتحقق تلقائيًا من `~/.local/share/rea/hopper/bin/Hopper`. استخدم `HOPPER_LAUNCHER_PATH` للمسارات الأخرى. إذا كان الملف موجودًا لكن محرك التحليل لا يظهر، فشغّل `ldd /absolute/path/to/Hopper | grep 'not found'` على مسار Hopper الفعلي للتحقق من المكتبات الناقصة. راجع [دليل Hopper](docs/installation.md#hopper).
### التحديث والإزالة
- يحدّث `rea update` تثبيت REA الحالي.
- يزيل `rea uninstall` تسجيلات الوكلاء وملفات سير العمل التي يديرها REA، ويترك Hopper مثبتًا.
- يزيل `rea uninstall --purge-data` أيضًا ذاكرة REA المؤقتة وحالته. استخدمه فقط إذا أردت حذف هذه البيانات.
## حالة الدعم
تُوصف قدرات المستودع الحالية ومتطلبات الأنظمة في [دليل الدعم الإنجليزي](README.md#current-status). قد يسبق فرع main [إصدار npm](docs/installation.md#released-package-and-main).
- يوفر Ghidra 25 عملية للقراءة فقط على Linux x64 وmacOS x64/arm64 وحدود Windows x64 P0 التجريبية. يدعم Linux/macOS أيضًا تعليقات الدوال الذرية على مستوى الجلسة. نظام Windows P0 للقراءة فقط، ولا يوفر Ghidra أي تحكم في الواجهة.
- يتطلب الفحص الثابت لنظام Android تجهيز JADX/Java بشكل منفصل؛ ويغطي التحقق بالموفر الحقيقي نظام Linux. راجع [تحليل Android](docs/android-analysis.md).
- تحدد طلبات المتصفح وElectron والعمليات هدفها وإجراءاتها ودورة حياتها مباشرة، وتعتمد على وصول المضيف الفعلي دون منح أذونات منفصلة من REA. ما زالت كتابة إعدادات Setup وتثبيت Hopper تتطلب الموافقة على خطتها الدقيقة.
- يصف `rea capabilities` عمليات جلسة الملف التنفيذي لا كل أدوات التطبيقات ووقت التشغيل. راجع قائمة أدوات MCP الكاملة والدليل ذا الصلة.
## استقصاء كامل بطلب واحد
بعد الإعداد، يمكنك أن تطلب من وكيلك:
> افتح التطبيق، واكتشف آلية عمل البحث من دون اتصال، واشرح تدفق التحكم، ثم ابنِ نسخة لمشروعي باستخدام TypeScript وSQLite.
يمكن للوكيل تحويل ذلك إلى سير عمل قابل للتحقق:
```text
فتح الهدف
→ انتظار اكتمال تحليل Hopper
→ جرد المعماريات والرموز والسلاسل النصية
→ تحديد نقاط الدخول والدوال المهمة
→ تتبع الاستدعاءات والمراجع المتبادلة وتدفق التحكم
→ فك ترجمة التنفيذ ذي الصلة
→ تلخيص السلوك والقيود والحالات الطرفية
→ بناء الميزة بما يلائم تقنيات المشروع ومتطلباته
```
## ما الذي يمكنك فعله؟
### فهم تطبيق لا تملك مصدره
اكشف نقاط الدخول، وأسماء الفئات، والسلاسل النصية، والأطر المستخدمة، ومسارات الميزات من الملف التنفيذي وحده.
### بناء ميزة تعجبك بطريقتك
استقصِ الميزة، وافهم سلوكها، ثم ابنِ نسخة ملائمة لمنتجك وتقنياتك ومتطلباتك.
### توثيق بروتوكول أو تنسيق غير موثق
تتبع الموزعات، والثوابت، والمقارنات، والقراءة والكتابة لفهم الرسائل وتنسيقات الملفات وآلات الحالات.
### إعادة إنشاء سلوك متوافق
حوّل منطقًا مفكوك الترجمة إلى مواصفات واضحة، ثم نفذ بديلًا نظيفًا تحكمه اختبارات السلوك الملحوظ.
### تدقيق منطق أمني حساس
افحص التحقق من الإدخال، والتشفير، والصلاحيات، والتخزين، ومسارات الأخطاء من دون رفع الملف التنفيذي إلى خدمة بعيدة.
## منصة أدوات التحقيق
| عائلة الأدوات | العدد | الاستخدام |
| ---------------------- | ----: | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| الفحص الأصلي | 41 | الدوال والشيفرة شبه المصدرية والتعليمات والسلاسل والرموز والاستدعاءات والمراجع والتعليقات وقراءة البايتات ومواضع الملفات |
| سير عمل التحقيق | 14 | نظرات عامة على التطبيقات وملفات الدوال وواجهات API الأصلية والتوزيع وفك الترجمة الدفعي وتتبع الميزات ومسارات الاستدعاء ومخططاته واكتشاف Swift وObjective-C |
| أدوات الملفات الثنائية | 10 | بيانات Mach-O والتوقيعات وplist والمعماريات وأسماء Swift ومراقبة الاستدعاءات عبر LLDB على macOS؛ تخطيط ELF وأدلة الحماية الثابتة وسجلات الأعطال على Linux |
| مخطط المخرجات | 7 | جرد الدلائل والحزم وملفات Interface Builder المترجمة وكتالوجات موارد Apple وتحليل تحميل Mach-O dylib والاستخراج واستدلال واجهات EVM دون اتصال |
| PE/CLI المُدار | 7 | هوية تجميعات .NET وبياناتها الوصفية وتعليمات CIL والاعتماديات الأصلية واستيراد إعادة البناء ومقارنة الإصدارات |
| البرامج الثابتة | 2 | فحص مناطق البرامج الثابتة على Linux واستخراجها الصريح |
| Android APK | 5 | بيانات الحزمة وmanifest والبحث عن الأصناف وقوائم الأعضاء وفك ترجمة الأساليب والمراجع الثابتة |
| مراقبة المتصفح | 12 | بنية الصفحات وبيانات الشبكة والبرامج النصية وخرائط المصدر واكتشاف WebMCP والصور ومقارنة الالتقاط |
| تحليل Electron | 5 | مراقبة العارضين وخريطة التطبيق الثابتة والمواءمة بين نتائج الثبات والتشغيل |
| وقت تشغيل JavaScript | 2 | اكتشاف أهداف Node/Electron Inspector ومواضع البرامج وأحداث سياقات التنفيذ |
| سير عمل التطبيقات | 13 | تصدير النصوص البرمجية الملتقطة، تتبع الميزات عبر الطبقات ومقارنة الإصدارات ومواءمة المصدر التاريخي ومقارنة أشكال القيم المعادة والتحقق من إعادة الإنشاء |
| مساحة العمل والملاحظة | 21 | الجلسات وحزم الأدلة وسياق التنقل ومقارنة العمليات والمخرجات والدوال وتسجيل الأسئلة غير المحسومة |
## خطة العمل
يشمل العمل التالي توسيع التحقق من الأهداف الأصلية، ومقارنة إصدارات JavaScript و.NET، ومراقبة وقت التشغيل والتحقق من إعادة الإنشاء. يتيح Setup بالفعل اختيار تكامل الوكيل وتثبيت Hopper. تثبيت أدوات تحليل أخرى ما زال عملًا لاحقًا. راجع [خطة التثبيت](docs/roadmap.md) و[تقييم أدوات التحليل](docs/provider-evaluation.md).
## استخدام REA مع وكلاء برمجة آخرين
يدعم Setup Claude Code وClaude Desktop وCodex وCursor وGemini CLI وWindsurf وDevin وOpenCode وAntigravity وGitHub Copilot CLI وCommand Code وVS Code. تكون تسجيلات REA الموجودة محددة افتراضياً، ويجب اختيار العملاء المكتشفين الآخرين يدوياً. يمكن لأي وكيل يدعم خوادم MCP المحلية الاتصال باستخدام الإعداد التالي:
<!-- x-release-please-start-version -->
```json
{
"mcpServers": {
"rea": {
"command": "npx",
"args": ["-y", "rea-agents@6.0.0", "mcp"]
}
}
}
```
<!-- x-release-please-end -->
## كيف يعمل؟
```mermaid
flowchart LR
Human[المستخدم] --> Agent[وكيل البرمجة]
Agent --> REA[REA]
Human -->|CLI| REA
REA --> Hopper[عمليات تحليل Hopper]
Hopper --> App[تطبيقك]
REA --> Ghidra[تحليل Ghidra للقراءة فقط<br/>جرد + تحليل الدوال]
Ghidra --> App
```
يستخدم CLI وخادم MCP سير عمل التحليل نفسه. تحرر أوامر الطرفية جلسة الجسر الخاصة بها عند انتهائها، بينما يمكن لجلسة الوكيل الحفاظ على الاتصال أثناء الاستقصاء. إغلاق جلسة REA لا يغلق تطبيق Hopper الذي يستخدمه المستخدم.
## أوامر CLI
سير عمل الوكيل أعلاه هو أسهل طريقة لاستخدام REA. للحصول على نظرة سريعة على تطبيق من الطرفية:
لواجهة CLI المثبّتة عبر npm:
```bash
npx -y rea-agents@latest analyze /Applications/Notes.app
npx -y rea-agents@latest compare /absolute/path/to/left-evidence.json /absolute/path/to/right-evidence.json
rea update
```
شغّل `npx -y rea-agents@latest --help` لمعرفة خيارات فك الترجمة المباشر والخيارات الأخرى.
لتحديث تسجيلات الوكلاء والمهارة، نفّذ أمر الإعداد الذي يعرضه التحديث.
يمكن لـ REA فتح مجلد `.app` على Mac مباشرة. إذا لم يعثر الوكيل على التطبيق، فأخبره بمكان تثبيته.
إذا كنت تستخدم `npx`، فحدّث إعداد وكيلك بالأمر التالي:
## سلوك Hopper
```bash
npx rea-agents@latest setup
```
يشغّل REA برنامج Hopper عند الحاجة. على macOS قد تظهر نافذته في المقدمة أو يحتاج أحد الحوارات إلى استجابة منك. لا يمكن ضمان بقاء النافذة في الخلفية.
راجع تغييرات الإعداد وأعد تشغيل وكيلك. لأوامر CLI التي تنفّذها مرة واحدة، استخدم `npx rea-agents@latest` متبوعًا بالأمر المطلوب.
يحدد REA تنسيق الهدف ومعماريته لتجنب حوارات الاختيار المعتادة. عند إغلاق الجلسة، يوقف الجسر وينظف موارده الخاصة، لكنه لا يغلق تطبيق Hopper الذي تستخدمه.
## كيف يعمل REA
## الأمان والخصوصية
يستدعي وكيلك REA عبر MCP لفحص الهدف وتتبع الشيفرة ذات الصلة. يعيد REA النتائج مع أدلتها. يستخدمها الوكيل لطرح أسئلة متابعة، أو شرح السلوك، أو كتابة تنفيذ واختباره. تستخدم أوامر CLI سير العمل نفسه.
- يبقى التحليل محليًا بين REA وموفر التحليل المختار عبر مقابس محلية خاصة، ومع IDA عبر تسجيل MCP المحلي المضبوط.
- لا يرفع REA الأهداف إلى خدمة مستضافة.
- تعمل أدوات التحليل والأهداف المطلقة بصلاحيات المستخدم نفسه؛ وما زال التقاط واجهة النظام على macOS يعتمد على الوصول إلى تسهيلات الاستخدام وتسجيل الشاشة. ولا ينفّذ التحليل الثابت للـ JavaScript الوحدات المستخرجة.
- تستخدم جلسات Ghidra مشروعًا مؤقتًا معزولًا ولا تفتح مشاريع Ghidra التي يملكها المستخدم أو تعدّلها.
- راجع الملفات التنفيذية غير الموثوقة واعزلها كما تفعل مع أي مدخل أصلي قد يكون ضارًا.
- أبلغ عن الثغرات وفق [سياسة الأمان](SECURITY.md)، وليس عبر قضية عامة.
![مسار الاستقصاء في REA: يسأل وكيلك عن هدف محلي، ويفحصه REA ويتتبعه بأدوات التحليل، ثم يستخدم الوكيل الشيفرة والمراجع والجوانب غير المحسومة التي أعادتها الأدوات لشرح السلوك وتنفيذه واختباره.](website/public/assets/figures/rea-investigation-flow.svg)
[افتح الشكل بحجمه الكامل](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## ما الذي يمكنك تحليله
يتطلب REA إصدار Node.js 22.x (>=22.19) أو 24.x (>=24.11) أو 26+، إضافة إلى npm. تعتمد الأدوات الإضافية والأنظمة المضيفة المدعومة على الهدف:
| الهدف | ما يعيده REA | المتطلبات والدليل |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| الملفات الثنائية للشيفرة الأصلية | شيفرة شبه برمجية، وتعليمات تجميع، وسلاسل نصية، ورموز، واستدعاءات، ومراجع | Hopper أو Ghidra أو IDA؛ [تحليل الشيفرة الأصلية](https://rea.tools/guides/native/) |
| بنية ELF دون تشغيل | الأقسام والمقاطع والرموز ومعلومات إعادة التموضع الأصلية، وآليات الحماية المحتملة المستدلّ عليها بالفحص الثابت | pwntools يوفّره المستدعي على Linux x64؛ [تشخيص الملفات الثنائية](docs/binary-diagnostics.md) |
| شيفرة EVM البايتية | محددات التوجيه، وإزاحات البايتات، والمعاملات المستنتجة، وقابلية تغيير الحالة | مدخل محلي يحمل بايتات خامًا أو تمثيلًا سداسيًا عشريًا على Linux x64؛ [دليل EVM دون تشغيل](docs/evm-bytecode.md) |
| أعطال Linux المسجّلة | سجلات note الخام، ومسجّلات المعالج/الإشارات لكل خيط مسجّل، وترشيحات اختيارية لخرائط الذاكرة | pwntools يوفّره المستدعي على Linux x64؛ GDB/pwndbg اختياريان؛ [الأعطال المسجّلة](docs/recorded-crashes.md) |
| JavaScript / Electron | الوحدات، وعمليات الاستيراد، وخرائط المصدر، والمسارات، وIPC، وعلاقات إضافات الشيفرة الأصلية | Node.js وnpm؛ [تحليل التطبيقات](https://rea.tools/guides/javascript/) |
| المواقع | بنية الصفحة، والسكربتات، وملاحظات الشبكة، ولقطات الشاشة المطلوبة | متصفح من عائلة Chrome؛ [تحليل المتصفح](https://rea.tools/guides/browser/) |
| تسجيلات الشبكة المحفوظة | الطلبات، والاستجابات، ومحتويات الحمولة المتاحة، ومواضعها في المصدر | HAR؛ وmitmdump على Linux لتسجيلات mitmproxy بصيغتها الأصلية؛ [دليل تسجيلات الشبكة](docs/web-network-captures.md) |
| تجميعات .NET | البيانات الوصفية، وتعليمات CIL، واعتماديات الشيفرة الأصلية المعلنة، ومقارنات البناء | فحص ثابت؛ [دليل الشيفرة المُدارة](docs/managed-code-analysis.md) |
| حزم Android APK | تصريحات ملف manifest، والأصناف، والدوال الناتجة عن فك الترجمة، والمراجع | JADX دون واجهة رسومية وJDK كامل على Linux/macOS/Windows x64؛ [دليل Android](docs/android-analysis.md) |
| أجهزة Android | الأجهزة والحزم والعمليات والسجلات والدامبات ولقطات الشاشة ونقل APK/الملفات | adb يوفّره المُستدعي (محاكي أو جهاز)؛ [دليل ADB](docs/adb-device-analysis.md) |
| مشاريع JEB | وحدات المشروع من المحرك وبصمات المصنّفات والكود الزائف للأنواع/الدوال | عميل JEB يبدأه المُستدعي ويقدّم MCP، ويُختار عبر REA_JEB_MCP_URL؛ [دليل JEB](docs/jeb-analysis.md) |
| موارد Android | البيان المفكوك الترميز وجداول السلاسل واللغات وحقائق الإصدار | مُشغّل Apktool يوفّره المُستدعي؛ [دليل الموارد](docs/apktool-resource-analysis.md) |
| البرامج الثابتة | المناطق، ونتائج الاستخراج، وما يُمرّر إلى تحليل الشيفرة الأصلية | Binwalk / Unblob على Linux؛ [دليل البرامج الثابتة](docs/firmware-analysis.md) |
| الحزم والموارد | قوائم الملفات، والبصمات، وملفات plist، وبنية حزم Apple، والموارد المستخرجة | [دليل تحليل الملفات وJavaScript](docs/javascript-artifact-reconstruction.md)، [تطبيقات Apple](docs/apple-application-analysis.md) |
| سلوك العمليات | مخرجات الطرفية، والتفاعلات، وملاحظات الخروج ونظام الملفات، ومقارنات التشغيل | Linux/macOS مع PTY أصلي؛ [تسجيل سلوك العمليات](docs/process-capture.md) |
يقرأ الفحص الثابت لـ JavaScript و.NET الملفات المقدّمة دون تشغيل التطبيق. يشغّل التسجيل أثناء التنفيذ الهدف المحدد أو يتفاعل معه بصلاحيات مستخدمك؛ ويشرح كل دليل للتسجيل أثناء التنفيذ آثاره.
<a id="choosing-a-deep-analysis-provider"></a>
تختلف صيغ ملفات الشيفرة الأصلية والأنظمة المضيفة المدعومة باختلاف الموفّر. راجع [إعداد Hopper وGhidra](docs/installation.md#hopper)، و[دليل IDA](docs/ida-provider.md)، و[دعم Ghidra التجريبي على Windows](docs/windows-ghidra-p0.md). يدعم Ghidra أيضًا [تحليل DOS ذي 16 بت](docs/ghidra-dos.md). لاختيار الموفّر، راجع [دليل CLI](docs/cli.md#choose-a-provider). تحقّق من [توفر الميزات في الإصدارات](docs/installation.md#released-package-and-main) للميزات المضافة بعد أحدث إصدار على npm.
## دراسات الحالة
[![رسوم توضيحية لأمثلة توزيع الصوت في DX-Ball وجسر الحافظة في Notion وحلقة الطلقات في TH04](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: إعادة بناء حساب توزيع الصوت بين القناتين
تتبّع استدعاء صوت إلى الدالة المساعدة التي تحوّل الموضع إلى توزيع بين القناتين، وافحص التعليمات، وحوّل الشيفرة شبه البرمجية غير المكتملة إلى C. تجتاز إعادة البناء 3,205 حالات اختبار على x86 الأصلي، وتعيد إنتاج جميع بايتات الدالة المترجمة البالغ عددها 63 بايتًا.
[اقرأ دراسة الحالة](https://rea.tools/showcase/dx-ball/) ·
[مستودع إعادة البناء](https://github.com/N0zoM1z0/dx-ball)
### Notion: تتبّع جسر الحافظة في Electron
اعثر على API الحافظة في عملية العرض، وتتبّعه عبر preload وIPC إلى العملية الرئيسية، وافحص صيغة الحافظة ذات التنسيق الغني.
[اقرأ دراسة الحالة](https://rea.tools/showcase/notion/)
### TH04: استعادة حساب حلقة المقذوفات في DOS
افحص تعليمات اللعبة الأصلية على PC-98 ذات 16 بت، واستعد حساب الزوايا الثابتة والموجّهة نحو الهدف، وقارن شيفرة C++ المعاد بناؤها بمخرجات المترجم المستخدم آنذاك.
[اقرأ دراسة الحالة](https://rea.tools/showcase/th04/) ·
[مستودع إعادة البناء](https://github.com/N0zoM1z0/th04)
إذا استخدمت REA لفحص هدف مثير للاهتمام، فنود الاطلاع عليه. شارك حالتك في [issue](https://github.com/morluto/rea/issues) أو [pull request](https://github.com/morluto/rea/pulls)، مع ذكر الهدف، وسؤالك، وكيف ساعدك REA، وما توصلت إليه.
## الأسئلة الشائعة
<details>
<summary><strong>هل يتضمن REA محرك فك ترجمة خاصًا به؟</strong></summary>
<summary><strong>أي وكلاء يمكنهم استخدام REA؟</strong></summary>
لا. يستطيع Setup تثبيت Hopper، لكنه يظل برنامجًا منفصلًا بترخيص خاص به. يوفر REA واجهة CLI وخادم MCP وسير العمل المخصص للوكلاء.
أي وكيل يدعم خوادم MCP المحلية. يهيّئ الإعداد [الوكلاء المدعومين](docs/installation.md#supported-agents)؛ ويمكن للعملاء الآخرين استخدام [تسجيل MCP يدويًا](docs/installation.md#mcp-registry).
</details>
<details>
<summary><strong>هل يجب أن يكون Hopper مفتوحًا مسبقًا؟</strong></summary>
<summary><strong>هل أحتاج إلى Hopper أو Ghidra أو IDA؟</strong></summary>
لا. يستطيع REA تشغيله. لكن Hopper قد يصبح مرئيًا أو يطلب إدخالًا عند الحاجة إلى قرار تفاعلي.
يستخدم تحليل الشيفرة الأصلية المتعمق أحدها. يعمل الفحص الثابت لـ JavaScript و.NET دون محرك لتحليل الشيفرة الأصلية. يستطيع الإعداد تثبيت Hopper بعد الموافقة؛ أما Ghidra وIDA فيستخدمان تثبيتاتك الموجودة. راجع [إعداد الموفّرين](docs/installation.md#hopper).
</details>
<details>
<summary><strong>هل يعمل REA على Linux أو Windows؟</strong></summary>
<summary><strong>هل أحتاج إلى تشغيل Hopper أولًا؟</strong></summary>
يدعم REA نظام macOS 12+ وUbuntu 24.04+ وFedora 41+ وArch Linux بنواة 64 بت وCachyOS. يعمل تحليل Ghidra للقراءة فقط على Linux x64 وmacOS x64/arm64 مع Ghidra 12.1.x وJDK الكامل الذي يعلنه التثبيت (JDK 21 أو أحدث دون حد أعلى في إصدارات 12.1 الحالية)، إضافة إلى حد Windows x64 P0 التجريبي لتطبيقات PE الأصلية x86-64 على NTFS محلي؛ راجع [دليل Windows Ghidra P0](docs/windows-ghidra-p0.md) للنطاق الموثق.
يشغّل REA برنامج Hopper عندما تحتاج العملية إليه. على macOS، قد تظهر عند التشغيل الأول نافذة تطلب اختيار وضع العرض التجريبي أو تفعيل الترخيص. راجع [تشغيل Hopper واستكشاف الأخطاء](docs/installation.md#launcher-paths-and-troubleshooting).
</details>
<details>
<summary><strong>هل يمكنني تحليل قواعد Hopper المحفوظة؟</strong></summary>
<summary><strong>ماذا يفعل تثبيت المهارة من skills.sh؟</strong></summary>
نعم. يدعم وقت التشغيل الملفات التنفيذية وقواعد `.hop`.
توفّر المهارة تعليمات الاستقصاء لوكيلك. استخدم `npx rea-agents setup` لتسجيل خادم MCP الخاص بـ REA وتثبيت التعليمات المطابقة، ثم أعد تشغيل وكيلك. راجع [تثبيت المهارة وحدها](docs/installation.md#skill-only-installation).
</details>
## التطوير
<details>
<summary><strong>ما الشيفرة التي يعيدها REA؟</strong></summary>
راجع [CONTRIBUTING.md](CONTRIBUTING.md) لإعداد بيئة التطوير وبنية المشروع والاختبارات وإرشادات الإصدار.
يعيد تحليل الشيفرة الأصلية شيفرة شبه برمجية وتعليمات تجميع. يستعيد تحليل JavaScript/Electron الوحدات والعلاقات بينها. يستخدم وكيلك هذه النتائج لكتابة تنفيذ واختباره؛ وتقدّم [دراسات الحالة](#دراسات-الحالة) أمثلة عملية.
## المشروع
</details>
- [حزمة npm](https://www.npmjs.com/package/rea-agents)
- [GitHub](https://github.com/morluto/rea)
- [القضايا والطلبات](https://github.com/morluto/rea/issues)
- [Hopper Disassembler](https://www.hopperapp.com/)
- [سياسة الأمان](SECURITY.md)
<details>
<summary><strong>هل يرفع REA تطبيقي؟</strong></summary>
## تاريخ النجوم
يحلّل REA الأهداف محليًا. يتلقى وكيلك نتائج الأدوات، ولموفّر النموذج الذي يستخدمه سياسة بيانات خاصة به.
🎉 **وصلنا إلى 20,000 نجمة على GitHub، شكرًا لكم!**
</details>
شكرًا لكل من يستخدم REA ويبلّغ عن الأخطاء ويختبر الإصدارات ويساهم في إصلاحها.
<details>
<summary><strong>ماذا أفعل إذا واجهت خطأ؟</strong></summary>
حدّث أولًا؛ فقد يكون إصدار حديث قد أصلح المشكلة بالفعل.
لواجهة CLI المثبّتة عبر npm:
```bash
rea update
```
لإعداد الوكيل عبر `npx`:
```bash
npx rea-agents@latest setup
```
إذا كنت تستخدم وكيلًا، فأكمل [تحديث الإعداد](#تحديث-rea) وأعد تشغيله. أعد محاولة المهمة نفسها. إذا استمرت المشكلة، [افتح issue](https://github.com/morluto/rea/issues) يتضمن إصدار REA، ونوع الهدف، وخطوات إعادة الإنتاج، ومخرجات الخطأ.
</details>
## التوثيق
ابدأ بـ [الأدلة العملية](https://rea.tools/guides/) على الموقع. للخيارات الدقيقة والمتطلبات وعقود النتائج:
- [التثبيت والإعداد](docs/installation.md): تسجيل الوكلاء، وتهيئة الموفّرين، والتحديثات، وإلغاء التثبيت.
- [الجاهزية واستكشاف الأخطاء](docs/installation.md#check-readiness-for-your-task): تشخيص وكيل أو محرك تحليل محدد.
- [CLI وEvidence](docs/cli.md): الأوامر، واختيار الموفّر، واللقطات، والاستيراد/التصدير، وحالات الخروج.
- [عقود MCP](docs/mcp-contracts.md) و[تعليمات الوكلاء](docs/mcp-prompts.md): نتائج الأدوات، والجلسات، والاستقصاءات الموجّهة.
- [كتالوج الأدوات](docs/mcp-contracts.md#generated-catalog): قائمة الأدوات والموفّرين وأوامر CLI المولّدة أثناء البناء.
- [خطة العمل](docs/roadmap.md): الأعمال المخطط لها ومتابعة القدرات.
أبلغ عن الثغرات وفق [SECURITY.md](SECURITY.md).
## سجل النجوم
🎉 **50,000 نجمة على GitHub — شكرًا لكم!**
شكرًا لكل من يستخدم REA، ويبلّغ عن الأخطاء، ويقترح ميزات، ويختبر إصدارات البناء، ويساهم بالإصلاحات.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="تاريخ نجوم REA على GitHub" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="سجل نجوم REA على GitHub" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## إخلاء المسؤولية
يوفّر REA أدوات لأبحاث الهندسة العكسية والتحليل وإعادة البناء المشروعة. أنت مسؤول عن الحصول على أي تفويض مطلوب والالتزام بالقوانين المعمول بها. لا يؤيد المشروع الاستخدام غير القانوني أو غير المصرّح به.
## المساهمة
نرحّب بمساعدتك في تطوير REA! [افتح issue](https://github.com/morluto/rea/issues) للإبلاغ عن خطأ أو اقتراح ميزة، أو [أرسل pull request](https://github.com/morluto/rea/pulls) لتحسين الشيفرة أو التوثيق.
راجع [CONTRIBUTING.md](CONTRIBUTING.md) لإعداد بيئة التطوير والفحوص، و[دليل الاختبار](docs/testing.md) لمسارات التحقق، و[خريطة البنية](docs/architecture.mermaid) لهيكل المشروع.
## الترخيص
[MIT](LICENSE)
+286
View File
@@ -0,0 +1,286 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · **Deutsch** · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA: Alles reverse-engineeren
### Ein MCP für das Reverse Engineering von Binärdateien, Anwendungen und Laufzeitverhalten.
**Eine Funktion gefällt dir? Verstehe, wie sie funktioniert – bis hinunter auf die Binärebene.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[Website](https://rea.tools/) · [Anleitungen](https://rea.tools/guides/) · [Fallstudien](https://rea.tools/showcase/)**
[Schnellstart](#schnellstart) · [So funktioniert REA](#so-funktioniert-rea) · [Was du analysieren kannst](#was-du-analysieren-kannst) · [Fallstudien](#fallstudien) · [Häufige Fragen](#häufige-fragen) · [Dokumentation](#dokumentation)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA startet seine Analysebrücke in Hopper und untersucht eine native Binärdatei" width="1200" />
<br /><br />
<table aria-label="REA-Community">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>Der Reverse-Engineering-Community beitreten</strong>
</a><br />
<sub>Discord · Fragen und Antworten · Ergebnisse teilen</sub>
</td>
</tr>
</table>
<br />
</div>
---
Du hast in einer App eine Funktion entdeckt, die du in dein eigenes Produkt übernehmen möchtest? Lass deinen Agenten sie mit REA untersuchen. Er kann die App ohne ihren Quellcode analysieren, die Funktionsweise erklären, Belege zeigen und eine passende Umsetzung für dein Projekt entwickeln.
REA verbindet deinen Agenten mit Werkzeugen zum Untersuchen nativer Binärdateien, von JavaScript- und Electron-Apps, .NET-Assemblies und Websites. Dieselben Werkzeuge kannst du auch im Terminal nutzen. Die Analyse läuft lokal; die Ergebnisse enthalten die Belege und Einschränkungen hinter jeder Schlussfolgerung.
Die Einrichtung registriert REA bei deinem Agenten und installiert passende Workflow-Anweisungen. Für native Analysen kannst du eine vorhandene Hopper- oder Ghidra-Installation verwenden. Mit deiner Zustimmung kann die Einrichtung auch Hopper installieren. Statische JavaScript-Analysen benötigen keines der beiden Programme.
> **[Besuche die REA-Website](https://rea.tools/)** für Einrichtungshinweise, bebilderte Anleitungen und echte Fallstudien.
## Schnellstart
### Deinen Agenten einrichten
Wenn Node.js und npm installiert sind, führe diesen Befehl aus:
```bash
npx rea-agents setup
```
Wähle deine Agenten aus, prüfe die geplanten Änderungen und bestätige sie. Die Einrichtung fügt den MCP-Server von REA und passende Workflow-Anweisungen hinzu und sichert vorhandene Konfigurationen. Starte deinen Agenten anschließend neu.
Die Einrichtung unterstützt Claude Code, Codex, Cursor, Gemini CLI, Grok Build und [weitere Agenten](docs/installation.md#supported-agents). Informationen zur Provider-Konfiguration und manuellen MCP-Registrierung findest du unter [Installation und Einrichtung](docs/installation.md).
### Deinen Agenten fragen
```text
Untersuche, wie die Suche in der Notes-App funktioniert, zeige mir die Belege und entwickle eine ähnliche Funktion für mein Projekt.
```
Ersetze Notes durch deine Ziel-App und benenne die Funktion, die du verstehen möchtest.
### Das Terminal verwenden
Untersuche ein entpacktes JavaScript-/Electron-App-Verzeichnis oder eine ASAR-Datei:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
Das Ergebnis enthält Module, Imports, Electron-Grenzen und die zugehörigen Belege. Ersetze den Pfad durch dein Ziel, beispielsweise `"D:/apps/example"` unter Windows.
Für die regelmäßige Nutzung kannst du den Befehl `rea` installieren:
```bash
npm install --global rea-agents
rea --help
```
Konfiguriere für native Analysen zuerst einen Provider. Native Befehle, Provider-Auswahl, Snapshots und Skriptnutzung beschreibt der [CLI- und Evidence-Leitfaden](docs/cli.md).
### REA aktualisieren
REA entwickelt sich schnell weiter; neue Versionen enthalten häufig Fehlerbehebungen. Halte deine Installation aktuell.
Für eine über npm installierte CLI:
```bash
rea update
```
Um die Agentenregistrierungen und den Skill zu aktualisieren, führe den Einrichtungsbefehl aus, den das Update ausgibt.
Wenn du `npx` verwendest, aktualisiere die Agenteneinrichtung mit:
```bash
npx rea-agents@latest setup
```
Prüfe die Änderungen und starte deinen Agenten neu. Für einzelne CLI-Aufrufe verwende `npx rea-agents@latest`, gefolgt vom gewünschten Befehl.
## So funktioniert REA
Dein Agent ruft REA über MCP auf, um das Ziel zu untersuchen und relevanten Code zu verfolgen. REA liefert Ergebnisse mit ihren Belegen zurück. Der Agent nutzt sie für weitere Fragen, Erklärungen oder zum Schreiben und Testen einer Implementierung. CLI-Befehle verwenden dieselben Workflows.
![REA-Untersuchungsablauf: Dein Agent fragt nach einem lokalen Ziel, REA untersucht und verfolgt es mit Analysewerkzeugen, und der Agent nutzt den zurückgegebenen Code, Verweise und offene Fragen zum Erklären, Implementieren und Testen.](website/public/assets/figures/rea-investigation-flow.svg)
[Abbildung in voller Größe öffnen](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## Was du analysieren kannst
REA benötigt Node.js 22.x (>=22.19), 24.x (>=24.11) oder 26+ sowie npm. Zusätzliche Werkzeuge und unterstützte Hostsysteme hängen vom Ziel ab:
| Ziel | Was REA zurückgibt | Voraussetzungen und Anleitung |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Native Binärdateien | Pseudocode, Assemblercode, Zeichenketten, Symbole, Aufrufe und Verweise | Hopper, Ghidra oder IDA; [native Analyse](https://rea.tools/guides/native/) |
| Offline-ELF-Struktur | Sektionen, Segmente, ursprüngliche Symbole/Relokationen und mögliche Schutzmaßnahmen aus statischer Analyse | Vom Aufrufer bereitgestelltes pwntools unter Linux x64; [Binärdiagnostik](docs/binary-diagnostics.md) |
| EVM-Bytecode | Dispatch-Selektoren, Byte-Offsets, abgeleitete Argumente und Veränderbarkeit des Zustands | Lokale Eingabe mit Rohbytes oder Hexdarstellung unter Linux x64; [Offline-EVM-Leitfaden](docs/evm-bytecode.md) |
| Aufgezeichnete Linux-Abstürze | Unverarbeitete Note-Einträge, Register/Signale aller aufgezeichneten Threads und optionale Zuordnungskandidaten | Vom Aufrufer bereitgestelltes pwntools unter Linux x64; optional GDB/pwndbg; [aufgezeichnete Abstürze](docs/recorded-crashes.md) |
| JavaScript / Electron | Module, Imports, Source Maps, Routen, IPC und Beziehungen zu nativen Add-ons | Node.js und npm; [Anwendungsanalyse](https://rea.tools/guides/javascript/) |
| Websites | Seitenstruktur, Skripte, Netzwerkbeobachtungen und angeforderte Screenshots | Ein Browser aus der Chrome-Familie; [Browseranalyse](https://rea.tools/guides/browser/) |
| Gespeicherte Netzwerkaufzeichnungen | Anfragen, Antworten, zugängliche Nutzdaten und Quellpositionen | HAR; mitmdump unter Linux für Aufzeichnungen im nativen mitmproxy-Format; [Leitfaden zu Netzwerkaufzeichnungen](docs/web-network-captures.md) |
| .NET-Assemblies | Metadaten, CIL-Anweisungen, deklarierte native Abhängigkeiten und Build-Vergleiche | Statische Untersuchung; [Leitfaden für verwalteten Code](docs/managed-code-analysis.md) |
| Android-APKs | Manifest-Deklarationen, Klassen, dekompilierte Methoden und Verweise | JADX ohne grafische Oberfläche und ein vollständiges JDK unter Linux/macOS/Windows x64; [Android-Leitfaden](docs/android-analysis.md) |
| Android-Geräte | Geräte, Pakete, Prozesse, Logs, Dumps, Bildschirmaufnahmen sowie APK- und Dateiübertragungen | Vom Aufrufer bereitgestelltes adb (Emulator oder Gerät); [ADB-Leitfaden](docs/adb-device-analysis.md) |
| JEB-Projekte | Engine-gestützte Projekteinheiten, Artefakt-Prüfsummen und Pseudokode von Typen/Methoden | Ein vom Aufrufer gestarteter JEB-Client mit MCP, ausgewählt über REA_JEB_MCP_URL; [JEB-Leitfaden](docs/jeb-analysis.md) |
| Android-Ressourcen | Dekodiertes Manifest, String-Tabellen, Sprachen und Versionsfakten | Vom Aufrufer bereitgestellter Apktool-Starter; [Ressourcen-Leitfaden](docs/apktool-resource-analysis.md) |
| Firmware | Bereiche, Extraktionsergebnisse und Übergaben an die native Analyse | Binwalk / Unblob unter Linux; [Firmware-Leitfaden](docs/firmware-analysis.md) |
| Pakete und Ressourcen | Dateiinventare, Hashwerte, plists, Aufbau von Apple-Bundles und extrahierte Ressourcen | [Artefakt- und JavaScript-Leitfaden](docs/javascript-artifact-reconstruction.md), [Apple-Anwendungen](docs/apple-application-analysis.md) |
| Prozessverhalten | Terminalausgabe, Interaktionen, Beobachtungen zu Prozessende und Dateisystem sowie Laufvergleiche | Linux/macOS mit nativer PTY; [Prozessaufzeichnung](docs/process-capture.md) |
Statische JavaScript- und .NET-Untersuchungen lesen die bereitgestellten Dateien, ohne die Anwendung auszuführen. Laufzeitaufzeichnungen führen das gewählte Ziel mit deinen Benutzerrechten aus oder interagieren damit; die jeweiligen Anleitungen beschreiben die Auswirkungen.
<a id="choosing-a-deep-analysis-provider"></a>
Native Formate und unterstützte Hostsysteme unterscheiden sich je nach Provider. Siehe [Hopper- und Ghidra-Einrichtung](docs/installation.md#hopper), den [IDA-Leitfaden](docs/ida-provider.md) und die [experimentelle Ghidra-Unterstützung unter Windows](docs/windows-ghidra-p0.md). Ghidra unterstützt auch [16-Bit-DOS-Analyse](docs/ghidra-dos.md). Die Provider-Auswahl beschreibt der [CLI-Leitfaden](docs/cli.md#choose-a-provider). Prüfe die [Verfügbarkeit in Releases](docs/installation.md#released-package-and-main) für Funktionen, die seit der neuesten npm-Version hinzugekommen sind.
## Fallstudien
[![Illustrationen der Fallstudien zu DX-Balls Klangbalance, Notions Zwischenablage-Brücke und TH04s Geschossring](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: Eine Stereo-Panning-Berechnung rekonstruieren
Verfolge einen Sound-Aufruf zur Hilfsfunktion, die Positionen in Panning-Werte umrechnet, untersuche die Anweisungen und überführe unvollständigen Pseudocode in C. Die Rekonstruktion besteht 3.205 Tests mit dem ursprünglichen x86-Code und reproduziert alle 63 Bytes der kompilierten Funktion.
[Fallstudie lesen](https://rea.tools/showcase/dx-ball/) · [Rekonstruktionsrepository](https://github.com/N0zoM1z0/dx-ball)
### Notion: Die Electron-Zwischenablagebrücke verfolgen
Finde die Zwischenablage-API des Renderers, verfolge sie über preload und IPC bis zum Hauptprozess und untersuche das Zwischenablageformat samt Formatierungsdaten.
[Fallstudie lesen](https://rea.tools/showcase/notion/)
### TH04: Eine DOS-Geschossring-Berechnung wiederherstellen
Untersuche die 16-Bit-Anweisungen des ursprünglichen PC-98-Spiels, rekonstruiere die festen und zielgerichteten Winkelberechnungen und vergleiche das rekonstruierte C++ mit der Ausgabe des damaligen Compilers.
[Fallstudie lesen](https://rea.tools/showcase/th04/) · [Rekonstruktionsrepository](https://github.com/N0zoM1z0/th04)
Wenn du mit REA etwas Interessantes untersucht hast, würden wir es gern sehen. Teile deine Fallstudie in einem [Issue](https://github.com/morluto/rea/issues) oder [Pull Request](https://github.com/morluto/rea/pulls) und beschreibe das Ziel, deine Frage, wie REA geholfen hat und was du herausgefunden hast.
## Häufige Fragen
<details>
<summary><strong>Welche Agenten können REA verwenden?</strong></summary>
Jeder Agent, der lokale MCP-Server unterstützt. Die Einrichtung konfiguriert die [unterstützten Agenten](docs/installation.md#supported-agents); andere Clients können die [manuelle MCP-Registrierung](docs/installation.md#mcp-registry) nutzen.
</details>
<details>
<summary><strong>Brauche ich Hopper, Ghidra oder IDA?</strong></summary>
Für tiefgehende native Analysen wird eines dieser Programme verwendet. Statische JavaScript- und .NET-Untersuchungen funktionieren ohne native Analyse-Engine. Die Einrichtung kann Hopper nach Zustimmung installieren; Ghidra und IDA nutzen deine vorhandenen Installationen. Siehe [Provider-Einrichtung](docs/installation.md#hopper).
</details>
<details>
<summary><strong>Muss ich Hopper vorher starten?</strong></summary>
REA startet Hopper, wenn eine Operation es benötigt. Unter macOS kann beim ersten Start ein Dialog erscheinen, in dem du den Demomodus auswählst oder deine Lizenz aktivierst. Siehe [Hopper-Start und Fehlerbehebung](docs/installation.md#launcher-paths-and-troubleshooting).
</details>
<details>
<summary><strong>Was bewirkt die Installation des Skills über skills.sh?</strong></summary>
Der Skill stellt Untersuchungsanweisungen für deinen Agenten bereit. Verwende `npx rea-agents setup`, um den MCP-Server von REA zu registrieren und passende Anweisungen zu installieren. Starte deinen Agenten anschließend neu. Siehe [Installation nur des Skills](docs/installation.md#skill-only-installation).
</details>
<details>
<summary><strong>Welchen Code liefert REA zurück?</strong></summary>
Native Analysen liefern Pseudocode und Assemblercode. JavaScript-/Electron-Analysen rekonstruieren Module und ihre Beziehungen. Dein Agent nutzt diese Ergebnisse zum Schreiben und Testen einer Implementierung; die [Fallstudien](#fallstudien) zeigen konkrete Beispiele.
</details>
<details>
<summary><strong>Lädt REA meine App hoch?</strong></summary>
REA analysiert Ziele lokal. Dein Agent erhält die Werkzeugergebnisse; sein Modellanbieter hat eine eigene Datenrichtlinie.
</details>
<details>
<summary><strong>Was soll ich tun, wenn ich einen Fehler finde?</strong></summary>
Aktualisiere zuerst; eine neuere Version könnte den Fehler bereits behoben haben.
Für eine über npm installierte CLI:
```bash
rea update
```
Für die Agenteneinrichtung über `npx`:
```bash
npx rea-agents@latest setup
```
Wenn du einen Agenten verwendest, schließe die [Aktualisierung der Einrichtung](#rea-aktualisieren) ab und starte ihn neu. Wiederhole dieselbe Aufgabe. Besteht das Problem weiterhin, [öffne ein Issue](https://github.com/morluto/rea/issues) mit deiner REA-Version, dem Zieltyp, den Reproduktionsschritten und der Fehlerausgabe.
</details>
## Dokumentation
Beginne mit den [praxisnahen Anleitungen](https://rea.tools/guides/) auf der Website. Genaue Optionen, Voraussetzungen und Ergebniskontrakte findest du hier:
- [Installation und Einrichtung](docs/installation.md): Agentenregistrierung, Provider-Konfiguration, Updates und Deinstallation.
- [Bereitschaft und Fehlerbehebung](docs/installation.md#check-readiness-for-your-task): Diagnose eines bestimmten Agenten oder einer Analyse-Engine.
- [CLI und Evidence](docs/cli.md): Befehle, Provider-Auswahl, Snapshots, Import/Export und Exit-Status.
- [MCP-Kontrakte](docs/mcp-contracts.md) und [Agenten-Prompts](docs/mcp-prompts.md): Werkzeugergebnisse, Sitzungen und geführte Untersuchungen.
- [Werkzeugkatalog](docs/mcp-contracts.md#generated-catalog): Beim Build erzeugtes Inventar von Werkzeugen, Providern und CLI-Befehlen.
- [Roadmap](docs/roadmap.md): Geplante Arbeiten und Fortschrittsübersichten zu Fähigkeiten.
Melde Sicherheitslücken gemäß [SECURITY.md](SECURITY.md).
## Sternverlauf
🎉 **50.000 GitHub-Sterne – vielen Dank!**
Danke an alle, die REA nutzen, Fehler melden, Funktionswünsche äußern, Builds testen und Fehlerbehebungen beitragen.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="GitHub-Sternverlauf von REA" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## Haftungsausschluss
REA stellt Werkzeuge für rechtmäßige Reverse-Engineering-Forschung, Analyse und Rekonstruktion bereit. Du bist dafür verantwortlich, erforderliche Genehmigungen einzuholen und geltendes Recht einzuhalten. Das Projekt unterstützt keine rechtswidrige oder unbefugte Nutzung.
## Mitwirken
Wir freuen uns über deine Hilfe bei REA! [Öffne ein Issue](https://github.com/morluto/rea/issues), um einen Fehler zu melden oder eine Funktion vorzuschlagen, oder [sende einen Pull Request](https://github.com/morluto/rea/pulls), um Code oder Dokumentation zu verbessern.
Die Entwicklungsumgebung und Prüfungen beschreibt [CONTRIBUTING.md](CONTRIBUTING.md), die Verifikationspfade der [Testleitfaden](docs/testing.md) und die Projektstruktur die [Architekturübersicht](docs/architecture.mermaid).
## Lizenz
[MIT](LICENSE)
+286
View File
@@ -0,0 +1,286 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · **Español** · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA: Ingeniería inversa de cualquier cosa
### Un solo MCP para la ingeniería inversa de binarios, aplicaciones y comportamiento en ejecución.
**¿Ves una función que te gusta? Entiende cómo funciona, hasta el nivel binario.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[Sitio web](https://rea.tools/) · [Guías](https://rea.tools/guides/) · [Casos prácticos](https://rea.tools/showcase/)**
[Inicio rápido](#inicio-rápido) · [Cómo funciona REA](#cómo-funciona-rea) · [Qué puedes analizar](#qué-puedes-analizar) · [Casos prácticos](#casos-prácticos) · [Preguntas frecuentes](#preguntas-frecuentes) · [Documentación](#documentación)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA inicia su puente de análisis dentro de Hopper mientras inspecciona un binario nativo" width="1200" />
<br /><br />
<table aria-label="Comunidad REA">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>Únete a la comunidad de ingeniería inversa</strong>
</a><br />
<sub>Discord · Preguntas y respuestas · Comparte tus resultados</sub>
</td>
</tr>
</table>
<br />
</div>
---
¿Has visto una función en una aplicación que quieres incorporar a tu producto? Pide a tu agente que la investigue con REA. Puede inspeccionar la aplicación sin su código fuente, explicar cómo funciona la función, mostrar las pruebas y crear una versión para tu proyecto.
REA conecta tu agente con herramientas para inspeccionar binarios nativos, aplicaciones JavaScript y Electron, ensamblados .NET y sitios web. También puedes usar las mismas herramientas desde la terminal. El análisis se ejecuta localmente y los resultados incluyen las pruebas y limitaciones que sustentan cada conclusión.
La configuración registra REA en tu agente e instala las instrucciones de trabajo correspondientes. El análisis nativo puede usar una instalación existente de Hopper o Ghidra; la configuración también puede instalar Hopper, si lo autorizas. El análisis estático de JavaScript no necesita ninguno de los dos motores.
> **[Visita el sitio web de REA](https://rea.tools/)** para encontrar instrucciones de configuración, guías ilustradas y casos reales.
## Inicio rápido
### Configura tu agente
Con Node.js y npm instalados, ejecuta:
```bash
npx rea-agents setup
```
Elige tus agentes, revisa los cambios propuestos y apruébalos. La configuración añade el servidor MCP de REA y las instrucciones de trabajo correspondientes, con copias de seguridad de la configuración existente. Reinicia tu agente al terminar.
La configuración admite Claude Code, Codex, Cursor, Gemini CLI, Grok Build y [otros agentes](docs/installation.md#supported-agents). Consulta [instalación y configuración](docs/installation.md) para configurar proveedores y registrar MCP manualmente.
### Pregunta a tu agente
```text
Investiga cómo funciona la búsqueda en la aplicación Notes, muéstrame las pruebas y crea una función similar para mi proyecto.
```
Sustituye Notes por la aplicación objetivo y especifica la función que quieres entender.
### Usa la terminal
Inspecciona un directorio extraído de una aplicación JavaScript/Electron o un archivo ASAR:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
El resultado incluye módulos, importaciones, límites de Electron y sus pruebas. Sustituye la ruta por la de tu objetivo, por ejemplo `"D:/apps/example"` en Windows.
Para instalar el comando `rea` y usarlo habitualmente:
```bash
npm install --global rea-agents
rea --help
```
Para el análisis nativo, configura primero un proveedor. Consulta la [guía de CLI y Evidence](docs/cli.md) para los comandos nativos, la selección de proveedores, las instantáneas y el uso en scripts.
### Actualiza REA
REA cambia rápidamente y las nuevas versiones incluyen correcciones frecuentes. Mantén tu instalación actualizada.
Para una CLI instalada mediante npm:
```bash
rea update
```
Para actualizar los registros de tus agentes y la skill, ejecuta el comando de configuración que muestra la actualización.
Si usas `npx`, actualiza la configuración de tu agente con:
```bash
npx rea-agents@latest setup
```
Revisa los cambios de configuración y reinicia tu agente. Para ejecutar comandos de CLI puntuales, usa `npx rea-agents@latest` seguido del comando.
## Cómo funciona REA
Tu agente llama a REA mediante MCP para inspeccionar el objetivo y seguir el código relevante. REA devuelve los hallazgos junto con sus pruebas. El agente los utiliza para hacer preguntas de seguimiento, explicar el comportamiento o escribir y probar una implementación. Los comandos de CLI usan los mismos flujos de trabajo.
![Flujo de investigación de REA: tu agente pregunta sobre un objetivo local, REA lo inspecciona y rastrea con herramientas de análisis, y el agente utiliza el código, las referencias y los aspectos desconocidos devueltos para explicar, implementar y probar.](website/public/assets/figures/rea-investigation-flow.svg)
[Abre la figura a tamaño completo](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## Qué puedes analizar
REA requiere Node.js 22.x (>=22.19), 24.x (>=24.11) o 26+, además de npm. Las herramientas adicionales y los sistemas anfitriones compatibles dependen del objetivo:
| Objetivo | Qué devuelve REA | Requisitos y guía |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| Binarios nativos | Pseudocódigo, ensamblador, cadenas, símbolos, llamadas y referencias | Hopper, Ghidra o IDA; [análisis nativo](https://rea.tools/guides/native/) |
| Estructura ELF sin ejecutar | Secciones, segmentos, símbolos/reubicaciones originales y posibles medidas de mitigación detectadas mediante análisis estático | pwntools proporcionado por quien llama, en Linux x64; [diagnóstico de binarios](docs/binary-diagnostics.md) |
| Bytecode EVM | Selectores de despacho, desplazamientos en bytes, argumentos inferidos y mutabilidad | Entrada local con bytes sin procesar o representación hexadecimal, en Linux x64; [guía de EVM sin ejecutar](docs/evm-bytecode.md) |
| Fallos de Linux registrados | Registros note sin procesar, registros/señales de cada hilo registrado y posibles correspondencias de memoria opcionales | pwntools proporcionado por quien llama, en Linux x64; GDB/pwndbg opcionales; [fallos registrados](docs/recorded-crashes.md) |
| JavaScript / Electron | Módulos, importaciones, mapas de código fuente, rutas, IPC y relaciones con complementos nativos | Node.js y npm; [análisis de aplicaciones](https://rea.tools/guides/javascript/) |
| Sitios web | Estructura de la página, scripts, observaciones de red y capturas de pantalla solicitadas | Un navegador de la familia Chrome; [análisis del navegador](https://rea.tools/guides/browser/) |
| Capturas de red guardadas | Solicitudes, respuestas, contenido accesible de las cargas útiles y ubicaciones de origen | HAR; mitmdump en Linux para capturas en formato nativo de mitmproxy; [guía de capturas](docs/web-network-captures.md) |
| Ensamblados .NET | Metadatos, instrucciones CIL, dependencias nativas declaradas y comparaciones de compilaciones | Inspección estática; [guía de código administrado](docs/managed-code-analysis.md) |
| APK de Android | Declaraciones del manifiesto, clases, métodos descompilados y referencias | JADX sin interfaz gráfica y un JDK completo en Linux/macOS/Windows x64; [guía de Android](docs/android-analysis.md) |
| Dispositivos Android | Dispositivos, paquetes, procesos, registros, volcados, capturas de pantalla y transferencias de APK/archivos | adb suministrado por el autor de la llamada (emulador o dispositivo); [guía de ADB](docs/adb-device-analysis.md) |
| Proyectos JEB | Unidades de proyecto del motor, resúmenes de artefactos y pseudocódigo de tipos/métodos | Un cliente JEB iniciado por el autor de la llamada que sirve MCP, seleccionado con REA_JEB_MCP_URL; [guía de JEB](docs/jeb-analysis.md) |
| Recursos de Android | Manifiesto decodificado, tablas de cadenas, idiomas y datos de versión | Lanzador de Apktool suministrado por el autor de la llamada; [guía de recursos](docs/apktool-resource-analysis.md) |
| Firmware | Regiones, resultados de extracción y derivaciones al análisis nativo | Binwalk / Unblob en Linux; [guía de firmware](docs/firmware-analysis.md) |
| Paquetes y recursos | Inventarios de archivos, resúmenes criptográficos, plists, estructura de paquetes de Apple y recursos extraídos | [Guía de artefactos y JavaScript](docs/javascript-artifact-reconstruction.md), [aplicaciones de Apple](docs/apple-application-analysis.md) |
| Comportamiento de procesos | Salida de la terminal, interacciones, observaciones de salida y del sistema de archivos, y comparaciones entre ejecuciones | Linux/macOS con una PTY nativa; [captura de procesos](docs/process-capture.md) |
La inspección estática de JavaScript y .NET lee los archivos suministrados sin ejecutar la aplicación. La captura en ejecución inicia el objetivo seleccionado o interactúa con él con los permisos de tu usuario; cada guía describe sus efectos.
<a id="choosing-a-deep-analysis-provider"></a>
Los formatos nativos y los sistemas anfitriones compatibles varían según el proveedor. Consulta [configuración de Hopper y Ghidra](docs/installation.md#hopper), la [guía de IDA](docs/ida-provider.md) y la [compatibilidad experimental de Ghidra en Windows](docs/windows-ghidra-p0.md). Ghidra también admite [análisis de DOS de 16 bits](docs/ghidra-dos.md). Para elegir un proveedor, consulta la [guía de CLI](docs/cli.md#choose-a-provider). Comprueba la [disponibilidad por versión](docs/installation.md#released-package-and-main) de las funciones añadidas después de la última versión publicada en npm.
## Casos prácticos
[![Ilustraciones de los casos de panoramización de sonido de DX-Ball, el puente del portapapeles de Notion y el anillo de proyectiles de TH04](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: reconstruir un cálculo de panoramización de sonido
Sigue una llamada de sonido hasta la función auxiliar que convierte la posición en panoramización, inspecciona las instrucciones y transforma el pseudocódigo incompleto en C. La reconstrucción supera 3.205 casos con el x86 original y reproduce los 63 bytes de la función compilada.
[Lee el caso práctico](https://rea.tools/showcase/dx-ball/) · [Repositorio de reconstrucción](https://github.com/N0zoM1z0/dx-ball)
### Notion: seguir el puente del portapapeles de Electron
Encuentra la API del portapapeles del proceso de renderizado, síguela a través de preload e IPC hasta el proceso principal e inspecciona el formato enriquecido del portapapeles.
[Lee el caso práctico](https://rea.tools/showcase/notion/)
### TH04: recuperar el cálculo de un anillo de proyectiles en DOS
Inspecciona las instrucciones de 16 bits del juego original para PC-98, recupera los cálculos de ángulos fijos y dirigidos, y compara el C++ reconstruido con la salida del compilador de la época.
[Lee el caso práctico](https://rea.tools/showcase/th04/) · [Repositorio de reconstrucción](https://github.com/N0zoM1z0/th04)
Si has usado REA para investigar algo interesante, nos gustaría verlo. Comparte tu caso en una [issue](https://github.com/morluto/rea/issues) o una [pull request](https://github.com/morluto/rea/pulls), incluyendo el objetivo, tu pregunta, cómo te ayudó REA y qué encontraste.
## Preguntas frecuentes
<details>
<summary><strong>¿Qué agentes pueden usar REA?</strong></summary>
Cualquier agente que admita servidores MCP locales. La configuración prepara los [agentes compatibles](docs/installation.md#supported-agents); otros clientes pueden usar el [registro manual de MCP](docs/installation.md#mcp-registry).
</details>
<details>
<summary><strong>¿Necesito Hopper, Ghidra o IDA?</strong></summary>
El análisis nativo en profundidad utiliza uno de ellos. La inspección estática de JavaScript y .NET funciona sin un motor de análisis nativo. La configuración puede instalar Hopper después de tu aprobación; Ghidra e IDA usan las instalaciones que ya tienes. Consulta [configuración de proveedores](docs/installation.md#hopper).
</details>
<details>
<summary><strong>¿Tengo que iniciar Hopper primero?</strong></summary>
REA inicia Hopper cuando una operación lo necesita. En macOS, puede aparecer un diálogo al iniciarlo por primera vez para elegir el modo de demostración o activar tu licencia. Consulta [inicio de Hopper y resolución de problemas](docs/installation.md#launcher-paths-and-troubleshooting).
</details>
<details>
<summary><strong>¿Qué hace la instalación de la skill desde skills.sh?</strong></summary>
La skill proporciona instrucciones de investigación a tu agente. Usa `npx rea-agents setup` para registrar el servidor MCP de REA e instalar las instrucciones correspondientes; después reinicia tu agente. Consulta [instalación solo de la skill](docs/installation.md#skill-only-installation).
</details>
<details>
<summary><strong>¿Qué código devuelve REA?</strong></summary>
El análisis nativo devuelve pseudocódigo y ensamblador. El análisis de JavaScript/Electron recupera módulos y sus relaciones. Tu agente utiliza estos hallazgos para escribir y probar una implementación; los [casos prácticos](#casos-prácticos) ofrecen ejemplos completos.
</details>
<details>
<summary><strong>¿REA sube mi aplicación?</strong></summary>
REA analiza los objetivos localmente. Tu agente recibe los resultados de las herramientas, y su proveedor de modelos tiene su propia política de datos.
</details>
<details>
<summary><strong>¿Qué debo hacer si encuentro un error?</strong></summary>
Actualiza primero; una versión reciente puede haber solucionado el problema.
Para una CLI instalada mediante npm:
```bash
rea update
```
Para configurar el agente mediante `npx`:
```bash
npx rea-agents@latest setup
```
Si usas un agente, completa la [actualización de la configuración](#actualiza-rea) y reinícialo. Repite la misma tarea. Si el problema continúa, [abre una issue](https://github.com/morluto/rea/issues) con tu versión de REA, el tipo de objetivo, los pasos para reproducirlo y la salida del error.
</details>
## Documentación
Empieza con las [guías prácticas](https://rea.tools/guides/) del sitio web. Para opciones exactas, requisitos y contratos de resultados:
- [Instalación y configuración](docs/installation.md): registro de agentes, configuración de proveedores, actualizaciones y desinstalación.
- [Preparación y resolución de problemas](docs/installation.md#check-readiness-for-your-task): diagnóstico de un agente o motor de análisis concreto.
- [CLI y Evidence](docs/cli.md): comandos, selección de proveedores, instantáneas, importación/exportación y estados de salida.
- [Contratos de MCP](docs/mcp-contracts.md) y [prompts para agentes](docs/mcp-prompts.md): resultados de herramientas, sesiones e investigaciones guiadas.
- [Catálogo de herramientas](docs/mcp-contracts.md#generated-catalog): inventario de herramientas, proveedores y comandos de CLI generado durante la compilación.
- [Hoja de ruta](docs/roadmap.md): trabajo previsto y seguimiento de capacidades.
Informa de vulnerabilidades siguiendo [SECURITY.md](SECURITY.md).
## Historial de estrellas
🎉 **50.000 estrellas en GitHub: ¡gracias!**
Gracias a quienes usan REA, informan de errores, solicitan funciones, prueban compilaciones y contribuyen con correcciones.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="Historial de estrellas de REA en GitHub" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## Aviso legal
REA proporciona herramientas para la investigación, el análisis y la reconstrucción mediante ingeniería inversa conforme a la ley. Eres responsable de obtener las autorizaciones necesarias y cumplir las leyes aplicables. El proyecto no respalda usos ilegales ni no autorizados.
## Contribuir
¡Nos encantaría que ayudaras con REA! [Abre una issue](https://github.com/morluto/rea/issues) para comunicar un error o proponer una función, o [envía una pull request](https://github.com/morluto/rea/pulls) para mejorar el código o la documentación.
Consulta [CONTRIBUTING.md](CONTRIBUTING.md) para preparar el entorno de desarrollo y las comprobaciones, la [guía de pruebas](docs/testing.md) para los procesos de verificación y el [mapa de arquitectura](docs/architecture.mermaid) para la estructura del proyecto.
## Licencia
[MIT](LICENSE)
+267
View File
@@ -0,0 +1,267 @@
<div align="center" dir="rtl">
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · **فارسی** · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA: مهندسی معکوس هر چیزی
### یک MCP برای مهندسی معکوس فایل‌های باینری، برنامه‌ها و رفتار زمان اجرا.
**قابلیتی دیده‌اید که دوستش دارید؟ سازوکارش را تا سطح باینری درک کنید.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55" /></a>
**[وب‌سایت](https://rea.tools/) · [راهنماها](https://rea.tools/guides/) · [نمونه‌های عملی](https://rea.tools/showcase/)**
[شروع سریع](#شروع-سریع) · [REA چگونه کار می‌کند؟](#rea-چگونه-کار-میکند) · [چه چیزهایی را میتوان تحلیل کرد؟](#چه-چیزهایی-را-میتوان-تحلیل-کرد) · [نمونه‌های عملی](#نمونههای-عملی) · [پرسش‌های متداول](#پرسشهای-متداول) · [مستندات](#مستندات)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="اجرای پل تحلیل REA در Hopper هنگام بررسی یک فایل باینری بومی" width="1200" />
<br /><br />
<table aria-label="انجمن REA"><tr><td align="center" width="360"><a href="https://discord.gg/GkcryMnJDM"><img src="docs/assets/discord.svg" height="42" alt="Discord" /><br /><strong>به انجمن مهندسی معکوس بپیوندید</strong></a><br /><sub>دیسکورد · پرسش و پاسخ · نمایش دستاوردها</sub></td></tr></table>
<br />
</div>
---
<div dir="rtl">
قابلیتی در یک برنامه دیده‌اید که می‌خواهید در محصول خودتان داشته باشید؟ از ایجنت خود بخواهید با REA آن را بررسی کند. ایجنت می‌تواند بدون دسترسی به کد منبع برنامه، نحوهٔ کار قابلیت را بررسی و توضیح دهد، شواهد را نشان دهد و نسخه‌ای مشابه برای پروژهٔ شما بسازد.
REA ایجنت شما را به ابزارهایی برای بررسی باینری‌های بومی، برنامه‌های JavaScript و Electron، اسمبلی‌های .NET و وب‌سایت‌ها متصل می‌کند. همین ابزارها از ترمینال نیز قابل استفاده‌اند. تحلیل به‌صورت محلی انجام می‌شود و نتایج شامل شواهد و محدودیت‌های پشت هر نتیجه‌گیری هستند.
فرایند راه‌اندازی، REA را در ایجنت شما ثبت می‌کند و دستورالعمل‌های گردش‌کار متناظر را نصب می‌کند. تحلیل بومی می‌تواند از نصب موجود Hopper یا Ghidra استفاده کند؛ همچنین راه‌اندازی می‌تواند با تأیید شما Hopper را به‌صورت اختیاری نصب کند. تحلیل ایستای JavaScript به هیچ‌یک از این موتورهای تحلیل نیاز ندارد.
> برای دستورالعمل‌های راه‌اندازی، راهنماهای تصویری و مطالعات موردی واقعی، **[به وب‌سایت REA مراجعه کنید](https://rea.tools/)**.
## شروع سریع
### ایجنت خود را راه‌اندازی کنید
پس از نصب Node.js و npm، دستور زیر را اجرا کنید:
```bash
npx rea-agents setup
```
ایجنت‌های موردنظر را انتخاب کنید، تغییرات پیشنهادی را بررسی و تأیید کنید. فرایند راه‌اندازی، سرور MCP مربوط به REA و دستورالعمل‌های گردش‌کار متناظر را اضافه می‌کند و از پیکربندی موجود نسخهٔ پشتیبان می‌گیرد. پس از آن ایجنت خود را مجدداً راه‌اندازی کنید.
راه‌اندازی از Claude Code، Codex، Cursor، Gemini CLI، Grok Build و [ایجنت‌های دیگر](docs/installation.md#supported-agents) پشتیبانی می‌کند. برای پیکربندی ارائه‌دهنده و ثبت دستی MCP، [نصب و راه‌اندازی](docs/installation.md) را ببینید.
### از ایجنت خود بپرسید
```text
بررسی کن جست‌وجو در برنامهٔ Notes چگونه کار می‌کند، شواهدش را نشان بده و قابلیتی مشابه برای پروژهٔ من بساز.
```
به‌جای Notes، نام برنامهٔ هدف و قابلیتی را قرار دهید که می‌خواهید درک کنید.
### استفاده از ترمینال
برای بررسی پوشهٔ استخراج‌شدهٔ یک برنامهٔ JavaScript/Electron یا فایل ASAR:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
نتیجه شامل ماژول‌ها، importها، مرزهای Electron و شواهد مربوط به آن‌هاست. مسیر را با مسیر برنامهٔ هدف جایگزین کنید؛ مثلاً در ویندوز `"D:/apps/example"`.
برای نصب دستور `rea` جهت استفادهٔ مداوم:
```bash
npm install --global rea-agents
rea --help
```
برای تحلیل بومی ابتدا یک ارائه‌دهنده پیکربندی کنید. برای دستورات بومی، انتخاب ارائه‌دهنده، snapshotها و اسکریپت‌نویسی، [راهنمای CLI و شواهد](docs/cli.md) را ببینید.
### به‌روزرسانی REA
REA به‌سرعت تغییر می‌کند و نسخه‌های جدید معمولاً شامل رفع اشکال‌های متعددی هستند. نصب خود را به‌روز نگه دارید.
برای CLI نصب‌شده از طریق npm:
```bash
rea update
```
برای به‌روزرسانی ثبت ایجنت‌ها و skill، دستور setup نمایش‌داده‌شده توسط به‌روزرسانی را اجرا کنید.
اگر از `npx` استفاده می‌کنید، راه‌اندازی ایجنت را با دستور زیر به‌روز کنید:
```bash
npx rea-agents@latest setup
```
تغییرات راه‌اندازی را بررسی کنید و ایجنت را دوباره اجرا کنید. برای اجرای یک‌بارهٔ دستورات CLI، از `npx rea-agents@latest` و سپس دستور موردنظر استفاده کنید.
## REA چگونه کار می‌کند؟
ایجنت شما از طریق MCP، REA را فراخوانی می‌کند تا هدف را بررسی و کد مرتبط را ردیابی کند. REA یافته‌ها را همراه با شواهد برمی‌گرداند. ایجنت از این نتایج برای طرح پرسش‌های تکمیلی، توضیح رفتار یا نوشتن و آزمایش یک پیاده‌سازی استفاده می‌کند. دستورات CLI نیز از همین گردش‌کارها بهره می‌برند.
![جریان بررسی REA: ایجنت دربارهٔ هدف محلی سؤال می‌پرسد، REA آن را با ابزارهای تحلیل بررسی و ردیابی می‌کند و ایجنت از کد، ارجاعات و ناشناخته‌های بازگردانده‌شده برای توضیح، پیاده‌سازی و آزمایش استفاده می‌کند.](website/public/assets/figures/rea-investigation-flow.svg)
[نمایش تصویر در اندازهٔ کامل](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## چه چیزهایی را می‌توان تحلیل کرد؟
REA به Node.js 22.x (>=22.19)، 24.x (>=24.11) یا 26+، به‌همراه npm نیاز دارد. ابزارهای اضافی و پشتیبانی سیستم میزبان به نوع هدف بستگی دارند:
| هدف | خروجی REA | پیش‌نیازها و راهنما |
| --------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| باینری‌های بومی | شبه‌کد، اسمبلی، رشته‌ها، نمادها، فراخوانی‌ها و ارجاعات | Hopper، Ghidra یا IDA؛ [تحلیل بومی](https://rea.tools/guides/native/) |
| ساختار ELF آفلاین | بخش‌ها، سگمنت‌ها، نمادها و relocationهای اصلی و گزینه‌های احتمالی کاهش آسیب‌پذیری ایستا | pwntools تأمین‌شده توسط فراخواننده روی Linux x64؛ [تشخیص باینری](docs/binary-diagnostics.md) |
| بایت‌کد EVM | selectorهای dispatch، offsetهای بایتی، آرگومان‌های استنباط‌شده و قابلیت تغییر وضعیت | دادهٔ خام/hex محلی روی Linux x64؛ [راهنمای EVM آفلاین](docs/evm-bytecode.md) |
| کرش‌های ثبت‌شدهٔ لینوکس | یادداشت‌های خام، رجیسترها/سیگنال‌های تمام threadهای ثبت‌شده و گزینه‌های احتمالی نگاشت | pwntools تأمین‌شده توسط فراخواننده روی Linux x64؛ GDB/pwndbg اختیاری؛ [کرش‌های ثبت‌شده](docs/recorded-crashes.md) |
| JavaScript / Electron | ماژول‌ها، importها، source mapها، مسیرها، IPC و ارتباط افزونه‌های بومی | Node.js و npm؛ [تحلیل برنامه](https://rea.tools/guides/javascript/) |
| وب‌سایت‌ها | ساختار صفحه، اسکریپت‌ها، مشاهدات شبکه و اسکرین‌شات‌های درخواستی | مرورگر مبتنی بر Chrome؛ [تحلیل مرورگر](https://rea.tools/guides/browser/) |
| داده‌های ضبط‌شدهٔ شبکه | درخواست‌ها، پاسخ‌ها، payloadهای آشکارشده و مکان آن‌ها در منبع | HAR؛ ابزار mitmdump در لینوکس برای ضبط‌های بومی mitmproxy؛ [راهنمای ضبط شبکه](docs/web-network-captures.md) |
| اسمبلی‌های .NET | فراداده، دستورالعمل‌های CIL، وابستگی‌های بومی اعلام‌شده و مقایسهٔ buildها | بررسی ایستا؛ [راهنمای کد مدیریت‌شده](docs/managed-code-analysis.md) |
| فایل‌های APK اندروید | تعاریف Manifest، کلاس‌ها، متدهای دیکامپایل‌شده و ارجاعات | JADX بدون رابط گرافیکی و JDK کامل در Linux/macOS/Windows x64؛ [راهنمای اندروید](docs/android-analysis.md) |
| دستگاه‌های اندروید | دستگاه‌ها، بسته‌ها، فرایندها، لاگ‌ها، دامپ‌ها، اسکرین‌شات‌ها و انتقال APK/فایل | adb تأمین‌شده توسط فراخوان‌کننده (شبیه‌ساز یا دستگاه)؛ [راهنمای ADB](docs/adb-device-analysis.md) |
| پروژه‌های JEB | واحدهای پروژه از موتور، هش‌های مصنوع و شبه‌کدِ نوع/متد | یک کلاینت JEB که توسط فراخوان‌کننده اجرا شده و MCP ارائه می‌دهد و با REA_JEB_MCP_URL انتخاب می‌شود؛ [راهنمای JEB](docs/jeb-analysis.md) |
| منابع اندروید | مانیفست رمزگشایی‌شده، جداول رشته‌ها، زبان‌ها و اطلاعات نسخه | راه‌انداز Apktool تأمین‌شده توسط فراخوان‌کننده؛ [راهنمای منابع](docs/apktool-resource-analysis.md) |
| Firmware | ناحیه‌ها، نتایج استخراج و تحویل به ابزارهای تحلیل بومی | Binwalk / Unblob در لینوکس؛ [راهنمای Firmware](docs/firmware-analysis.md) |
| بسته‌ها و منابع | فهرست فایل‌ها، digestها، فایل‌های plist، ساختار bundle اپل و منابع استخراج‌شده | [راهنمای آرتیفکت و JavaScript](docs/javascript-artifact-reconstruction.md)، [برنامه‌های اپل](docs/apple-application-analysis.md) |
| رفتار فرایند | خروجی ترمینال، تعاملات، وضعیت خروج، مشاهدات سیستم فایل و مقایسهٔ اجراها | Linux/macOS با PTY بومی؛ [ضبط فرایند](docs/process-capture.md) |
بررسی ایستای JavaScript و .NET فایل‌های ارائه‌شده را بدون اجرای برنامه می‌خواند. ضبط زمان اجرا، هدف انتخاب‌شده را با مجوزهای کاربری شما اجرا می‌کند یا با آن تعامل دارد؛ آثار این عملیات در راهنمای مربوط به هر نوع ضبط توضیح داده شده‌اند.
<a id="choosing-a-deep-analysis-provider"></a>
فرمت‌های بومی و پشتیبانی سیستم میزبان بر اساس ارائه‌دهنده متفاوت‌اند. [راه‌اندازی Hopper و Ghidra](docs/installation.md#hopper)، [راهنمای IDA](docs/ida-provider.md) و [پشتیبانی آزمایشی Ghidra در ویندوز](docs/windows-ghidra-p0.md) را ببینید. Ghidra همچنین از [تحلیل DOS شانزده‌بیتی](docs/ghidra-dos.md) پشتیبانی می‌کند. برای انتخاب ارائه‌دهنده، به [راهنمای CLI](docs/cli.md#choose-a-provider) مراجعه کنید. برای قابلیت‌هایی که پس از آخرین انتشار npm اضافه شده‌اند، [وضعیت انتشار](docs/installation.md#released-package-and-main) را بررسی کنید.
## نمونه‌های عملی
[![تصویرهایی از نمونه‌های پنینگ صدای DX-Ball، پل کلیپ‌بورد Notion و حلقهٔ گلوله‌های TH04](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: بازسازی محاسبهٔ موقعیت استریوی صدا
یک فراخوانی صوتی را تا تابع کمکی تبدیل موقعیت به pan دنبال کنید، دستورالعمل‌ها را بررسی کنید و شبه‌کد ناقص را به C تبدیل کنید. بازسازی حاصل، هر ۳٬۲۰۵ مورد آزمایش x86 اصلی را با موفقیت پشت سر می‌گذارد و هر ۶۳ بایت تابع کامپایل‌شده را دقیقاً بازتولید می‌کند.
[مطالعهٔ موردی](https://rea.tools/showcase/dx-ball/) · [مخزن بازسازی](https://github.com/N0zoM1z0/dx-ball)
### Notion: ردیابی پل کلیپ‌بورد Electron
API کلیپ‌بورد در renderer را پیدا کنید، مسیر آن را از preload و IPC تا فرایند اصلی دنبال کنید و قالب غنی کلیپ‌بورد را بررسی کنید.
[مطالعهٔ موردی](https://rea.tools/showcase/notion/)
### TH04: بازیابی محاسبهٔ حلقهٔ گلوله در DOS
دستورالعمل‌های ۱۶بیتی بازی اصلی PC-98 را بررسی کنید، محاسبات زاویهٔ ثابت و هدف‌گیری‌شده را بازیابی کنید و کد C++ بازسازی‌شده را با خروجی کامپایلر تاریخی مقایسه کنید.
[مطالعهٔ موردی](https://rea.tools/showcase/th04/) · [مخزن بازسازی](https://github.com/N0zoM1z0/th04)
اگر از REA برای بررسی موضوع جالبی استفاده کرده‌اید، خوشحال می‌شویم آن را به اشتراک بگذارید. یک [issue](https://github.com/morluto/rea/issues) یا [pull request](https://github.com/morluto/rea/pulls) ثبت کنید و هدف، پرسش خود، نقش REA و یافته‌هایتان را توضیح دهید.
## پرسش‌های متداول
<details><summary><strong>کدام ایجنت‌ها می‌توانند از REA استفاده کنند؟</strong></summary>
هر ایجنتی که از سرورهای MCP محلی پشتیبانی کند. فرایند setup، [ایجنت‌های پشتیبانی‌شده](docs/installation.md#supported-agents) را پیکربندی می‌کند؛ سایر کلاینت‌ها می‌توانند از [ثبت دستی MCP](docs/installation.md#mcp-registry) استفاده کنند.
</details>
<details><summary><strong>آیا به Hopper، Ghidra یا IDA نیاز دارم؟</strong></summary>
تحلیل عمیق بومی به یکی از آن‌ها نیاز دارد. بررسی ایستای JavaScript و .NET بدون موتور تحلیل بومی کار می‌کند. setup می‌تواند با تأیید شما Hopper را نصب کند؛ Ghidra و IDA از نصب‌های موجود شما استفاده می‌کنند. [راه‌اندازی ارائه‌دهنده](docs/installation.md#hopper) را ببینید.
</details>
<details><summary><strong>آیا باید ابتدا Hopper را اجرا کنم؟</strong></summary>
REA زمانی که عملیاتی به Hopper نیاز داشته باشد آن را اجرا می‌کند. در macOS، ممکن است هنگام نخستین اجرا پنجره‌ای برای انتخاب حالت آزمایشی یا فعال‌سازی مجوز نمایش داده شود. [راه‌اندازی Hopper و رفع اشکال](docs/installation.md#launcher-paths-and-troubleshooting) را ببینید.
</details>
<details><summary><strong>نصب skill از skills.sh چه کاری انجام می‌دهد؟</strong></summary>
این skill دستورالعمل‌های بررسی را برای ایجنت فراهم می‌کند. برای ثبت سرور MCP مربوط به REA و نصب دستورالعمل‌های متناظر، `npx rea-agents setup` را اجرا کنید و سپس ایجنت را مجدداً راه‌اندازی کنید. [نصب مستقل skill](docs/installation.md#skill-only-installation) را ببینید.
</details>
<details><summary><strong>REA چه نوع کدی برمی‌گرداند؟</strong></summary>
تحلیل بومی، شبه‌کد و اسمبلی برمی‌گرداند. تحلیل JavaScript/Electron ماژول‌ها و روابط میان آن‌ها را بازیابی می‌کند. ایجنت شما از این یافته‌ها برای نوشتن و آزمایش یک پیاده‌سازی استفاده می‌کند؛ [نمونه‌های عملی](#نمونههای-عملی) مثال‌های گام‌به‌گام ارائه می‌دهند.
</details>
<details><summary><strong>آیا REA برنامهٔ من را آپلود می‌کند؟</strong></summary>
REA اهداف را به‌صورت محلی تحلیل می‌کند. ایجنت شما نتایج ابزارها را دریافت می‌کند و ارائه‌دهندهٔ مدل آن سیاست مستقل خود را دربارهٔ داده‌ها دارد.
</details>
<details><summary><strong>اگر با خطا مواجه شدم چه کنم؟</strong></summary>
ابتدا به‌روزرسانی کنید؛ ممکن است مشکل در نسخه‌ای جدید رفع شده باشد.
برای CLI نصب‌شده با npm:
```bash
rea update
```
برای راه‌اندازی ایجنت با `npx`:
```bash
npx rea-agents@latest setup
```
اگر از ایجنت استفاده می‌کنید، [به‌روزرسانی راه‌اندازی](#بهروزرسانی-rea) را تکمیل و ایجنت را مجدداً اجرا کنید. همان کار را دوباره امتحان کنید. اگر مشکل ادامه داشت، یک [issue ثبت کنید](https://github.com/morluto/rea/issues) و نسخهٔ REA، نوع هدف، مراحل بازتولید و خروجی خطا را ذکر کنید.
</details>
## مستندات
از [راهنماهای عملی وب‌سایت](https://rea.tools/guides/) شروع کنید. برای گزینه‌های دقیق، پیش‌نیازها و قراردادهای خروجی:
- [نصب و راه‌اندازی](docs/installation.md): ثبت ایجنت، پیکربندی ارائه‌دهنده، به‌روزرسانی و حذف نصب.
- [آمادگی و رفع اشکال](docs/installation.md#check-readiness-for-your-task): عیب‌یابی یک ایجنت یا موتور تحلیل.
- [CLI و شواهد](docs/cli.md): دستورات، انتخاب ارائه‌دهنده، snapshotها، ورود/خروج داده و وضعیت‌های خروج.
- [قراردادهای MCP](docs/mcp-contracts.md) و [پرامپت‌های ایجنت](docs/mcp-prompts.md): نتایج ابزارها، نشست‌ها و بررسی‌های هدایت‌شده.
- [فهرست ابزارها](docs/mcp-contracts.md#generated-catalog): فهرست تولیدشده هنگام build از ابزارها، ارائه‌دهندگان و دستورات CLI.
- [نقشهٔ راه](docs/roadmap.md): برنامه‌های آینده و پیگیری قابلیت‌ها.
آسیب‌پذیری‌ها را از طریق [SECURITY.md](SECURITY.md) گزارش کنید.
## تاریخچهٔ ستاره‌ها
🎉 **۵۰٬۰۰۰ ستارهٔ GitHub — سپاسگزاریم!**
از همهٔ کسانی که از REA استفاده می‌کنند، خطاها را گزارش می‌دهند، قابلیت‌های جدید پیشنهاد می‌کنند، buildها را آزمایش می‌کنند و در بهبود پروژه مشارکت دارند سپاسگزاریم.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date"><picture><source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" /><source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" /><img alt="تاریخچهٔ ستاره‌های GitHub پروژهٔ REA" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" /></picture></a>
## سلب مسئولیت
REA ابزارهایی برای پژوهش، تحلیل و بازسازی قانونی در حوزهٔ مهندسی معکوس فراهم می‌کند. مسئولیت دریافت مجوزهای لازم و رعایت قوانین مربوط بر عهدهٔ شماست. این پروژه استفادهٔ غیرقانونی یا بدون مجوز را تأیید نمی‌کند.
## مشارکت
از کمک شما به REA استقبال می‌کنیم! برای گزارش خطا یا پیشنهاد قابلیت، یک [issue باز کنید](https://github.com/morluto/rea/issues) یا برای بهبود کد و مستندات [pull request بفرستید](https://github.com/morluto/rea/pulls).
برای راه‌اندازی محیط توسعه و بررسی‌ها، [CONTRIBUTING.md](CONTRIBUTING.md)، برای مراحل اعتبارسنجی [آزمایش‌ها](docs/testing.md) و برای ساختار پروژه [نقشهٔ معماری](docs/architecture.mermaid) را ببینید.
## مجوز
[MIT](LICENSE)
</div>
+287
View File
@@ -0,0 +1,287 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · **Français** · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA : rétro-ingénierie de tout
### Un seul MCP pour la rétro-ingénierie des binaires, des applications et du comportement à l'exécution.
**Repérez une fonctionnalité qui vous plaît. Comprenez son fonctionnement, jusqu'au niveau du binaire.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[Site web](https://rea.tools/) · [Guides](https://rea.tools/guides/) · [Études de cas](https://rea.tools/showcase/)**
[Démarrage rapide](#démarrage-rapide) · [Comment fonctionne REA](#comment-fonctionne-rea) · [Ce que vous pouvez analyser](#ce-que-vous-pouvez-analyser) · [Études de cas](#études-de-cas) · [Questions fréquentes](#questions-fréquentes) · [Documentation](#documentation)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA lance son pont d'analyse dans Hopper pendant l'inspection d'un binaire natif" width="1200" />
<br /><br />
<table aria-label="REA community">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>Rejoignez la communauté de rétro-ingénierie</strong>
</a><br />
<sub>Discord · Questions et réponses · Partage de projets</sub>
</td>
</tr>
</table>
<br />
</div>
---
Vous avez repéré dans une application une fonctionnalité que vous aimeriez avoir dans votre propre produit ? Demandez à votre agent de l'étudier avec REA. Il peut inspecter l'application sans son code source, expliquer le fonctionnement de la fonctionnalité, présenter les preuves et en construire une version pour votre projet.
REA connecte votre agent à des outils d'inspection de binaires natifs, d'applications JavaScript et Electron, d'assemblys .NET et de sites web. Les mêmes outils sont aussi disponibles depuis votre terminal. L'analyse s'exécute localement, et chaque conclusion s'accompagne des preuves et des limites sur lesquelles elle repose.
Setup enregistre REA auprès de votre agent et installe les instructions de workflow correspondantes. L'analyse native peut utiliser une installation existante de Hopper ou de Ghidra ; Setup peut aussi installer Hopper après votre accord. L'analyse statique JavaScript ne nécessite aucun de ces moteurs.
> **[Visitez le site web de REA](https://rea.tools/)** pour les instructions d'installation, des guides illustrés et des études de cas réelles.
## Démarrage rapide
### Configurer votre agent
Une fois Node.js et npm installés, exécutez :
```bash
npx rea-agents setup
```
Choisissez vos agents, vérifiez les modifications proposées et approuvez-les. Setup ajoute le serveur MCP de REA et les instructions de workflow correspondantes, et sauvegarde la configuration existante. Redémarrez ensuite votre agent.
Setup prend en charge Claude Code, Codex, Cursor, Gemini CLI, Grok Build et [d'autres agents](docs/installation.md#supported-agents). Consultez [Installation et configuration](docs/installation.md) pour la configuration des fournisseurs et l'enregistrement MCP manuel.
### Interroger votre agent
```text
Comprends comment fonctionne la recherche dans l'app Notes, montre-moi les preuves
et construis une fonctionnalité similaire pour mon projet.
```
Remplacez Notes par votre application cible et la fonctionnalité que vous voulez comprendre.
### Utiliser le terminal
Inspectez le répertoire extrait ou l'archive ASAR d'une application JavaScript/Electron :
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
Le résultat comprend les modules, les imports, les frontières Electron et les preuves associées. Remplacez le chemin par votre cible, par exemple `"D:/apps/example"` sous Windows.
Pour installer la commande `rea` pour un usage régulier :
```bash
npm install --global rea-agents
rea --help
```
Pour l'analyse native, configurez d'abord un fournisseur. Consultez le [guide CLI et Evidence](docs/cli.md) pour les commandes natives, le choix du fournisseur, les snapshots et l'utilisation dans des scripts.
### Mettre à jour REA
REA évolue rapidement, et les nouvelles versions apportent fréquemment des corrections de bugs. Maintenez votre installation à jour.
Pour une CLI installée avec npm :
```bash
rea update
```
Pour actualiser les enregistrements de vos agents et le skill, exécutez la commande setup affichée par la mise à jour.
Si vous utilisez `npx`, mettez à jour la configuration de votre agent avec :
```bash
npx rea-agents@latest setup
```
Vérifiez les modifications proposées par Setup et redémarrez votre agent. Pour des commandes CLI ponctuelles, utilisez `npx rea-agents@latest` suivi de la commande.
## Comment fonctionne REA
Votre agent appelle REA via MCP pour inspecter la cible et suivre le code pertinent. REA renvoie ses constatations avec les preuves correspondantes. L'agent s'en sert pour poser des questions complémentaires, expliquer le comportement, ou écrire et tester une implémentation. Les commandes CLI utilisent les mêmes workflows.
![Flux d'investigation de REA : votre agent pose une question sur une cible locale, REA l'inspecte et la trace avec des outils d'analyse, et l'agent utilise le code, les références et les inconnues renvoyés pour expliquer, implémenter et tester.](website/public/assets/figures/rea-investigation-flow.svg)
[Ouvrir la figure en taille réelle](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## Ce que vous pouvez analyser
REA nécessite Node.js 22.x (>=22.19), 24.x (>=24.11) ou 26+, ainsi que npm. Les outils supplémentaires et les hôtes pris en charge dépendent de la cible :
| Cible | Ce que REA renvoie | Prérequis et guide |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| Binaires natifs | Pseudo-code, assembleur, chaînes, symboles, appels et références | Hopper, Ghidra ou IDA ; [analyse native](https://rea.tools/guides/native/) |
| Structure ELF hors ligne | Sections, segments, symboles et relocations d'origine, et protections statiques candidates | pwntools fourni par l'utilisateur sous Linux x64 ; [diagnostics binaires](docs/binary-diagnostics.md) |
| Bytecode EVM | Sélecteurs de dispatch, offsets en octets, arguments inférés et mutabilité | Fichier local brut ou hexadécimal sous Linux x64 ; [guide EVM hors ligne](docs/evm-bytecode.md) |
| Crashs Linux enregistrés | Notes brutes, registres et signaux de chaque thread enregistré, et correspondances de mappings facultatives | pwntools fourni par l'utilisateur sous Linux x64 ; GDB/pwndbg en option ; [crashs enregistrés](docs/recorded-crashes.md) |
| JavaScript / Electron | Modules, imports, source maps, routes, IPC et relations avec les modules natifs | Node.js et npm ; [analyse d'applications](https://rea.tools/guides/javascript/) |
| Sites web | Structure des pages, scripts, observations réseau et captures d'écran demandées | Un navigateur de la famille Chrome ; [analyse du navigateur](https://rea.tools/guides/browser/) |
| Captures réseau enregistrées | Requêtes, réponses, payloads exposés et emplacements dans le code source | HAR ; mitmdump sous Linux pour les captures mitmproxy natives ; [guide des captures](docs/web-network-captures.md) |
| Assemblys .NET | Métadonnées, instructions CIL, dépendances natives déclarées et comparaisons de builds | Inspection statique ; [guide du code managé](docs/managed-code-analysis.md) |
| APK Android | Déclarations du manifeste, classes, méthodes décompilées et références | JADX headless et un JDK complet sous Linux/macOS/Windows x64 ; [guide Android](docs/android-analysis.md) |
| Appareils Android | Appareils, paquets, processus, journaux, dumps, captures d'écran et transferts d'APK/fichiers | adb fourni par l'appelant (émulateur ou appareil) ; [guide ADB](docs/adb-device-analysis.md) |
| Projets JEB | Unités de projet fournies par le moteur, condensés d'artefacts et pseudo-code de types/méthodes | Un client JEB démarré par l'appelant servant MCP, sélectionné via REA_JEB_MCP_URL ; [guide JEB](docs/jeb-analysis.md) |
| Ressources Android | Manifeste décodé, tables de chaînes, langues et faits de version | Lanceur Apktool fourni par l'appelant ; [guide des ressources](docs/apktool-resource-analysis.md) |
| Firmware | Régions, résultats d'extraction et passage de relais vers l'analyse native | Binwalk / Unblob sous Linux ; [guide firmware](docs/firmware-analysis.md) |
| Paquets et ressources | Inventaires de fichiers, empreintes, plists, anatomie des bundles Apple et ressources extraites | [Guide artefacts et JavaScript](docs/javascript-artifact-reconstruction.md), [applications Apple](docs/apple-application-analysis.md) |
| Comportement des processus | Sortie du terminal, interactions, code de sortie, observations du système de fichiers et comparaisons | Linux/macOS avec un PTY natif ; [capture de processus](docs/process-capture.md) |
L'inspection statique JavaScript et .NET lit les fichiers fournis sans exécuter l'application. La capture à l'exécution lance la cible choisie ou interagit avec elle avec vos permissions utilisateur ; chaque guide d'exécution décrit ses effets.
<a id="choosing-a-deep-analysis-provider"></a>
Les formats natifs et les hôtes pris en charge varient selon le fournisseur. Consultez [la configuration de Hopper et Ghidra](docs/installation.md#hopper), le [guide IDA](docs/ida-provider.md) et [la prise en charge expérimentale de Ghidra sous Windows](docs/windows-ghidra-p0.md). Ghidra prend aussi en charge [l'analyse DOS 16 bits](docs/ghidra-dos.md). Pour les gros binaires, augmentez son délai de démarrage avec `REA_GHIDRA_STARTUP_TIMEOUT_MS`. Pour le choix du fournisseur, consultez le [guide CLI](docs/cli.md#choose-a-provider). Vérifiez la [disponibilité dans les versions publiées](docs/installation.md#released-package-and-main) pour les fonctionnalités ajoutées depuis la dernière version npm.
## Études de cas
[![Illustrations des études sur la spatialisation sonore de DX-Ball, le pont du presse-papiers de Notion et le cercle de projectiles de TH04](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball : reconstruire un calcul de panoramique sonore
Suivez un appel sonore jusqu'à la fonction qui convertit une position en panoramique, inspectez ses instructions et transformez un pseudo-code incomplet en C. La reconstruction réussit 3 205 cas issus du x86 d'origine et reproduit à l'identique les 63 octets de la fonction compilée.
[Lire l'étude de cas](https://rea.tools/showcase/dx-ball/) · [Dépôt de la reconstruction](https://github.com/N0zoM1z0/dx-ball)
### Notion : suivre le pont du presse-papiers d'Electron
Trouvez l'API de presse-papiers du renderer, suivez-la à travers le preload et l'IPC jusqu'au processus principal, puis inspectez le format de presse-papiers enrichi.
[Lire l'étude de cas](https://rea.tools/showcase/notion/)
### TH04 : retrouver un calcul d'anneau de projectiles sous DOS
Inspectez les instructions 16 bits du jeu PC-98 d'origine, retrouvez les calculs d'angles fixes et visés, et comparez le C++ reconstruit avec la sortie du compilateur d'époque.
[Lire l'étude de cas](https://rea.tools/showcase/th04/) · [Dépôt de la reconstruction](https://github.com/N0zoM1z0/th04)
Si vous avez utilisé REA sur un projet intéressant, nous serions ravis de le découvrir. Partagez votre cas dans une [issue](https://github.com/morluto/rea/issues) ou une [pull request](https://github.com/morluto/rea/pulls), en précisant la cible, votre question, la manière dont REA vous a aidé et ce que vous avez découvert.
## Questions fréquentes
<details>
<summary><strong>Quels agents peuvent utiliser REA ?</strong></summary>
Tout agent compatible avec les serveurs MCP locaux. Setup configure les [agents pris en charge](docs/installation.md#supported-agents) ; les autres clients peuvent utiliser [l'enregistrement MCP manuel](docs/installation.md#mcp-registry).
</details>
<details>
<summary><strong>Ai-je besoin de Hopper, Ghidra ou IDA ?</strong></summary>
L'analyse native approfondie utilise l'un d'eux. L'inspection statique JavaScript et .NET fonctionne sans moteur d'analyse native. Setup peut installer Hopper après votre accord ; Ghidra et IDA utilisent vos installations existantes. Consultez [la configuration des fournisseurs](docs/installation.md#hopper).
</details>
<details>
<summary><strong>Dois-je lancer Hopper au préalable ?</strong></summary>
REA lance Hopper lorsqu'une opération en a besoin. Sous macOS, une boîte de dialogue de premier lancement peut vous demander de choisir le mode démo ou d'activer votre licence. Consultez [Démarrage et dépannage de Hopper](docs/installation.md#launcher-paths-and-troubleshooting).
</details>
<details>
<summary><strong>Que fait l'installation du skill depuis skills.sh ?</strong></summary>
Le skill fournit des instructions d'investigation à votre agent. Utilisez `npx rea-agents setup` pour enregistrer le serveur MCP de REA et installer les instructions correspondantes, puis redémarrez votre agent. Consultez [l'installation du skill seul](docs/installation.md#skill-only-installation).
</details>
<details>
<summary><strong>Quel code REA renvoie-t-il ?</strong></summary>
L'analyse native renvoie du pseudo-code et de l'assembleur. L'analyse JavaScript/Electron récupère les modules et leurs relations. Votre agent s'appuie sur ces résultats pour écrire et tester une implémentation ; les [études de cas](#études-de-cas) en donnent des exemples concrets.
</details>
<details>
<summary><strong>REA envoie-t-il mon application en ligne ?</strong></summary>
REA analyse les cibles localement. Votre agent reçoit les résultats des outils, et son fournisseur de modèle applique sa propre politique de données.
</details>
<details>
<summary><strong>Que faire si je rencontre un bug ?</strong></summary>
Commencez par mettre à jour ; une version récente l'a peut-être déjà corrigé.
Pour une CLI installée avec npm :
```bash
rea update
```
Pour une configuration d'agent via `npx` :
```bash
npx rea-agents@latest setup
```
Si vous utilisez un agent, terminez l'[actualisation de la configuration](#mettre-à-jour-rea) et redémarrez-le. Relancez la même tâche. Si le problème persiste, [ouvrez une issue](https://github.com/morluto/rea/issues) en indiquant votre version de REA, le type de cible, les étapes pour reproduire le problème et la sortie d'erreur.
</details>
## Documentation
Commencez par les [guides pas à pas](https://rea.tools/guides/) du site web. Pour les options exactes, les prérequis et les contrats de résultats :
- [Installation et configuration](docs/installation.md) : enregistrement des agents, configuration des fournisseurs, mises à jour et désinstallation.
- [Vérification et dépannage](docs/installation.md#check-readiness-for-your-task) : diagnostiquer un agent ou un moteur d'analyse précis.
- [CLI et Evidence](docs/cli.md) : commandes, choix du fournisseur, snapshots, import/export et codes de sortie.
- [Contrats MCP](docs/mcp-contracts.md) et [prompts pour agents](docs/mcp-prompts.md) : résultats des outils, sessions et investigations guidées.
- [Catalogue des outils](docs/mcp-contracts.md#generated-catalog) : inventaire des outils, fournisseurs et commandes CLI, généré lors du build.
- [Feuille de route](docs/roadmap.md) : travaux prévus et suivi des capacités.
Signalez les vulnérabilités via [SECURITY.md](SECURITY.md).
## Historique des étoiles
🎉 **50 000 étoiles GitHub — merci !**
Merci à toutes les personnes qui utilisent REA, signalent des bugs, proposent des fonctionnalités, testent les builds et contribuent des correctifs.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="Historique des étoiles GitHub de REA" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## Avertissement
REA fournit des outils destinés à la recherche, à l'analyse et à la reconstruction légales en rétro-ingénierie. Il vous appartient d'obtenir toute autorisation nécessaire et de respecter les lois applicables. Le projet n'encourage aucune utilisation illégale ou non autorisée.
## Contribuer
Votre aide sur REA est la bienvenue ! [Ouvrez une issue](https://github.com/morluto/rea/issues) pour signaler un bug ou proposer une fonctionnalité, ou [envoyez une pull request](https://github.com/morluto/rea/pulls) pour améliorer le code ou la documentation.
Consultez [CONTRIBUTING.md](CONTRIBUTING.md) pour l'environnement de développement et les vérifications, la page [tests](docs/testing.md) pour les filières de vérification, et la [carte de l'architecture](docs/architecture.mermaid) pour la structure du projet.
## Licence
[MIT](LICENSE)
+310
View File
@@ -0,0 +1,310 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · **Bahasa Indonesia** · [Italiano](README_it.md)
# REA: Rekayasa Balik Apa Pun
### Satu MCP untuk rekayasa balik pada berbagai biner, aplikasi, dan perilaku saat runtime.
**Melihat fitur yang Anda sukai. Pahami cara kerjanya hingga ke tingkat biner.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[Situs Web](https://rea.tools/) · [Panduan](https://rea.tools/guides/) · [Contoh Penggunaan](https://rea.tools/showcase/)**
[Mulai Cepat](#mulai-cepat) · [Cara Kerja REA](#cara-kerja-rea) · [Hal yang Dapat Anda Analisis](#hal-yang-dapat-anda-analisis) · [Contoh Penggunaan](#contoh-penggunaan) · [FAQ](#faq) · [Dokumentasi](#dokumentasi)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA menjalankan jembatan analisisnya di dalam Hopper saat memeriksa biner native" width="1200" />
<br /><br />
<table aria-label="Komunitas REA">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>Bergabunglah dengan Komunitas Rekayasa Balik</strong>
</a><br />
<sub>Discord · Tanya Jawab · Berbagi Hasil</sub>
</td>
</tr>
</table>
<br />
</div>
---
Melihat fitur dalam suatu aplikasi yang ingin Anda hadirkan di produk sendiri? Minta agen Anda menyelidikinya menggunakan REA. REA dapat memeriksa aplikasi tanpa kode sumbernya, menjelaskan cara kerja fitur tersebut, menunjukkan bukti, dan membangun versi untuk proyek Anda.
REA menghubungkan agen Anda dengan berbagai alat untuk memeriksa biner native, aplikasi JavaScript dan Electron, assembly .NET, serta situs web. Anda juga dapat menggunakan alat yang sama dari terminal. Analisis dijalankan secara lokal, dan hasilnya mencakup bukti serta keterbatasan yang mendasari setiap kesimpulan.
Proses penyiapan mendaftarkan REA ke agen Anda dan memasang instruksi alur kerja yang sesuai. Analisis native dapat menggunakan instalasi Hopper, Ghidra, atau IDA yang sudah ada. Proses penyiapan juga dapat memasang Hopper secara opsional setelah mendapatkan persetujuan. Analisis JavaScript statis tidak memerlukan mesin analisis native.
> **[Kunjungi situs web REA](https://rea.tools/)** untuk mendapatkan petunjuk penyiapan, panduan bergambar, dan studi kasus nyata.
## Mulai Cepat
### Siapkan agen Anda
Dengan Node.js dan npm yang telah terpasang, jalankan:
```bash
npx rea-agents setup
```
Pilih agen yang ingin digunakan, tinjau perubahan yang diusulkan, lalu setujui perubahan tersebut. Proses penyiapan menambahkan server MCP REA dan instruksi alur kerja yang sesuai, serta membuat cadangan konfigurasi yang sudah ada. Setelah itu, mulai ulang agen Anda.
Penyiapan mendukung Claude Code, Codex, Cursor, Gemini CLI, Grok Build, dan [agen lainnya](docs/installation.md#supported-agents). Lihat [instalasi dan penyiapan](docs/installation.md) untuk konfigurasi penyedia dan pendaftaran MCP secara manual.
### Minta agen Anda
```text
Pahami cara kerja pencarian di aplikasi Notes, tunjukkan buktinya, dan buat fitur serupa untuk proyek saya.
```
Ganti Notes dengan aplikasi target dan fitur yang ingin Anda pahami.
### Gunakan terminal
Periksa direktori aplikasi JavaScript/Electron yang telah diekstrak atau berkas ASAR:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
Hasilnya mencakup modul, impor, batas antarkomponen Electron, dan bukti yang mendasarinya. Ganti jalur tersebut dengan lokasi target Anda, misalnya `"D:/apps/example"` di Windows.
Untuk memasang perintah `rea` agar dapat digunakan secara rutin:
```bash
npm install --global rea-agents
rea --help
```
Untuk analisis native, konfigurasikan penyedia terlebih dahulu. Lihat [Panduan CLI dan Bukti](docs/cli.md) untuk perintah native, pemilihan penyedia, snapshot, dan pembuatan skrip.
### Perbarui REA
REA berkembang dengan cepat, dan rilis baru sering menyertakan perbaikan bug. Pastikan instalasi Anda selalu diperbarui.
Untuk CLI yang dipasang melalui npm:
```bash
rea update
```
Untuk memperbarui pendaftaran agen dan skill Anda, jalankan perintah penyiapan yang ditampilkan oleh proses pembaruan.
Jika Anda menggunakan `npx`, perbarui penyiapan agen dengan:
```bash
npx rea-agents@latest setup
```
Tinjau perubahan penyiapan dan mulai ulang agen Anda. Untuk menjalankan perintah CLI sekali pakai, gunakan `npx rea-agents@latest` diikuti dengan perintah yang diinginkan.
## Cara Kerja REA
Agen Anda memanggil REA melalui MCP untuk memeriksa target dan menelusuri kode yang relevan. REA mengembalikan temuan beserta bukti pendukungnya. Agen kemudian menggunakan temuan tersebut untuk mengajukan pertanyaan lanjutan, menjelaskan perilaku, atau menulis dan menguji implementasi.
Perintah CLI menggunakan alur kerja yang sama.
![Alur investigasi REA: agen Anda menanyakan sesuatu tentang target lokal, REA memeriksa dan menelusurinya menggunakan alat analisis, lalu agen menggunakan kode, referensi, dan hal-hal yang belum diketahui dari hasil tersebut untuk menjelaskan, mengimplementasikan, dan menguji.](website/public/assets/figures/rea-investigation-flow.svg)
[Buka ilustrasi dalam ukuran penuh](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## Hal yang Dapat Anda Analisis
REA memerlukan Node.js 22.x (>=22.19), 24.x (>=24.11), atau 26+, beserta npm.
Alat tambahan dan dukungan sistem host bergantung pada target yang dianalisis:
| Target | Hasil yang diberikan REA | Persyaratan dan panduan |
| -------------------------- | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| Biner native | Pseudocode, assembly, string, simbol, pemanggilan, dan referensi | Hopper, Ghidra, atau IDA; [analisis native](https://rea.tools/guides/native/) |
| Tata letak ELF offline | Bagian, segmen, simbol/relokasi asli, dan kandidat mitigasi statis | pwntools yang disediakan pemanggil pada Linux x64; [diagnostik biner](docs/binary-diagnostics.md) |
| Bytecode EVM | Selector dispatch, offset byte, argumen yang disimpulkan, dan sifat mutabilitas | Pembawa data raw/hex lokal; [panduan EVM offline](docs/evm-bytecode.md) |
| Crash Linux yang direkam | Catatan mentah, register/sinyal setiap thread yang direkam, dan kandidat pemetaan opsional | pwntools yang disediakan pemanggil; GDB/pwndbg opsional; [crash yang direkam](docs/recorded-crashes.md) |
| JavaScript / Electron | Modul, impor, source map, rute, IPC, dan hubungan add-on native | Node.js dan npm; [analisis aplikasi](https://rea.tools/guides/javascript/) |
| Situs web | Struktur halaman, skrip, pengamatan jaringan, dan tangkapan layar yang diminta | Peramban berbasis Chrome; [analisis peramban](https://rea.tools/guides/browser/) |
| Rekaman jaringan tersimpan | Permintaan, respons, payload yang terekspos, dan lokasi sumber | HAR; mitmdump di Linux untuk rekaman native mitmproxy; [panduan rekaman](docs/web-network-captures.md) |
| Assembly .NET | Metadata, instruksi CIL, dependensi native yang dideklarasikan, dan perbandingan build | Tidak ada (hanya analisis statis); [panduan kode terkelola](docs/managed-code-analysis.md) |
| APK Android | Deklarasi manifest, kelas, metode hasil dekompilasi, dan referensi | JADX mode headless dan JDK lengkap di Linux/macOS/Windows x64; [panduan Android](docs/android-analysis.md) |
| Perangkat Android | Perangkat, paket, proses, log, dump, tangkapan layar, serta transfer APK/berkas | adb buatan pemanggil (emulator atau perangkat); [panduan ADB](docs/adb-device-analysis.md) |
| Proyek JEB | Unit proyek bertenaga mesin, hash artefak, dan pseudokode tipe/metode | Klien JEB yang dijalankan pemanggil dan menyajikan MCP, dipilih dengan REA_JEB_MCP_URL; [panduan JEB](docs/jeb-analysis.md) |
| Resource Android | Manifest terdekode, tabel string, lokal, dan fakta versi | Peluncur Apktool buatan pemanggil; [panduan resource](docs/apktool-resource-analysis.md) |
| Firmware | Wilayah, hasil ekstraksi, dan pengalihan ke analisis native | Binwalk / Unblob di Linux; [panduan firmware](docs/firmware-analysis.md) |
| Paket dan sumber daya | Inventaris berkas, digest, plist, struktur paket Apple, dan sumber daya yang diekstrak | [Panduan artefak dan JavaScript](docs/javascript-artifact-reconstruction.md), [aplikasi Apple](docs/apple-application-analysis.md) |
| Perilaku proses | Keluaran terminal, interaksi, pengamatan proses keluar dan sistem berkas, serta perbandingan eksekusi | Linux/macOS dengan PTY native; [perekaman proses](docs/process-capture.md) |
Pemeriksaan JavaScript dan .NET statis membaca berkas yang disediakan tanpa menjalankan aplikasinya. Perekaman runtime menjalankan atau berinteraksi dengan target yang dipilih menggunakan izin pengguna Anda. Setiap panduan runtime menjelaskan dampaknya.
<a id="choosing-a-deep-analysis-provider"></a>
Format native dan dukungan sistem host berbeda-beda menurut penyedia. Lihat [penyiapan Hopper dan Ghidra](docs/installation.md#hopper), [panduan IDA](docs/ida-provider.md), dan [dukungan eksperimental Ghidra di Windows](docs/windows-ghidra-p0.md).
Ghidra juga mendukung [analisis DOS 16-bit](docs/ghidra-dos.md).
Untuk biner berukuran besar, tingkatkan batas waktu startup menggunakan `REA_GHIDRA_STARTUP_TIMEOUT_MS`.
Untuk memilih penyedia, lihat [panduan CLI](docs/cli.md#choose-a-provider).
Periksa [ketersediaan rilis](docs/installation.md#released-package-and-main) untuk mengetahui fitur yang ditambahkan setelah rilis npm terbaru.
## Contoh Penggunaan
[![Ilustrasi contoh penggunaan DX-Ball sound-pan, Notion clipboard-bridge, dan TH04 bullet-ring](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: merekonstruksi perhitungan sound-pan
Ikuti pemanggilan suara hingga ke fungsi pembantu yang mengubah posisi menjadi nilai pan, periksa instruksinya, lalu ubah pseudocode yang belum lengkap menjadi C. Hasil rekonstruksi tersebut lolos pada 3.205 kasus x86 asli dan mereproduksi seluruh 63 byte fungsi hasil kompilasi.
[Baca studi kasus](https://rea.tools/showcase/dx-ball/) · [Repositori rekonstruksi](https://github.com/N0zoM1z0/dx-ball)
### Notion: menelusuri jembatan clipboard Electron
Temukan API clipboard pada renderer, telusuri jalurnya melalui preload dan IPC hingga ke proses utama, lalu periksa format clipboard kaya.
[Baca studi kasus](https://rea.tools/showcase/notion/)
### TH04: memulihkan perhitungan bullet-ring DOS
Periksa instruksi 16-bit dari gim PC-98 asli, pulihkan perhitungan sudut tetap dan sudut yang diarahkan, lalu bandingkan C++ hasil rekonstruksi dengan keluaran historis kompiler.
[Baca studi kasus](https://rea.tools/showcase/th04/) · [Repositori rekonstruksi](https://github.com/N0zoM1z0/th04)
Jika Anda telah menggunakan REA untuk menganalisis sesuatu yang menarik, kami ingin melihat hasilnya. Bagikan kasus Anda melalui [issue](https://github.com/morluto/rea/issues) atau [pull request](https://github.com/morluto/rea/pulls), sertakan target, pertanyaan Anda, bagaimana REA membantu, dan apa yang Anda temukan.
## FAQ
<details>
<summary><strong>Agen apa saja yang dapat menggunakan REA?</strong></summary>
Agen apa pun yang mendukung server MCP lokal dapat menggunakan REA. Proses penyiapan mengonfigurasi [agen yang didukung](docs/installation.md#supported-agents). Klien lain dapat menggunakan [pendaftaran MCP manual](docs/installation.md#mcp-registry).
</details>
<details>
<summary><strong>Apakah saya memerlukan Hopper, Ghidra, atau IDA?</strong></summary>
Analisis native mendalam menggunakan salah satu dari ketiganya. Pemeriksaan JavaScript dan .NET statis dapat dilakukan tanpa mesin analisis native.
Proses penyiapan dapat memasang Hopper setelah memperoleh persetujuan. Ghidra dan IDA menggunakan instalasi yang sudah tersedia. Lihat [penyiapan penyedia](docs/installation.md#hopper).
</details>
<details>
<summary><strong>Apakah saya harus menjalankan Hopper terlebih dahulu?</strong></summary>
REA akan menjalankan Hopper saat suatu operasi membutuhkannya. Di macOS, dialog saat pertama kali dijalankan mungkin meminta Anda memilih mode demo atau mengaktifkan lisensi.
Lihat [startup dan pemecahan masalah Hopper](docs/installation.md#launcher-paths-and-troubleshooting).
</details>
<details>
<summary><strong>Apa fungsi memasang skill dari skills.sh?</strong></summary>
Skill tersebut menyediakan instruksi investigasi untuk agen Anda. Gunakan `npx rea-agents setup` untuk mendaftarkan server MCP REA dan memasang instruksi yang sesuai, lalu mulai ulang agen Anda.
Lihat [instalasi khusus skill](docs/installation.md#skill-only-installation).
</details>
<details>
<summary><strong>Kode seperti apa yang dihasilkan REA?</strong></summary>
Analisis native menghasilkan pseudocode dan assembly. Analisis JavaScript/Electron memulihkan modul dan hubungan antarmodulnya. Agen Anda menggunakan temuan tersebut untuk menulis dan menguji implementasi. [Contoh penggunaan](#contoh-penggunaan) menyediakan contoh yang telah dikerjakan.
</details>
<details>
<summary><strong>Apakah REA mengunggah aplikasi saya?</strong></summary>
REA menganalisis target secara lokal. Agen Anda menerima hasil alat, sedangkan penyedia model yang digunakannya memiliki kebijakan datanya sendiri.
</details>
<details>
<summary><strong>Apa yang harus saya lakukan jika menemukan bug?</strong></summary>
Perbarui terlebih dahulu. Rilis terbaru mungkin sudah memperbaiki masalah tersebut.
Untuk CLI yang dipasang melalui npm:
```bash
rea update
```
Untuk penyiapan agen melalui `npx`:
```bash
npx rea-agents@latest setup
```
Jika Anda menggunakan agen, selesaikan [pembaruan penyiapan](#perbarui-rea) dan mulai ulang agen tersebut.
Coba kembali tugas yang sama. Jika masalah masih terjadi, [buat issue](https://github.com/morluto/rea/issues) dengan menyertakan versi REA, jenis target, langkah-langkah untuk mereproduksi masalah, dan keluaran kesalahan.
</details>
## Dokumentasi
Mulailah dengan [panduan praktik di situs web](https://rea.tools/guides/).
Untuk mengetahui opsi, prasyarat, dan kontrak hasil secara tepat:
- [Instalasi dan penyiapan](docs/installation.md): pendaftaran agen, konfigurasi penyedia, pembaruan, dan penghapusan instalasi.
- [Kesiapan dan pemecahan masalah](docs/installation.md#check-readiness-for-your-task): mendiagnosis satu agen atau mesin analisis.
- [CLI dan Bukti](docs/cli.md): perintah, pemilihan penyedia, snapshot, impor/ekspor, dan status keluar.
- [Kontrak MCP](docs/mcp-contracts.md) dan [prompt agen](docs/mcp-prompts.md): hasil alat, sesi, dan investigasi terpandu.
- [Katalog alat](docs/mcp-contracts.md#generated-catalog): inventaris alat, penyedia, dan perintah CLI yang dibuat secara otomatis.
- [Peta jalan](docs/roadmap.md): pekerjaan yang direncanakan dan pelacak kemampuan.
Laporkan kerentanan melalui [SECURITY.md](SECURITY.md).
## Riwayat Bintang
🎉 **50.000 bintang GitHub, terima kasih!**
Terima kasih kepada semua orang yang menggunakan REA, melaporkan bug, meminta fitur, menguji build, dan berkontribusi dalam perbaikan.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="Riwayat bintang GitHub REA" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## Penafian
REA menyediakan alat untuk penelitian, analisis, dan rekonstruksi rekayasa balik yang sah. Anda bertanggung jawab untuk memperoleh otorisasi yang diperlukan dan mematuhi hukum yang berlaku. Proyek ini tidak mendukung penggunaan ilegal atau tanpa izin.
REA adalah proyek perangkat lunak sumber terbuka. Kami tidak menerbitkan atau mendukung mata uang kripto maupun token apa pun. Token yang menggunakan nama REA tidak berafiliasi dengan proyek ini.
## Kontribusi
Kami sangat menghargai bantuan Anda untuk REA! [Buat issue](https://github.com/morluto/rea/issues) untuk melaporkan bug atau menyarankan fitur, atau [kirim pull request](https://github.com/morluto/rea/pulls) untuk meningkatkan kode atau dokumentasi.
Lihat [CONTRIBUTING.md](CONTRIBUTING.md) untuk penyiapan pengembangan dan pemeriksaan, [pengujian](docs/testing.md) untuk tahapan verifikasi, serta [peta arsitektur](docs/architecture.mermaid) untuk struktur proyek.
## Lisensi
[MIT](LICENSE)
+289
View File
@@ -0,0 +1,289 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · **Italiano**
# REA: Reverse Engineer Anything
### Un unico MCP per l'ingegneria inversa su binari, applicazioni e comportamento a runtime.
**Vedi una funzionalità che ti piace. Capisci come funziona, fino al livello binario.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#cosa-puoi-analizzare)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[Sito web](https://rea.tools/) · [Guide](https://rea.tools/guides/) · [Showcase](https://rea.tools/showcase/)**
[Quick start](#quick-start) · [Come funziona REA](#come-funziona-rea) · [Cosa puoi analizzare](#cosa-puoi-analizzare) · [Showcase](#showcase) · [FAQ](#faq) · [Documentazione](#documentazione)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA che avvia il suo bridge di analisi dentro Hopper mentre ispeziona un binario nativo" width="1200" />
<br /><br />
<table aria-label="Community REA">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>Unisciti alla community di ingegneria inversa</strong>
</a><br />
<sub>Discord · Domande e risposte · Show and Tell</sub>
</td>
</tr>
</table>
<br />
</div>
---
Hai visto una funzionalità in un'app che vorresti nel tuo prodotto? Chiedi al tuo agente di analizzarla con REA. Può ispezionare l'app senza il suo codice sorgente, spiegare come funziona la funzionalità, mostrare le prove e realizzare una versione per il tuo progetto.
REA collega il tuo agente a strumenti per ispezionare binari nativi, app JavaScript ed Electron, assembly .NET e siti web. Puoi usare gli stessi strumenti anche dal terminale. L'analisi viene eseguita localmente e i risultati includono le prove e i limiti dietro ogni conclusione.
La configurazione registra REA con il tuo agente e installa le istruzioni di workflow corrispondenti. L'analisi nativa può usare un'installazione esistente di Hopper, Ghidra o IDA; la configurazione può installare opzionalmente Hopper previa approvazione. L'analisi statica JavaScript non richiede alcun motore di analisi nativo.
> **[Visita il sito web di REA](https://rea.tools/)** per istruzioni di configurazione, guide illustrate e veri casi studio.
## Quick start
### Configura il tuo agente
Con Node.js e npm installati, esegui:
```bash
npx rea-agents setup
```
Scegli i tuoi agenti, rivedi le modifiche proposte e approvale. La configurazione aggiunge il server MCP di REA e le istruzioni di workflow corrispondenti, con backup della configurazione esistente. Riavvia quindi il tuo agente.
La configurazione supporta Claude Code, Codex, Cursor, Gemini CLI, Grok Build e [altri agenti](docs/installation.md#supported-agents). Vedi [installazione e configurazione](docs/installation.md) per la configurazione dei provider e la registrazione manuale MCP.
### Chiedi al tuo agente
```text
Spiega come funziona la ricerca nell'app Note, mostrami le prove e realizza
una funzionalità simile per il mio progetto.
```
Sostituisci Note con la tua app di destinazione e la funzionalità che vuoi capire.
### Usa il terminale
Ispeziona una directory di app JavaScript/Electron estratta o un ASAR:
```bash
npx -y rea-agents@latest analyze-javascript-application /percorso/assoluto/verso/app --json
```
Il risultato include moduli, import, confini Electron e le relative prove. Sostituisci il percorso con il tuo bersaglio, ad esempio `"D:/apps/example"` su Windows.
Per installare il comando `rea` per un uso regolare:
```bash
npm install --global rea-agents
rea --help
```
Per l'analisi nativa, configura prima un provider. Vedi la [guida CLI ed Evidence](docs/cli.md) per i comandi nativi, la selezione del provider, gli snapshot e lo scripting.
### Aggiorna REA
REA cambia rapidamente e le nuove versioni includono correzioni di bug frequenti. Tieni aggiornata la tua installazione.
Per una CLI installata via npm:
```bash
rea update
```
Per aggiornare le registrazioni del tuo agente e lo skill, esegui il comando di configurazione mostrato dall'aggiornamento.
Se usi `npx`, aggiorna la configurazione del tuo agente con:
```bash
npx rea-agents@latest setup
```
Rivedi le modifiche di configurazione e riavvia il tuo agente. Per comandi CLI singoli, usa `npx rea-agents@latest` seguito dal comando.
## Come funziona REA
Il tuo agente chiama REA tramite MCP per ispezionare il bersaglio e tracciare il codice rilevante. REA restituisce i risultati con le relative prove. L'agente li usa per fare domande di approfondimento, spiegare il comportamento o scrivere e testare un'implementazione. Anche i comandi CLI usano gli stessi workflow.
![Flusso di indagine REA: il tuo agente pone domande su un bersaglio locale, REA lo ispeziona e ne traccia il codice usando strumenti di analisi, e l'agente usa il codice, i riferimenti e gli elementi sconosciuti restituiti per spiegare, implementare e testare.](website/public/assets/figures/rea-investigation-flow.svg)
[Apri la figura a dimensione intera](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## Cosa puoi analizzare
REA richiede Node.js 22.x (>=22.19), 24.x (>=24.11) o 26+, oltre a npm. Strumenti aggiuntivi e supporto host dipendono dal bersaglio:
| Obiettivo | Cosa restituisce REA | Requisiti e guida |
| ---------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Binari nativi | Pseudocodice, assembly, stringhe, simboli, chiamate e riferimenti | Hopper, Ghidra o IDA; [analisi nativa](https://rea.tools/guides/native/) |
| Layout ELF offline | Sezioni, segmenti, simboli/relocazioni originali e candidati mitigazioni statiche | pwntools fornito dal chiamante su Linux x64; [diagnostica binaria](docs/binary-diagnostics.md) |
| Bytecode EVM | Selettori di dispatch, offset dei byte, argomenti inferiti e mutabilità | Carrier raw/hex locale; [guida EVM offline](docs/evm-bytecode.md) |
| Crash Linux registrati | Note grezze, registri/segnai di ogni thread registrato e candidati mapping opzionali | pwntools fornito dal chiamante; GDB/pwndbg opzionale; [crash registrati](docs/recorded-crashes.md) |
| JavaScript / Electron | Moduli, import, source map, route, IPC e relazioni con add-on nativi | Node.js e npm; [analisi delle applicazioni](https://rea.tools/guides/javascript/) |
| Siti web | Struttura della pagina, script, osservazioni di rete e screenshot richiesti | Un browser della famiglia Chrome; [analisi browser](https://rea.tools/guides/browser/) |
| Acquisizioni di rete salvate | Richieste, risposte, payload esposti e posizioni sorgente | HAR; mitmdump su Linux per acquisizioni mitmproxy native; [guida alle acquisizioni](docs/web-network-captures.md) |
| Assembly .NET | Metadati, istruzioni CIL, dipendenze native dichiarate e confronti di build | Nessuno (solo statico); [guida managed-code](docs/managed-code-analysis.md) |
| APK Android | Dichiarazioni manifest, classi, metodi decompilati e riferimenti | JADX headless e un JDK completo su Linux/macOS/Windows x64; [guida Android](docs/android-analysis.md) |
| Dispositivi Android | Dispositivi, pacchetti, processi, log, dump, screenshot e trasferimenti APK/file | adb fornito dal chiamante (emulatore o hardware); [guida ADB](docs/adb-device-analysis.md) |
| Progetti JEB | Unità di progetto dal motore, digest degli artifact e pseudocodice di tipi/metodi | Client JEB avviato dal chiamante via MCP, selezionato con REA_JEB_MCP_URL; [guida JEB](docs/jeb-analysis.md) |
| Risorse Android | Manifest decodificato, tabelle stringhe, lingue e dati di versione | Launcher Apktool fornito dal chiamante; [guida alle risorse](docs/apktool-resource-analysis.md) |
| Firmware | Regioni, risultati di estrazione e passaggi all'analisi nativa | Binwalk / Unblob su Linux; [guida firmware](docs/firmware-analysis.md) |
| Pacchetti e risorse | Inventari file, digest, plist, anatomia dei bundle Apple e risorse estratte | [Guida artifact e JavaScript](docs/javascript-artifact-reconstruction.md), [Applicazioni Apple](docs/apple-application-analysis.md) |
| Comportamento dei processi | Output del terminale, interazioni, osservazioni su uscita e filesystem ed confronti di esecuzione | Linux/macOS con un PTY nativo; [cattura dei processi](docs/process-capture.md) |
L'ispezione statica di JavaScript e .NET legge i file forniti senza eseguire l'applicazione. La cattura a runtime esegue o interagisce con il bersaglio selezionato usando i tuoi permessi utente; ogni guida runtime descrive i suoi effetti.
<a id="choosing-a-deep-analysis-provider"></a>
I formati nativi e il supporto host variano in base al provider. Vedi la [configurazione di Hopper e Ghidra](docs/installation.md#hopper), la [guida IDA](docs/ida-provider.md) e il [supporto sperimentale Windows Ghidra](docs/windows-ghidra-p0.md). Ghidra supporta anche l'[analisi DOS a 16 bit](docs/ghidra-dos.md). Per binari di grandi dimensioni, aumenta il timeout di avvio con `REA_GHIDRA_STARTUP_TIMEOUT_MS`. Per la selezione del provider, vedi la [guida CLI](docs/cli.md#choose-a-provider). Controlla la [disponibilità delle release](docs/installation.md#released-package-and-main) per le funzionalità aggiunte dall'ultima release npm.
## Showcase
[![Illustrazioni degli showcase del sound-pan di DX-Ball, del clipboard-bridge di Notion e dell'anello di proiettili di TH04](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: ricostruisci un calcolo sound-pan
Segui una chiamata sonora fino al suo helper posizione-to-pan, ispeziona le istruzioni e trasforma il pseudocodice incompleto in C. La ricostruzione supera 3.205 casi x86 originali e riproduce tutti i 63 byte di funzione compilati.
[Leggi il case study](https://rea.tools/showcase/dx-ball/) · [Repository di ricostruzione](https://github.com/N0zoM1z0/dx-ball)
### Notion: traccia il clipboard bridge di Electron
Trova l'API clipboard del renderer, seguila attraverso preload e IPC fino al processo principale e ispeziona il formato rich clipboard.
[Leggi il case study](https://rea.tools/showcase/notion/)
### TH04: recupera un calcolo dell'anello di proiettili DOS
Ispeziona le istruzioni a 16 bit del gioco PC-98 originale, recupera i calcoli dell'angolo fisso e mirato e confronta il C++ ricostruito con l'output del compilatore storico.
[Leggi il case study](https://rea.tools/showcase/th04/) · [Repository di ricostruzione](https://github.com/N0zoM1z0/th04)
Se hai usato REA su qualcosa di interessante, ci piacerebbe vederlo. Condividi il tuo caso in una [issue](https://github.com/morluto/rea/issues) o in una [pull request](https://github.com/morluto/rea/pulls), includendo il bersaglio, la tua domanda, come REA ti ha aiutato e cosa hai scoperto.
## FAQ
<details>
<summary><strong>Quali agenti possono usare REA?</strong></summary>
Qualsiasi agente che supporti server MCP locali. La configurazione configura gli [agenti supportati](docs/installation.md#supported-agents); altri client possono usare la [registrazione MCP manuale](docs/installation.md#mcp-registry).
</details>
<details>
<summary><strong>Ho bisogno di Hopper, Ghidra o IDA?</strong></summary>
L'analisi nativa profonda ne usa uno. L'ispezione statica di JavaScript e .NET funziona senza un motore di analisi nativo. La configurazione può installare Hopper previa approvazione; Ghidra e IDA usano le tue installazioni esistenti. Vedi [configurazione provider](docs/installation.md#hopper).
</details>
<details>
<summary><strong>Devo avviare Hopper per primo?</strong></summary>
REA avvia Hopper quando un'operazione ne ha bisogno. Su macOS, una finestra di dialogo al primo avvio potrebbe chiederti di scegliere la modalità demo o di attivare la licenza. Vedi [avvio di Hopper e risoluzione dei problemi](docs/installation.md#launcher-paths-and-troubleshooting).
</details>
<details>
<summary><strong>Cosa fa l'installazione dello skill da skills.sh?</strong></summary>
Lo skill fornisce istruzioni di indagine per il tuo agente. Usa `npx rea-agents setup` per registrare il server MCP di REA e installare le istruzioni corrispondenti, quindi riavvia il tuo agente. Vedi [installazione solo skill](docs/installation.md#skill-only-installation).
</details>
<details>
<summary><strong>Quale codice restituisce REA?</strong></summary>
L'analisi nativa restituisce pseudocodice e assembly. L'analisi JavaScript/Electron recupera moduli e le loro relazioni. Il tuo agente usa questi risultati per scrivere e testare un'implementazione; gli [showcase](#showcase) offrono esempi concreti.
</details>
<details>
<summary><strong>REA carica la mia app da qualche parte?</strong></summary>
REA analizza i bersagli localmente. Il tuo agente riceve i risultati degli strumenti e il suo provider di modello ha la propria politica sui dati.
</details>
<details>
<summary><strong>Cosa devo fare se trovo un bug?</strong></summary>
Aggiorna prima; una release recente potrebbe averlo già risolto.
Per una CLI installata via npm:
```bash
rea update
```
Per la configurazione dell'agente tramite `npx`:
```bash
npx rea-agents@latest setup
```
Se stai usando un agente, completa l'[aggiornamento della configurazione](#aggiorna-rea) e riavvialo. Riprova lo stesso task. Se il problema persiste, [apri un issue](https://github.com/morluto/rea/issues) con la tua versione di REA, il tipo di bersaglio, i passaggi per riprodurlo e l'output di errore.
</details>
## Documentazione
Inizia dalle [guide pratiche](https://rea.tools/guides/) del sito web. Per opzioni esatte, prerequisiti e contratti dei risultati:
- [Installazione e configurazione](docs/installation.md): registrazione agente, configurazione provider, aggiornamenti e disinstallazione.
- [Pronto all'uso e risoluzione dei problemi](docs/installation.md#check-readiness-for-your-task): diagnostica un agente o un motore di analisi.
- [CLI ed Evidence](docs/cli.md): comandi, selezione provider, snapshot, import/export e stati di uscita.
- [Contratti MCP](docs/mcp-contracts.md) e [prompt agente](docs/mcp-prompts.md): risultati degli strumenti, sessioni e indagini guidate.
- [Catalogo strumenti](docs/mcp-contracts.md#generated-catalog): inventario generato di strumenti, provider e comandi CLI.
- [Roadmap](docs/roadmap.md): lavoro pianificato e tracker delle capacità.
Segnala vulnerabilità tramite [SECURITY.md](SECURITY.md).
## Cronologia delle stelle
🎉 **50.000 stelle su GitHub — grazie!**
Grazie a tutti coloro che usano REA, segnalano bug, propongono funzionalità, testano le build e contribuiscono con correzioni.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="Cronologia stelle GitHub di REA" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## Disclaimer
REA fornisce strumenti per la ricerca, l'analisi e la ricostruzione di ingegneria inversa lecita. Sei responsabile di ottenere le eventuali autorizzazioni richieste e di rispettare le leggi applicabili. Il progetto non approva l'uso illegale o non autorizzato.
REA è un progetto software open-source. Non abbiamo emesso né approvato alcuna criptovaluta o token. I token che usano il nome REA non sono affiliati al progetto.
## Contributing
Apprezzeremmo il tuo aiuto con REA! [Apri un issue](https://github.com/morluto/rea/issues) per segnalare un bug o suggerire una funzionalità, oppure [invia una pull request](https://github.com/morluto/rea/pulls) per migliorare il codice o la documentazione.
Vedi [CONTRIBUTING.md](CONTRIBUTING.md) per la configurazione di sviluppo e i controlli, [testing](docs/testing.md) per le lane di verifica e la [mappa dell'architettura](docs/architecture.mermaid) per la struttura del progetto.
## License
[MIT](LICENSE)
+178 -275
View File
@@ -1,27 +1,36 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · **日本語** · [한국어](README_ko.md) · [العربية](README_ar.md)
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · **日本語** · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA:あらゆるものをリバースエンジニアリング
### バイナリ、アプリ、実行時の動作をひとつの MCP でリバースエンジニアリング。
### バイナリ、アプリケーション、実行時の動作を、ひとつの MCP でリバースエンジニアリング。
**気に入った機能を見つけたら、その仕組みをバイナリのレベルまで理解する。**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](#調査ツールカタログ)
[![Node.js 22+](https://img.shields.io/badge/Node.js-22.19%2B-339933?style=flat-square&logo=nodedotjs&logoColor=white)](https://nodejs.org/)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[ウェブサイト(英語)](https://morluto.github.io/rea/) · [ガイド](https://morluto.github.io/rea/guides/) · [DX-Ball の事例](https://morluto.github.io/rea/showcase/dx-ball/)**
**[ウェブサイト](https://rea.tools/) · [ガイド](https://rea.tools/guides/) · [事例](https://rea.tools/showcase/)**
[クイックスタート](#クイックスタート) · [現在の対応状況](#現在の対応状況) · [バイナリから動作へ](#バイナリから動作へ) · [調査ツールカタログ](#調査ツールカタログ) · [ロードマップ](#ロードマップ) · [仕組み](#仕組み)
[クイックスタート](#クイックスタート) · [REA の仕組み](#rea-の仕組み) · [分析できる対象](#分析できる対象) · [事例](#事例) · [よくある質問](#よくある質問) · [ドキュメント](#ドキュメント)
<table aria-label="REA community">
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA が Hopper 内で分析ブリッジを起動し、ネイティブバイナリを調べる様子" width="1200" />
<br /><br />
<table aria-label="REA コミュニティ">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
@@ -35,342 +44,226 @@
<br />
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="Hopper 内で解析ブリッジを起動し、ネイティブバイナリを調べる REA" width="1200" />
</div>
---
自分のプロダクトにも欲しい機能を他のアプリで見つけたら、REA を使ってエージェントに調査を依頼できます。エージェントはソースコードがなくてもアプリを調べ、機能の仕組みを説明して根拠を示し、あなたのプロジェクト向けの実装まで進められます。
アプリに、自分の製品にも取り入れたい機能を見つけましたか?エージェントに REA で調査を依頼してください。ソースコードがなくてもアプリを調べ、機能の仕組みを説明し、根拠を示したうえで、あなたのプロジェクト向けに実装できます。
REA は、ネイティブバイナリ、JavaScript/Electron アプリ、.NET アセンブリ、Web サイトを調べるためのツールをエージェントに提供します。同じツールはターミナルからも使えます。解析はローカルで実行され、結果には各結論の根拠と制限が含まれます。
REA はエージェントを分析ツールにつなぎ、ネイティブバイナリ、JavaScript や Electron のアプリ、.NET アセンブリ、ウェブサイトを調べられるようにします。同じツールをターミナルからも使えます。分析はローカルで実行され、結果には各結論を裏付ける根拠と制限事項が含まれます。
セットアップは REA をエージェントに登録し、対応するワークフロー手順もインストールします。ネイティブ解析には既存の Hopper または Ghidra を使えます。承認すれば、セットアップで Hopper をインストールすることもできます。静的な JavaScript 解析にはどちらのエンジンも不要です。
セットアップはエージェントに REA を登録し、対応するワークフローの手順をインストールします。ネイティブ分析には既存の Hopper または Ghidra を使えます。承認すれば、セットアップで Hopper をインストールすることもできます。静的な JavaScript 分析には、どちらのエンジンも必要ありません。
## エージェントに頼むだけ
[セットアップ](#クイックスタート)後にエージェントを再起動し、次のように依頼します:
```text
メモアプリの検索機能を調べて根拠を示し、私のプロジェクト向けに同様の機能を実装してください。
```
「メモアプリ」を調べたいアプリに置き換えてください。まずは概要の調査を依頼することもできます。
## バイナリから動作へ
| 逆コンパイル | 理解 | 再現 |
| -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| ネイティブアプリや実行ファイルから、プロシージャ、疑似コード、アセンブリ、文字列、シンボル、セグメント、メタデータを復元します。 | 呼び出し元、呼び出し先、クロスリファレンス、コールグラフをたどり、機能やアルゴリズムの実際の動作を説明できる状態にします。 | エージェントが得た知見を、あなたの技術スタック、画面、要件に合うプロダクト機能へ変えます。 |
REA は結論に至った根拠を示します。元のソースコードを復元できる、あるいはアプリ全体を自動的に複製できるとは主張しません。
## REA を選ぶ理由
| | |
| -------------------------- | -------------------------------------------------------------------------------------------------------- |
| **エージェント向け** | アプリの動作を質問すると、エージェントが推測ではなく実際に調べて答えます。 |
| **CLI と MCP** | 同じリバースエンジニアリング機能を、ターミナルからもエージェントからも使えます。 |
| **ガイド付きセットアップ** | エージェントの設定、既存の解析ツールへの接続、承認したうえでの Hopper のインストールに対応します。 |
| **洞察からコードへ** | 機能を理解したら、同じコーディングセッションで自分のプロダクト向けに実装できます。 |
| **ローカルで解析** | 解析は対応するローカルホストで実行されます。REA がアプリをホスト型の解析サービスへ送ることはありません。 |
| **コンテキストを維持** | 質問のたびに解析をやり直すことなく、複数のアプリを続けて調査できます。 |
> **[REA のウェブサイト](https://rea.tools/)**で、セットアップ手順、図解ガイド、実際の事例を確認できます。
## クイックスタート
### セットアップを実行(推奨)
### エージェントを設定する
REA をエージェントで使えるように設定します:
Node.js と npm がインストールされている環境で実行します。
```bash
npx rea-agents setup
```
セットアップでは、まず REA を使うエージェントを選び(複数選択可)、具体的なパスと変更内容を確認してから承認します。既存の REA 登録は最初から選択されています。新しく検出されたエージェントは選択肢に表示されますが、検出されただけでは選択されません。選択したエージェントには、MCP 接続と REA のガイド付きワークフローが追加されます。Hopper のインストールは別の任意項目で、個別に承認が必要です。既存の Ghidra のインストール先を登録することもできます。
使うエージェントを選び、予定されている変更を確認して承認してください。セットアップは REA の MCP サーバーと対応するワークフローの手順を追加し、既存の設定をバックアップします。完了後にエージェントを再起動してください。
セットアップは変更を適用する前に内容を表示し、既存の設定をバックアップします。要件とセットアップのオプションは[インストールガイド](docs/installation.md)を参照してください。
セットアップは Claude Code、Codex、Cursor、Gemini CLI、Grok Build、および[その他のエージェント](docs/installation.md#supported-agents)に対応しています。プロバイダーの設定と MCP の手動登録については、[インストールとセットアップ](docs/installation.md)を参照してください。
### エージェントで使う(推奨)
### エージェントに依頼する
セットアップ後にエージェントを再起動し、理解したいアプリや機能を[説明してください](#エージェントに頼むだけ)。Hopper はデモモードでも動作します。初回起動の画面が表示されたら、デモを選ぶか既存のライセンスを入力してください。
REA は Claude Code、Claude Desktop、Codex、Cursor、Gemini CLI、Windsurf、Devin、OpenCode、Antigravity、GitHub Copilot CLI、Command Code、VS Code に対応しています。セットアップでは既存の REA 登録が最初から選択され、それ以外の検出済みエージェントは選択するまで対象になりません。その他のエージェントは[手動の MCP 設定](#他のコーディングエージェントで使う)を使えます。
### AI コーディングアシスタント向けスキル(任意)
AI コーディングアシスタントにスキルを追加すると、より豊富なコンテキストを利用できます:
```bash
npx skills add morluto/rea --skill reverse-engineer-anything
```text
Notes アプリの検索機能の仕組みを調べ、根拠を示して、私のプロジェクトにも同様の機能を実装してください。
```
このスキルは REA の調査ワークフローを提供します。REA をエージェントに接続して解析ツールを設定するには、上記のセットアップを実行してください。セットアップは既定でバージョンの一致したスキルをインストールします。このコマンドはリポジトリ版のスキルをインストールします。
Notes を対象のアプリに置き換え、理解したい機能を指定してください。
### ターミナルで最初の結果を得る
### ターミナルを使う
展開済みの JavaScript/Electron アプリのディレクトリまたは ASAR に対して、次を実行します:
展開済みの JavaScript/Electron アプリのディレクトリ、または ASAR を調べます。
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
パスは調査対象に置き換えてください(Windows では `"D:/apps/example"` など)。MCP の設定、Hopper、Ghidra を必要とせず、アプリを実行することもなく、Evidence、復元したグラフ、制限、未解決事項をその場で返します。ネイティブアプリの場合は、先にエンジンを設定してから、そのアプリのパスを指定して `analyze` を使います。`doctor` は問題を診断したいときに使うもので、解析のたびに実行する必要はありません。
結果にはモジュール、インポート、Electron の境界と、それらの根拠が含まれます。パスは対象に合わせて変更してください。Windows では、たとえば `"D:/apps/example"` を指定します。
### 作業に合わせて準備状況を確認する
オプションなしの `rea doctor` は連携全体の監査です。検出したすべてのエージェント登録、インストール済みのスキル、すべての任意の解析エンジンを確認するため、今の作業には支障がなくても `healthy: false` を報告することがあります。作業に合わせて確認範囲を指定してください:
| 作業 | 準備状況の確認 |
| ------------------------------------------ | ---------------------------------------------------------------------------------------------- |
| 静的な JavaScript/Electron 解析 | 不要です。`analyze-javascript-application` を直接実行します。 |
| 特定の解析エンジンのトラブルシューティング | `rea doctor --provider ghidra --json`(または `hopper`、`ida`) |
| 特定のエージェントの MCP 登録を確認 | `rea doctor --client codex --json`([クライアント ID](docs/installation.md#supported-agents)) |
| インストール済みのスキルを確認 | `rea doctor --skill --json` |
範囲を指定したレポートでは、`healthy` と終了ステータスを決めるのは `scope_checks` だけです。それ以外の項目は `informational_checks` に表示され、今の作業のために修正する必要はありません。たとえば、使っていないエンジンが見つからなくても対処は不要です。
ネイティブ対象に対応するエンジンが複数インストールされている場合、REA は自動ではどれも選びません。対象を開くと `code: "capability_unavailable"` と `details.selection_reason: "ambiguous"` で失敗し、`details.candidate_ids` に候補が示されます。CLI の `--provider` か `open_binary` の `provider_id` で一度選ぶか、常用する設定として `REA_ANALYSIS_PROVIDER` を指定してください。詳しくは[英語版の解説](README.md#choosing-a-deep-analysis-provider)を参照してください。
### rea コマンドをインストール
コマンドラインツールをインストールします:
```bash
curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash
```
Node.js と npm を先にインストールしておいてください。ターミナルで実行すると、インストーラーは `rea` を追加してセットアップを開始します。
npm でインストールしてから、セットアップを実行することもできます:
```bash
npm install --global rea-agents
rea setup
```
### 要件
静的な JavaScript 解析に必要なのは Node.js と npm だけです。ホストと外部ツールの前提条件は使うワークフローによって異なり、ネイティブ解析プロバイダーの対応プラットフォームは各ガイドで説明しています。
- macOS 12 以降
- Ubuntu 24.04+、Fedora 41+、64 ビット Arch Linux、または CachyOS
- Node.js 22.x (>=22.19)、24.x (>=24.11)、または 26+
- npm(特定のバージョンは不要で、REA が npm をインストールすることもありません)
ネイティブバイナリの詳細な解析には Hopper、Ghidra、IDA Pro のいずれかが必要です。Hopper は独自のライセンスを持つ別製品で、デモ版でもベンダーが定める制限の範囲で解析できます。Ghidra と IDA は、利用者が用意したものを使います。
Ghidra は Linux x64 と macOS x64/arm64 に対応しています。Ghidra 12.1.x と、そのインストールが宣言する 64 ビットの完全な JDK(`application.java.min` から `application.java.max` まで)を別途インストールし、REA で使うように設定してください。現行の 12.1 リリースは JDK 21 以降を必要とし、上限はありません。ブリッジは Ghidra 12.1.4 と JDK 21 で検証しています。macOS では、ホストのアーキテクチャに合うネイティブデコンパイラーも必要です。
```bash
export GHIDRA_INSTALL_DIR=/absolute/path/to/ghidra_12.1.4_PUBLIC
export JAVA_HOME=/absolute/path/to/jdk-21 # java と javac が PATH から解決できる場合は省略可
rea doctor --provider ghidra --json
rea setup
```
セットアップはこれらのインストールを確認し、承認後にパスを保存します。Ghidra、Java、Node.js、npm、Homebrew のインストールや更新は行いません。
IDA Pro は、すでに動作している [mrexodia/ida-pro-mcp](https://github.com/mrexodia/ida-pro-mcp) の MCP 登録を再利用します。開いている GUI の対象を読み取り専用で解析するか(`attached`、既定)、データベースのスーパーバイザーで指定したバイナリをヘッドレスで開いて解析します(`headless`)。REA が attached の GUI データベースを保存したり閉じたりすることはありません。最初の実環境での検証は、Windows の GUI と Windows x64 のヘッドレス IDA 9.3 が対象です。設定方法と対応範囲は [IDA プロバイダーガイド](docs/ida-provider.md)を参照してください。
```bash
export REA_IDA_MCP_CONFIG=/absolute/path/to/ida-mcp.json
rea function /absolute/path/to/program main --provider ida --json
```
リポジトリの main と npm 4.1.0 には、ローカル NTFS 上のネイティブ x86-64 PE アプリケーション(マネージドコードと DLL を除く)を対象とする、実験的な Windows x64 Ghidra P0 対応が含まれています。Job Object、プライベート DACL、パスの受け入れ検査の各制御も同梱されています。古い npm パッケージでこの機能を使えるか確認するには[リリース境界](docs/installation.md#released-package-and-main)を、前提条件と検証済みの範囲は [Windows Ghidra P0](docs/windows-ghidra-p0.md) を参照してください。
### トラブルシューティング
`npx -y rea-agents@latest doctor` は、ホスト、依存関係、解析ツール、エージェント設定を変更せずに確認します。構造化された診断結果が必要な場合は `--json` を追加してください。
Linux では実行可能な `/opt/hopper/bin/Hopper` を優先し、利用できない場合は `~/.local/share/rea/hopper/bin/Hopper` を自動的に確認します。それ以外の場所にインストールした場合は `HOPPER_LAUNCHER_PATH` を設定してください。ファイルがあるのに解析エンジンが見つからないと報告される場合は、実際の Hopper のパスに対して `ldd /absolute/path/to/Hopper | grep 'not found'` を実行し、不足しているライブラリを確認してください。詳しくは [Hopper ガイド](docs/installation.md#hopper)を参照してください。
### 更新とアンインストール
- `rea update` は現在の REA インストールを更新します。
- `rea uninstall` は REA が管理するエージェント登録とスキルだけを削除します。Hopper、Node.js、Evidence ファイル、キャプチャ、無関係なスキル、他の MCP サーバーは残ります。
- `rea uninstall --purge-data` は `~/.rea/cache` と `~/.rea/state` も削除します。それらを消したい場合にだけ使ってください。
## 現在の対応状況
リポジトリの現在の機能とプラットフォーム要件は[英語の対応状況ガイド](README.md#current-status)で説明しています。main は [npm リリース](docs/installation.md#released-package-and-main)より先行する場合があります。
- Ghidra は Linux x64、macOS x64/arm64、実験的な Windows x64 P0 境界で 25 種類の読み取り専用操作を提供します。Linux と macOS では、セッション内での関数名とエントリーコメントのアトミックな編集にも対応します。Windows P0 には変更の権限がなく、Ghidra には REA から操作できる GUI 機能はありません。
- IDA アダプターは、ドキュメントに記載された読み取り専用の関数・文字列操作を提供します。
- 静的な Android APK の検査は Linux と macOS に対応し、別途用意したヘッドレス JADX と完全な JDK が必要です。現在のメタデータブリッジは macOS arm64 で検証しています。詳しくは [Android 解析](docs/android-analysis.md)を参照してください。
- ブラウザー、Electron、プロセスの各リクエストは対象、操作、ライフサイクルを直接指定し、ホストで実際に許可されたアクセスの範囲で動作します。REA 側で別途権限を付与する必要はありません。セットアップによる設定の書き込みと Hopper のインストールには、引き続き具体的な計画の承認が必要です。
- `rea capabilities` と `rea providers` はバイナリセッションのプロバイダーと補助操作を説明するもので、ブラウザー、Android、アプリのすべてのワークフローの一覧ではありません。MCP の機能全体は、接続中の MCP ツール一覧と `binary_session` が示すツールの利用可否で確認してください。
## ひとつのプロンプトで調査を完結
```text
メモアプリをリバースエンジニアリングし、オフライン検索機能の仕組みを説明して、
TypeScript と SQLite を使って私のプロジェクト向けに実装してください。
```
| 手順 | エージェントの処理 | REA ツール |
| ---: | ------------------------------ | ---------------------------------------------------------------- |
| 1 | バイナリを開いて識別 | `open_binary`, `binary_overview` |
| 2 | オフライン検索の手掛かりを探す | `search_strings`, `search_procedures`, `list_names` |
| 3 | 手掛かりを実行コードに結び付け | `find_xrefs_to_name`, `xrefs`, `procedure_callers` |
| 4 | 関連する制御フローを復元 | `get_call_graph`, `procedure_callees`, `procedure_info` |
| 5 | 関連する処理を逆コンパイル | `procedure_pseudo_code`, `procedure_assembly`, `batch_decompile` |
| 6 | プロジェクトに機能を実装 | 技術スタック、プロダクト、要件に合わせたコード |
手順 1〜5 のアプリ解析は REA が担当します。手順 6 は、アプリについて得た知見をもとに、エージェントが通常の編集ツールとテストツールで行います。
## エージェントにできること
- 気に入った機能を調査し、自分のプロダクトに合わせた形で実装する。
- ソースコードが手に入らない機能の仕組みを説明する。
- アプリの認証、保存、更新、ネットワーク処理の流れを復元する。
- 文書化されていない形式やインターフェースについて、文書化に必要な構造を復元する。
- 文字列やシンボルから、疑わしい動作を実装しているコードまでたどる。
- 復元した動作を、プロダクト機能、テスト、移行メモ、移植版、相互運用できる代替実装に変える。
- マングルされたシンボルをひとつずつ手作業で読み解かなくても、Swift と Objective-C のメタデータを解析する。
- Hopper に名前、コメント、ブックマークを残し、人とエージェントの解析を互いに活かす。
## 調査ツールカタログ
| ツール分類 | 数 | 用途 |
| -------------------- | --: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ネイティブ検査 | 41 | 関数、疑似コード、アセンブリ、文字列、シンボル、呼び出し、参照、注釈、バイト読み取り、ファイルオフセット |
| 調査ワークフロー | 14 | アプリ概要、関数ドシエ、ネイティブ API とディスパッチ、一括逆コンパイル、機能トレース、コールパス、コールグラフ、Swift と Objective-C の検出 |
| ネイティブバイナリ | 10 | macOS の Mach-O メタデータ、署名、plist、アーキテクチャ、Swift シンボル、LLDB による呼び出し観測;Linux の ELF レイアウト、静的な保護機構の証拠と記録済みクラッシュ |
| 成果物グラフ | 7 | ディレクトリとパッケージの目録、コンパイル済み Interface Builder ファイル、Apple アセットカタログ、Mach-O dylib のロード解決、抽出、オフライン EVM インターフェース推定 |
| マネージド PE/CLI | 7 | .NET の識別情報、メタデータ、CIL 命令、ネイティブ依存関係、再構築結果のインポート、ビルド比較 |
| ファームウェア | 2 | Linux ファームウェア領域の検査と明示的な展開 |
| Android APK | 5 | パッケージと manifest の宣言、クラス検索、メンバー一覧、メソッドの逆コンパイル、静的な被参照 |
| ブラウザー観察 | 12 | ページ構成、ネットワークメタデータ、スクリプト、ソースマップ、WebMCP の検出、スクリーンショット、キャプチャ比較 |
| Electron 解析 | 5 | レンダラーの観察、静的なアプリのマッピング、静的結果と実行時結果の照合 |
| JavaScript 実行時 | 2 | Node/Electron Inspector の対象検出、スクリプトの位置、実行コンテキストのイベント |
| アプリワークフロー | 13 | 取得した Web スクリプトのエクスポート、Android/Apple の目録の投影、層をまたぐ機能トレース、ビルド比較、過去のソースとの対応付け、静的な戻り値形状の比較、再構築の検証 |
| ワークスペースと観察 | 21 | セッション、Evidence バンドル、ナビゲーションの文脈、プロセス・成果物・関数の比較、未解決事項の記録 |
## ロードマップ
[現在の対応状況](#現在の対応状況)は提供済みの機能です。今後の作業は次のとおりです。
- **現在:** ツール、プロバイダー、セットアップの選択肢、バージョンの変更に合わせてドキュメントを正確に保ち、Hopper と Ghidra で検証するネイティブバイナリのアーキテクチャと間接呼び出しの範囲を広げます。
- **次:** 機能トレースに静的抽出と実行時の観察を追加し、難読化された .NET アセンブリの比較を改善し、プロセス、プロトコル、ファイルシステム、再接続、バージョン比較の範囲を広げます。
- **その後:** ブラウザーと Electron のシナリオ操作を増やし、LLDB や Frida などによるネイティブアプリの実行時観察と、他の解析ツールや対象の評価を進めます。
セットアップでは、すでにエージェント連携と Hopper のインストールを選べます。その他の解析ツールのインストールへの対応は今後の作業です。[インストールのロードマップ](docs/roadmap.md)と[解析ツールの評価](docs/provider-evaluation.md)を参照してください。
## 他のコーディングエージェントで使う
セットアップは Claude Code、Claude Desktop、Codex、Cursor、Gemini CLI、Windsurf、Devin、OpenCode、Antigravity、GitHub Copilot CLI、Command Code、VS Code に対応しています。既存の REA 登録は最初から選択され、それ以外の検出済みエージェントは選択するまで対象になりません。ローカル MCP サーバーに対応するエージェントであれば、次の設定でも接続できます。
<!-- x-release-please-start-version -->
```json
{
"mcpServers": {
"rea": {
"command": "npx",
"args": ["-y", "rea-agents@6.0.0", "mcp"]
}
}
}
```
<!-- x-release-please-end -->
常用する登録では、パッケージのバージョンを 1 つに固定してください。`rea setup` はその固定バージョンを維持し、同梱のスキルも同時に更新します。
## 仕組み
```mermaid
flowchart LR
Agent["コーディングエージェント"] --> REA["REA<br/>CLI + MCP"]
Terminal["ターミナル"] --> REA
REA --> Hopper["Hopper プロバイダー"]
REA --> Ghidra["Ghidra プロバイダー<br/>インベントリ + 関数解析 + 注釈"]
REA --> Ida["IDA MCP プロバイダー<br/>attached GUI または headless データベース"]
Hopper --> App["あなたのアプリ"]
Ghidra --> App
Ida --> App
```
CLI と MCP サーバーは、同じアプリケーションワークフローと Evidence の契約を使います。ターミナルのコマンドは完了すると自身のブリッジセッションを解放し、エージェントのセッションは調査中の対象と Evidence を保持できます。REA のセッションを閉じても、利用中の Hopper アプリは終了しません。
## CLI
上のエージェントワークフローが、REA を使う最も簡単な方法です。ターミナルからアプリの概要を一度だけ調べる場合は、次を実行します。
```bash
npx -y rea-agents@latest analyze /Applications/Notes.app
```
直接の逆コンパイルやその他のオプションは、`npx -y rea-agents@latest --help` で確認できます。
グローバルな `rea` コマンドとしてもインストールできます。
日常的に使う場合は、`rea` コマンドをインストールできます。
```bash
npm install --global rea-agents
rea --help
rea mcp
```
REA は Mac の `.app` フォルダーを直接開けます。エージェントがアプリを名前で見つけられない場合は、インストール場所を伝えてください。
ネイティブ分析には、先にプロバイダーの設定が必要です。ネイティブ分析のコマンド、プロバイダーの選択、スナップショット、スクリプトでの利用は、[CLI と Evidence のガイド](docs/cli.md)を参照してください。
## Hopper アプリの動作
### REA を更新する
REA は操作に必要になった時点で Hopper を起動します。Hopper のランチャーは内部でアプリをアクティブにするため、REA がバックグラウンドでの起動を要求しても、macOS では Hopper のウィンドウやダイアログが前面に出る場合があります。デモやライセンスの画面では操作が必要になることがあります。
REA は更新が速く、新しいリリースには頻繁にバグ修正が含まれます。インストールしたバージョンを最新に保ってください。
Hopper は解析リクエストを一度に 1 つずつ処理します。待機をキャンセルしても、Hopper 内ですでに実行中の処理は止まりません。処理中かどうかはセッションが報告します。セッションを閉じると REA のブリッジと一時ソケットディレクトリを削除しますが、利用中の Hopper アプリは終了しません。後片付けを確認できなかった場合、`close_binary` は `cleanup_incomplete` と対象のリソースを報告します。
npm でインストールした CLI の場合:
## セキュリティモデル
```bash
rea update
```
解析はローカルで実行されます。REA は Hopper や Ghidra とは認証付きのプライベートなローカルソケットで、IDA とは設定済みのローカル MCP 登録を通じて通信します。Ghidra セッションは隔離された一時プロジェクトを使い、ユーザーの Ghidra プロジェクトを開いたり変更したりしません。
エージェントの登録とスキルを更新するには、更新処理が表示するセットアップコマンドを実行してください。
これはサンドボックスではありません。解析ツールと起動した対象は現在のユーザー権限で動作し、同じ OS ユーザー権限で動く悪意のあるプロセスは防げません。Windows Ghidra P0 では、ネイティブの Job Object、保護されたプライベート DACL、ハンドルベースの受け入れ検査を自動的に使います。脆弱性は [SECURITY.md](SECURITY.md) に記載された非公開の手順で報告してください。
`npx` を使っている場合は、次のコマンドでエージェントの設定を更新します。
## FAQ
```bash
npx rea-agents@latest setup
```
<details><summary><strong>Hopper を先に起動しておく必要はありますか?</strong></summary>
設定の変更を確認し、エージェントを再起動してください。単発の CLI 操作では、`npx rea-agents@latest` に続けてコマンドを指定します。
いいえ。REA は必要になった時点で Hopper を起動します。すでに起動している Hopper でも使えますが、既存の GUI ドキュメントには接続せず、新しい解析ドキュメントを開きます。
## REA の仕組み
エージェントは MCP 経由で REA を呼び出し、対象を調べて関連するコードを追跡します。REA は調査結果と根拠を返します。エージェントはそれを使って追加の質問をしたり、動作を説明したり、実装を書いてテストしたりします。CLI コマンドも同じワークフローを使います。
![REA の調査フロー:エージェントがローカルの対象について質問し、REA が分析ツールで調査・追跡します。エージェントは返されたコード、参照、未解明の点を使い、説明、実装、テストを行います。](website/public/assets/figures/rea-investigation-flow.svg)
[原寸大の図を開く](website/public/assets/figures/rea-investigation-flow.svg)。
<a id="current-status"></a>
## 分析できる対象
REA には Node.js 22.x(>=22.19)、24.x(>=24.11)、または 26+ と npm が必要です。追加のツールや対応ホストは、対象によって異なります。
| 対象 | REA が返すもの | 要件とガイド |
| -------------------------------- | ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| ネイティブバイナリ | 疑似コード、アセンブリ、文字列、シンボル、呼び出し、参照 | Hopper、Ghidra、または IDA;[ネイティブ分析](https://rea.tools/guides/native/) |
| オフライン ELF レイアウト | セクション、セグメント、元のシンボル/再配置情報、静的解析によるセキュリティ対策の候補 | Linux x64 で利用者が用意する pwntools;[バイナリ診断](docs/binary-diagnostics.md) |
| EVM バイトコード | ディスパッチセレクター、バイトオフセット、推定された引数と状態変更の可否 | Linux x64 上のローカルの生バイト/16 進数の入力ファイル;[オフライン EVM ガイド](docs/evm-bytecode.md) |
| 記録済みの Linux クラッシュ | 生の note レコード、記録された全スレッドのレジスター/シグナル、任意のマッピング候補 | Linux x64 で利用者が用意する pwntools;GDB/pwndbg は任意;[記録済みクラッシュ](docs/recorded-crashes.md) |
| JavaScript / Electron | モジュール、インポート、ソースマップ、ルート、IPC、ネイティブアドオンの関係 | Node.js と npm;[アプリケーション分析](https://rea.tools/guides/javascript/) |
| ウェブサイト | ページ構造、スクリプト、ネットワークの観測結果、依頼されたスクリーンショット | Chrome 系ブラウザー;[ブラウザー分析](https://rea.tools/guides/browser/) |
| 保存済みのネットワークキャプチャ | リクエスト、レスポンス、取得可能なペイロード、ソース内の位置 | HAR;mitmproxy ネイティブ形式のキャプチャには Linux 上の mitmdump;[キャプチャガイド](docs/web-network-captures.md) |
| .NET アセンブリ | メタデータ、CIL 命令、宣言されたネイティブ依存関係、ビルドの比較 | 静的な検査;[マネージドコードのガイド](docs/managed-code-analysis.md) |
| Android APK | マニフェストの宣言、クラス、逆コンパイルされたメソッド、参照 | Linux/macOS/Windows x64 上のヘッドレス JADX と完全な JDK;[Android ガイド](docs/android-analysis.md) |
| Android デバイス | デバイス、パッケージ、プロセス、ログ、ダンプ、スクリーンキャプチャ、APK/ファイル転送 | 呼び出し側が用意した adb(エミュレーターまたは実機);[ADB ガイド](docs/adb-device-analysis.md) |
| JEBプロジェクト | エンジンによるプロジェクトユニット、アーティファクトのダイジェスト、型/メソッドの擬似コード | 呼び出し側が起動し MCP を提供する JEB クライアント(REA_JEB_MCP_URL で選択);[JEB ガイド](docs/jeb-analysis.md) |
| Android リソース | デコードされたマニフェスト、文字列テーブル、ロケール、バージョン情報 | 呼び出し側が用意した Apktool ランチャー;[リソースガイド](docs/apktool-resource-analysis.md) |
| ファームウェア | 領域、抽出結果、ネイティブ分析への引き継ぎ | Linux 上の Binwalk / Unblob;[ファームウェアガイド](docs/firmware-analysis.md) |
| パッケージとリソース | ファイル一覧、ダイジェスト、plist、Apple バンドルの構造、抽出されたリソース | [アーティファクトと JavaScript のガイド](docs/javascript-artifact-reconstruction.md)、[Apple アプリケーション](docs/apple-application-analysis.md) |
| プロセスの動作 | ターミナル出力、対話、終了とファイルシステムの観測結果、実行の比較 | ネイティブ PTY を備えた Linux/macOS;[プロセスキャプチャ](docs/process-capture.md) |
静的な JavaScript と .NET の検査は、指定されたファイルを読み取り、アプリケーションを実行しません。実行時キャプチャは、あなたのユーザー権限で対象を実行したり、対象とやり取りしたりします。それぞれの実行時ガイドに、どのような操作が行われるかを記載しています。
<a id="choosing-a-deep-analysis-provider"></a>
対応するネイティブ形式とホストは、プロバイダーによって異なります。[Hopper と Ghidra のセットアップ](docs/installation.md#hopper)、[IDA ガイド](docs/ida-provider.md)、[Windows 向け Ghidra の実験的対応](docs/windows-ghidra-p0.md)を参照してください。Ghidra は [16 ビット DOS 分析](docs/ghidra-dos.md)にも対応しています。プロバイダーの選択は [CLI ガイド](docs/cli.md#choose-a-provider)を参照してください。最新の npm リリース以降に追加された機能については、[リリースでの利用可否](docs/installation.md#released-package-and-main)を確認してください。
## 事例
[![DX-Ball の音声パン、Notion のクリップボードブリッジ、TH04 の弾幕リングの事例を表すイラスト](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball:音声のパン計算を再構築する
音声の呼び出しから位置をパンに変換する補助関数をたどり、命令を調べ、不完全な疑似コードを C に書き直します。再構築した実装は、元の x86 に対する 3,205 ケースの検証を通過し、コンパイル後の関数の全 63 バイトを再現しています。
[事例を読む](https://rea.tools/showcase/dx-ball/) ·
[再構築リポジトリ](https://github.com/N0zoM1z0/dx-ball)
### Notion:Electron のクリップボードブリッジを追跡する
レンダラーのクリップボード API を見つけ、preload と IPC を経由してメインプロセスまでたどり、リッチなクリップボード形式を調べます。
[事例を読む](https://rea.tools/showcase/notion/)
### TH04:DOS の弾幕リングの計算を復元する
元の PC-98 ゲームの 16 ビット命令を調べ、固定角度と自機を狙う角度の計算を復元し、再構築した C++ を当時のコンパイラーの出力と比較します。
[事例を読む](https://rea.tools/showcase/th04/) ·
[再構築リポジトリ](https://github.com/N0zoM1z0/th04)
REA で興味深い対象を調べたら、ぜひ共有してください。[issue](https://github.com/morluto/rea/issues) または [pull request](https://github.com/morluto/rea/pulls) に、対象、調べたかったこと、REA がどう役立ったか、何が分かったかを記載してください。
## よくある質問
<details>
<summary><strong>どのエージェントで REA を使えますか?</strong></summary>
ローカル MCP サーバーに対応するエージェントなら使えます。セットアップは[対応エージェント](docs/installation.md#supported-agents)を設定します。その他のクライアントでは、[MCP の手動登録](docs/installation.md#mcp-registry)を利用できます。
</details>
<details><summary><strong>REA に Hopper は含まれていますか?</strong></summary>
<details>
<summary><strong>Hopper、Ghidra、IDA は必要ですか?</strong></summary>
含まれていません。セットアップで Hopper をインストールできますが、Hopper は独自のライセンスを持つ別製品です。REA は、エージェントが Hopper を使えるようにする CLI、MCP サーバー、ワークフローを提供します。
深いネイティブ分析には、そのいずれかを使います。静的な JavaScript と .NET の検査には、ネイティブ分析エンジンは必要ありません。セットアップは承認後に Hopper をインストールできます。Ghidra と IDA は既存のインストールを使います。[プロバイダーのセットアップ](docs/installation.md#hopper)を参照してください。
</details>
<details><summary><strong>REA は Ghidra や Java をインストールしたり同梱したりしますか?</strong></summary>
<details>
<summary><strong>先に Hopper を起動する必要はありますか?</strong></summary>
いいえ。REA は既存の Ghidra のインストールに接続します。[要件](#要件)にある Ghidra と Java のパスを設定してから、セットアップを実行してください。
REA は必要な操作の際に Hopper を起動します。macOS では、初回起動時にデモモードを選ぶか、ライセンスを有効化するよう求められることがあります。[Hopper の起動とトラブルシューティング](docs/installation.md#launcher-paths-and-troubleshooting)を参照してください。
</details>
<details><summary><strong>アプリはアップロードされますか?</strong></summary>
<details>
<summary><strong>skills.sh からスキルをインストールすると何ができますか?</strong></summary>
REA にホスト型の解析サービスはありません。現在のプロバイダーは、成果物の解析と動作のキャプチャをローカルで行います。エージェントやモデルの提供元には独自のデータポリシーがあるため、別途確認してください。
スキルはエージェントに調査の手順を提供します。`npx rea-agents setup` で REA の MCP サーバーを登録し、対応する手順をインストールしてから、エージェントを再起動してください。[スキルのみのインストール](docs/installation.md#skill-only-installation)を参照してください。
</details>
<details><summary><strong>元のソースコードを復元できますか?</strong></summary>
<details>
<summary><strong>REA はどのようなコードを返しますか?</strong></summary>
元のソースコードを確実に復元できるデコンパイラーはありません。REA はエージェントに疑似コード、アセンブリ、シンボル、文字列、メタデータ、それらの関係を提供し、観察された動作の説明や互換性のある再現に役立てられるようにします。
ネイティブ分析は疑似コードとアセンブリを返します。JavaScript/Electron 分析はモジュールとその関係を復元します。エージェントはその結果を使って実装を書き、テストします。[事例](#事例)に具体的な手順があります。
</details>
## 開発
<details>
<summary><strong>REA はアプリをアップロードしますか?</strong></summary>
開発環境、アーキテクチャ、テスト、リリース手順は [CONTRIBUTING.md](CONTRIBUTING.md) を参照してください。
REA は対象をローカルで分析します。エージェントはツールの結果を受け取り、そのモデルプロバイダーには独自のデータポリシーがあります。
</details>
<details>
<summary><strong>バグに遭遇したらどうすればよいですか?</strong></summary>
まず更新してください。最近のリリースですでに修正されている可能性があります。
npm でインストールした CLI の場合:
```bash
rea update
```
`npx` でエージェントを設定している場合:
```bash
npx rea-agents@latest setup
```
エージェントを使っている場合は、[設定の更新](#rea-を更新する)を完了し、再起動してください。同じタスクをもう一度試し、問題が続く場合は [issue を作成](https://github.com/morluto/rea/issues)して、REA のバージョン、対象の種類、再現手順、エラー出力を記載してください。
</details>
## ドキュメント
まずはウェブサイトの[実践ガイド](https://rea.tools/guides/)を参照してください。正確なオプション、前提条件、結果の契約については、以下を参照してください。
- [インストールとセットアップ](docs/installation.md):エージェントの登録、プロバイダーの設定、更新、アンインストール。
- [準備状況の確認とトラブルシューティング](docs/installation.md#check-readiness-for-your-task):特定のエージェントや分析エンジンを診断。
- [CLI と Evidence](docs/cli.md):コマンド、プロバイダーの選択、スナップショット、インポート/エクスポート、終了ステータス。
- [MCP 契約](docs/mcp-contracts.md)と[エージェント向けプロンプト](docs/mcp-prompts.md):ツールの結果、セッション、ガイド付き調査。
- [ツールカタログ](docs/mcp-contracts.md#generated-catalog):ビルド時に生成されるツール、プロバイダー、CLI コマンドの一覧。
- [ロードマップ](docs/roadmap.md):計画中の作業と機能の進捗。
脆弱性の報告は [SECURITY.md](SECURITY.md) に従ってください。
## スター履歴
🎉 **GitHub スターが 20,000 を突破しました。ありがとうございます!**
🎉 **GitHub スター 50,000 件、ありがとうございます!**
REA を使い、問題を報告し、ビルドをテストし、修正を届けてくださる皆さんに感謝します。
REA の利用、バグ報告、機能の要望、ビルドのテスト、修正への貢献に感謝します。
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
@@ -380,6 +273,16 @@ REA を使い、問題を報告し、ビルドをテストし、修正を届け
</picture>
</a>
## 免責事項
REA は、合法的なリバースエンジニアリングの研究、分析、再構築のためのツールを提供します。必要な許可を得て、適用される法律に従う責任は利用者にあります。このプロジェクトは違法または無許可の利用を支持しません。
## 貢献する
REA への貢献を歓迎します![issue を作成](https://github.com/morluto/rea/issues)してバグや機能の提案を報告したり、[pull request を送信](https://github.com/morluto/rea/pulls)してコードやドキュメントを改善したりできます。
開発環境とチェックは [CONTRIBUTING.md](CONTRIBUTING.md)、検証レーンは[テストガイド](docs/testing.md)、プロジェクト構造は[アーキテクチャ図](docs/architecture.mermaid)を参照してください。
## ライセンス
[MIT](LICENSE)
+186 -232
View File
@@ -1,325 +1,269 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [日本語](README_ja.md) · **한국어** · [العربية](README_ar.md)
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · **한국어** · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA: 무엇이든 리버스 엔지니어링
### 에이전트로 앱의 동작부터 네이티브 바이너리까지 조사하세요.
### 하나의 MCP로 바이너리, 애플리케이션, 런타임 동작을 리버스 엔지니어링합니다.
**마음에 드는 기능을 찾고, 작동 방식을 이해하고, 원하는 방식으로 구현하세요.**
**마음에 드는 기능을 발견했다면, 바이너리 수준까지 작동 원리를 이해하세요.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](#조사-도구-카탈로그)
[![Node.js 22+](https://img.shields.io/badge/Node.js-22.19%2B-339933?style=flat-square&logo=nodedotjs&logoColor=white)](https://nodejs.org/)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[웹사이트(영문)](https://morluto.github.io/rea/) · [가이드](https://morluto.github.io/rea/guides/) · [DX-Ball 사례](https://morluto.github.io/rea/showcase/dx-ball/)**
**[웹사이트](https://rea.tools/) · [가이드](https://rea.tools/guides/) · [사례](https://rea.tools/showcase/)**
[빠른 시작](#빠른-시작) · [현재 지원 범위](#현재-지원-범위) · [바이너리에서 동작까지](#바이너리에서-동작까지) · [조사 도구 카탈로그](#조사-도구-카탈로그) · [로드맵](#로드맵) · [작동 방식](#작동-방식)
[빠른 시작](#빠른-시작) · [REA의 작동 방식](#rea의-작동-방식) · [분석할 수 있는 대상](#분석할-수-있는-대상) · [사례](#사례) · [자주 묻는 질문](#자주-묻는-질문) · [문서](#문서)
<table aria-label="REA community">
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA가 Hopper 안에서 분석 브리지를 실행해 네이티브 바이너리를 검사하는 모습" width="1200" />
<br /><br />
<table aria-label="REA 커뮤니티">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>리버스 엔지니어링 커뮤니티에 참여하세요</strong>
</a><br />
<sub>Discord · 질문과 답변 · 작업 공유</sub>
<sub>Discord · 질문과 답변 · 결과 공유</sub>
</td>
</tr>
</table>
<br />
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="Hopper에서 분석 브리지를 시작하고 네이티브 바이너리를 조사하는 REA" width="1200" />
</div>
---
앱에서 마음에 드는 기능을 찾았다면 에이전트에게 REA로 조사해 달라고 요청하세요. 소스 코드가 없어도 앱을 분석하고, 기능의 동작과 근거를 설명한 뒤, 프로젝트에 맞는 기능을 구현할 수 있습니다.
앱에서 내 제품에도 넣고 싶은 기능을 발견했나요? 에이전트에게 REA로 조사해 달라고 요청하세요. 소스 코드가 없어도 앱을 검사하고, 기능의 작동 원리를 설명하고, 근거를 보여 주고, 프로젝트에 맞는 기능을 구현할 수 있습니다.
REA는 네이티브 바이너리, JavaScript/Electron 앱, .NET 어셈블리, 웹사이트 분석 도구를 제공합니다. 에이전트와 터미널에서 같은 도구를 사용할 수 있습니다. 분석은 로컬에서 실행되며 결과에는 근거와 제한 사항이 포함됩니다.
REA는 에이전트를 분석 도구에 연결해 네이티브 바이너리, JavaScript와 Electron 앱, .NET 어셈블리, 웹사이트를 검사할 수 있게 합니다. 터미널에서도 같은 도구를 사용할 수 있습니다. 분석은 로컬에서 실행되며, 결과에는 각 결론의 근거와 한계가 포함됩니다.
Setup은 에이전트를 설정하고 기존 Hopper 또는 Ghidra 설치에 연결합니다. 승인 후 Hopper를 설치할 수도 있습니다.
설정 과정은 에이전트에 REA를 등록하고 해당 버전에 맞는 워크플로 지침을 설치합니다. 네이티브 분석에는 기존 Hopper 또는 Ghidra 설치를 사용할 수 있습니다. 승인하면 설정 과정에서 Hopper를 설치할 수도 있습니다. 정적 JavaScript 분석에는 두 엔진 모두 필요하지 않습니다.
## 에이전트에게 바로 요청하기
[설정](#빠른-시작)을 마친 뒤 에이전트를 다시 시작하고 요청하세요.
```text
메모 앱의 검색 기능이 어떻게 동작하는지 조사하고 근거를 보여 주세요.
그다음 제 프로젝트에 비슷한 기능을 구현해 주세요.
```
메모 앱 대신 조사할 앱을 지정하거나 먼저 개요를 요청할 수 있습니다.
## 바이너리에서 동작까지
| 디컴파일 | 이해 | 재현 |
| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| 네이티브 앱이나 실행 파일에서 프로시저, 의사 코드, 어셈블리, 문자열, 심볼, 세그먼트, 메타데이터를 복구합니다. | 호출자, 피호출자, 상호 참조, 호출 그래프를 따라 기능이나 알고리즘의 실제 동작을 설명합니다. | 에이전트가 배운 내용을 사용자의 기술 스택, 화면, 요구 사항에 맞는 제품 기능으로 만듭니다. |
REA는 분석을 바이너리 증거에 근거하게 합니다. 원본 소스 코드를 복원하거나 앱 전체를 자동으로 복제한다고 주장하지 않습니다.
## REA를 사용하는 이유
| | |
| ------------------- | --------------------------------------------------------------------------------------------------- |
| **에이전트용** | 앱의 동작에 대해 질문하고 추측 대신 에이전트가 조사하게 합니다. |
| **CLI와 MCP** | 터미널과 에이전트에서 동일한 리버스 엔지니어링 기능을 사용합니다. |
| **안내식 설정** | 에이전트 설정, 기존 분석 도구 연결, 승인 후 Hopper 설치를 지원합니다. |
| **통찰에서 코드로** | 기능을 이해한 뒤 같은 코딩 세션에서 자신의 제품에 맞는 버전을 구현합니다. |
| **로컬 분석** | 분석은 지원되는 로컬 호스트에서 실행되며 REA는 바이너리를 호스팅 분석 서비스에 업로드하지 않습니다. |
| **컨텍스트 유지** | 질문마다 분석을 처음부터 시작하지 않고 여러 앱을 연속으로 조사합니다. |
> **[REA 웹사이트](https://rea.tools/)**에서 설정 방법, 그림으로 설명한 가이드, 실제 사례를 확인하세요.
## 빠른 시작
### 설정 실행하기(권장)
### 에이전트 설정
REA를 에이전트에 연결하세요.
Node.js와 npm이 설치된 환경에서 다음 명령을 실행하세요.
```bash
npx rea-agents setup
```
Setup은 먼저 연결할 에이전트를 여러 개 선택하도록 안내합니다. 기존 REA 등록은 기본 선택되며, 감지만 된 클라이언트는 자동 선택되지 않습니다. 아직 설정되지 않은 클라이언트도 직접 선택할 수 있습니다. 정확한 경로와 변경 사항을 검토한 뒤 승인하세요. 선택한 에이전트에는 기본적으로 REA 워크플로가 설치됩니다. Hopper는 별도의 선택 사항이며 따로 승인해야 합니다. 기존 Ghidra 경로도 등록할 수 있습니다.
에이전트를 선택하고, 예정된 변경 사항을 검토한 뒤 승인하세요. 설정 과정은 기존 설정을 백업하고 REA의 MCP 서버와 버전에 맞는 워크플로 지침을 추가합니다. 완료 후 에이전트를 다시 시작하세요.
변경 전에 계획을 표시하고 기존 설정을 백업합니다. 요구 사항과 추가 옵션은 [설치 안내](docs/installation.md)를 참고하세요.
설정은 Claude Code, Codex, Cursor, Gemini CLI, Grok Build 및 [다른 에이전트](docs/installation.md#supported-agents)를 지원합니다. 제공자 설정과 수동 MCP 등록은 [설치 및 설정](docs/installation.md)을 참고하세요.
### 에이전트에서 사용하기
### 에이전트에게 요청
설정 후 에이전트를 다시 시작하고 조사할 앱이나 기능을 설명하세요. REA는 Claude Code, Claude Desktop, Codex, Cursor, Gemini CLI, Windsurf, Devin, OpenCode, Antigravity, GitHub Copilot CLI, Command Code, VS Code를 지원합니다. 기존 REA 등록은 기본 선택되고, 그 밖의 감지된 클라이언트는 직접 선택해야 합니다. 다른 에이전트는 아래 MCP 설정을 사용할 수 있습니다.
Hopper는 데모 모드로 사용할 수 있습니다. 첫 실행 안내가 나오면 데모를 선택하거나 기존 라이선스를 입력하세요.
### AI 코딩 어시스턴트용 스킬(선택)
AI 코딩 어시스턴트에 스킬을 추가하면 더 풍부한 컨텍스트를 얻을 수 있습니다.
```bash
npx skills add morluto/rea --skill reverse-engineer-anything
```text
Notes 앱의 검색 기능이 어떻게 작동하는지 조사하고, 근거를 보여 준 다음, 내 프로젝트에 비슷한 기능을 구현해 줘.
```
이 스킬은 REA의 조사 워크플로를 제공합니다. 위 Setup을 실행해 REA를 에이전트에 연결하고 분석 도구를 설정하세요. Setup은 기본적으로 버전에 맞는 스킬을 설치합니다. 이 명령은 저장소 버전의 스킬을 설치합니다.
Notes를 대상 앱으로 바꾸고 이해하고 싶은 기능을 지정하세요.
압축을 해제한 JavaScript/Electron 앱 트리나 ASAR라면 MCP 설정이나 네이티브 엔진 없이 바로 분석할 수 있습니다.
### 터미널 사용
압축을 푼 JavaScript/Electron 앱 디렉터리 또는 ASAR를 검사합니다.
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
경로를 조사 대상의 경로로 바꾸세요(Windows에서는 `"D:/apps/example"` 같은 경로). 이 정적 워크플로에서는 이런 경로도 지원됩니다. 네이티브 분석에는 전용 엔진 설정이 필요합니다.
결과에는 모듈, 임포트, Electron 경계와 관련 근거가 포함됩니다. 경로를 분석할 대상으로 바꾸세요. Windows에서는 `"D:/apps/example"` 같은 경로를 사용할 수 있습니다.
### rea 명령 설치하기
명령줄 도구를 설치하세요.
```bash
curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash
```
Node.js와 npm이 먼저 설치되어 있어야 합니다. 터미널에서 실행하면 설치 프로그램이 `rea`를 설치하고 설정을 시작합니다.
npm으로 설치한 뒤 설정을 실행할 수도 있습니다.
```bash
npm install --global rea-agents
rea setup
```
### 요구 사항
- macOS 12 이상
- Ubuntu 24.04+, Fedora 41+, 64비트 Arch Linux 또는 CachyOS
- Node.js 22.x (>=22.19), 24.x (>=24.11) 또는 26+와 npm
네이티브 바이너리 분석에는 Hopper 또는 Ghidra가 필요합니다. Hopper는 별도 소프트웨어입니다. 데모에는 공급업체의 제한이 있지만 유료 라이선스가 필수는 아닙니다.
Ghidra는 Linux x64와 macOS x64/arm64를 지원합니다. Ghidra 12.1.x와 그 설치본이 선언한 완전한 64비트 JDK(`application.java.min`부터 `application.java.max`까지)를 별도로 설치한 뒤 REA에서 사용하도록 설정하세요. 현재 12.1 릴리스는 JDK 21 이상을 요구하고 상한은 없습니다. 브리지는 Ghidra 12.1.4와 JDK 21에서 검증됩니다. macOS에서는 호스트 아키텍처에 맞는 네이티브 디컴파일러도 필요합니다.
Setup은 설치를 확인하고 경로를 저장할 수 있습니다. Ghidra, Java, Node.js, npm, Homebrew를 설치하거나 업데이트하지 않습니다.
저장소 main과 npm 4.1.0에는 로컬 NTFS상의 네이티브 x86-64 PE 애플리케이션(비관리, 비 DLL 대상)을 위한 실험적인 Windows x64 Ghidra P0 지원이 포함되어 있습니다. Job Object, 비공개 DACL, 경로 승인 제어가 함께 제공됩니다. 이전 npm 패키지에 이 기능이 있을 것으로 기대하기 전에 [릴리스 경계](docs/installation.md#released-package-and-main)를 확인하세요. 전제 조건과 검증 범위는 [Windows Ghidra P0](docs/windows-ghidra-p0.md)를 참고하세요.
### 문제 해결
`npx -y rea-agents@latest doctor`는 호스트, 의존성, 분석 도구, 에이전트 설정을 변경 없이 확인합니다. 구조화된 진단에는 `--json`을 추가하세요.
Linux에서는 실행 가능한 `/opt/hopper/bin/Hopper`를 우선 사용하고, 사용할 수 없으면 `~/.local/share/rea/hopper/bin/Hopper`를 자동으로 확인합니다. 다른 위치에는 `HOPPER_LAUNCHER_PATH`를 설정하세요. 파일이 있는데도 분석 엔진이 없다고 하면 실제 Hopper 경로에 대해 `ldd /absolute/path/to/Hopper | grep 'not found'`를 실행해 누락된 라이브러리를 확인하세요. 자세한 내용은 [Hopper 안내](docs/installation.md#hopper)를 참고하세요.
### 업데이트와 제거
- `rea update`는 현재 REA 설치를 업데이트합니다.
- `rea uninstall`은 REA가 관리하는 에이전트 등록과 워크플로 파일을 제거합니다. Hopper는 유지합니다.
- `rea uninstall --purge-data`는 REA 캐시와 상태도 삭제합니다. 해당 데이터를 지우려는 경우에만 사용하세요.
## 현재 지원 범위
저장소의 현재 기능과 플랫폼 요구 사항은 [영문 지원 가이드](README.md#current-status)에 설명되어 있습니다. main은 [npm 릴리스](docs/installation.md#released-package-and-main)보다 앞선 내용이 포함될 수 있습니다.
- Ghidra는 Linux x64, macOS x64/arm64, 실험적인 Windows x64 P0 경계에서 25개의 읽기 전용 작업을 제공합니다. Linux/macOS에서는 원자적 세션 함수 주석도 추가로 지원합니다. Windows P0는 읽기 전용이며 Ghidra에는 GUI 제어가 없습니다.
- 정적 Android 검사는 별도로 준비한 JADX/Java가 필요합니다. 실제 제공자 검증은 Linux를 대상으로 합니다. [Android 분석](docs/android-analysis.md)을 참고하세요.
- 브라우저, Electron, 프로세스 요청은 대상·동작·수명 주기를 직접 지정하며 호스트의 실제 접근에 의존합니다. 별도의 REA 권한 승인은 필요 없습니다. Setup의 설정 쓰기와 Hopper 설치는 여전히 정확한 계획에 대한 승인이 필요합니다.
- `rea capabilities`는 모든 앱/런타임 도구의 목록이 아니라 바이너리 세션 작업을 설명합니다. 연결된 MCP 도구 목록과 관련 가이드를 참고하세요.
## 하나의 프롬프트로 전체 조사
```text
메모 앱을 리버스 엔지니어링해 오프라인 검색 기능의 작동 방식을 설명한 다음,
TypeScript와 SQLite를 사용해 제 프로젝트에 맞는 버전을 구현해 주세요.
```
| 단계 | 에이전트 작업 | REA 도구 |
| ---: | ----------------------- | ---------------------------------------------------------------- |
| 1 | 바이너리 열기 및 식별 | `open_binary`, `binary_overview` |
| 2 | 오프라인 검색 단서 찾기 | `search_strings`, `search_procedures`, `list_names` |
| 3 | 단서를 실행 코드에 연결 | `find_xrefs_to_name`, `xrefs`, `procedure_callers` |
| 4 | 제어 흐름 재구성 | `get_call_graph`, `procedure_callees`, `procedure_info` |
| 5 | 관련 루틴 디컴파일 | `procedure_pseudo_code`, `procedure_assembly`, `batch_decompile` |
| 6 | 프로젝트에 기능 구현 | 기술 스택, 제품, 요구 사항에 맞는 코드 |
REA는 1~5단계의 바이너리 분석을 처리합니다. 6단계는 에이전트가 일반 파일 편집 및 테스트 도구로 수행합니다.
## 에이전트가 할 수 있는 일
- 소스 코드가 없는 기능의 동작을 설명합니다.
- 앱의 인증, 저장소, 업데이트 또는 네트워크 흐름을 재구성합니다.
- 문서화되지 않은 형식이나 인터페이스의 구조를 복구합니다.
- 문자열이나 심볼에서 의심스러운 동작을 구현한 코드까지 추적합니다.
- 한 세션에서 두 앱 버전을 전환하며 구현 경로를 비교합니다.
- 마음에 드는 기능을 조사하고 자신의 제품에 맞는 버전으로 구현합니다.
- 복구한 동작을 제품 기능, 테스트, 마이그레이션 문서, 포팅 또는 상호 운용 가능한 대체품으로 변환합니다.
- Swift 및 Objective-C 메타데이터를 분석합니다.
- Hopper에 이름, 주석, 북마크를 남겨 사람과 에이전트의 분석을 연결합니다.
## 조사 도구 카탈로그
| 도구 분류 | 수 | 용도 |
| ----------------- | --: | ---------------------------------------------------------------------------------------------------------------------------------------- |
| 네이티브 검사 | 41 | 함수, 의사 코드, 어셈블리, 문자열, 심볼, 호출, 참조, 주석, 바이트 읽기, 파일 오프셋 |
| 조사 워크플로 | 14 | 앱 개요, 함수 기록서, 네이티브 API와 디스패치, 일괄 디컴파일, 기능 추적, 호출 경로, 호출 그래프, Swift와 Objective-C 탐색 |
| 네이티브 바이너리 | 10 | macOS의 Mach-O 메타데이터, 서명, plist, 아키텍처, Swift 심볼과 LLDB 호출 관찰; Linux의 ELF 레이아웃, 정적 보호 증거와 기록된 크래시 |
| 아티팩트 그래프 | 7 | 디렉터리와 패키지 목록, 컴파일된 Interface Builder 파일, Apple 애셋 카탈로그, Mach-O dylib 로드 해석, 추출, 오프라인 EVM 인터페이스 추론 |
| 관리 PE/CLI | 7 | .NET 식별, 메타데이터, CIL 명령어, 네이티브 종속성, 재구성 가져오기, 빌드 비교 |
| 펌웨어 | 2 | Linux 펌웨어 영역 검사 및 명시적 추출 |
| Android APK | 5 | 패키지와 manifest 선언, 클래스 검색, 멤버 목록, 메서드 디컴파일, 정적 참조 |
| 브라우저 관찰 | 12 | 페이지 구조, 네트워크 메타데이터, 스크립트, 소스 맵, WebMCP 탐색, 스크린샷, 캡처 비교 |
| Electron 분석 | 5 | 렌더러 관찰, 정적 앱 매핑, 정적·런타임 결과 연결 |
| JavaScript 런타임 | 2 | Node/Electron Inspector 대상 탐색, 스크립트 위치, 실행 컨텍스트 이벤트 |
| 앱 워크플로 | 13 | 캡처한 웹 스크립트 내보내기, 계층 간 기능 추적, 빌드 비교, 히스토리 소스 매핑, 정적 반환 구조 비교, 재구현 검증 |
| 작업 공간과 관찰 | 21 | 세션, 근거 번들, 탐색 컨텍스트, 프로세스·아티팩트·함수 비교, 미해결 항목 기록 |
## 로드맵
다음 작업은 네이티브 대상 검증 확대, JavaScript와 .NET의 버전 비교, 런타임 관찰과 재구현 검증입니다. Setup은 에이전트 연결과 Hopper 설치 선택을 이미 지원합니다. 다른 분석 도구 설치는 향후 작업입니다. [설치 로드맵](docs/roadmap.md)과 [분석 도구 평가](docs/provider-evaluation.md)를 참고하세요.
## 다른 코딩 에이전트에서 사용하기
Setup은 Claude Code, Claude Desktop, Codex, Cursor, Gemini CLI, Windsurf, Devin, OpenCode, Antigravity, GitHub Copilot CLI, Command Code, VS Code를 지원합니다. 기존 REA 등록은 기본 선택되고, 그 밖의 감지된 클라이언트는 직접 선택해야 합니다. 로컬 MCP 서버를 지원하는 에이전트는 다음 설정으로 연결할 수 있습니다.
<!-- x-release-please-start-version -->
```json
{
"mcpServers": {
"rea": {
"command": "npx",
"args": ["-y", "rea-agents@6.0.0", "mcp"]
}
}
}
```
<!-- x-release-please-end -->
## 작동 방식
```mermaid
flowchart LR
Agent["코딩 에이전트"] --> REA["REA<br/>CLI + MCP"]
Terminal["터미널"] --> REA
REA --> Hopper["Hopper 분석 작업"]
Hopper --> App["사용자의 앱"]
REA --> Ghidra["Ghidra 읽기 전용 분석<br/>인벤토리 + 함수 분석"]
Ghidra --> App
```
CLI와 MCP 서버는 같은 분석 워크플로를 사용합니다. 터미널 명령은 완료 후 자신의 브리지 세션을 해제하고, 에이전트 세션은 조사 중 연결을 유지할 수 있습니다. REA 세션을 닫아도 사용자가 이용 중인 Hopper 앱은 종료하지 않습니다.
## CLI
위의 에이전트 워크플로가 REA를 사용하는 가장 쉬운 방법입니다. 터미널에서 앱을 한 번 빠르게 살펴보려면 다음을 실행하세요.
```bash
npx -y rea-agents@latest analyze /Applications/Notes.app
```
직접 디컴파일하는 방법과 기타 옵션은 `npx -y rea-agents@latest --help`에서 확인할 수 있습니다.
전역 `rea` 명령으로 설치할 수도 있습니다.
자주 사용할 경우 `rea` 명령을 설치하세요.
```bash
npm install --global rea-agents
rea --help
rea mcp
```
REA는 macOS의 `.app` 폴더를 직접 열 수 있습니다. 에이전트가 앱을 찾지 못하면 설치 위치를 알려 주세요.
네이티브 분석에는 먼저 제공자를 설정해야 합니다. 네이티브 명령, 제공자 선택, 스냅샷, 스크립트 사용은 [CLI 및 Evidence 가이드](docs/cli.md)를 참고하세요.
## Hopper 앱 동작
### REA 업데이트
REA는 필요할 때 Hopper를 시작합니다. Hopper 런처는 내부적으로 앱을 활성화하므로 대상을 열 때 Hopper가 다른 창 앞으로 나타날 수 있습니다. REA는 백그라운드 시작을 요청하지만 항상 뒤에 머무르는 것을 보장할 수 없습니다.
REA는 빠르게 바뀌며 새 릴리스에는 버그 수정이 자주 포함됩니다. 설치된 버전을 최신으로 유지하세요.
명시적인 형식과 아키텍처 인자로 일반적인 FAT/ARM 선택 대화상자를 피하지만, 다른 Hopper 또는 macOS 대화상자에는 사람이 응답해야 할 수 있습니다. 세션 종료 시 브리지와 소켓 디렉터리를 제거하지만 사용자가 작업 중인 Hopper 앱은 종료하지 않습니다.
npm으로 설치한 CLI에서는 다음 명령을 사용합니다.
## 보안 모델
```bash
rea update
```
각 세션은 무작위 capability token과 현재 사용자 전용 Unix 소켓을 사용합니다. Ghidra 세션은 격리된 임시 프로젝트도 사용하며 사용자 소유 Ghidra 프로젝트를 열거나 수정하지 않습니다. 이는 샌드박스가 아니며 같은 운영 체제 사용자로 실행되는 악성 프로세스를 방어하지 않습니다. 신뢰할 수 없는 바이너리를 열면 선택한 로컬 공급자가 현재 사용자 권한으로 분석합니다. 취약점은 [SECURITY.md](SECURITY.md)의 비공개 절차로 신고하세요.
에이전트 등록과 스킬을 갱신하려면 업데이트 과정에서 출력된 설정 명령을 실행하세요.
## FAQ
`npx`를 사용한다면 다음 명령으로 에이전트 설정을 갱신하세요.
<details><summary><strong>Hopper를 미리 실행해야 하나요?</strong></summary>
```bash
npx rea-agents@latest setup
```
아니요. REA가 필요할 때 시작합니다. Hopper가 실행 중이어도 사용할 수 있지만 기존 GUI 문서에 연결하는 대신 새 분석 문서를 엽니다.
설정 변경 사항을 검토하고 에이전트를 다시 시작하세요. 일회성 CLI 작업에는 `npx rea-agents@latest` 뒤에 필요한 명령을 붙여 실행하세요.
## REA의 작동 방식
에이전트는 MCP를 통해 REA를 호출하여 대상을 검사하고 관련 코드를 추적합니다. REA는 조사 결과와 근거를 반환합니다. 에이전트는 이를 바탕으로 추가 질문을 하고, 동작을 설명하거나, 구현을 작성하고 테스트합니다. CLI 명령도 같은 워크플로를 사용합니다.
![REA 조사 흐름: 에이전트가 로컬 대상에 대해 질문하면 REA가 분석 도구로 대상을 검사하고 추적합니다. 에이전트는 반환된 코드, 참조, 확인되지 않은 사항을 이용해 설명하고 구현하고 테스트합니다.](website/public/assets/figures/rea-investigation-flow.svg)
[원본 크기의 그림 열기](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## 분석할 수 있는 대상
REA에는 Node.js 22.x(>=22.19), 24.x(>=24.11) 또는 26+와 npm이 필요합니다. 추가 도구와 호스트 지원은 대상에 따라 다릅니다.
| 대상 | REA가 반환하는 내용 | 요구 사항 및 가이드 |
| --------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| 네이티브 바이너리 | 의사 코드, 어셈블리, 문자열, 심볼, 호출, 참조 | Hopper, Ghidra 또는 IDA; [네이티브 분석](https://rea.tools/guides/native/) |
| 오프라인 ELF 레이아웃 | 섹션, 세그먼트, 원본 심볼/재배치 정보, 정적 분석으로 얻은 보안 완화 기법 후보 | Linux x64에서 호출자가 제공하는 pwntools; [바이너리 진단](docs/binary-diagnostics.md) |
| EVM 바이트코드 | 디스패치 선택자, 바이트 오프셋, 추론한 인자와 상태 변경 가능 여부 | Linux x64의 로컬 원시 바이트/16진수 입력 파일; [오프라인 EVM 가이드](docs/evm-bytecode.md) |
| 기록된 Linux 크래시 | 원시 note 레코드, 기록된 모든 스레드의 레지스터/시그널, 선택적 매핑 후보 | Linux x64에서 호출자가 제공하는 pwntools; GDB/pwndbg는 선택 사항; [기록된 크래시](docs/recorded-crashes.md) |
| JavaScript / Electron | 모듈, 임포트, 소스 맵, 라우트, IPC, 네이티브 애드온 관계 | Node.js와 npm; [애플리케이션 분석](https://rea.tools/guides/javascript/) |
| 웹사이트 | 페이지 구조, 스크립트, 네트워크 관찰 결과, 요청한 스크린샷 | Chrome 계열 브라우저; [브라우저 분석](https://rea.tools/guides/browser/) |
| 저장된 네트워크 캡처 | 요청, 응답, 접근 가능한 페이로드, 소스 위치 | HAR; mitmproxy 네이티브 캡처에는 Linux의 mitmdump; [캡처 가이드](docs/web-network-captures.md) |
| .NET 어셈블리 | 메타데이터, CIL 명령, 선언된 네이티브 의존성, 빌드 비교 | 정적 검사; [관리 코드 가이드](docs/managed-code-analysis.md) |
| Android APK | 매니페스트 선언, 클래스, 디컴파일된 메서드, 참조 | Linux/macOS/Windows x64의 헤드리스 JADX와 전체 JDK; [Android 가이드](docs/android-analysis.md) |
| Android 기기 | 기기, 패키지, 프로세스, 로그, 덤프, 화면 캡처, APK/파일 전송 | 호출자 제공 adb(에뮬레이터 또는 실제 기기); [ADB 가이드](docs/adb-device-analysis.md) |
| JEB 프로젝트 | 엔진 기반 프로젝트 유닛, 아티팩트 해시, 타입/메서드 의사코드 | 호출자가 시작하고 MCP를 제공하는 JEB 클라이언트(REA_JEB_MCP_URL로 선택); [JEB 가이드](docs/jeb-analysis.md) |
| Android 리소스 | 디코딩된 매니페스트, 문자열 테이블, 로캘, 버전 정보 | 호출자 제공 Apktool 런처; [리소스 가이드](docs/apktool-resource-analysis.md) |
| 펌웨어 | 영역, 추출 결과, 네이티브 분석으로 전달할 정보 | Linux의 Binwalk / Unblob; [펌웨어 가이드](docs/firmware-analysis.md) |
| 패키지 및 리소스 | 파일 목록, 다이제스트, plist, Apple 번들 구조, 추출한 리소스 | [아티팩트 및 JavaScript 가이드](docs/javascript-artifact-reconstruction.md), [Apple 애플리케이션](docs/apple-application-analysis.md) |
| 프로세스 동작 | 터미널 출력, 상호작용, 종료 및 파일 시스템 관찰 결과, 실행 비교 | 네이티브 PTY를 지원하는 Linux/macOS; [프로세스 캡처](docs/process-capture.md) |
정적 JavaScript 및 .NET 검사는 제공된 파일을 읽으며 애플리케이션을 실행하지 않습니다. 런타임 캡처는 사용자의 권한으로 선택한 대상을 실행하거나 대상과 상호작용합니다. 각 런타임 가이드에서 그 영향을 설명합니다.
<a id="choosing-a-deep-analysis-provider"></a>
지원하는 네이티브 형식과 호스트는 제공자마다 다릅니다. [Hopper 및 Ghidra 설정](docs/installation.md#hopper), [IDA 가이드](docs/ida-provider.md), [실험적 Windows Ghidra 지원](docs/windows-ghidra-p0.md)을 참고하세요. Ghidra는 [16비트 DOS 분석](docs/ghidra-dos.md)도 지원합니다. 제공자 선택은 [CLI 가이드](docs/cli.md#choose-a-provider)를 참고하세요. 최신 npm 릴리스 이후 추가된 기능은 [릴리스에서의 사용 가능 여부](docs/installation.md#released-package-and-main)를 확인하세요.
## 사례
[![DX-Ball 사운드 패닝, Notion 클립보드 브리지, TH04 탄환 고리 사례를 보여 주는 그림](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: 사운드 패닝 계산 재구현
사운드 호출에서 위치를 패닝 값으로 변환하는 보조 함수까지 추적하고, 명령을 검사하여 불완전한 의사 코드를 C로 옮깁니다. 재구현한 코드는 원본 x86에 대한 3,205개 테스트 케이스를 통과했으며, 컴파일된 함수의 63바이트 전체를 재현합니다.
[사례 읽기](https://rea.tools/showcase/dx-ball/) ·
[재구현 저장소](https://github.com/N0zoM1z0/dx-ball)
### Notion: Electron 클립보드 브리지 추적
렌더러의 클립보드 API를 찾고, preload와 IPC를 거쳐 메인 프로세스까지 추적한 뒤, 서식 있는 클립보드 형식을 검사합니다.
[사례 읽기](https://rea.tools/showcase/notion/)
### TH04: DOS 원형 탄막 계산 복원
원본 PC-98 게임의 16비트 명령을 검사하고 고정 각도와 조준 각도의 계산을 복원합니다. 재구현한 C++를 당시 컴파일러의 출력과 비교합니다.
[사례 읽기](https://rea.tools/showcase/th04/) ·
[재구현 저장소](https://github.com/N0zoM1z0/th04)
REA로 흥미로운 대상을 분석했다면 알려 주세요. [issue](https://github.com/morluto/rea/issues) 또는 [pull request](https://github.com/morluto/rea/pulls)에 대상, 조사하려던 질문, REA가 어떻게 도움이 되었는지, 무엇을 알아냈는지를 담아 공유하세요.
## 자주 묻는 질문
<details>
<summary><strong>어떤 에이전트에서 REA를 사용할 수 있나요?</strong></summary>
로컬 MCP 서버를 지원하는 에이전트라면 사용할 수 있습니다. 설정 과정은 [지원하는 에이전트](docs/installation.md#supported-agents)를 구성합니다. 다른 클라이언트는 [수동 MCP 등록](docs/installation.md#mcp-registry)을 이용할 수 있습니다.
</details>
<details><summary><strong>REA에 Hopper가 포함되나요?</strong></summary>
<details>
<summary><strong>Hopper, Ghidra 또는 IDA가 필요한가요?</strong></summary>
아니요. Setup이 Hopper를 설치할 수 있지만 Hopper는 자체 라이선스가 필요한 별도 소프트웨어입니다. REA는 CLI, MCP 서버, 에이전트용 워크플로를 제공합니다.
심층 네이티브 분석에는 이 중 하나를 사용합니다. 정적 JavaScript 및 .NET 검사에는 네이티브 분석 엔진이 필요하지 않습니다. 설정 과정에서 승인 후 Hopper를 설치할 수 있으며, Ghidra와 IDA는 기존 설치를 사용합니다. [제공자 설정](docs/installation.md#hopper)을 참고하세요.
</details>
<details><summary><strong>바이너리가 업로드되나요?</strong></summary>
<details>
<summary><strong>Hopper를 먼저 실행해야 하나요?</strong></summary>
REA에는 호스팅 분석 서비스가 없습니다. 로컬 Unix 소켓을 통해 Hopper를 조작합니다. 에이전트나 모델 공급자의 데이터 정책은 별도로 확인하세요.
REA는 작업에 필요할 때 Hopper를 실행합니다. macOS에서는 처음 실행할 때 데모 모드를 선택하거나 라이선스를 활성화하라는 대화 상자가 나타날 수 있습니다. [Hopper 실행 및 문제 해결](docs/installation.md#launcher-paths-and-troubleshooting)을 참고하세요.
</details>
<details><summary><strong>원본 소스 코드를 복구할 수 있나요?</strong></summary>
<details>
<summary><strong>skills.sh에서 설치하는 스킬은 어떤 역할을 하나요?</strong></summary>
보장할 수 없습니다. REA는 의사 코드, 어셈블리, 심볼, 문자열, 메타데이터 및 관계를 제공하여 에이전트가 관찰된 동작을 설명하거나 호환되게 재현하도록 돕습니다.
스킬은 에이전트에게 조사 지침을 제공합니다. `npx rea-agents setup`으로 REA의 MCP 서버를 등록하고 버전에 맞는 지침을 설치한 뒤 에이전트를 다시 시작하세요. [스킬만 설치하기](docs/installation.md#skill-only-installation)를 참고하세요.
</details>
## 개발
<details>
<summary><strong>REA는 어떤 코드를 반환하나요?</strong></summary>
개발 환경, 아키텍처, 테스트, 릴리스 지침은 [CONTRIBUTING.md](CONTRIBUTING.md)를 참고하세요.
네이티브 분석은 의사 코드와 어셈블리를 반환합니다. JavaScript/Electron 분석은 모듈과 그 관계를 복원합니다. 에이전트는 이 결과를 사용해 구현을 작성하고 테스트합니다. [사례](#사례)에서 구체적인 예를 볼 수 있습니다.
</details>
<details>
<summary><strong>REA가 내 앱을 업로드하나요?</strong></summary>
REA는 대상을 로컬에서 분석합니다. 에이전트는 도구 결과를 받으며, 에이전트의 모델 제공자에는 별도의 데이터 정책이 있습니다.
</details>
<details>
<summary><strong>버그가 발생하면 어떻게 해야 하나요?</strong></summary>
먼저 업데이트하세요. 최근 릴리스에서 이미 수정되었을 수 있습니다.
npm으로 설치한 CLI에서는 다음 명령을 사용합니다.
```bash
rea update
```
`npx`로 에이전트를 설정했다면 다음 명령을 사용합니다.
```bash
npx rea-agents@latest setup
```
에이전트를 사용 중이라면 [설정 갱신](#rea-업데이트)을 완료하고 다시 시작하세요. 같은 작업을 다시 시도하세요. 문제가 계속되면 REA 버전, 대상 유형, 재현 단계, 오류 출력을 포함해 [issue를 등록](https://github.com/morluto/rea/issues)하세요.
</details>
## 문서
웹사이트의 [실습 가이드](https://rea.tools/guides/)부터 읽어 보세요. 정확한 옵션, 사전 요구 사항, 결과 계약은 다음 문서를 참고하세요.
- [설치 및 설정](docs/installation.md): 에이전트 등록, 제공자 설정, 업데이트, 제거.
- [준비 상태 확인 및 문제 해결](docs/installation.md#check-readiness-for-your-task): 특정 에이전트 또는 분석 엔진 진단.
- [CLI 및 Evidence](docs/cli.md): 명령, 제공자 선택, 스냅샷, 가져오기/내보내기, 종료 상태.
- [MCP 계약](docs/mcp-contracts.md) 및 [에이전트 프롬프트](docs/mcp-prompts.md): 도구 결과, 세션, 안내에 따른 조사.
- [도구 카탈로그](docs/mcp-contracts.md#generated-catalog): 빌드 시 생성되는 도구, 제공자, CLI 명령 목록.
- [로드맵](docs/roadmap.md): 계획된 작업과 기능 진행 상황.
취약점은 [SECURITY.md](SECURITY.md)에 따라 보고하세요.
## 스타 기록
🎉 **GitHub 스타 20,000개, 감사합니다!**
🎉 **GitHub 스타 50,000개, 감사합니다!**
REA를 사용하고, 버그를 제보하고, 빌드를 테스트하고, 수정에 기여해 주신 모든 분께 감사드립니다.
REA를 사용하고, 버그를 보고하고, 기능을 요청하고, 빌드를 테스트하고, 수정에 기여해 주신 모든 분께 감사드립니다.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
@@ -329,6 +273,16 @@ REA를 사용하고, 버그를 제보하고, 빌드를 테스트하고, 수정
</picture>
</a>
## 면책 조항
REA는 합법적인 리버스 엔지니어링 연구, 분석, 재구성을 위한 도구를 제공합니다. 필요한 권한을 얻고 관련 법률을 준수할 책임은 사용자에게 있습니다. 이 프로젝트는 불법적이거나 허가받지 않은 사용을 지지하지 않습니다.
## 기여
REA에 도움을 보태 주세요! [issue를 등록](https://github.com/morluto/rea/issues)해 버그나 기능을 제안하거나, [pull request를 보내](https://github.com/morluto/rea/pulls) 코드와 문서를 개선할 수 있습니다.
개발 환경과 검사 항목은 [CONTRIBUTING.md](CONTRIBUTING.md), 검증 절차는 [테스트 가이드](docs/testing.md), 프로젝트 구조는 [아키텍처 지도](docs/architecture.mermaid)를 참고하세요.
## 라이선스
[MIT](LICENSE)
+286
View File
@@ -0,0 +1,286 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · **Polski** · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA: Reverse Engineer Anything
### Jeden serwer MCP do inżynierii wstecznej plików binarnych, aplikacji i zachowania w czasie wykonywania.
**Widzisz funkcję, która Ci się podoba? Dowiedz się, jak działa, aż do poziomu kodu binarnego.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[Strona internetowa](https://rea.tools/) · [Przewodniki](https://rea.tools/guides/) · [Przykłady zastosowań](https://rea.tools/showcase/)**
[Szybki start](#szybki-start) · [Jak działa REA](#jak-działa-rea) · [Co możesz analizować](#co-możesz-analizować) · [Przykłady zastosowań](#przykłady-zastosowań) · [FAQ](#faq) · [Dokumentacja](#dokumentacja)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA uruchamia most analityczny w Hopperze podczas analizy natywnego pliku binarnego" width="1200" />
<br /><br />
<table aria-label="Społeczność REA">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>Dołącz do społeczności inżynierii wstecznej</strong>
</a><br />
<sub>Discord · Pytania i odpowiedzi · Pokaż swój projekt</sub>
</td>
</tr>
</table>
<br />
</div>
---
Widzisz w aplikacji funkcję, którą chcesz mieć we własnym produkcie? Poproś swojego agenta, aby zbadał ją za pomocą REA. Może przeanalizować aplikację bez jej kodu źródłowego, wyjaśnić działanie funkcji, pokazać dowody i stworzyć jej wersję dla Twojego projektu.
REA łączy Twojego agenta z narzędziami do analizy natywnych plików binarnych, aplikacji JavaScript i Electron, zestawów .NET oraz stron internetowych. Z tych samych narzędzi możesz korzystać w terminalu. Analiza odbywa się lokalnie, a wyniki zawierają dowody i ograniczenia stojące za każdym wnioskiem.
Konfigurator rejestruje REA w Twoim agencie i instaluje pasujące instrukcje pracy. Analiza kodu natywnego może korzystać z istniejącej instalacji Hoppera lub Ghidry; konfigurator może też zainstalować Hoppera po uzyskaniu zgody. Statyczna analiza JavaScript nie wymaga żadnego z tych silników.
> **[Odwiedź stronę REA](https://rea.tools/)**, aby znaleźć instrukcje konfiguracji, ilustrowane przewodniki i rzeczywiste studia przypadków.
## Szybki start
### Skonfiguruj agenta
Po zainstalowaniu Node.js i npm uruchom:
```bash
npx rea-agents setup
```
Wybierz swoich agentów, sprawdź proponowane zmiany i zatwierdź je. Konfigurator dodaje serwer MCP REA i pasujące instrukcje pracy, tworząc kopie zapasowe istniejącej konfiguracji. Następnie uruchom agenta ponownie.
Konfigurator obsługuje Claude Code, Codex, Cursor, Gemini CLI, Grok Build i [innych agentów](docs/installation.md#supported-agents). Konfigurację dostawców analizy i ręczną rejestrację MCP opisuje przewodnik [instalacji i konfiguracji](docs/installation.md).
### Zapytaj agenta
```text
Sprawdź, jak działa wyszukiwanie w aplikacji Notes, pokaż mi dowody i stwórz podobną funkcję dla mojego projektu.
```
Zastąp Notes wybraną aplikacją i wskaż funkcję, którą chcesz zrozumieć.
### Korzystaj z terminala
Przeanalizuj rozpakowany katalog aplikacji JavaScript/Electron lub archiwum ASAR:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
Wynik obejmuje moduły, importy, granice komponentów Electron oraz dowody. Zastąp ścieżkę ścieżką do swojego celu, na przykład `"D:/apps/example"` w systemie Windows.
Aby zainstalować polecenie `rea` do regularnego użytku:
```bash
npm install --global rea-agents
rea --help
```
Przed analizą kodu natywnego skonfiguruj dostawcę analizy. Polecenia analizy natywnej, wybór dostawcy, migawki i użycie w skryptach opisuje [przewodnik CLI i Evidence](docs/cli.md).
### Zaktualizuj REA
REA szybko się rozwija, a nowe wydania często zawierają poprawki błędów. Dbaj o aktualność swojej instalacji.
Dla CLI zainstalowanego przez npm:
```bash
rea update
```
Aby odświeżyć rejestracje agentów i umiejętność, uruchom polecenie konfiguracji wyświetlone po aktualizacji.
Jeśli używasz `npx`, zaktualizuj konfigurację agenta poleceniem:
```bash
npx rea-agents@latest setup
```
Sprawdź zmiany konfiguracji i uruchom agenta ponownie. Do jednorazowych poleceń CLI używaj `npx rea-agents@latest`, a następnie nazwy polecenia.
## Jak działa REA
Twój agent wywołuje REA przez MCP, aby analizować cel i śledzić istotny kod. REA zwraca ustalenia wraz z dowodami. Agent wykorzystuje je do zadawania dalszych pytań, wyjaśniania zachowania lub pisania i testowania implementacji. Polecenia CLI korzystają z tych samych procedur.
![Przebieg badania z REA: agent pyta o lokalny cel, REA analizuje go i śledzi za pomocą narzędzi analitycznych, a agent korzysta ze zwróconego kodu, odwołań i niewiadomych, aby wyjaśnić działanie, stworzyć implementację i ją przetestować.](website/public/assets/figures/rea-investigation-flow.svg)
[Otwórz ilustrację w pełnym rozmiarze](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## Co możesz analizować
REA wymaga Node.js 22.x (>=22.19), 24.x (>=24.11) lub 26+ oraz npm. Dodatkowe narzędzia i obsługiwane platformy zależą od celu analizy:
| Cel | Co zwraca REA | Wymagania i przewodnik |
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| Natywne pliki binarne | Pseudokod, kod asemblera, ciągi znaków, symbole, wywołania i odwołania | Hopper, Ghidra lub IDA; [analiza kodu natywnego](https://rea.tools/guides/native/) |
| Układ pliku ELF w trybie offline | Sekcje, segmenty, oryginalne symbole/relokacje i potencjalne mechanizmy zabezpieczeń wskazane przez analizę statyczną | pwntools dostarczone przez użytkownika w systemie Linux x64; [diagnostyka plików binarnych](docs/binary-diagnostics.md) |
| Kod bajtowy EVM | Selektory wywołań, przesunięcia bajtowe, wywnioskowane argumenty i mutowalność | Lokalny plik z surowymi bajtami lub zapisem szesnastkowym w systemie Linux x64; [przewodnik EVM offline](docs/evm-bytecode.md) |
| Zarejestrowane awarie systemu Linux | Surowe rekordy note, rejestry/sygnały każdego zarejestrowanego wątku i opcjonalni kandydaci na mapowania | pwntools dostarczone przez użytkownika w systemie Linux x64; opcjonalnie GDB/pwndbg; [zarejestrowane awarie](docs/recorded-crashes.md) |
| JavaScript / Electron | Moduły, importy, mapy źródeł, trasy, IPC i powiązania z natywnymi dodatkami | Node.js i npm; [analiza aplikacji](https://rea.tools/guides/javascript/) |
| Strony internetowe | Struktura strony, skrypty, obserwacje sieciowe i zamówione zrzuty ekranu | Przeglądarka z rodziny Chrome; [analiza w przeglądarce](https://rea.tools/guides/browser/) |
| Zapisane przechwycenia ruchu sieciowego | Żądania, odpowiedzi, dostępne dane przesyłane i lokalizacje źródłowe | HAR; mitmdump w systemie Linux dla natywnych przechwyceń mitmproxy; [przewodnik przechwytywania](docs/web-network-captures.md) |
| Zestawy .NET | Metadane, instrukcje CIL, zadeklarowane zależności natywne i porównania kompilacji | Analiza statyczna; [przewodnik kodu zarządzanego](docs/managed-code-analysis.md) |
| Pakiety APK dla Androida | Deklaracje manifestu, klasy, zdekompilowane metody i odwołania | JADX bez interfejsu graficznego i pełny JDK w systemach Linux/macOS/Windows x64; [przewodnik Androida](docs/android-analysis.md) |
| Urządzenia z Androidem | Urządzenia, pakiety, procesy, logi, zrzuty, zrzuty ekranu oraz transfery APK/plików | adb dostarczony przez wywołującego (emulator lub urządzenie); [przewodnik ADB](docs/adb-device-analysis.md) |
| Projekty JEB | Jednostki projektu obsługiwane przez silnik, skróty artefaktów i pseudokod typów/metod | Uruchomiony przez wywołującego klient JEB udostępniający MCP, wybrany przez REA_JEB_MCP_URL; [przewodnik JEB](docs/jeb-analysis.md) |
| Zasoby Androida | Zdekodowany manifest, tablice ciągów, języki i informacje o wersji | Należący do wywołującego launcher Apktool; [przewodnik zasobów](docs/apktool-resource-analysis.md) |
| Oprogramowanie układowe | Regiony, wyniki wyodrębniania i przekazanie do analizy kodu natywnego | Binwalk / Unblob w systemie Linux; [przewodnik oprogramowania układowego](docs/firmware-analysis.md) |
| Pakiety i zasoby | Spisy plików, skróty, pliki plist, struktura pakietów Apple i wyodrębnione zasoby | [Przewodnik artefaktów i JavaScript](docs/javascript-artifact-reconstruction.md), [aplikacje Apple](docs/apple-application-analysis.md) |
| Zachowanie procesów | Wyjście terminala, interakcje, obserwacje zakończenia i systemu plików oraz porównania uruchomień | Linux/macOS z natywnym PTY; [przechwytywanie procesów](docs/process-capture.md) |
Statyczna analiza JavaScript i .NET odczytuje dostarczone pliki bez uruchamiania aplikacji. Przechwytywanie w czasie wykonywania uruchamia wybrany cel lub wchodzi z nim w interakcje z uprawnieniami Twojego użytkownika; skutki opisano w odpowiednich przewodnikach.
<a id="choosing-a-deep-analysis-provider"></a>
Obsługiwane formaty natywne i platformy zależą od dostawcy analizy. Zobacz [konfigurację Hoppera i Ghidry](docs/installation.md#hopper), [przewodnik IDA](docs/ida-provider.md) oraz [eksperymentalną obsługę Ghidry w systemie Windows](docs/windows-ghidra-p0.md). Ghidra obsługuje też [analizę 16-bitowego DOS-a](docs/ghidra-dos.md). Wybór dostawcy opisuje [przewodnik CLI](docs/cli.md#choose-a-provider). Sprawdź [dostępność w wydaniach](docs/installation.md#released-package-and-main) dla funkcji dodanych po najnowszym wydaniu npm.
## Przykłady zastosowań
[![Ilustracje studiów przypadku panoramowania dźwięku w DX-Ball, mostka schowka w Notion i pierścienia pocisków w TH04](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: odtworzenie obliczania panoramy dźwięku
Prześledź wywołanie dźwięku do funkcji pomocniczej przeliczającej pozycję na panoramę, sprawdź instrukcje i przekształć niepełny pseudokod w C. Odtworzona implementacja przechodzi 3 205 przypadków dla oryginalnego x86 i odtwarza wszystkie 63 bajty skompilowanej funkcji.
[Przeczytaj studium przypadku](https://rea.tools/showcase/dx-ball/) · [Repozytorium odtworzonej implementacji](https://github.com/N0zoM1z0/dx-ball)
### Notion: śledzenie mostu schowka w Electron
Znajdź API schowka w procesie renderującym, prześledź je przez preload i IPC do procesu głównego, a następnie sprawdź format schowka wraz z danymi formatowania.
[Przeczytaj studium przypadku](https://rea.tools/showcase/notion/)
### TH04: odtworzenie obliczania pierścienia pocisków w DOS-ie
Sprawdź 16-bitowe instrukcje oryginalnej gry na PC-98, odtwórz obliczenia kątów stałych i skierowanych na cel oraz porównaj odtworzony C++ z wynikiem historycznego kompilatora.
[Przeczytaj studium przypadku](https://rea.tools/showcase/th04/) · [Repozytorium odtworzonej implementacji](https://github.com/N0zoM1z0/th04)
Jeśli użyłeś REA do czegoś ciekawego, chętnie to zobaczymy. Opisz swój przypadek w [zgłoszeniu](https://github.com/morluto/rea/issues) lub [pull requeście](https://github.com/morluto/rea/pulls), podając cel analizy, pytanie, sposób, w jaki REA pomogło, i swoje ustalenia.
## FAQ
<details>
<summary><strong>Którzy agenci mogą korzystać z REA?</strong></summary>
Każdy agent obsługujący lokalne serwery MCP. Konfigurator konfiguruje [obsługiwanych agentów](docs/installation.md#supported-agents); inne klienty mogą użyć [ręcznej rejestracji MCP](docs/installation.md#mcp-registry).
</details>
<details>
<summary><strong>Czy potrzebuję Hoppera, Ghidry lub IDA?</strong></summary>
Dogłębna analiza kodu natywnego używa jednego z nich. Statyczna analiza JavaScript i .NET działa bez silnika analizy natywnej. Konfigurator może zainstalować Hoppera po uzyskaniu zgody; Ghidra i IDA korzystają z istniejących instalacji. Zobacz [konfigurację dostawców analizy](docs/installation.md#hopper).
</details>
<details>
<summary><strong>Czy muszę najpierw uruchomić Hoppera?</strong></summary>
REA uruchamia Hoppera, gdy wymaga tego operacja. W systemie macOS przy pierwszym uruchomieniu okno dialogowe może poprosić o wybór trybu demonstracyjnego lub aktywację licencji. Zobacz [uruchamianie Hoppera i rozwiązywanie problemów](docs/installation.md#launcher-paths-and-troubleshooting).
</details>
<details>
<summary><strong>Co daje zainstalowanie umiejętności z skills.sh?</strong></summary>
Umiejętność dostarcza agentowi instrukcje prowadzenia analizy. Użyj `npx rea-agents setup`, aby zarejestrować serwer MCP REA i zainstalować pasujące instrukcje, a następnie uruchom agenta ponownie. Zobacz [instalację samej umiejętności](docs/installation.md#skill-only-installation).
</details>
<details>
<summary><strong>Jaki kod zwraca REA?</strong></summary>
Analiza kodu natywnego zwraca pseudokod i kod asemblera. Analiza JavaScript/Electron odzyskuje moduły i ich powiązania. Agent wykorzystuje te ustalenia do napisania i przetestowania implementacji; [przykłady zastosowań](#przykłady-zastosowań) pokazują ten proces w praktyce.
</details>
<details>
<summary><strong>Czy REA przesyła moją aplikację?</strong></summary>
REA analizuje cele lokalnie. Twój agent otrzymuje wyniki narzędzi, a dostawca jego modelu ma własną politykę dotyczącą danych.
</details>
<details>
<summary><strong>Co zrobić, gdy napotkam błąd?</strong></summary>
Najpierw zaktualizuj REA; najnowsze wydanie mogło już naprawić ten problem.
Dla CLI zainstalowanego przez npm:
```bash
rea update
```
Dla konfiguracji agenta przez `npx`:
```bash
npx rea-agents@latest setup
```
Jeśli używasz agenta, wykonaj [odświeżenie konfiguracji](#zaktualizuj-rea) i uruchom go ponownie. Ponów tę samą operację. Jeśli problem pozostaje, [otwórz zgłoszenie](https://github.com/morluto/rea/issues), podając wersję REA, typ celu analizy, kroki odtworzenia problemu i komunikaty błędu.
</details>
## Dokumentacja
Zacznij od [przewodników z przykładami](https://rea.tools/guides/) na stronie internetowej. Dokładne opcje, wymagania wstępne i kontrakty wyników opisano tutaj:
- [Instalacja i konfiguracja](docs/installation.md): rejestracja agentów, konfiguracja dostawców analizy, aktualizacje i odinstalowanie.
- [Gotowość i rozwiązywanie problemów](docs/installation.md#check-readiness-for-your-task): diagnostyka jednego agenta lub silnika analizy.
- [CLI i Evidence](docs/cli.md): polecenia, wybór dostawcy, migawki, import/eksport i kody zakończenia.
- [Kontrakty MCP](docs/mcp-contracts.md) i [prompty dla agentów](docs/mcp-prompts.md): wyniki narzędzi, sesje i prowadzone analizy.
- [Katalog narzędzi](docs/mcp-contracts.md#generated-catalog): generowany podczas kompilacji wykaz narzędzi, dostawców i poleceń CLI.
- [Plan rozwoju](docs/roadmap.md): planowane prace i śledzenie funkcjonalności.
Zgłaszaj podatności zgodnie z [SECURITY.md](SECURITY.md).
## Historia gwiazdek
🎉 **50 000 gwiazdek na GitHubie — dziękujemy!**
Dziękujemy wszystkim, którzy używają REA, zgłaszają błędy, proponują nowe funkcje, testują kompilacje i przesyłają poprawki.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="Historia gwiazdek REA na GitHubie" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## Zastrzeżenie
REA dostarcza narzędzia do zgodnych z prawem badań z zakresu inżynierii wstecznej, analizy i odtwarzania. Odpowiadasz za uzyskanie wymaganych zezwoleń i przestrzeganie obowiązującego prawa. Projekt nie popiera działań nielegalnych ani nieautoryzowanych.
## Współtworzenie
Chętnie przyjmiemy Twoją pomoc w rozwoju REA! [Otwórz zgłoszenie](https://github.com/morluto/rea/issues), aby poinformować o błędzie lub zaproponować funkcję, albo [wyślij pull request](https://github.com/morluto/rea/pulls) z ulepszeniami kodu lub dokumentacji.
Zobacz [CONTRIBUTING.md](CONTRIBUTING.md), aby poznać konfigurację środowiska programistycznego i kontrole, [testowanie](docs/testing.md), aby poznać ścieżki weryfikacji, oraz [mapę architektury](docs/architecture.mermaid), aby poznać strukturę projektu.
## Licencja
[MIT](LICENSE)
+286
View File
@@ -0,0 +1,286 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · **Português (Brasil)** · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA: Faça engenharia reversa de qualquer coisa
### Um único MCP para engenharia reversa de binários, aplicativos e comportamento em execução.
**Viu uma funcionalidade de que gostou? Entenda como ela funciona, até o nível binário.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[Site](https://rea.tools/) · [Guias](https://rea.tools/guides/) · [Casos de uso](https://rea.tools/showcase/)**
[Início rápido](#início-rápido) · [Como o REA funciona](#como-o-rea-funciona) · [O que você pode analisar](#o-que-você-pode-analisar) · [Casos de uso](#casos-de-uso) · [Perguntas frequentes](#perguntas-frequentes) · [Documentação](#documentação)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA inicia sua ponte de análise dentro do Hopper enquanto inspeciona um binário nativo" width="1200" />
<br /><br />
<table aria-label="Comunidade REA">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>Participe da comunidade de engenharia reversa</strong>
</a><br />
<sub>Discord · Perguntas e respostas · Compartilhe seus resultados</sub>
</td>
</tr>
</table>
<br />
</div>
---
Viu uma funcionalidade em um aplicativo que gostaria de ter no seu próprio produto? Peça ao seu agente para investigá-la com o REA. Ele pode inspecionar o aplicativo sem o código-fonte, explicar como a funcionalidade funciona, apresentar as evidências e criar uma versão para o seu projeto.
O REA conecta seu agente a ferramentas para inspecionar binários nativos, aplicativos JavaScript e Electron, assemblies .NET e sites. Você também pode usar as mesmas ferramentas pelo terminal. A análise acontece localmente, e os resultados incluem as evidências e limitações por trás de cada conclusão.
A configuração registra o REA no seu agente e instala as instruções de fluxo de trabalho correspondentes. A análise nativa pode usar uma instalação existente do Hopper ou do Ghidra; a configuração também pode instalar o Hopper opcionalmente, mediante aprovação. A análise estática de JavaScript não precisa de nenhum dos dois motores.
> **[Visite o site do REA](https://rea.tools/)** para instruções de configuração, guias ilustrados e estudos de caso reais.
## Início rápido
### Configure seu agente
Com Node.js e npm instalados, execute:
```bash
npx rea-agents setup
```
Escolha seus agentes, revise as alterações propostas e aprove-as. A configuração adiciona o servidor MCP do REA e as instruções de fluxo de trabalho correspondentes, com backups das configurações existentes. Reinicie seu agente depois.
A configuração oferece suporte ao Claude Code, Codex, Cursor, Gemini CLI, Grok Build e [outros agentes](docs/installation.md#supported-agents). Consulte [instalação e configuração](docs/installation.md) para configurar provedores e registrar o MCP manualmente.
### Peça ao seu agente
```text
Investigue como a busca funciona no aplicativo Notes, mostre as evidências e crie uma funcionalidade semelhante para o meu projeto.
```
Substitua Notes pelo aplicativo alvo e indique a funcionalidade que deseja entender.
### Use o terminal
Inspecione um diretório extraído de um aplicativo JavaScript/Electron ou um arquivo ASAR:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
O resultado inclui módulos, importações, limites do Electron e suas evidências. Substitua o caminho pelo do seu alvo, como `"D:/apps/example"` no Windows.
Para instalar o comando `rea` e usá-lo regularmente:
```bash
npm install --global rea-agents
rea --help
```
Para análise nativa, configure primeiro um provedor. Consulte o [guia de CLI e Evidence](docs/cli.md) para comandos nativos, seleção de provedores, snapshots e uso em scripts.
### Atualize o REA
O REA muda rapidamente, e novas versões incluem correções frequentes de bugs. Mantenha sua instalação atualizada.
Para uma CLI instalada pelo npm:
```bash
rea update
```
Para atualizar os registros dos agentes e a skill, execute o comando de configuração exibido pela atualização.
Se você usa `npx`, atualize a configuração do agente com:
```bash
npx rea-agents@latest setup
```
Revise as alterações de configuração e reinicie seu agente. Para comandos avulsos da CLI, use `npx rea-agents@latest` seguido do comando.
## Como o REA funciona
Seu agente chama o REA por MCP para inspecionar o alvo e rastrear o código relevante. O REA retorna os resultados com suas evidências. O agente usa esses resultados para fazer novas perguntas, explicar o comportamento ou escrever e testar uma implementação. Os comandos da CLI usam os mesmos fluxos de trabalho.
![Fluxo de investigação do REA: seu agente pergunta sobre um alvo local, o REA o inspeciona e rastreia com ferramentas de análise, e o agente usa o código, as referências e os pontos desconhecidos retornados para explicar, implementar e testar.](website/public/assets/figures/rea-investigation-flow.svg)
[Abra a figura em tamanho completo](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## O que você pode analisar
O REA requer Node.js 22.x (>=22.19), 24.x (>=24.11) ou 26+, além do npm. As ferramentas adicionais e os sistemas anfitriões compatíveis dependem do alvo:
| Alvo | O que o REA retorna | Requisitos e guia |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| Binários nativos | Pseudocódigo, assembly, strings, símbolos, chamadas e referências | Hopper, Ghidra ou IDA; [análise nativa](https://rea.tools/guides/native/) |
| Estrutura ELF sem execução | Seções, segmentos, símbolos/relocações originais e possíveis mecanismos de mitigação identificados por análise estática | pwntools fornecido pelo chamador no Linux x64; [diagnóstico de binários](docs/binary-diagnostics.md) |
| Bytecode EVM | Seletores de despacho, offsets de bytes, argumentos inferidos e mutabilidade | Entrada local com bytes brutos ou representação hexadecimal no Linux x64; [guia de EVM sem execução](docs/evm-bytecode.md) |
| Falhas do Linux registradas | Registros note brutos, registradores/sinais de cada thread registrada e candidatos opcionais a mapeamentos | pwntools fornecido pelo chamador no Linux x64; GDB/pwndbg opcionais; [falhas registradas](docs/recorded-crashes.md) |
| JavaScript / Electron | Módulos, importações, source maps, rotas, IPC e relações com complementos nativos | Node.js e npm; [análise de aplicativos](https://rea.tools/guides/javascript/) |
| Sites | Estrutura da página, scripts, observações de rede e capturas de tela solicitadas | Um navegador da família Chrome; [análise do navegador](https://rea.tools/guides/browser/) |
| Capturas de rede salvas | Requisições, respostas, payloads acessíveis e localizações de origem | HAR; mitmdump no Linux para capturas no formato nativo do mitmproxy; [guia de capturas](docs/web-network-captures.md) |
| Assemblies .NET | Metadados, instruções CIL, dependências nativas declaradas e comparações de builds | Inspeção estática; [guia de código gerenciado](docs/managed-code-analysis.md) |
| APKs Android | Declarações do manifesto, classes, métodos descompilados e referências | JADX sem interface gráfica e um JDK completo no Linux/macOS/Windows x64; [guia de Android](docs/android-analysis.md) |
| Dispositivos Android | Dispositivos, pacotes, processos, logs, despejos, capturas de tela e transferências de APK/arquivos | adb fornecido pelo chamador (emulador ou aparelho); [guia de ADB](docs/adb-device-analysis.md) |
| Projetos JEB | Unidades de projeto do motor, hashes de artefatos e pseudocódigo de tipos/métodos | Um cliente JEB iniciado pelo chamador servindo MCP, selecionado com REA_JEB_MCP_URL; [guia de JEB](docs/jeb-analysis.md) |
| Recursos do Android | Manifesto decodificado, tabelas de strings, idiomas e fatos de versão | Lançador do Apktool fornecido pelo chamador; [guia de recursos](docs/apktool-resource-analysis.md) |
| Firmware | Regiões, resultados de extração e encaminhamentos à análise nativa | Binwalk / Unblob no Linux; [guia de firmware](docs/firmware-analysis.md) |
| Pacotes e recursos | Inventários de arquivos, digests, plists, estrutura de bundles Apple e recursos extraídos | [Guia de artefatos e JavaScript](docs/javascript-artifact-reconstruction.md), [aplicativos Apple](docs/apple-application-analysis.md) |
| Comportamento de processos | Saída do terminal, interações, observações de encerramento e do sistema de arquivos, e comparações entre execuções | Linux/macOS com PTY nativo; [captura de processos](docs/process-capture.md) |
A inspeção estática de JavaScript e .NET lê os arquivos fornecidos sem executar o aplicativo. A captura em execução inicia o alvo selecionado ou interage com ele usando as permissões do seu usuário; cada guia descreve seus efeitos.
<a id="choosing-a-deep-analysis-provider"></a>
Os formatos nativos e os sistemas anfitriões compatíveis variam por provedor. Consulte [configuração do Hopper e Ghidra](docs/installation.md#hopper), o [guia do IDA](docs/ida-provider.md) e o [suporte experimental ao Ghidra no Windows](docs/windows-ghidra-p0.md). O Ghidra também oferece [análise de DOS de 16 bits](docs/ghidra-dos.md). Para selecionar um provedor, consulte o [guia da CLI](docs/cli.md#choose-a-provider). Verifique a [disponibilidade nas versões](docs/installation.md#released-package-and-main) das funcionalidades adicionadas após a versão mais recente no npm.
## Casos de uso
[![Ilustrações dos estudos de panoramização de áudio do DX-Ball, da ponte da área de transferência do Notion e do anel de projéteis do TH04](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: reconstruir um cálculo de panorâmica de áudio
Siga uma chamada de áudio até a função auxiliar que converte posição em panorâmica, inspecione as instruções e transforme pseudocódigo incompleto em C. A reconstrução passa em 3.205 casos com o x86 original e reproduz todos os 63 bytes da função compilada.
[Leia o estudo de caso](https://rea.tools/showcase/dx-ball/) · [Repositório da reconstrução](https://github.com/N0zoM1z0/dx-ball)
### Notion: rastrear a ponte da área de transferência do Electron
Encontre a API da área de transferência do renderizador, siga-a por preload e IPC até o processo principal e inspecione o formato da área de transferência com seus dados de formatação.
[Leia o estudo de caso](https://rea.tools/showcase/notion/)
### TH04: recuperar o cálculo de um anel de projéteis no DOS
Inspecione as instruções de 16 bits do jogo original para PC-98, recupere os cálculos de ângulos fixos e direcionados e compare o C++ reconstruído com a saída do compilador da época.
[Leia o estudo de caso](https://rea.tools/showcase/th04/) · [Repositório da reconstrução](https://github.com/N0zoM1z0/th04)
Se você usou o REA em algo interessante, gostaríamos de conhecer. Compartilhe seu caso em uma [issue](https://github.com/morluto/rea/issues) ou um [pull request](https://github.com/morluto/rea/pulls), incluindo o alvo, sua pergunta, como o REA ajudou e o que descobriu.
## Perguntas frequentes
<details>
<summary><strong>Quais agentes podem usar o REA?</strong></summary>
Qualquer agente que ofereça suporte a servidores MCP locais. A configuração prepara os [agentes compatíveis](docs/installation.md#supported-agents); outros clientes podem usar o [registro manual do MCP](docs/installation.md#mcp-registry).
</details>
<details>
<summary><strong>Preciso do Hopper, Ghidra ou IDA?</strong></summary>
A análise nativa aprofundada usa um desses motores. A inspeção estática de JavaScript e .NET funciona sem um motor de análise nativa. A configuração pode instalar o Hopper após aprovação; Ghidra e IDA usam as instalações existentes. Consulte [configuração dos provedores](docs/installation.md#hopper).
</details>
<details>
<summary><strong>Preciso iniciar o Hopper antes?</strong></summary>
O REA inicia o Hopper quando uma operação precisa dele. No macOS, um diálogo na primeira execução pode pedir que você escolha o modo de demonstração ou ative a licença. Consulte [inicialização do Hopper e solução de problemas](docs/installation.md#launcher-paths-and-troubleshooting).
</details>
<details>
<summary><strong>O que faz a instalação da skill pelo skills.sh?</strong></summary>
A skill fornece instruções de investigação ao seu agente. Use `npx rea-agents setup` para registrar o servidor MCP do REA e instalar as instruções correspondentes, depois reinicie seu agente. Consulte [instalação apenas da skill](docs/installation.md#skill-only-installation).
</details>
<details>
<summary><strong>Que código o REA retorna?</strong></summary>
A análise nativa retorna pseudocódigo e assembly. A análise de JavaScript/Electron recupera módulos e suas relações. Seu agente usa esses resultados para escrever e testar uma implementação; os [casos de uso](#casos-de-uso) apresentam exemplos completos.
</details>
<details>
<summary><strong>O REA envia meu aplicativo para algum servidor?</strong></summary>
O REA analisa os alvos localmente. Seu agente recebe os resultados das ferramentas, e o provedor do modelo tem sua própria política de dados.
</details>
<details>
<summary><strong>O que devo fazer se encontrar um bug?</strong></summary>
Atualize primeiro; uma versão recente pode já ter corrigido o problema.
Para uma CLI instalada pelo npm:
```bash
rea update
```
Para configurar o agente por `npx`:
```bash
npx rea-agents@latest setup
```
Se você usa um agente, conclua a [atualização da configuração](#atualize-o-rea) e reinicie-o. Tente executar a mesma tarefa novamente. Se o problema persistir, [abra uma issue](https://github.com/morluto/rea/issues) com sua versão do REA, o tipo de alvo, os passos para reproduzir e a saída do erro.
</details>
## Documentação
Comece pelos [guias práticos](https://rea.tools/guides/) do site. Para opções exatas, pré-requisitos e contratos dos resultados:
- [Instalação e configuração](docs/installation.md): registro de agentes, configuração de provedores, atualizações e desinstalação.
- [Prontidão e solução de problemas](docs/installation.md#check-readiness-for-your-task): diagnóstico de um agente ou motor de análise específico.
- [CLI e Evidence](docs/cli.md): comandos, seleção de provedores, snapshots, importação/exportação e status de saída.
- [Contratos MCP](docs/mcp-contracts.md) e [prompts para agentes](docs/mcp-prompts.md): resultados das ferramentas, sessões e investigações guiadas.
- [Catálogo de ferramentas](docs/mcp-contracts.md#generated-catalog): inventário de ferramentas, provedores e comandos da CLI gerado durante o build.
- [Roadmap](docs/roadmap.md): trabalho planejado e acompanhamento das capacidades.
Relate vulnerabilidades conforme [SECURITY.md](SECURITY.md).
## Histórico de estrelas
🎉 **50.000 estrelas no GitHub — muito obrigado!**
Obrigado a todos que usam o REA, relatam bugs, sugerem funcionalidades, testam builds e contribuem com correções.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="Histórico de estrelas do REA no GitHub" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## Aviso legal
O REA fornece ferramentas para pesquisa, análise e reconstrução por engenharia reversa dentro da lei. Você é responsável por obter as autorizações necessárias e cumprir as leis aplicáveis. O projeto não apoia usos ilegais ou não autorizados.
## Contribuir
Sua ajuda com o REA é bem-vinda! [Abra uma issue](https://github.com/morluto/rea/issues) para relatar um bug ou sugerir uma funcionalidade, ou [envie um pull request](https://github.com/morluto/rea/pulls) para melhorar o código ou a documentação.
Consulte [CONTRIBUTING.md](CONTRIBUTING.md) para configurar o ambiente de desenvolvimento e as verificações, o [guia de testes](docs/testing.md) para os fluxos de verificação e o [mapa da arquitetura](docs/architecture.mermaid) para a estrutura do projeto.
## Licença
[MIT](LICENSE)
+286
View File
@@ -0,0 +1,286 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · **Русский** · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA: Реверс-инжиниринг чего угодно
### Один MCP для реверс-инжиниринга бинарных файлов, приложений и поведения во время выполнения.
**Нашли интересную функцию? Разберитесь, как она работает, вплоть до двоичного кода.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[Сайт](https://rea.tools/) · [Руководства](https://rea.tools/guides/) · [Примеры](https://rea.tools/showcase/)**
[Быстрый старт](#быстрый-старт) · [Как работает REA](#как-работает-rea) · [Что можно анализировать](#что-можно-анализировать) · [Примеры](#примеры) · [Частые вопросы](#частые-вопросы) · [Документация](#документация)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA запускает мост анализа внутри Hopper при исследовании нативного бинарного файла" width="1200" />
<br /><br />
<table aria-label="Сообщество REA">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>Присоединяйтесь к сообществу реверс-инжиниринга</strong>
</a><br />
<sub>Discord · Вопросы и ответы · Обмен результатами</sub>
</td>
</tr>
</table>
<br />
</div>
---
Увидели в приложении функцию, которую хотите добавить в свой продукт? Попросите агента исследовать её с помощью REA. Он может изучить приложение без исходного кода, объяснить работу функции, показать подтверждающие данные и создать подходящую реализацию для вашего проекта.
REA подключает вашего агента к инструментам для исследования нативных бинарных файлов, приложений JavaScript и Electron, сборок .NET и сайтов. Те же инструменты доступны в терминале. Анализ выполняется локально, а результаты содержат данные и ограничения, на которых основан каждый вывод.
Настройка регистрирует REA в вашем агенте и устанавливает соответствующие инструкции по работе. Для нативного анализа можно использовать уже установленный Hopper или Ghidra; настройка также может установить Hopper с вашего согласия. Для статического анализа JavaScript не нужен ни один из этих движков.
> **[Посетите сайт REA](https://rea.tools/)**: там есть инструкции по настройке, иллюстрированные руководства и реальные исследования.
## Быстрый старт
### Настройте агента
Если Node.js и npm установлены, выполните:
```bash
npx rea-agents setup
```
Выберите агентов, проверьте предлагаемые изменения и подтвердите их. Настройка добавляет MCP-сервер REA и соответствующие рабочие инструкции, сохраняя резервные копии существующих настроек. После этого перезапустите агента.
Настройка поддерживает Claude Code, Codex, Cursor, Gemini CLI, Grok Build и [других агентов](docs/installation.md#supported-agents). Настройка провайдеров и ручная регистрация MCP описаны в разделе [установка и настройка](docs/installation.md).
### Задайте вопрос агенту
```text
Исследуй, как работает поиск в приложении Notes, покажи подтверждающие данные и создай похожую функцию для моего проекта.
```
Замените Notes нужным приложением и укажите функцию, которую хотите понять.
### Используйте терминал
Исследуйте распакованный каталог приложения JavaScript/Electron или файл ASAR:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
Результат включает модули, импорты, границы Electron и подтверждающие данные. Замените путь своим, например `"D:/apps/example"` в Windows.
Для регулярного использования установите команду `rea`:
```bash
npm install --global rea-agents
rea --help
```
Для нативного анализа сначала настройте провайдер. Нативные команды, выбор провайдера, снимки и работу со скриптами описывает [руководство по CLI и Evidence](docs/cli.md).
### Обновите REA
REA быстро развивается, и новые версии часто содержат исправления ошибок. Регулярно обновляйте установленную версию.
Для CLI, установленного через npm:
```bash
rea update
```
Чтобы обновить регистрации агентов и skill, выполните команду настройки, которую выведет обновление.
Если используете `npx`, обновите настройку агента командой:
```bash
npx rea-agents@latest setup
```
Проверьте изменения настроек и перезапустите агента. Для разовых команд CLI используйте `npx rea-agents@latest`, а затем нужную команду.
## Как работает REA
Агент вызывает REA через MCP, чтобы исследовать цель и проследить связанный код. REA возвращает результаты вместе с подтверждающими данными. Агент использует их для уточняющих вопросов, объяснения поведения или написания и тестирования реализации. Команды CLI используют те же рабочие процессы.
![Процесс исследования с REA: агент задаёт вопрос о локальной цели, REA исследует её инструментами анализа, а агент использует возвращённый код, ссылки и неизвестные сведения для объяснения, реализации и тестирования.](website/public/assets/figures/rea-investigation-flow.svg)
[Открыть рисунок в полном размере](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## Что можно анализировать
REA требует Node.js 22.x (>=22.19), 24.x (>=24.11) или 26+, а также npm. Дополнительные инструменты и поддерживаемые системы зависят от цели:
| Цель | Что возвращает REA | Требования и руководство |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Нативные бинарные файлы | Псевдокод, ассемблер, строки, символы, вызовы и ссылки | Hopper, Ghidra или IDA; [нативный анализ](https://rea.tools/guides/native/) |
| Структура ELF без запуска | Секции, сегменты, исходные символы/релокации и возможные механизмы защиты по данным статического анализа | pwntools, предоставленный вызывающей стороной, в Linux x64; [диагностика бинарных файлов](docs/binary-diagnostics.md) |
| Байт-код EVM | Селекторы диспетчеризации, смещения байтов, предполагаемые аргументы и изменяемость состояния | Локальные необработанные байты или шестнадцатеричное представление в Linux x64; [руководство по EVM без запуска](docs/evm-bytecode.md) |
| Записанные сбои Linux | Необработанные записи note, регистры/сигналы каждого записанного потока и необязательные кандидаты сопоставления с памятью | pwntools, предоставленный вызывающей стороной, в Linux x64; необязательные GDB/pwndbg; [записанные сбои](docs/recorded-crashes.md) |
| JavaScript / Electron | Модули, импорты, карты исходного кода, маршруты, IPC и связи с нативными дополнениями | Node.js и npm; [анализ приложений](https://rea.tools/guides/javascript/) |
| Сайты | Структура страницы, скрипты, наблюдения за сетью и запрошенные снимки экрана | Браузер семейства Chrome; [анализ браузера](https://rea.tools/guides/browser/) |
| Сохранённые сетевые захваты | Запросы, ответы, доступные полезные данные и позиции в источнике | HAR; mitmdump в Linux для захватов в собственном формате mitmproxy; [руководство по сетевым захватам](docs/web-network-captures.md) |
| Сборки .NET | Метаданные, инструкции CIL, объявленные нативные зависимости и сравнения сборок | Статическое исследование; [руководство по управляемому коду](docs/managed-code-analysis.md) |
| Android APK | Объявления манифеста, классы, декомпилированные методы и ссылки | JADX без графического интерфейса и полный JDK в Linux/macOS/Windows x64; [руководство по Android](docs/android-analysis.md) |
| Устройства Android | Устройства, пакеты, процессы, журналы, дампы, снимки экрана и передача APK/файлов | adb, предоставленный вызывающей стороной (эмулятор или устройство); [руководство по ADB](docs/adb-device-analysis.md) |
| Проекты JEB | Единицы проекта от движка, дайджесты артефактов и псевдокод типов/методов | Запущенный вызывающей стороной клиент JEB с интерфейсом MCP, выбирается через REA_JEB_MCP_URL; [руководство по JEB](docs/jeb-analysis.md) |
| Ресурсы Android | Декодированный манифест, таблицы строк, языки и сведения о версии | Запуск Apktool, предоставленный вызывающей стороной; [руководство по ресурсам](docs/apktool-resource-analysis.md) |
| Прошивки | Области, результаты извлечения и передача в нативный анализ | Binwalk / Unblob в Linux; [руководство по прошивкам](docs/firmware-analysis.md) |
| Пакеты и ресурсы | Списки файлов, хеши, plist, структура пакетов Apple и извлечённые ресурсы | [Руководство по артефактам и JavaScript](docs/javascript-artifact-reconstruction.md), [приложения Apple](docs/apple-application-analysis.md) |
| Поведение процессов | Вывод терминала, взаимодействия, наблюдения за завершением и файловой системой, сравнения запусков | Linux/macOS с нативным PTY; [захват процессов](docs/process-capture.md) |
Статическое исследование JavaScript и .NET читает предоставленные файлы, не запуская приложение. Захват во время выполнения запускает выбранную цель или взаимодействует с ней с правами вашего пользователя; соответствующие руководства описывают последствия.
<a id="choosing-a-deep-analysis-provider"></a>
Нативные форматы и поддерживаемые системы различаются у разных провайдеров. См. [настройку Hopper и Ghidra](docs/installation.md#hopper), [руководство по IDA](docs/ida-provider.md) и [экспериментальную поддержку Ghidra в Windows](docs/windows-ghidra-p0.md). Ghidra также поддерживает [анализ 16-битного DOS](docs/ghidra-dos.md). Выбор провайдера описан в [руководстве по CLI](docs/cli.md#choose-a-provider). Для функций, добавленных после последней версии в npm, проверьте [доступность в релизах](docs/installation.md#released-package-and-main).
## Примеры
[![Иллюстрации примеров панорамирования звука в DX-Ball, моста буфера обмена Notion и кольца пуль в TH04](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: восстановление расчёта звуковой панорамы
Проследите звуковой вызов до функции, преобразующей координату в значение панорамы, изучите инструкции и превратите неполный псевдокод в C. Восстановленная реализация проходит 3 205 тестов с исходным x86-кодом и воспроизводит все 63 байта скомпилированной функции.
[Прочитать исследование](https://rea.tools/showcase/dx-ball/) · [Репозиторий реконструкции](https://github.com/N0zoM1z0/dx-ball)
### Notion: исследование моста буфера обмена Electron
Найдите API буфера обмена в процессе рендеринга, проследите его через preload и IPC до основного процесса и изучите формат буфера обмена с форматированием.
[Прочитать исследование](https://rea.tools/showcase/notion/)
### TH04: восстановление расчёта кольца пуль в DOS
Изучите 16-битные инструкции оригинальной игры для PC-98, восстановите расчёты фиксированных и прицельных углов и сравните восстановленный C++ с выводом компилятора того времени.
[Прочитать исследование](https://rea.tools/showcase/th04/) · [Репозиторий реконструкции](https://github.com/N0zoM1z0/th04)
Если вы исследовали с REA что-то интересное, поделитесь результатом. Создайте [issue](https://github.com/morluto/rea/issues) или [pull request](https://github.com/morluto/rea/pulls) и укажите цель, ваш вопрос, как помог REA и что удалось узнать.
## Частые вопросы
<details>
<summary><strong>Какие агенты могут использовать REA?</strong></summary>
Любой агент с поддержкой локальных MCP-серверов. Настройка конфигурирует [поддерживаемых агентов](docs/installation.md#supported-agents); другие клиенты могут использовать [ручную регистрацию MCP](docs/installation.md#mcp-registry).
</details>
<details>
<summary><strong>Нужны ли мне Hopper, Ghidra или IDA?</strong></summary>
Углублённый нативный анализ использует один из этих инструментов. Статическое исследование JavaScript и .NET работает без движка нативного анализа. Настройка может установить Hopper после подтверждения; Ghidra и IDA используют существующие установки. См. [настройку провайдеров](docs/installation.md#hopper).
</details>
<details>
<summary><strong>Нужно ли сначала запускать Hopper?</strong></summary>
REA запускает Hopper, когда он нужен для операции. В macOS при первом запуске может появиться диалог выбора деморежима или активации лицензии. См. [запуск Hopper и устранение неполадок](docs/installation.md#launcher-paths-and-troubleshooting).
</details>
<details>
<summary><strong>Что даёт установка skill с skills.sh?</strong></summary>
Skill предоставляет агенту инструкции по исследованию. Используйте `npx rea-agents setup`, чтобы зарегистрировать MCP-сервер REA и установить соответствующие инструкции, затем перезапустите агента. См. [установку только skill](docs/installation.md#skill-only-installation).
</details>
<details>
<summary><strong>Какой код возвращает REA?</strong></summary>
Нативный анализ возвращает псевдокод и ассемблер. Анализ JavaScript/Electron восстанавливает модули и их связи. Агент использует эти результаты, чтобы написать и протестировать реализацию; в [примерах](#примеры) показаны практические исследования.
</details>
<details>
<summary><strong>REA загружает моё приложение на сервер?</strong></summary>
REA анализирует цели локально. Ваш агент получает результаты инструментов, а у его поставщика моделей есть собственная политика обработки данных.
</details>
<details>
<summary><strong>Что делать, если я столкнулся с ошибкой?</strong></summary>
Сначала обновитесь: недавний релиз мог уже исправить ошибку.
Для CLI, установленного через npm:
```bash
rea update
```
Для настройки агента через `npx`:
```bash
npx rea-agents@latest setup
```
Если используете агента, завершите [обновление настройки](#обновите-rea) и перезапустите его. Повторите ту же задачу. Если проблема сохраняется, [откройте issue](https://github.com/morluto/rea/issues), указав версию REA, тип цели, шаги воспроизведения и вывод ошибки.
</details>
## Документация
Начните с [практических руководств](https://rea.tools/guides/) на сайте. Точные параметры, требования и контракты результатов описаны здесь:
- [Установка и настройка](docs/installation.md): регистрация агентов, настройка провайдеров, обновление и удаление.
- [Готовность и устранение неполадок](docs/installation.md#check-readiness-for-your-task): диагностика конкретного агента или движка анализа.
- [CLI и Evidence](docs/cli.md): команды, выбор провайдера, снимки, импорт/экспорт и коды завершения.
- [Контракты MCP](docs/mcp-contracts.md) и [промпты агентов](docs/mcp-prompts.md): результаты инструментов, сеансы и исследования с подсказками.
- [Каталог инструментов](docs/mcp-contracts.md#generated-catalog): создаваемый при сборке перечень инструментов, провайдеров и команд CLI.
- [План развития](docs/roadmap.md): запланированные работы и отслеживание возможностей.
Сообщайте об уязвимостях согласно [SECURITY.md](SECURITY.md).
## История звёзд
🎉 **50 000 звёзд на GitHub — спасибо!**
Спасибо всем, кто использует REA, сообщает об ошибках, предлагает новые функции, тестирует сборки и помогает с исправлениями.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="История звёзд REA на GitHub" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## Отказ от ответственности
REA предоставляет инструменты для законных исследований, анализа и реконструкции с помощью реверс-инжиниринга. Вы отвечаете за получение необходимых разрешений и соблюдение применимых законов. Проект не поддерживает незаконное или несанкционированное использование.
## Участие в проекте
Будем рады вашей помощи с REA! [Откройте issue](https://github.com/morluto/rea/issues), чтобы сообщить об ошибке или предложить функцию, либо [отправьте pull request](https://github.com/morluto/rea/pulls) с улучшениями кода или документации.
Настройка среды разработки и проверки описаны в [CONTRIBUTING.md](CONTRIBUTING.md), направления проверки — в [руководстве по тестированию](docs/testing.md), а структура проекта — на [схеме архитектуры](docs/architecture.mermaid).
## Лицензия
[MIT](LICENSE)
+286
View File
@@ -0,0 +1,286 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · **ไทย** · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA: Reverse Engineer Anything
### MCP เดียวสำหรับวิศวกรรมย้อนกลับ ทั้งไบนารี แอปพลิเคชัน และพฤติกรรมขณะทำงาน
**เห็นฟีเจอร์ที่ชอบแล้วอยากรู้ว่าทำงานอย่างไร? เข้าใจได้ลึกถึงระดับไบนารี**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[เว็บไซต์](https://rea.tools/) · [คู่มือ](https://rea.tools/guides/) · [ตัวอย่างการใช้งาน](https://rea.tools/showcase/)**
[เริ่มต้นอย่างรวดเร็ว](#เริ่มต้นอย่างรวดเร็ว) · [REA ทำงานอย่างไร](#rea-ทำงานอย่างไร) · [สิ่งที่วิเคราะห์ได้](#สิ่งที่วิเคราะห์ได้) · [ตัวอย่างการใช้งาน](#ตัวอย่างการใช้งาน) · [คำถามที่พบบ่อย](#คำถามที่พบบ่อย) · [เอกสาร](#เอกสาร)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA เริ่มบริดจ์การวิเคราะห์ภายใน Hopper ขณะตรวจสอบไบนารีเนทีฟ" width="1200" />
<br /><br />
<table aria-label="ชุมชน REA">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>เข้าร่วมชุมชนวิศวกรรมย้อนกลับ</strong>
</a><br />
<sub>Discord · ถามตอบ · แบ่งปันผลงาน</sub>
</td>
</tr>
</table>
<br />
</div>
---
เห็นฟีเจอร์ในแอปที่อยากนำมาใช้ในผลิตภัณฑ์ของคุณเองหรือไม่? ขอให้เอเจนต์ของคุณตรวจสอบด้วย REA เอเจนต์สามารถวิเคราะห์แอปโดยไม่ต้องมีซอร์สโค้ด อธิบายการทำงานของฟีเจอร์ แสดงหลักฐาน และสร้างเวอร์ชันสำหรับโปรเจกต์ของคุณได้
REA เชื่อมเอเจนต์ของคุณกับเครื่องมือสำหรับตรวจสอบไบนารีเนทีฟ แอป JavaScript และ Electron แอสเซมบลี .NET และเว็บไซต์ คุณใช้เครื่องมือเดียวกันจากเทอร์มินัลได้ การวิเคราะห์ทำงานบนเครื่องของคุณ และผลลัพธ์มีทั้งหลักฐานและข้อจำกัดที่ประกอบแต่ละข้อสรุป
ขั้นตอนตั้งค่าจะลงทะเบียน REA กับเอเจนต์และติดตั้งคำแนะนำการทำงานที่ตรงกัน การวิเคราะห์เนทีฟใช้ Hopper หรือ Ghidra ที่ติดตั้งอยู่แล้วได้ และขั้นตอนตั้งค่าสามารถติดตั้ง Hopper เพิ่มเติมเมื่อได้รับอนุมัติ การวิเคราะห์ JavaScript แบบสถิตไม่ต้องใช้เอนจินทั้งสองนี้
> **[เยี่ยมชมเว็บไซต์ REA](https://rea.tools/)** เพื่อดูคำแนะนำการตั้งค่า คู่มือพร้อมภาพประกอบ และกรณีศึกษาจริง
## เริ่มต้นอย่างรวดเร็ว
### ตั้งค่าเอเจนต์
เมื่อติดตั้ง Node.js และ npm แล้ว ให้เรียกใช้:
```bash
npx rea-agents setup
```
เลือกเอเจนต์ ตรวจสอบการเปลี่ยนแปลงที่เสนอ แล้วอนุมัติ ขั้นตอนตั้งค่าจะเพิ่มเซิร์ฟเวอร์ MCP ของ REA และคำแนะนำการทำงานที่ตรงกัน พร้อมสำรองการตั้งค่าที่มีอยู่ จากนั้นเริ่มเอเจนต์ใหม่
ขั้นตอนตั้งค่ารองรับ Claude Code, Codex, Cursor, Gemini CLI, Grok Build และ[เอเจนต์อื่น ๆ](docs/installation.md#supported-agents) ดู[การติดตั้งและตั้งค่า](docs/installation.md) สำหรับการตั้งค่าผู้ให้บริการวิเคราะห์และการลงทะเบียน MCP ด้วยตนเอง
### ถามเอเจนต์
```text
ตรวจสอบว่าการค้นหาในแอป Notes ทำงานอย่างไร แสดงหลักฐานให้ฉันดู และสร้างฟีเจอร์ที่คล้ายกันสำหรับโปรเจกต์ของฉัน
```
แทนที่ Notes ด้วยแอปเป้าหมายและฟีเจอร์ที่คุณต้องการเข้าใจ
### ใช้เทอร์มินัล
ตรวจสอบไดเรกทอรีแอป JavaScript/Electron ที่แตกไฟล์แล้ว หรือไฟล์ ASAR:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
ผลลัพธ์ประกอบด้วยโมดูล การนำเข้า ขอบเขตของ Electron และหลักฐาน แทนที่พาธด้วยเป้าหมายของคุณ เช่น `"D:/apps/example"` บน Windows
หากต้องการติดตั้งคำสั่ง `rea` สำหรับใช้งานเป็นประจำ:
```bash
npm install --global rea-agents
rea --help
```
สำหรับการวิเคราะห์เนทีฟ ให้ตั้งค่าผู้ให้บริการวิเคราะห์ก่อน ดู[คู่มือ CLI และ Evidence](docs/cli.md) สำหรับคำสั่งเนทีฟ การเลือกผู้ให้บริการ สแนปช็อต และการใช้งานในสคริปต์
### อัปเดต REA
REA เปลี่ยนแปลงอย่างรวดเร็ว และรุ่นใหม่มีการแก้ไขบั๊กอยู่บ่อยครั้ง โปรดอัปเดตการติดตั้งของคุณให้เป็นปัจจุบัน
สำหรับ CLI ที่ติดตั้งผ่าน npm:
```bash
rea update
```
หากต้องการปรับปรุงการลงทะเบียนเอเจนต์และสกิลให้เป็นปัจจุบัน ให้เรียกใช้คำสั่งตั้งค่าที่แสดงหลังการอัปเดต
หากใช้ `npx` ให้อัปเดตการตั้งค่าเอเจนต์ด้วย:
```bash
npx rea-agents@latest setup
```
ตรวจสอบการเปลี่ยนแปลงการตั้งค่าและเริ่มเอเจนต์ใหม่ สำหรับคำสั่ง CLI ที่ใช้ครั้งเดียว ให้ใช้ `npx rea-agents@latest` ตามด้วยคำสั่งที่ต้องการ
## REA ทำงานอย่างไร
เอเจนต์เรียก REA ผ่าน MCP เพื่อตรวจสอบเป้าหมายและติดตามโค้ดที่เกี่ยวข้อง REA ส่งข้อค้นพบกลับมาพร้อมหลักฐาน เอเจนต์ใช้ข้อมูลนี้เพื่อถามคำถามต่อ อธิบายพฤติกรรม หรือเขียนและทดสอบการนำไปใช้งาน คำสั่ง CLI ใช้กระบวนการเดียวกัน
![กระบวนการตรวจสอบด้วย REA: เอเจนต์ถามเกี่ยวกับเป้าหมายบนเครื่อง REA ตรวจสอบและติดตามด้วยเครื่องมือวิเคราะห์ แล้วเอเจนต์ใช้โค้ด การอ้างอิง และสิ่งที่ยังไม่ทราบที่ได้รับกลับมาเพื่ออธิบาย สร้าง และทดสอบ](website/public/assets/figures/rea-investigation-flow.svg)
[เปิดภาพขนาดเต็ม](website/public/assets/figures/rea-investigation-flow.svg)
<a id="current-status"></a>
## สิ่งที่วิเคราะห์ได้
REA ต้องใช้ Node.js 22.x (>=22.19), 24.x (>=24.11) หรือ 26+ และ npm เครื่องมือเพิ่มเติมและแพลตฟอร์มที่รองรับขึ้นอยู่กับเป้าหมาย:
| เป้าหมาย | สิ่งที่ REA ส่งกลับ | ข้อกำหนดและคู่มือ |
| ---------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| ไบนารีเนทีฟ | โค้ดเทียม แอสเซมบลี สตริง สัญลักษณ์ การเรียก และการอ้างอิง | Hopper, Ghidra หรือ IDA; [การวิเคราะห์เนทีฟ](https://rea.tools/guides/native/) |
| โครงสร้าง ELF แบบออฟไลน์ | เซกชัน เซกเมนต์ สัญลักษณ์/รีโลเคชันต้นฉบับ และตัวเลือกกลไกป้องกันที่พบจากการวิเคราะห์แบบสถิต | pwntools ที่ผู้ใช้จัดเตรียมบน Linux x64; [การวินิจฉัยไบนารี](docs/binary-diagnostics.md) |
| ไบต์โค้ด EVM | ตัวเลือกฟังก์ชันสำหรับการเรียก ออฟเซ็ตไบต์ อาร์กิวเมนต์และความสามารถในการเปลี่ยนสถานะที่อนุมานได้ | ไฟล์บนเครื่องที่มีไบต์ดิบหรือข้อมูลเลขฐานสิบหกบน Linux x64; [คู่มือ EVM แบบออฟไลน์](docs/evm-bytecode.md) |
| ข้อมูลการแครชของ Linux ที่บันทึกไว้ | ระเบียน note ดิบ รีจิสเตอร์/สัญญาณของทุกเธรดที่บันทึกไว้ และตัวเลือกการแมปเพิ่มเติม | pwntools ที่ผู้ใช้จัดเตรียมบน Linux x64; เลือกใช้ GDB/pwndbg เพิ่มเติมได้; [การแครชที่บันทึกไว้](docs/recorded-crashes.md) |
| JavaScript / Electron | โมดูล การนำเข้า ซอร์สแมป เส้นทาง IPC และความสัมพันธ์กับส่วนเสริมเนทีฟ | Node.js และ npm; [การวิเคราะห์แอปพลิเคชัน](https://rea.tools/guides/javascript/) |
| เว็บไซต์ | โครงสร้างหน้า สคริปต์ ข้อมูลเครือข่ายที่สังเกตได้ และภาพหน้าจอที่ร้องขอ | เบราว์เซอร์ในตระกูล Chrome; [การวิเคราะห์ผ่านเบราว์เซอร์](https://rea.tools/guides/browser/) |
| ข้อมูลเครือข่ายที่บันทึกไว้ | คำขอ คำตอบ เพย์โหลดที่ปรากฏ และตำแหน่งต้นทาง | HAR; mitmdump บน Linux สำหรับข้อมูลที่บันทึกในรูปแบบเนทีฟของ mitmproxy; [คู่มือการบันทึกข้อมูล](docs/web-network-captures.md) |
| แอสเซมบลี .NET | เมทาดาทา คำสั่ง CIL การพึ่งพาเนทีฟที่ประกาศไว้ และการเปรียบเทียบผลการบิลด์ | การตรวจสอบแบบสถิต; [คู่มือโค้ดแบบจัดการ](docs/managed-code-analysis.md) |
| APK ของ Android | การประกาศใน manifest คลาส เมธอดที่ดีคอมไพล์ และการอ้างอิง | JADX แบบไม่มี GUI และ JDK แบบเต็มบน Linux/macOS/Windows x64; [คู่มือ Android](docs/android-analysis.md) |
| อุปกรณ์ Android | อุปกรณ์ แพ็กเกจ โพรเซส บันทึก ดัมพ์ ภาพหน้าจอ และการถ่ายโอน APK/ไฟล์ | adb ที่ผู้เรียกจัดเตรียม (โปรแกรมจำลองหรืออุปกรณ์จริง); [คู่มือ ADB](docs/adb-device-analysis.md) |
| โปรเจกต์ JEB | หน่วยโปรเจกต์จากเอนจิน, แฮชของอาร์ติแฟกต์ และซูโดโค้ดของไทป์/เมท็อด | ไคลเอนต์ JEB ที่ผู้เรียกเริ่มและให้บริการ MCP เลือกด้วย REA_JEB_MCP_URL; [คู่มือ JEB](docs/jeb-analysis.md) |
| ทรัพยากร Android | ไฟล์ manifest ที่ถอดรหัสแล้ว ตารางสตริง ภาษา และข้อมูลเวอร์ชัน | ตัวเรียก Apktool ที่ผู้เรียกจัดเตรียม; [คู่มือทรัพยากร](docs/apktool-resource-analysis.md) |
| เฟิร์มแวร์ | พื้นที่ข้อมูล ผลการแตกไฟล์ และการส่งต่อไปวิเคราะห์เนทีฟ | Binwalk / Unblob บน Linux; [คู่มือเฟิร์มแวร์](docs/firmware-analysis.md) |
| แพ็กเกจและทรัพยากร | รายการไฟล์ ค่าแฮช plist โครงสร้างบันเดิลของ Apple และทรัพยากรที่แตกออกมา | [คู่มืออาร์ติแฟกต์และ JavaScript](docs/javascript-artifact-reconstruction.md), [แอปพลิเคชัน Apple](docs/apple-application-analysis.md) |
| พฤติกรรมของโปรเซส | เอาต์พุตเทอร์มินัล การโต้ตอบ ข้อมูลการสิ้นสุดและระบบไฟล์ที่สังเกตได้ และการเปรียบเทียบการรัน | Linux/macOS ที่มี PTY เนทีฟ; [การบันทึกโปรเซส](docs/process-capture.md) |
การตรวจสอบ JavaScript และ .NET แบบสถิตอ่านไฟล์ที่ให้มาโดยไม่รันแอปพลิเคชัน การบันทึกขณะทำงานจะรันหรือโต้ตอบกับเป้าหมายที่เลือกโดยใช้สิทธิ์ของผู้ใช้คุณ คู่มือการทำงานแต่ละฉบับอธิบายผลที่เกิดขึ้นไว้
<a id="choosing-a-deep-analysis-provider"></a>
รูปแบบไบนารีเนทีฟและแพลตฟอร์มที่รองรับแตกต่างกันตามผู้ให้บริการวิเคราะห์ ดู[การตั้งค่า Hopper และ Ghidra](docs/installation.md#hopper), [คู่มือ IDA](docs/ida-provider.md) และ[การรองรับ Ghidra บน Windows แบบทดลอง](docs/windows-ghidra-p0.md) Ghidra ยังรองรับ[การวิเคราะห์ DOS แบบ 16 บิต](docs/ghidra-dos.md) สำหรับการเลือกผู้ให้บริการ ดู[คู่มือ CLI](docs/cli.md#choose-a-provider) ตรวจสอบ[ความพร้อมใช้งานในแต่ละรุ่น](docs/installation.md#released-package-and-main) สำหรับฟีเจอร์ที่เพิ่มหลังรุ่นล่าสุดบน npm
## ตัวอย่างการใช้งาน
[![ภาพประกอบกรณีศึกษาการแพนเสียงใน DX-Ball บริดจ์คลิปบอร์ดของ Notion และวงแหวนกระสุนใน TH04](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: สร้างการคำนวณแพนเสียงขึ้นใหม่
ติดตามการเรียกเสียงไปยังฟังก์ชันช่วยแปลงตำแหน่งเป็นค่าแพน ตรวจสอบคำสั่ง และแปลงโค้ดเทียมที่ยังไม่สมบูรณ์เป็น C การสร้างขึ้นใหม่นี้ผ่านการทดสอบ 3,205 กรณีเทียบกับ x86 ต้นฉบับ และสร้างไบต์ทั้ง 63 ไบต์ของฟังก์ชันที่คอมไพล์แล้วได้ตรงกัน
[อ่านกรณีศึกษา](https://rea.tools/showcase/dx-ball/) · [รีโพซิทอรีการสร้างขึ้นใหม่](https://github.com/N0zoM1z0/dx-ball)
### Notion: ติดตามบริดจ์คลิปบอร์ดของ Electron
ค้นหา API คลิปบอร์ดของ renderer ติดตามผ่าน preload และ IPC ไปยังโปรเซสหลัก แล้วตรวจสอบรูปแบบคลิปบอร์ดที่มีข้อมูลการจัดรูปแบบ
[อ่านกรณีศึกษา](https://rea.tools/showcase/notion/)
### TH04: กู้คืนการคำนวณวงแหวนกระสุนของ DOS
ตรวจสอบคำสั่ง 16 บิตของเกมต้นฉบับบน PC-98 กู้คืนการคำนวณมุมคงที่และมุมเล็งเป้าหมาย แล้วเปรียบเทียบ C++ ที่สร้างขึ้นใหม่กับผลลัพธ์จากคอมไพเลอร์ในยุคนั้น
[อ่านกรณีศึกษา](https://rea.tools/showcase/th04/) · [รีโพซิทอรีการสร้างขึ้นใหม่](https://github.com/N0zoM1z0/th04)
หากคุณใช้ REA กับสิ่งที่น่าสนใจ เราอยากเห็นผลงานของคุณ แบ่งปันกรณีของคุณผ่าน [issue](https://github.com/morluto/rea/issues) หรือ [pull request](https://github.com/morluto/rea/pulls) พร้อมระบุเป้าหมาย คำถามของคุณ REA ช่วยอย่างไร และสิ่งที่คุณค้นพบ
## คำถามที่พบบ่อย
<details>
<summary><strong>เอเจนต์ใดใช้ REA ได้บ้าง?</strong></summary>
เอเจนต์ใดก็ตามที่รองรับเซิร์ฟเวอร์ MCP บนเครื่อง ขั้นตอนตั้งค่าจะกำหนดค่าให้กับ[เอเจนต์ที่รองรับ](docs/installation.md#supported-agents) ส่วนไคลเอนต์อื่นใช้[การลงทะเบียน MCP ด้วยตนเอง](docs/installation.md#mcp-registry) ได้
</details>
<details>
<summary><strong>จำเป็นต้องมี Hopper, Ghidra หรือ IDA หรือไม่?</strong></summary>
การวิเคราะห์เนทีฟเชิงลึกต้องใช้หนึ่งในเครื่องมือเหล่านี้ การตรวจสอบ JavaScript และ .NET แบบสถิตทำงานได้โดยไม่มีเอนจินวิเคราะห์เนทีฟ ขั้นตอนตั้งค่าสามารถติดตั้ง Hopper หลังได้รับอนุมัติ ส่วน Ghidra และ IDA ใช้การติดตั้งที่คุณมีอยู่แล้ว ดู[การตั้งค่าผู้ให้บริการวิเคราะห์](docs/installation.md#hopper)
</details>
<details>
<summary><strong>ต้องเริ่ม Hopper ก่อนหรือไม่?</strong></summary>
REA เริ่ม Hopper เมื่อการดำเนินการต้องใช้ บน macOS อาจมีหน้าต่างเมื่อรันครั้งแรกให้เลือกโหมดทดลองหรือเปิดใช้ใบอนุญาต ดู[การเริ่ม Hopper และการแก้ไขปัญหา](docs/installation.md#launcher-paths-and-troubleshooting)
</details>
<details>
<summary><strong>การติดตั้งสกิลจาก skills.sh ทำอะไร?</strong></summary>
สกิลให้คำแนะนำการตรวจสอบแก่เอเจนต์ ใช้ `npx rea-agents setup` เพื่อลงทะเบียนเซิร์ฟเวอร์ MCP ของ REA และติดตั้งคำแนะนำที่ตรงกัน แล้วเริ่มเอเจนต์ใหม่ ดู[การติดตั้งเฉพาะสกิล](docs/installation.md#skill-only-installation)
</details>
<details>
<summary><strong>REA ส่งกลับโค้ดแบบใด?</strong></summary>
การวิเคราะห์เนทีฟส่งกลับโค้ดเทียมและแอสเซมบลี การวิเคราะห์ JavaScript/Electron กู้คืนโมดูลและความสัมพันธ์ระหว่างโมดูล เอเจนต์ใช้ข้อค้นพบเหล่านี้เพื่อเขียนและทดสอบการนำไปใช้งาน ดูตัวอย่างที่ทำจริงใน[ตัวอย่างการใช้งาน](#ตัวอย่างการใช้งาน)
</details>
<details>
<summary><strong>REA อัปโหลดแอปของฉันหรือไม่?</strong></summary>
REA วิเคราะห์เป้าหมายบนเครื่องของคุณ เอเจนต์ได้รับผลลัพธ์ของเครื่องมือ และผู้ให้บริการโมเดลของเอเจนต์มีนโยบายข้อมูลของตนเอง
</details>
<details>
<summary><strong>ควรทำอย่างไรเมื่อพบข้อผิดพลาด?</strong></summary>
อัปเดตก่อน รุ่นล่าสุดอาจแก้ไขปัญหานี้แล้ว
สำหรับ CLI ที่ติดตั้งผ่าน npm:
```bash
rea update
```
สำหรับการตั้งค่าเอเจนต์ผ่าน `npx`:
```bash
npx rea-agents@latest setup
```
หากใช้เอเจนต์ ให้ทำ[การปรับปรุงการตั้งค่า](#อัปเดต-rea) ให้เสร็จแล้วเริ่มเอเจนต์ใหม่ ลองงานเดิมอีกครั้ง หากยังพบปัญหา ให้[เปิด issue](https://github.com/morluto/rea/issues) พร้อมระบุรุ่น REA ประเภทเป้าหมาย ขั้นตอนทำให้เกิดปัญหา และข้อความข้อผิดพลาด
</details>
## เอกสาร
เริ่มจาก[คู่มือพร้อมตัวอย่าง](https://rea.tools/guides/) บนเว็บไซต์ สำหรับตัวเลือก ข้อกำหนดเบื้องต้น และสัญญาผลลัพธ์ที่แน่นอน:
- [การติดตั้งและตั้งค่า](docs/installation.md): การลงทะเบียนเอเจนต์ การตั้งค่าผู้ให้บริการ การอัปเดต และการถอนการติดตั้ง
- [ความพร้อมใช้งานและการแก้ไขปัญหา](docs/installation.md#check-readiness-for-your-task): ตรวจวินิจฉัยเอเจนต์หรือเอนจินวิเคราะห์หนึ่งตัว
- [CLI และ Evidence](docs/cli.md): คำสั่ง การเลือกผู้ให้บริการ สแนปช็อต การนำเข้า/ส่งออก และรหัสการสิ้นสุด
- [สัญญา MCP](docs/mcp-contracts.md) และ[พรอมป์ต์สำหรับเอเจนต์](docs/mcp-prompts.md): ผลลัพธ์เครื่องมือ เซสชัน และการตรวจสอบตามคำแนะนำ
- [แค็ตตาล็อกเครื่องมือ](docs/mcp-contracts.md#generated-catalog): รายการเครื่องมือ ผู้ให้บริการ และคำสั่ง CLI ที่สร้างระหว่างการบิลด์
- [แผนพัฒนา](docs/roadmap.md): งานที่วางแผนไว้และรายการติดตามความสามารถ
รายงานช่องโหว่ผ่าน [SECURITY.md](SECURITY.md)
## ประวัติดาว
🎉 **50,000 ดาวบน GitHub — ขอบคุณทุกคน!**
ขอบคุณทุกคนที่ใช้ REA รายงานบั๊ก เสนอฟีเจอร์ ทดสอบบิลด์ และช่วยแก้ไข
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="ประวัติดาว GitHub ของ REA" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## ข้อสงวนสิทธิ์
REA มีเครื่องมือสำหรับการวิจัยวิศวกรรมย้อนกลับ การวิเคราะห์ และการสร้างขึ้นใหม่อย่างถูกกฎหมาย คุณมีหน้าที่ขออนุญาตตามที่จำเป็นและปฏิบัติตามกฎหมายที่เกี่ยวข้อง โปรเจกต์นี้ไม่สนับสนุนการใช้งานที่ผิดกฎหมายหรือไม่ได้รับอนุญาต
## การมีส่วนร่วม
เรายินดีรับความช่วยเหลือในการพัฒนา REA! [เปิด issue](https://github.com/morluto/rea/issues) เพื่อรายงานบั๊กหรือเสนอฟีเจอร์ หรือ[ส่ง pull request](https://github.com/morluto/rea/pulls) เพื่อปรับปรุงโค้ดหรือเอกสาร
ดู [CONTRIBUTING.md](CONTRIBUTING.md) สำหรับการตั้งค่าสภาพแวดล้อมพัฒนาและการตรวจสอบ ดู[การทดสอบ](docs/testing.md) สำหรับแนวทางการตรวจยืนยัน และ[แผนผังสถาปัตยกรรม](docs/architecture.mermaid) สำหรับโครงสร้างโปรเจกต์
## สัญญาอนุญาต
[MIT](LICENSE)
+286
View File
@@ -0,0 +1,286 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · **Türkçe** · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA: Her şeyi tersine mühendislikle inceleyin
### İkili dosyaların, uygulamaların ve çalışma zamanı davranışının tersine mühendisliği için tek bir MCP.
**Beğendiğiniz bir özellik mi gördünüz? İkili kod düzeyine kadar nasıl çalıştığını anlayın.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[Web sitesi](https://rea.tools/) · [Rehberler](https://rea.tools/guides/) · [Örnek çalışmalar](https://rea.tools/showcase/)**
[Hızlı başlangıç](#hızlı-başlangıç) · [REA nasıl çalışır](#rea-nasıl-çalışır) · [Neleri analiz edebilirsiniz](#neleri-analiz-edebilirsiniz) · [Örnek çalışmalar](#örnek-çalışmalar) · [Sık sorulan sorular](#sık-sorulan-sorular) · [Belgeler](#belgeler)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA, yerel bir ikili dosyayı incelerken Hopper içinde analiz köprüsünü başlatıyor" width="1200" />
<br /><br />
<table aria-label="REA topluluğu">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>Tersine mühendislik topluluğuna katılın</strong>
</a><br />
<sub>Discord · Soru-cevap · Sonuç paylaşımı</sub>
</td>
</tr>
</table>
<br />
</div>
---
Bir uygulamada kendi ürününüze eklemek istediğiniz bir özellik mi gördünüz? Ajanınızdan REA ile araştırmasını isteyin. Kaynak kodu olmadan uygulamayı inceleyebilir, özelliğin nasıl çalıştığını açıklayabilir, kanıtları gösterebilir ve projenize uygun bir sürümünü geliştirebilir.
REA, ajanınızı yerel makine kodu içeren ikili dosyaları, JavaScript ve Electron uygulamalarını, .NET derlemelerini ve web sitelerini inceleyen araçlara bağlar. Aynı araçları terminalden de kullanabilirsiniz. Analiz yerel olarak çalışır; sonuçlar her çıkarımın dayandığı kanıtları ve sınırlamaları içerir.
Kurulum, REA'yı ajanınıza kaydeder ve uyumlu iş akışı talimatlarını yükler. Yerel makine kodu analizi mevcut bir Hopper veya Ghidra kurulumunu kullanabilir; kurulum işlemi, onayınızla isteğe bağlı olarak Hopper da yükleyebilir. Statik JavaScript analizi bu iki motora da ihtiyaç duymaz.
> Kurulum talimatları, görselli rehberler ve gerçek örnek çalışmalar için **[REA web sitesini ziyaret edin](https://rea.tools/)**.
## Hızlı başlangıç
### Ajanınızı yapılandırın
Node.js ve npm yüklüyken şu komutu çalıştırın:
```bash
npx rea-agents setup
```
Ajanlarınızı seçin, önerilen değişiklikleri inceleyin ve onaylayın. Kurulum, mevcut yapılandırmaları yedekleyerek REA'nın MCP sunucusunu ve uyumlu iş akışı talimatlarını ekler. Ardından ajanınızı yeniden başlatın.
Kurulum Claude Code, Codex, Cursor, Gemini CLI, Grok Build ve [diğer ajanları](docs/installation.md#supported-agents) destekler. Sağlayıcı yapılandırması ve elle MCP kaydı için [yükleme ve kurulum](docs/installation.md) belgesine bakın.
### Ajanınıza sorun
```text
Notes uygulamasında aramanın nasıl çalıştığını araştır, kanıtları göster ve projem için benzer bir özellik geliştir.
```
Notes yerine hedef uygulamanızı ve anlamak istediğiniz özelliği belirtin.
### Terminali kullanın
Çıkarılmış bir JavaScript/Electron uygulama dizinini veya ASAR dosyasını inceleyin:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
Sonuç; modülleri, içe aktarmaları, Electron sınırlarını ve bunlara ilişkin kanıtları içerir. Yolu hedefinizle değiştirin; Windows'ta örneğin `"D:/apps/example"` kullanabilirsiniz.
Düzenli kullanım için `rea` komutunu yüklemek üzere:
```bash
npm install --global rea-agents
rea --help
```
Yerel makine kodu analizi için önce bir sağlayıcı yapılandırın. Yerel analiz komutları, sağlayıcı seçimi, anlık görüntüler ve betik kullanımı için [CLI ve Evidence rehberine](docs/cli.md) bakın.
### REA'yı güncelleyin
REA hızla değişir ve yeni sürümler sık sık hata düzeltmeleri içerir. Kurulumunuzu güncel tutun.
npm ile yüklenen CLI için:
```bash
rea update
```
Ajan kayıtlarını ve skill'i güncellemek için güncellemenin çıktısında gösterilen kurulum komutunu çalıştırın.
`npx` kullanıyorsanız ajan kurulumunu şu komutla güncelleyin:
```bash
npx rea-agents@latest setup
```
Kurulum değişikliklerini inceleyin ve ajanınızı yeniden başlatın. Tek seferlik CLI işlemleri için `npx rea-agents@latest` komutunun ardından istediğiniz komutu yazın.
## REA nasıl çalışır
Ajanınız, hedefi incelemek ve ilgili kodu izlemek için MCP üzerinden REA'yı çağırır. REA bulguları kanıtlarıyla birlikte döndürür. Ajan bunları takip soruları sormak, davranışı açıklamak veya bir uygulama yazıp test etmek için kullanır. CLI komutları aynı iş akışlarını kullanır.
![REA araştırma akışı: ajanınız yerel bir hedef hakkında soru sorar, REA analiz araçlarıyla hedefi inceler ve izler; ajan döndürülen kodu, referansları ve bilinmeyenleri açıklama, geliştirme ve test için kullanır.](website/public/assets/figures/rea-investigation-flow.svg)
[Şekli tam boyutuyla açın](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## Neleri analiz edebilirsiniz
REA; Node.js 22.x (>=22.19), 24.x (>=24.11) veya 26+ ve npm gerektirir. Ek araçlar ve desteklenen ana bilgisayar sistemleri hedefe bağlıdır:
| Hedef | REA'nın döndürdükleri | Gereksinimler ve rehber |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| Yerel makine kodu içeren ikili dosyalar | Sözde kod, assembly kodu, dizeler, semboller, çağrılar ve referanslar | Hopper, Ghidra veya IDA; [yerel kod analizi](https://rea.tools/guides/native/) |
| Çevrimdışı ELF yapısı | Bölümler, segmentler, özgün semboller/yeniden konumlandırmalar ve statik analizden olası güvenlik önlemleri | Linux x64 üzerinde çağıranın sağladığı pwntools; [ikili dosya tanılama](docs/binary-diagnostics.md) |
| EVM bayt kodu | Yönlendirme seçicileri, bayt ofsetleri, çıkarımla belirlenen argümanlar ve durum değiştirilebilirliği | Linux x64 üzerinde yerel ham bayt/onaltılık girdi; [çevrimdışı EVM rehberi](docs/evm-bytecode.md) |
| Kaydedilmiş Linux çökmeleri | Ham note kayıtları, kaydedilen her iş parçacığının yazmaçları/sinyalleri ve isteğe bağlı eşleme adayları | Linux x64 üzerinde çağıranın sağladığı pwntools; isteğe bağlı GDB/pwndbg; [kaydedilmiş çökmeler](docs/recorded-crashes.md) |
| JavaScript / Electron | Modüller, içe aktarmalar, kaynak haritaları, rotalar, IPC ve yerel eklenti ilişkileri | Node.js ve npm; [uygulama analizi](https://rea.tools/guides/javascript/) |
| Web siteleri | Sayfa yapısı, betikler, ağ gözlemleri ve istenen ekran görüntüleri | Chrome ailesinden bir tarayıcı; [tarayıcı analizi](https://rea.tools/guides/browser/) |
| Kaydedilmiş ağ yakalamaları | İstekler, yanıtlar, erişilebilir yük içerikleri ve kaynak konumları | HAR; mitmproxy'nin kendi biçimindeki yakalamalar için Linux üzerinde mitmdump; [ağ yakalama rehberi](docs/web-network-captures.md) |
| .NET derlemeleri | Meta veriler, CIL talimatları, bildirilmiş yerel bağımlılıklar ve derleme karşılaştırmaları | Statik inceleme; [yönetilen kod rehberi](docs/managed-code-analysis.md) |
| Android APK'leri | Manifest bildirimleri, sınıflar, tersine derlenmiş metotlar ve referanslar | Linux/macOS/Windows x64 üzerinde arayüzsüz JADX ve tam bir JDK; [Android rehberi](docs/android-analysis.md) |
| Android cihazları | Cihazlar, paketler, süreçler, günlükler, dökümler, ekran görüntüleri ve APK/dosya aktarımları | Çağıranın sağladığı adb (emülatör veya cihaz); [ADB rehberi](docs/adb-device-analysis.md) |
| JEB projeleri | Motor destekli proje birimleri, artefakt özetleri ve tür/metot sözdekodu | Çağıranın başlattığı, MCP sunan bir JEB istemcisi, REA_JEB_MCP_URL ile seçilir; [JEB rehberi](docs/jeb-analysis.md) |
| Android kaynakları | Çözülmüş manifest, dize tabloları, diller ve sürüm bilgileri | Çağıranın sağladığı Apktool başlatıcısı; [kaynak rehberi](docs/apktool-resource-analysis.md) |
| Donanım yazılımı | Bölgeler, çıkarma sonuçları ve yerel kod analizine devirler | Linux üzerinde Binwalk / Unblob; [donanım yazılımı rehberi](docs/firmware-analysis.md) |
| Paketler ve kaynaklar | Dosya envanterleri, özet değerleri, plist'ler, Apple paket yapısı ve çıkarılmış kaynaklar | [Artefakt ve JavaScript rehberi](docs/javascript-artifact-reconstruction.md), [Apple uygulamaları](docs/apple-application-analysis.md) |
| Süreç davranışı | Terminal çıktısı, etkileşimler, sonlanma ve dosya sistemi gözlemleri, çalıştırma karşılaştırmaları | Yerel PTY ile Linux/macOS; [süreç yakalama](docs/process-capture.md) |
Statik JavaScript ve .NET incelemesi, uygulamayı çalıştırmadan sağlanan dosyaları okur. Çalışma zamanı yakalaması, seçilen hedefi kullanıcı izinlerinizle çalıştırır veya onunla etkileşime girer; her çalışma zamanı rehberi etkilerini açıklar.
<a id="choosing-a-deep-analysis-provider"></a>
Yerel makine kodu içeren ikili dosya biçimleri ve ana bilgisayar desteği sağlayıcıya göre değişir. [Hopper ve Ghidra kurulumu](docs/installation.md#hopper), [IDA rehberi](docs/ida-provider.md) ve [Windows için deneysel Ghidra desteği](docs/windows-ghidra-p0.md) belgelerine bakın. Ghidra ayrıca [16 bit DOS analizini](docs/ghidra-dos.md) destekler. Sağlayıcı seçimi için [CLI rehberine](docs/cli.md#choose-a-provider) bakın. En son npm sürümünden sonra eklenen özellikler için [sürümlerde kullanılabilirliği](docs/installation.md#released-package-and-main) kontrol edin.
## Örnek çalışmalar
[![DX-Ball ses kaydırma, Notion pano köprüsü ve TH04 mermi halkası örneklerinin çizimleri](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: Sesin stereo konumlandırma hesabını yeniden oluşturma
Bir ses çağrısından konumu stereo konumlandırmaya dönüştüren yardımcı fonksiyona ilerleyin, talimatları inceleyin ve eksik sözde kodu C'ye dönüştürün. Yeniden oluşturulan kod, özgün x86 üzerinde 3.205 test durumunu geçer ve derlenmiş fonksiyonun 63 baytının tamamını yeniden üretir.
[Örnek çalışmayı okuyun](https://rea.tools/showcase/dx-ball/) · [Yeniden oluşturma deposu](https://github.com/N0zoM1z0/dx-ball)
### Notion: Electron pano köprüsünü izleme
İşleyici sürecin pano API'sini bulun, preload ve IPC üzerinden ana sürece kadar izleyin ve zengin pano biçimini inceleyin.
[Örnek çalışmayı okuyun](https://rea.tools/showcase/notion/)
### TH04: DOS mermi halkası hesabını geri çıkarma
Özgün PC-98 oyununun 16 bit talimatlarını inceleyin, sabit ve hedefe yönelik açı hesaplarını geri çıkarın ve yeniden oluşturulan C++ kodunu dönemin derleyici çıktısıyla karşılaştırın.
[Örnek çalışmayı okuyun](https://rea.tools/showcase/th04/) · [Yeniden oluşturma deposu](https://github.com/N0zoM1z0/th04)
REA'yı ilginç bir konuda kullandıysanız görmek isteriz. Hedefi, sorunuzu, REA'nın nasıl yardımcı olduğunu ve bulgularınızı bir [issue](https://github.com/morluto/rea/issues) veya [pull request](https://github.com/morluto/rea/pulls) ile paylaşın.
## Sık sorulan sorular
<details>
<summary><strong>Hangi ajanlar REA'yı kullanabilir?</strong></summary>
Yerel MCP sunucularını destekleyen her ajan REA'yı kullanabilir. Kurulum, [desteklenen ajanları](docs/installation.md#supported-agents) yapılandırır; diğer istemciler [elle MCP kaydını](docs/installation.md#mcp-registry) kullanabilir.
</details>
<details>
<summary><strong>Hopper, Ghidra veya IDA gerekiyor mu?</strong></summary>
Derin yerel kod analizi bunlardan birini kullanır. Statik JavaScript ve .NET incelemesi yerel analiz motoru olmadan çalışır. Kurulum onaydan sonra Hopper yükleyebilir; Ghidra ve IDA mevcut kurulumlarınızı kullanır. [Sağlayıcı kurulumuna](docs/installation.md#hopper) bakın.
</details>
<details>
<summary><strong>Önce Hopper'ı başlatmam gerekiyor mu?</strong></summary>
REA, bir işlem gerektirdiğinde Hopper'ı başlatır. macOS'ta ilk çalıştırmada demo modunu seçmenizi veya lisansınızı etkinleştirmenizi isteyen bir iletişim kutusu açılabilir. [Hopper başlatma ve sorun giderme](docs/installation.md#launcher-paths-and-troubleshooting) belgesine bakın.
</details>
<details>
<summary><strong>skills.sh üzerinden skill yüklemek ne yapar?</strong></summary>
Skill, ajanınıza araştırma talimatları sağlar. REA'nın MCP sunucusunu kaydetmek ve uyumlu talimatları yüklemek için `npx rea-agents setup` kullanın, ardından ajanınızı yeniden başlatın. [Yalnızca skill yükleme](docs/installation.md#skill-only-installation) belgesine bakın.
</details>
<details>
<summary><strong>REA hangi kodu döndürür?</strong></summary>
Yerel kod analizi sözde kod ve assembly kodu döndürür. JavaScript/Electron analizi modülleri ve aralarındaki ilişkileri geri çıkarır. Ajanınız bu bulgularla bir uygulama yazar ve test eder; [örnek çalışmalar](#örnek-çalışmalar) uygulamalı örnekler sunar.
</details>
<details>
<summary><strong>REA uygulamamı yükler mi?</strong></summary>
REA hedefleri yerel olarak analiz eder. Ajanınız araç sonuçlarını alır ve model sağlayıcısının kendi veri politikası vardır.
</details>
<details>
<summary><strong>Bir hatayla karşılaşırsam ne yapmalıyım?</strong></summary>
Önce güncelleyin; yakın tarihli bir sürüm hatayı düzeltmiş olabilir.
npm ile yüklenen CLI için:
```bash
rea update
```
`npx` üzerinden ajan kurulumu için:
```bash
npx rea-agents@latest setup
```
Ajan kullanıyorsanız [kurulum yenilemesini](#reayı-güncelleyin) tamamlayın ve ajanı yeniden başlatın. Aynı görevi tekrar deneyin. Sorun sürerse REA sürümünüzü, hedef türünü, yeniden üretme adımlarını ve hata çıktısını içeren bir [issue açın](https://github.com/morluto/rea/issues).
</details>
## Belgeler
Web sitesindeki [uygulamalı rehberlerden](https://rea.tools/guides/) başlayın. Kesin seçenekler, ön koşullar ve sonuç sözleşmeleri için:
- [Yükleme ve kurulum](docs/installation.md): ajan kaydı, sağlayıcı yapılandırması, güncellemeler ve kaldırma.
- [Hazırlık ve sorun giderme](docs/installation.md#check-readiness-for-your-task): belirli bir ajanı veya analiz motorunu tanılama.
- [CLI ve Evidence](docs/cli.md): komutlar, sağlayıcı seçimi, anlık görüntüler, içe/dışa aktarma ve çıkış durumları.
- [MCP sözleşmeleri](docs/mcp-contracts.md) ve [ajan istemleri](docs/mcp-prompts.md): araç sonuçları, oturumlar ve yönlendirmeli araştırmalar.
- [Araç kataloğu](docs/mcp-contracts.md#generated-catalog): derleme sırasında oluşturulan araç, sağlayıcı ve CLI komutu envanteri.
- [Yol haritası](docs/roadmap.md): planlanan çalışmalar ve yetenek takibi.
Güvenlik açıklarını [SECURITY.md](SECURITY.md) üzerinden bildirin.
## Yıldız geçmişi
🎉 **GitHub'da 50.000 yıldız — teşekkürler!**
REA'yı kullanan, hata bildiren, özellik talep eden, derlemeleri test eden ve düzeltmelere katkıda bulunan herkese teşekkürler.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="REA GitHub yıldız geçmişi" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## Sorumluluk reddi
REA, yasal tersine mühendislik araştırması, analizi ve yeniden oluşturma için araçlar sağlar. Gerekli izinleri almak ve geçerli yasalara uymak sizin sorumluluğunuzdadır. Proje yasa dışı veya yetkisiz kullanımı desteklemez.
## Katkıda bulunma
REA'ya katkınızı bekliyoruz! Hata bildirmek veya özellik önermek için bir [issue açın](https://github.com/morluto/rea/issues); kodu veya belgeleri geliştirmek için bir [pull request gönderin](https://github.com/morluto/rea/pulls).
Geliştirme ortamı ve kontroller için [CONTRIBUTING.md](CONTRIBUTING.md), doğrulama süreçleri için [test rehberi](docs/testing.md) ve proje yapısı için [mimari harita](docs/architecture.mermaid) belgelerine bakın.
## Lisans
[MIT](LICENSE)
+286
View File
@@ -0,0 +1,286 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · **Українська** · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA: Реверс-інжиніринг будь-чого
### Один MCP для реверс-інжинірингу бінарних файлів, застосунків і поведінки під час виконання.
**Побачили цікаву функцію? Зрозумійте, як вона працює, аж до рівня двійкового коду.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[Сайт](https://rea.tools/) · [Посібники](https://rea.tools/guides/) · [Приклади](https://rea.tools/showcase/)**
[Швидкий старт](#швидкий-старт) · [Як працює REA](#як-працює-rea) · [Що можна аналізувати](#що-можна-аналізувати) · [Приклади](#приклади) · [Поширені запитання](#поширені-запитання) · [Документація](#документація)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA запускає міст аналізу всередині Hopper під час дослідження нативного бінарного файла" width="1200" />
<br /><br />
<table aria-label="Спільнота REA">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>Приєднуйтеся до спільноти реверс-інжинірингу</strong>
</a><br />
<sub>Discord · Запитання й відповіді · Обмін результатами</sub>
</td>
</tr>
</table>
<br />
</div>
---
Побачили в застосунку функцію, яку хочете додати до свого продукту? Попросіть агента дослідити її за допомогою REA. Він може перевірити застосунок без вихідного коду, пояснити роботу функції, показати підтвердження та створити реалізацію для вашого проєкту.
REA підключає вашого агента до інструментів дослідження нативних бінарних файлів, застосунків JavaScript і Electron, збірок .NET та сайтів. Ті самі інструменти можна використовувати з термінала. Аналіз виконується локально, а результати містять підтвердження й обмеження, на яких ґрунтується кожен висновок.
Налаштування реєструє REA у вашому агенті та встановлює відповідні інструкції робочих процесів. Для нативного аналізу можна використати вже встановлений Hopper або Ghidra; налаштування також може встановити Hopper за вашою згодою. Статичному аналізу JavaScript не потрібен жоден із цих рушіїв.
> **[Відвідайте сайт REA](https://rea.tools/)**, щоб знайти інструкції налаштування, ілюстровані посібники та реальні дослідження.
## Швидкий старт
### Налаштуйте агента
Якщо Node.js і npm встановлено, виконайте:
```bash
npx rea-agents setup
```
Виберіть агентів, перевірте запропоновані зміни та схваліть їх. Налаштування додає MCP-сервер REA та відповідні інструкції робочих процесів, створюючи резервні копії наявної конфігурації. Після цього перезапустіть агента.
Налаштування підтримує Claude Code, Codex, Cursor, Gemini CLI, Grok Build та [інших агентів](docs/installation.md#supported-agents). Конфігурацію провайдерів і ручну реєстрацію MCP описано в розділі [встановлення й налаштування](docs/installation.md).
### Запитайте агента
```text
Досліди, як працює пошук у застосунку Notes, покажи підтвердження й створи подібну функцію для мого проєкту.
```
Замініть Notes цільовим застосунком і вкажіть функцію, яку хочете зрозуміти.
### Використовуйте термінал
Перевірте розпакований каталог застосунку JavaScript/Electron або файл ASAR:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
Результат містить модулі, імпорти, межі Electron і підтвердження для них. Замініть шлях своїм, наприклад `"D:/apps/example"` у Windows.
Для регулярного використання встановіть команду `rea`:
```bash
npm install --global rea-agents
rea --help
```
Для нативного аналізу спочатку налаштуйте провайдера. Нативні команди, вибір провайдера, знімки та використання у скриптах описує [посібник CLI та Evidence](docs/cli.md).
### Оновіть REA
REA швидко розвивається, а нові випуски часто містять виправлення помилок. Підтримуйте встановлену версію актуальною.
Для CLI, встановленого через npm:
```bash
rea update
```
Щоб оновити реєстрації агентів і skill, виконайте команду налаштування, яку виведе оновлення.
Якщо використовуєте `npx`, оновіть налаштування агента командою:
```bash
npx rea-agents@latest setup
```
Перевірте зміни налаштувань і перезапустіть агента. Для разових команд CLI використовуйте `npx rea-agents@latest`, а потім потрібну команду.
## Як працює REA
Агент викликає REA через MCP, щоб перевірити ціль і простежити пов'язаний код. REA повертає знахідки разом із підтвердженнями. Агент використовує їх для уточнювальних запитань, пояснення поведінки або написання й тестування реалізації. Команди CLI використовують ті самі робочі процеси.
![Процес дослідження з REA: агент запитує про локальну ціль, REA перевіряє й простежує її інструментами аналізу, а агент використовує повернений код, посилання та невідомі дані для пояснення, реалізації й тестування.](website/public/assets/figures/rea-investigation-flow.svg)
[Відкрити зображення в повному розмірі](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## Що можна аналізувати
REA потребує Node.js 22.x (>=22.19), 24.x (>=24.11) або 26+, а також npm. Додаткові інструменти й підтримувані системи залежать від цілі:
| Ціль | Що повертає REA | Вимоги й посібник |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| Нативні бінарні файли | Псевдокод, асемблерний код, рядки, символи, виклики й посилання | Hopper, Ghidra або IDA; [нативний аналіз](https://rea.tools/guides/native/) |
| Структура ELF без запуску | Секції, сегменти, початкові символи/релокації та можливі захисні механізми за даними статичного аналізу | pwntools, наданий стороною, що викликає інструмент, у Linux x64; [діагностика бінарних файлів](docs/binary-diagnostics.md) |
| Байт-код EVM | Селектори диспетчеризації, зміщення байтів, виведені припущення про аргументи та змінюваність стану | Локальні необроблені байти або шістнадцяткове представлення у Linux x64; [посібник EVM без запуску](docs/evm-bytecode.md) |
| Записані аварійні завершення в Linux | Необроблені записи note, регістри/сигнали кожного записаного потоку й необов'язкові кандидати зіставлення пам'яті | pwntools, наданий стороною, що викликає інструмент, у Linux x64; необов'язкові GDB/pwndbg; [записані аварійні завершення](docs/recorded-crashes.md) |
| JavaScript / Electron | Модулі, імпорти, карти вихідного коду, маршрути, IPC і зв'язки з нативними доповненнями | Node.js і npm; [аналіз застосунків](https://rea.tools/guides/javascript/) |
| Сайти | Структура сторінки, скрипти, мережеві спостереження й запитані знімки екрана | Браузер сімейства Chrome; [аналіз браузера](https://rea.tools/guides/browser/) |
| Збережені мережеві захоплення | Запити, відповіді, доступні корисні дані та місця в джерелі | HAR; mitmdump у Linux для захоплень у власному форматі mitmproxy; [посібник мережевих захоплень](docs/web-network-captures.md) |
| Збірки .NET | Метадані, інструкції CIL, оголошені нативні залежності й порівняння збірок | Статична перевірка; [посібник керованого коду](docs/managed-code-analysis.md) |
| Android APK | Оголошення маніфесту, класи, декомпільовані методи й посилання | JADX без графічного інтерфейсу й повний JDK у Linux/macOS/Windows x64; [посібник Android](docs/android-analysis.md) |
| Пристрої Android | Пристрої, пакети, процеси, журнали, дампи, знімки екрана та передавання APK/файлів | adb, наданий викликаючою стороною (емулятор або пристрій); [підручник ADB](docs/adb-device-analysis.md) |
| Проєкти JEB | Єдиниці проєкту від рушія, дайджести артефактів і псевдокод типів/методів | Запущений викликаною стороною клієнт JEB з MCP, обирається через REA_JEB_MCP_URL; [посібник JEB](docs/jeb-analysis.md) |
| Ресурси Android | Декодований маніфест, таблиці рядків, мови та відомості про версію | Засіб запуску Apktool, наданий викликаючою стороною; [підручник ресурсів](docs/apktool-resource-analysis.md) |
| Прошивки | Області, результати видобування й передавання до нативного аналізу | Binwalk / Unblob у Linux; [посібник прошивок](docs/firmware-analysis.md) |
| Пакети й ресурси | Переліки файлів, хеші, plist, структура пакетів Apple та видобуті ресурси | [Посібник артефактів і JavaScript](docs/javascript-artifact-reconstruction.md), [застосунки Apple](docs/apple-application-analysis.md) |
| Поведінка процесів | Вивід термінала, взаємодії, спостереження за завершенням і файловою системою та порівняння запусків | Linux/macOS із нативним PTY; [захоплення процесів](docs/process-capture.md) |
Статична перевірка JavaScript і .NET читає надані файли, не запускаючи застосунок. Захоплення під час виконання запускає вибрану ціль або взаємодіє з нею з правами вашого користувача; відповідні посібники описують його вплив.
<a id="choosing-a-deep-analysis-provider"></a>
Нативні формати й підтримка систем відрізняються залежно від провайдера. Дивіться [налаштування Hopper і Ghidra](docs/installation.md#hopper), [посібник IDA](docs/ida-provider.md) та [експериментальну підтримку Ghidra у Windows](docs/windows-ghidra-p0.md). Ghidra також підтримує [аналіз 16-бітного DOS](docs/ghidra-dos.md). Для вибору провайдера дивіться [посібник CLI](docs/cli.md#choose-a-provider). Для функцій, доданих після найновішої версії в npm, перевірте [доступність у випусках](docs/installation.md#released-package-and-main).
## Приклади
[![Ілюстрації прикладів панорамування звуку в DX-Ball, мосту буфера обміну Notion та кільця куль у TH04](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: відновлення розрахунку звукової панорами
Простежте звуковий виклик до допоміжної функції, що перетворює координату на панорамування, перевірте інструкції та перетворіть неповний псевдокод на C. Відновлена реалізація проходить 3 205 тестів з оригінальним x86-кодом і відтворює всі 63 байти скомпільованої функції.
[Прочитати дослідження](https://rea.tools/showcase/dx-ball/) · [Репозиторій реконструкції](https://github.com/N0zoM1z0/dx-ball)
### Notion: відстеження мосту буфера обміну Electron
Знайдіть API буфера обміну в процесі рендерингу, простежте його через preload та IPC до головного процесу й перевірте формат буфера обміну з даними форматування.
[Прочитати дослідження](https://rea.tools/showcase/notion/)
### TH04: відновлення розрахунку кільця куль у DOS
Перевірте 16-бітні інструкції оригінальної гри для PC-98, відновіть розрахунки фіксованих і прицільних кутів та порівняйте відновлений C++ із виводом тогочасного компілятора.
[Прочитати дослідження](https://rea.tools/showcase/th04/) · [Репозиторій реконструкції](https://github.com/N0zoM1z0/th04)
Якщо ви дослідили з REA щось цікаве, поділіться результатом. Створіть [issue](https://github.com/morluto/rea/issues) або [pull request](https://github.com/morluto/rea/pulls) і вкажіть ціль, ваше запитання, як допоміг REA та що ви з'ясували.
## Поширені запитання
<details>
<summary><strong>Які агенти можуть використовувати REA?</strong></summary>
Будь-який агент, що підтримує локальні MCP-сервери. Налаштування конфігурує [підтримуваних агентів](docs/installation.md#supported-agents); інші клієнти можуть використати [ручну реєстрацію MCP](docs/installation.md#mcp-registry).
</details>
<details>
<summary><strong>Чи потрібні мені Hopper, Ghidra або IDA?</strong></summary>
Поглиблений нативний аналіз використовує один із цих інструментів. Статична перевірка JavaScript і .NET працює без рушія нативного аналізу. Налаштування може встановити Hopper після схвалення; Ghidra й IDA використовують наявні встановлення. Дивіться [налаштування провайдерів](docs/installation.md#hopper).
</details>
<details>
<summary><strong>Чи потрібно спочатку запускати Hopper?</strong></summary>
REA запускає Hopper, коли він потрібен для операції. У macOS під час першого запуску може з'явитися діалог вибору деморежиму або активації ліцензії. Дивіться [запуск Hopper та усунення неполадок](docs/installation.md#launcher-paths-and-troubleshooting).
</details>
<details>
<summary><strong>Що дає встановлення skill із skills.sh?</strong></summary>
Skill надає агенту інструкції дослідження. Використовуйте `npx rea-agents setup`, щоб зареєструвати MCP-сервер REA та встановити відповідні інструкції, а потім перезапустіть агента. Дивіться [встановлення лише skill](docs/installation.md#skill-only-installation).
</details>
<details>
<summary><strong>Який код повертає REA?</strong></summary>
Нативний аналіз повертає псевдокод і асемблерний код. Аналіз JavaScript/Electron відновлює модулі та їхні зв'язки. Агент використовує ці результати, щоб написати й протестувати реалізацію; [приклади](#приклади) містять практичні дослідження.
</details>
<details>
<summary><strong>Чи завантажує REA мій застосунок на сервер?</strong></summary>
REA аналізує цілі локально. Ваш агент отримує результати інструментів, а постачальник його моделі має власну політику даних.
</details>
<details>
<summary><strong>Що робити, якщо я зіткнувся з помилкою?</strong></summary>
Спочатку оновіться: нещодавній випуск уже міг виправити помилку.
Для CLI, встановленого через npm:
```bash
rea update
```
Для налаштування агента через `npx`:
```bash
npx rea-agents@latest setup
```
Якщо використовуєте агента, завершіть [оновлення налаштувань](#оновіть-rea) і перезапустіть його. Повторіть те саме завдання. Якщо проблема залишається, [відкрийте issue](https://github.com/morluto/rea/issues) із версією REA, типом цілі, кроками відтворення та виводом помилки.
</details>
## Документація
Почніть із [практичних посібників](https://rea.tools/guides/) на сайті. Точні параметри, передумови й контракти результатів описано тут:
- [Встановлення й налаштування](docs/installation.md): реєстрація агентів, конфігурація провайдерів, оновлення та видалення.
- [Готовність та усунення неполадок](docs/installation.md#check-readiness-for-your-task): діагностика конкретного агента або рушія аналізу.
- [CLI та Evidence](docs/cli.md): команди, вибір провайдера, знімки, імпорт/експорт і статуси завершення.
- [Контракти MCP](docs/mcp-contracts.md) і [промпти агентів](docs/mcp-prompts.md): результати інструментів, сеанси й керовані дослідження.
- [Каталог інструментів](docs/mcp-contracts.md#generated-catalog): створюваний під час збірки перелік інструментів, провайдерів і команд CLI.
- [План розвитку](docs/roadmap.md): заплановані роботи й відстеження можливостей.
Повідомляйте про вразливості згідно з [SECURITY.md](SECURITY.md).
## Історія зірок
🎉 **50 000 зірок на GitHub — дякуємо!**
Дякуємо всім, хто використовує REA, повідомляє про помилки, пропонує нові функції, тестує збірки й допомагає з виправленнями.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="Історія зірок REA на GitHub" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## Відмова від відповідальності
REA надає інструменти для законних досліджень, аналізу й реконструкції за допомогою реверс-інжинірингу. Ви відповідаєте за отримання необхідних дозволів і дотримання застосовних законів. Проєкт не підтримує незаконне або несанкціоноване використання.
## Участь у проєкті
Будемо раді вашій допомозі з REA! [Відкрийте issue](https://github.com/morluto/rea/issues), щоб повідомити про помилку чи запропонувати функцію, або [надішліть pull request](https://github.com/morluto/rea/pulls) з поліпшеннями коду чи документації.
Налаштування середовища розробки й перевірки описано в [CONTRIBUTING.md](CONTRIBUTING.md), шляхи верифікації — у [посібнику тестування](docs/testing.md), а структуру проєкту — на [схемі архітектури](docs/architecture.mermaid).
## Ліцензія
[MIT](LICENSE)
+286
View File
@@ -0,0 +1,286 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · **Tiếng Việt** · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA: Kỹ thuật dịch ngược cho mọi thứ
### Một MCP để dịch ngược tệp nhị phân, ứng dụng và hành vi khi chạy.
**Thấy một tính năng bạn thích? Hiểu cách nó hoạt động, đến tận mức mã nhị phân.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[Trang web](https://rea.tools/) · [Hướng dẫn](https://rea.tools/guides/) · [Các nghiên cứu điển hình](https://rea.tools/showcase/)**
[Bắt đầu nhanh](#bắt-đầu-nhanh) · [Cách REA hoạt động](#cách-rea-hoạt-động) · [Những gì bạn có thể phân tích](#những-gì-bạn-có-thể-phân-tích) · [Các nghiên cứu điển hình](#các-nghiên-cứu-điển-hình) · [Câu hỏi thường gặp](#câu-hỏi-thường-gặp) · [Tài liệu](#tài-liệu)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA khởi chạy cầu nối phân tích bên trong Hopper khi kiểm tra tệp nhị phân mã máy" width="1200" />
<br /><br />
<table aria-label="Cộng đồng REA">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>Tham gia cộng đồng kỹ thuật dịch ngược</strong>
</a><br />
<sub>Discord · Hỏi đáp · Chia sẻ kết quả</sub>
</td>
</tr>
</table>
<br />
</div>
---
Bạn thấy một tính năng trong ứng dụng và muốn đưa nó vào sản phẩm của mình? Hãy nhờ tác nhân của bạn điều tra bằng REA. Tác nhân có thể kiểm tra ứng dụng mà không cần mã nguồn, giải thích cách tính năng hoạt động, đưa ra bằng chứng và xây dựng một phiên bản cho dự án của bạn.
REA kết nối tác nhân của bạn với các công cụ kiểm tra tệp nhị phân mã máy, ứng dụng JavaScript và Electron, assembly .NET và trang web. Bạn cũng có thể dùng các công cụ đó từ terminal. Việc phân tích chạy cục bộ; kết quả bao gồm bằng chứng và giới hạn làm cơ sở cho từng kết luận.
Quá trình thiết lập đăng ký REA với tác nhân và cài đặt các hướng dẫn quy trình tương ứng. Phân tích mã máy có thể sử dụng Hopper hoặc Ghidra đã cài sẵn; quá trình thiết lập cũng có thể cài Hopper nếu bạn chấp thuận. Phân tích tĩnh JavaScript không cần công cụ nào trong hai công cụ này.
> **[Truy cập trang web REA](https://rea.tools/)** để xem cách thiết lập, hướng dẫn có hình minh họa và các nghiên cứu điển hình thực tế.
## Bắt đầu nhanh
### Thiết lập tác nhân
Sau khi cài Node.js và npm, chạy:
```bash
npx rea-agents setup
```
Chọn các tác nhân, xem lại những thay đổi được đề xuất và chấp thuận. Quá trình thiết lập thêm máy chủ MCP của REA cùng hướng dẫn quy trình tương ứng, đồng thời sao lưu cấu hình hiện có. Sau đó khởi động lại tác nhân.
Quá trình thiết lập hỗ trợ Claude Code, Codex, Cursor, Gemini CLI, Grok Build và [các tác nhân khác](docs/installation.md#supported-agents). Xem [cài đặt và thiết lập](docs/installation.md) để cấu hình trình phân tích và đăng ký MCP thủ công.
### Hỏi tác nhân
```text
Tìm hiểu cách tính năng tìm kiếm trong ứng dụng Notes hoạt động, cho tôi xem bằng chứng và xây dựng tính năng tương tự cho dự án của tôi.
```
Thay Notes bằng ứng dụng mục tiêu và chỉ rõ tính năng bạn muốn hiểu.
### Sử dụng terminal
Kiểm tra thư mục ứng dụng JavaScript/Electron đã giải nén hoặc tệp ASAR:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
Kết quả bao gồm mô-đun, các khai báo import, ranh giới Electron và bằng chứng tương ứng. Thay đường dẫn bằng mục tiêu của bạn, chẳng hạn `"D:/apps/example"` trên Windows.
Để cài lệnh `rea` cho việc sử dụng thường xuyên:
```bash
npm install --global rea-agents
rea --help
```
Để phân tích mã máy, trước tiên hãy cấu hình trình phân tích. Xem [hướng dẫn CLI và Evidence](docs/cli.md) về các lệnh phân tích mã máy, lựa chọn trình phân tích, ảnh chụp trạng thái và sử dụng trong script.
### Cập nhật REA
REA thay đổi nhanh và các bản phát hành mới thường xuyên có bản sửa lỗi. Hãy giữ bản cài đặt của bạn được cập nhật.
Với CLI được cài bằng npm:
```bash
rea update
```
Để cập nhật đăng ký tác nhân và skill, chạy lệnh thiết lập được in ra sau khi cập nhật.
Nếu dùng `npx`, cập nhật thiết lập tác nhân bằng:
```bash
npx rea-agents@latest setup
```
Xem lại thay đổi cấu hình và khởi động lại tác nhân. Với lệnh CLI dùng một lần, dùng `npx rea-agents@latest` rồi thêm lệnh cần chạy.
## Cách REA hoạt động
Tác nhân gọi REA qua MCP để kiểm tra mục tiêu và lần theo mã liên quan. REA trả về các phát hiện kèm bằng chứng. Tác nhân dùng chúng để đặt câu hỏi tiếp theo, giải thích hành vi hoặc viết và kiểm thử một cách triển khai. Các lệnh CLI sử dụng cùng quy trình.
![Quy trình điều tra của REA: tác nhân hỏi về mục tiêu cục bộ, REA kiểm tra và lần theo mục tiêu bằng công cụ phân tích, rồi tác nhân dùng mã, tham chiếu và những điểm chưa biết được trả về để giải thích, triển khai và kiểm thử.](website/public/assets/figures/rea-investigation-flow.svg)
[Mở hình ở kích thước đầy đủ](website/public/assets/figures/rea-investigation-flow.svg).
<a id="current-status"></a>
## Những gì bạn có thể phân tích
REA yêu cầu Node.js 22.x (>=22.19), 24.x (>=24.11) hoặc 26+, cùng với npm. Công cụ bổ sung và nền tảng chạy REA được hỗ trợ tùy thuộc vào mục tiêu:
| Mục tiêu | REA trả về gì | Yêu cầu và hướng dẫn |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Tệp nhị phân mã máy | Mã giả, hợp ngữ, chuỗi, ký hiệu, lời gọi và tham chiếu | Hopper, Ghidra hoặc IDA; [phân tích mã máy](https://rea.tools/guides/native/) |
| Bố cục ELF ngoại tuyến | Các section, segment, ký hiệu/thông tin tái định vị gốc và các biện pháp giảm thiểu có thể có từ phân tích tĩnh | pwntools do bên gọi cung cấp trên Linux x64; [chẩn đoán tệp nhị phân](docs/binary-diagnostics.md) |
| Bytecode EVM | Bộ chọn điều phối, độ lệch byte, tham số suy luận và khả năng thay đổi trạng thái | Đầu vào cục bộ chứa byte thô hoặc dạng thập lục phân trên Linux x64; [hướng dẫn EVM ngoại tuyến](docs/evm-bytecode.md) |
| Sự cố Linux đã ghi lại | Bản ghi note thô, thanh ghi/tín hiệu của mọi luồng được ghi lại và các ứng viên ánh xạ tùy chọn | pwntools do bên gọi cung cấp trên Linux x64; GDB/pwndbg tùy chọn; [sự cố đã ghi lại](docs/recorded-crashes.md) |
| JavaScript / Electron | Mô-đun, các khai báo import, source map, tuyến, IPC và quan hệ với tiện ích mở rộng mã máy | Node.js và npm; [phân tích ứng dụng](https://rea.tools/guides/javascript/) |
| Trang web | Cấu trúc trang, script, quan sát mạng và ảnh chụp màn hình được yêu cầu | Trình duyệt thuộc họ Chrome; [phân tích trình duyệt](https://rea.tools/guides/browser/) |
| Bản ghi lưu lượng mạng đã lưu | Yêu cầu, phản hồi, payload có thể truy cập và vị trí nguồn | HAR; mitmdump trên Linux cho bản ghi định dạng gốc của mitmproxy; [hướng dẫn bản ghi mạng](docs/web-network-captures.md) |
| Assembly .NET | Siêu dữ liệu, lệnh CIL, các phụ thuộc mã máy được khai báo và so sánh bản dựng | Kiểm tra tĩnh; [hướng dẫn mã được quản lý](docs/managed-code-analysis.md) |
| APK Android | Khai báo manifest, lớp, phương thức được dịch ngược và tham chiếu | JADX không giao diện đồ họa và JDK đầy đủ trên Linux/macOS/Windows x64; [hướng dẫn Android](docs/android-analysis.md) |
| Thiết bị Android | Thiết bị, gói, tiến trình, nhật ký, dump, ảnh chụp màn hình và truyền APK/tệp | adb do nơi gọi cung cấp (trình giả lập hoặc thiết bị); [hướng dẫn ADB](docs/adb-device-analysis.md) |
| Dự án JEB | Đơn vị dự án từ engine, hash của artifact và mã giả của kiểu/phương thức | Một ứng dụng JEB do nơi gọi khởi động, phục vụ MCP, chọn bằng REA_JEB_MCP_URL; [hướng dẫn JEB](docs/jeb-analysis.md) |
| Tài nguyên Android | Manifest đã giải mã, bảng chuỗi, ngôn ngữ và thông tin phiên bản | Trình khởi chạy Apktool do nơi gọi cung cấp; [hướng dẫn tài nguyên](docs/apktool-resource-analysis.md) |
| Phần sụn | Các vùng, kết quả trích xuất và dữ liệu chuyển sang phân tích mã máy | Binwalk / Unblob trên Linux; [hướng dẫn phần sụn](docs/firmware-analysis.md) |
| Gói và tài nguyên | Danh sách tệp, giá trị băm, plist, cấu trúc bundle Apple và tài nguyên được trích xuất | [Hướng dẫn hiện vật phần mềm và JavaScript](docs/javascript-artifact-reconstruction.md), [ứng dụng Apple](docs/apple-application-analysis.md) |
| Hành vi tiến trình | Đầu ra terminal, tương tác, quan sát khi thoát và hệ thống tệp, cùng so sánh các lần chạy | Linux/macOS có PTY gốc; [ghi lại tiến trình](docs/process-capture.md) |
Kiểm tra tĩnh JavaScript và .NET đọc các tệp được cung cấp mà không chạy ứng dụng. Ghi lại khi chạy sẽ khởi chạy hoặc tương tác với mục tiêu đã chọn bằng quyền người dùng của bạn; từng hướng dẫn mô tả tác động của nó.
<a id="choosing-a-deep-analysis-provider"></a>
Định dạng mã máy và nền tảng chạy REA được hỗ trợ khác nhau tùy trình phân tích. Xem [thiết lập Hopper và Ghidra](docs/installation.md#hopper), [hướng dẫn IDA](docs/ida-provider.md) và [hỗ trợ Ghidra thử nghiệm trên Windows](docs/windows-ghidra-p0.md). Ghidra cũng hỗ trợ [phân tích DOS 16 bit](docs/ghidra-dos.md). Để chọn trình phân tích, xem [hướng dẫn CLI](docs/cli.md#choose-a-provider). Kiểm tra [khả năng sử dụng theo bản phát hành](docs/installation.md#released-package-and-main) đối với tính năng được bổ sung sau phiên bản npm mới nhất.
## Các nghiên cứu điển hình
[![Minh họa các ví dụ về cân bằng âm thanh DX-Ball, cầu nối bảng nhớ tạm Notion và vòng đạn TH04](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: tái tạo phép tính phân bố âm thanh trái phải
Lần theo lời gọi âm thanh đến hàm hỗ trợ chuyển vị trí thành giá trị phân bố âm thanh, kiểm tra các lệnh và chuyển mã giả chưa đầy đủ sang C. Bản tái tạo vượt qua 3.205 trường hợp kiểm thử với x86 gốc và tái tạo đủ 63 byte của hàm đã biên dịch.
[Đọc nghiên cứu điển hình](https://rea.tools/showcase/dx-ball/) · [Kho mã tái tạo](https://github.com/N0zoM1z0/dx-ball)
### Notion: lần theo cầu nối clipboard của Electron
Tìm API clipboard trong tiến trình kết xuất, lần theo qua preload và IPC đến tiến trình chính, rồi kiểm tra định dạng clipboard có dữ liệu định dạng phong phú.
[Đọc nghiên cứu điển hình](https://rea.tools/showcase/notion/)
### TH04: khôi phục phép tính vòng đạn trong DOS
Kiểm tra các lệnh 16 bit của trò chơi PC-98 gốc, khôi phục phép tính góc cố định và góc nhắm mục tiêu, rồi so sánh C++ được tái tạo với đầu ra của trình biên dịch thời đó.
[Đọc nghiên cứu điển hình](https://rea.tools/showcase/th04/) · [Kho mã tái tạo](https://github.com/N0zoM1z0/th04)
Nếu bạn dùng REA cho một mục tiêu thú vị, chúng tôi muốn biết. Chia sẻ trường hợp của bạn qua [issue](https://github.com/morluto/rea/issues) hoặc [pull request](https://github.com/morluto/rea/pulls), nêu mục tiêu, câu hỏi, cách REA giúp bạn và những gì tìm được.
## Câu hỏi thường gặp
<details>
<summary><strong>Tác nhân nào có thể dùng REA?</strong></summary>
Bất kỳ tác nhân nào hỗ trợ máy chủ MCP cục bộ. Quá trình thiết lập cấu hình các [tác nhân được hỗ trợ](docs/installation.md#supported-agents); ứng dụng khách khác có thể dùng [đăng ký MCP thủ công](docs/installation.md#mcp-registry).
</details>
<details>
<summary><strong>Tôi có cần Hopper, Ghidra hoặc IDA không?</strong></summary>
Phân tích mã máy chuyên sâu sử dụng một trong những công cụ đó. Kiểm tra tĩnh JavaScript và .NET hoạt động mà không cần bộ máy phân tích mã máy. Quá trình thiết lập có thể cài Hopper sau khi được chấp thuận; Ghidra và IDA dùng bản cài đặt sẵn có. Xem [thiết lập trình phân tích](docs/installation.md#hopper).
</details>
<details>
<summary><strong>Tôi có cần khởi chạy Hopper trước không?</strong></summary>
REA khởi chạy Hopper khi một thao tác cần đến nó. Trên macOS, hộp thoại lần chạy đầu có thể yêu cầu chọn chế độ dùng thử hoặc kích hoạt giấy phép. Xem [khởi động Hopper và khắc phục sự cố](docs/installation.md#launcher-paths-and-troubleshooting).
</details>
<details>
<summary><strong>Cài skill từ skills.sh có tác dụng gì?</strong></summary>
Skill cung cấp hướng dẫn điều tra cho tác nhân. Dùng `npx rea-agents setup` để đăng ký máy chủ MCP của REA và cài hướng dẫn tương ứng, sau đó khởi động lại tác nhân. Xem [chỉ cài skill](docs/installation.md#skill-only-installation).
</details>
<details>
<summary><strong>REA trả về mã gì?</strong></summary>
Phân tích mã máy trả về mã giả và hợp ngữ. Phân tích JavaScript/Electron khôi phục mô-đun cùng quan hệ giữa chúng. Tác nhân dùng các phát hiện này để viết và kiểm thử cách triển khai; các [nghiên cứu điển hình](#các-nghiên-cứu-điển-hình) cung cấp ví dụ thực hành.
</details>
<details>
<summary><strong>REA có tải ứng dụng của tôi lên không?</strong></summary>
REA phân tích mục tiêu cục bộ. Tác nhân nhận kết quả công cụ, và nhà cung cấp mô hình của tác nhân có chính sách dữ liệu riêng.
</details>
<details>
<summary><strong>Tôi nên làm gì khi gặp lỗi?</strong></summary>
Hãy cập nhật trước; một bản phát hành gần đây có thể đã sửa lỗi.
Với CLI được cài bằng npm:
```bash
rea update
```
Với thiết lập tác nhân qua `npx`:
```bash
npx rea-agents@latest setup
```
Nếu dùng tác nhân, hãy hoàn tất [làm mới thiết lập](#cập-nhật-rea) và khởi động lại nó. Thử lại cùng tác vụ. Nếu vấn đề vẫn còn, [mở issue](https://github.com/morluto/rea/issues) với phiên bản REA, loại mục tiêu, các bước tái hiện và đầu ra lỗi.
</details>
## Tài liệu
Bắt đầu với [hướng dẫn thực hành](https://rea.tools/guides/) trên trang web. Để biết tùy chọn cụ thể, điều kiện tiên quyết và hợp đồng kết quả:
- [Cài đặt và thiết lập](docs/installation.md): đăng ký tác nhân, cấu hình trình phân tích, cập nhật và gỡ cài đặt.
- [Kiểm tra mức sẵn sàng và khắc phục sự cố](docs/installation.md#check-readiness-for-your-task): chẩn đoán một tác nhân hoặc bộ máy phân tích cụ thể.
- [CLI và Evidence](docs/cli.md): lệnh, lựa chọn trình phân tích, ảnh chụp trạng thái, nhập/xuất và trạng thái thoát.
- [Hợp đồng MCP](docs/mcp-contracts.md) và [prompt cho tác nhân](docs/mcp-prompts.md): kết quả công cụ, phiên làm việc và điều tra có hướng dẫn.
- [Danh mục công cụ](docs/mcp-contracts.md#generated-catalog): danh sách công cụ, trình phân tích và lệnh CLI được tạo khi dựng dự án.
- [Lộ trình](docs/roadmap.md): công việc dự kiến và theo dõi các khả năng.
Báo cáo lỗ hổng theo [SECURITY.md](SECURITY.md).
## Lịch sử sao
🎉 **50.000 sao trên GitHub — xin cảm ơn!**
Cảm ơn mọi người đã sử dụng REA, báo lỗi, đề xuất tính năng, kiểm thử bản dựng và đóng góp bản sửa lỗi.
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="Lịch sử sao GitHub của REA" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## Miễn trừ trách nhiệm
REA cung cấp công cụ cho nghiên cứu dịch ngược, phân tích và tái tạo hợp pháp. Bạn có trách nhiệm có được các quyền cho phép cần thiết và tuân thủ luật áp dụng. Dự án không ủng hộ việc sử dụng trái pháp luật hoặc không được cho phép.
## Đóng góp
Chúng tôi hoan nghênh bạn giúp phát triển REA! [Mở issue](https://github.com/morluto/rea/issues) để báo lỗi hoặc đề xuất tính năng, hoặc [gửi pull request](https://github.com/morluto/rea/pulls) để cải thiện mã hay tài liệu.
Xem [CONTRIBUTING.md](CONTRIBUTING.md) về thiết lập môi trường phát triển và các bước kiểm tra, [hướng dẫn kiểm thử](docs/testing.md) về các luồng xác minh và [sơ đồ kiến trúc](docs/architecture.mermaid) về cấu trúc dự án.
## Giấy phép
[MIT](LICENSE)
+288
View File
@@ -0,0 +1,288 @@
<div align="center">
[English](README.md) · [简体中文](README_zh.md) · **繁體中文** · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA:逆向一切
### 通過一個 MCP 服務,逆向分析二進位檔案、應用程式和執行階段行為。
**看到喜歡的功能,弄清它的工作原理,深入到二進位層面。**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[網站](https://rea.tools/) · [指南](https://rea.tools/guides/) · [案例](https://rea.tools/showcase/)**
[快速開始](#快速開始) · [REA 的工作原理](#rea-的工作原理) · [可以分析什麼](#可以分析什麼) · [案例](#案例) · [常見問題](#常見問題) · [文件](#文件)
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA 在 Hopper 中啟動分析橋,檢查原生二進位檔案" width="1200" />
<br /><br />
<table aria-label="REA 社群">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="docs/assets/discord.svg" height="42" alt="Discord" /><br />
<strong>加入逆向工程社群</strong>
</a><br />
<sub>Discord · 問答 · 成果分享</sub>
</td>
</tr>
</table>
<br />
</div>
---
在應用中看到一個想加入自己產品的功能?讓 AI 代理用 REA 調查它。即使沒有原始碼,AI 代理也可以檢查應用、解釋功能的工作方式、展示證據,並為你的專案實現類似功能。
REA 將 AI 代理連接到分析工具,用於檢查原生二進位檔案、JavaScript 和 Electron 應用、.NET 程式集以及網站。你也可以在終端中使用同樣的工具。分析在本機執行,結果包含支撐各項結論的證據和相關限制。
設定流程會向 AI 代理註冊 REA,並安裝對應的工作流程指引。原生分析可以使用已有的 Hopper 或 Ghidra;設定流程也可以在你核准後安裝 Hopper。靜態 JavaScript 分析不需要這兩個引擎。
> **[訪問 REA 網站](https://rea.tools/)**,查看設定說明、圖解指南和真實案例。
## 快速開始
### 設定 AI 代理
安裝 Node.js 和 npm 後,執行:
```bash
npx rea-agents setup
```
選擇 AI 代理,檢查計劃中的變更並核准。設定流程會添加 REA 的 MCP 服務和對應的工作流程指引,並備份已有組態。完成後重新啟動 AI 代理。
設定流程支援 Claude Code、Codex、Cursor、Gemini CLI、Grok Build 和[其他 AI 代理](docs/installation.md#supported-agents)。提供者組態和手動註冊 MCP 的方法見[安裝與設定](docs/installation.md)。
### 詢問 AI 代理
```text
弄清 Notes 應用的搜尋功能如何工作,展示證據,並為我的專案實現類似功能。
```
把 Notes 替換為目標應用,並描述你想瞭解的功能。
### 使用終端
檢查已解包的 JavaScript/Electron 應用目錄或 ASAR 檔案:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
結果包含模組、匯入、Electron 邊界及相關證據。將路徑替換為你的目標路徑,例如 Windows 上的 `"D:/apps/example"`。
如果需要經常使用,可以安裝 `rea` 命令:
```bash
npm install --global rea-agents
rea --help
```
原生分析需要先設定分析提供者。原生命令、提供者選擇、快照和腳本用法見 [CLI 與 Evidence 指南](docs/cli.md)。
### 更新 REA
REA 更新較快,新版本經常包含錯誤修復。請將安裝的版本保持最新。
通過 npm 安裝的 CLI 使用:
```bash
rea update
```
要更新 AI 代理註冊和 skill,請執行更新命令輸出的設定命令。
如果使用 `npx`,通過以下命令更新 AI 代理設定:
```bash
npx rea-agents@latest setup
```
檢查設定變更並重新啟動 AI 代理。單次 CLI 操作可使用 `npx rea-agents@latest`,後接所需命令。
## REA 的工作原理
AI 代理通過 MCP 呼叫 REA,檢查目標並追蹤相關程式碼。REA 返回發現及對應證據。AI 代理據此提出後續問題、解釋行為,或編寫並測試實現。CLI 命令使用同樣的工作流程。
![REA 調查流程:AI 代理詢問本地目標的行為,REA 使用分析工具檢查和追蹤目標,AI 代理再利用返回的程式碼、引用和未知項進行解釋、實現與測試。](website/public/assets/figures/rea-investigation-flow.svg)
[打開完整尺寸的圖示](website/public/assets/figures/rea-investigation-flow.svg)。
<a id="current-status"></a>
## 可以分析什麼
REA 需要 Node.js 22.x(>=22.19)、24.x(>=24.11)或 26+,以及 npm。額外工具和主機支援取決於分析目標:
| 目標 | REA 返回的內容 | 要求與指南 |
| --------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| 原生二進位檔案 | 偽程式碼、組合語言、字串、符號、呼叫和引用 | Hopper、Ghidra 或 IDA;[原生分析](https://rea.tools/guides/native/) |
| 離線 ELF 佈局 | 節、段、原始符號/重定位資訊及靜態防護機制候選項 | Linux x64 上由呼叫方提供的 pwntools;[二進位診斷](docs/binary-diagnostics.md) |
| EVM 位元組碼 | 分派選擇器、位元組偏移、推斷的參數和狀態可變性 | Linux x64 上的本地原始位元組/十六進位輸入載體;[離線 EVM 指南](docs/evm-bytecode.md) |
| 已記錄的 Linux 崩潰 | 原始 note 記錄、每個已記錄執行緒的暫存器/訊號及可選的對映候選項 | Linux x64 上由呼叫方提供的 pwntools;可選的 GDB/pwndbg;[已記錄崩潰](docs/recorded-crashes.md) |
| JavaScript / Electron | 模組、匯入、source map、路由、IPC 和原生附加元件關係 | Node.js 和 npm;[應用分析](https://rea.tools/guides/javascript/) |
| 網站 | 頁面結構、腳本、網路觀察結果和按請求獲取的螢幕擷取畫面 | Chrome 系瀏覽器;[瀏覽器分析](https://rea.tools/guides/browser/) |
| 已保存的網路擷取 | 請求、回應、可訪問的酬載和來源位置 | HAR;原生 mitmproxy 擷取需要 Linux 上的 mitmdump;[擷取指南](docs/web-network-captures.md) |
| .NET 程式集 | 中繼資料、CIL 指令、聲明的原生依賴和建置對比 | 靜態檢查;[托管程式碼指南](docs/managed-code-analysis.md) |
| Android APK | 清單聲明、類別、反編譯的方法和引用 | Linux/macOS/Windows x64 上的無界面 JADX 和完整 JDK;[Android 指南](docs/android-analysis.md) |
| Android 裝置 | 裝置、套件、程序、日誌、傾印、螢幕擷取以及 APK/檔案傳輸 | 呼叫端提供的 adb(模擬器或實體裝置);[ADB 指南](docs/adb-device-analysis.md) |
| JEB 專案 | 引擎支援的專案單元、成品摘要和型別/方法的虛擬碼 | 由呼叫端啟動、提供 MCP 的 JEB 用戶端,透過 REA_JEB_MCP_URL 選擇;[JEB 指南](docs/jeb-analysis.md) |
| Android 資源 | 解碼後的清單、字串表、語系和版本資訊 | 呼叫端提供的 Apktool 啟動器;[資源指南](docs/apktool-resource-analysis.md) |
| 韌體 | 區域、提取結果和轉交原生分析的內容 | Linux 上的 Binwalk / Unblob;[韌體指南](docs/firmware-analysis.md) |
| 軟體包與資源 | 檔案清單、摘要、plist、Apple bundle 結構和提取的資源 | [製品與 JavaScript 指南](docs/javascript-artifact-reconstruction.md)、[Apple 應用](docs/apple-application-analysis.md) |
| 處理程序行為 | 終端輸出、互動、退出和檔案系統觀察結果,以及執行對比 | 支援原生 PTY 的 Linux/macOS;[處理程序擷取](docs/process-capture.md) |
靜態 JavaScript 和 .NET 檢查讀取提供的檔案,不執行應用。執行階段擷取會以你的使用者權限執行目標或與之互動;各執行階段指南說明瞭具體影響。
<a id="choosing-a-deep-analysis-provider"></a>
不同提供者支援的原生格式和主機系統有所不同。請參閱 [Hopper 與 Ghidra 設定](docs/installation.md#hopper)、[IDA 指南](docs/ida-provider.md)和[實驗性 Windows Ghidra 支援](docs/windows-ghidra-p0.md)。Ghidra 也支援 [16 位 DOS 分析](docs/ghidra-dos.md)。提供者選擇見 [CLI 指南](docs/cli.md#choose-a-provider)。對於最新 npm 版本發佈後新增的功能,請查看[發佈可用性](docs/installation.md#released-package-and-main)。
## 案例
[![DX-Ball 聲音平移、Notion 剪貼簿橋接與 TH04 彈幕環案例的插圖](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball:重建聲像計算
沿聲音呼叫追蹤到根據位置計算聲像的輔助函數,檢查指令,將不完整的偽程式碼轉為 C。重建結果通過了 3,205 個原始 x86 測試用例,並復現了編譯後函數的全部 63 個位元組。
[閱讀案例](https://rea.tools/showcase/dx-ball/) ·
[重建專案儲存庫](https://github.com/N0zoM1z0/dx-ball)
### Notion:追蹤 Electron 剪貼簿橋
找到渲染處理程序的剪貼簿 API,沿 preload 和 IPC 追蹤到主處理程序,並檢查富格式剪貼簿資料。
[閱讀案例](https://rea.tools/showcase/notion/)
### TH04:恢復 DOS 環形子彈的計算
檢查原始 PC-98 遊戲的 16 位指令,恢復固定角度和瞄準角度的計算,並將重建的 C++ 與當年的編譯器輸出進行對比。
[閱讀案例](https://rea.tools/showcase/th04/) ·
[重建專案儲存庫](https://github.com/N0zoM1z0/th04)
如果你用 REA 分析了有趣的目標,我們很想瞭解。歡迎通過 [issue](https://github.com/morluto/rea/issues) 或 [pull request](https://github.com/morluto/rea/pulls) 分享案例,說明目標、你的問題、REA 如何提供幫助,以及你的發現。
## 常見問題
<details>
<summary><strong>哪些 AI 代理可以使用 REA?</strong></summary>
任何支援本地 MCP 服務的 AI 代理都可以使用。設定流程會設定[受支援的 AI 代理](docs/installation.md#supported-agents);其他客戶端可通過[手動註冊 MCP](docs/installation.md#mcp-registry) 使用。
</details>
<details>
<summary><strong>需要 Hopper、Ghidra 或 IDA 嗎?</strong></summary>
深入的原生分析需要其中一個引擎。靜態 JavaScript 和 .NET 檢查不需要原生分析引擎。設定流程可以在你核准後安裝 Hopper;Ghidra 和 IDA 則使用已有安裝。見[提供者設定](docs/installation.md#hopper)。
</details>
<details>
<summary><strong>需要先啟動 Hopper 嗎?</strong></summary>
REA 會在操作需要時啟動 Hopper。在 macOS 上,首次執行時可能會出現對話框,讓你選擇演示模式或啟用授權。見 [Hopper 啟動與故障排查](docs/installation.md#launcher-paths-and-troubleshooting)。
</details>
<details>
<summary><strong>從 skills.sh 安裝 skill 有什麼作用?</strong></summary>
skill 為 AI 代理提供調查指引。使用 `npx rea-agents setup` 註冊 REA 的 MCP 服務並安裝對應的指引,然後重新啟動 AI 代理。見[僅安裝 skill](docs/installation.md#skill-only-installation)。
</details>
<details>
<summary><strong>REA 返回什麼程式碼?</strong></summary>
原生分析返回偽程式碼和組合語言。JavaScript/Electron 分析恢復模組及其關係。AI 代理利用這些發現編寫並測試實現;[案例](#案例)提供了完整示例。
</details>
<details>
<summary><strong>REA 會上傳我的應用嗎?</strong></summary>
REA 在本機分析目標。AI 代理會接收工具結果,其模型提供商有自己的資料政策。
</details>
<details>
<summary><strong>遇到錯誤時該怎麼辦?</strong></summary>
先更新;最近的版本可能已經修復了問題。
通過 npm 安裝的 CLI 使用:
```bash
rea update
```
通過 `npx` 設定 AI 代理時使用:
```bash
npx rea-agents@latest setup
```
如果正在使用 AI 代理,請完成[設定更新](#更新-rea)並重新啟動 AI 代理。重試同一任務。如果問題仍然存在,請[提交 issue](https://github.com/morluto/rea/issues),附上 REA 版本、目標類型、復現步驟和錯誤輸出。
</details>
## 文件
可以先閱讀網站上的[實操指南](https://rea.tools/guides/)。具體選項、前提條件和結果契約見:
- [安裝與設定](docs/installation.md):AI 代理註冊、提供者組態、更新和卸載。
- [就緒檢查與故障排查](docs/installation.md#check-readiness-for-your-task):診斷特定 AI 代理或分析引擎。
- [CLI 與 Evidence](docs/cli.md):命令、提供者選擇、快照、匯入/匯出和退出狀態。
- [MCP 契約](docs/mcp-contracts.md)和[AI 代理提示詞](docs/mcp-prompts.md):工具結果、會話和引導式調查。
- [工具目錄](docs/mcp-contracts.md#generated-catalog):建置時生成的工具、提供者和 CLI 命令清單。
- [路線圖](docs/roadmap.md):計劃中的工作和能力跟蹤。
請按照 [SECURITY.md](SECURITY.md) 報告漏洞。
## Star 歷史
🎉 **GitHub Star 達到 50,000 個,感謝大家!**
感謝每一位使用 REA、報告錯誤、提出功能需求、測試建置和貢獻修復的朋友。
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="REA 的 GitHub Star 歷史" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## 免責聲明
REA 為合法的逆向工程研究、分析和重建提供工具。你有責任取得所需授權並遵守適用法律。本專案不認同非法或未經授權的使用。
## 參與貢獻
歡迎幫助改進 REA!你可以[提交 issue](https://github.com/morluto/rea/issues) 報告錯誤或建議功能,也可以[提交 pull request](https://github.com/morluto/rea/pulls) 改進程式碼或文件。
開發設定和檢查見 [CONTRIBUTING.md](CONTRIBUTING.md),驗證流程見[測試指南](docs/testing.md),專案結構見[架構圖](docs/architecture.mermaid)。
## 授權條款
[MIT](LICENSE)
+185 -232
View File
@@ -1,27 +1,36 @@
<div align="center">
[English](README.md) · **简体中文** · [日本語](README_ja.md) · [한국어](README_ko.md) · [العربية](README_ar.md)
[English](README.md) · **简体中文** · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Français](README_fr.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
# REA:逆向工程一切
# REA:逆向一切
### 使用智能体逆向工程任何程序,从应用行为到原生二进制文件。
### 通过一个 MCP 服务,逆向分析二进制文件、应用程序和运行时行为。
**看到喜欢的功能。理解它的原理。按照你的方式实现。**
**看到喜欢的功能,弄清它的工作原理,深入到二进制层面。**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](#调查工具目录)
[![Node.js 22+](https://img.shields.io/badge/Node.js-22.19%2B-339933?style=flat-square&logo=nodedotjs&logoColor=white)](https://nodejs.org/)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
[![Node.js requirements](https://img.shields.io/badge/Node.js-requirements-339933?style=flat-square&logo=nodedotjs&logoColor=white)](#current-status)
[![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/discord/1556595354999332884?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/GkcryMnJDM)
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
**[网站(英文)](https://morluto.github.io/rea/) · [使用指南](https://morluto.github.io/rea/guides/) · [DX-Ball 案例](https://morluto.github.io/rea/showcase/dx-ball/)**
**[网站](https://rea.tools/) · [指南](https://rea.tools/guides/) · [案例](https://rea.tools/showcase/)**
[快速开始](#快速开始) · [当前状态](#当前状态) · [从二进制到行为](#从二进制到行为) · [调查工具目录](#调查工具目录) · [路线图](#路线图) · [工作原理](#工作原理)
[快速开始](#快速开始) · [REA 的工作原理](#rea-的工作原理) · [可以分析什么](#可以分析什么) · [案例](#案例) · [常见问题](#常见问题) · [文档](#文档)
<table aria-label="REA community">
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA 在 Hopper 中启动分析桥,检查原生二进制文件" width="1200" />
<br /><br />
<table aria-label="REA 社区">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
@@ -35,301 +44,245 @@
<br />
<code>npx rea-agents setup</code>
<br />
<img src="docs/assets/rea-hopper-analysis.png" alt="REA 在 Hopper 中启动分析桥并检查原生二进制文件" width="1200" />
</div>
---
看到某个应用中想加入自己产品的功能?让智能体用 REA 调查它。即使没有源代码,智能体也可以检查应用、解释功能的工作方式、展示证据,并为你的项目实现类似功能。
在应用中看到一个想加入自己产品的功能?让智能体用 REA 调查它。即使没有源代码,智能体也可以检查应用、解释功能的工作方式、展示证据,并为你的项目实现类似功能。
REA 提供原生二进制、JavaScript 与 Electron 应用、.NET 程序集和网站的分析工具。你可以从智能体或终端使用它们。分析在本机运行,结果会说明证据和限制。
REA 将智能体连接到分析工具,用于检查原生二进制文件、JavaScript 和 Electron 应用、.NET 程序集以及网站。你也可以在终端中使用同样的工具。分析在本机运行,结果包含支撑各项结论的证据和相关限制。
Setup 可以配置智能体、连接已安装的 Hopper 或 Ghidra,也可以在你批准后安装 Hopper。
设置流程会向智能体注册 REA,并安装匹配的工作流指引。原生分析可以使用已有的 Hopper 或 Ghidra;设置流程也可以在你批准后安装 Hopper。静态 JavaScript 分析不需要这两个引擎。
## 直接询问智能体
完成[设置](#快速开始)后,重启智能体并提出问题:
```text
解释“备忘录”应用的搜索功能,展示证据,然后为我的项目实现类似功能。
```
把“备忘录”替换成你想了解的应用,也可以先请求概览。
## 从二进制到行为
| 反编译 | 理解 | 重建 |
| ---------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| 打开原生应用或可执行文件,恢复过程、伪代码、汇编、字符串、符号、段和元数据。 | 沿调用者、被调用者、交叉引用和调用图追踪,直到智能体能够解释功能或算法的实际工作方式。 | 将智能体学到的内容变成适合你的技术栈、界面和需求的产品功能。 |
REA 让调查始终以二进制证据为依据。它不会声称能恢复原始源代码,也不会自动克隆整个应用。
## 为什么选择 REA
| | |
| ---------------- | -------------------------------------------------------------------- |
| **为智能体设计** | 直接询问应用的行为,让智能体去检查,而不是猜测。 |
| **CLI 与 MCP** | 在终端或智能体中使用同一套逆向工程能力。 |
| **引导式设置** | 配置智能体、连接已有分析工具,或在你批准后安装 Hopper。 |
| **从洞察到代码** | 理解功能后,在同一次编程会话中构建属于你自己的版本。 |
| **本地运行** | 分析在受支持的本机系统上运行;REA 不会把二进制上传到托管式分析服务。 |
| **保留上下文** | 连续调查多个应用,无需为每个问题重新开始整个分析过程。 |
> **[访问 REA 网站](https://rea.tools/)**,查看设置说明、图解指南和真实案例。
## 快速开始
### 运行设置(推荐)
### 设置智能体
配置 REA 与智能体的连接:
安装 Node.js 和 npm 后,运行:
```bash
npx rea-agents setup
```
Setup 首先让你多选要连接的智能体。已有 REA 注册默认选中;仅被检测到的客户端不会自动选中,也可以手动选择尚未配置的客户端。查看具体路径和变更后再批准。所选智能体默认安装 REA 工作流;Hopper 是单独的可选操作,需要单独批准。Setup 也可以记录现有 Ghidra 的路径。
选择智能体,检查计划中的变更并批准。设置流程会添加 REA 的 MCP 服务和匹配的工作流指引,并备份已有配置。完成后重启智能体。
Setup 会先展示变更并备份已有配置。要求与更多选项见[安装与设置](docs/installation.md)。
设置流程支持 Claude Code、Codex、Cursor、Gemini CLI、Grok Build 和[其他智能体](docs/installation.md#supported-agents)。提供方配置和手动注册 MCP 的方法见[安装与设置](docs/installation.md)。
### 使用智能体
### 询问智能体
设置完成后,重启智能体并描述你想了解的应用或功能。REA 支持 Claude Code、Claude Desktop、Codex、Cursor、Gemini CLI、Windsurf、Devin、OpenCode、Antigravity、GitHub Copilot CLI、Command Code 和 VS Code。已有 REA 注册默认选中;其他检测到的客户端需手动选择。其他智能体可以使用下方的 MCP 配置。
Hopper 支持演示模式。如果首次启动时出现提示,选择演示模式或输入已有许可证。
### AI 编程助手技能(可选)
为你的 AI 编程助手添加 skill,以获得更丰富的上下文:
```bash
npx skills add morluto/rea --skill reverse-engineer-anything
```text
弄清 Notes 应用的搜索功能如何工作,展示证据,并为我的项目实现类似功能。
```
该 skill 提供 REA 的调查工作流。先运行上文的 setup,把 REA 连接到你的智能体并配置分析工具。Setup 默认会安装版本匹配的 skill;这条命令安装的是仓库版本。
把 Notes 替换为目标应用,并描述你想了解的功能。
对于已解包的 JavaScript/Electron 应用目录或 ASAR,无需 MCP 配置,也无需原生引擎:
### 使用终端
检查已解包的 JavaScript/Electron 应用目录或 ASAR 文件:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
把路径换成你的目标(例如 Windows 上的 `"D:/apps/example"`)。这条静态流程支持此类路径。原生分析仍需要先配置对应的分析引擎。
结果包含模块、导入、Electron 边界及相关证据。将路径替换为你的目标路径,例如 Windows 上的 `"D:/apps/example"`。
### 安装 rea 命令
安装命令行工具:
```bash
curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash
```
需要预先安装 Node.js 和 npm。在终端中运行时,安装程序会安装 `rea` 并启动设置。
也可以用 npm 安装,再运行设置:
```bash
npm install --global rea-agents
rea setup
```
### 系统要求
- macOS 12 或更高版本
- Ubuntu 24.04+、Fedora 41+、64 位 Arch Linux 或 CachyOS
- Node.js 22.x (>=22.19)、24.x (>=24.11) 或 26+,以及 npm
原生二进制分析需要 Hopper 或 Ghidra。Hopper 是独立软件;演示模式有厂商规定的限制,不要求购买许可证。
Ghidra 支持 Linux x64 和 macOS x64/arm64。单独安装 Ghidra 12.1.x,以及该安装在 `application.java.min` 到 `application.java.max` 中声明的完整 64 位 JDK,然后配置 REA 使用它们。当前 12.1 发行版要求 JDK 21 或更新版本,并且不设置上限。桥接在 Ghidra 12.1.4 和 JDK 21 上完成验证。macOS 还需要对应架构的原生反编译器。
Setup 可以验证安装并保存路径,不会安装或升级 Ghidra、Java、Node.js、npm 或 Homebrew。
仓库 main 分支与 npm 4.1.0 已包含实验性的 Windows x64 Ghidra P0 支持,适用于本地 NTFS 上的原生 x86-64 PE 应用(非托管、非 DLL),并附带 Job Object、私有 DACL 与路径准入控制。请先确认[发布边界](docs/installation.md#released-package-and-main),再假定旧版 npm 包具备该能力。详见 [Windows Ghidra P0](docs/windows-ghidra-p0.md) 的前置条件与已验证范围。
### 故障排除
运行 `npx -y rea-agents@latest doctor`,检查主机、依赖、分析工具和智能体配置。该命令不会修改文件。添加 `--json` 可获取结构化诊断。
Linux 上 REA 会优先使用可执行的 `/opt/hopper/bin/Hopper`;如果不可用,则自动检查 `~/.local/share/rea/hopper/bin/Hopper`。其他路径可通过 `HOPPER_LAUNCHER_PATH` 指定。如果文件存在但仍报告缺少分析引擎,请对实际 Hopper 路径运行 `ldd /absolute/path/to/Hopper | grep 'not found'` 检查缺少的系统库。安装详情见 [Hopper 指南](docs/installation.md#hopper)。
### 更新与卸载
- `rea update` 更新当前 REA 安装。
- `rea uninstall` 移除 REA 管理的智能体配置项和工作流文件,保留 Hopper。
- `rea uninstall --purge-data` 还会删除 REA 的缓存和状态。仅在需要移除这些数据时使用。
## 当前状态
仓库当前能力与平台要求见[英文支持指南](README.md#current-status)。main 分支可能领先于 [npm 发布版](docs/installation.md#released-package-and-main)。
- Ghidra 在 Linux x64、macOS x64/arm64 以及实验性的 Windows x64 P0 边界上提供 25 个只读操作。Linux/macOS 额外支持原子化的会话级函数注释。Windows P0 为只读;Ghidra 不提供 GUI 控制。
- 静态 Android 检查需要自备 JADX/Java,前置条件独立;真机验证覆盖 Linux。详见 [Android 分析](docs/android-analysis.md)。
- 浏览器、Electron 与进程请求需直接声明目标、动作与生命周期,并依赖宿主的实际访问权限,无需 REA 另行授权。Setup 的配置写入与 Hopper 安装仍需逐项批准确切计划。
- `rea capabilities` 描述的是二进制会话操作,而非全部应用/运行时工具。请以已连接 MCP 工具列表与相关指南为准。
## 一个提示词,完成一次完整调查
```text
逆向工程“备忘录”应用,找到离线搜索功能的工作方式,解释其控制流,
并使用 TypeScript 和 SQLite 为我的项目构建一个版本。
```
| 步骤 | 智能体的操作 | REA 工具 |
| ---: | ---------------------- | ---------------------------------------------------------------- |
| 1 | 打开并识别二进制文件 | `open_binary`, `binary_overview` |
| 2 | 搜索可能的离线搜索线索 | `search_strings`, `search_procedures`, `list_names` |
| 3 | 将线索连接到可执行代码 | `find_xrefs_to_name`, `xrefs`, `procedure_callers` |
| 4 | 重建相关控制流 | `get_call_graph`, `procedure_callees`, `procedure_info` |
| 5 | 反编译相关程序 | `procedure_pseudo_code`, `procedure_assembly`, `batch_decompile` |
| 6 | 在你的项目中构建该功能 | 适合你的技术栈、产品和需求的代码 |
REA 负责第 1–5 步中的二进制分析。第 6 步由智能体使用其常规文件编辑与测试工具完成。
## 智能体可以完成什么
- 在没有源代码时解释某项功能的实现方式。
- 重建应用的身份验证、存储、更新或网络流程。
- 恢复足够的结构,以记录未公开的格式或接口。
- 从字符串或符号追踪到实现可疑行为的代码。
- 在一个会话中切换两个应用版本并比较实现路径。
- 调查你喜欢的功能,并为自己的产品构建量身定制的版本。
- 将恢复的行为转换为产品功能、测试、迁移说明、移植代码或互操作替代品。
- 分析 Swift 和 Objective-C 元数据。
- 在 Hopper 中留下名称、注释与书签,使人与智能体的分析互相增强。
## 调查工具目录
| 工具类别 | 数量 | 用途 |
| ----------------- | ---: | -------------------------------------------------------------------------------------------------------------------- |
| 原生检查 | 41 | 函数、伪代码、汇编、字符串、符号、调用、引用、注释、字节读取与文件偏移 |
| 调查工作流 | 14 | 应用概览、函数档案、原生 API 与分发、批量反编译、功能追踪、调用路径与调用图、Swift 与 Objective-C 发现 |
| 原生二进制工具 | 10 | macOS 的 Mach-O 元数据、签名、plist、架构、Swift 符号与 LLDB 调用观察;Linux 的 ELF 布局、静态保护证据与历史崩溃记录 |
| 产物图 | 7 | 目录与软件包清单、编译后的 Interface Builder 文件、Apple 资源目录、Mach-O dylib 加载解析、提取与离线 EVM 接口推断 |
| 托管 PE/CLI | 7 | .NET 程序集身份、元数据、CIL 指令、原生依赖声明、重建导入与构建比较 |
| 固件 | 2 | Linux 固件区域检查与显式提取 |
| Android APK | 5 | 包与 manifest 声明、类搜索、成员清单、方法反编译与静态引用 |
| 浏览器观察 | 12 | 页面结构、网络元数据、脚本、来源映射、WebMCP 发现、截图与捕获比较 |
| Electron 分析 | 5 | 渲染进程观察、静态应用映射、静态/运行时结果关联 |
| JavaScript 运行时 | 2 | Node/Electron Inspector 目标发现、脚本位置与执行上下文事件 |
| 应用工作流 | 13 | 捕获的网站脚本导出、跨层功能追踪、构建比较、历史源码映射、静态返回结构比较与重建验证 |
| 工作区与观察 | 21 | 会话、证据包、导航上下文、进程/产物/函数比较与待解决问题跟踪 |
## 路线图
接下来的工作包括更多原生目标验证、JavaScript 与 .NET 跨版本比较,以及运行时观察和重建验证。当前设置已支持选择智能体集成和 Hopper 安装;安装其他分析工具仍是后续工作。详见[安装路线图](docs/roadmap.md)和[分析工具评估](docs/provider-evaluation.md)。
## 与其他编程智能体一起使用
Setup 支持 Claude Code、Claude Desktop、Codex、Cursor、Gemini CLI、Windsurf、Devin、OpenCode、Antigravity、GitHub Copilot CLI、Command Code 和 VS Code。已有 REA 注册默认选中;其他检测到的客户端需手动选择。任何支持本地 MCP 服务器的智能体都可以使用以下配置连接 REA。
<!-- x-release-please-start-version -->
```json
{
"mcpServers": {
"rea": {
"command": "npx",
"args": ["-y", "rea-agents@6.0.0", "mcp"]
}
}
}
```
<!-- x-release-please-end -->
## 工作原理
```mermaid
flowchart LR
Agent["编程智能体"] --> REA["REA<br/>CLI + MCP"]
Terminal["终端"] --> REA
REA --> Hopper["Hopper 分析操作"]
Hopper --> App["你的应用"]
REA --> Ghidra["Ghidra 只读分析<br/>清单 + 函数分析"]
Ghidra --> App
```
CLI 与 MCP 服务器使用相同的分析流程。终端命令完成后释放自己创建的桥接会话;智能体会话可以在调查期间保持连接。关闭 REA 会话不会退出用户正在使用的 Hopper 应用。
## CLI
上面的智能体工作流是使用 REA 最简单的方式。如果只想在终端中快速了解一个应用:
```bash
npx -y rea-agents@latest analyze /Applications/Notes.app
```
运行 `npx -y rea-agents@latest --help` 查看直接反编译和其他选项。
也可以全局安装 `rea` 命令:
如果需要经常使用,可以安装 `rea` 命令:
```bash
npm install --global rea-agents
rea --help
rea mcp
```
REA 可以直接打开 Mac 的 `.app` 文件夹。如果智能体找不到应用,请告诉它应用安装在哪里。
原生分析需要先配置分析提供方。原生命令、提供方选择、快照和脚本用法见 [CLI 与 Evidence 指南](docs/cli.md)。
## Hopper 应用行为
### 更新 REA
REA 会在需要时启动 Hopper,无需预先运行。Hopper 启动器内部会激活应用,因此打开目标时 Hopper 可能出现在其他窗口前。REA 会请求 macOS 在后台启动 Hopper,但无法保证窗口始终位于后台。
REA 更新较快,新版本经常包含错误修复。请保持安装的版本为最新。
REA 会推导明确的格式和架构参数,以避免常见的 FAT 与 ARM 选择对话框。其他 Hopper 或 macOS 对话框仍可能需要人工响应。关闭 REA 会话会终止桥并删除私有套接字目录,但不会退出用户正在使用的 Hopper 应用。
通过 npm 安装的 CLI 使用:
## 安全模型
```bash
rea update
```
每个桥会话都使用随机能力令牌和仅限当前用户的 Unix 套接字。诊断保留本机路径、摘要和错误位置等排查信息,同时移除凭据和认证令牌。Ghidra 会话还使用隔离的临时项目,不会打开或修改用户自己的 Ghidra 项目。
要更新智能体注册和 skill,请运行更新命令输出的设置命令。
这不是沙箱,也无法防御以同一操作系统用户身份运行的恶意进程。打开不可信二进制文件会让所选本地提供商以当前用户权限进行解析和分析。请按照 [SECURITY.md](SECURITY.md) 中的私密流程报告漏洞。
如果使用 `npx`,通过以下命令更新智能体设置:
```bash
npx rea-agents@latest setup
```
检查设置变更并重启智能体。单次 CLI 操作可使用 `npx rea-agents@latest`,后接所需命令。
## REA 的工作原理
智能体通过 MCP 调用 REA,检查目标并追踪相关代码。REA 返回发现及对应证据。智能体据此提出后续问题、解释行为,或编写并测试实现。CLI 命令使用同样的工作流。
![REA 调查流程:智能体询问本地目标的行为,REA 使用分析工具检查和追踪目标,智能体再利用返回的代码、引用和未知项进行解释、实现与测试。](website/public/assets/figures/rea-investigation-flow.svg)
[打开完整尺寸的图示](website/public/assets/figures/rea-investigation-flow.svg)。
<a id="current-status"></a>
## 可以分析什么
REA 需要 Node.js 22.x(>=22.19)、24.x(>=24.11)或 26+,以及 npm。额外工具和主机支持取决于分析目标:
| 目标 | REA 返回的内容 | 要求与指南 |
| --------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| 原生二进制文件 | 伪代码、汇编、字符串、符号、调用和引用 | Hopper、Ghidra 或 IDA;[原生分析](https://rea.tools/guides/native/) |
| 离线 ELF 布局 | 节、段、原始符号/重定位信息及静态防护机制候选项 | Linux x64 上由调用方提供的 pwntools;[二进制诊断](docs/binary-diagnostics.md) |
| EVM 字节码 | 分派选择器、字节偏移、推断的参数和状态可变性 | Linux x64 上的本地原始字节/十六进制输入载体;[离线 EVM 指南](docs/evm-bytecode.md) |
| 已记录的 Linux 崩溃 | 原始 note 记录、每个已记录线程的寄存器/信号及可选的映射候选项 | Linux x64 上由调用方提供的 pwntools;可选的 GDB/pwndbg;[已记录崩溃](docs/recorded-crashes.md) |
| JavaScript / Electron | 模块、导入、source map、路由、IPC 和原生扩展关系 | Node.js 和 npm;[应用分析](https://rea.tools/guides/javascript/) |
| 网站 | 页面结构、脚本、网络观察结果和按请求获取的截图 | Chrome 系浏览器;[浏览器分析](https://rea.tools/guides/browser/) |
| 已保存的网络捕获 | 请求、响应、可访问的载荷和来源位置 | HAR;原生 mitmproxy 捕获需要 Linux 上的 mitmdump;[捕获指南](docs/web-network-captures.md) |
| .NET 程序集 | 元数据、CIL 指令、声明的原生依赖和构建对比 | 静态检查;[托管代码指南](docs/managed-code-analysis.md) |
| Android APK | 清单声明、类、反编译的方法和引用 | Linux/macOS/Windows x64 上的无界面 JADX 和完整 JDK;[Android 指南](docs/android-analysis.md) |
| Android 设备 | 设备、软件包、进程、日志、转储、屏幕截图以及 APK/文件传输 | 调用方提供的 adb(模拟器或实体设备);[ADB 指南](docs/adb-device-analysis.md) |
| JEB 项目 | 引擎支持的项目单元、工件摘要和类型/方法的伪代码 | 由调用方启动、提供 MCP 的 JEB 客户端,通过 REA_JEB_MCP_URL 选择;[JEB 指南](docs/jeb-analysis.md) |
| Android 资源 | 解码后的清单、字符串表、语言区域和版本信息 | 调用方提供的 Apktool 启动器;[资源指南](docs/apktool-resource-analysis.md) |
| 固件 | 区域、提取结果和转交原生分析的内容 | Linux 上的 Binwalk / Unblob;[固件指南](docs/firmware-analysis.md) |
| 软件包与资源 | 文件清单、摘要、plist、Apple bundle 结构和提取的资源 | [制品与 JavaScript 指南](docs/javascript-artifact-reconstruction.md)、[Apple 应用](docs/apple-application-analysis.md) |
| 进程行为 | 终端输出、交互、退出和文件系统观察结果,以及运行对比 | 支持原生 PTY 的 Linux/macOS;[进程捕获](docs/process-capture.md) |
静态 JavaScript 和 .NET 检查读取提供的文件,不运行应用。运行时捕获会以你的用户权限运行目标或与之交互;各运行时指南说明了具体影响。
<a id="choosing-a-deep-analysis-provider"></a>
不同提供方支持的原生格式和主机系统有所不同。请参阅 [Hopper 与 Ghidra 设置](docs/installation.md#hopper)、[IDA 指南](docs/ida-provider.md)和[实验性 Windows Ghidra 支持](docs/windows-ghidra-p0.md)。Ghidra 也支持 [16 位 DOS 分析](docs/ghidra-dos.md)。提供方选择见 [CLI 指南](docs/cli.md#choose-a-provider)。对于最新 npm 版本发布后新增的功能,请查看[发布可用性](docs/installation.md#released-package-and-main)。
## 案例
[![DX-Ball 声音平移、Notion 剪贴板桥接与 TH04 弹幕环案例的插图](docs/assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball:重建声像计算
沿声音调用追踪到根据位置计算声像的辅助函数,检查指令,将不完整的伪代码转为 C。重建结果通过了 3,205 个原始 x86 测试用例,并复现了编译后函数的全部 63 个字节。
[阅读案例](https://rea.tools/showcase/dx-ball/) ·
[重建项目仓库](https://github.com/N0zoM1z0/dx-ball)
### Notion:追踪 Electron 剪贴板桥
找到渲染进程的剪贴板 API,沿 preload 和 IPC 追踪到主进程,并检查富格式剪贴板数据。
[阅读案例](https://rea.tools/showcase/notion/)
### TH04:恢复 DOS 环形子弹的计算
检查原始 PC-98 游戏的 16 位指令,恢复固定角度和瞄准角度的计算,并将重建的 C++ 与当年的编译器输出进行对比。
[阅读案例](https://rea.tools/showcase/th04/) ·
[重建项目仓库](https://github.com/N0zoM1z0/th04)
如果你用 REA 分析了有趣的目标,我们很想了解。欢迎通过 [issue](https://github.com/morluto/rea/issues) 或 [pull request](https://github.com/morluto/rea/pulls) 分享案例,说明目标、你的问题、REA 如何提供帮助,以及你的发现。
## 常见问题
<details><summary><strong>Hopper 是否需要提前运行?</strong></summary>
<details>
<summary><strong>哪些智能体可以使用 REA?</strong></summary>
不需要。REA 会在操作需要时启动 Hopper。Hopper 已经运行时也可以使用,但 REA 会打开新的分析文档,不会连接并复用现有 GUI 文档。
任何支持本地 MCP 服务的智能体都可以使用。设置流程会配置[受支持的智能体](docs/installation.md#supported-agents);其他客户端可通过[手动注册 MCP](docs/installation.md#mcp-registry) 使用。
</details>
<details><summary><strong>REA 是否包含 Hopper?</strong></summary>
<details>
<summary><strong>需要 Hopper、Ghidra 或 IDA 吗?</strong></summary>
不包含。Setup 可以为你安装 Hopper,但 Hopper 仍是需要单独授权的软件。REA 提供 CLI、MCP 服务器和面向智能体的工作流。
深入的原生分析需要其中一个引擎。静态 JavaScript 和 .NET 检查不需要原生分析引擎。设置流程可以在你批准后安装 Hopper;Ghidra 和 IDA 则使用已有安装。见[提供方设置](docs/installation.md#hopper)。
</details>
<details><summary><strong>REA 会上传我的二进制文件吗?</strong></summary>
<details>
<summary><strong>需要先启动 Hopper 吗?</strong></summary>
REA 不提供托管分析服务,而是通过本地 Unix 套接字把操作交给 Hopper。你的智能体或模型服务商可能有自己的数据政策,请单独核查。
REA 会在操作需要时启动 Hopper。在 macOS 上,首次运行时可能会出现对话框,让你选择演示模式或激活许可证。见 [Hopper 启动与故障排查](docs/installation.md#launcher-paths-and-troubleshooting)。
</details>
<details><summary><strong>REA 能恢复原始源代码吗?</strong></summary>
<details>
<summary><strong>从 skills.sh 安装 skill 有什么作用?</strong></summary>
不能保证。REA 提供伪代码、汇编、符号、字符串、元数据和关系,智能体可据此解释或兼容地重建观察到的行为。
skill 为智能体提供调查指引。使用 `npx rea-agents setup` 注册 REA 的 MCP 服务并安装匹配的指引,然后重启智能体。见[仅安装 skill](docs/installation.md#skill-only-installation)。
</details>
## 开发
<details>
<summary><strong>REA 返回什么代码?</strong></summary>
开发环境、架构、测试和发布说明请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。
原生分析返回伪代码和汇编。JavaScript/Electron 分析恢复模块及其关系。智能体利用这些发现编写并测试实现;[案例](#案例)提供了完整示例。
</details>
<details>
<summary><strong>REA 会上传我的应用吗?</strong></summary>
REA 在本机分析目标。智能体会接收工具结果,其模型提供商有自己的数据政策。
</details>
<details>
<summary><strong>遇到错误时该怎么办?</strong></summary>
先更新;最近的版本可能已经修复了问题。
通过 npm 安装的 CLI 使用:
```bash
rea update
```
通过 `npx` 设置智能体时使用:
```bash
npx rea-agents@latest setup
```
如果正在使用智能体,请完成[设置更新](#更新-rea)并重启智能体。重试同一任务。如果问题仍然存在,请[提交 issue](https://github.com/morluto/rea/issues),附上 REA 版本、目标类型、复现步骤和错误输出。
</details>
## 文档
可以先阅读网站上的[实操指南](https://rea.tools/guides/)。具体选项、前提条件和结果契约见:
- [安装与设置](docs/installation.md):智能体注册、提供方配置、更新和卸载。
- [就绪检查与故障排查](docs/installation.md#check-readiness-for-your-task):诊断特定智能体或分析引擎。
- [CLI 与 Evidence](docs/cli.md):命令、提供方选择、快照、导入/导出和退出状态。
- [MCP 契约](docs/mcp-contracts.md)和[智能体提示词](docs/mcp-prompts.md):工具结果、会话和引导式调查。
- [工具目录](docs/mcp-contracts.md#generated-catalog):构建时生成的工具、提供方和 CLI 命令清单。
- [路线图](docs/roadmap.md):计划中的工作和能力跟踪。
请按照 [SECURITY.md](SECURITY.md) 报告漏洞。
## Star 历史
🎉 **GitHub Star 突破 20,000,感谢大家!**
🎉 **GitHub Star 达到 50,000 个,感谢大家!**
感谢每一位使用 REA、反馈问题、测试构建和贡献修复的朋友。
感谢每一位使用 REA、报告错误、提出功能需求、测试构建和贡献修复的朋友。
<a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date&amp;theme=dark&amp;legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="REA GitHub Star 历史" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
<img alt="REA 的 GitHub Star 历史" src="https://api.star-history.com/chart?repos=morluto/rea&amp;type=date" />
</picture>
</a>
## 免责声明
REA 为合法的逆向工程研究、分析和重建提供工具。你有责任取得所需授权并遵守适用法律。项目不支持非法或未经授权的使用。
## 参与贡献
欢迎帮助改进 REA!你可以[提交 issue](https://github.com/morluto/rea/issues) 报告错误或建议功能,也可以[提交 pull request](https://github.com/morluto/rea/pulls) 改进代码或文档。
开发设置和检查见 [CONTRIBUTING.md](CONTRIBUTING.md),验证流程见[测试指南](docs/testing.md),项目结构见[架构图](docs/architecture.mermaid)。
## 许可证
[MIT](LICENSE)
+14 -5
View File
@@ -25,6 +25,11 @@ class ReaJadxBridge {
private record MethodSnapshot(String name, String shortId, Map<String, Object> summary) {}
private record ClassSnapshot(JavaClass node, List<MethodSnapshot> methods, Map<String, Object> summary) {}
private static final class InputFailure extends IllegalArgumentException {
final String field;
InputFailure(String field, String message) { super(message); this.field = field; }
}
private ReaJadxBridge(SessionHolder holder) { this.holder = holder; }
private static CallToolResult text(String value, boolean failed) {
@@ -100,8 +105,9 @@ class ReaJadxBridge {
}
String name = string(args, "class_name");
List<ClassSnapshot> candidates = classes.get(name);
if (candidates == null) throw new IllegalArgumentException("Exact class not found: " + name);
if (candidates.size() != 1) throw new IllegalArgumentException("Ambiguous metadata class identity: " + name
if (candidates == null) throw new InputFailure("class_name", "Exact class not found: " + name
+ "; use search_android_classes to discover fully qualified names.");
if (candidates.size() != 1) throw new InputFailure("class_name", "Ambiguous metadata class identity: " + name
+ "; raw identities: " + candidates.stream().map(candidate -> candidate.node().getRawName()).toList());
return candidates.get(0);
}
@@ -109,7 +115,8 @@ class ReaJadxBridge {
private List<MethodSnapshot> methods(ClassSnapshot cls, JsonObject args) {
String name = string(args, "method_name");
List<MethodSnapshot> result = cls.methods().stream().filter(method -> method.name().equals(name)).toList();
if (result.isEmpty()) throw new IllegalArgumentException("Method not found: " + name);
if (result.isEmpty()) throw new InputFailure("method_name", "Method not found: " + name
+ "; use inspect_android_class to discover available methods.");
return result;
}
@@ -141,7 +148,7 @@ class ReaJadxBridge {
if (name.equals("get_method_body")) {
List<MethodSnapshot> overloads = methods(cls, args);
int index = integer(args, "overload_index", 0);
if (index >= overloads.size()) throw new IllegalArgumentException("overload_index out of range: " + index);
if (index >= overloads.size()) throw new InputFailure("overload_index", "overload_index out of range: " + index);
JavaMethod method = method(cls, overloads.get(index));
JadxSession.SmartCode code = current.getMethodBodySmart(method, current.getMaxSourceBytes(), true);
return json(Map.of("class_name", cls.summary().get("full_name"),
@@ -155,7 +162,7 @@ class ReaJadxBridge {
if (name.equals("get_xrefs_to_class")) uses = cls.node().getUseIn();
else {
List<MethodSnapshot> overloads = methods(cls, args);
if (overloads.size() != 1) throw new IllegalArgumentException("Method references require a unique overload");
if (overloads.size() != 1) throw new InputFailure("method_name", "Method references require a unique overload");
target += "." + overloads.get(0).name();
uses = method(cls, overloads.get(0)).getUseIn();
}
@@ -211,6 +218,8 @@ class ReaJadxBridge {
tool.getInputSchema().getRequired(), null), description, null, null, null, null, null, null);
server.addTool(narrowed, (connection, request, continuation) -> {
try { return bridge.handle(name, request.getArguments()); }
catch (InputFailure error) { return text(JSON.toJson(Map.of(
"kind", "invalid-input", "field", error.field, "message", error.getMessage())), true); }
catch (IllegalArgumentException error) { return text(error.getMessage(), true); }
});
}
+280 -56
View File
@@ -52,6 +52,8 @@ import ghidra.app.decompiler.ClangCaseToken;
import ghidra.app.decompiler.ClangNode;
import ghidra.framework.Application;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressIterator;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.address.AddressRangeIterator;
@@ -118,6 +120,8 @@ public final class ReaGhidraBridge extends HeadlessScript {
);
private static final String[] CAPABILITIES = {
"annotate_native_function",
"set_address_name",
"set_addresses_names",
"inspect_native_load_image",
"read_bytes",
"address_to_file_offset",
@@ -372,6 +376,12 @@ public final class ReaGhidraBridge extends HeadlessScript {
case "resolve_native_call_targets" -> resolveNativeCallTargets(request.params);
case "xrefs" -> xrefs(request.params);
case "analyze_function" -> analyzeFunction(request.params);
case "set_address_name", "set_addresses_names" -> {
if (!descriptor.transport.equals("unix-socket"))
throw new RequestFailure("method_unavailable", "Windows P0 does not admit database mutation");
yield request.method.equals("set_address_name")
? setAddressName(request.params) : setAddressesNames(request.params);
}
case "annotate_native_function" -> {
if (!descriptor.transport.equals("unix-socket"))
throw new RequestFailure("method_unavailable", "Windows P0 does not admit database mutation");
@@ -415,7 +425,8 @@ public final class ReaGhidraBridge extends HeadlessScript {
result.addProperty("analysis_timed_out", timedOut);
result.add("capabilities", GSON.toJsonTree(
java.util.Arrays.stream(CAPABILITIES)
.filter(value -> !readOnly || !value.equals("annotate_native_function"))
.filter(value -> !readOnly || !(value.equals("annotate_native_function")
|| value.equals("set_address_name") || value.equals("set_addresses_names")))
.toArray(String[]::new)
));
result.add("target", target);
@@ -723,8 +734,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
if (!direction.equals("incoming") && !direction.equals("outgoing")) {
throw new RequestFailure("invalid_request", "direction must be incoming or outgoing");
}
InstructionScan scan = scanInstructions(function, Integer.MAX_VALUE);
List<Reference> references = collectReferences(scan.instructions, direction);
List<Reference> references = collectReferences(function, direction);
JsonArray edges = new JsonArray();
for (Reference reference : references) {
edges.add(referenceEdge(reference));
@@ -735,7 +745,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
result.add("references", edges);
result.addProperty("reference_kinds_available", true);
JsonArray unresolvedCalls = new JsonArray();
if (direction.equals("outgoing")) for (Instruction instruction : scan.instructions) {
if (direction.equals("outgoing")) for (Instruction instruction : scanInstructions(function, Integer.MAX_VALUE).instructions) {
if (!instruction.getFlowType().isCall()) continue;
boolean resolved = false;
for (Reference reference : instruction.getReferencesFrom()) if (reference.getReferenceType().isCall()) resolved = true;
@@ -840,14 +850,13 @@ public final class ReaGhidraBridge extends HeadlessScript {
private JsonObject instructionReference(Reference reference) {
JsonObject item = new JsonObject();
RefType type = reference.getReferenceType();
JsonObject kind = referenceKind(reference);
item.addProperty("source_address", canonicalAddress(reference.getFromAddress()));
item.addProperty("target_address", canonicalAddress(reference.getToAddress()));
item.addProperty("type", type.getName());
item.addProperty("call", type.isCall());
item.addProperty("jump", type.isJump());
item.addProperty("indirect", type.isIndirect());
item.addProperty("computed", type.isComputed());
item.addProperty("operand_index", reference.getOperandIndex());
for (String field : List.of("type", "call", "jump", "indirect", "computed",
"operand_index", "data", "read", "write", "primary", "provenance"))
item.add(field, kind.get(field));
item.addProperty("source", normalizedSource(reference.getSource()));
return item;
}
@@ -865,6 +874,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
JsonArray operands = new JsonArray();
JsonArray references = new JsonArray();
JsonArray destinations = new JsonArray();
JsonArray flowEvidence = new JsonArray();
JsonObject flow = new JsonObject();
flow.addProperty("kind", "unavailable");
flow.addProperty("conditional", false);
@@ -880,7 +890,20 @@ public final class ReaGhidraBridge extends HeadlessScript {
result.addProperty("mnemonic", instruction.getMnemonicString());
result.addProperty("raw_disassembly", instruction.toString());
RefType type = instruction.getFlowType();
flow.addProperty("kind", type.isCall() ? "call" : type.isJump() ? "jump" : type.isTerminal() ? "terminal" : "fallthrough");
JsonObject listingFlow = new JsonObject();
listingFlow.addProperty("source", "ghidra-listing-flow-type");
listingFlow.addProperty("value", type.getName());
flowEvidence.add(listingFlow);
boolean decodedReturn = false;
for (PcodeOp operation : instruction.getPcode()) {
if (operation.getOpcode() != PcodeOp.RETURN) continue;
decodedReturn = true;
JsonObject returnEvidence = new JsonObject();
returnEvidence.addProperty("source", "ghidra-instruction-pcode");
returnEvidence.addProperty("value", operation.getMnemonic());
flowEvidence.add(returnEvidence);
}
flow.addProperty("kind", type.isCall() ? "call" : type.isJump() ? "jump" : decodedReturn ? "return" : type.isTerminal() ? "terminal" : "fallthrough");
flow.addProperty("conditional", type.isConditional());
flow.addProperty("computed", type.isComputed());
if (!type.isComputed()) for (Address target : instruction.getFlows()) destinations.add(canonicalAddress(target));
@@ -916,10 +939,13 @@ public final class ReaGhidraBridge extends HeadlessScript {
}
}
flow.add("direct_destinations", destinations);
flow.add("classification_evidence", flowEvidence);
result.add("operands", operands);
result.add("flow", flow);
result.add("references", references);
result.add("limitations", GSON.toJsonTree(List.of("Operand components are Ghidra Listing decoder tokens; effective memory base/index/displacement roles and per-instruction context mode are unavailable. The mode field is the program language variant.", "Terminal flow is not classified as a return without provider evidence.")));
List<String> limitations = new ArrayList<>(List.of("Operand components are Ghidra Listing decoder tokens; effective memory base/index/displacement roles and per-instruction context mode are unavailable. The mode field is the program language variant."));
if (flow.get("kind").getAsString().equals("terminal")) limitations.add("No RETURN operation was observed in the provider's instruction p-code; terminal classification remains generic.");
result.add("limitations", GSON.toJsonTree(limitations));
return result;
}
@@ -1007,9 +1033,14 @@ public final class ReaGhidraBridge extends HeadlessScript {
Address entry = function.getEntryPoint();
if (function.isExternal() || !currentProgram.getMemory().contains(entry))
throw new RequestFailure("invalid_request", "Annotations require a local function entry: " + canonicalAddress(entry));
for (String field : List.of("name", "comment", "inline_comment")) {
if (params.has(field)) validateAnnotationText(requireText(params, field), field);
}
int transaction = currentProgram.startTransaction("REA function annotations");
boolean commit = false;
try {
String leafName = params.has("name")
? symbolLeafName(function.getSymbol(), requireString(params, "name")) : null;
// Validate edits through Ghidra's own setters, including name rules.
// A later invalid name must roll back earlier comment writes.
for (String field : List.of("comment", "inline_comment")) {
@@ -1020,7 +1051,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
}
}
if (params.has("name"))
function.setName(requireString(params, "name"), SourceType.USER_DEFINED);
function.setName(leafName, SourceType.USER_DEFINED);
monitor.checkCancelled();
invalidateAnalysisCaches();
JsonObject readback = annotationReadback(function);
@@ -1028,7 +1059,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
if (!params.has(field)) continue;
String requested = requireText(params, field);
JsonElement measured = readback.get(field);
String expected = !field.equals("name") && requested.isEmpty() ? null : requested;
String expected = field.equals("name") ? leafName : requested.isEmpty() ? null : requested;
String observed = field.equals("name") ? function.getName() :
(measured.isJsonNull() ? null : measured.getAsString());
if (!java.util.Objects.equals(expected, observed))
@@ -1058,6 +1089,22 @@ public final class ReaGhidraBridge extends HeadlessScript {
}
}
private String symbolLeafName(Symbol symbol, String requested) throws ghidra.util.exception.InvalidInputException {
// Fully qualified readback must be usable as an idempotent rename input.
if (requested.equals(symbol.getName(true))) return symbol.getName();
String namespace = symbol.getParentNamespace().isGlobal()
? "" : symbol.getParentNamespace().getName(true);
String prefix = namespace + "::";
if (!namespace.isEmpty() && requested.startsWith(prefix)) {
String leaf = requested.substring(prefix.length());
if (!leaf.isEmpty()) return leaf;
throw new ghidra.util.exception.InvalidInputException(
"Symbol name has an empty leaf within namespace " + namespace + " at " +
canonicalAddress(symbol.getAddress()) + ": " + requested);
}
return requested;
}
private static String requireText(JsonObject params, String field) {
JsonElement value = params.get(field);
if (value == null || !value.isJsonPrimitive() || !value.getAsJsonPrimitive().isString())
@@ -1065,6 +1112,21 @@ public final class ReaGhidraBridge extends HeadlessScript {
return value.getAsString();
}
private static void validateAnnotationText(String text, String field) {
for (int index = 0; index < text.length(); index++) {
char character = text.charAt(index);
if (character == 0)
throw new RequestFailure("invalid_request", "Annotation " + field + " contains NUL at UTF-16 index " + index + "; Ghidra's decompiler cannot marshal NUL text");
if (Character.isHighSurrogate(character) && index + 1 < text.length() &&
Character.isLowSurrogate(text.charAt(index + 1))) {
index++;
continue;
}
if (Character.isSurrogate(character))
throw new RequestFailure("invalid_request", "Annotation " + field + " contains an unpaired Unicode surrogate at UTF-16 index " + index + "; Ghidra cannot preserve it as annotation text");
}
}
private JsonObject analyzeFunction(JsonObject params) throws Exception {
requireKeys(params, Set.of("procedure"));
Function function = resolveProcedure(requireString(params, "procedure"));
@@ -1074,11 +1136,11 @@ public final class ReaGhidraBridge extends HeadlessScript {
if (pseudocode == null) {
pseudocode = "";
}
List<Reference> incomingReferences = collectReferences(scan.instructions, "incoming")
List<Reference> incomingReferences = collectReferences(function, "incoming")
.stream()
.filter(reference -> !function.getBody().contains(reference.getFromAddress()))
.toList();
List<Reference> outgoingReferences = collectReferences(scan.instructions, "outgoing");
List<Reference> outgoingReferences = collectReferences(function, "outgoing");
JsonArray incoming = referenceEdges(incomingReferences);
JsonArray outgoing = referenceEdges(outgoingReferences);
JsonArray comments = comments(scan.instructions);
@@ -1363,6 +1425,68 @@ public final class ReaGhidraBridge extends HeadlessScript {
return symbol == null ? JsonNull.INSTANCE : GSON.toJsonTree(symbol.getName(true));
}
// Analyst naming: a function entry renames the function, other addresses get a primary label.
private boolean applyAddressName(Address address, String name) throws Exception {
if (!currentProgram.getMemory().contains(address))
throw new RequestFailure("invalid_request", "Address is not mapped: " + canonicalAddress(address));
validateAnnotationText(name, "name");
int transaction = currentProgram.startTransaction("REA address name");
boolean commit = false;
try {
Function function = currentProgram.getFunctionManager().getFunctionAt(address);
String expected = name;
if (function != null) {
expected = symbolLeafName(function.getSymbol(), name);
function.setName(expected, SourceType.USER_DEFINED);
} else {
var table = currentProgram.getSymbolTable();
Symbol primary = table.getPrimarySymbol(address);
if (primary != null && !primary.isDynamic()) {
expected = symbolLeafName(primary, name);
primary.setName(expected, SourceType.USER_DEFINED);
} else {
Symbol created = table.createLabel(address, name, SourceType.USER_DEFINED);
created.setPrimary();
}
}
invalidateAnalysisCaches();
Symbol readback = currentProgram.getSymbolTable().getPrimarySymbol(address);
commit = readback != null && expected.equals(readback.getName());
return commit;
}
catch (ghidra.util.exception.InvalidInputException | ghidra.util.exception.DuplicateNameException exception) {
return false;
}
finally {
currentProgram.endTransaction(transaction, commit);
}
}
private JsonElement setAddressName(JsonObject params) throws Exception {
requireKeys(params, Set.of("document", "address", "name"));
requireDocument(params);
return GSON.toJsonTree(applyAddressName(requireAddress(params, "address"), requireString(params, "name")));
}
private JsonElement setAddressesNames(JsonObject params) throws Exception {
requireKeys(params, Set.of("document", "names"));
requireDocument(params);
if (!params.has("names") || !params.get("names").isJsonObject())
throw new RequestFailure("invalid_request", "names must be an object of address -> name");
JsonObject result = new JsonObject();
for (Map.Entry<String, JsonElement> entry : params.getAsJsonObject("names").entrySet()) {
boolean ok;
try {
ok = applyAddressName(parseReaAddress(entry.getKey()), entry.getValue().getAsString());
}
catch (RequestFailure failure) {
ok = false;
}
result.addProperty(entry.getKey(), ok);
}
return result;
}
private JsonArray listDocuments(JsonObject params) {
requireKeys(params, Set.of());
JsonArray result = new JsonArray();
@@ -1471,6 +1595,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
: regexMatcher(expression, caseSensitive);
JsonArray items = new JsonArray();
for (InventoryItem item : inventory) {
monitor.checkCancelled();
if (!matcher.matches(item.value)) {
continue;
}
@@ -1581,33 +1706,47 @@ public final class ReaGhidraBridge extends HeadlessScript {
}
private Function resolveProcedure(String value) throws Exception {
Address address = tryParseAddress(value);
if (address != null) {
Function function = currentProgram.getFunctionManager().getFunctionAt(address);
if (function == null && address.isMemoryAddress()) {
function = currentProgram.getFunctionManager().getFunctionContaining(address);
// Explicit address syntax wins; an unprefixed identifier is first an
// exact symbol name, even when every character is a hexadecimal digit.
boolean explicitAddress = isExplicitReaAddress(value);
if (!explicitAddress) {
List<Function> matches = new ArrayList<>();
for (FunctionEntry entry : procedures()) {
monitor.checkCancelled();
Function function = entry.function;
Symbol symbol = function.getSymbol();
String qualified = symbol == null ? function.getName() : symbol.getName(true);
boolean matchesName = function.getName().equals(value) || qualified.equals(value);
if (!matchesName) {
// Imported labels (for example Mach-O _main) can share a
// function entry without becoming its primary symbol. Only
// exact entries qualify; an interior label is not a selector.
for (Symbol entrySymbol : currentProgram.getSymbolTable().getSymbols(function.getEntryPoint())) {
monitor.checkCancelled();
if (entrySymbol.getName().equals(value) || entrySymbol.getName(true).equals(value)) {
matchesName = true;
break;
}
}
}
if (matchesName) matches.add(function);
}
if (function == null) {
throw new RequestFailure("not_found", "No procedure exists at the requested address");
}
return function;
if (matches.size() > 1)
throw new RequestFailure("ambiguous", "Ghidra procedure name is ambiguous: " + value +
"; select an exact entry address from " + matches.stream()
.map(function -> canonicalAddress(function.getEntryPoint())).toList());
if (matches.size() == 1) return matches.get(0);
}
List<Function> matches = new ArrayList<>();
for (FunctionEntry entry : procedures()) {
Function function = entry.function;
Symbol symbol = function.getSymbol();
String qualified = symbol == null ? function.getName() : symbol.getName(true);
if (function.getName().equals(value) || qualified.equals(value)) {
matches.add(function);
}
}
if (matches.isEmpty()) {
throw new RequestFailure("not_found", "Unknown Ghidra procedure name");
}
if (matches.size() != 1) {
throw new RequestFailure("ambiguous", "Ghidra procedure name is ambiguous");
}
return matches.get(0);
// Retain legacy bare-hex address input only when no symbol matches.
Address address = explicitAddress ? parseReaAddress(value) : tryParseAddress(value);
if (address == null)
throw new RequestFailure("not_found", "Unknown Ghidra procedure name or address: " + value);
Function function = currentProgram.getFunctionManager().getFunctionAt(address);
if (function == null && address.isMemoryAddress())
function = currentProgram.getFunctionManager().getFunctionContaining(address);
if (function == null)
throw new RequestFailure("not_found", "No procedure exists at the requested address: " + value);
return function;
}
private JsonObject nativeApiBoundary(
@@ -2530,21 +2669,32 @@ public final class ReaGhidraBridge extends HeadlessScript {
}
private List<Reference> collectReferences(
List<Instruction> instructions,
Function function,
String direction) throws Exception {
// References can target instruction interiors or originate in embedded
// data. Use actual body ownership, including an external's exact entry.
AddressSet scope = new AddressSet(function.getBody());
scope.add(function.getEntryPoint());
boolean outgoing = direction.equals("outgoing");
AddressIterator addresses = outgoing
? currentProgram.getReferenceManager().getReferenceSourceIterator(scope, true)
: currentProgram.getReferenceManager().getReferenceDestinationIterator(scope, true);
TreeMap<String, Reference> observed = new TreeMap<>();
for (Instruction instruction : instructions) {
while (addresses.hasNext()) {
monitor.checkCancelled();
if (direction.equals("outgoing")) {
Address address = addresses.next();
if (outgoing) {
for (Reference reference : currentProgram.getReferenceManager()
.getReferencesFrom(instruction.getAddress())) {
.getReferencesFrom(address)) {
monitor.checkCancelled();
addReference(observed, reference);
}
}
else {
ReferenceIterator iterator = currentProgram.getReferenceManager()
.getReferencesTo(instruction.getAddress());
.getReferencesTo(address);
while (iterator.hasNext()) {
monitor.checkCancelled();
addReference(observed, iterator.next());
}
}
@@ -2944,10 +3094,46 @@ public final class ReaGhidraBridge extends HeadlessScript {
return parseReaAddress(requireString(params, name));
}
private static boolean isExplicitReaAddress(String value) {
if (value.regionMatches(true, 0, "0x", 0, 2) &&
isHexadecimal(value, 2, value.length()))
return true;
int separator = value.toLowerCase(Locale.ROOT).lastIndexOf(":0x");
if (separator <= 0 || !isHexadecimal(value, separator + 3, value.length()))
return false;
// Classify the encoded space iteratively. A repeated regex alternation
// can exhaust Java's stack on a long ordinary symbol name.
for (int index = 0; index < separator; index++) {
char item = value.charAt(index);
if ((item >= 'A' && item <= 'Z') ||
(item >= 'a' && item <= 'z') ||
(item >= '0' && item <= '9') ||
item == '.' || item == '_' || item == '~' || item == '-')
continue;
if (item != '%' || index + 2 >= separator ||
!isHexadecimal(value, index + 1, index + 3))
return false;
index += 2;
}
return true;
}
private static boolean isHexadecimal(String value, int start, int end) {
if (start >= end) return false;
for (int index = start; index < end; index++) {
char item = value.charAt(index);
if (!((item >= '0' && item <= '9') ||
(item >= 'a' && item <= 'f') ||
(item >= 'A' && item <= 'F')))
return false;
}
return true;
}
private Address parseReaAddress(String value) {
Address address = tryParseAddress(value);
if (address == null) {
throw new RequestFailure("invalid_request", "Unknown or invalid Ghidra address");
throw new RequestFailure("invalid_request", "Unknown or invalid Ghidra address: " + value);
}
return address;
}
@@ -2956,22 +3142,31 @@ public final class ReaGhidraBridge extends HeadlessScript {
try {
String spaceName = null;
String offset = value;
int separator = value.lastIndexOf(":0x");
int separator = value.toLowerCase(Locale.ROOT).lastIndexOf(":0x");
if (separator >= 0) {
spaceName = decodeAddressSpace(value.substring(0, separator));
offset = value.substring(separator + 3);
}
else if (value.startsWith("0x")) {
else if (value.startsWith("0x") || value.startsWith("0X")) {
offset = value.substring(2);
}
if (!offset.matches("[0-9A-Fa-f]+")) {
if (!isHexadecimal(offset, 0, offset.length())) {
return null;
}
AddressSpace space = spaceName == null
? currentProgram.getAddressFactory().getDefaultAddressSpace()
: currentProgram.getAddressFactory().getAddressSpace(spaceName);
return space == null ? null : space.getAddress(offset);
if (space == null) return null;
Address address = space.getAddress(offset);
BigInteger requestedOffset = new BigInteger(offset, 16);
BigInteger parsedOffset = new BigInteger(Long.toUnsignedString(address.getOffset()));
if (!requestedOffset.equals(parsedOffset))
throw new RequestFailure("invalid_request",
"Ghidra address offset cannot be represented without truncation in space " +
space.getName() + ": requested " + value + ", parsed " + canonicalAddress(address));
return address;
}
catch (RequestFailure failure) { throw failure; }
catch (Exception exception) {
return null;
}
@@ -3055,9 +3250,29 @@ public final class ReaGhidraBridge extends HeadlessScript {
);
}
catch (PatternSyntaxException exception) {
throw new RequestFailure("invalid_request", "Invalid regex pattern");
// Java wraps compiler stack exhaustion in PatternSyntaxException
// without retaining its cause. This producer reason is not bad syntax.
if (exception.getDescription().equals("Stack overflow during pattern compilation"))
throw regexStackExhausted(expression, "compiling");
throw new RequestFailure("invalid_request", "Invalid regex pattern " + expression + ": " + exception.getDescription() + " at index " + exception.getIndex());
}
return value -> pattern.matcher(value).find();
catch (StackOverflowError exhausted) {
throw regexStackExhausted(expression, "compiling");
}
return value -> {
try {
return pattern.matcher(value).find();
}
catch (StackOverflowError exhausted) {
throw regexStackExhausted(expression, "matching");
}
};
}
private static RequestFailure regexStackExhausted(String expression, String stage) {
return new RequestFailure("regex_stack_exhausted",
"Ghidra's Java regex engine exhausted its stack while " + stage +
" pattern " + expression + ". Use literal mode or simplify the regex; the session remains usable.");
}
private static SessionDescriptor readDescriptor(Path path) throws IOException {
@@ -3114,7 +3329,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
private void requireDocument(JsonObject params) {
String document = optionalString(params, "document");
if (document != null && !document.equals(currentProgram.getName())) {
throw new RequestFailure("not_found", "Unknown Ghidra Program identity");
throw new RequestFailure("not_found", "Unknown Ghidra Program identity: " + document + "; active program: " + currentProgram.getName());
}
}
@@ -3226,7 +3441,16 @@ public final class ReaGhidraBridge extends HeadlessScript {
private static void writeResponse(BufferedWriter writer, JsonObject response) throws IOException {
String encoded = GSON.toJson(response);
writer.write(encoded);
// Gson leaves UTF-16 surrogates literal. Escape them in JSON so even
// diagnostics quoting ill-formed caller text remain lossless UTF-8.
int start = 0;
for (int index = 0; index < encoded.length(); index++) {
if (!Character.isSurrogate(encoded.charAt(index))) continue;
writer.write(encoded, start, index - start);
writer.write("\\u" + Integer.toHexString(encoded.charAt(index)));
start = index + 1;
}
writer.write(encoded, start, encoded.length() - start);
writer.newLine();
writer.flush();
}
+89
View File
@@ -0,0 +1,89 @@
import ghidra.app.cmd.function.CreateFunctionCmd;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.FlowType;
import ghidra.program.model.pcode.PcodeOp;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* Undo wrong no-return flags from auto-analysis. A function flagged no-return that contains a
* real RET is an ordinary function (stream readers, cxa_guard_acquire, ...). Callers treated the
* call as a terminator and the decompiler truncated them. Clear the flag, then re-disassemble only
* the call sites of the functions that were cleared and refit their owning functions in place.
*/
public final class ReaGhidraNoReturnFix extends GhidraScript {
@Override
public void run() throws Exception {
// Windows P0 does not admit analysis-database mutation.
if (System.getProperty("os.name", "").startsWith("Windows")) return;
FunctionManager fm = currentProgram.getFunctionManager();
Listing li = currentProgram.getListing();
Set<Address> cleared = new HashSet<>();
for (Function f : fm.getFunctions(true)) {
monitor.checkCancelled();
if (!f.hasNoReturn() || f.isThunk()) continue;
for (Instruction ins : li.getInstructions(f.getBody(), true)) {
FlowType ft = ins.getFlowType();
boolean decodedReturn = false;
for (PcodeOp operation : ins.getPcode()) {
if (operation.getOpcode() == PcodeOp.RETURN) decodedReturn = true;
}
if (decodedReturn && !ft.isJump() && !ft.isCall()) {
f.setNoReturn(false);
cleared.add(f.getEntryPoint());
break;
}
}
}
// A thunk inherits the flag of the function it forwards to.
for (Function f : fm.getFunctions(true)) {
monitor.checkCancelled();
if (!f.isThunk()) continue;
Function target = f.getThunkedFunction(true);
if (target != null && cleared.contains(target.getEntryPoint())) {
cleared.add(f.getEntryPoint());
}
}
int redone = 0;
TreeSet<Address> owners = new TreeSet<>();
if (!cleared.isEmpty()) {
List<Address> sites = new ArrayList<>();
for (Instruction ins : li.getInstructions(true)) {
monitor.checkCancelled();
FlowType ft = ins.getFlowType();
if (!(ft.isCall() && ft.isTerminal())) continue;
Address[] flows = ins.getFlows();
if (flows.length == 0 || !cleared.contains(flows[0])) continue;
// Do not redisassemble into an independently identified function.
Address next = ins.getMaxAddress().add(1);
if (fm.getFunctionAt(next) != null || !currentProgram.getMemory().contains(next)) continue;
sites.add(ins.getAddress());
}
for (Address s : sites) {
monitor.checkCancelled();
Instruction ins = li.getInstructionAt(s);
if (ins == null) continue;
Function owner = fm.getFunctionContaining(s);
if (owner != null && !owner.isThunk()) owners.add(owner.getEntryPoint());
clearListing(ins.getMinAddress(), ins.getMaxAddress());
disassemble(s);
redone++;
}
for (Address e : owners) {
monitor.checkCancelled();
Function f = fm.getFunctionAt(e);
// Refit the body in place so the name, signature and calling convention survive.
if (f != null) CreateFunctionCmd.fixupFunctionBody(currentProgram, f, monitor);
}
// No analyzeChanges here: on libpl2.so it adds about 70 s, which pushes startup past the 330 s deadline.
}
println(
"REA no-return fix: cleared=" + cleared.size() + " sites=" + redone + " refit=" + owners.size());
}
}
+317 -128
View File
@@ -8,12 +8,12 @@ API access on this thread: moving dispatch to a worker can deadlock Hopper.
import json
import hmac
import os
import re
import socket
from typing import Any, Optional, Protocol, Sequence
BAD_ADDRESSES = (-1, 0xFFFFFFFFFFFFFFFF, None)
_selected_document = None
# The native label setter truncates NSString names at this UTF-16 extent.
HOPPER_SYMBOL_NAME_UTF16_UNITS = 1024
_rea_session_document = None
_search_inventory_cache = {}
_pseudocode_cache = {}
@@ -89,9 +89,11 @@ def _session_document():
global _rea_session_document
documents = _api().documents()
if _rea_session_document is not None:
# Hopper recreates Python wrappers; equality compares native handles.
# Retain our bound wrapper so cache identity stays stable across calls.
return (
_rea_session_document
if any(document is _rea_session_document for document in documents)
if any(document == _rea_session_document for document in documents)
else None
)
return _bind_session_document(documents)
@@ -174,46 +176,89 @@ def _json_safe(value):
def _document(name=None):
"""Resolve an explicit or session-selected document without changing Hopper UI."""
global _selected_document
api = _api()
documents = api.documents()
if name is not None:
matches = [candidate for candidate in documents if candidate.getDocumentName() == name]
if len(matches) == 1:
return matches[0]
if len(matches) > 1:
current = api.current_document()
if current is not None and current.getDocumentName() == name:
return current
raise InvalidRequestError("Hopper document name is ambiguous")
raise InvalidRequestError("Unknown Hopper document")
if _selected_document is not None:
for candidate in documents:
if candidate.getDocumentName() == _selected_document:
return candidate
"""Keep observations and mutations bound to the active REA target."""
documents = _api().documents()
session_document = _session_document()
if session_document is not None:
return session_document
current = api.current_document()
if current is None:
raise CapabilityUnavailableError("No Hopper document is loaded")
return current
if session_document is None:
raise CapabilityUnavailableError("The active REA target's Hopper document is no longer open; reopen the target with open_binary")
if name is not None:
# A document name is display metadata; scope it to the bound native
# handle even when another open target happens to have the same name.
if session_document.getDocumentName() == name:
return session_document
if any(candidate.getDocumentName() == name for candidate in documents):
raise InvalidRequestError("Hopper document belongs to another target; use open_binary to select that target")
raise InvalidRequestError("Unknown Hopper document")
return session_document
def _api_text(value, field):
"""Validate text before passing it to Hopper's native UTF-8 string API."""
if not isinstance(value, str):
raise InvalidRequestError("%s must be a string" % field)
if "\0" in value:
raise InvalidRequestError("%s contains a NUL character, which Hopper's Python API cannot represent" % field)
try:
value.encode("utf-8")
except UnicodeEncodeError as error:
raise InvalidRequestError("%s contains an unpaired Unicode surrogate, which Hopper's Python API cannot represent" % field) from error
return value
def _validate_name_targets(document, names):
"""Keep Hopper's unique-label moves within the explicitly selected addresses."""
targets = {address for _, address, _ in names}
if len(targets) != len(names):
raise InvalidRequestError("Batch rename selects the same address more than once; use one canonical address per target")
labels = set()
for _, address, name in names:
_segment(document, address)
if not name:
continue
if name in labels:
raise InvalidRequestError("Batch rename assigns the same name more than once: %s" % name)
labels.add(name)
owner = document.getAddressForName(name)
if owner not in BAD_ADDRESSES and owner != address and owner not in targets:
raise InvalidRequestError("Name %s is already assigned to %s; include that address in the batch with a replacement name" % (name, _hex(owner)))
def _symbol_name(value, field):
"""Reject native label truncation without altering the caller's name."""
value = _api_text(value, field)
if len(value.encode("utf-16-le")) // 2 > HOPPER_SYMBOL_NAME_UTF16_UNITS:
raise InvalidRequestError("%s exceeds Hopper's %s UTF-16 code-unit symbol-name limit" % (field, HOPPER_SYMBOL_NAME_UTF16_UNITS))
return value
def _name_matches(document, address, name):
observed = _segment(document, address).getNameAtAddress(address)
return observed == name or (not name and observed is None)
def _address(document, value=None):
"""Resolve hexadecimal addresses first, then fall back to Hopper symbol names."""
"""Keep explicit hexadecimal coordinates distinct from symbol names."""
if value is None:
return document.getCurrentAddress()
if not isinstance(value, str):
raise InvalidRequestError("Address must be a string")
try:
return int(value, 16)
except ValueError:
result = document.getAddressForName(value)
if result in BAD_ADDRESSES:
raise InvalidRequestError("Unknown Hopper address or name")
return result
_api_text(value, "Address")
if value.lower().startswith("0x"):
try:
address = int(value, 16)
except ValueError as error:
raise InvalidRequestError("Invalid hexadecimal Hopper address: %s" % value) from error
else:
# Names such as `add` and `face` are valid hexadecimal strings too.
# Prefer an observed symbol, retaining bare-hex compatibility only
# when Hopper has no symbol with the supplied name.
address = document.getAddressForName(value)
if address in BAD_ADDRESSES:
try:
address = int(value, 16)
except ValueError as error:
raise InvalidRequestError("Unknown Hopper address or name: %s" % value) from error
if not 0 <= address < 0xFFFFFFFFFFFFFFFF:
raise InvalidRequestError("Address is outside Hopper's usable unsigned 64-bit range: %s" % value)
return address
def _segment(document, address):
@@ -249,14 +294,18 @@ def _procedure_identity(procedure):
def _procedure_locals(procedure):
"""Project opaque Hopper local-variable objects into an exact public shape."""
return [
{
"description": str(local),
"""Preserve public local-variable names and observed stack displacements."""
result = []
for local in procedure.getLocalVariableList():
name = local.name()
displacement = local.displacement()
result.append({
"description": "%s (stack displacement %s)" % (name if name is not None else "Unnamed local", displacement),
"name": name,
"stack_displacement": str(displacement) if displacement is not None else None,
"provenance": "hopper-public-python-api",
}
for local in procedure.getLocalVariableList()
]
})
return result
def _containing_procedure(document, address):
@@ -267,26 +316,75 @@ def _containing_procedure(document, address):
return (procedure, None) if procedure is not None else (None, "not_in_procedure")
def _basic_block_end(procedure, block):
"""Normalize native block endpoints to an exclusive byte address."""
owner_at = getattr(procedure, "getBasicBlockAtAddress", None)
if not callable(owner_at):
raise CapabilityUnavailableError(
"Instruction enumeration requires Hopper basic-block ownership"
)
end = block.getEndingAddress()
# Hopper 6.1 returns the final instruction address, despite the Python
# documentation describing an exclusive end. Membership distinguishes
# that representation from an actual exclusive endpoint in other builds.
if owner_at(end) == block:
instruction = procedure.getSegment().getInstructionAtAddress(end)
if instruction is not None and instruction.getInstructionLength() > 0:
return end + instruction.getInstructionLength()
return end
def _block_instruction_addresses(procedure, block):
"""Walk either endpoint convention using Hopper's block ownership API.
Some Hopper builds return the final instruction start, despite the public
API documenting an exclusive end. Equality compares fresh native wrappers;
probing ownership also keeps an exclusive endpoint in the next block out.
"""
segment = procedure.getSegment()
address = block.getStartingAddress()
end = _basic_block_end(procedure, block)
while address < end:
if procedure.getBasicBlockAtAddress(address) != block:
break
instruction = segment.getInstructionAtAddress(address)
if instruction is None:
break
length = instruction.getInstructionLength()
if length <= 0 or address + length > end:
break
yield address
address += length
def _instruction_addresses(procedure):
result = []
seen = set()
segment = procedure.getSegment()
for block in procedure.basicBlockIterator():
address = block.getStartingAddress()
end = block.getEndingAddress()
while address < end and address not in seen:
for address in _block_instruction_addresses(procedure, block):
if address in seen:
continue
seen.add(address)
instruction = segment.getInstructionAtAddress(address)
if instruction is None:
break
result.append(address)
length = instruction.getInstructionLength()
if length <= 0:
break
address += length
return result
def _native_calls(procedure, direction):
references = procedure.getAllCallees() if direction == "outgoing" else procedure.getAllCallers()
kinds = {0: "none", 1: "unknown", 2: "direct", 3: "objective_c"}
calls = {}
unresolved = []
for reference in references:
source, target, kind = reference.fromAddress(), reference.toAddress(), reference.type()
if source in BAD_ADDRESSES:
continue
if target in BAD_ADDRESSES:
unresolved.append({"address": _hex(source), "reason": "Native CallReference has no resolved target (type %s)" % kind})
continue
calls[(source, target)] = {"classification": kinds.get(kind, "unknown"), "provider_type": kind, "provenance": "hopper-public-python-api:CallReference"}
return calls, sorted(unresolved, key=lambda item: int(item["address"], 16))
def _procedure_references(document, params):
procedure = _procedure(document, params.get("procedure"))
direction = params.get("direction", "outgoing")
@@ -299,6 +397,8 @@ def _procedure_references(document, params):
references = segment.getReferencesFromAddress(address) if direction == "outgoing" else segment.getReferencesOfAddress(address)
for reference in references:
edges.add((address, reference) if direction == "outgoing" else (reference, address))
calls, unresolved = _native_calls(procedure, direction)
edges.update(calls)
ordered = sorted(edges)
items = []
for source, target in ordered:
@@ -309,16 +409,15 @@ def _procedure_references(document, params):
"target_address": _hex(target),
"source_procedure": _procedure_identity(source_procedure) if source_procedure is not None else None,
"target_procedure": _procedure_identity(target_procedure) if target_procedure is not None else None,
"kind": _unavailable("Hopper's public Python API does not classify reference kinds"),
"kind": _unavailable("Hopper exposes partial CallReference classification, but not detailed reference flags"),
**({"call": calls[(source, target)]} if (source, target) in calls else {}),
})
return {
"procedure": _procedure_identity(procedure), "direction": direction,
"reference_kinds_available": False,
# The public Hopper API returns observed references but does not expose
# enough flow metadata to enumerate calls with no resolved target.
# Keep the required list field explicit; the provider records this as
# unknown coverage rather than claiming the list is exhaustive.
"unresolved_calls": [],
# These are native CallReference objects, not proof that every unresolved
# dispatch site has been enumerated by Hopper.
"unresolved_calls": unresolved,
"references": items,
}
@@ -333,11 +432,61 @@ def _procedure_map(document):
def _strings(document):
result = {}
for segment in document.getSegmentsList():
for value, address in segment.getStringsList():
result[_hex(address)] = value
return result
return {address: record["value"] for address, record in _string_inventory(document).items()}
def _string_record(segment, address, display):
"""Read one native typed object, retaining its shortened display separately."""
length = segment.getObjectLength(address)
end = segment.getStartingAddress() + segment.getLength()
if isinstance(length, bool) or not isinstance(length, int) or length <= 0 or length > end - address:
raise CapabilityUnavailableError("Hopper reported an invalid string object extent at %s" % _hex(address))
raw = segment.readBytes(address, length)
if not isinstance(raw, (bytes, bytearray)) or len(raw) != length:
raise CapabilityUnavailableError("Hopper could not read the complete string object at %s" % _hex(address))
kind = segment.getTypeAtAddress(address)
encodings = ("utf-8", "latin-1") if kind == segment.TYPE_ASCII else ("utf-16-le", "utf-16-be") if kind == segment.TYPE_UNICODE else ()
# Native display escaping is not invertible (a literal backslash-n and a
# newline can render alike). Decode byte strings directly; for UTF-16,
# compare rendered candidates to establish an unambiguous byte order.
candidates = []
for encoding in encodings:
terminator = b"\x00\x00" if encoding.startswith("utf-16") else b"\x00"
terminated = raw.endswith(terminator)
payload = raw[:-len(terminator)] if terminated else raw
try:
value = payload.decode(encoding)
except UnicodeDecodeError:
continue
record = {"value": value, "provider_value": display, "string": {"encoding": encoding, "encoding_status": "inferred", "termination": "present_or_not_required" if terminated else "missing", "byte_length": length}}
if kind == segment.TYPE_ASCII:
return record
rendered = value.replace('"', '\\"').replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t")
if rendered == display or (display.endswith("\u2026") and display[:-1] and rendered.startswith(display[:-1])):
candidates.append(record)
if candidates and len({candidate["value"] for candidate in candidates}) == 1:
return candidates[0]
raise CapabilityUnavailableError("Hopper's string display cannot be reconciled with its typed bytes at %s; inspect the bytes and encoding explicitly" % _hex(address))
def _string_inventory(document, addresses=None):
key = (id(document), "string_objects")
objects = _search_inventory_cache.get(key)
if objects is None:
objects = {address: (segment, display) for segment in document.getSegmentsList() for display, address in segment.getStringsList()}
_search_inventory_cache[key] = objects
key = (id(document), "string_records")
records = _search_inventory_cache.setdefault(key, {})
selected = sorted(objects if addresses is None else objects.keys() & addresses)
for address in selected:
name = _hex(address)
if name not in records:
segment, display = objects[address]
try:
records[name] = _string_record(segment, address, display)
except CapabilityUnavailableError as error:
records[name] = {"value": display, "provider_value": display, "decoding": _unavailable(str(error))}
return {_hex(address): records[_hex(address)] for address in selected}
def _invalidate_search_inventory(document):
@@ -397,17 +546,18 @@ def _search_results(document, kind, params):
needle = pattern if case_sensitive else pattern.casefold()
matches = lambda value: needle in (value if case_sensitive else value.casefold())
else:
try:
expression = re.compile(pattern, 0 if case_sensitive else re.IGNORECASE)
except (re.error, OverflowError) as error:
raise InvalidRequestError("Invalid regex pattern") from error
matches = lambda value: expression.search(value) is not None
raise CapabilityUnavailableError("Regex matching requires REA's supervised worker; the native bridge only executes literal searches")
selected = []
for item in _search_inventory(document, kind):
if not matches(item[1]):
continue
selected.append(item)
if not selected:
return []
if kind == "string":
records = _string_inventory(document)
return [{"address": address, **records[address]} for address, _ in selected]
return [
{
"address": address,
@@ -450,25 +600,11 @@ def _render_instruction(segment, address):
def _assembly(procedure):
"""Render assembly while guarding against malformed instruction cycles."""
lines = []
segment = procedure.getSegment()
seen = set()
for block in procedure.basicBlockIterator():
address = block.getStartingAddress()
end = block.getEndingAddress()
while address < end and address not in seen:
seen.add(address)
instruction = segment.getInstructionAtAddress(address)
if instruction is None:
break
line = _render_instruction(segment, address)
if line is not None:
lines.append(line)
length = instruction.getInstructionLength()
if length <= 0:
break
address += length
return "\n".join(lines)
return "\n".join(
line for address in _instruction_addresses(procedure)
if (line := _render_instruction(segment, address)) is not None
)
def _read_function_instructions(document, params):
@@ -505,7 +641,7 @@ def _analyze_function(document, params):
successors.append(_hex(successor))
blocks.append({
"start": _hex(block.getStartingAddress()),
"end": _hex(block.getEndingAddress()),
"end": _hex(_basic_block_end(procedure, block)),
"successors": sorted(set(successors), key=lambda value: int(value, 16)),
})
pseudo = _pseudocode(document, procedure) or ""
@@ -529,6 +665,10 @@ def _analyze_function(document, params):
incoming = []
outgoing = []
procedure_addresses = set(addresses)
outgoing_calls, unresolved_calls = _native_calls(procedure, "outgoing")
incoming_calls, _ = _native_calls(procedure, "incoming")
calls = {**incoming_calls, **outgoing_calls}
edges.update(calls)
for source, target in sorted(edges):
source_procedure, _ = _containing_procedure(document, source)
target_procedure, _ = _containing_procedure(document, target)
@@ -537,16 +677,14 @@ def _analyze_function(document, params):
"target_address": _hex(target),
"source_procedure": _procedure_identity(source_procedure) if source_procedure is not None else None,
"target_procedure": _procedure_identity(target_procedure) if target_procedure is not None else None,
"kind": _unavailable("Hopper's public Python API does not classify reference kinds"),
"kind": _unavailable("Hopper exposes partial CallReference classification, but not detailed reference flags"),
**({"call": calls[(source, target)]} if (source, target) in calls else {}),
}
if target in procedure_addresses and source not in procedure_addresses:
incoming.append(item)
if source in procedure_addresses:
outgoing.append(item)
string_map = {
int(address, 16): value
for address, value in _search_inventory(document, "string")
}
string_map = {int(address, 16): record for address, record in _string_inventory(document, {int(edge["target_address"], 16) for edge in outgoing}).items()}
name_map = {
int(address, 16): value
for address, value in _search_inventory(document, "name")
@@ -556,7 +694,7 @@ def _analyze_function(document, params):
for edge in outgoing:
target = int(edge["target_address"], 16)
if target in string_map:
referenced_strings.append({"address": edge["target_address"], "value": string_map[target], "source_address": edge["source_address"]})
referenced_strings.append({"address": edge["target_address"], **string_map[target], "source_address": edge["source_address"]})
if target in name_map:
referenced_names.append({"address": edge["target_address"], "value": name_map[target], "source_address": edge["source_address"]})
comments.sort(key=lambda item: (int(item["address"], 16), item["kind"]))
@@ -574,13 +712,16 @@ def _analyze_function(document, params):
"callers": callers, "callees": callees,
"incoming_references": incoming,
"outgoing_references": outgoing,
"unresolved_calls": unresolved_calls,
"referenced_strings": referenced_strings,
"referenced_names": referenced_names,
"basic_blocks": blocks,
"native_api": None,
"native_value_flow": None,
"limitations": [
"Hopper's public Python API does not classify reference kinds.",
"Native CallReference classifications are observed where available; detailed reference flags remain unknown.",
"Hopper's public Python API does not expose equivalent external or thunk classification in this dossier.",
"Unresolved indirect calls without reported target addresses are not represented as call edges.",
"Native calls without resolved target addresses are not represented as edges; enumeration beyond reported CallReference objects is unknown.",
"Pseudocode and assembly are provider-specific representations, not original source.",
],
}
@@ -588,7 +729,6 @@ def _analyze_function(document, params):
def _dispatch(method, params):
"""Dispatch only the closed operation set implemented by REA's public tools."""
global _selected_document
if method == "health":
return {"name": "REA Hopper bridge", "version": "1.0.0", "run_id": REA_RUN_ID}
if method in ("shutdown", "shutdown_document"):
@@ -622,14 +762,9 @@ def _dispatch(method, params):
"document_closed": document_closed,
}
if method == "list_documents":
return [document.getDocumentName() for document in Document.getAllDocuments()]
return [document.getDocumentName() for document in _api().documents()]
if method == "current_document":
return _document().getDocumentName()
if method == "set_current_document":
document = _document(params.get("document"))
_selected_document = document.getDocumentName()
return _selected_document
document = _document(params.get("document"))
if method in EXHAUSTIVE_ANALYSIS_METHODS:
_api().require_analysis_complete(document, method)
@@ -650,10 +785,17 @@ def _dispatch(method, params):
"Hopper's public Python API does not expose readBytes"
)
address = _address(document, params.get("address"))
value = reader(address, length)
segment = _segment(document, address)
# Document.readBytes delegates to one Segment and returns False when
# the requested range crosses its end. Preserve the readable prefix.
available = segment.getStartingAddress() + segment.getLength() - address
value = reader(address, min(length, available))
if value is False or value is None:
raise InvalidRequestError("Hopper could not read the requested byte range at %s" % _hex(address))
if not isinstance(value, (bytes, bytearray)):
raise CapabilityUnavailableError(
"Hopper's public Python API returned an unsupported byte representation"
"Hopper readBytes returned %s for the requested %s-byte range at %s"
% (type(value).__name__, length, _hex(address))
)
data = bytes(value)
return {
@@ -678,7 +820,26 @@ def _dispatch(method, params):
or offset < 0
):
raise InvalidRequestError("Address has no authoritative file-offset mapping")
return {"address": _hex(address), "file_offset": offset}
inverse = getattr(document, "getAddressFromFileOffset", None)
if not callable(inverse):
raise CapabilityUnavailableError(
"Hopper's public Python API cannot verify the file-offset mapping by reverse lookup"
)
# Synthetic memory can report offset zero, which belongs to the actual
# file header. An integer alone does not prove source-file provenance.
if inverse(offset) != address:
raise InvalidRequestError("Address has no authoritative file-offset mapping: reverse lookup disagrees at %s" % _hex(address))
if offset > 9007199254740991:
raise CapabilityUnavailableError("Provider file offset exceeds the exact JSON integer range")
header_address = inverse(0)
reader = getattr(document, "readBytes", None)
header = reader(header_address, 12) if header_address not in BAD_ADDRESSES and document.getSegmentAtAddress(header_address) is not None and callable(reader) else None
return {
"address": _hex(address),
"provider_file_offset": offset,
"provider_source_path": document.getExecutableFilePath(),
"provider_image_header_hex": bytes(header).hex() if isinstance(header, (bytes, bytearray)) and len(header) == 12 else None,
}
if method == "resolve_containing_procedure":
address = _address(document, params.get("address"))
procedure, reason = _containing_procedure(document, address)
@@ -694,8 +855,13 @@ def _dispatch(method, params):
return _procedure_name(_procedure(document))
if method == "goto_address":
address = _address(document, params.get("address"))
segment = _segment(document, address)
expected = segment.getInstructionStart(address)
document.moveCursorAtAddress(address)
return _hex(address)
observed = document.getCurrentAddress()
if observed != (address if expected in BAD_ADDRESSES else expected):
raise InvalidRequestError("Hopper cursor did not reach the requested object at %s; observed %s" % (_hex(address), _hex(observed)))
return _hex(observed)
if method in ("address_name", "comment", "inline_comment", "xrefs"):
target = _address(document, params.get("address"))
segment = _segment(document, target)
@@ -708,12 +874,22 @@ def _dispatch(method, params):
return [_hex(value) for value in segment.getReferencesOfAddress(target)]
if method in ("next_address", "prev_address"):
target = _address(document, params.get("address"))
segment = _segment(document, target)
if method == "next_address":
result = target + max(1, document.getObjectLength(target))
start = segment.getInstructionStart(target)
if start in BAD_ADDRESSES:
raise InvalidRequestError("No analyzed object exists at the requested address")
length = segment.getObjectLength(start)
if length in BAD_ADDRESSES or length <= 0:
raise InvalidRequestError("No next analyzed object exists at the requested address")
result = start + length
else:
result = document.getInstructionStart(max(0, target - 1))
if result in BAD_ADDRESSES:
raise InvalidRequestError("No adjacent address")
previous_segment = document.getSegmentAtAddress(target - 1) if target > 0 else None
if previous_segment is None:
raise InvalidRequestError("No previous address exists in mapped memory")
result = previous_segment.getInstructionStart(target - 1)
if result in BAD_ADDRESSES or document.getSegmentAtAddress(result) is None:
raise InvalidRequestError("No adjacent analyzed object exists in mapped memory")
return _hex(result)
if method == "list_segments":
result = []
@@ -747,12 +923,9 @@ def _dispatch(method, params):
if method == "list_procedures":
return [{"address": address, "value": value} for address, value in _search_inventory(document, "procedure")]
if method == "list_strings":
values = dict(_search_inventory(document, "string"))
requested = params.get("address")
if requested is not None:
key = _hex(_address(document, requested))
values = {key: values[key]} if key in values else {}
return [{"address": address, "value": value} for address, value in values.items()]
values = _string_inventory(document, None if requested is None else {_address(document, requested)})
return [{"address": address, **record} for address, record in values.items()]
if method == "list_names":
result = dict(_search_inventory(document, "name"))
requested = params.get("address")
@@ -777,7 +950,7 @@ def _dispatch(method, params):
return sorted((_hex(item.getEntryPoint()) for item in procedure.getAllCalleeProcedures()), key=lambda value: int(value, 16))
if method == "procedure_info":
blocks = list(procedure.basicBlockIterator())
length = sum(max(0, block.getEndingAddress() - block.getStartingAddress()) for block in blocks)
length = sum(max(0, _basic_block_end(procedure, block) - block.getStartingAddress()) for block in blocks)
return {
"name": _procedure_name(procedure),
"entrypoint": _hex(procedure.getEntryPoint()),
@@ -790,35 +963,51 @@ def _dispatch(method, params):
}
if method == "set_address_name":
address = _address(document, params.get("address"))
name = _symbol_name(params["name"], "Name")
_validate_name_targets(document, [(params.get("address"), address, name)])
try:
result = document.setNameAtAddress(address, params["name"])
result = document.setNameAtAddress(address, name)
finally:
_invalidate_search_inventory(document)
_invalidate_pseudocode(document)
return result
return bool(result) and _name_matches(document, address, name)
if method == "set_addresses_names":
# Validate all destinations before applying any annotation. A malformed
# later address must not discard the result of an earlier mutation.
names = [(key, _address(document, key), _symbol_name(value, "Name for %s" % key)) for key, value in params["names"].items()]
_validate_name_targets(document, names)
try:
result = {key: document.setNameAtAddress(_address(document, key), value) for key, value in params["names"].items()}
result = {key: document.setNameAtAddress(address, value) for key, address, value in names}
finally:
_invalidate_search_inventory(document)
_invalidate_pseudocode(document)
return result
return {key: bool(result[key]) and _name_matches(document, address, value) for key, address, value in names}
if method in ("set_comment", "set_inline_comment"):
address = _address(document, params.get("address"))
comment = _api_text(params["comment"], "Comment")
segment = _segment(document, address)
setter = segment.setCommentAtAddress if method == "set_comment" else segment.setInlineCommentAtAddress
getter = segment.getCommentAtAddress if method == "set_comment" else segment.getInlineCommentAtAddress
setter(address, params["comment"])
setter(address, comment)
_invalidate_pseudocode(document)
return getter(address) == params["comment"]
observed = getter(address)
return observed == comment or (comment == "" and observed is None)
if method == "list_bookmarks":
return [{"address": _hex(item), "name": document.getBookmarkName(item)} for item in document.getBookmarks()]
if method == "set_bookmark":
address = _address(document, params.get("address"))
document.setBookmarkAtAddress(address, params.get("name"))
_segment(document, address)
name = params.get("name")
if name is not None:
_api_text(name, "Bookmark name")
document.setBookmarkAtAddress(address, name)
return document.hasBookmarkAtAddress(address)
if method == "unset_bookmark":
address = _address(document, params.get("address"))
# Permit removing a legacy orphan bookmark, but do not report success
# for an unmapped address with no bookmark to remove.
if not document.hasBookmarkAtAddress(address):
_segment(document, address)
document.removeBookmarkAtAddress(address)
return not document.hasBookmarkAtAddress(address)
raise InvalidRequestError("Unknown bridge method")
@@ -913,14 +1102,14 @@ def _diagnostic_type(error):
def _safe_diagnostic(error):
"""Project one exception without retaining provider or credential text."""
"""Preserve bridge validation reasons while excluding transport credentials."""
diagnostic_type = _diagnostic_type(error)
if diagnostic_type == "capability_unavailable":
message = str(error)
elif diagnostic_type == "authorization":
message = "Invalid bridge capability"
elif diagnostic_type == "invalid_request":
message = "Invalid Hopper bridge request"
message = str(error)
else:
message = "%s: Hopper bridge operation failed" % type(error).__name__
return {"code": -32000, "message": message, "type": diagnostic_type}
+630 -94
View File
@@ -3,12 +3,18 @@
REA imports this module into `lldb --batch` and runs `rea_trace <config.json>`.
It launches one owned process, stops at the requested functions and
Objective-C methods, records each entry from registers and memory reads only,
continues, and kills the process once it exits, the event limit is reached or
the duration elapses. No expression is evaluated and no target code runs on
the tracer's behalf. The result is written as JSON to the configured path.
continues, and kills the process once it exits, the event or aggregate resource
limit is reached, or the duration elapses. Target output is drained through
bounded FIFOs. No expression is evaluated and no target code runs on the
tracer's behalf. The result is written as JSON to the configured path.
"""
import errno
import hashlib
import json
import os
import select
import threading
import time
import lldb
@@ -22,9 +28,218 @@ ARGUMENT_REGISTERS = {
MAX_SELECTOR_BYTES = 1024
MAX_REPORTED_LOCATIONS = 64
MAX_OTHER_STOPS = 256
MAX_TRACE_BYTES = 8 * 1024 * 1024
MAX_TRACE_FRAMES = 65_536
MAX_OBSERVATION_JOURNAL_BYTES = MAX_TRACE_BYTES
MAX_BREAKPOINT_LOCATION_BYTES = 8 * 1024 * 1024
MAX_TARGET_OUTPUT_BYTES = 1024 * 1024
OUTPUT_DRAIN_BYTES_PER_PASS = 1024 * 1024
OUTPUT_EOF_WAIT_SECONDS = 1.0
OUTPUT_READER_JOIN_SECONDS = 0.5
LISTENER_NAME = "rea-native-call-observation"
def _can_retain_trace(current_bytes, current_frames, event_bytes, event_frames):
"""Whether a complete event fits both aggregate trace budgets."""
return (
current_bytes + event_bytes <= MAX_TRACE_BYTES
and current_frames + event_frames <= MAX_TRACE_FRAMES
)
def _estimated_json_size(value):
"""Estimate JSON size without encoding potentially oversized values."""
if isinstance(value, str):
# json.dumps defaults to ensure_ascii=True; supplementary characters
# can become two six-byte Unicode escapes.
return len(value) * 12 + 2
if value is None or isinstance(value, (bool, int, float)):
return 32
if isinstance(value, dict):
return 2 + sum(
len(key) * 6 + 4 + _estimated_json_size(item)
for key, item in value.items()
)
if isinstance(value, (list, tuple)):
return 2 + sum(_estimated_json_size(item) + 1 for item in value)
return 64
def _fits_trace_budget(value, remaining_bytes):
return _estimated_json_size(value) <= remaining_bytes
class _ObservationJournal:
"""Flush a bounded JSONL prefix so observations survive tracer failure."""
def __init__(self, handle, max_bytes=MAX_OBSERVATION_JOURNAL_BYTES):
self.handle = handle
self.max_bytes = max_bytes
self.bytes = 0
def append(self, record):
encoded = (json.dumps(record) + "\n").encode("utf-8")
if self.bytes + len(encoded) > self.max_bytes:
return False
self.handle.write(encoded)
self.handle.flush()
self.bytes += len(encoded)
return True
def _set_launch_flags(launch):
launch.SetLaunchFlags(
launch.GetLaunchFlags()
| lldb.eLaunchFlagDebug
| lldb.eLaunchFlagStopAtEntry
)
def _hash_file(path):
digest = hashlib.sha256()
with open(path, "rb") as target_file:
while True:
chunk = target_file.read(1024 * 1024)
if not chunk:
break
digest.update(chunk)
return digest.hexdigest()
def _file_identity(path):
info = os.stat(path)
return str(info.st_dev), str(info.st_ino)
def _module_identity(target):
module = target.FindModule(target.GetExecutable())
if not module.IsValid():
return None, None, None
spec = module.GetFileSpec()
path = str(spec) if spec.IsValid() else None
identity = None
if path:
try:
identity = _file_identity(path)
except OSError:
pass
return path, identity, module.GetUUIDString() or None
def _wait_for_identity_ack(config):
"""Hold the target at entry while the host adapter captures its start identity."""
path = config.get("identity_ack_path")
if not path:
return
while True:
try:
with open(path, "r") as handle:
return handle.read(32).strip()
except FileNotFoundError:
time.sleep(0.025)
class _OutputPipe:
"""Drain a target FIFO while retaining only its bounded output prefix."""
def __init__(self, fifo_path, capture_path, max_bytes):
os.mkfifo(fifo_path, 0o600)
self.path = fifo_path
try:
self.fd = os.open(fifo_path, os.O_RDONLY | os.O_NONBLOCK)
except Exception:
os.unlink(fifo_path)
raise
try:
self.capture = open(capture_path, "wb")
except Exception:
os.close(self.fd)
os.unlink(fifo_path)
raise
self.max_bytes = max_bytes
self.bytes = 0
self.truncated = False
self.closed = False
self.stop_reader = threading.Event()
self.reader_thread = None
self.reader_error = None
self.launched = False
self.eof = threading.Event()
self.complete = False
def start(self):
if self.reader_thread is None:
self.reader_thread = threading.Thread(target=self._reader_loop, daemon=True)
self.reader_thread.start()
def _reader_loop(self):
try:
while not self.stop_reader.is_set():
readable, _, _ = select.select([self.fd], [], [], 0.05)
if not readable:
continue
if self.drain(OUTPUT_DRAIN_BYTES_PER_PASS) == 0:
# A FIFO read end is readable at EOF before the target opens it.
time.sleep(0.01)
except Exception as error:
self.reader_error = error
self.stop_reader.set()
def mark_launched(self):
self.launched = True
def drain(self, max_bytes=OUTPUT_DRAIN_BYTES_PER_PASS):
consumed = 0
while consumed < max_bytes:
try:
chunk = os.read(self.fd, min(65_536, max_bytes - consumed))
except OSError as error:
if error.errno in (errno.EAGAIN, errno.EWOULDBLOCK):
return consumed
raise
if not chunk:
if self.launched:
self.eof.set()
return consumed
consumed += len(chunk)
self.bytes += len(chunk)
remaining = max(0, self.max_bytes - self.capture.tell())
if remaining:
self.capture.write(chunk[:remaining])
if len(chunk) > remaining:
self.truncated = True
def close(self, expected_exit=False):
if self.closed:
return
if expected_exit and self.launched:
self.eof.wait(OUTPUT_EOF_WAIT_SECONDS)
self.stop_reader.set()
if self.reader_thread is not None:
self.reader_thread.join(OUTPUT_READER_JOIN_SECONDS)
stopped = self.reader_thread is None or not self.reader_thread.is_alive()
if stopped:
try:
self.drain(OUTPUT_DRAIN_BYTES_PER_PASS)
finally:
try:
self.capture.close()
finally:
os.close(self.fd)
self.closed = True
else:
# A daemon reader may still be unwinding a blocked filesystem write.
# Leave its handles alone rather than racing that thread at shutdown.
self.closed = True
self.complete = bool(
stopped
and (not self.launched or (expected_exit and self.eof.is_set()))
and self.reader_error is None
)
if not self.complete:
self.truncated = True
def _hex(value):
return "0x%x" % value
@@ -34,7 +249,7 @@ def _location(address, target):
module = address.GetModule()
symbol = address.GetSymbol()
file_address = address.GetFileAddress()
return {
location = {
"load_address": _hex(address.GetLoadAddress(target)),
"file_address": None
if file_address == lldb.LLDB_INVALID_ADDRESS
@@ -43,6 +258,7 @@ def _location(address, target):
"module_path": str(module.GetFileSpec()) if module.IsValid() else None,
"symbol": symbol.GetName() if symbol.IsValid() else None,
}
return location
def _no_files():
@@ -107,33 +323,54 @@ def _wanted(spec, symbol):
return symbol.startswith("-[" if method_type == "instance" else "+[")
def _record(context, thread, index, sequence):
def _read_register(frame, name):
error = lldb.SBError()
value = frame.FindRegister(name)
if not value.IsValid():
raise RuntimeError("LLDB breakpoint register %s is unavailable" % name)
number = value.GetValueAsUnsigned(error)
if error.Fail():
raise RuntimeError(
"LLDB breakpoint register %s could not be read: %s" % (name, error)
)
return number
def _record(context, thread, frame, index, sequence, location, remaining_bytes):
target, process, config = context["target"], context["process"], context["config"]
frame = thread.GetFrameAtIndex(0)
location = _location(frame.GetPCAddress(), target)
symbol = location["symbol"] or ""
if not _wanted(config["breakpoints"][index], symbol):
return None
names = ARGUMENT_REGISTERS.get(config["architecture"], [])
objc_method = symbol.startswith("-[") or symbol.startswith("+[")
values = {
name: _read_register(frame, name)
for name in names[: max(config["argument_registers"], 2 if objc_method else 0)]
}
registers = [
{"name": name, "value": _hex(frame.FindRegister(name).GetValueAsUnsigned())}
{"name": name, "value": _hex(values[name])}
for name in names[: config["argument_registers"]]
]
receiver_class = None
selector = None
if symbol.startswith("-[") or symbol.startswith("+["):
if objc_method:
error = lldb.SBError()
text = process.ReadCStringFromMemory(
frame.FindRegister(names[1]).GetValueAsUnsigned(),
values[names[1]],
MAX_SELECTOR_BYTES,
error,
)
selector = text if error.Success() and text else None
if symbol.startswith("-["):
receiver_class = _dynamic_class(
target, frame.FindRegister(names[0]).GetValueAsUnsigned()
)
frames = min(thread.GetNumFrames(), 1 + config["backtrace_frames"])
receiver_class = _dynamic_class(target, values[names[0]])
estimated_base = (
_estimated_json_size(location)
+ _estimated_json_size(receiver_class)
+ _estimated_json_size(selector)
+ 2048
)
if estimated_base > remaining_bytes:
raise ValueError("trace event exceeds aggregate byte budget")
record = {
"sequence": sequence,
"elapsed_ms": round((time.monotonic() - context["started"]) * 1000, 3),
@@ -142,55 +379,154 @@ def _record(context, thread, index, sequence):
"receiver_class": receiver_class,
"selector": selector,
"registers": registers,
"backtrace": [
_location(thread.GetFrameAtIndex(depth).GetPCAddress(), target)
for depth in range(1, frames)
],
"backtrace": [],
}
record.update(location)
return record
def _handle_stop(context, events, other_stops):
"""Record breakpoint hits of one stop; return an outcome when tracing must end."""
process = context["process"]
for thread in process:
reason = thread.GetStopReason()
if reason == lldb.eStopReasonBreakpoint:
index = context["breakpoint_index"].get(thread.GetStopReasonDataAtIndex(0))
if index is None:
continue
record = _record(context, thread, index, len(events))
if record is not None:
events.append(record)
if len(events) >= context["config"]["max_events"]:
return "event-limit"
elif reason in (lldb.eStopReasonSignal, lldb.eStopReasonException):
other_stops.append(thread.GetStopDescription(256))
# One trace runs in each owned LLDB subprocess. Its callbacks execute at the
# breakpoint before LLDB resumes, unlike snapshots of later public stop events.
_TRACE_CONTEXT = None
def _handle_breakpoint(context, frame, index):
"""Read one hit while LLDB's breakpoint callback owns the stopped frame."""
if not frame.IsValid() or frame.GetPC() == lldb.LLDB_INVALID_ADDRESS:
raise RuntimeError("LLDB breakpoint callback did not supply a readable frame")
thread = frame.GetThread()
events = context["events"]
location = _location(frame.GetPCAddress(), context["target"])
symbol = location["symbol"] or ""
if not _wanted(context["config"]["breakpoints"][index], symbol):
return None
frame_count = max(
0,
min(thread.GetNumFrames() - 1, context["config"]["backtrace_frames"]),
)
event_frame_count = 1 + frame_count
if not _can_retain_trace(
context["retained_trace_bytes"],
context["retained_frames"],
0,
event_frame_count,
):
return "resource-limit"
try:
remaining_bytes = MAX_TRACE_BYTES - context["retained_trace_bytes"]
record = _record(
context, thread, frame, index, len(events), location, remaining_bytes
)
except ValueError:
return "resource-limit"
if record is not None:
if not _fits_trace_budget(record, remaining_bytes):
return "resource-limit"
record_bytes = len(json.dumps(record).encode("utf-8"))
if context["retained_trace_bytes"] + record_bytes > MAX_TRACE_BYTES:
return "resource-limit"
for depth in range(1, frame_count + 1):
try:
location = _location(
thread.GetFrameAtIndex(depth).GetPCAddress(), context["target"]
)
except ValueError:
return "resource-limit"
if (
_estimated_json_size(location) + record_bytes + 1
> MAX_TRACE_BYTES - context["retained_trace_bytes"]
):
return "resource-limit"
location_bytes = len(json.dumps(location).encode("utf-8"))
addition = location_bytes + (1 if record["backtrace"] else 0)
if (
context["retained_trace_bytes"]
+ record_bytes
+ addition
> MAX_TRACE_BYTES
):
return "resource-limit"
record["backtrace"].append(location)
record_bytes += addition
journal = context.get("observation_journal")
if journal is not None and not journal.append(
{"kind": "event", "event": record}
):
return "resource-limit"
events.append(record)
context["retained_frames"] += event_frame_count
context["retained_trace_bytes"] += record_bytes
if len(events) >= context["config"]["max_events"]:
return "event-limit"
return None
def breakpoint_hit(frame, location, internal_dict):
"""LLDB callback: capture before resuming, and stop on a limit or failure."""
context = _TRACE_CONTEXT
if context is None or context["outcome"] is not None or context["failure"] is not None:
return True
try:
index = context["breakpoint_index"][location.GetBreakpoint().GetID()]
context["outcome"] = _handle_breakpoint(context, frame, index)
except Exception as error:
context["failure"] = "%s: %s" % (type(error).__name__, error)
return True
return context["outcome"] is not None
def _handle_stop(context, other_stops):
"""Retain non-breakpoint stop observations; callbacks already capture hits."""
for thread in context["process"]:
if thread.GetStopReason() in (lldb.eStopReasonSignal, lldb.eStopReasonException):
stop_description = thread.GetStopDescription(256)
journal = context.get("observation_journal")
if journal is not None and not journal.append(
{"kind": "other-stop", "reason": stop_description}
):
return "resource-limit"
other_stops.append(stop_description)
if len(other_stops) >= MAX_OTHER_STOPS:
return "stop-limit"
return None
def _breakpoint_report(target, created):
def _breakpoint_report(target, created, config):
report = []
retained_location_bytes = 0
locations_truncated = False
for index, breakpoints in enumerate(created):
locations = []
count = 0
for breakpoint in breakpoints:
count += breakpoint.GetNumLocations()
for position in range(breakpoint.GetNumLocations()):
address = breakpoint.GetLocationAtIndex(position).GetAddress()
location = _location(address, target)
if not _wanted(config["breakpoints"][index], location["symbol"] or ""):
continue
count += 1
if len(locations) < MAX_REPORTED_LOCATIONS:
locations.append(
_location(breakpoint.GetLocationAtIndex(position).GetAddress(), target)
remaining_bytes = (
MAX_BREAKPOINT_LOCATION_BYTES - retained_location_bytes
)
if not _fits_trace_budget(location, remaining_bytes):
locations_truncated = True
continue
location_bytes = len(json.dumps(location).encode("utf-8"))
addition = location_bytes + (1 if locations else 0)
if addition > remaining_bytes:
locations_truncated = True
continue
locations.append(location)
retained_location_bytes += addition
report.append({"index": index, "location_count": count, "locations": locations})
return report
return report, locations_truncated
def _launch_info(target, config, listener):
launch = lldb.SBLaunchInfo(config["arguments"])
launch.SetListener(listener)
_set_launch_flags(launch)
environment = target.GetEnvironment()
for key, value in config["environment"].items():
environment.Set(key, value, True)
@@ -210,81 +546,281 @@ def _wait_for_exit(listener, process, seconds):
listener.WaitForEvent(1, event)
def _failed_launch_description(process):
if process.GetState() != lldb.eStateExited or process.GetExitStatus() != -1:
return None
description = process.GetExitDescription()
if isinstance(description, str) and description.lower().startswith(("attach failed", "launch failed")):
return description
return None
def trace(debugger, config):
global _TRACE_CONTEXT
debugger.SetAsync(True)
# Stop at the symbol itself, where argument registers still hold the ABI
# arguments, even when line tables would let LLDB skip the prologue.
lldb.SBDebugger.SetInternalVariable(
"target.skip-prologue", "false", debugger.GetInstanceName()
)
try:
before_digest = _hash_file(config["executable"])
before_identity = _file_identity(config["executable"])
except OSError as error:
return {"status": "target-integrity-error", "error": str(error)}
if before_digest != config["expected_sha256"]:
return {
"status": "target-integrity-error",
"error": "selected executable digest changed before LLDB target creation",
}
error = lldb.SBError()
target = debugger.CreateTarget(
config["executable"], config["architecture"], None, False, error
)
if not target.IsValid():
return {"status": "target-error", "error": error.GetCString()}
module_path_before, module_file_identity_before, module_uuid_before = (
_module_identity(target)
)
if (
module_file_identity_before is not None
and module_file_identity_before != before_identity
):
return {
"status": "target-integrity-error",
"error": "LLDB executable module resolved to a different pre-launch file identity",
}
created = [_create_breakpoints(target, spec) for spec in config["breakpoints"]]
breakpoint_index = {}
for index, breakpoints in enumerate(created):
for breakpoint in breakpoints:
breakpoint_index[breakpoint.GetID()] = index
listener = lldb.SBListener(LISTENER_NAME)
output_budget = config.get("max_output_bytes", MAX_TARGET_OUTPUT_BYTES)
stdout = _OutputPipe(
config["stdout_path"], config["stdout_capture_path"], output_budget
)
try:
stderr = _OutputPipe(
config["stderr_path"], config["stderr_capture_path"], output_budget
)
except Exception:
stdout.close()
raise
stdout.start()
stderr.start()
observation_journal = None
started = time.monotonic()
process = target.Launch(_launch_info(target, config, listener), error)
if not error.Success() or not process.IsValid():
return {"status": "launch-error", "error": error.GetCString()}
with open(config["pid_path"], "w") as handle:
handle.write(str(process.GetProcessID()))
context = {
"target": target,
"process": process,
"config": config,
"started": started,
"breakpoint_index": breakpoint_index,
}
events = []
other_stops = []
outcome = None
deadline = started + config["duration_ms"] / 1000
event = lldb.SBEvent()
while outcome is None:
if time.monotonic() >= deadline:
outcome = "duration-elapsed"
break
if not listener.WaitForEvent(1, event):
continue
if not lldb.SBProcess.EventIsProcessEvent(event):
continue
state = lldb.SBProcess.GetStateFromEvent(event)
if state == lldb.eStateExited:
outcome = "exited"
elif state == lldb.eStateStopped and not lldb.SBProcess.GetRestartedFromEvent(event):
outcome = _handle_stop(context, events, other_stops)
if outcome is None:
process.Continue()
pid = process.GetProcessID()
exit_status = None
exit_description = None
if outcome == "exited":
exit_status = process.GetExitStatus()
exit_description = process.GetExitDescription()
else:
process.Kill()
_wait_for_exit(listener, process, 5)
return {
"status": "traced",
"version": lldb.SBDebugger.GetVersionString().splitlines()[0],
"pid": pid,
"outcome": outcome,
"exit_status": exit_status,
"exit_description": exit_description,
"killed": outcome != "exited",
"terminated": process.GetState() == lldb.eStateExited,
"elapsed_ms": round((time.monotonic() - started) * 1000, 3),
"breakpoints": _breakpoint_report(target, created),
"events": events,
"other_stops": other_stops,
}
process = None
try:
observation_path = config.get("observation_path")
if observation_path:
observation_journal = _ObservationJournal(
open(observation_path, "wb")
)
process = target.Launch(_launch_info(target, config, listener), error)
if not error.Success() or not process.IsValid():
stdout.close()
stderr.close()
return {"status": "launch-error", "error": error.GetCString()}
launch_failure = _failed_launch_description(process)
if launch_failure is not None:
stdout.close(expected_exit=True)
stderr.close(expected_exit=True)
return {"status": "launch-error", "error": launch_failure}
stdout.mark_launched()
stderr.mark_launched()
# Publish the PID before any post-launch file or module inspection. The
# process is stopped at entry and remains there until identity_ack.
with open(config["pid_path"], "w") as handle:
handle.write(str(process.GetProcessID()))
identity_ack = _wait_for_identity_ack(config)
if identity_ack != "readable":
process.Kill()
_wait_for_exit(listener, process, 5)
expected_exit = process.GetState() == lldb.eStateExited
stdout.close(expected_exit=expected_exit)
stderr.close(expected_exit=expected_exit)
return {
"status": "target-identity-unavailable",
"error": "host could not establish the launched process identity; target was stopped",
}
try:
after_digest = _hash_file(config["executable"])
after_identity = _file_identity(config["executable"])
except OSError as identity_error:
process.Kill()
stdout.close(expected_exit=process.GetState() == lldb.eStateExited)
stderr.close(expected_exit=process.GetState() == lldb.eStateExited)
return {"status": "target-integrity-error", "error": str(identity_error)}
if after_digest != config["expected_sha256"] or after_identity != before_identity:
process.Kill()
_wait_for_exit(listener, process, 5)
stdout.close(expected_exit=process.GetState() == lldb.eStateExited)
stderr.close(expected_exit=process.GetState() == lldb.eStateExited)
return {
"status": "target-integrity-error",
"error": "selected executable digest or file identity changed during LLDB launch",
}
module_path_after, module_file_identity_after, module_uuid_after = (
_module_identity(target)
)
if (
module_file_identity_after is not None
and module_file_identity_after != before_identity
):
process.Kill()
_wait_for_exit(listener, process, 5)
stdout.close(expected_exit=process.GetState() == lldb.eStateExited)
stderr.close(expected_exit=process.GetState() == lldb.eStateExited)
return {
"status": "target-integrity-error",
"error": "LLDB executable module resolved to a different file identity",
}
if (
module_uuid_before is not None
and module_uuid_after is not None
and module_uuid_before != module_uuid_after
):
process.Kill()
_wait_for_exit(listener, process, 5)
stdout.close(expected_exit=process.GetState() == lldb.eStateExited)
stderr.close(expected_exit=process.GetState() == lldb.eStateExited)
return {
"status": "target-integrity-error",
"error": "LLDB executable module identity changed during launch",
}
context = {
"target": target,
"process": process,
"config": config,
"started": started,
"breakpoint_index": breakpoint_index,
"retained_frames": 0,
"retained_trace_bytes": 0,
"observation_journal": observation_journal,
}
events = []
context.update({"events": events, "outcome": None, "failure": None})
_TRACE_CONTEXT = context
for breakpoints in created:
for breakpoint in breakpoints:
breakpoint.SetScriptCallbackFunction("rea_lldb_tracer.breakpoint_hit")
other_stops = []
outcome = None
deadline = started + config["duration_ms"] / 1000
event = lldb.SBEvent()
while outcome is None:
if stdout.reader_error is not None:
raise RuntimeError("stdout capture failed: %s" % stdout.reader_error)
if stderr.reader_error is not None:
raise RuntimeError("stderr capture failed: %s" % stderr.reader_error)
if time.monotonic() >= deadline:
outcome = "duration-elapsed"
break
if not listener.WaitForEvent(1, event):
continue
if not lldb.SBProcess.EventIsProcessEvent(event):
continue
state = lldb.SBProcess.GetStateFromEvent(event)
if state == lldb.eStateExited:
outcome = "exited"
elif state == lldb.eStateStopped and not lldb.SBProcess.GetRestartedFromEvent(event):
if context["failure"] is not None:
raise RuntimeError(context["failure"])
outcome = context["outcome"] or _handle_stop(context, other_stops)
if outcome is None:
process.Continue()
pid = process.GetProcessID()
exit_status = None
exit_description = None
if outcome == "exited":
exit_status = process.GetExitStatus()
exit_description = process.GetExitDescription()
else:
process.Kill()
_wait_for_exit(listener, process, 5)
process_exited = process.GetState() == lldb.eStateExited
stdout.close(expected_exit=process_exited)
stderr.close(expected_exit=process_exited)
# SBTarget.Launch may succeed before debugserver reports an asynchronous
# attach failure as an exited SBProcess. Its -1 status is not a target
# exit code; preserve the debugger's concrete launch denial.
launch_failure = _failed_launch_description(process)
if launch_failure is not None:
return {"status": "launch-error", "error": launch_failure}
launch_identity_stable = (
module_path_before is not None
and module_path_after == module_path_before
and module_file_identity_before == before_identity
and module_file_identity_after == module_file_identity_before
and module_uuid_before is not None
and module_uuid_after == module_uuid_before
)
breakpoint_report, breakpoint_locations_truncated = _breakpoint_report(
target, created, config
)
return {
"status": "traced",
"version": lldb.SBDebugger.GetVersionString().splitlines()[0],
"pid": pid,
"outcome": outcome,
"exit_status": exit_status,
"exit_description": exit_description,
"killed": outcome != "exited",
"terminated": process.GetState() == lldb.eStateExited,
"elapsed_ms": round((time.monotonic() - started) * 1000, 3),
"breakpoints": breakpoint_report,
"breakpoint_locations_truncated": breakpoint_locations_truncated,
"events": events,
"resource_limit_reached": outcome == "resource-limit",
"target_output": {
"stdout_bytes": stdout.bytes,
"stderr_bytes": stderr.bytes,
"stdout_truncated": stdout.truncated,
"stderr_truncated": stderr.truncated,
"stdout_complete": stdout.complete,
"stderr_complete": stderr.complete,
},
"target_identity": {
"selected_file_sha256": after_digest,
"loaded_image_sha256": None,
"file_device": after_identity[0],
"file_inode": after_identity[1],
"module_path": module_path_after,
"module_uuid": module_uuid_after,
# This records matching path/module identity observations. LLDB
# does not expose the exact mapped bytes, so it never proves a digest.
"stable": launch_identity_stable,
},
"other_stops": other_stops,
}
finally:
_TRACE_CONTEXT = None
if observation_journal is not None:
try:
observation_journal.handle.close()
except Exception:
pass
if process is not None:
try:
if process.IsValid() and process.GetState() != lldb.eStateExited:
process.Kill()
_wait_for_exit(listener, process, 5)
except Exception:
pass
for output_pipe in (stdout, stderr):
try:
output_pipe.close(
expected_exit=(
process is not None
and process.IsValid()
and process.GetState() == lldb.eStateExited
)
)
except Exception:
pass
def run(debugger, command, result, internal_dict):
+273
View File
@@ -0,0 +1,273 @@
"""Source-owned tests for the LLDB bridge's bounded retention helpers."""
from io import BytesIO
import importlib.util
import json
import os
import sys
import tempfile
import types
import unittest
fake_lldb = sys.modules.setdefault("lldb", types.ModuleType("lldb"))
fake_lldb.LLDB_INVALID_ADDRESS = -1
fake_lldb.eLaunchFlagDebug = 2
fake_lldb.eLaunchFlagStopAtEntry = 4
spec = importlib.util.spec_from_file_location(
"rea_lldb_tracer", os.path.join(os.path.dirname(__file__), "rea_lldb_tracer.py")
)
tracer = importlib.util.module_from_spec(spec)
spec.loader.exec_module(tracer)
class NativeTraceBudgetTests(unittest.TestCase):
def test_journal_checks_exact_byte_budget_before_writing(self):
record = {"kind": "other-stop", "reason": "signal"}
encoded_size = len((tracer.json.dumps(record) + "\n").encode("utf-8"))
stream = BytesIO()
journal = tracer._ObservationJournal(stream, max_bytes=encoded_size - 1)
self.assertFalse(journal.append(record))
self.assertEqual(stream.getvalue(), b"")
self.assertEqual(journal.bytes, 0)
def test_journal_appends_each_row_once_and_flushes_it(self):
class CountingStream(BytesIO):
writes = 0
flushes = 0
def write(self, value):
self.writes += 1
return super().write(value)
def flush(self):
self.flushes += 1
return super().flush()
stream = CountingStream()
journal = tracer._ObservationJournal(stream)
journal.append({"kind": "event", "event": {"sequence": 0}})
journal.append({"kind": "other-stop", "reason": "signal"})
self.assertEqual((stream.writes, stream.flushes), (2, 2))
self.assertEqual(journal.bytes, len(stream.getvalue()))
def test_aggregate_trace_budget_admits_exact_boundary_and_rejects_next_record(self):
self.assertTrue(
tracer._can_retain_trace(
tracer.MAX_TRACE_BYTES - 10,
tracer.MAX_TRACE_FRAMES - 2,
10,
2,
)
)
self.assertFalse(
tracer._can_retain_trace(
tracer.MAX_TRACE_BYTES - 10,
tracer.MAX_TRACE_FRAMES - 2,
11,
2,
)
)
self.assertFalse(
tracer._can_retain_trace(
tracer.MAX_TRACE_BYTES - 10,
tracer.MAX_TRACE_FRAMES - 2,
10,
3,
)
)
def test_oversized_producer_string_is_rejected_before_serialization(self):
self.assertTrue(tracer._fits_trace_budget("method", 1024))
self.assertFalse(tracer._fits_trace_budget("m" * 2048, 1024))
self.assertGreater(
tracer._estimated_json_size("🙂"), len('"🙂"'.encode("utf-8"))
)
def test_launch_flags_preserve_default_debug_and_stop_at_entry(self):
class Launch:
flags = 10
def GetLaunchFlags(self):
return self.flags
def SetLaunchFlags(self, flags):
self.flags = flags
launch = Launch()
tracer._set_launch_flags(launch)
self.assertEqual(launch.flags, 14)
def test_output_pipe_counts_all_bytes_and_keeps_only_the_prefix(self):
with tempfile.TemporaryDirectory() as directory:
fifo = os.path.join(directory, "stdout.fifo")
capture = os.path.join(directory, "stdout.capture")
sink = tracer._OutputPipe(fifo, capture, 5)
sink.start()
sink.mark_launched()
writer = os.open(fifo, os.O_WRONLY)
try:
for index in range(100):
chunk = (b"hello world" if index == 0 else b"x" * 4096)
os.write(writer, chunk)
finally:
os.close(writer)
sink.drain()
sink.close(expected_exit=True)
with open(capture, "rb") as retained:
self.assertEqual(retained.read(), b"hello")
self.assertEqual(sink.bytes, 11 + 99 * 4096)
self.assertTrue(sink.truncated)
self.assertTrue(sink.complete)
def test_output_pipe_reports_incomplete_capture_after_unexpected_close(self):
with tempfile.TemporaryDirectory() as directory:
fifo = os.path.join(directory, "stdout.fifo")
capture = os.path.join(directory, "stdout.capture")
sink = tracer._OutputPipe(fifo, capture, 5)
sink.start()
sink.mark_launched()
sink.close(expected_exit=False)
self.assertFalse(sink.complete)
self.assertTrue(sink.truncated)
def test_selector_location_report_uses_the_requested_method_type(self):
class Symbol:
def IsValid(self):
return True
def GetName(self):
return "+[Greeter shared]"
class FileSpec:
def GetFilename(self):
return "Fixture"
def __str__(self):
return "/tmp/Fixture"
class Module:
def IsValid(self):
return True
def GetFileSpec(self):
return FileSpec()
class Address:
def GetModule(self):
return Module()
def GetSymbol(self):
return Symbol()
def GetFileAddress(self):
return 1
def GetLoadAddress(self, target):
return 2
class Location:
def GetAddress(self):
return Address()
class Breakpoint:
def GetNumLocations(self):
return 1
def GetLocationAtIndex(self, index):
return Location()
report, locations_truncated = tracer._breakpoint_report(
object(),
[[Breakpoint()]],
{
"breakpoints": [
{
"kind": "objc-method",
"selector": "shared",
"method_type": "instance",
}
]
},
)
self.assertEqual(report[0]["location_count"], 0)
self.assertEqual(report[0]["locations"], [])
self.assertFalse(locations_truncated)
def test_breakpoint_report_bounds_aggregate_location_json(self):
tracer.lldb.LLDB_INVALID_ADDRESS = -1
symbol_name = (
"-[VeryLongButPlausibleObjectiveCController "
"performTransactionWithRequestIdentifier:accountContext:"
"securityPolicy:completionHandler:]"
)
module_path = (
"/Applications/Enterprise Product.app/Contents/Frameworks/"
"EnterpriseSubsystem.framework/Versions/A/EnterpriseSubsystem"
)
class Symbol:
def IsValid(self):
return True
def GetName(self):
return symbol_name
class FileSpec:
def GetFilename(self):
return "EnterpriseSubsystem"
def __str__(self):
return module_path
class Module:
def IsValid(self):
return True
def GetFileSpec(self):
return FileSpec()
class Address:
def GetModule(self):
return Module()
def GetSymbol(self):
return Symbol()
def GetFileAddress(self):
return 0x123456789
def GetLoadAddress(self, target):
return 0x7123456789
class Location:
def GetAddress(self):
return Address()
class Breakpoint:
def GetNumLocations(self):
return 64
def GetLocationAtIndex(self, index):
return Location()
breakpoint_count = 1000
created = [[Breakpoint()] for _ in range(breakpoint_count)]
config = {"breakpoints": [{"kind": "objc-method"}] * breakpoint_count}
report, locations_truncated = tracer._breakpoint_report(
object(), created, config
)
retained_bytes = sum(
len(json.dumps(location).encode("utf-8"))
+ (1 if index > 0 else 0)
for row in report
for index, location in enumerate(row["locations"])
)
self.assertTrue(locations_truncated)
self.assertEqual(sum(row["location_count"] for row in report), 64_000)
self.assertLess(sum(len(row["locations"]) for row in report), 64_000)
self.assertLessEqual(retained_bytes, tracer.MAX_BREAKPOINT_LOCATION_BYTES)
if __name__ == "__main__":
unittest.main()
+8 -4
View File
@@ -152,7 +152,14 @@ private func readRunToken(pid: Int32, pointerSize: Int) -> RunTokenObservation {
}
bytes = Array(bytes.prefix(size))
do {
return RunTokenObservation(pid: pid, state: "readable", run_id: try token(in: bytes, pointerSize: pointerSize), reason: nil)
let runId = try token(in: bytes, pointerSize: pointerSize)
// A complete empty environment is readable for an ordinary image. Apple
// platform images can expose the same layout after the kernel withholds
// their environment, so they remain explicitly unverified without a token.
if runId == nil && isPlatformBinary(pid: pid) {
return unavailable(pid: pid, reason: "platform_binary_environment_withheld")
}
return RunTokenObservation(pid: pid, state: "readable", run_id: runId, reason: nil)
} catch RunTokenReadError.duplicateToken {
return unavailable(pid: pid, reason: "duplicate_run_token")
} catch RunTokenReadError.invalidTokenEncoding {
@@ -259,9 +266,6 @@ func token(in bytes: [UInt8], pointerSize: Int = MemoryLayout<UnsafeRawPointer>.
throw RunTokenReadError.ambiguousEnvironmentBoundary
}
let environmentEntries = trailingEntries[..<appleVectorStart]
guard !environmentEntries.isEmpty else {
throw RunTokenReadError.environmentUnavailable
}
var found: String?
for entry in environmentEntries {
if entry.starts(with: Array("REA_PROCESS_RUN_ID=".utf8)) {
+4
View File
@@ -43,6 +43,10 @@ def inspect_core(path, cache):
raise CoreFailure("unsupported-target", "Initial recorded-core profile requires ELF64 little-endian.")
if len(content) < 64:
raise CoreFailure("format", "Selected ELF64 core header is truncated.")
if content[6] != 1:
raise CoreFailure("format", "ELF identification version is not EV_CURRENT.")
if int.from_bytes(content[20:24], "little") != 1:
raise CoreFailure("format", "ELF header version is not EV_CURRENT.")
# Linux commonly emits ELFOSABI_NONE (0), also accepted as GNU/Linux (3).
# Other declared OSABIs must never select Linux note ctypes.
if content[7] not in (0, 3) or content[8] != 0:
+1 -2
View File
@@ -55,7 +55,7 @@ export default defineConfig({
{ text: "Ghidra on Windows", link: "/windows-ghidra-p0" },
{ text: "Ghidra DOS analysis", link: "/ghidra-dos" },
{ text: "Ghidra NativeAOT", link: "/ghidra-nativeaot" },
{ text: "Provider evaluation", link: "/provider-evaluation" },
{ text: "Ghidra semantics", link: "/ghidra-provider" },
],
},
{
@@ -66,7 +66,6 @@ export default defineConfig({
{ text: "Tool design", link: "/tool-design" },
{ text: "Testing", link: "/testing" },
{ text: "Releasing", link: "/releasing" },
{ text: "Architecture decisions", link: "/adr/README" },
],
},
],
+170
View File
@@ -0,0 +1,170 @@
# ADB device inspection and acquisition
REA inspects connected Android devices, reads device state, and transfers
files and packages through the caller's `adb` binary. Emulators, USB
devices, and network devices participate alike: REA neither starts nor
manages them and never installs platform tools. Every operation composes a
fixed adb argument vector — caller values occupy positional arguments only
and are quoted when adb forwards them to the device shell.
The adb client may start its local server on first device query; that is adb
client behavior, recorded in the tool result when observed.
`inspect_adb_client` probes only the binary and never contacts the server.
## Supply tools
Use any Android platform-tools `adb` (verified with 34.0.5). Select it
through the environment:
```sh
# Optional: absolute path to the adb binary; without it, adb resolves from PATH.
export REA_ADB_PATH=/absolute/path/to/adb
```
REA never installs the Android SDK, an emulator, or a system image.
Readiness is `rea inspect-adb-client`: it runs `adb version` and reports the
resolved binary, its version, and where it was selected from. A missing
binary reports `capability_unavailable` with the `REA_ADB_PATH` remediation
rather than attempting an installation.
## Answer an analyst question
```sh
# Device identity
rea inspect-adb-client
rea list-adb-devices
rea inspect-adb-device emulator-5554
rea inspect-adb-display emulator-5554
rea list-adb-features emulator-5554
rea list-adb-services emulator-5554
# Find and acquire an app (the easy-get flow)
rea resolve-adb-packages emulator-5554 whatsapp
rea list-adb-packages emulator-5554 --scope third_party
rea inspect-adb-package emulator-5554 com.whatsapp
rea pull-adb-package emulator-5554 com.whatsapp --output-directory /tmp/acq
rea inspect-android-package /tmp/acq/com.whatsapp/base.apk
# Device state and files
rea list-adb-processes emulator-5554
rea inspect-adb-window emulator-5554
rea read-adb-setting emulator-5554 global adb_enabled
rea read-adb-logcat emulator-5554 --count 200
rea list-adb-directory emulator-5554 /data/data/com.whatsapp
rea pull-adb-file emulator-5554 /data/local/tmp/notes.txt --output-directory /tmp/acq
rea push-adb-file emulator-5554 /tools/frida-server /data/local/tmp/frida-server
rea capture-adb-screen emulator-5554 --output-directory /tmp/shots
rea collect-adb-bugreport emulator-5554 --output-directory /tmp/bugs
# Package lifecycle and dynamic analysis (device-mutating)
rea install-adb-package emulator-5554 /tmp/app.apk --replace
rea start-adb-app emulator-5554 com.example.app
rea read-adb-logcat emulator-5554 --pid 12345
rea start-adb-activity emulator-5554 android.intent.action.VIEW --data-uri https://example.com
rea stop-adb-app emulator-5554 com.example.app
rea uninstall-adb-package emulator-5554 com.example.app
```
Equivalent MCP methods use the snake_case names (`list_adb_devices`,
`pull_adb_package`, `resolve_adb_packages`, …). Device operations take
`serial` exactly as `adb devices` reports it. The pulled APK set feeds the
existing analysis families directly, for example
`rea inspect-android-package /tmp/acq/<package>/base.apk`.
## Operations
| Tool | Kind | What it does |
| ----------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `inspect_adb_client` | read | Resolved binary, version, install path; never contacts the server |
| `list_adb_devices` | read | Serial, state, transport, model metadata, inferred emulator/physical kind with basis |
| `inspect_adb_device` | read | Fixed `getprop` whitelist: build, SDK, patch, fingerprint, product, ABIs, debuggable, `ro.kernel.qemu` |
| `inspect_adb_display` | read | `wm size` and `wm density` as declared |
| `list_adb_features` | read | `pm list features` (hardware/software features, hex GL versions) |
| `list_adb_services` | read | `service list` binder services and interfaces |
| `list_adb_processes` | read | `ps -A`: user, pid, ppid, rss, state, name |
| `inspect_adb_window` | read | `dumpsys window` focus declarations (what is on screen) |
| `read_adb_setting` | read | One `settings get` value; device-side null is reported as such |
| `read_adb_logcat` | read | Bounded `logcat -d -t` dump for one buffer, optional pid filter |
| `list_adb_packages` | read | `pm list packages -f` with scope; base APK device paths |
| `resolve_adb_packages` | read | Case-insensitive package-name substring search with exact-match flag |
| `inspect_adb_package` | read | `dumpsys package` projection: versions, install times, installer, flags, permission count |
| `list_adb_directory` | read | `ls -la`: kinds, permissions, owner, group, sizes, symlink targets |
| `pull_adb_package` | read | Complete split APK set from `pm path`, each file digested |
| `pull_adb_file` | read | One absolute device path pulled and digested |
| `capture_adb_screen` | read | One `screencap -p` frame (exec-out, no device-side file) with dimensions |
| `collect_adb_bugreport` | read | Device-generated bugreport zip, digested |
| `push_adb_file` | **mutates device** | One local file to a device path (e.g. pushing tools into `/data/local/tmp`); refuses existing targets without explicit overwrite; verifies via the device's own sha256sum |
| `install_adb_package` | **mutates device** | Local APK via `adb install [-r]`; preserves the device's Success/Failure verdict |
| `uninstall_adb_package` | **mutates device** | Removes a package and its data for user 0 |
| `start_adb_app` | **mutates device** | Resolves the package's launcher activity (`cmd package resolve-activity --brief`) and starts it (`am start -n`) |
| `start_adb_activity` | **mutates device** | Starts an intent (`am start -a` with optional URI, component, and up to 16 typed extras); preserves the activity manager's verdict |
| `stop_adb_app` | **mutates device** | Force-stops every process of a package, ending a dynamic-analysis run |
## Interpret the result
- **Inferences carry their basis.** Device `kind` reports
`kind_basis` (serial prefix or USB transport); APK `role` reports
`role_basis: file_name`; `emulator_observed` is the build's own
`ro.kernel.qemu` value, `null` when absent.
- **Device paths are not host paths.** `base_apk_device_path` values live on
the device filesystem. Only pulls and captures produce host-local paths,
each paired with byte size and SHA-256 digest.
- **Splits are part of the answer.** `pm path` enumerates the base APK and
every installed split; pulls cover the whole set. System packages whose
APKs keep other names report the `unknown` role rather than guessing.
- **Partial results keep facts.** Failed individual pulls return successful
artifacts with `coverage: "partial"` and per-file `failures`. Listings
that contain unrecognized lines report them as `unparsed_lines` and mark
partial coverage instead of dropping rows.
- **Mutations are explicit.** `push_adb_file`, `install_adb_package`, and
`uninstall_adb_package` declare `mutatesTarget` and never run implicitly:
pushes refuse existing device files unless `overwrite` is set and verify
the transfer with the device's own `sha256sum`; installs preserve the
device's `Failure [...]` reason verbatim.
- **Producer identity stays attached.** Every result embeds the producing
adb client (`binary_path`, `path_source`, `version`, `installed_path`).
## Resource and lifecycle limits
- Caller values reach adb only as positional arguments in fixed vectors;
no tool accepts an arbitrary shell command line, and UI interaction
(`input`, `am`, `monkey`) is deliberately not exposed.
- Per-invocation budgets: client/devices 10-20 s, shell reads 20-60 s with
64 KiB-8 MiB capture caps (logcat 4 MiB, screen 32 MiB), transfers and
bugreports 600 s. Exceeded budgets report `resource_constraint`; stopped
commands report `provider_timeout`.
- Pull and capture outputs are additive: the destination must not already
exist. Re-running a completed pull refuses the existing directory instead
of overwriting evidence.
- Cancellation during a package pull preserves caller-selected output. The
error includes partial observations identifying completed artifacts and the
interrupted local path; remaining APKs were not attempted.
- Failed package acquisition rollback retains its directory identity and retries
cleanup before later work and during shutdown. Cleanup refuses a replacement
directory. Terminal shutdown stops admission and drains active operations.
- The provider holds no long-lived processes; every invocation is one
bounded adb run. The adb server belongs to the caller.
## Related capability and follow-up lanes
UI interaction beyond intent starts (tapping, typing, monkey fuzzing, screen
recording) remains a separate lane: candidates such as
[mobile-device-mcp](https://github.com/srmorete/mobile-device-mcp) install
driver software on the device and pair with the Frida instrumentation lane
(#1359) behind explicit mutation-authority contracts. Network transports
beyond already-connected devices (`adb connect`) are not exposed yet.
## Real verification
`npm run verify:adb` exercises every operation against a live device. It
requires `adb` (or `REA_ADB_PATH`) and any attached emulator or phone;
`--serial` selects one when several are attached, `--pull PACKAGE` pulls a
real package and verifies the returned digests against the files on disk,
and `--install-apk PATH` drives a full install → resolve → uninstall
lifecycle with a lane-owned probe.
Record: verified against adb 34.0.5 on Linux against an Android 14
(API 34) x86_64 emulator — all operations above, a 224-package inventory,
287 services, 92 features, a real two-APK split set pulled with byte-exact
digests, a verified push/pull roundtrip, a 1.3 MB screen capture, and the
complete package lifecycle; see `docs/testing.md` for the lane summary.
@@ -1,578 +0,0 @@
# ADR-0001: Provider selection and analysis profiles
- Status: Accepted
- Date: 2026-07-15
- Implementation status: The provider registry, deterministic selection,
target binding, analysis-profile commitment, and snapshot/Evidence migration
are implemented. Ghidra discovery, target/profile resolution, doctor checks,
the private headless-session foundation, thirteen read-only inventory/load-image
capabilities, and twelve function-analysis capabilities are implemented with
real cross-format conformance. Linux/macOS also supports atomic session
function annotations; experimental Windows x64 P0 uses bundled native controls
and admits only the 25 read-only operations. See the
[release boundary](../installation.md#released-package-and-main).
## Context
Before this decision, REA composed the artifact, native macOS, and Hopper
providers with `CompositeProvider`. That class intentionally requires every
operation to have one route. Hopper and Ghidra will both implement the deep
static-analysis operation family, so putting both into that composite would
either fail at construction or make array order an undeclared selection policy.
The active `BinarySession` also owned one composite client. `open_binary` had no
provider selector, and the domain `BinaryTarget` contained Hopper loader
arguments. Analysis snapshot v1 committed those loader arguments and each
cached entry's provider identity, but it did not commit the selected analysis
engine, engine version, or complete analysis configuration. Two analyses of the
same bytes could therefore disagree because of language, compiler, loader,
analyzer, or provider-version differences while appearing target-compatible.
The decision addressed the earlier representations of
[`CompositeProvider`](https://github.com/morluto/rea/blob/main/src/application/binary/CompositeProvider.ts),
[runtime composition](https://github.com/morluto/rea/blob/main/src/composition/binary.ts),
[`BinarySession`](https://github.com/morluto/rea/blob/main/src/application/binary/BinarySession.ts),
[`BinaryTarget`](https://github.com/morluto/rea/blob/main/src/domain/binaryTarget.ts),
[analysis snapshot](https://github.com/morluto/rea/blob/main/src/domain/analysisSnapshot.ts), and
[session lifecycle inputs](https://github.com/morluto/rea/blob/main/src/contracts/sessionLifecycleInputs.ts).
The next deep provider must not weaken the existing product invariants:
- stable provider-neutral CLI and MCP tool names;
- exact provenance and explicit unavailable or degraded capabilities;
- CLI and MCP parity;
- no silent provider fallback;
- provider-specific code outside the domain and application models;
- local, actionable diagnostics with only genuine secrets redacted; and
- snapshot reuse only when semantic analysis inputs are identical.
## Decision drivers
1. Hopper and Ghidra need to declare overlapping operations without ambiguous
dispatch.
2. A target must have one explainable deep-analysis producer for its lifetime.
3. Target-free discovery must remain useful and must not start an analysis
process.
4. Existing Hopper-only configurations must keep working when no selector is
supplied.
5. Adding a second installed provider must not silently change results.
6. Snapshot and Evidence compatibility must include every setting that can
materially change analysis.
7. Provider-specific open settings must not leak into `BinaryTarget` or become
generic application fields.
## Terminology
- **Deep provider**: an engine such as Hopper or Ghidra that implements the
overlapping static-analysis operation family.
- **Auxiliary provider**: a provider with a disjoint operation family, such as
artifact inventory or native macOS inspection.
- **Candidate**: a registered deep provider before target selection.
- **Binding**: the selected deep provider and analysis profile attached to one
active target.
- **Analysis profile**: a canonical commitment to the selected provider,
provider version, and normalized semantic analysis settings.
- **Available**: the adapter and its required local runtime can be used on this
host.
- **Supported**: the candidate accepts the parsed target and supplied open
options. Availability and target support are separate observations.
## Decision
### 1. Separate disjoint composition from overlapping selection
`CompositeProvider` remains the mechanism for operation families whose routes
are disjoint. It must continue rejecting duplicate operation declarations. It
must not acquire priority, racing, fallback, or provider-selection behavior.
A new `AnalysisProviderRegistry` owns the configured deep-provider candidates.
Provider IDs are unique; duplicate IDs are a configuration error. The registry
may hold multiple candidates that declare the same operation. It performs
candidate discovery, target-support evaluation, option parsing, profile
resolution, and selection, but it does not choose a different provider for each
request.
After selection, the session composes exactly one bound deep provider with the
auxiliary disjoint families:
```text
target-free discovery
|
AnalysisProviderRegistry
/ \
Hopper Ghidra
\ /
one selected binding
|
+-------------------------+-------------------------+
| | |
selected deep family artifact family native family
+-------------------------+-------------------------+
|
BinarySession
```
An auxiliary operation continues to report its actual auxiliary provider as
provenance. A deep operation always reports the provider in the active binding.
The synthetic composite identity is never evidence that two engines jointly
produced one observation.
Operation ownership is fixed by family:
| Operation family | Executor |
| ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
| Deep direct operations and provider-native function analysis | The one bound Hopper or Ghidra provider |
| Application-enhanced deep workflows | Application composition over the bound provider's declared operations |
| Native macOS inspection | The disjoint native provider |
| Artifact inventory and extraction | The disjoint artifact provider |
| Browser and Electron observation | Their independently authorized CDP providers; they do not participate in deep-provider selection |
| Session lifecycle, Evidence, comparisons, and reconstruction | The application/session layer using the exact provider provenance recorded by their source operations |
Selecting a deep provider selects the whole deep family. If that provider marks
an operation unavailable, REA returns the unavailability; it does not borrow
that one operation from another deep provider. Application-enhanced workflows
run only when the bound provider supplies their declared dependencies.
### 2. Discover candidates without launching analysis
Each registered candidate exposes three bounded adapter-owned observations:
1. identity and declared capability descriptors;
2. host availability, including an actionable rejection when unavailable; and
3. target support plus normalized profile resolution when a target is known.
Target-free discovery may inspect configuration, manifests, executable
metadata, and documented version files. It must not import a target, create a
project, open a GUI, or start the long-lived analysis process. Any short-lived
version probe added later must be explicitly bounded and truthfully declared as
a process effect.
Candidate output is sorted by provider ID for determinism. Sort order is not
selection priority. Availability and support use stable codes plus a human
diagnostic:
| Code | Meaning |
| ---------------------------- | --------------------------------------------------------------- |
| `not_configured` | Required provider location or configuration is absent |
| `executable_missing` | The configured provider entry point is missing or not runnable |
| `runtime_missing` | A required provider runtime, such as Java, is unavailable |
| `unsupported_host` | The host platform or architecture is unsupported |
| `unsupported_version` | The discovered provider or runtime version is unsupported |
| `target_kind_unsupported` | The provider does not accept this target kind |
| `target_format_unsupported` | The provider does not accept this target format |
| `architecture_unsupported` | The selected target architecture is unsupported |
| `target_role_unsupported` | The provider rejects this executable image role |
| `managed_target_unsupported` | The provider does not admit managed code through this deep path |
| `open_options_invalid` | The selected adapter rejected its open options |
| `version_unresolved` | A concrete analysis-engine version could not be committed |
Diagnostics retain useful local paths, observed versions, architectures, and
mismatch details. Credentials, authorization headers, license secrets, and
other genuine secrets remain redacted.
### 3. Use one deterministic selection algorithm
The caller-visible selectors are:
- MCP `open_binary.provider_id`;
- `rea ... --provider <provider-id|auto>` on every one-shot command that needs
deep analysis; and
- `REA_ANALYSIS_PROVIDER=<provider-id|auto>`, defaulting to `auto`.
The literal value `auto` is reserved and cannot be a provider ID. Precedence is
request or CLI flag, then environment configuration, then the default `auto`.
An explicit request for `auto` overrides a concrete environment preference and
re-enters automatic selection.
Selection occurs after provider-neutral target parsing and before a deep client
is created:
1. A concrete requested provider ID must exist, be available, support the
target, accept its options, and resolve a concrete version and profile. Any
failure returns a typed selection error; another provider is never tried.
2. `auto` filters candidates by availability and target support.
3. Exactly one usable candidate is selected with source
`auto-single-candidate`.
4. More than one usable candidate is an `ambiguous` selection error. The
diagnostic lists the candidates and asks for `provider_id`, `--provider`, or
`REA_ANALYSIS_PROVIDER`. REA does not prefer Hopper, Ghidra, registration
order, the fastest startup, or the first health response.
5. When no deep candidate is usable, an automatic open may still establish an
unbound target so disjoint artifact or native operations remain available.
Deep operations are then explicitly unavailable with the candidate
rejections. A concrete request, or a concrete environment preference for a
deep-eligible target, remains a hard requirement and fails instead of
becoming unbound.
6. A target that no deep adapter declares support for, such as an artifact-only
target, is `not_applicable` rather than a failed deep analysis. Supplying a
concrete provider in that open request is still an actionable unsupported-
target error. A global environment preference does not make an artifact-only
target require a deep provider.
This preserves target opening for non-Hopper capabilities on hosts without a
deep engine while ensuring that installing a second usable deep engine never
changes analysis silently.
### 4. Bind once and never fail over mid-session
An active deep binding contains:
```text
canonical target identity
selected provider identity and concrete version
selection source: request | environment | auto-single-candidate
analysis profile commitment
owned provider client, once started
```
The binding is immutable until `close_binary` or an explicit open/switch
transaction. Provider client creation may remain lazy, but laziness cannot
change which provider was selected.
- Opening the same canonical target without a new selector keeps the existing
binding.
- Opening the same target with the same provider and profile is idempotent.
- A different explicit provider or a profile-changing option is a real switch:
drain active calls, close owned resources, resolve the new binding, and start
it as one serialized transaction.
- If a switch fails, restore the prior target and binding on a best-effort
transactional path and return the original switch error.
- Provider process exit, timeout, cancellation, capability failure, or adapter
error never triggers fallback. The binding stays visible and unavailable
until the caller explicitly switches or closes it.
- A snapshot never chooses or changes the provider. Selection happens first;
snapshot compatibility is checked against the resulting binding.
Calls already admitted to one binding complete or cancel against that binding.
No request can cross a concurrent target or provider transition.
### 5. Keep provider open options adapter-owned
`BinaryTarget` retains only provider-neutral source identity and classification:
canonical path, source digest, generic kind and format, selected architecture,
and available architectures. Hopper loader arguments leave the domain model.
Provider-owned databases use a generic analysis-database classification; their
adapter determines support. A legacy `.hop` target is therefore accepted only
by Hopper without teaching the domain how to open it. Ghidra v1 continues to use
private temporary projects and does not open user projects.
The generic transport may carry one bounded JSON `provider_options` object.
Only the selected adapter parses its keys and reports `open_options_invalid` at
that boundary. If this object is exposed over MCP, the CLI parity surface is
`--provider-options-json` with the same JSON schema and limits. Unknown keys,
wrong-provider options, excessive depth or size, and non-JSON values fail
closed.
Environment settings that are inherently adapter-specific, such as the Hopper
launcher or future Ghidra installation path, remain in adapter configuration.
They do not become `BinaryTarget` fields. The application layer transports an
opaque, already-bounded JSON value and the generic commitment described below;
it does not interpret Hopper or Ghidra option names.
### 6. Commit a canonical analysis profile
Before creating a deep client, the selected adapter normalizes every semantic
input that can affect analysis. Examples include Hopper loader selection and
architecture flags, or Ghidra language ID, compiler specification, import mode,
analyzer set, and analyzer options. Defaults are made explicit, unordered sets
are sorted, and implicit host-dependent choices are resolved.
The adapter returns this provider-neutral envelope:
```json
{
"provider": { "id": "ghidra", "version": "<concrete version>" },
"parameters": {},
"digest": "<sha256 of RFC 8785 canonical JSON excluding digest>"
}
```
`parameters` is bounded JSON interpreted only by that provider adapter. It
contains analysis semantics, not credentials, authorization data, temporary
paths, installation paths, process IDs, timestamps, or other incidental host
state. The generic domain validates the envelope and digest but treats the
parameters as opaque data.
A selected deep binding requires a concrete provider version. If the adapter
cannot determine it, the candidate is unavailable with `version_unresolved`;
REA does not persist a cache that merely commits `null` or "whatever is
installed". Provider identity, normalized parameters, or provider version
changes produce a different digest.
The same target, configuration, and provider must resolve the same profile over
CLI and MCP. Profile resolution must be side-effect-free and complete before
the provider imports the target.
### 7. Make snapshots provider- and profile-exact
Analysis snapshots replace Hopper loader arguments with an explicit binding
commitment:
```text
target: digest + generic format/kind + selected architecture
binding: provider identity + analysis profile commitment
entries: exact immutable queries
evidence_bundle: retained Evidence records
```
The snapshot target identity, canonical snapshot content digest, and every
query ID commit the provider ID, concrete provider version, and profile digest.
A cached entry is reusable only when all of the following match exactly:
- target digest, generic format and kind, and selected architecture;
- provider ID and provider version;
- profile digest;
- operation and canonical parameters; and
- the existing cacheability and immutability rules.
Provider or profile switches select a separate cache partition and cannot reuse
entries from the previous binding. Auxiliary operations are cacheable only if
their provider defines an equivalent explicit profile commitment; otherwise
they remain Evidence but not snapshot entries.
Snapshot v1 cannot be parsed as the current snapshot format. Its `loader_args`
cannot prove which engine version, defaults, or analyzer settings produced the
entries, so snapshots must be recaptured before they can be used as a cache.
An embedded Evidence bundle can still be imported separately through the
Evidence import flow; it is never promoted into an analysis cache.
### 8. Add profile commitments to new deep Evidence while preserving legacy records
The optional `analysis_profile` field uses the canonical envelope above. Every
newly created deep-analysis observation must include it, and its provider ID
and version must match the record's provider. The field participates in the
Evidence semantic ID.
Existing Evidence records without `analysis_profile` remain valid and keep
their existing IDs. Absence on a legacy deep record means the analysis profile
is unknown; REA does not infer or enrich it during import. Such evidence can be
displayed and cited but cannot establish profile compatibility, seed snapshot
replay, or support an "unchanged" conclusion that depends on identical analysis
semantics.
Different providers or profile digests are never snapshot-compatible. A
derived comparison may compare cross-provider normalized facts only when its
own contract explicitly defines that semantic comparison. Exact pseudocode,
provider text, or provider-specific metadata is not treated as equivalent. A
missing or incompatible profile yields unknown or incompatible, never equal.
### 9. Expose selection truth in status and diagnostics
`binary_session`, `rea providers`, and `rea capabilities` expose the same
candidate and binding model. The target-free form does not start providers and
uses `unknown` for target support:
```json
{
"analysis_provider_binding": null,
"analysis_provider_candidates": [
{
"provider": {
"id": "hopper",
"name": "Hopper Disassembler",
"version": "<detected version>"
},
"availability": {
"status": "available",
"code": null,
"reason": null,
"diagnostics": {}
},
"target_support": {
"status": "unknown",
"code": null,
"reason": "No target is open."
},
"selected": false,
"capabilities": []
}
]
}
```
With a binding, `analysis_provider_binding` includes the selected identity,
selection source, and complete profile commitment. Every candidate reports
`supported`, `unsupported`, or `unknown` target support and whether it was
selected. Candidate capability descriptors preserve supported, unsupported,
and degraded truth independently.
An open target also exposes `analysis_run`. Its run ID is allocated by the
session before client construction and propagated into selected Hopper or
Ghidra bridge handshake and process environment. Dynamic clients retain
provider-attributed lineage snapshots only after revalidating launcher
parent/command and every observed launcher or descendant run token. `not_observed`
means no dynamic provider has supplied a snapshot. Once one or more start,
`snapshots` preserves every provider observation; each remains explicitly
`unavailable` or `verified` and records its `observed_at` time. Retained
snapshots are not live inventories, and a point-in-time observation never proves
historical absence.
The existing flat `provider`, `providers`, and `capabilities` status fields stay
during the 1.x compatibility window. Their effective deep-operation entries
come only from the active binding; target-free ambiguity is unavailable rather
than arbitrarily collapsed. The new candidate fields are authoritative for
selection. A future major release may remove the synthetic composite provider
field after callers have migrated.
Selection failures extend the tagged `ProviderSelectionError` with a stable
reason:
- `unknown_provider`;
- `provider_unavailable`;
- `target_unsupported`;
- `ambiguous`;
- `invalid_options`.
The error includes the requested ID or `auto`, candidate IDs, rejection codes,
and actionable local diagnostics. `AnalysisCapabilityUnavailableError` remains
the error for an operation the selected provider cannot supply.
`ProviderAdapterError` and more specific provider errors remain failures of the
already selected provider. None authorizes fallback.
A snapshot whose provider or profile differs from the selected binding returns
`EvidenceIntegrityError` with stable `profile_mismatch` details. It is an
integrity incompatibility after selection, not permission to select the
snapshot's provider.
### 10. Preserve CLI and MCP parity
- `open_binary.provider_id` and one-shot `--provider` use the same parser and
selection service.
- `provider_id: "auto"`, `--provider auto`, and
`REA_ANALYSIS_PROVIDER=auto` have identical auto semantics.
- Startup targets opened from environment configuration use the same service.
- `rea providers`, `rea capabilities`, and target-free `binary_session` use the
same candidate snapshot and reason codes.
- Guided prompt `provider_id` context is a preference to forward into the open
operation; it does not create a hidden routing channel.
- Tool names and normalized output contracts remain provider-neutral. REA does
not add `ghidra_decompile` or `hopper_decompile` tools.
## Compatibility and migration
| Existing behavior or data | Decision |
| ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| No provider selector, only Hopper usable | `auto` selects the sole candidate; behavior remains equivalent |
| No deep provider usable | Automatic open may remain unbound for auxiliary operations; deep capabilities explain why they are unavailable |
| Hopper and Ghidra both usable, no preference | Open fails with `ambiguous`; installation order never becomes policy |
| Existing Hopper environment settings | Remain supported as Hopper adapter configuration |
| `open_binary` and CLI structured `loaderArgs` output | Retained as a deprecated Hopper-only compatibility projection for 1.x; the analysis profile is authoritative |
| `BinaryTarget.loaderArgs` | Removed; Hopper derives them inside its adapter and commits normalized semantics in the profile |
| Legacy `.hop` input | Classified generically as an analysis database and accepted only by Hopper |
| Snapshot v1 | Not accepted as the current snapshot format; recapture before cache replay |
| Existing Evidence without a profile | Accepted unchanged; profile compatibility is unknown |
| New deep-analysis Evidence | Must include `analysis_profile`; its semantic ID commits the field |
| Existing status fields | Retained for 1.x with additive binding and candidate fields |
| Provider failure after selection | Returned from the selected provider; no transparent retry through another engine |
The deprecated `loaderArgs` response must never be read to select a provider or
validate a snapshot. It is empty for non-Hopper bindings and may be removed only
with a separately documented major contract change.
## Required behavior scenarios
| Scenario | Result |
| ---------------------------------------------------------- | --------------------------------------------------------------------------- |
| Hopper is the only usable candidate, selector omitted | Hopper is bound by `auto-single-candidate` |
| Ghidra is the only usable candidate, selector omitted | Ghidra is bound by `auto-single-candidate` |
| Both are usable, selector omitted | Typed `ambiguous` error; neither provider starts |
| Environment selects Ghidra, request omits a selector | Ghidra is required and bound or the open fails with its rejection |
| Environment selects Ghidra, request selects Hopper | Request wins; Hopper is required |
| Environment selects Ghidra, request selects `auto` | Auto policy runs and is ambiguous when both are usable |
| Unknown concrete provider ID | Typed `unknown_provider`; no target transition |
| Selected provider rejects the target or options | Typed rejection from that candidate only |
| Selected provider times out after binding | Binding remains selected and unavailable; no fallback |
| Same target is reopened without a selector | Existing binding remains unchanged |
| Same bytes are opened with a different profile | Real provider switch and a separate snapshot partition |
| Snapshot provider or profile differs from the binding | Typed `EvidenceIntegrityError` with `profile_mismatch`; nothing is imported |
| Artifact-only target has no deep candidate | Target opens unbound; disjoint artifact capabilities remain usable |
| Environment prefers Ghidra for an artifact-only target | Deep selection is `not_applicable`; auxiliary operations remain usable |
| Concrete deep provider is requested for artifact-only data | Typed `target_unsupported`; the request is not silently ignored |
## Consequences
Positive consequences:
- Hopper and Ghidra can coexist without ambiguous operation routes.
- Provider choice is reproducible, visible, and stable for a target.
- Installation of another provider cannot silently change analysis.
- Snapshot and Evidence identities become analysis-configuration aware.
- Provider adapters retain ownership of their option schemas and diagnostics.
- Auxiliary capabilities remain usable when no deep engine is installed.
Costs and tradeoffs:
- Multi-provider hosts must choose when more than one candidate is usable.
- Snapshots must be recaptured when their provider or profile binding changes.
- Providers must expose deterministic availability, support, version, and
profile resolution before they can be admitted.
- Status and error contracts gain additive structured metadata.
- Hopper needs an adapter-owned version/profile implementation before profile-
exact snapshot persistence is complete.
## Rejected alternatives
### Let `CompositeProvider` choose the first duplicate route
Array order is not a product policy, becomes fragile during wiring changes, and
hides ambiguity from callers.
### Race providers and keep the first healthy response
Machine load would determine provenance and results. It also starts resources
the operator did not select and makes cancellation and cleanup harder.
### Fall back after a provider error
Mid-session fallback can combine incompatible engine state and evidence under
one apparent target. Explicit close or switch is required instead.
### Add provider-prefixed tools
Parallel Hopper and Ghidra tool families would leak adapters into the product
contract and prevent shared workflows from using capability metadata.
### Store raw provider options in `BinaryTarget`
That repeats the current Hopper coupling and makes every generic consumer learn
provider schemas. Only canonical profile commitments cross the adapter boundary.
### Treat matching target bytes and provider ID as sufficient for snapshots
Provider versions, analyzer defaults, loaders, languages, and compiler models
can change results without changing either value.
### Silently upgrade snapshot v1
The missing engine version and analysis settings cannot be reconstructed from
Hopper loader arguments. A fabricated profile would turn unknown provenance
into false certainty.
## Implementation progress
The first six implementation stages are shipped:
1. Provider-specific target state was replaced by generic profile and snapshot
v2 commitments while preserving Hopper execution behavior.
2. The registry, selectors, candidate status, binding lifecycle, and
overlapping-provider production seams were added.
3. Proven process-lifecycle primitives were extracted for shared use.
4. Ghidra availability, target/profile resolution, doctor checks, and a private
read-only headless session were admitted without declaring operations.
5. Program identity, procedures, strings, symbols, memory blocks,
address/name resolution, containing-procedure resolution, and search
were admitted with exact wire schemas and real debug/stripped ELF
conformance.
6. Function metadata, persistent decompilation, assembly, resolved
callers/callees, typed references, xrefs, CFG, and complete function dossiers
were admitted. A serial per-Program queue keeps API access ordered without a
fixed queue length or per-operation deadline. Real conformance covers
x86-64 and AArch64 ELF, PE, Mach-O, stripped symbols, targetless indirect
calls, cancellation, and cleanup.
Future stages may deepen format and indirect-flow coverage, but must continue
to compare normalized semantics rather than provider-specific pseudocode or
assembly text. Linux and macOS now admit atomic function-name and entry-comment
edits in the ephemeral database, with readback, rollback, and cache invalidation.
Executable bytes remain unchanged. Windows P0 retains its read-only boundary;
GUI and other unimplemented mutations remain unavailable.
@@ -1,551 +0,0 @@
# ADR-0002: Controlled JavaScript replay authority and sandbox policy
- Status: Superseded; the controlled JavaScript replay tool was removed
- Date: 2026-07-16
- Implementation status: The implementation was removed. The design below is
retained as historical context and does not describe a supported REA tool.
> Historical design note: The tool, sandbox backend, and plan/execute workflow
> described here are no longer part of REA. For runtime behavior, run probes
> directly against the application and use the available browser, Electron, or
> process capture workflows.
## Context
REA can reconstruct JavaScript and Electron artifacts, observe an existing
browser or Electron page through passive CDP, capture an explicitly approved
process scenario, and correlate those observations without executing bundle
code in the REA server. The next research workflow needs to execute selected,
extracted JavaScript modules with controlled inputs and deterministic stubs so
that parsers, sanitizers, serializers, and similar pure logic can be compared
across versions.
That workflow crosses a qualitatively different boundary. Source recovered
from an application is untrusted code. It can intentionally or accidentally
read files, contact services, spawn processes, exhaust resources, corrupt the
analysis process, forge protocol output, or interact with another same-user
process. A JavaScript realm or Node.js `vm` context is useful for constructing
an API surface, but it is not a security boundary. Node.js also documents its
permission model as protection against accidental access by trusted code, not
as containment for malicious code.
Existing authorities cannot be widened to cover this behavior:
- `browser_observe` and `electron_observe` authorize passive attachment to an
already-running, operator-owned target. They do not authorize evaluation,
navigation, input, or target lifecycle changes.
- `process_capture` authorizes one declared host process scenario and explicitly
states that it is not a sandbox. It cannot silently become permission to run
recovered code.
- static artifact reads authorize inspection of bytes, not execution of those
bytes.
- the Evidence authority `controlled-replay` already describes observations
from an approved process experiment. Reusing that epistemic authority is
correct, but reusing the process permission capability is not.
The implementation following this ADR must fail closed on hosts where REA
cannot establish the promised operating-system boundary. It must not copy the
research `vm.runInContext` scripts into the production server and call that
isolation.
## Decision drivers
1. Passive observation must never imply authority to execute application code.
2. The exact code, inputs, stubs, runtime, sandbox policy, and limits approved
by the operator must be the ones executed.
3. Recovered code must not run in the MCP server, CLI adapter, or any provider
process.
4. A sandbox failure must make the capability unavailable, not select a weaker
execution mode.
5. The default policy must provide no host network and no writable host path.
6. Time, memory, process count, temporary storage, protocol, and output must be
bounded independently.
7. Results must distinguish an observed return, an observed exception or
termination, a derived comparison, and an unresolved application-level
claim.
8. A reproducer must commit enough provenance to detect every relevant change
without committing proprietary application source to the repository.
9. CLI and MCP must expose the same plan, approval, execution, cancellation,
failure, and Evidence semantics.
## Terminology
- **Passive observation**: bounded reads from an existing browser or Electron
target without evaluating code, driving input, navigating, or controlling
its lifecycle.
- **Controlled replay**: execution of operator-selected code in a declared,
isolated environment with committed inputs and limits. This is an Evidence
authority, not a claim that the real application behaved identically.
- **Extracted-module replay**: the only admitted JavaScript replay mode in v1.
REA evaluates a finite manifest of module bytes and explicit stubs without
launching the application.
- **Application interaction**: launching or driving the original application,
browser, renderer, or Electron main process. This is not extracted-module
replay and is not authorized by this ADR.
- **Replay plan**: the canonical, content-addressed description of one proposed
run before execution.
- **Replay worker**: the disposable Node.js process inside the OS sandbox. It
is never the REA server process.
- **Sandbox backend**: the OS mechanisms and adapter that establish namespaces,
resource controls, filesystem visibility, and owned cleanup.
## Threat model
### Protected assets
The boundary protects:
- the REA MCP/CLI process, its memory, credentials, sockets, and Evidence
ledger;
- user files outside the approved source reads and all host files from writes;
- other same-user processes and their control interfaces;
- host network interfaces, loopback services, Unix sockets, and external
services;
- process, memory, CPU, temporary-storage, output, and protocol capacity;
- the integrity of the replay plan, result, Evidence provenance, and exported
reproducer; and
- proprietary module bytes, which remain local and are never repository
fixtures.
### Adversaries and failure sources
REA treats all of the following as untrusted:
- recovered module source, including transitive modules and source maps;
- caller-provided JavaScript stubs;
- structured test inputs and generated fuzz cases;
- returned values, exceptions, console data, and worker protocol messages;
- source paths, symbolic links, and files that can change between planning and
execution; and
- a worker that crashes, hangs, forks, allocates aggressively, or exits while
descendants remain alive.
An operator-controlled sandbox executable, kernel, Node.js runtime, and REA
installation are trusted computing base. A hostile host administrator, kernel
or sandbox vulnerability, hardware side channel, and denial of service by an
already-compromised same-user process are out of scope. These exclusions do not
permit REA to omit the per-run resource controls in this decision.
### Required mitigations
The implementation must address:
| Threat | Required control |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| Server-process compromise | Separate worker process inside the OS sandbox; no in-process fallback |
| Host file reads | Empty sandbox root; only a minimal read-only runtime closure; module bytes enter over a private bounded channel |
| Host file writes | No writable bind mounts; size-limited private tmpfs only |
| Network access | Separate network namespace with no host or external connectivity; no allowlist mode in v1 |
| Host process control | PID/user/IPC/UTS isolation, no inherited control sockets, new session, dropped capabilities |
| Kernel escape/inspection surface | Architecture-checked seccomp denial policy in addition to namespaces, capabilities, and cgroups |
| Fork, memory, or CPU exhaustion | Per-run cgroup v2 task, memory, swap, and CPU limits plus an outer wall-clock deadline |
| Output/protocol exhaustion | Independent byte/message/depth limits enforced by the parent before parsing or retaining output |
| Symlink and file-change races | Canonical authorization, descriptor-backed reads, digesting, staging, and exact plan revalidation |
| Undeclared dependencies | Closed module manifest; exact imports only; missing/dynamic imports fail rather than use host resolution |
| Nondeterministic globals | Versioned clock, PRNG, locale, timezone, platform, and API stubs; undeclared globals are unavailable |
| Orphan descendants | Owned PID namespace and cgroup kill followed by an observable empty-cgroup cleanup check |
| Forged result claims | Framed worker protocol, strict schemas, parent-computed commitments, and bounded stderr kept separate |
| Secret leakage | Empty environment, no credential inheritance, bounded local results, and existing genuine-secret redaction |
## Decision
### 1. Add a distinct `javascript_replay` permission capability
JavaScript replay receives a new permission capability named
`javascript_replay`. It does not inherit, imply, or satisfy
`process_capture`, `browser_observe`, `electron_observe`, artifact-read, or
workspace permissions. Grants for any of those capabilities do not satisfy a
JavaScript replay request, and a JavaScript replay grant does not authorize
them.
The administrator ceiling is disabled by default. Its eventual configuration
must commit:
- canonical roots from which module and optional stub files may be read;
- the exact Node.js and sandbox-backend executables;
- filesystem mount authority needed only to construct the private sandbox;
- network mode `none`; and
- no inherited environment names.
Configuration establishes only the maximum authority. Every execution also
requires an active permission grant and literal per-call approval bound to the
exact replay plan. Project, session, and administrator grants may satisfy the
permission-policy layer, but none replace that per-run approval.
Reproducer export is a separate host write after the sandbox has stopped. This
ADR's root-scoped `evidence_write` authority was removed; current exports use
the path supplied by the caller, while replay still waits for complete sandbox
cleanup before writing.
### 2. Admit extracted modules only
The v1 mode executes a finite, closed manifest of JavaScript modules. The
manifest identifies one entry module and every admitted dependency by a stable
sandbox alias and SHA-256 digest. Imports resolve only to another manifest
entry or to an explicitly declared, versioned stub. Bare package lookup,
ambient `node_modules`, import maps from the host, network imports, native
addons, WASI, FFI, child processes, workers, inspector activation, and implicit
dynamic import are unavailable.
Modules and stubs are read and hashed by the authorized parent, then copied as
bytes through a bounded private channel. Original host paths are not mounted
into the sandbox. The worker cannot reopen the operator's source path.
Source maps may supply locations, but source-map source code is not executed
unless its bytes are separately present in the approved manifest. A source-map
name or Webpack module ordinal is never execution authority.
REA does not launch, attach to, navigate, click, type into, or terminate the
user's application under this capability. A full application process remains
an independently approved Process Capture experiment; browser and Electron
targets remain passive. Any future mode that drives an application or permits
host/allowlisted network requires a new ADR and a distinct permission scope.
### 3. Use a two-phase, content-bound approval flow
One public replay surface supports a plan phase and an execute phase with the
same schema through CLI and MCP.
The plan phase:
1. validates all caller input and hard limits before file access;
2. obtains authority to read every selected module or stub path;
3. canonicalizes and opens each file without following an unapproved identity;
4. reads bounded bytes, computes digests, and closes the source descriptors;
5. resolves and probes the exact runtime and sandbox backend without running
application code;
6. normalizes stubs, inputs, generator settings, and limits; and
7. returns the complete proposed effects and a canonical `plan_digest`.
The plan must disclose at least:
- module aliases, canonical local paths, byte counts, and SHA-256 digests;
- input and stub identities, provenance, and digests;
- runtime and sandbox executable paths, versions, and executable digests;
- sandbox policy version and digest;
- network `none`, visible read-only runtime paths, and private writable tmpfs
size;
- time, CPU, memory, swap, task, temporary-storage, input, output, protocol,
case-count, and serialization limits;
- deterministic clock, PRNG seed/algorithm, locale, timezone, and platform
projection; and
- expected Evidence and cleanup behavior.
Execution requires the exact `plan_digest`. REA
rebuilds the plan immediately before admission. Any changed file, runtime,
sandbox executable, policy, stub, input, limit, or environment commitment
returns `plan_stale` before application code starts. Approval is not transferable
to a different plan and cannot be represented by a bare Boolean alone.
Interactive CLI may print the plan and ask for confirmation. Non-interactive
CLI and MCP must perform the same explicit plan/execute exchange; they may not
auto-approve because the caller requested JSON output or because permission
elicitation is supported.
### 4. Require an OS sandbox; fail closed elsewhere
The first production backend is Linux-only. It must combine:
- an empty mount namespace rooted in private tmpfs;
- a new user namespace with all capabilities dropped and further nested user
namespaces disabled;
- new PID, network, IPC, UTS, and cgroup namespaces;
- a new terminal session and parent-death behavior;
- no host D-Bus, agent, browser, Docker, Wayland/X11, SSH, GPG, audio, device,
or application sockets;
- a minimal, read-only runtime closure rather than `/`, the user's home,
working directory, or host `/tmp`;
- a fresh `/proc` for the sandbox PID namespace and a minimal private `/dev`;
- a parent-generated, architecture-checked seccomp policy that denies at least
namespace or mount changes, `ptrace` and cross-process memory inspection,
BPF/perf access, kernel keyring and module control, reboot/swap controls, and
the `TIOCSTI` terminal injection path;
- cgroup v2 `memory.max`, `memory.swap.max=0`, `pids.max`, and bounded CPU
controls owned for the one run; and
- an outer REA supervisor that can kill the complete cgroup and verify it is
empty.
The seccomp program is passed by descriptor, has a version and digest committed
to the replay plan, validates the syscall architecture before the syscall
number, and never permits `ptrace`-based mediation. Seccomp reduces exposed
kernel surface; it is not described as a complete sandbox by itself.
The reference backend for the implementation PR is Bubblewrap for namespace,
mount, and seccomp construction plus a delegated cgroup v2 manager for resource
enforcement. REA must feature-probe the actual required operations; version
text alone is insufficient. A setuid Bubblewrap installation, a backend that
silently skips a requested namespace or filter, unavailable user namespaces,
missing cgroup delegation, or inability to prove cleanup makes the capability
unavailable. REA setup must not install or upgrade Bubblewrap, systemd, Node.js,
or kernel components.
macOS, Windows, Linux hosts without every required feature, containers that
block the required namespaces, and alternative backends are unavailable in
v1. They must return precise diagnostics and remediation, not a process-only or
`vm`-only degraded mode.
Node.js runs with its permission model enabled and without grants for network,
filesystem, child processes, workers, native addons, WASI, FFI, or inspector.
That layer is defense in depth. It is never cited as the OS security boundary,
because Node.js explicitly does not promise containment of malicious code.
### 5. Make the worker disposable and deterministic by construction
Each approved run receives a new sandbox, runtime root, worker process, module
loader, and deterministic state. No module cache, realm, timer, file, global,
or child survives into another run. Within a multi-case run, every case gets a
fresh realm and fresh module instances; case order and generator state are
committed.
The worker exposes a small versioned set of language primitives and explicitly
selected stubs. It does not expose `process`, `require`, host `console`, timers,
`fetch`, sockets, filesystem APIs, `Buffer`, worker APIs, native bindings, or
ambient environment variables. Date/time, randomness, locale, timezone, and
platform values come only from committed deterministic providers. An
unsupported global or import produces an observed exception; REA does not
substitute a convenient host implementation.
Caller-provided stubs are executable untrusted code and receive the same
sandbox treatment as recovered modules. Built-in stubs have stable IDs,
versions, canonical source digests, and documented semantics. No undeclared
fallback stub is allowed.
Inputs are bounded canonical JSON. Results are projected without invoking
getters, proxies, `toJSON`, or arbitrary coercion: only admitted primitives,
arrays, and plain data properties are serialized. Cycles, accessors, functions,
symbols, unsupported prototypes, excessive depth, excessive nodes, and
oversized values become explicit serialization outcomes. Worker stdout is the
framed protocol only; bounded diagnostic stderr and bounded, opt-in console
observations remain separate.
### 6. Enforce independent resource ceilings
Every limit has a conservative product default. The v1 plan and result commit:
- an outer wall-clock deadline for the complete disposable run;
- cgroup memory, swap, task, and CPU ceilings;
- Node/V8 heap ceiling as defense in depth;
- private tmpfs bytes;
- serialized worker-protocol bytes, aggregate module bytes, and case-input
bytes; preset-generated cases also have a fixed preflight count ceiling;
- stdout, stderr, exception, stack, and aggregate retained-output bytes; and
- structured-result depth and node count.
The parent enforces protocol and output limits while bytes arrive, before JSON
parse or Evidence retention. The worker cannot request wider limits. A limit
hit terminates the complete run cgroup and is an observed termination, not a
partial successful return.
### 7. Preserve exact provenance and the right Evidence authority
A run that reaches worker admission produces Evidence with:
- provider `rea-javascript-replay` and a concrete implementation version;
- operation `run_controlled_replay`;
- authority `controlled-replay`;
- confidence `observed` for the exact returned value, thrown exception,
sandbox denial, limit termination, signal, exit, or crash that REA directly
observed;
- environment isolation `container`, the host platform/architecture, runtime
identity, sandbox-backend identity, and sandbox-policy digest;
- the replay plan digest, module and stub digests, canonical input or generated
case digests, deterministic providers, and every effective limit;
- bounded raw input, output, and exception data when retained, plus their
canonical digests and truncation state;
- start/admission/termination/cleanup states; and
- explicit limitations for incomplete output, nondeterminism not checked,
sandbox diagnostics, or cleanup that could not be proven.
The host module path remains an actionable local diagnostic and Evidence
subject location, while the worker sees only a stable alias. Module source is
not embedded in ordinary Evidence. A separately approved reproducer may copy
module/stub bytes or may retain path-plus-digest references; its manifest says
which mode was used. Repository tests use source-owned fixtures, and real-app
verification stores only digests and expected structural facts.
Derived differential results use confidence `derived` and link every source
run Evidence ID. A repeat with the same commitment can establish
`repeat-confirmed` for those runs; a single deterministic plan is only
`committed-not-confirmed`. Neither state proves behavior in the original
application.
When replay observations are added to the JavaScript Application Graph, their
graph-fact authority is `controlled-replay`. A claim that the real renderer,
preload, main process, or remote service behaves the same remains inferred or
unknown until compatible runtime authority exists. Static inference, passive
CDP observation, controlled replay, and real application interaction are never
promoted into one another.
### 8. Treat post-admission failures as observations
Pre-admission failures return a typed error and create no claim that module code
ran. Once the worker is admitted, REA retains a bounded execution record even
when the requested function does not return normally.
| Condition | Caller result and Evidence semantics |
| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
| Disabled capability or missing grant | `permission_required`/`capability_unavailable`; no worker admission and no replay observation |
| Sandbox/runtime probe failure | `capability_unavailable` with exact failed feature; no module execution |
| Plan digest mismatch or changed source | `plan_stale`; no module execution |
| Sandbox setup fails before worker admission | `execution_failure`; no controlled-replay claim about the module |
| Module returns admitted data | Observed return value with complete or explicitly limited coverage |
| Module throws or result serialization rejects | Successful replay observation with outcome `exception` or `serialization_error`; application claim unknown |
| Node permission or sandbox denies an operation | Observed denial/termination when attributable; no claim that all attempted side effects were enumerated |
| Timeout, memory, CPU, task, tmpfs, or output hit | Observed limit termination; requested functional result unknown |
| Signal, runtime crash, or malformed protocol | Observed termination plus bounded diagnostics; functional result unknown |
| Caller cancellation after admission | Kill full cgroup, record cancellation/cleanup if possible, and project the public cancellation contract |
| Cleanup proves an empty cgroup and removed root | `cleanup: complete` |
| Cleanup cannot prove emptiness or removal | `cleanup_incomplete`, name every residual resource, and do not report success |
An exception is data, not an adapter failure. A sandbox setup error is not
evidence that the module crashed. A timeout is not evidence that the function
would never return. An output limit is not evidence that the truncated prefix
equals the full result. These distinctions are part of the public contract.
Cancellation and cleanup must be idempotent. REA first stops admission and
input, kills the owned cgroup, waits for an empty-cgroup observation, removes
the private runtime root, closes protocol descriptors, and releases timers.
Failure at one cleanup step does not skip the remaining steps.
### 9. Keep replay records reproducible without overstating determinism
The canonical replay manifest commits:
```text
plan structure and policy identity
REA/provider/runtime/sandbox executable identities and digests
module aliases, dependency graph, bytes digests, and source references
stub IDs, versions, source digests, and caller-provided stub digests
canonical inputs or generator algorithm, seed, case order, and case digests
clock, PRNG, timezone, locale, platform, and exposed-global commitments
all resource and serialization limits
network and filesystem projections
expected entry export and invocation convention
```
The result manifest adds canonical output/exception/termination digests,
coverage, dropped-data counts, cleanup state, and source Evidence links.
Canonical digests are computed by the trusted parent; worker-provided digests
are ignored.
Reproduction requires exact manifest compatibility. A runtime, sandbox policy,
built-in stub, module byte, generated case, limit, architecture, or platform
change is a different experiment. Cross-environment comparison may still be a
derived investigation, but it is never an exact replay.
### 10. Expose availability and policy truth before execution
`rea doctor`, capability inventory, and the planning response must report the
JavaScript replay capability without executing application code. Diagnostics
name the exact missing executable, unsupported host, failed namespace feature,
cgroup delegation failure, setuid rejection, runtime mismatch, or cleanup-probe
failure. Genuine secrets remain redacted; local executable paths, versions,
digests, and kernel feature failures remain visible.
The capability must be absent from executable tool routing until implemented.
Accepting this ADR does not increase the current tool count and does not add a
hidden experimental flag.
## Required implementation and verification gate
The implementation PR cannot merge until all of the following are true:
1. `javascript_replay` exists in configuration, permission policy, project
grants, policy explanation, CLI, MCP, docs, and capability inventory with
fail-closed defaults.
2. Plan and execute phases have schema-identical CLI/MCP behavior and an exact
plan-digest stale check.
3. No replay-disabled static, browser, Electron, session, setup, doctor, or
application workflow can reach module execution.
4. The worker never imports into the REA server process and no adapter offers a
`vm`-only fallback.
5. The Linux backend feature-probes namespaces, seccomp installation and
denial, delegated cgroup v2 limits, and the exact admitted architecture.
Every plan content-addresses the worker, seccomp filter, Node executable,
ELF loader, shared-library closure, and sandbox executables.
6. Source-owned fixtures cover parser, sanitizer, clipboard, exception,
ambient side-effect attempts, memory pressure, and busy loops. The worker
exposes no filesystem, environment, network, process, worker, native-addon,
timer, inspector, or ambient package-resolution API.
7. Tests and the real verifier prove bounded protocol/diagnostics, timeout and
OOM cgroup termination, and observed cgroup cleanup.
8. Evidence tests cover observed return/exception/termination, derived
comparison with source Evidence links, stale admission, cancellation
projection, and explicit limitations on application-level claims.
9. Package verification exercises the target-free public contract. The
dedicated real-Linux workflow exercises the sandbox backend; environments
without delegated user namespaces or cgroups report truthful unavailability
rather than selecting a weaker backend.
10. A real operator-local Notion-like parser or sanitizer benchmark can run
without committing its source, and exports only approved local reproducer
material.
## Rejected alternatives
### Reuse `browser_observe`, `electron_observe`, or `process_capture`
Rejected because those grants authorize different effects. Reuse would turn a
passive or unsandboxed process permission into recovered-code execution.
### Execute in the MCP server with `vm.runInContext`
Rejected because a VM context is not a security boundary and a crash, resource
attack, or escape would compromise the long-lived session and its credentials.
### Use only the Node.js permission model
Rejected because Node.js documents it as a seat belt for trusted code and
explicitly does not guarantee containment of malicious code. It remains a
defense-in-depth layer inside the OS sandbox.
### Ship a process-only fallback on unsupported hosts
Rejected because it changes the security claim while preserving the same tool
name. Unsupported hosts return unavailable.
### Permit network allowlists in v1
Rejected because DNS, redirects, proxies, credentials, service identity, and
response nondeterminism would substantially expand the threat and Evidence
model. The v1 namespace has no host or external network.
### Mount the approved project root read-only
Rejected because one approved module does not imply authority to disclose
every file in its project. The parent stages only exact, digested bytes.
### Treat exceptions, crashes, or limit hits as ordinary tool errors only
Rejected because that discards the principal behavioral observation and makes
negative results impossible to reproduce. Post-admission termination is
retained with explicit functional uncertainty.
## Consequences
- JavaScript replay is Linux-only at first and may be unavailable on containers
or distributions that disable user namespaces or cgroup delegation.
- The implementation requires more host probing and lifecycle code than a
simple Node worker, but the public security claim remains stable.
- Plans require two calls in non-interactive environments and become stale when
any committed input changes.
- Network-dependent modules and full application interactions are excluded;
their absence is explicit rather than emulated implicitly.
- Results are reproducible for the committed isolated experiment, not proof of
production behavior.
- Adding another sandbox backend, network mode, or application-interaction mode
requires a separate reviewed decision and conformance suite.
## References
- [Node.js permissions](https://nodejs.org/api/permissions.html) documents that
the permission model does not protect against malicious code and describes
its known filesystem and cross-process limitations.
- [Bubblewrap README](https://github.com/containers/bubblewrap/blob/main/README.md)
describes its namespace construction and makes clear that the caller's
arguments, not Bubblewrap alone, define the sandbox security model.
- [Linux seccomp filter documentation](https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html)
explains that syscall filtering reduces kernel surface but is not a complete
sandbox by itself.
- [ADR-0001](0001-provider-selection-and-analysis-profiles.md) establishes the
existing rule that provider selection, Evidence provenance, and capability
unavailability remain explicit and never silently fall back.
@@ -1,452 +0,0 @@
# ADR-0003: Managed-code evidence and provider boundary
> Historical design record: The non-executing runtime-correlation planning
> tool described in earlier revisions was removed. This ADR's current
> implementation status below covers only the static managed tools that ship.
- Status: Superseded for runtime planning; static evidence boundary remains in force
- Date: 2026-07-16
- Implementation status: Read-only PE/CLI triage and exact identity are shipped
through `inspect_managed_artifact` / `rea inspect-managed-artifact`. Bounded
metadata, signatures, method bodies, raw CIL hashes, limited
decoded-instruction-tuple v1 hashes, exception regions, call edges, and
field-access anchors are shipped through `inspect_managed_members`; `rea
inspect-managed-members` provides CLI parity. Static member comparison and build-local
token remapping are shipped through `compare_managed_members` /
`rea compare-managed-members`. Declaration-only managed/native boundary
inventory for ModuleRef, ImplMap/PInvoke, ReadyToRun indicators, and non-IL
method flags is shipped through `inspect_managed_native_boundaries` /
`rea inspect-managed-native-boundaries`. Managed/native export or function
Evidence matching is shipped through `verify_managed_native_boundaries` /
`rea verify-managed-native-boundaries`; it verifies only supplied P/Invoke
export/function observations and does not map managed tokens to native
addresses. Decompiler reconstruction import is
shipped through `import_managed_reconstruction` /
`rea import-managed-reconstruction`; it records user-supplied C#/IL/pseudocode
as analyst inference only after exact static member locks match. Managed
inspection does not execute assemblies or observe CLR internals. Managed static graph
projection is shipped through
`project_managed_application_graph` /
`rea project-managed-application-graph`; it projects authenticated managed
Evidence into the application graph without changing managed tokens into
native addresses. Native-body bridge mapping and an actual runtime executor
remain future contracts.
## Context
Professional C# reverse engineering is not one decompiler operation. A file
described as “.NET” can be ordinary Common Intermediate Language (CIL),
ReadyToRun code containing both CIL and native implementations, a single-file
deployment, C++/CLI mixed mode, Unity Mono, Unity IL2CPP, or NativeAOT. Those
forms have different sources of truth and different native-analysis needs.
Choosing a decompiler before classifying the artifact can therefore produce a
plausible but false model.
The durable static facts in an ordinary managed PE are its PE/CLI headers,
metadata tables, signatures, method bodies, exception regions, and CIL. A C#
decompiler reconstructs source-like control flow and language constructs from
those facts. That reconstruction is valuable, but it is not the original
source and cannot replace the underlying metadata and CIL evidence. Obfuscation
makes names especially weak while tokens remain coordinates in only one build.
REA already separates one selected deep native provider from disjoint auxiliary
providers under [ADR-0001](0001-provider-selection-and-analysis-profiles.md).
It also separates static evidence, passive observation, process capture, and
interactive observation authorities. Managed analysis must fit those boundaries
without requiring a CLR to inspect an artifact, loading target code into the
REA process, or treating a managed token as a native address.
The design is informed by exact-build, reflection-free metadata extraction,
hash-locked method manifests, independent behavior models, and managed/native
boundary analysis performed against a local C# application. The application,
its decompiler output, and its runtime observations are research inputs only;
they are not distributable REA fixtures.
## Decision drivers
1. Classify the deployment before selecting an analysis route.
2. Make metadata and CIL independently inspectable without a CLR or target
execution.
3. Preserve exact-build provenance while enabling structural comparison across
builds whose MVIDs, tokens, names, and layout differ.
4. Compose managed and native analysis without introducing another ambiguous
deep-provider candidate.
5. Keep decompiled C# useful but epistemically subordinate to canonical bytes.
6. Analyze Linux, macOS, and Windows managed artifacts through the same local
CLI/MCP contracts on REA's supported hosts.
7. Keep setup additive and prevent managed analysis from installing .NET,
ILSpy, an SDK, or another unrelated toolchain.
8. Prove semantics with source-built conformance artifacts and compact,
operator-local real-application checks.
## Terminology
- **Managed artifact**: a PE, bundle component, or related metadata artifact
that carries a CLI header, CLI metadata, CIL, or another managed-runtime
commitment.
- **Classification vector**: independently observed container, runtime family,
implementation form, and architecture. It is not one guessed label.
- **Canonical static observation**: a bounded value decoded directly from the
target bytes under a versioned parser contract.
- **Reconstruction**: source-like output, including decompiled C#, derived from
canonical observations.
- **Structural inference**: a relationship or cross-version match derived from
signatures, APIs, constants, control/data-flow shape, or other observations.
- **Validation**: an independently checked proposition, for example a
source-built oracle assertion or a behavior-model corpus result.
- **Runtime observation**: a separately authorized fact obtained by attaching,
loading, debugging, instrumenting, or otherwise executing code.
## Decision
### 1. Classify before analyzing
Managed triage returns a classification vector and the observations supporting
each dimension. Absence of a marker produces `unknown` or `not_applicable`, not
an invented runtime family.
| Dimension | Initial values |
| ------------------- | ------------------------------------------------------------------------------------------------------------ |
| Container | PE file, single-file bundle, bundle component, Unity metadata pair, native image, malformed, unknown |
| Runtime family | .NET Framework, modern .NET, Unity Mono, Unity IL2CPP, NativeAOT, mixed CLR/native, unknown |
| Implementation form | CIL, CIL plus ReadyToRun, native only, C++/CLI mixed, metadata only, unsupported, unknown |
| Architecture | PE machine plus CLI flags; component-specific architecture for bundles; conflicting or unknown when required |
Target-framework attributes, assembly references, metadata stream versions,
bundle manifests, ReadyToRun directories, and native headers are observations.
They may support a runtime-family inference, but no single string is treated as
authoritative when the other bytes conflict.
Classification selects these routes:
| Observed form | Managed route | Native route and limitation |
| --------------------------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
| Ordinary Framework or modern CIL | Full metadata, signatures, method bodies, and CIL | Optional only for declared interop boundaries |
| Obfuscated CIL | Same canonical route; names receive no special trust | Optional for declared interop boundaries |
| Unity Mono assembly | Same canonical route with Unity context retained | Optional for engine/native boundaries |
| ReadyToRun | Metadata/CIL where present; implementation availability is per method | Selected Hopper/Ghidra analyzes native sections; CIL absence is reported per method |
| C++/CLI mixed mode | Metadata/CIL for managed members and explicit mixed-mode boundary observations | Selected Hopper/Ghidra analyzes native bodies; REA never converts tokens directly to native addresses |
| Single-file deployment | Inventory the bundle, then analyze each authenticated managed component | Selected Hopper/Ghidra analyzes the host/native components; unsupported compression remains explicit |
| Unity IL2CPP | Pair and authenticate available Unity metadata; do not claim canonical CIL | Selected Hopper/Ghidra analyzes the generated native binary; semantic recovery is degraded until supported |
| NativeAOT | Report any independently present managed metadata, otherwise no CIL claim | Treat as a native target with NativeAOT provenance; managed source reconstruction is unavailable |
| Malformed or unsupported artifact | Return bounded partial observations and typed unavailable/unknown scopes | Do not silently retry by loading or executing the file |
Classification is byte-driven and bounded. File extensions, product names,
process names, and an operator's description are hints only.
### 2. Implement managed static analysis as a disjoint auxiliary provider
The initial producer is a REA-owned auxiliary provider with ID
`rea-dotnet-static`. It owns a disjoint managed-artifact operation family. It is
not registered as a Hopper/Ghidra deep-provider candidate because it does not
compete for the same operation names and must be able to coexist with the one
selected native provider.
```text
one opened artifact/session
|
SessionProviderRouter
/ \
rea-dotnet-static auxiliary selected deep binding
PE/CLI metadata and CIL Hopper or Ghidra
\ /
explicit managed/native links
|
Evidence and workflows
```
An ordinary managed artifact can therefore remain unbound to a deep native
provider while managed operations work. ReadyToRun, C++/CLI, IL2CPP, NativeAOT,
and interop workflows may additionally require a caller-selected native
binding. Native-provider failure never causes managed evidence to be relabeled,
and managed-parser failure never causes an implicit native fallback.
Provider mechanics live under a provider directory such as `src/dotnet/`.
Provider-neutral identities, evidence states, and bounded values may live in
the domain/contracts layers. Application code composes results but does not
parse PE headers, metadata tables, signatures, CIL, ReadyToRun headers, or
provider-specific output.
### 3. Make the production static path byte-only and execution-free
`rea-dotnet-static` reads approved local bytes and implements the required
PE/CLI metadata and CIL subset in TypeScript. It does not call any reflection
API and does not require the .NET runtime. In particular, static inspection
must never:
- call `Assembly.Load`, `Assembly.LoadFrom`, `ReflectionOnlyLoad`, or an
equivalent runtime loader;
- resolve target dependencies by executing target-controlled resolver code;
- run module initializers, constructors, entry points, build tasks, plugins, or
generated helpers;
- start the target, attach to a process, contact a service, or inherit target
configuration and credentials; or
- interpret a decompiler, CLR, or native-provider diagnostic as an observation
from the artifact bytes.
The parser uses checked offsets and additions, explicit endianness, bounded
table/heap/body counts, cycle-safe traversal, and typed partial results. A bad
row, signature, body, resource, or stream does not authorize an unbounded retry
or a CLR load. Complete-coverage claims require every applicable bounded region
to have been admitted; otherwise coverage is partial, unknown, or unavailable
with exact offsets and reasons.
The caller selects the local input path directly. Local artifact
paths, digests, MVIDs, tokens, malformed offsets, and analysis metadata are
actionable diagnostics and are not secrets. Credentials, authorization data,
and genuine secrets remain redacted.
### 4. Bind every finding to exact artifact and producer identity
Every managed result carries a commitment with at least:
```text
artifact: canonical path + byte length + SHA-256
component: container identity + component path/name + component SHA-256, when applicable
classification: container + runtime family + implementation form + architecture
assembly/module: simple name + version + culture + public-key identity + module name + MVID
producer: provider ID + exact version + analysis-affecting parameters + profile digest
```
An assembly-qualified name does not replace the artifact digest or MVID.
Neither an MVID nor an Authenticode signature proves who authored the behavior.
Bundle components retain both their container and component commitments so that
bytes extracted from another host cannot be silently substituted.
Method observations add:
```text
declaring type + normalized CLI signature
build-local metadata token
RVA/file extent when present
raw CIL byte length + SHA-256 when the body is admitted
decoded-instruction-tuple SHA-256 when CIL is valid
separate max-stack, locals-token, and exception-region observations
```
The shipped `il_sha256` commits only the raw CIL byte stream identified by the
method header's `il_size`. It does not commit the method header, local-signature
blob, alignment padding, or extra sections such as exception clauses. Those
facts remain separate observations and the enclosing artifact SHA-256 binds
them to the exact file. A digest over the complete method body is not shipped.
The caller-visible field remains named `normalized_il_sha256`, but its shipped
v1 meaning is deliberately narrower than a canonical semantic CIL identity.
For a completely decoded method, REA serializes the instruction-order array of
`[opcode, operand_kind, operand]` tuples with JavaScript `JSON.stringify`,
encodes that text as UTF-8, and reports its lowercase SHA-256. The tuple
projection is defined here; the member result carries only the described
normalized digest.
Operands retain the current decoder projection: metadata and user-string
operands are build-local lowercase hexadecimal tokens, scalar branch operands
are decimal target CIL byte offsets, and `switch` retains only its decimal case
count. Constants and variable indexes are decimal strings; an operand-free
instruction uses kind `none` and value `null`. Opcode names preserve distinct
short forms and prefix instructions, but instruction offsets, branch target
instruction identity, switch targets, resolved token identities, method
headers, locals, and exception regions are not part of this digest. A partial
or malformed decode has no `normalized_il_sha256`.
Consequently v1 is a deterministic decoded-tuple fingerprint, not proof of
semantic equivalence. In particular, methods with the same opcodes and switch
case counts can share it despite different switch targets, and token movement
can change it without a semantic change. Cross-build comparison may use it as
one unique-only structural tier while retaining artifact/MVID commitments and
ambiguity; it must not describe the digest itself as token-remapped canonical
CIL. Canonical operand resolution, complete control-flow operands,
exception/local commitments, and an explicit algorithm version require a new
normalized-CIL schema.
Metadata tokens are reported because they are precise coordinates inside one
module. Cross-version identity never consists of a token alone. Matching tries
exact CIL/signature identity, then an exact declared-type/name/signature tuple,
then structural shape; a name by itself never selects a pair. Partial or
malformed bodies leave body facets unknown after a signature tuple pairs the
methods. Matches cite both build commitments, both local tokens, and all
competing candidates. V1 cannot cite a separate matching-algorithm version
because none is exposed.
### 5. Separate five evidence layers
Managed workflows retain these layers independently:
| Layer | Examples | Permitted claim |
| ---------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------- |
| Static observation | Metadata row, signature, CIL opcode, literal, exception region | “These bounded bytes decode to this value.” |
| Reconstruction | Decompiled C#, async/iterator source shape, expression simplification | “This is one source-like representation of cited observations.” |
| Structural inference | Likely caller, field flow, behavior slice, cross-build method match | “These cited structures support this relationship.” |
| Independent validation | Synthetic oracle, corpus result, second parser agreement | “This declared proposition passed the named independent check.” |
| Runtime observation | Exact-build attach/load/instrumentation event | “This separately authorized experiment observed this event.” |
Each layer has its own producer, authority, state, confidence, coverage, and
limitations. A readable C# method is never emitted as original source or exact
semantic proof. A validator does not upgrade unrelated claims. Runtime
agreement does not retroactively turn a static inference into an observation.
Negative results are scope-qualified. For example, “no declared P/Invoke rows
were found in the admitted metadata tables” does not prove the application has
no native, dynamically resolved, generated, server-side, or protected path.
### 6. Admit ILSpy only as an optional reconstruction and conformance tool
REA's canonical static operations do not depend on ILSpy, a .NET SDK/runtime,
dnlib, or Mono.Cecil. The following review was current on the decision date:
| Tool | Reviewed coordinate | License | Runtime/host observation | Decision |
| ---------------------------- | ------------------- | ------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `System.Reflection.Metadata` | 10.0.10 | MIT | Library targets .NET Framework 4.6.2, .NET 8/9/10, and .NET Standard 2.0 | Pinned independent metadata oracle for conformance; not shipped or invoked by production parsing |
| `ICSharpCode.Decompiler` | 10.1.1.8388 | MIT | Library targets .NET Standard 2.0; output is reconstruction | Pinned reconstruction/differential oracle candidate |
| `ilspycmd` | 9.1.0.7988 | MIT | Cross-platform .NET 8 tool; newer 10.1.1.8388 requires .NET 10 | Initial optional BYO reconstruction coordinate because it matches the source research baseline |
| dnlib | 4.5.0 | MIT | Cross-platform library; also exposes assembly-writing APIs | Differential test candidate only; its writable model is outside the production trust boundary |
| Mono.Cecil | 0.11.6 | MIT | Cross-platform .NET Framework/.NET Standard library with read/write support | Differential test candidate only; not a production dependency |
Coordinates and package hashes used by real verification are checked into a
source-owned lock manifest when that verifier is implemented. “Latest” is
never a reproducibility coordinate. A version change requires conformance and
an explicit profile/version change.
Artifact platform and REA host support are separate. The byte-only parser must
inspect PE/CLI artifacts produced for Windows on a supported Linux or macOS REA
host; that is not a claim that REA itself currently runs on Windows. Managed
library/tool candidates above are cross-platform at their reviewed targets, but
native composition remains limited by the selected Hopper/Ghidra host and
format support. Real verification runs the canonical path on Linux and macOS
and may run pinned oracle checks on Windows without turning that development
check into a public Windows-host claim.
If a caller-visible C# reconstruction operation is admitted, it is a distinct
optional capability. It accepts only an exact supported BYO `ilspycmd`, records
the tool and decompiler version, runs in an owned bounded process without
loading target code into REA, and links output to the canonical method
observation. Setup and installers do not download or install ILSpy, .NET, an
SDK, or a runtime. Doctor may inspect an explicitly configured executable and
report exact actionable incompatibility. Missing reconstruction never removes
canonical metadata/CIL capabilities.
This decision does not make a decompiler process a security sandbox. The
initial public path can defer C# reconstruction while canonical contracts and
process isolation are proven.
### 7. Use source-built conformance and operator-local real targets
The repository stores source, build descriptions, expected semantic facts,
and tool lock manifests, but not compiled managed binaries. An isolated build
step creates fixtures outside source directories and records their SHA-256 and
MVID before verification. At minimum, the corpus covers:
- Framework-compatible and modern .NET metadata;
- AnyCPU, x86, and x64 PE/CLI flags;
- generics, nested types, overloaded signatures, properties, events, resources,
attributes, and constants;
- exceptions, filters, prefixes, switch branches, P/Invoke, async and iterator
state machines;
- obfuscated and Unicode names without assigning semantics from names;
- malformed headers, tables, heaps, signatures, bodies, and exception regions;
and
- two semantically related builds with different MVIDs, tokens, layout, and
selected names.
Expected facts are checked directly and against pinned
`System.Reflection.Metadata`; ILSpy, dnlib, or Mono.Cecil may add differential
coverage but do not vote by majority. Disagreement is a failing or explicitly
unsupported case, not silently normalized output.
The real-application benchmark is an operator-local, opt-in osu! check derived
from the research workflow. It accepts an explicit path plus a compact
expectation manifest; verifies target SHA-256, MVID, architecture, and expected
assembly identity before analysis; and emits only bounded identities, tokens,
signatures, IL lengths/hashes, match states, and assertion results. It does not
emit full IL, decompiled source, runtime logs, user data, credentials, or
service/account material. No proprietary binary, hash-locked application
manifest, or derived dump is committed to REA.
### 8. Keep runtime behavior separate from static managed analysis
No managed runtime planning or execution tool ships. Managed inspection does
not execute assemblies or establish which methods ran. Where supported, direct
process capture can record target-level inputs and outputs, but it does not
prove CLR method execution or resolution. Internal managed behavior remains
unknown until independently observed with suitable runtime evidence.
## Public contract consequences
- Managed static operations will have CLI and MCP parity and produce the same
Evidence commitments.
- Adding managed operations changes the caller-visible tool inventory and
generated product catalog only in the implementation PR that admits them.
- Partial parsing includes admitted/dropped counts, exact limitations, and
coverage; it never returns a partial list labeled complete.
- Managed addresses distinguish file offsets, RVAs, native virtual addresses,
metadata tokens, and CIL offsets. They are not interchangeable.
- Cache compatibility is exact on artifact/component commitment, member-result
fields, parser profile, and producer version. For shipped v1,
`normalized_il_sha256` has no independent algorithm-version field.
- Provider-neutral workflows may compose canonical managed findings with the
one native binding, but every source operation retains its actual producer.
## Alternatives rejected
### Make ILSpy the only managed provider
This would make canonical metadata/IL inventory depend on a separately
installed CLR and conflate source reconstruction with byte observations. It
would also make tool-version drift part of ordinary inventory. ILSpy remains a
valuable optional reconstruction and conformance tool instead.
### Use `Assembly.Load` or reflection-only loading
Both delegate parsing and dependency behavior to a CLR and make static support
runtime-dependent. Ordinary loading can execute target code; reflection-only
loading still establishes a CLR load boundary and is unavailable across modern
runtimes in a uniform way. Neither is required to decode ECMA-335 bytes.
### Register the managed analyzer as another deep candidate
That would force callers to choose managed analysis instead of Hopper/Ghidra
for ReadyToRun and mixed-mode artifacts even though both are needed. Disjoint
auxiliary composition represents the real ownership boundary.
### Treat tokens, names, or decompiler output as durable identity
Tokens and obfuscated names change across builds, while decompiler output
changes across tools and versions. They remain useful build-local coordinates
or reconstruction labels but are insufficient for exact or structural
cross-version identity.
### Package a .NET runtime or mutable managed library in REA
This would expand installer effects, package size, patching obligations, and
the target-parsing attack surface. The initial byte parser keeps canonical
support within REA's existing Node runtime; external managed tools remain BYO
or development-only oracles.
## Rollout gates
1. Add read-only triage and identity with malformed-input bounds. Shipped.
2. Add metadata, signatures, method bodies, deterministic decoded-CIL tuple
fingerprints, and exact artifact Evidence. Shipped with the v1 limitations
above; full normalized-CIL semantics remain planned.
3. Add obfuscation-resistant slices and cross-build match states. Shipped.
4. Compose explicit managed/native boundaries with Hopper/Ghidra. Declaration
inventory and native export/function Evidence matching shipped; native-body
bridge mapping remains planned.
5. Add source-built, pinned real-tool, package, CLI, and MCP conformance.
Source-owned conformance is shipped; pinned external real-tool checks remain
planned.
6. Project authenticated managed static Evidence into the application graph.
Shipped.
Every gate must keep unsupported ReadyToRun, NativeAOT, IL2CPP, mixed-mode, or
bundle cases explicit rather than broadening claims to make a fixture pass.
## References
- [ECMA-335: Common Language Infrastructure](https://ecma-international.org/publications-and-standards/standards/ecma-335/)
- [.NET ReadyToRun deployment overview](https://learn.microsoft.com/en-us/dotnet/core/deploying/ready-to-run)
- [.NET Native AOT deployment overview](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/)
- [.NET single-file deployment overview](https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/overview)
- [`System.Reflection.Metadata` package](https://www.nuget.org/packages/System.Reflection.Metadata/10.0.10)
- [ILSpy repository and releases](https://github.com/icsharpcode/ILSpy)
- [dnlib repository](https://github.com/0xd4d/dnlib)
- [Mono.Cecil repository](https://github.com/jbevain/cecil)
-11
View File
@@ -1,11 +0,0 @@
# Architecture decision records
Accepted decisions describe the architecture that implementation PRs must
follow. Acceptance does not by itself mean the behavior is shipped; each record
states its implementation status separately.
| ADR | Status | Implementation |
| ------------------------------------------------------------------------------------------------------------------ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| [0001: Provider selection and analysis profiles](0001-provider-selection-and-analysis-profiles.md) | Accepted | Provider selection and 25 read-only Ghidra operations on Linux/macOS and experimental Windows x64 P0; Linux/macOS session annotations |
| [0002: Controlled JavaScript replay authority and sandbox policy](0002-controlled-replay-authority-and-sandbox.md) | Superseded | Historical design; the controlled JavaScript replay tool was removed |
| [0003: Managed-code evidence and provider boundary](0003-managed-code-evidence-and-provider-boundary.md) | Partially superseded | Seven static managed tools remain; runtime planning removed |
+82 -4
View File
@@ -23,10 +23,37 @@ export REA_JADX_MCP_JAR=/absolute/path/jadx-headless-mcp-0.7.1-all.jar
export JAVA_HOME=/absolute/path/existing-jdk
```
On Windows x64, use a REA package with its matching bundled Windows native
controls **including owned protocol stdin support**. This Windows boundary is
new on repository main; an older released package can still reject this host.
PowerShell accepts paths containing spaces without additional escaping
inside these environment values:
```powershell
$env:REA_JADX_MCP_JAR = 'D:\tools\jadx-headless-mcp-0.7.1-all.jar'
$env:JAVA_HOME = 'D:\tools\jdk-21'
rea inspect-android-package 'D:\targets\Example.apk'
```
REA selects `JAVA_HOME\bin\java.exe`, or resolves `java.exe` on the selected
Windows `PATH`. A missing or mismatched native artifact reports the package
prerequisite rather than attempting an unowned Java launch. Windows arm64 is
outside this provider's current native boundary.
Readiness checks the selected JAR's ZIP directory for the classes consumed by
REA's metadata bridge, as well as Java's compiler and version modules. It does
not load an APK or execute engine code. Invalid archives and missing bridge
classes report JAR-specific recovery; classpath inventory alone does not prove
that every class or engine operation will load successfully. Discovery limits
each ZIP metadata read to 8 MiB before allocation; a larger directory reports
the exhausted read budget and the selected JAR path.
The current metadata bridge is verified on macOS arm64 with OpenJDK 21 and the
public Appium ApiDemos fixture. The POSIX adapter also supports Linux; the new
bridge has not yet undergone real verification on Linux/JDK 25.
Windows is unsupported for this provider's owned stdio process boundary.
Windows x64 uses an owned Job Object with bidirectional stdio, atomic job
assignment and kill-on-owner-close. Real Windows verification uses JDK 21 and
the pinned JADX 0.7.1 JAR; see the real verification lane below.
## Answer an analyst question
@@ -91,10 +118,25 @@ selected overload. Native/abstract methods with no decompiled body report
responses remain in Evidence. Source revision is populated only for bytes
matching the audited release JAR.
If a later step fails, the error's `details.partial_observation` retains the
selected and resolved APK paths, digest, observed provider identity and versions,
and each upstream request and reply collected before the failure. Failed replies
remain available even when their payload cannot be interpreted. Cancellation
also stops target hashing before provider admission.
These operations do not execute the APK or provide split APK/AAB handling,
signature validation, full resource-table semantics, native-library analysis or
Android runtime capture. Existing artifact inventory/extraction tools can supply
archive evidence. Project that Evidence with the execution-free inventory tool:
Android runtime capture. An `.aab` suffix is a ZIP archive, not an APK, so
Android tools and the application graph do not treat it as a standalone APK.
Existing artifact inventory/extraction tools can supply archive evidence.
Inventory records an APK root only for ZIP bytes whose name ends in `.apk`.
The projection adds a limitation when no root `AndroidManifest.xml` was
observed, because such a ZIP may not be an APK. Nested members take a ZIP or
ASAR family from their bytes; an unread member keeps an unknown format.
Inventory keeps ZIP names that differ only in case and records that a
case-insensitive destination cannot store both spellings. Extraction fails
only when that destination directory cannot keep both names. Project that
Evidence with the execution-free inventory tool:
```sh
rea project-android-application-graph '{"inventory_evidence":[<inventory_artifact Evidence>]}'
@@ -111,7 +153,19 @@ rea project-android-application-graph '{"inventory_evidence":[<inventory_artifac
The projection reports exact component paths and hashes, runtime-family hints,
and path-based bridge hypotheses. It does not decode DEX or claim observed
runtime calls.
runtime calls. Framework hints match complete native library names, such as
`libreactnativejni.so`, `libreactnative.so`, `libhermes.so`,
`libhermes_executor.so`, `libflutter.so`, and `libunity.so`; unrelated names
such as `libcommunity.so` and `libreactivity.so` do not identify those families.
The bridge basis is inferred from the native path and repeated for each managed
component, so it does not identify a specific JNI binding. Bridge hypotheses form a DEX/JVM-class by native-library
Cartesian product. The projection computes the product and exact serialized
candidate-array size before creating candidate objects, then retains a
deterministic prefix within a 2 MiB UTF-8 JSON budget. If candidates are omitted,
`bridge_candidate_coverage` reports total, emitted, and omitted counts; overall
coverage is `partial` while component arrays still include every component
from the supplied inventory pages. A path pair does not establish that a
managed declaration names, loads, or calls the native library.
## Resource and lifecycle limits
@@ -123,6 +177,19 @@ target/configuration changes, failure, timeout, cancellation, MCP disconnect or
server shutdown. One-shot CLI commands always join cleanup before returning.
REA never writes to the original APK or launches target code.
On Windows, stdin writes preserve stream backpressure and run outside the Node
event loop. Cancellation terminates the retained job, including descendants,
before workspace cleanup. An abrupt CLI/server process termination closes the
job and stops Java, but cannot run JavaScript workspace cleanup; temporary
workspace files can remain after that forced exit.
If Java cannot start the bridge, REA reports the selected executable and retained
startup diagnostics. Select a full JDK through `JAVA_HOME` or `PATH`, and use
`java --list-modules` to confirm `jdk.compiler` is present. A runnable JRE alone
cannot compile the bridge. Missing or ambiguous class and method selections are
input failures; discover names with `search_android_classes` and
`inspect_android_class` before correcting the selected argument.
If process cleanup cannot be confirmed, REA retains the workspace and reports its
location. That provider instance blocks subsequent engine launches until the
caller resolves the reported resources and starts a fresh instance.
@@ -170,6 +237,17 @@ export REA_ANDROID_TEST_APK="$PWD/_reference/apk-integration/ApiDemos-debug.apk"
npm run verify:android
```
The lane also uses the selected full JDK's `jlink` to create a disposable JRE
without the compiler module. It checks real Java startup failures, missing
selectors, recovery after failures, and CLI cancellation with owned cleanup.
The original APK and host Java configuration remain unchanged.
The same lane runs on Windows x64 with the bundled native controls and a full
JDK. It checks CLI/MCP results, real MCP cancellation and disconnect, and Java
exit after abrupt CLI owner termination. Windows forced termination is checked
separately from the POSIX CLI SIGTERM handler; it does not claim a structured
cancellation result or workspace removal after the owner is forcibly killed.
The download script verifies fixed SHA-256 values, reuses matching files and
refuses to overwrite a different existing file. APK/JAR files live under ignored
`_reference/` and are excluded from package contents. The lane exercises actual
+86
View File
@@ -0,0 +1,86 @@
# Apktool resource decoding
REA decodes Android resource tables and the binary manifest through the
caller's Apktool launcher. This completes the static triad for Android
targets: Java/Kotlin sources through the JADX family, engine-grade
decompilation through JEB, and resources through this family. REA never
installs Apktool or a Java runtime.
## Supply tools
Use Apktool 2.7.0 or newer (verified with 2.7.0) and a Java runtime the
launcher can find. Select the launcher through the environment:
```sh
# Optional: absolute path to the apktool launcher (upstream wrapper or a
# java -jar script); without it, apktool resolves from PATH.
export REA_APKTOOL_COMMAND=/absolute/path/apktool
```
Readiness is `rea inspect-apktool-client`: it runs `apktool --version` and
reports the resolved launcher, its selection source, and its version. A
missing launcher reports `capability_unavailable` with the
`REA_APKTOOL_COMMAND` remediation rather than attempting an installation.
## Answer an analyst question
```sh
rea inspect-apktool-client
rea decode-android-resources /targets/Example.apk
rea decode-android-resources /targets/Example.apk --locale de
rea decode-android-resources /targets/Example.apk --no-strings
```
Equivalent MCP methods are `inspect_apktool_client` and
`decode_android_resources`. The decode request takes `path`, an optional
`locale` (project `res/values-<locale>/strings.xml` instead of the default
table), and `include_strings` (default true). Regional locales such as `pt-BR`
select Android's `values-pt-rBR`; Android qualifiers such as `pt-rBR` and
`b+zh+Hans+CN` may also be supplied directly.
## Interpret the result
- **An owned APK snapshot is digested and decoded.** `target.sha256` and
`target.bytes` bind the observation to the exact APK that was decoded.
- **Metadata comes from apktool.yml as apktool printed it.** Version codes
keep their own spelling (`'7'` versus `7`); `package_name` is read from
the decoded manifest, not inferred.
- **The manifest is the decoded text**, bounded at 512 KiB and reported as
truncated when larger.
- **Strings are projected verbatim.** Escaped entities stay escaped, and
entries containing nested markup (`<b>`, `<xliff:g>`) are counted as
unparsed rather than flattened — the limitation names the count. The
default table is bounded to 2000 entries with partial coverage when more
exist; `locales` lists every `values-<locale>` that has a strings table.
- **Smali is skipped by design** (`apktool d --no-src`): Java-source
recovery belongs to the JADX family. Resource smali edits and rebuild are
a follow-up lane with mutation authority.
- **Workspaces are owned and short-lived.** Decoding happens in a
provider-owned temporary directory that is removed before the result is
returned. The APK snapshot and framework cache both live inside this directory.
If removal fails, the result names the residual path and the provider retains
ownership for a cleanup retry on close, including failed decodes.
## Resource and lifecycle limits
- The decode runs with a 600 s deadline and a 4 MiB output capture budget;
a stopped decode reports `provider_timeout` and exceeded budgets report
`resource_constraint`.
- Manifest reads are bounded to 512 KiB before decoding UTF-8. Strings XML
reads are bounded to 8 MiB; larger documents are skipped with partial
coverage and an explicit limit, rather than reported as missing.
- `decoded_file_count` is capped at 100,000 files; the cap is reported in
the limitations when hit.
- Apktool's own decode failures (`AndrolibException`, directory traversal
refusals) surface as `unsupported_target` with apktool's reason preserved
verbatim.
## Real verification
`npm run verify:apktool -- --apk PATH` exercises both operations against a
real launcher. Record: apktool 2.7.0-dirty (Debian packaging) on Linux with
OpenJDK 25 against a signed aapt2-built probe APK carrying two resource
locales — launcher version, on-disk digest agreement, apktool.yml metadata
(1.2.3, SDK 24–34), manifest package agreement, default and `de` string
tables projected. Parser goldens in the test suite come from the same
decode. See `docs/testing.md` for the lane summary.
+52 -11
View File
@@ -7,6 +7,16 @@ hashes, detected formats, bundle anatomy, runtime-family hints, and path-based
bridge hypotheses. It does not parse plist or CMS semantics or claim observed
runtime calls.
Framework hints match complete path segments such as `React.framework`,
`ReactNative.framework`, `hermes.framework`, `Flutter.framework`, and
`UnityFramework.framework`. Substrings in `Preact.framework`,
`Community.framework`, or `MyApp.framework` do not identify those families.
A generic `App.framework` also does not identify Flutter by itself. Runtime
families remain inventory-derived hints, not observed loading. Generic framework
and dylib paths do not establish Swift or Objective-C; this projection does not
decode language metadata. A bridge basis is inferred from the native path and
repeated for each paired script, rather than proving a particular binding.
```sh
rea project-apple-application-graph '{"inventory_evidence":[<inventory_artifact Evidence>]}'
```
@@ -20,16 +30,35 @@ rea project-apple-application-graph '{"inventory_evidence":[<inventory_artifact
}
```
The result includes every component in each inventory category and every
JavaScript-to-native bridge candidate pair. It has no caller-selected component
budget, prefix truncation, or omitted-count fields. Duplicate inventory pages
are merged by artifact identity and occurrence path; their Evidence IDs remain
attached as source Evidence.
The result includes every component in each inventory category. Bridge
hypotheses are the path-based JavaScript/native pairs within each application
root. To keep their Cartesian expansion bounded, the projection limits the
serialized candidate array to 2 MiB. It computes the pair count and
exact UTF-8 JSON size before creating candidate objects, then retains a
deterministic prefix when the byte budget is exceeded. The result's
`bridge_candidate_coverage` reports total, emitted, and omitted pair counts;
overall coverage becomes `partial` and a limitation explains the omission.
Duplicate inventory pages are merged by artifact identity and occurrence path;
their Evidence IDs remain attached as source Evidence.
Content nodes identify bytes by SHA-256 and report only content-derived formats.
Each occurrence reports its own `artifact_kind`, `artifact_format`, and executable
permission. Identical bytes can therefore appear as a script, resource, or native
addon at different paths without overwriting another occurrence's role. Package
formats such as APK and IPA belong to the occurrence; their ZIP bytes share a
content format. Graph and directory identities use locale-independent Unicode
ordering.
For IPA inventories, archive components outside every application root remain
in the component lists. Their JavaScript and native candidates are grouped with
other unrooted components, preserving the inventory projection's path pairing
semantics without attributing them to an application bundle.
Coverage is `complete-within-inventory` when the supplied pages reconstruct the
complete authenticated inventory, and `partial` otherwise. A partial result
states that absence is unknown. Component and bridge-candidate arrays are still
the complete projection of the inventory that was supplied.
states that absence is unknown. Component arrays remain complete when candidate
hypotheses are omitted; component arrays still include every component from
the supplied inventory pages, and overall coverage is `partial` in that case.
## Application roots
@@ -177,10 +206,22 @@ cache rather than on disk, so REA does not check them against the host.
- `required-load-unresolved`, `weak-load-unresolved`, and `lazy-load-unresolved`.
`LC_LAZY_LOAD_DYLIB` dependencies are resolved but not traversed, because dyld
loads them on first use; an unresolved one is not a launch failure.
- `earlier-rpath-candidate-absent`: a Mach-O placed at an earlier search path
would load first. Whether code-signing library validation would reject it is
not evaluated; use `inspect_signature`.
- `dyld-environment-present`: `LC_DYLD_ENVIRONMENT` search paths are not modeled.
- `earlier-rpath-candidate-absent`: a compatible Mach-O placed at an earlier
modeled search path could take precedence, subject to unmodeled search inputs
and code-signing library validation. These findings do not establish which
image dyld will load; use `inspect_signature` for signing metadata.
- `dyld-environment-present`: preserves observed `LC_DYLD_ENVIRONMENT` entries.
Only an executable root supplies process settings; entries on library and
other non-executable roots do not alter resolution or coverage. Applicable
executable image-selection overrides are not modeled.
Empty dyld settings have different consumers. Modern dyld appends a slash and
image name to ordinary and fallback directory entries, so an empty entry can
search `/child.dylib` or `/Foo.framework/Foo`. REA retains uncertainty for those
unchecked paths; an empty fallback does not preempt an ordinary-search hit.
Empty versioned-directory lists do not scan a directory, and empty suffixes
only repeat the original candidate, so they do not add search uncertainty.
Reported command values are retained in all cases.
`verify:macos-bundle` checks the parser against `otool -l` for every traced
image. It also compares the predicted load order of two process roots with the
+1 -1
View File
@@ -58,7 +58,7 @@ graph TD
end
subgraph "Configuration"
CONFIG["src/config.ts + src/config/<br/>Zod-validated env parsing<br/>provider settings and origins"]
CONFIG["src/config/<br/>Zod-validated env parsing<br/>provider settings and origins"]
end
subgraph "Tests"
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

+58
View File
@@ -84,6 +84,19 @@ uses isolated mode and an owned cache. Exact upstream profiles are recorded in
stack can accompany an unknown (`null`) NX indicator. ET_DYN can be a shared
library, and an absent canary symbol does not prove every function unprotected.
When complete layout Evidence is already retained, `inspect_analysis_view` /
`inspect-analysis-view` projects a summary, the mitigations or linkage facet,
one section or symbol, or a stable page without re-running the decoder. CLI
one-shot invocations pass portable inline Evidence JSON; an MCP session uses
the retained `evidence_id`. Page `limit` is required and bounded by the
measured MCP stdio budget documented on the tool contract.
Over MCP, `inspect_binary_layout` with `"detail": "summary"` retains the
complete layout Evidence in the session and returns only its summary view.
Its `normalized_result.parent_evidence_id` names the retained layout for later
section, symbol, mitigation or linkage views. The default `complete` detail and
CLI output are unchanged.
Complete results have a 32 MiB input, 64 MiB reply, 1 MiB combined diagnostics
and 30-second owned command deadline. The reply budget applies to the decoder
record; the CLI/MCP Evidence envelope adds copies and encoding overhead. The
@@ -129,3 +142,48 @@ malformed limit reports remain unknown with their read failure preserved. A
received signal alone does not establish its exact cause. Dynamic tags require
a complete DT_NULL inside PT_DYNAMIC; interpreter names and ranges end at the
first NUL, with any padding still represented by the original segment range.
## Portable PE resources
`inspect_pe_resources` / `inspect-pe-resources` inspects an explicit PE32 or
PE32+ file without an active target, native engine, Python, or Windows SDK:
```sh
rea inspect-pe-resources ./selected.exe --json
```
```json
{
"name": "inspect_pe_resources",
"arguments": { "path": "/artifacts/selected.exe" }
}
```
The complete Evidence identifies the stable artifact snapshot by path, byte
count and SHA-256. Resources retain separate type, name and language identities:
numeric IDs are distinct from UTF-16 names, whose original bytes are also
reported. Directory headers, entries, data entries and payloads retain original
file offsets and lengths. Each opaque payload has its own SHA-256; code page and
reserved data-entry fields are preserved.
RT_GROUP_ICON records expose original image descriptors and RT_ICON candidates.
A reference resolves only when an icon with the same numeric ID and language
exists. Missing references, other-language candidates and declared-size mismatch
remain explicit. Encoded dimensions are preserved (zero denotes 256 pixels).
This is static reference inspection; no image decoding, language fallback,
resource loading or selected-file execution occurs.
An absent resource data directory is a complete empty inventory. Malformed
headers, truncated tables, cycles, duplicate sibling identities, unbacked or
ambiguous RVA mappings, nonidentical overlapping ranges and unsupported tree
shapes fail explicitly, rather than returning partial inventories. Exact shared
payload ranges are supported. The supported tree has three levels: type, name,
and language. Other resource payload formats remain opaque.
`max_file_bytes` defaults to 64 MiB (maximum 512 MiB); `max_entries` defaults to
4096 (maximum 65536). CLI options are `--max-file-bytes` and `--max-entries`.
Metadata is bounded to 8 MiB; exceeding any budget fails without truncation.
Large Evidence envelopes may require a caller-configured MCP transport receive
buffer because envelope copies add overhead. Requests honor cancellation during
snapshot reading, directory traversal and payload hashing. The operation reads
regular files only and rejects symbolic links.
+11 -7
View File
@@ -14,10 +14,11 @@ REA can attach to a user-owned Chrome-family browser through the Chrome DevTools
- `inspect_web_page` / `rea inspect-web-page` captures DOM structure, accessibility nodes, scripts, resources, safe response/DOM metadata, attach-window network and console metadata, WebSocket frame sizes, workers, quota, and optionally selected storage key names, redacted storage-content fingerprints, or script sources.
- `analyze_web_bundle` / `rea analyze-web-bundle` parses selected script artifacts without execution and derives chunk edges, route and endpoint candidates, vendor fingerprints, static WebMCP declarations, and optionally source-map/original-source evidence.
- `observe_web_session` / `rea observe-web-session` arms an observation window of the requested duration for an external user action and records ordered reload, SPA navigation, redirect, failure, lifecycle, and target-termination metadata.
- `discover_webmcp_tools` / `rea discover-webmcp-tools` uses the experimental CDP WebMCP domain to return every in-scope registration and its complete structural input-schema summary inline. Registrations with the same name and URL in distinct observed frames retain separate identities. `tool_key` includes the observed frame ID; it is not a stable identity across navigation or browser sessions. Same-frame registration updates replace that owner only, and removal leaves other owners intact. REA never exposes `WebMCP.invokeTool`; malformed protocol payloads fail explicitly instead of returning incomplete tool metadata.
- `discover_webmcp_tools` / `rea discover-webmcp-tools` uses the experimental CDP WebMCP domain to return every in-scope registration and its complete observed `input_schema` declaration and canonical `input_schema_sha256` digest inline. Declarations are untrusted JSON data, including declared types, required fields, enums, examples and reference URLs. REA does not resolve schema references. These fields replace `input_schema_shape`. Registrations with the same name and URL in distinct observed frames retain separate identities. `tool_key` includes the observed frame ID; it is not a stable identity across navigation or browser sessions. Same-frame registration updates replace that owner only, and removal leaves other owners intact. REA never exposes `WebMCP.invokeTool`; malformed protocol payloads fail explicitly instead of returning incomplete tool metadata.
- `compare_web_captures` / `rea compare-web-captures` compares passive captures or exact-step-aligned browser scenarios. Scenario results commit reproducible literal normalization and expose alignment failures plus artifact-level action, screenshot, DOM, accessibility, URL, history, storage, and event differences. Missing or truncated evidence is never treated as equivalence.
- `capture_web_screenshot` / `rea capture-web-screenshot` returns a content-addressed visible-viewport PNG.
- `compare_web_screenshots` / `rea compare-web-screenshots` performs bounded local PNG pixel comparison without OCR or external services.
- The CLI comparison commands accept each capture, screenshot artifact or normalization policy as inline JSON or a JSON file path. Use files for screenshot artifacts and scenario captures, whose embedded PNG bytes can exceed the host's command-line length limit.
- Every surface has equivalent CLI and MCP contracts and returns Evidence provenance.
- MCP tools return complete results inline and include the Evidence ID. Session evidence can be exported with `export_evidence_bundle`.
@@ -134,11 +135,11 @@ REA retains local observation data and removes only URL userinfo credentials, ex
- DOM snapshots retain node types, node names, value lengths, and attribute names, but not text or attribute values.
- Accessibility structure and roles are retained by default, while names and descriptions require `include_accessibility_text: true`.
- Network observations retain method, status, MIME type, size, type, initiator stack location, and complete URLs with userinfo credentials removed. Redirects reported by CDP are attached as ordered `redirects` on the one request ID, with the prior request URL, CDP response URL, method/type, response status/MIME/encoded length, request timestamp, and the next `requestWillBeSent` event timestamp. CDP delivers `redirectResponse` with that next request event, so the latter is an event boundary rather than an exact response timestamp. Redirect response headers and bodies are discarded; hops outside the selected origins are discarded with the request chain. Headers are discarded after an allowlisted projection of length/encoding, structured CSP/Link/policy fields, and untrusted agent hints. Cookies and authorization headers are never retained.
- Request/response bodies are not requested or parsed by default. When selected, only allowed-origin JSON media types are read, converted immediately to complete value-free property paths/types, and discarded. `Network.getResponseBody` is never sent unless JSON body shape capture is selected.
- Request/response bodies are not requested or parsed by default. When selected, only allowed-origin JSON media types are read, converted immediately to complete value-free typed paths, types and observation counts, and discarded. Each path segment is either `{ "kind": "property", "name": "raw property name" }` or `{ "kind": "array-element" }`; array-element types include primitives and nested arrays. Literal `*` properties remain distinct from array elements. `Network.getResponseBody` is never sent unless JSON body shape capture is selected. Comparison uses body shapes only when both captures selected them, and compares request/response shapes only where both observations provide those facts. Unavailable or truncated selected coverage makes equivalence unknown; observed differences still report changed.
- Console observations with a stack source retain call type, argument types, timestamp, and source location. When console text capture is selected, already-delivered primitive values are retained verbatim; objects, getters, and remote properties are never expanded.
- WebSocket observations retain direction, opcode, and payload byte length. When shape capture is selected, text frames are classified as text or complete value-free JSON shape; binary bytes, hashes, prefixes, and raw frames are never retained.
- Storage observations always redact values. Key names, IndexedDB names, and cache names require `include_storage_keys`; stable content fingerprints require the additional `include_storage_fingerprints` selection. Cookie fingerprints cover cookies applicable to the current main-frame URL, including its path, rather than every cookie path on that origin. Other storage remains scoped to the origin. Cache bodies above 64 KiB and partial IndexedDB remote objects make fingerprint coverage incomplete, so identical observations remain `unknown`.
- Script metadata is included only when CDP supplies a URL on an allowed origin. Stable keys exclude transient CDP script IDs, and exact transient raw URLs are used only during script/resource reconciliation. URL-less scripts are excluded because their origin cannot be established. When CDP supplies an execution-context association, the accepted script retains its authorized frame ID for later attribution. Source content is omitted unless explicitly requested and is returned inline as a self-verifying artifact with its SHA-256 digest.
- Script metadata is included only when CDP supplies a URL on an allowed origin. Stable keys exclude transient CDP script IDs, and exact transient raw URLs are used only during script/resource reconciliation. URL-less scripts are excluded because their origin cannot be established. When CDP supplies an execution-context association, the accepted script retains its authorized frame ID for later attribution. Script metadata admission bounds retained identity and source-map strings to 8 MiB and 50,000 records. When a source-map URL cannot fit, the script identity remains and source-map coverage reports `resource_budget_exhausted`; rejected script observations are counted without retaining their IDs. Source content is omitted unless explicitly requested and is returned inline as a self-verifying artifact with its SHA-256 digest.
Frames, resources, scripts, events, and workers outside the selected origin scope are excluded. An explicit `allowed_origins` list can include additional origins; excluded target details are counted without being exposed.
Retained workers include validated opener-target and parent-frame IDs when CDP
@@ -148,18 +149,21 @@ prove static module ownership.
## Completeness and limits
The default inspection window is 500 ms; callers choose its duration. The
capture returns all in-scope frames, DOM and accessibility nodes, scripts,
capture returns in-scope frames, DOM and accessibility nodes, admitted scripts,
resources, workers, storage names, and observed network, console, and WebSocket
events. Full selected text, script sources, and JSON shapes are returned inline.
The result distinguishes
`complete_within_window`, `policy_filtered`, `attach_limited`, and `truncated`
coverage. It reports excluded items and any values omitted or truncated by
validation; it does not drop records to meet an internal collection quota.
validation and resource bounds. Omitted script metadata makes its affected
section explicitly truncated.
Disallowed-origin entries are filtered before retention.
CDP discovery, WebSocket connection, and commands continue until the peer responds or the caller cancels the operation; REA has no internal byte, message-count, or pending-command quota for these exchanges. Without caller cancellation, a stalled peer can leave an operation waiting. On cancellation, REA closes only its own WebSocket, waiting up to one second before terminating it. Malformed unsolicited protocol events poison the connection so later commands fail closed.
CDP discovery, WebSocket connection, and commands continue until the peer responds or the caller cancels the operation; REA has no internal byte, message-count, or pending-command quota for these exchanges. Without caller cancellation, a stalled peer can leave an operation waiting. On cancellation, REA closes only its own WebSocket, waiting up to one second before terminating it. Malformed unsolicited events and malformed replies to pending commands poison the connection so later commands fail closed. When a correlated reply reports a session ID, it must match the command's selected session. An optional method is reported unavailable only when the browser rejects it as unknown; other command rejections retain their reported failure.
Network and console coverage starts only after REA attaches and enables the relevant CDP domains. `prior_activity_available` is always `false`; absence from these arrays is not evidence that an event never occurred. Source maps are not fetched by inspection. Bundle analysis fetches them only when `fetch_source_maps` is selected, with exact-origin redirect checks and no credentials, cookies, or referrer. Every requested map, mapping, original source, AST node, and finding from parsed content is returned inline; failed maps remain explicitly unavailable and make bundle completeness partial. Original source artifacts with `.ts`, `.tsx`, `.mts`, or `.cts` suffixes carry `text/typescript`; other source names retain `text/javascript`.
Network and console coverage starts only after REA attaches and enables the relevant CDP domains. `prior_activity_available` is always `false`; absence from these arrays is not evidence that an event never occurred. If CDP reuses a request ID without supplying redirect metadata, REA retains the predecessor observation and marks network coverage incomplete.
Source maps are not fetched by inspection. Bundle analysis fetches them only when `fetch_source_maps` is selected, with exact-origin redirect checks and no credentials, cookies, or referrer. Each fetch operation has a 30-second deadline and a 64 MiB aggregate streamed-response budget across redirects. A deadline or byte-limit failure remains explicitly unavailable and makes bundle completeness partial. Source-map decoding also bounds raw resolved identities to 64 MiB and aggregate inline evidence to 32 MiB. Failed maps preserve their failure context when it fits; if another context cannot fit, collection stops with the full requested count, the returned processed count, and an explicit unknown-results limitation. Retained mappings and original sources are returned inline. See [source-location limits](web-source-location.md) for the structural decoder bounds. Original source artifacts with `.ts`, `.tsx`, `.mts`, or `.cts` suffixes carry `text/typescript`; other source names retain `text/javascript`.
## Non-goals and threat model
+5 -4
View File
@@ -236,12 +236,13 @@ network metadata observation; listing `network` in `events` is then optional.
Each observed request object receives a capture-scoped `transaction_id`.
Requests sharing a URL remain distinct. Redirects link to the preceding
transaction only when it was observed; a null predecessor does not establish
that no earlier hop existed. Older captures without IDs remain readable and
their transaction association is unknown.
that no earlier hop existed. Request events require both transaction fields;
an absent ID is malformed capture data, while a null redirect predecessor is
an explicit unknown.
`scenario.network_content` records the resolved content selection. Comparing
captures with different selection, or legacy captures without that coverage
information, reports network evidence as unknown with a recovery instruction.
captures with different selections reports network evidence as unknown with a
recovery instruction.
Capturing more data alone does not establish a website change.
`network-content` events reference the exact request or response event through
-477
View File
@@ -1,477 +0,0 @@
# Incremental capability migration
This working guide tracks the migration in #740. Update it as concrete domains
migrate. Existing public contracts and domain-specific ports remain authoritative;
there is no new universal provider interface or fixed module manifest.
## Ownership to preserve
| Responsibility | Current owner | Migration direction |
| --------------------------------------------- | ----------------------------------- | ----------------------------------------------------- |
| Analyst semantics and Evidence representation | domain | Keep pure and provider-neutral |
| Named public input/output contracts | contracts | Keep exact CLI/MCP meaning and complete discovery |
| Producer parsing and external tool protocols | provider adapters | Keep behind the relevant typed port |
| Shared analyst workflows | application | Share between CLI and MCP |
| Concrete provider construction | composition, MCP startup | Keep fresh typed factories at the production boundary |
| Investigation Evidence and Unknowns | InvestigationRecords/EvidenceLedger | Consume narrow read/write/atomic record ports |
| Target/profile snapshots and invalidation | BinarySessionRecords/BinarySession | Keep binary-owned |
| Subprocess ownership and host primitives | process/windows | Reuse; preserve cancellation and cleanup |
| Public translation | CLI/MCP adapters | Delegate to shared workflows and named contracts |
Retain exact Evidence IDs, provenance, detached reads, atomic Evidence/Unknown
mutations and optimistic revisions. Preserve current close and failed-cleanup
record clearing while extracting ownership; #721 owns any retention-policy change.
Each CLI invocation and MCP connection keeps its own state. Provider registration
must not launch engines or install prerequisites.
## Migrate before generalizing
1. Record the actual callers, state, environment, protocol and verification owner
of the capability being migrated.
2. Move concrete construction behind its existing typed port. Preserve injected
ports, selected environment, queues, failure state and cleanup behavior.
3. Test both caller paths and the applicable package/real-provider boundary.
4. Use independently migrated capabilities to identify repeated metadata and
composition needs. Derive a small source declaration only when those needs
are established; keep unlike target/lifecycle semantics separate.
5. Move a coherent capability's files, fixtures and verification lanes in a
mechanical PR. Update all path-sensitive consumers in that same PR.
Pure helpers do not need an interface each. A capture-format adapter or typed
factory may be sufficient. Avoid generic JSON execution, external MCP catalog
passthrough, eager provider acquisition, new permission fields or a multi-package
rewrite. Optional loading should preserve successful peers and report the failed
capability without hiding tools from the catalog.
## Checks before and after a move
`npm run verify:test-discovery` compares actual Vitest file discovery with every
repository-owned `*.test.ts` under src and tests, including newly added files. The
check requires Git, includes untracked non-ignored tests, and excludes removed
paths during a move. It
rejects missing files and overlapping project ownership. It only lists files;
it does not replace behavior tests or real-provider verification.
Check imports, project isolation and coverage, development-test selection,
lint exceptions, catalog/generator imports, npm and CI verification entrypoints,
fixture ownership, and installed-package bridge/native path resolution.
Domain and contracts must not import application workflows, caller adapters or
provider implementations. Production composition is a deliberate outer boundary.
Other existing adapter imports will migrate incrementally; do not widen a lint
exception to conceal new protocol code inside application workflows.
`npm run verify:module-boundaries` parses repository-owned source imports,
reexports, type imports and literal dynamic imports, then checks their resolved
source layer. Nested names such as `domain/android` are domain code; `src/android`
is the provider adapter. The check runs with lint, including cached static gates.
It covers tracked and untracked non-ignored TypeScript source and skips cached
paths removed during a move. Pass exact source paths for a focused check.
Pure source and its tests keep inward dependencies. Application/server provider
construction guards cover the migrated deep, Android, firmware, JavaScript recovery and observation
implementations. Application workflows cannot import composition, including the
former binary runtime entrypoint; shared browser capture/export helpers remain admitted while their
ownership is reviewed. Test lane restrictions still use Oxlint. Producer-dependent
browser and managed comparison tests live in boundary lanes with their original
fixtures and assertions. This is a development guard, not runtime authorization.
Select verification by the claim changed: schema/composition, package, real
engine or host-native workflow. Record host/target prerequisites and source-owned
fixtures. Run heavy lanes serially with bounded workers/heaps and reuse existing
engines. Recording ports do not prove real provider or platform support.
## Extension examples to validate during migration
An implementation of an existing port should require a provider adapter, typed
production factory selection, exact producer parsing/provenance and matching
verification. Existing workflow meaning and public contracts should stay stable.
A new analyst capability deliberately adds semantics, named contracts, a typed
port/workflow when needed, both caller adapters, availability, documentation and
verification. Its integration is broader than swapping a provider. The migration
should eliminate incidental duplicate wiring, not erase those design decisions.
Update these examples with real migrated entrypoints before closing #740.
## First production factory migration
`src/composition/android.ts` and `src/composition/firmware.ts` construct providers
behind the existing AndroidAnalysisPort and FirmwareAnalysisPort. CLI registrars
pass their selected environment; MCP uses the process environment unless a caller
injects a port. Each factory call returns a fresh instance and acquires no process,
workspace or toolchain. Queues, cleanup-failure state and per-request cleanup stay
inside the provider. The existing launcher seams remain available to boundary
fixtures, which now exercise the production factories.
Application workflows and MCP registration must not import these concrete
providers. Composition may import their implementations. Binary composition also
uses this outer boundary after its direct-analysis callers were migrated.
This concrete pilot does not introduce a shared provider interface or module
manifest.
## Independent optional observation adapters
Browser observation, browser scenarios, Electron observation, Electron scenarios
and V8 Inspector observation now have separate factories in `src/composition/`.
CLI commands reuse them; MCP startup dynamically imports each factory independently.
`OptionalObservationProviders` describes these five existing typed ports only. It
is provisional startup wiring, not an extensible plugin manifest or a universal
provider interface.
A failed import or constructor retains the successful peers. The complete tool
catalog remains advertised. Session availability reports the failed adapter and
its actual reason, and affected handlers return the existing capability-unavailable
error. Explicit loading failures take precedence over configured availability.
Passive Electron and active Electron failures are independent; static JavaScript
analysis and runtime reconciliation remain usable without either adapter. CLI
Electron commands also load only their selected runtime factory at execution.
Source identities are available without importing the optional implementations.
Registration acquires no engines, probes no endpoints, changes no permissions and
installs nothing. Core transport failures and shutdown still use their existing
lifecycle. Fault-injection coverage uses the production loading/startup path and
actual MCP SDK calls; recording ports establish composition behavior, while the
real Inspector lane separately establishes runtime behavior.
## Investigation record ownership pilot
`src/application/investigation/InvestigationRecords.ts` owns one existing
EvidenceLedger per runtime. The production session composition constructs that
owner explicitly; the direct BinarySession constructor retains a fresh default
for compatibility. There is no second ledger, global store, persistence or new
retention policy.
The ledger, Unknown Evidence helper and the ledger's two original behavior tests
now live beside the owner in `src/application/investigation/`. Bundle validation
and record-owner consumers follow the new paths; retained-reference access still
uses the narrow record ports. The move preserves implementation bodies and test
assertions. Binary snapshot/cache files remain with their existing owner.
EvidenceReader, EvidenceWriter and EvidenceUnknownWriter describe existing
read/write/atomic callback needs. UnknownRegistryPort preserves optimistic
revisions and consistency verification. Non-binary MCP registrars use these
record types without depending on the binary execution/lifecycle surface.
BinarySessionPort retains its compatible record methods through composition.
BinarySessionRecords remains the snapshot owner and compatibility facade. It
passes the actual active target explicitly for recordUnknown/updateUnknown;
recordEvidenceWithUnknown keeps its target-free mutation subject. Snapshot import
merges records without notifying midway, then emits after the cache commits.
Bundle import retains the full change delta so Unknown-only changes notify even
when recordsAdded is zero. Clearing resets records, cache and invalidation before
notification; observer failures remain best effort after a committed mutation.
Close and failed-cleanup clearing, ordinary target-switch retention, detached
reads, Evidence identities and deterministic bundle transfer keep their existing
behavior. Snapshots still require an active target and concrete analysis profile;
extracting investigation ownership does not make them a target-free record store.
#721 remains responsible for any future lifetime-policy change.
## Inspector adapter ownership
`src/inspector/` owns V8 Inspector discovery, passive capture, script/target
location interpretation and its lightweight provider identity. The composition
factory and optional loader use this owner. Browser CDP connection, endpoint/value
and Electron file-location helpers remain deliberate shared adapter utilities at
their existing paths; no provider wire protocol moves into domain or process.
Loopback fixtures and producer boundaries now live under
`tests/fixtures/inspector/` and `tests/boundary/inspector/`. The socket-backed
unresolved-target reconciliation test moves from composition into the forked
boundary lane with its original assertions. Adapter tests retain fork isolation.
`npm run verify:inspector` keeps its public development entrypoint and delegates
to `scripts/verify/inspector/runtime-observation.mjs`, using the real Node fixture
under `tests/conformance/inspector/`. Catalog imports, source guards and test
discovery follow the new paths. Observation authority, lifecycle, producer
interpretation and caller-visible contracts stay unchanged.
## Auxiliary source declaration pilot
Artifact, macOS native and managed static metadata now belongs to each adapter's
`*ProviderMetadata.ts` module. The implementation and
`src/composition/auxiliaryAnalysisProviders.ts` reuse the same identity and exact
capability descriptors. The declarations reference existing AnalysisProvider
loaders; they cover these three disjoint auxiliary implementations only. Deep
candidate selection and the five typed observation ports remain separate.
The binary runtime reads these source declarations while auxiliary construction
stays lazy. The separate managed-only entrypoint retains direct construction for
its execution-free workflow. The MCP catalog generator reads declarations without
constructing implementations, using its canonical macOS platform; actual runtime
host restrictions remain explicit.
Discovery and binary operation-kind routing now consume canonical source contracts
rather than their generated JSON artifact. No declaration imports its generated
output. Generated catalog facts and public schemas stay unchanged.
All observation registrars resolve contracts by name. An isolated compiled-process
test reverses presentation arrays and performs actual MCP SDK calls to verify
advertised schemas and handler meaning. Reordering metadata must not select a
different operation, schema, provider or deep-provider priority.
## Android layer and verification ownership
Android workflows and their existing typed port live in `src/application/android/`,
pure APK/inventory semantics in `src/domain/android/`, and the named inspection
contracts in `src/contracts/android/`. The headless JADX producer remains in
`src/android/`; `src/composition/android.ts` supplies its fresh factory to both
caller adapters. Public names, result meaning and JVM/queue/cleanup limits are
unchanged. Inventory-only application projection remains execution-free.
The real lane and signal-cleanup helper belong to `scripts/verify/android/`; its
explicit downloader and fixed manifest belong to `scripts/fixtures/android/`.
`verify:android` and `fixtures:android` keep their command names and repository-root
`_reference/apk-integration/` fixture default. Synthetic producer fixtures stay in
`tests/fixtures/android/`, with matching boundary and composition ownership. Real
JADX CLI/MCP parity requires the fixed APK and existing audited JAR; synthetic
protocol/cancellation success does not establish that engine or an unverified host.
## Deep-provider source declarations
Hopper, Ghidra and IDA declare their implemented analyst operations in their
own `*ProviderCapabilities.ts` modules. Hopper's inventory is typed against the
existing direct-operation contracts; Ghidra reuses its inventory/function adapter
operations; IDA retains its read-only operation family. Frozen operation arrays
feed the existing capability builders without importing generated catalog data.
The catalog generator reads these source declarations and joins operation names
to canonical `TOOL_CONTRACTS`. A missing contract identifies the declaring provider
and operation. Public schemas and descriptions remain owned by contracts; the
declarations describe implementation coverage. Provider adapters must not consume
the generated MCP catalog that is derived from them. The resolved module guard
checks this edge while admitting canonical source contracts, generated package
metadata and the existing application snapshot-cache consumer.
Exact provider effects and lifecycle differences remain in their adapters:
Hopper's GUI and mutation effects, Ghidra's experimental Windows authority and
mutation restrictions, and IDA's attached/headless effects and live observations.
This source increment introduces no common provider lifecycle or new interface.
## JavaScript application ownership
`src/application/javascript/` owns JavaScript/Electron artifact analysis and
graph projection, feature/version/export/source comparisons, runtime Evidence
and reconciliation, observation ports, and source recovery workflows. Pure
analysis and public schemas keep their existing domain/contract ownership;
shared artifact inventory, investigation records and execution types remain
shared. CLI, MCP and production factories import the owning workflow directly.
`src/domain/javascript/` owns static parsing and semantic IR, application and
semantic graphs, Electron facts, runtime reconciliation, recovery result
semantics, and source-to-bundle comparisons. Shared Evidence, digests, ordering,
comparison semantics and historical-source graphs stay at their existing owners.
Native handoffs link exact-subject Evidence without selecting or executing a
provider.
`src/contracts/javascript/` owns the JavaScript/Electron observation and recovery
contracts, JavaScript-specific workflow requests, and their examples. The shared
`applicationToolContracts.ts` aggregate stays at the contract root because it also
owns reconstruction and Android/Apple projection operations. Canonical tool
aggregation, named handler binding and SDK schema presentation remain unchanged.
Catalog source paths, compiled verifier/SDK fixtures and recovery CI filters
follow the domain/contract owners.
`scripts/verify/javascript/` groups application-workflow, runtime-reconciliation,
large-digest and real-recovery entrypoints. Their existing npm commands retain
their invocation semantics. Recovery fixture compilation lives beside its
unchanged sources under `scripts/fixtures/javascript-recovery/`. Its default
REA entrypoint still resolves to `scripts/rea.mjs`. Managed conformance imports
the relocated compiled workflow; owning CI source filters follow the new paths.
`src/artifacts/javascript/` owns directory/ASAR reader construction and relevant
file acquisition, including root/nested byte verification, UTF-8 diagnostics and
nested reader cleanup. Its narrow factory returns the existing `ArtifactReader`;
the application retains input admission, inventory, graph construction and its
original root-reader `finally` close. Pure file facts live in
`src/domain/javascript/javascriptArtifactFiles.ts`, and the shared immutable
inventory snapshot lives in `src/domain/artifactInventorySnapshot.ts`. Inventory
options and integrity policy remain application-owned. Shared stream hashing
lives in `src/artifacts/ArtifactHash.ts`, preserving complete byte counts and the
bounded classification prefix. Acquisition/hash guards reject imports from
application, composition or caller adapters; JavaScript workflows use the factory
instead of importing concrete ASAR/directory reader classes.
ZIP, native-DMG and Mach-O inventory reader selection keep their existing
lifecycles. Runtime ports retain their distinct Inspector, passive Electron and
active Electron effects; shipped Electron hooks remain at their existing
provider boundary.
## Managed capability ownership
`src/domain/managed/` owns managed artifact and member semantics, reconstruction
import, native-boundary verification and application graph projection.
`src/application/managed/` owns their shared Evidence workflows, and
`src/contracts/managed/` owns their named contracts and examples. Producer
metadata/IL parsing stays in `src/dotnet/`; target resolution, Evidence, ordering
and investigation records retain their shared owners. Path-based member
comparison preserves its actual target/byte-digest admission and existing parser
helper.
`scripts/verify/managed/` groups the portable conformance entrypoint and its
support, manifest, oracle and completion-report helpers. Its PE byte fixture
builder and declaration live in `scripts/fixtures/managed/`, shared with the
installed-package lane and existing managed conformance tests. `verify:managed`
keeps its command name and optional caller-cwd manifest resolution. Compiled
catalog and generator imports follow the owners; document-check cache inputs
include the relocated runtime verifier and fixture files.
Portable byte fixtures, optional operator-local manifests, actual ILSpy oracles
and real Ghidra NativeAOT checks retain their distinct proof levels and
prerequisites. The existing NativeAOT fixture/engine lane keeps its owner. This
move preserves implementations, Evidence identities and generated commitments.
## Binary application ownership
`src/application/binary/` owns the active session, deep-provider registry and
evaluation, operation routing, disjoint provider composition, lazy auxiliary
clients, cancellation and client cleanup. Its records facade and snapshot
cache/files remain bound to the exact target and analysis profile. Investigation
records still have their separate owner in `src/application/investigation/`.
`AnalysisProvider.ts` stays shared because its identity/execution types also serve
nonbinary ports. `BinaryTargetResolver.ts` stays shared because Android, firmware,
managed and artifact workflows use its target parsing. Production wiring lives
in `src/composition/binary.ts`; application workflows gain no outward composition
dependency.
The three colocated application tests move with their owner. Composition cases
remain in `tests/composition/analysis-sessions/`; filesystem and SDK cases retain
their boundary lanes. The shared `tests/fixtures/binarySession.ts` factory supports
several capability families. Existing recursive application globs discover the
moved tests; bridge assets and real-verifier entrypoints remain at their owners.
## Firmware layer and verification ownership
Firmware workflows and their existing typed port live in
`src/application/firmware/`, pure request/result semantics in
`src/domain/firmware/`, and named contracts in `src/contracts/firmware/`.
`src/firmware/` keeps producer commands, report parsing, source copies, publication
and cleanup; `src/composition/firmware.ts` supplies a fresh typed factory.
The real lane belongs to `scripts/verify/firmware/analysis.mjs`; the fixture runner
and its unchanged Python producer belong together in `scripts/fixtures/firmware/`.
The npm command names and selected `REA_FIRMWARE_FIXTURE_ROOT` are unchanged. The
runner retains its working-directory-relative default; the verifier retains its
repository-root default. Both point to `_reference/firmware-integration/generated`
when invoked through the documented npm commands. Optional ext4/Ghidra lanes keep
their own prerequisites. Source-fixture generation and synthetic producer tests
do not establish real Binwalk/Unblob analysis or another host's execution support.
## Apple artifact capability ownership
`src/domain/apple/` owns Apple application anatomy/projection, asset catalog
facts, Interface Builder graphs, keyed archive semantics and plist values.
`src/application/apple/AppleApplicationService.ts` retains the shared workflow
that projects authenticated IPA/macOS inventory Evidence.
`src/artifacts/apple/` owns the actual producer boundary: directory acquisition,
assetutil invocation, plist/NIB decoding, encoded view-parent interpretation and
keyed archive inspection. These helpers are used by ArtifactProvider, retain
its existing typed analysis boundary, injected assetutil seam and original reader
cleanup, and do not require a new port for each helper. Producer code no longer
lives in the application layer. Guards reject application/composition/caller
imports from this owner while admitting pure facts and shared artifact readers.
Adapter-source tests retain their assertions in the existing forked adapter lane.
`scripts/verify/apple/` groups archive, asset catalog, Interface Builder,
Objective-C/Swift dispatch and macOS bundle verification. The macOS bundle fixture
builder lives in `scripts/fixtures/apple/`; NIB byte fixtures stay beside their
artifact decoder. Existing format-specific conformance sources and goldens keep
their locations, and relocated verifiers resolve them against their own file
URLs. Public npm entrypoints and CLI/MCP contracts stay stable; generated-document
cache inputs include the relocated runtime scripts and fixture builder.
Portable decoder and injected producer tests establish their format/boundary
claims. Actual Swift/Xcode, assetutil, native NIB, bundle signing and DMG lifecycle
claims require the real Apple lane. Native binary API/value-flow semantics and
shared cross-domain contract aggregates keep their separate owners.
## Artifact inventory and extraction ownership
`src/artifacts/inventory/` owns format classification, reader selection, inventory
policy, canonical scanning and artifact graph construction. The shared artifact
provider and JavaScript reconstruction workflow consume this owner. Snapshot
semantics remain in `src/domain/artifactInventorySnapshot.ts`.
`src/artifacts/extraction/` owns member selection, integrity checks and transactional
materialization through the existing readers and safe output tree. Reader cleanup,
cancellation, rollback, archive containment and caller-visible results retain their
existing behavior. Acquisition guards reject imports from these producer owners
into application workflows, production composition or CLI/MCP adapters.
`src/application/artifacts/ArtifactExtractionDestination.ts` owns the caller's
default temporary output-root choice for both CLI and MCP. The adapters pass this
destination to the existing provider operation; format handling and member writes
remain in the artifact owner.
Add format-specific acquisition behavior beside the inventory readers and exercise
its actual producer representation in filesystem boundary tests. Add caller
workflow behavior in the application owner and verify both adapters. The installed
package lane checks inventory identity and extraction through CLI and MCP; the
real Apple bundle lane separately establishes DMG mount and detach behavior.
## Binary production composition closure
`src/composition/binary.ts` is the shared production owner for deep candidate
construction, lazy auxiliary composition and the managed-only session factory.
It preserves the existing constructor bodies, selection policy and fresh session
per invocation. Factory registration acquires no engine or target.
`DirectAnalysis` and `DirectAnalysisStatus` receive these two existing factories
through `DirectAnalysisDependencies`. They retain configuration parsing, selected
status environment, cancellation, snapshot replay/binding, Evidence projection
and finally-close. The dependency uses the existing BinarySession type, including
its replay policy; it adds no universal backend or lifecycle contract.
`src/composition/directAnalysis.ts` binds the production factories for CLI and
one-shot managed MCP callers. Binding creates no session and stores no retained
analysis state. MCP startup constructs its connection session through the same
binary factory. Source and compiled fixtures use these entrypoints. The former
application runtime path is removed, and the source guard no longer admits its
outward provider/composition imports.
## Native analyst capability ownership
`src/domain/native/` owns portable native inspection, instruction/data types,
load-image facts, API boundaries, annotations, metadata recovery, UI observation
semantics and value/investigation graphs. `src/application/native/` owns shared
API projection, call routes, dispatch inspection and UI/value tracing. Its tests
keep the existing service lane. `src/contracts/native/` owns the named native
adapter contracts; shared official/enhanced aggregates remain at their owners.
Producer interpretation, external commands and host UI lifecycle remain in
`src/native/`, Hopper, Ghidra and IDA. The shared function dossier still lives in
`domain/hopperValues.ts`: its historical name does not make its meaning exclusive
to Hopper. This move retains existing typed ports, exact result schemas,
observed/derived/unknown distinctions, profiles and Evidence links.
Source and compiled verifier imports follow the new owners. Host UI and real
native-value verifier locations are retained until their own proof lanes migrate;
interactive macOS UI success and real dependency tracing require their respective
host/engine workflows. Portable source fixtures and injected call-route tests
establish their narrower boundaries, without expanding provider/platform support.
## Process capture and analyst workflow ownership
`src/domain/process/` owns scenario/capture validation, portable process trees,
trace specifications, observations, comparisons and the canonical process Evidence
identity. The standalone contract example lives in `src/contracts/process/`;
shared session contracts retain their broader investigation owner.
`src/process/capture/` owns the actual PTY boundary, terminal rendering, sampling,
selected child environment, filesystem snapshots/effects, runtime path admission,
event journal, settlement and resource cleanup. It reuses `src/process/` ownership
primitives and the Windows host substrate. Its identity import follows the
existing pure declaration directly. A source guard rejects outward application,
composition and caller imports; no new provider or lifecycle interface is added.
`src/application/process/` retains Evidence projection and file-backed CLI
capture/comparison workflows. Capture helper tests use the forked adapter lane;
Evidence/host integration tests use the serial process-boundary lane. Their
fixtures and assertions remain unchanged. Installed capability-probe URLs follow
the new compiled adapter path, including the optional-dependency failure probe.
Windows PTY capture retains its existing unavailable outcome because descendant
cleanup is not yet verified. Native Job Objects and a PTY binary do not establish
that capture workflow. Real POSIX capture/cleanup and installed terminal/PTY module
resolution require their actual host and package lanes; portable comparison
fixtures establish their separate evidence semantics.
+49 -5
View File
@@ -20,6 +20,23 @@ files when neither `--provider` nor `--snapshot` is supplied. See
[JavaScript artifact reconstruction](javascript-artifact-reconstruction.md)
for results, integrity checks and coverage.
The complete application Evidence can be hundreds of megabytes for a real
application. When an agent or a person reads the result, save it to a file and
project a summary, a module page or one module from the saved Evidence:
```bash
rea analyze-javascript-application /absolute/path/to/app --json > app-evidence.json
jq -c '{source: {kind: "inline", evidence: .}, view: {kind: "summary"}}' app-evidence.json > app-view.json
rea inspect-analysis-view app-view.json
```
For example, a 334 MB Obsidian application Evidence file yields a summary view
of about 10 KB. Replace the view with
`{"kind": "page", "collection": "modules", "offset": 0, "limit": 32}` for a
module page. See
[JavaScript application workflows](javascript-application-workflows.md) for
views, feature traces and comparisons that take the same saved Evidence.
## Native analysis
Configure [Hopper or Ghidra](installation.md#hopper), or the
@@ -80,7 +97,7 @@ or close. Provider failures are returned with their original reason. For an
`ambiguous` selection error, choose from `details.candidate_ids`; for
`provider_unavailable`, run `rea doctor --provider ID --json` to diagnose the
selected engine. See [task readiness](installation.md#check-readiness-for-your-task)
and [provider selection](adr/0001-provider-selection-and-analysis-profiles.md).
and [provider selection](mcp-contracts.md#identity-and-discovery).
The session reports work still in progress through `analysis_activity`.
A client timeout can end its wait while the provider continues analyzing.
@@ -96,6 +113,12 @@ an exact result when the target bytes, operation, parameters, provider and
settings match. Mutations and cursor-dependent calls are excluded from the
cache. Snapshot files are local and use owner-only permissions.
Snapshots retain eligible target-scoped question histories in full, including
mutation Evidence recorded while another target was active. Observations and
related questions must still belong to the saved target. If those dependencies
cannot be retained, the entire history is excluded instead of reverting the
question to an earlier revision or disposition.
```bash
rea analyze /absolute/path/to/program --provider ghidra --snapshot /absolute/path/to/analysis/program.json
# Repeat the same query to reuse its saved result.
@@ -109,6 +132,13 @@ cached result. `close_binary` accepts `snapshot_path` and optional
`overwrite: true` to save before releasing provider resources. A failed save
leaves the session open so the caller can resolve the output failure.
The MCP save receipt reports `primitive_entries`, `workflow_entries`, and
`evidence_records` separately. Zero primitive bindings can still accompany retained workflow
results and Evidence. These are cached observations, not a saved provider
database: only eligible exact queries can reuse a result, and new or live
queries can still require provider startup. The CLI uses the same snapshot
format and preserves these records when loading and updating it.
## Import, export and compare Evidence
Evidence records retain artifact identity, source locations, observations,
@@ -136,9 +166,20 @@ rea import-reference-source /absolute/path/to/source
```
The import records hashes and metadata for the supplied files, separately
from observations of the current app. File names do not automatically exclude
files. Set `REA_REFERENCE_SECRET_PATTERNS_JSON` to a JSON array of ignore
patterns when you want to exclude selected paths.
from observations of the current app. It honors the source tree's `.gitignore`
and applies default exclusions for common generated and dependency paths such
as `node_modules/`, `dist/`, and `*.log`. Pattern-based exclusions record the
matched pattern and whether it came from project, default, caller, or sensitive
path policy. Set `REA_REFERENCE_SECRET_PATTERNS_JSON` to a JSON array of ignore
patterns when you want to mark selected paths as sensitive; those patterns are
reported separately as configured-secret exclusions.
Re-import saved graphs whose pattern-based exclusions lack `pattern` before
using them in source-to-bundle comparisons.
JavaScript and TypeScript import parsing requires valid UTF-8. Malformed source
bytes retain their original hashes and sizes with a decoding diagnostic; REA
does not infer module targets from replacement characters.
Historical-source import requires safe no-follow file opens on Linux or
macOS. Native Windows returns `unsupported_host`; use Linux REA inside WSL
@@ -162,7 +203,10 @@ user permissions; consult the chosen guide for host requirements and effects.
## Output and exit status
The default terminal format is TOON. Use `--json` when saving results for a
JSON consumer. Output selection and formatting do not change operation status.
JSON consumer. `--json` is indented on a terminal and compact when piped or
redirected, which keeps large results smaller for agents and scripts; pipe
through `jq .` for indented files. Output selection and formatting do not change
operation status.
| Status | Meaning |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
+30 -7
View File
@@ -15,7 +15,11 @@ when both Evidence sets already exist.
The request supplies a literal-port loopback endpoint and, for inspection, a
target ID. REA accepts local hostless `file://` URLs that resolve to regular
files; remote hosts, encoded path separators, and nonexistent paths are
files, including pages a packaged application serves from inside `app.asar`.
For those, the first `.asar` path component that is a regular file is the
archive, the remainder must name a regular file in its header, and the reported
path is the canonical archive path joined with that member. Remote hosts,
encoded path separators, ASAR directories or links, and nonexistent paths are
rejected. The endpoint exposes every eligible target and its local path
metadata.
@@ -86,16 +90,33 @@ rea capture-electron-scenario scenario.json --json
The result records action status and targets, correlated app/window/WebContents,
preload, session, navigation, shell, permission, popup, download, protocol,
native-addon, process, and IPC timeline events. IPC channels are capped at
1,024 characters and argument-shape metadata at 32 entries; values are never
retained. Renderer crash/restart and deep-link actions are synthetic
native-addon, process, and IPC timeline events. IPC channels and argument-shape
metadata retain their observed lengths; payload values are never retained.
Renderer crash/restart and deep-link actions are synthetic
scenario controls; their attempted and observed outcomes remain in the
timeline. The active hook blocks and records external shell/navigation,
permission, download, popup, updater, and OS-integration effects. The timeline
is explicitly partial when attachment starts after application activity. The
owned experiment has an internal 60-second deadline and a 5-second per-action
timeout so hung work reaches process cleanup; these are lifecycle timeouts, not
caller-selected capture limits.
startup has a 60-second deadline. Actions wait until completion or request
cancellation; a click whose target never appears remains pending until cancelled.
CLI SIGINT/SIGTERM requests cancellation and awaits owned-process cleanup.
Window IDs, URLs, and cached titles come from one main-process Electron snapshot,
so a crashed renderer does not require a successful renderer-side title query.
Window instrumentation uses Electron's window-created event, including runtimes
with a read-only `BrowserWindow` export. Preload configuration comes from the
window's runtime metadata, including Electron's optional internal preload
descriptor when web preferences omit it. This descriptor is verified on
Electron 44.7.0; runtimes that expose neither representation retain an unavailable
path. A configured path or working IPC handler does not prove preload execution.
If cleanup cannot be verified, the error retains collected observations in
`details.partial_observation` and marks their application cleanup `unverified`.
Cleanup uncertainty does not authorize signaling unrelated processes.
The real verifier exercises compiled CLI and stdio MCP discovery, page/script
inspection, static/runtime reconciliation, active observation, and CLI SIGTERM
cleanup before checking the IPC, renderer crash/reload, utility/child-process,
deep-link, and blocked-effect fixture. A cleanup error keeps the full lane failed
even when the retained capture contains useful observations.
Active Electron Evidence can also be supplied to
[`reconcile_javascript_runtime`](javascript-runtime-reconciliation.md). That
@@ -103,3 +124,5 @@ projection is intentionally target-only and partial: it binds the selected
application path and capture outcome to the static graph, while frames, scripts,
workers, and execution claims remain unavailable until a separate passive runtime
capture provides them.
ASAR observation reads the header through one open file handle, validates its declared lengths against the archive size, and limits encoded JSON headers to 16 MiB before parsing. The header cache also retains at most 16 MiB of encoded headers across eight archives. Oversized headers produce a scope refusal.
+9 -2
View File
@@ -25,6 +25,12 @@ extraction have independent prerequisites; one does not require the other.
Both require util-linux `prlimit`, normally `/usr/bin/prlimit`; override its
absolute path with `REA_FIRMWARE_PRLIMIT_COMMAND` if needed.
REA retains at most 8 MiB of combined stdout and stderr per command. Exceeding
that diagnostic budget stops analysis with an explicit truncated-output error;
child process limits do not bound parent-side pipe retention. Completed commands
drain their output streams before recording diagnostics. Failed worker cleanup
retains the worker and workspace for retry before another request or at shutdown.
Unblob needs the external extractor for the selected format on its inherited
`PATH`: for example, `debugfs` for ext2/ext3/ext4. Its default Landlock sandbox
and skip rules stay enabled. Sandbox startup failures remain actionable errors;
@@ -129,8 +135,9 @@ tree semantics, vulnerability scanning, emulation or hardware runtime capture.
Unblob one worker. No automatic parallel extraction engines.
- **120-second** deadline; inherited **1 GiB per-process address-space** limit,
120 CPU seconds and zero core-dump allowance through `prlimit`.
- JSON reports: at most **8 MiB**; oversized reports fail without a truncated
success. Diagnostic output is bounded with exact captured byte counts.
- JSON reports: at most **8 MiB** and valid UTF-8; malformed encoding and
oversized reports fail without repairing or truncating producer data.
Diagnostic output is bounded with exact captured byte counts.
- Default staging budget: **256 MiB** and **10,000 entries**, configurable using
`max_output_bytes` / `max_output_files` (CLI `--max-output-bytes` /
`--max-output-files`). Depth defaults to 3, allowed range 1–10.
+6 -2
View File
@@ -1,7 +1,7 @@
# DOS MZ and COM analysis with Ghidra
REA can analyze DOS MZ executables and explicitly selected COM images through the bring-your-own Ghidra adapter.
The Linux x64 verification lane exercises actual 16-bit disassembly and
The Linux x64 and macOS arm64 verification lanes exercise actual 16-bit disassembly and
decompilation through the CLI and stdio MCP. Provider admission accepts Ghidra
12.1.x and that installation's declared JDK range. The verification lane uses
Ghidra 12.1.4 and JDK 21; no DOS emulator or cross-compiler is required.
@@ -87,6 +87,10 @@ address for subsequent lookups and leaves instruction decoding context with
Ghidra. These coordinates are analysis load addresses, not file offsets or
observations of a running DOS system.
Offsets that Ghidra would truncate to a different address are rejected before
reading or annotating a function. This also applies to explicit or encoded
address-space names; leading zeros preserve the numeric offset.
`procedure_info` and function dossiers include `body` evidence:
```json
@@ -150,7 +154,7 @@ are separate from the initialized MZ module. Raw COM files and DOS extenders
without an admitted MZ real-mode entry are outside this import boundary.
DOS MZ is available through Ghidra, with no Hopper support claim. It is outside
the Windows native PE P0 boundary. macOS DOS verification remains unverified.
the Windows native PE P0 boundary. macOS x64 DOS verification remains unverified.
## Real verification
+112
View File
@@ -0,0 +1,112 @@
# MIPS ELF analysis through Ghidra
This lane extends native ELF analysis; it does not execute MIPS code or rehost
firmware. It advances the generic-MIPS portion of
[#718](https://github.com/morluto/rea/issues/718), not the whole firmware roadmap.
PSP/Allegrex remains a separate specialization tracked in
[#1330](https://github.com/morluto/rea/issues/1330).
## Admission boundary
ELF `EM_MIPS` is retained as the provider-neutral `mips` family. The target also
retains class, byte order, `e_type`, raw `e_flags`, and inspected ABI declarations.
Recognition does not mean every provider or MIPS variant is supported. Existing
PE, managed and Mach-O architecture sets are unchanged.
The first Ghidra lane admits ELF32 `ET_EXEC`, little or big endian, with explicit
o32 and `EF_MIPS_ARCH_32R2` flags and no machine-specific or ASE encoding flags.
These are header declarations, not proof that every instruction conforms to
that ISA. ELF64, n32/n64, unspecified ABI, MIPS16/microMIPS, machine-specific
variants, shared/relocatable objects and PSP PRX are not covered by this lane.
Their family may be identified, but provider selection returns the specific
unsupported constraint rather than guessing a compatible profile.
Explicit `EF_MIPS_FP64` and `EF_MIPS_NAN2008` declarations are refused. Their
absence is insufficient: Clang can emit identical `e_flags` for FP32, FP64 and
soft-float targets. Target resolution also reads the 24-byte ABI flags record
identified by `PT_MIPS_ABIFLAGS` and/or `SHT_MIPS_ABIFLAGS`, without relying on
section names or the record being inside the initial 4 KiB header probe.
Program and section declarations must agree; duplicate, conflicting, truncated
or out-of-file records are rejected. Stripped section tables and section-only
records are supported. Extended table numbering is explicitly unsupported.
For carved ELFs whose section table extends beyond the captured file, REA
examines every complete captured section header and records the unavailable
headers as a limitation. A valid program-header ABI record can still establish
the supported declaration. Available section declarations must agree with it;
their duplicate, conflicting or unreadable records remain errors. A missing
program-header record does not make ABI declarations in uncaptured sections
absent or supply a default ABI.
The field layout follows
[`Elf_MIPS_ABIFlags_v0`](https://github.com/bminor/glibc/blob/master/elf/elf.h).
Provider admission requires record version 0, MIPS32r2, 32-bit GPR/CPR1, no CPR2,
and a double-precision or FPXX ABI declaration with no ISA extension, ASE or
unknown general flags. Missing records remain unknown rather than defaulting
to a compatible ABI, and this initial lane refuses them. Unknown record values
are retained for diagnosis but do not gain provider support. These checks bind
the declared interpretation; the integer-only fixture does not establish full
floating-point behavioral conformance.
MIPS header and ABI record facts are committed in the analysis profile so
interpretation changes invalidate profile-bound snapshots. The support-lane
identity is versioned independently of file identity. Evidence, lifecycle
outputs and saved snapshots preserve the `mips` family. Hopper and IDA adapters
do not implicitly gain MIPS support. Windows Ghidra P0 remains PE x86/x86-64 only.
## Use
With a caller-installed Ghidra and compatible JDK on a supported Linux/macOS host:
```bash
rea analyze /absolute/path/to/mips.elf --provider ghidra --json
rea function /absolute/path/to/mips.elf function_name --provider ghidra --json
```
MCP uses the existing tools, including `open_binary` with an absolute path and
`provider_id: "ghidra"`. No MIPS-specific tool catalog or emulator is introduced.
Inspect instructions, caller relationships and data alongside pseudocode. In
particular, delay-slot semantics are supplied by Ghidra, not reconstructed by
REA's ELF parser.
## Verification
The source-owned freestanding fixture is `tests/conformance/c/mips.c`. The
optional cross-target lane requires a caller-supplied Clang with MIPS targets,
LLD, GNU `readelf`, Ghidra and its compatible JDK; ordinary host-native checks
do not acquire these tools. `REA_MIPS_CLANG` selects Clang and
`REA_MIPS_READELF` selects GNU readelf (for example `greadelf` on macOS).
These are test-time prerequisites, not REA runtime providers.
```bash
GHIDRA_INSTALL_DIR=/absolute/path/to/ghidra npm run verify:ghidra:mips
```
The lane compiles both byte orders and never executes the targets. GNU readelf
independently supplies header/ABI facts and symbol addresses, compared with the
production REA target resolver before provider startup. Its version, bounded
command output and selected tool path are retained in the verification report.
The parser deliberately recognizes only this fixture's GNU output, rejecting
missing, ambiguous or unexpected fields rather than substituting defaults.
Existing public MCP operations check Ghidra's **observed** language/compiler
specification and loaded-file hashes. The source-owned `mips-probe.S` supplies
fixed ADDIU and conditional-branch encodings: verification checks bytes, length,
immediate and direct destination, independent of decompiler variable names.
Global and string bytes are checked at independently reported symbol addresses.
ELF load-image results retain observations even though REA's independent
load-image comparison currently covers DOS, not ELF; this lane checks those
observations and does not relabel the upstream result as verified.
CLI/MCP discovery and decompilation, direct calls, target/profile/Evidence
identity, snapshot round-trip and final process cleanup remain covered.
For both byte orders, the lane also carves away the section table while retaining
all program-header payloads. It checks the actual Ghidra language, entry-address
decompilation, distinct artifact digest and missing-section limitations through
CLI Evidence and an MCP-produced snapshot. Caller-selected Ghidra heap limits
are passed to these child workflows.
Pseudocode presence is a liveness check, not proof of semantic equivalence.
Instruction decoding and reader agreement likewise do not establish runtime,
delay-slot execution or complete floating-point semantics. Assertion regressions
reject incorrect byte order, constants, destinations and loaded identities.
Parser/profile tests are narrower checks, not substitutes for this real-provider
run. Report the actual lanes run and leave unexecuted verification pending.
+75
View File
@@ -0,0 +1,75 @@
# Ghidra provider semantics
REA imports one target into an ephemeral Ghidra database. Linux/macOS support
read-only analysis and atomic function-name/entry-comment edits; Windows P0 is
read-only. GUI controls and persistent database mutation are unavailable.
Executable bytes remain unchanged.
Use [installation](installation.md#ghidra) for supported hosts, prerequisites,
configuration, startup deadlines, resource controls, and cleanup recovery.
[Windows P0](windows-ghidra-p0.md) has its own admission and lifecycle boundary;
[NativeAOT recovery](ghidra-nativeaot.md) is an optional, separately verified
extension. Check the [release boundary](installation.md#released-package-and-main)
when using npm.
Provider selection and profile identity follow
[MCP contracts](mcp-contracts.md#identity-and-discovery). One deep
provider stays bound to the target; runtime failure never selects another
provider automatically. The contracts below describe Ghidra observations,
not equivalence with another engine's pseudocode or analysis database.
## Admitted inventory semantics
| Concern | Ghidra contract |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Program identity | One `analyzeHeadless` import produces exactly one Program; `list_documents` therefore returns exactly one name. |
| Addresses | Default memory uses lowercase `0x` hexadecimal. Non-default and external spaces use `<percent-encoded-space>:0x<hex>` and remain round-trippable. The handshake commits image base and default address-space name. |
| Symbols | `list_names` includes address-bearing memory and external symbols, including dynamic symbols, while excluding variable and no-address namespace records. Each item reports primary, dynamic, external, symbol type, and source facts. |
| Procedures | Both non-external and external functions are listed. A local thunk remains distinct from its resolved target; exact and qualified name lookup fails on ambiguity rather than guessing. |
| Strings | Only Ghidra-defined string `Data` is observed. Items report charset, byte length, and whether a required null terminator is missing. The API cannot distinguish a present terminator from fixed/Pascal layouts when no terminator is missing, so that state is named `present_or_not_required`. |
| Memory | Memory-block end addresses are exclusive. Read/write/execute, initialization, overlay, address space, and image base are direct Ghidra observations. |
| Inventory | Procedure, symbol, and string listings plus searches return the complete matching collection in one response; callers do not provide offsets or result-count limits. |
| Search | Literal and Java-regex searches scan the complete immutable inventory and return all matching entries inline. Search waits for a reply or caller cancellation; there are no caller-supplied offsets or result-count limits. |
| Analysis state | The socket is exposed only after default auto-analysis completes. Established operations wait for their reply or caller cancellation; there is no fixed response-size ceiling. |
## Admitted function-analysis semantics
| Concern | Ghidra contract |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Decompiler lifetime | One persistent `DecompInterface` is opened for the imported Program and disposed during bridge shutdown. Native decompilation has no fixed per-function deadline. External functions or functions without bodies return `null`; cancellation and native failure remain distinct. |
| Serialization | A FIFO sends one Program request at a time. Caller cancellation removes queued work promptly and is passed to active socket waits. This is an adapter safety commitment, not a claim that every Ghidra API is thread-safe. |
| Function identity | Every function result carries the entry address and Ghidra FunctionManager classification for external, thunk, and resolved thunk target. These are observations, not proof that unresolved targetless calls have been recovered. |
| Assembly and pseudocode | Assembly is complete Ghidra Listing text; pseudocode is Ghidra decompiler output. Neither is original source, and cross-provider comparison never treats Hopper and Ghidra text as equal or unequal semantic facts. |
| Instruction fast path | `read_function_instructions` returns every raw Listing instruction for the requested function without invoking the decompiler or whole-program name/string inventories. |
| Calls and references | Callers/callees contain only resolved functions. Reference edges preserve exact ReferenceManager type and call/jump/data/read/write/indirect/computed/conditional/terminal/external facts. Targetless computed flow remains unknown. Synthetic entry-point references without actionable memory sources are omitted explicitly. |
| CFG | Dossiers use `BasicBlockModel` and retain only non-call successors inside the function body. CFG topology is address-normalized for comparison; provider-specific block construction remains a declared difference. |
| P-code value flow | Function dossiers include up to 3,000 high-p-code operations, at most 64 inputs per operation, and 12,000 def-use edges. Results identify memory reads/writes, branches, and calls by p-code opcode, and mark decompiler-dead operations. Large results report truncation, an omitted-operation lower bound, and known omitted-input/edge counts. The dossier is an intra-function graph; `trace_native_values` composes derived parameter/argument and return/output dependencies across resolved calls. It does not resolve memory aliasing, call side effects, runtime behavior, persistent state, or business meaning. |
| Result extent | Function instruction scans and native API boundary observations remain complete. P-code flow is the explicit bounded exception; its count fields distinguish exact retained counts from lower-bound or known-omitted counts. Caller cancellation and provider failures remain distinct. |
`npm run verify:ghidra` compiles the versioned C oracle into debug and stripped
host-native targets (x86-64/AArch64 ELF on Linux or Mach-O on macOS), plus a native
DWARF 4 type-layout object. It proves the admitted operations, external functions, resolved thunks, exports, stripped-name
behavior, direct and targetless indirect calls, typed references, strings/xrefs,
multi-block CFG, bounded p-code def-use/effect links, semantic enhanced workflows, cancellation, startup deadlines,
serialized concurrency, malformed-target rejection, profile identity, and
process/project cleanup against real Ghidra 12.1.4. Unit fixtures separately
cover startup deadlines, process exit, queued cancellation, and malformed wire
output.
`npm run verify:ghidra:cross-format` adds AArch64 ELF, x86-64 PE, and x86-64
Mach-O target coverage. It requires `clang`, LLD, and `lld-link`; set
`REA_CLANG`, `REA_LLD`, or `REA_LLD_LINK` to select them. The verifier checks
these tools before compilation. Keeping this matrix separate lets Linux
host/provider acceptance run with only the host compiler.
`npm run verify:ghidra:windows` checks source-owned native x86-64 PE applications;
`-- --x86` selects x86 and `-- --dll` selects DLLs, and the flags can be combined.
These lanes check all 25 read-only operations, target/snapshot/import SHA-256 linkage,
and project, endpoint, process, and runtime cleanup. The independent native
lane checks DACLs, handle admission, cancellation, and Job Object lifecycle.
`npm run verify:ghidra:windows:package` packs and installs REA into an isolated
prefix, then checks ordinary-user CLI/MCP operations against canonical contracts.
It accepts the same architecture and DLL flags and verifies the selected PE role
in the analysis profile.
All lanes require matching native controls; package startup alone establishes
only package compatibility.
+387 -26
View File
@@ -68,7 +68,15 @@ selects the npm release, and persistent MCP registrations are pinned to the
version that performed setup. Installing newer instructions does not update a
running server or its registration.
The release checked on **2026-10-07** was **5.0.0** (133 MCP tools), published
The npm release checked on **2026-10-10** was **6.3.0**, published from
[`74cf9e14`](https://github.com/morluto/rea/commit/74cf9e1401fcd89482fe39c27cc898f5858e9b72),
with bundled skill version 34. It does not include automatic Pi or Hermes
registration: `setup --client pi` and `setup --client hermes` reject those IDs
before writing configuration. Their setup workflows below require a source build
or a later release containing those integrations; `@latest` alone cannot select
unpublished changes.
The earlier release checked on **2026-10-07** was **5.0.0** (133 MCP tools), published
from the fixed checkpoint
[`b33236ec`](https://github.com/morluto/rea/releases/tag/rea-agents-5.0.0).
The public CLI, MCP catalog and target-free session, and isolated update from
@@ -95,7 +103,7 @@ npx skills add morluto/rea --skill reverse-engineer-anything
This installs agent instructions and bundled references, not REA MCP
registration or analysis engines. Follow the skill's
[conditional connection guide](https://github.com/morluto/rea/blob/main/skill-src/reverse-engineer-anything/SKILL.md#connect-only-when-needed).
[conditional connection guide](https://github.com/morluto/rea/blob/main/.agents/skills/reverse-engineer-anything/SKILL.md#connect-only-when-needed).
Working tools can be used immediately. If tools are missing, inspect the current
client's registration with `doctor --client codex --json` (substitute its client
ID), then plan repairs with `setup --client codex --dry-run --json`. Show and
@@ -119,7 +127,8 @@ readiness for one task instead of auditing every integration, see
## Supported agents
Setup can configure these clients for REA's local MCP server:
Setup can configure these clients for REA's local MCP server. Grok Bot is
listed after the table because its connector is not one of these files:
| Client | `--client` value |
| ------------------ | ---------------- |
@@ -134,12 +143,184 @@ Setup can configure these clients for REA's local MCP server:
| Antigravity | `antigravity` |
| GitHub Copilot CLI | `copilot_cli` |
| Command Code | `commandcode` |
| Qwen Code | `qwen_code` |
| VS Code | `vscode` |
| Grok Build | `grok_build` |
| OMP | `omp` |
| Pi | `pi` |
| Hermes | `hermes` |
For GitHub Copilot CLI 1.0.95, `gpt-4.1` model metadata can block ordinary
chat with REA's full input-schema profile before sending a model request
(`compaction_static_context_blocked`; [#1554](https://github.com/morluto/rea/issues/1554)).
For the native offline OpenAI-compatible BYOK adapter, full-profile chat and
analysis also passed with a distinct `COPILOT_PROVIDER_MODEL_ID` such as
`rea-gpt-4.1`, `COPILOT_PROVIDER_WIRE_MODEL=gpt-4.1`, and that distinct ID selected
through `copilot --model rea-gpt-4.1`. The local fixture requested
`COPILOT_PROVIDER_MAX_PROMPT_TOKENS=1000000`; configure the limit supported by
your backend. This keeps every full schema and the actual wire model intact.
It does not establish the effective client budget or fix the built-in-ID path.
The existing compact profile passed native chat and analysis with the complete
tool inventory on Linux using a loopback model fixture. After setup, add
`"REA_MCP_INPUT_SCHEMA_PROFILE": "compact"` to the `env` object of the
`mcpServers.rea` entry in Copilot's `mcp-config.json`, preserving its other
settings, then restart the client. Compact advertisements can reduce nested
schema constraints; REA still validates complete canonical inputs. Full-profile
`gpt-5.4` metadata is also verified locally. Live model API acceptance and
Windows remain unverified; see [native client verification](testing.md).
For [Pi](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/mcp.md),
automatic setup requires a build containing the integration; npm 6.3.0 does not
include it. See [released package and main](#released-package-and-main).
In a supported build,
setup writes a `type: "stdio"` entry under `mcpServers.rea` in the user-level
`~/.pi/agent/mcp.json` and installs the bundled skill under `~/.agents/skills`.
Use `rea setup --client pi --dry-run --json` to inspect the plan, then
`rea setup --client pi --yes --json` to approve it. Check the registration with
`rea doctor --client pi --json`. Pi reads `mcp.json` as strict JSON, like its
own loader: comments, trailing commas, a byte-order mark, or an empty existing
file are invalid, and setup reports them instead of rewriting the file. Repair
such a file to plain JSON first, then rerun setup.
Setup follows Pi's `PI_CODING_AGENT_DIR`: unset or empty selects the default;
`~` and `~/` expand to the home directory; absolute paths and file URLs select
that directory; relative paths stay relative to the command's working directory.
On Windows, native paths, `~\`, and Git Bash/MSYS, Cygwin, and WSL drive paths
are normalized as Pi does. Run REA and Pi from the same working directory when
using a relative override. Pi has no profiles: `OMP_PROFILE`, `PI_PROFILE`,
`PI_CONFIG_DIR`, and OMP's `enabledServers`/`disabledServers` lists do not affect
Pi registration. Doctor accepts an omitted `type` for stdio but reports a
non-stdio type as invalid; `enabled: false` stays disabled.
REA configures only the user scope. Pi also reads `.pi/mcp.json` in trusted
projects; a same-name project entry can replace the user entry or override its
enabled state and exposure. Check that file if the user registration is aligned
but unavailable in a project. An extension that registers `/mcp` can replace
Pi's built-in MCP support and use its own configuration instead. Run `/reload`
in an existing Pi session after changing servers outside the session.
For Qwen Code, setup registers `rea` in the `mcpServers` table of the
user-level `~/.qwen/settings.json`, or `$QWEN_HOME/settings.json` when configured.
Setup and doctor follow Qwen Code's tilde and working-directory-relative home
overrides. Qwen Code also discovers personal skills in `~/.agents/skills`,
where setup installs the bundled workflow.
Gemini CLI uses `$GEMINI_CLI_HOME/.gemini/settings.json` when that home override
is nonempty, including its shared personal skills at
`$GEMINI_CLI_HOME/.agents/skills`. Setup and doctor check MCP allow/exclude
policies from system defaults, user settings, trusted workspace settings, and
system overrides. Workspace trust follows `GEMINI_CLI_TRUST_WORKSPACE`,
`GEMINI_RESTRICTED_MODE`, the effective `security.folderTrust.enabled` setting,
and the selected `trustedFolders.json` (including
`GEMINI_CLI_TRUSTED_FOLDERS_PATH`). Settings in an untrusted workspace do not
participate. A workspace or system `mcpServers.rea` replaces the entire user
entry; setup stops if the winning definition conflicts with its planned entry.
Review those files manually: setup never edits administrator/workspace settings
or grants workspace trust. Trust supplied only by a running IDE is outside this
standalone CLI check.
Codex treats an unset or empty `CODEX_HOME` as `~/.codex`. Devin honors
`XDG_CONFIG_HOME` for its `devin/mcp_config.json` on non-Windows systems.
For OMP, setup writes a `type: "stdio"` entry to the user-level
`~/.omp/agent/mcp.json`. It follows `PI_CONFIG_DIR` and
`PI_CODING_AGENT_DIR` (relative to the setup working directory), and the profile selected by `OMP_PROFILE` or
`PI_PROFILE` (`~/.omp/profiles/<name>/agent/mcp.json`). Setup also removes
`rea` from that file's `disabledServers` list, which would otherwise hide the
registration. Doctor treats an `enabled: false` entry as active when
`enabledServers` lists `rea`, as OMP does, unless `disabledServers` also lists
it. Run setup under each profile that should load REA.
For Hermes, automatic setup also requires a build containing the integration;
npm 6.3.0 does not include it. See
[released package and main](#released-package-and-main).
In a supported build, setup writes a `mcp_servers.rea` entry to `config.yaml`, preserving
comments and unrelated settings. It resolves that file from `HERMES_HOME`, else
from the platform default Hermes itself uses — `%LOCALAPPDATA%\hermes` on
Windows, `~/.hermes` elsewhere — including any `HERMES_DATA_DIR_SUFFIX`. Hermes
connects an entry unless `enabled` is false, so setup states `enabled: true`.
Hermes personal skills install under the active Hermes home's `skills` directory.
Setup, doctor and uninstall follow the root's `active_profile` selection, as
plain Hermes CLI commands do. An explicit `HERMES_HOME` pointing to
`profiles/<name>` selects that named profile directly. An invalid, missing or
deleted sticky profile is reported instead of writing into the default home;
repair the profile or run `hermes profile use default` before retrying.
REA follows `HERMES_HOME` whitespace trimming, environment-variable expansion,
and home expansion before resolving that profile. Setup previews the resolved
configuration and skill destinations; doctor and uninstall use those same paths.
### DeepSeek Harness
DeepSeek Harness uses a Cordis YAML patch sequence rather than a `mcpServers`
object. REA's `setup --client` does not edit this format. For Harness
`0.2.0-rc.2`, append the following entry to `$DSH_HOME/cordis.patch.yml`
(`~/.dsh/cordis.patch.yml` when `DSH_HOME` is unset). Preserve existing patches
and replace the executable paths with absolute paths from your installation:
```yaml
- insert:
- id: rea-mcp
name: "@deepseek-ai/dsh-mcp-client"
config:
serverName: rea
transport: stdio
command: /absolute/path/to/node
args: ["/absolute/path/to/rea/scripts/rea.mjs", mcp]
cwd: !!js process.cwd()
```
For a global npm installation, the launcher is under
`$(npm root -g)/rea-agents/scripts/rea.mjs`. Check the Node executable with
`command -v node`. Register `serverName: rea` only once in each active profile,
then restart Harness. It exposes tools as `mcp__rea__<tool_name>`.
Run `rea setup --skill --dry-run`, review the destination, then
`rea setup --skill --yes` to install the workflow in `~/.agents/skills`.
Harness discovers that directory, or `$DSH_AGENTS_HOME/skills` when configured;
its native `skill` tool can load `reverse-engineer-anything`.
REA's optional [native client verification](testing.md#end-to-end-integration-and-golden-evidence)
checks headless chat, skill loading, all tool input schemas and actual analysis
using the installed Harness and a local model fixture. This establishes the
Harness integration, with live DeepSeek API compatibility remaining unverified.
See the [Harness MCP guide](https://github.com/deepseek-ai/deepseek-harness/blob/639ed015397290b3745d163aafe02ffee4aa3f84/packages/mcp/mcp-client/README.md)
for its native configuration contract.
### Other client settings
For OpenCode, setup writes the V1 `mcp.rea` entry, which OpenCode V1 and V2
both load. If the configuration already uses OpenCode V2's native
`mcp.servers` table, setup registers REA there instead and replaces any earlier
`mcp.rea` entry from REA.
`mcp.rea` entry from REA. Setup honors `OPENCODE_CONFIG_DIR` and
`OPENCODE_CONFIG`, preferring the later-loaded JSONC file when both JSON and
JSONC exist. The ordinary XDG global configuration still participates when a
custom directory is selected. Doctor checks the merged user registration; uninstall removes
REA-owned entries from every applicable user file so an older entry cannot
become active again. Malformed applicable files block setup before changes.
Grok Build loads `[mcp_servers.rea]` from `$GROK_HOME/config.toml`, or from
`~/.grok/config.toml` when `GROK_HOME` is unset or empty. Setup edits that server
table, `[mcp_servers.rea.env]`, and a root `disabled_mcp_servers` entry that
names `rea`. It sets `startup_timeout_sec = 30` and leaves every other name
in that list. The shared skill installed under `~/.agents/skills` is already
on Grok Build's skill path.
Grok Bot (`grok_bot`) is detected from `~/.grokbot`, or from `SAND_DATA_ROOT`
when that value is an absolute path. A relative or empty `SAND_DATA_ROOT`
stays on `~/.grokbot`. That directory is not the connector store. Grok Bot
keeps connectors in the signed-in account and runs them on its hosted
computer. It does not import `mcp.json` from the data directory, and it does
not attach a stdio server running on this machine. Setup does not call the
account connector API, does not write a registration file, and does not report
the data directory as aligned. Ask the Grok Bot chat to add a custom MCP
server named `rea` that runs on the Bot's computer:
```bash
npx -y rea-agents@<version> mcp
```
Do not put credentials in that command or its arguments. `rea doctor --client grok_bot`
reports this manual step. `rea uninstall` does not remove the account connector.
## Review setup changes
@@ -156,6 +337,20 @@ default. Hopper is a separate optional choice: setup shows its proposed
installation or connection and requires its own explicit approval. It can also
save verified paths for an existing Ghidra installation.
The bundled skill is installed where each selected client discovers personal
skills: Claude Code uses `~/.claude/skills` (or
`$CLAUDE_CONFIG_DIR/skills` when configured). Gemini CLI uses `.agents/skills`
under its selected home; Antigravity 2.0 uses `~/.gemini/config/skills`.
Other integrations, including Qwen Code, use `~/.agents/skills`.
A mixed selection plans each distinct destination. Selecting the skill without a client uses the shared
directory. Setup leaves existing skill copies in other locations untouched.
`doctor --skill --json` verifies the selected copies against the bundled
instructions and references. Consumers should use `identity.skill.state`,
`installed_version`, and `installed_tool_count` for skill readiness. The
obsolete `installed_catalog_digest` field has been removed; current catalog
identity remains available at `identity.catalog`.
After selection, review the plan's exact paths and changes and approve before
REA writes files or installs Hopper. You can cancel at any prompt.
@@ -163,14 +358,21 @@ Before applying changes, REA checks your current configuration. The plan lists:
- an existing Hopper installation, a verified existing Ghidra installation, or the official Hopper package it proposes to install;
- each detected agent configuration path;
- the REA skill destination;
- each selected REA skill destination;
- external software, network origins, integrity evidence, and package-manager
commands.
Malformed or unsafe existing configuration blocks the whole transaction before
Hopper installation or any file write. Declining or pressing Ctrl-C makes no
changes. Agent configuration writes preserve unrelated
entries, create backups, use atomic replacement, and verify their result.
changes. Agent configuration writes preserve unrelated entries and comments,
create backups, use atomic replacement, and verify their result. Setup and
uninstall retain an existing `.rea.backup` rather than replacing the first snapshot.
Setup also retains valid environment overrides in REA's existing server entry,
such as `REA_MCP_INPUT_SCHEMA_PROFILE` and `REA_MCP_MAX_RESPONSE_BYTES`.
Detected provider settings replace only matching environment keys.
Setup and doctor report a malformed REA environment map or invalid runtime
setting before setup writes files. Repair the named setting in the client
configuration; setup does not silently discard the rest of the map.
After setup, REA reports which agents, analysis tools, and workflow files passed
its final checks. Restart any agent named in the completion message, then begin
@@ -209,7 +411,7 @@ rea setup --yes --all-detected --install-hopper --json
Setup pins package-runner MCP registrations to the exact installed REA version,
installs the matching skill and on-demand references in the same plan, and adds
`startup_timeout_sec = 30` for Codex. `rea update` installs the exact resolved
`startup_timeout_sec = 30` for Codex and Grok Build. `rea update` installs the exact resolved
release into the npm prefix that owns the running package, then checks the new
executable's version before reporting success. It does not reopen onboarding.
Release lookup and installation both use npm's configured registry.
@@ -253,7 +455,7 @@ vendor-defined limits, and a paid license is optional. REA reuses any detected
installation and preserves Hopper during uninstall.
The supported native host baseline is macOS 12+, Ubuntu 24.04+, Fedora 41+,
64-bit Arch Linux, or CachyOS. Ghidra and IDA have their own provider-specific
Nobara 44+, 64-bit Arch Linux, or CachyOS. Ghidra and IDA have their own provider-specific
host requirements; Windows Ghidra uses the [experimental P0 boundary](windows-ghidra-p0.md).
On macOS, approved setup downloads the official DMG, checks its published size
@@ -284,6 +486,19 @@ host mount and the rest of `/tmp` remain unchanged; this fallback never invokes
`sudo`. `rea doctor --provider hopper --json` reports the selected
strategy and both host and effective mount facts.
The supported Linux demo forwards additional launches into its existing
application, even across private displays. REA therefore reserves one Linux
Hopper application per user across cooperating REA processes. A competing
CLI or MCP session receives the owning session ID before Hopper is launched,
for both the same target and a different target. Switch targets through that
MCP session, or close it before starting another session. Closing the owner
releases the reservation. This does not attach to or claim ownership of
manually opened Hopper applications.
Stale lease recovery is serialized. If an interrupted recovery leaves its
reservation directory, the diagnostic identifies that exact path. Stop REA
sessions before removing that recovery directory and retrying.
### Launcher paths and troubleshooting
On macOS, REA uses
@@ -314,9 +529,69 @@ Hopper serializes analysis requests. Cancelling a wait can leave provider work
running, which the session reports. Successful decompilation is cached until
a relevant rename or comment changes it.
Closing a session shuts down REA's bridge and removes its temporary socket
directory while preserving the Hopper application. A `cleanup_incomplete`
Analysis and annotation calls stay bound to the active target's native Hopper
document, even when GUI focus changes or other documents have the same display
name. Use `open_binary` to change targets. Byte reads stop at a segment boundary
and return the readable prefix with `complete: false`. File-offset mapping checks
the reverse lookup and original executable bounds; synthetic external-symbol
memory has no original file offset. For FAT Mach-O, offsets refer to the original
container file. Results retain Hopper's image-relative offset, the observed slice
base, and the source executable path.
Loader selection reads the Mach-O container header, including FAT files with a
single architecture. For FAT64, REA validates the architecture table and selected
Mach-O header, prepares a private thin image, and loads it with Hopper's native
Mach-O loader. It checks the entire source's SHA-256 while copying the slice;
source identity and reported offsets still refer to the original container.
An ambiguous architecture subtype requires an explicitly extracted thin image;
REA does not guess. Configured loader arguments remain explicit overrides.
FAT64 is distinct from the CPU architecture: FAT32 containers can contain 64-bit
executable images. This preparation avoids the Raw Binary loader dialog observed
with native FAT64 loading on Hopper 6.1.0-demo.
The prepared image and its owned document close together, including on MCP exit;
if document closure is unconfirmed, REA retains the backing image and reports
`cleanup_incomplete` with its path. Ordinary documents retain their existing
MCP-exit behavior.
Startup deadlines report missing bridge readiness and preserve the launcher
outcome; a successful helper exit does not prove that a loader dialog completed.
Cursor navigation returns the observed object start when Hopper snaps an interior
address; adjacent-object navigation rejects unmapped inputs and document ends.
Native API text rejects NUL characters and unpaired Unicode surrogates before
annotation changes. Renames preserve unselected label owners; use a batch with
all affected addresses to move or swap existing labels explicitly. Every rename
destination must be mapped, and native symbol names must fit Hopper's 1024 UTF-16
code-unit limit. Oversized names fail before any batch edits; bookmarks and
literal string results are not subject to that symbol-name limit. Rename success
requires exact final readback. New bookmarks must point into mapped memory;
existing legacy bookmarks outside it can still be removed.
String results read each native typed object's complete bytes, retain the original
provider display in `provider_value`, and report its encoding, byte length, and
termination. `encoding_status: inferred` distinguishes REA's decoding from an
observed source encoding. Hopper can split long literals into adjacent
unterminated objects; search matches each object's decoded bytes independently.
Undecodable objects retain native display text with `decoding.available: false`
and a reason, so one uncertain object does not block unrelated inspections.
Function dossiers retain this same string evidence. Native call edges retain
Hopper's partial `CallReference` classification and exact endpoints; detailed
reference flags remain unavailable rather than being invented.
Regex searches use ECMAScript Unicode syntax in a cancellable worker with a
five-second matching deadline. Deadline or cancellation stops matching while
leaving the Hopper API available. Literal mode retains Unicode casefold matching.
Closing or switching a target closes its bound Hopper document, shuts down REA's
bridge and removes its temporary socket directory while preserving the Hopper
application and unrelated documents. A `cleanup_incomplete`
result identifies resources whose cleanup could not be verified.
REA retains unresolved cleanup ownership and any confirmed shutdown phases.
After addressing the reported failure, retry `close_binary` on the same
connection. Unconfirmed document or process cleanup retains the target/application
lease and prevents another client from launching against that owned resource.
Once document and process closure are confirmed, the lease can be released even
if temporary-file cleanup fails. Another client can then launch, but the owning
client must finish its retained cleanup before starting again.
An unconfirmed external document can be retried while its authenticated bridge
remains connected. If that bridge has disconnected, another close cannot confirm
the document: inspect and close the reported document in Hopper before ending
the owning REA connection.
### Hopper in CI
@@ -340,14 +615,20 @@ copying license secrets into logs, or killing unrelated Hopper processes.
## Ghidra
REA connects to an existing Ghidra installation on Linux x64, macOS x64/arm64,
REA connects to an existing Ghidra installation on Linux x64/arm64, macOS x64/arm64,
or experimental Windows x64 P0.
It accepts Ghidra 12.1.x and the 64-bit full JDK declared by that installation's
`application.java.min` and `application.java.max`. Current 12.1 releases require
JDK 21 or newer and set no maximum. The bridge is verified with Ghidra 12.1.4
and JDK 21. On macOS, the installation
must include the native decompiler for the host architecture; REA does not
build it or change Gatekeeper quarantine settings.
and JDK 21. Each installation must include the native decompiler for the host
architecture in `Ghidra/Features/Decompiler/os/<platform>/` or the corresponding
`build/os/<platform>/` directory. Linux ARM64 uses `linux_arm_64`; official
release archives may require you to build that native component separately.
REA checks the executable prerequisite by inspecting the file's own executable
header, so a native component built for another platform or architecture is
reported as incompatible instead of being admitted from its directory name, and
a header that cannot be read or recognized is reported as unknown. REA does not
build or install native tools, or change Gatekeeper quarantine settings.
The adapter exposes 25 read-only operations: thirteen inventory/name/search
operations and twelve function-analysis operations. These cover metadata,
@@ -356,11 +637,13 @@ dossiers, instructions, recovered data types, measured load mappings, loaded
memory bytes, and observed file offsets. Independent load-image attestation
supports DOS MZ and explicitly selected COM; PE returns its measurements with that limitation.
On Linux and macOS, `annotate_native_function` also edits a function name and/or
entry comments atomically and returns refreshed analysis. These session metadata
edits leave executable bytes unchanged and are discarded on close. GUI controls
entry comments atomically and returns refreshed analysis, and `set_address_name`
and `set_addresses_names` name a function entry or any other mapped address
(creating or renaming its primary label) with per-address success results. These
session metadata edits leave executable bytes unchanged and are discarded on close. GUI controls
require Hopper; Windows P0 remains read-only.
Windows P0 admits native x86 and x86-64 PE applications on fixed local NTFS volumes.
Windows P0 admits native x86 and x86-64 PE applications and DLLs on fixed local NTFS volumes.
The npm package bundles native Job Object ownership, protected private runtime
DACLs, and handle-based path admission; no separate addon installation is needed.
See the [Windows Ghidra P0 guide](windows-ghidra-p0.md) for verified scope and
@@ -401,17 +684,32 @@ installs, upgrades, or modifies Ghidra or Java.
Each verified session uses an ephemeral temporary project and isolated
home/cache/config/temp paths. REA passes `-readOnly`, `-deleteProject`, uses
Ghidra's default analysis and resource settings, and loads its packaged Java
Ghidra's default analysis settings, and loads its packaged Java
bridge via `-scriptPath`; it never opens an existing user project. Linux and
macOS use a current-user-only local bridge socket and descriptor. The
experimental Windows transport uses authenticated IPv4 loopback with a
project remains under the selected temporary directory. If its Unix socket
pathname would exceed the host's byte limit, REA allocates a separate mode-0700
socket directory under `/tmp` and removes it on close, cancellation, or failure.
Diagnostics retain the actual endpoint and both owned directories.
On Linux and macOS, REA starts the inspected JVM directly using Ghidra's own LaunchSupport
configuration. Apple platform shell wrappers hide their environments from
ownership inspection, so retaining those wrappers would prevent verified
process-group cancellation during startup.
If ownership remains unverifiable, it reports the reason and retains the process
supervisor and private runtime instead of removing files beneath a live provider.
The experimental Windows transport uses authenticated IPv4 loopback with a
private native-owned bearer descriptor and Job Object process ownership.
Operations begin only after default auto-analysis completes. `open_binary`
selects and validates the target/provider binding; it does not wait for Ghidra
import and auto-analysis. The first Ghidra-backed query starts that work lazily.
The provider startup deadline is 330,000 ms for import, analysis, bridge, and
health readiness; a startup failure is returned by the query that triggered it,
The provider startup deadline is 330,000 ms by default for import, analysis,
bridge, and health readiness. Large binaries can need more: set
`REA_GHIDRA_STARTUP_TIMEOUT_MS` to an integer between 1 and 2,147,483,647
milliseconds in the server environment. An absent setting uses the default;
empty, invalid or out-of-range supplied values fail configuration validation.
REA parses the supplied configuration environment and
passes the deadline to each provider client; a startup failure is returned by the query that triggered it,
without exposing partial analysis. This deadline is separate from MCP transport
initialization and the client's deadline for that individual tool call. A client
can time out earlier even when Ghidra would complete within its startup deadline.
@@ -427,6 +725,65 @@ is no fixed per-operation or response-size ceiling. Unresolved computed calls
remain unknown, reference-kind provenance is preserved, and provider-specific
pseudocode is never treated as original source or Hopper-equivalent text.
### Ghidra heap and CPU controls
Set resource controls in the environment that launches the CLI or MCP server,
before opening a new Ghidra session. On Linux and macOS, REA chooses the first
nonempty setting in this order: `GHIDRA_HEADLESS_MAXMEM`, `GHIDRA_MAXMEM`, then
`2G`. The chosen value becomes the JVM's `-Xmx` argument. Use a JVM heap-size
value such as `512M` or `2G`; an invalid value causes Java startup to fail.
The supported Ghidra 12.1.4 Windows headless script consumes the same settings
with the same precedence.
For a small target on a constrained host:
```bash
export GHIDRA_HEADLESS_MAXMEM=512M
```
In PowerShell:
```powershell
$env:GHIDRA_HEADLESS_MAXMEM = "512M"
```
An MCP client must pass this setting to its REA server process; changing an
unrelated terminal's environment does not reconfigure an existing server or
JVM. A 512 MiB heap was verified with small native fixtures, but larger targets
can require more memory. The Java heap limit does not bound JVM RSS, Node's
heap, or total memory used by the process family. The startup deadline controls
waiting time independently of these memory settings.
REA clears `_JAVA_OPTIONS`, `JAVA_TOOL_OPTIONS`, `JDK_JAVA_OPTIONS`, and
`GHIDRA_JAVA_OPTIONS` inherited from the caller, and owns
`GHIDRA_HEADLESS_JAVA_OPTIONS`. Custom flags injected through these variables
are not supported configuration. On Windows, REA replaces `JDK_JAVA_OPTIONS`
with its own isolated home/temp settings and `-XX:-UsePerfData`; on Linux and
macOS it supplies isolated paths directly to Java. Use the supported heap
settings above instead of adding a second `-Xmx` through an injection variable.
The Linux/macOS launch sets `-XX:ParallelGCThreads=2` and
`-XX:CICompilerCount=2`; the supported Windows headless script also sets these
counts. These constrain particular JVM thread pools, not all analysis threads
or CPU usage. REA does not pass Ghidra's `-max-cpu` option or expose a general
Ghidra CPU limit. When needed, apply host CPU affinity and scheduling controls
to the REA process and verify the resulting JVM's affinity. Select CPUs allowed
on the host; do not assume CPU numbers from another machine are valid.
Verify controls at their consumer after the first Ghidra-backed query starts
the JVM: inspect that owned JVM's effective `-Xmx` and GC/compiler flags, CPU
affinity, and observed memory use. Do not infer them from the parent shell's
environment or the absence of an error. On Linux, `/proc/<jvm-pid>/cmdline`
contains the launch arguments and `/proc/<jvm-pid>/status` reports
`Cpus_allowed_list` and `VmRSS`. Inspect only the process belonging to this
session and retain the resource flags needed for the measurement rather than
copying full command lines or environments into reports. Heap and affinity
settings affect cost and latency; they are not part of REA's semantic analysis
profile identity. See [real-provider testing](testing.md) for bounded
verification workflows.
### Ghidra diagnostics and verification
Unexpected request failures retain their original internal cause. CLI and MCP
errors expose Error names, messages, and available codes under
`details.diagnostics.failure_cause`; other rejection values retain their
@@ -436,7 +793,7 @@ continues. These messages redact known bridge authentication tokens and
preserve local paths and other analysis context.
Run `GHIDRA_INSTALL_DIR=... npm run verify:ghidra` from a source checkout to
compile and analyze debug and stripped host-native fixtures (ELF on Linux x64
compile and analyze debug and stripped host-native fixtures (ELF on Linux x64/arm64
or Mach-O on macOS), plus a native DWARF 4 type-layout object. This lane needs a
host C compiler in addition to Ghidra and its JDK.
@@ -468,8 +825,12 @@ rea uninstall --purge-data
Uninstall preserves Hopper, Node.js, Evidence files, captures, unrelated skills
and other MCP servers. Purging removes only REA's cache and state under
`~/.rea`; malformed client configuration or purge-path symlinks stop the
operation. See the [CLI guide](cli.md#output-and-exit-status) for exit statuses.
`~/.rea`. A client configuration that is malformed, unreadable, or at an unsafe
path stops the operation before anything is removed, and a client that fails
while being updated stops the remaining removals. A purge path that is a
symbolic link is retained and reported rather than followed. Uninstall checks
REA's managed shared and Claude Code personal skill locations. See the
[CLI guide](cli.md#output-and-exit-status) for exit statuses.
## MCP Registry
@@ -490,7 +851,7 @@ For a client that requires manual configuration, use:
"mcpServers": {
"rea": {
"command": "npx",
"args": ["-y", "rea-agents@6.0.0", "mcp"]
"args": ["-y", "rea-agents@6.3.0", "mcp"]
}
}
}
+12
View File
@@ -73,6 +73,18 @@ The directed relation vocabulary is `contains`, `loads`, `imports`, `maps_to`,
and `changed_from`. Provider names are deliberately absent from both
vocabularies.
For a `maps_to` edge targeting a source-map node, the edge carries
`resolved_path` and `declared_url_sha256`. The target node's reference
observation carries that same digest and the exact `declared_url`; match the
digest to select the URL belonging to that edge when several references share
one physical source map. The full URL is kept out of node identity, display
label, and edge properties, so large inline data URLs are stored once per
source-map reference.
Consumers previously reading `edge.properties.declared_url` should follow
`target_node_id` and select the observation by `declared_url_sha256` instead.
Node labels serve display; the observation preserves the original URL.
For example, a source-owned synthetic fixture proves this path without using a
third-party application:
+111 -23
View File
@@ -2,12 +2,15 @@
REA derives a complete reachable feature trace from one authenticated JavaScript
Application Graph and compares two authenticated graph versions. The MCP tools
are `trace_application_feature`, `trace_javascript_semantics`,
`compare_application_versions`, `compare_source_to_bundle`, and
`compare_javascript_export_shapes`; their CLI equivalents use the same names
with hyphens.
are `inspect_analysis_view`, `trace_application_feature`,
`trace_javascript_semantics`, `compare_application_versions`,
`compare_source_to_bundle`, and `compare_javascript_export_shapes`; their CLI
equivalents use the same names with hyphens. `inspect_analysis_view` projects a
summary, module page, or one module from already completed application
Evidence; it does not walk relationships.
These workflows consume Evidence produced by
`inspect_analysis_view` also projects retained `inspect_binary_layout`
Evidence. The remaining workflows consume Evidence produced by
`analyze_javascript_application` or `reconcile_javascript_runtime`. They do not
read an artifact, execute application code, attach to a process, or open a
native-analysis provider. Static artifact observations, passive runtime
@@ -20,6 +23,15 @@ artifact digest and structural graph ID. Semantic tracing requires the semantic
relation graph and reports when it is unavailable rather than treating missing
data as an empty graph.
The semantic graph wire format stores shared non-location provenance once in
its required `evidence_contexts` table. Each node, relation, fingerprint, and
unknown retains its exact `evidence.location` and names the owning context with
`evidence.context_id`. This is a breaking representation change: consumers
reading fields such as `evidence.authority` must look up the context by ID and
combine its fields with the fact's location. Semantic trace results include the
canonical context subset referenced by their returned facts, so those facts
remain self-contained in the response.
## Feature tracing
Select one literal seed kind: node ID, route, string, API, IPC channel, module,
@@ -57,13 +69,12 @@ validation boundaries, and built-in resource acquisition/release.
Mutation tracking covers explicit member assignments, updates, deletion, and
loop assignment targets, including the supported local aliases and shared
nested references. Calls such as `Object.assign`, `Reflect.set`, and
`Reflect.deleteProperty`, and writes reaching a caller's object through another
function's parameter, are not tracked by this mutation pass. These channels
can leave an initializer-derived literal in the graph even after the runtime
value changes. Treat such a result as an uncovered mutation channel, not as
proof of the current runtime value; a follow-up needs to model that channel
and verify its caller/alias behavior.
nested references. Calls conservatively invalidate exposed mutable references;
callee bodies and built-ins such as `Object.assign`, `Reflect.set`, and
`Reflect.deleteProperty` are not interpreted to establish exact post-call
values. This uncertainty does not prove that a call actually mutated a value.
Interprocedural aliasing beyond the supported call-site references remains
outside this mutation pass.
Function fingerprints commit normalized syntax, control-flow shape, relation
shape, literal sets, arity, and detected effects without using local names or
@@ -79,6 +90,44 @@ keep the result ambiguous. Runtime Evidence can later corroborate an exact
mapped candidate, but structural reachability, semantic influence, runtime
observation, and causal proof remain separate claims.
Semantic literal nodes keep their complete value in `properties.value`; literal
queries match that field. String labels use `string literal` when that is
shorter than the complete JSON value. A literal's `identity.role_key` commits
its canonical JSON value as `value-sha256:<digest>` when the digest key is
shorter; smaller values keep their existing JSON key. This keeps large values
out of identity and display metadata without expanding short values or
truncating their Evidence.
New analyses therefore produce different IDs for hashed literals from the
earlier payload-bearing role keys. Use IDs returned by the selected parent
graph and read literal values from `properties.value`, rather than decoding
role keys or labels. Previously stored graphs and their original IDs remain
valid inputs.
Endpoint nodes keep the exact endpoint in each observation's `properties.value`;
semantic request and response nodes keep it in `properties.endpoint`. Endpoint
identity keys use `value-sha256:<digest>` over the canonical JSON string when
that is shorter, or when the original value starts with the reserved digest
prefix. Other short endpoint keys remain unchanged. Endpoint labels use the
shorter of the exact value and `<kind> endpoint`; semantic request/response
labels use the shorter of the endpoint and operation method. These labels are
display metadata, not endpoint lookup values.
New analyses therefore change hashed endpoint IDs and longer endpoint labels.
Use IDs from the selected graph and read the complete endpoint properties;
previously stored graphs still support their original IDs. Literal endpoint
search, semantic tracing, and version comparison use the preserved values.
Event and listener nodes likewise preserve the complete event name in
`properties.event_name`. Event role keys use the same reserved-prefix string
digest rule, scoped to the emitter; repeated registrations, removals, and
dispatches keep one event per exact emitter/name pair. Long event labels use
`event`, and listener labels use the shorter of `<method>:<name>` and
`<method>:listener`. Dynamic names remain `null` with explicit uncertainty. New analyses
change hashed event IDs and longer event/listener labels; query the preserved
name or select IDs from the parent graph. Previously stored graphs keep their
original IDs and remain valid trace inputs.
## Version comparison
REA pairs entities only when a tier produces one unique candidate on each side.
@@ -134,25 +183,64 @@ Direct return expressions, including expression-bodied arrows, are evaluated
through an execution-free value lattice. Literal object fields and direct
return sites are represented in the result. Calls, dynamic spreads, computed
keys, and parser recovery remain partial or unknown.
Objects and arrays passed to calls, constructors, or tagged templates, used
as method receivers, or stored through property targets are not assumed
unchanged afterward. Property stores conservatively retain reference escape
uncertainty rather than pretending to execute later writes. References
handed back by local functions, methods, constructors, async functions, and
generators also retain escape uncertainty, including when the call is read-only;
this does not establish that a mutation occurred. Aliases
and shared children in spread and rest copies retain that uncertainty; copied
primitive slots and unrelated containing properties remain known. Object rest
excludes consumed keys, array rest excludes the consumed prefix for known
arrays, and later explicit data properties and methods replace earlier object
spread references. A known array prefix does not expose values from a following
spread. Accessors, custom or uncertain iteration, unknown computed keys, and
unknown spread lengths retain conservative uncertainty.
Nested callable returns are not assigned to their parent callable. Projected
graph observations carry source ranges but never source text.
Return variants pair only when a literal discriminant such as `/type` has one
unique occurrence on each side and pairing is reciprocal. Changes use JSON
Pointer paths with `added`, `removed`, `changed`, or `unknown` status. A missing
field is added or removed only when the relevant parent-property coverage is
complete on both shapes. The output includes exact selector candidates,
omissions, Evidence links, coverage, and limitations; it does not execute
JavaScript. When runtime semantics matter, run behavioral probes directly
against the relevant application versions and capture them through the
available browser, Electron, or process workflows.
unique occurrence on each side and pairing is reciprocal. Source order never
implies correspondence. Each retained variant contributes a property inventory
of observed JSON Pointer names, including fields whose static values stay
unknown, plus that variant's parent-property coverage.
Changes use JSON Pointer paths with `added`, `removed`, `changed`, or `unknown`
status and a separate `presence` object (`present`, `absent`, or
`unknown-coverage`) on each side. A name is `added` or `removed` when one paired
shape proves presence and the other proves absence. Complete parent-property
coverage can establish absence even when field values stay unresolved. Identical literals are
omitted. Unresolved values that remain on both sides stay `unknown` when the
projections differ, and are omitted when presence is unchanged and the unknown
projections match. Incomplete spreads and other partial parent coverage keep
one-sided names `unknown` with `unknown-coverage` on the incomplete side.
Unpaired variants remain visible as unknown changes and still list their
property inventories, each with its own `source_range`. Inventories exclude
array holes and slots whose presence was invalidated by mutation; an unresolved
value alone does not make an observed property uncertain. `summary.added` and
`summary.removed` count
presence-level add/remove as well as literal value add/remove;
`summary.unknown` does not absorb complete-coverage presence-only gaps.
A partial comparison still records an unknown in the MCP session when matching
uncertain projections produce no changes and `summary.unknown` is zero.
The output includes exact selector candidates, omissions, Evidence links,
coverage, and limitations; it does not execute JavaScript. When runtime
semantics matter, run behavioral probes directly against the relevant
application versions and capture them through the available browser, Electron,
or process workflows.
## CLI and verification
All five CLI commands accept inline JSON or a path to a JSON file. The CLI
All six CLI commands accept inline JSON or a path to a JSON file. The CLI
returns an Evidence record directly. Put the full records in a later CLI input;
a separate CLI process has no retained MCP connection state.
File inputs must be regular files; symlinks to regular files are accepted.
Directories, named pipes and device files produce an input error before JSON
parsing.
For a literal string trace, analyze your supplied tree once, then build the
input from the saved Evidence (replace the target and seed):
@@ -167,8 +255,8 @@ writeFileSync("trace-input.json", JSON.stringify({
rea trace-application-feature ./trace-input.json --json
```
MCP analysis returns an envelope containing `result`, `evidence_id`, and full
`evidence`. If the connected server advertises retained references, reuse its
MCP analysis returns the complete Evidence record, with the operation result
in `normalized_result` and its identity in `evidence_id`. If the connected server advertises retained references, reuse its
exact returned ID as `{"kind":"retained-evidence","evidence_id":"RETURNED_ID"}`
in `application`, or `left`/`right` for comparisons. `RETURNED_ID` is a template,
not a literal valid ID. Native Evidence arrays still use complete records.
+129 -15
View File
@@ -22,7 +22,7 @@ The tool reads the caller-selected local directory or ASAR path directly:
```bash
rea analyze /absolute/path/to/apps/app.asar --json
rea analyze-javascript-application /absolute/path/to/apps/app.asar \
--json
--integrity-policy record-and-continue --json
```
Generic `rea analyze` selects this static provider for directories and `.asar`
@@ -47,11 +47,14 @@ The equivalent MCP input is:
```json
{
"input_path": "/absolute/path/to/apps/app.asar",
"format": "auto"
"format": "auto",
"integrity_policy": "fail"
}
```
`input_path` must be absolute. `format` accepts `auto`, `asar`, or `directory`.
`integrity_policy` accepts `fail` or `record-and-continue`; both CLI routes and
the MCP tool default to `fail`.
The result retains the canonical local path, root artifact digest, artifact
manifest and graph commitments, JavaScript Application Graph, static
Electron summary, reconstruction statistics, and explicit limitations. It does
@@ -63,8 +66,12 @@ ASAR inventory checks Electron integrity metadata for embedded archive entries
and supplied `.asar.unpacked` companion files. An integrity failure identifies
the logical path, declared and calculated SHA-256 values, and whether the entry
was unpacked. By default, a mismatch is returned as a failure with its artifact
context. Requests that support `integrity_policy` can explicitly select
`record-and-continue` to inspect verified siblings while retaining the mismatch.
context. Application analysis can explicitly select `record-and-continue` to
analyze observed bytes while retaining each contradiction's declared and
observed hashes and `observed-untrusted` trust. Such results mark application
graph coverage partial and include every contradicted path in the limitations.
Mismatched nested ASARs stay opaque rather than being expanded. An unpacked
entry whose companion bytes were not supplied remains `unavailable`.
An unpacked entry whose companion bytes were not supplied remains
`unavailable`. REA continues analyzing embedded JavaScript and records the
@@ -82,9 +89,9 @@ queries use per-file range indexes, while call sites use exact-range lookups.
Existing node budgets and coverage reporting remain in effect.
Progress identifies the source file being parsed and projected. Cancellation is
checked between files, with event-loop yields that allow notifications and
completed file-local allocations to be released. A single file's synchronous
parser and semantic extraction still need to finish before that boundary.
checked between files and throughout result transfer. The owned analyzer can
be stopped while its synchronous parser or semantic extractor is active;
the CLI/MCP process remains available for control requests.
Graph and Evidence identifiers hash canonical JSON incrementally, without
assembling a single string for the whole graph. The canonical bytes and existing
@@ -105,17 +112,85 @@ Field selection remains useful when the caller needs a
smaller view, for example `--format json --filter-output
evidence_id,normalized_result.statistics`. Streaming output does not bound the
memory needed to construct the analysis graph itself.
JavaScript source parsing, static analysis and semantic projection run in one
owned analysis process, reused sequentially across files. Target code is never
executed. The analyzer defaults to 1024 MiB of V8 old-space and a 300000 ms
deadline per source, including startup and fact transfer. Select
`max_heap_mb` and `analysis_timeout_ms` through MCP, or `--max-heap-mb` and
`--analysis-timeout-ms` on the dedicated CLI command. These choices control the
analyzer; the caller's `NODE_OPTIONS` still controls the CLI/MCP process heap.
V8 old-space limits do not impose a process RSS limit.
A source that exhausts the analyzer heap does not terminate the CLI/MCP
process. Completed static facts are retained, other files can still be analyzed,
and unexamined semantic relationships remain explicit unknowns. The parent
also checks transfer expansion and accumulated results against its remaining
heap before accepting semantic facts. A resource-limited result has partial
coverage, the observed limits and an `analyze-javascript-source` unknown scope
with the specific failure, including captured diagnostics when available.
Resource failures do not increment syntax parse failures. There is no fixed
source-length cutoff.
Static observations also need memory when expanded into nodes, relationships
and Evidence. If that expansion does not fit, the file node retains
`static_analysis` and any admitted `semantic_module_analysis` observations,
including their exact values and source locations. Use the public modules item
view to read them. The graph marks those unexpanded relationships as unknown.
If cumulative result capacity is exhausted, analysis stops; inventoried but
unexamined files remain present with explicit unknown scopes.
A timeout stops the remaining analysis and returns typed failure details with
completed partial Evidence. MCP failure details return
`partial_observation: { kind: "retained-evidence", evidence_id: "..." }`
after recording succeeds, so `inspect_analysis_view` can open that analysis
directly without serializing the entire partial graph into the error response.
CLI failure output retains the complete partial Evidence.
Cancellation after source analysis begins likewise
retains completed facts; an SDK client may reject its cancelled request before
receiving that reply. On the same MCP connection, inspect the Evidence bundle
and use the retained analysis ID with `inspect_analysis_view`. Owned analyzer
cleanup is verified before its private files are released. Cleanup uncertainty
is reported separately and retains ownership for retry.
CLI workflows parse larger JSON input files incrementally from one verified
regular-file handle, without constructing a document-sized string. Smaller
files retain native JSON parsing. Both paths require strict JSON and valid
UTF-8, and return one complete value; the assembled object still needs memory.
An individual JSON string exceeding the native length limit or the available
heap headroom for assembly returns
`resource_constraint` with `input_reason: "too-large"`. Supply a smaller valid
value; for Evidence workflows, re-analyze a smaller selection of the original
target and use its complete Evidence. Splitting JSON text or trimming Evidence
fields does not produce a valid workflow input.
Evidence bundle and analysis snapshot file readers still decode whole
documents. Their runtime string-limit failures report a resource constraint
with the selected path, observed bytes and UTF-16 limit, rather than malformed
JSON.
`analyze_javascript_application` returns the complete analysis Evidence by
default. Select `"detail": "summary"` to retain that complete Evidence in the
current session and receive only its `inspect_analysis_view` summary: artifact
identity, statistics, Electron surface counts, application and semantic
coverage, limitations, and `normalized_result.parent_evidence_id`. Pass that ID
to `inspect_analysis_view` for module pages or items, or to the application
workflows as a retained reference. The summary does not repeat or truncate the
analysis; a server without session retention refuses summary detail with
`capability_unavailable`. CLI output is unchanged and always complete.
MCP prepares the complete repeated response incrementally against the pinned
SDK's 10 MiB stdio receive-buffer budget. Oversized results return an actionable
transport constraint and the exact same-session Evidence reference. Use
`trace_application_feature` to inspect a selected module's relationships, or
`export_evidence_bundle` to write the complete canonical bundle without a
document-sized allocation. Same-session analysis reads reuse authenticated
immutable snapshots; foreign inline Evidence is still parsed and authenticated.
`inspect_analysis_view` with the retained Evidence ID for a summary, one
module, or a stable page of module identities. Use `trace_application_feature`
once a module, route, or string seed is known, or `export_evidence_bundle` to
write the complete canonical bundle without a document-sized allocation.
Same-session analysis reads reuse authenticated immutable snapshots; foreign
inline Evidence is still parsed and authenticated.
See [MCP tool results](mcp-contracts.md#tool-results) for larger client buffers
and `REA_MCP_MAX_RESPONSE_BYTES`. Follow-up results remain complete and can also
exceed the transport budget. Compact result views are tracked separately in
[#1050](https://github.com/morluto/rea/issues/1050).
exceed the transport budget.
## What is reconstructed
@@ -125,6 +200,13 @@ SHA-256 digests, inventory IDs, ASAR container identity, and `.asar.unpacked`
status. Direct ASAR inputs and filesystem-backed ASAR files nested beneath a
directory are supported.
JavaScript sources (`.js`, `.jsx`, `.mjs`, and `.cjs`) and TypeScript sources
(`.ts`, `.tsx`, `.mts`, and `.cts`) are parsed as inert text; analysis does not
execute them.
JavaScript and HTML source ranges retain an initial UTF-8 BOM as one UTF-16
code unit, matching the original bytes identified by the artifact digest.
If an ASAR declares an unpacked companion entry but the corresponding
`<archive>.unpacked` file is absent from the operator-supplied artifact set, REA
keeps the ASAR occurrence with `hash_status: unavailable`, records an explicit
@@ -133,6 +215,9 @@ missing bytes. This allows static JavaScript/Electron reconstruction to proceed
for the embedded files while preserving the missing native/resource bytes as an
unknown instead of silently treating them as absent or verified.
Plain `.ts` artifact sources use TypeScript syntax without JSX, including
angle-bracket type assertions. `.tsx` and `.jsx` retain JSX parsing.
Selected bounded text is then parsed as inert data to recover:
- `package.json` metadata and declared main or renderer entrypoints;
@@ -156,6 +241,12 @@ Selected bounded text is then parsed as inert data to recover:
- utility-process entrypoints and native `.node` binding requests without
parsing or executing the add-on.
Overloaded `.open` calls use lexical receiver facts: ambient browser window and
document receivers are treated as browsing-context or document operations,
while locally shadowed receivers can still contribute network endpoint
candidates. A template recovered with a parser error and no cooked value stays
dynamic; its raw spelling is not treated as a valid JavaScript string.
Each recovered bundle module retains the exact factory-source digest. A complete
bounded AST also receives a `babel-ast-v1` structural fingerprint that ignores
ordinary identifier names while retaining syntax, literals, operators, object
@@ -217,6 +308,22 @@ These safeguards are not caller-selectable output budgets. Source-map parsing
reports truncation when its format or parser safety boundary is reached. The
application graph has no aggregate node, edge, root, or observation prefix cap.
Semantic evaluation retains at most 256 distinct primitive candidates per
expression and at most 1 MiB of worst-case JSON string bytes across a normalized
primitive value's string candidates. The byte budget estimates six JSON bytes
per UTF-16 code unit, the expansion bound for escaped strings, and bounds both
retained candidate strings and temporary canonical-key serialization. This is
an in-memory semantic allocation bound independent of CLI or MCP transport
budgets. Source literal bytes remain in the parsed source and artifact evidence;
when a normalized semantic value exceeds the bound, its value is unknown and
coverage is partial. Expression
evaluation and provenance walks stop after 256 nested levels. Union products
and string lengths are checked before allocating combinations or concatenated
strings. When a boundary is reached, the value stays unknown, semantic coverage
becomes partial, and graph evidence retains the expression location and typed
limiting reason. The number of unresolved alternatives is unknown; it is not
reported as an exact omission count.
Byte, entry, path, and graph-shape bounds are hard limits. The parse deadline is
checked before and between bounded parsing and traversal phases; the synchronous
Babel and JSON parser calls cannot be preempted mid-call, so their input byte
@@ -250,6 +357,8 @@ such as `./web3:app.js` still names a local artifact.
Package `exports` fallback arrays are supported both at the top level and under
the root `"."` entry. The resolver selects targets in declared order using the
same conditional and invalid-entry handling as nested exports arrays.
For imports and requires, the active Node conditions include `module-sync`;
earlier active conditions retain precedence over later ones.
ESM relative module paths and selected package exports targets use URL suffix handling
and one percent-decoding pass. CommonJS relative paths and legacy package main
@@ -261,7 +370,12 @@ do not select a later entry. Rejected references retain the package metadata
path, original target, failed constraint, and importing source location.
HTML script references resolve to exact inventoried files after applying the
document base and query/fragment rules. CommonJS module lookups retain extension
and directory resolution.
document base and query/fragment rules. As in a browser, the script URL and base
href are read without surrounding whitespace or embedded tabs and newlines, and
their percent-encoded path bytes are decoded; encoded dot and separator bytes
are still rejected. CommonJS module lookups retain extension and directory
resolution.
Unresolved HTML references retain their declaration, source range, and resolution
reason in the renderer observations.
HTML script source ranges follow the HTML parser across LF, CRLF, and bare CR
line endings, preserving UTF-16 columns.
+34 -7
View File
@@ -7,19 +7,46 @@ never executes the selected or recovered application code.
## Caller-supplied engine
The initial adapter is verified on Linux x64 with Wakaru **1.13.0**. Set
`REA_WAKARU_COMMAND` to the absolute path of an executable supplied by the caller.
The adapter uses util-linux `prlimit` (default `/usr/bin/prlimit`; override with
an absolute `REA_JAVASCRIPT_PRLIMIT_COMMAND`). REA does not install either tool.
Engine configuration is checked only when recovery is requested; other REA
capabilities remain available without it.
REA accepts Wakaru **^1.13.0** on Linux x64. The report parser is verified with
Wakaru **1.14.0**. Another release in that range is accepted, the observed
version is reported, and a limitation records that the parser was not verified
against that release. Wakaru changes `--version`, `--json` and `provenance.json`
only by addition within a major version
([compatibility policy](https://github.com/pionxzh/wakaru/blob/v1.14.0/docs/cli.md#machine-readable-output-compatibility)),
so the parser keeps unknown report fields and reported module statuses.
Set `REA_WAKARU_COMMAND` to the absolute path of an executable supplied by the
caller. The adapter uses util-linux `prlimit` (default `/usr/bin/prlimit`;
override with an absolute `REA_JAVASCRIPT_PRLIMIT_COMMAND`). REA does not install
either tool. Engine configuration is checked only when recovery is requested;
other REA capabilities remain available without it.
Unmodified upstream source is retained in `third_party/wakaru`, pinned to
`6070266d24b32951fa2fe1d2dad5b4313bd5c81b` (v1.13.0, Apache-2.0).
`8219bf5016a063d7fb215101a8c45d5959ec733f` (v1.14.0, Apache-2.0).
The result reports the executed binary's exact path, SHA-256 and observed version.
The audited source revision is distinct from `executed_source_revision: null`:
a version string cannot prove which source produced a caller-supplied binary.
### Install Wakaru
Use the official release binary, the same one CI verifies:
```sh
curl -fL https://github.com/pionxzh/wakaru/releases/download/v1.14.0/wakaru-linux-x64.tar.gz | tar -xz wakaru
export REA_WAKARU_COMMAND="$PWD/wakaru"
```
Or install it from npm. Point at the platform binary, not the Node.js shim in
`node_modules/.bin`:
```sh
npm install wakaru@1.14.0
export REA_WAKARU_COMMAND="$(realpath node_modules/@wakaru/cli-linux-x64/wakaru)"
```
Both give the same binary (SHA-256
`664fa06782a61eda7ed15885134b52525fd565dd77607e642062ceb6cd927c38`).
## Recover and analyze
```sh
+12 -6
View File
@@ -119,12 +119,18 @@ targets belong to the same Electron application.
## Capture and determinism
Every observation records its time window and returns all valid script and
execution-context events received during it. Per-location protocol validation
remains in force. Scripts are validated after capture, deduplicated by stable
metadata, and canonically sorted. Wall-clock timestamps and protocol script IDs
are excluded from the durable result, so identical inputs and captured metadata
produce the same Evidence ID.
Capture retains valid script and execution-context metadata within an 8 MiB
aggregate budget, including conservative estimates for UTF-16 strings, record
and collection overhead, and projected URL fields. Each CDP message also has a
16 MiB transport limit. A message over that limit fails with `payload_limit`;
when the aggregate budget is reached, later metadata events are dropped and
the partial result reports `events_dropped`, `truncated: true`, and
`retained_metadata_budget_exceeded`. Repeated context transitions update the
current context record instead of accumulating duplicate objects. Scripts are
validated after capture, deduplicated by stable metadata, and canonically
sorted. Wall-clock timestamps and protocol script IDs are excluded from the
durable result, so identical inputs and captured metadata produce the same
Evidence ID.
Inspector attach is inherently incomplete. Enabling `Debugger` reports known
and uncollected scripts, but scripts collected before attachment may be
+36
View File
@@ -0,0 +1,36 @@
# JEB instrumentation and analysis
REA exposes JEB-backed project, unit, and decompilation inspection through the CLI and MCP, served by JEB's own MCP interface. JEB is a bring-your-own engine: REA never installs it, launches it, or opens its project databases itself.
## Bring-your-own engine
Start a JEB client that serves MCP and point REA at it:
- Default endpoint: `http://127.0.0.1:8425/mcp`. Override with `REA_JEB_MCP_URL` (absolute `http`/`https` URL with literal host `127.0.0.1` or `[::1]`; redirects, remote hosts, credentials, query strings, and fragments are rejected rather than silently dropped).
- In the JEB GUI client, start the MCP server from the _File_ menu (or via the VIBRE assistant).
- Headless, use JEB's documented programmatic route (`JebMcpServerInstance` from the JEB API) with the JEB client on your classpath; JEB 5.48's `-c` headless mode does not accept `--mcp` directly.
Verified against JEB 5.48.0 (Linux x64, licensed build) serving `jeb-mcp-server` 1.3.0 over streamable HTTP.
## Operations
| MCP tool / CLI command | Purpose |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `inspect_jeb_client` / `inspect-jeb-client` | Engine version, GUI or headless mode, startup time |
| `open_jeb_project` / `open-jeb-project` | Open or create a project from an artifact or `.jdb2` on the engine host; returns input-file SHA-256 digests and top-level units |
| `list_jeb_units` / `list-jeb-units` | Page units by stable path and type (`filter`, `parent-unit-path`, `index`, `count`) |
| `decompile_jeb_item` / `decompile-jeb-item` | Decompile one type or method to engine pseudo-code |
All four are read-only with respect to the target file; only `open_jeb_project` changes engine-side project state, and Evidence records the endpoint, the caller-selected parameters, and the engine-reported digests. Mutation workflows the engine also offers (renames, comments, `save_project`, `close_project`) are intentionally not exposed yet.
**Engine coverage note (verified):** JEB 5.48.0 headless MCP instances do not advertise `open_project` — the target must be selected when the engine client starts (`--infile` on the programmatic launcher, or the GUI's file opening). REA preserves that refusal with the engine's reason instead of failing silently; `open_jeb_project` completes only against engine builds that advertise the tool, such as GUI clients.
## Semantics
- Paths in `open_jeb_project` are resolved by the JEB process, not by REA; REA does not require the artifact to exist locally.
- The engine caps `list_units` pages at 100; a full page is reported as `coverage: "partial"` because more units may exist. An empty remainder is `complete` only when fewer units than requested were returned.
- When `decompile_jeb_item` omits `unit_path`, the engine implicitly selects the project's first code unit; REA reports `unit_path: null` and a limitation instead of guessing the effective unit.
- Engine refusals (`success: false` envelopes) are preserved as unsupported-target errors carrying the engine's own message, for example a nonexistent item address.
- An unreachable endpoint is a provider-availability failure with recovery guidance; REA does not retry or spawn the engine.
Real-engine verification lives in the JEB lane described in [testing.md](testing.md); mock transport tests do not establish real-engine compatibility.
+68 -226
View File
@@ -1,4 +1,4 @@
# Managed-code analysis and planned extensions
# Managed-code analysis
REA inspects .NET PE/CLI artifacts without loading or executing their code.
It can identify an assembly, inspect metadata and CIL, compare members across
@@ -20,12 +20,11 @@ The seven shipped tools are:
Each has a matching CLI command: replace underscores with hyphens and prefix
the name with `rea`, for example `rea inspect-managed-artifact`.
Native-body bridge mapping remains planned; managed runtime execution is not
part of the current tool set.
Native-body bridge mapping and managed runtime execution are outside the
current tool set.
This guide describes the implementation and verification of
[ADR-0003](adr/0003-managed-code-evidence-and-provider-boundary.md). The canonical
tool inventory is the [build-generated catalog](mcp-contracts.md#generated-catalog).
The canonical tool inventory is the
[build-generated catalog](mcp-contracts.md#generated-catalog).
## Shipped scope
@@ -36,10 +35,22 @@ NativeAOT identity from an ordinary native PE. Inputs without admitted CLI
metadata do not become managed assemblies through naming or routing guesses.
Inspect separately obtained components explicitly and preserve their identities.
The broader deployment classification and native-body mapping below are design
goals from ADR-0003, not claims that every row has an implemented parser. A
valid marker can establish a candidate native boundary, not recovered native
semantics or runtime behavior.
A valid implementation marker establishes a candidate native boundary, not
recovered native semantics or runtime behavior.
### Resource admission
The static provider admits regular input files up to 128 MiB before retaining
their bytes. Reads remain bounded if a file grows after admission. Metadata,
CIL decoding, and projected inspection records have a separate conservative
64 MiB representation budget; shared heap strings are cached, but repeated
output occurrences still consume that budget. These are inspection resource
policies, not PE format limits or a hard bound on total V8 heap use.
Input overflow returns a resource constraint. Decode or projection overflow
reports `resource-limit` with unavailable or partial coverage; omitted facts do
not become empty observations. Ambiguous PE section mappings are rejected
rather than interpreted according to section order.
## Analysis objective
@@ -57,40 +68,7 @@ collapsing them:
The ordinary workflow ends at question four. Static analysis never loads or
executes the target.
## Planned deployment classification
The intended extended classifier proceeds from outermost authenticated bytes inward:
```text
source path
-> canonical path, size, SHA-256
-> container inventory
-> PE/native header and architecture
-> CLI header and metadata root
-> deployment/runtime markers
-> per-component and per-method implementation availability
-> managed-only, native-only, composed, degraded, or unsupported route
```
The planned result is a vector rather than one label. For example, a single-file modern
.NET deployment can contain a native host, ordinary CIL assemblies, and
ReadyToRun components. Each component receives its own digest, classification,
coverage, and route while retaining the outer bundle commitment.
| Case | Required positive observations | Claims that remain unavailable or inferred |
| --------------------- | ---------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| .NET Framework | Valid CLI metadata plus bounded Framework-specific target/reference evidence | Exact installed CLR and runtime behavior |
| Modern .NET | Valid CLI metadata plus bounded target/reference/runtime-config evidence | Exact runtime selected on another host |
| Unity Mono | Valid managed assembly plus authenticated Unity context when supplied | Engine behavior or native integration not represented by metadata |
| ReadyToRun | Valid managed metadata plus authenticated ReadyToRun header/sections | Native implementation semantics until a selected deep provider analyzes them |
| C++/CLI | Valid CLI metadata plus mixed-mode PE/header evidence | Mapping managed declarations to native implementations without explicit bridge evidence |
| Single-file | Valid authenticated bundle inventory and component extents | Components that are compressed or encoded by an unsupported bundle version |
| Unity IL2CPP | Authenticated native image/metadata pairing and supported metadata version | Canonical CIL and source-equivalent C# |
| NativeAOT | Native image plus bounded NativeAOT evidence | Ordinary CLI metadata/CIL unless independently present |
| Obfuscated assembly | Same positive byte observations as its underlying deployment form | Meaning inferred only from names |
| Malformed/unsupported | Exact admitted regions and failure locations | Completeness, successfully skipped rows, or semantics beyond the admitted parser boundary |
### NativeAOT metadata recovery
## NativeAOT metadata recovery
NativeAOT removes the ordinary CIL method bodies, so a CIL decompiler cannot
reconstruct those bodies as C# source. The executable remains a native target
@@ -110,70 +88,44 @@ lists supported OS/architecture targets and deployment limitations, while its
[native library guide](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/libraries)
describes exported shared-library entry points.
The [Ghidra NativeAOT analyzer](https://github.com/Washi1337/ghidra-nativeaot)
is a useful optional companion for recovering ReadyToRun metadata. It
rehydrates the `DEHYDRATED_DATA` section and annotates method tables, type
relationships, vtable slots, frozen objects, and strings. It does not recover
original C# method bodies. It is a separate Ghidra extension and interactive
metadata browser; REA does not currently install or invoke it through its
headless bridge. Its README describes ReadyToRun header discovery, including
symbol-based and heuristic paths, so a missed header or unsupported binary
should remain an explicit limitation rather than a failed claim about the
binary's contents.
REA supports an optional headless adapter for the Ghidra NativeAOT analyzer.
Supply a locally built `REA_GHIDRA_NATIVEAOT_JAR`; REA does not install the
extension or its toolchain. The verified boundary is .NET 8.0.22 RTR 9.1,
x86-64 ELF and native Windows PE targets analyzed on Linux x64 with Ghidra
12.1.4 and JDK 21. Other layouts, architectures, and hosts are unsupported.
See [NativeAOT recovery](ghidra-nativeaot.md) for build/configuration, recovered
metadata, derived-memory provenance, and the real verification lane.
The upstream analyzer currently gates its own analysis to x86-64. NativeAOT's
broader platform matrix does not establish REA coverage: PE/COFF, ELF, Mach-O,
shared libraries, target architectures, and runtime metadata versions each need
their own provider verification. REA's experimental Windows Ghidra boundary is
limited to admitted native x86 and x86-64 PE applications, so it does not currently
establish coverage for PE DLLs. Mobile NativeAOT targets should remain
experimental until REA has a matching provider and package-level verification.
REA's experimental Windows Ghidra boundary admits native x86 and x86-64 PE
applications and DLLs for static analysis. This does not establish Windows
NativeAOT metadata-recovery coverage.
For REA's native analysis, preserve the same artifact path and digest used by
`inspect_managed_artifact`, and report recovered type data as provider
observations. Linking those types to native function addresses requires verified
For NativeAOT analysis, preserve the selected native artifact's path and digest
and report recovered type data as provider observations. Linking those types
to native function addresses requires verified
provider evidence; names or vtable similarity alone do not prove that a native
function implements a specific managed method.
## Evidence record shape
Every planned operation returns a provider result and Evidence with four
commitment groups:
Member comparison, application graph projection, and managed/native verification
authenticate supplied inspection Evidence and check that any subject SHA-256
matches the normalized artifact SHA-256. A valid Evidence ID alone does not
establish that those two identities agree. Evidence without a subject remains
usable, with no subject digest available to cross-check.
### Artifact commitment
Artifact inspection returns the selected path, byte length and SHA-256, observed
PE/CLI classification, assembly and module identities, and metadata coverage.
Member inspection binds build-local tokens, signatures, row offsets, method
bodies, and decoded relationships to that artifact and MVID. Missing or malformed
facts remain explicit in coverage and per-member status.
- canonical local path, byte length, and SHA-256;
- outer-container identity and digest when inspecting a component;
- component name/path, byte extent, and SHA-256;
- observed PE machine, CLI flags, and conflicts;
- classification vector, supporting observations, and unresolved dimensions.
CLI `#GUID` heap values retain their exact 16-byte GUID text. REA does not impose
RFC 4122 UUID version or variant bits on MVID, EncId, or EncBaseId because
ECMA-335 metadata does not require those bit patterns. Tokens and RVAs are
build-local coordinates, not durable cross-build identities or native addresses.
### Module commitment
- assembly simple name, version, culture, public-key/token state, flags, and
hash algorithm;
- module name, generation, and MVID;
- target framework and runtime/version strings with their exact metadata
locations;
- provider identity, analysis-affecting parameters, and their profile digest.
CLI `#GUID` heap values are committed as their exact 16-byte GUID text. REA
does not impose RFC 4122 UUID version or variant bits on MVID, EncId, or
EncBaseId because ECMA-335 metadata does not require those bit patterns.
### Entity commitment
- table kind and build-local token;
- declaring scope and normalized CLI signature;
- row/heap/body locations expressed as typed file offsets, RVAs, or CIL
offsets;
- exact raw bytes or bounded value digest;
- raw CIL digest plus separately reported method-header, locals-token, and
exception-region observations where available;
- a deterministic decoded-instruction-tuple digest for completely decoded
CIL, with the limitations below.
### Shipped decoded-CIL fingerprint
## Decoded-CIL fingerprint
`inspect_managed_members` exposes two method CIL hashes with different byte
boundaries:
@@ -202,9 +154,7 @@ reproducible decoded-tuple fingerprint, not a canonical semantic CIL identity:
it does not resolve tokens across MVIDs, does not commit full control flow or
exception semantics, and does not replace the raw CIL digest. Cross-build
comparison uses the value only as one unique-only structural tier and reports
ambiguity when that evidence is insufficient. A future normalized-CIL
commitment would need canonical token/literal identities,
complete branch and switch targets, and explicit locals/exception semantics.
ambiguity when that evidence is insufficient.
For example, a decoded `nop; ret` body serializes exactly as
`[["nop","none",null],["ret","none",null]]` and has digest
@@ -212,73 +162,10 @@ For example, a decoded `nop; ret` body serializes exactly as
This vector specifies the tuple order, `null` handling, absence of whitespace,
UTF-8 encoding, and lowercase hexadecimal output.
### Epistemic commitment
## Member comparison
- authority: static bytes, reconstruction, structural inference, independent
validation, native provider, or future runtime observation;
- state: observed, inferred, unknown, or unavailable;
- confidence independent of authority;
- coverage and admitted/dropped counts;
- exact supporting Evidence IDs and actionable limitations.
A semantic label such as `score_submission_gate` can annotate an entity, but it
is never the entity's identity. The same applies to an obfuscated name, token,
RVA, or decompiler-generated local name.
## Planned static capabilities
The caller-visible grouping and exact tool names are decided with the contracts
that implement them. The underlying capability slices are:
1. **Triage and inventory**: container/component classification, assembly and
module identity, references, files, exported types, resources, attributes,
and runtime markers.
2. **Member inventory**: file-backed types, methods, fields, properties, events,
interfaces, nesting, generics, and normalized signatures.
3. **Method inspection**: headers, max stack, locals, CIL instructions,
constants, metadata operands, exception regions, and implementation flags.
4. **Relationships**: declared overrides, interface implementations, member
references, direct CIL callers/callees, field access, construction, and
interop declarations. Dynamic dispatch remains qualified.
5. **Structural search and comparison**: signature/API/constant/flow anchors,
exact and normalized hashes, competing candidates, and explicit
exact/structural/missing/ambiguous states.
6. **Managed/native composition**: P/Invoke, unmanaged exports, COM/mixed-mode
declarations, ReadyToRun/native bodies, single-file hosts, and authenticated
IL2CPP pairs linked to selected Hopper/Ghidra evidence. The shipped
verification workflow checks P/Invoke declarations against supplied native
export or function Evidence; native-body, thunk, and token-to-address bridge
mapping remain unavailable without explicit provider-supported evidence.
7. **Application graph projection**: managed assembly/module/type/method/field,
P/Invoke, and native-implementation declarations enter the same
Evidence-backed application graph vocabulary as JavaScript/Electron
findings while preserving managed static-analysis authority.
Inventory lists preserve deterministic order and include every fact available
from the admitted PE/CLI streams. Malformed ranges and unsupported metadata are
reported as coverage issues instead of being silently omitted. Search exposes
scanned, matched, returned, and dropped counts. An unresolved indirect call or
a failed signature decode is not silently omitted from a completeness claim.
## Obfuscation-resistant method slices
Names are one weak feature among many. A behavior slice records the smallest
bounded set of observations needed to investigate a proposition:
- normalized declaring/member signatures and inheritance/interface shape;
- framework and application API references;
- exact strings, numeric constants, enum-like values, and serialization keys;
- branch, switch, exception, loop, call, and field-flow shape;
- construction and generic-instantiation sites;
- raw CIL and decoded-tuple commitments, plus separate header, locals, and
exception observations;
- callers, callees, shared fields, and competing candidates; and
- limitations from reflection, dynamic dispatch, generated code, protection,
native transitions, or incomplete coverage.
The workflow produces separate observation, inference, validation, and unknown
tables. It may say that a method is a strong candidate for a role; it cannot
turn that role into the method's durable identity.
Names and semantic labels do not establish durable member identity. Comparison
preserves observed differences, structural inferences, and unknowns separately.
Cross-version matching first prefers exact CIL/signature identity. When that
does not match, it pairs an exact declared type, method name, and raw signature
@@ -304,16 +191,14 @@ Tokens are always remapped through observed structure. A caller cannot carry
## Managed/native boundary rules
| Boundary | Managed observation | Native observation | Permitted link |
| ----------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| P/Invoke | Module, entry point, charset/calling-convention flags, declaring method | Import/export/symbol/function evidence from the selected deep provider | Exact declared-name/module link or qualified resolution inference |
| COM | Interop attributes, GUIDs, imported interfaces, method signatures | Native registration/vtable evidence when independently available | Identifier/signature inference with explicit environment limitations |
| C++/CLI | Managed declaration and implementation flags | Native body/function evidence | Only a provider-supported bridge observation; never token-as-address |
| ReadyToRun | Component/header and per-method CIL/native availability | Native section/function evidence | Authenticated image mapping with format/profile version |
| Unmanaged export | Export metadata/attribute when present | PE export and native thunk/function | Exact export identity plus provider-qualified address |
| Single-file host | Bundle entry/component identity | Host and native component evidence | Outer bundle plus component digest/extent commitment |
| Unity IL2CPP | Supported metadata entity with authenticated pairing | Generated native function/type evidence | Versioned IL2CPP mapping only; no invented CIL |
| Runtime-resolved native | API/constant/data-flow candidate | Loaded-module/symbol observation from an independently collected runtime source | Static candidate remains inference until separately observed |
`verify_managed_native_boundaries` compares declared P/Invoke module and entry
point identities with supplied native export or function evidence. Name/module
matches establish declaration links; they do not establish that a call executed.
Metadata tokens are not native addresses. Native body mapping for C++/CLI,
ReadyToRun, NativeAOT, and IL2CPP requires separately verified format and provider
support. The managed static tools do not recover those mappings. The optional
[Ghidra NativeAOT extension](ghidra-nativeaot.md) has its own supported boundary.
Declared import inventory supports a bounded positive claim. Its absence does
not exclude dynamic resolution, generated code, protected code, native helpers,
@@ -327,16 +212,12 @@ fixtures and expected semantic facts. An optional real ILSpy lane runs only when
its executable is explicitly supplied; the default lane does not establish
independent pinned-oracle parity. Production inspection needs none of those tools.
- A pinned `System.Reflection.Metadata` differential oracle is planned; it is
not part of the current verifier.
- `ICSharpCode.Decompiler`/`ilspycmd` can supply reconstruction inference.
A BYO reconstruction import records the supplied version
and remains non-canonical. When `REA_ILSPY_CMD_PATH` points to an absolute
runnable `ilspycmd`, `verify:managed` runs a source-owned real ILSpy oracle
and imports its C# output as reconstruction inference against exact static
member Evidence.
- dnlib and Mono.Cecil are potential future differential oracles. Their mutation APIs
are not exposed or included in the production parsing boundary.
- The package contains no .NET runtime, SDK, ILSpy installation, proprietary
assembly, or compiled conformance fixture.
- Setup never installs or upgrades those tools. Doctor may inspect an explicit
@@ -354,29 +235,15 @@ they do not claim that the REA application itself supports Windows. Native
ReadyToRun, C++/CLI, NativeAOT, or IL2CPP coverage is additionally constrained
by the selected Hopper/Ghidra host and format matrix.
## Source-built conformance corpus
## Conformance verification
The current lane uses source-owned byte-built fixtures and malformed-input
regressions, with optional operator-supplied applications and ILSpy verification.
The table below describes the desired expanded corpus; it is not a report that
all compiler-generated forms have been independently verified.
Fixture sources are intentionally small and behavior-focused. Build outputs
are generated outside tracked fixture directories and must not remain after
verification or packaging.
| Corpus slice | Required properties |
| ---------------------- | ------------------------------------------------------------------------------------------ |
| Identity | Assembly/module/version/culture/public key, references, attributes, resources, MVID |
| Signatures | Nested/generic types, arrays, pointers, by-ref, function pointers where supported, varargs |
| CIL | Short/long branches, switch, prefixes, constants, locals, calls, fields, boxing, tokens |
| Exceptions | Catch, finally, fault/filter where the compiler/toolchain supports them |
| Generated structure | Async and iterator state machines, lambdas, closures, properties, events |
| Interop | P/Invoke flags, module/name mapping, managed/unmanaged implementation metadata |
| Architecture | AnyCPU, preferred-32-bit where applicable, x86, x64 |
| Obfuscation resistance | Unicode/meaningless/duplicate-looking names and structure-preserving renames |
| Cross-build comparison | At least two builds with changed MVID/token order/layout and known same/changed behaviors |
| Malformed/adversarial | Truncated/overflowing headers, streams, tables, heaps, signatures, bodies, and EH sections |
Run the deterministic lane with `npm run verify:managed`. See
[testing](testing.md#real-toolchain-verification-lanes) for prerequisites and
coverage. Generated outputs belong outside tracked fixture directories and must
not remain after verification or packaging.
Verification compares semantic facts, not decompiler text. It checks resource
ceilings, deterministic ordering, complete cleanup, CLI/MCP parity, Evidence
@@ -486,32 +353,7 @@ evidence is collected. A direct process capture can retain declared inputs,
outputs, filesystem and protocol activity for a target run; it does not prove
which managed methods executed or how the CLR resolved them.
## Delivery sequence
The managed-code track advances as reviewable pull requests:
1. accepted evidence/provider boundary (this document and ADR);
2. read-only artifact triage and exact identity (shipped);
3. file-backed metadata, signatures, method bodies, raw CIL hashes, and the
decoded-instruction-tuple fingerprint (shipped; complete normalized-CIL
semantics remain planned);
4. obfuscation-resistant slices and cross-version comparison (shipped for
static member observations);
5. decompiler reconstruction import (shipped as analyst inference; REA does
not run ILSpy/dnSpy, and metadata/CIL remain canonical);
6. managed/native composition and truthful deployment degradation (declaration
inventory and native export/function Evidence matching shipped; native-body
bridge mapping remains planned);
7. source-built managed conformance and package/CLI verification (source-owned
PE/CLI corpus shipped through `npm run verify:managed`; optional BYO
`ilspycmd` real-tool oracle shipped through `REA_ILSPY_CMD_PATH`; dnSpy and
pinned Windows checks remain planned); and
8. managed static Evidence projection into the application graph (shipped).
Each implementation PR updates generated product facts only for behavior it
actually ships and states which real-tool checks were performed.
### Method metadata during build comparison
## Method metadata during build comparison
Managed member comparisons report a `metadata` dimension when an observed
MethodDef flags or implementation flags value differs, including accessibility
+219 -50
View File
@@ -2,9 +2,9 @@
## Generated catalog
Run `npm run build:cached` in a source checkout to generate the machine-readable
catalog at `docs/public/product-catalog.json`. The [catalog](product-catalog.json)
is also included in documentation builds. PR CI retains it with the packaged
Run `npm run docs:generate` in a source checkout to generate the machine-readable
catalog at `docs/public/product-catalog.json`. Documentation deployments serve
the same file at [/rea/product-catalog.json](/rea/product-catalog.json). PR CI retains it with the packaged
skill and portable conformance projections in the `generated-docs` artifact.
These outputs describe the exact source revision being built; they are not
checked-in snapshots. For a running server, `binary_session` remains the
@@ -24,22 +24,92 @@ health transition leaves that catalog unchanged and does not emit
`notifications/tools/list_changed`.
Advertised input and output schemas contain no reachable recursive references.
The input compatibility profile limits nesting to ten object, array, and
`anyOf`/`oneOf`/`allOf` levels, following local references per path. Property
maps, reference definitions, and example data do not add schema levels. Tests
check the complete catalog after SDK conversion and its generated counterpart.
This is REA's local compatibility profile; individual model APIs can impose
additional limits.
Schemas share repeated definitions through schema-local references while
preserving complete nested fields and validation rules. Input properties retain
their descriptions and literal examples.
For passive `compare_web_captures` inputs, pass each complete
`inspect_web_page` result in `before.inspection` or `after.inspection`, with an
optional complete `discover_webmcp_tools` result in the matching `webmcp` field.
The input schema describes these producer-result objects as round-trip payloads.
For scenario comparisons, pass complete `capture_browser_scenario` results in
`before_scenario` and `after_scenario`. REA validates all nested fields with the
original capture schemas; observation output schemas remain complete. Scenario
authoring inputs and comparison normalization options retain their full
advertised structure.
Hosts forward input schemas to the model with every request, so advertised
examples never copy complete producer Evidence. An embedded Evidence record is
shown as its exact `{"kind":"retained-evidence","evidence_id":"ev_..."}`
reference where the tool accepts one. An example that can only carry inline
Evidence stays in the canonical contract and its executable tests, but is not
advertised. Every advertised example is a distinct valid canonical input.
Root object unions are presented as
one object without root `anyOf`, `oneOf`, or `allOf` for model API compatibility.
The projection merges properties, retains shared required fields and
group-specific field dependencies, and describes the accepted input groups.
Canonical runtime validation enforces the exact union, including exclusions
that the advertised projection does not express. Tests validate the schemas
after SDK conversion and check advertised validation and actual calls.
Individual model APIs can impose additional nesting limits; complete producer
captures can exceed ten structural levels.
### Compact input schema profile
Some function-calling providers reject a request while any single tool's
`parameters` schema exceeds a literal serialized size cap; Moonshot clients
such as kimi-cli fail every request while the default catalog is attached
([#1484](https://github.com/morluto/rea/issues/1484)). Setting the server's
`REA_MCP_INPUT_SCHEMA_PROFILE` environment variable to `compact` renders every
advertised input schema within a 13,312-byte budget, measured to sit below
Moonshot's observed cap (community measurements: a 13.7 KB schema is accepted
while a ~15 KB one is rejected). The setting is read at startup; restart the
server to apply changes, as with `REA_MCP_MAX_RESPONSE_BYTES`. The default
value `full` keeps the complete advertisement unchanged.
The compact profile renders the same tool set, output schemas, annotations,
and canonical server-side validation. It changes only the advertised input
JSON Schema:
- Annotation prose leaves the advertised form: nested property descriptions,
literal examples, defaults, and titles are dropped. The root keeps its
description because it states the accepted input groups.
- Schema-local references are inlined within the budget. Kimi Code expands
references before sending provider requests, so sharing definitions cannot
establish the provider-facing size. Expansion stops at the budget before
allocating an oversized presentation. Unconstrained JSON fields advertise
all JSON value types explicitly so Kimi cannot infer string for Evidence
objects or arrays.
- The few schemas whose validation structure alone exceeds the budget
(`compare_web_captures`, `build_reconstruction_obligation_ledger`,
`evaluate_reconstruction_coverage`, `project_managed_application_graph`,
`compare_application_versions`, `capture_browser_scenario`) are advertised
in a reduced form: property names, reference-resolved types (including union
alternatives), first-level guidance, and the root's required-field constraints,
with nested validation detail elided. The
canonical schema still rejects malformed calls server-side, so callers
following the reduced advertisement receive the canonical typed error
instead of silent acceptance.
Boundary tests pin every advertised compact schema to the budget, keep them
valid JSON Schema that still accepts every canonical example, and hold the
set of six reduced presentations as contracts evolve. Client verification
also checks provider-facing sizes and canonical examples after conversion by
the actual Kimi Code CLI; local captures do not establish Moonshot acceptance.
Self-contained output schemas advertise a content-bound `$id`, including their
declared dialect. SDK validators can reuse compiled schemas across complete
catalog refreshes and equivalent tool outputs; changing the schema changes its
identity. Explicit schema IDs and relative external reference bases are
preserved. This keeps every tool and validation rule in discovery and does not
change the SDK's catalog invalidation or availability checks.
`compare_web_captures` accepts exactly one of two input shapes:
- Passive: `before` and `after` each contain `inspection`, the complete
`normalized_result` from `inspect_web_page`. Each may also contain `webmcp`,
the complete `normalized_result` from `discover_webmcp_tools`, or null.
- Scenario: `before_scenario` and `after_scenario` contain complete
`normalized_result` objects from `capture_browser_scenario`. Optional
`normalization` defaults to `{ "rules": [] }`.
The advertised schema includes complete nested capture fields and rejects
incomplete pairs and structurally malformed captures. Mixed comparison families
can pass advertised validation; the SDK rejects them against the canonical
input schema before invoking the handler. Domain validation additionally checks
relationships such as event sequence references and retained counts; JSON
Schema does not express those cross-field invariants.
Call `binary_session` with `{}` and read `result.tool_availability` to choose a
callable operation for the current target, provider, host, and negotiated client
@@ -71,19 +141,52 @@ inventories, and do not claim that no short-lived descendant existed.
## Progress and cancellation
Tool execution failures return `isError: true` and the complete canonical
`{ "error": ... }` diagnostic as JSON in text `content`. Read that diagnostic
for the error code, target details, partial observations, and remediation.
Failures omit `structuredContent`, since each advertised `outputSchema`
describes successful results. Successful replies retain their schema-validated
structured data and matching text projection. Oversized errors are retained
as Evidence before delivery of a bounded diagnostic with an export reference;
if retention is unavailable or fails, the diagnostic reports that reason.
REA accepts ordinary `tools/call` progress tokens. Updates are monotonic,
rate-bounded to at most one intermediate update per 100 ms, and always allow a
terminal update. Unknown totals are omitted; REA does not fabricate percentages.
`capture_process_scenario` uses that boundary only when the client supplies a
progress token. Notifications set `progress` to the count of collected terminal
frames, process samples, and interaction events, omit `total`, and put the
lifecycle phase, elapsed time, and final cleanup status in `message`. A client
that does not send a progress token receives no progress notifications. The
tool result is unchanged either way.
Provider calls receive the request cancellation signal. Artifact traversal,
hashing, version comparisons, Hopper requests, and process capture
check the same signal. Cancellation is distinct from timeout. A cleanup failure
uses `cleanup_incomplete` and lists only the owned resource kinds that remain.
Native call tracing and process capture retain available observations in
`details.partial_observation` on failure, including when cleanup succeeds.
The observation reports its partial coverage; cleanup details describe host
state separately from the execution failure.
Derived comparisons and reconstruction verification yield before computation
and before publication, so cancellation cannot race with successful Evidence.
CLI calls work without a progress token and translate SIGINT into the same
AbortSignal used by providers. Existing controlled-process cleanup and provider
shutdown rules still apply; REA never kills a process it cannot prove it owns.
`analyze_javascript_application` also yields between reconstruction phases and
during graph/result sealing, cross-graph binding checks, Evidence JSON validation,
and canonical hashing. Its final result validation reuses exact graphs whose
owned constructors validated and completely sealed them; imported graphs still
receive full schema and commitment checks.
Cancellation observed before completion returns `cancelled` and prevents the
provisional result from entering the session ledger; prior Evidence stays usable.
Single-file parsing, graph construction, and validation of imported graphs
still run synchronously, so control messages can wait for those
phases to release the event loop. A rejected client promise alone does not
establish that the server has stopped its work.
Direct CLI analysis calls work without a progress token and translate SIGINT or
SIGTERM into the same AbortSignal used by providers. Signal guards remain active
through provider cleanup, including repeated delivery by package runners.
Existing controlled-process cleanup and provider shutdown rules still apply;
REA never kills a process it cannot prove it owns.
## Ghidra first-query deadlines and recovery
@@ -95,11 +198,11 @@ auto-analysis, bridge connection, and health readiness before returning analysis
These deadlines have different owners:
| Deadline | Owner and effect |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MCP initialize | The client bounds transport/REA connection startup, before any target query. |
| Ghidra startup | REA allows 330,000 ms for engine readiness from the first provider query; startup failure is reported by that query. |
| Individual tool call | The client bounds its wait, including cold engine startup. The pinned client SDK 2.3.1 defaults to 60,000 ms and can cancel earlier than REA's startup deadline. |
| Deadline | Owner and effect |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MCP initialize | The client bounds transport/REA connection startup, before any target query. |
| Ghidra startup | REA allows 330,000 ms by default; `REA_GHIDRA_STARTUP_TIMEOUT_MS` accepts decimal integers from 1–2,147,483,647 ms. Invalid supplied values fail configuration validation. Startup failure is reported by the first provider query. |
| Individual tool call | The client bounds its wait, including cold engine startup. The pinned client SDK 2.3.1 defaults to 60,000 ms and can cancel earlier than REA's startup deadline. |
For an already connected client using the pinned SDK, request options are the
**second** argument of `callTool`:
@@ -148,33 +251,62 @@ the current client, so it is not a fresh-start recovery. On the same connection:
This close/reopen flow was exercised on one real Linux stdio connection after a
controlled startup timeout, followed by a successful overview and function
analysis. It is not a Windows/macOS coverage claim. REA cleans only resources it
owns and never switches to another provider automatically. A provider timeout,
installation failure, or host permission denial needs its own reported recovery;
increasing a client deadline alone does not fix those failures.
analysis. A separate Windows x64 stdio run with Ghidra 12.1.4, JDK 21 and Node
22.19.0 exercised the same connection and caller-selected native PE: the default
60-second client request timed out, close succeeded, and reopening before a
240-second request completed the cold overview in about 163 seconds. The next
overview took about 19 ms. The cold and warm overviews reported two procedures
and two segments; the input digest was unchanged and no owned runtime root or
observed process-family member remained after final close. This was a small
1,024-byte fixture, so the longer request setting remains an example, not a
guarantee for larger targets. No macOS cold-start recovery was exercised.
With a supplied progress token, the Windows run received an operation-start
notification before timeout and start/completion notifications for the
successful retry. It received no intermediate import or auto-analysis progress.
These operation markers do not measure analysis work completed or extend the
client's deadline. Each new provider session still imports the target into a
fresh temporary project.
REA cleans only resources it owns and never switches to another provider
automatically. A provider timeout, installation failure, or host permission
denial needs its own reported recovery; increasing a client deadline alone does
not fix those failures.
## Tool results
Evidence-producing tools return `{ result, evidence_id, evidence }` in both
text and structured content. `evidence` is the complete canonical Evidence
record, including `normalized_result`, which equals `result`. The same record
is retained in the session bundle. Read `result` directly, or pass `evidence`
to a compatible comparison tool: `analyze_function` Evidence can be passed
Custom clients upgrading from 6.1 should follow the
[6.2 migration guide](migration-6.2.md#mcp-results-and-evidence).
Evidence-producing tools return the complete canonical Evidence record in both
text and structured content. Read `structuredContent.normalized_result` for the
operation result and `structuredContent.evidence_id` for its identity.
`raw_result` holds a provider representation distinct from that result, such
as an upstream tool's original report, and is `null` when there is none. The same
record is retained in the session bundle. `analysis_profile` is always present:
a concrete profile object or `null`; either value participates in semantic
identity. Records omitting this field are rejected. Pass the returned Evidence
directly to a compatible comparison tool: `analyze_function` Evidence can be passed
directly to `compare_functions`, and `inspect_artifact` Evidence to
`compare_artifacts`. Use `get_evidence_bundle` when the task needs broader
retained session history or an explicit bundle for transfer.
REA prepares complete MCP results within the pinned stdio client's 10 MiB
receive-buffer budget, including both text and structured representations and
room for the JSON-RPC envelope. If a result cannot fit, REA returns
room for the JSON-RPC envelope. Tool errors carry only their text
representation, so only that text counts against the budget. Response budget settings are captured at startup;
restart or recreate the server to apply changes. If a result cannot fit, REA returns
`resource_constraint` with `details.resource: "transport"` before constructing
a document-sized string. Analysis Evidence remains complete in the current
session. Its exact reference is reported in
`details.reported_limits.evidence_reference`; use it with a focused application
workflow, or call `export_evidence_bundle` with a destination path. Complete
`details.reported_limits.evidence_reference`; call `inspect_analysis_view` with
that reference for a summary, one section/module, or a stable page, or call
`export_evidence_bundle` with a destination path. Complete
bundle exports stream canonical JSON into an atomically published file. A broad
follow-up or `get_evidence_bundle` can also exceed the response budget; exporting
preserves the complete session without sending it through a single MCP frame.
Cancelling an export stops further serialization and removes its staging file.
The destination changes only when a complete export is atomically published.
Clients that explicitly configure a larger receive buffer can set the REA
server's `REA_MCP_MAX_RESPONSE_BYTES` environment variable to the same byte
@@ -186,6 +318,33 @@ Ordinary responses keep their existing complete result contract.
## Retained application Evidence inputs
`analyze_javascript_application` and `inspect_binary_layout` accept `detail`:
`complete` (default) returns the complete analysis Evidence; `summary` records
that complete Evidence in the session and returns the derived
`inspect_analysis_view` summary Evidence instead. Its
`normalized_result.parent_evidence_id` and `evidence_links` name the retained
analysis, so later views and application workflows read it without repeating
analysis or moving the complete record through the response. A server without
session retention refuses summary detail with `capability_unavailable`.
`inspect_analysis_view` projects a caller-selected view of already completed
`inspect_binary_layout`, `analyze_javascript_application`, or `analyze_function`
Evidence. Native views select procedure, pseudocode, assembly, basic blocks,
comments, callers/callees, references, unresolved calls, referenced strings and
names, the native API record, and high-pcode facets without starting a provider. Native offset
and limit default to 0 and 64; pseudocode uses UTF-16 code units and never
splits surrogate pairs, while other pages count rows. Unavailable facts and
provider limitations remain explicit. Source is
an exact same-session retained reference or portable inline Evidence. Views are
a summary, a layout mitigations or linkage facet, one section/symbol/module, or
a stable page with a caller-selected positive `limit`. Module pages include
JavaScript assets, bundled modules, and source modules. Select an exact
`node_id` when a path is ambiguous or unavailable. Module items retain their
recorded property values and source locations; summaries include parent
application and semantic coverage. The result carries a digest of the selected
facts. Actual serialized size determines MCP transport admission: reduce the
page size or export retained Evidence if the view is too large.
`trace_application_feature`, `trace_javascript_semantics`,
`compare_application_versions`, `compare_source_to_bundle`, and
`compare_javascript_export_shapes` accept complete inline application Evidence
@@ -276,19 +435,29 @@ and returns its result and Evidence inline.
## Integrity record-and-continue
Artifact integrity fails closed by default. `inspect_artifact`,
`extract_artifact`, and `analyze_javascript_application` accept
Artifact integrity fails closed by default. A request can explicitly select
`integrity_policy=record-and-continue` when the investigation needs verified
siblings to continue after a mismatch. A common expected mismatch is an
unpacked native module that macOS code signing rewrote after the ASAR header
recorded its integrity.
siblings to continue after a mismatch.
Contradictory bytes are quarantined from nested expansion and recorded with
declared and observed hashes, trust, provenance, path, and unpacked state.
Verified siblings continue. Extraction writes the observed bytes and returns the
contradictions with its result; JavaScript analysis reads contradicted files as
observed and lists them in `integrity_contradictions`. Comparisons classify the
result as a contradiction and reconstruction cannot treat it as unchanged.
Application comparisons and feature traces retain the source integrity warnings
and report incomplete coverage. Extraction retains nested contradiction records
without claiming that the nested members were materialized separately.
Verified siblings continue. Comparisons classify the result as a contradiction
and reconstruction cannot treat it as unchanged.
`analyze_javascript_application` accepts the same policy in MCP and as
`--integrity-policy` on both JavaScript CLI routes. Its result returns the
canonical `integrity_contradictions` records and marks application graph
coverage partial when any mismatch is continued. Contradicted nested ASARs
remain opaque.
`extract_artifact` accepts the same policy in MCP and as `--integrity-policy`
on `rea extract-artifact`. With `record-and-continue` it writes the observed
bytes and returns the `integrity_contradictions` records for the extracted
files. An active ASAR unpacked entry whose companion file is absent cannot be
materialized; extraction fails as `unavailable` with that logical path.
Packaging tools commonly sign or strip `.asar.unpacked` native binaries after
writing the archive header, so their declared hashes no longer match. Electron
does not check unpacked companions against those hashes at runtime. Integrity
failures for such entries name this cause and the operation to rerun with
`record-and-continue`; REA does not exempt unpacked entries silently.
+3 -1
View File
@@ -27,7 +27,9 @@ prompt argument or tool explicitly accepts one.
For a JavaScript/Electron application directory, `investigate_feature` points
directly to `analyze_javascript_application` with `input_path`; it does not
require `open_binary`. The CLI equivalent is `rea analyze <directory>`.
require `open_binary`. When that Evidence, or `inspect_binary_layout` Evidence,
is already retained, it suggests `inspect_analysis_view` before tracing a
feature seed. The CLI equivalent is `rea analyze <directory>`.
`open_binary` and the doctor target check admit files and macOS app bundles.
A directory outside that opening route is reported with an available analysis
action; this does not establish support for every directory format.
+157
View File
@@ -0,0 +1,157 @@
# Upgrading from REA 6.1 to 6.2
REA 6.2 includes stability fixes and changes to public result and saved-data
contracts. The repository uses `always-bump-minor`, including breaking releases;
the minor version increment does not imply backward compatibility. Refresh cached
MCP tool definitions after upgrading and adapt custom consumers using this guide.
## MCP results and Evidence
Evidence-producing tools now return the complete Evidence record directly in
`structuredContent` and JSON text. The old `{ result, evidence_id, evidence }`
wrapper is gone.
For a successful Evidence-producing call, change:
```javascript
// 6.1
const value = reply.structuredContent.result;
const evidence = reply.structuredContent.evidence;
// 6.2
const evidence = reply.structuredContent;
const value = evidence.normalized_result;
const evidenceId = evidence.evidence_id;
```
Check `isError` before reading success fields. Error results have `isError: true`
and carry their typed JSON diagnostic in a text content block; they omit
`structuredContent` so they cannot violate the advertised success output schema.
```javascript
if (reply.isError === true) {
const text = reply.content.find((part) => part.type === "text");
if (text === undefined) throw new Error("REA error has no text diagnostic");
const { error: diagnostic } = JSON.parse(text.text);
// Handle diagnostic.code, diagnostic.message and diagnostic.details.
}
```
Lifecycle and other non-Evidence tools still use their own advertised output
contracts. Do not assume every successful tool returns Evidence. Consult
[`tools/list` and the result guide](mcp-contracts.md#tool-results).
A transport `resource_constraint` error can include a retained
`details.reported_limits.evidence_reference`. Use `inspect_analysis_view` or
`export_evidence_bundle` on the same connection to consume the complete retained
Evidence. Response-budget settings are captured when the server starts; recreate
the server to change them, and keep the client's receive budget aligned. Raising
the server budget does not change the client's limit or analysis coverage.
Every Evidence record now requires `analysis_profile`, either its observed
profile object or `null`. The field participates in Evidence identity. Records
that omitted it cannot be migrated by inserting `null` while retaining the old
`evidence_id`. Keep the original files and regenerate affected observations with
6.2; use the new returned identities when linking or comparing them. Existing
records that already satisfy the complete canonical contract remain usable.
The `binary_session` result removes the redundant top-level `provider` and
`providers` aliases. Read `analysis_provider_binding`,
`analysis_provider_candidates` and per-operation `capabilities` for selection
and availability. Select a deep provider through `open_binary.provider_id`
or CLI `--provider`, using the advertised values.
These changes establish one complete result representation and explicit
provider/profile ownership rather than accepting incomplete producer records.
See [63bf914](https://github.com/morluto/rea/commit/63bf91405cf97b114a84f337fb1272d98a267999)
and [#1277](https://github.com/morluto/rea/pull/1277).
## Saved snapshots and artifact inventories
Analysis snapshots require `workflow_entries` and a corresponding profile-bound
Evidence record for every cached query. Import rejects incomplete bindings
instead of silently discarding them. Preserve an incompatible snapshot and
choose a new output path when rerunning analysis, for example:
```bash
rea analyze /absolute/path/to/program --provider ghidra --snapshot /absolute/path/to/analysis/program-6.2.json
```
In MCP, open the target without the incompatible `snapshot_path`, run the
required queries, then save to a new path through `close_binary.snapshot_path`.
Do not fabricate missing provider profiles or query bindings. See
[snapshot usage](cli.md#save-and-reuse-analysis-snapshots).
Artifact inventory nodes identify content bytes. Path-specific role and
permissions now belong to each occurrence:
| Previously read | Read in 6.2 |
| -------------------------------- | ----------------------------------------- |
| `nodes[].kind` | `occurrences[].artifact_kind` |
| Path-specific `nodes[].format` | `occurrences[].artifact_format` |
| `nodes[].executable` | `occurrences[].executable` |
| Content identity and byte format | `nodes[].artifact_id`, `sha256`, `format` |
Join an occurrence to its content node using `artifact_id`; inspect the selected
occurrence's role rather than choosing one role for all paths with equal bytes.
An executable binary format can have `artifact_kind: "executable"` while its
current filesystem permission produces `executable: false`. A `.js` and `.txt`
file with identical bytes can share a node and retain different roles.
Regenerate old inventories: a merged content node alone cannot recover the
per-path facts that were lost. These changes are part of
[63bf914](https://github.com/morluto/rea/commit/63bf91405cf97b114a84f337fb1272d98a267999).
## Process captures and cleanup failures
REA no longer converts legacy v3 process captures on import. Captures require
explicit selected/launch executable identity and `event_journal`; missing data
is rejected instead of being filled during parsing. Preserve old captures for
historical reference and recapture with 6.2 when current comparisons are needed.
Do not infer the original launched binary from a later file digest, or invent
event ordering from independently recorded collections. An explicitly empty
journal is valid under its advertised contract; the field cannot be omitted.
See [2a77469](https://github.com/morluto/rea/commit/2a7746998d47446c4db6d4f524e0f183d6803f3f).
Filesystem effects can now report `status: "unknown"` with a reason when a
partial snapshot cannot establish creation or deletion. Update exhaustive
status readers and retain observed facts separately from absence assumptions.
A completed one-shot analysis can report `cleanup_incomplete` rather than
silently returning success when provider cleanup fails. Preserve its
`details.partial_observation` or primary execution diagnostics, inspect the
reported owned resources, and address cleanup before retrying. A successful
analysis observation does not prove successful cleanup. This behavior is covered
by [#1211](https://github.com/morluto/rea/pull/1211). That change also makes
configured agent-evaluation fixture checks grade cited Evidence; routing or
answer wording alone no longer passes an assessed fixture.
## JavaScript and function comparisons
JavaScript return-field projections require `presence` with `present`, `absent`
or `unknown-coverage`. Export-shape change rows retain both sides' presence,
and `property_inventories` report examined properties and coverage. Unknown
values and unknown presence are distinct; callers must not treat an unknown
value as a missing property. Semantic object-operation graph observations use
`properties.property_path`, an array of complete path segments or `null`,
rather than a flattened property name. Regenerate old application analysis
before depending on nested mutation or presence facts. See
[475a0f8](https://github.com/morluto/rea/commit/475a0f84dac63d710e032bc7f731c1a3bda624ec).
Function comparison dimension statuses are `unchanged`, `changed` or `unknown`.
The unreachable `truncated` status and `summary.truncated` counter have been
removed. Update exhaustive enum handling and display logic; unavailable facts
remain `unknown`. See
[5510b27](https://github.com/morluto/rea/commit/5510b27d7f863a3df26212fba4a59f8df0da3712).
## Historical-source symlinks
Source graph symlinks with `target_state: "unreadable"` or `"unknown"` require
`target: null`. Internal, external and missing targets retain their actual
recorded target strings. External targets use the observed absolute target;
display placeholders such as `<outside-root>` cannot serve as lookup data.
Reimport the source tree when the old graph retained only a placeholder, and
handle nullable targets in custom readers. See
[b7b4333](https://github.com/morluto/rea/commit/b7b433370310c3ffe33d5027d8393151d5e862da).
Keep original saved artifacts until their replacements and consuming workflows
have been checked. Fresh analysis may establish different facts if the target,
source tree or runtime changed; it does not rewrite what an older capture proved.
+228 -9
View File
@@ -12,6 +12,27 @@ input file and include the observed lipo slice offset for universal binaries.
If that offset is unavailable, segment evidence locations are omitted with an
explicit limitation; architecture inventory locations remain available.
Hopper's `address_to_file_offset` combines the native image-relative mapping with
original-file coordinates only after checking the source against the session's
SHA-256. FAT tables and embedded Mach-O headers come from that same hashing pass.
A changed or nonregular source reports `artifact_changed`; an unreadable or
missing source reports its access or filesystem failure. Those errors retain the native offset,
loaded header and provider source path in `details.partial_observation`, with the
original-file coordinate explicitly unavailable. Restore the original bytes or
reopen the changed executable to obtain verified coordinates. Snapshot replay
remains historical evidence for its recorded artifact identity.
A selected Hopper database's digest identifies the database rather than its
original executable. Original-file mapping is unavailable for that selection;
native mapping facts remain in partial evidence, and `read_bytes` still reads
the loaded database. Open the original executable to verify source coordinates.
Native Xcode command execution uses shared process supervision with a 60-second
deadline and a 64 MiB aggregate stdout/stderr budget. Timeout, cancellation,
stream failure, and output exhaustion retain the captured output, exit details,
and cleanup outcome in the error result. Truncated output is never parsed as a
complete observation.
- `trace_dylib_resolution` / `rea trace-dylib-resolution <app-or-mach-o>`
parses Mach-O load commands in TypeScript and follows dyld's path expansion
for every executable in an app bundle, or for one Mach-O within its directory.
@@ -37,6 +58,28 @@ explicit limitation; architecture inventory locations remain available.
connections and controller/class names. `verify:interface-builder` compiles
a source-owned AppKit XIB with `ibtool`. Storyboards require an installed
iOS platform; unsupported archive forms remain explicit.
XML plist archives accept UTF-8 and BOM-marked UTF-16 in either byte order.
App bundle `Info.plist` executable resolution uses the same decoder as keyed
archives and Interface Builder. The decoder consumes an initial
BOM and rejects malformed byte sequences, unsupported encoding declarations,
and declarations that disagree with the detected encoding. It never substitutes
UTF-8 for a declared encoding it cannot process. Archive and evidence digests
still identify the original serialized bytes. Bundle resolution reports
malformed bytes and unsupported encodings against the original plist path
before looking up the executable. Interface Builder decoding
limits aggregate input archives to 32 MiB.
Before decoding, it also bounds the serialized structure: expanded binary
plist references, NIB table records, XML elements and text, plus their
projected representations must fit the 256 MiB aggregate decode budget.
NIB string values, data, property names and class names are charged at each
projected JSON occurrence, including when the archive reuses one source
value. Binary plist data projection also accounts for the temporary byte
copy made by the pinned decoder projection. These are format-derived
representation reservations, not exact heap measurements or a process-wide
heap ceiling.
Archives beyond either aggregate budget are omitted with their paths and an
explicitly partial `archive_decode` facet; previously decoded documents and
their identities remain available.
- `inspect_native_dispatch_metadata` /
`rea inspect-native-dispatch-metadata <app-or-binary>` prefers a validated macOS Mach-O byte reader. It decodes
64-bit little-endian Objective-C class/metaclass records, superclass pointers,
@@ -53,8 +96,18 @@ explicit limitation; architecture inventory locations remain available.
So an external superclass resolves from its `_OBJC_CLASS_$_` bind (for
example `NSObject`). The `pointer_fixups` coverage facet names the mechanism.
Class properties, with parsed attributes, and `__objc_catlist` categories are
also decoded. Categories record the extended class, local or external, plus
Class properties preserve each encoded attribute as a raw `{name, value}`
pair, for example `{ name: "N", value: "" }`, and report atomicity on the
property: `N` means `nonatomic`; a complete typed attribute string without
`N` means the Objective-C default `atomic`;
missing or incomplete attribute metadata leaves `atomicity` and any
unestablished read-only value null. `is_meta_class`, `is_root_class`, and
`ivar_count` are also nullable when the selected provider exposes only symbol
names. Class implementation methods have null `is_required` and `is_optional`
fields because those facts apply to protocol declarations; decoded protocol
method lists retain their observed required/optional values. Class properties
and `__objc_catlist` categories are also decoded. Categories record the
extended class, local or external, plus
their methods, protocols and properties; category methods appear as
implementations with a `category`. Swift field-offset globals that are only
initialized at runtime stay unresolved. Generic, resilient, async and
@@ -62,10 +115,73 @@ explicit limitation; architecture inventory locations remain available.
partial coverage. Other providers retain the
existing symbol-based inventory with its narrower coverage.
## Exact CLI selectors
`function`, `instructions` and `decompile` accept `--procedure=<name-or-address>`;
`xrefs` accepts `--address=<name-or-address>`. `search` accepts `--pattern=<text>`
and `trace` accepts `--query=<text>`. These alternatives preserve names and text
that begin with a dash, including Objective-C names such as
`rea function ./app '--procedure=-[REAWidget delegate]' --provider hopper --format json`.
Use the equals form when the value resembles a CLI flag, for example
`rea trace ./app --query=--help --provider hopper --format json`.
The existing positional forms remain available. Missing selectors and conflicting
positional/named values fail before analysis starts; identical selections agree.
## Native instruction, call and type primitives
Ghidra supplies three exact-object operations:
Ghidra accepts hexadecimal addresses with or without a `0x` prefix, in either
letter case, and explicit address-space coordinates such as `EXTERNAL:0x1`.
Results use canonical lowercase hexadecimal offsets. For a procedure identifier,
an explicit `0x` or address-space prefix selects an address; otherwise an exact
database symbol name takes precedence over a bare hexadecimal address. Thus a
function renamed to `dead` remains selectable by name. Use the names returned
by the inventory, including their namespaces and any platform symbol prefix.
Ghidra also accepts secondary symbols at a function entry, such as an imported
`_main` label. A label inside a function is not a procedure-name selector; use
its address when selecting the containing function.
Overloads can share a fully qualified name; ambiguity errors return every
matching entry address so the caller can select the intended function directly.
`resolve_containing_procedure` also resolves an exact external entry. Its empty
body remains explicit; nearby external addresses do not inherit that identity.
Ghidra function references cover the complete function-body AddressSet and its
exact entry, including references into instruction interiors and references
from embedded data. Addresses inside an enclosing span but outside the owned
body are excluded. `procedure_references` returns internal and external edges;
`analyze_function` omits incoming edges whose sources belong to the same function.
The reference collector's semantics participate in the analysis profile, so
older snapshots cannot replay the former incomplete results under this profile.
Ghidra regex searches use Java Pattern semantics. If compiling or matching a
pattern exhausts the engine's stack, REA returns a resource constraint and
preserves the active database and annotations. Retry in literal mode or simplify
the regex; successful literal searches retain complete matching strings.
Cancelling an active request terminates the ephemeral database and discards its
annotations. REA retains the selected target and imports the original artifact
again on the next Ghidra query.
Opening the same target and profile again retains the live database, including
annotations. It does not make those edits eligible for an immutable snapshot.
Snapshot closes drain earlier provider requests before saving and keep later
requests waiting until the save and close finish. A concurrent successful edit
therefore rejects the snapshot save and leaves the edited session open.
After metadata edits, snapshot saves and imports remain unavailable in that
session. Use `export_evidence_bundle` to retain the observations, close without
`snapshot_path`, and reopen the target before importing or saving a snapshot.
Ghidra checks its private import copy against the artifact digest selected by
`open_binary`. If the source changes before that copy is acquired, the query
reports `artifact_changed` with the selected path and both digests. Reopen the
stable target to acquire its current identity. An already imported database
continues to describe its captured bytes even if the original path is changed
or removed; this identity failure does not mark the Ghidra installation unavailable.
On Linux and macOS, an unreadable source reports `access_denied`; a removed or
nonregular replacement reports `artifact_changed`. Source copying is cancellable
and never replaces an existing private snapshot.
```bash
rea inspect-native-instruction <binary> <address> --provider ghidra
rea resolve-native-call-targets <binary> <call-site> --provider ghidra
@@ -79,10 +195,43 @@ outside-memory and undecodable addresses have separate outcomes. Effective
memory base/index/displacement roles and per-instruction context mode remain
unavailable; `mode` is the program language variant.
Compact instruction references and call-target references preserve the source
address, operand index, DATA/READ/WRITE classification, primary status, provider
`provenance`, and reference `source` (for Ghidra: `analysis`, `default`, `imported`
or `user_defined`). Primary status reports the provider's chosen reference; it
does not establish literal addressing. Analyzer-inferred indexed targets remain
static references, not observed runtime reads or writes. Older evidence may omit
the additive fields, and null or omitted facts mean unavailable rather than false.
Ghidra distinguishes a return using decoded instruction p-code's `RETURN`
operation. `flow.classification_evidence` preserves the Listing flow type and
the observed return evidence; mnemonic spelling alone is not the classifier.
Other terminal or trap flows retain the provider's classification, and this
inspection does not change function extents or prove a calling convention.
The analysis profile commits this decoder behavior. Snapshots from the earlier
profile produce a profile mismatch rather than replaying the former generic
terminal result. The old snapshot's `evidence_bundle` remains valid retained
Evidence: copy that object to a separate JSON file and use `rea evidence-import`
to validate it. Run analysis without the old snapshot and save a fresh one
under the current profile. Other providers and older captures may omit the
classification evidence field.
Call resolution reports direct, resolved indirect, ambiguous, unresolved and
non-call outcomes from static call references. It does not establish runtime
execution or classify Objective-C/Swift/vtable/closure mechanisms from names.
`batch_decompile` keeps each caller-selected symbol or address in `items[].address`.
The separate `procedure` field reports the canonical entry and the provider's
observed entry label. An interior address therefore remains visible without
being mistaken for the function entry. Identity failures are reported as
`procedure.status: "unknown"`; label failures leave a null name and `name_error`.
Neither failure discards usable pseudocode, and names are not parsed from it.
Resolved entries also appear in the composed Evidence locations. New batch
Evidence commits the revised workflow profile; retained historical Evidence
remains valid. This tool
has no dedicated CLI command; the existing `decompile` command remains the
single-procedure CLI operation.
Type inspection selects one exact database pathname or typed data address.
Struct/union fields, enums, pointers, arrays, typedefs, size, alignment, packing
and bitfields retain database authority. Child types use exact IDs for further
@@ -188,16 +337,42 @@ arguments. The receiver class comes from LLDB's Objective-C runtime reader
without running target code; no expression is evaluated, and REA never
attaches to a process it did not launch.
The run ends when the process exits, `max_events` entries are recorded, or
`duration_ms` elapses. In the last two cases the process is killed, and REA
confirms that it is gone. The result reports:
The run ends when the process exits, `max_events` entries are recorded,
`duration_ms` elapses, or the aggregate trace resource budget is exhausted.
Bounded termination reports partial coverage. REA checks process termination
using a launch-time OS start identity; if ownership or cleanup cannot be
verified, the result or error preserves that uncertainty. The result reports:
- the outcome, exit status and captured stdout/stderr (1 MiB kept per stream);
- the outcome, exit status and captured stdout/stderr (1 MiB kept per stream
while excess bytes are drained and counted without growing capture files).
Each stream reports `complete`; when draining could not finish, its byte
count is an observed lower bound and truncation is explicit;
- caller-selected arguments, working directory, and environment overrides;
- `selected_file_sha256` and LLDB module identity observations. These checks do
not pin the executable against concurrent mutation; `loaded_image_sha256`
remains unknown;
- signal or exception stops;
- every breakpoint's resolved locations; a breakpoint that matched no loaded
code makes coverage partial;
- limitations.
The bridge limits retained event JSON to 8 MiB and caller frames to 65,536
across the run. It checks admission before retaining another complete event;
`resource-limit` reports which observations could not be completed without
silently changing the requested event or frame settings.
Resolved breakpoint locations have a separate aggregate 8 MiB metadata budget.
If their details exceed it, `location_count` retains the full observed match
count, coverage is partial, and `breakpoint_locations_truncated` is true. This
post-run metadata limit does not imply that the target was killed.
Accepted entries and signal stops are also flushed to a bounded 8 MiB journal.
If cancellation, timeout, capture failure, or a later bridge error prevents a
full result, the error retains this evidence in `details.partial_observation`
with partial coverage. Available output prefixes remain inline; their byte
counts are observed lower bounds when final drain counters are unavailable.
The original failure classification and cleanup uncertainty remain separate.
An interrupted journal row is ignored with an explicit limitation.
Only entries are observed: return values, floating-point and stack arguments,
and inlined or `objc_direct` calls are not. The target runs with the current
user's permissions and may change files, show UI or use the network.
@@ -210,15 +385,30 @@ the tool fails with a `debugger-attach-denied` reason.
## Provider and verification boundaries
Install a Ghidra 12.1.x release and the 64-bit full JDK it declares, then configure REA to
use them. Ghidra analysis supports Linux x64 and macOS x64/arm64; macOS requires
use them. Ghidra analysis supports Linux x64/arm64 and macOS x64/arm64; each installation requires
the matching native decompiler. Experimental Windows x64 P0 admits native
x86-64 PE applications on local NTFS using bundled Job Object ownership,
x86 and x86-64 PE applications and DLLs on local NTFS using bundled Job Object ownership,
protected runtime DACLs, and handle-based path admission. See [Windows Ghidra P0](windows-ghidra-p0.md) and
[issue #527](https://github.com/morluto/rea/issues/527).
On Linux and macOS, `annotate_native_function` atomically edits a function name
and entry comments in the ephemeral database, returning refreshed analysis
without changing executable bytes. Windows P0 remains read-only. Ghidra has no
without changing executable bytes. Annotation text must contain no NUL or
unpaired Unicode surrogate; a rejection identifies the field and UTF-16 index
and leaves every annotation unchanged. CRLF, supplementary Unicode characters,
and combining characters are preserved. Windows P0 remains read-only. Ghidra has no
GUI authority, and REA never falls back automatically to Hopper.
`set_address_name` and `set_addresses_names` give Ghidra sessions the same
compact naming results as Hopper: a local function entry renames that function,
and any other mapped address, such as a global, receives a new or renamed primary
label. A batch applies each address separately and reports one success boolean
per address. Use them to name many globals and helpers cheaply; use
`annotate_native_function` when you also want comments and a refreshed dossier.
Ghidra name edits preserve the existing namespace. Supply either a leaf name
such as `renamed` or a fully qualified name in that namespace, such as
`alpha::renamed`. The returned qualified name can be reused as an idempotent
rename input. Edits retain the existing namespace; other namespace-like text
remains literal leaf-name text. A qualified name with an empty leaf is rejected
before any comment or name is changed.
- `npm run verify:ghidra`: host-native debug/stripped targets, native type layout,
instruction/call facts, value dependencies and process/project cleanup.
@@ -238,3 +428,32 @@ GUI authority, and REA never falls back automatically to Hopper.
macOS ARM64 is the real host verified during this implementation. Admission of
macOS Intel does not claim an Intel verification run. Unsupported metadata and
unresolved runtime/value semantics remain visible in results.
## Interface Builder hierarchy coverage
A keyed-archive hierarchy UID without an object-table entry marks the hierarchy
as partial while preserving decoded objects and known links. UID 0 remains
archived nil and does not count as a missing reference. Archive and evidence
digests identify the original serialized bytes.
## Keyed archive integer precision
The archive reader observes XML number element types and binary number markers.
Integers beyond the exact range of a JSON number are reported with the original
decimal text as `{ "$plist_type": "integer", "decimal": "<exact digits>" }` when
that source value can be associated unambiguously. Integral real values remain
numbers. Colliding integer/real values, unclassified numbers, and malformed UID
markers remain decoded with an explicit precision limitation. The limitation
also counts observed unsafe integer literals, including observations outside the
selected object page. Incomplete supplemental metadata produces an explicit
precision note without rejecting an archive accepted by the byte decoder.
Mixed XML number content (comments, CDATA, processing instructions or child
elements) and integer text the supplemental reader cannot classify disable exact
association and retain decoded numbers with that precision note. Nonnumeric
`UID` and `CF$UID` dictionary values remain ordinary data and are projected
recursively; numeric reference markers retain their original representation.
Value projection preserves serialized node kinds, IDs, references and pagination.
Exact and ambiguous value counts describe emitted root/object value instances;
a root and an object may contain the same value. Archive digests identify the
original bytes.
+173 -3
View File
@@ -51,6 +51,34 @@ format is TOON. The file contains the complete capture Evidence record.
Choose an output file distinct from the scenario input: shell redirection opens
and truncates the output before REA reads the scenario.
While the capture runs, REA writes live status to stderr as one JSON object per
line. Stdout stays the final Evidence document:
```json
{
"rea_progress": {
"phase": "running",
"completed": 3,
"total": null,
"message": "elapsed_ms=1200 frames=1 samples=2 interactions=0",
"sequence": 4
}
}
```
`phase` is the observed lifecycle stage: `prepare`, `running`, `settling`, or
`cleanup`. `completed` counts collected terminal frames, process samples, and
interaction events. `total` stays null; REA does not invent a unit total or a
percentage. `message` reports elapsed time and those counts. The final line uses
`phase` `cleanup`, sets `terminal` to true, and adds `disposition` (`exited`,
`timeout`, `idle_timeout`, `cancelled`, or `failed`) plus the owned-process,
renderer, and temporary-root cleanup states. Updates use the shared progress
boundary and are limited to one intermediate line per 100 ms; the terminal line
is always emitted. If a receiver is slow, intermediate observations are merged
into the latest status, and stale live observations are discarded before final
cleanup status. Progress never copies child output. Child output remains in the
capture Evidence on stdout.
For example:
```json
@@ -86,6 +114,12 @@ from launch, must be ordered, and must fall within `timeout_ms`. Inputs marked
Environment overrides are recorded in the scenario commitment; inherited
values are not copied into Evidence.
Terminal dimensions must satisfy `columns × (rows + scrollback) ≤ 1,000,000`.
Every scheduled resize uses the same selected scrollback and must fit this
working-buffer budget. REA rejects oversized scenarios before launching the
command; it never clamps the requested dimensions. This limit is independent
of `limits.output_bytes`, which bounds retained terminal observations.
The capture contains raw PTY output chunks and rendered terminal states,
interaction dispatch outcomes, exit reason, sampled process-tree observations,
and settlement status. When filesystem paths are selected, REA records
@@ -94,7 +128,52 @@ deleted, modified, or unchanged. These are bounded snapshots, not a syscall
trace; short-lived changes between snapshots may be missed. With no selected
paths, filesystem effects remain unknown.
Output, file count, file size, process sampling, filesystem depth, total
A missing entry proves creation or deletion only when the corresponding
observation root's path enumeration was exhausted. Otherwise its effect has
`status: "unknown"`, the available before/after state, and a reason; a null
state in this variant means unobserved. Paths below symlinks that REA did not
follow also remain unknown. Partial enumeration of one root does not erase
known effects in another, and unavailable content hashes do not by themselves
make path absence unknown.
Terminal frame `data` is the comparison text after the selected normalization.
New captures also preserve `raw_data` when normalization changes a PTY chunk;
otherwise `data` is already the original text. Older captures may lack the
original text for changed chunks. Both values participate in Evidence identity,
while comparisons and trace assertions use the normalized text. Retaining the
original adds at most `limits.output_bytes` of text, because it comes from the
same admitted PTY chunks rather than a second unbounded stream.
Rendered frame `lines` hold the visible rows after normalization, with trailing
U+0020 spaces removed. Blank rows and internal spaces remain. `columns` records
terminal cell width; normalization and Unicode can make string lengths differ
from that width. `serialized_state` holds terminal serialization after the
selected normalization. Original admitted PTY chunks are available through
`raw_data ?? data`, as described above. Captures commit this line format in their
comparison contract, so a capture whose lines were padded to full width does not
compare as the same contract.
Custom `normalization.patterns` replace literal text with the caller's literal
replacement, including dollar sequences such as `$&` and `$$`. An empty pattern
also matches the first and last string positions. Captures with custom patterns
commit `pattern_normalization_version: "literal-replacements-v1"`. Legacy captures
remain readable. Cross-version comparison is rejected; capture both sides with
the same replacement semantics. Captures without custom patterns keep their
existing comparison contract.
Port normalization recognizes explicit `port`, `tcp_port`, `udp_port`, and
`listen` fields, URL authorities, IP endpoints, and `localhost` endpoints, with
ports from 0 through 65535. A port may end a sentence, as in `port: 8080.`;
a period followed by a letter or digit continues a decimal, version, or host
name instead. Each PTY chunk is normalized on its own, so a port whose period
ends the chunk is left unchanged because its continuation is not yet known. It preserves ordinary counters, dimensions, file line numbers,
and ambiguous bare host labels. Use explicit literal `patterns`
for a different application-specific spelling. Set `ports: false` to preserve
all endpoint numbers in comparison text. Captures commit the port-normalization
version so older broad numeric normalization cannot silently compare as the
same contract.
Output retention, file count, aggregate file-hashing bytes, process sampling, filesystem depth, total
runtime, idle time, and post-exit settlement are bounded by the scenario's
limits. The result marks truncated observations and residual unknowns rather
than treating missing data as proof of equivalence. Cancellation and timeout
@@ -102,12 +181,98 @@ run the same owned-process cleanup path. Settlement reports whether the
sampled process group quiesced or whether cleanup was needed or unverifiable;
sampling cannot prove that every short-lived or detached descendant was seen.
Every capture requires `truncation_details`, with separate accounting for:
- `raw_terminal`: original UTF-8 PTY chunk bytes and observed/retained chunk
counts. A chunk that does not fit `limits.output_bytes` is omitted whole;
a later smaller chunk can still fit.
- `rendered_terminal`: cumulative UTF-8 serialized-state and visible-line
bytes, plus observed/retained frame counts. This is independent of the raw
chunk budget and does not count JSON encoding. Repeated screen snapshots can
exhaust it even when all raw output fits. Rendered states use retained PTY
input, so raw omissions also limit rendered coverage.
- `filesystem_before` and `filesystem_after`: file-count/depth limits,
enumeration failures, whole-file hash budget and bytes successfully hashed.
Directory names are read incrementally within the remaining entry capacity.
When a directory exceeds that capacity, the retained subset follows filesystem
enumeration order and is then sorted; it is explicitly incomplete and cannot
establish that an omitted path is absent.
Each retained regular file without a digest has an aliased path, size,
remaining budget and reason: `file_bytes_budget`,
`file_changed_or_short_read`, or `file_unavailable`. Its `system_code` is
null unless an OS file operation failed, in which case it preserves the
reported error code. A file too large for the remaining budget is
skipped; a later smaller file can still be hashed. Hash omissions do not
imply incomplete path enumeration.
- `process`: sampling limit and whether sampling ended partially. Coverage
remains `sampled`, including when that limit was not exhausted.
The aggregate `truncated` flag summarizes these observations. Comparisons retain
results for unaffected dimensions and mark affected dimensions unknown; an
incomplete capture cannot locate the first divergence across all dimensions.
Trace assertions use coverage for the sources they select, so an assertion
about complete raw terminal output need not fail because rendered snapshots
were omitted. Captures missing `truncation_details` are rejected on import;
preserve them as historical files and recapture for current comparisons.
`limits.file_bytes` is already the cumulative whole-file hashing budget,
independent of `limits.output_bytes`, which bounds retained terminal content.
Each filesystem checkpoint starts with a fresh `file_bytes` budget across all
selected roots; it is not a per-file allowance. File contents are read in
64 KiB chunks for hashing and are not embedded in capture Evidence.
When the host withholds an unrelated process’s ownership token, REA leaves that
process untouched and records its PID and reason in `cleanup.unverified_processes`
and process residual unknowns. Successful cleanup verifies the owned group;
it does not attribute those unrelated processes. Related or otherwise unexplained
unreadable processes still prevent successful cleanup.
On macOS, changing a Node process's `process.title` can make its run token
unreadable. Node documents that [setting the title overwrites argv memory](https://nodejs.org/download/release/v24.18.0/docs/api/process.html#processtitle).
With the pinned toolchain, a live child retained a readable start identity
while its token became unavailable after this change; npm changes its title
as well. A newly started unreadable process can prevent verified cleanup even
after the selected command exits. REA preserves this uncertainty and leaves
that process untouched.
## Hash a report independently of terminal output
Select the producer's report directory and give `file_bytes` enough room for
the complete files you need, including other files in those roots. For example,
save this scenario and run `rea capture-process ./scenario.json --json > capture.json`:
```json
{
"executable": "node",
"arguments": [
"-e",
"const fs=require('node:fs');fs.mkdirSync('reports',{recursive:true});fs.writeFileSync('reports/final.json',JSON.stringify({status:'complete',data:'X'.repeat(131072)}));console.log('x'.repeat(8192));"
],
"working_directory": ".",
"filesystem_observation_paths": ["./reports"],
"limits": { "output_bytes": 1024, "file_bytes": 262144 }
}
```
The report exceeds the terminal budget but fits the independent 256 KiB hash
budget. Its complete SHA-256 appears in `normalized_result.files_after` at
`root_0:final.json`; check `truncation_details.filesystem_after` for omissions
and actual bytes hashed. The verbose terminal output is truncated without
preventing the report digest. The same scenario object is the MCP
`capture_process_scenario` input. REA never returns a prefix hash as a full-file
digest: an insufficient remaining budget produces a null digest and an
explicit omission reason.
A digest binds the complete bytes observed at that checkpoint, not the
producer's notion of a finished report. A stable periodic or running report
can also have a complete digest. Choose the final file and verify the
producer's documented completion marker, exit outcome and settlement
observations before calling it final. `after_settlement` names a filesystem
checkpoint, not a guarantee that an application finished successfully or
that an unobserved writer will never change the file. REA checks opened-file
identity/state around hashing and reports observed changes or unavailable
files; cancellation stops the hash. If an external sealer produces a manifest,
keep its completion claims and digest separate from REA's checkpoint facts.
## Compare two captures
Compare saved capture Evidence with:
@@ -130,7 +295,12 @@ causal evidence. Trace comparison returns `unknown` when a capture lacks the
required complete event journal or contains relevant residual unknowns.
Each capture carries commitments for the selected scenario, executable,
comparison contract, and normalization rules. Comparison rejects captures
whose comparison contracts differ. Captures are local Evidence files; keep
comparison contract, and normalization rules. The comparison contract covers
the working directory, explicit environment, filesystem observation paths,
terminal size, scripted events, timeouts, limits, and normalization; the
executable and its arguments may differ. Comparison rejects captures whose
comparison contracts differ and names the differing fields, so run both
scenarios from the same absolute working directory and observation paths.
Captures are local Evidence files; keep
their source artifacts and invocation context available when interpreting a
difference.
-219
View File
@@ -1,219 +0,0 @@
# Static-analysis provider evaluation
This guide describes repository main. Check the [released package boundary](installation.md#released-package-and-main) when using npm.
Ghidra read-only analysis is available on Linux x64 and macOS x64/arm64.
Install a Ghidra 12.1.x release and the 64-bit full JDK that release declares,
then configure REA to use them. Current 12.1 releases require JDK 21 or newer
and set no maximum. The bridge is verified with Ghidra 12.1.4 and JDK 21.
macOS installations need the matching native decompiler.
REA imports one target into a temporary project and exposes 25 read-only
operations after analysis completes. They cover inventories, search,
decompilation, assembly, function metadata, resolved calls, references, control
flow, instructions, and recovered types. Results identify the provider version,
analysis settings, target digest, and any unavailable or incomplete facts.
On Linux and macOS, `annotate_native_function` additionally edits names and entry
comments atomically, verifies readback, and returns refreshed function analysis.
Changes live only in the session database and leave executable bytes unchanged.
Ghidra does not expose GUI controls; Windows P0 remains read-only.
Windows x64 P0 supports native x86 and x86-64 PE applications on local NTFS with
bundled Job Object ownership, protected runtime DACLs, and handle-based path
admission. Real ordinary-user verification covers all 25 read-only operations
through the packaged CLI and MCP, target integrity, and cleanup. This remains
an experimental boundary; see [Windows Ghidra P0](windows-ghidra-p0.md) and
[issue #527](https://github.com/morluto/rea/issues/527).
[ADR-0001](adr/0001-provider-selection-and-analysis-profiles.md) fixes the
provider registry, deterministic selection, target binding, analysis profile,
snapshot migration, and compatibility semantics that implementation must
follow.
## Approved Ghidra v1 boundary
- Keep the existing provider-neutral CLI and MCP tool names.
- Bind one deep-analysis provider to a target for the target's lifetime; never
fail over silently between Hopper and Ghidra.
- Use an existing Ghidra installation and a compatible Java runtime. Setup must
not install or upgrade Ghidra or Java.
- Run Ghidra headlessly in an owned process with a private temporary project,
startup and cleanup deadlines, caller cancellation, and complete replies.
- Prefer a packaged Java bridge loaded through Ghidra's script path. PyGhidra
remains useful for prototypes but is not a mandatory production dependency.
- Treat authenticated `ping` and `shutdown` as lifecycle proof only. Inventory,
xref, CFG, and decompilation claims require separately admitted operation
contracts and real-provider conformance.
- Implement read-only inventories, assembly, decompilation, function metadata,
calls, references, containment, and complete inventory search first.
- Report GUI cursor/navigation and persistent mutation operations as unavailable
until their semantics and project ownership are explicitly designed.
- Verify real claims on Linux with at least two distinct source-owned binaries.
Verify the Windows host claim with the deterministic source-owned x86 and x86-64 PE
fixtures and all admitted operations; compare normalized semantic facts rather
than provider-specific pseudocode text.
## Shipped foundation boundary
`GHIDRA_INSTALL_DIR` must identify an extracted Ghidra 12.1.x release. Optional
`JAVA_HOME` must identify a 64-bit full JDK inside that installation's
`application.java.min` and `application.java.max` (JDK 21 or newer, with no
maximum, when the release leaves those at the 12.1 defaults). Otherwise doctor
probes `java`/`javac` or `java.exe`/`javac.exe` from `PATH`. Supported Linux and macOS
hosts accept compatible ELF, PE, and Mach-O executable targets. Host admission
and target compatibility are separate checks. Windows x64 P0 admits only native,
non-managed, non-DLL x86 and x86-64 PE applications on fixed local NTFS, with the packaged
native authority available before launch.
The launcher creates one ephemeral runtime root with project,
home/cache/config/data/temp, logs, descriptor, endpoint, target snapshot, and
ownership manifest.
It passes `-readOnly` and `-deleteProject`, and uses Ghidra's default analysis
and resource settings; inherited Java option injection variables are cleared.
On Linux, the mode-0600 descriptor carries the random token without
exposing it in argv or environment and the Java bridge binds a mode-restricted
Unix socket. macOS uses the same local transport. The bridge reports actual
Ghidra/language/compiler/analysis/import-digest metadata and accepts only
authenticated `ping`, `shutdown`, thirteen read-only inventory/load-image methods,
and twelve function-analysis methods. Linux/macOS also admits atomic function
annotation changes in the ephemeral database. Close, cancellation, timeout, malformed protocol,
or process exit stops the owned process resources, closes the socket, and
removes the runtime root.
The experimental Windows transport uses authenticated IPv4 loopback with a
token-free endpoint record. The bundled native authority establishes Job Object
ownership, protected runtime DACLs, and handle-based path admission before
launch. If the bundle or an admission constraint is unavailable, the provider
remains unavailable; a `taskkill` fallback does not establish that authority.
The provider catalog lists 25 read-only Ghidra operations and the Linux/macOS
session annotation operation. GUI cursor/navigation and persistent mutations
remain unavailable; Windows P0 admits no database mutation. The router therefore
reports them unavailable instead of borrowing Hopper semantics or inferring
capability from a successful import.
## Admitted inventory semantics
| Concern | Ghidra contract |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Program identity | One `analyzeHeadless` import produces exactly one Program; `list_documents` therefore returns exactly one name. |
| Addresses | Default memory uses lowercase `0x` hexadecimal. Non-default and external spaces use `<percent-encoded-space>:0x<hex>` and remain round-trippable. The handshake commits image base and default address-space name. |
| Symbols | `list_names` includes address-bearing memory and external symbols, including dynamic symbols, while excluding variable and no-address namespace records. Each item reports primary, dynamic, external, symbol type, and source facts. |
| Procedures | Both non-external and external functions are listed. A local thunk remains distinct from its resolved target; exact and qualified name lookup fails on ambiguity rather than guessing. |
| Strings | Only Ghidra-defined string `Data` is observed. Items report charset, byte length, and whether a required null terminator is missing. The API cannot distinguish a present terminator from fixed/Pascal layouts when no terminator is missing, so that state is named `present_or_not_required`. |
| Memory | Memory-block end addresses are exclusive. Read/write/execute, initialization, overlay, address space, and image base are direct Ghidra observations. |
| Inventory | Procedure, symbol, and string listings plus searches return the complete matching collection in one response; callers do not provide offsets or result-count limits. |
| Search | Literal and Java-regex searches scan the complete immutable inventory and return all matching entries inline. Search waits for a reply or caller cancellation; there are no caller-supplied offsets or result-count limits. |
| Analysis state | The socket is exposed only after default auto-analysis completes. Established operations wait for their reply or caller cancellation; there is no fixed response-size ceiling. |
## Admitted function-analysis semantics
| Concern | Ghidra contract |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Decompiler lifetime | One persistent `DecompInterface` is opened for the imported Program and disposed during bridge shutdown. Native decompilation has no fixed per-function deadline. External functions or functions without bodies return `null`; cancellation and native failure remain distinct. |
| Serialization | A FIFO sends one Program request at a time. Caller cancellation removes queued work promptly and is passed to active socket waits. This is an adapter safety commitment, not a claim that every Ghidra API is thread-safe. |
| Function identity | Every function result carries the entry address and Ghidra FunctionManager classification for external, thunk, and resolved thunk target. These are observations, not proof that unresolved targetless calls have been recovered. |
| Assembly and pseudocode | Assembly is complete Ghidra Listing text; pseudocode is Ghidra decompiler output. Neither is original source, and cross-provider comparison never treats Hopper and Ghidra text as equal or unequal semantic facts. |
| Instruction fast path | `read_function_instructions` returns every raw Listing instruction for the requested function without invoking the decompiler or whole-program name/string inventories. |
| Calls and references | Callers/callees contain only resolved functions. Reference edges preserve exact ReferenceManager type and call/jump/data/read/write/indirect/computed/conditional/terminal/external facts. Targetless computed flow remains unknown. Synthetic entry-point references without actionable memory sources are omitted explicitly. |
| CFG | Dossiers use `BasicBlockModel` and retain only non-call successors inside the function body. CFG topology is address-normalized for comparison; provider-specific block construction remains a declared difference. |
| P-code value flow | Function dossiers include up to 3,000 high-p-code operations, at most 64 inputs per operation, and 12,000 def-use edges. Results identify memory reads/writes, branches, and calls by p-code opcode, and mark decompiler-dead operations. Large results report truncation, an omitted-operation lower bound, and known omitted-input/edge counts. The dossier is an intra-function graph; `trace_native_values` composes derived parameter/argument and return/output dependencies across resolved calls. It does not resolve memory aliasing, call side effects, runtime behavior, persistent state, or business meaning. |
| Result extent | Function instruction scans and native API boundary observations remain complete. P-code flow is the explicit bounded exception; its count fields distinguish exact retained counts from lower-bound or known-omitted counts. Caller cancellation and provider failures remain distinct. |
`npm run verify:ghidra` compiles the versioned C oracle into debug and stripped
host-native targets (x86-64 ELF on Linux x64 or Mach-O on macOS), plus a native
DWARF 4 type-layout object. It proves the admitted operations, external functions, resolved thunks, exports, stripped-name
behavior, direct and targetless indirect calls, typed references, strings/xrefs,
multi-block CFG, bounded p-code def-use/effect links, semantic enhanced workflows, cancellation, startup deadlines,
serialized concurrency, malformed-target rejection, profile identity, and
process/project cleanup against real Ghidra 12.1.4. Unit fixtures separately
cover startup deadlines, process exit, queued cancellation, and malformed wire
output.
`npm run verify:ghidra:cross-format` adds AArch64 ELF, x86-64 PE, and x86-64
Mach-O target coverage. It requires `clang`, LLD, and `lld-link`; set
`REA_CLANG`, `REA_LLD`, or `REA_LLD_LINK` to select them. The verifier checks
these tools before compilation. Keeping this matrix separate lets Linux
host/provider acceptance run with only the host compiler.
`npm run verify:ghidra:windows` and its `-- --x86` variant check the source-owned native x86 and x86-64 PE
fixture, all 25 read-only operations, target/snapshot/import SHA-256 linkage,
and project, endpoint, process, and runtime cleanup. The independent native
lane checks DACLs, handle admission, cancellation, and Job Object lifecycle.
`npm run verify:ghidra:windows:package` packs and installs REA into an isolated
prefix, then checks ordinary-user CLI/MCP operations against canonical contracts.
All lanes require matching native controls; package startup alone establishes
only package compatibility.
## Shared provider-process foundation
`src/process/` now provides the mechanisms that a long-lived Hopper or Ghidra
adapter shares: POSIX run-token-authenticated process-group ownership,
ephemeral temporary runtime roots, one absolute startup deadline, correlated
request cancellation and lifecycle-deadline cleanup, bounded stdout and stderr retention with
exact byte counts, process-exit diagnostics, and bounded TERM-to-KILL shutdown.
Reusable fixtures exercise exit, timeout, cancellation, graceful termination,
forced termination, double-close, spawn failure, and resource release. Windows
Ghidra uses its native Job Object, private runtime, and path-admission boundary;
generic process-tree termination alone cannot establish provider availability.
The foundation does not define a bridge schema, socket framing, health payload,
analysis model, or shutdown acknowledgement. Hopper keeps its authenticated
NDJSON-over-Unix-socket protocol in `src/hopper/`; Ghidra has a separate strict
NDJSON protocol implemented by the packaged Java `HeadlessScript` and reuses
only the generic process mechanisms.
## Shortlist
| Provider | License / automation surface | What it brings | REA fit and blockers |
| ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Ghidra](https://github.com/NationalSecurityAgency/ghidra) | Apache-2.0 source license; `analyzeHeadless`, Java APIs, and PyGhidra | Static analysis, multiple processors and formats, scripting, and project/database workflows | 25 read-only operations shipped on Linux/macOS with installation checks, temporary projects, a serial API queue, and real ELF/PE/Mach-O conformance. Experimental Windows x64 P0 supports native x86 and x86-64 PE on local NTFS with bundled native controls and ordinary-user CLI/MCP verification; Linux/macOS additionally support atomic session function annotations; Windows mutation and all Ghidra GUI operations are unavailable. |
| [Rizin](https://github.com/rizinorg/rizin) / [rz-pipe](https://github.com/rizinorg/rz-pipe) | Rizin repository contains LGPL-3.0 and GPL-3.0 components; `rizin`, `rz-bin`, and language bridges through `rzpipe` | Portable CLI analysis, disassembly/debugging, many architectures and file formats, JSON command output | Good candidate for a process-backed Linux provider and fast metadata fallback. License/component inventory must be preserved; command output needs version-pinned parsers and semantic conformance before evidence is trusted. |
| [LIEF](https://github.com/lief-project/LIEF) | Apache-2.0; C++, Python, and other bindings | Deterministic parsing and modification of ELF, PE, Mach-O, COFF, and related executable formats; headers, sections, symbols, relocations, and functions | Best near-term complement, not a decompiler replacement. It can cover format metadata and artifact evidence without a long-lived analysis process; function semantics, pseudocode, CFG, and cross-reference parity remain out of scope unless separately demonstrated. |
| [Binary Ninja](https://docs.binary.ninja/dev/index.html) | API/documentation components are MIT, while the analysis product is licensed by edition; commercial, Ultimate, or Headless license is required for headless automation | Python/Core/C++/Rust APIs, headless loading, IL layers, function analysis, plugins, and configurable analysis | Strong technical fit for a native provider, especially function dossiers. Commercial licensing, license-secret handling, native runtime packaging, and multithreaded lifecycle rules are material deployment blockers. |
## Recommended order
1. Use the implemented explicit provider registry and target binding without
changing Hopper behavior.
2. Maintain the admitted Ghidra function boundary through the shared
conformance corpus and add formats or semantics only after real proof.
3. Connect Electron/native-add-on application findings to the selected native
analysis provider without introducing provider-prefixed tools.
4. Evaluate LIEF or Rizin later as complementary metadata/disassembly providers,
and Binary Ninja as an optional licensed provider, using the same admission
gate.
## Required admission gate
Before implementation, an adapter proposal must provide:
- a capability matrix covering supported, unsupported, and degraded results;
- provider identity, version, analysis profile, target digest, authority,
limitations, and deterministic locations in every Evidence record;
- bounded subprocess or library lifetime, cancellation, timeouts, and cleanup;
- actionable local diagnostics that retain paths, digests, mismatch locations,
and provider metadata while redacting credentials, authorization headers,
license secrets, and other genuine secrets;
- the same source-owned fixture corpus across architectures and formats;
- repeatable checks for function identity, addresses, strings, names, xrefs,
CFG, and pseudocode wherever those capabilities are claimed.
These gates turn the accepted direction into verified capabilities rather than
prematurely claiming equivalence or redistribution support.
## Primary-source notes
- Ghidra 12.1.4 documents headless batch mode and its Java runtime requirements
in its [release-specific Getting Started guide](https://github.com/NationalSecurityAgency/ghidra/blob/Ghidra_12.1.4_build/GhidraDocs/GettingStarted.md);
the [official release](https://github.com/NationalSecurityAgency/ghidra/releases/tag/Ghidra_12.1.4_build)
supplies the corresponding distribution and checksums.
- Rizin lists supported formats, architectures, tools, and `rzpipe` bridges in
its [repository README](https://github.com/rizinorg/rizin); `rz-pipe` documents
JSON command transport and pipe backends.
- LIEF's [format tutorial](https://lief.re/doc/stable/tutorials/01_play_with_formats.html)
and [Python API](https://lief.re/doc/latest/api/binary_abstraction/python.html)
document parsing and format-agnostic binary access.
- Binary Ninja documents its [headless automation model](https://docs.binary.ninja/dev/batch.html),
[edition licenses](https://docs.binary.ninja/about/license.html), and the
[MIT license for API/documentation components](https://docs.binary.ninja/about/open-source.html).
+49 -21
View File
@@ -1,15 +1,32 @@
# Releasing from a checkpoint
# Releasing REA
REA releases use an explicit source checkpoint. Main can continue accepting
changes while a release is tested and published. The Release workflow runs
only when a maintainer dispatches it; main pushes do not refresh release PRs.
Pushes to main automatically open or refresh a Release Please PR with the next
version and changelog. Review its migration notes and wait for its current CI
checks to pass. Merging that PR into main starts publication automatically.
## 1. Select the source
The Release workflow validates the merged release metadata and ancestry before
creating a tag. npm and MCP Registry publication use the exact reviewed merge
SHA returned by Release Please. Later main commits cannot change that source.
Ordinary main pushes and closed, unmerged PRs cannot publish packages. Check
both publication jobs and the published-package canary; a merged PR or GitHub
tag alone does not establish that publication finished. Retry failed jobs in
the original run after a partial publication.
Choose the next version from the unreleased Conventional Commits, including
For a release that needs an independently frozen application checkpoint, use
the optional manual path below. It retains explicit prepare and publish phases.
## 1. Select a source for a manual checkpoint
Use the next minor version proposed by Release Please, including releases with
breaking changes. Record the full source SHA and create `release/VERSION` at
that commit. The version is a maintainer choice; Release Please's proposed
version must agree before publication.
that commit. The selected version and Release Please's proposed version must
agree before publication.
When choosing the manual path, leave the automatic main release PR unmerged.
Select the application commit from main, create the frozen branch, and prepare
its own release PR using the steps below. Merging the main release PR starts
automatic publication instead. Close the superseded main PR after the manual
release has published and its metadata has been synchronized back to main.
`release/VERSION` also sets the expected version for the workflow. Use an exact
SemVer such as `release/6.1.0` or `release/6.1.0-rc.1`, without build metadata.
@@ -18,19 +35,24 @@ registry metadata or changelog disagrees with that version before creating a tag
### Compatibility and version selection
REA uses the default SemVer strategy: compatible fixes increment patch;
compatible capabilities increment minor; incompatible public behavior increments
major. Adding tools, internal refactoring and correcting behavior outside the
supported contract do not by themselves require a major release.
For the 6.2 candidate, review the [6.1 to 6.2 migration guide](migration-6.2.md)
alongside the changelog before publication.
REA uses Release Please's `always-bump-minor` strategy: every release increments
minor and resets patch, including releases with breaking changes. For example,
the next release after 6.0.0 is 6.1.0. Version numbers use the SemVer format,
but a minor increment does not promise backward compatibility. Review the
changelog's breaking-change section and migration notes before upgrading.
The supported public surface includes documented CLI commands/options, MCP tool
names and input/result contracts, saved evidence formats and supported runtime
requirements. Before adding `!` or a `BREAKING CHANGE` footer, a PR must identify
a previously valid call or configuration that will fail or change meaning,
explain why compatibility cannot be preserved, and give its migration. Prefer
optional additions, compatibility adapters and a documented deprecation period;
group deliberate removals into a planned major release. Maintainers review this
impact before merging; the bot parses markers and cannot infer compatibility.
optional additions, compatibility adapters and a documented deprecation period.
Keep breaking markers so the bot includes migration notes without incrementing
major. Maintainers review this impact before merging; the bot parses markers
and cannot infer compatibility.
For example, adding an optional inspection tool is a minor change. Rejecting a
relative MCP path previously accepted by the public contract is breaking;
@@ -80,9 +102,11 @@ and the PR titles in GitHub's default merge messages. The report preserves the
original merge subject alongside the extracted Conventional Commit title.
This matters after merging a side-branch release back into a newer main:
Release Please's chronological history cutoff can omit unreleased mainline
commits. Unreleased breaking markers require a major increment and references
in the new release's breaking-change migration section. Other omitted entries
are reported for review. Historical notes from an older release cannot satisfy
commits. Under `always-bump-minor`, unreleased breaking markers allow a minor
increment and still require references in the new release's breaking-change
migration section. Checkpoints using the default strategy retain the major
increment requirement. Other omitted entries are reported for review.
Historical notes from an older release cannot satisfy
the new release's migration check. This audits declared markers and references;
it does not prove API compatibility or the quality of a migration explanation.
@@ -115,6 +139,8 @@ gh workflow run release.yml --ref release/5.0.0 \
Publication creates the release from the merged bot PR without preparing or
updating another PR. Both npm and MCP Registry jobs check out Release Please's
exact release SHA. They do not build the current main tip or a mutable branch.
Stable versions publish to npm's `latest` tag; prerelease versions publish to
the `next` tag so they cannot replace the stable install by default.
The publish dispatch runs from the frozen release branch so npm's provenance
records the actual release commit. Before Release Please creates a tag, the
workflow accepts only `prepare` or `publish` and requires the selected branch
@@ -139,7 +165,7 @@ A GitHub tag alone does not establish npm or MCP Registry publication.
## 4. Sync metadata back to main
Post-release synchronization is part of completing the release. Finish it
Manual checkpoint synchronization is part of completing that release. Finish it
before cutting the next checkpoint; otherwise main retains the previous
release baseline and can propose an already-published version again.
@@ -161,8 +187,10 @@ git fetch origin main --tags
git merge-base --is-ancestor rea-agents-5.0.0 origin/main
```
Close any superseded rolling release PR. Future releases repeat the checkpoint
procedure from main; never resume automatic release-PR refreshes on main pushes.
Close the superseded main proposal before merging the synchronization PR.
That merge's main push opens a proposal for the following release using the
updated baseline. Future releases can use the automatic main PR or repeat the
manual checkpoint procedure; automatic proposals do not move frozen branches.
Preparation generates and validates the catalog, portable conformance
projections, and packaged skill from the candidate checkout without committing
them. The checkpoint validator binds tracked version authority to the source
+27 -117
View File
@@ -1,125 +1,35 @@
# REA roadmap
## Tool direction
The [platform tracker](https://github.com/morluto/rea/issues/32),
[process/Hopper tracker](https://github.com/morluto/rea/issues/48), and
[browser tracker](https://github.com/morluto/rea/issues/39) track capability and
verification work. Available tools and setup are documented in the
[investigation guides](https://rea.tools/guides/),
[installation guide](installation.md), and
[generated catalog](mcp-contracts.md#generated-catalog).
REA provides inspection, capture, and comparison tools that return evidence
directly. Agents choose commands, paths, browser actions, scripts, and local
fixture servers, then compose experiments from those results. CLI and MCP must
expose equivalent behavior and preserve observations, inferences, and unknowns.
## Priorities
[#555](https://github.com/morluto/rea/pull/555) removed REA permission grants,
scope ceilings, elicitation, and repeated approval fields.
[#572](https://github.com/morluto/rea/pull/572) removed the replay engines,
Node characterization prepare/execute flow, and plan-only managed runtime
correlation tool. Those systems are retired roadmap items. Existing evidence
authority labels remain readable as provenance; they do not imply a current
replay executor.
- Expand native architecture, type, and indirect-call verification.
- Connect static findings and runtime observations across application layers.
- Improve obfuscated managed-code comparisons and verified native links.
- Extend process, protocol, filesystem, reconnect, and build-comparison coverage.
- Evaluate additional providers and targets when an analyst workflow demonstrates
a capability gap.
Local operations use the current user's OS permissions. Input and protocol
validation, provider prerequisites, target identity, cancellation, and owned
resource cleanup remain part of each tool's contract. Setup still discloses
installation changes and requires approval before writing or installing.
## Admission criteria
## Planned work
New capabilities must return useful evidence through shared CLI/MCP workflows,
preserve observations and unknowns, and declare actual authority and lifecycle
constraints. Agents compose experiments using ordinary commands, scripts, and
fixture servers; custom orchestration needs a demonstrated requirement.
The [website guides](https://morluto.github.io/rea/guides/) and
[generated catalog](product-catalog.json) describe available workflows.
Current development priorities are:
Provider and platform claims require their corresponding
[real verification lanes](testing.md#real-toolchain-verification-lanes).
See [tool design](tool-design.md) for choosing a tool boundary and
[Ghidra semantics](ghidra-provider.md) for the existing deep-provider contract.
- Keep generated metadata and narrative documentation aligned with tools,
providers, setup options and releases.
- Expand native architecture, type and indirect-call verification across
Hopper and Ghidra.
- Connect additional static extractors and runtime observations to
cross-layer feature traces.
- Improve obfuscated .NET comparisons and links between managed findings
and verified native analysis.
- Extend process, protocol, filesystem, reconnect and build-comparison
coverage, plus browser and Electron scenario actions.
- Evaluate native runtime observation through LLDB, Frida, system logs and
API tracing, and additional tools and targets such as Binary Ninja, Rizin,
LIEF, Windows-native workflows, mobile applications and firmware.
Provider additions and platform support require the corresponding real
verification lanes; see [testing](testing.md) and
[provider evaluation](provider-evaluation.md).
## Remaining evidence and provider work
The [platform roadmap](https://github.com/morluto/rea/issues/32),
[process and Hopper fidelity tracker](https://github.com/morluto/rea/issues/48),
and [browser tracker](https://github.com/morluto/rea/issues/39) track remaining
capabilities and proof. Their scope follows direct tools and agent-composed
experiments; custom replay languages and grant systems are not completion gates.
[Inline Evidence composition](https://github.com/morluto/rea/pull/585) now returns
the complete record accepted by comparison tools. Managed inspection uses an
explicit PE/CLI target independently of the native provider selection. Comparisons
preserve unknowns when observation is incomplete, and PTY diagnostics retain the
actual loader or startup failure. Browser cleanup reports incomplete teardown
alongside the primary failure; transient documents invalidate only the affected
frame's WebMCP registrations. Real-provider and platform claims still require
their corresponding verification lanes.
## Shipped behavior
REA setup lets you select agent integration and optional Hopper installation.
It installs the bundled workflow, configures detected agents, and can save
verified paths for an existing Ghidra installation. It configures Claude Code,
Claude Desktop, Codex, Cursor, Gemini CLI, Windsurf, Devin, OpenCode, Antigravity,
GitHub Copilot CLI, Command Code, and VS Code using each client's configuration format.
Ghidra analysis supports Linux x64 and macOS x64/arm64 with Ghidra 12.1.x and the
64-bit full JDK that installation declares. Current 12.1 releases require JDK 21
or newer and set no maximum; the bridge is verified with Ghidra 12.1.4 and JDK 21.
macOS also requires the matching native decompiler. The
adapter exposes thirteen inventory operations and twelve function-analysis
operations, for 25 read-only operations total. Linux and macOS additionally support
atomic function-name and entry-comment edits with refreshed analysis; metadata
is discarded on close and executable bytes stay unchanged. Approved setup saves verified
installation paths in agent configurations without installing or changing
Ghidra or Java.
Real-provider verification uses host-native debug and stripped fixtures plus
a native type-layout object. A separate lane covers AArch64 ELF, PE, and
Mach-O cross-target fixtures. See [testing](testing.md) for the prerequisites
and exact commands.
Experimental Windows x64 P0 now supplies bundled Job Object ownership,
protected runtime DACLs, and handle-based admission for native x86 and x86-64 PE
applications on local NTFS. Real ordinary-user CLI/MCP verification covers
all 25 read-only operations and cleanup. The [Windows P0 guide](windows-ghidra-p0.md)
describes this boundary and unverified broader coverage.
## Ghidra maintenance boundary
Extend formats or semantics only with normalized provider-neutral contracts and
real source-owned conformance. Hopper and Ghidra pseudocode or assembly text is
not expected to match; unresolved targetless flow remains unknown. Automatic
Ghidra acquisition, if ever added, remains a separately planned and approved
related-tool change; setup must never install Java.
Maintain Windows P0 with independent DACL readback, handle-based admission,
private authenticated IPC, and Job Object assignment before provider execution.
Process capture, Hopper, and broad filesystem-sensitive workflows remain
separate Windows projects; P0 does not imply their parity.
## Capability-selective setup
Setup already lets users select agent integration and Hopper installation.
Once REA supports installing additional analysis tools, it can expand these
choices to match the work a user wants to do. It may ask whether the operator wants to investigate
native binaries, websites, mobile applications, firmware, or runtime protocols,
then propose only the tools needed for the selected work.
That future installer must preserve the current safety boundary:
- detect and reuse existing tools;
- disclose every source, destination, license, command, and system effect;
- prefer user-local installation;
- install only explicitly selected toolchains;
- require tool-specific authorization for unattended system changes;
- verify each installed tool before reporting readiness.
No placeholder tool choices or speculative installer registry are implemented
until another supported toolchain makes the abstraction concrete.
Setup remains additive, reuses existing tools, and requires approval for disclosed
configuration and Hopper installation changes. Additional installer choices need
an implemented toolchain and explicit scope; setup does not install or upgrade
unrelated runtimes or dependencies.
+606 -120
View File
@@ -1,32 +1,36 @@
# Testing REA
Prefer evidence in this order: full end-to-end workflows with real production
providers, integration tests across data/API boundaries, then golden regressions
from real captured inputs. Keep focused module tests for distinct failure or
semantic cases that these workflows cannot reliably reproduce. A test's path
or suite name does not establish its behavioral depth.
Use this guide when choosing coverage, pruning tests, or running a verification
lane. For commands, jump to [developer commands](#developer-commands); for engine
prerequisites, use [real-toolchain lanes](#real-toolchain-verification-lanes).
Avoid tests that mirror getters, enum mappings, fixture helpers, or prescribed
call sequences. Prefer one representative workflow over a Cartesian matrix
when every row crosses the same boundary. Keep distinct command handlers,
producer representations, failure reasons, and lifecycle states covered.
Consolidate their shared setup without hiding the inputs or expected evidence.
Prefer real public CLI/MCP workflows, then production-boundary integration,
then goldens captured from real producers. Keep module tests for distinct
failures or semantics that stronger workflows cannot reliably reproduce.
Paths, compiled imports, and suite names do not establish test depth.
Tests are grouped into Vitest projects so ownership, allowed dependencies and
runtime cost are visible from their paths. Before pruning a distinct boundary
regression, identify the replacement scenario and its assertions; passing
success journeys do not replace malformed input, cancellation, permission or
cleanup coverage. Trivial helper checks do not need a replacement. If only
tests consume a production module, trace CLI/MCP and verifier imports,
including imports of compiled files, and remove abandoned scaffolding with its
tests when it has no runtime consumer.
Prune tests that mirror implementation details or duplicate a stronger claim.
Before deleting a distinct regression, identify the replacement scenario and
assertions. Preserve malformed formats, cancellation, cleanup, permissions,
capacity, target identity, and combinations with distinct interactions.
Trivial helper assertions need no replacement. Remove abandoned production
scaffolding only after checking runtime and verifier consumers, including
compiled imports.
Measure slow files before removing capacity regressions. Optimize repeated
process startup, fixture construction, and production algorithms when they
dominate runtime. Keep at least one input beyond each formerly failing size or
depth; smaller fixtures do not establish that truncation or stack exhaustion
has been fixed. Record the toolchain, coverage mode, and cache conditions when
comparing durations.
Use representative scenarios rather than Cartesian matrices of equivalent
cases. Share setup without hiding inputs or expected evidence. For successful
`Result` values, throw the typed error before asserting the value; a preceding
`.ok` assertion adds no coverage. Protocol fixtures must reject unmodeled
commands and preserve actual producer reply shapes.
Report unavailable authority as a named skip. Await owned cleanup before a
verifier reports success. Native process inspectors are released at Vitest
worker teardown; fork termination does not run Node exit hooks, and per-file
teardown would retire inspectors still needed by other files.
Measure slow cases before pruning capacity coverage. Retain inputs beyond the
formerly failing size/depth and distinguish cold runs, warm builds, coverage,
and toolchain conditions when comparing timings.
## Behavioral depths
@@ -49,12 +53,6 @@ registries but do not cross production filesystem, process, socket, or browser b
Boundary tests cross one production boundary. Only acceptance tests assemble
the complete runtime or invoke the compiled product surface.
Binary session, registry, lazy-client and snapshot module cases live under
`src/application/binary/`. Their composition cases stay in
`tests/composition/analysis-sessions/`; snapshot persistence and actual SDK calls
stay in the filesystem and MCP boundary lanes. The shared injected session fixture
serves several capabilities and remains under `tests/fixtures/`.
Focused immutable builders and recording ports shared by one test family live
beside their production owner as `src/**/*.fixture.ts`. They are typechecked
with the suite and excluded from package builds; broader runtime and provider
@@ -90,6 +88,191 @@ entrypoint and include its verifier/fixture files in their cache inputs.
## End-to-end, integration and golden evidence
The optional `verify:qwen-client`, `verify:pi-client`, and `verify:hermes-client`
lanes require an installed native client. Select its executable with
`REA_VERIFY_QWEN_COMMAND`, `REA_VERIFY_PI_COMMAND`, or `REA_VERIFY_HERMES_COMMAND`.
They configure disposable profiles through the public REA CLI, preserve caller
settings and backups, and exercise real stdio MCP calls and skill loading. The
`call` mode checks complete catalog discovery and actual JavaScript Evidence;
pass `-- chat` to check plain chat with REA enabled. Qwen also reads the full
result that its client offloads, and Pi exercises default codemode execution.
Use `REA_VERIFY_RUNTIME_ROOT` to select a production-only installed REA package.
Receipts retain client versions, result digests, host coverage and owned-process
cleanup. These POSIX lanes use a deterministic loopback model, so they do not
prove live model-provider or native Windows compatibility. Qwen, Pi and Hermes
bind both `HOME` and `USERPROFILE` to the disposable account. Qwen and Pi discover
the shared personal skill through their default search paths without an explicit
skill setting; Hermes discovers it through the selected `HERMES_HOME`.
Set `REA_VERIFY_HERMES_STICKY_PROFILE=1` to exercise native Hermes selection of
a named sticky profile with `HERMES_HOME` still pointing to its root.
`verify:gemini-client` requires an installed Gemini CLI (verified with
`@google/gemini-cli@0.63.0`); select it with `REA_VERIFY_GEMINI_COMMAND`.
The optional POSIX lane uses native `GEMINI_CLI_HOME` discovery in an isolated
Git project, checks setup plans, backups and idempotence, activates the installed
personal skill, validates all forwarded input JSON Schemas against their declared
dialect, forwards the complete REA catalog and checks full JavaScript
Evidence for a Unicode path. Use `-- chat` for ordinary chat with REA enabled,
or `REA_VERIFY_RUNTIME_ROOT` for a production-only installed REA package.
The local fixture exercises the real Gemini API adapter, including its
`untrusted_context` tool-result envelope. Token counts are synthetic; live
Google API and native Windows compatibility remain unverified. The lane disables
the client's memory-based relaunch to preserve the caller's Node heap budget.
`verify:opencode-client` requires an installed OpenCode (verified with
`opencode-ai@1.18.35`); select it with `REA_VERIFY_OPENCODE_COMMAND`.
The optional POSIX lane configures isolated XDG roots and `OPENCODE_CONFIG_DIR`,
checks setup plans, backups, preserved JSONC comments and idempotence, activates
the installed skill, validates all forwarded input schemas and verifies complete
JavaScript Evidence for a Unicode path. JSONC is the default fixture; set
`REA_VERIFY_OPENCODE_CONFIG_FORMAT=json` for JSON. Use `-- chat` for ordinary
chat or `REA_VERIFY_RUNTIME_ROOT` for a production-only installed package.
The native core runs with external plugins disabled through `OPENCODE_PURE`;
the local OpenAI-compatible fixture has a caller-declared one-million-token
context and synthetic usage. Skills use an explicit isolated `skills.paths`
directory, so default OS-home discovery remains unverified. Live model APIs and
native Windows are also unverified.
`verify:claude-client` requires installed Claude Code (verified with
`@anthropic-ai/claude-code@2.1.296`); select it with `REA_VERIFY_CLAUDE_COMMAND`.
The optional POSIX lane uses native `CLAUDE_CONFIG_DIR` discovery, an independent
Git workspace, user settings and default built-in tools. It preserves caller
preferences and backups, checks idempotent setup, waits through the native
`WaitForMcpServers` tool when discovery is pending, and validates the complete
catalog and forwarded input schemas. Call mode loads the personal skill through
native `Skill`, checks its full body and verifies named-schema JavaScript Evidence
for a Unicode path. Use `-- chat` for ordinary chat with REA enabled, or
`REA_VERIFY_RUNTIME_ROOT` for a production-only installed package. The local
Anthropic Messages/SSE fixture preserves native resource-hint envelopes in its
request artifacts. Usage is synthetic; live Anthropic API, native Windows and
bare-mode personal-skill activation remain unverified by this lane.
`verify:copilot-client` requires installed GitHub Copilot CLI (verified with
`@github/copilot@1.0.95`); select it with `REA_VERIFY_COPILOT_COMMAND`.
The optional POSIX lane uses native `COPILOT_HOME` discovery, an independent
Git workspace, guarded setup plans, preserved registrations, backups and
idempotence. Native `skill add` registers the isolated installed skill; call
mode loads its full body, validates all forwarded input schemas and checks
named-schema JavaScript Evidence for a Unicode path. When Copilot spills a
large MCP result, the model requests native `view` with `forceReadLargeFiles`
and validates the complete returned Evidence rather than its preview.
Use `-- chat` for ordinary
chat or `REA_VERIFY_RUNTIME_ROOT` for a production-only installed package.
The native offline BYOK adapter uses a loopback OpenAI completions/SSE fixture
and `gpt-5.4` model metadata; model inference and token usage are synthetic.
Set `REA_VERIFY_COPILOT_MODEL` to examine another client model ID and
`REA_VERIFY_COPILOT_WIRE_MODEL` for its backend model name (defaults to the client
ID). Every actual HTTP request's model is checked and recorded separately.
Both `HOME` and `USERPROFILE` point to the disposable account; native `skill add`
still selects the installed skill directory explicitly.
The same native client passed full-profile chat and analysis with the actual
wire model `gpt-4.1` under a distinct BYOK model ID:
```bash
REA_VERIFY_COPILOT_MODEL=rea-gpt-4.1 REA_VERIFY_COPILOT_WIRE_MODEL=gpt-4.1 npm run verify:copilot-client -- chat
REA_VERIFY_COPILOT_MODEL=rea-gpt-4.1 REA_VERIFY_COPILOT_WIRE_MODEL=gpt-4.1 npm run verify:copilot-client -- call
```
These runs retain full canonical input/output schemas, all tools, installed-skill
loading and complete Evidence readback. They use the fixture's requested
one-million-token BYOK prompt setting; effective capacity and live API acceptance
remain unknown. With the built-in `gpt-4.1` model ID, the verified client still
blocks the full input-schema profile before HTTP with
`compaction_static_context_blocked`, even when requesting a larger BYOK prompt
capacity. The effective capacity is unknown. The default verifier preserves
the complete catalog and full schemas. To verify the existing compact profile:
```bash
REA_VERIFY_COPILOT_MODEL=gpt-4.1 REA_VERIFY_COPILOT_SCHEMA_PROFILE=compact npm run verify:copilot-client -- chat
REA_VERIFY_COPILOT_MODEL=gpt-4.1 REA_VERIFY_COPILOT_SCHEMA_PROFILE=compact npm run verify:copilot-client -- call
```
Both native workflows passed with the complete tool inventory. The verifier selects the
profile only in its disposable Copilot registration and records it in the
receipt. Compact advertisements can reduce nested validation structure; the
server still validates complete canonical inputs. This is a tested alternate
workflow, not a fix for the full-profile client/model limit tracked in #1554.
Live model APIs, native Windows and default OS-home skill discovery remain
unverified.
`verify:grok-client` requires installed Grok Build (verified with the official
Linux x64 1.0.50 binary); select it with `REA_VERIFY_GROK_COMMAND`. This optional
POSIX lane isolates `GROK_HOME`, an independent Git workspace and additional
skill roots, disables foreign configuration discovery, guards setup writes,
preserves unrelated registrations/backups and checks idempotence. Call mode
loads the full skill through native `read_file`, queries all REA names and input
schemas through native `search_tool`, and calls analysis through `use_tool`.
If discovery reports `partial`, the native agent diagnoses REA registration and
retries discovery. No startup-timeout override or fixed readiness delay is used.
A larger Unicode-path fixture exercises native result offloading: the full
retained Evidence is validated against its named schema, then native terminal
queries recover the selected export facts, subject and full artifact digest in
the next model request. This verifies useful artifact recovery without claiming
that every offloaded graph fact enters model context. Native line-number and
truncation envelopes remain in the request artifacts. Use `-- chat` for ordinary
chat, or `REA_VERIFY_RUNTIME_ROOT` for a production-only installed package.
The loopback OpenAI completions/SSE custom model declares a one-million-token
context and synthetic usage. Live xAI APIs, native Windows and default OS-home
skill discovery remain unverified.
`verify:commandcode-client` requires installed Command Code (verified with npm
1.79.2); select it with `REA_VERIFY_COMMANDCODE_COMMAND`. Auth, MCP tokens and
sessions use the actual OS home, so provision a disposable POSIX account rather
than overriding `HOME`. Set `REA_VERIFY_COMMANDCODE_ACCOUNT_HOME` to that account's
actual home and create `.rea-client-verification` there with exactly
`Disposable REA client verification account` followed by a newline. The lane
owns that account's `.commandcode` configuration and shared REA skill. Build the
runtime as the checkout owner, then run `node scripts/verify-commandcode-client.mjs`
as the disposable account; the npm shortcut also needs a writable checkout.
The verifier does not create accounts or install clients. It guards setup
targets, preserves an unrelated registration and backups, checks idempotence,
and verifies native default shared-skill discovery and complete activation.
Default deferred-schema delivery stays enabled: the native prompt advertises
every REA tool, exact-name `search_tools` returns every input schema, and a native
shell query recovers the saved catalog's count and digest when the client spills
it. Actual analysis of a Unicode-path fixture delivers full named-schema Evidence
to the next model request. Use `-- chat` for ordinary chat or
`REA_VERIFY_RUNTIME_ROOT` for a production-only installed package. The loopback
OpenAI completions/SSE model is a keyless BYOK endpoint declaring a million-token
context with synthetic usage. A synthetic account-key value satisfies the
client's print-mode gate; native local-only mode refuses hosted API calls.
Updates, telemetry and cron are disabled. Hosted authentication, live models
and Windows remain unverified.
`verify:omp-client` requires installed OMP (verified with the official Linux x64
18.8.7 binary); select it with `REA_VERIFY_OMP_COMMAND`. This optional POSIX lane
isolates the default agent, global config and XDG roots, guards setup targets,
preserves unrelated registrations and backups, and checks idempotence. It
compares native rejection of an invalid profile with REA's refusal to plan
fallback writes. OMP's default `xd://` interface mounts the complete REA catalog
as devices: call mode reads the complete installed skill and tool documentation,
then dispatches analysis through native `write`. It checks full named-schema
JavaScript Evidence with a Unicode path in the next model request. Device
metadata and documentation are distinct from forwarding all JSON schemas as
model functions. Native print-mode MCP readiness uses its defaults.
Use `-- chat` for ordinary chat or `REA_VERIFY_RUNTIME_ROOT` for a production-only
installed package. The loopback OpenAI completions/SSE model fixture declares a
one-million-token context and synthetic usage. Live model APIs, native Windows,
named-profile native execution and default OS-home skill discovery are
unverified; skill discovery uses an explicit isolated custom directory.
`verify:deepseek-client` requires an installed DeepSeek Harness (`dsh`;
verified with `@deepseek-ai/dsh@0.2.0-rc.2`) and Git. Set
`REA_VERIFY_DEEPSEEK_COMMAND` to select its executable. This optional POSIX lane
installs the skill through `rea setup --skill`, writes the native Cordis MCP
patch into an isolated `DSH_HOME`, and binds `HOME` and `USERPROFILE` to the
disposable account. The native default `~/.agents/skills` search path discovers
the installed skill without a `DSH_AGENTS_HOME` override. A separate Git root prevents inherited project skills from
masking a missing installation. The default `call` mode checks skill loading,
complete catalog discovery, the actual forwarded input schemas and regexes,
and full JavaScript Evidence for a Unicode path. Use `-- chat` for ordinary
chat with REA enabled, or `REA_VERIFY_RUNTIME_ROOT` for an installed package.
The fixture uses Harness's custom OpenAI adapter and the one-million-token
context capacity declared by its default DeepSeek Flash model; it does not
establish live DeepSeek API or native Windows coverage. Receipts include
request artifacts, result digests and owned-process lineage.
Full E2E tests invoke the production command dispatcher and real providers,
without fake launchers, runners or responses. `verify:keyed-archive` writes an
actual Foundation binary archive, runs the CLI and a separate stdio MCP
@@ -113,38 +296,92 @@ covers `trace-dylib-resolution`:
- for the main executable and an XPC service, a predicted load order equal to
the images dyld actually loads under `DYLD_PRINT_LIBRARIES`.
The lane also compiles executable/library pairs with empty embedded directory,
versioned-path, and suffix settings. It checks present and removed dependencies
through CLI and MCP, and compares actual `DYLD_PRINT_SEARCHING` diagnostics for
root-level candidates. These cases distinguish an empty search directory from
an empty versioned scan or a suffix that only repeats the original path.
It runs in macOS CI.
Apple artifact verifiers live in `scripts/verify/apple/`, with the macOS bundle
builder under `scripts/fixtures/apple/` and NIB byte fixtures beside the decoder
in `src/artifacts/apple/`. The npm entrypoints are unchanged. Format-specific
Swift/XIB/asset sources and goldens retain their locations; real Apple workflows
resolve them from the verifier file URL and run in the macOS CI lane.
Portable native semantics and their tests live in `src/domain/native/`; shared
analyst workflows and service-lane tests live in `src/application/native/`.
Named native contracts live in `src/contracts/native/`. Provider protocol and
host UI tests retain their adapter/boundary lanes, and real verifier command
names remain unchanged.
The existing Apple CI job also runs the host Swift-demangling CLI/MCP regression
suites, including option-like symbols, carriage returns and multiline rejection.
Process semantics/tests live in `src/domain/process/`; PTY capture implementation
and forked helper tests live in `src/process/capture/`. Evidence projection and
file workflows live in `src/application/process/`; producer-backed Evidence/host
cases run in the serial `tests/boundary/process/` lane. Installed-package probes
load the compiled capture capability owner, including the missing-optional-module
case. Real capture tests preserve actual descendant and cleanup checks.
The existing Apple job also exercises the relocated filesystem snapshot identity,
cancellation and descriptor cleanup regressions on macOS.
Prepare the native inspector before cases that measure producer output or exit
behavior; keep startup deadlines and cancellation in distinct cases. Run real
process-capture verification separately from package or build checks. On macOS,
new npm processes can become token-unreadable after changing their display
title and prevent verified cleanup during a capture's ownership sweep.
MCP SDK transport tests with recording providers remain integration tests.
They are useful for schema drift and failure projection but do not prove that
Hopper, Ghidra or another substituted engine works. `verify:package` proves
packaging/install behavior and fake-provider integration; use the corresponding
real-provider lanes for engine claims. Real Apple dispatch and Interface
real-provider lanes for engine claims. Packed-bridge checks verify shipped files and Python syntax.
Real Apple dispatch and Interface
Builder verifiers currently prove format integration through production readers.
`verify:hopper` exercises an installed Hopper through the production stdio MCP
server and CLI. It checks source-owned call chains, CFG edges, references and
complete large inventories, then probes unnamed bookmarks, annotation clearing,
batch validation before mutation, malformed addresses and regexes, segment-end
partial reads, and synthetic file-offset rejection. Advertised schemas are
validated in their JSON Schema dialect and successful replies are checked against
their advertised output schemas. Navigation checks cover interior-object cursor
readback and mapped-memory boundaries. Annotation probes verify invalid native
text and duplicate destinations/names before mutation, preserve unselected label
owners, and exercise explicit batch label swaps. Function locals retain observed
names and stack displacements. Graph probes check symbol/interior-address parity
and a source-owned recursive cycle; literal tracing preserves complete queries
and whitespace. Disposable binary copies prove that switching and closing
actually removes the native document, and that CLI byte, function-dossier,
literal-trace results and invalid-address diagnostics agree with MCP.
No provider is mocked in this lane.
Real search probes cover Unicode names, literal metacharacters, case and regex
modes, annotation cache invalidation, complete native fragments of long literals
checked against byte reads, escaped UTF-8/control text, byte-preserving Latin-1
decoding, and Hopper's UTF-16 symbol-name truncation boundary. It verifies native
CallReference classifications across reference and dossier results, retains long
string fragment metadata in dossiers, and exercises pathological regex deadline
and cancellation followed by successful requests in the same native session. When the macOS
Objective-C fixture is present, the lane also verifies native UTF-16 string objects
and their inferred encodings against their actual bytes. Native terminal calls
are checked across reference, instruction, assembly, block-range and procedure-length
projections; block endpoints are normalized using actual native membership.
Exact Objective-C names also exercise named CLI selectors for function, instruction,
decompilation, reference and search operations. A literal `--help` trace query proves
that selector data is preserved independently of global CLI flags.
Unmapped annotation destinations and
oversized later batch names fail before any earlier edit is applied.
`verify:hopper:deadlines` checks the native client's optional request deadlines
on macOS with an owned source-built fixture. Zero and elapsed deadlines must
leave native comments unchanged, including when a synchronous progress observer
delays timer dispatch. It also observes a short analysis deadline and verifies
subsequent wire recovery and clean shutdown. Caller timeout does not interrupt
Hopper's synchronous native operation. Socket boundary tests deterministically
cover active and queued expiry, late replies and timer cleanup.
The Linux demo lane remains a separate `verify:hopper:linux` command. Its
lifecycle checks attempt competing CLI launches for the active target and a
different target, requiring rejection before either can change the owning
MCP session's documents or procedures. Lease boundary tests also preserve
unresponsive or malformed live endpoints while allowing confirmed stale
sockets to recover.
`verify:hopper:fat` is a separate macOS lane requiring installed Hopper and the
existing Xcode clang/lipo toolchain. It compiles arm64/x86-64 thin executables and
one- and two-slice FAT32 containers, verifies exact/interior address mappings
against bytes in the original files, checks CLI/MCP parity, and checks owned
runtime cleanup. Source byte changes, removal, permission denial (for non-root
callers), and nonregular replacement must retain native partial mapping facts,
reject unverified original-file coordinates,
and recover after restoration. Single-slice FAT cases also relocate the slice
without changing its loaded bytes. `verify:hopper:fat64` additionally checks
FAT64 preparation through Hopper's native Mach-O loader, source-container
mappings, profile identity,
malformed and ambiguous slice rejection, and temporary-image lifetime. Both
lanes have been verified on Hopper 6.1.0-demo; this establishes REA's prepared
FAT64 workflow, not native FAT64-loader support.
Cross-architecture fixture compilation is not required by `verify:hopper`.
Golden tests use immutable captured text inputs with producer/source provenance
under `tests/fixtures/golden/`. Expected results are reviewed for the semantic
claim; capture commands do not automatically approve new expected outputs.
@@ -152,11 +389,18 @@ Do not call handcrafted utility output or synthetic binary builders real-data
goldens. Keep unsupported binary layouts and malformed boundaries as targeted
regressions until a real fixture establishes equivalent coverage.
`verify:browser` exercises source-map failure isolation and expanded-output limits through the compiled CLI and stdio MCP with real Chrome. It also submits five 2 MiB source-map annotations, checks retained script identities and explicit map omissions, and closes its owned fixture target. Replacement and document-reset behavior has separate producer-boundary coverage.
`verify:browser` also captures a source-owned noise canvas as a real PNG above
8 MiB through the CLI and stdio MCP, with complete byte/digest parity and real PNG
decoding. Its SDK client explicitly permits the larger inline JSON response;
this lane does not establish large image-comparison request transport coverage.
The scenario checks read locale, timezone, device scale and viewport dimensions
from actual page JavaScript through CLI and stdio MCP DOM captures. They also
verify that attached-page emulation is released after success, initialization
failure, action failure and cancellation while the external target stays open.
`verify:browser:network` is a focused real-browser lane for transaction identity,
selected request/response bytes, binary and compressed responses, duplicate
headers, credential and declared-secret redaction, redirects, streaming cutoff,
@@ -202,12 +446,25 @@ prove behavior on the verified Ghidra 12.1.4 and JDK 21 build.
| Ghidra lane | Supported runner/target | Additional local tools |
| ------------------------------------------ | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| `npm run verify:ghidra` | Linux x64 ELF or macOS x64/arm64 Mach-O | Host C compiler, Ghidra 12.1.4, and full JDK 21 |
| `npm run verify:ghidra` | Linux x64/arm64 ELF or macOS x64/arm64 Mach-O | Host C compiler, Ghidra 12.1.4, and full JDK 21 |
| `npm run verify:ghidra:swift` | macOS x64/arm64 Mach-O | Host Swift compiler, Ghidra 12.1.4, and full JDK 21 |
| `npm run verify:ghidra:switch` | Linux x64 ELF; GCC/Clang optimized and stripped switch fixtures | GCC, Clang, GNU nm/objdump/strip, Ghidra 12.1.4, and full JDK 21 |
| `npm run verify:ghidra:aarch64-jump-table` | Any supported Ghidra host; AArch64 ELF; byte/halfword tables; host ARM64 Mach-O | Clang with AArch64 target support, Ghidra 12.1.4, and full JDK 21 |
| `npm run verify:ghidra:cross-format` | Any supported Ghidra host; also analyzes AArch64 ELF, x86-64 PE, and x86-64 Mach-O | `clang`, LLD, and `lld-link` in addition to host-lane prerequisites |
| `npm run verify:ghidra:windows` | Controlled Windows x64 with native x86-64 PE; `-- --x86` selects native x86 PE | Ghidra 12.1.4, full JDK 21, and the matching native artifact |
The optional Swift lane compiles a source-owned fixture and checks modern and
provider-demangled procedure names through real stdio MCP, with and without the
dSYM companion. It checks unfiltered, structs, and literal-name filters,
same-address alias evidence, deduplication, and explicit unresolved categories.
It does not add a Swift prerequisite to the host C fixture lane.
The host lane also verifies namespaced C++ ABI symbols and annotation identity.
That facet requires Ghidra's matching `demangler_gnu_v2_41` native component in
`GPL/DemanglerGnu/os/<platform>/` or `build/os/<platform>/`, in addition to the
native decompiler. The namespace verifier reports missing or non-executable
components before testing the fixture. REA does not build or install them.
Windows native conformance runs with `npm run verify:windows-native` and does
not require Ghidra or Java. An optional independently compiled Windows fixture
adds in-place reparse, breakaway, environment, and token observations.
@@ -219,6 +476,67 @@ The host-native Ghidra lane also verifies native value tracing through the
production CLI and a separate stdio MCP process. It compares complete dependency
graphs, validates Evidence and upstream/workflow profiles, checks capability
discovery, and closes the MCP session. No provider or transport is mocked.
It also validates every advertised input/output JSON Schema and the exercised
MCP outputs, probes address spelling and name/address ambiguity, and checks
direct versus targetless calls, byte-read completeness, invalid input diagnostics,
CLI/MCP parity, atomic annotation rollback, refreshed inventories, unchanged
executable bytes, and discarded edits after reopen. A deliberately long temporary
path exercises private Unix socket allocation and cleanup, including cancellation
after a real headless process launches. Native annotation probes reject NUL and
unpaired Unicode surrogates without partial edits or a broken bridge, preserve
supported Unicode and control text, and check lossless malformed-text diagnostics.
Memory-to-file mapping is checked against original artifact bytes.
The fixture also stores a pointer one byte past a function entry; exact
xrefs, raw procedure references, and CLI/MCP dossiers must retain that data edge.
A valid legacy snapshot reconstructs the former omitted edge under its older
profile; CLI and MCP must reject that binding with a mismatch reason and
recovery advice. The rejected open must preserve the active live session.
Exact external entries must resolve while retaining an empty body; unknown
external addresses remain unresolved and external annotations are rejected.
An adversarial regex over a full 12 KB literal must report stack exhaustion as
a resource constraint, preserve live annotations, and allow complete literal
searches afterward; CLI and MCP must agree on both results and recovery advice.
Real snapshot lifecycle checks retain edited API results as Evidence while
rejecting immutable snapshot saves and imports before and after a repeated
open of the same target. They verify unchanged live annotations and run identity,
absent rejected output files, an unchanged source snapshot, and successful
snapshot import/save after closing and recreating the database. The pristine
snapshot is written by an independent real CLI session.
They also start a real annotation and snapshot close concurrently: the edit
must succeed, the snapshot must be rejected without creating a file, and the
edited session must remain usable until explicitly closed.
Source-admission probes change a caller-owned fixture after `open_binary` but
before the first Ghidra query. They require an actionable `artifact_changed`
error preserving both digests and the selected path, unchanged provider
availability, failed-copy cleanup, and successful recovery after reopening.
After import, deleting that source must preserve the captured database identity.
Instruction inspection and containing-function lookup also agree across
hexadecimal case, leading zeros, and encoded default address-space spellings.
The same source-acquisition workflow exercises missing and directory-replaced
inputs, plus real read-permission denial on a non-root host. Root runs report
that permission-denial check as unverified. Filesystem integration separately checks selected-platform routing and exclusive creation.
Namespace annotation probes compile a separate host C fixture with C++ ABI
symbols, avoiding a C++ runtime prerequisite. Real Ghidra demangling supplies
duplicate leaf names in two top-level namespaces and a nested namespace. The
workflow verifies leaf and qualified renames, repeated reuse of fully qualified
readback, lookup by the returned name, literal namespace-like leaf names,
rejection of empty qualified leaf names without changing comments, CLI
behavior, and independent CLI/MCP database ownership.
Large-result probes compile initialized host-native data sized from the pinned
MCP SDK receive budget. Real byte reads, annotation edits and function dossiers
exceed that budget while preserving the connection and active analysis run.
Successful-result and oversized-error delivery constraints must identify their
successfully retained Evidence records;
export must recover every source byte, complete annotation and original error
diagnostic, with CLI parity
and an unchanged executable. Formatter integration separately checks unacknowledged Evidence recording.
Long ordinary procedure names and encoded address-space selectors must produce
normal validation errors without exhausting Java's regex stack or losing the
private bridge connection. Each rejection is followed by a real provider lookup;
address-like literal names still resolve exactly after annotation.
Malformed annotation readback, memory completeness, and inventory data remain separate
SDK/provider integration cases; success from a real
provider cannot establish rejection of a contradictory provider response.
The Linux switch lane checks dense, sparse-with-holes, shared-body, nonzero,
negative, and nonexact JSON integer labels plus a comparison-only control.
@@ -251,17 +569,19 @@ the CLI and stdio MCP, including special filenames, unresolved discovery
locations, and independently resolved loaded scripts. Double-quote filenames
are tested on POSIX only because Windows does not support them.
Inspector adapters live in `src/inspector/`, with loopback fixtures under
`tests/fixtures/inspector/` and forked producer boundaries under
`tests/boundary/inspector/`. The real lane is owned by
`scripts/verify/inspector/runtime-observation.mjs` and
`tests/conformance/inspector/`. Browser and Inspector deliberately share the
existing browser CDP transport/value and file-location helpers. Node fixture
success proves this Inspector workflow on the tested host; it does not prove
Electron GUI behavior or another engine.
Node Inspector verification does not establish Electron GUI or other engine
behavior. Browser and Inspector share CDP transport/value and file-location
helpers; their producer workflows remain distinct.
## Android APK analysis
The real Android lane also runs on Windows x64 with its matching bundled native
controls. It verifies bidirectional protocol input, CLI/MCP result parity,
real MCP cancellation/disconnect and Java exit after abrupt CLI owner
termination. The forced Windows exit does not exercise the POSIX SIGTERM
handler and can leave temporary workspace files. `verify:windows-native`
separately checks binary input, backpressure, EOF and pending-write job closure.
`npm run verify:android` requires an existing Java 17+ and an explicit
`REA_JADX_MCP_JAR` for jadx-headless-mcp 0.7.1. Set `REA_ANDROID_TEST_APK` to the
fixed public ApiDemos v6.0.18 fixture. Obtain both with the explicit
@@ -270,23 +590,79 @@ kept under ignored `_reference/`. No Gradle build, Android SDK, emulator or
application execution is required. The lane compares real CLI/MCP package,
class search, class inventory, method decompilation and incoming references.
See [Android analysis](android-analysis.md) for boundaries and resource budgets.
`verify:jeb` requires a caller-started JEB client serving MCP at
`REA_JEB_MCP_URL` (default `http://127.0.0.1:8425/mcp`) with a project
already open, and verifies real CLI client inspection, unit listing coverage,
and method decompilation. The script records the engine's exact response to
`open_jeb_project`; JEB 5.48.0 headless instances do not advertise that tool.
REA does not install or launch JEB; see [JEB analysis](jeb-analysis.md) for
the bring-your-own boundary. Verified against JEB 5.48.0 serving
`jeb-mcp-server` 1.3.0 at four scales: a compiled Java class fixture, a
locally built signed probe APK with a launcher activity (manifest, v1/v2/v3
certificates, dex bytecode, filtered and paginated listing), the published
Signal 8.30.3 universal release APK (109 MB, R8-processed Kotlin/Compose,
four signature schemes, native arm64 ELF units) with MainActivity method
decompilation through both CLI and MCP, and the official Flutter Gallery
2.9.2 release APK (112 MB): per-ABI `libapp.so` Dart AOT snapshot images
analyzed as native code (75k methods on arm64) and decompiled through both
CLI and MCP with explicit unit selection, plus the thin Java wrapper and
decoded manifest. The dedicated Dart snapshot processor and `run_script`
remain GUI-only surfaces in JEB 5.48.0 headless.
Authenticated IPA and macOS application inventory projection is documented in
[Apple application analysis](apple-application-analysis.md).
The lane and owned-process cancellation helper live in `scripts/verify/android/`.
The explicit downloader and fixed manifest live in `scripts/fixtures/android/`;
their default remains repository-root `_reference/apk-integration/`. Producer
fixtures live in `tests/fixtures/android/`, boundary cases in
`tests/boundary/android/`, and inventory projection composition cases in
`tests/composition/android/`. Real engine success and synthetic protocol success
are separate proof levels.
Synthetic producer regressions run independently:
```sh
npm run test:focused -- tests/boundary/android/jadxIntegration.test.ts tests/boundary/mcp/androidAnalysisMcp.test.ts
npm run test:focused -- tests/boundary/process/jadxIntegration.test.ts tests/boundary/process/androidAnalysisMcp.test.ts
```
## Apktool resource decoding
`npm run verify:apktool -- --apk PATH` exercises both Apktool operations
against a real launcher (`REA_APKTOOL_COMMAND` or PATH) and one APK. No
download or build step is involved. Record: apktool 2.7.0-dirty (Debian
packaging) on Linux with OpenJDK 25, against a signed aapt2-built probe APK
carrying two resource locales — launcher version, on-disk digest agreement
with the reported target identity, apktool.yml metadata projection
(1.2.3, SDK 24–34), manifest package agreement, and both the default and
`de` string tables projected through the locale option. Parser goldens in
`src/apktool/ApktoolDecodeOutput.test.ts` come from the same decode. See
[Apktool resource analysis](apktool-resource-analysis.md) for boundaries and
budgets.
## ADB device acquisition
`npm run verify:adb` exercises every ADB operation against a live device or
emulator through the caller's adb binary (`REA_ADB_PATH` or PATH). No SDK
installation or emulator management is involved; the device-mutating tools
run only in the explicit lifecycle section (`--install-apk` drives a
lane-owned install → resolve → start → observe → force-stop → uninstall
probe). `--pull` acquires a real package and re-digests the pulled files on
disk against the returned SHA-256 values; `--serial` selects a device when
several are attached.
Record: adb 34.0.5-debian on Linux against an Android 14 (API 34) x86_64
emulator. The lane covered the complete observation surface — 337-process
listing, 287 binder services including AIDL `/`-suffixed names, 92 features
including hex GL versions, display size/density, window focus (legitimately
null on headless devices), `settings get global adb_enabled`, bounded
logcat, directory listings — plus a real two-APK split set
(`base.apk` plus `split_probe.apk`, built and installed through
`install-multiple`) pulled with byte-exact digests, a push/pull roundtrip
verified by the device's own sha256sum, a 1.3 MB screen capture with PNG
dimensions, `dumpsys package` projection, and the full lifecycle: unique
resolution before launch, launcher-activity start through
`cmd package resolve-activity` with `am start -W`, the started app visible
in the process listing, force-stop, uninstall, and zero matches after
removal. System-package pulls whose APKs keep non-`base.apk` names report
the `unknown` role with the file-name basis, verified with
`com.android.settings` (single 73.9 MB APK). Parser goldens for
`adb devices -l`, `getprop`, `pm list packages -f`, and `pm path` come from
the same device. See [ADB device analysis](adb-device-analysis.md) for
boundaries and budgets.
## Optional NativeAOT Ghidra analysis
This lane is separate from the default native lane. `build:fixtures:nativeaot`
@@ -356,22 +732,27 @@ a DOS emulator or compiler, then checks real 16-bit decoding, segment
relocation, near/far calls, decompilation, disjoint function body ranges,
stable CLI/MCP observations, unchanged source bytes, and owned process/project
cleanup. Raw p-code address-space selector tokens are reported separately from
the stable observation comparison. Linux x64 is verified; macOS DOS remains
unverified. This lane is separate from host-native and optional cross-format
the stable observation comparison. Linux x64 and macOS arm64 are verified;
macOS x64 remains unverified. This lane is separate from host-native and optional cross-format
verification. See [DOS analysis](ghidra-dos.md).
`npm run verify:ghidra:com` uses a generated headerless fixture with no compiler,
DOS emulator or game data. It exercises explicit admission, BinaryLoader entry
preparation, measured register context, whole-file byte readback, source offsets,
unmapped PSP/partial reads, actual decompilation, CLI/MCP parity and owned cleanup.
Both segmented-address lanes reject oversized default, explicit-space and encoded-space
coordinates through real reads, function queries and annotation attempts. Rejected
annotations must preserve the live function dossier; CLI and MCP must report the
truncation constraint, while leading-zero coordinates still resolve correctly.
It has the same Ghidra/JDK prerequisites as the MZ lane. Neither lane claims DOS
runtime or PC-98 device execution.
## Apple Interface Builder archives
`npm run verify:interface-builder` compiles the source-owned AppKit XIB into a
real `.nib` with Xcode `ibtool`, wraps it in a temporary app bundle, and checks
the decoded view hierarchy, outlet, action, evidence coverage, and truncation
real `.nib` with Xcode `ibtool`, wraps it in a temporary app bundle, and runs
the compiled CLI and stdio MCP server with production providers. It compares
their decoded results and checks the view hierarchy, outlet, action, evidence coverage, and truncation
status. Storyboard compilation additionally requires an installed iOS platform.
Keep the provider-specific acceptance path independent from optional
@@ -380,6 +761,17 @@ not make native host acceptance unavailable.
## Native platform baseline in CI
Pull requests that change only root `README*.md` files, `docs/`, `AGENTS.md`,
or `CONTRIBUTING.md` run formatting and generated-document validation without
the source-test shards or native package lanes. Classification compares the PR
head with its merge base, so later base-branch changes do not expand that scope.
The required static and coverage aggregate jobs remain present and fail if
classification fails. Mixed changes, unknown paths and CI configuration changes
retain full checks. Main pushes retain the full baseline, including after
documentation merges; newer commits cancel superseded CI for the same PR or
main branch. Release publication has its own concurrency group and retains its
package verification and public-registry canary.
CI exercises the pinned Node.js runtime on native hosted runners:
| Host | Runner | Baseline checks |
@@ -390,18 +782,14 @@ CI exercises the pinned Node.js runtime on native hosted runners:
| macOS 15 x64 | `macos-15-intel` | Installed package and real Node Inspector CLI/MCP |
| Windows x64 | `windows-latest` | Curated capabilities, native controls, installed package and real Node Inspector CLI/MCP |
Package and Inspector matrices assert the actual Node platform/architecture
before verification and record those values with the Node version. Each matrix
Package lanes assert the actual Node platform/architecture before verification
and record those values with the Node version. The four-host package matrix
runs at most two jobs concurrently with explicit timeouts and Node heap/thread
limits. Package checks cover installation, CLI/MCP discovery, target-free
limits; Windows retains its curated capability lane. Package checks cover
installation, CLI/MCP discovery, target-free
analysis, configuration backups/recovery, Evidence and owned lifecycle; Inspector
checks execute source-owned loopback targets and special filename cases.
macOS uses one OS version with one native baseline job per architecture. Each job
runs package and Inspector checks after a single dependency installation. The
separate Inspector matrix covers Linux and Windows; Apple artifact checks retain
their own macOS 15 arm64 job for Xcode-dependent workflows.
These native baseline checks complement the Linux source-test shards and the
separate Apple-artifact and real-provider lanes. Actual Hopper, Ghidra, IDA,
browser and managed-tool claims require their corresponding verification lanes.
@@ -446,6 +834,17 @@ The dry-run option reports the chosen merge base, scope and build prerequisite
without executing tests or building. A missing Git base reports how to fetch
it or select another revision.
Source typechecking needs no compiled runtime or generated test metadata.
`npm run build:cached` compiles the CLI/MCP runtime and its packaged skill.
`npm run test:prepare` also generates the MCP contract test catalog, product
catalog, and portable managed evidence used by the complete suite. Focused
tests prepare those extra outputs only when their selected files consume them.
The MCP test catalog is JSON in `.cache/mcp-tool-catalog.json`; the tracked
test loader supplies its types without making generation a source-check
prerequisite. Run `npm run mcp-catalog:generate` to refresh it independently.
Documentation generation and managed conformance run through their separate
`docs:generate` and `evidence:generate` task graphs.
Changed selection can miss runtime registration, generated data, shell
entrypoints, bridges, or other relationships absent from the import graph.
An empty changed selection means no tests were selected, not verified
@@ -460,21 +859,15 @@ broad changes or diagnosing CI, rather than after every edit. Package/install
changes additionally need package verification; provider changes need actual
provider evidence.
Each Vitest project uses up to two workers, bounded by available host parallelism.
Default-group projects can run together. Only `process-boundary` runs in the
later sequence group and serializes its files because process-tree observations
share host sampling resources. Acceptance and process-global files retain isolated
forks but are not serialized; isolation does not imply serial scheduling. CI uses
the same per-project worker bound.
The pure domain/contracts and recording-port service projects share one worker
module context because their tests own no mutable runtime resources. MCP
boundary files also share the immutable server module graph while creating and
closing independent in-memory sessions. Adapter, composition, acceptance,
process-global, and other boundary projects retain per-file isolation.
Build and documentation writers use checkout-local locks for their respective
output files. `npm test` delegates its build to the build lock; the Vitest suite
does not hold a test-command lock. `check:pr` runs its test task before starting
generated-document validation.
Vitest projects use up to two workers, bounded by host parallelism.
`process-boundary` runs later with serial files because process-tree sampling
shares host resources. Acceptance and process-global cases use isolated forks
without serial scheduling. Pure domain/service and MCP boundary projects share
immutable module graphs; each MCP session still owns its resources. Other
projects retain per-file isolation. See `vitest.config.ts` for current settings.
Build/documentation writers hold checkout-local output locks. Tests do not
hold a broad command lock; `check:pr` finishes tests before document validation.
Vitest and Node persistent compile caches are deliberately not enabled by
default. To evaluate repeated local runs, opt in for both cold and warm
@@ -490,13 +883,9 @@ instrumentation remains equivalent.
## Coverage and timing
CI owns coverage. The aggregate floors are 65% statements, 60% branches, 60%
functions, and 68% lines. `src/domain/**` must reach 80% statements, 75%
branches, 75% functions, and 80% lines. `src/contracts/**` must reach 85%
statements, 80% branches, 80% functions, and 85% lines. Thresholds are
glob-specific rather than per-file and are never updated automatically.
Coverage does not replace named boundary, acceptance, or real-provider scenario
matrices.
CI owns coverage; aggregate and domain/contract thresholds are maintained in
`vitest.config.ts`. They are glob-specific and never updated automatically.
Coverage does not replace named boundary or real-provider scenarios.
CI runs four native Vitest shards without retries. Each shard emits a blob
report; the merge job produces aggregate coverage plus JUnit and JSON timing
@@ -532,24 +921,36 @@ conformance/vtable fixture.
Both commands reject a changed executable digest and clean up the fixture
process and helper. These lanes require an interactive macOS desktop. See [native investigation](native-investigation.md)
`npm run verify:native-calls` needs only macOS with Command Line Tools (`clang`,
`lldb`, `codesign`, `nm`). It compiles `tests/conformance/native/calls.m` and
`npm run verify:native-calls` needs macOS with Command Line Tools (`clang`,
`lldb`, `codesign`, `nm`) and actual debugger access to the owned fixtures.
The lane reports Developer Mode status without treating it as proof of access
or denial, and does not change host settings. LLDB and target entitlements
establish the tested permission boundary.
It compiles `tests/conformance/native/calls.m` and
runs `observe-native-calls` through the CLI and stdio MCP. It checks:
- the receiver class, selector and argument registers of every entry, and that
breakpoint addresses equal `nm`'s symbol addresses;
- captured stdout and an environment override;
- overlapping breakpoint selections retain each selection's hits and share
the aggregate event limit; callback capture reads the stopped frame before
LLDB resumes, avoiding stale frame metadata from asynchronous stop events;
- captured stdout and an environment override, plus a 2 MiB flood on each
output stream with bounded retained prefixes and exact drained-byte counts;
- the event-limit and duration outcomes, with the process confirmed gone;
- that a hardened-runtime copy is refused with `debugger-attach-denied`, and
that the same copy signed with `get-task-allow` is traced.
for the exact ABI, authority, graph and observation boundaries.
### Firmware adapters
Linux-owned provider launches require a procps-compatible `ps` on REA's `PATH`
so ownership can be inspected before launching a child. A missing or incompatible
command fails with an actionable capability error before the launch.
`npm run fixtures:firmware` uses existing Python 3 and a host C compiler to make
an ignored gzip/USTAR firmware fixture and independent offset/hash oracle.
`npm run verify:firmware` requires caller-supplied Binwalk 3.1.0, Unblob 26.6.4
and util-linux prlimit on Linux. The provider also accepts other 3.1.x and
and util-linux prlimit on Linux, with `7z` on `PATH` for the gzip/USTAR
fixture's Unblob extractor. The provider also accepts other 3.1.x and
26.6.x builds and reports them as unverified; this lane proves the audited
releases. It verifies CLI/MCP parity, selected ranges,
unknown chunks, depth limits and extracted child digests. The optional
@@ -558,22 +959,18 @@ unknown chunks, depth limits and extracted child digests. The optional
Neither optional toolchain is a base-lane prerequisite. See
[firmware analysis](firmware-analysis.md) for limits and unverified formats.
The real entrypoint is `scripts/verify/firmware/analysis.mjs`; the fixture runner
and unchanged Python producer belong together in `scripts/fixtures/firmware/`.
Producer fixtures and boundaries remain in `tests/fixtures/firmware/` and
`tests/boundary/firmware/`. Source-fixture generation proves the runner and
independent oracle; actual Binwalk/Unblob CLI/MCP proof requires selected tools.
### JavaScript source recovery
Build once with `npm run build:cached`, then run `npm run verify:javascript:recovery`.
This focused lane requires Linux x64, util-linux `prlimit`,
`REA_WAKARU_COMMAND` pointing to the official Wakaru 1.13.0 Linux x64 binary,
`REA_WAKARU_COMMAND` pointing to the official Wakaru 1.14.0 Linux x64 binary,
and `REA_JAVASCRIPT_FIXTURE_TOOLS` pointing to an isolated npm prefix containing
esbuild 0.25.10 and webpack 5.101.3. No global installation is required.
The lane compiles source-owned fixtures, exercises CLI and stdio MCP, verifies
published bytes and provenance, feeds recovered modules into existing analysis,
and compares a finite set of known fixture results. It does not establish
and compares a finite set of known fixture results. The provider also accepts
other ^1.13.0 releases and reports them as unverified; this lane proves the
audited release. It does not establish
arbitrary recovered-application equivalence. CI installs these prerequisites only
in `.github/workflows/real-javascript-recovery.yml`; the existing `real-browser`
lane uses real Chrome for browser capture and website workflows.
@@ -686,8 +1083,97 @@ real local Codex CLI with:
npm run verify:agent
```
Its report records tool selection, repeated calls, token use, completion quality,
and handling of permissions and unknowns.
The lane runs scenarios sequentially in standalone Codex (`--no-daemon`) with a
disposable HOME and CODEX_HOME under `~/.cache/rea-agent-evaluations/`. Set
`REA_AGENT_EVAL_ROOT` to choose another parent directory outside the OS temporary
directory: current Codex refuses helper aliases under `/tmp`, preventing shell
commands and skill reads even if MCP works. Each owned run directory is removed
after verification unless fixture retention is requested. The lane
installs the packaged skill and MCP registration through public `rea setup`,
rather than copying a skill into a project that also inherits the caller's
skills and configuration. Only authentication is copied, when present, and it
is removed even with `REA_AGENT_EVAL_KEEP_FIXTURES=true`. No user configuration,
rules, plugins or history is copied; shell snapshots and additional agents are
disabled. Existing API-key environment authentication remains available.
The native missing-provider scenario preapproves only `open_binary` and
`close_binary` in the disposable client so it reaches REA's actual provider
boundary instead of stopping at Codex approval. This does not validate a real
native engine or authorize arbitrary runtime execution.
Select a smaller run with `REA_AGENT_EVAL_SCENARIOS`, a comma-separated list of
scenario IDs. `asar-zh` exercises the packaged desktop rubric from a Chinese
request. `javascript-module-view` exercises summary analysis, module paging and
item inspection in a tree with unrelated modules; its routing and text checks
remain heuristic, so review the retained transcript for selector choice and
coverage claims. Set `REA_CODEX_CLI` to an installed Codex executable and
`REA_AGENT_EVAL_MODEL` to an account-supported model. Use an external resource
limit for the whole process tree when testing on a constrained host; a Node
heap limit alone does not bound client and child-process memory.
`missing-target` leaves desktop fixtures visible without selecting one in the
request. It requires zero REA calls and a structured request for an app name or
artifact path. Its `expectedFirstTool` is `null`, and
`targetClarificationPassed` grades that limited routing outcome independently
of analysis prose heuristics. Analyzing a nearby example cannot pass this case.
The packaged desktop and parser-comparison scenarios now assess a closed set of
known fixture claims. Each final answer must be a strict JSON manifest containing
exactly the requested claim IDs, values, Evidence IDs, and Evidence authority and
confidence. Golden values are not included in the prompt. The evaluator checks
exact values against both the fixture oracle and authenticated successful REA
results; an Evidence ID by itself is insufficient. Missing, duplicate, extra,
contradictory, incorrectly sourced, or unsupported claims fail the scenario.
The desktop rubric covers the exposed bridge API and members, renderer and main
IPC operations, and the resolved preload. It binds its Evidence to the exact
packaged artifact path and SHA-256. The parser rubric checks the precise heading
depth addition, discriminant, complete comparison counts, and the explicit limit
on runtime semantics. Its comparison must link to the two delivered source
analyses and use the requested module and export selectors. Boundary tests package
the same source-owned desktop fixture and compare the same source-owned parser
files through actual MCP tool results, then verify that fabricated answers fail.
Per-scenario `factualCorrectness` is `passed`, `failed`, or `not_assessed` within
the `configured_fixture_claims` scope. A pass establishes only the configured
claims, not unrestricted factual correctness. Native, managed, browser,
navigation-context, and address-context scenarios have no factual rubric and
remain `not_assessed`; the managed workflow requires both artifact and member
inspection to answer its type and entry-point question.
The closed factual scenarios request complete producer Evidence on the initial
analysis so their source selectors can authenticate all configured facts.
Summary/page/item workflows are exercised separately by `javascript-module-view`;
its heuristic gate does not establish full-producer factual correctness.
All scenarios retain routing, workflow, validation, repetition, process-exit,
and token-use gates. Configured factual scenarios additionally require a factual
pass. Their answer-text heuristics are diagnostic and do not affect the gate.
Validation counts include complete text-only REA `invalid_request` envelopes
and failed SDK calls whose arguments violate the named current REA contract.
Client approval rejections and provider unavailability remain distinct failures;
truncated JSON previews are not parsed into invented error codes.
Repeated `binary_session` observations separated by a successful `open_binary`
or `close_binary` are treated as lifecycle verification. An unchanged retry,
including one after a failed lifecycle call, still counts as repetition.
Scenarios without a rubric retain the legacy text-heuristic gate.
`answerTermCoverageMet` checks case-insensitive substrings,
`epistemicCuePresent` checks keywords, and `finalCitesEvidence` checks only an ID's
presence. These metrics can still accept fabricated prose and must not be read
as factual assessments. Set `REA_AGENT_EVAL_TRANSCRIPT_DIR` to retain complete
tool results and final answers for review.
Report schema version 4 adds negative routing scenarios with nullable
`expectedFirstTool` and a `targetClarificationPassed` outcome. Consumers must
allow an expected absence of REA calls; this does not make an analysis scenario
pass without its required tools. Version 3 changed the top-level
`factualCorrectness` from a constant
string to an assessment summary with status, scope, and assessed/passed/failed/
not-assessed scenario counts. Scenario records include the factual assessment and
configured claim IDs. The evaluation scope is
`routing_workflow_and_configured_fixture_claims`. Update report consumers for
these changes. The narrower heuristic field names introduced in version 2 remain:
`answerHeuristicsMet`, `epistemicCuePresent`, `answerTermCoverageMet`, and
`requiredAnswerTermGroups`.
Regenerate the managed conformance manifest and Evidence completion ledger from
live verification results, or check them for drift:
+75 -94
View File
@@ -1,106 +1,87 @@
# MCP tool design
Design tools around analyst tasks. A provider API is an implementation detail;
expose it directly when it gives agents a useful, reusable capability that
cannot be expressed through an existing contract. Do not impose caller-facing
limits merely to make work fit an assumed agent budget. Keep real input-format,
protocol, authority, and resource-safety constraints, and report their effects.
## Choose the tool shape
| Shape | Use it for | Contract should return |
| --------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `inspect` | Facts about one explicit target, address, object, or resource | Relevant fields, source locations, and facet-level availability |
| `search` / `list` | Finding candidate targets or entities | Stable ordering and useful result context; expose pagination when the result format or caller's query needs it |
| `trace` | Relationships across code, metadata, UI resources, or observations | Typed edges, supporting evidence, and unresolved paths; identify any genuine traversal boundary |
| `compare` | Two explicitly identified artifacts, versions, or evidence sets | Paired identity, comparable coverage, and deltas with evidence |
| `workflow` | A distinct analyst outcome that benefits from composition inside REA | A useful inline result, contributing evidence, and partial/unavailable facets |
| `observe` / `capture` | A question that requires runtime behavior | Required authority, launch/attach behavior, real operational constraints, lifecycle, and cleanup status |
These are task shapes, not required prefixes. Name a tool for the action and
object agents reason about; keep the name distinct from nearby alternatives.
## Prefer primitives; compose workflows
Start with a primitive when one call can report a reusable fact about one
identified object or relationship, such as an instruction decode, a type
layout, a reference, a dispatch target, or a resource graph. The same primitive
should be useful across different applications or analyst questions. A
format-specific decoder can still be a primitive when it describes a reusable
format rather than one application's product behavior.
Add a workflow when repeated analysis shows that callers need the same
multi-source result and REA can join the evidence without hiding important
choices or uncertainty. A useful check is whether the workflow remains
meaningful for different applications that share the relevant evidence types.
If its purpose depends on one application's business rules or product concepts,
keep that interpretation outside the general tool contract and expose the
underlying evidence through reusable primitives.
## Decide whether to add a tool
1. State the user intent and the smallest result that answers it.
2. Inspect the canonical tool contracts, current provider capabilities, and
representative CLI/MCP traces. Record the nearest competing tool.
3. Extend an existing contract when the intent and result are the same. Add a
batch or composed workflow when it materially improves a demonstrated task;
do not force agents through extra calls or collapse distinct tasks into one
tool. Add a tool when it answers a distinct analyst question or has a
materially different authority or result contract.
4. Keep public tool names and result semantics provider-neutral. Put engine-
specific parsing and protocol handling in adapters. Advertise exact support
per provider; do not create parallel tools just because engines differ.
5. Keep prompts optional and concise. They may point out useful tools, but must
not prescribe a call sequence when the task can be answered directly.
Design around the analyst question. Inspect the current canonical contracts,
provider capabilities, and nearest existing tool before changing the surface.
Extend a tool when intent and result contract match; add one for a distinct
outcome or materially different authority. Public names and semantics remain
provider-neutral, with exact coverage reported per provider.
Avoid opaque mode flags and mega-tools that combine unrelated discovery,
execution, and mutation. Prefer a useful direct tool call over a tool sequence
or model-authored loop when one call can answer the question.
Keep the catalog complete; report capability/session availability instead of
truncating schemas. Serialized bytes alone do not establish agent usability.
## Choose the tool shape
| Shape | Use it for | Result |
| --------------------- | ------------------------------------------- | ------------------------------------------------------------------------- |
| `inspect` | Facts about one target, object, or resource | Relevant fields, locations, and facet availability |
| `search` / `list` | Candidate discovery | Stable ordering and context; pagination when the query or format needs it |
| `trace` | Relationships across evidence | Typed edges, supporting facts, and unresolved paths |
| `compare` | Explicitly paired artifacts or observations | Identity, comparable coverage, and supported deltas |
| `workflow` | A recurring outcome needing composition | Inline answer, contributing evidence, and partial facets |
| `observe` / `capture` | Runtime behavior | Authority, launch/attach effects, lifecycle, and cleanup status |
These are task shapes, not mandatory prefixes. Name tools for the action and
object callers reason about. Avoid unrelated discovery/execution/mutation modes
inside one tool.
## Prefer primitives; compose workflows
A primitive reports a reusable fact about an identified object or relationship.
A format-specific decoder qualifies; one application's business interpretation
belongs outside the general contract. Expose provider APIs when they add a
useful capability that existing tools cannot express.
Compose a workflow when repeated use demonstrates a multi-source outcome REA
can join without hiding caller choices or uncertainty. Batch homogeneous reads
when that removes repeated work while preserving per-item outcomes. Keep prompts
optional and avoid prescribing call sequences that a direct tool can replace.
Agents can compose experiments with ordinary commands, scripts, and local
fixture servers. Custom orchestration languages, replay engines, or separate
prepare/execute plans need an observed requirement those primitives cannot
satisfy. A plan without execution does not establish runtime behavior.
## Define the contract
- Use strict object inputs with explicit required fields and enums. Add numeric
bounds only when the format, protocol, authority, or a measured resource
constraint requires them.
- Return complete results by default. Make real pagination, truncation, partial
failure, cancellation, and unavailable states explicit. Missing evidence is
unknown, not empty or false.
- Return task-oriented results inline with artifact identity, provider/version,
addresses or resource paths, Evidence references, confidence, and relevant
limitations. Do not require agents to fetch a resource or dereference an
opaque Evidence link to understand a tool result.
- Separate observed facts from derived and inferred edges. Cite the evidence
supporting every important relationship; preserve unresolved edges.
- Declare read-only, mutation, process, filesystem, network, and UI effects
truthfully in the contract and enforce the target and lifecycle named in the
request.
- Keep provider-specific types out of provider-neutral domain and application
layers. Normalize supported provider results without implying equal coverage.
- Use strict inputs with explicit target identity and required fields. Preserve
meaningful target, action, capture, and output choices; remove ignored options
and repeated permission declarations.
- Return complete evidence inline, with artifact/provider identity, source
locations, Evidence references, and relevant confidence and limitations.
Missing coverage is unknown, not absence. Avoid extra lookups solely to
understand the answer or its provenance.
- Keep observed, derived, and inferred relationships distinct. Preserve
unresolved edges and partial provider facts instead of requiring every
provider to supply the same metadata.
- Declare process, filesystem, network, UI, and mutation effects truthfully;
enforce the requested target and lifecycle.
- Add limits only for real format, protocol, authority, or measured resource
constraints. Report pagination, truncation, cancellation, and partial failure.
An assumed agent budget is insufficient justification for a limit.
## Implement and evaluate
- Put shared user workflows in the application layer; keep MCP translation in
the server adapter and CLI behavior aligned with the same workflow. Share
Evidence provenance, unknown projection, and eligible snapshot binding through
application/session owners. Matching result payloads alone do not establish
equivalent retention or replay behavior.
- Derive each facet's coverage from examined records, unsupported representations,
and exhaustiveness. Keep issues structured until presentation; do not select a
facet by matching diagnostic prose or infer completeness from an empty failure
list. Preserve available observations independently of cleanup success.
- Measure the resource consumed before choosing a limit. Value alternatives,
retained records, trace-frame products, output bytes, and temporary-file growth
need different accounting. Enforce a justified budget before the costly step
and report its effect; an input-byte or graph-node cap does not bound every stage.
- Update the canonical contract inventory, output schemas, examples, generated
catalog, and relevant docs together.
- Verify valid, malformed, boundary, unavailable, cancellation, and partial
results at the owning boundaries. Use real-provider checks for claims that
depend on external analysis engines.
- Evaluate representative broad and direct task prompts on the intended MCP
host when tool selection is the question. Record the host, model-facing tool
catalog, selected tool, arguments, errors, retries, and task outcome.
Schema validity or word-overlap heuristics do not prove discoverability.
Put provider protocols/parsing in adapters and shared CLI/MCP workflows in the
application layer. Share Evidence provenance, unknown projection, and session
retention semantics; matching payloads alone do not establish parity.
See [mcp-contracts.md](mcp-contracts.md) for shipped runtime behavior and
[testing.md](testing.md) for test boundaries and verification lanes.
Measure the resource before choosing a budget and enforce it before the costly
step. Account for value alternatives, trace-frame products, retained records,
serialization expansion, and temporary-file growth separately. Derive facet
completeness from examined records and exhaustiveness, rather than diagnostic
prose or an empty failure list. Preserve observations independently of cleanup
success.
Update canonical contracts, output schemas, examples, generated artifacts, and
relevant docs together. Verify converted advertised schemas and success,
malformed, unavailable, cancellation, and partial outcomes through affected
consumers. Real-engine claims require the matching provider lane; see
[testing.md](testing.md).
When discoverability changes, evaluate representative broad, direct, and negative
tasks on the intended host. Record host/model/catalog, selected tools, arguments,
errors, retries, and task outcomes. Schema validity and keyword heuristics do not
establish successful tool selection. See [mcp-contracts.md](mcp-contracts.md) for
shipped runtime behavior.
+2 -2
View File
@@ -56,7 +56,7 @@ harm_rank,location,trigger,current_copy,user_risk,proposed_replacement,implement
46,src/application/Uninstall.ts:removeManagedPath symlink,Managed cache/state/skill path is a symbolic link,Refused to follow symlink {path}.,Exposes local path and does not explain manual safety check,"REA did not remove this item because its managed path is a symbolic link. Verify the link target before removing it manually.",implemented,focused assertion passed
47,src/application/Uninstall.ts:removeManagedPath failure,Managed item removal fails,{path} could not be removed.,Exposes local path and gives no recovery,"This item could not be removed. Check file permissions, then rerun uninstall.",implemented,verified by injected managed-path removal failure test
48,src/application/DoctorDiagnostics.ts:node,Runtime version is outside supported ranges,"Install Node.js 22.x (>=22.19), 24.x (>=24.11), or 26+.",Low risk; exact dependency recovery,Keep current copy,unchanged,verified by doctor unit test
49,src/application/Doctor.ts:host,Host OS/distribution is unsupported,"REA supports macOS 12+, Ubuntu 24.04+, Fedora 41+, 64-bit Arch Linux, and CachyOS.",Low risk; clearly states supported choices,Keep current copy,unchanged,verified by doctor unit tests
49,src/application/Doctor.ts:host,Host OS/distribution is unsupported,"REA supports macOS 12+, Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, and CachyOS.",Low risk; clearly states supported choices,Keep current copy,unchanged,verified by doctor unit tests
50,src/application/Doctor.ts:analysis engine,Optional deep-analysis executable cannot be found,"Run rea setup to install Hopper, or set HOPPER_LAUNCHER_PATH.",Low risk in setup-specific diagnostic; exact recovery paths,Keep current copy,unchanged,verified by doctor unit tests
51,src/application/Doctor.ts:target,Optional target path fails shared validation,Supply a readable local app or program path.,Low risk; tells caller valid target class,Keep current copy,unchanged,verified by doctor unit test
52,src/application/Setup.ts:approval,Setup plan lacks approval,"Review the setup plan, then rerun interactively or with --yes.",Low risk; exact authorization recovery,Keep current copy,unchanged,verified by setup unit tests
@@ -67,7 +67,7 @@ harm_rank,location,trigger,current_copy,user_risk,proposed_replacement,implement
57,src/application/Setup.ts:unsupported platform,Platform is neither macOS nor Linux,REA supports Hopper on macOS and selected 64-bit Linux distributions.,Low risk; states support boundary,Keep current copy,unchanged,verified by setup unit test
58,src/application/SetupHost.ts:unsupported Node,Runtime version cannot run setup,"Install Node.js 22.x (>=22.19), 24.x (>=24.11), or 26+ and rerun setup.",Low risk; exact dependency and retry,Keep current copy,unchanged,verified by setup host tests
59,src/application/Setup.ts:unsupported macOS,macOS version is missing or older than 12,Upgrade to macOS 12 or newer.,Low risk; exact support floor,Keep current copy,unchanged,verified by setup host tests
60,src/application/Setup.ts:unsupported Linux,Linux distribution is outside supported set,"REA supports Hopper on Ubuntu 24.04+, Fedora 41+, 64-bit Arch Linux, and CachyOS.",Low risk; exact supported alternatives,Keep current copy,unchanged,verified by setup unit test
60,src/application/Setup.ts:unsupported Linux,Linux distribution is outside supported set,"REA supports Hopper on Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, and CachyOS.",Low risk; exact supported alternatives,Keep current copy,unchanged,verified by setup unit test
61,src/application/process/ProcessCli.ts:readJson read,Process scenario or evidence file cannot be read,Raw filesystem exception through CLI framework,Can expose local paths/codes and no recovery,"Process input file could not be read. Check that the path exists and is readable.",implemented,verified by focused CLI test
62,src/application/process/ProcessCli.ts:readJson size,Process scenario or evidence file exceeds 64 MiB,Process JSON input exceeds byte limit,Does not state limit or recovery,"Process input file is too large. Reduce it below 64 MiB, then try again.",implemented,verified by focused sparse-file CLI test
63,src/application/process/ProcessCli.ts:readJson parse,Process scenario or evidence file is malformed JSON,Raw JSON parser exception through CLI framework,Can expose parser implementation and lacks recovery,"Process input file is not valid JSON. Repair the file, then try again.",implemented,verified by focused CLI test
1 harm_rank location trigger current_copy user_risk proposed_replacement implementation_status verification_result
56 46 src/application/Uninstall.ts:removeManagedPath symlink Managed cache/state/skill path is a symbolic link Refused to follow symlink {path}. Exposes local path and does not explain manual safety check REA did not remove this item because its managed path is a symbolic link. Verify the link target before removing it manually. implemented focused assertion passed
57 47 src/application/Uninstall.ts:removeManagedPath failure Managed item removal fails {path} could not be removed. Exposes local path and gives no recovery This item could not be removed. Check file permissions, then rerun uninstall. implemented verified by injected managed-path removal failure test
58 48 src/application/DoctorDiagnostics.ts:node Runtime version is outside supported ranges Install Node.js 22.x (>=22.19), 24.x (>=24.11), or 26+. Low risk; exact dependency recovery Keep current copy unchanged verified by doctor unit test
59 49 src/application/Doctor.ts:host Host OS/distribution is unsupported REA supports macOS 12+, Ubuntu 24.04+, Fedora 41+, 64-bit Arch Linux, and CachyOS. REA supports macOS 12+, Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, and CachyOS. Low risk; clearly states supported choices Keep current copy unchanged verified by doctor unit tests
60 50 src/application/Doctor.ts:analysis engine Optional deep-analysis executable cannot be found Run rea setup to install Hopper, or set HOPPER_LAUNCHER_PATH. Low risk in setup-specific diagnostic; exact recovery paths Keep current copy unchanged verified by doctor unit tests
61 51 src/application/Doctor.ts:target Optional target path fails shared validation Supply a readable local app or program path. Low risk; tells caller valid target class Keep current copy unchanged verified by doctor unit test
62 52 src/application/Setup.ts:approval Setup plan lacks approval Review the setup plan, then rerun interactively or with --yes. Low risk; exact authorization recovery Keep current copy unchanged verified by setup unit tests
67 57 src/application/Setup.ts:unsupported platform Platform is neither macOS nor Linux REA supports Hopper on macOS and selected 64-bit Linux distributions. Low risk; states support boundary Keep current copy unchanged verified by setup unit test
68 58 src/application/SetupHost.ts:unsupported Node Runtime version cannot run setup Install Node.js 22.x (>=22.19), 24.x (>=24.11), or 26+ and rerun setup. Low risk; exact dependency and retry Keep current copy unchanged verified by setup host tests
69 59 src/application/Setup.ts:unsupported macOS macOS version is missing or older than 12 Upgrade to macOS 12 or newer. Low risk; exact support floor Keep current copy unchanged verified by setup host tests
70 60 src/application/Setup.ts:unsupported Linux Linux distribution is outside supported set REA supports Hopper on Ubuntu 24.04+, Fedora 41+, 64-bit Arch Linux, and CachyOS. REA supports Hopper on Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, and CachyOS. Low risk; exact supported alternatives Keep current copy unchanged verified by setup unit test
71 61 src/application/process/ProcessCli.ts:readJson read Process scenario or evidence file cannot be read Raw filesystem exception through CLI framework Can expose local paths/codes and no recovery Process input file could not be read. Check that the path exists and is readable. implemented verified by focused CLI test
72 62 src/application/process/ProcessCli.ts:readJson size Process scenario or evidence file exceeds 64 MiB Process JSON input exceeds byte limit Does not state limit or recovery Process input file is too large. Reduce it below 64 MiB, then try again. implemented verified by focused sparse-file CLI test
73 63 src/application/process/ProcessCli.ts:readJson parse Process scenario or evidence file is malformed JSON Raw JSON parser exception through CLI framework Can expose parser implementation and lacks recovery Process input file is not valid JSON. Repair the file, then try again. implemented verified by focused CLI test
+9
View File
@@ -126,6 +126,15 @@ process cleanup. Owned decoder diagnostics retain at most 1 MiB across stdout
and stderr; the collector drops overflow as it arrives, reports the limit
failure and verifies cleanup. Heap limits alone do not establish aggregate RSS limits.
Observed decoder memory exhaustion returns `resource_constraint`, with the
selected capture, applicable limits and retained process diagnostics. HAR's
old-generation heap is fixed; inherited `NODE_OPTIONS` cannot raise it.
Record selection happens after complete decoding and does not reduce that
workload. Use a smaller capture exported by its producer or another decoder
with sufficient capacity, retaining the original for provenance. Subsets do
not establish complete-capture coverage. Repeating the same workload or
running provider health diagnostics does not resolve the heap constraint.
Stable regular-file reads reject symlinks, replacement and concurrent changes.
Private snapshots, declarations and tool configuration are removed before the
result returns. Cleanup uncertainty retains the selected capture, resource and
+3 -1
View File
@@ -20,7 +20,9 @@ Results retain:
- The selected target, frame and document loader identity; local armed/end timestamps and separate backend monotonic coverage timestamps.
- Every admitted producer function/block range, exclusive end offset and execution count in UTF-16 code units, with verified bounds when exact text is available. Nested/overlapping counts are preserved and must not be summed.
- Main-document script inventory, exact session script IDs, resource start coordinates, sourceURL/source-map declarations, producer hash and independently computed UTF-8 text digest.
- Armed-window requests from the selected main frame and selected origins, complete reported initiator objects (including stack hierarchy/descriptions), derived callsites, exact script-ID associations and unresolved async parent IDs. Source association does not establish UI causality.
- Armed-window requests from the selected main frame and selected origins, complete reported initiator objects (including stack hierarchy/descriptions), derived callsites, exact script-ID associations and unresolved async parent IDs. Source association does not establish UI causality. Callsite and listener `line_number`/`column_number` values are CDP's zero-based lines and UTF-16 columns in the resource named by `url`. With a `script_id`, that is the script's enclosing resource: the script file for an external script, or the HTML document for an inline script. `resource_start` is where the script text starts in that resource. A callsite with an empty `script_id` comes from the request's reported initiator rather than a script call frame, such as markup that the parser read in a document or a module import in a script file. It still locates a position in `url`, but has no session-script association, so it cannot be joined to captured source or `resource_start`. `trace_web_source_location` takes one-based, script-relative lines and zero-based UTF-16 columns.
For an external script, where `url` is the script file, use `line = line_number + 1` and keep `column = column_number`; this also applies to an empty-`script_id` initiator position in a script file. For an inline script, which requires a `script_id` and its `resource_start`, use `line = line_number - resource_start.line_number + 1`. Subtract `resource_start.column_number` from `column_number` only when `line_number === resource_start.line_number`; keep the reported column on later lines. Columns remain zero-based. This conversion requires known source-start and column coordinates; preserve unavailable coordinates as unknown.
The coverage counter interval starts at backend acceptance before the armed receipt and ends at the resetting sample after the local timer. Counts may include execution during these command intervals; request events are restricted to the locally armed window. The result retains both backend timestamps and the distinct local clock.
+27
View File
@@ -84,6 +84,33 @@ are made.
## Verification
Browser bundle collection uses absolute section offsets for nested inline maps.
An enclosing column offset contributes only when the nested section starts on
that enclosing section's first generated line. Parent boundaries still clip
preceding browser mappings when a nested section starts with a gap or has no
child leaves. Raw map text, original source identities and the dedicated decoder
profile are preserved.
Browser collection accepts up to 64 MiB of map responses per inspection and
preflights indexed sections, sources, names, generated rows and mapping segments
against a 262144-record decode budget before upstream flattening. Indexed maps
are limited to 64 nested levels. These structural limits bound decoded object
growth while preserving large embedded `sourcesContent` strings within the
response-byte budget. It also bounds the expanded inline evidence to 32 MiB
across the inspection, checking resolved source identities and mapping rows
before publishing them, and bounds raw resolved-source identities to 64 MiB
before upstream materializes their arrays. Exceeding either decoder budget
returns a `fetch_failed` item while retaining other maps. Decoded coordinates
and source/name indexes are validated per map; a malformed map is reported as
`invalid` without discarding earlier or later maps.
Collection reserves each requested map's failure context before fetching it.
When the aggregate inline-result budget cannot reserve another item, remaining
requests are left unprocessed and reported as unknown through the top-level
`limitation`; `requested` retains the full count and `processed` counts returned
items.
Malformed UTF-8 map responses are reported as invalid rather than repaired with
replacement characters.
Focused tests cover duplicate mappings, indexed offsets/overlap/local indexes,
32-bit VLQ overflow, nullable content, UTF-16/CRLF positions, immutable artifact
identity, cancellation, late output closure, cleanup failures, SDK schemas and
+5 -2
View File
@@ -10,8 +10,11 @@ verified manifest into one caller-selected, absent directory.
For passive inspection, select `include_script_sources: true` (CLI:
`--include-script-sources`). For scenarios, select
`capture.network.response_body: true`. Save either the complete Evidence record
or its normalized result as UTF-8 JSON. The compact MCP wrapper's `evidence`
field contains the complete Evidence record.
or its normalized result as UTF-8 JSON. MCP `structuredContent` contains the complete Evidence record.
The capture must be a regular file. A symlink to a regular file is accepted;
directories, named pipes and device files are rejected before reading capture
bytes or creating output.
```sh
rea export-web-scripts /analysis/capture.json /analysis/exported-scripts --json
+13 -2
View File
@@ -17,7 +17,7 @@ additional permission flag or degraded mode is required.
- Node.js 22.x (>=22.19), 24.x (>=24.11), or 26+;
- an operator-installed Ghidra 12.1.x distribution (verified with 12.1.4);
- a 64-bit full JDK inside that installation's declared Java range (JDK 21 or newer, with no maximum, for current 12.1 releases);
- an explicit native, non-managed, non-DLL x86 or x86-64 PE application; and
- an explicit native, non-managed x86 or x86-64 PE application or DLL; and
- the 25 read-only Ghidra inventory, memory, and function-analysis operations.
Loaded memory reads and file offsets preserve Ghidra's observed source mappings.
@@ -38,6 +38,13 @@ REA selects its packaged bridge scripts by explicit path. Same-named files or
directories in the caller's working directory do not select a different
script or require users to clean that directory before analysis.
Native DLL analysis preserves the PE shared-library role in the analysis profile.
REA imports an immutable copy for static analysis; it does not load the library
into the analyst process or execute its entry routine. The source-owned DLL
fixtures have no entry routine or imports and expose two exported functions.
The same native snapshot, path-admission and cleanup requirements apply to EXEs
and DLLs.
## Configuration
```powershell
@@ -100,7 +107,7 @@ and artifact SHA-256 before loading the package-owned addon. Native failure
reasons remain distinct from a valid installation and an unsupported target.
PE header classification and SHA-256 come from the same open file. The Windows
provider admits native x86 and x86-64 PE applications and rejects unsupported roles,
provider admits native x86 and x86-64 PE applications and DLLs and rejects unsupported roles,
architectures, managed images, and malformed headers. The original selected
source coordinate is preserved for native admission.
@@ -159,7 +166,11 @@ artifact and manifest.
npm run verify:windows-native
npm run verify:ghidra:windows
npm run verify:ghidra:windows -- --x86
npm run verify:ghidra:windows -- --dll
npm run verify:ghidra:windows -- --x86 --dll
npm run verify:ghidra:windows:package -- --x86
npm run verify:ghidra:windows:package -- --dll
npm run verify:ghidra:windows:package -- --x86 --dll
npm run verify:ghidra:windows:package -- C:\fixtures\installed-rea C:\fixtures\sample.exe
```
+7 -4
View File
@@ -85,19 +85,22 @@ if [[ "$version" =~ \+ ]]; then
fail "npm cannot install an exact version with build metadata. Pass a version without build metadata, then retry."
fi
prefix_args=()
install_args=(install --global)
if [[ "$platform" == "Linux" ]]; then
prefix_args=(--prefix "$HOME/.local")
install_args+=(--prefix "$HOME/.local")
install_bin="$HOME/.local/bin/rea"
else
npm_prefix="$(npm prefix --global)" || fail "the npm global prefix could not be read. Repair the npm configuration, then retry."
install_bin="$npm_prefix/bin/rea"
fi
install_args+=("$PACKAGE@$version")
printf 'REA install plan\n'
printf ' Version: %s\n' "$version"
printf ' Runtime: Node.js %s\n' "$node_version"
printf ' Command: npm install --global %s@%s\n' "$PACKAGE" "$version"
printf ' Command:'
printf ' %q' npm "${install_args[@]}"
printf '\n'
printf ' Binary: %s\n' "$install_bin"
printf ' Setup: %s\n' "$([[ "$start_setup" == true ]] && printf 'start when a terminal is available' || printf 'skipped')"
@@ -107,7 +110,7 @@ if [[ "$dry_run" == true ]]; then
fi
printf 'Installing %s@%s...\n' "$PACKAGE" "$version"
npm install --global ${prefix_args[@]+"${prefix_args[@]}"} "$PACKAGE@$version" || fail "npm could not install REA. Check registry access and npm permissions, then retry."
npm "${install_args[@]}" || fail "npm could not install REA. Check registry access and npm permissions, then retry."
[[ -x "$install_bin" ]] || fail "npm completed without installing the rea command. Check the npm global bin directory and PATH, then retry."
installed_version="$("$install_bin" --version 2>/dev/null | tr -d '[:space:]')" || fail "the installed REA version could not be read. Reinstall the requested version, then retry."
[[ "$installed_version" == "$version" ]] || fail "installed version $installed_version does not match $version. Reinstall the requested version, then retry."
+9 -1
View File
@@ -1,6 +1,14 @@
{
"$schema": "./node_modules/knip/schema.json",
"entry": ["src/main.ts", "src/cli.ts", "src/contracts/errorSchemas.ts"],
"entry": [
"src/main.ts",
"src/cli.ts",
"src/composition/javascriptAnalysisWorkerProcess.ts",
"src/contracts/errorSchemas.ts",
"src/evaluation/AgentEvaluationFixtures.ts",
"src/application/RealHopperAssertions.ts",
"tests/processOwnershipRunner.ts"
],
"project": ["src/**/*.ts", "tests/**/*.ts", "scripts/**/*.mjs"],
"vitepress": {
"entry": ["docs/.vitepress/config.ts"]
+3 -1
View File
@@ -57,7 +57,9 @@ without this lane reports Windows native controls as unavailable.
deduplicated using Windows ordinal comparison, preserving their native Unicode
semantics and caller-selected values.
- Cleanup walks locked directory objects, removes files by handle, and unlinks
reparse entries without traversing their targets. Normal close, cancellation,
reparse entries without traversing their targets. Failed removal retains the
root and ancestor leases for retry; a partially removed runtime accepts only
cleanup, and its registry entry remains until removal succeeds. Normal close, cancellation,
startup failure, and timeout release provider resources. Abrupt owner death
kills the owned job; it can leave private runtime files for later operator
cleanup and does not claim transactional deletion after a crash.
+5 -2
View File
@@ -86,6 +86,7 @@ struct Runtime : Resource {
std::vector<Handle> parents;
Handle directory;
std::vector<Handle> immutableFiles;
bool closing = false;
// Main-thread admission is single-flight; only the accepted copy owns the
// atomic cancellation flag consumed by its async worker. ERROR_BUSY rejects
// another copy before it can reset that flag or replace pending ownership.
@@ -94,7 +95,8 @@ struct Runtime : Resource {
Runtime() : Resource(Kind::Runtime) {}
};
struct Process : Resource {
Handle job, process, stdoutRead, stderrRead;
Handle job, process, stdoutRead, stderrRead, stdinWrite;
bool inputPending = false;
DWORD pid = 0;
Process() : Resource(Kind::Process) {}
};
@@ -122,7 +124,8 @@ void closeRuntime(Runtime& runtime);
napi_value filesystemCall(napi_env env, const std::wstring& operation,
const std::vector<napi_value>& args);
std::unique_ptr<Process> spawnProcess(const std::wstring& command, const std::wstring& commandLine,
const std::wstring& cwd, const std::vector<std::wstring>& environment);
const std::wstring& cwd, const std::vector<std::wstring>& environment,
bool protocolStdin = false);
napi_value processCall(napi_env env, const std::wstring& operation,
const std::vector<napi_value>& args);
napi_value inspect(napi_env env);
+6 -4
View File
@@ -328,14 +328,11 @@ static void disposeSnapshot(Runtime& root, Handle& file, const std::wstring& pat
void closeRuntime(Runtime& root) {
if (root.closed) return;
root.closing = true;
// Windows keeps the bearer descriptor and snapshot leases until this owner
// cleanup. POSIX removes its consumed descriptor earlier. Abrupt owner death
// closes process jobs but cannot run this walk, so private files can remain.
root.immutableFiles.clear();
struct ReleaseRuntime {
Runtime& root;
~ReleaseRuntime() { root.directory.reset(); root.parents.clear(); root.closed = true; }
} release{root};
// Each traversed directory stays locked against replacement. Reparse entries
// are unlinked as objects; their targets are never enumerated or deleted.
struct Frame {
@@ -380,6 +377,10 @@ void closeRuntime(Runtime& root) {
frames.push_back(std::make_unique<Frame>(std::move(child), path));
else dispose(child.get(), path);
}
// Failed walks retain the root's identity leases for a later cleanup retry.
root.directory.reset();
root.parents.clear();
root.closed = true;
}
struct SnapshotWork {
@@ -528,6 +529,7 @@ napi_value filesystemCall(napi_env env, const std::wstring& operation, const std
return result;
}
auto& root = static_cast<Runtime&>(resource(env, args[0], Kind::Runtime));
require(!root.closing || operation == L"runtime_close", "Runtime cleanup is pending", root.path, ERROR_BUSY);
if (operation == L"runtime_snapshot_cancel") { root.snapshotCancelled.store(true); return null(env); }
require(!root.snapshotPending, "Runtime snapshot is still pending", root.path, ERROR_BUSY);
// Reject overlapping operations before snapshot() resets cancellation. The
+100 -9
View File
@@ -34,16 +34,17 @@ static Handle createJob() {
return job;
}
static void pipe(Handle& read, Handle& write) {
static void pipe(Handle& read, Handle& write, bool parentReads = true) {
SECURITY_ATTRIBUTES attributes{sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE};
HANDLE rawRead, rawWrite;
require(CreatePipe(&rawRead, &rawWrite, &attributes, 0), "Create owned process output pipe failed");
read.reset(rawRead); write.reset(rawWrite);
require(SetHandleInformation(read.get(), HANDLE_FLAG_INHERIT, 0), "Protect process output handle inheritance failed");
require(SetHandleInformation(parentReads ? read.get() : write.get(), HANDLE_FLAG_INHERIT, 0), "Protect parent process pipe handle inheritance failed");
}
std::unique_ptr<Process> spawnProcess(const std::wstring& command, const std::wstring& commandLine,
const std::wstring& cwd, const std::vector<std::wstring>& environment) {
const std::wstring& cwd, const std::vector<std::wstring>& environment,
bool protocolStdin) {
const auto executable = ordinaryDriveSeparators(command);
require(executable.size() >= 3 && executable[1] == L':' && executable[2] == L'\\',
"Owned Windows process requires an absolute executable path", command, ERROR_INVALID_PARAMETER);
@@ -52,9 +53,13 @@ std::unique_ptr<Process> spawnProcess(const std::wstring& command, const std::ws
Handle stdoutWrite, stderrWrite;
pipe(result->stdoutRead, stdoutWrite); pipe(result->stderrRead, stderrWrite);
SECURITY_ATTRIBUTES security{sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE};
Handle input(CreateFileW(L"NUL", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
&security, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
require(input.valid(), "Open owned process null input failed");
Handle input;
if (protocolStdin) pipe(input, result->stdinWrite, false);
else {
input.reset(CreateFileW(L"NUL", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
&security, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
require(input.valid(), "Open owned process null input failed");
}
Attributes attributes(2);
HANDLE job = result->job.get();
attributes.add(PROC_THREAD_ATTRIBUTE_JOB_LIST, &job, sizeof(job));
@@ -198,16 +203,93 @@ static napi_value callerToken(napi_env env) {
return result;
}
struct InputWork {
napi_async_work work = nullptr;
napi_deferred deferred = nullptr;
napi_ref processReference = nullptr;
Process* process;
Handle pipe;
std::vector<unsigned char> bytes;
size_t written = 0;
std::unique_ptr<Failure> failure;
explicit InputWork(Process& process) : process(&process) {}
};
static void writeInput(napi_env, void* pointer) {
auto& work = *static_cast<InputWork*>(pointer);
try {
// Anonymous pipe writes may block. Keep them off the JS thread so output
// polling and job termination remain live while a child stops reading.
while (work.written < work.bytes.size()) {
DWORD written = 0;
const auto count = static_cast<DWORD>(std::min<size_t>(65536, work.bytes.size() - work.written));
require(WriteFile(work.pipe.get(), work.bytes.data() + work.written, count, &written, nullptr),
"Write owned process input failed");
require(written > 0, "Owned process input write made no progress", L"", ERROR_WRITE_FAULT);
work.written += written;
}
} catch (const Failure& failure) {
work.failure = std::make_unique<Failure>(failure);
} catch (const std::exception& failure) {
work.failure = std::make_unique<Failure>(failure.what(), L"", ERROR_GEN_FAILURE);
}
}
static void completeInput(napi_env env, napi_status status, void* pointer) {
std::unique_ptr<InputWork> work(static_cast<InputWork*>(pointer));
work->process->inputPending = false;
if (work->failure) napi_reject_deferred(env, work->deferred, failureValue(env, *work->failure));
else if (status != napi_ok)
napi_reject_deferred(env, work->deferred, failureValue(env, Failure("Owned process input worker was cancelled", L"", ERROR_OPERATION_ABORTED)));
else napi_resolve_deferred(env, work->deferred, number(env, work->written));
napi_delete_reference(env, work->processReference);
napi_delete_async_work(env, work->work);
}
static napi_value inputWrite(napi_env env, napi_value owner, Process& process, napi_value input) {
require(process.stdinWrite.valid(), "Owned process has no writable input", L"", ERROR_BROKEN_PIPE);
require(!process.inputPending, "Owned process input already has a pending write", L"", ERROR_BUSY);
auto work = std::make_unique<InputWork>(process);
void* bytes = nullptr;
size_t size = 0;
bool buffer = false;
check(napi_is_buffer(env, input, &buffer));
require(buffer, "Owned process input must be a Buffer", L"", ERROR_INVALID_PARAMETER);
check(napi_get_buffer_info(env, input, &bytes, &size));
if (size > 0) work->bytes.assign(static_cast<unsigned char*>(bytes), static_cast<unsigned char*>(bytes) + size);
HANDLE pipe;
require(DuplicateHandle(GetCurrentProcess(), process.stdinWrite.get(), GetCurrentProcess(), &pipe,
0, FALSE, DUPLICATE_SAME_ACCESS), "Retain owned process input handle failed");
work->pipe.reset(pipe);
napi_value promise;
check(napi_create_promise(env, &work->deferred, &promise));
check(napi_create_reference(env, owner, 1, &work->processReference));
try {
check(napi_create_async_work(env, nullptr, string(env, std::string("REA owned process input")),
writeInput, completeInput, work.get(), &work->work));
check(napi_queue_async_work(env, work->work));
process.inputPending = true;
} catch (...) {
if (work->work) napi_delete_async_work(env, work->work);
napi_delete_reference(env, work->processReference);
throw;
}
work.release();
return promise;
}
napi_value processCall(napi_env env, const std::wstring& operation, const std::vector<napi_value>& args) {
if (operation == L"process_caller_token") {
require(args.empty(), "Caller token observation takes no arguments", L"", ERROR_INVALID_PARAMETER);
return callerToken(env);
}
if (operation == L"process_spawn") {
require(args.size() == 4, "Wrong native process launch argument count", L"", ERROR_INVALID_PARAMETER);
require(args.size() == 4 || args.size() == 5, "Wrong native process launch argument count", L"", ERROR_INVALID_PARAMETER);
bool protocolStdin = false;
if (args.size() == 5) check(napi_get_value_bool(env, args[4], &protocolStdin));
std::vector<std::wstring> environment;
for (const auto& entry : array(env, args[3])) environment.push_back(wide(env, entry));
auto process = spawnProcess(wide(env, args[0]), wide(env, args[1]), wide(env, args[2]), environment);
auto process = spawnProcess(wide(env, args[0]), wide(env, args[1]), wide(env, args[2]), environment, protocolStdin);
auto result = object(env);
set(env, result, "pid", number(env, process->pid));
set(env, result, "jobAssigned", boolean(env, true));
@@ -215,8 +297,16 @@ napi_value processCall(napi_env env, const std::wstring& operation, const std::v
set(env, result, "handle", wrap(env, std::move(process)));
return result;
}
if (operation == L"process_stdin_write") {
require(args.size() == 2, "Wrong native process input argument count", L"", ERROR_INVALID_PARAMETER);
return inputWrite(env, args[0], static_cast<Process&>(resource(env, args[0], Kind::Process)), args[1]);
}
require(args.size() == 1, "Wrong native process handle argument count", L"", ERROR_INVALID_PARAMETER);
auto& process = static_cast<Process&>(resource(env, args[0], Kind::Process));
if (operation == L"process_stdin_close") {
process.stdinWrite.reset();
return null(env);
}
if (operation == L"process_poll") {
auto result = object(env);
bool stdoutEnded = false, stderrEnded = false;
@@ -240,7 +330,7 @@ napi_value processCall(napi_env env, const std::wstring& operation, const std::v
}
if (operation == L"process_close") {
// Closing the job is the crash-safe authority; no PID enumeration is used.
process.job.reset(); process.process.reset(); process.stdoutRead.reset(); process.stderrRead.reset();
process.job.reset(); process.process.reset(); process.stdoutRead.reset(); process.stderrRead.reset(); process.stdinWrite.reset();
process.closed = true;
return null(env);
}
@@ -266,6 +356,7 @@ napi_value inspect(napi_env env) {
set(env, result, "privateDacl", boolean(env, true));
set(env, result, "atomicJobAssignment", boolean(env, true));
set(env, result, "killOnOwnerClose", boolean(env, true));
set(env, result, "protocolStdin", boolean(env, true));
return result;
}
+26 -4
View File
@@ -1,12 +1,12 @@
{
"name": "rea-agents",
"version": "6.0.0",
"version": "6.3.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "rea-agents",
"version": "6.0.0",
"version": "6.3.0",
"license": "MIT",
"dependencies": {
"@babel/parser": "8.0.4",
@@ -38,8 +38,10 @@
"plist": "5.0.0",
"semver": "7.8.5",
"smol-toml": "1.9.0",
"stream-json": "3.7.0",
"write-file-atomic": "7.0.0",
"ws": "8.21.0",
"yaml": "2.9.0",
"zod": "4.4.3"
},
"bin": {
@@ -63,8 +65,7 @@
"turbo": "2.11.7",
"typescript": "7.0.2",
"vitepress": "1.6.4",
"vitest": "5.0.3",
"yaml": "2.9.0"
"vitest": "5.0.3"
},
"engines": {
"node": "^22.19.0 || ^24.11.0 || >=26.0.0"
@@ -7070,6 +7071,27 @@
"dev": true,
"license": "MIT"
},
"node_modules/stream-chain": {
"version": "4.2.6",
"resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-4.2.6.tgz",
"integrity": "sha512-1zeJ8CrtJfmiba26ui8jXkq/xLRFvhzkdH02D5QLO9Cnovgeb28IJxg88DdraWnjnkbOol/++uIAybJbJhk7ig==",
"license": "BSD-3-Clause",
"funding": {
"url": "https://github.com/sponsors/uhop"
}
},
"node_modules/stream-json": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/stream-json/-/stream-json-3.7.0.tgz",
"integrity": "sha512-rCSBdcBP/bPk6T8QFcxAj1MSzAuc5i49cYW6IE7sYObNEPccBJIUiL6fU9c9BWt40aJK0siVynLX7lWaW8alXw==",
"license": "BSD-3-Clause",
"dependencies": {
"stream-chain": "^4.2.5"
},
"funding": {
"url": "https://github.com/sponsors/uhop"
}
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",

Some files were not shown because too many files have changed in this diff Show More