mirror of
https://github.com/morluto/rea
synced 2026-10-28 23:11:11 -04:00
5508b2affd
Retain authenticated provider source records independently of snapshot replay eligibility and return them explicitly to plain application callers, including late cancellation. CLI/MCP commit source records before delivering links; function dossiers share the canonical Evidence constructor. Keep directory replies compact and preserve successful retry verification. Real Ghidra CLI/MCP investigations verify 652-function ls, historical report provenance, cross-session resume, unchanged source/project content and complete offline Evidence. Final full 14,338-function libcrypto comparison matches all metadata/pseudocode facts and independent fresh-import observations: 14,194 written, 143 external, one recorded deadline; 494.03 s, 445.63 CPU s, 1.584 GiB sampled family peak under 2-CPU/8-GiB guards, with no OOM or cleanup failure. 144 focused tests and static/docs/site checks pass; latest-main integration passes 289 cases plus typecheck/lint and actual CLI snapshot source retrieval. Final CI source/static/build/docs/quality/package checks pass. Four ADB shard failures also occur in main CI 40349559391; cancelled coverage remains unverified and author declarations stay unchecked under the user's explicit bypass authorization. No human-review attestation is made.
150 lines
9.2 KiB
Markdown
150 lines
9.2 KiB
Markdown
# Directory decompilation: capacity, resume and source Evidence
|
||
|
||
The directory-export feature requested in #6090 already shipped in #6170.
|
||
This follow-up verifies the current public workflow and fixes a source-provenance
|
||
gap found while combining it with existing Ghidra projects (#1048).
|
||
|
||
## Completed task and correctness
|
||
|
||
The analyst asks for all functions as local pseudocode files, without putting
|
||
their bodies in agent context. The committed `decompile-directory.mjs` driver
|
||
uses the production stdio MCP entrypoint and installed SDK. It discovers the
|
||
catalog, exports an initial chunk, closes/reopens the provider, resumes all
|
||
remaining work, and resumes again to verify settled files. It authenticates an
|
||
explicitly exported Evidence bundle and checks the original target/project.
|
||
|
||
Every written file is checked against its index SHA-256 and address/profile
|
||
header. Existing file hashes and modification times must survive both resumes.
|
||
Comparison facts include every address, name, status, body range and pseudocode
|
||
digest. An independent fresh-import investigation from #1048 additionally checks
|
||
the complete inventory and two nonempty pseudocode observations. This establishes
|
||
export preservation of provider observations; it does not establish discovery of
|
||
every actual function or equivalence to original source.
|
||
|
||
| Real artifact | Provider inventory | Written | External | Failed |
|
||
| ----------------------- | -----------------: | ------: | -------: | -----: |
|
||
| `/usr/bin/ls` | 652 | 541 | 111 | 0 |
|
||
| system `libcrypto.so.3` | 14,338 | 14,194 | 143 | 1 |
|
||
|
||
Target SHA-256 values are respectively
|
||
`cb30d69b24245bf2ecdc9e7f53bbad19159999970b6d82c0c00c7d32d9e37aa4` and
|
||
`aa01e614af634bc7c8b678c9250b5c4f613c61989bacf0a5d6aed6570e7dcabd`.
|
||
These installed ELF x86-64 binaries were analyzed statically, never executed.
|
||
The large run explicitly selected a five-second per-function deadline; function
|
||
`0x387f00` exceeded it, remained a recorded failure, and was retried on resume.
|
||
Later functions were still exported. No disappearance of that failure is claimed.
|
||
The resulting large tree occupies about 107 MiB on this filesystem.
|
||
|
||
## Source-provenance correction
|
||
|
||
Before this change, `BinarySession` retained provider `sourceEvidence` only inside
|
||
its snapshot-eligible branch. Ghidra procedure reads without a document selector
|
||
are not snapshot eligible. A composed directory export therefore lost saved
|
||
project reports even though the provider supplied them. The workflow also ignored
|
||
source-record IDs, and the function-dossier adapter copied observation fields
|
||
manually without those links.
|
||
|
||
The session now authenticates/retains source records independently of replay
|
||
eligibility. Plain application helpers also return authenticated immutable source
|
||
records with their outcome, including late cancellation. Both adapters explicitly
|
||
commit them before delivering links; an adapter without a retention owner refuses
|
||
the response. Source collection borrows ledger records without constructing or
|
||
hashing an intermediate bundle. The workflow links distinct source IDs without copying their payloads.
|
||
The function adapter uses the common observation-to-Evidence constructor,
|
||
preserving sources through normal and late-cancelled completion. Queries with no
|
||
source records avoid the extra recording path. Complete provider bodies remain
|
||
in the exported function files; this does not add per-function payload retention.
|
||
|
||
A real test project contains historical seed and disabled-analyzer reports saved
|
||
by REA's actual Ghidra pre-scripts. The unmodified runtime completed the export
|
||
but failed the provenance oracle: its bundle had two workflow records and no
|
||
historical source. The fixed runtime retains exactly one historical source and
|
||
links the workflow to it. All 652 inventory entries and the sampled pseudocode
|
||
still match fresh import; source project content stays unchanged. The report is
|
||
historical, with remaining original settings/completeness explicitly unknown.
|
||
|
||
## Measured costs
|
||
|
||
Baseline runtime: `19447516a4bdbc9437d112ebd3f12a5fd062db83`.
|
||
Initial fixed runtime: `f50763fd21527bdf3bab944633617b9df61dded4`, rebased on
|
||
main `f02df45a4`. Both use Node 24.22.1, locked dependencies, actual Ghidra 12.1.4
|
||
and JDK 21.0.12.1+1. The fixed driver later delegates transcript publication to
|
||
the existing cleanup/receipt owner; the protocol and task are unchanged.
|
||
|
||
| Completed task | Wall s | Family CPU s | Peak family GiB | Full-wire token estimate |
|
||
| --------------------------------- | ------: | -----------: | --------------: | -----------------------: |
|
||
| ls, before | 51.411 | 78.984 | 0.943 | 57,082 |
|
||
| ls, initial fix | 50.937 | 79.891 | 1.201 | 57,072 |
|
||
| ls with historical reports, fixed | 52.827 | 80.236 | 1.097 | 57,207 |
|
||
| libcrypto, baseline capacity run | 506.387 | 459.818 | 1.502 | 57,322 |
|
||
|
||
The plain ls pair has identical complete comparison facts. Runtime is similar;
|
||
the higher sampled memory in the fixed run is reported rather than treated as an
|
||
improvement. These sequential shared-host samples establish no generic speed or
|
||
memory ratio. [PR #7250](https://github.com/morluto/rea/pull/7250) records the final
|
||
large-run comparison and CI/review results.
|
||
The failed historical baseline is excluded from completed-task comparisons.
|
||
|
||
The complete MCP replies stayed around 11–12 KiB, including repeated textual and
|
||
structured representations, profile and caveats. The normalized result is only
|
||
the manifest. For example, the large continuation costs about 3,159 estimated
|
||
wire tokens; its complete task is 57,322 because discovery alone costs 47,049.
|
||
Both numbers include actual protocol content, rather than only pseudocode bytes.
|
||
|
||
Estimates use `cl100k_base` on the actual JSON-RPC messages, including discovery,
|
||
requests, responses and notifications, excluding only transport framing and the
|
||
driver's local transcript wrapper. They are not actual model billing. Host
|
||
projection, prompts/reasoning and later agent file reads remain unmeasured.
|
||
The historical source increases response token cost slightly while preserving
|
||
provenance. No token-reduction claim is made for this correctness fix.
|
||
|
||
CPU and memory cover the driver, REA and provider process family. Each run uses
|
||
CPU affinity 0,1 and an 8-GiB sampled family-RSS guard; Java heaps are 1536M for ls
|
||
and 3072M for crypto. RSS is sampled every 100 ms and summed: shared pages may be
|
||
counted repeatedly and short peaks may be missed. CPU is waited child usage.
|
||
Reported completed runs had no resource stop, OOM or cleanup failure.
|
||
Project preparation is excluded and documented separately in
|
||
[project reuse](ghidra-project-reuse.md). Provider starts are process-cold, with
|
||
host filesystem caches unflushed; verified resume occurs in the second session.
|
||
|
||
The index and inventory still scale with function count. This 14,338-item run
|
||
does not establish a larger capacity guarantee. Real Windows/macOS filesystems,
|
||
other decompilers and native DWARF directory layout remain unverified. The current
|
||
workflow reports unavailable DWARF layout explicitly instead of inventing it.
|
||
|
||
Actual CLI `decompile-all` calls additionally selected only `0x10a420`, reported
|
||
651 excluded entries and `debug_layout_unavailable` for requested dwarf layout,
|
||
then resumed in a new process. The existing file's hash and modification time
|
||
stayed unchanged; the returned historical source ID stayed stable. This CLI check
|
||
verifies the returned manifest/link and local function file, not offline retrieval
|
||
of the separately retained source record after the CLI process exits.
|
||
|
||
## Reproduce and inspect
|
||
|
||
Prepare an owned project using the documented
|
||
[existing-project route](../../docs/installation.md#reuse-an-existing-ghidra-project).
|
||
Use fresh receipt/output paths; the driver refuses existing output directories.
|
||
|
||
```sh
|
||
node experiments/analysis-efficiency/decompile-directory.mjs \
|
||
--runtime /absolute/rea --output /absolute/new-receipt \
|
||
--target /usr/bin/ls --project /absolute/ls-analysis.gpr --program ls \
|
||
--ghidra "$GHIDRA_INSTALL_DIR" --java "$JAVA_HOME"
|
||
```
|
||
|
||
Use `--chunk 512 --heap 3072M --decompile-seconds 5` for the crypto case.
|
||
`--control /absolute/previous-receipt` compares all exported facts;
|
||
`--golden /absolute/fresh-import-receipt` checks the #1048 driver's inventory and
|
||
pseudocode oracle. `--history required` additionally requires a linked historical
|
||
source. The driver allows failed functions to succeed on a later retry, verifies only
|
||
previously written files remain unchanged, and reloads the final index before
|
||
comparison. Complete local receipts include the transcript, resource report, index,
|
||
function files, comparison facts and authenticated Evidence export. The resource
|
||
report is supplied by the external process-family sampler, not the driver.
|
||
|
||
The current nine-file suite passed 144 tests. Against unmodified main source,
|
||
the three source-retention/constructor suites reproduce seven failures and 70
|
||
passes; the fixed full suite passes. This includes invalid source commitments,
|
||
live and cursor-dependent reads, shared source deduplication, selected/null/provider
|
||
subjects, and source links on late-cancelled completion.
|