Compare commits

...
Author SHA1 Message Date
gensokyo-dev 6d5610fe5f fix(process): preserve exit scope and share native wait budgets
Retain the original bracketed ownership snapshot before applying later exit observations, so an exiting verified parent cannot erase a still-live child’s scope. Own one lazily started native-exit waiting budget per cleanup attempt and pass it through discovery, validation, revalidation and final verification.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-19 18:12:05 +00:00
gensokyo-dev 33450d02ea fix(ci): retain trace coverage limits after integration
Restore explicit unverified symlink aliases and same-Node stat/status purpose in the shared coverage contract and guide. The native-exit and trace-attribution integration does not establish those properties. Preserve both limitations rather than silently broadening the reported qualification.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-19 17:46:06 +00:00
gensokyo-dev 3de261cc5e Merge remote-tracking branch 'origin/audit/ci-tests-20261019-round2' into fix/ci-process-observation-baseline 2026-10-19 17:39:33 +00:00
gensokyo-dev 2026d0099b fix(process): type native exit predicates and ownership fixtures precisely 2026-10-19 17:37:40 +00:00
gensokyo-dev 0ac49fbb1f Merge remote-tracking branch 'origin/main' into fix/ci-process-observation-baseline 2026-10-19 17:31:08 +00:00
gensokyo-dev 6892c8bc52 chore: integrate registration and native capture clock fixes 2026-10-19 17:31:03 +00:00
gensokyo-dev 8ea965261e fix(process): integrate main and confirm native exit transitions 2026-10-19 17:30:45 +00:00
gensokyo-dev 54e971a148 chore: integrate current main Evidence parity controls
Adopt main’s selected-path versus artifact-identity test correction and Rizin plain-output update. Product ownership and recorded-crash qualification code are unchanged from the locally and remotely verified 2a42096e1 implementation.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-19 17:27:38 +00:00
morluto b44cb5bd30 test(javascript): distinguish selected paths from artifact identity
Check CLI parity against the admitted absolute selection and verify that MCP retains relative selections separately. Equal canonical artifact results do not imply equal Evidence IDs when caller-selected paths differ.
2026-10-20 01:17:45 +08:00
gensokyo-devandKaoru0822 2dd5effe2a fix(rizin): default one-shot output to plain presentation (#5269)
Default native one-shot Rizin presentation to plain text before collection while preserving caller colour overrides, literal output, recorded argv and shared CLI/MCP Evidence.

Fixes #4488

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-20 01:12:35 +08:00
gensokyo-dev 2a42096e15 chore: integrate main registration isolation and native lifecycle clocks
Retain main’s provider-independent registration fixtures and stronger native lifecycle controls. The earlier shared-host EACCES failure remains recorded; no permission error is suppressed.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-19 17:04:32 +00:00
morluto 0e62094b69 test(setup): isolate registration checks from installed providers
Select absent Hopper, Ghidra and Java locations consistently across registration environment acceptance fixtures. Host PATH Java was executing during IDA budget checks and exposing those checks to unrelated provider cleanup failures. Keep the process ownership failure policy and all registration assertions intact.
2026-10-20 00:53:52 +08:00
morlutoandgensokyo-dev 5199c672ff fix(process): keep lifecycle waits independent of application timers
Use Node promise timers consistently for ownership retries, final verification and capture-journal quiet settlement. Preserve the existing elapsed-time budgets, ownership checks, cancellation and trailing-callback drain.

Adapt the ownership timer correction from gensokyo-dev's PR #5249 and complete the same fix in the adjacent capture-journal owner. Three new controlled regressions fail before the fix; 93 source tests and 94 CLI/MCP/process boundary tests pass afterward, with static checks passing. Global performance replacement and ordinary native Jadx incidence remain unverified.

Fixes #5267

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-20 00:45:49 +08:00
c4aaf813e0 fix(javascript): retain selected application paths in Evidence
Record the admitted selected path separately from canonical artifact identity in successful and partial Evidence. Anchor relative inputs consistently across both CLI routes using the existing caller-path owner.

Adapt shared client verifier assertions and boundary coverage from PR #5261, and the dedicated-route anchoring correction proposed in PR #5265. Historical parsing remains independent of live paths, including legacy records without the parameter.

Validation: 118 focused tests in eight files, static and docs checks, discovery, and installed Gemini CLI 0.29.5 loopback verification of 207 schemas/241 examples passed. Synthetic static-analysis fixtures; no live Google API or native target execution.

Fixes #5258

Co-authored-by: kwakhyun <khyun2348@naver.com>
Co-authored-by: vishal-tambi <tambivishal3@gmail.com>
2026-10-20 00:37:45 +08:00
gensokyo-dev 40ab4048bf fix(ci): retain process edges in ownership trace inventory
Keep fork/vfork and resumed edges along with clone events so the shared attribution owner receives the complete process relation facts it consumes.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-19 16:32:48 +00:00
gensokyo-dev 2761410d44 chore: integrate current main ownership and verification fixes
Use main’s shared canonical base64 schema and lifetime/UID facts. Consolidate traced ownership attribution with the strict PID/path policy, preserving exact ps arguments, thread-group boundaries and both historical-PID controls. Remove superseded schemas, classifiers and absence controls; declare alias and same-process attribution gaps.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-19 16:30:12 +00:00
gensokyo-dev 6768d4ab52 fix(process): keep ownership retries on the native clock 2026-10-19 16:16:28 +00:00
morluto aacf740a04 fix(ci): correlate ownership trace threads and preserve setup failures
Follow CLONE_THREAD edges across strace -ff files when excluding the ownership process's stat/status reads. Keep provider child processes outside the allowance and document the same-process attribution limit.

Validate setup result array shapes and preserve the original failed-plan JSON instead of masking it with a diagnostic TypeError.
2026-10-20 00:05:22 +08:00
morluto 0949313d8f fix(schema): compose portable stack-safe base64 constraints
Replace the lookahead-based pattern with separate allOf/not JSON Schema rules for quartet length, alphabet, padding and canonical pad bits. Share the runtime predicates with HAR and padded base64 parsing.

Validate converted advertised leaves with the MCP SDK validator, preserve permissive versus canonical semantics, and exercise every pattern near the 32 MiB encoded-input budget in all JavaScript modes.
2026-10-20 00:05:22 +08:00
morluto 4af71a45f9 fix(process): reconcile native lifetime and selective Linux UID facts
Settle absent and zombie candidates before retaining baseline or token-read failures. Preserve fail-closed behavior for live and unknown generations, and stop retrying exited candidates.

Bind Linux effective UID to stat-bracketed status reads only for unreadable-token candidates, preserving partial identity facts and avoiding full-table UID enrichment.
2026-10-20 00:05:22 +08:00
gensokyo-dev 818a9c6dfe chore: integrate I/O priority coverage and selector controls
Preserve the shared syscall catalog and the explicit unverified coverage for
other PID-directed interfaces. Consolidate I/O priority cases while retaining
UID, self, distinct-PID, cross-selector and unresolved-target controls.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-19 16:00:40 +00:00
Edgar Arakelyanandgensokyo-dev 60bd646478 feat(mcp): add opt-in streamable HTTP transport (#4955)
Add an explicit Streamable HTTP entry for environment/gateway hosts while keeping stdio registrations and default behavior. Preserve the shared provider/session owner across DELETE and replacement; fence and drain tool/completion work before handover or teardown.

Bound HTTP input and plain-response admission, cancel refused bodies, join whole exchanges and asynchronous response cleanup before provider hooks, gate startup readiness, and reject queued HTTP/1.1 pipelining while retaining sequential keep-alive.

Validation: 8 static/build tasks, 83 adapter tests and registry metadata pass. A real installed gh binary produces seven equivalent CLI/stdio/HTTP reports with DELETE/replacement and clean signal shutdown. Broader local native-provider/ownership failures reproduce on clean main and are documented with limitations in the PR.

Co-authored-by: Edgar Arakelyan <edgar.arakelyan@scale.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-19 23:58:51 +08:00
gensokyo-dev 1c73ea7e4e chore: integrate portable schemas and PID target contracts
Keep one producer-owned PID syscall catalog while incorporating the portable
canonical-base64 schema fix. Consolidate equivalent resource cases around the
stronger read/write, failed-attempt, self and distinct-PID controls.

The integrated policy and base64 families pass 91 tests across four files.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-19 15:39:50 +00:00
gensokyo-dev 1130d1b222 fix(ci): classify I/O priority and qualify PID trace coverage 2026-10-19 15:28:47 +00:00
gensokyo-dev 128610df12 fix(ci): share explicit PID syscall contracts with tracing
Derive tracer selection and reported coverage from the same named target
contracts used by the access checker. Cover resource limits, scheduler calls,
process metadata, PID groups, capabilities and pidfd operations without mixing
UIDs, policy enums, self selectors or output values with target PIDs.

Interpret each target once and retain unresolved target facts as a distinct
failure. Emit the coverage catalog once per verifier result.

The previous oracle misses 28 new controls. All 83 controls pass after the
change; real native resource/scheduler probes capture 14 previously missed
calls with resource limits and affinity unchanged. All 35 selected syscall
names are accepted by the pinned local strace.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-19 15:25:11 +00:00
gensokyo-dev 99cec9a56e fix(schema): preserve portable large base64 validation 2026-10-19 15:17:47 +00:00
gensokyo-dev 73c88afb87 fix(ci): reject historical PID resource and scheduler calls 2026-10-19 15:12:14 +00:00
gensokyo-dev 9c49e7a24c chore: integrate historical PID priority verification 2026-10-19 14:58:53 +00:00
gensokyo-dev 26b870b1b2 fix(ci): preserve C-quoted components in traced path checks
strace renders non-ASCII pathname bytes as C octal escapes, not JSON strings.
Keep those components opaque when resolving literal ASCII path separators and
proc PID selectors, matching the existing absolute-path interpretation.

Two controls fail before the correction and all 35 pass afterward. An actual
strace observation independently reproduces the rejection of an unrelated
Chinese filename and verifies the corrected classification.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-19 14:56:01 +00:00
gensokyo-dev 8dd8ca0804 chore: integrate current CI pathname verification
# Conflicts:
#	docs/recorded-crashes.md
2026-10-19 14:48:25 +00:00
gensokyo-dev 1e84699018 fix(ci): reject priority access to historical PIDs 2026-10-19 14:46:50 +00:00
gensokyo-dev 5c656717ef test(ci): declare unresolved legacy pathname coverage
Report the historical-PID access surfaces actually checked and explicitly mark
legacy cwd-relative pathname calls unverified. The existing tracer does not
provide their cwd identity, and a blanket rejection also rejects legitimate
GDB build-ID metadata queries.

Retain every committed access guard and document the preexisting limit without
claiming absence from missing path evidence. The complete real 44-case CLI/MCP
recorded-crash qualification passes with the coverage declaration.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-19 14:45:05 +00:00
gensokyo-dev 804caa2cb2 chore: merge latest main for CI verification 2026-10-19 14:19:22 +00:00
gensokyo-dev 5d2895d2b2 fix(ci): resolve traced directory paths across pathname syscalls
Classify producer-decoded FD/path pairs once instead of limiting failed relative
lookup detection to openat on /proc. This preserves attempted readlinkat, statx
and newfstatat accesses with no returned descriptor.

Three regression cases fail against the previous policy and all 33 controls
pass with the shared pathname interpretation.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-19 14:19:22 +00:00
gensokyo-dev d34c8514a1 fix(ci): trace historical PID handles and signal probes 2026-10-19 14:14:27 +00:00
morluto 255d906e15 fix(native): scan byte-pattern inputs without regexp stack growth
Keep exact wildcard, whitespace and aligned-mask validation in the shared
domain refinement. Advertise descriptive string inputs instead of repeating
regexes, and remove discarded byte/mask array materialization.

Preserve caller spelling and error precedence; cover large public stdio
queries, provider-boundary parsing and connection recovery.

Fixes #5257
2026-10-19 22:09:42 +08:00
morluto 49b4edfe77 fix(browser): validate large base64 without regexp stack overflow
Share padded decoding across CDP response shapes and cache fingerprints,
and count binary WebSocket bytes without allocating a decoded buffer.
Preserve HAR canonical pad bits and validate before allocation.

Replace repeated alphabet quartets in canonical schemas with separate
alphabet, padding and fixed-width length assertions. Cover near-32MiB
encodings under ordinary, Unicode and Unicode-set modes, plus complete
4MiB CLI and MCP retained-evidence export workflows.

Fixes #5253
2026-10-19 21:46:23 +08:00
gensokyo-dev b82ae1962f test(ci): verify decoded historical PID controls before tracing 2026-10-19 13:40:12 +00:00
gensokyo-dev b32ce58c3a fix(ci): distinguish process inventory from historical PID lookups 2026-10-19 13:28:25 +00:00
gensokyo-dev 5f94077b3c fix(process): classify baseline cleanup with current ownership facts
Use the pre-launch baseline only to select candidates for current native
identity/token validation. Preserve confirmed absence and verified foreign
generations instead of carrying a premature baseline identity failure.

Exercise the real Linux enumeration/exit race and retain countercontrols for
unknown identities and live token-owned processes.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-19 13:11:13 +00:00
gensokyo-devandKaoru0822 3ea0d9489e feat(objdump): select native disassembly by symbol (#5171)
Push optional native symbol selection into GNU objdump before collecting Evidence. Preserve native matching, raw output, artifact identity, scoped limitations and the existing full-disassembly default through the shared CLI/MCP workflow.

Fixes #5159

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-19 20:15:20 +08:00
morluto dc936f433c test(process): distinguish native preparation from capture allocation
A missing temporary path stops Darwin native-inspector preparation before
capture allocation can account for resources. Keep its progress coverage
unknown; Linux reaches the capture root allocation and reports not-required
resources. Assert the public typed failure preserves the selected temp path.

The combined Electron/progress focused rerun passed 33 tests on macOS arm64
with Node 24.18.0. The seven progress cases passed; native Linux was not run.
Static checks, docs checks and test discovery also passed on the final tree.
2026-10-19 20:04:00 +08:00
morluto 49e67aa1d9 fix(process): retain native ownership evidence through cleanup
Keep a run-scoped evidence owner from acquisition through settlement and
cleanup retry. Bind token observations to native generations and retain
related generations and unresolved identity lookups across table omissions,
reparenting and process-group changes without treating PID hints as authority.

Use native effective UID facts for withholding decisions, corroborate Linux
procfs absence, and share the Linux stat parser with sampling and debugger
identity checks. Signal only after current token and group revalidation.
Complete swept cleanup across all groups with one bounded final family check;
retain unresolved owners and successful-peer completion across retries.

Validation: npm run check, docs:check and test discovery passed. Focused
ownership/consumer coverage totals 513 passed and 1 skipped across 35 files,
including the corrected Electron cancellation test rerun independently. Darwin helper compilation, real
owned Node child cleanup, CLI/MCP capture and retained cleanup retries ran.
Real Electron applications, native Linux races/PID reuse and Windows cleanup
were not qualified. The original Linux reports remain open for that work.

Fixes #5238
Refs #4322, #5206
2026-10-19 20:04:00 +08:00
gensokyo-dev 0fc8462be1 fix(tests): complete independent agent evaluation cleanup
Attempt independent auth and run-tree cleanup even after permission denial,
retaining the primary verification failure alongside cleanup errors. Exercise
both retention modes through the verifier entrypoint, preserve startup
diagnostics, and retain cooperative coverage for root.

Fixes #5095

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-19 11:54:04 +00:00
gensokyo-dev b999e72476 fix(ci): repair capture ownership and portable ABI validation (#5224)
* fix(tests): restore reliable snapshot and container CI checks

Keep exact cancellation causes and partial snapshot facts in regression oracles. Match fault injection to real directory handles and isolated MCP module ownership; await terminal cleanup progress within the existing test deadline. Reuse the valid ASAR Pickle fixture and preserve truncated-container rejection.

* fix(tests): isolate runtime faults and own CLI subprocesses

Keep the runtime provider mock in the isolated project after reused CLI graphs exposed lost fault injection. Use the existing owned CLI fixture for Inspector parity and update command checks, retain caller environment choices, and require the removed alias to fail with COMMAND_NOT_FOUND. Keep current test deadlines and production behavior.

* fix(process): retain executable handles through read cancellation

Use the existing borrowed descriptor reader so stream cancellation cannot invalidate a handle owned by capture. Preserve the exact cancellation and permit immediate scope reuse after cleanup. Reproduce the native-stream failure with actual file IO and retain completed/failed-close controls.

Synchronize runtime cancellation and backwards-clock injection with observed running progress. The corrected clock oracle now rejects a Date.now-based deadline under controlled rollback; keep test deadlines and narrow host cleanup checks unchanged.

* test(process): observe prelaunch cancellation at descriptor reads

* fix(process): retain read failures alongside observed cancellation

* fix(flutter): advertise portable Unicode ABI selectors
2026-10-19 19:32:22 +08:00
morluto a0edd145d3 fix(analysis): preserve input diagnostics and reuse JEB contracts 2026-10-19 18:45:48 +08:00
morlutoandYi-111-a 64abd4aefb fix(flutter): select reported ABI labels through shared contracts
Reuse canonical CLI fields and preserve literal archive labels through exact selection. Keep UTF-8 path budgets at inventory while advertising the same bounded Unicode selector that runtime admission enforces.

Co-authored-by: Yi-111-a <153097222+Yi-111-a@users.noreply.github.com>
2026-10-19 18:38:57 +08:00
morluto 69aa5465cd fix(frida): preserve resume failures across caller cancellation 2026-10-19 18:21:16 +08:00
morluto 2ec602b191 fix(frida): clarify device selection and cleanup contracts 2026-10-19 18:17:54 +08:00
morluto 44b6ec97ee fix(frida): retain cancellation through final session cleanup 2026-10-19 18:17:45 +08:00
morluto 69fe86c5c7 fix(frida): separate attachment from target resume observations 2026-10-19 18:11:27 +08:00
morluto 00dd959b82 fix(mcp): derive shared provider cleanup from loaded ports
Separate load-failure metadata from the typed optional observation ports
and derive the process cleanup inventory from those ports. This includes
the JavaScript runtime owner and removes the separate four-provider list.

Preserve all load failures in server injection and keep shared providers
caller-owned across individual server closure. Retain failed close hooks
for retry while removing peers whose cleanup completed.

Validated with 19 focused lifecycle/isolation checks and a final rerun of
the new boundary regression, check, docs and exact test discovery. The
runner test uses real idle providers with controlled SDK/shutdown handles
and a close rejection; active Inspector resource consequences, native
Linux/Windows and end-to-end stdio shutdown remain unverified.

Fixes #5222
2026-10-19 18:03:22 +08:00
morlutoandPrabhuram Karki 435efe7afc fix(frida): share exact JSON string byte accounting
Count the serialized JSON representation at its owner, including escaped
lone UTF-16 surrogates. Frida now retains the correct bounded prefix and
reports truncation in script results and subsequent session Evidence.

Move the existing exact managed string counter into the domain layer and
use it for Frida, managed projections and Ghidra inline PDB caveats. Remove
the superseded counters while keeping Ghidra's bounded length guards and
NativeAOT's distinct raw-byte admission before string allocation.

Validated with 296 focused tests, check, docs and exact test discovery.
The Unicode oracle checks every UTF-16 code unit and adjacent fragments
against native JSON encoding. Frida execution uses simulated native handles
through the real MCP handlers/client; real target instrumentation is unverified.

Fixes #5097

Co-authored-by: Prabhuram Karki <prabhuramkarki07@gmail.com>
2026-10-19 17:50:50 +08:00
4cbcead46c fix(frida): share canonical discovery results across adapters
Own device and process discovery projection in the application workflow,
bound to each named output contract. CLI and MCP now consume that result
directly, including retained observations when final CLI cleanup fails.

Remove the duplicate adapter projections and preserve provider failures,
caller-selected identifiers, process records and cleanup diagnostics.

Validated with 103 focused tests, npm run check and docs:check. Real local
Frida 17.23.2 discovery on macOS arm64 returned the same three devices
through the compiled CLI and production stdio MCP; both now pass the
advertised schema. Remote endpoints and native Linux/Windows unverified.

Fixes #4637

Co-authored-by: shreyansh1729 <shreyanshiitian1729@gmail.com>
Co-authored-by: Kaushalendra-Marcus <yadavkausha4a5@gmail.com>
2026-10-19 17:35:10 +08:00
91884c3743 fix(ghidra): own operation-scoped JVM failure evidence
Scan provider output before retention and keep bounded confirmed token facts
through output completion. Exclude identifier prefixes, pre-checkpoint context,
and unconfirmed tails; preserve invalid UTF-8 and directional truncation facts.

Make confirmed OOME observations authoritative for projection. Retained raw
prefixes cannot establish an OOME, and unrelated output cannot supply its
resource kind or recovery advice. Incomplete no-OOME output preserves the
primary error and explains uncertainty. Current checkpoint coverage remains
separate from historical budget loss.

Adapt the retention approach from #4774 with independently reproduced scanner
and projection counterexamples corrected before integration.

Validation: 268 focused tests, npm run check, npm run docs:check, and test
discovery (1639 files exactly once) pass. Controlled Node pipes/socket and fake
Ghidra JVM only; real Ghidra and native Linux/Windows behavior are unverified.

Fixes #4682
Fixes #5220

Co-authored-by: reason-machines[bot] <293529679+reason-machines[bot]@users.noreply.github.com>
Co-authored-by: Saim Shafique <msaimshafique4664@gmail.com>
2026-10-19 17:15:32 +08:00
morluto 048d70755e fix(frida): preserve script evidence through cancellation and decoding
Keep per-script messages and truncation in one owned capture through native
load completion and awaited cleanup. Return cancelled partial observations
when cancellation is observed at native completion, including native rejection;
retain failed cleanup for retry and preserve earlier failures during cleanup.
Report missing creation handles without claiming the engine did no work.

Hash original script-file bytes and retain replacement-decoding provenance
without changing normalized CLI/MCP result schemas or accepted file behavior.
Share this projection across persistent and one-shot Evidence.

Validation: 103 focused tests, final 38 manager source tests, npm run check,
and npm run docs:check pass. Controlled public CLI/MCP workflows and fake
Frida bindings only; no real target injection or device verification.

Fixes #3979
Fixes #3396
2026-10-19 16:41:15 +08:00
morluto 39275420ea fix(process): preserve cancellation through liveness rechecks
Forward the accepted observation signal into per-member process-table
rechecks and preserve its exact cancellation reason. Keep uncancelled
inspection failures unverifiable and guard successful late completions.

Fixes #5205
2026-10-19 15:52:36 +08:00
morluto ca71e91d23 fix(process): await owned observation commands through finalization
Supervise sampler and ownership-query commands through physical exit on
cancellation. Share Darwin helper command ownership, reject new commands
after close starts, and drain admitted commands before removing the root.
Keep failed root cleanup retryable without rerunning completed queries.

Fixes #5199
Fixes #5202
2026-10-19 15:37:15 +08:00
morluto ba866a26ec fix(process): preserve partial sampling observations and shutdown gaps
Keep procfs absence separate from denied and failed reads. Carry successful
rows, thread children and bounded diagnostics together so one failed sibling
cannot erase readable peers. Retain root initialization failures and validate
ps-discovered Linux candidates through stable procfs identity brackets.

Await issued reads during shutdown, retain completed rows and report an
unfinished pass through the existing sampling failure/diagnostic contract.
Derive partial coverage at its owner and preserve actual read errors when
shutdown also interrupts observation. Keep the public capture schema unchanged
and verify it with the previous strict capture reader.

Update directly affected coverage consumers and regression fixtures, including
identity contradictions, mixed outcomes, late failures, cleanup, cancellation,
process-only comparison unknowns and converted MCP schemas.

Validation: 12 focused files / 123 tests; full check; docs check (5 tests);
test discovery (1,635 files). Real macOS CLI/MCP controls exercised source-owned
PTY targets. Linux permission behavior uses deterministic boundary fixtures;
real Linux and Windows qualification remain unavailable. Completed CLI cost
comparisons do not establish a speedup.

Fixes #5081
Fixes #5194
2026-10-19 15:14:42 +08:00
morluto e8da7e1edd fix(artifacts): share bounded ASAR signature observations
Parse Pickle extents once at the ASAR boundary and carry finalized signature
facts through root and nested classification. Scan JSON whitespace within its
declared extent and decode budget without retaining the whitespace prefix.
Keep prefix storage bounded independently of stream chunk ownership.

Fill fixed ASAR prefixes and DMG trailers across short reads, preserve
cancellation through admission and stream EOF, and retain existing cleanup
ownership. Cover public CLI/MCP selection, root/nested inventory, malformed
JSON whitespace and padding, limits, native/XML consumers and descriptor faults.

Validation: 24 focused files / 170 tests; full check; docs check; test discovery.
Official inert ASAR fixtures and controlled descriptor faults were exercised;
real Electron execution, Windows and natural OS short-read frequency remain
unverified. Equivalent compact CLI tasks returned identical results and reply
token estimates; repeated timings do not establish a speedup.

Fixes #3574
Fixes #5188
2026-10-19 14:32:48 +08:00
morluto 2e5171e391 fix(browser): retain historical capture outcomes through cleanup 2026-10-19 14:03:57 +08:00
morluto 87ab054ea3 fix(runtime): retain Inspector and Electron cleanup ownership 2026-10-19 14:03:28 +08:00
morluto 7f4e7d5577 fix(browser): preserve caller cancellation through CDP observations 2026-10-19 14:00:01 +08:00
morluto 9aca543f46 fix(browser): isolate web bundle analysis with bounded partial results
Run inert captured-script analysis in owned children with per-script and aggregate deadlines, bounded source/result transfer and explicit per-script coverage. Preserve completed facts and exact cleanup authority across cancellation, mixed descriptor/process failures and cross-consumer retry.

Share aggregate source admission across page and Electron capture, expose CLI/MCP resource controls and retain selected parameters in Evidence. Verified with controlled CDP public workflows, real owned Node failure controls and the reporter-matching ReactDOM UMD artifact; real Chrome/Electron and Windows/Bun remain unqualified.
2026-10-19 13:22:54 +08:00
morluto 715d93e954 refactor(process): share ownership for isolated analysis workers
Separate child and private-root ownership from JavaScript analysis protocols. Retain exact cleanup lifetimes across retries, late handshakes and runtime reuse; observe request-stream errors and preserve per-job file cleanup during worker reuse.
2026-10-19 13:12:25 +08:00
e4c3d72396 fix(javascript): converge cyclic aliases with explicit projection widening
Replace initializer-history and full-path enumeration with a finite projection
join at each source read. Retain conservative local returned-reference effects
and disclose precision loss through static, semantic and captured-web results.
Close full-binding callback cycles while preserving narrowed read semantics.

Fixes #4348
Fixes #5138
Refs #4349
Refs #4364

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Fuxuan-CN <3072252442@qq.com>
2026-10-19 12:26:54 +08:00
morluto 9af0b6113c fix(process): retain snapshot handles and partial read outcomes 2026-10-19 11:37:41 +08:00
morluto 974487f00f fix(process): preserve cleanup ownership through retries and close
Carry historical cleanup reports with the exact lease that can confirm
release. Bind originating capture errors and typed retry aggregates to
those owners while preserving primary failures and completed observations.

Keep those bindings through MCP close and compose mixed session/process
cleanup failures. Start both close operations even when a child throws a
typed failure synchronously.

Fixes #5144
Fixes #5163
Fixes #5166
2026-10-19 10:52:55 +08:00
morluto dfe8378cf5 fix(electron): preserve callback ownership through listener removal
Keep canonical callback ownership independent of writable raw-listener
metadata. Resolve the native removal argument in current registration order,
then let EventEmitter own mutation, getter timing and removal meta-events.

Leave registrations unwrapped with explicit observation gaps when methods
or receivers do not support that ownership model. Preserve per-callback
Evidence for supported registrations and document the remaining limits.

Fixes #4513
2026-10-19 09:51:04 +08:00
morlutoandDeryFerd d6ca7b3f20 fix(process): gate launch and retain cancellation provenance
Check cancellation at the PTY execution boundary after executable sampling
and descriptor cleanup settle. Completed file observations cannot authorize
launch for a cancelled request. Preserve exact caller reasons in the shared
capture cancellation constructor and its admission, exit and finalization
consumers instead of reconstructing them downstream.

Exercise real executable reads and closes through the capture API with a
throwing PTY sentinel at five schedules. Retain a real completed Node capture
and its cleanup facts when the final progress callback cancels the request.
Strengthen existing metadata and baseline cancellation controls.

Adapted after review of #4836 at 014afa3892.
Raw snapshot/sampler descriptor cleanup ownership remains tracked in #5140;
this execution-admission change does not claim to solve failed close recovery.

Closes #4512
Closes #5142

Co-authored-by: DeryFerd <deryferdikao125@gmail.com>
2026-10-19 09:14:00 +08:00
morlutoandshreyansh1729 d3627b1038 fix(mcp): preserve procedure aliases and complete name ambiguity
Derive address suggestions separately from name uniqueness across every
validated inventory row. Keep the sole exact address or an explicit ambiguous
state per name, without retaining a set of all name/address pairs. Reuse the
canonical address/value leaf contract for completion's parsed facts.

Cover order independence, same-address duplicates, later ambiguity and alias
rows beyond the MCP reply limit through the public SDK. Preserve provider
spelling, document context, cold-session admission and cancellation behavior.

Adapted from #4648 at 5b019e1179.

Closes #4623

Co-authored-by: shreyansh1729 <shreyanshiitian1729@gmail.com>
2026-10-19 08:54:23 +08:00
Vaidehi Kakad 273bb66276 fix(setup): treat empty APPDATA as unset for VS Code, Trae and Devin (#5126) 2026-10-19 08:45:04 +08:00
morluto 6296fdf560 fix(reference)!: preserve symlink races and root failure facts
Classify replacement EINVAL at the readlink syscall so the reader and importer
retain sibling observations. Give an admitted root's enumeration failure its
own typed field, use it for unresolved symlink coverage, and project it as a
graph limitation instead of an invalid dot-path child entry. Keep admission,
cancellation and cleanup failures distinct.

Closes #5135
Closes #5136

BREAKING CHANGE: Partial reference-source reader results report failed root
enumeration in rootFailure instead of a failed directory child at path ".".
Historical source graphs preserve the root failure as a top-level limitation.
2026-10-19 08:36:53 +08:00
morlutoandrudrakshagarwal4200-ai c85b44e1b1 fix(process)!: retain partial filesystem snapshot observations
Keep expected readlink and follow-up lstat failures as typed entry omissions,
including the observed path and errno. Retain directory metadata and sibling
observations, distinguish known identity replacements, and keep cancellation
and unexpected I/O failures terminal. Reuse admitted root metadata and test
cancellation by descriptor state rather than a count of named lookups.

Adapt the symlink race handling proposed in #4587 at fae4e25539.

Closes #4575

BREAKING CHANGE: Filesystem enumeration omission reasons now also include
entry_unavailable and identity_changed. Clients validating the old literal
reason must accept the expanded capture schema.

Co-authored-by: rudrakshagarwal4200-ai <rudrakshagarwal4200@gmail.com>
2026-10-19 08:34:39 +08:00
morlutoandDragolone 95c8f57aa2 fix(investigation): scope automatic unknowns to result Evidence
Construct automatic unknown identity once at the application boundary.
Validate the original question before adding immutable Evidence scope, and
preserve each result's supporting link through CLI and MCP producers.

Apply the shared policy to derived investigations, managed comparisons and
verification, composed workflow residuals, and process-capture residuals.
This prevents registry conflicts and silent loss of later result links.
Keep explicit creation/update semantics and exact Evidence replays intact.

Cover all affected producer families with public MCP regressions, preserve
snapshot provenance distinctions, and retain blank-question/error handling.
Remove the superseded single-result call-path test.

Fixes #3333

Co-authored-by: Dragolone <160818051+Dragolone@users.noreply.github.com>
2026-10-19 08:02:03 +08:00
morlutoandHenglie 92dadf9334 fix(domain): preserve partial reference comparison facts
Own endpoint identity and per-edge kind knowledge in one parsed reference
representation. Preserve exact same-artifact coordinates and cross-artifact
name uncertainty, including generated and nonunique procedure labels.

Use exact multiplicity-preserving sparse compatibility flow instead of
positional/greedy pairing or a quadratic adjacency matrix. Share the native
coordinate parser with call paths and remove the superseded projections.

Validate public MCP comparison/reconstruction outcomes, independent tiny
permutation oracles, dense matching and advertised JSON Schemas.

Fixes #4210
Fixes #5131

Co-authored-by: Henglie <ebhenglie@gmail.com>
2026-10-19 07:45:34 +08:00
morluto 559af3d3ff fix(uninstall): retain per-file partial outcomes
Preserve configuration paths and constituent actions independently of aggregate status. Derive summaries from all leaf outcomes, including after final cleanup reporting, so a later failure cannot hide an earlier removal.

Closes #5079
2026-10-19 07:22:01 +08:00
morluto a80575c736 fix(native): preserve partial call reference evidence
Retain provider-reported call sites and raw classification independently of generic reference flags. Keep all endpoint evidence when containing-procedure routes merge, and include relation in edge identity to avoid order-dependent labels.

Closes #5130
2026-10-19 07:12:44 +08:00
morluto fdaffe21cc docs(manifest): align plan with top-level body parsing 2026-10-19 07:08:20 +08:00
291059adb4 feat(analysis-view): project an environment manifest from web network captures (#4954)
* feat(analysis-view): project an environment manifest from web network captures

Add the environment-manifest view kind to inspect_analysis_view for retained
HAR Evidence: the primary origin's recorded request lines become a
deterministic tool surface (names, path templates, parameters with their
rule and basis, observed query names, value-free body shapes, record
pointers), with excluded groups, three fixed unknowns and the shared
projection budget. The four format rules always apply; after-uid-literal,
opaque-token and sibling-variance are opt-in and labelled, and literal
fold-in never touches a format-rule parameter. The api-surface accumulator
moves onto shared route, media-type and budget helpers without behaviour
change.

Refs morluto/rea#4933

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(web-network): check the manifest refusal text like the api-surface refusal

The real-capture verifier stringified the whole MCP result for the
environment-manifest refusal, so a declared "[" literal matched the result
envelope itself; compare the parsed refusal as the api-surface branch does.

Refs morluto/rea#4933

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs(specs): record the hosted web-network lane run for the manifest view

Refs morluto/rea#4933

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs(specs): reconcile the manifest view verification scope note with the hosted run

Refs morluto/rea#4933

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(analysis-view): bound body, route and name work in the environment manifest

Addresses the automated review findings on the PR: read request bodies at the
top level only instead of walking nested values; admit every literal route
part before materializing it; compare at most 32 segments in sibling-variance
and say so; keep stop words literal after a uid literal; keep the next
collision suffix per tool-name base; preserve a templated exclusion when two
groups print the same row.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(analysis-view): keep manifest folding, naming and media-type reads linear

Addresses the second automated review round: fold literal siblings through
set membership, key collision suffixes by the truncated name they share, and
charge a request media type before it is scanned.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(analysis-view): charge the manifest group key before building it

Addresses the third automated review round: the composite key copies the
method, origin, template and rules, so that copy is reserved before the key
is stringified.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(analysis-view): accept a +json suffix only on application media types

Addresses the fourth automated review round: `image/example+json` or
`text/example+json` no longer counts as JSON for origin selection, exclusion
or body shapes, matching the documented `application/json` and
`application/*+json` contract.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(analysis-view): require the capture parent's exact subject for a manifest

Addresses the fifth automated review round: the manifest cites the report
path and digest, so a parent whose subject is absent or names another path or
SHA-256 is refused at admission, as the capture view already does; the
api-surface view keeps its existing admission.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(analysis-view): share truncated suffix allocation work

Track suffix progress by the actual truncated prefix and suffix width. Distinct full names can collide only after suffix truncation; sharing that progress prevents quadratic rescanning while preserving shorter free names and existing allocation order.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>

* fix(analysis-view): merge only identifier-like siblings under sibling-variance

Addresses the sixth automated review finding: a bucket merged whenever one
literal carried a digit, folding plain words such as `mine` into the
parameter. The rule now partitions the bucket, merges the identifier-like
siblings and leaves the other literals as their own tools.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(analysis-view): combine qualifying sibling cohorts

Keep coded identifiers and a qualifying plural hyphenated cohort in one eligibility Set before checking the minimum merge size. Read each literal once and reuse the same membership at the consumer, preserving non-identifier routes and the three-hyphen minimum.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>

* docs(analysis-view): clarify opt-in sibling folding

State the additional sibling-variance selection in the guide, acceptance specification and MCP parameter description. Preserve the existing single-rule behavior and caller-selected inference rules.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-19 07:07:37 +08:00
morluto 65884350ff fix(native): retain partial call routes and omitted sites
Separate enumeration outcome from retained facts in the native call-route
owner. Keep every available typed call with its source provider and site,
supplement incomplete kinds with inferred fallback targets, and retain
known routes when fallback fails. Per-reference unknowns take precedence
over aggregate availability; cancellation remains terminal.

Project partial routes before enumeration failures, preserve each omitted
route's relation, and include its call site in the omitted-edge identity
so distinct observations to one target cannot overwrite each other.
Remove the superseded success-only provider/result representation.

Validation: 69 focused cases plus final 30-case rerun, including nine
public SDK MCP regressions; full static/architecture, docs and discovery
checks pass. Controlled-provider source REDs reproduce both route loss
and omitted-site collisions. Real native providers remain unverified.

Closes #5073
Closes #3922
Closes #5128
2026-10-19 06:48:14 +08:00
22ddd82014 fix(uninstall): preflight repeated registration ownership
Read shadowed registrations from the effective JSONC syntax tree before
any client is changed. Share the same typed ownership decision with the
reread before removal, including foreign OpenCode V1 fallbacks. Remove
all admitted duplicates using one member/separator planner and grant
serializer authority only for exact admitted paths.

Setup may remove its explicitly superseded OpenCode V1 path. Preserve
inactive repeated parents, unrelated entries, comments and source backups.
Use the pinned JSONC scanner instead of handwritten string decoding.

Validation: final 86 focused cases and 9 setup acceptance cases passed;
104 additional filesystem consumer cases passed. Static/architecture,
docs and discovery checks passed. A broader 186-case run had one OMP
timeout; its isolated 9-case rerun passed, with timeout cause unverified.
Controlled compiled CLI comparisons verify removal/refusal and backups;
real developer-client execution remains unverified.

Adapted from #4977 at 4cd22d4ec2.
Closes #4976

Co-authored-by: Nikhil Bhagat <knewboy.nykhil@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 06:32:14 +08:00
morluto d1adc60795 test(contracts): align plist and UI finalization regressions
Update public-boundary expectations after the explicit XML unknown-scalar
and native UI deadline provenance changes. Retain raw malformed literals,
independent exact integers, expanded-year ISO dates, and partial UI reports.
Assert successful cleanup releases its lease and failed cleanup retains it
until close retries. Keep malformed-input and true date-range coverage.

The shared number fixture owns CLI/filesystem/MCP expectations. Native
plutil controls confirm integer entities are invalid plist literals, even
though they are valid XML. No runtime behavior or CI gates change.

Validation: 187 source cases, 138 focused public cases, final 97-case
rerun after fixture typing/group changes, full static/architecture checks,
and test discovery (1591 files).
2026-10-19 06:22:32 +08:00
morluto 32f0e51209 fix(session): describe native UI trace source routes
Share source operations with execution owners and derive availability and missing prerequisites from one evaluation. Distinguish authored UI dispatch from native-seed call tracing without inventing a default request mode. Preserve target gates, typed failures and partial results.

Fixes #5071
2026-10-19 03:39:02 +08:00
morlutoandMert Kaya 29910d16b9 fix(apktool)!: select numeric regions using Android b+ qualifiers
Normalize three-digit region aliases at the shared locale owner, preserving
caller labels and physical-table reuse. Reject malformed legacy qualifiers
through the same CLI/MCP contract and table classifier.

Adapt the owner correction and regressions from PR #4918 after checking Android
and supported Apktool qualifier sources. Add public MCP validation and preserve
existing two-letter regional selectors.

Fixes #4916

BREAKING CHANGE: Numeric legacy locale selectors such as es-r419 are rejected.
Use es-419 or b+es+419. Two-letter region selectors remain supported.

Co-authored-by: Mert Kaya <47145541+mertkayacs@users.noreply.github.com>
2026-10-19 03:25:25 +08:00
morluto 50b6975d86 fix(session): admit direct native dispatch metadata providers
Share named metadata source operations between execution and capability discovery. Preserve symbol fallback and typed runtime failure behavior, and cover availability through public MCP workflows.

Fixes #5070
2026-10-19 03:19:33 +08:00
morluto 1d5bf5ff08 fix(session): align call relationship discovery with traversal modes
Declare the missing trace composition and correct call graph prerequisites to require address resolution plus the selected relationship direction. Report forward/backward modes and the actual default independently, preserving missing operations, owner failure reasons and direct partial outcomes.

Share the direction-to-provider mapping across runtime and discovery, reuse the mode evaluator, select defaults by name, and check composition coverage against every canonical enhanced contract. Keep same-endpoint traces callable without relationship reads.

Adapt the missing trace-composition correction proposed in PR #4729 and complete the directly related ownership/refactoring and sibling graph correction.

Validation: 75 source tests and 76 public MCP/schema tests passed; full static/architecture checks, docs and test discovery passed. Controlled SDK/provider workflows verified unchanged catalogs and normalized traces. Small whole-session costs were recorded, with no speedup claim. No native-engine, CLI, Linux/Windows or model tool-selection qualification.

Fixes #4687
Fixes #5068
Co-authored-by: AHMED <aptech356@gmail.com>
2026-10-19 03:08:39 +08:00
morluto 3537e58c1a fix(plist)!: preserve unknown XML scalar identities
Interpret complete scalar source at the XML owner instead of accepting numeric prefixes, permissive date strings or nonempty booleans. Retain malformed content as explicit unknown scalars with original literals and reasons, while preserving the surrounding archive and independent numeric facts.

Share the representation across plist, keyed archive, Interface Builder and entitlement projection; remove the superseded numeric fallback and helpers. Parse date fields as UTC, retain real entity/CDATA semantics, and distinguish native integer/real whitespace without ambiguous whitespace backtracking.

Validation: 276 source tests and 60 compiled/public tests passed, with updated scalar regressions rerun; static, architecture and docs checks passed. Native macOS plutil controls and CLI/MCP source-hash/time-zone controls executed. No Linux/Windows or deep-provider qualification. Tiny completed CLI task costs recorded; no performance improvement claimed.

BREAKING CHANGE: Unresolved XML scalar values now use $plist_type unknown wrappers with element, literal and reason. This replaces the former real/null unknown marker and malformed scalar prefix fallback. Supported extended UTC years now preserve their timestamp.

Fixes #4852
2026-10-19 02:48:09 +08:00
morlutoandAvichal Pandey cee95b2ae6 fix(plist): preserve source semantics in XML data decoding
Adapt the completed-quartet decoder from PR #4981 at 4cf6cac14. Bind raw source spans to validated DOM nodes before entity and line-ending interpretation can change data bytes. Preserve depth preflight, reject invalid data forms and allocate exact decoded output through one shared quartet grammar.

Fixes #4978

Co-authored-by: Avichal Pandey <avichal2018lko@gmail.com>
2026-10-19 02:28:27 +08:00
morluto eb2c3b589e fix(native): retain LLDB evidence prefixes after read failures
Return byte prefixes with tagged read outcomes and exact causes. Share those facts across partial journals and captures, preserve typed primary failures and successful siblings, and keep zero-byte failures unavailable. Retain failed descriptor and root owners through retry.

Fixes #5058
2026-10-19 02:06:07 +08:00
morluto d4e233946a fix(errors): retain secondary failures without replacing primary causes
Give the typed error owner a separate retained secondary-failure collection. Preserve exact direct causes, including caller cancellation reasons and absent causes, while keeping existing diagnostic and live cleanup ownership projections.

Fixes #5059
2026-10-19 01:56:58 +08:00
morluto 292e7bef27 fix(native): bound LLDB PID reads before validation
Derive the read limit from the accepted safe decimal PID plus a tolerated CRLF and overflow sentinel. Retain short-read handling, cached valid facts and existing descriptor ownership and handshake semantics.

Fixes #5057
2026-10-19 01:48:37 +08:00
morluto 36d156ff05 fix(native): retain UI interruption source through final cleanup
Record caller cancellation versus the owned deadline once and share that provenance through helper execution, scenario waits and finalization. Preserve independent failures and partial reports, consolidate scenario failure handling and dispose listeners on every exit.

Fixes #5056
2026-10-19 01:41:52 +08:00
morluto 7201e8a443 fix(native): validate LLDB readback encoding before reporting facts
Decode completed journal rows strictly while retaining valid neighbors and torn-tail semantics. Preserve structured result read, decoding, JSON and schema failures through the typed fallback.

Fixes #5055
2026-10-19 01:41:48 +08:00
morluto 9e259f87c8 fix(native): retain signature roots until descriptor cleanup completes
Give each signature snapshot a private child-resource scope. Its composite
root lease closes those children before removing the directory and retains
both stages across failed retries. Bind local cleanup failures to their
exact owner so child release cannot clear a failed root removal.

Replace the mixed-outcome regression that expected premature root removal.
Cover real descriptor denial, primary/cancellation preservation, MCP close
and same-connection recovery. Expose underlying real codesign test errors
before asserting result fields.

Fixes #5052
2026-10-19 01:24:40 +08:00
morlutoand星闌 8307ea3717 fix(adb): preserve command failure target identities
Keep the selected device, addressed file and actual host operand distinct
at the command owner. Parse known device and file diagnostics before
projection, including AOSP host write/read failures and exact snapshots.
Classify complete captured stderr before shortening display text, and
scan leading notices without expanding the capture into a line array.

Adapt Xinglan233's PR #4655 and extend its source-shaped host controls.
Add built CLI/MCP identity, long-path, recovery and input-preservation
coverage. Real platform-tools and Android devices remain unverified.

Fixes #4641
Fixes #4643
Fixes #5051

Co-authored-by: 星闌 <xinglan233@163.com>
2026-10-19 01:13:57 +08:00
morlutoandMangolycheematcha fd728f271e fix(plist): ignore processing instructions between container members
Exclude processing-instruction nodes at the shared container-member owner
before dispatching plist tags. Keep strict syntax validation and scalar
content rules, with app-resolution and CLI/MCP evidence regressions.

Adapted from Mangolycheematcha's PR #4965, including its boundary controls.
Added built CLI/MCP coverage and verified container fixtures with plutil.

Fixes #4964

Co-authored-by: Mangolycheematcha <288892596+Mangolycheematcha@users.noreply.github.com>
2026-10-19 01:03:32 +08:00
gensokyo-devandKaoru0822 b0b485abff fix(hopper): verify and repair the Linux embedding runtime (#5041)
Verify the distribution Python embedding library during approved Linux Hopper
setup, conditionally repair the matching Ubuntu dependency, and confirm that
the library loads. Share fresh bounded observations with doctor, preserve
unknown configuration and caller cancellation, and join probe exit through
the existing process supervisor.

Validate clean Ubuntu installation, normal-user real Hopper CLI/MCP workflows,
independent ELF/SQLite oracles, cancellation and cleanup regressions, 154
focused checks and all 40 current-head CI checks. Preserve measured artifact
identity, failed attempts and local host-memory guard limitations.

Closes #5015.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-19 00:11:10 +08:00
gensokyo-dev 23f984b1a8 fix(tests): restore Android prerequisite verification
Supply a real retained resource owner to every Android verifier prerequisite
check, sharing the existing Ghidra verifier cleanup scope. Match recovery
checks to typed Java or archive failures and applicable remediation, preserving
exact close retry authority and primary failures.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-18 12:46:25 +00:00
gensokyo-dev 093ce695f0 fix(tests): preserve temporary fixture ownership
Normalize shared test fixture prefixes using the hygiene verifier ownership rule. Preserve caller labels, existing owned names, and third-party caches; cover retained fixtures and exact cleanup through subprocess regressions.
2026-10-18 11:34:44 +00:00
gensokyo-devandKaoru0822 63c970812b perf(hopper): reuse decoded records for literal string matches (#5017)
Keep complete decoded string records in Hopper's existing search inventory
and directly project literal matches, removing the redundant full record
projection and superseded value-only representation.

Record real Linux CLI/MCP correctness and Evidence checks, shorter warm
queries, negative whole-task costs, native coverage gaps and resource stops.

Fixes #5010.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-18 19:19:20 +08:00
gensokyo-devandKaoru0822 c12d9eda87 docs(jeb): qualify Linux CE native workflows (#5002)
Qualify the official Linux CE headless launcher and engine-native item references.
Record real native CLI/MCP qualification, costs, failures and integration controls.

Closes #4996

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-18 17:13:04 +08:00
morluto a25eb5fbb4 chore(release): sync 6.7.0 checkpoint
Preserve the immutable 6.7.0 tag ancestry and synchronize version metadata after verified npm publication. Keep newer main performance changes and the full 6.6.0 changelog.
2026-10-18 16:18:49 +08:00
github-actions[bot]andmorluto 27dc42d102 chore(release/6.7.0): release rea-agents 6.7.0 (#4983)
* chore(release/6.7.0): release rea-agents 6.7.0

* docs(release): finalize frozen 6.7.0 contribution notes

---------

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-18 15:40:45 +08:00
7c458f04b9 perf(apktool): avoid duplicated primary strings on request
Add opt-in string_tables_only and CLI --string-tables-only to keep selected
strings once in typed table facts. Preserve existing defaults and legacy replies;
charge aggregate output capacity for the copies actually requested.

Validate shared CLI/MCP behavior with independent XML oracles, three real APKs,
94 source tests, nine compiled boundary tests, 36 completed MCP tasks and three
CLI parity tasks. Preserve full task estimates, negative timings, resource
admission refusal and verification limitations in the measured report.

Fixes #4982

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-18 15:38:16 +08:00
8f7d12e30d perf(analysis-view): reuse validated immutable parents
Reuse successful format validation for exact authenticated immutable native and imported JavaScript results. Preserve schema normalization and alias topology before borrowing source data; owned JavaScript graph wrappers retain their existing metadata-normalization path.

Validated with 130 source tests, 36 compiled CLI/MCP boundary tests, 27 default-deadline integration tests, full checks/docs/build, and paired real retained-Evidence tasks. The report preserves cold costs, previous negative results, incomplete resource-stopped runs, and the limits of offline token estimates.

Fixes #4810

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-18 14:38:00 +08:00
Kaoru0822andClaude Opus 5.5 b83b9caf4a fix(setup): edit the duplicate JSON member that clients read (#4957)
JSON.parse, JSONC parse, and native Claude Code keep the last duplicate
object member, and parseClientConfiguration therefore validates the last
one. The shared setup/uninstall serializer instead edited text through
jsonc-parser's modify and findNodeAtLocation, which select the first
matching member, so setup and uninstall on configurations with repeated
server tables or rea members wrote into a shadowed member and failed
readback.

Locate every JSON text edit by the effective (last) member in one place,
replacing the first-member modify path. Removing an effective member
that shadows an earlier duplicate would activate that duplicate, whatever
its ownership, so the serializer now returns a tagged shadowed_member
failure and setup and uninstall refuse before writing a backup or the
configuration.

Fixes #4952

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:15:47 -07:00
morluto bb212ffecb fix(tests): inherit server identity deadline policy
Remove per-case ten-second overrides from MCP catalog and identity checks. Keep the suite-owned bounded ordinary and coverage deadlines, all assertions, and session cleanup.

Fixes #4967
2026-10-18 13:01:44 +08:00
morluto 6b180783ed fix(tests): budget CLI coverage from parsed options
Use the pinned Vitest parser for coverage and shard flags. Keep ordinary CLI workers at 384 MiB and covered workers at the tested 512 MiB with unchanged concurrency. Retain complete coverage and add actual-config regressions for false, provider-only and spaced-shard options.

Validation: 27 focused cases; 16 covered cases with CLI preloaded; 5 docs checks; typecheck/lint; exact discovery of 1578 files. Measured covered control: 22.18s elapsed, 46.52s CPU, about 2.33 GiB sampled summed process-family RSS on macOS arm64. Full Linux CI pending. No runtime/device verification claimed.

Fixes #4960
2026-10-18 12:43:17 +08:00
morluto 8cbaf6c702 fix(tests): isolate command finalization module mocks
Move the five registered WASM finalization cases into the existing per-file isolated project. Preserve all result, exit-code, observation and cleanup assertions. A preloaded shared CLI graph reproduces three failures before the move; the isolated covered packet passes.

Fixes #4959
2026-10-18 12:42:26 +08:00
github-actions[bot]andmorluto 2c4338db1f chore(main): release rea-agents 6.6.0 (#3476)
* chore(main): release rea-agents 6.6.0

* docs(release): finalize 6.6.0 notes and contribution record

---------

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-18 11:39:53 +08:00
Kaoru0822andClaude Opus 5.5 18aa9af2b2 fix(setup): admit only strict JSON for Claude Code configuration (#4944)
Claude Code shared the generic `json` client format, which the shared
configuration reader admits through JSONC parsing with comments and
trailing commas enabled. Native Claude Code reads `.claude.json` with a
strict JSON parser (after a UTF-8 BOM), so setup reported `ready`, wrote
a registration into a file the client rejects as corrupt, and doctor
reported it `aligned`.

Give Claude Code its own `claude_code` configuration format and parse it
at the owning boundary with strict JSON.parse after removing a leading
BOM. Setup, doctor, and uninstall all consume that parser, so comment or
trailing-comma documents are now refused as malformed before any backup
or write, while plain and BOM-prefixed JSON still configure. Clients that
natively accept JSONC keep the `json` format and its behavior.

Fixes #4940

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:57:28 -07:00
morluto 1f23e977b5 fix(pwntools): retain exact cleanup owners through finalization
Give retained processes and runtime roots separate cleanup leases. Bind
composed failures to their exact dependencies so process retirement removes
only process labels and root deletion resolves the remaining markers.
Retain local evidence while descriptor cleanup is unresolved.

Preserve completed decoded facts and the original cancellation reason when
final cleanup itself fails, then expose that primary after successful retry.
Remove the superseded root-error composition branch after descriptor gating.

Validation: 68 focused tests across nine files, including real retained file
handles, late process handshakes, failed final cleanup, mixed child outcomes
and cleanup retry. Static, docs (five checks) and discovery (1577 files) pass.
The producer qualification scope is controlled Node/file fixtures with the
real macOS inspector and a simulated availability gate, not native pwntools
or GDB. Task tokens/CPU/process-family memory are unmeasured; no speed claim.

Fixes #4945
2026-10-18 10:51:51 +08:00
morluto 08fbeb8bda fix(pwntools): preserve producer cancellation outcomes
Keep opaque reasons at admission, queued work, command/file projection and
successful final cleanup. Normalize Node's ABORT_ERR envelope only at the
snapshot write API that produced it, using the verified original cause.
Remove downstream signal/name/identity guesses in decoder and debugger
catches, including reply-close and path-probe handling.

The initial regressions failed 15 cases with seven controls passing.
The complete final series passes 68 focused tests, static checks, docs and
discovery. Real owned Node/file fixtures use the actual macOS inspector;
only the Linux x64 availability gate is simulated. No native pwntools or
GDB qualification or performance improvement is claimed.

Refs #4945
2026-10-18 10:51:50 +08:00
47d3c6b1a1 test(perf): verify authentic retained investigation queries (#4814)
Verify retained queries against authentic SQLite ELF and npm histories, retain failed RPC/cleanup/output costs, and make mixed-history verification repeatable. Record the separate validation-reuse bottleneck in #4810.

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-18 02:32:58 +00:00
morluto b33c0df02e fix(pwndbg): reject core mapping paths that escape sysroot
Interpret source-bound ELF64 NT_FILE descriptors once before debugger
launch. Bound counts and pathname coverage by the descriptor, retain exact
path bytes, and refuse relative names or dot segments rather than letting
GDB resolve them against the host. Pin GDB's pathname semantics to Unix.

Preserve the decoded partial observation on refusal, basic-only recovery,
and pre-admission cancellation. Share an exact mapping fixture and replace
the old fixture boolean modes with explicit report producers.

Validation: final series has 33 passing Vitest cases plus five Python
producer controls; 38 Linux x64 provider cases are explicitly skipped on
macOS. Typecheck/lint, docs checks and test discovery pass. Real GDB16.3
and strace reproduce the relative-path escape using only an owned fixture;
compiled admission admits a real absolute-path core and refuses that
relative-path core. Full native pwndbg / Linux x64 remain unverified here.
Task token, CPU and peak-family-memory costs are unmeasured; no speed claim.

Fixes #4942
2026-10-18 10:27:37 +08:00
morluto 5bf4fffc1b fix(pwndbg): prevent core-triggered executable discovery
Occupy GDB's executable slot with its owned /proc/self/exe while loading a
core, then discard it before mapping queries. Select the validated decoder
architecture explicitly and restrict build-ID lookup to the owned empty path.
Preserve cancellation reasons at debugger admission.

Keep the original fixture executable present during syscall verification and
add Debian 13 / GDB 16 coverage alongside Ubuntu 24.04 in the CI definition.

Validation: controlled producer regressions and request-profile controls;
real GDB 16.3 / strace on Linux arm64 shows the old bridge opening the
recorded executable and the fix returning the same mapping without that
access. A cross-architecture gdb-multiarch probe confirms profile selection.
The plugin was controlled; full native pwndbg and Linux x64 remain unverified.
No performance improvement claimed; task tokens/CPU/family memory unmeasured.

Fixes #4914
2026-10-18 10:26:42 +08:00
morlutoandLuigi Pinna 847472acf5 fix(gdb): report close disposition as a capability precondition
Adapt #4732 using canonical provider identity and explicit producer recovery. Keep the valid session retained for caller-selected disposition and preserve default capability error behavior. Refs #4653.

Co-authored-by: Luigi Pinna <luigipinna3@gmail.com>
2026-10-18 10:03:39 +08:00
Kaoru0822andClaude Opus 5.5 270bc38f72 fix(setup): read signed 64-bit TOML integers losslessly (#4937)
Codex and Grok client TOML was parsed with smol-toml's default reader,
which rejects any integer beyond JavaScript's safe Number range. Valid
TOML 1.0 Int64 values such as `max_bytes = 9223372036854775807` made
setup, doctor and uninstall treat the whole file as malformed.

The client TOML owner now parses with `integersAsBigInt: "asNeeded"`,
keeping safe integers as numbers and larger ones exact as bigint, and
rejects values outside signed Int64 before any write. All TOML parses in
the document owner (document read, inline string decoding and the
preserving-edit check) use that reader. The inline-table writer emits
bigint values, and setup and doctor accept a positive bigint
`startup_timeout_sec`/`tool_timeout_sec` instead of replacing or
rejecting it.

Fixes #4917

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:02:26 -07:00
morlutoandXander-AJ d5fc7e6ebf fix(rizin): preserve output whitespace before completion markers
Adapt #4044 at the shared normal/interrupted frame owner. Preserve the decoded prefix before byte-budget accounting and cover MCP delivery across framing and UTF-8 boundaries. Refs #4016.

Co-authored-by: Xander-AJ <133286098+Xander-AJ@users.noreply.github.com>
2026-10-18 09:53:59 +08:00
morlutoandTapraj-Pathak 279c590ef6 fix(cli): require cancellation through command finalization
Adapt the forwarding proposal in #4652 with a required signal before optional resource diagnostics. Migrate all callers and cover actual command registration during final close. Refs #4939.

Co-authored-by: Tapraj-Pathak <165466587+Tapraj-Pathak@users.noreply.github.com>
2026-10-18 09:48:11 +08:00
morluto 2ae4e1608f fix(cli): preserve omitted positions in filtered JSON arrays
Normalize only filter-owned selections before streamed JSON and JSONL output, and count the same normalized payload. Keep source values and strict domain JSON validation intact. Refs #4938.
2026-10-18 09:40:02 +08:00
morluto ba98130049 fix(mcp): distinguish schema references from literal metadata
Share schema keyword roles and preserve reference bases for explicit local pointer targets and uncertain intermediate scopes. Retain literal values and canonical validation. Refs #4936.
2026-10-18 09:32:28 +08:00
Ysopwnable 1accac27c3 fix(ci): restore plist, verifier, and TOML capacity checks (#4930)
Correct stale plist and prerequisite fixtures, and replace the TOML serializer's repeated terminal-LF regex scans with a backward scan.

Keep capacity, timeout, source-preservation, backup, and idempotence coverage intact.

Fixes #4931
2026-10-18 01:20:43 +00:00
morluto 9df559b7e7 fix(analysis): gate document selection fallback and completion 2026-10-18 09:19:37 +08:00
morluto 94bc7ed322 fix(browser): retain module resolution through finalization 2026-10-18 09:07:53 +08:00
morluto 52b73ee857 fix(analysis): retain artifact admission cancellation reasons 2026-10-18 08:52:55 +08:00
morluto a8170163b9 test(rust): verify CLI retries exact descriptor cleanup 2026-10-18 08:51:13 +08:00
morluto bbfe6edd60 fix(artifacts): bind inventory and extraction cleanup to exact owners
Preserve typed failed attempts through root admission, hashing, inventory,
nested JavaScript readers and extraction rollback. Remove the intermediate
cause/resource records that discarded canonical cleanup capabilities.

Resolve original provider errors after confirmed release while preserving
primary failures, partial observations and invalidated-handle uncertainty.

Fixes #4928
2026-10-18 08:44:49 +08:00
morluto 2582c267af fix(artifacts): carry exact cleanup authority through scope failures
Return the canonical owner and lease from failed releases. Compose initial
cleanup failures from explicit operation outcomes and failed attempts, and
carry their authority through the shared artifact failure contract.

Keep independent unknown cleanup unresolved. Distinguish operation failures
from completed work whose close rejected. Let the scope own current child
resource labels without replacing its canonical retry lease.

Cover mixed owners, partial release, cancellation provenance, typed close
rejections and independent unknown cleanup through the producing boundaries.
2026-10-18 08:44:41 +08:00
morluto 2183c9598c fix(process): retain kernel limit descriptor cleanup ownership
Use the shared artifact file owner for kernel report reads, preserving the
physical outcome and exact retry lease through failed close and recovery.
Remove the handwritten finally path that discarded this authority.

Cover successful and failed reads with and without a caller scope, denied
retry, blocked replacement admission, and recovery of original error markers.
Adapt the separate descriptor repair proposed in #4863.

Fixes #4926
Co-authored-by: abdooo2235 <abdalrhmantheiv15@gmail.com>
2026-10-18 08:29:57 +08:00
morlutoandabdooo2235 93196449ad test(javascript): verify endpoint certainty through CLI and MCP
Exercise Map omission, escaped prototypes, opaque eval and candidate Evidence
through the rebuilt CLI worker and public MCP transport. Preserve exact static
fetch evidence and SQLite certainty controls.

Co-authored-by: abdooo2235 <abdalrhmantheiv15@gmail.com>
2026-10-18 08:25:28 +08:00
morluto fbfdb6abe9 fix(javascript): distinguish Map lookups from network endpoints
Resolve unchanged Map operations through shared binding, capture, mutation,
and ambient escape facts. Reuse that proof in application and captured
bundle analysis; unresolved get/delete receivers remain inferred candidates.

Preserve repeated native operations without manufacturing receiver escapes.
Retain uncertainty for real escapes, opaque eval, and changed constructor
adder hooks. Converge stored aliases at the producing boundary.

Adapt the JavaScript changes from #4863, excluding its Linux resource fix.
Add captured-bundle parity, repeated-operation and constructor-hook coverage.

Fixes #4853
Co-authored-by: abdooo2235 <abdalrhmantheiv15@gmail.com>
2026-10-18 08:25:06 +08:00
morluto e6c487799b fix(native): preserve resolved plist selection intent
Resolve lookup identity and selected/default origin together in the plist
source owner. Physical-file and conversion failures consume that fact
rather than reconstructing intent from omission of the path argument.
Selected plist artifacts resolve independently of readiness; unresolved
scope admission does not acquire an invented file-selection context.
Remove the superseded resolver and path/requested representation.

Cover direct-target CLI/MCP refusals, physical file conditions, permission
denial, default controls, unresolved scope context and cleanup retry for
both explicit path and selected-target workflows.

Fixes #4923. Related: #4849.

Validation: public CLI/MCP baseline3 failed8 controls passed; final55
passed across7files, check:fast, docs5, discovery1566 and source review.
Actual macOS26.3 plutil CLI/MCP; no Linux/Windows native qualification.
2026-10-18 08:11:46 +08:00
morlutoandapitoagents 7ca7e38717 fix(native): retain bounded plutil refusal diagnostics
Read failed conversion diagnostics from both output streams, retaining
raw bounded excerpts, observed byte totals, exit status and truncation.
Remove only repeated path prefixes from display text and report a useful
reason when the command prints no diagnostic. Reuse native failure
capture bounds rather than expanding accepted nonzero output into errors.

Adapted from PR #4851. Fixes #4849.

Validation: six controlled boundary failures on baseline, including the
stdout-only empty-reason defect; final46 passed across6files, real macOS
CLI/MCP controls, static checks, docs5 and discovery1565. On macOS26.3
plutil uses stderr; stdout-only coverage is controlled output. Separate
selected-target classification defect is reproduced and tracked as#4923.

Co-authored-by: apitoagents <339136651+apitoagents@users.noreply.github.com>
2026-10-18 08:04:33 +08:00
morluto f2b7bbb312 fix(plist): retain known binary non-finite value identity
Make XML numeric uncertainty explicit at its producing boundary, separate
from decoded IEEE NaN and signed infinities. Shared projection preserves
known values using canonical numeric labels; unresolved XML numeric
values remain explicit unknowns. Remove the superseded known-value
wrapper and spelling alias, keeping numeric interpretation with its owner.

Cover public CLI/MCP binary archives, lookalike dictionaries, authored
32/64-bit IEEE payloads, signed zero, and XML parsing/overflow uncertainty.
Document canonical labels and unrepresented NaN payload/sign details.

Fixes #4919. Related: #4906, #4852.

Validation: baseline 2 failures/5 controls through public CLI/MCP; stable
final 439 passed across25files, check:fast, docs:check and discovery.
Native macOS plutil and existing codesign controls executed; no
Linux/Windows run or real Interface Builder engine qualification.
2026-10-18 07:55:51 +08:00
morluto 69324b0f86 fix(native): project decoded entitlement scalars through plist owners
Consume shared value and exact-number projections before JSON validation
so decoded plist scalars cannot leak as ordinary dictionaries. Carry
projection limitations into signature evidence with entitlement context.

Related: #4906. Controlled command-runner regression passed. Real
codesign refused the authored non-finite entitlement; this does not claim
real entitlement support. Existing real signature CLI controls passed.
2026-10-18 07:48:25 +08:00
morlutoandMert Kaya 6c98708793 fix(plist): preserve observed non-finite XML reals
Recognize complete CFPropertyList literals at the XML owner and retain
canonical NaN and signed infinity identity as typed scalars. Keep scalar
wrappers distinct from lookalike dictionaries, share limitation text and
document alias normalization. Incomplete markup retains its existing
compatibility fallback and limitation. Bound token matching before case
normalization using the accepted grammar.

Adapted from PR #4908. Fixes #4906.

Validation: public CLI/MCP regression baseline 2 failed, 4 passed.
Final focused validation 430 passed across 25 files, including controlled
entitlement response coverage in the following commit. Real macOS plutil
CLI, check:fast, docs:check and discovery passed. Binary value identity
remains tracked in #4919; malformed literal policy remains #4852.

Co-authored-by: Mert Kaya <47145541+mertkayacs@users.noreply.github.com>
2026-10-18 07:48:18 +08:00
morlutoandMert Kaya d205c528e3 test(pcap): verify UTC metadata against authored capture records
Use capinfos epoch output and compare public CLI/MCP results with UTC
instants derived independently from the known authored PCAP records.
Avoid comparing product output with the same host-local display text.

Related: #4907, #4909. Syntax checked; live Linux verification not run.

Co-authored-by: Mert Kaya <47145541+mertkayacs@users.noreply.github.com>
2026-10-18 07:40:35 +08:00
morlutoandMert Kaya 796faa0e4e fix(pcap): preserve exact UTC capture instants
Request epoch timestamps from capinfos and normalize them once at the
metadata boundary, preserving nanosecond precision and explicit unknowns.
Bound numeric parsing to the producer representation and cover negative
fractions, calendar limits, malformed output and MCP projection.

Adapted from PR #4909. Fixes #4907.

Validation: 47 passed, 24 platform-specific skips across five focused
files; check:fast and test discovery passed. No live Wireshark or
Linux/Windows capture execution was performed on this macOS host.

Co-authored-by: Mert Kaya <47145541+mertkayacs@users.noreply.github.com>
2026-10-18 07:40:25 +08:00
morluto f0b9ef34c4 fix(verify): request command JSON for Cutter inspection
Use --json-output for the verifier's ij observation. Exercise the actual
verifier-selected arguments through the public CLI and authenticated fixture
bridge, asserting command JSON mode and retained Evidence. The old bare --json
selection fails this control. A live Cutter GUI was not qualified here.

Fixes #4912
2026-10-18 07:34:08 +08:00
morluto f4456dc196 fix(verify): restore owned firmware fixture hashing
Replace the removed hashFirmwareFile export with shared stable verifier hashing.
Keep hashing under the file scope and close MCP/file owners independently before
removing their fixture parent. Preserve the primary failure if cleanup also fails.

The actual firmware entrypoint now reaches its prerequisite gate; descriptor
retry and mixed-cleanup controls pass. Real Linux firmware-engine qualification
was not run here. Refs #4912.
2026-10-18 07:34:07 +08:00
morluto 7d79a6a85b fix(verify): own asynchronous Ghidra prerequisite inspection
Await installation inspection through one shared helper with a real resource
scope at all 13 verifier call sites. Retain exact close owners, complete cleanup,
and preserve primary plus cleanup failures. Keep compiler-only loading lazy and
use the namespace workflow's selected environment.

Add admission contract and native-file lifecycle controls, plus a real script
prerequisite rejection check. Controlled Java/header observations do not qualify
a real Ghidra engine. Combined verification selection: 122 tests passed across
five files; static/format/discovery passed; two scoped source reviews clear.

Refs #4912
2026-10-18 07:33:58 +08:00
morluto 823521085a fix(setup): transfer unscoped registration cleanup ownership
Preserve original RegularFileCleanupFailure capabilities when registration
inspection or maintenance planning has no caller-supplied resource scope.
Keep scoped diagnostics with the scope that already retained the descriptor.

Cover configuration and policy sources, completed and malformed-UTF8 reads,
all four exported reader/planner boundaries, exact descriptor retry after
pathname replacement, no subsequent execution, and scoped cleanup retry.

Validation: 79 tests across four focused files; the historical baseline fails
all 16 new ownership-transfer controls with eight existing/scoped controls
passing. check:fast, format:check, test discovery and six isolated completed
public doctor comparisons passed. Scoped source review found no blocker.

Real temporary descriptors and injected close rejection on macOS arm64 /
Node24.18.0; no native Windows/Linux close faults or provider verification.

Fixes #4910
2026-10-18 07:22:14 +08:00
morluto abb54ce374 test(setup): cover configuration identity regressions
Add direct controls for literal AppData roots, denied MSIX target rechecks,
and unrecognized Claude package deployments. Verify setup refuses mutation
and registration diagnostics remain invalid for unknown package readers.

Six new controls fail at 6d5281407 before the existing 9abdad335 fix; one
existing-behavior guard passes. All seven pass on current main. Keep native
Windows/app behavior distinct from macOS filesystem and platform-selected
adapter checks.

Validation: 82 tests across four configuration/CLI files, 42 header/skill/
lifecycle tests, 144 Ghidra/doctor consumer tests, check:fast, format:check,
and test-discovery verification passed. No provider/target execution.

Refs #4378, #4432, #4496, #4501, #4384, #4676
2026-10-18 07:16:10 +08:00
morluto d818c3d263 fix(doctor): preserve unresolved client configuration evidence
Use entry metadata to discover registration evidence independently of target
readability. Preserve failed metadata inspection as a named invalid diagnostic
instead of treating all lookup failures as absence. Remove the duplicate
boolean existence wrapper; configuration parsing remains the read owner.

Cover native permission-denied targets and metadata, dangling configuration
entries, maintenance exclusion, and public doctor output without mutation.

Validation: 73 focused tests across four files, check:fast, format:check,
and six isolated completed public doctor cost comparisons passed on macOS
arm64 / Node24.18.0. Native Windows/Linux permissions were not verified;
POSIX permission controls skip unsupported hosts and root.

Fixes #4905
2026-10-18 07:10:44 +08:00
morluto d0253c99d6 fix(setup): preserve the selected destination during configuration publication
Replace configuration-specific write-file-atomic delegation with a verified
input snapshot, exclusive private staging, and an explicit canonical-parent
destination. Existing files publish by rename; first-run files use an exclusive
link so a newly created destination is retained. Both consumers read back the
publication owner's selected path.

Retain descriptor and staging cleanup capabilities through recovery and host
retry. Preserve mode and ownership, remove temporary permission handoffs, and
use positional restoration writes. Keep UTF-8 diagnostics with failed cleanup.

Validation: 284 focused tests passed, one skipped across 14 files; check:fast,
format:check, docs:check (including five consistency tests), two source reviews,
and 12 completed isolated public CLI setup/uninstall cost controls passed.
Native Windows/Linux, real editor concurrency, and providers were not verified.
Final-check/publication races and same-inode concurrent writers remain unexcluded.

Fixes #4904
2026-10-18 07:06:15 +08:00
morluto 2fb5e204a3 fix(uninstall): retain configuration publication ownership through recovery
Replace pathname writes with the shared configuration publication owner.
Reject replacement readback and restore through the exact staged descriptor.
Retain initial-read, readback and publication cleanup owners for retry. Share
nested cleanup handling with setup without granting authority to opaque
cancellation reasons. Separate host admission from nested file cleanup gates.

Preserve uninstall file modes, including readable read-only configurations.
Hold the exact staging permission owner through writable-descriptor handoff
and failed mode restoration. Remove the superseded writeText effect contract.

Validation: 206 focused tests across 9 files, check:fast, formatting and
docs:check passed. Three uninstall replacement controls fail on baseline
7e4eed9dd while thirteen setup controls pass. Twelve completed CLI uninstall
tasks preserve equivalent outputs, config, backups and modes0400/0640.
Two read-only source reviews completed. Native Windows/Linux and real editor
races remain unverified; in-place writer exclusion is still not provided.

Closes #4902
2026-10-18 06:50:22 +08:00
morluto 7e4eed9dd4 fix(setup): bind recovery to the published configuration file
Retain the staged file descriptor through atomic publication, readback and
recovery. Refuse detected replacements or edits and restore through that
owned descriptor instead of reopening a pathname. First-run readback failure
now retains the file for manual recovery because pathname deletion cannot
prove exact ownership. Keep both descriptor owners when nested closes fail;
opaque close rejections do not transfer ownership.

Validation: 192 focused checks in 9 files, check:fast, formatting and docs:check
passed. Three replacement regressions fail on the baseline while six existing
recovery controls pass. Six completed setup tasks preserve equivalent config
and backups. Two read-only source reviews completed on macOS arm64 / Node24.
Native Windows/Linux and real concurrent editor behavior remain unverified.
State checks do not exclude an in-place writer after the last check.

Closes #4900
2026-10-18 06:33:04 +08:00
morluto 19329e43bb fix(setup): preserve launcher identity and uncertainty
Use one registration classifier for doctor, maintenance and uninstall.
Preserve unknown identity when launcher resolution fails, and compare native
paths without collapsing symlink traversal. Keep Node argv script selection
separate; ambiguous direct-launch interpretations cannot authorize removal.
Remove the superseded boolean ownership parser.

Validation: 183 focused tests passed, 2 Windows cases skipped; check:fast
and docs:check passed. Five public regressions fail on the baseline, including
foreign registration removal in an isolated fixture. Source review and authored
Node shebang controls completed on macOS with Node 24.18.0. Native Windows,
Linux and real mise upgrades remain unverified.

Closes #4895
Closes #4896
2026-10-18 06:18:34 +08:00
morluto 01cdbbdc55 fix(update): bound package-manager output retention
Reuse supervised raw-byte capture with a 4 MiB aggregate budget. Drain package-manager output through physical close, reject oversized complete replies, and let verbose installs finish with explicitly bounded failure diagnostics. Preserve existing command resolution, selected environment/cwd, runtime prerequisites and signal policy.

Own human progress backpressure and final write acknowledgements without ending borrowed stderr. Continue draining after destination failures and observe outstanding write rejections through their error event.

Validation: 152 checks across 12 focused files, followed by a 44-check rerun including two additional no-deadline waiter controls; typecheck/lint, docs and discovery pass. The public oversized-metadata regression fails on 4f7b5fb60. Fixtures execute owned Node/fake npm/Bun commands; no actual package install or registry request. Native Windows/Linux and exhausting-output/OOM scenarios were not run.

Small completed CLI checks return identical replies and token estimates. Six sequential baseline/candidate tasks separate first-process and two warm repeats; no speedup, true-cold or large-install memory claim. Existing descendant cleanup and signal behavior is outside this output-bound fix.

Closes #4888.
2026-10-18 05:57:57 +08:00
morluto 182e9a268c refactor(process): allow awaiting physical output closure
Allow the existing supervised output wait to omit its deadline while preserving bounded waits and abort-listener cleanup for current consumers. Updater package-manager commands can await physical stream completion without an invented install timeout.

Refs #4888.
2026-10-18 05:57:36 +08:00
morluto 4f7b5fb602 fix(cli): route update flag through verified updater
Normalize the unambiguous root --update alias before output handling and
through direct createCli().serve calls. Reuse the existing output-value scan
and canonical update command, including selected environment, installation
ownership, Windows-aware launch, verification, maintenance and failure facts.
Retain option data and help/check precedence. Reject remaining Incur install
requests: update:false does not disable its explicit installer in0.6.1.
Remove the superseded output-only normalizer name and update its consumers.

Validation:123focused checks/7files pass, including compiled CLI with an owned
rejecting fake npm and direct serve across5formats. Original argument owner
fails6new controls/7pass; isolated baseline fails8workflow checks/2controls
pass. Static/docs/discovery1561 pass. Both scoped source reviews are clear.
Six completed equivalent current-version workflows compare baseline canonical
update with the alias; complete replies identical. Native Windows upgrade,
real package-manager installation and full install costs remain unverified.

The first baseline escaped a Vitest-only builtin mock and installed REA in the
pinned Node global prefix. Removed the newly added package and verified original
Node/npm/Corepack tools. Re-ran using the real builtin spy with synchronized
ESM exports, an independently rejecting PATH shim and owned npm prefix/cache.
Keep heavy tests/profiling stopped. Independent updater output bounds remain
tracked in #4888 rather than changing collection policy in this routing fix.

Fixes #4883
2026-10-18 05:33:21 +08:00
morluto c555caad65 fix(setup): resolve Hermes named-user homes before planning
Resolve the current named POSIX account through OS identity rather than the
caller-selected HOME/USERPROFILE. Preserve the home prefix for repeated
separators using the same joining semantics as the existing ~/ branch.
Require an absolute HERMES_HOME for unresolved names and Windows named forms
before exposing config or skill write destinations. Reuse the shared Hermes
path owner and existing diagnostics across setup, doctor, skills and uninstall.

Validation: 113 checks across seven files pass, including the compiled CLI
setup/doctor/skill/repeat/uninstall workflow over an owned profile beneath the
actual account home and a separate caller home. The isolated unchanged baseline
fails the five new checks and passes44existing checks; final repeated-separator
controls also fail that baseline. Static/docs/discovery1559 pass. Both source
reviewers clear after correcting repeated-separator composition.

Twelve completed setup dry runs compare normal and named overrides, with exact
normal-home replies unchanged. Measurements have source hashes and separate
first/warm runs; no speedup, full Hermes agent/model or native Windows/Linux
qualification claim. No provider software was installed; heavy tests/profiling
remain stopped.

Fixes #4841
2026-10-18 05:17:31 +08:00
morluto 9ac76d3d94 fix(javascript): invalidate stale facts across direct eval
Index unshadowed direct-eval sites once at the semantic owner. Distinguish
lexical rebinding, non-strict eval-introduced names, and possible mutation
of reachable objects. Reuse existing effect timing and capture proofs;
retain original definitions and module origins without inventing assignments
or parsing or executing eval payloads. Query object uncertainty conservatively
across the owning activation so aliases remain covered when names are shadowed
or leave block scope. Retain no binding-by-eval table.

Use the shared facts for values, read provenance, reference effects and child
argument shapes. Preserve indirect/optional/shadowed eval controls, unrelated
activations, immutable shapes, strict-mode bindings and prior primitive
captures. Remove obsolete reference plumbing and the source-wide eval blocker.

Validation: 306 focused checks across 16 files pass, including compiled CLI
and stdio MCP return projections, constructor uncertainty and child-process
consumers. Against the preceding SQLite commit, 9 of 23 selected checks fail
and 14 controls pass. Static/docs/test discovery (1559 files) pass. Two source
reviews found no remaining scoped blocker after alias and sloppy-name fixes.
No analyzed JavaScript, SQLite engine, heavy test or profiler was executed.
Conservative object reachability can intentionally lose exactness; large-case
opaque-query CPU and memory remain unmeasured.

Fixes #4875
2026-10-18 05:08:37 +08:00
morluto fc847ffe35 fix(javascript): preserve SQLite constructor provenance
Use Database spelling only to select a candidate. Reuse shared expression
provenance and indexed mutation facts to omit proven local constructors and
retain known SQLite API origins separately from uncertain names. Match ESM
default/namespace and CommonJS export forms without collapsing their identity.
Keep type-only import origins as ambiguous runtime values, including aliases.

Carry candidate interpretation through the worker schema and graph nodes and
edges with low confidence, explicit limitations and distinct identities.
Remove the name-only SQLite storage classifier. Other storage APIs retain
existing handling; PR4863's separate Map endpoint work is not integrated.

Validation: initial9negative controls fail unchangedf5fcf5216 while4positive
controls pass; final67focused checks/8files plus60provenance-consumer checks/
4files pass. Static/docs/discovery1557 pass. Two source reviewers clear after
correcting namespace constructor identity. Public CLI checks worker/schema
projection and separate exact/candidate identities with the same filename.

Twelve small completed CLI workflows preserve exact known-API replies and
remove false local-class storage facts. No speedup/large-case memory or real
SQLite execution claim. Direct eval's existing generic invalidation defect
remains tracked separately in #4875. Heavy tests/profiling remain stopped.

Additional consumer validation caught and corrected runtime import-equals
classification: require-mode import origins remain runtime values. Three new
SQLite controls cover runtime and erased import-equals forms; compiled
child-process CLI/MCP stdio workflows pass after the correction.

Fixes #4854
2026-10-18 05:06:46 +08:00
morluto f5fcf5216f fix(apktool): retain decode facts across interrupted read stages
Keep one typed accumulation of observed decode facts instead of constructing
partial Evidence only after string projection. Record decoded client/target
before the post-command cancellation checkpoint, parsed metadata before
manifest reads, raw manifest before interpretation, and inventory prefix
before rethrowing its exact original cause. Omit unexamined fields.

Return inventory success or exact failure plus completed prefix through
Result. Keep resource-cap stops distinct from physical failures. Attach
truncation and inventory limitations at their producing stages. Validate
complete results with the named domain schema; centralize partial Evidence
assembly in the existing failure/cleanup boundary.

Validation: six authored stage controls fail unchanged34a88d6c1; 131 focused
checks across7files, check:fast, docs:check and discovery1556 pass. Covers
manifest bytes/XML, interrupted inventory, late cleanup cancellation,
denied removal/retry and existing table interruption. Two source reviewers
clear after moving the command handoff checkpoint. No separate runtime
qualification of that precise handoff race.

Public CLI manifest failure retains metadata/raw manifest with unknown
fields omitted and original failure framing unchanged. Twelve small normal
CLI tasks retain exact replies. No speedup or memory-saving claim; failure
reply estimate189 to610cl100k tokens preserves completed Evidence. No real
Apktool, large-case memory or whole-agent qualification. Heavy tests remain
stopped.

Fixes #4882
2026-10-18 04:36:30 +08:00
morluto 34a88d6c16 fix(apktool): retain completed facts after locale read failures
Return completed string projections with the exact failure cause in Result.
Force partial coverage and disclose the interrupted selection and remaining
unattempted selections without inventing table status or counts.

Assemble execution once from success or partial projection. Preserve the
original failure through existing ownership/cleanup classification, then
retain completed Evidence before snapshot fallback. Existing producer
observations retain precedence. Remove the throw-only projection contract.

Validation: four authored filesystem controls fail unchanged f1edf0da0;
99 focused checks across six files, check:fast and docs:check pass. Covers
late cancellation, denied workspace cleanup and retry, opaque cancellation
between tables, exact physical cause, and CLI/MCP contracts. Public CLI
failure retains completed facts; original failure framing is unchanged.
Two source reviews found no blocker.

Twelve small normal-path CLI tasks preserve exact replies. Measurements
show no speedup; failure reply grows to retain Evidence (cl100k estimate
189 to 696). No real decoder, whole-agent, or large-case memory claim.
Heavy tests and profiling remain stopped.

Fixes #4880
2026-10-18 04:29:41 +08:00
morluto f1edf0da0c fix(cli): preserve APK locale-list schema bounds
Reuse the named domain locales field instead of reconstructing an optional
array from its element type. Preserve min/max selection bounds through the
CLI parser and public JSON Schema while retaining the repeat-flag guidance.
The application service already validates the input; provider authority is
unchanged.

Add a public schema regression and compare advertised Ajv2020 acceptance
and CLI parser acceptance with the owner for omission, empty, valid,
maximum, oversized and invalid-element selections.

Validation: regression fails unchanged d37c34647; 21 focused checks across
4 files, check:fast and docs:check pass. Source review found no blocker.
No real-provider or performance qualification claim. Heavy tests remain
stopped.

Fixes #4876
2026-10-18 04:21:19 +08:00
morluto d37c346477 fix(apktool): retain observed table counts through output limits
Separate physical string-table facts from per-selection output allocation.
Use one owner for legacy and batched projections, preserving caller labels
and normalized-directory reuse. Retain complete counts and at most one
bounded table prefix for later aliases. A skipped cached alias keeps its
known counts; unexamined tables keep explicit unknown counts.

Remove the provider's duplicated parsing and status branches. Charge the
primary legacy copy before selecting output entries and derive limitation
text from the actual emitted count. Reuse the named request input type and
clarify nullable count descriptions without changing their schema types.

Have the workspace report retained raw-prefix bytes, including a stripped
UTF-8 BOM, instead of reconstructing source cost from decoded text.

Validation: 145 focused checks across 8 files; baseline count control fails
unchanged fd6da7092; check:fast, docs:check and discovery 1556 pass. Twelve
small public CLI decode workflows preserve exact normal-path replies and
request/reply token estimates. Timing variation is noise-level; no speedup,
large-case memory or real Apktool qualification claim. Heavy tests/profiling
remain stopped.

Fixes #4874
2026-10-18 04:19:10 +08:00
ShuaixinHuangandmorluto 9e372c6bc9 fix(cli): preserve spaced output flag values (#4823)
* fix(cli): preserve spaced output flag values

* docs(readme): fix French heading spacing

* fix(ci): retain portable build cache until snapshot upload

* test(browser): assert composed Electron cleanup failures

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-18 04:02:45 +08:00
morluto fd6da70920 fix(cli): report string capacity failures during result formatting
Recover completed ordinary command results when pinned Incur formatting
exceeds the runtime string limit before stdout begins. Emit a small typed
memory constraint with an explicit unknown formatted size, the runtime limit
and JSON/filter remediation. Preserve full-output framing and leave normal
CTA, human and token-window formatting with Incur. Never rerun analysis.

Capture canonical failure identity at its logging owner, including thrown
AnalysisError projections. Recovery reads compact captured facts without
revalidating or retaining large diagnostics. Keep destination failure ownership,
prevent a second stdout document and retain quiet SIGPIPE status during recovery.

Validation: 111 distinct focused tests across 10 files; check:fast,
docs:check and discovery of all 1555 test files. Sixteen authored formatter
controls fail unchanged e103ae0ce and pass with this fix. A separate closed
reader control caught and now covers recovery EPIPE handling. The heavy JSON
string-limit regression remains excluded; no large Electron reproduction ran.

Twelve small public CLI artifact inspections preserve identical raw replies
and token estimates in TOON and JSON. Timings are noise-level, with no speedup,
cold-cache, large-result memory or real-provider qualification claim. Sentinel
and generator protocols keep their existing ownership.

Fixes #4806
2026-10-18 04:00:15 +08:00
Abhay Tiwari 6668424343 feat(apktool): share one APK resource decode across selected locale tables (#4777) (#4804)
Project default and multiple selected localized string tables from one
immutable decode pass. Remove the need for repeated APK snapshotting,
digesting, version probing, apktool d invocations, and workspace enumeration.

- Contract: add optional locales array to decode_android_resources input
  schema (bounded to 20 locales) and structured string_tables to output schema
  with per-table status, strings, total_count, unparsed_count, and coverage.
  Preserve legacy strings and locale fields for complete backward compatibility.
- Bounds: enforce 32 MiB aggregate XML read cap and 10,000 aggregate string
  entries cap across batched projections. Handle missing, oversized, and
  malformed tables per-table without failing or losing completed tables.
- Lifecycle: maintain strict descriptor cleanup and provider-owned workspace
  removal in finally, preserving typed cancellation and failure details.
- Adapters: add --locales repeatable option to CLI and update MCP contract.

Validation: 10 service tests, 3 CLI boundary tests, and MCP boundary schema
tests pass. Fast typecheck/lint and turbo docs:check:built pass.
Fixes #4777
2026-10-18 03:57:17 +08:00
pablodiazjorge 3b5605ecd2 fix(plist): keep negative-zero reals distinct from positive zero (#4839)
Plist inspection reported a serialized -0.0 real as the JSON number 0.
- The shared plist projection reports it as a typed real scalar whose value is the string -0, counted in a limitation for keyed archives and inspect_plist.
- The plutil JSON path applies the same value when it decodes -0.
- The XML decoder no longer returns -0 for a mixed-content integer.

Fixes #4834
2026-10-18 03:56:43 +08:00
Prasad Navale 09de00b410 fix(javascript): admit CommonJS bare scoped package directory resolution (#4838) 2026-10-18 03:54:51 +08:00
morluto e103ae0ce5 fix(clients): advance TOML statement lines without document rescans
Reuse the writer's monotonic statement index to find the last physical line
of an assignment. Remove the full line-start scan performed for every key.
Preserve source edits, multiline values, BOM, CRLF and final-line handling.

Add LF/CRLF controls with adjacent assignments, multiline values, an empty
value and EOF without a newline. Validated 85 focused tests across six files,
check:fast, docs:check and discovery of all 1553 test files.

Twelve bounded public CLI uninstall tasks preserve equivalent replies,
configuration and original backups. Warm 10000-assignment elapsed medians
were 0.538/0.520 s and CPU 0.817/0.744 s before/after; small-input timings
were noisy and slower in the candidate. No general speedup, cold-cache,
real-client or analysis-provider claim. Heavy profiling remains stopped.

Fixes #4873
2026-10-18 03:41:32 +08:00
hhang c43bc0bf66 fix(clients): preserve large TOML documents without argument spreads
Fixes #4856
2026-10-18 03:38:12 +08:00
morluto 3460ceac3f fix(browser): retain exact scenario cleanup ownership
Transfer canonical leases through opening, session and storage boundaries. Keep response deadlines separate from actual completion, drain independent owners, and join late opening failure cleanup before confirming recovery. Remove error copies in favor of canonical primary/cleanup composition.

Preserve exact caller reasons, completed observations and independent physical failures through final-close cancellation and retry. Closes #4869.

Validation:155 tests pass across15 focused source, service, CLI subprocess and MCP files; static/docs/discovery1551 pass. Two original-revision controls fail as expected. Bounded authored-session public CLI comparison preserves equivalent Evidence and1282 reply token estimates; no real Chromium qualification or forced-termination recovery claim (#4659).
2026-10-18 03:22:29 +08:00
morluto 16924e275e fix(artifacts): serialize concurrent cleanup lease releases
Share the in-flight release for one exact owner, preserve failed attempts for retry, and notify dependent errors only after confirmed completion.

Validation: concurrency control fails on3fcba0796 with two cleanup attempts; isolated foundation passes38 selected lease/scope/resource tests. Authored lifecycle controls, no native provider qualification.
2026-10-18 03:21:02 +08:00
morluto 3fcba07962 fix(process): preserve file outcomes through exact cleanup recovery
Classify canonical physical file outcomes through the provider mapper before composing cleanup. Retain unknown capabilities as unresolved and replace runtime failure maps with exact leases, including mixed cleanup and partial retry.

Keep completed-read cancellation output and cleanup history. Closes #4865.

Validation: 179 unique focused tests passed across 13 selected files, 7 Linux-only skips; static checks, docs checks and 1551-file discovery passed. Authored Node producers and controlled real-descriptor faults do not qualify native providers.
2026-10-18 02:55:41 +08:00
morluto daa641aa3c fix(artifacts): retain canonical cleanup leases for scope owners
Pair each retry owner with its exact lease and reuse that lease for release and recovery. Remove variant-based lease inference.

Validation: isolated scope foundation passed 23 selected tests; final candidate passed the broader focused suite and static checks. Real-provider behavior was not qualified.
2026-10-18 02:55:19 +08:00
morluto 8a247fc70f fix(providers): preserve artifact producer cancellation facts
Wire sigrok and tshark finalization to the effective signal. Services and file-failure adapters retain exact opaque reasons and completed Evidence instead of guessing from error names. Preserve typed primary outcomes through failed cleanup and recovery.

Validation: latest per-file coverage is 114 passing tests across nine selected files with 14 explicit Linux-only skips; core foundation passes independently. check:fast, docs and discovery pass. Four finalization controls failed before the signal ownership fix. Bounded completed authored-producer service workflows have identical Evidence with no performance improvement claim. Real sigrok/tshark and native Linux/Windows were not verified.

Closes #4858
2026-10-18 02:38:30 +08:00
morluto 147ae9718a fix(process): preserve artifact cancellation through finalization
Consume owner-recorded cancellation reasons, recheck admission after pending cleanup, and keep typed cancellation with completed observations through final workspace cleanup and retry. Existing physical failures remain primary.

Validation: 18 core tests pass; 20 combined boundary controls fail on baseline before consumer migration, and four final-close service controls failed before finalization signal ownership. Focused integration, static/docs and bounded service comparisons pass. No native Linux/Windows or real sigrok/tshark qualification.
2026-10-18 02:37:53 +08:00
morluto 300905c11b fix(android): retain archive admission ownership through cleanup retries
Borrow the archive descriptor from the canonical artifact file workflow. Preserve primary configuration failures, completed archive facts and exact cancellation through final close, retain failed descriptor leases, and join provider and doctor shutdown without nested resource admission.

Validation: three baseline failed-close regressions; 65 passing tests across seven files, nine real CLI and nine real MCP tiny APK inspections, check:fast, docs and discovery. Two read-only reviews clear. Bounded equivalent workflow costs recorded without a speedup claim; no actual OS close fault or native Windows/Linux qualification.

Closes #4846
2026-10-18 02:19:12 +08:00
morluto f1d18859eb fix(artifacts): preserve opaque ZIP cancellation reasons
Use the canonical artifact cancellation checkpoint for enumeration, open and extraction instead of dropping the caller reason in a ZIP-specific helper.

Validation: both new ZIP reason controls fail on the unchanged baseline and pass on the candidate; the focused seven-file run passes 65 tests. Native Windows/Linux were not run.
2026-10-18 02:18:55 +08:00
morluto 662fad9072 fix(cli): finalize doctor cancellation after failure logging
Make the signal boundary own logging and projection as it does for other cancellable commands. Preserve SIGINT/SIGTERM exit disposition after joined doctor cleanup without changing generic failure classification.

Validation: both public signal controls fail on the baseline with exit1 and pass with130/143 after the fix; selected Java groups are empty. Twenty focused tests across five files, check:fast, docs and discovery pass. Authored launcher fixtures do not establish real JVM or native Windows/Linux behavior.

Closes #4848
2026-10-18 02:07:41 +08:00
morluto ceeff5a417 fix(android): own Java prerequisite probing and readiness shutdown
Run the selected module-listing command through owned supervision, preserve completed module facts through finalization, and retain failed cleanup in provider/doctor scopes. Join complete availability calls on shutdown, preserve opaque interruption reasons, and validate numeric Java facts before reporting them.

Validation: 223 passing focused tests across 21 affected files, one platform skip; controlled baseline returns before child exit; real doctor cancellation leaves the selected Java group empty; nine real CLI and nine MCP tiny-APK inspections pass; six bounded MCP cost comparisons preserve normalized results. Native Windows/Linux and actual JVM failure modes remain unverified. Separate CLI exit disposition and archive failed-close findings remain open.

Closes #4845
2026-10-18 02:00:29 +08:00
morluto 964decd989 fix(providers): preserve live cleanup ownership through retries
Share exact command/helper cleanup adoption across Java probes. Preserve complete live resource labels and explicit unknowns through inspection leases, and retain unresolved ownership when a cleanup capability is unavailable.

Validation: focused cleanup, provider/doctor and Kuna consumer checks; shared Ghidra lifecycle and public doctor regressions. Native Windows/Linux provider behavior remains unverified.
2026-10-18 01:59:10 +08:00
morluto 3ad1032b11 fix(android): finalize startup diagnostics before reporting failure
Record the first transport failure before SDK teardown, then capture terminal stderr after owned retirement. Preserve exact opaque cancellation reasons and keep foreign cleanup ownership separate through retries.

Validation: 119 focused tests across eight files; five selected baseline regressions; check:fast, docs:check, test discovery; nine real CLI and nine real MCP tiny-APK inspections. Native Windows/Linux startup failures and actual JVM OOM remain unverified.

Closes #4844
2026-10-18 01:28:36 +08:00
YsopwnableandShuaixinHuang 3ddb2e4cf7 fix(ci): handle cache eviction and composed cleanup assertions (#4824)
* fix(ci): handle eviction when staging portable build cache

* docs(readme): fix French heading spacing

(cherry picked from commit 0ccd0e6999)

* test(ci): verify observed cache coverage during eviction

* test(electron): assert composed launch cleanup diagnostics

(cherry picked from commit e1466dc480e715b427cddfc3569b2baf03574405)

---------

Co-authored-by: ShuaixinHuang <1836656514@qq.com>
2026-10-18 01:08:14 +08:00
morluto 7016951394 fix(process): retain diagnostics through bounded output finalization
Separate verified process cleanup from output closure. Bound additional retention from owned stop entry through cleanup retry, drain before detaching capture, and mark unreadable or abandoned output incomplete. Release owned event-loop references on drain timeout without changing the proven cleanup disposition; preserve borrowed handle reference state.

Cover held and failed cleanup, late tail, bounded drain, stream errors, borrowed authority, and a real POSIX inherited-stderr release barrier. The real pipe control drops its final ten bytes on the baseline and retains them with this change. Focused consumer checks passed, including simulated Windows ownership; native Windows and real provider failure scope remain unverified.

Android still constructs its startup error snapshot before retirement; that consumer correction remains separate work.

Fixes #4840
2026-10-18 01:03:19 +08:00
morluto 3fa972af7c fix(android): preserve typed JVM memory failures during loading
Translate actual OutOfMemoryError at the bridge boundary before upstream stringifies it. Preserve observed heap bytes, missing reasons, coroutine context and cancellation; retain SessionHolder ownership and load options. Restrict heap-specific remediation to known heap reasons and parse named bridge failure contracts once.

Coordinate bridge protocol v4, clarify doctor configuration versus target capacity, and preserve the memory primary across cleanup failure/retry. Verify controlled immediate/late/inline continuation outcomes with the pinned JAR and real JDK, focused tests, and tiny real CLI/MCP method workflows.

Actual heap exhaustion, the reported APK, pre-handshake failures, Linux and Windows remain unverified; no stress or profiling run.

Fixes #3517
2026-10-18 00:48:12 +08:00
morluto 9fa6d2b254 fix(android): preserve primary failures through cleanup retries
Compose cleanup failures with the canonical primary error and bind current resource attribution to the retained acquisition record. Remove the stale diagnostic alias and duplicate failed-handle representation.

Validate the strengthened controlled cleanup regression in an isolated checkout; it fails on the baseline's stale resources and passes with this commit. Real JVM cleanup failure is unverified.

Fixes #4835
2026-10-18 00:47:46 +08:00
morlutoandTaksh 63c65a2243 fix(android): recover original bodies when Java source is omitted
Resolve smali using frozen raw method names and full DEX descriptors. Select
one complete block before truncation for missing Java, static initializers
and decompiler marker fallbacks. Reject ambiguous or incomplete blocks and
preserve upstream disassembly failure notes.

Bind method replies to the selected descriptor with bridge protocol 3.
Remove consumer placeholder/error-prefix interpretations and the superseded
blanket overload fallback rejection. Producer failures now use the shared
failed-tool path before truncation. Migrate protocol fixtures and consumers.

Adapt the direct selector guard from PR #3450; recover original bytecode
instead of inferring a holder from generated comments.

Validation: 122 focused tests in 9 files; real pinned-JAR baseline regression
fails and candidate passes, including overloads, aliases after generation,
branches/handlers, 16-byte output and negative selection controls. Nine real
CLI and nine MCP fixture calls pass with parity/identity/digest/no-mutation
checks. Static/docs checks and two source reviews pass. Six completed real
MCP cost workflows recorded; same calls with improved source, no speedup
claim. Tiny authored APKs, macOS/JDK 21 only; reported editor APK and native
Linux/Windows unverified. Heavy profiling and stress remain stopped.

Fixes #3443

Co-authored-by: Taksh <takshkothari09@gmail.com>
2026-10-18 00:25:36 +08:00
morlutoandbalkan16 742b6f587f fix(android): preserve native and abstract body absence
Freeze body-absence access flags with stable parsed method identity, before
code generation can rewrite method metadata. Skip source slicing for these
methods and return unavailable empty source with explicit native/abstract
markers, rather than attributing neighbouring members to the selected method.

Adapt the access-flag guard and tiny Smali fixtures from PR #3527. Extend real
metadata and public CLI/MCP regressions for native, static native, abstract,
concrete overloads and re-reading frozen facts after neighbouring generation.
Rename the expanded method-body verifier and remove its old entry point.

Validation: 72 focused tests in 3 files; real pinned-JAR baseline control
fails and candidate passes without triggering code generation; 6 real CLI
and 6 MCP fixture calls with parity, identity and unchanged APK; docs/static
checks and two source reviews. Six measured real MCP workflows, no speedup
claim. Tiny authored APK only; reported BinaryEye, Linux/Windows and browser
workflows unverified. Heavy profiling/stress remain stopped.

Fixes #3488

Co-authored-by: balkan16 <57933796+balkan16@users.noreply.github.com>
2026-10-17 23:53:23 +08:00
Prasad Navale 3c1cce78ee fix(domain): admit Qualcomm Hexagon (EM_HEXAGON, 164) ELF binaries (#4819)
* fix(domain): admit Qualcomm Hexagon (EM_HEXAGON, 164) ELF binaries

Resolve missing ELF admission case for Qualcomm Hexagon DSP targets (e_machine = 164, EM_HEXAGON).

- Add 'hexagon' to BINARY_ARCHITECTURES and HeaderArchitecture
- Map EM_HEXAGON (164) in elfArchitecture() to 'hexagon'
- Include 'hexagon' in GhidraProvider's SUPPORTED_ARCHITECTURES
- Gracefully decline 'hexagon' with Ghidra-directed diagnostic in Hopper and IDA
- Add unit tests for Hexagon ELF parsing and adapter admission checks

Fixes #4781

* fix(hopper,ghidra): add Ghidra guidance to Hopper Hexagon refusal and add Ghidra admission regression test
2026-10-17 23:52:03 +08:00
morluto b27e1a74c9 docs(i18n): complete Malayalam locale registration and links
Resolve eight nested README links from their owning directory. Preserve the
shared README/website inventory contract by registering Malayalam with an
explicitly untranslated catalog and the existing visible, noindex English
fallback. Regenerate the shared website navigation and catalog references.
Existing parsed translations remain unchanged.

Validation: docs check, full website check (401 HTML pages, 27790 local
references, 19 tests), all 19 generated Malayalam fallback pages, and two
source reviews. No Malayalam website translation or browser layout claim.

Fixes #4821
2026-10-17 23:39:40 +08:00
morlutoandAbhay Tiwari dc2e8117b6 fix(apktool): distinguish document failures from entry omissions
Return tagged string-document parsing failures instead of fabricating one unparsed entry. Preserve XML failure reasons and publish unknown counts with partial coverage; count only examined unsupported entries in validated documents. Migrate every consumer, remove the superseded throwing XML wrapper, and retain completed failure Evidence through cancellation and failed cleanup.

Adapt the document-versus-entry distinction from PR #4804 using the shared Result and XML owner. Multi-table projection and its aggregate bounds remain under review in #4777.

Validation before incoming main rebase: 229 focused tests in 15 files, four baseline controls fail, static/docs checks and two source reviews. Twelve tiny actual MCP workflows and four CLI controls; authored launchers only, no real Apktool/JVM/Windows qualification.

Fixes #4820

Co-authored-by: Abhay Tiwari <abhaytiwari0821@gmail.com>
2026-10-17 23:27:29 +08:00
rodricksz4h5 bec88b9d77 fix(javascript): retain CommonJS exports defined with Object.defineProperty (#4725)
* fix(javascript): retain CommonJS exports defined with Object.defineProperty

tsc, Babel and Rollup emit Object.defineProperty(exports, name, descriptor) for CommonJS re-exports. The semantic projection only recognised assignments, so these exports were missing from export_names and exposes edges. Recognise the call on exports or module.exports with the existing unmodified-global and receiver checks, track its receiver lifetime like an assignment, and link a data descriptor's value like the assigned value; an accessor's result stays unknown.

* fix(javascript): unwrap assignment chains in defined CommonJS export values

A descriptor value such as holder.parse = require("./parser").parse lost its require origin because only the assignment path took the rightmost assigned value. Do it once in the shared export builder.
2026-10-17 23:23:47 +08:00
ShuaixinHuang 6b0113a534 fix(browser): preserve URL paths when removing credentials (#4731)
* fix(browser): preserve URL paths when removing credentials

* test(browser): verify URL userinfo through real V8 captures
2026-10-17 23:23:37 +08:00
ShuaixinHuang 68c3c5b538 fix(native): preserve leading U+FEFF in Apple metadata names (#4730)
* fix(native): preserve leading U+FEFF in Apple metadata names

* test(native): run property metadata regressions on macOS
2026-10-17 23:23:27 +08:00
kraken-503 af67ad5047 docs: add ml translation (#4792)
* docs: add malayalam translation

* docs: add ml hyperlinks to other docs

* docs: fix ml hyperlinks

* docs: fix ml hyperlinks

* docs: add english hyperlink in README_ml.md

* docs: fix README_ml.md

* docs: fix README_ml.md

* Update links and headings in README_ml.md
2026-10-17 23:22:58 +08:00
Shivam Dwivedi c1fe0d653d fix(setup): recognize shared CLI launcher aliases (#4803) 2026-10-17 23:22:43 +08:00
morluto d38f099692 fix(apktool): disclose platform and release advisory windows
Carry the selected host into the version owner, disclose the Windows follow-up before 2.9.3, and bound the 3.0.x resource type-name validation warning before 3.0.2. Share warning formatting and preserve reported spelling, prerelease semantics and exact dirty-release handling.

Verify the upstream producing-boundary patch instead of assuming a file-writer sanitizer. Explicitly label inclusion of the tagged 3.0.0 release line as source-derived; version and host guidance do not establish engine contents or backports. Retain warnings with completed Evidence during cancellation and failed cleanup.

Validation: 222 focused tests in 15 files, 16 baseline controls fail, static/docs checks and two source reviews. Twelve tiny actual MCP workflows and six CLI controls with authored launchers; no real Apktool/JVM, native Windows, exploit or true cold verification.

Fixes #4818
2026-10-17 23:16:13 +08:00
morlutoandGovindu Sasanka 63696d2773 fix(apktool): retain advisory facts from the version observation
Parse the launcher version once to own both compatibility and CVE-2024-21633 advisory facts. Inspection and decoding consume those facts, including completed Evidence retained during cancellation. Preserve source spelling, exact dirty-release handling, prerelease semantics, and existing version-only failure diagnostics.

Adapt the Apktool warning policy from PR #3440. State that a reported version does not establish engine contents or downstream backports; avoid recommending 2.9.2+ as generally safe. Other advisory applicability and release-range questions are tracked in #4818.

Validation: 194 focused tests in 15 files; final 87 source checks; five baseline controls fail; static/docs checks; two source reviews. Twelve tiny actual MCP workflow comparisons and four CLI controls; authored launcher only, no real Apktool/JVM/Windows or exploit verification.

Fixes #3438

Co-authored-by: Govindu Sasanka <31107592+GovinduSasanka@users.noreply.github.com>
2026-10-17 23:08:00 +08:00
morluto 6385ef4355 fix(apktool): derive locale size from resource configuration fields
Allow the 23-character script-region-variant representation emitted by Apktool, retaining the shared admission grammar and request aliases. Exact discovery and CLI/MCP selection consume the same bound.

Validation: 67 focused tests across four files; five controls fail on the baseline; static/docs checks and two source reviews. Twelve ordinary tiny CLI/MCP task comparisons preserve Evidence; two actual authored-launcher long-locale CLI/MCP calls select the table. No real Apktool/JVM or native Windows verification.

Fixes #4817
2026-10-17 23:00:26 +08:00
morlutoandOke Iyanuoluwa E. 98886adddf fix(apktool): disclose tables outside exact locale selection
Inventory observed entries through the owned artifact traversal, preserve other configuration names, and disclose non-regular tables with partial coverage. Share request alias normalization with exact table classification and preserve filesystem failures.

Adapt the disclosure policy from #4738. Correct the fixture command separator so all advertised tables are actually created.

Validation: 164 focused tests; check:fast; test discovery; docs:check. Two regression controls fail on the baseline. Twenty-four tiny authored CLI/MCP comparisons; no real Apktool or Windows verification.

Fixes #4612

Co-authored-by: Oke Iyanuoluwa E. <oke.iyanuoluwa12@gmail.com>
2026-10-17 22:55:08 +08:00
morlutoandPeter cc038da218 fix(apktool): attribute decode refusals to the selected APK
Carry caller-selected target identity separately from launcher selection. Only fully collected ordinary nonzero decode exits represent target refusals; startup, preparation, capture and signal failures retain provider attribution. Reuse one command/preparation output projection for probe and decode errors.

Adapt the target-path correction from PR #3462 (08d3d0d3a0) and extend its producer-boundary classification and regression coverage.

Validation: 131 focused tests in 12 files, final 50 source checks, build, typecheck/lint and docs. Ten regression controls fail on baseline 4844ae812. Twenty-four tiny actual CLI/stdio MCP refusal tasks preserve every projected field except the corrected message/path. Authored launchers only; no real Apktool/JVM or native Windows claim. Heavy stress/profiling remained stopped.

Closes #3340

Co-authored-by: Peter <304086198+peter-research@users.noreply.github.com>
2026-10-17 22:44:00 +08:00
morluto 4844ae812b fix(apktool): own file and workspace finalization
Replace raw descriptor and workspace bookkeeping with artifact file ownership, canonical chunk reads, private roots and cleanup leases. Retain failed owners, fence replacement acquisition, release successful peers once, and preserve completed Evidence and physical failures through final cleanup and cancellation.

Use the shared directory reader and enforce the examined-entry budget before special-file omission. Keep command and artifact retry ownership separate by exact lease identity; remove superseded reads, implicit traversal and suppressing closes.

Validation: 163 focused tests in 20 files, build, typecheck/lint, docs and discovery passed. Six public controls fail on clean baseline 11bcf4425. Tiny FIFO, descriptor denial/retry, late allocation and mixed outcomes are controlled fixtures. Twenty-four completed CLI/stdio MCP comparisons return byte-identical replies; no speedup claim. Actual Apktool/JVM, natural OS denial and native Windows remain unverified; heavy stress/profiling stayed stopped.

Closes #4812
2026-10-17 22:36:51 +08:00
morluto 11bcf44252 fix(apktool): retain command cleanup ownership through recovery
Admit provider operations through one command resource scope, retain exact process and preparation-helper cleanup capabilities, and bind original failures to their live cleanup leases. Keep unknown recovery capabilities unresolved and fence their workspaces.

Interpret version output at command completion, preserve opaque cancellation and compiler output, and attribute prerequisite failures to the consuming operation. Prepare Darwin ownership outside the short version deadline.

Validation: 106 focused tests across 11 files; final 44 source regressions; build, typecheck/lint, docs and test discovery. Eight new controls fail on the clean baseline. Tiny authored launchers exercise process cleanup and public CLI/stdio MCP; actual Apktool/JVM and native Windows remain unverified. Heavy stress/profiling remained stopped.

Closes #4808
2026-10-17 22:22:47 +08:00
morlutoandJ0UH 376eeca770 fix(ghidra): prepare ownership before Java probe deadline
Allow independently bounded Darwin helper compilation to finish before the five-second Java deadline starts. Keep Linux process-table preparation under command supervision.

Share preparation failure translation between both stages so physical compiler outcomes, exact cancellation reasons and cleanup capabilities retain one owner. Adapt contributor PR #4795 and extend preparation handoff and retry controls.

Fixes #4793

Co-authored-by: J0UH <217747670+J0UH@users.noreply.github.com>
2026-10-17 22:06:16 +08:00
morluto f4322b15ed fix(javascript): bound semantic unknown retention at projection
Admit unknowns before canonical construction and provenance interning. Offer independent per-file and application capacities through CLI, Evidence and the owned analysis worker, and reject over-allocation during streamed decoding.

Report examined omitted emission occurrences by family and reason without retaining discarded identities. Preserve omission-free graph identities and distinguish node truncation from overall partial coverage.

Fixes #4797
2026-10-17 21:57:31 +08:00
morlutoandAniketXD 926e18b3fc fix(native): report PE resource subject architecture
Reuse the canonical COFF decoder and one optional-header magic rule. Preserve unknown architecture for conflicting headers and unproven managed OS overrides; assert subject parity through CLI and MCP.

Adapted from AniketR10/rea-aniket PR #4801 (250c9d726f), with expanded ARM and late-cancellation coverage.

Fixes #4800

Co-authored-by: AniketXD <aniketrawat826@gmail.com>
2026-10-17 21:44:54 +08:00
morluto e7df00e807 fix(electron): retain process and transport cleanup owners
Retain independent teardown leases, block capture admission until recovery, and preserve cancellation through failed finalization. Reuse pending close operations and require fresh Windows lineage plus passive family absence proof without cached descendant kills.

Fixes #4805
2026-10-17 21:40:46 +08:00
morlutoandhhang f9de41371f fix(electron): own fuse cleanup through adapters and shutdown
Adapt the prepared descriptor lifecycle repair from xu91102/rea dbb7db16. Bind exact file cleanup leases, retain typed physical failures and cancellation reasons, and join CLI/MCP finalization and active preflight. Share canonical Evidence construction and retain completed reports across reader handoff cancellation.

Scope active capture admission through shutdown and gate launch after close. Preserve successful descriptor peers and retry only unresolved owners. Separate process/transport retry ownership remains tracked in #4805.

Validation: 168 focused checks passed, one Windows-only skip; built CLI and actual stdio MCP controlled descriptor recovery; build, static and docs checks. No natural OS fault or real Electron launch/teardown claim. Ordinary full replies and Evidence IDs remain byte identical across 30 small CLI tasks.

Fixes #4658

Co-authored-by: hhang <169027046+xu91102@users.noreply.github.com>
2026-10-17 21:24:00 +08:00
2d84c800bc perf(android): filter class pages before bridge serialization (#4791)
Filter class names at the native owner before serialization, and resume matching pages through contiguous inventory positions without a second index or query-result cache. Preserve selected source Evidence, query identity, complete top-level coverage and shared CLI/MCP behavior.

Fixes #4776.

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-17 13:21:37 +00:00
Ysopwnable 060eb43b54 docs: celebrate 300,000 GitHub stars 🎉 (#4778) 2026-10-17 21:12:16 +08:00
morlutoandKaoru0822 bf54c46264 fix(electron): share executable architecture facts for fuse inspection
Own ELF machine and canonical family in the fixed-header parser. Fuse inspection consumes validated ELF facts and complete COFF machine values while retaining null for unknown or incomplete headers. Binary target, MIPS and Go consumers reuse the parsed facts.

Adapt public CLI controls and fixture builders from #4788; extend x86, ELF byte order, malformed and unknown headers, MCP projection and byte preservation coverage. 430 focused tests passed, one Windows-only skip. Five authored inert fixtures have full actual CLI/stdio MCP Evidence parity; real Linux/Windows Electron apps remain unverified.

Fixes #4786

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-17 21:10:07 +08:00
Ysopwnable bd3210eb24 fix(ci): format keyed archive CLI regression test (#4796)
Apply the locked formatter to the keyed-archive CLI/MCP regression test. Preserve all assertions and runtime behavior.
2026-10-17 13:05:59 +00:00
morluto 22a0746f90 fix(wasm): retain cleanup ownership through WABT recovery
Bind runtime and descriptor cleanup to exact retry leases and retain command supervisors until stop is confirmed. Preserve primary errors, partial Evidence and finalization cancellation reasons.

Validate with 88 focused tests, official WABT 1.0.42 CLI/MCP verifier (51 cases), build, static and documentation checks. Command stop failures use controlled source seams; real permission failures and target execution are unverified.

Fixes #4787

Fixes #4798
2026-10-17 21:02:50 +08:00
morluto 7aa4b98c98 fix(plist): own XML values and numeric facts in one decoder
Interpret the validated, depth-bounded DOM directly. Collect source number
facts during the same traversal and share them with keyed archives, Interface
Builder and native plist projections. Remove the second XML parse, key aliases,
source-location rewriting and both duplicate XML numeric scanners. Preserve
character references, container/null behavior, safe own-property construction
and prototype omission accounting.

Decode signed hexadecimal integers and combine real text/CDATA. Retain exact
integer identity when a finite integer exceeds even Number's finite range,
using the shared scalar projector. Keep unsupported mixed integer syntax
conservative and report incomplete metadata.

Adapt @apitoagents's hexadecimal regression and literal-parsing proposal from
PR #3475. Native plutil controls establish the supported hex/real cases and
confirm that the synthetic 401-digit overflow case exceeds native bounds;
retaining accepted input does not claim native-format support.

Validation: 274 focused checks in 30 files pass, one skipped; build,
check:fast and docs:check pass. Built CLI/actual stdio MCP, native plist and
Interface Builder controls cover kinds, references, exact digits and digests.
Eight baseline checks fail; native binary conversion independently verifies
updated CDATA real expectations. 48 tiny completed CLI cost comparisons
preserve ordinary XML/binary and all three native replies byte for byte.
Two read-only reviews clear. No statistical speed claim, heavy profiler,
investigated-target execution or real deep-provider verification.

Fixes #3373
Fixes #4042
Fixes #4789
2026-10-17 20:40:55 +08:00
morluto 78cf6100f3 fix(plist): preserve complete XML dictionary key identities
Use the validated DOM's character-data key names for both identity and
prototype omission. Replace first-child reinterpretation with canonical,
collision-free aliases inside the pinned decoder boundary; restore names
through the existing dictionary projection. Alias every spelling of the
same name to preserve duplicate assignment order. Handle empty key spellings
and keep scalar key elements outside aliasing. Preserve value text and bytes.

Adapt @thangldw's tests and proposal from PR #3426. Avoid the proposal's
closing-content scanner and re-escaping source names. Add duplicate, empty,
alias-collision, scalar-key, native fallback and Interface Builder controls.

Validation: 180 focused checks across 20 files pass, including built CLI and
actual stdio MCP, build, check:fast and docs:check. Baseline public inspection
truncates main to ma. 24 tiny completed CLI cost controls preserve ordinary
XML/binary full replies and Evidence IDs byte for byte. No statistical speed
claim, heavy profiling, investigated-target or real deep-provider execution.

Fixes #3371
2026-10-17 20:28:01 +08:00
morluto 2cf9c28f27 fix(apple): preserve decoded keyed archive scalar identity
Move plist projection into the graph owner and identify generated scalar
wrappers by producer identity through every dictionary/UID consumer. Remove
the intermediate JSON clone that erased those facts. Literal wrapper-shaped
dictionaries remain dictionaries; scalar $top values fail as malformed.
Keep numeric projection after graph interpretation, preserve unknown counts,
and retain binary prototype-key partial facts with an explicit limitation.

Adapt @Jax367's relevant scalar proposal and public regression from PR #4317.
Add scalar-root, literal-root and binary prototype controls. Correct only
the captured Foundation data node expectation and its manifest digest;
original producer bytes and source are unchanged. Unrelated PR changes excluded.

Validation: 175 focused checks across 23 files pass, one skipped; build,
check:fast and docs:check pass. Public CLI and stdio MCP cover both encodings.
Baseline scalar controls fail; 24 tiny completed CLI cost comparisons retain
ordinary full replies and Evidence IDs byte for byte. No statistical speed
claim, heavy profiling, target execution or real deep-provider verification.

Fixes #4295
Fixes #4785
2026-10-17 20:20:53 +08:00
morluto 5d6029ea62 fix(apple): derive launchd domains from owning directories
Use the matched Contents/Library/LaunchAgents or LaunchDaemons suffix to
select a plist's domain. Remove the independent scan of every ancestor.
Keep regular-file, application-root, sidecar and suffix admission rules.

Adapt @bnkaiteam's proposal and ZIP boundary regression from PR #3504,
adding public CLI/stdio MCP controls for nested bundles, case variants,
misleading ancestors and excluded paths.

Validation: 53 focused checks, build, check:fast and docs:check pass.
Two new controls fail before the fix. 12 completed actual built CLI cost
controls preserve the ordinary reply and projection ID byte for byte.
No heavy profiling, target or real deep-provider execution; npm release
and whole-agent costs remain unverified.

Fixes #3353
2026-10-17 20:10:12 +08:00
morluto fc935d0df3 fix(mobile): derive runtime hints from classified components
Use the owning DEX/JVM and Ark/JavaScript component lists for runtime
summaries. Remove the independent filename checks and Harmony path copy.
Preserve native format checks and framework path conventions.

Adapt @eco-null's proposal and regressions from PR #3627. Cover all eight
supported source extensions and unrelated content, plus the Android
inverse mismatch discovered during consumer review: .dex/.class files
had no bytecode components but produced runtime hints.

Validation: 44 focused checks, build, check:fast and docs:check pass.
Six Harmony assertions and one Android built CLI assertion fail before
this fix. 36 actual built CLI cost controls preserve four ordinary
complete replies and projection IDs byte for byte. No heavy profiling,
target or real deep-provider execution; npm release unverified.

Fixes #3350
Fixes #4782
2026-10-17 20:02:26 +08:00
morluto a425b3e528 fix(mobile): classify authenticated file occurrences as components
Select file and slice identity once before Android, Apple and Harmony
classification. Keep directory/link facts in source inventory and Apple
anatomy rather than deriving code roles, runtime hints or bridges from them.
Preserve occurrence order, multiplicity and existing unavailable facts.

Adapt @flyl1u's proposal and public CLI/stdio MCP controls from PR #3830,
extending the controls and structural fix to Apple and slice/link semantics.

Validation: 80 focused checks, build, check:fast and docs:check pass.
Four package controls fail before the fix. 72 tiny completed source cost
tasks preserve all regular-file control replies and projection IDs byte
for byte. No heavy profiling, target or real deep-provider execution;
full agent/public-task costs and published npm package unverified.

Fixes #3349
2026-10-17 19:58:18 +08:00
morluto 149a0fc06c fix(apple): derive bundle anatomy from directory facts
Build separate directory and authenticated-file indexes before applying
anatomy name preferences. Share those facts across application roots,
nested bundles, layout, metadata, executable candidates and signing paths.
Remove mixed child-name interpretation and downstream membership repairs.

A leaf Contents/Versions resource no longer changes a shallow layout, and
leaf files/symlinks cannot manufacture application roots. Real explicit
and implied directories retain their existing semantics and spelling.

Adapt the directory-identity proposal and source regressions from PR #3505
by @bnkaiteam, extending it to metadata file selection and root admission.

Validation: 57 focused checks, build, check:fast and docs:check pass.
30 tiny completed source projection cost controls preserve ordinary deep
and versioned replies byte for byte. No real-provider/target execution,
heavy profiling or published npm verification.

Fixes #3359
Fixes #4779
2026-10-17 19:53:45 +08:00
morluto c192c58815 fix(apple): retain unavailable application components
Preserve unread file and slice facts before Apple attribution. Report partial
component coverage while keeping manifest count completeness independent.
Directories and symlinks retain their existing representation.

Consolidate occurrence identity interpretation and component schemas across
Apple, Android and Harmony; remove superseded producers. Android/Harmony
completed source replies and projection IDs remain byte-identical in controls.
Apple's additive unavailable_components field changes its projection IDs.

Adapt the unavailable-component proposal and real ZIP regressions from
PR #4692 by @rodricksz4h5, adding directory, CLI, MCP and non-encrypted controls.

Validation: 77 focused checks; check:fast; docs:check (5 README checks).
18 tiny completed source cost controls; no real-provider/target execution
or heavy profiling. Published npm package and large-input costs unverified.

Fixes #4688
2026-10-17 19:46:20 +08:00
e5ee3ac658 fix(apktool): preserve decoded APK Evidence subject (#4771)
Bind shared CLI/MCP Evidence to the digest already computed from the owned
APK snapshot. Exercise source mutation during decoding through the shared
application workflow and verify subject identity in the real Apktool lane.

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-17 11:36:21 +00:00
morluto 969aafcf28 fix(ghidra): compare final DOS relocation windows
Adapt the correction and authored overlap control proposed by @berelels in #4156 to the bounded prepared-image owner. Retain each fixup's application facts, then read every memory window after all writes. Carry the producer's load segment into comparison and advance only the MZ evidence revision.

Validation: 129 focused parser/comparison/MCP checks, 38 shared MCP harness checks and 41 selected provider checks passed, with 15 checks overlapping those runs. Fourteen lifecycle checks also passed, plus static/build/docs checks. Two baseline controls failed before the correction. Twelve completed normal source comparisons retained byte-identical replies; no real Ghidra or maximal-relocation performance qualification is claimed.

Fixes #3981
2026-10-17 19:30:11 +08:00
Kaoru0822andClaude Opus 5.5 34239d445b fix(flutter): keep completed inspection facts when cancelled during snapshot cleanup (#4766)
FlutterBuildProvider.execute checks the caller signal after its awaited
snapshot-root removal. When the signal was aborted during a successful
first removal, that check replaced the completed AnalysisExecution with a
bare AnalysisCancelledError, so identify-flutter-build and
inspect-dart-aot reported a typed cancellation without
details.partial_observation and the shared CLI/MCP Evidence assembly
never saw the facts.

The post-cleanup check now keeps the caller's abort reason and retains a
completed result as the cancellation's partial observation. The Evidence
composition from executeProviderOperation moves into
createAnalysisExecutionEvidence beside the provider contract, so the
success path and the retained cancellation use one composer and carry
identical Evidence. Failed results keep their existing classification.

Fixes #4717

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:27:55 -07:00
Kaoru0822andClaude Opus 5.5 83d2780008 fix(ida): refuse universal Mach-O targets in attached profiles (#4765)
Attached IDA binds the open database to the target only through the
recorded whole-input SHA-256, path and image base. Every slice of a
universal Mach-O shares that digest, so an attached database of another
slice passed the identity check and its results were attributed to the
host-selected architecture. Attached admission now reports the target
format as unsupported, with lipo -thin and headless recovery, before any
upstream contact. Headless mode keeps thinning the selected slice.

Fixes #3871

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:27:46 -07:00
Kaoru0822andClaude Opus 5.5 8589b7e778 fix(evidence): verify staged output identity after its final write (#4764)
* fix(evidence): verify staged output identity after its final write

On macOS FAT32 and exFAT volumes an empty file reports a placeholder file
ID, and the first write assigns its cluster-derived ID. The staged JSON
writer sampled the descriptor identity right after exclusive creation, so
publication and cleanup both rejected REA's own staged file as replaced:
every export failed with cleanup_incomplete and retained a .rea-write-*
directory.

The staged output owner now observes the descriptor identity immediately
before closing it, after the last write, and uses that identity for the
publication and cleanup pathname checks. A failed observation leaves the
identity unknown, so cleanup still refuses pathname removal.

Fixes #4613

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

* test(evidence): cover failed final staged identity reads

Reject the staged descriptor's final stat and verify that the writer
still closes the descriptor, refuses publication, and retains the
unverified staged content with incomplete cleanup.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:27:38 -07:00
Kaoru0822andClaude Opus 5.5 63c530998e fix(flutter): report cancellation during snapshot cleanup with completed observations (#4762)
The one-shot Flutter CLI commands passed their command signal to the
inspection but not to finishAnalysisCommand, whose post-close cancellation
guard only runs when a signal is supplied. When the provider's first
snapshot-root removal failed, close() retried it after the inspection had
returned; SIGINT during that retry set exit status 130 while the command
still printed ordinary successful Evidence.

Pass the command signal to the finisher so an abort observed after the
awaited cleanup retry yields typed cancellation that retains the completed
Evidence as partial_observation. A failed retry still reports
cleanup_incomplete ahead of the later signal.

Fixes #4640

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:27:23 -07:00
Kaoru0822andClaude Opus 5.5 f03a55909d fix(mcp): accept authentic native Evidence for managed boundary verification (#4761)
The MCP verify_managed_native_boundaries handler resolved native
observations through an inspect_macho/analyze_function allowlist before
calling the shared verification service, and reported any other authentic
operation as evidence_integrity_mismatch. The domain already owns which
native operations it can read symbols from and counts the rest as
unsupported, which is what the CLI returns. The MCP resolver now only
authenticates native observations and leaves operation support to the
shared workflow, so both adapters return the same partial verification.

Fixes #4639

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:27:06 -07:00
Kaoru0822andClaude Opus 5.5 f1ab5959bd fix(javascript): bind response endpoints only from writes that reach the read (#4759)
collectResponseConsumers copied the linked request's endpoint onto a
response consumer whenever the receiver binding had exactly one
initializer (added in 0323ce0a2, #3822). A single initializer is a source
fact, not proof that the write reaches the read: an incoming parameter
that is overwritten only conditionally, or only after the read, still
lets the consumer read a caller-supplied response, yet it received the
request's exact endpoint.

The sole write now also has to cover the read, using the same rule the
call resolver applies to incoming values: either it is the binding's
stable unconditional declaration initializer, or the shared read-position
owner (semanticBindingAtRead) reports a definite preceding initializer.
Otherwise the endpoint stays null.

Fixes #4606

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:26:55 -07:00
Kaoru0822andClaude Opus 5.5 31c87b40ee fix(javascript): report oversized recovery inputs as file-size limits (#4757)
scanRecoveryFile raised a plain AnalysisOutputError when a selected file
exceeded the remaining operation-wide input allowance, and
snapshotRecoveryInput folded that, read failures and UTF-8 decode
failures into one invalid_value request issue. A 64 MiB + 1 input was
therefore reported as a retryable invalid argument whose only record of
the 67108864-byte budget was message text that also called it an
invalid analysis output, and malformed UTF-8 received the same reason.

The scanner now marks its byte-bound refusals with the bound it
enforced. snapshotRecoveryInput, which owns the meaning of that bound
as the remaining total input allowance, reports it as a non-retryable
file-size AnalysisResourceConstraintError with maximum_input_bytes and
remaining_input_bytes, and decodes UTF-8 separately as an invalid_format
issue. Other scanner consumers still receive an AnalysisOutputError, and
the limit stays enforced.

Fixes #4629

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:26:39 -07:00
Kaoru0822andClaude Opus 5.5 6a407619fe fix(javascript): report malformed runtime context events as excluded (#4755)
V8 Inspector capture counted an execution-context created or destroyed
event whose context ID was missing or not a safe integer as retained,
but recorded nothing about it. The capture counters claimed the event
was kept while the context list silently omitted it, and no unknown
identified the loss.

The producer that parses the event and owns the capture counters now
records an invalid-context count, mirroring the existing invalid-script
accounting. The projection reports a non-zero count as an explicit
unknown, so the retained count and the reported omission agree. No
context is invented from a malformed ID, and all-valid captures are
unchanged.

Fixes #4685

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:26:25 -07:00
Kaoru0822andClaude Opus 5.5 95b561f2e9 fix(native): retain Apple dispatch metadata descriptor cleanup ownership (#4745)
* fix(native): retain Apple dispatch metadata descriptor cleanup ownership

inspect_native_dispatch_metadata opened the target with raw
openRegularFile and closed it in a finally block, so a rejected close
replaced integrity, capacity or cancellation failures and left no owner
to retry. The read now uses the shared owned regular-file operation in a
client resource scope; the physical failure stays the cleanup primary,
client close retries the exact descriptor, and a confirmed release
clears the original error's cleanup uncertainty. Decoding runs after the
descriptor is released.

Fixes #4743

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

* fix(verify): give the Apple dispatch verifier an owned file scope

Pass an ArtifactResourceScope to inspectAppleDispatchMetadata and close
it after inspection so a failed descriptor close is retained and retried
rather than reaching an undefined scope.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:20:40 -07:00
morluto 2f9b9c48b8 fix(ghidra): stream DOS MZ overlay attestation
Keep initialized image facts and full source identity separate at the snapshot owner. Stream overlay bytes into original and modified digests, retain format-bounded image bytes, and consume prepared relocation/mapping facts. Preserve completed comparisons, exact cancellation and cleanup retry through descriptor finalization. Keep explicit source refusals as typed primary failures.

Validation: 119 focused parser/comparison/MCP checks, 40 selected provider checks and 14 lifecycle checks passed; static checks, runtime build, discovery and docs checks passed. Twelve small completed source comparisons retained byte-identical full replies. Real Ghidra, large input and full public CLI/MCP performance remain unverified. The separate overlap timing issue #3981 remains open.

Fixes #4770
2026-10-17 19:18:34 +08:00
morluto 3fc007534b fix(native): validate NativeAOT PE virtual ownership
Reject contradictory headers, overlapping virtual sections, DOS header reuse and image intervals outside the 64-bit address domain before metadata interpretation. Preserve empty and adjacent ranges, source section order, and raw padding semantics. Advance the metadata profile revision and retain provider snapshot refusal facts.

Validation: 37 parser checks and 35 selected provider checks passed; check:fast and build:cached passed. Six tiny authored-fixture summary/detail tasks returned byte-identical 791-token replies. No real-engine or Windows loader qualification.

Fixes #4763
2026-10-17 19:02:29 +08:00
morluto 9c56d09c05 fix(ghidra): preserve load-image completion through cancellation
Consume the named inventory observation once and compare typed facts through one final cancellation check. Retain measured or completed load-image facts and exact reasons, preserve source partials and cleanup, and remove duplicate interpretation and format-specific abort guards.

Validation: 131 contract/projection checks, 40 selected provider checks, and 24 selected private-file/socket lifecycle checks pass; typecheck, lint and builds pass. Includes the original confirmed descriptor-close boundary and late result consumption. Tiny authored fixtures and simulated installation/engine facts; no real Ghidra, investigated target or heavy profiling.

Equivalent completed DOS/raw/NativeAOT tasks retain byte-identical full replies and one source read. First processes and two alternating warm repeats; no statistically established performance improvement.

Fixes #3977
2026-10-17 18:52:42 +08:00
morluto a43ce8a98f fix(ghidra): retain measured facts through NativeAOT failures
Attach each caller’s measured observations before source failure and cleanup projection. Preserve those facts through admission, peer and draining cancellation, cached results, cleanup fences and later lease resolution.

Validation: selected NativeAOT provider controls and typecheck/lint passed in the load-image audit tree. Related consumer validation follows in the next commit.

Refs #3977, #4753
2026-10-17 18:52:42 +08:00
ae029fe2f8 perf(ghidra): aggregate binary overview at the provider boundary (#4754)
Compute overview counts at the Ghidra inventory owner, preserve complete inventory access and coverage, and share CLI/MCP projection. Keep native aggregate Evidence separate from workflow snapshot identities.

Fixes #4746

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-17 10:44:24 +00:00
morluto 5120eb4412 fix(ghidra): join shared NativeAOT derivation and retain outcomes
Replace the private promise race with a named snapshot owner using SharedStartupAttempt. Keep peers independent, stop and join final departure, preserve source failures and completed facts through draining waits, and fence replacement behind retained cleanup. Close joins derivation before releasing the underlying client.

Validation: 31 selected simulated-provider lifecycle and NativeAOT checks, 80 shared-contract/schema/projection checks, typecheck, lint and builds. Completed tiny summary/detail/close comparison preserves full replies and one snapshot read. No real Ghidra, investigated target or heavy profiler execution.

Refs #4753
2026-10-17 18:37:57 +08:00
Ysopwnableandabdooo2235 f0d175dace fix(verifiers): read packed bridge without extraction
Parse only the exact regular packed Python bridge member without extracting into the caller-owned private runtime root. Preserve required Ghidra admission, typed callers, native lease ownership and cleanup on success or failure.

Validation: 263 focused real tar/Python/ownership and CI selection checks, 42 official WABT packaged CLI/MCP cases, full check:ci/check:fast/actionlint, real-package alternating measurements and exact-head hosted CI passed. The required Windows lane exercises the retained native lease without skipping missing authority.

Fixes #4134.

Co-authored-by: abdooo2235 <abdalrhmantheiv15@gmail.com>
2026-10-17 10:35:31 +00:00
morluto 73965f9431 fix(ghidra): retain snapshot outcomes and join reader cleanup
Use the shared artifact resource scope for snapshot reads. Preserve completed facts, exact cancellation reasons and descriptor cleanup leases through session and public error projection; keep parent cleanup pending until all retained resources release.

Validation: 22 selected snapshot lifecycle checks and 85 contract, projection and bounded-reader checks; typecheck, lint and runtime builds. Uses small authored Node/socket fixtures, not real Ghidra or investigated target execution.

Refs #4752, #3977
2026-10-17 18:25:59 +08:00
morluto 5e13e0a876 refactor(files): allow reader-owned cancellation failures 2026-10-17 18:25:52 +08:00
morluto 4a076f368c fix(native): bound NativeAOT reads to declared PE headers
Validate the consumed optional-header extent before interpreting mapping fields. Require complete header-backed read intervals and prevent failed header reads from falling through to section mappings. Advance NativeAOT profile interpretation identity to v4.

Refs #4750
2026-10-17 18:07:29 +08:00
morluto d9099190ab fix(native)!: retain UI outcomes through finalization
Carry caller and runtime deadline cancellation through helper cleanup, preserve command-owner reasons and physical failures, and retain collected scenario reports with typed terminal errors.

BREAKING CHANGE: failed or cancelled native UI scenarios now return typed errors with the collected report in partial_observation instead of successful reports containing failed or cancelled steps.

Refs #4227
2026-10-17 17:57:50 +08:00
morluto 04221e5f01 fix(native): bind UI runtime cleanup to exact owners
Join admitted helper work before runtime removal, retain one preparation outcome and root, and bind originating and retry errors to exact runtime release leases with live resources.

Refs #4227
2026-10-17 17:57:50 +08:00
Ysopwnable 2092f90b7e perf(ci): upload only current portable build cache entries
Stage only the current portable Turbo task archives, metadata and available manifests for same-run artifact consumers. Share task identity/hash validation with cross-run keys and fail publication on incomplete preparation, while retaining existing cache authority and consumer build/prepack verification.

Validation: 252 focused tests, full check:ci, docs:check, check:fast, actionlint, real Turbo output equivalence and invalidation, restored CLI/MCP scenarios and full Linux package verification passed. Fault injection detected historical-entry inclusion. Exact-head hosted CI and available review passed; measurement limits are recorded in the PR.

Refs #4744.
2026-10-17 09:44:11 +00:00
morluto 0f7fd005db fix(native): retain LLDB readback ownership through cleanup
Own journal, capture, result and PID descriptors through confirmed release. Preserve parsed facts and exact cancellation reasons while retaining unresolved children and gating runtime removal on their completion.

Refs #4742
2026-10-17 17:40:49 +08:00
gongfppandgongfpp 5a7e8a166a fix(mcp): normalize browser scenario input errors (#4661)
Co-authored-by: gongfpp <22683417+gongfpp@users.noreply.github.com>
2026-10-17 17:36:32 +08:00
gongfppandgongfpp 9534e42ec8 fix(adb): mark unknown permission coverage partial (#4663)
fix(adb): mark unknown package coverage partial

Co-authored-by: gongfpp <22683417+gongfpp@users.noreply.github.com>
2026-10-17 17:36:19 +08:00
6b27d8f4e3 fix(electron): retain fuse descriptor ownership through failed final close (#4668)
* fix(electron): retain fuse descriptor ownership through failed final close

Static Electron fuse inspection admitted a file descriptor and closed it
in a bare finally: a rejecting final close() replaced the in-flight read
error, was classified by errno (e.g. EACCES) as a read permission failure,
and silently dropped ownership of the still-live descriptor.

Route the read through withOwnedRegularFile so a failed close keeps its
exact owner, preserves the primary error in the outcome, and surfaces as
RegularFileCleanupFailure. The provider now maps that to a primary error
with its own classification plus a ProviderCleanupError reporting
incomplete cleanup, instead of an access-denied read failure.

Regression tests fault close() (EACCES) with and without a primary read
error (EIO): both fail on the pre-fix revision and pass with the fix.

Fixes #4658

* fix(electron): keep cleanup report and partial evidence through cancel and successful reads

Address automated review on #4668:

- Handle RegularFileCleanupFailure before the cancellation check in
  failureFor: a cancelled operation whose final close rejects now reports a
  typed cancellation composed with the incomplete-cleanup error, instead of a
  bare AnalysisCancelledError that silently dropped the descriptor owner.
- Attach the completed fuse image as an explicitly partial Evidence
  observation when only the final close fails, instead of discarding the
  successful read. The abort-after-completion path keeps the same evidence on
  the composed cancellation error.
- Add provider-level regression tests: combined read+close faults, abort
  synchronized with the faulted close boundary, and partial-observation
  retention. Abort-during-close and partial-evidence tests fail pre-fix.

29/29 electron tests green; npm run check:fast clean.

---------

Co-authored-by: nosmile99 <nosmile99@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-17 17:36:06 +08:00
Oke Iyanuoluwa EnochandClaude Opus 5.5 f85a932d71 test(paths): pin Windows separator normalization before native admission (#4733)
rea-agents 6.5.0 passed an absolute caller path to Windows native
snapshot admission verbatim, so a spelling with forward slashes or
repeated separators reached the native component walker, which rejects
empty components as "Ambiguous Windows path component is unsupported"
(Win32 50). Current main already resolves every Windows caller path with
win32.resolve (fc791bb60), which collapses those spellings.

Pin that boundary: absoluteCallerPath normalizes four separator spellings
of one absolute Windows path, and on Windows parseBinaryTarget returns the
same canonical sourcePath for each of them. The Windows test fails when
the 6.5.0 verbatim-absolute-path rule is restored.

Fixes #4707

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 17:14:16 +08:00
morluto 69e670d268 fix(native): own call preflight hashing through client close
Reuse stable-file hashing and exact cleanup leases for target verification, join admitted call workflows before tracer close, and block replacement work while descriptor cleanup remains unresolved. Preserve physical failures, exact cancellation reasons and completed call facts; remove the duplicate reader and AbortError-name heuristic.

Validate real inert-file cleanup controls and controlled tracers through provider and MCP boundaries. No LLDB execution, real OS close-failure or Windows qualification.

Refs #4740
2026-10-17 17:12:39 +08:00
Ysopwnable 9d5b931875 perf(tests): reuse MCP connections within source matrices
Reuse test-owned stdio MCP connections within two stateless source-analysis matrices while retaining every original CLI/MCP scenario, schema/Evidence checks and test-finished cleanup. Add cross-input identity controls.

Validation: 23 focused public-workflow tests and complete check:ci passed; stale-response fault detected. Exact-head hosted CI and available review passed. Pinned workload measurements and their limits are recorded in the PR.

Refs #4737.
2026-10-17 09:11:22 +00:00
morluto 715c9c8a84 fix(native): retain signature facts through finalization cancellation
Bind signature inspection to its named domain result and retain completed facts in typed cancellation. Check cancellation after descriptor and root finalization, preserve exact caller reasons, and keep physical failures primary. Use explicit cancellation checkpoints instead of signal-state guesses.

Validate root and descriptor cleanup, retries, late root handoff, opaque reasons, provider projections, and existing real codesign/CLI controls. No real OS close-failure or Windows qualification.

Refs #4735
2026-10-17 17:01:21 +08:00
morluto 4f3b573b09 fix(native): bind signature snapshot cleanup to exact leases
Retain roots and descriptors through shared cleanup leases and bind composed errors to their actual pending owners. Successful retries shrink live attribution and reveal the original typed failure.

Validate mixed root and descriptor failures, partial/final release, existing target binding, and real codesign and CLI controls. No real OS close-failure or Windows qualification.

Refs #4734
2026-10-17 16:52:28 +08:00
morluto e09a503f44 fix(native): retain plist descriptor cleanup ownership
Use shared owned file operations for plist admission and source probes. Join admitted work during close, retain exact descriptor leases through retries, and preserve physical failures, cancellation reasons and completed converter output.

Validate with controlled cleanup faults and native plist CLI workflows on inert data. Real OS close-failure incidence and Windows behavior remain unverified.

Refs #4723
2026-10-17 16:43:14 +08:00
morluto 26bb85c007 fix(core): keep released cleanup dependencies empty
Distinguish unbound resource attribution from a completed dependency set so final release cannot restore historical resource names.

Refs #4578
2026-10-17 16:43:14 +08:00
9744d07211 docs(skills): capture measured analysis optimization workflow
Add a reusable contributor workflow for locating analysis bottlenecks, preserving Evidence and cache ownership, and comparing equivalent real tasks. Keep pinned Kuna results and experimental limits in an optional case study.

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-17 08:33:18 +00:00
ShuaixinHuang a040533470 fix(ghidra): reject byte matches outside searched coverage (#4531)
* fix(ghidra): reject byte matches outside searched coverage

* test(ghidra): cover inclusive and overlay byte match bounds

* test(firmware): assert composed cleanup error evidence

* test(ghidra): assert cancellation during profile shutdown

* test(jeb): retain Linux ownership prerequisite in isolation
2026-10-17 16:18:18 +08:00
ShuaixinHuang abe49808b2 fix(plist): ignore inherited XML entity lookup properties (#4530)
* fix(plist): ignore inherited XML entity lookup properties

* test(firmware): assert composed cleanup error evidence

* test(ghidra): assert cancellation during profile shutdown

* test(jeb): retain Linux ownership prerequisite in isolation
2026-10-17 16:17:53 +08:00
morluto 70de702109 fix(browser): share DOM snapshot admission
Own decoded node columns, attributes and parent validity once for web, Electron and SVG interpretation. Reject dangling, self and cyclic parent facts; preserve source positions and independently unknown fields. Remove fallback conversions and duplicated string/attribute interpretation.

Validation: baseline public CLI controls failed for four malformed cases with valid control passing; final 103 focused checks, 5 final built CLI controls, 1 late-detach cancellation control (20 skipped), check:fast and docs:check passed. Fake CDP producers and generated local files; no real browser/Electron or Windows qualification.

Refs #4709
2026-10-17 15:59:57 +08:00
4e14452ddb fix(native): report unidentified text plists as unknown (#4320)
* fix(native): report unidentified text plists as unknown

Require explicit XML identification in file output instead of treating all
text as XML. Preserve decoded plist values and source-format provenance
when plutil falls back to XML conversion.

Add provider-boundary regressions and real macOS CLI controls for OpenStep,
data-bearing OpenStep, XML, UTF-16 XML and binary property lists.

Fixes #4294

* fix(native): keep XML plists without a declaration labeled xml

`file -b` names XML only when a document declaration is present, so the
narrowed `\bXML\b` check reported a declaration-less XML plist as unknown and
broke the real-plutil `decodes xml plists that plutil cannot express as JSON`
CLI test. When `file` reports only text, read the source head once and label it
XML only when its first non-whitespace character (after a UTF-8 BOM) is `<`;
OpenStep and other text stay unknown.

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

* fix(native): distinguish OpenStep data from XML source markup

Recognize XML markup instead of treating every leading angle bracket as XML.
Keep data-only OpenStep sources unknown, honor explicit JSON identification,
and decode BOM-marked UTF-16 prefixes before detecting declarationless XML.
Add source-format regressions and macOS CLI cases for data-only sources.

---------

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 15:52:25 +08:00
星闌 de9371b85d fix(javascript): preserve effective child-process stdio options (#4336)
* fix(javascript): preserve effective child-process stdio options

* fix(javascript): retain proven callbacks and primitive stdio keys

* fix(javascript): preserve argv shapes and nullish spreads

* fix(javascript): bound callable proofs and retain exposed binding uncertainty

* test(javascript): keep callback acceptance within transport budget

* test(javascript): inspect application coverage for callback proof limits

* fix(javascript): keep spread command argument slots uncertain

* fix(javascript): bound mapped argument content proofs

* fix(javascript): distinguish erased declarations from runtime shadows

* fix(javascript): prove runtime module context before binding isolation

* fix(javascript): share erased declaration and opaque scope proofs

* fix(javascript): keep lowered enum scopes opaque

* fix(javascript): narrow stdio proofs and consolidate regressions

* perf(javascript): reuse lexical references for child shapes

* fix(javascript): retain CommonJS child argument context

* fix(javascript): keep Annex B affected child arguments unknown

* fix(javascript): recognize value import-equals runtime modules

* fix(javascript): retain exact stdio through module and primitive syntax

* fix(javascript): bound inline spread property resolution

* fix(javascript): distinguish copied methods from getters
2026-10-17 15:51:55 +08:00
郭立 Guo Li 0cd4eafd61 perf: reduce MCP launcher and browser capture overhead (#4350)
* perf(browser): 为单次捕获复用脚本资源索引

* docs(setup): 说明多会话直接启动以减少 npm 驻留
2026-10-17 15:51:23 +08:00
Tapraj-PathakandCopilot 509d4c8f56 Fix permissions count issue for pkg=null in ADB analysis and add test cases (#4665)
* Fix permissions count issue for `pkg=null` in ADB analysis and add test cases

* fix(adb): handle null package permission counts

Recognize pkg=null as unknown permission data and keep the provider projection aligned with the parser. Add regression coverage for the parser and provider.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-17 15:45:15 +08:00
morluto 79d2b71896 fix(electron): preserve unknown resource sizes
Use one typed CDP resource-size owner in web and Electron capture. Supplied invalid sizes retain null plus completeness diagnostics; omitted sizes remain unknown without inventing malformed metadata. Preserve other resource facts and valid zero/positive values.

Validation: public CLI regression failed against baseline clamping; 36 focused controls passed after the fix, check:fast and docs:check passed. Fake CDP producer with real CLI/transport and tiny local files; no real Electron/browser or heavy profiling qualification.

Refs #4708
2026-10-17 15:41:07 +08:00
Kaoru0822andClaude Opus 5.5 9be493880c fix(kuna): name the setting that owns a timed-out Kuna run (#4343)
* fix(kuna): name the setting that owns a timed-out Kuna run

A Kuna run past its deadline surfaced the generic "Analysis took too
long. Try a smaller request" message. The request is already one
function or one whole-program scan, and the same run takes as long
again, so the advice was wrong and REA_KUNA_TIMEOUT_MS or
REA_KUNA_PROJECT_TIMEOUT_MS was never mentioned.

Each Kuna command now carries a KunaDeadline: the configured
milliseconds and the setting that owns them, from KunaConfiguration.
A timeout reports, for example, "kuna decompile did not finish within
REA_KUNA_TIMEOUT_MS (120000 ms)." Its remediation says to raise that
setting and restart REA, and for a single-function decompile that the
session's project export can still answer. AnalysisTimeoutError now
accepts a producer message and remediation, which projection uses and
per-waiter scan errors keep.

Refs #1957

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

* docs(kuna): scope the provider_timeout statement to direct Kuna runs

A timed-out project export is reported through the export failure as
capability_unavailable, not provider_timeout.

Refs #1957

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

* fix(kuna): verify native xrefs under the project deadline

The provider's xrefs scan runs under REA_KUNA_PROJECT_TIMEOUT_MS, but the
native oracle in verify:kuna aborted at REA_KUNA_TIMEOUT_MS. A scan that
fit the project deadline but not the function deadline failed
verification although the provider answered it. Use the same deadline.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 00:38:16 -07:00
morluto 748ac7f0df fix(sqlite): preserve column identity before row selection
Read raw column metadata through the built-in PRAGMA in the private empty temp schema. Validate bytes before names become SQL identifiers, and select inventory subsets by exact encoded identity so unrelated malformed names cannot alias valid columns.

Validation: 5 focused identity controls; 15 selected producer/provider controls (33 skipped); public CLI baseline collision, fixed format refusal and valid-subset success; check:fast and docs:check. Generated inert SQLite fixtures on macOS arm64 with Node 24.18.0; no Windows qualification or large-file/stress workload.

Refs #4710
2026-10-17 15:33:59 +08:00
Saim ShafiqueandSaim Shafique 77c8a1ba32 fix(javascript): mark resource-skipped files parse_status skipped (#3852)
* fix(javascript): mark resource-skipped files parse_status skipped

Files above ~5 MB exhaust the worker heap during static analysis (or exceed
the 8 MB static-checkpoint budget with a larger heap). They were inventoried
with text included but never parsed, leaving parse_status null and no
counter, so the summary read as 'nothing there' instead of 'not analyzed'.

Report them as skipped: parse_status 'skipped' on the file observation and a
skipped_javascript_files statistics counter. The analysis-failure reason keeps
surfacing as a limitation entry.

Fixes #3670

* fix(javascript): default skipped_javascript_files when reading old saved evidence

Saved analysis evidence written before skipped_javascript_files existed failed validation against the strict reconstruction statistics schema, so users could not reuse old results for comparisons or runtime reconciliation. Accept the field's absence on read (defaulting to 0) while continuing to write it for new results.

* fix(javascript): preserve unknown skipped count for legacy evidence

The .default(0) gate fix fabricated a measured zero for saved
pre-change evidence, so comparisons would receive a definitive
"no files skipped" fact the producer never established. Use the
codebase's exactOptional idiom instead: legacy reads accept absence
and keep omission (unknown), while the producer still always writes
the field (required by JavaScriptArtifactReconstructionResult).

Tests: legacy payload now asserts the key stays absent/undefined;
current-output test keeps asserting the producer-written counter.

* fix(javascript): add required failure scope and status to graph fixture

---------

Co-authored-by: Saim Shafique <sx4im@users.noreply.github.com>
2026-10-17 16:33:41 +09:00
Mohamed Ayoub Eleuch 8a2a1a2b8b fix(cutter): preserve mixed Unicode output within the frame limit
Count real UTF-8 bytes in bounded chunks and retain authenticated omission for malformed Unicode. Preserve existing wire/resource limits and completion semantics.

Validation: producer/client regressions, fresh real Linux Cutter CLI/MCP output and Evidence recovery, and complete exact-head CI passed. Hosted unrelated CLI timeout and unchanged rerun results remain recorded in the PR.

Fixes #3330.
2026-10-17 07:30:30 +00:00
morluto c7e9e096d3 fix(plist): reject malformed XML before value decoding
Reuse the shared validated XML document for depth and prototype-key preflight, preventing recovery-only values from being projected as observations. Preserve OpenStep and valid XML source semantics.

Validation: 46 focused checks; 5 final syntax controls; 10 encoding and public CLI/MCP overlap checks; check:fast. Public malformed-entity CLI changed from success to typed format failure. Generated inert artifacts only; no real Apple application or native engine execution.

Refs #4714
2026-10-17 15:24:57 +08:00
Aditya kharmale 8c62a4aa36 fix(javascript): preserve case-sensitive Unicode seed identity
Use NFC for case-sensitive feature seeds while preserving the existing explicit insensitive compatibility fold.

Validation: exact/substring/absent controls, fresh public CLI/MCP workflows and complete exact-head CI passed. Hosted CLI-worker failure and unchanged rerun results remain recorded in the PR.

Fixes #3314.
2026-10-17 07:20:34 +00:00
morluto 3cfa00a29c fix(ghidra): preserve valid Unicode language metadata
Validate XML bytes before shared syntax parsing so literal U+FFFD remains valid while malformed bytes and declaration mismatches fail at their producing boundary.

Validation: 92 focused checks, 3 selected fake Apktool boundary checks, 6 final encoding controls, check:fast and docs:check. Ghidra coverage uses tiny real files and descriptors, without a real engine or Windows qualification.

Refs #4712
2026-10-17 15:17:03 +08:00
morluto 623339a7ab refactor(xml): centralize strict document parsing
Own syntax validation and source-located DOM projection together. Preserve explicit consumer policies and remove duplicated warning-message filters from Apktool and SAZ.

Validation: 92 focused checks, 3 selected fake Apktool boundary checks, check:fast and docs:check. No real Apktool or Ghidra execution.

Refs #4694
2026-10-17 15:16:24 +08:00
Kshitiz Jain c0b3cd14b1 fix(javascript): exclude class member keys from lexical reads
Classify noncomputed class member keys and private names at the shared reference owner, avoiding false reads and closure captures. Preserve computed keys and initializer/body reads.

Validation: regression controls, fresh public CLI/MCP workflows and complete exact-head CI passed.

Fixes #3310.
2026-10-17 07:11:19 +00:00
siegfly 195cf18818 docs(native): distinguish analysis memory from source bytes
Document initialized Ghidra analysis-memory bytes, source mappings and incomplete coverage. Retain the portable test-owned alternate ELF for liveness cancellation.

Validation: fresh docs:check and complete exact-head CI passed. Historical real Ghidra checks remain explicitly attributed to their recorded revision/platform in the PR.

Refs #3075.
2026-10-17 07:11:10 +00:00
keeponlight e26bb49a4b fix(managed): avoid duplicate decode budget charging on cached metadata strings
Charge each immutable metadata heap string decode once; keep unique-string and per-occurrence projection accounting bounded.

Validation: focused capacity regressions, fresh real .NET DLL CLI/MCP workflows and complete exact-head CI passed. Before/after measurements and their limits are recorded in the PR.

Fixes #3449.
2026-10-17 07:10:58 +00:00
Sua Choi 326c073880 fix(apktool): preserve valid replacement characters in decoded XML (#4697) 2026-10-17 15:09:14 +08:00
Ysopwnable c6b62754b0 perf(kuna): reuse sorted string inventory for exact lookups
Reuse the validated string inventory's numeric address order for O(log n + matches) exact reads, preserving every encoding at the selected address without a second lookup index. Keep streaming validation, session cache lifetime, full listings, provenance and caller choices.

Validation: complete latest-head CI passed. Original real Kuna 1.833 Linux correctness and warm-lookup measurements remain pinned to their recorded feature revisions in the PR. The latest local 300 ms export-deadline observation and unchanged 31-test provider recheck are explicitly documented there; no assertion or timeout was weakened.

Refs #4695.
2026-10-17 07:04:16 +00:00
morluto 264799b0ff fix(kuna): retain workspace rollback failures
Compose failed rollback with the original target or read failure, bind it to the exact workspace lease, and retain the failed attempt while cleanup remains unresolved. Remove the silent release wrapper and duplicate exception wrapping; keep clean failures retryable and unknown causes opaque.

Refs: #4704
2026-10-17 14:56:01 +08:00
Ysopwnable 5b24399387 test(kuna): preserve caller and producer graph failure context
Align malformed call-graph retry assertions with caller-attributed errors while retaining the parser operation in diagnostics and the cause. Keep all malformed shapes, corrected-response retry, exact native-command count and owned-client cleanup coverage.

Validation: clean main reproduces 3 failed / 14 passed; corrected complete Kuna boundary selection passes 266 tests across 26 files; full check:ci and complete current-head CI passed. Greptile 5/5; human owner reviewed the diff/evidence and explicitly declared readiness. Codex review remains unavailable due repository usage limits. Test-only; no production/schema/authority change or real-engine qualification.

Fixes #4701.
2026-10-17 06:47:06 +00:00
morluto 5927937179 fix(kuna): preserve cancellation and cleanup ownership
Reuse shared startup ownership for query waits and preserve opaque cancellation reasons, captured command facts and typed primary failures. Bind retained command errors to exact process and workspace leases; share close attempts and update earlier caller and aggregate errors after cleanup retry.

Refs: #4700, #4702
2026-10-17 14:38:50 +08:00
morluto 988494abdb fix(kuna): own cancellable installation startup
Reuse the shared startup owner for independent caller waits, final departure cleanup, and session closure. Carry the producer signal through version probing and fingerprint finalization. Retry cleanly cancelled acquisition after settlement while retaining authored failures and exact descriptor cleanup dependencies.

Refs: #4698
2026-10-17 14:23:17 +08:00
Ysopwnable 3c9b5d6d02 test(ci): align fixtures with runtime and evidence contracts
Restore test fixture runtime prerequisites and align assertions with current Evidence and uncertainty contracts. Separate actual CLI publisher refusal from explicitly admitted Hopper socket/CLI fixtures, retaining exact wire identity and cleanup coverage. Validate retained EVM Evidence against exact unchanged source-carrier bytes.

Validation: 88 targeted local test passes across three completed selections, two platform skips, full check:ci; hosted Windows probes and complete current-head CI. No production authority, authentication or schema change. Controlled fixtures do not qualify actual disassemblers or workers.

Fixes #4690.
2026-10-17 06:20:23 +00:00
morluto 54c71313ae fix(kuna): attribute inventory failures to callers
Normalize shared installation and inventory failures at the session boundary, retaining producer operation metadata. Preserve exact cancellation reasons before admission and while waiting without adopting foreign cleanup authority.

Refs: #4689
2026-10-17 14:13:25 +08:00
morluto 6eb55be4e8 fix(kuna): preserve live cleanup in caller failures
Reuse canonical typed failure attribution instead of copying cleanup markers. Preserve captured facts, typed primary outcomes and opaque cancellation reasons; bind caller projections to the exact producer cleanup owner.

Refs: #4693
2026-10-17 14:13:16 +08:00
morluto 5717ad24aa fix(kuna): attribute installation failures to caller operations
Project the immutable shared installation failure through the existing authored-failure normalizer for each requesting operation. Preserve direct health identity, diagnostics, retryability and live cleanup dependencies.

Validation: ten baseline/candidate public CLI cases each; nineteen focused boundary checks plus four overlapping final cleanup controls, check:fast and docs:check passed. Concurrent callers share one acquisition failure without mutating its producer. No real Kuna, Windows, MCP-specific failure replay or performance measurement. Refs #4631.
2026-10-17 13:49:27 +08:00
morluto d09be9cfa2 docs(browser): clarify scenario cleanup after termination
Document retained profile data, missing-executable Playwright artifacts, platform cancellation differences and the absence of later reclamation. Keep recovery work tracked in #4659.

Confirmed installed Playwright 1.58.2 preparation order and one public CLI missing-executable reproduction in a private fixture; an empty artifacts directory remained and was removed only with the owned experiment root. Forced termination was not rerun. docs:check passed.
2026-10-17 13:49:20 +08:00
morluto 7086768a27 fix(adb): preserve display-scoped window focus declarations
Retain every focus declaration with its display header and identity, including explicit absence, unknown identities and duplicates. Derive singular summaries only for one unambiguous context; preserve scope and ambiguity through named CLI/MCP contracts.

Validation: original public CLI replay before/after, four failing baseline parser controls, 23 focused checks plus 11 overlapping provider/parser controls, converted MCP schemas, check:fast and docs:check. Bounded completed synthetic CLI warm reply tokens 282/513, elapsed 0.391/0.403s and CPU 0.622/0.622s; no efficiency claim. No live Android, vendor or large-output qualification. Refs #4660.
2026-10-17 13:40:09 +08:00
morluto be0b2d138c fix(adb): scope package uninstall requests to user zero
Send shell pm uninstall --user 0 through the shared quoted command boundary. Align tool guidance and Evidence limitations with the selected request scope while preserving device refusal diagnostics.

Validation: two provider controls failed before the fix and pass afterward; three public CLI/MCP scenarios capture exact arguments and equivalent success facts; nineteen command/SDK contract checks, check:fast and docs:check pass. No real device, multi-user data preservation, vendor/APEX behavior or performance measurement. Refs #4673.
2026-10-17 13:30:29 +08:00
morluto c360cfcd6d fix(browser): parse complete COOP and COEP structured items
Validate token items and their parameters before projecting exact declared policy tokens. Keep malformed and non-token values unknown; retain separate grammar for other policy headers.

Validation: real pinned Chrome public CLI baseline/candidate, 101 focused checks and 90 overlapping final checks, 834 upstream item-vector adaptations with two permitted refusals, check:fast and docs:check. Other browser/platform and policy-specific MCP delivery unverified; no performance measurement. Refs #4677.
2026-10-17 13:26:13 +08:00
morluto df2fc251e3 fix(browser): preserve repeated document Link fields
Parse CDP repeated field lines independently before applying URI and quoted-parameter delimiters. Preserve declaration order and derive agent hints from retained links.

Validation: real pinned Chrome public CLI baseline and candidate each captured three responses per fixture; repeated Document links/hints restored and comma/single/Fetch controls unchanged. Three source controls failed before the fix. Sixty-one focused checks plus fifteen overlapping final network checks, check:fast and docs:check passed. No performance measurement or other browser/platform claim. Refs #4679.
2026-10-17 13:21:50 +08:00
morluto 0ec4826633 fix(evm): preserve command owner cancellation reasons
Copy the exact opaque reason already recorded by OwnedCommand rather than discarding it at EVM failure conversion. Keep physical, timeout and incomplete cleanup outcomes distinct.

Validation: direct compiled probe and eight source controls; four reason controls failed before the fix. Twenty-one overlapping service/adapter checks, check:fast and docs:check passed. No real Linux x64 worker cancellation or public delivery exercised. Refs #4686.
2026-10-17 13:18:05 +08:00
morluto d694aef227 fix(evm): retain completed evidence through cleanup cancellation
Share validated interface Evidence assembly across success, cleanup failure and late cancellation. Preserve exact admission and completion abort reasons.

Validation: 26 service, MCP and host-refusal checks passed; check:fast passed. Thirty Linux x64 provider checks skipped on Darwin arm64, including expanded root-removal controls. Linux real-worker and public SIGINT reproduction remain unverified; no performance measurement. Refs #4683.
2026-10-17 13:16:40 +08:00
morluto 5853089885 fix(hopper): retain search failure context and cleanup ownership
Attribute regex inventory failures to the accepted search operation while retaining wire identity, typed outcomes, captured facts and live cleanup dependencies. Preserve exact cancellation reasons at inventory and progress completion.

Validated with focused source, socket-boundary and public CLI fixtures, existing MCP contract checks, check:fast and docs:check. Simulated Hopper only; real-engine behavior and performance costs remain unmeasured. Refs #4680.
2026-10-17 13:12:43 +08:00
morluto 4d980d0176 fix(javascript): preserve unresolved version relationships
Keep positive topology differences separate from unpaired neighbor identity. Preserve exact content pairing and source observations, report unresolved relationships without inventing incomplete inventory, and omit comparison edges when no substantive difference was observed.

Validated with 45 focused domain/CLI/MCP tests, nine expanded domain controls, check:fast, and docs:check. Clean baseline fails seven controls and passes two positive controls. Controlled static fixtures only; no target execution or large-bundle profiling.

Refs #4681
2026-10-17 12:51:04 +08:00
morluto 556504edcb fix(javascript): distinguish relocation from application changes
Keep location-only matched pairs unchanged under complete coverage while retaining both coordinates and location dimensions. Preserve incomplete coverage as unknown and retain definite content, property, and relationship changes.

Validated with focused domain, compiled CLI and MCP workflows, static checks and docs checks. A tiny public CLI bundle fixture reproduces the issue; the reported Bitwarden releases were not rerun.

Refs #4520
2026-10-17 12:36:21 +08:00
morluto 1e36e707b1 fix(ghidra): preserve launch outcomes through cancellation and rollback
Carry producer cancellation separately from physical launch errors and diagnostic causes. Retain exact opaque reasons, LaunchSupport warnings, and rollback owners; consume the authored outcome without reclassifying failed launches from a later deadline.

Validation: focused client/provider/rollback and helper/MCP tests, check:fast, docs:check. Controlled native process ownership and Node bridge only; real Ghidra/JVM and Windows/Linux fault behavior unverified.

Refs #4517
2026-10-17 12:27:08 +08:00
morluto e31aa72c9d fix(ghidra): retain executable header read and cleanup ownership
Read bounded stable prefixes through the installation file owner, preserve unknown header diagnostics, and propagate cancellation or incomplete cleanup. Share extent and identity validation with full artifact reads.

Validated with 269 focused tests, check:fast, and docs:check. Controlled Darwin file faults reproduce the original lost owner; real Ghidra and native Windows/Linux verification remain unperformed.

Refs #4676
2026-10-17 12:17:44 +08:00
1251 changed files with 187533 additions and 53557 deletions

No files matched your search

@@ -0,0 +1,113 @@
---
name: rea-analysis-optimization
description: Optimize REA providers and shared analysis workflows for agent context, latency, CPU, and memory while preserving correctness and Evidence. Use for analysis bottlenecks and cache or query design; CI/test-suite optimization belongs to rea-ci-tests-audit.
---
# REA analysis optimization
Find a concrete source of unnecessary work, change it at its owner, and verify
equivalent completed investigations. A useful outcome can also be a measured
decision to leave an implementation alone.
Follow the checkout's [performance priorities](../../../AGENTS.md#performance),
[tool design](../../../docs/tool-design.md), and
[testing guide](../../../docs/testing.md). This skill supplies an optimization
workflow, not additional permission to execute targets, publish, or merge.
Use the current contracts, provider prerequisites, and user authorization.
Read [the Kuna case study](references/kuna-case-study.md) when selecting a
reuse strategy or interpreting a benchmark. Its pinned observations illustrate
tradeoffs; they are not current-provider guarantees or universal speedups.
## Pin the question and the correctness oracle
Describe the analyst's completed task, including the facts and relationships
needed to answer it, requested detail, source access, and meaningful unknowns.
Choose a representative real artifact and a small or empty case. Record the
baseline revision, target digest, engine identity, options, host, and entrypoint.
Use a separate checkout for changes without disturbing other work.
Establish an oracle independent of the changed implementation: source-built
fixture expectations, independently mapped file bytes, or a native producer
paired with checks of its interpretation. Comparing two wrappers around the
same faulty decoder does not establish correctness. Preserve address widths,
same-address alternatives, unresolved endpoints, coverage, and source linkage.
An empty result proves absence only within the actually examined scope.
## Locate the earliest unnecessary work
Trace one public CLI or MCP task through shared application code to its producer.
Measure relevant phases: admission and identity checks, native analysis,
decoding, lookup, projection, serialization, Evidence retention, and cleanup.
Include catalog discovery and extra calls when they affect the completed task.
Use the evidence to choose the smallest structural correction:
| Observed cost | Candidate correction | Condition to establish |
| --------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| Repeated scans of validated facts | Reuse existing order or lookup structure | The owner establishes ordering and identity; every matching alternative survives |
| Repeated equivalent engine work | Share a validated result or in-flight producer | Inputs, freshness, lifetime, and per-caller outcomes remain explicit |
| Full reports for selected facts | Push selection or projection to the earliest capable owner | Required facts and evidence remain reachable; examined coverage is reported |
| Large temporary transport buffers | Decode incrementally or use bounded source reads | Validate the whole admitted document; retained facts and copies still consume memory |
| Many repeated homogeneous reads | Share admission, decoding, or batch work | Preserve item identity, order where required, and individual failures |
Do not introduce an index, generic cache, batch endpoint, or orchestration layer
without identifying the work it removes and its maintenance/resource cost.
Projection after materializing a full report may reduce output while leaving
analysis time and peak memory unchanged. Fix missing or incorrect facts before
benchmarking an alternative composition against a better-covered workflow.
## Keep one interpretation and a defined reuse lifetime
Let the producer boundary validate and normalize facts once. Consumers query
that representation through the shared CLI/MCP implementation; adapters should
not rebuild relationships or independently reinterpret raw reports. Keep lookup
identity separate from display formatting. Reuse contracts when their intent
matches, honoring requested detail and complete Evidence access.
For every cache or shared producer, state its key, owner, invalidation, retained
size, and lifetime. Account for result-affecting target bytes, engine contents,
analysis options, architecture/load mapping, and parser/schema versions where
they affect reuse. Validate live state before calling a cached observation
current. Cache a refusal only when it is deterministic for that validated key;
malformed, partial, transient, or cancelled attempts need explicit retry policy.
One cancelled waiter must not invalidate a successful peer. Preserve producer
failure context and each caller's cancellation reason. Retain ownership and
capacity charges until shared work and cleanup settle; preserve completed
observations when cleanup fails. Exercise invalidation, concurrent consumers,
last-waiter cancellation, close, and cleanup retry when those paths change.
Bound the process family and retained state, not just a parent heap or worker
count. Account for decoding and serialization expansion before allocation.
Choose CPU, memory, concurrency, and disk limits from the host and workload;
stop before OOM and verify owned cleanup. A guard-stopped task is incomplete.
Do not replace a transport buffer cap with an unbounded retained inventory or
hide partial results behind a success status.
## Compare completed tasks and limit the claim
Run the affected real public workflow before and after with equivalent inputs,
results, coverage, and Evidence semantics. Include small inputs so setup costs
and regressions are visible. Distinguish fresh sessions, warm runtime caches,
and OS file caches. Alternate or repeat runs when variance affects the decision.
Choose meaningful boundary regressions for cases the actual engine cannot
reliably reproduce; a fake engine does not qualify a real provider.
Report task outcome, relevant phase timings, total elapsed and CPU time, peak
process-family memory and its accounting method, resource stops, and cleanup.
Check the payload exit status as well as the profiler's. Keep failed attempts
and identify unmeasured costs; a passing retry does not explain a failure.
For token claims, count schemas/discovery, arguments, replies, retries, and
continuations needed to finish the task. Label tokenizer estimates separately
from actual model usage and record the client/catalog behavior. Smaller JSON
alone establishes neither fewer model tokens nor better investigation quality.
Do not claim a complex-software advantage without completed representative
investigations and comparable correctness/coverage.
Finish with the bottleneck, owning change, preserved semantics, executed
checks, before/after measurements, and remaining limits. Keep any integration
record current with its tested revision and distinguish merged production work
from experiment-only code. Stop when the demonstrated bottleneck is resolved
or further benefit remains speculative.
@@ -0,0 +1,4 @@
interface:
display_name: "REA analysis optimization"
short_description: "Optimize analysis with preserved Evidence and measured costs"
default_prompt: "Use $rea-analysis-optimization to find and verify a concrete analysis bottleneck while preserving correctness and Evidence."
@@ -0,0 +1,112 @@
# Kuna: reuse before adding machinery
Read this reference for concrete examples of the skill's decisions. The records
below concern static Linux analysis with caller-supplied Kuna. They do not
establish parity with another provider or a general advantage for Code Mode,
atomic tools, or any particular orchestration design.
## Exact-address lookup: a measured, narrow improvement
[PR #4695](https://github.com/morluto/rea/pull/4695) reused the validated string
inventory's numeric address order. Previously, each `list_strings(address)`
filtered all cached facts. The owner now performs a binary lower-bound lookup
and returns every encoding at that address: O(log n + matches), without a
second retained lookup index.
The owning implementation is
[`KunaStringInventory.ts`](../../../../src/kuna/KunaStringInventory.ts), consumed
by [`KunaStringQueries.ts`](../../../../src/kuna/KunaStringQueries.ts). Inspect
their current versions before adapting the example. Numeric u64 addresses,
same-address encodings, duplicate rejection, source digests, caller selection,
and the existing session lifetime were part of the contract. Full listings and
literal/regex searches kept their semantics. An attempted removal of the
duplicate-detection set was dropped: no stable memory benefit was established,
and it delayed malformed-input rejection.
### Recorded workload and results
The benchmark used unmodified Kuna 1.833 and LLVM 16 on Linux x86-64, with
602,544 string facts. Baseline was `be0b2d138`; the final feature was
`5f564962da0e1b17f00a68a74a312539f0209a01`, subsequently integrated in
`c6b62754b095a134d6d67877508fa34311a2eda2`. These are historical observations,
not a benchmark of every subsequent main revision.
The same production stdio MCP task discovered the catalog, opened the binary,
made one cold selected read and 28 warm exact reads, checked retained Evidence,
and closed the session. Five selected addresses and two absent selectors were
read four times. A native filtered scan selected the strings; an independent
ELF load-header mapping checked the source bytes and terminators. Returned
facts, source linkage, target digests, and cleanup were checked.
Three alternating fresh sessions per implementation used one CPU, a 4 GiB
process-family hard limit, a 3 GiB early stop, and no swap. OS file caches were
warm. Whole-harness costs include the independent native oracle, hashing,
catalog/client work, and correctness checks.
| Median | Before | After |
| ---------------------------------------- | ---------: | ---------: |
| 28 warm exact MCP reads | 495.2 ms | 90.8 ms |
| Cold selected MCP read | 11.30 s | 11.01 s |
| Whole harness elapsed | 28.24 s | 27.43 s |
| Whole process-family CPU | 27.71 s | 26.89 s |
| Kernel family peak, including file cache | 2237.6 MiB | 2240.6 MiB |
Warm totals ranged from 491.7–544.3 ms before to 84.8–99.5 ms after: about
5.5 times faster at this phase. Cold/whole-task timing and memory overlapped;
no stable improvement in those costs was established. One small SQLite pair
(7,985 facts) measured 20 warm reads at 88.6 → 80.5 ms and the whole harness at
13.68 → 13.94 s. The large-inventory lookup benefit does not generalize to a
whole-task speedup on small inputs.
Catalog hashes, call counts, and normalized facts were unchanged. A
`cl100k_base` estimate over one pass of raw catalog JSON, arguments, and replies
was about 846,000 tokens in both lanes, with about 802,562 from the catalog.
This was transport serialization, not rendered model context or actual usage;
client discovery, prompts, replay, and protocol framing were unmeasured.
**No token reduction or improved agent investigation outcome was established.**
Pinned target SHA-256:
`f62d254b7f2bf42df8c8b07d46ee3bb4c2cafeca436b2e6bc6ccbe4581f58f40`.
Pinned engine SHA-256:
`d858918b0766435cd96b999a77f2d5a31a0cc4f07256421c883b5b9dc4dd58e4`.
All six normalized-result sequence digests were
`4d2f90269da8568984090b20274163c4a7c2a0538aab63530bd2fe44840a0bba`.
Selected byte agreement does not prove native discovery completeness; missing
strings and relationships can remain unknown.
## Other transferable changes and their limits
- [Cached string inventory and search, #4095](https://github.com/morluto/rea/pull/4095):
share validated facts across queries in a defined session. Audit key inputs
and lifetime before extending reuse across targets or engine revisions.
- [Shared single-function work, #4045](https://github.com/morluto/rea/pull/4045)
and [repeat-request reuse, #4169](https://github.com/morluto/rea/pull/4169):
avoid duplicate native work while retaining per-caller cancellation and
cleanup ownership. A query count alone cannot reveal duplicate subprocesses.
- [Streamed strings, #4318](https://github.com/morluto/rea/pull/4318)
and [streamed call graph, #4329](https://github.com/morluto/rea/pull/4329):
remove fixed aggregate transport-buffer failures through incremental parsing.
Streaming transport does not bound every retained object or final reply.
These links establish changes; no numerical speedup is asserted here.
Typed reference facts, native string-query projection, and shared native byte
reads remained experimental at the 2026-10-17 checkpoint
`65f2f9a22bc892f61d2b00f9a4611124f57d4bff` on
`experiment/atomic-codemode-20261016`. Some experiments used a patched native
engine. Check current integration and bring-your-own engine capabilities before
proposing them; a working experiment is not a stock-provider guarantee.
## Applying the reasoning elsewhere
For another provider or format, inspect its actual representation and native
capabilities before borrowing the implementation. Existing numeric ordering
may support range reads; an on-disk native query may avoid materializing an
inventory; an immutable parse may support several views. Measure the relevant
alternative rather than requiring every provider to use Kuna's cached array.
For live observations, immutable artifact caching rules are insufficient:
validate the process/session identity and freshness required by the caller.
For compact replies, preserve access to source Evidence and report examined
coverage; projection must not silently turn an unresolved edge into no edge.
For batching, test mixed successes and failures and measure the entire task,
including discovery, extra calls, native work, and serialization.
@@ -69,3 +69,11 @@ When the connected schema advertises `include_query_parameter_names`, select
it in the view for distinct observed names with original record ordinals. Query
values are omitted; the names establish neither required parameters nor a
complete server schema. Keep the original parent Evidence for exact URLs.
Use `inspect_analysis_view` with `view: {kind: "environment-manifest"}` on the
same retained HAR Evidence to project the primary origin's request lines into
named tools with path templates, parameters, observed query names, value-free
body shapes and record pointers for an agent environment. Opt into
`template_rules` only when recorded identifiers need them; every template,
parameter and merged sibling is an inference, no header, cookie or body value is
copied, and the three stated unknowns stay unresolved.
@@ -124,6 +124,26 @@ operation's full ordered list. Candidate capabilities describe possible
providers. Top-level session capabilities describe the current route, and
`analysis_provider_binding` identifies the selected provider.
## Static memory and original file bytes
For Ghidra, `read_bytes` reads initialized analysis memory, including loader
fixups; it does not read a running process. Check `returned_bytes` and `complete`
before decoding a table. An incomplete read is missing coverage, not a zero-filled
tail. Use `list_segments` to inspect the selected block's initialization and address-space
facts, and retain unavailable facts as unknown.
Use `address_to_file_offset` to anchor one observed address to original file
bytes. A mapping for the first address does not establish a contiguous mapping
for an entire table, and loader fixups can make analysis bytes differ from source
bytes. Keep source ranges and analysis-memory observations separate.
A pointer table can refer to writable slots populated by a constructor rather
than directly to immutable resources. An uninitialized block or an observed zero
does not establish the slot's later runtime value. Follow `xrefs` and the relevant
writer's assembly or pseudocode; distinguish recorded assignments from inferred
execution order. Do not replace unreadable bytes with zeros or conclude that a
resource is absent without the necessary initialization evidence.
## DOS MZ with Ghidra
For an admitted DOS MZ target, use `inspect_native_load_image` to check measured
@@ -133,10 +153,8 @@ reported static image, not runtime DOS or PC-98 hardware behavior.
For Ghidra decompilation, `procedure_pseudo_code` also accepts `procedure: "file-offset:0x..."`; CLI `rea decompile <path> --file-offset=0x... --provider ghidra` resolves the source byte offset internally. An unresolved 0x-prefixed numeric procedure selector also falls back to a unique file mapping. Existing symbols and analysis addresses win; multiple mappings fail as ambiguous. Preserve the returned file-offset and address locations and raw selection observations. ELF virtual addresses are distinct from file offsets; never assume an arbitrary offset plus image base is an analysis address.
Use `read_bytes` for initialized analysis memory and `address_to_file_offset` to
anchor one observed address to original file bytes. Loader fixups can change a
word; a source offset does not imply byte equality. Complete function body ranges
use inclusive ends and can contain gaps. Do not treat the enclosing span as code.
Complete function body ranges 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.
@@ -24,19 +24,7 @@ runs:
BUILD_CACHE_PREFIX: rea-portable-build-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.npmrc', '.nvmrc', 'package-lock.json') }}
run: |
npm run --silent test:prepare -- --dry=json |
node --input-type=module -e '
import { createHash } from "node:crypto";
import { readFileSync } from "node:fs";
const { tasks } = JSON.parse(readFileSync(0, "utf8"));
const hashes = tasks.map(({ taskId, hash }) => {
if (typeof hash !== "string")
throw new Error(`Build task ${taskId} must have an eager Turbo hash`);
return `${taskId}:${hash}`;
}).sort();
const hash = createHash("sha256").update(hashes.join("\n")).digest("hex");
console.log(`key=${process.env.BUILD_CACHE_PREFIX}-${hash}`);
console.log(`prefix=${process.env.BUILD_CACHE_PREFIX}-`);
' >> "$GITHUB_OUTPUT"
node scripts/ci/portable-build-cache.mjs key >> "$GITHUB_OUTPUT"
- name: Restore portable build outputs
if: inputs.build_cache_artifact == '' && inputs.save != 'true'
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
+8 -1
View File
@@ -357,10 +357,15 @@ jobs:
# test:prepare caches only portable JS, skill, and catalog outputs.
# Native package jobs still run their build and prepack checks; Turbo
# restores matching outputs or rebuilds when their inputs differ.
- name: Stage current portable build task cache
shell: bash
run: |
# A new Turbo dry run can evict the entries this build just used.
node scripts/ci/portable-build-cache.mjs snapshot < .cache/ci-build-plan.json
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: rea-build-cache
path: .turbo/cache/
path: .cache/ci-build-cache/
include-hidden-files: true
if-no-files-found: error
retention-days: 7
@@ -648,6 +653,7 @@ jobs:
tests/boundary/cli/nativePlistPrototypeKeyCli.test.ts
tests/boundary/cli/nativePlistSelectionFailureCli.test.ts
tests/boundary/cli/nativeDemangleCli.test.ts
tests/boundary/cli/nativeDispatchPropertyAttributes.test.ts
tests/boundary/mcp/nativeDemangleMcp.test.ts
tests/boundary/providers/native/nativeSignatureTargetBinding.test.ts
tests/boundary/cli/nativeSignatureCli.test.ts
@@ -748,6 +754,7 @@ jobs:
tests/boundary/filesystem/webScriptManifestPaths.test.ts
tests/boundary/process/ProcessEvidence.host.test.ts
tests/boundary/process/packageNpmInvocation.test.ts
tests/boundary/process/packedBridgeVerification.test.ts
tests/boundary/process/windowsOutputCapture.test.ts
tests/acceptance/webModuleCli.test.ts
tests/acceptance/webSourceLocationCli.test.ts
+12 -5
View File
@@ -24,7 +24,19 @@ jobs:
real-recorded-crash:
runs-on: ubuntu-24.04
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
image: ["ubuntu:24.04", "debian:trixie-slim"]
container: ${{ matrix.image }}
steps:
- name: Install fixture and debugger prerequisites in the disposable container
shell: bash
run: |
apt-get update -qq
apt-get install --yes --no-install-recommends \
ca-certificates git python3-venv gcc libc6-dev strace gdb
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
@@ -36,11 +48,6 @@ jobs:
- uses: ./.github/actions/portable-build-cache
with:
build_cache_artifact: ${{ inputs.build_cache_artifact }}
- name: Install GDB on the disposable CI runner
shell: bash
run: |
sudo apt-get update -qq
sudo apt-get install --yes --no-install-recommends gdb
- name: Acquire exact unchanged upstreams in isolated runner storage
shell: bash
run: |
+1 -1
View File
@@ -1,3 +1,3 @@
{
".": "6.5.0"
".": "6.7.0"
}
+88
View File
@@ -1,5 +1,93 @@
# Changelog
## [6.7.0](https://github.com/morluto/rea/compare/rea-agents-6.6.0...rea-agents-6.7.0) (2026-10-18)
### Highlights
- Client configuration edits follow the duplicate-member semantics used by MCP clients.
### Changes
- Includes the [6.6.0 changes and migration notes](https://github.com/morluto/rea/releases/tag/rea-agents-6.6.0). That version was tagged but was not published to npm.
### Fixes
- **Client configuration:** Setup edits the last repeated JSON/JSONC member, matching the value clients actually read. Setup and uninstall refuse a removal that would reactivate a shadowed duplicate, preserving the original configuration. ([#4957](https://github.com/morluto/rea/pull/4957), [morluto/rea#4952](https://github.com/morluto/rea/issues/4952)). Thanks @kaoru0822-kitauji, @xu91102.
Full contribution record: [4 commits and 1 merged PR](https://github.com/morluto/rea/blob/rea-agents-6.7.0/docs/releases/6.7.0.contributions.json).
## [6.6.0](https://github.com/morluto/rea/compare/rea-agents-6.5.0...rea-agents-6.6.0) (2026-10-18)
### Highlights
- Add Kuna as a caller-supplied static-analysis provider.
- Query selected JavaScript facts and multiple APK locale tables without repeating the underlying analysis.
- Extend Ghidra analysis to Windows ARM PE targets and explicit raw m68k images.
- Preserve completed Evidence, cancellation reasons and retryable cleanup across provider and CLI finalization.
### Changes
- **Kuna analysis:** Use a caller-installed Kuna for procedure listings, pseudocode, assembly, call relationships, exact-address xrefs and cached string searches. Project exports retain source spans and digests; repeated requests reuse completed work. Recorded real-provider coverage uses Kuna 1.833 on Linux; Windows, PE and universal Mach-O are unsupported. See [the provider guide](docs/kuna-provider.md). ([#3832](https://github.com/morluto/rea/pull/3832), [#3854](https://github.com/morluto/rea/pull/3854), [#4071](https://github.com/morluto/rea/pull/4071), [#4095](https://github.com/morluto/rea/pull/4095)). Thanks @gensokyo-dev, @kaoru0822-kitauji, @N0zoM1z0.
- **Retained JavaScript facts:** Query exact application paths, selected properties and filtered module references through `inspect_analysis_view`, with paging and complete row Evidence. These views reuse completed analysis and preserve source selection and unknown coverage. ([#4265](https://github.com/morluto/rea/pull/4265), [morluto/rea#4190](https://github.com/morluto/rea/issues/4190), [#4097](https://github.com/morluto/rea/pull/4097), [morluto/rea#4092](https://github.com/morluto/rea/issues/4092)). Thanks @kaoru0822-kitauji, @N0zoM1z0.
- **APK locale tables:** Request several resource locales in one decode with repeatable CLI `--locales` or MCP `locales`. Each table reports its status and coverage; existing single-locale fields remain available. ([#4804](https://github.com/morluto/rea/pull/4804), [morluto/rea#4777](https://github.com/morluto/rea/issues/4777)). Thanks @abhay-2108, @N0zoM1z0.
- **Windows ARM binaries:** Ghidra admits ARMNT/Thumb-2 and ARM64 PE applications and DLLs on the Windows x64 host lane. Recorded Ghidra 12.1.4 verification uses `WindowsResourceReference` disabled and raised startup budgets; default-analyzer completion, ARM64EC/ARM64X and Windows-on-Arm hosts remain unverified or unsupported. See [the exact scope](docs/windows-ghidra-p0.md#native-authority-and-target-identity). ([#3965](https://github.com/morluto/rea/pull/3965), [morluto/rea#2186](https://github.com/morluto/rea/issues/2186)). Thanks @N0zoM1z0, @WestLabsAI.
- **Raw m68k images:** Analyze explicitly selected big-endian m68k raw binaries using Ghidra’s fixed 68000 profile and a caller-supplied aligned entry. Real CLI/MCP verification used Ghidra 12.1.4 on macOS arm64; Linux is unverified and Windows P0 does not admit m68k. See [mapping requirements](docs/raw-binary.md). ([#4018](https://github.com/morluto/rea/pull/4018)). Thanks @icedac.
- **JADX deadlines:** Set `REA_JADX_OPERATION_TIMEOUT_MS` to extend APK loading and upstream operation deadlines together. Doctor reports the effective value and setup forwards an explicit selection. ([#4466](https://github.com/morluto/rea/pull/4466), [morluto/rea#3918](https://github.com/morluto/rea/issues/3918)). Thanks @jaychou813, @SandstromPL.
- **Electron window options:** Resolve stable local constant `BrowserWindow` options while retaining source provenance. Relevant writes and escapes keep the result unknown. ([#4400](https://github.com/morluto/rea/pull/4400), [morluto/rea#4366](https://github.com/morluto/rea/issues/4366)). Thanks @kaoru0822-kitauji, @N0zoM1z0.
- **Language editions:** Add the Greek website edition and Malayalam documentation, with Korean typography and translation corrections across the site. ([#3520](https://github.com/morluto/rea/pull/3520), [#4792](https://github.com/morluto/rea/pull/4792), [#3821](https://github.com/morluto/rea/pull/3821), [morluto/rea#3820](https://github.com/morluto/rea/issues/3820), [#3799](https://github.com/morluto/rea/pull/3799), [morluto/rea#3798](https://github.com/morluto/rea/issues/3798), [#4344](https://github.com/morluto/rea/pull/4344), [#3856](https://github.com/morluto/rea/pull/3856), [#4166](https://github.com/morluto/rea/pull/4166)). Thanks @gensokyo-dev, @hi2242, @kalayciburak, @kaoru0822-kitauji, @kraken-503, @kukinghan, @N0zoM1z0, @yeseong0412.
### Fixes
- **Cancellation and cleanup:** Keep completed observations, exact cancellation reasons and the original physical failure through finalization. Failed cleanup retains its process or file owner for retry; recovered resources disappear from pending-cleanup reports without replacing the original error. ([#4238](https://github.com/morluto/rea/pull/4238), [morluto/rea#4232](https://github.com/morluto/rea/issues/4232), [#4274](https://github.com/morluto/rea/pull/4274), [morluto/rea#3923](https://github.com/morluto/rea/issues/3923), [3e82366](https://github.com/morluto/rea/commit/3e8236639abffa39deb5d5e939ec8baf6aaf3ca3), [16924e2](https://github.com/morluto/rea/commit/16924e275e939d0543ba01493324959a9e1d731c), [bbfe6ed](https://github.com/morluto/rea/commit/bbfe6edd60290f9bfbec68c8a0bcf605d8bbf5b3), [1f23e97](https://github.com/morluto/rea/commit/1f23e977b50301e91f02a4a17c9f8d48bb7b60f3), [08fbeb8](https://github.com/morluto/rea/commit/08fbeb8bdab27118b6c57039aef7c0fa8b6463bc)). Thanks @coygeek.
- **Provider startup:** Join prerequisite probes and in-flight readiness work before shutdown, preserve typed timeout and JVM-memory failures, and retain startup diagnostics through cleanup. Ghidra recognizes keg-only Homebrew JDKs and names the setting responsible for a startup timeout. ([376eeca](https://github.com/morluto/rea/commit/376eeca770820b31f7f8d4c5fcc397315621643e), [ceeff5a](https://github.com/morluto/rea/commit/ceeff5a41788e47e5aee96a4baf191a6ce7fde4b), [3ad1032](https://github.com/morluto/rea/commit/3ad1032b11edea2dcb054e78f951cc43159ae83d), [964decd](https://github.com/morluto/rea/commit/964decd989acfa84c4bfc3295362c4c46877fc20), [3fa972a](https://github.com/morluto/rea/commit/3fa972af7c7cb6cf014ffc426bdf7130dc6f2fd2), [#4557](https://github.com/morluto/rea/pull/4557), [morluto/rea#4556](https://github.com/morluto/rea/issues/4556), [#4590](https://github.com/morluto/rea/pull/4590), [morluto/rea#4241](https://github.com/morluto/rea/issues/4241)). Thanks @DanielCvz1, @J0UH, @Rinkia, @RishTheFish21, @vadlachary2002.
- **Client configuration:** Preserve the selected launcher, destination file, caller timeout choices and unresolved configuration evidence. Setup/uninstall recovery stays bound to the exact published file, keeps current verified backups, and transfers failed cleanup ownership for retry. ([d0253c9](https://github.com/morluto/rea/commit/d0253c99d65afbbd12732a2fdaf711640574e17f), [7e4eed9](https://github.com/morluto/rea/commit/7e4eed9dd48485b6a7100300aa98401811c2deb9), [2fb5e20](https://github.com/morluto/rea/commit/2fb5e204a35723f6f843d56ca47b0db94d8fcc44), [8235210](https://github.com/morluto/rea/commit/823521085a28f825e7fee1929d852d420042d1f7), [d818c3d](https://github.com/morluto/rea/commit/d818c3d2639d3115edb8a5269a754101aea6c3bd), [19329e4](https://github.com/morluto/rea/commit/19329e43bb38ca9d64512d801b25abcb188d2512), [dadf909](https://github.com/morluto/rea/commit/dadf909dce2e8b3d055541de69b4118d21276316), [333e0ab](https://github.com/morluto/rea/commit/333e0ab0dfc126a9915907d5079ed6195190e38e), [c15c206](https://github.com/morluto/rea/commit/c15c2062ad815cc9a3222ccfaeb7ef53cacd8b72)). Thanks @Adolanium.
- **Configuration formats:** Read signed 64-bit TOML integers without rounding, handle large TOML documents without argument-spread failures, preserve JSONC trivia and Hermes YAML scalar text, and reject NUL bytes in registration environment values. ([#4937](https://github.com/morluto/rea/pull/4937), [morluto/rea#4917](https://github.com/morluto/rea/issues/4917), [c43bc0b](https://github.com/morluto/rea/commit/c43bc0bf66a4e245a0cafa40def0d0207bcbd73c), [4fd28fc](https://github.com/morluto/rea/commit/4fd28fc9e0c4f8358147af38c72ab9e814f52d61), [#3568](https://github.com/morluto/rea/pull/3568), [#4335](https://github.com/morluto/rea/pull/4335)). Thanks @alfredo1491, @gensokyo-dev, @kaoru0822-kitauji, @N0zoM1z0, @ShuaixinHuang, @xu91102.
- **Claude Code configuration:** Setup, doctor and uninstall now accept only the strict JSON format Claude Code reads, including a leading UTF-8 BOM. Comments and trailing commas are refused before backup or writing; clients that support JSONC retain their existing behavior. ([#4944](https://github.com/morluto/rea/pull/4944), [morluto/rea#4940](https://github.com/morluto/rea/issues/4940)). Thanks @kaoru0822-kitauji, @xu91102.
- **CLI output and dispatch:** Accept `--flag=value` and spaced global output values, keep array positions in filtered JSON, validate integer tokens before coercion, and exit quietly when the output reader closes. Cancellation remains effective through command finalization; app bundles and static native inspections select the intended workflow. ([#3811](https://github.com/morluto/rea/pull/3811), [#4823](https://github.com/morluto/rea/pull/4823), [2ae4e16](https://github.com/morluto/rea/commit/2ae4e1608f290c95ff7cff28c4d16a79b301d03d), [8d82579](https://github.com/morluto/rea/commit/8d8257928bbe8d43fedffc4db5fca26c8108820f), [#3781](https://github.com/morluto/rea/pull/3781), [279c590](https://github.com/morluto/rea/commit/279c590ef6bb737d4a48ea696a0ae5eb30010b3d), [#3511](https://github.com/morluto/rea/pull/3511), [morluto/rea#3321](https://github.com/morluto/rea/issues/3321), [f31b231](https://github.com/morluto/rea/commit/f31b231a92a61be6bd1800b16be0b3210ae82944)). Thanks @arjunprabhulal, @coygeek, @kaoru0822-kitauji, @ShuaixinHuang, @Sriram-PR, @Tapraj-Pathak.
- **Updates:** Route `--update` through the verified updater and bound retained package-manager diagnostics. ([4f7b5fb](https://github.com/morluto/rea/commit/4f7b5fb6023ce2ec449561782d09e3c7e5ac7c7b), [01cdbbd](https://github.com/morluto/rea/commit/01cdbbdc556262c47d04a5b3391dd9c17946d3fc)).
- **MCP contracts:** Advertise self-contained tool inputs while preserving tuple, array, Boolean and nested-JSON constraints across schema profiles. Schema-reference handling no longer rewrites literal metadata; catalog identity includes the output-schema profile. ([5e30969](https://github.com/morluto/rea/commit/5e30969cc5f1255d44ec7a1f1ca8dbac0af5e7c4), [10aa74d](https://github.com/morluto/rea/commit/10aa74dfedc3ae776f50d1fa1eb83b64ae82d3d6), [204b9f3](https://github.com/morluto/rea/commit/204b9f3ac140a993c3e458bb0e117de31818ab29), [b3389a5](https://github.com/morluto/rea/commit/b3389a5b0834265fe7a40391be315d810a53a97e), [a2e3016](https://github.com/morluto/rea/commit/a2e30168a046f3b79319eb7fbaf807b802104199), [ba98130](https://github.com/morluto/rea/commit/ba98130049fa40ade66b03611ff70c7ddc011a1d), [c5fb86d](https://github.com/morluto/rea/commit/c5fb86d1948af0a287a581b29b2b1d554743c607)). Thanks @akushonkamen, @HarsH-1877, @kaoru0822-kitauji, @xingzihai.
- **Session ordering:** Keep snapshot admission ahead of later calls on the same connection, retain shutdown signals until cleanup succeeds, and preserve inspection authority through investigation publication. ([#3661](https://github.com/morluto/rea/pull/3661), [morluto/rea#3334](https://github.com/morluto/rea/issues/3334), [8873b39](https://github.com/morluto/rea/commit/8873b39770e89eae22b7693bc492d7e423b22bea), [663d07f](https://github.com/morluto/rea/commit/663d07f02cd62c99d81c59391d2c6d745c875335)). Thanks @coygeek, @rudycelekli, @Swatantra-66.
- **JavaScript exports and resolution:** Retain CommonJS exports created with `Object.defineProperty` and track export receiver lifetimes. Resolve scoped packages, package `main`, JSON requires and `.mts`/`.cts` imports using the owning loader; overwritten `require` bindings and erased type-only imports no longer create false runtime links. ([#4725](https://github.com/morluto/rea/pull/4725), [morluto/rea#4724](https://github.com/morluto/rea/issues/4724), [#3567](https://github.com/morluto/rea/pull/3567), [morluto/rea#3541](https://github.com/morluto/rea/issues/3541), [#4838](https://github.com/morluto/rea/pull/4838), [morluto/rea#4632](https://github.com/morluto/rea/issues/4632), [#3844](https://github.com/morluto/rea/pull/3844), [morluto/rea#3383](https://github.com/morluto/rea/issues/3383), [#4164](https://github.com/morluto/rea/pull/4164), [morluto/rea#3915](https://github.com/morluto/rea/issues/3915), [#4223](https://github.com/morluto/rea/pull/4223), [#3801](https://github.com/morluto/rea/pull/3801), [morluto/rea#3393](https://github.com/morluto/rea/issues/3393), [#4165](https://github.com/morluto/rea/pull/4165), [morluto/rea#3932](https://github.com/morluto/rea/issues/3932)). Thanks @Abishek0070, @coygeek, @JNTMTMTM, @kaoru0822-kitauji, @prasad2512, @rodricksz4h5, @xu91102.
- **JavaScript value flow:** Preserve values captured before later assignments, guarded factory fallthrough and nested destructuring. Track exact property keys and setter writes; direct `eval`, compound assignments and incoming callbacks preserve unresolved effects instead of inventing certainty. ([#4196](https://github.com/morluto/rea/pull/4196), [morluto/rea#3881](https://github.com/morluto/rea/issues/3881), [#4341](https://github.com/morluto/rea/pull/4341), [morluto/rea#3963](https://github.com/morluto/rea/issues/3963), [bfb7ed0](https://github.com/morluto/rea/commit/bfb7ed0bd43edc605e00fc52c6e21e735b285904), [#3480](https://github.com/morluto/rea/pull/3480), [#3831](https://github.com/morluto/rea/pull/3831), [morluto/rea#3312](https://github.com/morluto/rea/issues/3312), [9ac76d3](https://github.com/morluto/rea/commit/9ac76d3d9486856d25395b413d7ac5ffa744cad0), [#4342](https://github.com/morluto/rea/pull/4342), [morluto/rea#4206](https://github.com/morluto/rea/issues/4206), [#4243](https://github.com/morluto/rea/pull/4243), [morluto/rea#3880](https://github.com/morluto/rea/issues/3880)). Thanks @coygeek, @kaoru0822-kitauji, @maxazure, @N0zoM1z0, @ShuaixinHuang.
- **JavaScript relationships:** Distinguish `Map` reads from network endpoints, associate response endpoints only with writes that reach the read, and preserve child-process receiver ownership and effective stdio choices. Version comparisons keep relocation and unknown relationships distinct from application changes. ([fbfdb6a](https://github.com/morluto/rea/commit/fbfdb6abe9d663be0be146a15a489e33ccba0f68), [#4759](https://github.com/morluto/rea/pull/4759), [morluto/rea#4606](https://github.com/morluto/rea/issues/4606), [#3819](https://github.com/morluto/rea/pull/3819), [morluto/rea#3362](https://github.com/morluto/rea/issues/3362), [#4336](https://github.com/morluto/rea/pull/4336), [morluto/rea#3355](https://github.com/morluto/rea/issues/3355), [556504e](https://github.com/morluto/rea/commit/556504edcbb0f8cd9eaf81a91b18ff891b8f5457), [4d980d0](https://github.com/morluto/rea/commit/4d980d017622d3175d86aaf3b0dcfbdf4ca3d091)). Thanks @Abdooo2235, @coygeek, @kaoru0822-kitauji, @Xinglan233.
- **JavaScript source admission:** Parse JavaScript with its own grammar, refuse FIFO recovery inputs without blocking, and report oversized or resource-skipped files with their actual capacity and coverage state. Malformed runtime events stay excluded rather than becoming policy-filtered facts. ([#3782](https://github.com/morluto/rea/pull/3782), [morluto/rea#3780](https://github.com/morluto/rea/issues/3780), [#3788](https://github.com/morluto/rea/pull/3788), [morluto/rea#3332](https://github.com/morluto/rea/issues/3332), [#4757](https://github.com/morluto/rea/pull/4757), [morluto/rea#4629](https://github.com/morluto/rea/issues/4629), [#3852](https://github.com/morluto/rea/pull/3852), [morluto/rea#3670](https://github.com/morluto/rea/issues/3670), [#4755](https://github.com/morluto/rea/pull/4755), [morluto/rea#4685](https://github.com/morluto/rea/issues/4685)). Thanks @andresaragon, @coygeek, @kaoru0822-kitauji, @sx4im.
- **Browser capture:** Bound CDP handshakes and command responses, preserve malformed inventory uncertainty and partial cleanup diagnostics, and report cancellation after content reads and final cleanup. Accessibility comparisons require observed coverage; attached emulation teardown limits remain explicit. ([#3555](https://github.com/morluto/rea/pull/3555), [morluto/rea#3553](https://github.com/morluto/rea/issues/3553), [#3901](https://github.com/morluto/rea/pull/3901), [morluto/rea#3379](https://github.com/morluto/rea/issues/3379), [4cc044b](https://github.com/morluto/rea/commit/4cc044be68f813e96907e6cedcf422d0a3170de3), [#4406](https://github.com/morluto/rea/pull/4406), [morluto/rea#4403](https://github.com/morluto/rea/issues/4403), [#2893](https://github.com/morluto/rea/pull/2893), [0123d59](https://github.com/morluto/rea/commit/0123d5976828bfe621bd51daa4cf39fee48a1349), [2ff0867](https://github.com/morluto/rea/commit/2ff086796ad7b8f60397956750584e170dbe2910)). Thanks @coygeek, @dakjdakd, @kaoru0822-kitauji, @maxazure, @N0zoM1z0, @YunzhouLi-hub.
- **Browser page facts:** Preserve URL path bytes when removing credentials, repeated document `Link` headers and complete COOP/COEP structured items. WebMCP discovery reads the actual schema properties and exact receiver path. ([#4731](https://github.com/morluto/rea/pull/4731), [df2fc25](https://github.com/morluto/rea/commit/df2fc251e318a1255309dba232f9f73c700777b6), [c360cfc](https://github.com/morluto/rea/commit/c360cfcd6d7901514b16dd6113eba2e0b0fdf422), [ebd5a82](https://github.com/morluto/rea/commit/ebd5a82c439f6deb3a06062225ce009eb03257cf), [38f92d1](https://github.com/morluto/rea/commit/38f92d108e3148cdf47e4ffbfe3de8a76e795d51)). Thanks @Abdooo2235, @geekwolf, @ShuaixinHuang.
- **Electron runtime capture:** Keep native IPC listener and one-shot dispatch behavior, block synchronous shell effects during capture, refuse active scenarios when the inspect fuse is disabled, and preserve fuse/transport cleanup ownership. ([#4389](https://github.com/morluto/rea/pull/4389), [morluto/rea#4390](https://github.com/morluto/rea/issues/4390), [#4605](https://github.com/morluto/rea/pull/4605), [morluto/rea#4593](https://github.com/morluto/rea/issues/4593), [#4562](https://github.com/morluto/rea/pull/4562), [morluto/rea#4393](https://github.com/morluto/rea/issues/4393), [#3605](https://github.com/morluto/rea/pull/3605), [morluto/rea#3453](https://github.com/morluto/rea/issues/3453), [f9de413](https://github.com/morluto/rea/commit/f9de41371f7536e2e22ce6e43c9314fa2f238a30), [e7df00e](https://github.com/morluto/rea/commit/e7df00e80777757b329bbe8aba6d421d8892b9d5)). Thanks @Adolanium, @gensokyo-dev, @gkobayashi0, @HarsH-1877, @kaoru0822-kitauji, @keeponlight, @N0zoM1z0, @Nitin13-git, @xu91102.
- **APK resource accuracy:** Retain completed tables and decode facts after interrupted or failed reads. Derive locale limits from resource configuration fields, disclose unselectable qualified tables, distinguish document failures from omitted entries, and bind Evidence to the decoded snapshot. ([34a88d6](https://github.com/morluto/rea/commit/34a88d6c1674710953e2c94bd0a17332cd69ca6f), [f5fcf52](https://github.com/morluto/rea/commit/f5fcf5216ffb3a266b8c00f6d9a0943051084ab5), [6385ef4](https://github.com/morluto/rea/commit/6385ef4355d7a794b3154ee38529cbddee583336), [98886ad](https://github.com/morluto/rea/commit/98886adddfcbd7b4f4236b3a9825f91878c3cb11), [dc2e811](https://github.com/morluto/rea/commit/dc2e8117b60c4481372ed89b077e6c1cf81ee653), [#4771](https://github.com/morluto/rea/pull/4771), [morluto/rea#4768](https://github.com/morluto/rea/issues/4768)). Thanks @abhay-2108, @gensokyo-dev, @Iyanuoluwa007, @kaoru0822-kitauji, @N0zoM1z0.
- **Apktool guidance:** Retain the observed version and disclose the matching platform/release advisory windows without treating a version string as proof of decoder safety. Missing prerequisites and decode refusals identify the selected APK or launcher. ([d38f099](https://github.com/morluto/rea/commit/d38f099692394ec90c582f9f0a14b036b421b160), [63696d2](https://github.com/morluto/rea/commit/63696d277328f556c971d1fc9f81ae83128d468b), [cc038da](https://github.com/morluto/rea/commit/cc038da218cada68c87700477aba3db4739791ff)). Thanks @GovinduSasanka, @peter-research.
- **Android method bodies:** Recover original bytecode bodies when Java source is omitted while preserving genuine native/abstract body absence and primary failures during retryable cleanup. ([63c65a2](https://github.com/morluto/rea/commit/63c65a22430a4bbc0c1807a0298edb867775001f), [742b6f5](https://github.com/morluto/rea/commit/742b6f587f3c4ef1b8212e7376d6f3a305b194dc), [9fa6d2b](https://github.com/morluto/rea/commit/9fa6d2b254cc390665974efb52463386a029e9fc)). Thanks @balkan16, @Chessing234.
- **ADB observations and transfers:** Preserve display-scoped focus, distinguish missing declarations from absent focus, retain numeric physical density and mark unknown permission coverage partial. Transfers use consumed snapshot identity and refuse unknown destination existence; uninstall requests explicitly select user zero. ([7086768](https://github.com/morluto/rea/commit/7086768a27242a15daa93486aefbaacc3c891e78), [3d028db](https://github.com/morluto/rea/commit/3d028dbc74a465f6f8df1813a931fbb5362e7dc3), [#4074](https://github.com/morluto/rea/pull/4074), [morluto/rea#3942](https://github.com/morluto/rea/issues/3942), [#4663](https://github.com/morluto/rea/pull/4663), [#4665](https://github.com/morluto/rea/pull/4665), [1342127](https://github.com/morluto/rea/commit/1342127e91d4db8b4113a7a4e85be909bc96e1db), [61e6880](https://github.com/morluto/rea/commit/61e688070f48016b6d178cd04c02fcc2f33e19ad), [be0b2d1](https://github.com/morluto/rea/commit/be0b2d138c46bb951fc3c8ee57ef7b0d57fed312)). Thanks @Copilot, @coygeek, @gongfpp, @Tapraj-Pathak, @yankikucuk.
- **Apple metadata:** Preserve exact plist/keyed-archive integers, negative zero, non-finite real identity and dictionary keys. Reject malformed XML before value decoding, retain undecodable dates as unknown and report unsupported OpenStep entries explicitly. ([#4324](https://github.com/morluto/rea/pull/4324), [morluto/rea#4292](https://github.com/morluto/rea/issues/4292), [2cf9c28](https://github.com/morluto/rea/commit/2cf9c28f27261b7e64af2ba7ecb4e23ea7714aee), [#4839](https://github.com/morluto/rea/pull/4839), [morluto/rea#4834](https://github.com/morluto/rea/issues/4834), [f2b7bbb](https://github.com/morluto/rea/commit/f2b7bbb31279a820f4cf32d439570f8e5381d010), [6c98708](https://github.com/morluto/rea/commit/6c98708793c23615de8053b2cd14d9f164b960c5), [78cf610](https://github.com/morluto/rea/commit/78cf6100f33ad2412c0a3d60b83f8a44a43fbbb5), [c7e9e09](https://github.com/morluto/rea/commit/c7e9e096d3e2444e4c251123b8e914e9c0941f4e), [#3793](https://github.com/morluto/rea/pull/3793), [#4105](https://github.com/morluto/rea/pull/4105), [morluto/rea#3892](https://github.com/morluto/rea/issues/3892)). Thanks @coygeek, @kaoru0822-kitauji, @mertkayacs, @pablodiazjorge, @pollychen-lab, @xu91102.
- **Apple application structure:** Derive bundle components and launchd domains from their owning directories, retain unavailable components, and select only exact `Assets.car` names as asset catalogs. Interface Builder keeps unresolved classes and counts hierarchy records beyond the returned object page. ([149a0fc](https://github.com/morluto/rea/commit/149a0fc06c3c67ee45624e6da14dfb0754473758), [5d6029e](https://github.com/morluto/rea/commit/5d6029ea62a65ec34fd739ee40223c77c6fdb63b), [c192c58](https://github.com/morluto/rea/commit/c192c58815ddeaf5cf30159e7082c742c0bc36b7), [#4094](https://github.com/morluto/rea/pull/4094), [morluto/rea#3914](https://github.com/morluto/rea/issues/3914), [#4118](https://github.com/morluto/rea/pull/4118), [morluto/rea#3958](https://github.com/morluto/rea/issues/3958), [#4162](https://github.com/morluto/rea/pull/4162), [morluto/rea#3950](https://github.com/morluto/rea/issues/3950)). Thanks @coygeek, @kaoru0822-kitauji.
- **Native names and layout:** Keep valid Objective-C records beside malformed neighbors, preserve leading U+FEFF and repeated load-command fields, and select exact arm64e.x1 slices. PE resource ownership and NativeAOT reads stay within declared image/header ranges. ([#3833](https://github.com/morluto/rea/pull/3833), [morluto/rea#3336](https://github.com/morluto/rea/issues/3336), [#4549](https://github.com/morluto/rea/pull/4549), [morluto/rea#4540](https://github.com/morluto/rea/issues/4540), [morluto/rea#4541](https://github.com/morluto/rea/issues/4541), [#4730](https://github.com/morluto/rea/pull/4730), [#4048](https://github.com/morluto/rea/pull/4048), [morluto/rea#4008](https://github.com/morluto/rea/issues/4008), [#3500](https://github.com/morluto/rea/pull/3500), [morluto/rea#3389](https://github.com/morluto/rea/issues/3389), [#4463](https://github.com/morluto/rea/pull/4463), [morluto/rea#4373](https://github.com/morluto/rea/issues/4373), [morluto/rea#4455](https://github.com/morluto/rea/issues/4455), [3fc0075](https://github.com/morluto/rea/commit/3fc007534bb2104d662b43cc712281f9d1d6a7d3), [4a076f3](https://github.com/morluto/rea/commit/4a076f368c62bdfb19415accad342e03a38d1005)). Thanks @coygeek, @Iyanuoluwa007, @jayinvers, @kaoru0822-kitauji, @kevinjosh10, @maxazure, @ShuaixinHuang.
- **Native analysis providers:** Keep Ghidra byte matches within examined coverage, retain PE PDB/function-boundary limitations and preserve configured MIPS choices. Attached IDA refuses universal Mach-O rather than silently choosing a slice; request timeout identity and captured output survive adapter handling. ([#4531](https://github.com/morluto/rea/pull/4531), [#2933](https://github.com/morluto/rea/pull/2933), [morluto/rea#2259](https://github.com/morluto/rea/issues/2259), [01a1b3f](https://github.com/morluto/rea/commit/01a1b3fda6a7dacd24a0b10619d41d12153080d4), [50dd9fc](https://github.com/morluto/rea/commit/50dd9fcad1efb47cb404192c30bdf190dcdaca58), [#4765](https://github.com/morluto/rea/pull/4765), [morluto/rea#3871](https://github.com/morluto/rea/issues/3871), [c0cfccb](https://github.com/morluto/rea/commit/c0cfccb45fe43e7eeff18e56c64caa5b121988f9)). Thanks @BeLit-Development-2, @coygeek, @kaoru0822-kitauji, @N0zoM1z0, @ShuaixinHuang.
- **Recorded crashes:** Prevent GDB from discovering an executable named by an untrusted core, reject core mapping paths that escape the isolated sysroot, and preserve pwntools worker ownership across launcher exec. Completed decode facts and cancellation reasons remain available through failed final cleanup. ([5bf4fff](https://github.com/morluto/rea/commit/5bf4fffc1b835130ddb16f96db9ce13b639591db), [b33c0df](https://github.com/morluto/rea/commit/b33c0df02e93fabca00a44f2de625b1a63637ee9), [#4435](https://github.com/morluto/rea/pull/4435), [morluto/rea#4011](https://github.com/morluto/rea/issues/4011)). Thanks @coygeek, @N0zoM1z0.
- **Cutter and Rizin:** Read Cutter’s active document from core configuration and attribute its host version correctly. Keep interrupted Rizin frames and output whitespace before completion markers, with exact command and cleanup failure attribution. ([#4507](https://github.com/morluto/rea/pull/4507), [morluto/rea#4497](https://github.com/morluto/rea/issues/4497), [#4514](https://github.com/morluto/rea/pull/4514), [morluto/rea#4498](https://github.com/morluto/rea/issues/4498), [#4459](https://github.com/morluto/rea/pull/4459), [morluto/rea#4015](https://github.com/morluto/rea/issues/4015), [d5fc7e6](https://github.com/morluto/rea/commit/d5fc7e6ebf9af050081fc4c6e18b9079cfaa5cdc), [199396f](https://github.com/morluto/rea/commit/199396f61c8f61da326d059606a992304a760147)). Thanks @coygeek, @N0zoM1z0, @Xander-AJ.
- **Windows cleanup:** Retain unpublished runtimes after failed removal, handle read-only attributes and sharing conflicts, preserve primary snapshot failures and honor caller environment overrides. ([f78d137](https://github.com/morluto/rea/commit/f78d137b42741a0ed5fb8ac161286f9a50220c4d), [d69acc3](https://github.com/morluto/rea/commit/d69acc3455c33f90a2fc4381db43d38b6af50622), [0679a79](https://github.com/morluto/rea/commit/0679a7972b4f2b02eee6a86a44f50f4c2967d3cb), [5f9ac2c](https://github.com/morluto/rea/commit/5f9ac2c98a6fe11988c41afb737df9b6d5c3a1b3), [1bbf4bd](https://github.com/morluto/rea/commit/1bbf4bd16ca134cdb2187eaf29291cae90d14a57)). Thanks @DeryFerd.
- **Managed metadata:** Compare nominal signatures and declaring identities across builds, preserve empty names without display substitutions, verify ABI-prefixed Mach-O exports exactly, and charge cached metadata once. Metadata errors report artifact file offsets; mixed-mode assemblies retain their actual boundary classification. ([#3059](https://github.com/morluto/rea/pull/3059), [#3079](https://github.com/morluto/rea/pull/3079), [#3853](https://github.com/morluto/rea/pull/3853), [morluto/rea#3352](https://github.com/morluto/rea/issues/3352), [#3974](https://github.com/morluto/rea/pull/3974), [morluto/rea#3961](https://github.com/morluto/rea/issues/3961), [#3491](https://github.com/morluto/rea/pull/3491), [morluto/rea#3449](https://github.com/morluto/rea/issues/3449), [#4418](https://github.com/morluto/rea/pull/4418), [morluto/rea#4372](https://github.com/morluto/rea/issues/4372), [#3516](https://github.com/morluto/rea/pull/3516), [morluto/rea#3366](https://github.com/morluto/rea/issues/3366)). Thanks @8rulerstar, @coygeek, @duckhunt113, @Hahaa909, @JayOfTheKeyboard, @kaoru0822-kitauji, @keeponlight, @N0zoM1z0, @tomyrms.
- **Archive and filesystem identity:** Reject colliding extraction paths before writing, classify ZIP offsets beyond EOF as malformed, normalize ZIP current-directory prefixes once, and preserve symlink and unreadable-path provenance. A directory named `*.map` is no longer mistaken for a source-map file. ([862a0b2](https://github.com/morluto/rea/commit/862a0b2631785492f8dc20c8acd396646c545fd1), [c209dcb](https://github.com/morluto/rea/commit/c209dcb209118069f123e789949eeba1ef78853e), [6b1c36e](https://github.com/morluto/rea/commit/6b1c36e336eeacbb7159b211e687b4b84f99b9f5), [25c2222](https://github.com/morluto/rea/commit/25c22222abe7a681491bdb4d7316250fdcf32973), [d6e4fe4](https://github.com/morluto/rea/commit/d6e4fe4a4dd8914ec3db50d2a7fc3d0802649262), [#4131](https://github.com/morluto/rea/pull/4131), [morluto/rea#3909](https://github.com/morluto/rea/issues/3909)). Thanks @Adkid-Zephyr, @coygeek, @jackie-cqz, @kaoru0822-kitauji, @maxazure, @XY-code1.
- **Evidence and reconstruction:** Authenticate all retained inventory substeps, preserve source-attributed caveats in composed workflows, and require comparable cited Evidence before declaring reconstruction coverage or readiness. Missing Evidence and residual replay uncertainty stay explicit. ([9ac91e0](https://github.com/morluto/rea/commit/9ac91e0c1e13e91cd21341635ad5be89b0e8642d), [c4608a2](https://github.com/morluto/rea/commit/c4608a29620ea3e7bb8259b47357b942fe4e4709), [#4075](https://github.com/morluto/rea/pull/4075), [morluto/rea#3357](https://github.com/morluto/rea/issues/3357), [#3526](https://github.com/morluto/rea/pull/3526), [morluto/rea#3363](https://github.com/morluto/rea/issues/3363), [153017d](https://github.com/morluto/rea/commit/153017d750322188c1a112b2284c1b8065c67320)). Thanks @coygeek, @gensokyo-dev, @kaoru0822-kitauji, @N0zoM1z0, @rudycelekli.
- **Offline data:** Preserve exact UTC packet-capture instants, SQLite column identity and snapshot admission failures, and cooked WASM directive literals. Cleanup cancellation retains completed EVM/WASM observations rather than losing them. ([796faa0](https://github.com/morluto/rea/commit/796faa0e4e6bf745bcdc33acef65af8ccfc3622d), [748ac7f](https://github.com/morluto/rea/commit/748ac7f0df340f0d0569eca2e803a59cd51ffdbd), [bc51d0e](https://github.com/morluto/rea/commit/bc51d0ea5df7dcee1fcc42dfae3ab0c62c9cca5e), [4f87f02](https://github.com/morluto/rea/commit/4f87f02bb19bf77349a683a5bcb2da2d1da427d0), [d694aef](https://github.com/morluto/rea/commit/d694aef227e90164e6654ea9e5ce6a854d099404), [321cacb](https://github.com/morluto/rea/commit/321cacb84a020f447e1110df5c58fa71d99b7bf1)). Thanks @himamaheswarreddy, @mertkayacs, @rollroyces, @viniciusdsandrade.
- **Kuna recovery:** Share concurrent single-function requests and cache repeats, validate warm exports once, stream string inventories beyond the former fixed buffer ceiling, and keep unproven processes in their run slots until close confirms release. Failure messages distinguish final buffer refusals from configurable deadlines. ([#4045](https://github.com/morluto/rea/pull/4045), [#4169](https://github.com/morluto/rea/pull/4169), [#4049](https://github.com/morluto/rea/pull/4049), [#4318](https://github.com/morluto/rea/pull/4318), [#4052](https://github.com/morluto/rea/pull/4052), [#4098](https://github.com/morluto/rea/pull/4098), [#4343](https://github.com/morluto/rea/pull/4343)). Thanks @kaoru0822-kitauji.
- **Flutter snapshots:** Check symbol-table ranges against loadable segments and retain completed inspection facts when cancellation occurs during snapshot cleanup. ([#3859](https://github.com/morluto/rea/pull/3859), [morluto/rea#3346](https://github.com/morluto/rea/issues/3346), [#4766](https://github.com/morluto/rea/pull/4766), [morluto/rea#4717](https://github.com/morluto/rea/issues/4717), [#4762](https://github.com/morluto/rea/pull/4762), [morluto/rea#4640](https://github.com/morluto/rea/issues/4640)). Thanks @coygeek, @kaoru0822-kitauji.
- **Native metadata recovery:** Keep unknown Objective-C category classes, empty protocol names, undecoded Swift aliases and unfinished property types explicit instead of discarding neighboring valid records. Preserve unnamed segment identity and exclude a dylib’s own install name from dependencies. ([#4093](https://github.com/morluto/rea/pull/4093), [morluto/rea#4012](https://github.com/morluto/rea/issues/4012), [#4078](https://github.com/morluto/rea/pull/4078), [morluto/rea#3873](https://github.com/morluto/rea/issues/3873), [#4085](https://github.com/morluto/rea/pull/4085), [morluto/rea#3934](https://github.com/morluto/rea/issues/3934), [#3825](https://github.com/morluto/rea/pull/3825), [morluto/rea#3345](https://github.com/morluto/rea/issues/3345), [#4051](https://github.com/morluto/rea/pull/4051), [morluto/rea#3875](https://github.com/morluto/rea/issues/3875), [#4050](https://github.com/morluto/rea/pull/4050), [morluto/rea#3872](https://github.com/morluto/rea/issues/3872)). Thanks @coygeek, @kaoru0822-kitauji.
- **Document selection:** Preserve explicitly selected plist paths and bundle defaults, and only use document fallback after confirming its applicability. Finalization keeps completed selection facts and cancellation outcomes. ([e6c4877](https://github.com/morluto/rea/commit/e6c487799bb64f559e66b69be1863e6ec5187548), [#3774](https://github.com/morluto/rea/pull/3774), [9df559b](https://github.com/morluto/rea/commit/9df559b7e712298a761ff26e9caae8d659b7e54b)). Thanks @kaoru0822-kitauji.
- **Capture and comparison accuracy:** Admit schema-valid HAR numeric values while retaining exact-publication limits, preserve empty URL path segments, and keep unrelated process traces and unnamed reference endpoints distinct or unknown. ([#3159](https://github.com/morluto/rea/pull/3159), [morluto/rea#3145](https://github.com/morluto/rea/issues/3145), [#3792](https://github.com/morluto/rea/pull/3792), [morluto/rea#3307](https://github.com/morluto/rea/issues/3307), [#4178](https://github.com/morluto/rea/pull/4178), [morluto/rea#3931](https://github.com/morluto/rea/issues/3931), [#3809](https://github.com/morluto/rea/pull/3809), [morluto/rea#3388](https://github.com/morluto/rea/issues/3388)). Thanks @coygeek, @gensokyo-dev, @kaoru0822-kitauji, @N0zoM1z0, @pablodiazjorge, @xu91102.
- **Evidence publication:** Recheck staged output identity after its final write, classify missing review Evidence and duplicate ledger entries as caller input, and preserve the selected freshness requirement in comparison parameters. ([#4764](https://github.com/morluto/rea/pull/4764), [morluto/rea#4613](https://github.com/morluto/rea/issues/4613), [#4452](https://github.com/morluto/rea/pull/4452), [morluto/rea#4444](https://github.com/morluto/rea/issues/4444), [#4065](https://github.com/morluto/rea/pull/4065), [morluto/rea#4000](https://github.com/morluto/rea/issues/4000)). Thanks @amyanger, @coygeek, @kaoru0822-kitauji, @Rinkia, @Swatantra-66.
### ⚠ BREAKING CHANGES
- **Saved Evidence:** Evidence and analysis snapshots now require explicit nullable `relationship_coverage` in their identity commitments. Artifact inventories require scoped coverage and explicit `integrity_contradictions`; obsolete `coverage_status` and prose-based coverage inference are removed. Regenerate old Evidence/snapshots and inventory observations with this release: saved files are not migrated and omitted facts are not filled with guessed defaults. ([db8128d](https://github.com/morluto/rea/commit/db8128dc0d1c4f731f3d19877fa00d25cf17f657), [0405c9d](https://github.com/morluto/rea/commit/0405c9d361de6d904dfa16cc0b6d8350407f2c9b), [a9588be](https://github.com/morluto/rea/commit/a9588be4ebdd20eeda975cb63ffcdb1cd868b340)).
- **Browser capture results:** Consumers must retain resolved capture limits, event families and omission facts. Set desired budgets through the supported capture options; omitted caller inputs still select defaults, but stored observations must report the resolved values. Admitted content reads queue behind bounded concurrency. ([57a23f0](https://github.com/morluto/rea/commit/57a23f0a2da0fdc3835e203718ded8acea5a34e6)).
- **Android version codes:** `inspect_adb_package.version_code` is a decimal string rather than a JSON number. Read it as a string, or use `BigInt` for numeric comparison. ([#3485](https://github.com/morluto/rea/pull/3485), [morluto/rea#3368](https://github.com/morluto/rea/issues/3368), [7666a48](https://github.com/morluto/rea/commit/7666a482b69dc7cabdbac3bbaf89a43e32300192)). Thanks @coygeek, @kaoru0822-kitauji.
- **Native UI failures:** Failed or cancelled native UI scenarios now return typed errors with the collected report in `partial_observation`. Handle the error path and read that report instead of expecting a successful result containing failed steps. ([d909919](https://github.com/morluto/rea/commit/d9099190ab3a819bd3a9fd62a8714cef398016d5)).
- **Provider status:** `binary_session` candidate availability can be unknown during owner finalization. Preserve that state rather than treating it as unavailable; internal consumers must await the asynchronous session status API. ([150e996](https://github.com/morluto/rea/commit/150e996a86f2bec4982ba87f37bf502a8d5e8214)).
- **Swift symbol locations:** `swift_symbols` entries may have a null `address` when the provider supplies no location. Handle unknown addresses; optional `evidence.reported_address` retains the original provider value. ([8116dc0](https://github.com/morluto/rea/commit/8116dc06512b4609d8db63cebc9f2ff8cb964151)).
- **Linux Hopper admission:** Older builds previously admitted by a fixed allowlist need retained publisher-signed package evidence or an approved update to the current public demo. Update explicit `HOPPER_LAUNCHER_PATH` selections when migrating; the live feed offers only its current release. The official RPM metadata mismatch remains unresolved and is refused. ([#3590](https://github.com/morluto/rea/pull/3590), [morluto/rea#3577](https://github.com/morluto/rea/issues/3577), [70cd4cb](https://github.com/morluto/rea/commit/70cd4cbfb849b61f05d97d2690372a9782831426)). Thanks @gensokyo-dev, @kaoru0822-kitauji, @N0zoM1z0.
Full contribution record: [571 commits and 236 merged PRs](https://github.com/morluto/rea/blob/rea-agents-6.6.0/docs/releases/6.6.0.contributions.json).
## [6.5.0](https://github.com/morluto/rea/compare/rea-agents-6.4.0...rea-agents-6.5.0) (2026-10-13)
Provider prerequisites and recorded verification scope are listed in [the testing guide](docs/testing.md).
+3
View File
@@ -21,6 +21,9 @@ For analysis workflows and agent interfaces, follow the
[performance priorities](AGENTS.md#performance). Explain the selected output
scope, reuse/cache decisions, and relevant before/after measurements when these
costs change.
Use the [analysis optimization skill](.agents/skills/rea-analysis-optimization/SKILL.md)
to locate provider and shared-workflow bottlenecks, preserve Evidence, and
compare equivalent real tasks before claiming an improvement.
When adding or changing an MCP tool, follow the [tool design guide](docs/tool-design.md) and preserve the canonical contracts and generated catalog.
+10 -2
View File
@@ -1,7 +1,7 @@
<div align="center">
**English** · [简体中文](docs/readme/README_zh.md) · [繁體中文](docs/readme/README_zh-TW.md) · [日本語](docs/readme/README_ja.md) · [한국어](docs/readme/README_ko.md) · [Türkçe](docs/readme/README_tr.md) · [Русский](docs/readme/README_ru.md) · [Tiếng Việt](docs/readme/README_vi.md) · [ไทย](docs/readme/README_th.md) · [Deutsch](docs/readme/README_de.md) · [Español](docs/readme/README_es.md) · [Français](docs/readme/README_fr.md) · [Українська](docs/readme/README_uk.md) · [Polski](docs/readme/README_pl.md) · [Português (Brasil)](docs/readme/README_pt-BR.md) · [العربية](docs/readme/README_ar.md) · [فارسی](docs/readme/README_fa.md) · [Bahasa Indonesia](docs/readme/README_id.md) · [Italiano](docs/readme/README_it.md)
· [Ελληνικά](docs/readme/README_el.md)
· [Ελληνικά](docs/readme/README_el.md) · [മലയാളം](docs/readme/README_ml.md)
# REA: Reverse Engineer Anything
@@ -132,6 +132,14 @@ For a CLI installed with `npm install --global` or `bun add --global`:
rea update
```
`rea --update` is an alias for this verified workflow and accepts the same global
output flags. Use `rea update` when combining it with other command controls.
Updater commands retain at most 4 MiB of stdout and stderr combined. Oversized
metadata replies are rejected after the command exits; verbose installs continue
with bounded diagnostics. Human progress output respects terminal backpressure
and waits for submitted writes to finish.
Bun global updates require Bun 1.2.17 or later. With an older Bun release,
upgrade Bun manually before running `rea update`.
@@ -345,7 +353,7 @@ Report vulnerabilities through [SECURITY.md](SECURITY.md).
## Star history
🎉 **250,000 GitHub stars — thank you!**
🎉 **300,000 GitHub stars — thank you!**
Thanks to everyone using REA, reporting bugs, requesting features, testing builds, and contributing fixes.
+167 -23
View File
@@ -15,11 +15,14 @@ import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;
import kotlin.Unit;
import kotlin.ResultKt;
import kotlin.coroutines.Continuation;
import kotlin.coroutines.CoroutineContext;
import kotlin.coroutines.EmptyCoroutineContext;
import kotlin.coroutines.intrinsics.IntrinsicsKt;
import kotlinx.coroutines.BuildersKt;
import kotlinx.io.CoreKt;
import kotlinx.io.JvmCoreKt;
import kotlinx.serialization.json.JsonObject;
/** REA-owned metadata boundary for the unmodified jadx-headless-mcp 0.7.1 JAR. */
class ReaJadxBridge {
@@ -28,7 +31,8 @@ class ReaJadxBridge {
private JadxSession indexedSession;
private Map<String, List<ClassSnapshot>> classes = Map.of();
private record MethodSnapshot(String name, String shortId, Map<String, Object> summary) {}
private record MethodSnapshot(String name, String rawName, String shortId, List<String> bodyAbsenceMarkers,
Map<String, Object> summary) {}
private record ClassSnapshot(JavaClass node, List<MethodSnapshot> methods, Map<String, Object> summary) {}
private static final class InputFailure extends IllegalArgumentException {
@@ -44,15 +48,93 @@ class ReaJadxBridge {
private static CallToolResult json(Object value) { return text(JSON.toJson(value), false); }
/** Translate the typed load outcome before upstream drops its exception identity. */
static Object loadResult(Object result) {
try { ResultKt.throwOnFailure(result); }
catch (Throwable failure) {
if (failure instanceof java.util.concurrent.CancellationException
|| failure instanceof Error && !(failure instanceof OutOfMemoryError)) return result;
if (failure instanceof OutOfMemoryError) {
String reason = failure.getMessage();
boolean heap = "Java heap space".equals(reason) || "GC overhead limit exceeded".equals(reason);
Map<String, Object> reply = new LinkedHashMap<>();
reply.put("kind", "jvm-memory-failure");
reply.put("memory_area", heap ? "heap" : "unknown");
reply.put("exception_type", "java.lang.OutOfMemoryError");
if (reason != null) reply.put("message", reason);
reply.put("max_heap_bytes", Runtime.getRuntime().maxMemory());
return text(JSON.toJson(reply), true);
}
return text("load failed: " + failure.getMessage(), true);
}
SessionHolder.LoadResult loaded = (SessionHolder.LoadResult) result;
Map<String, Object> reply = new LinkedHashMap<>();
reply.put("state", "LOADED");
reply.put("apk_path", loaded.getApkPath());
reply.put("class_count", loaded.getClassCount());
reply.put("raw_class_count", loaded.getRawClassCount());
reply.put("resource_count", loaded.getResourceCount());
reply.put("load_duration_ms", loaded.getLoadDurationMs());
reply.put("decompile_timeout_ms", loaded.getDecompileTimeoutMs());
reply.put("threads", loaded.getThreads());
reply.put("code_cache_size", loaded.getCodeCacheSize());
reply.put("resources", loaded.getResourceMode());
if (!loaded.getIncludePackages().isEmpty()) reply.put("include_packages", loaded.getIncludePackages());
if (!loaded.getExcludePackages().isEmpty()) reply.put("exclude_packages", loaded.getExcludePackages());
return json(reply);
}
private Object load(kotlinx.serialization.json.JsonObject arguments, SessionConfig defaults,
Continuation<? super CallToolResult> continuation) {
JsonObject args = JsonParser.parseString(arguments.toString()).getAsJsonObject();
String path = string(args, "path");
SessionConfig options = defaults.withLoadOverrides(
optionalString(args, "include_packages"), optionalString(args, "exclude_packages"),
args.has("threads") ? integer(args, "threads", 1) : null,
args.has("code_cache_size") ? integer(args, "code_cache_size", 64) : null,
optionalString(args, "resources"));
return loadCall(next -> holder.load(path, options, next), continuation);
}
static Object loadCall(kotlin.jvm.functions.Function1<Continuation<SessionHolder.LoadResult>, Object> load,
Continuation<? super CallToolResult> continuation) {
var forwarded = new java.util.concurrent.atomic.AtomicBoolean();
Continuation<SessionHolder.LoadResult> resumed = new Continuation<>() {
public CoroutineContext getContext() { return continuation.getContext(); }
public void resumeWith(Object result) {
if (!forwarded.compareAndSet(false, true)) throw new IllegalStateException("Load resumed twice");
Object translated;
try { translated = loadResult(result); }
catch (Throwable failure) { translated = ResultKt.createFailure(failure); }
// Keep the consumer outside the translation catch, including inline completion.
continuation.resumeWith(translated);
}
};
Object result;
try { result = load.invoke(resumed); }
catch (Throwable failure) {
if (forwarded.get()) ResultKt.throwOnFailure(ResultKt.createFailure(failure));
result = ResultKt.createFailure(failure);
}
if (result == IntrinsicsKt.getCOROUTINE_SUSPENDED()) return result;
Object translated = loadResult(result);
ResultKt.throwOnFailure(translated);
return translated;
}
private static String optionalString(JsonObject args, String name) {
return args.has(name) ? string(args, name) : null;
}
private static String string(JsonObject args, String name) {
JsonElement value = JsonParser.parseString(args.toString()).getAsJsonObject().get(name);
JsonElement value = args.get(name);
if (value == null || !value.isJsonPrimitive() || !value.getAsJsonPrimitive().isString())
throw new IllegalArgumentException(name + " must be a string");
return value.getAsString();
}
private static int integer(JsonObject args, String name, int fallback) {
JsonElement value = JsonParser.parseString(args.toString()).getAsJsonObject().get(name);
JsonElement value = args.get(name);
if (value == null) return fallback;
if (!value.isJsonPrimitive() || !value.getAsJsonPrimitive().isNumber())
throw new IllegalArgumentException(name + " must be a nonnegative integer");
@@ -90,10 +172,13 @@ class ReaJadxBridge {
if (!shortId.startsWith(rawName + "("))
throw new IllegalStateException("JADX method ID has no raw-name prefix: " + shortId);
String descriptor = shortId.substring(rawName.length());
List<String> bodyAbsenceMarkers = new ArrayList<>();
if (method.getAccessFlags().isNative()) bodyAbsenceMarkers.add("native_method");
if (method.getAccessFlags().isAbstract()) bodyAbsenceMarkers.add("abstract_method");
String signature = name + "(" + method.getArgTypes().stream()
.map(Object::toString).collect(Collectors.joining(", "))
+ "): " + method.getReturnType().toString();
return new MethodSnapshot(name, shortId, Map.of(
return new MethodSnapshot(name, rawName, shortId, List.copyOf(bodyAbsenceMarkers), Map.of(
"name", name, "signature", signature,
"dex_descriptor", descriptor,
"is_constructor", method.isConstructor(), "def_pos", 0));
@@ -140,16 +225,52 @@ class ReaJadxBridge {
private JadxSession.SmartCode methodBody(JadxSession current, ClassSnapshot cls,
MethodSnapshot selected, JavaMethod method) {
if (!selected.shortId().equals("<clinit>()V"))
return current.getMethodBodySmart(method, current.getMaxSourceBytes(), true);
// Access flags belong to the parsed member, before code generation rewrites it.
// These methods have no Java body; source slicing can include unrelated members.
if (!selected.bodyAbsenceMarkers().isEmpty())
return new JadxSession.SmartCode("", "java", false, selected.bodyAbsenceMarkers());
// Java code generation can fold all or part of <clinit> into field declarations.
// Its method text cannot establish coverage, even when a static block remains.
JadxSession.MethodSmali smali = current.getMethodSmali(cls.node(), method.getName());
if (!smali.getFound() || smali.getBlocks().size() != 1)
throw new IllegalArgumentException("Static initializer disassembly requires one exact method: " + selected.shortId());
if (selected.shortId().equals("<clinit>()V"))
return exactMethodSmali(current, cls, selected, List.of("static_initializer_disassembly"));
String java = current.getMethodSource(method);
if (java.startsWith("// ERROR:")) throw new IllegalArgumentException(java);
// The upstream placeholder means only that Java code was omitted, including
// methods merged into synthetic bridges. Access flags established absence above.
if (java.isEmpty() || java.equals(
"// method exists but has no decompiled body (native/abstract)"))
return exactMethodSmali(current, cls, selected, List.of("java_body_unavailable"));
List<String> markers = DecompileFailureKt.detectDecompileFailure(java);
if (markers.stream().anyMatch(DecompileFailureKt.getSTRONG_FAILURE_MARKERS()::contains))
return exactMethodSmali(current, cls, selected, markers);
return new JadxSession.SmartCode(
TextUtilKt.truncateToBytes(smali.getBlocks().get(0), current.getMaxSourceBytes()),
"smali", true, List.of("static_initializer_disassembly"));
TextUtilKt.truncateToBytes(java, current.getMaxSourceBytes()), "java", false, markers);
}
private JadxSession.SmartCode exactMethodSmali(JadxSession current, ClassSnapshot cls,
MethodSnapshot selected, List<String> markers) {
JadxSession.MethodSmali smali = current.getMethodSmali(cls.node(), selected.rawName());
String block = selectMethodSmali(smali, selected.shortId());
return new JadxSession.SmartCode(
TextUtilKt.truncateToBytes(block, current.getMaxSourceBytes()), "smali", true, markers);
}
private static String selectMethodSmali(JadxSession.MethodSmali smali, String shortId) {
if (!smali.getFound())
throw new IllegalArgumentException("JADX could not disassemble " + shortId
+ (smali.getNote() == null ? "" : ": " + smali.getNote()));
// Upstream returns every same-name overload, and can return an unterminated
// trailing block. Match the full original identity before applying output limits.
List<String> matches = smali.getBlocks().stream().filter(block -> {
String header = block.lines().findFirst().orElse("").strip();
return header.startsWith(".method ") && header.endsWith(" " + shortId);
}).toList();
if (matches.size() != 1)
throw new IllegalArgumentException("Disassembly could not establish one selected method: " + shortId);
String block = matches.get(0);
if (!block.stripTrailing().endsWith("\n.end method"))
throw new IllegalArgumentException("Selected method disassembly is incomplete: " + shortId);
return block;
}
// The local transport admits 8 MiB frames. Reserve 1 KiB for the fixed
@@ -203,7 +324,8 @@ class ReaJadxBridge {
return new DirectInvokes(sites, exhaustive[0]);
}
private CallToolResult handle(String name, JsonObject args) {
private CallToolResult handle(String name, kotlinx.serialization.json.JsonObject input) {
JsonObject args = JsonParser.parseString(input.toString()).getAsJsonObject();
if (name.equals("rea_jvm_status")) return json(Map.of(
"engine_reported_version", BuildInfo.VERSION,
"max_heap_bytes", Runtime.getRuntime().maxMemory(),
@@ -213,12 +335,25 @@ class ReaJadxBridge {
JadxSession current = session();
if (name.equals("list_classes")) {
List<String> names = current.getClassFqns();
String query = args.has("query") ? string(args, "query") : "";
int offset = integer(args, "offset", 0);
int limit = integer(args, "limit", 200);
int start = Math.min(offset, names.size());
int end = (int) Math.min((long) start + limit, names.size());
return json(Map.of("total", names.size(), "offset", offset, "limit", limit,
"items", names.subList(start, end)));
int end = start;
List<String> items;
if (query.isEmpty()) {
end = (int) Math.min((long) start + limit, names.size());
items = names.subList(start, end);
} else {
items = new ArrayList<>();
while (end < names.size() && items.size() < limit) {
String nameInInventory = names.get(end++);
if (nameInInventory.contains(query)) items.add(nameInInventory);
}
}
return json(Map.of("total_classes", names.size(), "next_offset", end,
"scope", "top_level", "offset", offset, "limit", limit,
"items", items));
}
ClassSnapshot cls = selected(args);
if (name.equals("get_class_summary")) return json(cls.summary());
@@ -230,6 +365,7 @@ class ReaJadxBridge {
JadxSession.SmartCode code = methodBody(current, cls, overloads.get(index), method);
return json(Map.of("class_name", cls.summary().get("full_name"),
"method_name", overloads.get(index).name(), "full_name", method.getFullName(),
"dex_descriptor", overloads.get(index).summary().get("dex_descriptor"),
"overload_index", index, "overload_count", overloads.size(),
"mode", code.getKind(), "fell_back", code.getFellBack(),
"markers", code.getMarkers(), "body", code.getText()));
@@ -241,7 +377,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 && !args.containsKey("overload_index"))
if (overloads.size() != 1 && !args.has("overload_index"))
throw new InputFailure("overload_index", "Select one of " + overloads.size() + " method overloads");
overloadIndex = integer(args, "overload_index", 0);
if (overloadIndex >= overloads.size())
@@ -287,11 +423,12 @@ class ReaJadxBridge {
public static void main(String[] args) throws Exception {
PrintStream protocolOut = System.out;
System.setOut(System.err);
SessionHolder holder = new SessionHolder(new SessionConfig(
1048576, 0, 90000L, 1, List.of(), List.of(), 64, ResourceMode.FULL));
SessionConfig defaults = new SessionConfig(
1048576, 0, 90000L, 1, List.of(), List.of(), 64, ResourceMode.FULL);
SessionHolder holder = new SessionHolder(defaults);
ServerCapabilities capabilities = new ServerCapabilities(
new ServerCapabilities.Tools(null), null, null, null, null, null, null, Map.of());
Server server = new Server(new Implementation("rea-jadx-bridge", "1", null, null, null),
Server server = new Server(new Implementation("rea-jadx-bridge", "4", null, null, null),
new ServerOptions(capabilities), "", ignored -> Unit.INSTANCE);
SessionToolsKt.registerSessionTools(server, holder);
ManifestToolsKt.registerManifestTools(server, holder);
@@ -299,13 +436,17 @@ class ReaJadxBridge {
MethodToolsKt.registerMethodTools(server, holder);
XrefToolsKt.registerXrefTools(server, holder);
ReaJadxBridge bridge = new ReaJadxBridge(holder);
Tool loadTool = server.getTools().get("load_apk").getTool();
server.removeTool("load_apk");
server.addTool(loadTool, (connection, request, continuation) ->
bridge.load(request.getArguments(), defaults, continuation));
Set<String> consumed = Set.of("load_apk", "get_app_info", "get_android_manifest",
"list_classes", "get_class_summary", "get_method_body",
"get_xrefs_to_class", "get_xrefs_to_method");
for (String name : new ArrayList<>(server.getTools().keySet()))
if (!consumed.contains(name)) server.removeTool(name);
Tool diagnostics = new Tool("rea_jvm_status",
new ToolSchema(null, new JsonObject(Map.of()), List.of(), null),
new ToolSchema(null, new kotlinx.serialization.json.JsonObject(Map.of()), List.of(), null),
"Observed worker JVM and metadata scope", null, null, null, null, null, null);
server.addTool(diagnostics, (connection, request, continuation) -> bridge.handle("rea_jvm_status", request.getArguments()));
for (String name : List.of("list_classes", "get_class_summary",
@@ -320,13 +461,16 @@ class ReaJadxBridge {
};
Map<String, kotlinx.serialization.json.JsonElement> properties = new LinkedHashMap<>();
for (String field : fields) properties.put(field, tool.getInputSchema().getProperties().get(field));
if (name.equals("list_classes")) properties.put("query",
new kotlinx.serialization.json.JsonObject(Map.of(
"type", kotlinx.serialization.json.JsonElementKt.JsonPrimitive("string"))));
String description = switch (name) {
case "list_classes" -> "Indexed pages of all top-level class names, with offset and limit.";
case "list_classes" -> "Pages of case-sensitive matching top-level class names; offset and next_offset are inventory positions, limit bounds matching rows. Omitted or empty query inventories all names.";
case "get_class_summary" -> "Parsed member metadata for one exact class name; no source generation.";
case "get_method_body" -> "Source for an exact class and stable same-name overload index; static initializers use smali to preserve folded field initialization.";
default -> "Complete static using-node inventory for an exact class or selected method overload; one node may contain multiple invoke instructions, and source lines are unresolved.";
};
Tool narrowed = new Tool(name, new ToolSchema(null, new JsonObject(properties),
Tool narrowed = new Tool(name, new ToolSchema(null, new kotlinx.serialization.json.JsonObject(properties),
tool.getInputSchema().getRequired(), null), description, null, null, null, null, null, null);
server.addTool(narrowed, (connection, request, continuation) -> {
try { return bridge.handle(name, request.getArguments()); }
+13 -5
View File
@@ -783,14 +783,22 @@ def _within_response_limit(value: Any) -> bool:
current = pending.pop()
if isinstance(current, str):
size += 2
if len(current) > MAX_FRAME_BYTES - size:
return False
if current.isascii():
size += len(current)
size += current.count('"') + current.count("\\")
size += sum(5 for character in current if ord(character) < 0x20)
else:
size += 4 * len(current)
size += current.count('"') + current.count("\\")
size += sum(5 for character in current if ord(character) < 0x20)
# Count UTF-8 bytes without allocating a copy of the whole output.
try:
size += sum(
len(current[start:start + 65536].encode("utf-8"))
for start in range(0, len(current), 65536)
)
except UnicodeEncodeError:
# Unencodable output also needs the signed omission fallback.
return False
size += current.count('"') + current.count("\\")
size += sum(5 for character in current if ord(character) < 0x20)
elif isinstance(current, dict):
identity = id(current)
if identity in seen:
+18
View File
@@ -140,6 +140,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
"params"
);
private static final String[] CAPABILITIES = {
"read_binary_inventory_summary",
"annotate_native_function",
"set_address_name",
"set_addresses_names",
@@ -427,6 +428,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
);
}
return switch (request.method) {
case "read_binary_inventory_summary" -> binaryInventorySummary(request.params);
case "inspect_native_load_image" -> inspectNativeLoadImage(request.params);
case "read_bytes" -> readMemoryBytes(request.params);
case "search_bytes" -> searchMemoryBytes(request.params, descriptor);
@@ -1974,6 +1976,18 @@ public final class ReaGhidraBridge extends HeadlessScript {
return result;
}
private JsonObject binaryInventorySummary(JsonObject params) throws Exception {
requireKeys(params, Set.of());
JsonObject result = new JsonObject();
result.addProperty("document", currentProgram.getName());
result.add("segments", segments());
// Count the owning inventories, preserving their exact discovery rules
// without serializing function identities or string values for counts.
result.addProperty("procedure_count", procedures().size());
result.addProperty("string_count", strings().size());
return result;
}
private JsonArray listNames(JsonObject params) throws Exception {
requireKeys(params, Set.of("document", "address"));
requireDocument(params);
@@ -2000,6 +2014,10 @@ public final class ReaGhidraBridge extends HeadlessScript {
private JsonArray listSegments(JsonObject params) {
requireKeys(params, Set.of("document"));
requireDocument(params);
return segments();
}
private JsonArray segments() {
JsonArray result = new JsonArray();
String imageBase = canonicalAddress(currentProgram.getImageBase());
MemoryBlock[] blocks = currentProgram.getMemory().getBlocks();
+10 -20
View File
@@ -431,10 +431,6 @@ def _procedure_map(document):
return result
def _strings(document):
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)
@@ -521,7 +517,7 @@ def _search_inventory(document, kind):
if kind == "procedure":
values = _procedure_map(document)
elif kind == "string":
values = _strings(document)
values = _string_inventory(document)
elif kind == "name":
values = {_hex(address): value for address, value in _name_map(document).items()}
else:
@@ -548,23 +544,17 @@ def _search_results(document, kind, params):
else:
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,
"value": value,
}
for address, value in selected
return [
{"address": address, **record}
for address, record in _search_inventory(document, kind)
if matches(record["value"])
]
return [
{"address": address, "value": value}
for address, value in _search_inventory(document, kind)
if matches(value)
]
def _unavailable(reason):
+65 -7
View File
@@ -12,16 +12,29 @@ struct ProcessIdentityObservation: Encodable {
let pid: Int32
let state: String
let identity: String?
let effective_uid: UInt32?
let lifecycle: String?
let relation: ProcessRelationObservation?
let reason: String?
}
private struct ProcessMetadata {
struct ProcessRelationObservation: Encodable {
let state: String
let parent_pid: Int32
let process_group_id: Int32
}
struct ProcessMetadata {
let identity: String
let effectiveUid: UInt32
let lifecycle: String
let parentPid: Int32
let processGroupId: Int32
let pointerSize: Int
}
struct ProcessSnapshot {
fileprivate let metadata: [Int32: ProcessMetadata]
let metadata: [Int32: ProcessMetadata]
let failure: String?
}
@@ -75,6 +88,10 @@ func readProcessSnapshot(
process.kp_proc.p_pid,
ProcessMetadata(
identity: "\(start.tv_sec):\(start.tv_usec)",
effectiveUid: process.kp_eproc.e_ucred.cr_uid,
lifecycle: process.kp_proc.p_stat == SZOMB ? "zombie" : "non-zombie",
parentPid: process.kp_eproc.e_ppid,
processGroupId: process.kp_eproc.e_pgid,
pointerSize: process.kp_proc.p_flag & P_LP64 != 0 ? 8 : 4
)
)
@@ -87,20 +104,61 @@ func readProcessSnapshot(
}
func readProcessIdentities(pids: [Int32]) -> [ProcessIdentityObservation] {
let snapshot = readProcessSnapshot()
readProcessIdentities(pids: pids, snapshot: readProcessSnapshot())
}
func readProcessIdentities(
pids: [Int32],
snapshot: ProcessSnapshot
) -> [ProcessIdentityObservation] {
return pids.map { pid in
guard pid > 0 else {
return unavailableIdentity(pid: pid, reason: "invalid_process_id")
}
guard let metadata = snapshot.metadata[pid] else {
return unavailableIdentity(
if let failure = snapshot.failure {
return unavailableIdentity(pid: pid, reason: failure)
}
// This records absence from this successful KERN_PROC_ALL snapshot only.
// Unlike the Linux procfs path, it has no PID-specific kill(0)
// corroboration; callers must not treat it as universal or future exit
// proof.
return ProcessIdentityObservation(
pid: pid,
reason: snapshot.failure ?? "process_not_in_snapshot"
state: "absent",
identity: nil,
effective_uid: nil,
lifecycle: nil,
relation: nil,
reason: "not-in-snapshot"
)
}
return ProcessIdentityObservation(pid: pid, state: "readable", identity: metadata.identity, reason: nil)
return ProcessIdentityObservation(
pid: pid,
state: "readable",
identity: metadata.identity,
effective_uid: metadata.effectiveUid,
lifecycle: metadata.lifecycle,
relation: ProcessRelationObservation(
state: "observed",
parent_pid: metadata.parentPid,
process_group_id: metadata.processGroupId
),
reason: nil
)
}
}
private func unavailableIdentity(pid: Int32, reason: String) -> ProcessIdentityObservation {
ProcessIdentityObservation(pid: pid, state: "unavailable", identity: nil, reason: reason)
ProcessIdentityObservation(
pid: pid,
state: "unavailable",
identity: nil,
effective_uid: nil,
lifecycle: nil,
relation: nil,
reason: reason
)
}
enum RunTokenReadError: Error {
+15 -2
View File
@@ -20,8 +20,9 @@ def inspect(request):
root = Path(os.environ["REA_CORE_CONTEXT_REQUEST"]).parent
empty = root / "no-libraries"
empty.mkdir(mode=0o700)
for command in ["set auto-load off", "set debuginfod enabled off", "set auto-solib-add off", "set history save off", "set pagination off",
"set sysroot ./no-libraries", "set solib-search-path ./no-libraries"]:
for command in ["set auto-load off", "set debuginfod enabled off", "set auto-solib-add off", "set history save off", "set pagination off", "set target-file-system-kind unix",
"set sysroot ./no-libraries", "set solib-search-path ./no-libraries",
"set debug-file-directory ./no-libraries"]:
gdb.execute(command, to_string=True)
entry = request["gdbinit"]
try:
@@ -38,7 +39,19 @@ def inspect(request):
# relative filename in the owned cwd so no selected path becomes GDB syntax.
if Path(request["snapshot_path"]) != root.parent / "object.snapshot":
raise ContextFailure("decoder", "Core context request did not select the shared owned snapshot.")
# GDB 16 searches AT_EXECFN/NT_FILE outside sysroot when no executable BFD
# is selected. Occupy that slot with the already running, owned debugger;
# exec-file loads no symbols and never runs it. Clear it before any query.
# /proc/self/exe identifies this process, not the core's historical PID.
architecture = {"x86_64-little-endian": "i386:x86-64", "aarch64-little-endian": "aarch64"}.get(request["architecture"])
if architecture is None:
raise ContextFailure("unsupported", "Unsupported recorded core architecture.")
gdb.execute("exec-file /proc/self/exe", to_string=True)
# The placeholder must not select the core's architecture. Reuse the
# decoder's validated profile, including for cross-architecture GDB builds.
gdb.execute("set architecture " + architecture, to_string=True)
gdb.execute("core-file ../object.snapshot", to_string=True)
gdb.execute("file", to_string=True)
inferior = gdb.selected_inferior()
if inferior.connection is None or inferior.connection.type != "core" or gdb.current_progspace().filename is not None:
raise ContextFailure("decoder", "Requested core-only boundary was not established; no mapping query performed.")
+117
View File
@@ -0,0 +1,117 @@
"""Producer regressions with controlled GDB state, not native debugger qualification."""
import json
import os
from pathlib import Path
import runpy
import sys
import tempfile
import types
import unittest
from unittest.mock import patch
BRIDGE = Path(__file__).with_name("core_context.py")
class CoreContextTests(unittest.TestCase):
def inspect(self, failure=None, connection="core", symbols=None, architecture="x86_64-little-endian"):
commands, reads, queries = [], [], []
state = {"executable": None, "symbols": None, "connection": None}
gdb = types.ModuleType("gdb")
gdb.VERSION = "16.3"
gdb.selected_inferior = lambda: types.SimpleNamespace(
connection=state["connection"], pid=123)
gdb.current_progspace = lambda: types.SimpleNamespace(filename=state["symbols"])
def execute(command, to_string):
self.assertTrue(to_string)
commands.append(command)
if command == failure:
raise RuntimeError("controlled command failure")
if command == "exec-file /proc/self/exe":
state["executable"] = "/proc/self/exe"
elif command == "core-file ../object.snapshot":
if state["executable"] is None:
reads.append("recorded-executable")
state["executable"] = state["symbols"] = "recorded-executable"
state["connection"] = types.SimpleNamespace(type=connection)
elif command == "file":
state["executable"] = None
state["symbols"] = symbols
gdb.execute = execute
pwndbg = types.ModuleType("pwndbg")
pwndbg.aglib = types.ModuleType("pwndbg.aglib")
pwndbg.aglib.vmmap = types.ModuleType("pwndbg.aglib.vmmap")
pwndbg.lib = types.ModuleType("pwndbg.lib")
pwndbg.lib.version = types.ModuleType("pwndbg.lib.version")
pwndbg.lib.version.__version__ = "2026.09.15"
def maps():
self.assertIsNone(state["executable"], "Helper executable must be discarded before mapping queries")
queries.append("maps")
return [types.SimpleNamespace(start=4096, end=8192, offset=0, flags=5, objfile="recorded-executable")]
pwndbg.aglib.vmmap.get = maps
modules = {module.__name__: module for module in [
gdb, pwndbg, pwndbg.aglib, pwndbg.aglib.vmmap, pwndbg.lib, pwndbg.lib.version]}
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
stage = root / "debugger"
stage.mkdir()
plugin = root / "gdbinit.py"
plugin.write_text("")
request = stage / "request.json"
reply = stage / "reply.json"
request.write_text(json.dumps({"gdbinit": str(plugin), "architecture": architecture, "snapshot_path": str(root / "object.snapshot"), "reply_path": str(reply)}))
with patch.dict(sys.modules, modules), patch.dict(os.environ, REA_CORE_CONTEXT_REQUEST=str(request)):
runpy.run_path(str(BRIDGE))
result = json.loads(reply.read_text())
return result, commands, reads, queries
def test_core_load_never_opens_recorded_executable_and_queries_only_after_discard(self):
result, commands, reads, queries = self.inspect()
self.assertTrue(result["ok"], result)
self.assertEqual(reads, [])
self.assertEqual(queries, ["maps"])
self.assertEqual(commands[-4:], ["exec-file /proc/self/exe", "set architecture i386:x86-64", "core-file ../object.snapshot", "file"])
self.assertLess(commands.index("set debug-file-directory ./no-libraries"), commands.index("core-file ../object.snapshot"))
self.assertIsNone(result["value"]["executable"])
self.assertEqual(result["value"]["maps"][0]["current_file_identity"], "unknown")
def test_failed_guard_core_load_or_discard_never_queries_mappings(self):
for command in ["exec-file /proc/self/exe", "set architecture i386:x86-64", "core-file ../object.snapshot", "file"]:
with self.subTest(command=command):
result, commands, reads, queries = self.inspect(failure=command)
self.assertFalse(result["ok"])
self.assertEqual(reads, [])
self.assertEqual(queries, [])
if command in ["exec-file /proc/self/exe", "set architecture i386:x86-64"]:
self.assertNotIn("core-file ../object.snapshot", commands)
def test_cross_architecture_uses_the_validated_decoder_profile(self):
result, commands, reads, queries = self.inspect(architecture="aarch64-little-endian")
self.assertTrue(result["ok"], result)
self.assertEqual(reads, [])
self.assertEqual(queries, ["maps"])
self.assertLess(commands.index("set architecture aarch64"), commands.index("core-file ../object.snapshot"))
def test_unknown_architecture_refuses_before_loading_core(self):
result, commands, reads, queries = self.inspect(architecture="unknown")
self.assertFalse(result["ok"])
self.assertEqual(result["reason"], "unsupported")
self.assertNotIn("core-file ../object.snapshot", commands)
self.assertEqual(reads, [])
self.assertEqual(queries, [])
def test_wrong_connection_or_remaining_symbols_never_queries_mappings(self):
for options in [{"connection": "native"}, {"symbols": "unexpected-symbols"}]:
with self.subTest(options=options):
result, _, reads, queries = self.inspect(**options)
self.assertFalse(result["ok"])
self.assertEqual(reads, [])
self.assertEqual(queries, [])
if __name__ == "__main__":
unittest.main()
+14 -6
View File
@@ -98,16 +98,24 @@ existing analysis families directly, for example
| `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`); checks for existing targets and refuses them without explicit overwrite (the check is not atomic); compares digests when device `sha256sum` is available |
| `install_adb_package` | **mutates device** | Local APK via `adb install [-r]`; preserves its Success/Failure verdict, records `replace_requested`, and leaves actual replacement `null` because prior package state is not observed |
| `uninstall_adb_package` | **mutates device** | Removes a package and its data for user 0 |
| `uninstall_adb_package` | **mutates device** | Requests package removal for user 0 via `adb shell pm uninstall --user 0`, without data retention |
| `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 |
For `inspect_adb_window`, an explicitly printed null focus reference becomes
JSON `null`. `observed_lines` retains the original focus declarations, including
their field names, so explicit absence can be distinguished from omitted
declarations. REA reads the displays section only when the windows section
declares neither focus field. If both sections omit them, focus remains unknown.
For `inspect_adb_window`, `focus_contexts` retains each display header, its exact
display ID when recognized, and every focus declaration with its original line.
Declarations without a display header are explicitly `unscoped`. A missing
declaration differs from a declaration whose `value` is JSON `null`.
`source_section` identifies the selected dumpsys section; `observed_lines`
preserves its focus declarations and display headers in source order.
`focus_summary` is `single_context` only for one context with no repeated focus
field. The singular `focused_window` and `focused_app` summarize that context;
they do not establish device-wide focus. Multiple contexts or repeated fields
produce `ambiguous` with null singular fields and all declarations retained.
When no focus field was declared, the status is `unavailable`. REA reads the
displays section only when the windows section declares neither focus field.
For `install_adb_package`, `replace_requested` records whether `-r` was sent.
The `replaced` result is `null`: the successful install response does not say
+45 -11
View File
@@ -103,9 +103,10 @@ 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.
The filtered class-page bridge (protocol 2) is verified on Linux x86-64 with
Temurin 21, public Appium ApiDemos 6.0.18 and NewPipe 0.29.1 APKs. Earlier
metadata-bridge records covered macOS arm64/OpenJDK 21 and Windows x64/JDK 21;
this protocol revision has not been rerun on those hosts or Linux/JDK 25.
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.
@@ -146,10 +147,20 @@ queries accept the same `overload_index`; the bridge resolves the selected
method node and the result reports its index and displayed signature. These
indices are tied to the current artifact and engine, not stable across builds.
The engine's smali fallback also joins same-name overloads; REA rejects that
fallback for an overloaded method instead of attributing all bodies to one
selected overload. Native/abstract methods with no decompiled body report
`body_status: "not_available"` without inferring which implementation flag caused it.
Smali fallbacks select one complete block using the original method name and DEX
descriptor, before applying the source byte limit. This preserves the selected
overload even when Java code generation renames a method. If the selected Java
body was omitted, including a method merged into a synthetic bridge, REA returns
its original smali with the `java_body_unavailable` marker. The marker describes
missing Java; it does not infer why the method was omitted or name a replacement.
Unresolved or duplicate disassembly identities fail instead of attributing another
method's instructions to the selection.
Native and abstract methods are identified from access flags
captured before code generation. They report `body_status: "not_available"`, an
empty source, and the `native_method` or `abstract_method` marker; their declarations
are not passed through the engine's source slicer. Other missing decompiled bodies
do not establish either access flag.
Static initializers (`<clinit>`) return smali with the
`static_initializer_disassembly` marker. Java decompilation can move their
@@ -163,7 +174,10 @@ the same source byte limit and explicit truncation reporting.
permissions and class/resource counts. Summary fields are extracted by the
upstream engine and should be checked against the retained XML when needed.
Signature verification is explicitly `not_performed`.
- Class search consumes all pages and checks their counts. An empty `query`
- Class search filters the engine's cached top-level names before transferring
pages, then follows contiguous inventory positions without rescanning earlier
rows. It checks selection, scope, examined ranges and counts before reporting
complete coverage. Complete producer replies stay in Evidence; an empty `query`
inventories all class-name rows; class names are decompiler representations.
Repeated names remain repeated in `matches` so the inventory row count and
producer evidence stay visible. `duplicate_names` identifies matching names
@@ -233,8 +247,12 @@ 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. Framework hints match complete native library names, such as
and path-based bridge hypotheses. File and slice occurrences supply component
endpoints; directory trees and symlinks retain their identities in the source
inventory without being classified as code files. It does not decode DEX or
claim observed runtime calls. DEX/JVM runtime hints summarize the classified
bytecode component lists. 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.
@@ -299,7 +317,15 @@ settings. Evidence reports the worker's observed `Runtime.maxMemory()` rounded
down to MiB and retains exact bytes, Java version and visible processors in its
raw runtime response. The observed allocatable heap can differ from configured
`-Xmx`, especially with Serial GC. Heap is not a total RSS cap: the JVM also
uses native memory. Independent REA instances have independent queues. Whole
uses native memory. A typed JVM memory allocation failure during APK loading
reports `resource_constraint` with the observed maximum heap in bytes. Known
heap failures name `REA_JADX_HEAP_MIB` in remediation; other memory regions
remain unknown. A healthy doctor configuration check does not establish that
any particular APK fits. Failures before the bridge can report a typed result
and upstream errors from other operations retain their existing diagnostics;
error text alone does not establish memory exhaustion.
Independent REA instances have independent queues. Whole
operations have a **120-second** execution deadline by default, starting after
they reach the queue's front. For a known slow cold load, such as a large
multidex APK, select another finite deadline:
@@ -337,6 +363,14 @@ export REA_ANDROID_TEST_APK="$PWD/_reference/apk-integration/ApiDemos-debug.apk"
npm run verify:android
```
The main lane and Windows Java-selection checks validate the selected JDK and
engine archive through `validateVerifierJadxConfiguration`. This shared verifier
boundary supplies the production validator's resource owner and waits for
retained cleanup before proceeding. Failed closes retain their exact owners for
retry; prerequisite failures must not be mistaken for completed bridge tests.
Recovery checks match the typed Java or archive failure and its applicable
remediation.
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.
+81 -11
View File
@@ -8,7 +8,7 @@ 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
Use Apktool 2.7.0 or newer (verified with 2.7.0 and 3.0.3 on Linux) and a Java runtime the
launcher can find. Select the launcher through the environment:
```sh
@@ -24,6 +24,30 @@ missing launcher reports `capability_unavailable` with the
`binary_session` uses the same host probe for tool availability; it does not
validate a particular APK or guarantee that the selected input can be decoded.
Client inspection and decode results disclose the following reported-version
advisory windows without refusing otherwise compatible launchers:
| Advisory | Reported version window | Host scope |
| ----------------------------------------------------------------------------------------------------- | ------------------------------------------------ | ---------- |
| [CVE-2024-21633](https://github.com/iBotPeaches/Apktool/security/advisories/GHSA-2hqv-2xv4-5h5w) | Before 2.9.2 | All |
| [GHSA-vgwr-4w3p-xmjv](https://github.com/iBotPeaches/Apktool/security/advisories/GHSA-vgwr-4w3p-xmjv) | Before 2.9.3 | Windows |
| [CVE-2026-39973](https://github.com/iBotPeaches/Apktool/security/advisories/GHSA-m8mh-x359-vm8m) | 3.0.0 release line through versions before 3.0.2 | All |
The 2026 advisory names 3.0.1 and its 3.0.2 fix. Inclusion of 3.0.0 is
source-derived: [tagged 3.0.0](https://github.com/iBotPeaches/Apktool/blob/f770b39e425af4fa6ac4ca1e9ea6c4824339c6d3/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/ResTypeSpec.java)
passes type names through unchanged; the [3.0.2 patch](https://github.com/iBotPeaches/Apktool/commit/65dd8480dfcb63068562ffaa527f71bb0a9f772c)
validates those names at their owner before they reach the output-path producer.
Prereleases before the fixed release are conservatively disclosed; the exact
`-dirty` downstream marker is compared as a release while preserving its spelling.
This is version guidance, not verification of a particular prerelease or decoder.
A launcher version does not prove the decoder's contents, execution platform,
downstream backports, or overall safety. Windows applicability uses the selected
local host; an opaque wrapper may run another engine. A missing warning means
only that none of these version/host windows matched. Verify the selected
decoder's patches before decoding untrusted APKs; the compatibility floor above
is not a security recommendation. REA does not fetch advisories at runtime.
On Windows, a `.bat` or `.cmd` launcher (such as Chocolatey's `apktool.bat`)
runs through an explicit `cmd.exe /d /s /c` call. That call has no AutoRun,
no delayed expansion, and quotes every argument. A launcher path that
@@ -38,20 +62,36 @@ reports `capability_unavailable`.
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 --locales de --locales pt-BR
rea decode-android-resources /targets/Example.apk --locales de --locales pt-BR --string-tables-only
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.
primary `locale` (project `res/values-<locale>/strings.xml` instead of the default
table), `locales` (repeatable array of additional localized string tables to project
from the same single decode pass), and `include_strings` (default true). Regional locales such as `pt-BR`
select Android's `values-pt-rBR`. A three-digit region such as `es-419`
selects `values-b+es+419`; `es-r419` is rejected because Android's legacy
`-r` form requires a two-letter region. Android qualifiers such as `pt-rBR`
and `b+zh+Hans+CN` may also be supplied directly.
Set `string_tables_only: true` (CLI `--string-tables-only`) to return string
entries only inside `string_tables`, including when selecting a single table.
The top-level `strings` array is then empty by request; it does not establish
that the primary table is empty. Table status, counts and coverage still describe
the examined source. This avoids repeating primary entries in multi-locale
responses and charges the aggregate output budget for one copy per table.
Omitting the option preserves existing responses. `include_strings: false`
still suppresses all string projection, including in this mode.
## 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.
The Evidence subject carries the same snapshot digest and caller-selected
path, including when the original file changes during decoding.
- **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.
@@ -59,9 +99,29 @@ select Android's `values-pt-rBR`; Android qualifiers such as `pt-rBR` and
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.
unparsed rather than flattened — the limitation names the examined count.
Malformed XML and a wrong document root are whole-document projection
failures: the result is partial, the failure reason is disclosed, and entry
counts remain unknown. They are not counted as one unsupported string.
The default table is bounded to 2000 entries with partial coverage when more
exist. `locales` lists observed regular `strings.xml` tables whose exact
`values-<locale>` directory is selectable by the request's locale grammar.
Locale suffixes allow up to 23 ASCII characters, derived from Apktool's
language, script, region, and variant fields; for example,
`b+sr+Latn+RS+REVISED` selects that exact table.
Other table directories, including combined qualifiers such as
`values-en-rUS-v21` and `values-mcc310-fr`, are named in limitations with
their source spelling. They are not advertised as selectable locales;
REA does not infer Android's runtime resource matching. Non-regular
strings-table paths are disclosed with partial coverage. Discovery uses
the same bounded traversal as the file count; filesystem failures remain
failures rather than being interpreted as missing tables.
When multiple tables are requested with `locales`, `string_tables` records
each projected table with its locale, status (`present`, `missing`,
`oversized`, `malformed`, or `skipped`), entry counts, and coverage,
bounded at an aggregate budget of 10,000 strings and 32 MiB XML. When `locales`
is omitted and `string_tables_only` is not true, legacy single-table payloads are preserved
without adding `string_tables`.
- **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.
@@ -81,9 +141,11 @@ select Android's `values-pt-rBR`; Android qualifiers such as `pt-rBR` and
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.
- An ordinary nonzero decode exit surfaces as `unsupported_target` naming
the caller-selected APK, with Apktool's diagnostic and captured output.
Launcher startup, ownership preparation, signal termination and incomplete
output collection remain provider failures; they do not establish that the
selected APK is unsupported.
## Real verification
@@ -94,3 +156,11 @@ 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.
Multi-locale and table-only projection were also verified through real CLI and
stdio MCP workflows on Linux with Apktool 3.0.3/JDK 21 against NewPipe 0.29.1,
ApiDemos 6.0.18 and Appium Settings 8.2.1. Independent XML projection checks,
exact facts/Evidence parity and bounded task costs are recorded in the
[shared-decode and table-only checkpoint](../experiments/analysis-efficiency/apktool-string-tables.md).
This qualifies selected resource facts, not application execution or independent
binary resource-decoder completeness.
+18
View File
@@ -60,6 +60,15 @@ 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.
Inventoried files whose bytes were not read, such as encrypted archive members,
are listed in `unavailable_components` with their original path, format,
encryption flag, limitations, and null content identity. The same application-root
and AppleDouble attribution rules apply. These files make overall coverage
`partial`; component absence is unknown even when `inventory_complete` is true.
Directories have no file bytes and symlinks remain in `symlinks`, so neither is
an unavailable file component. The additive field participates in `projection_id`,
including when empty, so Apple projection identifiers change.
## Application roots
| Inventory root | Application root |
@@ -68,6 +77,15 @@ the supplied inventory pages, and overall coverage is `partial` in that case.
| `.app` directory | `.`, the inventoried bundle itself |
| Directory, ZIP, or DMG containing apps | Each outermost `<Name>.app` followed by `Contents/` |
File and slice occurrences supply component endpoints. Directory tree identities
remain in source inventory and bundle anatomy, and links remain in `symlinks`.
Root and layout discovery use known directories and ancestors implied by deeper
inventory paths. A leaf file or symlink named `*.app`, `Contents`, or `Versions`
does not establish that directory. Directory and authenticated-file identity are
selected before applying anatomy case preferences, so a file cannot shadow a
folded directory name or a directory shadow a metadata/signature file.
ZIP archives made with `ditto -c -k --keepParent` report `<Name>.app`. A DMG
reports `<image>.dmg/<Volume>/<Name>.app`; DMG child inventory needs the native
macOS mounting adapter. When a DMG has only its root identity, the projection is
+3 -3
View File
@@ -1,8 +1,8 @@
graph TD
subgraph "Entry Points"
CLI["src/cli.ts + src/cli/<br/>One-shot CLI adapter<br/>setup, diagnostics, analysis, decompilation"]
MAIN["src/main.ts + src/main/<br/>MCP stdio server adapter<br/>config, session, process lifetime"]
DISPATCH["scripts/rea.mjs<br/>Executable dispatcher<br/>routes mcp / one-shot"]
MAIN["src/main.ts + src/main/<br/>MCP server adapter: stdio default, streamable HTTP opt-in<br/>config, session, process lifetime"]
DISPATCH["scripts/rea.mjs<br/>Executable dispatcher<br/>routes mcp / mcp --http / one-shot"]
end
subgraph "Production Composition"
@@ -10,7 +10,7 @@ graph TD
end
subgraph "Adapters"
SERVER["src/server/<br/>MCP request translation<br/>createServer, tool registration, toolResult"]
SERVER["src/server/<br/>MCP request translation<br/>createServer, tool registration, toolResult<br/>http/: streamable HTTP listener and node:http bridge"]
HOPPER_BRIDGE["bridge/hopper_bridge.py<br/>Runs inside Hopper<br/>adapts operations to Hopper Python API"]
GHIDRA_BRIDGE["bridge/ghidra/ReaGhidraBridge.java<br/>Packaged HeadlessScript<br/>inventory, decompiler, references, CFG"]
INSTALL["src/cli/ + src/application/Setup*<br/>Host installation adapters<br/>macOS: verified vendor DMG to ~/Applications<br/>Linux: verified vendor package + apt/dnf/pacman"]
+6 -1
View File
@@ -160,7 +160,12 @@ launch builder. It is a configuration fact, not measured memory use or proof of
the effective JVM limit; JVM environment options may affect that limit.
When a Windows script wrapper selects the JVM, this value remains unknown.
Historical stdout and stderr remain available, but classification uses only the
failing operation's `failure_output`. Output draining waits at most one second,
failing operation's `failure_output`. Retained stdout and stderr share an 8 MiB
budget, but every drained byte is scanned for `java.lang.OutOfMemoryError`:
`failure_output.observed_oome` records the latest confirmed token's bounded line per stream from
the failing operation, with its byte offset, even after the budget is spent. These observations own OOME detection; retained text that ends at a class-name prefix cannot confirm a complete token. `line_complete` distinguishes a known line end from an incomplete trailing context; `invalid_utf8` marks replacement-decoded context.
Incomplete operation output without an observed OOME keeps the original failure code and explains that a memory cause cannot be ruled out. Incompleteness alone does not confirm a memory constraint or justify heap-specific advice. Token context stays within the failing operation's checkpoint; a class-name prefix in a different identifier is not OOME evidence. A trailing bare token requires an observed stream EOF to establish its boundary.
Output draining waits at most one second,
subject to earlier cancellation or the startup deadline. `output_incomplete`
marks a snapshot taken before stream closure; cleanup ownership remains with
the session until release succeeds.
+42
View File
@@ -285,6 +285,14 @@ REA establishes a main-frame origin boundary before enabling Runtime, Debugger,
## Data minimization
The Link projection parses repeated CDP header field lines independently and
retains their declarations in order, including derived untrusted agent hints.
Commas inside URI targets or quoted parameters remain part of those values.
COOP and COEP projections retain the exact declared token after validating the
complete Structured Field Item, including parameters such as `report-to`.
These are declarations, not an assessment of the document's effective policy;
absent, malformed or non-token items project as `null`.
REA retains local observation data and removes only URL userinfo credentials, explicitly declared scenario secrets, and values from structured credential/storage fields:
- URL observations preserve the complete local URL, including query values, fragments, duplicate parameters, and their order. Only username/password userinfo is removed; malformed original URL strings remain available with `origin: null`.
@@ -342,6 +350,40 @@ validation and resource bounds. Omitted script metadata makes its affected
section explicitly truncated.
Disallowed-origin entries are filtered before retention.
Selected script-source collection shares a 32 MiB aggregate UTF-8 retention
budget and a 20-second deadline across the capture. An oversized source is
omitted while later smaller sources may still fit. When the deadline expires,
remaining source reads are skipped. Script metadata, per-item omission reasons,
and `script_sources` completeness remain available. A single CDP response can
still be materialized up to the separate 64 MiB transport limit before source
admission; the retention budget does not bound that transient allocation.
Bundle parsing and semantic inspection run sequentially in an owned child,
without executing captured code. `max_heap_mb` defaults to 1024 MiB V8
old-space; `analysis_timeout_ms` defaults to 30000 per script, including startup
and transfer. A failed or timed-out script becomes an explicit unknown while
completed findings and later scripts remain available. `total_analysis_timeout_ms`
defaults to 300000 across script analysis; expiry returns a typed timeout with
partial Evidence and identifies unstarted scripts. These controls are also
available as CLI flags with hyphenated names. Capture and optional source-map
fetching have separate budgets.
One web-bundle capture/analysis is admitted per REA process at a time. Completed
script results share an 8 MiB serialized transfer budget, with host heap
reservation checked before decoding and validating another result.
Exhausted result capacity stops further script launches and returns a typed
resource failure with completed facts and explicit unstarted-script unknowns.
Worker control frames are limited to 64 KiB. Cleanup must confirm child termination
before releasing its private files; failed cleanup retains its exact owner and
blocks replacement until retry succeeds. Cancellation retains completed bundle
facts, including cancellation during final cleanup.
The worker heap setting is not a process-family RSS limit. Node enforces V8
old-space flags; Bun ignores them. Windows Bun instead uses an owned process
commit limit with a 512 MiB runtime reserve; other Bun hosts have no enforced
memory limit. These bounds do not establish an aggregate host-memory limit
across other REA operations or external processes.
Resource-tree inventories distinguish a valid empty `resources` array from a
missing or malformed collection. Invalid resource entries are omitted with
incomplete coverage, while valid resources from that frame and other frames
+12
View File
@@ -144,6 +144,18 @@ distinction: it closes and deletes provider-owned profiles, but only disconnects
from an external CDP browser. Real-browser verification checks both outcomes and
confirms that an attached external browser remains alive.
That cleanup requires REA to remain running. Abrupt termination, including
Windows process-tree termination or POSIX `SIGKILL`, can leave the launch
profile and Playwright artifacts behind. A profile can retain cookies, history,
cache and origin storage. Later REA runs currently do not reclaim these paths.
Playwright 1.58.2 can also leave an artifacts directory when launch preparation
fails before a browser process exists, such as for a missing executable.
POSIX wrappers can request awaited cancellation with `SIGINT` or `SIGTERM`;
Windows process termination is not an equivalent graceful-cancellation channel.
Do not identify owned artifacts by directory prefix or creation time alone.
See [#4659](https://github.com/morluto/rea/issues/4659) for the remaining recovery
and wrapper-cancellation work.
Keeping that browser alive does not guarantee its emulation state survives.
Chromium can clear caller-owned `navigator.platform` emulation when a page CDP
session disconnects, including sessions that sent no emulation commands. REA
+32
View File
@@ -286,6 +286,12 @@ reported separately as configured-secret exclusions.
Re-import saved graphs whose pattern-based exclusions lack `pattern` before
using them in source-to-bundle comparisons.
Entries that change during an import retain an unavailable-entry diagnostic
alongside readable siblings. If enumeration of an already admitted root fails,
the graph keeps its observed children and records the root failure as a
top-level limitation. That partial inventory does not establish absence among
unexamined children.
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.
@@ -310,6 +316,28 @@ Choose the guide for the target and intended interaction:
Runtime requests name the target and actions. Launched targets run with your
user permissions; consult the chosen guide for host requirements and effects.
## Serve MCP over streamable HTTP
`rea mcp` speaks stdio to the client that launched it. To serve the same MCP
catalog over streamable HTTP for one local client, such as an agent environment
runtime, start the dispatcher entry with `--http`:
```sh
rea mcp --http --port 8765
```
`--host` and `--port` default to `MCP_HOST` and `MCP_PORT` from the environment,
then to `127.0.0.1` and an ephemeral port. The bound URL is written to stderr as
one JSON log line (`"msg":"MCP transport listening"`) whatever `REA_LOG_LEVEL`
is set to; nothing is written to stdout. `rea mcp --http --help` lists the accepted options. The listener serves
one client at a time: a session ends with the client's `DELETE`, and a client
that connects while another session is open takes it over, so a client that
exited without ending its session needs no restart. The listener runs until
SIGINT or SIGTERM and does not stop when stdin closes. See
[transports](mcp-contracts.md#transports) for the session, `Host` header and
shutdown contract. Client registrations written by setup and the MCP registry
entry keep stdio.
## Output and exit status
`rea mcp doctor --json` checks production MCP startup and reports child logs in
@@ -344,6 +372,10 @@ output formatting.
| `1` | The operation could not complete. Structured output identifies invalid input, permissions, cancellation, timeouts or another failure when available. |
| `128 + N` | Signal-derived status. An unhandled signal may have ended the process, with the shell or runtime preserving the conventional status; a command may instead have handled the signal, waited for its operation and cleanup to settle, and assigned the same status (`130` for SIGINT, `143` for SIGTERM). In the handled case, it may also have printed a structured `cancelled` result. |
`rea mcp --http` is long-running and prints no structured result. It exits
`130` on SIGINT or `143` on SIGTERM after closing the listener, the session and
its providers, and `1` when that cleanup fails.
A `cancelled` result does not by itself determine the exit status; it depends on
the command's signal handling. Commands routed through the shared
`withCommandCancellation` handler in the CLI set status `130` for SIGINT or
+3 -1
View File
@@ -457,7 +457,9 @@ 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
after verification unless fixture retention is requested. Cleanup attempts the
remaining run tree even if auth removal fails, and reports unresolved cleanup
together with the original verification failure. 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
+40 -5
View File
@@ -33,6 +33,12 @@ encoded path separators, ASAR directories or links, and nonexistent paths are
rejected. The endpoint exposes every eligible target and its local path
metadata.
Cancellation stops further file authorization after an already-started filesystem
operation settles. ASAR descriptor-close failures remain typed incomplete cleanup
with an exact retryable owner; they are not treated as a missing or unauthorized
page. A later authorization and provider shutdown retry retained descriptors
before reporting their release.
## Workflow
`list_electron_targets` returns every eligible target served by the supplied endpoint in one inline array.
@@ -56,12 +62,24 @@ rea inspect-electron-page http://127.0.0.1:9223 TARGET_ID \
The normalized result contains canonical local paths, frame and DOM
structure, resource metadata, stable script/resource identities, explicit
completeness, and content-addressed script artifacts. Script metadata
retains its execution-context frame ID when CDP supplies one. The capture also
completeness, and content-addressed script artifacts. Resource sizes are unknown
when omitted or invalid; supplied invalid sizes also produce an explicit
completeness diagnostic.
DOM node indices retain their snapshot positions. Invalid rows are omitted with
completeness diagnostics, so `total_nodes` can exceed the retained node count
and a parent index can refer to an omitted source node.
Script metadata retains its execution-context frame ID when CDP supplies one. The capture also
inventories worker, service-worker, and shared-worker targets with
validated opener-target and parent-frame IDs. Worker discovery uses passive
target metadata; REA does not attach to or execute code in those targets.
Collection counts and aggregate script-source bytes are not capped. Like every
Script-source collection retains at most 32 MiB of UTF-8 text across scripts
and shares a 20-second collection deadline. Omitted sources retain their script
metadata and an explicit reason; later smaller sources may still fit after an
oversized source is omitted. The separate 64 MiB CDP response limit bounds one
wire message before retention admission, rather than total transient memory.
The source budget adds no script-count cap. Like every
target, frame, script, and resource, a worker URL must resolve to a local
file before it is retained. Relationship IDs improve
attribution but do not prove which static module started a worker or that its
@@ -186,8 +204,25 @@ Caller-defined `.listener` properties can change the identity exposed by
wrapper recognition. Re-registering a raw recording wrapper on another channel
retains the original registration's channel attribution.
Mutating `.listener` on a raw recording wrapper can also prevent removal through
application decorators; the reproduced identity conflict is tracked in
[#4513](https://github.com/morluto/rea/issues/4513).
application decorators that bypass the hook's removal methods. When a removal
request reaches the hook's methods and its registration order is known, private
callback ownership preserves removal by the original function and the newest
matching registration when public metadata is changed or deleted. Native removal
still determines getter execution, exceptions and removal meta-events.
If registration or removal methods differ from the Node methods captured at hook
initialization, the hook leaves listener callbacks unwrapped and records a
`listener-registration` observation gap. The application keeps its original
callback and receiver; callback execution remains unobserved. This comparison
assumes Node's EventEmitter prototype has not itself been globally decorated
before hook initialization. The provider loads the hook before the application
and excludes `NODE_OPTIONS` from the child environment.
An opaque later listener or unsupported emitter state can prevent proof of
removal order. The hook then delegates removal
to the native method and records a `listener-removal` gap rather than claiming
which registration was removed. These gaps are distinct from dropped records
and do not establish IPC delivery or successful removal.
### Target fuse prerequisites
+3 -1
View File
@@ -23,7 +23,9 @@ rea inspect-dart-aot /targets/Example.apk --abi armeabi-v7a
The equivalent MCP methods are `identify_flutter_build` (with `path`) and
`inspect_dart_aot` (with `path` and an optional `abi`; the default prefers
arm64-v8a, then x86_64, then x86, then armeabi-v7a, then the remaining
ABIs alphabetically).
ABIs alphabetically). An explicit `abi` is the directory label exactly as
`identify_flutter_build` reports it, so a payload under a nonstandard label
stays selectable and keeps that label in the result.
## Optional retained AOT delivery
+1 -1
View File
@@ -8,6 +8,6 @@ MCP exposes `list_frida_devices`, `list_frida_processes`, `start_frida_session`,
Failed startup cleanup retains acquired Frida handles, including a paused spawn that has not attached, for later cleanup retries. Its remote connection stays leased until session detach and target resume complete. CLI commands await provider cleanup before returning; MCP retains these resources for cleanup when its server closes. Server shutdown stops admitting new Frida operations and waits for admitted startup, discovery, and queued work before releasing their resources. A failed cleanup remains reported and can be retried by closing the server again, rather than treating an unregistered session as fully released.
Frida scripts execute inside the selected target with that process's memory, filesystem, and network authority. Message capture is bounded to 16 MiB and reports truncation. Script source is not stored in Evidence; its selected path and SHA-256 digest are. Evidence retains non-authentication target selection such as device or endpoint, mode, program or PID, and spawn arguments. Authentication values remain excluded. Results report the observed session and messages, while unsupported platform metadata remains unknown. A request cancelled before a Frida operation starts has no provider effects. If cancellation arrives during a native Frida call, REA waits for that call to return, then closes any session it created and returns the observed session as a partial observation. A cancelled script load on an existing session releases only its new script before queued operations can run; the session and previously loaded scripts remain available. Once the provider commits a successful load, later request cancellation does not unload that script; use `unload_frida_script` to release it. If script cleanup fails, the script remains owned and a paused target cannot resume until the pending instrumentation is released. Queued script loads, resumes, and unloads check cancellation before dispatching native effects. Cancellation Evidence separately reports whether a target resume was observed, whether instrumentation cleanup completed, and that final target liveness remains unknown. REA does not kill the target. Remote discovery retains its observations and reports a separate cleanup error if the temporary connection cannot be removed.
Frida scripts execute inside the selected target with that process's memory, filesystem, and network authority. Message capture is bounded to 16 MiB and reports truncation. Script source is not stored in Evidence; its selected path and SHA-256 digest are. For a file, `source_sha256` identifies the original selected bytes. Invalid UTF-8 continues to use replacement decoding; Evidence then records that limitation and `raw_result.source_representation` with the encoding, decoding mode, and `loaded_source_sha256` of the UTF-8 string passed to Frida. Valid UTF-8 files and inline scripts do not need this additional representation fact. Evidence retains non-authentication target selection such as device or endpoint, mode, program or PID, and spawn arguments. Authentication values remain excluded. Results report the observed session and messages, while unsupported platform metadata remains unknown. A request cancelled before a Frida operation starts has no provider effects. If cancellation arrives during a native Frida call, REA waits for that call to return, then closes any session it created and returns the observed session as a partial observation. A cancelled script load on an existing session releases only its new script before queued operations can run; the session and previously loaded scripts remain available. If cancellation is observed when the native call returns, partial Evidence retains the source identity and captured messages even if that call rejects, including messages emitted during awaited cleanup. The caller's cancellation reason remains primary and a native rejection is retained as a sanitized diagnostic. A failure already observed before cleanup stays primary if cancellation arrives during cleanup. The cancellation cutoff is REA's observation of native completion, rather than a claim about unobservable native event order. `script_id` is REA's load-attempt identity. When creation rejects without returning a handle, `script_cleanup: "no_handle"` means REA acquired no handle to unload; it does not prove that the engine performed no work. Once the provider commits a successful load, later request cancellation does not unload that script; use `unload_frida_script` to release it. If script cleanup fails, the script remains owned and a paused target cannot resume until the pending instrumentation is released. Queued script loads, resumes, and unloads check cancellation before dispatching native effects. Cancellation Evidence separately reports whether a target resume was observed, whether instrumentation cleanup completed, and that final target liveness remains unknown. REA does not kill the target. Remote discovery retains its observations and reports a separate cleanup error if the temporary connection cannot be removed.
The [Frida Core API](https://frida.re/docs/frida-core-api/) documents device management, sessions, and script loading; the [JavaScript API](https://frida.re/docs/javascript-api/) documents target-side instrumentation. [Luma](https://luma.frida.re/) is Frida's standalone GUI; REA does not automate or control it. `npm run verify:frida` requires a Linux host with the optional Frida binding and uses a short-lived local Node.js fixture created by the verifier. Add `-- --address HOST:PORT --pid PID` to run the separate remote attach lane against a caller-selected target. Mock tests do not establish real device/server compatibility.
+8
View File
@@ -124,6 +124,10 @@ FileBytes digests, every source mapping and its memory digest, relocation record
module partitions, relocation fixups and linear coordinates rather than relying
on the imported executable SHA alone.
Expected DOS relocation records retain each fixup's pre-application bytes and
applied value. Their memory-byte windows come from the final relocated image,
including changes made by later overlapping fixups.
The result is `verified`, `mismatch`, or `unsupported`. Every check retains its
expected and observed values. A memory-digest mismatch identifies the source
range's file offset and analysis address; it does not locate the first differing
@@ -134,6 +138,10 @@ their contents and DOS runtime semantics are not verified. Independent verificat
also covers explicit [raw-binary imports](raw-binary.md); other formats return
`unsupported` with measured observations.
MZ verification retains the initialized image described by the header's page
count and streams appended overlay bytes into the complete original and modified
source digests. Overlay size does not increase the retained image allocation.
`read_bytes` returns initialized provider memory, including loader fixups; an
unmapped or uninitialized byte ends the read with an explicit returned length and
`complete: false`. `address_to_file_offset` uses the provider's source mapping;
+8
View File
@@ -65,6 +65,14 @@ PDB, or change analyzer settings.
## Loaded addresses and file offsets
Ghidra computes overview procedure and string counts from the same inventories
used by `list_procedures` and `list_strings`, without transporting those rows
solely to count them. Counts include external functions and only Ghidra-defined
strings; they do not establish discovery of unidentified functions or undefined
string bytes. Complete inventories remain available through the list tools.
Overview reuse follows the target/profile snapshot lifetime and is invalidated
by session metadata edits.
`rea analyze <path> --provider ghidra --json` and MCP `binary_overview` report
the observed loaded `image_base` in `normalized_result`. They retain each
segment's reported `image_base` and `address_space`. A provider that does not
+6
View File
@@ -45,6 +45,12 @@ The MCP tool `project_harmony_application_graph` takes the same
- path-based N-API bridge hypotheses between bytecode and `libs/<abi>` native
libraries
File and slice occurrences supply component and child-package paths; directory
trees and symlinks retain their identities in the source inventory without
being classified as code files. Ark and JavaScript runtime hints summarize the
classified bytecode and JavaScript lists; supported source extensions share the
same classification rule as their component rows.
Every claim is path-presence only. Manifest semantics (module identity,
abilities, entry points, permissions, dependencies), Ark bytecode contents and
versions, resource resolution, signing verification, and observed native
+1 -1
View File
@@ -41,7 +41,7 @@ rea function /absolute/path/to/program main --json
rea decompile /absolute/path/to/program main --json
```
Open the **original input binary** in REA, not an `.idb` or `.i64` database. Its SHA-256 must match IDA's recorded input hash. REA checks the attached identity and image base around each analysis request. A mismatch or target switch fails with recovery guidance. The original input must remain readable by REA; WSL can use its mounted alias while the GUI runs on Windows.
Open the **original input binary** in REA, not an `.idb` or `.i64` database. Its SHA-256 must match IDA's recorded input hash. REA checks the attached identity and image base around each analysis request. A mismatch or target switch fails with recovery guidance. The original input must remain readable by REA; WSL can use its mounted alias while the GUI runs on Windows. Attached profiles, including native mode, refuse universal Mach-O inputs at admission: every slice shares the recorded whole-file hash, so REA cannot verify which slice the GUI loaded. Open a thin file extracted with `lipo -thin` in both IDA and REA, or use headless mode, which analyzes the selected slice.
REA's close operation releases its MCP connection or proxy. It never saves or closes the existing GUI database. External edits remain visible because results are live and are not replayed from snapshots. These checks do not lock the GUI or prove that the database is unpatched.
+73 -6
View File
@@ -57,14 +57,26 @@ Before applying changes, REA checks your current configuration. The plan lists:
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 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.
create backups, stage changes in a private directory, and verify their result.
Before publication, they refuse detected changes to the selected configuration.
Replacement uses an explicit destination under the selected canonical parent;
it does not follow a newly inserted destination symlink. First-run setup uses
an exclusive hard link and fails without overwriting a newly created destination;
filesystems without hard-link support cannot publish a first-run configuration.
Setup and uninstall retain an existing `.rea.backup` rather than replacing the
first snapshot.
If that snapshot differs from the current configuration, setup and uninstall
preserve a verified `.rea.backup.<sha256>.recovery` copy of the current bytes
before editing; setup also previews it. Both snapshots remain available.
When an edit made a backup, a failed uninstall update or restore, and a failed
setup readback or rollback, name the backup path that holds the bytes from just
before that edit.
If setup cannot verify a newly created configuration, it retains the file and
reports manual recovery instead of deleting a pathname that may have changed.
For an existing configuration, setup and uninstall recovery refuse a detected
replacement or edit and name the recovery backup. Quit clients before editing their configuration;
these checks do not lock out another writer modifying the same file in place,
or exclude pathname changes between the final check and publication.
Setup also retains valid environment overrides in REA's existing server entry,
such as `REA_MCP_INPUT_SCHEMA_PROFILE`, `REA_MCP_OUTPUT_SCHEMA_PROFILE`, and
`REA_MCP_MAX_RESPONSE_BYTES`.
@@ -264,14 +276,14 @@ Register with the variable unset:
<!-- x-release-please-start-version -->
```bash
claude mcp add --scope local rea -- npx -y rea-agents@6.5.0 mcp
claude mcp add --scope local rea -- npx -y rea-agents@6.7.0 mcp
```
On native Windows, use the same project directory and wrap the package-runner
shim so the stdio client can launch it:
```powershell
claude mcp add --scope local rea -- cmd.exe /d /c npx -y rea-agents@6.5.0 mcp
claude mcp add --scope local rea -- cmd.exe /d /c npx -y rea-agents@6.7.0 mcp
```
<!-- x-release-please-end -->
@@ -364,7 +376,17 @@ Uninstall preserves Hopper, Node.js, Evidence files, captures, unrelated skills
and other MCP servers. Purging removes only REA's cache and state under
`~/.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
while being updated stops the remaining removals. Uninstall reports each
candidate `configuration_path` with its outcome. A client with multiple files
keeps their individual `actions` alongside its aggregate status and detail,
including earlier removals when a later file fails. The paths name
the discovered configuration candidates, not resolved physical file identities.
For JSON clients, uninstall removes every repeated `rea` member in the effective
server table only when each registration is REA-owned. An unowned earlier
member, or an unowned OpenCode V1 entry that removing V2 would expose, stops
preflight before any
removal. Repeats inside an inactive earlier copy of the server table stay
unchanged. 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.
@@ -587,6 +609,20 @@ 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.
Hopper also embeds Python; the Python executable and standard library alone
are insufficient on Ubuntu. Approved setup checks the system interpreter
at `/usr/bin/python3` and, when necessary, installs its matching
`libpython3.X` package, then verifies that its shared library can load.
APT resolves the concrete package (for example, `libpython3.12t64` on Ubuntu
24.04). Doctor includes these fresh observations in the `embedded_python`
details of its `hopper-demo-runtime` check, alongside the private-display
diagnostic. Failed inspections remain unknown rather than proving a library
absent. Run `rea setup --yes --install-hopper` to repair a supported install.
This prerequisite check does not launch the bridge or validate a custom Python
interpreter configured inside Hopper; that interpreter needs its own matching
shared runtime. Custom installation prefixes or shared-library ABIs require
manual dependency repair.
When the package-manager step fails, setup reports the failing command and its
captured output, so a package conflict is distinguishable from an authorization
failure. On CachyOS, an unversioned compatibility package such as
@@ -901,6 +937,12 @@ Properties format limit. Reads preserve Ghidra's Latin-1 byte mapping and check
the descriptor and selected name for changes. Permission failures and resource
refusals remain explicit; failed descriptor cleanup must succeed before that
owner admits another inspection.
Native decompiler compatibility inspection follows the selected executable symlink
and reads at most the first 4096 bytes through the same descriptor owner. It
checks the full extent and selected name for changes without reading the remainder.
An unreadable or unrecognized header leaves compatibility unknown; diagnostics
retain read failures. Cancellation and incomplete cleanup propagate as failures,
and failed cleanup retains the exact descriptor for retry.
This coordinate selects only REA's session-private configuration directory, not
the installation or an existing user configuration directory.
@@ -919,6 +961,10 @@ 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.
Startup preserves an observed launch failure when cancellation arrives during
rollback. Producer cancellation retains the caller's exact reason separately
from LaunchSupport warnings and cleanup failures. Failed rollback keeps the
original process owner for a later cleanup retry.
The experimental Windows transport uses authenticated IPv4 loopback with a
private native-owned bearer descriptor and Job Object process ownership.
@@ -1014,6 +1060,8 @@ export REA_GHIDRA_COMPILER_SPEC_ID="borlandcpp" # optional; requires a languag
REA passes `-processor`/`-cspec`, checks both against the installation's `.ldefs`, and records them in the analysis profile. DOS imports reject an override.
Language definitions must be well-formed XML encoded as UTF-8 or BOM-marked UTF-16, with any encoding declaration matching the bytes. Literal Unicode replacement characters (U+FFFD) are accepted; malformed source bytes are rejected.
To seed code that auto-analysis cannot reach (computed jumps, pointers in data):
```bash
@@ -1113,6 +1161,10 @@ compiler remains distinguishable from a compiler that exited with an error.
The helper compile deadline defaults to 120,000 ms; set
`REA_SWIFTC_COMPILE_TIMEOUT_MS` to an integer between 1 and 2,147,483,647 when
a busy host needs longer.
On macOS, the Java prerequisite probe waits for this independently bounded
preparation before starting its five-second command deadline. Caller cancellation
still interrupts preparation, and failed helper cleanup remains owned for retry.
Linux process-table preparation remains inside the command deadline.
Other rejection values retain their primitive value or an explicit type.
Shutdown warnings include the failure
kind, message, and diagnostics, while process and temporary-project cleanup
@@ -1159,7 +1211,7 @@ For a client that requires manual configuration, use:
"mcpServers": {
"rea": {
"command": "npx",
"args": ["-y", "rea-agents@6.5.0", "mcp"]
"args": ["-y", "rea-agents@6.7.0", "mcp"]
}
}
}
@@ -1224,6 +1276,21 @@ on the shell `PATH`. Use the setup command above for the guided setup
journey, `npx -y rea-agents@latest` for unattended one-off commands, or install globally
with `npm install --global rea-agents` for a shell-visible `rea` command.
For many concurrent agent sessions, run setup directly from a global installation
to avoid keeping a separate npm launcher process for each MCP connection:
```bash
npm install --global rea-agents
rea setup
```
Review the plan, approve the selected client changes, then restart those clients.
This registers the installed entrypoint directly; installing the global package
alone does not replace existing `npx` registrations. Each client still has its own
REA process and analysis state. Direct registrations follow the installed CLI;
use `rea update` to update it. Running setup through `npx` again selects the pinned
package-runner command. Do not register paths inside npm's temporary package cache.
The optional curl wrapper installs only the global npm package:
```bash
+32
View File
@@ -195,6 +195,17 @@ earlier read or captured alias. Unproved ordering across branches or function
activations remains conservative. Returned-reference effects use the same
read-position facts as call resolution.
Returned-reference effects share one property-projection state per source read.
When several paths reach that read, differing keys at the same depth become
wildcards; differing depths become an unknown-depth selection. This retains a
conservative superset of the represented local targets rather than enumerating
every alias history or dropping paths at a query cap. It can add possible effects,
including for finite projection cycles. Static limitations disclose this loss of
precision; semantic graphs retain `dynamic-property` unknowns at the affected
callee coordinates, and captured web bundles identify the affected script keys.
These candidates do not prove runtime calls or mutations. Existing source-worker
and result-admission limits still apply.
Mutation tracking covers explicit member assignments, updates, deletion, and
loop assignment targets, including the supported local aliases and shared
nested references. Calls conservatively invalidate exposed mutable references;
@@ -288,6 +299,27 @@ and the result includes its basis, candidates, changed dimensions, Evidence
links, limitations, and a `changed_from` graph containing all compared nodes,
their observations, and relationships.
A matched pair whose only differing dimension is `location` counts as
`unchanged` when both input graphs have complete coverage and its neighboring
relationship identities are resolved. This includes an
identical module shifted by an earlier bundle edit and a named IPC channel
observed at a new offset. The item still reports `dimensions: ["location"]`
and both node IDs; the graph retains both original observations and coordinates.
Content, property, and complete relationship differences still count as
`changed`. With incomplete coverage, relocation alone remains `unknown` and
retains the location and coverage dimensions. Matching confidence is unchanged:
an inferred pair is not promoted to exact identity by this classification.
Complete inventory does not resolve ambiguous or unmatched relationship targets.
A matched module with identical bytes can therefore remain `unknown` when a
neighbor, including its containing chunk, has no cross-version match. The item
retains its exact content match, coordinates, candidate inventory, and an explicit
relationship-identity limitation. `coverage` is added to its dimensions only for
incomplete inventory. Definite content, property, or complete topology differences
remain `changed` while retaining any separate relationship uncertainty.
An unknown item with no observed content, property, or relationship difference
does not emit a `changed_from` edge; its pairing and uncertainty remain in the item.
One-sided absence is `added` or `removed` only when the opposite input graph has
complete coverage. With partial, unavailable, or truncated input, the same
condition is `unknown`. The comparison retains every classified item and
@@ -50,6 +50,12 @@ The equivalent MCP input is:
`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`.
Evidence parameters retain the caller-selected `input_path`, including a
symlink alias. Both CLI routes anchor relative inputs to their working
directory without resolving symlinks. The subject and normalized result use
the resolved path for artifact identity; the selected path remains a separate
request fact. Older Evidence can omit this parameter; retained records are
validated without resolving their paths against the live filesystem.
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
@@ -586,6 +592,21 @@ not bypass worker heap, execution deadline or parent result admission. Truncated
coverage reports both effective node ceilings; omitted relationships remain
unknown.
Unknown records have independent defaults of 100000 across the application and
20000 per source. Select `max_semantic_unknowns` and
`max_semantic_unknowns_per_file` (CLI: `--max-semantic-unknowns` and
`--max-semantic-unknowns-per-file`), each from 1 to 1000000. The parent offers the
remaining capacity to the worker, and rejects excess records before adoption.
Unknown admission happens before canonical identity and provenance construction.
When capacity is exhausted, coverage is partial and truncated and names both
effective unknown ceilings. `coverage.omitted_unknown_occurrences` counts examined
emission occurrences by family and reason, including repeated emissions. It does
not claim distinct discarded identities or count frontiers in unexamined source.
Omitted unknown provenance and IDs are not retained. Existing source, node,
execution and memory limits continue to determine examined coverage. Raising only
a node capacity does not raise the unknown capacity. Graphs without unknown
omissions omit this optional coverage field, preserving their existing identities.
While sources remain, the sequential worker reserves one next compact static
checkpoint at its 8 MiB bound with the same 6x retention expansion used at
admission. Earlier checkpoints are already charged to retained bytes; the
+5 -2
View File
@@ -133,8 +133,11 @@ Each operation uses one worker, a 1 GiB address-space ceiling and a 120-second
deadline; it accepts up to 64 MiB of total input across all selected files and
128 MiB/10000 entries of staged
output, with 8 MiB per diagnostic/report stream. Exceeding a limit is an explicit
failure with rollback. These limits apply per operation and do not claim aggregate
host containment across concurrent callers.
failure with rollback. Selected inputs beyond the total input allowance return a
non-retryable `resource_constraint` with `resource: "file-size"` and
`reported_limits.maximum_input_bytes`/`remaining_input_bytes`; input that is not
valid UTF-8 is an `invalid_format` request issue. These limits apply per
operation and do not claim aggregate host containment across concurrent callers.
See [testing.md](testing.md#javascript-source-recovery) for the focused real
Wakaru CLI/MCP lane and its source-owned compiler fixtures. Other host platforms
+12 -1
View File
@@ -109,7 +109,9 @@ The direct observations are:
- `Runtime.executionContextCreated`,
`Runtime.executionContextDestroyed`, and
`Runtime.executionContextsCleared`, establishing context lifecycle within
the capture window.
the capture window. A created or destroyed event whose context ID is
missing or not a safe integer adds no context record; it is retained only
as a count reported in `unknowns`.
The Inspector protocol does not directly expose require/import caller edges,
EventEmitter emissions or listener invocation, Electron IPC messages or
@@ -150,6 +152,15 @@ and uncollected scripts, but scripts collected before attachment may be
missing. Absence from the observation window never proves that a script or
behavior does not occur.
Cancellation stops new target-file authorization after the current filesystem
operation settles. Cancellation diagnostics retain the examined target prefix;
unexamined targets remain unknown. Observation cancellation keeps its original
reason and any completed Evidence. Finalization waits for REA's bounded socket
close (up to two seconds for graceful and forced confirmation). A failed close
retains its exact transport owner and blocks replacement connections until
cleanup succeeds; CLI finalization and MCP shutdown also retry retained cleanup.
Closing REA's connection does not stop the caller-owned runtime.
## Static correlation
Pass the resulting observation Evidence and an
+14 -4
View File
@@ -8,7 +8,16 @@ 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.
- Headless, the official Linux CE build `5.48.0.202610071539` supports `-c --mcp`. From the JEB installation directory, select JDK 21 or newer through `JAVA_HOME`, choose your target and bind explicitly to loopback:
```sh
"$JAVA_HOME/bin/java" -jar bin/app/jeb.jar -c --mcp --interface=127.0.0.1 \
--port=8425 --infile=/absolute/path/to/target
```
Complete the vendor's first-use EULA and license-key activation when prompted. The Linux audit used an isolated installation, a 1536 MiB Java heap and one active processor inside a separately bounded process family; JVM heap limits alone do not bound the whole family.
- JEB's documented programmatic route (`JebMcpServerInstance` from the JEB API) remains an alternative. The earlier licensed 5.48 headless verification used that route because its CLI did not accept `--mcp`. Check your installed build's `-c --help` and live tool catalog; the version number alone does not establish the launcher options or supported operations.
For setup registration, set `REA_JEB_MCP_URL` in the REA process environment
before running `rea setup`. The approved setup plan preserves the exact selected
@@ -31,7 +40,7 @@ or establish one end-to-end deadline across a whole CLI or MCP operation. A
request that reaches its budget returns a typed timeout, while caller
cancellation remains a cancellation.
Verified against JEB 5.48.0 (Linux x64, licensed build) serving `jeb-mcp-server` 1.3.0 over streamable HTTP.
Earlier verification used JEB 5.48.0 (Linux x64, licensed build) serving `jeb-mcp-server` 1.3.0 over streamable HTTP. The official Linux x64 CE build `5.48.0.202610071539` was also verified through real CLI and production stdio MCP native-code workflows; see the [Linux CE audit](../experiments/analysis-efficiency/jeb-linux-native.md) for measurements and limits. CE verification does not establish licensed/Demo Android decompilation or GUI behavior.
## Operations
@@ -42,15 +51,16 @@ Verified against JEB 5.48.0 (Linux x64, licensed build) serving `jeb-mcp-server`
| `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.
All four preserve target-file bytes. `open_jeb_project` selects or creates an engine-side project; analysis queries can populate computed analysis within it. Evidence records the endpoint, caller-selected parameters, and available 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.
**Engine coverage note:** The earlier licensed 5.48.0 headless verification did not advertise `open_project`; it selected the target when the engine client started. For that build, use `--infile` on the programmatic launcher or open the file in the GUI. The audited CE headless catalog also omitted `open_project`; the verified CLI route above selects its input at startup. Use `binary_session` to inspect the current engine's advertised operations. REA preserves an unavailable tool's refusal; `open_jeb_project` requires an engine that advertises `open_project`. The CE audit does not establish GUI project-opening support.
## 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.
- `item_address` is a JEB code-item reference, such as a value returned by the engine's `list_code_items`. Preserve that representation and select its code unit explicitly. For the audited CE SQLite unit, the exported method reference was `sqlite3_libversion_number`; using its raw ELF symbol address did not produce a successful decompilation. File offsets, ELF virtual addresses and engine item references have different semantics. REA currently exposes unit listing, while code-item discovery remains an upstream JEB operation.
- Engine refusals (`success: false` envelopes) are preserved as unsupported-target errors carrying the engine's own message, for example a nonexistent item address.
- Successfully parsed client information is reused for the lifetime of the MCP connection, including when the engine omits its version. Explicit client inspection and availability probes refresh it.
- An unreachable endpoint is a provider-availability failure with recovery guidance; REA does not retry or spawn the engine.
+21 -1
View File
@@ -22,6 +22,8 @@ Select it explicitly with `--provider kuna`, MCP's `open_binary.provider_id: "ku
| `REA_KUNA_TIMEOUT_MS` | 120 s | Deadline for one single-function decompile, and for the inventory run REA makes when the export ends without one. |
| `REA_KUNA_JOBS` | 1 | `decompile-project --jobs`. 1 is Kuna's reference answer; more jobs finish sooner but lose callee-first prototypes, and change about 40–60% of function bodies on the measured binaries. |
A single-function decompile, inventory, string, graph or xref run that exceeds its deadline fails as `provider_timeout`, naming the setting that owns the deadline and that raising it takes a restart. A project export that exceeds `REA_KUNA_PROJECT_TIMEOUT_MS` is an export failure instead: requests that need the export report `capability_unavailable` with the export's own retry guidance.
Windows is not supported yet. Supported targets are ELF and thin Mach-O executables for x86-64, AArch64 and ARM; PE and universal Mach-O are rejected with a typed reason.
## What Kuna answers
@@ -68,7 +70,7 @@ Single-function subprocess output and each cached source facet share a 16 MiB bu
Results keep exact u64 virtual addresses, decoded text, native encoding, terminator status and byte length including any terminator. Kuna scans mapped sections or segments for runs of at least five characters; unterminated fragments can include instruction bytes. `all` includes ASCII, UTF-8 and the engine's Latin-range UTF-16LE reading. Other text, including short strings, non-Latin wide text and UTF-16BE, can remain undiscovered. An empty result does not prove absence.
Use `search_strings` for the matching rows or `list_strings` with an exact address for that location. Literal and regex matching run in REA, preserving the existing case and ECMAScript Unicode semantics instead of substituting Kuna's different regex dialect. Procedure and string regex queries share one worker slot per session. Input projections are materialized only after admission, so queued queries retain no per-query inventory arrays. Close cancels and drains matching. Native metadata queries also share one admission slot, including references; a failed stop retains admission until cleanup is proven.
Use `search_strings` for the matching rows or `list_strings` with an exact address for that location. The validated inventory is sorted by numeric address and encoding. Once cached, exact-address reads use binary search and return every encoding at that address without scanning the full inventory or retaining another lookup index. Literal and regex matching run in REA, preserving the existing case and ECMAScript Unicode semantics instead of substituting Kuna's different regex dialect. Procedure and string regex queries share one worker slot per session. Input projections are materialized only after admission, so queued queries retain no per-query inventory arrays. Close cancels and drains matching. Native metadata queries also share one admission slot, including references; a failed stop retains admission until cleanup is proven.
`raw_result.strings` reports the source JSON digest/size, scanned scope, extraction policy, complete inventory count and selected count without copying unrequested text into the answer. Omit the address from `list_strings` to retrieve the complete inventory as Evidence; normal session retention and bundle export apply, including transport-capacity errors for oversized inline replies. These operations preserve their complete-result contracts and do not add paging. Function-referenced string facets in `analyze_function` remain unavailable; call `xrefs` explicitly when references to one returned string are needed.
@@ -82,6 +84,24 @@ REA parses the graph as Kuna writes it, like the string scan, so the graph has n
Evidence includes only selected addresses or dossier neighbors, the producing JSON's SHA-256/byte count, coverage and relevant function facts; unrequested program-wide JSON and instruction text are omitted. Reference caches are in memory and expire on close: a fresh CLI process or MCP server rebuilds them. A first call query therefore costs a whole-program reference walk even when a C export is warm. These operations do not establish full Ghidra/IDA feature parity.
Failures from shared installation or inventory work identify the operation the
caller requested. `diagnostics.producer_operation` retains the internal producer
name when it differs. Caller-specific failures keep the producer's typed outcome,
captured output, partial facts and live cleanup dependencies; cleanup retry
updates every projection rather than preserving an independent stale marker.
Installation acquisition is shared, with independently cancellable caller waits.
The final departing caller stops the probe and joins its cleanup; session close
also stops and joins acquisition. A cleanly cancelled acquisition can be retried,
while a retained cleanup failure blocks replacement until its owner is closed.
Shared string and reference queries preserve caller cancellation reasons and
join the final departing caller's command cleanup. A command cleanup error keeps
its typed primary failure and captured output. Its live resource list follows
both process and workspace ownership: proving process exit does not prove that
the private workspace was removed, and retry updates earlier caller errors.
If workspace setup fails, an unsuccessful rollback retains the original target
or read failure together with its cleanup owner. Replacement stays blocked until
that rollback is resolved; a clean rollback permits another setup attempt.
## Provenance and limitations
- Addresses and bytes are Kuna's observations of the image. Procedure entries and extents are its derivations: extents are upper bounds clipped at the next entry, and Kuna can split one function at an entry its own analysis infers. Pseudocode is its reconstruction, never original source.
+163 -1
View File
@@ -2,7 +2,8 @@
Use this reference to call REA tools and interpret their replies on one MCP
connection. Start with [tool results](#tool-results), [retained Evidence](#retained-application-evidence-inputs),
and [session discovery](#identity-and-discovery). See [cancellation](#progress-and-cancellation)
and [session discovery](#identity-and-discovery). See [transports](#transports)
for the opt-in HTTP listener, [cancellation](#progress-and-cancellation)
for partial-result recovery and [first-query deadlines](#ghidra-first-query-deadlines-and-recovery)
when a cold provider exceeds the client's wait.
@@ -132,6 +133,12 @@ is null. `total` counts all matching heads; each page preserves complete records
in stable unknown ID order. Filters apply before paging. Pages reflect current
session state, so keep the unknown ledger unchanged while traversing it.
Automatically retained workflow questions include their immutable result
Evidence ID. Distinct results retain independent questions and source links;
repeating the same result does not create another unknown. Workflow Evidence
keeps the original residual question text. Explicit `record_unknown` requests
keep caller-selected identity and reject duplicate creation.
For a portable exported bundle, the CLI shares this projection:
`rea inspect-evidence-bundle '{"path":"/tmp/evidence.json","detail":"summary","filters":{"operation":"analyze_function"}}' --format json`.
The CLI validates and materializes that local bundle under its existing memory
@@ -210,6 +217,14 @@ inferred Evidence whenever any group is templated, and derived Evidence only whe
no group was templated.
See [derived API surfaces](web-network-captures.md#derived-api-surface).
`inspect_analysis_view` also accepts `environment-manifest` for retained HAR capture
Evidence, projecting the primary origin's request lines into named tools with path
templates, parameters, observed query names, value-free body shapes and record
pointers, plus excluded groups and three fixed unknowns. Templates, parameters and
names are inferences; the Evidence is inferred whenever any tool or excluded group
is templated, and derived otherwise.
See [environment manifests](web-network-captures.md#environment-manifest).
`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,
@@ -355,6 +370,17 @@ checking that a client received the full catalog. An operation absent from all
groups is missing from the complete inventory; it is not an implicit
unavailable entry.
`get_call_graph` and `trace_call_path` report `forward` and `backward` modes.
Each requires `procedure_address` plus `procedure_callees` or `procedure_callers`,
respectively. The tool is available when either traversal mode is supported;
`default_mode_available` describes the default forward direction. Read each mode's
missing operations and remediation before selecting a direction. These facts
describe traversal prerequisites, not relationship completeness or a guarantee
for every selector. A trace whose start and goal resolve to the same address can
finish without reading relationships, even when neither traversal mode is
available. Discovery does not block that direct invocation or replace its typed
partial/error outcomes.
The `effects` and `annotations` arrays list the true members of their fixed
vocabularies. A known member omitted from either array is false. This applies
only to these closed flag sets; it does not make an omitted tool, provider, mode,
@@ -418,6 +444,96 @@ inspection fails or is cancelled before a provider client exists. If no client
remains, no provider run or health observation is available; follow the cleanup
error's reported resources.
## Transports
stdio is the default transport and the only one that client registrations,
`rea mcp doctor` and the MCP registry entry describe. `rea mcp --http [--host H]
[--port N]` is an opt-in alternative that serves the same catalog over the
streamable HTTP transport at `/mcp`; it replaces stdio for that process rather
than running beside it. Host and port come from the flags, then `MCP_HOST` and
`MCP_PORT`, then `127.0.0.1` and an ephemeral port. The bound URL is announced
as one JSON log line on stderr (`"msg":"MCP transport listening"` with `url`)
at every `REA_LOG_LEVEL`, because an ephemeral port is otherwise unreachable;
stdout stays unused.
This endpoint uses plain HTTP without TLS or client authentication. Use it only
within a trusted local or isolated environment; an explicit non-loopback bind
makes the same tools and active analysis state reachable at that address. It
does not provide separate users or independent target sessions. Standard client
registrations continue to use a dedicated stdio process.
The HTTP server is stateful and serves one client at a time on one server
instance. `initialize` returns an `Mcp-Session-Id`; `notifications/initialized`
is acknowledged with `202`; responses arrive as JSON or SSE frames; `DELETE
/mcp` with the session id ends the session with `200`. Ending a session is not
a server shutdown: the process keeps listening, the instance keeps its providers
and the shared active target, and the next client opens a fresh session against
them. A client ending or replacing a session cancels its running tool calls and
prompt completions, stops request-body reads and fences further message dispatch,
then waits up to ten seconds for request dispatch, handlers and cleanup to finish before reusing the
server. A timeout returns `503`; the old calls remain owned, and later requests
retry the drain rather than starting another session against those resources.
Requests that finish parsing or SDK dispatch after their session closed are
refused, and their response streams are cancelled. Tool callbacks whose
validation finishes after cancellation never start.
Body forwarding stops when SDK request processing ends, including early header
and size refusals, rather than remaining active until the session closes.
HTTP input/route dispatch is limited to eight concurrent requests by default,
shared by MCP and plain routes. Excess requests receive `503` with a closing
connection before their bodies are converted, read or cloned. An embedder can
select `maxConcurrentDispatches`; the SDK's per-body size limit still applies.
MCP responses with fully read or bodyless requests do not hold admission slots,
so an idle MCP SSE stream does not prevent later calls. Plain routes retain their
slots through response delivery and response-source cancellation cleanup. An
unread upload retains its slot until input finishes or either side closes,
even with a long response. Sequential keep-alive is supported; a peer pipelining
behind an unfinished response is disconnected before queued requests dispatch.
Concurrent MCP requests use separate connections.
This bounds concurrent input work, not total provider or process memory.
Provider-backed prompt completions use the same request owner and drain, so a
cancelled completion cannot keep using providers after handover or shutdown.
HTTP factories enable `RequestTrackingMcpServer` tracking so completion is tracked
even when cancellation suppresses the SDK's reply; stdio retains the SDK's
original callback behavior. Full server shutdown stops the listener and waits
for MCP work, plain-route handlers and response-source cancellation to settle
before running provider shutdown hooks or closing providers. Response producers
must finish provider work before closing their stream and expose asynchronous
disconnect cleanup through the stream's `cancel()` result. Cancellation does not
delay delivery of a HEAD reply; a caller retaining a sibling of a teed response
must consume or cancel that sibling before shutdown can finish. Failed response
cleanup remains owned, blocks further admission and prevents provider teardown.
The server continues cleanup
automatically when they finish, including after a client handover timed out.
All routes return `503` until the server factory succeeds; startup failure closes
the listener and joins its pending replies before rejecting the factory.
The newest client replaces an open session: an `initialize` that arrives
while a session is open ends that session instead of being refused, because a
client that exits without `DELETE` must not wedge the listener; the replaced
client's open streams are closed and its later requests are refused. Only an
`initialize` that carries the streamable headers (`Content-Type:
application/json` and an `Accept` naming both `application/json` and
`text/event-stream`) and passes the Host and Origin checks can replace a
session; any other sessionless POST goes to the live transport, which refuses
it without disturbing the session. Requests that carry no valid session id are
refused with `400` or `404` as the SDK transport defines. A bind is loopback by
address class, not spelling, and is classified from the address the listener
actually bound: any `127.0.0.0/8` address, `::1`, or an IPv4-mapped loopback.
Configured names, including `localhost` and its aliases, do not establish that
the bound address is local; names are added only after classifying the actual IP.
On such a bind, requests whose `Host` header is outside the SDK loopback allowlist plus
the configured name and the bound address are refused with `403`, and a browser
`Origin` outside that allowlist is refused the same way (a missing `Origin`
passes); a non-loopback bind relaxes both checks and logs the relaxation. A reply sent before a request body was read (a refused `Host` or `Origin`, an unknown route, the startup `503`) closes the connection after the reply, so an unread upload cannot keep a socket open. Request targets are taken verbatim as origin-form paths (`//host/path` is a path, not another origin); an absolute-form target, a target containing a raw fragment delimiter (`#`), or one whose path URL parsing would rewrite (dot segments such as `/public/../mcp`), is refused with `400`, and a method Fetch does not support with `405`. Percent-encoded `%23` remains valid query data. Only a lone `initialize` can replace an open session; a batch that carries one is left to the transport's refusal. Scoped
IPv6 literals (`fe80::1%eth0`) are refused before binding, because no URL can
name them. Listener errors reach the runtime's connection-loss handler only
after a successful bind; a bind failure prints the listen-failure message alone. Request bodies are bounded by the SDK's
4 MiB limit, and the response budget keeps its stdio-derived floor. The
listener ends on SIGINT or SIGTERM only, not on stdin EOF, and exits `130` or
`143` after cleanup settles. A signal that arrives while startup is still
running is recorded and acted on as soon as the listener and its providers are
owned, so startup never ends without cleanup; a second signal during startup
exits immediately.
## Progress and cancellation
REA accepts ordinary `tools/call` progress tokens. The numeric `progress` counts
@@ -524,6 +640,12 @@ analysis runtime. These failures are reported at the operation that needs
them. A configured provider or an endpoint alone does not establish that a
target is supported.
Composite Hopper regex searches report failures against the accepted
`search_strings` or `search_procedures` operation. The underlying inventory
method and request ID remain in `details.diagnostics.provider_request`, with
the bridge error code and diagnostic type when available. Reattribution
preserves the failure class, captured output, and live cleanup ownership.
Evidence bundles, snapshots, and extraction use the paths and output behavior
declared by their tools. Artifact extraction materializes the selected regular
files into a fresh REA-chosen temporary directory and reports its path.
@@ -534,6 +656,25 @@ temporary source files are declared as `launchesProcess` and `writesFilesystem`,
including for a single JavaScript source. This internal analysis does not execute
the supplied application code.
## Static Ghidra bytes and source mappings
`read_bytes` returns initialized analysis memory, including loader fixups, rather
than live process memory. Check `returned_bytes` and `complete` before decoding:
reads stop at unmapped or uninitialized bytes. Missing bytes are unknown; do not
pad an incomplete read with zeros and treat the result as an observation.
`list_segments` reports memory-block initialization and address-space facts.
`address_to_file_offset` maps one address through the provider's source-byte
mapping. A successful start-address mapping does not establish that an entire
range is contiguous in the original file, or that its bytes equal analysis
memory after loader fixups. Uninitialized, missing, and ambiguous mappings fail
explicitly; preserve the reported failure rather than guessing an offset.
For constructor-populated pointer or resource slots, a static zero is not proof
of a later null value. Inspect the slot's `xrefs` and the writer's assembly or
pseudocode, retaining uncertainty about execution order and runtime values.
These operations inspect static evidence and do not execute the target.
## Ghidra first-query deadlines and recovery
A successful MCP initialize handshake establishes the REA connection.
@@ -726,6 +867,12 @@ 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.
`search_bytes` advertises its pattern and mask as descriptive strings. Its
shared canonical validator scans byte pairs, whitespace, wildcards and aligned
masks without a repeating regular expression or temporary byte arrays. The
server rejects malformed or unconstrained patterns before provider dispatch;
the advertised strings alone do not express those rules.
Boolean literal constraints in input schemas are relaxed only in this
advertisement. For example, a boolean `const` is presented as `type: boolean`;
an affected `not` is omitted, conditional predicates and their branches are
@@ -832,6 +979,21 @@ includes all dimension limitations. Equal CFGs establish only equal observed
block sizes and successor relationships. Text from different provider
identities remains unknown.
The `references` dimension preserves each edge's direction, endpoint identity
and available kind facts. Within one artifact it compares exact raw endpoint
coordinates, including the address space; hexadecimal case and zero padding
do not change identity. Resolving an endpoint to a containing procedure does
not replace the raw coordinate. Unparseable coordinates stay unknown.
Across artifacts, reference endpoints use stable procedure names. Missing or
address-generated names remain unknown. A name observed at multiple procedure
entries retains its label constraint but cannot establish equal endpoints.
Pairing preserves duplicate counts and considers alternative compatible
pairings; array order never identifies an edge. Compatible records with
unknown endpoint identity or kind facts remain `unknown`. Independent known
facts that contradict every possible pairing still establish `changed`.
Source Evidence retains the original addresses, names and unavailable facts.
### Comparison input shapes
`compare_web_captures` accepts exactly one of two input shapes:
+7 -5
View File
@@ -108,11 +108,13 @@ list does not establish that the target has no procedures.
| Artifact occurrence | Occurrence IDs present in schema-valid retained artifact inventory pages. |
| Residual unknown | Current non-resolved unknown heads only. |
Suggestions are Unicode-normalized, case-insensitive prefix matches. The server
deduplicates them and sorts by code point for deterministic results. Procedure
completion derives candidates from the complete inventory, so a name is offered
only when it identifies one address in that inventory. A completion reply
carries at most 100 values, the MCP limit. `total` counts every match and
Prefix matching is Unicode-normalized and case-insensitive; suggestions retain
their original spelling. The server deduplicates them and sorts by code point
for deterministic results. Procedure completion derives candidates from the
complete inventory, so a name is offered only when it identifies one address in
that inventory. Every name at a shared address participates in this check,
including later rows that establish ambiguity. A completion reply carries at
most 100 values, the MCP limit. `total` counts every match and
`hasMore` is `true` when values were omitted. Completion has no paging
controls. A longer prefix reaches an omitted value only when it excludes other
matches; matching uses normalized, case-insensitive forms, so a value can stay
+118 -11
View File
@@ -216,6 +216,36 @@ sites remain distinct. A static route does not establish runtime reachability.
Swift/closure dispatch requires resolved static references; unavailable ABI
forms remain unknown.
Incomplete reference kinds do not discard known typed calls or partial
provider call references. A `provider_call` with `observed` resolution retains
the provider-reported call site and endpoint without claiming generic direct,
indirect or Objective-C dispatch semantics. Its `call_reference` evidence
preserves the original endpoints, classification, raw provider type and
provenance, even when the target node is a containing procedure. Hopper's
`none`, `unknown`, `direct` and `objective_c` labels stay provider-scoped;
unknown numeric types remain available in the raw type field. Target-only
callee fallback uses `provider_call` with `inferred` resolution.
Callee fallback adds inferred targets while each retained route keeps its
original provider and call site. If enumeration fails, known routes remain alongside an unresolved
failure; cancellation still terminates the request. A node-limit omission keeps
the route's known relation while marking its target unresolved. Distinct call
sites to the same omitted target retain separate evidence.
Reports sharing a call site and containing target procedure retain all their
original endpoint evidence on the shared graph edge. Different reported
relations retain separate edges, independent of enumeration order.
Session discovery describes two automatic source routes for this trace:
`authored_ui_dispatch` needs Interface Builder decoding and dispatch metadata;
`native_seed_call_trace` needs native address resolution, dispatch metadata and
a call reader. Metadata can come from direct inspection or `list_names`;
the call reader can supply typed `procedure_references` or inferred
`procedure_callees`. An authored UI-to-handler edge remains useful without
call expansion, and native-seed tracing can proceed without UI decoding.
These routes add no request option or default mode, so discovery omits
`default_mode_available`. Availability describes source prerequisites;
the result reports the query's actual matches, coverage and failures.
`trace_native_values` / `rea trace-native-values <binary> <procedure> --provider
ghidra` composes high-p-code def-use graphs across statically resolved calls.
Logical CALL arguments bind to recovered parameter ordinals; recovered RETURN
@@ -261,6 +291,23 @@ Mach-O fixtures check each case against source-owned return values.
## Static inspection
`inspect_plist.format` describes the selected source, not plutil's conversion
format. Sources explicitly identified as XML, binary or JSON retain those
labels. For generic text, a bounded source-prefix probe recognizes leading XML
markup, including UTF-8 and BOM-marked UTF-16 sources. Unidentified text and
OpenStep plists, including a data-only value such as `<deadbeef>`, report
`unknown` even when plutil decodes their values through an XML conversion.
A plist explicitly selected through the path input or as the active plist target
reports an unreadable or malformed selection as `invalid_request`. A missing or
unreadable default plist of another target reports `capability_unavailable`.
Permission failures remain `access_denied`; output and cleanup failures retain
their own error categories.
A plist decode refusal includes plutil's diagnostic from either output stream.
`details.captured_output` retains bounded stdout/stderr excerpts, observed byte
totals and exit status. `truncated: true` means those excerpts are incomplete.
`inspect_macho.selected_architecture` identifies the exact selected lipo slice
and its `container_file_offset` in the input file. A thin Mach-O has a known
offset of zero; an unknown universal-slice offset stays null. The Evidence
@@ -317,12 +364,22 @@ complete observation.
shared/cyclic references, class descriptors, raw serialized fields and
malformed/unresolved/nil references. Missing fields stay absent; unknown
classes are preserved. Select `root`, `offset` and `limit` explicitly.
Object `kind` describes the decoded archive value: data, dates and numbers
remain `scalar` when their JSON value uses a `$plist_type` wrapper. An actual
dictionary with the same fields remains `dictionary`.
XML must be well-formed. Data literals use
[CoreFoundation's raw ASCII quartet rules](https://github.com/swiftlang/swift-corelibs-foundation/blob/384ff680be7c7445fee6ce0c55e9ae11a46e07c5/Sources/CoreFoundation/CFPropertyList.c#L1588):
non-alphabet ASCII characters are ignored and an incomplete final quartet
emits no bytes. Character references retain their source spelling for data
decoding. Non-ASCII content, child markup and self-closing `<data/>` are format
failures; explicit `<data></data>` represents empty data.
UID 0 cannot distinguish conditional nil from ordinary nil. Limits are
64 MiB of input, 200,000 objects/references and 128 nesting levels.
XML dictionary entries decoded as `__proto__` are omitted with an explicit
count because REA results cannot represent that key. XML tag whitespace and
comments do not change that handling. Other values and the original archive
digest are preserved; key interpretation follows the pinned plist decoder.
comments do not change that handling. XML key names combine their text and
CDATA segments without trimming or expanding literal CDATA entities. Other
values and the original archive digest are preserved.
- `decode_interface_builder` / `rea decode-interface-builder <app>` reads
compiled storyboard and nib resources into objects, outlets, actions,
connections and controller/class names. A full app graph is often several
@@ -403,6 +460,12 @@ complete observation.
address is retained as `reported_address` in the symbol's evidence, whose
location also remains unknown. Nonempty provider address syntax is preserved.
Session discovery reports this workflow available when the bound provider
offers direct metadata inspection or a `list_names` symbol inventory. The
workflow tries direct metadata first and uses the symbol fallback only when
that operation is unavailable; runtime failures remain failures rather than
being replaced by symbol-only results.
## Native desktop observation
`observe_native_ui` captures one explicitly selected existing PID/window ID.
@@ -418,7 +481,11 @@ decrement scrolling and text-value entry, or bounded waits. No global event
injection is used. Unsupported AX actions fail explicitly. The result preserves
ordered before/after captures and gaps; an action may have occurred before a
post-action capture fails. Application state is left as-is; REA does not attempt
to restore it.
to restore it. Failed or cancelled scenarios return a typed error with the
collected report in `partial_observation`, including ordered step outcomes.
Cancellation preserves the caller's reason and remains observable through helper
cleanup. A later abort does not replace an earlier helper or output failure.
Cleanup failures retain their runtime owner until a confirmed cleanup retry.
Scenarios accept caller-selected action lists and accessibility node counts.
Individual waits cannot exceed the operation's 180-second deadline, and the
@@ -572,6 +639,12 @@ digests identify the original serialized bytes.
## Keyed archive integer precision
The archive reader observes XML number element types and binary number markers.
XML values and their number facts are interpreted together from the validated
DOM and its original scalar source spans. Hexadecimal `<integer>` text, including
an optional sign, retains its value;
`<real>` text and CDATA segments are combined without inferring text from nested
elements. Real character references expand outside CDATA; integer and date
literals use raw source text.
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
@@ -580,9 +653,9 @@ 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
Malformed XML scalar content becomes an explicit unknown rather than a prefix
number, guessed timestamp, or tag-only boolean. These unknowns do not disable
exact association for unrelated observed numbers. Nonnumeric
`UID` and `CF$UID` dictionary values remain ordinary data and are projected
recursively; numeric reference markers retain their original representation.
@@ -603,11 +676,45 @@ decode budget reserves estimated room for number metadata and attribute
projection; these estimates are not a hard process-memory bound. Native
NIBArchive decoding is unchanged by this plist-specific representation.
Dates are reported as `{ "$plist_type": "date", "iso8601": "<timestamp>" }`. A
date the decoder cannot represent, such as an XML date with a year beyond 9999
or a negative year, is reported as `{ "$plist_type": "date", "iso8601": null }`
with a counted limitation; the rest of the plist or archive is still decoded.
`inspect_plist` and Interface Builder decoding use the same projection.
Dates are reported as `{ "$plist_type": "date", "iso8601": "<timestamp>" }`.
XML dates require a complete UTC spelling with fixed two-digit month, day and
time fields; short, negative and extended years are interpreted as UTC year
fields within JavaScript's date range. Unsupported calendar fields (including
leap seconds) and out-of-range dates remain explicit unknowns. REA does not
emulate CoreFoundation's normalization of overflowing calendar fields. Invalid
dates returned by other decoders retain `{ "$plist_type": "date", "iso8601": null }`
with a counted limitation. `inspect_plist` and Interface Builder decoding use
the same projection.
A negative-zero real is reported as `{ "$plist_type": "real", "value": "-0" }`
because a JSON number cannot carry the sign of zero. `inspect_plist` and
`inspect_keyed_archive` count these values in a limitation, and Interface
Builder node attributes use the same value. Positive zero and integer zero,
including an `<integer>-0</integer>` literal, remain the number `0`.
Known non-finite reals are reported as
`{ "$plist_type": "real", "value": "nan" | "+infinity" | "-infinity" }`.
These are canonical numeric labels, not a claim about original source spelling.
Binary IEEE reals retain NaN versus signed infinity; NaN payload bits and sign
are not represented in the JSON value, and the original bytes remain the source
for those details. XML CFPropertyList literals (`nan`, `+infinity`, `-infinity`,
`infinity`, `inf`, `+inf`, `-inf`, case-insensitively) decode to the same known
values. Case and aliases normalize; original archive bytes retain source text.
XML scalars whose identity cannot be established use
`{ "$plist_type": "unknown", "element": "integer" | "real" | "date" | "true" | "false", "literal": "<original content>", "reason": "invalid-literal" | "unsupported-markup" | "unrepresentable" }`.
A counted limitation accompanies these wrappers. Literal content retains its
original entity spelling, markup and line endings. Whole XML documents must
still pass strict well-formedness checks. Empty integer, real and date elements
are unknown scalars; boolean elements must be empty. Complete decimal/exponent
reals and signed decimal/hexadecimal integers accept their respective native
leading whitespace but reject trailing text. Arbitrary-precision integers
remain an intentional REA extension beyond CoreFoundation's integer range.
Finite real spellings that overflow the numeric representation remain unknown,
rather than becoming observed infinities. Known non-finite and unresolved scalar
values have separate counts. This replaces the former prefix-number and
incomplete-metadata fallback for malformed XML numeric content. Native
`inspect_plist` uses the same projection for plutil's XML conversion.
## Locate a byte signature
+5
View File
@@ -58,6 +58,11 @@ tools read that copy, which is hashed again after analysis. Capture metadata and
literal field values are producer observations; address/protocol counts and DNS
associations are derivations. Capture Evidence has historical-reference authority.
`capture_start` and `capture_end` are RFC 3339 UTC instants derived from
`capinfos -S` epoch seconds, retaining all producer fractional digits (up to
nanoseconds). Empty captures, malformed timestamps and instants outside years
0000–9999 remain `null`; host-local timestamps without a zone are not inferred.
Addresses count once per packet, including loopback and nested IP occurrences.
DNS addresses are associated only with one question in the same response packet;
additional records may be included, so this does not prove final resolution.
+48
View File
@@ -38,6 +38,10 @@ supervision on macOS. REA removes that directory when it exits. REA does not
install Xcode, Command Line Tools, or other software. Capability checks prepare
this helper before reporting macOS capture as available.
Stopping process sampling or cancelling an ownership query waits for its issued
inspection command to exit. Closing a macOS ownership reader rejects new queries
and waits for admitted helper commands before removing their executable directory.
## Capture a command
For a small first capture, save this as `scenario.json`:
@@ -241,6 +245,15 @@ 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.
When a follow-up read fails after an entry's metadata was observed, the
snapshot keeps unaffected observations and records an `entry_unavailable`
enumeration omission with the root-aliased path and system error code.
Successfully observed identity replacements use `identity_changed` with a null
system code. Unstable symlink targets are omitted; already observed directory
metadata remains available. The affected root stays incomplete, so omitted
entries do not prove deletion. A path missing at its initial lookup remains an
observed absence. Cancellation and unexpected I/O failures still stop capture.
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
@@ -419,6 +432,17 @@ Every capture requires `truncation_details`, with separate accounting for:
imply incomplete path enumeration.
- `process`: sampling limit and whether sampling ended partially. Coverage
remains `sampled`, including when that limit was not exhausted.
`sampling_failures` counts failed read observations plus at most one
unfinished pass interrupted by sampler shutdown. `first_sampling_failure`
retains the first attributed read diagnostic, with shutdown context appended
when applicable; interruption alone has an explicit shutdown diagnostic.
Denied or failed procfs reads mark
sampling partial while preserving readable process rows and thread children;
a process with unreadable identity is not attributed. Expected process-exit
races are separate from failed observations. Shutdown counts only when it
interrupts a read or leaves traversal unfinished; a completed pass does not
become partial merely because the sampler stops. Completed rows
remain available and issued reads settle before final coverage is returned.
The aggregate `truncated` flag summarizes these observations. Comparisons retain
results for unaffected dimensions and mark affected dimensions unknown; an
@@ -435,12 +459,36 @@ 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.
Ownership inspections bind run-token reads to native start identities and retain
related generations through reparenting, group changes, omitted rows, and cleanup
retries. The captured run keeps one evidence owner through settlement and cleanup.
An absent or changed token leaves a previously related generation unresolved;
current token proof is still required before signaling. Swept cleanup verifies the
remaining family after its group signals. Coverage is bounded by the native
snapshots and generations inspected; sampled group IDs select candidates.
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.
Failed cleanup retains its exact resources for the owning session to retry.
The CLI retries before projecting its error; MCP retries pending cleanup before
admitting another capture and during session cleanup. Once every attributed
owner confirms release, the live error status clears `cleanup_incomplete`.
The original failure, observations and `cleanup_report` retain the facts from
the earlier attempt, including any cleanup failure recorded then.
Snapshot file handles, directory handles, and the selected executable reader
follow the same ownership rule. A failed close preserves completed observations
and any primary read failure; it cannot turn a completed digest into a successful
capture with unresolved cleanup. Interrupted snapshots retain examined entries
with incomplete coverage in `partial_observation`, alongside the failure.
File-handle retry uses the exact retained owner. After a directory close rejects,
Node does not expose enough handle validity to authorize another native close;
REA retains that unresolved owner and blocks further captures in the session.
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
+2 -2
View File
@@ -1,7 +1,7 @@
<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_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: هندسة عكسية لأي شيء
@@ -274,7 +274,7 @@ npx rea-agents@latest setup
## سجل النجوم
🎉 **250,000 نجمة على GitHub — شكرًا لكم!**
🎉 **300,000 نجمة على GitHub — شكرًا لكم!**
شكرًا لكل من يستخدم REA، ويبلّغ عن الأخطاء، ويقترح ميزات، ويختبر إصدارات البناء، ويساهم بالإصلاحات.
+2 -2
View File
@@ -1,7 +1,7 @@
<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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: Alles reverse-engineeren
@@ -272,7 +272,7 @@ Melde Sicherheitslücken gemäß [SECURITY.md](../../SECURITY.md).
## Sternverlauf
🎉 **250.000 GitHub-Sterne – vielen Dank!**
🎉 **300.000 GitHub-Sterne – vielen Dank!**
Danke an alle, die REA nutzen, Fehler melden, Funktionswünsche äußern, Builds testen und Fehlerbehebungen beitragen.
+2 -2
View File
@@ -1,6 +1,6 @@
<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](README_it.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_ar.md) · [فارسی](README_fa.md) · [Bahasa Indonesia](README_id.md) · [Italiano](README_it.md) · **Ελληνικά** · [മലയാളം](README_ml.md)
# REA: Reverse Engineer Anything
@@ -285,7 +285,7 @@ npx rea-agents@latest setup
## Ιστορικό αστεριών
🎉 **250.000 αστέρια στο GitHub — σας ευχαριστούμε!**
🎉 **300.000 αστέρια στο GitHub — σας ευχαριστούμε!**
Ευχαριστούμε όλους όσοι χρησιμοποιούν το REA, αναφέρουν σφάλματα, ζητούν νέες λειτουργίες, δοκιμάζουν builds και συνεισφέρουν διορθώσεις.
+2 -2
View File
@@ -1,7 +1,7 @@
<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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: Ingeniería inversa de cualquier cosa
@@ -272,7 +272,7 @@ Informa de vulnerabilidades siguiendo [SECURITY.md](../../SECURITY.md).
## Historial de estrellas
🎉 **250.000 estrellas en GitHub: ¡gracias!**
🎉 **300.000 estrellas en GitHub: ¡gracias!**
Gracias a quienes usan REA, informan de errores, solicitan funciones, prueban compilaciones y contribuyen con correcciones.
+2 -2
View File
@@ -1,7 +1,7 @@
<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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: مهندسی معکوس هر چیزی
@@ -257,7 +257,7 @@ npx rea-agents@latest setup
## تاریخچهٔ ستاره‌ها
🎉 **۲۵۰٬۰۰۰ ستارهٔ GitHub — سپاسگزاریم!**
🎉 **۳۰۰٬۰۰۰ ستارهٔ GitHub — سپاسگزاریم!**
از همهٔ کسانی که از REA استفاده می‌کنند، خطاها را گزارش می‌دهند، قابلیت‌های جدید پیشنهاد می‌کنند، buildها را آزمایش می‌کنند و در بهبود پروژه مشارکت دارند سپاسگزاریم.
+2 -2
View File
@@ -1,7 +1,7 @@
<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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA : rétro-ingénierie de tout
@@ -276,7 +276,7 @@ Signalez les vulnérabilités via [SECURITY.md](../../SECURITY.md).
## Historique des étoiles
🎉 **250 000 étoiles GitHub — merci !**
🎉 **300 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.
+2 -2
View File
@@ -1,7 +1,7 @@
<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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: Rekayasa Balik Apa Pun
@@ -297,7 +297,7 @@ Laporkan kerentanan melalui [SECURITY.md](../../SECURITY.md).
## Riwayat Bintang
🎉 **250.000 bintang GitHub, terima kasih!**
🎉 **300.000 bintang GitHub, terima kasih!**
Terima kasih kepada semua orang yang menggunakan REA, melaporkan bug, meminta fitur, menguji build, dan berkontribusi dalam perbaikan.
+2 -2
View File
@@ -1,7 +1,7 @@
<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**
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: Reverse Engineer Anything
@@ -276,7 +276,7 @@ Segnala vulnerabilità tramite [SECURITY.md](../../SECURITY.md).
## Cronologia delle stelle
🎉 **250.000 stelle su GitHub — grazie!**
🎉 **300.000 stelle su GitHub — grazie!**
Grazie a tutti coloro che usano REA, segnalano bug, propongono funzionalità, testano le build e contribuiscono con correzioni.
+2 -2
View File
@@ -1,7 +1,7 @@
<div align="center">
[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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA:あらゆるものをリバースエンジニアリング
@@ -274,7 +274,7 @@ npx rea-agents@latest setup
## スター履歴
🎉 **GitHub スター 250,000 件、ありがとうございます!**
🎉 **GitHub スター 300,000 件、ありがとうございます!**
REA の利用、バグ報告、機能の要望、ビルドのテスト、修正への貢献に感謝します。
+2 -2
View File
@@ -1,7 +1,7 @@
<div align="center">
[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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: 무엇이든 리버스 엔지니어링
@@ -283,7 +283,7 @@ npx rea-agents@latest setup
## 스타 기록
🎉 **GitHub 스타 250,000개, 감사합니다!**
🎉 **GitHub 스타 300,000개, 감사합니다!**
REA를 사용하고, 버그를 보고하고, 기능을 요청하고, 빌드를 테스트하고, 수정에 기여해 주신 모든 분께 감사드립니다.
+325
View File
@@ -0,0 +1,325 @@
<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](README_it.md)
· [Ελληνικά](README_el.md) · **മലയാളം**
# REA: എന്തും Reverse Engineer ചെയ്യുക
### Binaries, applications, runtime behavior എന്നിവയുടെ Reverse Engineering-നായി ഒരൊറ്റ MCP.
**നിങ്ങൾക്ക് ഇഷ്ടപ്പെട്ട ഒരു feature കണ്ടോ? അത് എങ്ങനെ പ്രവർത്തിക്കുന്നു എന്ന് binary തലത്തിലേക്ക് വരെ മനസ്സിലാക്കൂ.**
[![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
[![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](../mcp-contracts.md#generated-catalog)
[![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>
**[വെബ്സൈറ്റ്](https://rea.tools/) · [ഗൈഡുകൾ](https://rea.tools/guides/) · [ഉദാഹരണങ്ങൾ](https://rea.tools/showcase/)**
[ദ്രുതാരംഭം](#ദ്രുതാരംഭം) · [REA എങ്ങനെ പ്രവർത്തിക്കുന്നു](#rea-എങ്ങനെ-പ്രവർത്തിക്കുന്നു) · [എന്തൊക്കെ വിശകലനം ചെയ്യാം](#എന്തൊക്കെ-വിശകലനം-ചെയ്യാം) · [ഉദാഹരണങ്ങൾ](#ഉദാഹരണങ്ങൾ) · [പതിവുചോദ്യങ്ങൾ](#പതിവുചോദ്യങ്ങൾ) · [ഡോക്യുമെന്റേഷൻ](#ഡോക്യുമെന്റേഷൻ)
<code>npx rea-agents setup</code>
</div>
> [!IMPORTANT]
> REA ലഭ്യമാക്കേണ്ടത് [morluto/rea](https://github.com/morluto/rea),
> [rea.tools](https://rea.tools/), അല്ലെങ്കിൽ [rea-agents npm package](https://www.npmjs.com/package/rea-agents) എന്നിവയിൽ നിന്നാണ്.
> ഈ ഔദ്യോഗിക ഉറവിടങ്ങളിലെ ഇൻസ്റ്റലേഷൻ, റിലീസ് ലിങ്കുകൾ പിന്തുടരുക. സമാനമായ
> repository പേരോ പകർത്തിയ README-യോ മാത്രം ഒരു download ഔദ്യോഗികമാണെന്ന് ഉറപ്പാക്കുന്നില്ല.
<div align="center">
<br />
<img src="../assets/rea-hopper-analysis.png" alt="ഒരു native binary പരിശോധിക്കുന്നതിനിടെ Hopper-ൽ REA അതിന്റെ analysis bridge ആരംഭിക്കുന്നു" width="1200" />
<br /><br />
<table aria-label="REA community">
<tr>
<td align="center" width="360">
<a href="https://discord.gg/GkcryMnJDM">
<img src="../assets/discord.svg" height="42" alt="Discord" /><br />
<strong>Reverse Engineering കമ്മ്യൂണിറ്റിയിൽ ചേരുക</strong>
</a><br />
<sub>Discord · ചോദ്യോത്തരങ്ങൾ · അനുഭവങ്ങളും കണ്ടെത്തലുകളും പങ്കിടുക</sub>
</td>
</tr>
</table>
<br />
</div>
---
നിങ്ങളുടെ സ്വന്തം product-ൽ ഉൾപ്പെടുത്താൻ ആഗ്രഹിക്കുന്ന ഒരു feature ഏതെങ്കിലും app-ൽ കണ്ടോ? REA ഉപയോഗിച്ച് അത് പരിശോധിക്കാൻ നിങ്ങളുടെ agent-നോട് ആവശ്യപ്പെടുക. source code ഇല്ലാതെയും അതിന് app പരിശോധിക്കാനും feature എങ്ങനെ പ്രവർത്തിക്കുന്നുവെന്ന് വിശദീകരിക്കാനും അതിനുള്ള തെളിവുകൾ കാണിക്കാനും നിങ്ങളുടെ project-നായി അതിന് സമാനമായൊരു പതിപ്പ് നിർമ്മിക്കാനും കഴിയും.
Native binaries, JavaScript, Electron apps, .NET assemblies, websites എന്നിവ പരിശോധിക്കുന്നതിനുള്ള tools-ലേക്ക് REA നിങ്ങളുടെ agent-നെ ബന്ധിപ്പിക്കുന്നു. ഇതേ tools നിങ്ങളുടെ terminal-ൽ നിന്നും ഉപയോഗിക്കാം. വിശകലനം local ആയി നടക്കുന്നു; ഓരോ നിഗമനത്തിനും പിന്നിലെ തെളിവുകളും പരിമിതികളും ഫലങ്ങളിൽ ഉൾപ്പെടുന്നു.
Setup നിങ്ങളുടെ agent-ിൽ REA രജിസ്റ്റർ ചെയ്യുകയും അനുയോജ്യമായ workflow നിർദ്ദേശങ്ങൾ ഇൻസ്റ്റാൾ ചെയ്യുകയും ചെയ്യുന്നു. Native analysis-നായി നിലവിലുള്ള Hopper, Ghidra, അല്ലെങ്കിൽ IDA installation ഉപയോഗിക്കാം; അനുമതി നൽകിയാൽ setup-ന് Hopper ഇൻസ്റ്റാൾ ചെയ്യാനും കഴിയും. Static JavaScript analysis-ന് native analysis engine ആവശ്യമില്ല.
> **[REA വെബ്സൈറ്റ് സന്ദർശിക്കുക](https://rea.tools/)** — setup നിർദ്ദേശങ്ങൾക്കും ചിത്രങ്ങളോടുകൂടിയ ഗൈഡുകൾക്കും യഥാർത്ഥ case study-കൾക്കും.
## ദ്രുതാരംഭം
Linux-ൽ Ghidra, JADX, firmware tool launches, static JavaScript/Electron analysis എന്നിവയ്ക്ക് process ownership പരിശോധിക്കാൻ REA-യുടെ `PATH`-ൽ procps-compatible `ps` ആവശ്യമാണ്. പരിഹാര നടപടികൾ `docs/installation.md`-യിലെ "Linux owned-process prerequisite" എന്ന വിഭാഗത്തിൽ ലഭ്യമാണ്.
### നിങ്ങളുടെ agent സജ്ജമാക്കുക
Node.js-ഉം npm-ഉം ഇൻസ്റ്റാൾ ചെയ്തശേഷം ഈ command പ്രവർത്തിപ്പിക്കുക:
```bash
npx rea-agents setup
```
നിങ്ങൾ ഉപയോഗിക്കുന്ന agents തിരഞ്ഞെടുക്കുക, നിർദ്ദേശിച്ച മാറ്റങ്ങൾ പരിശോധിക്കുക, തുടർന്ന് അവയ്ക്ക് അനുമതി നൽകുക. നിലവിലുള്ള configuration-ന്റെ backup-ുകൾ സൂക്ഷിച്ചുകൊണ്ട് setup, REA-യുടെ MCP server-ഉം അനുയോജ്യമായ workflow നിർദ്ദേശങ്ങളും ചേർക്കും. അതിനുശേഷം നിങ്ങളുടെ agent വീണ്ടും ആരംഭിക്കുക.
Claude Code, Codex, Cursor, Gemini CLI, Grok Build, കൂടാതെ [മറ്റ് agents](../installation.md#supported-agents) എന്നിവയെ setup പിന്തുണയ്ക്കുന്നു. provider configuration-നും manual MCP registration-നും [installation and setup](../installation.md) കാണുക.
### നിങ്ങളുടെ agent-നോട് ആവശ്യപ്പെടുക
```text
Notes app-ൽ search എങ്ങനെ പ്രവർത്തിക്കുന്നു എന്ന് മനസ്സിലാക്കി, അതിനുള്ള തെളിവുകൾ കാണിച്ചുതരികയും എന്റെ project-നായി സമാനമായൊരു feature നിർമ്മിക്കുകയും ചെയ്യുക.
```
`Notes` എന്നതിന് പകരം നിങ്ങൾ പരിശോധിക്കാൻ ആഗ്രഹിക്കുന്ന app-ിന്റെയും മനസ്സിലാക്കേണ്ട feature-ിന്റെയും പേരുകൾ നൽകുക.
### Terminal ഉപയോഗിക്കുക
Extract ചെയ്ത JavaScript/Electron app directory അല്ലെങ്കിൽ ASAR പരിശോധിക്കുക:
```bash
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
```
ഫലത്തിൽ modules, imports, Electron boundaries, അവയ്ക്കുള്ള തെളിവുകൾ എന്നിവ ഉൾപ്പെടും. `/absolute/path/to/app` എന്നതിന് പകരം നിങ്ങളുടെ target-ന്റെ path നൽകുക; Windows-ൽ ഉദാഹരണത്തിന് `"D:/apps/example"` ഉപയോഗിക്കാം.
സാധാരണ ഉപയോഗത്തിനായി `rea` command ഇൻസ്റ്റാൾ ചെയ്യാൻ:
```bash
npm install --global rea-agents
rea --help
```
Native analysis നടത്തുന്നതിന് മുമ്പ് ഒരു provider ക്രമീകരിക്കുക. Native commands, provider തിരഞ്ഞെടുക്കൽ, snapshots, scripting എന്നിവയ്ക്കായി [CLI and Evidence guide](../cli.md) കാണുക.
### REA അപ്‌ഡേറ്റ് ചെയ്യുക
REA-യിൽ പതിവായി മാറ്റങ്ങൾ വരുന്നു; പുതിയ releases-ൽ പല bug fixes-ഉം ഉൾപ്പെടുന്നു. നിങ്ങളുടെ installation ഏറ്റവും പുതിയ പതിപ്പിലേക്ക് അപ്‌ഡേറ്റ് ചെയ്യുക.
`npm install --global` അല്ലെങ്കിൽ `bun add --global` ഉപയോഗിച്ച് ഇൻസ്റ്റാൾ ചെയ്ത CLI-ക്കായി:
```bash
rea update
```
Bun-ന്റെ global updates-ന് Bun 1.2.17 അല്ലെങ്കിൽ അതിനുശേഷമുള്ള പതിപ്പ് ആവശ്യമാണ്. പഴയ Bun പതിപ്പാണെങ്കിൽ `rea update` പ്രവർത്തിപ്പിക്കുന്നതിന് മുമ്പ് Bun സ്വമേധയാ അപ്‌ഗ്രേഡ് ചെയ്യുക.
Agent registrations-ഉം skill-ഉം പുതുക്കാൻ, update കാണിക്കുന്ന setup command പ്രവർത്തിപ്പിക്കുക.
`npx` ഉപയോഗിക്കുന്നുവെങ്കിൽ, agent setup പുതുക്കാൻ:
```bash
npx rea-agents@latest setup
```
Setup-ൽ വരുത്തുന്ന മാറ്റങ്ങൾ പരിശോധിച്ച് നിങ്ങളുടെ agent വീണ്ടും ആരംഭിക്കുക. ഒറ്റത്തവണ മാത്രം ഉപയോഗിക്കുന്ന CLI commands-നായി command-ന് മുമ്പ് `npx rea-agents@latest` ഉപയോഗിക്കുക. Bun ഉപയോഗിക്കുമ്പോൾ `npx rea-agents@latest`-ന് പകരം `bunx rea-agents@latest` ഉപയോഗിക്കുക.
## REA എങ്ങനെ പ്രവർത്തിക്കുന്നു
Target പരിശോധിക്കാനും പ്രസക്തമായ code-ന്റെ പാത പിന്തുടരാനും നിങ്ങളുടെ agent MCP വഴി REA-യെ വിളിക്കുന്നു. REA കണ്ടെത്തലുകളും അവയ്ക്കുള്ള തെളിവുകളും തിരികെ നൽകുന്നു. തുടർന്ന് agent കൂടുതൽ ചോദ്യങ്ങൾ ചോദിക്കാനും പെരുമാറ്റം വിശദീകരിക്കാനും implementation എഴുതുകയും പരിശോധിക്കുകയും ചെയ്യാനും അവ ഉപയോഗിക്കുന്നു. CLI commands-ഉം ഇതേ workflows ഉപയോഗിക്കുന്നു.
![REA അന്വേഷണ പ്രവാഹം: നിങ്ങളുടെ agent ഒരു local target-നെക്കുറിച്ച് ചോദിക്കുന്നു; REA analysis tools ഉപയോഗിച്ച് അത് പരിശോധിക്കുകയും code-ന്റെ പാത പിന്തുടരുകയും ചെയ്യുന്നു; തിരികെ ലഭിക്കുന്ന code, references, അറിയാത്ത കാര്യങ്ങൾ എന്നിവ ഉപയോഗിച്ച് agent വിശദീകരിക്കുകയും implementation നടത്തുകയും പരിശോധിക്കുകയും ചെയ്യുന്നു.](../../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-ഉം ആവശ്യമാണ്. Target അനുസരിച്ച് അധിക tools-ഉം host support-ഉം വ്യത്യാസപ്പെടും:
| Target | REA നൽകുന്ന ഫലങ്ങൾ | ആവശ്യകതകളും ഗൈഡും |
| ---------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Native binaries | Pseudocode, assembly, strings, symbols, calls, references | Hopper, Ghidra അല്ലെങ്കിൽ IDA; [native analysis](../native-investigation.md) |
| Offline ELF layout | Sections, segments, യഥാർത്ഥ symbols/relocations, static mitigation candidates | Linux x64-ൽ caller നൽകുന്ന pwntools; [binary diagnostics](../binary-diagnostics.md) |
| Go binaries | ഉൾച്ചേർത്ത compiler version, modules, replacements, build settings | Built-in static ELF/PE/thin Mach-O പരിശോധന; Go installation ആവശ്യമില്ല |
| Rust binaries | ഉൾച്ചേർത്ത cargo-auditable crate പേരുകൾ, versions, sources, dependency edges | Built-in static ELF/PE/thin Mach-O പരിശോധന; [Rust binaries](../rust-binaries.md) |
| WASM artifact | Validation, sections, കൃത്യമായ import/export WAT രൂപങ്ങൾ, decoded WAT | Caller നൽകുന്ന WABT 1.0.42; `inspect_wasm_artifact` |
| EVM bytecode | Dispatch selectors, byte offsets, അനുമാനിച്ച arguments, mutability | Linux x64-ൽ local raw/hex carrier; [offline EVM guide](../evm-bytecode.md) |
| SQLite databases | Tables, columns, indexes, views, triggers, തിരഞ്ഞെടുത്ത സാധാരണ table rows | Local database/WAL snapshot; native SQLite പരിമിതികളോടെ Node.js 24.x >=24.15 അല്ലെങ്കിൽ 26+ |
| Recorded Linux crashes | Raw notes, രേഖപ്പെടുത്തിയ ഓരോ thread-ന്റെയും registers/signals, ഐച്ഛിക mapping candidates | Linux x64-ൽ caller നൽകുന്ന pwntools; ഐച്ഛിക GDB/pwndbg; [recorded crashes](../recorded-crashes.md) |
| JavaScript / Electron | Modules, imports, source maps, routes, IPC, native add-on ബന്ധങ്ങൾ | Node.js, npm; Linux: procps-compatible `ps`; [application analysis](../javascript-application-workflows.md) |
| Websites | Page structure, scripts, network observations, ആവശ്യപ്പെട്ട screenshots | Chrome-family browser; [browser analysis](../browser-observation.md) |
| Saved network captures | Requests, responses, പുറത്തുകാണുന്ന payload-ുകൾ, source locations | HAR അല്ലെങ്കിൽ Fiddler Everywhere SAZ; native mitmproxy-നായി Linux-ൽ mitmdump; [capture guide](../web-network-captures.md) |
| .NET assemblies | Metadata, CIL instructions, പ്രഖ്യാപിച്ച native dependencies, build comparisons | ഒന്നും ആവശ്യമില്ല (static മാത്രം); [managed-code guide](../managed-code-analysis.md) |
| Android APKs | Manifest declarations, classes, decompiled methods, references | Linux/macOS/Windows x64-ൽ Headless JADX-ഉം full JDK-ഉം; [Android guide](../android-analysis.md) |
| Android devices | Devices, packages, processes, logs, dumps, screen captures, APK/file transfers | Caller നൽകുന്ന adb (emulator അല്ലെങ്കിൽ hardware); [ADB guide](../adb-device-analysis.md) |
| JEB projects | Engine-backed project units, artifact digests, type/method pseudo-code | MCP സേവനം നൽകുന്ന caller ആരംഭിച്ച JEB client; REA_JEB_MCP_URL ഉപയോഗിച്ച് തിരഞ്ഞെടുക്കുക; [JEB guide](../jeb-analysis.md) |
| Android resources | Decoded manifest, string tables, locales, version വിവരങ്ങൾ | Caller നൽകുന്ന Apktool launcher; [resource guide](../apktool-resource-analysis.md) |
| Flutter apps | Dart snapshot hash, ഓരോ ABI-യിലെയും library digests, engine build provenance | ഒന്നും ആവശ്യമില്ല (static APK parsing); [Flutter guide](../flutter-analysis.md) |
| Firmware | Regions, extraction results, native-analysis handoffs | Linux-ൽ Binwalk / Unblob; [firmware guide](../firmware-analysis.md) |
| Recorded packets | തിരഞ്ഞെടുത്ത fields, ആവർത്തിക്കുന്ന values, filters, decode-as rules | Linux: TShark 4.x + prlimit; [capture guide](../packet-captures.md) |
| Packet summaries | Endpoints, DNS, TLS SNI, protocol distribution, HTTP requests | Caller നൽകുന്ന tshark, capinfos (Linux-ൽ പരിശോധിച്ചത്); [pcap guide](../pcap-analysis.md) |
| Recorded logic signals | Decoder annotations, sample ranges, diagnostics | Linux: sigrok-cli 0.7.2 + prlimit; [signal recordings](../signal-recordings.md) |
| Packages and resources | File inventories, digests, plists, Apple bundle ഘടന, extracted resources | [Artifact and JavaScript guide](../javascript-artifact-reconstruction.md), [Apple applications](../apple-application-analysis.md) |
| Process behavior | Terminal output, interactions, exit, filesystem observations, run comparisons | Native PTY ഉള്ള Linux/macOS; [process capture](../process-capture.md) |
Static JavaScript, .NET പരിശോധനകൾ application പ്രവർത്തിപ്പിക്കാതെ നൽകിയ files വായിച്ചാണ് നടത്തുന്നത്. Runtime capture, നിങ്ങളുടെ user permissions ഉപയോഗിച്ച് തിരഞ്ഞെടുത്ത target പ്രവർത്തിപ്പിക്കുകയോ അതുമായി ഇടപെടുകയോ ചെയ്യുന്നു; ഓരോ runtime guide-ലും അതിന്റെ പ്രത്യാഘാതങ്ങൾ വിശദീകരിച്ചിട്ടുണ്ട്.
Offline native-binary പരിശോധനയ്ക്കായി REA, caller നൽകുന്ന GNU objdump, Rizin എന്നിവയും പിന്തുണയ്ക്കുന്നു. Provider setup, CLI commands, Evidence-ന്റെ പരിമിതികൾ എന്നിവയ്ക്കായി [reverse-engineering tools guide](../reverse-engineering-tools.md) കാണുക. ഈ providers ഒന്നും REA ഇൻസ്റ്റാൾ ചെയ്യുകയോ അപ്‌ഡേറ്റ് ചെയ്യുകയോ ചെയ്യുന്നില്ല.
<a id="choosing-a-deep-analysis-provider"></a>
Native formats-ഉം host support-ഉം provider അനുസരിച്ച് വ്യത്യാസപ്പെടും. [Hopper and Ghidra setup](../installation.md#hopper), [IDA guide](../ida-provider.md) (ഐച്ഛിക native MCP bridge ഉൾപ്പെടെ), [Kuna decompiler guide](../kuna-provider.md), [പരീക്ഷണഘട്ടത്തിലുള്ള Windows Ghidra support](../windows-ghidra-p0.md) എന്നിവ കാണുക.
Ghidra, [16-bit DOS analysis](../ghidra-dos.md)-ഉം പിന്തുണയ്ക്കുന്നു.
വലിയ binaries-നായി `REA_GHIDRA_STARTUP_TIMEOUT_MS` അല്ലെങ്കിൽ `REA_HOPPER_STARTUP_TIMEOUT_MS` ഉപയോഗിച്ച് provider-ന്റെ startup deadline വർധിപ്പിക്കുക.
Provider തിരഞ്ഞെടുക്കാൻ [CLI guide](../cli.md#choose-a-provider) കാണുക.
ഏറ്റവും പുതിയ npm release-നുശേഷം ചേർത്ത features അറിയാൻ [release availability](../installation.md#released-package-and-main) പരിശോധിക്കുക.
## ഉദാഹരണങ്ങൾ
[![DX-Ball sound-pan, Notion clipboard-bridge, TH04 bullet-ring എന്നിവയുടെ ചിത്രീകരണങ്ങൾ](../assets/rea-showcases.png)](https://rea.tools/showcase/)
### DX-Ball: sound-pan കണക്കുകൂട്ടൽ പുനർനിർമ്മിക്കുക
ഒരു sound call-നെ അതിന്റെ position-to-pan helper വരെ പിന്തുടരുക, instructions പരിശോധിക്കുക, അപൂർണ്ണമായ pseudocode-നെ C-യാക്കി മാറ്റുക. ഈ പുനർനിർമ്മാണം യഥാർത്ഥ x86-ലെ 3,205 test cases വിജയിക്കുകയും compile ചെയ്ത function-ന്റെ 63 bytes-ഉം അതേപടി പുനരുത്പാദിപ്പിക്കുകയും ചെയ്യുന്നു.
[Case study വായിക്കുക](https://rea.tools/showcase/dx-ball/) ·
[പുനർനിർമ്മാണ repository](https://github.com/N0zoM1z0/dx-ball)
### Notion: Electron clipboard bridge പിന്തുടരുക
Renderer-ന്റെ clipboard API കണ്ടെത്തി, അതിനെ preload-ഉം IPC-ഉം വഴി main process വരെ പിന്തുടർന്ന് rich clipboard format പരിശോധിക്കുക.
[Case study വായിക്കുക](https://rea.tools/showcase/notion/)
### TH04: DOS bullet-ring കണക്കുകൂട്ടൽ വീണ്ടെടുക്കുക
യഥാർത്ഥ PC-98 game-ന്റെ 16-bit instructions പരിശോധിക്കുക, fixed, aimed angle കണക്കുകൂട്ടലുകൾ വീണ്ടെടുക്കുക, പുനർനിർമ്മിച്ച C++-നെ ചരിത്രപരമായ compiler output-ുമായി താരതമ്യം ചെയ്യുക.
[Case study വായിക്കുക](https://rea.tools/showcase/th04/) ·
[പുനർനിർമ്മാണ repository](https://github.com/N0zoM1z0/th04)
REA ഉപയോഗിച്ച് നിങ്ങൾ രസകരമായ എന്തെങ്കിലും പരിശോധിച്ചിട്ടുണ്ടെങ്കിൽ അത് കാണാൻ ഞങ്ങൾ ആഗ്രഹിക്കുന്നു. പരിശോധിച്ച target, നിങ്ങളുടെ ചോദ്യം, REA എങ്ങനെ സഹായിച്ചു, നിങ്ങൾ കണ്ടെത്തിയത് എന്നിവ ഉൾപ്പെടുത്തി [issue](https://github.com/morluto/rea/issues) അല്ലെങ്കിൽ [pull request](https://github.com/morluto/rea/pulls) വഴി നിങ്ങളുടെ case പങ്കിടുക.
## പതിവുചോദ്യങ്ങൾ
<details>
<summary><strong>ഏതൊക്കെ agents-ന് REA ഉപയോഗിക്കാം?</strong></summary>
Local MCP servers പിന്തുണയ്ക്കുന്ന ഏത് agent-നും REA ഉപയോഗിക്കാം. Setup, [പിന്തുണയ്ക്കുന്ന agents](../installation.md#supported-agents) ക്രമീകരിക്കുന്നു; മറ്റ് clients-ന് [manual MCP registration](../installation.md#mcp-registry) ഉപയോഗിക്കാം.
</details>
<details>
<summary><strong>Hopper, Ghidra അല്ലെങ്കിൽ IDA ആവശ്യമാണോ?</strong></summary>
ആഴത്തിലുള്ള native analysis-ന് ഇവയിൽ ഒന്ന് ആവശ്യമാണ്. Static JavaScript, .NET പരിശോധനകൾ native analysis engine ഇല്ലാതെയും പ്രവർത്തിക്കും. അനുമതി ലഭിച്ചാൽ setup-ന് Hopper ഇൻസ്റ്റാൾ ചെയ്യാം; Ghidra, IDA എന്നിവയ്ക്കായി നിങ്ങളുടെ നിലവിലുള്ള installations ഉപയോഗിക്കുന്നു. [Provider setup](../installation.md#hopper) കാണുക.
</details>
<details>
<summary><strong>Hopper ആദ്യം ആരംഭിക്കേണ്ടതുണ്ടോ?</strong></summary>
ഒരു operation-ന് ആവശ്യമാകുമ്പോൾ REA Hopper ആരംഭിക്കും. macOS-ൽ ആദ്യമായി പ്രവർത്തിപ്പിക്കുമ്പോൾ demo mode തിരഞ്ഞെടുക്കാനോ license activate ചെയ്യാനോ ആവശ്യപ്പെടുന്ന dialog പ്രത്യക്ഷപ്പെടാം. ആദ്യ CLI/MCP operation അല്ലെങ്കിൽ unattended job നടത്തുന്നതിന് മുമ്പ് അതേ user session-ൽ ആ prompt പൂർത്തിയാക്കുക. ആവശ്യമെങ്കിൽ Hopper സ്വമേധയാ തുറക്കുക. [Hopper startup and troubleshooting](../installation.md#launcher-paths-and-troubleshooting) കാണുക.
</details>
<details>
<summary><strong>skills.sh-ൽ നിന്ന് skill ഇൻസ്റ്റാൾ ചെയ്യുന്നത് എന്താണ് ചെയ്യുന്നത്?</strong></summary>
ഈ skill നിങ്ങളുടെ agent-ന് അന്വേഷണ നിർദ്ദേശങ്ങൾ നൽകുന്നു. REA-യുടെ MCP server രജിസ്റ്റർ ചെയ്യാനും അനുയോജ്യമായ നിർദ്ദേശങ്ങൾ ഇൻസ്റ്റാൾ ചെയ്യാനും `npx rea-agents setup` ഉപയോഗിക്കുക; തുടർന്ന് നിങ്ങളുടെ agent വീണ്ടും ആരംഭിക്കുക. [Skill-only installation](../installation.md#skill-only-installation) കാണുക.
</details>
<details>
<summary><strong>REA ഏത് തരത്തിലുള്ള code ആണ് നൽകുന്നത്?</strong></summary>
Native analysis pseudocode-ഉം assembly-ഉം നൽകുന്നു. JavaScript/Electron analysis modules-ഉം അവയുടെ ബന്ധങ്ങളും വീണ്ടെടുക്കുന്നു. ഈ കണ്ടെത്തലുകൾ ഉപയോഗിച്ച് നിങ്ങളുടെ agent implementation എഴുതുകയും പരിശോധിക്കുകയും ചെയ്യും; പ്രായോഗിക ഉദാഹരണങ്ങൾക്കായി [ഉദാഹരണങ്ങൾ](#showcases) കാണുക.
</details>
<details>
<summary><strong>REA എന്റെ app upload ചെയ്യുമോ?</strong></summary>
REA targets local ആയി വിശകലനം ചെയ്യുന്നു. Tool-ൽ നിന്നുള്ള ഫലങ്ങൾ നിങ്ങളുടെ agent-ന് ലഭിക്കും; അതിന്റെ model provider-ന് സ്വന്തമായ data policy ഉണ്ടായിരിക്കും.
</details>
<details>
<summary><strong>ഒരു bug നേരിട്ടാൽ എന്തുചെയ്യണം?</strong></summary>
ആദ്യം അപ്‌ഡേറ്റ് ചെയ്യുക; പുതിയ release-ൽ ആ പ്രശ്നത്തിനുള്ള പരിഹാരം ഇതിനകം ഉണ്ടായേക്കാം.
`npm install --global` അല്ലെങ്കിൽ `bun add --global` ഉപയോഗിച്ച് ഇൻസ്റ്റാൾ ചെയ്ത CLI-ക്കായി:
```bash
rea update
```
`npx` വഴി agent setup നടത്തുന്നതിനായി:
```bash
npx rea-agents@latest setup
```
നിങ്ങൾ agent ഉപയോഗിക്കുന്നുണ്ടെങ്കിൽ, [setup പുതുക്കൽ](#update-rea) പൂർത്തിയാക്കി അത് വീണ്ടും ആരംഭിക്കുക. അതേ task വീണ്ടും ശ്രമിക്കുക. പ്രശ്നം തുടരുകയാണെങ്കിൽ, നിങ്ങളുടെ REA version, target type, പ്രശ്നം ആവർത്തിക്കാൻ ആവശ്യമായ ഘട്ടങ്ങൾ, error output എന്നിവ ഉൾപ്പെടുത്തി [issue തുറക്കുക](https://github.com/morluto/rea/issues).
</details>
## ഡോക്യുമെന്റേഷൻ
വെബ്സൈറ്റിലെ [പ്രായോഗിക ഗൈഡുകൾ](https://rea.tools/guides/) ഉപയോഗിച്ച് തുടങ്ങുക.
കൃത്യമായ options, prerequisites, result contracts എന്നിവയ്ക്കായി:
- [Installation and setup](../installation.md): agent registration, provider configuration, updates, uninstall.
- [Readiness and troubleshooting](../installation.md#check-readiness-for-your-task): ഒരു agent-ന്റെയോ analysis engine-ന്റെയോ പ്രശ്നങ്ങൾ കണ്ടെത്തുക.
- [CLI and Evidence](../cli.md): commands, provider തിരഞ്ഞെടുക്കൽ, snapshots, import/export, exit statuses.
- [MCP contracts](../mcp-contracts.md), [agent prompts](../mcp-prompts.md): tool results, sessions, guided investigations.
- [Tool catalog](../mcp-contracts.md#generated-catalog): tools, providers, CLI commands എന്നിവയുടെ സ്വയമേവ സൃഷ്ടിച്ച പട്ടിക.
- [Roadmap](../roadmap.md): ആസൂത്രണം ചെയ്ത പ്രവർത്തനങ്ങളും capability trackers-ഉം.
സുരക്ഷാ ദുർബലതകൾ [SECURITY.md](../../SECURITY.md) വഴി റിപ്പോർട്ട് ചെയ്യുക.
## Star ചരിത്രം
🎉 **250,000 GitHub stars — നന്ദി!**
REA ഉപയോഗിക്കുന്നവർക്കും, bugs റിപ്പോർട്ട് ചെയ്യുന്നവർക്കും, features ആവശ്യപ്പെടുന്നവർക്കും, builds പരിശോധിക്കുന്നവർക്കും, fixes സംഭാവന ചെയ്യുന്നവർക്കും നന്ദി.
<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>
## നിരാകരണം
ഉത്തരവാദിത്തത്തോടെ ഉപയോഗിക്കുന്നതിനുള്ള മാർഗനിർദ്ദേശങ്ങൾക്ക് [DISCLAIMER.md](../../DISCLAIMER.md) കാണുക.
നിയമവിരുദ്ധമോ അനുമതിയില്ലാത്തതോ ആയ ഉപയോഗത്തെക്കുറിച്ചുള്ള project-ന്റെ നിലപാട് എല്ലാ REA versions-നും distribution channels-നും platforms-നും ബാധകമാണ്; ഓരോ copy-യും അതിന് ബാധകമായ licenses നിലനിർത്തുന്നു.
നിയമാനുസൃതമായ research, education, interoperability, software preservation, കൂടാതെ നിങ്ങൾക്ക് സ്വന്തമായതോ പരിശോധിക്കാൻ അനുമതിയുള്ളതോ ആയ software-ന്റെ analysis എന്നിവയ്ക്കാണ് REA ഉദ്ദേശിച്ചിരിക്കുന്നത്.
## സംഭാവനകൾ
REA-യ്ക്കായി നിങ്ങളുടെ സഹായം ഞങ്ങൾ സ്വാഗതം ചെയ്യുന്നു! bug റിപ്പോർട്ട് ചെയ്യാനോ feature നിർദ്ദേശിക്കാനോ [issue തുറക്കുക](https://github.com/morluto/rea/issues), code അല്ലെങ്കിൽ docs മെച്ചപ്പെടുത്താൻ [pull request അയയ്ക്കുക](https://github.com/morluto/rea/pulls).
Development setup-നും checks-നും [CONTRIBUTING.md](../../CONTRIBUTING.md), verification lanes-നായി [testing](../testing.md), project ഘടനയ്ക്കായി [architecture map](../architecture.mermaid) എന്നിവ കാണുക.
## ലൈസൻസ്
[MIT](../../LICENSE)
REA-യുടെ രചയിതാക്കൾ സൃഷ്ടിച്ച code MIT license പ്രകാരമാണ് ലൈസൻസ് ചെയ്തിരിക്കുന്നത്. Third-party material അതിന്റെ സ്വന്തം licenses-ഉം copyright notices-ഉം നിലനിർത്തുന്നു; dependencies-ന്റെ പട്ടിക, നിലനിർത്തിയ license text-ുകൾ, external tool നിബന്ധനകൾ എന്നിവയ്ക്കായി [Third-party notices](../../THIRD_PARTY_NOTICES.md) കാണുക.
**IDA Pro / Hex-Rays decompilers, Hopper, JEB എന്നിവ ഉൾപ്പെടെയുള്ള commercial tools നിയമാനുസൃതമായി സ്വന്തമാക്കുകയും അവയുടെ ബാധകമായ licenses പ്രകാരം ഉപയോഗിക്കാൻ അനുമതിയുണ്ടെന്ന് ഉറപ്പാക്കുകയും വേണം.** REA ഒരു tool license-ഓ key-യോ activation entitlement-ഓ നൽകുന്നില്ല. Trials-ഉം demos-ഉം ഉൾപ്പെടെ vendor നിബന്ധനകൾക്ക് വിധേയമാണ്; ഇതിൽ user, feature, automation, output sharing നിയന്ത്രണങ്ങളും ഉൾപ്പെടാം. Cracked copies, മോഷ്ടിച്ച keys, അനുമതിയില്ലാത്ത key sharing, license നിയന്ത്രണങ്ങൾ മറികടക്കൽ എന്നിവയ്ക്ക് അനുമതിയില്ല. ഈ മാർഗനിർദ്ദേശം MIT അല്ലെങ്കിൽ third-party licenses-ൽ മാറ്റം വരുത്തുന്നില്ല.
+2 -2
View File
@@ -1,7 +1,7 @@
<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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: Reverse Engineer Anything
@@ -272,7 +272,7 @@ Zgłaszaj podatności zgodnie z [SECURITY.md](../../SECURITY.md).
## Historia gwiazdek
🎉 **250 000 gwiazdek na GitHubie — dziękujemy!**
🎉 **300 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.
+2 -2
View File
@@ -1,7 +1,7 @@
<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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: Faça engenharia reversa de qualquer coisa
@@ -272,7 +272,7 @@ Relate vulnerabilidades conforme [SECURITY.md](../../SECURITY.md).
## Histórico de estrelas
🎉 **250.000 estrelas no GitHub — muito obrigado!**
🎉 **300.000 estrelas no GitHub — muito obrigado!**
Obrigado a todos que usam o REA, relatam bugs, sugerem funcionalidades, testam builds e contribuem com correções.
+2 -2
View File
@@ -1,7 +1,7 @@
<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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: Реверс-инжиниринг чего угодно
@@ -272,7 +272,7 @@ npx rea-agents@latest setup
## История звёзд
🎉 **250 000 звёзд на GitHub — спасибо!**
🎉 **300 000 звёзд на GitHub — спасибо!**
Спасибо всем, кто использует REA, сообщает об ошибках, предлагает новые функции, тестирует сборки и помогает с исправлениями.
+2 -2
View File
@@ -1,7 +1,7 @@
<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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: Reverse Engineer Anything
@@ -272,7 +272,7 @@ npx rea-agents@latest setup
## ประวัติดาว
🎉 **250,000 ดาวบน GitHub — ขอบคุณทุกคน!**
🎉 **300,000 ดาวบน GitHub — ขอบคุณทุกคน!**
ขอบคุณทุกคนที่ใช้ REA รายงานบั๊ก เสนอฟีเจอร์ ทดสอบบิลด์ และช่วยแก้ไข
+2 -2
View File
@@ -1,7 +1,7 @@
<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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: Her şeyi tersine mühendislikle inceleyin
@@ -277,7 +277,7 @@ Güvenlik açıklarını [SECURITY.md](../../SECURITY.md) üzerinden bildirin.
## Yıldız geçmişi
🎉 **GitHub'da 250.000 yıldız — teşekkürler!**
🎉 **GitHub'da 300.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.
+2 -2
View File
@@ -1,7 +1,7 @@
<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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: Реверс-інжиніринг будь-чого
@@ -272,7 +272,7 @@ npx rea-agents@latest setup
## Історія зірок
🎉 **250 000 зірок на GitHub — дякуємо!**
🎉 **300 000 зірок на GitHub — дякуємо!**
Дякуємо всім, хто використовує REA, повідомляє про помилки, пропонує нові функції, тестує збірки й допомагає з виправленнями.
+2 -2
View File
@@ -1,7 +1,7 @@
<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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA: Kỹ thuật dịch ngược cho mọi thứ
@@ -272,7 +272,7 @@ Báo cáo lỗ hổng theo [SECURITY.md](../../SECURITY.md).
## Lịch sử sao
🎉 **250.000 sao trên GitHub — xin cảm ơn!**
🎉 **300.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.
+2 -2
View File
@@ -1,7 +1,7 @@
<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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA:逆向一切
@@ -278,7 +278,7 @@ npx rea-agents@latest setup
## Star 歷史
🎉 **GitHub Star 達到 250,000 個,感謝大家!**
🎉 **GitHub Star 達到 300,000 個,感謝大家!**
感謝每一位使用 REA、報告錯誤、提出功能需求、測試建置和貢獻修復的朋友。
+2 -2
View File
@@ -1,7 +1,7 @@
<div align="center">
[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)
· [Ελληνικά](README_el.md)
· [Ελληνικά](README_el.md) · [മലയാളം](README_ml.md)
# REA:逆向一切
@@ -278,7 +278,7 @@ npx rea-agents@latest setup
## Star 历史
🎉 **GitHub Star 达到 250,000 个,感谢大家!**
🎉 **GitHub Star 达到 300,000 个,感谢大家!**
感谢每一位使用 REA、报告错误、提出功能需求、测试构建和贡献修复的朋友。
+39 -4
View File
@@ -61,9 +61,21 @@ The outer provider owns both processes and one stable core snapshot. An owned
Python launcher lowers inherited soft limits before replacing itself with GDB.
GDB starts without initfiles, auto-load, debuginfod or automatic shared-library
loading. Owned empty library search paths and caches are used, with plugin
updates disabled. Fixed package code verifies a core connection and no paired
executable before querying mapping candidates. No caller GDB command language is
exposed. The exact observed GDB/plugin version strings are retained.
updates disabled. Debug-file lookup is also restricted to the owned empty
search directory. GDB 16 can otherwise locate the recorded executable independently
of these settings. While opening the core, fixed package code temporarily selects
`/proc/self/exe` (the already running debugger) with `exec-file`, without loading
symbols or running an inferior. This occupies GDB's executable slot and prevents
its automatic executable discovery. The validated decoder profile selects the
core architecture explicitly, so the placeholder cannot select it instead. The
bridge discards that selection with `file` before querying mapping candidates,
and verifies the core connection and absence of a main symbol file. Before launching GDB, the provider also checks
source-bound `NT_FILE` descriptors: mapping names must be absolute Unix paths
without dot segments. Relative names bypass GDB's sysroot, and traversal can
escape it. Unresolved or unsafe mapping coverage refuses debugger enrichment
while retaining the basic decoded observation and original bytes. No caller GDB
command language is exposed. The exact observed GDB/plugin version strings are
retained.
Mapping names are producer display metadata, with unknown current file identity.
Map permissions are derived from reported flags; zero/unfamiliar flags leave
@@ -93,4 +105,27 @@ GDB/Python/pwndbg/strace. Fixture generation explicitly launches its owned test
program; subsequent inspection only reads the resulting core. Real acceptance
checks recorded threads, high registers, missing/malformed notes, opaque owners,
CLI/MCP parity, optional debugger context and historical PID collision with an
owned live sentinel. Original inputs and host configuration remain unchanged.
owned live sentinel. An observed Node thread group must launch the exact ownership
`ps` inventory before it can read that live process's `stat` or `status` for native
identity/UID facts. Only traced `CLONE_THREAD` members share this allowance;
exec-replaced threads, ordinary children, debugger and decoder processes cannot
use it. The purpose of stat/status reads within the same Node thread group
cannot be distinguished by strace. A second recording uses a valid
historical PID above the host's assignable PID range and rejects resolved lookups,
including Node `stat`/`status` reads, to detect historical-PID-driven access separately
from live inventory. Descriptor paths come from strace's `-yy` decoding; exact
PID-directory opens and relative accesses through those handles are rejected.
Failed FD-relative pathname attempts are checked across syscall variants.
Legacy relative pathname calls without dirfd/cwd evidence and symlink aliases
remain unverified; the verification report declares these gaps rather than
establishing their absence.
One syscall/selector contract supplies trace selection, target interpretation
and the report's explicit coverage catalog. Unlisted PID-directed syscalls remain
unverified. The catalog includes PID-directed resource
limits, scheduling, priority, process metadata, signals and pidfd controls.
Self, group and UID selectors retain their syscall-defined meanings; unresolved
targets cannot qualify. Coverage is reported once for all CLI/MCP traces and
does not establish containment of every possible kernel interaction.
The syscall trace also rejects access to the still-present
source executable. The CI workflow defines Ubuntu 24.04 and Debian 13 (GDB 16)
container lanes. Original inputs and host configuration remain unchanged.
File diff suppressed because it is too large. Load diff
+112
View File
@@ -0,0 +1,112 @@
{
"schemaVersion": 1,
"repository": "morluto/rea",
"version": "6.7.0",
"base": "2c4338db1fdb7773e05376301c558cff2a0b4b80",
"target": "b83b9caf4a5f0241a5fd370792f1aed1bffbb2cf",
"commits": [
{
"sha": "8cbaf6c7021b97dd4de6b5771c35fbed06b240e9",
"subject": "fix(tests): isolate command finalization module mocks",
"body": "fix(tests): isolate command finalization module mocks\n\nMove the five registered WASM finalization cases into the existing per-file isolated project. Preserve all result, exit-code, observation and cleanup assertions. A preloaded shared CLI graph reproduces three failures before the move; the isolated covered packet passes.\n\nFixes #4959\n",
"parents": ["2c4338db1fdb7773e05376301c558cff2a0b4b80"],
"authors": [
{
"name": "morluto",
"email": "76467478+morluto@users.noreply.github.com",
"user": {
"login": "morluto",
"__typename": "User"
}
}
],
"pullRequests": []
},
{
"sha": "6b180783ed04ebc87548c8385c80e05725804c47",
"subject": "fix(tests): budget CLI coverage from parsed options",
"body": "fix(tests): budget CLI coverage from parsed options\n\nUse the pinned Vitest parser for coverage and shard flags. Keep ordinary CLI workers at 384 MiB and covered workers at the tested 512 MiB with unchanged concurrency. Retain complete coverage and add actual-config regressions for false, provider-only and spaced-shard options.\n\nValidation: 27 focused cases; 16 covered cases with CLI preloaded; 5 docs checks; typecheck/lint; exact discovery of 1578 files. Measured covered control: 22.18s elapsed, 46.52s CPU, about 2.33 GiB sampled summed process-family RSS on macOS arm64. Full Linux CI pending. No runtime/device verification claimed.\n\nFixes #4960\n",
"parents": ["8cbaf6c7021b97dd4de6b5771c35fbed06b240e9"],
"authors": [
{
"name": "morluto",
"email": "76467478+morluto@users.noreply.github.com",
"user": {
"login": "morluto",
"__typename": "User"
}
}
],
"pullRequests": []
},
{
"sha": "bb212ffecb47e129cc569b9867b2b6e7c9b65685",
"subject": "fix(tests): inherit server identity deadline policy",
"body": "fix(tests): inherit server identity deadline policy\n\nRemove per-case ten-second overrides from MCP catalog and identity checks. Keep the suite-owned bounded ordinary and coverage deadlines, all assertions, and session cleanup.\n\nFixes #4967\n",
"parents": ["6b180783ed04ebc87548c8385c80e05725804c47"],
"authors": [
{
"name": "morluto",
"email": "76467478+morluto@users.noreply.github.com",
"user": {
"login": "morluto",
"__typename": "User"
}
}
],
"pullRequests": []
},
{
"sha": "b83b9caf4a5f0241a5fd370792f1aed1bffbb2cf",
"subject": "fix(setup): edit the duplicate JSON member that clients read (#4957)",
"body": "fix(setup): edit the duplicate JSON member that clients read (#4957)\n\nJSON.parse, JSONC parse, and native Claude Code keep the last duplicate\nobject member, and parseClientConfiguration therefore validates the last\none. The shared setup/uninstall serializer instead edited text through\njsonc-parser's modify and findNodeAtLocation, which select the first\nmatching member, so setup and uninstall on configurations with repeated\nserver tables or rea members wrote into a shadowed member and failed\nreadback.\n\nLocate every JSON text edit by the effective (last) member in one place,\nreplacing the first-member modify path. Removing an effective member\nthat shadows an earlier duplicate would activate that duplicate, whatever\nits ownership, so the serializer now returns a tagged shadowed_member\nfailure and setup and uninstall refuse before writing a backup or the\nconfiguration.\n\nFixes #4952\n\nCo-authored-by: Claude Opus 5.5 <noreply@anthropic.com>",
"parents": ["bb212ffecb47e129cc569b9867b2b6e7c9b65685"],
"authors": [
{
"name": "Kaoru0822",
"email": "kanadekitauji@proton.me",
"user": {
"login": "kaoru0822-kitauji",
"__typename": "User"
}
},
{
"name": "Claude Opus 5.5",
"email": "noreply@anthropic.com",
"user": {
"login": "claude",
"__typename": "User"
}
}
],
"pullRequests": [4957]
}
],
"pullRequests": [
{
"number": 4957,
"title": "fix(setup): edit the duplicate JSON member that clients read",
"url": "https://github.com/morluto/rea/pull/4957",
"author": {
"login": "kaoru0822-kitauji",
"__typename": "User"
},
"mergeCommit": {
"oid": "b83b9caf4a5f0241a5fd370792f1aed1bffbb2cf"
},
"issues": [
{
"number": 4952,
"url": "https://github.com/morluto/rea/issues/4952",
"author": {
"login": "xu91102",
"__typename": "User"
},
"repository": {
"nameWithOwner": "morluto/rea"
}
}
]
}
]
}
+4 -1
View File
@@ -18,8 +18,11 @@ can run.
For DWARF, REA does not follow local debug links by default. Set `follow_debug_links` to `true` to pass `-WK`; external debug-file identities are not bound to Evidence when following links is enabled. The CLI flag is `--follow-debug-links`; `--no-follow-debug-links` or `--follow-debug-links=false` keeps the default. A separate `true` or `false` word after the flag is not its value. REA clears `DEBUGINFOD_URLS` in the objdump child environment to disable debuginfod network access on GNU binutils versions that do not support `-WE`. The complete raw output is authoritative; REA does not normalize it into a version-independent disassembly schema.
For a known native symbol, use `operation: "disassemble", symbol: "my_function"` in MCP or `--symbol my_function` in CLI. REA passes `--disassemble=my_function` to objdump before collecting output, rather than producing the whole disassembly and filtering it afterward. Omit `symbol` to keep full code-section disassembly. Other operations reject this selector. Use a nonempty, NUL-free name with well-formed Unicode; unsupported values are rejected before reading the artifact or starting objdump. Symbol names are passed unchanged; matching, versioned symbols, aliases and the end of the disassembly follow the installed GNU objdump's semantics. Evidence records the selector and actual arguments. An empty match does not establish artifact-wide absence, and the selected observation does not contain the omitted disassembly; request the complete operation when needed.
```sh
rea inspect-with-objdump ./program disassemble
rea inspect-with-objdump ./program disassemble --symbol my_function
rea inspect-with-objdump ./program dwarf
rea inspect-with-objdump ./program dwarf --follow-debug-links
```
@@ -50,7 +53,7 @@ Persistent command Evidence retains the caller-selected and resolved startup pat
rea debug-with-rizin --inferior-tty /dev/pts/7 ./program dr
```
`execute_rizin_command` and `rea execute-rizin-command` run one selected command against a local artifact. The one-shot profile uses `-N -q -c`, suppressing user settings and scripts while leaving plugins available. Commands and plugins run with the REA process user's security context and may access files, the network, or perform other actions. REA preserves raw output and does not claim that command-specific JSON has one universal schema.
`execute_rizin_command` and `rea execute-rizin-command` run one selected command against a local artifact. The one-shot profile uses `-N -q -e scr.color=0 -c`, suppressing user settings and scripts while leaving plugins available. Native terminal presentation defaults to plain text; the caller can explicitly enable colour with `e scr.color=1` in the selected command. REA preserves raw output, including literal ANSI bytes, and does not claim that command-specific JSON has one universal schema. Commands and plugins run with the REA process user's security context and may access files, the network, or perform other actions.
```sh
rea execute-rizin-command ./program iI
@@ -0,0 +1,32 @@
# Implementation plan
1. Widen the runtime `serve` dependency to a transport-neutral factory that may
bind asynchronously. `startMcpTransport` awaits it, hands it the server
logger, and keeps stdio as the default; the shutdown handle type loses its
stdio name.
2. Add `src/server/http/nodeHttpBridge.ts` to turn an IncomingMessage into a web
Request (headers, streamed body, abort on client close) and to pipe a web
Response back with flushed headers, and `src/server/http/serveStreamableHttp.ts`
to own one `McpServer` instance and one stateful transport per session,
ended by `DELETE` or replaced by the next client's `initialize` without
running the instance's shutdown hooks, plus plain routes, loopback Host
validation, the listening log line and idempotent close. The typed listen
error lives in its own module so the stdio entry never loads the listener.
3. Parse `--http`, `--host` and `--port` in `src/main/mcpHttpArguments.ts` from
one schema that also renders help; resolve `MCP_HOST`/`MCP_PORT` in
`src/config/mcpHttpEndpoint.ts` as a `Result` that names rejected settings
without their values.
4. Route the dispatcher to `runMcpHttpEntrypoint` when the `mcp` entry carries
`--http`; compose HTTP dependencies in `src/main.ts` with the shared
`run()` path so configuration, session, providers and shutdown stay common.
5. Register signals only for HTTP mode through `registerSignalShutdown`, a
projection of `registerProcessShutdown` without stdin that sets the signal
exit status before the idempotent shutdown runs; stdio keeps its stdin
end/close triggers.
6. Document the transport in docs/mcp-contracts.md and docs/cli.md, relabel the
architecture diagram, and cover each boundary with adapters, dispatcher,
mcp-boundary and process-boundary tests plus a Python SDK client exchange.
No new dependency is introduced: the transport, Host validation and body bound
come from the already pinned `@modelcontextprotocol/server` root export. Tool
contracts, catalog digests, response budgets and stdio behaviour are unchanged.
@@ -0,0 +1,79 @@
# Streamable HTTP transport for the MCP server
Issue: https://github.com/morluto/rea/issues/4933
## Outcome
`rea mcp --http [--host H] [--port N]` serves the existing MCP tool catalog over
the pinned SDK's streamable HTTP transport instead of stdio, so an agent
environment runtime or any HTTP MCP client can reach REA on a local URL. The
listener is opt-in: bare `rea mcp`, `rea mcp doctor`, `rea mcp add` and every
client registration keep stdio.
## Requirements
- Route `mcp --http ...` and `--mcp --http ...` to the MCP runtime in the
dispatcher without changing bare `mcp`, `mcp doctor` or `mcp add`.
- Resolve host and port from the flags, then `MCP_HOST`/`MCP_PORT` from the
environment snapshot, then `127.0.0.1` and port `0`; announce the bound URL as
one pino JSON line on stderr at every log level and leave stdout unused.
- Use `WebStandardStreamableHTTPServerTransport` in stateful mode around one
server instance built once, after the listener has bound. `DELETE` ends the session on its transport without
running the instance's shutdown hooks, so the same instance keeps its
providers and serves the next client on a fresh transport; the hooks run when
the listener closes.
- Let a new client's `initialize` replace a session that is still open, closing
the earlier transport the same way, so a client that left without `DELETE`
cannot block the listener; the replaced client's later requests are refused
(`404` while the replacing session is open).
- Bridge node:http to web Request/Response in `src/server/http/`, streaming
response chunks as they are produced and turning a client disconnect into a
request abort and body cancellation.
- Classify a loopback bind by the actual bound IP (`127.0.0.0/8`, `::1`, or
IPv4-mapped loopback), without using the configured DNS name as evidence; validate
the `Host` and `Origin` headers with the SDK loopback allowlist plus the
configured name and the bound address on such binds, and relax both for
other binds and log that relaxation. Refuse scoped IPv6 literals before
binding, close the listener if its URL cannot be formed, and forward
listener errors to `onerror` only after a successful bind.
- Let the caller own instance cleanup (`closeInstance: false`) when its factory
owner already closes every instance, as the MCP runtime does.
- Let only an `initialize` that carries the streamable headers and passes those
checks replace an open session; refuse requests once the slot is closed, join
an arming session during shutdown, and keep close stages retryable.
- End the HTTP listener on SIGINT/SIGTERM only, never on stdin EOF, and exit with
the signal status (`130`/`143`) after cleanup settles; latch a signal that
arrives during startup so it is acted on as soon as the lifecycle owner exists,
and exit at once on a second one.
- Export `serveStreamableHttp({ host, port, createMcpServer, routes, logger })`
returning `{ url, close }` so an agent environment server can add plain routes
beside `/mcp` without a second bridge.
- Keep listener failure causes out of stderr behind a fixed message while the
typed listen error carries the system cause (such as `EADDRINUSE`) into the
error-level log line.
## Acceptance and limits
Adapters tests cover the bridge (method, URL, headers, body, GET without body,
incremental streaming, abort and cancel) and the listener (listening line, one
factory call across three sessions, replacement of an open session by the next
`initialize`, two `initialize` requests racing to replace one session while the
instance's shutdown hook stays installed, a working tool call after `DELETE`,
the instance's shutdown hook firing only when the listener closes, plain
routes, 404, Host refusal, port release, typed bind failure naming
`EADDRINUSE`). The dispatcher test covers the new routes and keeps `mcp add
--http` with the CLI. An mcp-boundary test spawns the built CLI and drives
initialize, tools/list, `binary_session` and `DELETE` with the SDK streamable
HTTP client, then proves `binary_session` still answers in the next session and
in a session that replaced one left open; a process-boundary test asserts
`143`/`130` exits and a released port. Concurrent clients are not supported:
the newest `initialize` owns the server. The non-loopback relaxation is covered
only through its pure allowlist helper; no wide bind runs in tests. Response
budgets keep their stdio-derived floor; registrations, `rea mcp doctor` and
`server.json` stay stdio.
## Deferred issue criteria
Serving an environment manifest with replayed records, its environment card and
the exported bundle are later increments of #4933. This PR must reference rather
than close the issue.
@@ -0,0 +1,11 @@
# Tasks
- [x] Define single-feature requirements and implementation plan before code.
- [x] Widen the runtime serve seam and shutdown handle to transport-neutral types.
- [x] Implement the node:http bridge and the streamable HTTP listener module.
- [x] Parse flags and `MCP_HOST`/`MCP_PORT`, route the dispatcher, add signals-only shutdown.
- [x] Document the transport, CLI entry, exit status and architecture label.
- [x] Verify bridge, listener, dispatcher, SDK client, Python client and shutdown behavior.
- [x] Keep providers alive across sessions, replace a session left open, name the bind cause in the log.
- [x] Resolve the re-review: capture the shutdown hook once, one shutdown registration primitive, flags-only HTTP routing.
- [x] Run relevant repository checks and prepare a separately scoped PR.
@@ -0,0 +1,297 @@
# Verification
Verified base: 18aa9af2b2c26fd114113dd39528a91224801840 (fetched main).
The worktree was moved onto that base with the slice's changes kept
uncommitted, then reinstalled with `npm ci` (exit 0; 540 packages added, 541
audited; 6.56 s elapsed, 3.85 s user, 8.07 s sys, 881459200 bytes maximum
resident set size). After the edits of this pass the tree was rebuilt with
`npm run build` (exit 0, three turbo tasks; 5.23 s elapsed, 13.94 s user,
2.93 s sys, 2964652032 bytes) and `npm run test:prepare` (exit 0, six tasks
with three cache hits; 1.37 s elapsed, 3.07 s user, 0.76 s sys, 422625280
bytes); `dist/mcp/` carries the rebuilt `serveStreamableHttp-*.js` chunk beside
`main.js`.
Static gates on the final tree: `npm run check:fast` passed (typecheck and
lint, two tasks; 4.69 s elapsed, 24.25 s user, 3.00 s sys, 4480139264 bytes).
`npx oxlint` over the files touched in this pass reported no findings. After
the last edit, including this record, `npm run format` ran over 4032 files
(0.68 s elapsed, 4.11 s user, 0.74 s sys, 227393536 bytes) and `npm run
format:check` passed (0.69 s elapsed, 4.09 s user, 0.62 s sys, 216989696
bytes). `npx knip` exited 0 (3.80 s elapsed, 5.10 s user, 0.72 s sys,
868679680 bytes). `npm run check:ci:tasks` passed all eight tasks, seven of
them turbo cache hits from the run on the same sources (0.88 s elapsed, 4.52 s
user, 1.04 s sys, 215171072 bytes): jscpd reported 2576 clones and 3.35%
duplicated lines across 3143 files under the 3.5% threshold, lint:built 0
errors over 3734 files, and format:check ran fresh. `npm run docs:check`
passed, including the README consistency test (5 cases; 3.27 s elapsed,
3.43 s user, 0.80 s sys, 288866304 bytes). `git diff --stat` lists 13 tracked
files, none under `src/domain/`.
Source-group tests: `/usr/bin/time -l npx vitest run --project adapters
src/server/http src/server/shutdownRegistration.test.ts` passed 3 files, 17
tests in 2.74 s elapsed, 3.12 s user, 0.93 s sys, 289767424 bytes.
`serveStreamableHttp.test.ts` gained the concurrent case: a slot with one open
session receives two `initialize` requests through `Promise.all`, exactly one
answers `200` with a session id and the other `400`, the instance's `onclose`
hook has fired zero times, and `slot.close()` fires it once. Run before the fix
against the same file, that case failed with the hook count `0` instead of `1`
(1 failed, 5 passed; 1.07 s elapsed, 0.84 s user, 0.21 s sys, 158187520
bytes), which is the pinned no-op hook the review described.
`shutdownRegistration.test.ts` asserts that `registerProcessShutdown` hands
the handler `SIGINT`/`SIGTERM` by name and `undefined` for stdin end, that
omitting stdin registers no input listener, and that `registerSignalShutdown`
reports `143`/`130`.
Built-group tests ran after `npm run test:prepare`. The targeted dispatcher
run, `/usr/bin/time -l npx vitest run --project cli-boundary
tests/boundary/cli/dispatcher.test.ts`, passed 3 tests in 1.08 s elapsed,
0.89 s user, 0.26 s sys, 153026560 bytes, now including `mcp add --http`
routed to the CLI beside `mcp --http --port 0`, `--mcp --http` and `mcp --host
127.0.0.1 --http` routed to the HTTP entry and `mcp doctor --http`, `mcp add`
and `--mcp extra` keeping their routes.
The four full projects ran in sequence while a sibling worktree ran its own
`cli-boundary`, `mcp-boundary` and `acceptance` chain on the same host.
`/usr/bin/time -l npx vitest run --project adapters` passed 247 files, 3945
tests with 8 skipped, in 93.77 s elapsed, 80.21 s user, 30.69 s sys, 344260608
bytes. `/usr/bin/time -l npx vitest run --project mcp-boundary` passed 155
files with 2 skipped, 910 tests with 7 skipped, in 167.51 s elapsed, 321.24 s
user, 51.30 s sys, 4923490304 bytes (the Vitest parent, its workers and the
spawned CLI children). `/usr/bin/time -l npx vitest run --project
process-boundary` exited 1: 56 files passed, 2 skipped and 2 failed, 460 tests
passed, 19 skipped and 7 failed, in 544.81 s elapsed, 160.89 s user, 133.49 s
sys, 1028931584 bytes. `/usr/bin/time -l npx vitest run --project
cli-boundary` exited 1: 108 files passed and 3 failed, 658 tests passed, 2
skipped and 7 failed, in 452.34 s elapsed, 734.29 s user, 234.02 s sys,
648495104 bytes. No failing file belongs to this slice.
The failures split into two kinds. Load: six `jadxIntegration.test.ts` cases
hit the 30 s test or 10 s hook timeout, and six `javascriptApplication*.test.ts`
cases failed with the worker's result-capacity constraint; re-run alone in this
worktree after the other chains ended, `jadxIntegration.test.ts` passed all 48
tests and both JavaScript files passed all 20 tests (`cli-boundary` three files:
20 passed, 1 failed, 23.38 s elapsed, 32.99 s user, 10.97 s sys, 343244800
bytes; `process-boundary` two files: 48 passed, 1 failed, 62.48 s elapsed,
21.89 s user, 17.55 s sys, 686620672 bytes). Pre-existing on main in this
environment: `closedStdout.test.ts` "stops quietly when the reader closes
during streamed JSON" exits `1` instead of `141` with 1009 bytes received and
empty stderr, and `releaseArtifactCanary.test.ts` fails parsing `npm pack
--json`, which npm 12.0.2 emits as an object keyed by package name rather than
the tuple the test expects. Both reproduce identically on the clean sibling
clone at `52b73ee857029a3ab8f5c6eeef233b295951a46c` (no tracked or untracked
changes; `closedStdout` 1 failed, 3 passed, 8.86 s elapsed, 6.98 s user, 2.29 s
sys, 348012544 bytes; the canary 1 failed, 7.91 s elapsed, 7.76 s user, 1.84 s
sys, 668729344 bytes). That clone predates the verified base by 15 commits,
none touching either test or `scripts/rea.mjs`. Because the dispatcher is on
the `closedStdout` path, its scenario was also replayed against this
worktree's built `dist/` with the `18aa9af2` `scripts/rea.mjs` and with the
edited one, three runs each: all six exited `1` with 1009 bytes received and
empty stderr. Nothing in this pass was changed for these failures.
Cross-implementation check with the Python `mcp` 1.30.0 client (httpx 0.28.1,
Python 3.12.12) against the built `node scripts/rea.mjs mcp --http --port 0 <
/dev/null`: stderr announced
`{"transport":"streamable-http","url":"http://127.0.0.1:57093/mcp","msg":"MCP transport listening"}`.
Session A: `initialize` POST returned `200 text/event-stream` with
`mcp-session-id`; `notifications/initialized` returned `202` with no body; the
standalone GET and the `tools/list` and `tools/call` POSTs returned `200
text/event-stream`; `tools/list` reported 207 tools including
`binary_session`; `binary_session` with `{}` returned `isError=False`; `DELETE
/mcp` returned `200`. Session B, opened after that `DELETE`, initialized with a
new session id, listed the same 207 tools, and `binary_session` again returned
`isError=False` before its own `DELETE` returned `200`. The server logged two
`MCP HTTP session opened` and two `MCP HTTP session closed by the client`
lines, SIGTERM then exited it with status `143`, and stdout stayed empty. The
methods, statuses and session-id handling of session A match the recorded
reference exchange step for step; the reference's echo server labelled its
`202` and `DELETE` replies `application/json`, where this listener sends no
content type for those bodiless replies.
## Independent review
An adversarial review of the first implementation reproduced that, after a
`DELETE`, the next session could initialize and list tools but every tool call
failed with a `cancelled` error because the SDK's `DELETE` handling closed the
transport and the server's `onclose` hooks ran provider teardown. It also found
that a session ended without `DELETE` blocked the listener until restart, that
the bind-failure log line omitted the system cause, a duplicated foreign-`Host`
probe, a missing trailing newline on `rea mcp --http --help`, and a static
import of the HTTP listener on the stdio path. Each finding is addressed and
covered by the adapters, mcp-boundary and Python checks in this document.
The re-review of the rebased tree raised four points, all resolved here. Two
concurrent `initialize` POSTs could leave the no-op `onclose` hook installed,
because each session end captured the hook current at that moment and the
later `finally` restored the other call's no-op; `McpSessionSlot` now captures
the instance's hook once, after the factory returns the fully wrapped server,
and every session end restores exactly that, with the adapters case above
failing before and passing after the change. The optional stdin parameter of
`registerProcessShutdown` was dead in production; `registerSignalShutdown` is
now a projection of `registerProcessShutdown(handler, { signals })`, so one
primitive owns registration while the handler learns the signal and keeps
`130`/`143`. The dispatcher routed any `mcp` invocation containing `--http` to
the HTTP entry; it now does so only when the first token after `mcp` or
`--mcp` is a flag, so `rea mcp add --http` keeps the CLI's own diagnostic, and
the dispatcher test covers that case. The formatter hunk in
`src/domain/propertyListXml.test.ts` noted in the earlier record is gone after
the rebase, as `git diff --stat` confirms. The replacement rule stays as
documented, and `docs/mcp-contracts.md` now states it in one sentence with its
rationale so maintainers can decide on it.
## Scope and measurement limits
The concurrent-`initialize` case is exercised at the slot with in-memory
`Request` objects, where both calls advance in lockstep; over TCP two
connections are served in separate event-loop turns, so the race is reachable
only in-process and the listener-level behaviour remains "the newest client
owns the server, the other sees `400` or `404`". The non-loopback relaxation
path is covered only through the pure allowlist helper and the loopback smoke
runs; no wide bind was exercised. Sessions are served one at a time;
concurrent clients are not supported. The two failures that reproduce on the
clean clone are environmental (macOS with Node 22.23.1 and npm 12.0.2) and are
left for their owners; the load-induced timeouts were classified by isolated
re-runs, not by repeating the full projects on an idle host. The error-level
log line that names the bind cause was observed in earlier runs, not asserted
by `mainErrors.test.ts`. Response budgets keep the stdio-derived floor and were
not re-measured over HTTP. Windows was not run.
## Automated review findings on the PR (2026-10-18)
Codex and Greptile left eight inline findings on morluto/rea#4955 at
46dd8f0e; each was checked against the code and addressed in one follow-up
commit, with a regression test where the behaviour is observable:
- A late `initialize` could arm a fresh transport after shutdown (Codex, P1):
the slot now records that it is closed, `close()` joins an arming session
before ending it, and every request after that is refused with `503`. Test:
an initialize racing `close()` gets `503`, the shutdown hook fires once, and
the next request gets `503`.
- A failed `close()` was memoized forever (both reviewers, P1): the close runs
three stages once each and a failed stage is retried by the next call. Test:
the instance's first `close()` rejects, the second call resolves and the port
is released.
- Loopback aliases skipped Host validation (both reviewers, P2 and P1): a bind
is now loopback by address class (`127.0.0.0/8`, `::1`, IPv4-mapped loopback,
`localhost` names) after the same normalization the SDK applies to the Host
header, and the allowlist adds the bind's own hostname so requests to
`127.0.0.2` or `localhost.` are still served. Test: twelve spellings.
- A sessionless POST could close the live session before any header check
(Greptile, P1): on loopback binds the route validates `Origin` with the same
allowlist as `Host`, and only a POST carrying `Content-Type:
application/json` and an `Accept` naming both `application/json` and
`text/event-stream` may replace a session; others reach the live transport,
which refuses them. Test: a `text/plain` initialize and one with a foreign
`Origin` are refused (4xx and 403) while the connected client keeps echoing.
- The bound URL disappeared at quiet log levels (Greptile, P2): the listening
line is written through a child logger pinned to `info`. Test: a `warn`
logger still receives the line with the URL.
- `rea mcp -h --http` reached the ordinary CLI (Greptile, P2): the dispatcher
predicate accepts any flag after the entry. Test: the dispatcher case.
Checks after the change: `oxfmt --check .` clean; `tsc --noEmit` clean;
`oxlint` on the touched sources clean after extracting the staged close into
its own function; `npx knip` no findings; `npm run jscpd` 3.35 % duplicated
lines; `scan:todos` none; `verify:test-discovery` 1,583 files once; `vitest
run` over the listener and bridge adapters tests 14 passed in 2 files; after
`npm run build:cached`, `vitest run` over the dispatcher, option, streamable
HTTP, shutdown and main-error boundary tests 22 passed in 5 files.
A second automated round on the fix (Codex, two P2 findings) was addressed in
the next commit: the replacement guard compares the media type proper, so
`application/json-patch+json` no longer counts as JSON (test: such an
initialize is refused while the connected client keeps echoing), and the
server instance is created only after the listener has bound, so a bind
failure has nothing to clean up and a factory failure releases the listener
and rethrows (test: a throwing factory rejects without announcing a URL).
A third round (Greptile and Codex, five findings) was addressed next: the
listener's `error` forwarding to `onerror` is registered after the bind, so
`EADDRINUSE` prints only the listen-failure message (test: an occupied port
rejects without calling `onerror`); scoped IPv6 literals are refused before
binding and a URL that cannot be formed from the bound address closes the
listener (test: `fe80::1%lo0` rejects before the factory runs); loopback is
classified from the bound address with the configured name added to the
allowlist (test: `ip6-localhost` bound to `::1`, `dev.local` bound to
`127.0.0.1`); and the MCP runtime passes `closeInstance: false` so the factory
owner in `startMcpTransport` remains the single owner of instance cleanup
(test: `close` leaves the instance open until its owner closes it).
A fourth round (Codex, two findings) was addressed next: the replacement
guard parses `Accept` into media ranges and requires exact `application/json`
and `text/event-stream` entries (test: `application/json-patch+json,
text/event-streaming` is refused while the connected client keeps echoing),
and a session whose transport shutdown rejected stays owned so the next close
retries it (test: a failing transport close rejects `close()` once, the second
call completes, the shutdown hook fires once and later requests get `503`).
A fifth round (Codex, three findings) was addressed next: the instance's
shutdown hook now runs exactly once even when the listener closes without a
live session (test: two closes of an idle slot fire it once; an idle listener
close fires it once); the initialize probe no longer awaits cancelling its
cloned body, which is one branch of a tee and would wait for the original
request to drain (test: a 4.5 MB sessionless initialize is refused promptly
while the connected client keeps echoing); and the node:http bridge passes
repeated `Set-Cookie` values as an array instead of collapsing them (test: two
cookies from a composed route both arrive).
A sixth round (Codex, one P1) was addressed next: signal handlers were only
installed after the asynchronous startup returned, so a SIGINT or SIGTERM
during target opening, provider loading or the HTTP bind ended the process
without cleanup. The HTTP entry now latches signals before startup, the
lifecycle owner picks the recorded signal up as soon as it registers, and a
second signal during startup exits at once (test: the latch records `143`,
exits on the second signal, hands the status over on release and leaves no
listeners behind).
Both reviewers then noted that the latched signal's status was overwritten by
the entry's normal `0` return: the HTTP entry now owns its exit status through
`createExitStatus`, where a `0` after a recorded signal keeps the signal's
status and a real failure still wins (unit test), and a process test sends the
signal the moment the listening line appears and asserts the signal status.
An eighth finding (Codex): a reply sent before the MCP handler read the body
left that body unread on a paused bridged stream, so a slow uploader could
hold the socket. The bridge now closes the connection after any reply whose
request body was never read (test: an unknown-route POST and a foreign-Host
POST are answered with `Connection: close`, while a keep-alive GET without a
body keeps its connection).
A ninth round (Greptile and Codex): request conversion ran outside the guard,
so a method Fetch refuses (`TRACE`) could crash the process; the conversion is
now guarded and answered with `405` and a closed connection (test: `TRACE`
gets `405` and the next client still echoes). The unread-body decision now
comes from the incoming message's own body declaration, so a `GET` or `HEAD`
that carries a body also closes, and the regression uses a keep-alive agent
and checks that the socket actually closes after the early reply while a
bodiless `GET` keeps its socket.
A tenth round (Codex, three findings): the takeover guard now requires a lone
`initialize`, mirroring the transport (test: a batch of `initialize` plus
`notifications/initialized` is refused while the connected client keeps
echoing); the shutdown hook records completion only after it returns, so a
hook that threw stays eligible for the next close (test: a hook that throws
once runs twice across two closes and then no more); and the bridge joins the
request target onto the listener's origin verbatim, refusing absolute-form
targets (test: `//attacker.example/card` is a 404 for that path, a plain route
sees the bound host only, and `http://attacker.example/card` gets `400`).
An eleventh finding (Codex): URL construction canonicalized dot segments, so
`/public/../mcp` reached `/mcp`. The bridge now refuses any target whose path
differs after URL parsing, so routing always sees the path the client sent
(test: `/public/../mcp`, `/public/%2e%2e/mcp` and `/./mcp` get `400`; `/card?x=1`
still routes).
A twelfth finding (Codex): `bodyUsed` means disturbed, not consumed, so a
composed route that read one chunk of an upload left the rest paused on a
keep-alive socket. The close decision now uses the incoming message's end of
stream (test: a route that reads one chunk of a 256 KiB upload is answered
with `Connection: close` and a closed socket; a route that reads it all keeps
the connection).
A thirteenth round (Codex): an `Accept` range with `q=0` no longer counts toward
the takeover guard (test: `application/json;q=0, text/event-stream` is refused
while the connected client keeps echoing). The same round noted that a failed
startup leaves cleanup of the already opened session and providers to a single
attempt; that path is the pre-existing stdio startup-failure cleanup, which the
HTTP mode now reaches on `EADDRINUSE`, and is left for the maintainers to decide.
@@ -0,0 +1,29 @@
# Implementation plan
1. Lift the api-surface accumulator's shared pieces into
`webNetworkRouteTemplates.ts` (format rules, media-type essence, request-line
and query-name readers, route scanning, byte allowances) and an abstract
`WebNetworkProjectionAccumulator` (retained/temporary budget, admission,
limitations) with `admitHarCaptureParent` for the shared parent guards, so
both grouping views own one interpretation.
2. Add `environmentManifestRules.ts` as pure functions: the opt-in template
rules, re-bucketing and sibling merging, parameter naming, path templates and
deterministic tool names.
3. Add `EnvironmentManifestAccumulator.ts`: per-record pointers, group state,
primary-origin selection, body-shape parsing through `parseJsonObject` with
top-level key types only, without walking nested values, exclusion reasons,
fixed unknowns and the finished manifest fields.
4. Add `environmentManifestView.ts` with the strict request schema (defaults
applied in the echoed view), the result fields and the projector; register
the kind first in `projectAnalysisView`, extend the result union and
`UnsignedAnalysisView`, and wire the accumulator and confidence rule in
`AnalysisViewService`.
5. Publish the `inspect_analysis_view` description and a fixture-generated
example; port the Grafana-shaped HAR into a source-owned TypeScript builder.
6. Cover domain, accumulator budget, service, MCP boundary, CLI boundary and
acceptance behavior; extend the real-capture verifier; document the view in
the capture guide, the contracts reference and the authored skill.
No new tool, provider, side effect or network activity is introduced. The
manifest is a projection of already retained Evidence; replaying or serving it
is deferred.
@@ -0,0 +1,63 @@
# Environment manifest view from web network captures
Issue: https://github.com/morluto/rea/issues/4933
## Outcome
`inspect_analysis_view` accepts `view: {"kind": "environment-manifest"}` for
retained HAR Evidence and projects the primary origin's recorded request lines
into a replayable tool surface: deterministic tool names, path templates,
parameters, observed query names, value-free body shapes, status and
content-type sets and record pointers, with excluded groups, three fixed
unknowns and the shared projection representation budget. This increment adds
the view kind only; serving and exporting an agent environment from the
manifest are later increments.
## Requirements
- Accept only `inspect_web_network_capture` HAR parents; refuse native
mitmproxy, SAZ and qlog parents, and parents whose Evidence does not record
`sensitive_value_count: 0`, with the same typed unsupported errors as the
api-surface view.
- Without opt-in rules, every tool template must equal the api-surface template
of the same group; the four format rules always apply with `basis: inferred`.
- Apply `after-uid-literal`, `opaque-token` and `sibling-variance` only when
listed, each at most once, in that order. With `sibling-variance` selected,
fold literal siblings within its comparison scope into existing opt-in
parameters unless they are stop words, whichever was recorded first. With only
`opaque-token`, a non-opaque literal remains a separate tool. Never fold a
literal into a format-rule parameter or template a stop word;
`sibling-variance` compares routes of at most 32 segments and the manifest
states when a route exceeded that.
- Derive tool names from the method and route literals deterministically, at
most 60 characters, unique within one manifest.
- Derive `body_shape` for `POST`, `PUT` and `PATCH` from the tool's earliest
record when it carries a JSON-typed request body, as top-level key types
only without walking nested values; copy no header, cookie, query or body
value anywhere in the result.
- List records as pointers (`ordinal`, `method`, `path`, `status`,
`content_type`) and excluded groups with reason `other-origin`,
`ui-page-or-asset` or `non-json`.
- Mark the Evidence inferred whenever any tool or excluded group is templated,
derived otherwise; keep the parent's authority.
- Admit the capture clone, the inline envelope, every retained pointer, group,
route part, observed value, query name and body-shape key before allocation,
and charge body parsing as temporary bytes, within the existing 96 MiB budget.
## Acceptance and limits
A source-owned Grafana-shaped HAR fixture (28 recorded exchanges on two
origins) drives domain, service, MCP, CLI and acceptance coverage. Without
rules the templates equal the api-surface grouping; with all three rules the
fixture yields `/api/dashboards/uid/{uid}`, `/api/folders/{uid}` folding
`general`, `/api/plugins/{plugin_id}/settings` and
`/api/datasources/uid/{uid}/health`. A published contract example is
reproduced byte-for-byte from fixture bytes through the real decoder and view
service. The view performs no network activity and replays nothing; it does
not establish handler identity, schemas, authorization or state transitions.
## Deferred issue criteria
Serving a manifest over streamable HTTP, exporting an agent environment from a
manifest and the hosted verification lane are later independent increments of
#4933. This PR must reference rather than close the whole issue.
@@ -0,0 +1,12 @@
# Tasks
- [x] Record the view contract, requirements and deferred increments.
- [x] Factor shared route, media-type and budget helpers out of the api-surface
accumulator without changing its behavior.
- [x] Implement the opt-in template rules, naming and manifest accumulator.
- [x] Register the `environment-manifest` kind, result schema, service wiring and
confidence rule.
- [x] Port the Grafana-shaped HAR fixture and publish a reproducible example.
- [x] Add domain, service, MCP, CLI and acceptance coverage.
- [x] Document the view in the capture guide, contracts reference and skill.
- [x] Run static, formatting, duplication, documentation and test gates.
@@ -0,0 +1,186 @@
# Verification
Verified base: 18aa9af2b2c26fd114113dd39528a91224801840 (fetched main).
Executed on the implementation worktree after `npm ci`, `npm run build` and
`npm run test:prepare`; every check below ran as written in this pass. The
built-group projects and the built-CLI checks ran against a `dist/` rebuilt
after the last source change.
- `npm run check:fast`: typecheck and lint passed (2 tasks successful).
- `npm run format` then `npm run format:check`: all 4028 matched files use the
correct format.
- `npx knip`: ok (exit 0, no unused files, exports or dependencies reported).
- `npm run check:ci:tasks`: typecheck, lint:built (3730 files, 0 errors), format:check, knip,
metadata:check, jscpd (3.35% duplicated lines over 3140 files and 2581
clones, under the 3.5% gate) and the tech-debt marker scan passed (8 tasks,
3 replayed from this worktree's cache).
- `npm run docs:check`: the six built documentation checks and the README
consistency conformance test (5 tests) passed; no tracked generated file
changed.
- `npx vitest run --project domain --project services` (full source group):
312 files, 5412 tests passed, 3 pre-existing skips.
- `npx vitest run --project cli-boundary` (full project): 111 files; 659 tests passed, 2
pre-existing skips, 8 failed in three files that drive no analysis-view
command (`closedStdout`, `commandFinalizationCancellation`,
`javascriptApplicationJsonOutput`). Re-run in isolation on this worktree the
three WASM interrupt cases and the four JavaScript JSON-output cases passed
and only `closedStdout` "stops quietly when the reader closes during streamed
JSON" (`inspect-sqlite-database`) exited 1 instead of 141. The same three
files run on a clean export of 18aa9af2 (`git archive`, fresh `npm ci`,
`npm run build`, `npm run test:prepare`, nothing from this slice) reproduced
exactly that one failure and passed the other 16, so none of the eight is
attributable to this slice and none was changed here.
- `npx vitest run --project mcp-boundary` (full project): 153 files passed, 2
pre-existing file skips; 901 tests passed, 7 pre-existing skips, no failures.
- `npx vitest run --project acceptance` (full project): 123 files passed, 1
pre-existing file skip; 608 tests passed, 13 pre-existing skips, no failures.
- Built CLI end-to-end on the 28-record Grafana-shaped capture:
`inspect-web-network-capture ... har --format json` then
`inspect-analysis-view` with `environment-manifest`, with and without the
three opt-in rules, and with `api-surface`, twice each. Without rules the 22
tool templates plus the 3 primary-origin exclusions equal the 25 api-surface
groups on that origin and every `path_template` equals its
`api_surface_template`; with rules `/api/dashboards/uid/{uid}`,
`/api/folders/{uid}` (observed values `fg1jo91e57e2ob` and `general`, records
12 and 13), `/api/plugins/{plugin_id}/settings` and
`/api/datasources/uid/{uid}/health` appear across 19 tools with 13 templated
groups; `normalized_result` and `evidence_id` are identical across the two
runs of each view; records carry only pointer keys; no recorded body or query
value appears; three unknowns and `view_digest` are present; confidence is
`inferred` with authority `historical-reference`.
- Built CLI on the same capture extended with `GET /api/teams/search` and
`GET /api/teams/mine` (30 records), all three rules selected:
`/api/teams/{numeric}` keeps observed value `1` only and `get_teams_search`
and `get_teams_mine` stay their own tools; 21 tools, 13 templated groups.
## Independent review
Findings repaired at their owning boundary:
1. A `__proto__` key in a recorded JSON body became a prototype rather than an
own property, and the schema clone then dropped it silently. The manifest
accumulator builds body shapes with `Object.fromEntries`, omits that key and
states the omission as a limitation; a domain regression covers it.
2. The contract example carried a readonly tuple that the mutable JSON example
type rejects; the example keeps a literal-typed mutable tuple.
3. Folding a literal sibling into an already templated position took the parts
of the earliest group, so a literal recorded before the token kept its
literal, dropped the parameter and claimed the token's record under a
template it does not match. `mergeGroups` now takes the templated group as
the shape for parts while the earliest group still names
`api_surface_template`, `body_shape` and record order; a domain regression
with the literal recorded first covers it.
4. The request-body parse accepted `text/plain` and `text/markdown` bodies; it
accepts only `application/json` and `application/*+json`, and the capture
guide states the earliest-record rule; a domain test covers both media
types.
5. A repeated entry in `template_rules` was accepted, echoed and hashed into
`view_digest` while the accumulator deduplicated it; the request schema
refuses repeats with `template_rules must not repeat a rule`.
6. The sibling-variance fold-in absorbed a non-conforming literal into a
parameter produced by one of the four format rules, so `/api/teams/mine`
became an observed value of `/api/teams/{numeric}` and the published rule no
longer described every observed value. Fold-in is restricted to parameters
produced by the opt-in rules; literal siblings of a format-rule parameter
stay their own tools or merge among themselves under `sibling-variance`
only when identifier-like. A domain test with `/api/teams/1`,
`/api/teams/2`, `/api/teams/search` and `/api/teams/mine`, the capture
guide and the spec state the rule; the built-CLI check above exercises it.
## Hosted lane
- `real-web-network-captures` (hosted ubuntu-24.04, workflow run
https://github.com/earakely-scale/rea/actions/runs/39097105064 on the fork
at 2d95597f) passed with the manifest block of
`scripts/verify-web-network-captures.mjs` executed against the lane's
producer and mitmproxy captures. The first run at 61d35369 failed only in
that block: the refusal check stringified the whole MCP result, so the
declared `[` literal matched the result envelope; the follow-up compares the
parsed refusal as the api-surface branch does.
## Scope and measurement limits
macOS `/usr/bin/time -l`, command accounting only: `npm run check:fast`
reported 5.23 seconds elapsed, 24.20 user and 2.92 system seconds, and
4449140736 bytes maximum RSS; `npm run format` 0.74 seconds elapsed, 4.14
user and 0.73 system seconds, and 223363072 bytes maximum RSS;
`npm run format:check` 0.66 seconds elapsed, 4.03 user and 0.61 system
seconds, and 218759168 bytes maximum RSS; the full source group reported
25.10 seconds elapsed, 67.26 user and 2.72 system seconds, and 2659172352
bytes maximum RSS; `npx knip` 3.68 seconds elapsed, 5.24 user and 0.70 system
seconds, and 865599488 bytes maximum RSS; `npm run check:ci:tasks` 4.65
seconds elapsed, 15.03 user and 4.36 system seconds, and 843333632 bytes
maximum RSS; `npm run docs:check` 3.61 seconds elapsed, 3.81 user and 0.99
system seconds, and 289472512 bytes maximum RSS; the full `cli-boundary`
project 425.66 seconds elapsed, 703.52 user and 206.77 system seconds, and
630456320 bytes maximum RSS; the full `mcp-boundary` project 164.19 seconds
elapsed, 302.85 user and 47.08 system seconds, and 4457529344 bytes maximum
RSS; the full `acceptance` project 960.25 seconds elapsed, 1520.91 user and
520.68 system seconds, and 800063488 bytes maximum RSS. `npx knip` ran while
the `cli-boundary` project was executing, and the clean 18aa9af2 export's
`npm ci`, build and test preparation overlapped the `mcp-boundary` and
`acceptance` runs, so those elapsed figures include host contention. Token usage and full process-family peak are
unmeasured. Local real-tool verification ran on macOS arm64; the hosted Linux lane result is recorded above.
## Automated review findings on the PR (2026-10-18)
Codex and Greptile left seven inline findings on morluto/rea#4954 at
b6d18d23; each was checked against the code and addressed in one follow-up
commit, with a regression test where the behaviour is observable:
- Body shapes walked nested values (both reviewers, P1): `#bodyShape` passed
the text to `inferJsonShape`, whose per-node path copies grow with the square
of depth, so a small deeply nested body could exceed the budget it had
reserved. The reader now parses once and reads top-level key types from the
parsed object; a test feeds a 2,500-level nested body and gets the four
top-level types back.
- Literal route parts were not admitted (Codex, P2): a path of many short
literal segments materialized one part object per segment without a charge.
Every route part is now charged before the group is created; a test shows a
5,000-segment path refused under a 1 MiB budget while a 100-segment path is
retained.
- `sibling-variance` rebuilt a key over the whole route at every position
(Greptile, P1): routes longer than 32 segments are no longer compared, the
manifest states it in a limitation, and a test shows two 39-segment siblings
left unmerged beside a merged short pair.
- `after-uid-literal` templated stop words (Greptile, P1): the rule now skips
them; a test keeps `/api/items/uid/search` literal beside
`/api/items/uid/{uid}`.
- Tool-name suffixes restarted at 2 on every collision (Greptile, P2): the
registry keeps the next suffix per base; a test projects 300 dotted literals
into `get_item` and `get_item_2` through `get_item_300`.
- An exclusion row could lose its templated flag when two groups printed the
same row (Codex, P2): the flag is now the logical or of both. The scenario
needs a literal segment spelled `{numeric}`, which the WHATWG URL parser
percent-encodes in recorded paths, so no capture reaches it; the one-line
defence is kept without a test.
Checks after the change: `oxfmt --check .` clean; `tsc --noEmit` clean;
`npm run lint` and `verify:module-boundaries` clean (the complexity warnings
on `#append` predate the change); `npx knip` no findings; `npm run jscpd`
3.35 % duplicated lines; `scan:todos` none; `verify:test-discovery` 1,580
files once; `vitest run` over the view, accumulator, JSON-shape and contract
example tests 32 passed in 4 files; `vitest run` over the service, CLI and
MCP boundary tests for analysis views 73 passed in 3 files.
A sixth automated finding (Codex) was addressed after the collaborator's
merge of main: `sibling-variance` merged a whole bucket when any one literal
carried a digit, so `/api/items/mine` could be folded into `{item_id}`. The
rule now partitions the bucket and merges only the identifier-like siblings
(each with a digit or colon, or three or more hyphenated names under a plural
literal), leaving the other literals as their own tools; with the rule alone
the fixture therefore keeps `/api/folders/general` and
`/api/folders/fg1jo91e57e2ob` separate, while all three rules still fold
`general` into `/api/folders/{uid}` through the opaque-token parameter. Tests:
the new partition case and the updated single-rule table.
Follow-up mixed-cohort regressions reproduced two omissions on `dd87f54e`
with main `8307ea37`: two coded siblings prevented three qualifying hyphenated
siblings from joining the parameter, and one coded sibling was omitted when
three hyphenated siblings merged. Eligibility now belongs to one Set that
combines both qualifying cohorts before the minimum group size is checked.
The consumer reuses that Set and materializes its merge order once. Three
cases cover both omissions and preserve the three-hyphen minimum when only
two hyphenated siblings accompany coded identifiers; `mine` and `search`
remain literal and every source record remains represented.
+4 -1
View File
@@ -57,7 +57,10 @@ triggers or arbitrary SQL.
Rows are optional. `table` selects one exact ordinary-table name. `columns`
(CLI repeated `--column`) selects exact visible column names in the requested
order; omission selects all visible columns, including generated columns.
Unselected cells are not evaluated or projected. Column selection requires a
Unselected cells are not evaluated or projected. Malformed column-name bytes
cause a format refusal when all columns are requested. In inventory scope, an explicit valid subset can
still be sampled without decoding unrelated malformed column names.
Column selection requires a
table and at least one name; empty-string identifiers are valid. `row_limit`
requires `table`, defaults to 20 and accepts positive safe integers. Samples
remain subject to the byte and worker resource limits below, regardless of row count. The result reports
+70 -11
View File
@@ -92,7 +92,7 @@ without serial scheduling. Pure domain/service, composition, conformance,
evaluation, CLI boundary, and MCP boundary projects share module graphs. Their
tests avoid process-global state and keep resource cleanup test-scoped. Each
MCP session still owns its resources, and CLI cases retain fresh command
instances or subprocesses. CLI module mocks belong in `tests/process-global/`
instances or subprocesses. CLI and MCP module mocks belong in `tests/process-global/`
so they keep per-file isolation. Product catalog verification stays with the
isolated filesystem boundary tests because it loads both source and compiled
module graphs. Adapter, other boundary, acceptance, and process-global projects
@@ -110,9 +110,14 @@ rendered declarations. Keep canonical rejection checks separate from the
intentionally reduced compact advertisement, and probe actual client renderers
when changing schema representations.
The reused CLI boundary workers cap V8 old space at 384 MiB, based on their
profiled allocation and cleanup behavior. This encourages collection between
files; spawned REA processes retain their own heap settings.
The reused CLI boundary workers cap V8 old space at 384 MiB for ordinary runs
and 512 MiB with coverage enabled. Covered ADB fixtures exhaust the ordinary
384 MiB budget; those fixtures also complete with the shared CLI graph preloaded
at 512 MiB. This is a measured capacity control, not a suite-wide speedup claim.
Both profiles keep the
same bounded worker count, and spawned REA processes retain their own heap
settings. Explicitly disabling coverage retains the ordinary profile; coverage
provider options alone do not enable instrumentation.
Vitest worker limits do not bound subprocesses launched within a test. Bound
those batches separately so repeated CLI validation cannot oversubscribe the
@@ -216,6 +221,12 @@ controlled production seam for interleavings that cannot be reproduced reliably.
| Cleanup fails after success or primary failure | Public output retains the completed observation or primary diagnostic, remaining resources, and owner recovery action. Restore the denied resource and verify the owning cleanup retry. |
| Target exits without an acknowledgement, or transport disappears while it stays alive | Positive owned exit proof resolves target lifetime; other resources still need cleanup. Lost transport alone does not prove exit. Verify unrelated/attached targets survive and same-connection recovery works when supported. |
Shared process-supervision controls separate leader exit from output closure.
Cover output during held or failed cleanup, bounded retention and drain timeout,
retry, and borrowed stream authority. The POSIX inherited-stderr control uses a
separate pipe as a release barrier after leader exit; it does not establish
native Windows Job Object behavior.
Synchronize cancellation with the finalization boundary being tested; a fixed
delay after dispatch does not establish that phase. Use markers, barriers, or
owned cleanup seams while preserving real cleanup where feasible. Check server
@@ -225,6 +236,30 @@ cover cancellation during final cleanup.
Use explicit abort reasons and assert their identity at admission and after
provider completion, alongside retained observations and cleanup state.
Electron fuse regressions cover actual descriptor close denial and retry through
the built CLI, same-connection MCP recovery, mixed descriptor outcomes, and
server shutdown. Controlled seams cover cancellation during final close and
after reader finalization, plus active-provider shutdown during preflight.
They preserve real filesystem cleanup where possible; mocked launch boundaries
do not establish real Electron teardown or naturally occurring OS failures.
Active Electron cleanup controls retain independent transport and process-family
owners, block replacement captures until recovery, and retry only unresolved
owners. Cover late close acknowledgement and rejection after a wait deadline,
opaque rejection reasons, cancellation during failed finalization, and missing
lineage followed by a confirmed passive family census. Windows controls require
a fresh lineage observation and do not signal cached descendant PIDs after root
termination. Simulated Windows controls do not establish native Windows behavior.
Native process-ownership controls distinguish start identity, zombie lifecycle,
current parent/group relation, and token-read evidence. Retain generation-bound
candidates through smaller lineage observations, table omissions, reparenting,
group changes, and failed cleanup retries. A readable token with unavailable
identity stays unresolved. Native UID facts, rather than an earlier process-table
row, determine whether a token denial concerns another user. Darwin tests compile
the helper and exercise snapshot growth, absence, lifecycle, and UID observations;
controlled Linux procfs tests do not establish real Linux exit or PID-reuse behavior.
For atomic writes, exercise cancellation on both sides of the documented commit
point and preserve any publication receipt. A late interruption does not prove
that no output was published.
@@ -329,6 +364,11 @@ The process-global Vitest configuration contract rejects new direct temporary-ro
creation outside the workspace seam and its narrowly documented boundary/package
exceptions.
The shared temporary-directory and workspace helpers preserve caller labels
under an owned `rea-` prefix when needed. `npm run verify:test-temp-hygiene`
uses the same ownership rule to find retained fixtures under a private temporary
root. Third-party caches remain outside that ownership rule.
Real Hopper, Ghidra, IDA, browser, package, and managed-code claims belong to their
explicit `npm run verify:*` lanes. The reconstruction-readiness lane also
checks deterministic rerun, tamper, and stale-input handling; those checks do
@@ -503,7 +543,7 @@ costs. Its queue, execution, and failures are independent of the required gate
and publication. CPU time and peak process-family memory are not measured by this API.
The build job saves portable Turbo outputs across runs. Eight Linux real-system
lanes restore this cache without waiting for the build job. The shared action
lanes reuse its current-run artifact; standalone dispatches restore the cross-run cache. The shared action
derives its key from `test:prepare --dry=json` task hashes, runner OS and
architecture, `.npmrc`, `.nvmrc`, and the lockfile; test-only changes can reuse compiled outputs. Every
build and verification command still runs, so Turbo checks task inputs and
@@ -513,7 +553,15 @@ that generator's entry. Native outputs are not stored in this cache.
Native package jobs, the Windows curated lane, and the Apple artifact lane reuse
the same workflow's Turbo cache for portable compiled JavaScript, skills, and
catalogs. The Windows lane relies on the Linux static job for typechecking. They retain the normal build and prepack
catalogs. The key parser retains the validated `test:prepare` task identities in
`.cache/ci-build-plan.json`; staging reads this plan without starting another
Turbo run that could evict cache entries. The producer stages matching archives,
metadata, and available manifests into `.cache/ci-build-cache/`.
`portable-build-cache.json` records availability per task. Evicted or partially
missing entries are omitted as whole entries, and consumers rebuild cache misses,
including when every entry is unavailable. Malformed plans, non-file entries,
and I/O errors other than disappearance still fail publication. Older cross-run entries stay in the
original cache. The Windows lane relies on the Linux static job for typechecking. They retain the normal build and prepack
commands, which restore matching outputs or rebuild on a cache miss. Native
artifacts, dependency installs, package archives, and runtime verification remain
host-local. Keep platform-dependent outputs out of this shared cache.
@@ -712,11 +760,12 @@ 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,
already open, and exercises shared application/provider 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.
`open_jeb_project`; the earlier licensed 5.48.0 headless verification did 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
the bring-your-own boundary. The earlier licensed build was 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
@@ -727,7 +776,12 @@ decompilation through both CLI and MCP, and the official Flutter Gallery
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.
remained GUI-only surfaces in that headless build.
The separate [Linux CE native audit](../experiments/analysis-efficiency/jeb-linux-native.md)
uses the official CE `5.48.0.202610071539` direct CLI launcher and real
CLI/stdio MCP ELF workflows. That audit does not qualify CE Java/Android
decompilation or GUI project opening, and it does not replace the licensed
verification above.
Authenticated IPA and macOS application inventory projection is documented in
[Apple application analysis](apple-application-analysis.md).
@@ -1536,7 +1590,12 @@ NUL-containing names. It compares exact WAT,
section output and selected/tool digests through the compiled CLI and real MCP
SDK, validates advertised schemas, checks identical CLI/MCP Evidence IDs and
session bundle readback, retains invalid/truncated module diagnostics, preserves
all inputs and checks workspace cleanup. Pass an installed package's
all inputs and checks workspace cleanup.
The lane also injects one cleanup denial for exact private runtime roots and
input descriptors, checks recovered CLI errors, and verifies retry on the same
MCP connection after repeated runtime-removal denial. These are controlled
faults, not naturally occurring permission failures; no WASM target is executed.
Pass an installed package's
`scripts/rea.mjs` as the first argument to run the same lane against the package.
`npm run verify:wasm:package` packs and installs REA into an isolated temporary
prefix with lifecycle scripts disabled and runs the same required real-tool lane.
+7
View File
@@ -79,6 +79,13 @@ providers need not expose identical state machines.
and resource release separate. A valid process handle, successful launcher,
or selected target establishes only its own fact. Publish available identity
and exit observations even when launch fails; retain unknown ownership.
- Process exit does not establish output closure. The shared process supervisor
retains at most 64 KiB of additional diagnostics from owned stop entry,
including pending cleanup and retries, and drains for up to one second after
verified stop. It marks output incomplete when closure cannot be
observed and releases owned event-loop references without changing the proven
process-cleanup outcome. Failed process cleanup retains capture for retry;
borrowed processes and streams retain their own lifetime and reference state.
- Authenticate and capture identity through the same boundary on initial and
recovery handshakes. Bound abandoned unauthenticated listeners where the
protocol permits it; that deadline must not expire authenticated idle sessions
+94
View File
@@ -55,6 +55,12 @@ it as inline Evidence to `inspect-analysis-view`; the same summary and capture
page contracts apply. Large complete records can still exceed MCP's response
budget; export the retained Evidence when a single record cannot fit.
If decoding completes before cancellation or private-root cleanup fails, the
failure retains the completed capture as Evidence with the requested record
selection and explicit sensitivity exclusions. Earlier decode failures remain
primary. Failed cleanup stays linked to its exact owner, including through
redaction, and its live status clears only after a confirmed retry.
## Formats and upstream profiles
HAR uses unchanged `har-schema@2.0.0` draft-06 schemas, `ajv@8.20.0`,
@@ -315,6 +321,94 @@ parent envelope, capture and examined records are deduplicated onto the view.
Portable captures must retain unique ordinals within their declared total;
caller-selected subsets can preserve any requested ordinal order.
## Environment manifest
Pass retained HAR Evidence to `inspect_analysis_view` with
`view: {"kind":"environment-manifest"}` to project one application's recorded
request lines into a replayable tool surface: the environment manifest that an
agent environment later serves from retained Evidence. The view reuses the
api-surface grouping, then keeps the groups on the primary origin, the origin
with the most JSON-like records (`application/json`, `application/*+json`,
`text/plain`, `text/markdown`), whose path starts with `/api/` or `/apis/` or
whose content types are JSON-like. Every other group is listed under
`excluded` with reason `other-origin`, `ui-page-or-asset` or `non-json`, and
retained records without a usable request line are counted in a limitation.
```json
{
"name": "inspect_analysis_view",
"arguments": {
"source": { "kind": "retained-evidence", "evidence_id": "ev_..." },
"view": {
"kind": "environment-manifest",
"template_rules": [
"after-uid-literal",
"opaque-token",
"sibling-variance"
],
"include_query_parameter_names": true
}
}
}
```
`origin` and `name` identify the environment; the name is the kebab-case
primary host with dots and ports replaced by hyphens, `grafana-example` for
`http://grafana.example`. Each tool carries a deterministic `name`, `method`,
`path_template`, `api_surface_template` (the four-rule template of its
earliest record), `params`, `query_parameter_names`, `body_shape`,
`statuses`, `content_types` and `record_ordinals`. `records` lists one pointer
`{ordinal, method, path, status, content_type}` per record a tool cites and
never a header, cookie or body. Tools sort by template then method.
Without `template_rules`, every `path_template` equals the api-surface
template and `params` carry the four format rules with names `id`, `uuid`,
`hash` and `date`; a repeated name gets a numeric suffix. Opt-in rules apply
only when listed, each at most once (a repeated rule is an `invalid_request`),
in this order:
| Rule | Applies to | Parameter |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| `after-uid-literal` | The literal segment right after a literal `uid`, unless it is a stop word | `uid` |
| `opaque-token` | A lowercase alphanumeric segment of twelve or more characters mixing letters and digits that is not a `v1`-style version | `uid` |
| `sibling-variance` | Groups equal in method, origin and segment count that differ in one literal at index 2 or later; the siblings whose literal is identifier-like (a digit or `:`, or three or more hyphenated names under a plural literal) merge, never a stop word, and the other literals stay their own tools | singular previous literal plus `_id`, else `id` |
With `sibling-variance` selected, literal siblings within its comparison scope
fold into existing opt-in parameters as observed values unless they are stop words.
For example, select both `opaque-token` and `sibling-variance` so
`/api/folders/{uid}` lists `general` beside the recorded token. With only
`opaque-token`, `/api/folders/general` stays a separate literal tool.
A position templated by one of the four format rules
absorbs no literal, so `/api/teams/{numeric}` keeps its exact-format meaning
and `/api/teams/search` stays its own tool. Opt-in placeholders use the
parameter name; format-rule placeholders keep their api-surface spelling. Tool names are
`<method>_<literals>` with `api`, `apis`, `namespaces`, `default`, `v`-prefixed
version tokens and a `uid` literal before a parameter dropped, dotted literals
cut to their first label, `_by_<params>` appended when parameters exist,
sanitized to `[a-z0-9_]`, at most 60 characters and made unique with numeric
suffixes: `get_dashboards_by_uid`, `get_plugins_settings_by_plugin_id`.
`sibling-variance` compares routes of at most 32 segments; longer routes keep
their grouped templates and the manifest says so in a limitation. `body_shape`
is derived for `POST`, `PUT` and `PATCH` from the tool's earliest record when it
carries an `application/json` or `application/*+json` request body: top-level
keys and their JSON type names, never values and never nested structure; a body
on a later record adds nothing. `unknowns` always states three facts: the authorization model, response
semantics and state transitions are not established by a capture.
`templated_groups` counts tools and excluded groups with a templated segment;
whenever it is nonzero the Evidence is inferred, otherwise derived. The view
performs no network activity and replays nothing. Native mitmproxy, SAZ and
qlog captures, and parents inspected with `sensitive_values`, return the same
typed unsupported errors as the api-surface view, including the canonical
token `sensitive_values_unretained`.
The manifest accumulator shares the api-surface admission model: the capture
clone, the inline envelope, record pointers, groups, every route part, observed
values, query names and body-shape keys are admitted before allocation, and each
recorded body is charged as temporary bytes before it is parsed. Retained state and
temporary work must fit together within the 96 MiB projection representation
budget; exceeding it returns `resource_constraint` without a partial manifest.
## Resource and lifecycle boundaries
Complete evidence has a 32 MiB input, 96 MiB decoder reply and 64-level nesting
+30
View File
@@ -1,5 +1,35 @@
# Analysis efficiency measurements
For Hopper literal string queries, see the [decoded-record checkpoint](hopper-string-records.md).
It measures record reuse through real Linux CLI/MCP workflows, preserving
native recognition gaps, guard-stopped attempts and negative whole-task costs.
The [Linux embedding-runtime follow-up](hopper-linux-python-runtime.md) checks
actual clean setup, dependency repair and normal-user analysis, retaining
failed attempts and distinguishing prerequisite correctness from speedups.
For JEB on Linux, see the [CE native audit](jeb-linux-native.md). It qualifies
the direct headless launch route and measures selected function reads through
real CLI and production stdio MCP, preserving timeout attempts and the limits
of wrapper-cache and token claims.
For Apktool locale queries, see the
[shared-decode and table-only checkpoint](apktool-string-tables.md). It separates
the existing decode reuse from duplicate string delivery, with three real APKs,
CLI/MCP parity, whole-task estimates and negative timing results.
For immutable imported native/JavaScript parents, see the
[validation-reuse checkpoint](immutable-parent-validation.md). It measures the
owning format change with the existing retained-query driver, including first
view costs, small cases, unchanged token estimates, and noisy whole-task results.
For authentic old Evidence and mixed investigations, see the
[retained-query checkpoint](retained-investigation-workflows.md).
`retained-investigation.mjs` compares existing complete delivery with selected
pages, including capacity-refusal recovery and original-record round trips.
It records negative model results and separates imported-format validation work
from the query contract.
For genuine Fiddler captures, see the [SAZ selection checkpoint](saz-selection-workflows.md).
`measure.mjs --saz-selection baseline|focused|retained` compares default complete
delivery (including retained-reference recovery), caller-selected ordinals, and
@@ -187,6 +187,7 @@ def main():
'inspect_managed_members', 'inspect_managed_native_boundaries',
'inspect_artifact', 'inspect_wasm_artifact',
'inspect_evm_interface', 'get_evidence_bundle', 'export_evidence_bundle',
'import_evidence_bundle', 'list_unknowns', 'verify_unknown_resolution',
'capture_browser_scenario',
'resolve_containing_procedure', 'analyze_function', 'close_binary']:
config += '[mcp_servers.rea.tools.' + tool + ']\napproval_mode = "approve"\n'
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,171 @@
# Apktool shared decoding and table-only projection
The measured question is the same in every comparison: inspect an APK's
metadata/manifest and its default, German and Brazilian Portuguese string tables.
One existing batch removes repeated decoding. An optional table-only projection
then removes repeated primary strings without changing the selected facts.
This is a static resource-query measurement, not an agent evaluation or a claim
about reconstructing an application's behavior. The machine-readable measured
summary is [apktool-string-tables.json](apktool-string-tables.json).
## Revisions, inputs and execution
- Baseline: `8f7d12e30d63f3d3b4cfe2a90336362841438f56`, latest main at issue start.
- Projection source: `406af90023a545fb280601bf51f445e122c36378`.
- Existing shared decode: [#4777](https://github.com/morluto/rea/issues/4777),
integrated by [#4804](https://github.com/morluto/rea/pull/4804).
- Projection follow-up: [#4982](https://github.com/morluto/rea/issues/4982).
- Linux x86-64, kernel 6.1.0-53-cloud-amd64, Node 24.18.0, npm 11.16.0,
Temurin 21.0.12.1, Apktool 3.0.3. The selected JAR's closeout digest is
`dbf930b076c6b9be08d57c449cacefc3bdd6b71ebd59b3066fc0e1f5b14f9423`;
decoder contents were not independently hashed for every request.
- [newpipe](https://github.com/TeamNewPipe/NewPipe/releases/tag/v0.29.1): 11,507,122 bytes; SHA-256 `18447bfb1e06d113edc88df93f471827280de06f6f3d4dc42f56f28b9c1bab79`. Valid projected counts: 1126/833/779; unsupported entries: 1/1/1.
- [apidemos](https://github.com/appium/android-apidemos/releases/tag/v6.0.18): 6,521,217 bytes; SHA-256 `a9eecf37b26cd084855c530db81c2bb1b91f4c1b095a04f47aa7c20e2791f686`. Valid projected counts: 967/29/29; unsupported entries: 8/0/0.
- [settings](https://github.com/appium/io.appium.settings/releases/tag/v8.2.1): 3,099,589 bytes; SHA-256 `e4024b3ee348929252bcaf5eb422bcab9e4ace96703499a84f3332281c03375f`. Valid projected counts: 25/19/19; unsupported entries: 0/0/0.
The counts are default/de/pt-BR respectively. Source paths, XML digests, exact
caller paths, runtime hashes and per-run identities/costs are in the JSON summary.
The APKs were never installed or executed. Input digests were checked before and
after each completed task; provider-owned workspaces were confirmed absent.
Each task uses a fresh production stdio MCP runtime, complete paginated tool
discovery, client inspection, resource call(s), `close_binary`, transport close
and owned cleanup. OS file caches were not flushed. Every decode has a fresh JVM,
APK snapshot, framework directory and workspace: these are not warm retained
engine/database queries, nor cold-disk measurements.
Tasks run serially on one logical CPU, with an 8 GiB family hard limit, 7 GiB
early stop and no swap. Admission requires 16 GiB host availability; running
tasks stop below 8 GiB host availability. CPU and kernel `memory.peak` cover
the complete owned cgroup, including subprocesses, observer and file cache.
Counters are captured at payload exit while the observer is alive; disappeared
final whole-scope counters remain unknown. All completed payload receipts show
successful owned cleanup and zero observed OOM/limit events at that checkpoint.
## Correctness and owning change
Separate native decodes were retained for independent Python Expat validation.
It checks direct string entries, source entity spelling, unsupported markup
counts, ordering and emitted prefixes against the XML bytes. Manifest text and
package identity are checked separately. All six serial/batch pairs agree on
selected strings, manifest, metadata and target identity. All nine projection
pairs additionally preserve table counts and coverage; batch/table-only counts
and coverage match the XML oracle. This qualifies REA's projection of these
native outputs, not independent binary ARSC decoder completeness.
The existing default batch repeats its primary table in top-level `strings` and
`string_tables[0]`. On NewPipe this made the full resource replies larger than
three serial replies despite reducing decode calls: 616,059 → 680,188 bytes.
ApiDemos' larger common manifest produces the opposite tradeoff. The existing
batch remains the compatibility default.
`string_tables_only: true` (CLI `--string-tables-only`) keeps the complete
requested table facts inline in `string_tables` and leaves `strings` empty by
request. An unrequested field does not establish that a source table is empty.
This also supports one table without `locales`. `include_strings: false` still
suppresses string projection. Omitting the new option preserves old requests:
three real legacy workflows produce identical complete MCP replies, including
Evidence identity, at the new source revision.
The resource projection owner computes the output choice and charges aggregate
entries for the copies actually emitted. The same 10,000-entry policy can thus
return five distinct 2,000-entry tables rather than consuming capacity on a
duplicate primary copy. Per-table limits, XML budgets, physical alias reuse,
coverage, partial observations and cancellation remain at the existing owner.
CLI and MCP share this implementation; there is no new tool or cross-call cache.
## Existing shared decode: three serial calls versus one batch
Three alternating fresh-session pairs per APK, all at the same main revision.
The table reports marginal medians; paired speedups are reported separately.
Elapsed/CPU include discovery, client/Java startup, calls, transcript/hash checks
and cleanup. Native oracle creation, tokenization and verification gates are
separate costs in the JSON, not hidden inside these task timings.
| Target | Resource calls, s | Whole elapsed, s | Whole CPU, s | Family peak, MiB |
| -------- | ----------------: | ---------------: | ------------: | ---------------: |
| newpipe | 23.19 → 7.40 | 35.32 → 19.86 | 34.95 → 19.65 | 1341.7 → 1309.5 |
| apidemos | 17.43 → 6.22 | 30.32 → 18.85 | 30.05 → 18.63 | 1187.1 → 1202.7 |
Paired resource-call speedup medians: NewPipe **3.23×** (2.90–3.23), ApiDemos
**2.80×** (2.66–3.09). Instrumentation confirms three versus one actual decoder
invocations. These call timings include protocol/projection costs; they do not
isolate the Java engine phase. NewPipe's whole raw token estimate increases
951,332 → 962,330 with the default batch; ApiDemos decreases
1,054,893 → 948,591. Fewer calls alone do not establish less context.
## New selector: default batch versus table-only batch
Three alternating pairs per APK; NewPipe repetitions 1/4/3, others 1/2/3.
Repetition 4 replaces a refused start, described below. Both variants still
perform one decode and return the same required facts.
| Target | Resource call, s | Whole elapsed, s | Whole CPU, s | Family peak, MiB |
| -------- | ---------------: | ---------------: | ------------: | ---------------: |
| newpipe | 9.18 → 9.35 | 23.95 → 24.85 | 23.65 → 23.82 | 1327.5 → 1323.6 |
| apidemos | 6.46 → 5.81 | 23.28 → 19.79 | 22.90 → 19.47 | 1247.8 → 1197.0 |
| settings | 4.21 → 4.06 | 17.66 → 19.39 | 17.42 → 19.04 | 1191.6 → 1122.4 |
There is no consistent latency or whole-family memory improvement established
for the selector. NewPipe and Settings have higher whole-task elapsed and CPU
medians. Elapsed ranges overlap: NewPipe 23.53–34.46 → 21.59–42.80 s;
ApiDemos 18.55–27.07 → 19.25–25.96 s; Settings 16.55–23.39 → 16.14–21.72 s.
The cause of this variation was not established; a passing or faster run does
not explain a slower one. The selector's supported benefit is reduced duplicate
delivery, with its full task costs retained here.
Full resource reply bytes fall 680,188 → 506,481 for NewPipe,
616,841 → 463,588 for ApiDemos and 38,725 → 34,199 for Settings.
Offline `tiktoken` 0.12.0 / `cl100k_base` estimates count one complete catalog
page-array plus every call name/argument/reply, including inspection and close.
Full replies include both textual and structured copies. Text-only replies are
also counted separately. These are serialization estimates, not actual model
usage; initialization/framing, prompts, client filtering/rendering/replay and
continuations are unmeasured.
| Target | Text reply tokens | Whole raw transport tokens | Whole estimated reduction |
| -------- | ----------------: | -------------------------: | ------------------------: |
| newpipe | 73,661 → 55,797 | 962,330 → 924,352 | 3.95% |
| apidemos | 65,693 → 49,162 | 948,591 → 913,693 | 3.68% |
| settings | 4,387 → 3,942 | 814,859 → 814,029 | 0.10% |
Discovery still has 207 tools; only `decode_android_resources` changes.
The added schema costs 557 catalog bytes / 113 estimated catalog tokens
(805,217 → 805,330). Raw discovery dominates this transport estimate; it does
not establish what a client supplies to its model. Smaller replies and these
estimates do not prove an actual agent context or investigation advantage.
## Verification, attempts and limits
- 94 source tests: provider/resource projection/service, including alias reads,
aggregate output exhaustion, malformed/physical failures, partial facts,
cancellation and cleanup. The table-only capacity, single-table provider
and CLI cases fail on the old implementation (three selected failures,
82 unrelated tests skipped).
- Nine compiled CLI/MCP tests: schema conversion/advertisement, option forwarding,
Evidence parameters, legacy locale grammar and existing boolean choices.
- 36 completed real MCP tasks and three real CLI tasks. Nine exact projection
oracle pairs; three legacy full-reply comparisons; alias/missing, single-table
and omitted-string cases pass. CLI normalized data, subjects and Evidence IDs
match MCP exactly on all three APKs.
- `check:fast`, `build:cached` and `verify:test-discovery` passed; the last
discovered all 1,579 test files exactly once. `npm run check` and `npm run docs:check` also passed.
- An authored test group initially exceeded the 150-line lint limit (153).
That gate failed after 189.31 s / 186.19 CPU s, peak 4,487,798,784 bytes;
build/compiled checks did not run in that attempt. The capacity test was moved
out of that group, and the complete corrected gate passed after 343.97 s /
338.67 CPU s, peak 4,311,293,952 bytes. No rule was disabled.
- `projection-newpipe-after-2` was refused before scope/payload creation because
host availability was below 16 GiB; a following poll showed about 10.5 GiB.
It has no payload timing/counters and is not a completed measurement. The
refusal stays recorded; a fresh whole repetition-4 pair ran after recovery.
No existing receipts were overwritten and resource thresholds were unchanged.
Raw transcripts, native outputs, intermediate failures and per-request workspace
arguments remain in ignored local audit storage; the committed JSON is a curated
summary. Small Settings resources and negative time results are retained.
Actual models, APK execution, other providers/platforms and general complex
software effectiveness were not verified by this checkpoint.
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,203 @@
# Linux Hopper embedding-runtime qualification
This follow-up to the [string-record audit](hopper-string-records.md) resolves
[#5015](https://github.com/morluto/rea/issues/5015): a successful package install
could leave Hopper unable to start its Python bridge. This is a prerequisite
correctness fix. It does not establish faster equivalent investigations.
## Reproduction and owning correction
Baseline REA `093ce695f0a7c3407c7fde520ed8b20c0981b408` ran the actual public
`rea setup --yes --install-hopper --format json` in a fresh Ubuntu Base root,
with full Linux UID/GID support, successful strict APT metadata refresh,
default APT recommendations and unchanged vendor post-install scripts. Setup
reported `ready` and `installed_hopper`; `dpkg --audit` was empty. Python 3.12
was configured, but its reported `/usr/lib/x86_64-linux-gnu/libpython3.12.so.1.0`
was absent. The signed Hopper package did not declare this dependency.
An actual public MCP control-ELF workflow then timed out at its selected
30-second startup budget. Installing only `libpython3.12` resolved to
`libpython3.12t64` version `3.12.3-1ubuntu0.17`: one new package, no upgrades or
removals. The unchanged REA runtime and target then completed all 13 calls.
The independent earlier bootstrap dialog and controlled package intervention
support the embedding-dependency diagnosis; timing alone does not.
The shared Linux installer now asks `/usr/bin/python3` for its version and
shared-library location after the original package transaction. It attempts an
actual load. For a missing standard Ubuntu ABI/layout it installs the matching
versioned library and verifies loadability again. APT success alone cannot
establish readiness. Unknown metadata, alternate prefixes and alternate SONAMEs
retain an explicit unknown diagnosis instead of guessing a package.
Doctor consumes the same fresh, bounded producer, retaining both private-display
and Python observations. Its Python facts concern the system interpreter;
the interpreter actually selected inside Hopper remains unknown. The query
uses isolated Python mode, disables site hooks and bytecode writes, has a
10-second work deadline and 64-KiB output bound, and is not cached: package/interpreter
changes must be visible immediately. The approval plan discloses the conditional
package change without returning the probe program. Existing MCP analysis
contracts and Evidence semantics are unchanged.
Cancellation prevents starting another install stage and preserves the original
reason. A running package transaction is allowed to settle, avoiding forced
interruption of dpkg. This qualifies the install API's signal behavior through
boundary tests; it does not claim new CLI interrupt plumbing or actual
interruption of a real package transaction.
A review follow-up preserves cancellation through doctor as well. A cancelled
Python probe now raises the existing domain cancellation error with its original
reason and completed private-display observations; the owned doctor workflow
performs cleanup and attaches any cleanup failure. It no longer becomes an
ordinary unknown diagnostic. The probe also opts into the existing
stop-and-wait supervisor: cancellation and timeout wait for Python to exit,
with the shared five-second grace period and forced-kill fallback. A real
Python fixture holds its SIGTERM handler until the test releases it, checking
that the probe retains ownership until exit. The success-path native measurements below precede
this error-branch correction. Its boundary tests cover both successful cleanup
and cleanup refusal; final-head validation is tracked on the PR. A pre-fix red
execution and a final-head native rerun are not claimed.
## Pinned environment and artifacts
Native success measurements pin the initial fix at
`0c70be0030f6bb821c4292c4f5b7f776b365c8ec`, based on main
`23f984b1a884baefc3c44e4ab697f6eff61dffb6`.
The measured runtime and bridge manifest covers 1,733 regular files, 26,537,393
bytes. Its SHA-256 is
`8800edc8e70965ae2132e57ca6d999ba276503f27f1045b33305c83cd0e2ff2a`
(sorted paths, compact sorted-key JSON records containing path, bytes and
SHA-256). The tiny MCP loader alone is not a whole-runtime identity.
Earlier prototype runs have a separately recorded manifest; they are not
presented as executions of that same artifact.
- Node 24.18.0; npm 11.16.0; Debian 12 x86-64 host.
- Official [Hopper 6.6.0 Linux demo](https://www.hopperapp.com:443/downloader/public/Hopper-6.6.0-Linux-demo.deb),
35,748,722 bytes, SHA-256
`59705e50f7ebf9104abe1e72ac3949bed1a8e43ec67a8c9510a1c5056c200d27`.
REA's real publisher verifier authenticated signing fingerprint
`7C2D73BAFAF5B9A710A69DA1A26DF815099B1BCD`; launcher SHA-256
`b2271008fb82bf14cfae5c3644cdde2b11fc6804bd7c99d67032ec1b1942d53c`.
- Private [Ubuntu Base 24.04.5 root](https://cdimage.ubuntu.com/ubuntu-base/releases/24.04/release/ubuntu-base-24.04.5-base-amd64.tar.gz),
SHA-256 `e77b6f10c2590cef872b33ee9f635a0e3fd1f57fb074c0e52b5c7f56147a0c86`,
matched its official HTTPS checksum; its publisher signature was not
independently verified. The host glibc 2.36 cannot run this Hopper package;
the private root supplies glibc 2.39. Related packages were installed only
there. Strict refresh used `APT::Update::Error-Mode=any`.
- Small control ELF: 17,360 bytes, SHA-256
`1a6f55303712e096ff5196c7fd6e8acf75473fbf0f7467d7b315f96f50b3f841`.
GNU objdump independently maps the arithmetic at `0x401126` to
`arg0 * 7 + 13`; the original build flags were not recovered. The known
`rea_jeb_native_probe` literal has one native string hit.
- Shipped Debian SQLite 3.40.1-2+deb12u2, `libsqlite3.so.0.8.6`, 1,437,848
bytes, SHA-256
`2e6eef9a727f081f0d453b4e5e6cbd8b9ef8b6f86cbf7681cbad444d3b0b55c8`.
Independent objdump identifies `sqlite3_libversion_number` at `0xa1d50`,
returning `0x2e6301` (`3040001`). This is a shipped library qualification,
not a claim about current SQLite versions or whole-program correctness.
## Actual workflows and measurements
The accompanying [receipt](hopper-linux-python-runtime.json) preserves native
stage outcomes, elapsed time, CPU time, peak memory, cleanup and token-estimate
scope, including failed and stopped attempts. Installation uses root inside the
owned fixture. Final analysis also uses a normal UID 1004 with a separate home
and the authenticated public publisher evidence copied unchanged into that
user's cache; production verification still checks it. No target was executed
or modified. Non-root package installation through real pkexec authorization,
custom Hopper Python configuration, native Debian installation and other
operating systems remain unverified.
Fresh final setup reported `ready` / `installed_hopper`, installed the matching
shared library, left `dpkg --audit` empty and passed actual public doctor.
Final normal-user sessions completed the positive, repeated, negative and
decompilation checks: 19 `sqlite_master` matches in 1,437 recognized strings,
74 broader `sqlite` matches and the expected version constant. Both CLI runs
matched their MCP facts and Evidence identity; both target files stayed unchanged.
| Stage / outcome | Elapsed (s) | Native CPU (s) | Native peak (MiB) |
| ---------------------------------------------- | ----------: | -------------: | ----------------: |
| Baseline setup: ready, library absent | 75.353 | 39.002 | 1395.4 |
| Baseline control MCP: startup timeout | 49.541 | 24.158 | 1282.5 |
| Install only matching libPython | 5.012 | 1.925 | 174.8 |
| Unchanged runtime control MCP: passed | 24.791 | 23.608 | 1228.4 |
| Fixed fresh setup: ready | 80.739 | 40.404 | 1382.6 |
| Fixed public doctor: healthy | 6.035 | 5.160 | 560.9 |
| Fixed normal-user control MCP: 13 calls passed | 24.434 | 23.305 | 1195.7 |
| Fixed normal-user SQLite MCP: 16 calls passed | 92.504 | 90.138 | 1507.2 |
| Fixed normal-user control CLI: parity passed | 8.981 | 7.831 | 613.5 |
| Fixed normal-user SQLite CLI: parity passed | 70.207 | 68.704 | 781.6 |
Each control MCP session includes discovery and 13 calls: open, status, first
literal query, six repeats, absent query, procedure listing, decompilation and
close. SQLite uses 16 calls: a known exported address avoids a separate name
lookup, and full native string inventory, broader query, regex, case and absence
checks are included. Applicable returned string bytes are checked against the
file. Warm queries must preserve facts and Evidence ID. CLI searches compare
normalized facts and Evidence ID with their corresponding MCP result. Both
target digests are checked after the task.
“Fresh” means a new installation state or Hopper process, as indicated; OS
caches were not flushed. Installation fixtures preload 247 previously fetched
APT archives (138,023,324 bytes) without installing packages. These are not
cold-network benchmarks. The baseline failure and successful repair are
different outcomes, not a paired speedup. This change adds no analysis cache
and makes no token reduction or complex-investigation advantage claim.
Native stages have a 6-GiB container cap, 5-GiB early stop, no swap, 128 tasks,
one CPU and explicit affinity. Their separate controller has a 512-MiB cap,
no swap and 64 tasks. Native plus controller caps total 6.5 GiB. Heavy tasks
run serially; admission waits for at least 16 GiB host availability and aborts
below 8 GiB. Host build/check stages have an 8-GiB cap and 7-GiB early stop.
No other user's processes were signalled.
Native CPU and kernel memory peaks include the container guardian and observer.
Payload-exit observations verify no analysis children remain before stopping
the container. Controller counters are separate partial snapshots; adding
separate peaks is only an upper bound, not a simultaneous measurement. Shared
Docker daemon, containerd and system-manager costs and final counters after
scope removal are unknown. Stopped attempts without payload-exit observations
retain unknown cleanup/counter fields. Observed zero OOM counters at payload
exit are not a claim about the whole host.
## Failed attempts and limits
- A single-ID namespace could not apply the real vendor/package UID/GID
ownership changes. It did not qualify a successful installation.
- An inherited container-loopback proxy prevented publisher downloads; the
fixture was corrected to forward the same configured proxy through the
owned bridge gateway. No global proxy configuration was changed.
- An early APT refresh exited zero with failed-index warnings. It was not
counted as a successful refresh; the strict clean run establishes the result.
- One earlier setup was stopped by the host-memory guard during unpacking.
Its interrupted package state was retained separately; clean fixtures were
used for the qualified baseline and final installations.
- SQLite exceeded a caller-selected 30-second startup budget. With the normal
120-second budget the bridge started, but an initial `libc` positive oracle
failed: those `.dynstr` bytes were not a recognized Hopper string. The
corrected native positive is `sqlite_master`. These attempts remain in the
receipt. Empty recognized-string results do not prove physical absence.
- Early candidate compilation found a TypeScript signal-narrowing error; the
fix reads live signal state through a helper. Lint found oversized new test
groups; they were split by behavior. Failed checks are retained as failures.
- Full local fast checks were stopped twice when other host workloads reduced
available memory. Those attempts did not pass; complete CI and later executed
checks must be reported separately.
- Local package verification completed installation, update, module loading,
discovery and several CLI stages, then the same host-memory guard stopped it
during setup/uninstall after 336.196 seconds (sampled peak 1,742,426,112
bytes). This is an incomplete package gate, despite the separately completed
real Hopper setup and analysis workflows. Its payload-exit counters and
cleanup observation are unknown. CI must complete this gate before merging.
Offline `cl100k_base` estimates include each discovered full catalog, named
arguments and raw replies once per recorded session, plus selected CLI arguments
and stdout. Raw MCP replies can contain both text and structured copies.
The final control and SQLite MCP validation transcripts estimate 845,126 and
1,064,574 tokens respectively, including 805,330 catalog tokens each. The CLI
rows estimate 695 and 2,905 tokens for one selected search each. Those CLI rows
cover different tasks from the multi-call MCP qualification sessions, which
also include full-inventory validation; they do not form an interface-efficiency
comparison. Failed attempts and retries have separate rows in the receipt.
Actual agent/model usage, host schema filtering, protocol framing, prompts,
rendering/replay, independent oracle context and unrecorded in-flight failures
are unmeasured. This is provider qualification, not an agent benchmark.
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,236 @@
# Hopper literal search: reuse decoded records
For [#5010](https://github.com/morluto/rea/issues/5010), the bridge now keeps
the existing decoded records in its sorted search inventory and projects only
matches. Previously, every positive literal search called `_string_inventory`
again, sorting all native object addresses and building another complete map
before selecting records. The value-only `_strings` representation and the
intermediate match list have been removed.
This removes repeated work at its owner. Three paired SQLite workflows found
shorter warm queries, but **did not demonstrate an overall task speedup**:
whole elapsed and CPU were worse. Token estimates were effectively unchanged; no memory
improvement was established. The [curated receipt](hopper-string-records.json)
keeps individual measurements, equality checks and failed attempts.
## Representation and reuse boundary
The existing `(id(document), kind)` search cache now holds references to full
records rather than just their decoded values. The existing string-record
owner still performs byte decoding, encoding inference and unknown handling.
Matching reads `record.value`; output copies the selected record with its
address, retaining native display, encoding/extent metadata and decoding
failures. The original document lifetime and annotation invalidation apply.
This does not add another cache or duplicate decoded payloads. Both CLI and
MCP use the same bridge through the existing application workflow. Regex keeps
its supervised worker implementation.
The lookup remains a linear scan of recognized native strings. A complete
inventory is still decoded for the first exhaustive search, and returned hits
still consume output and retained Evidence. This change does not introduce
pagination, broader binary string discovery or a new context contract.
## Pinned real-provider scope
Baseline: REA 6.7.0 at `c12d9eda87aa5a022ee7e18ea96d8d03bfd12e96`, Node
24.18.0, Debian 12 x86-64, Linux `6.1.0-53-cloud-amd64`. All paired tasks used
the same compiled runtime SHA-256
`0809b5004f214efa4b79775d5fda796eaecf4ad5756c55ee3b9d7cf82d91b750`.
Baseline and candidate bridge digests are recorded separately in the receipt;
the baseline file was mounted read-only over the bridge for baseline runs.
The official [Hopper 6.6.0 Linux demo package](https://www.hopperapp.com:443/downloader/public/Hopper-6.6.0-Linux-demo.deb)
was authenticated through REA's production publisher verifier: 35,748,722
bytes, SHA-256
`59705e50f7ebf9104abe1e72ac3949bed1a8e43ec67a8c9510a1c5056c200d27`,
primary signing fingerprint `7C2D73BAFAF5B9A710A69DA1A26DF815099B1BCD`.
The extracted launcher digest was
`b2271008fb82bf14cfae5c3644cdde2b11fc6804bd7c99d67032ec1b1942d53c`.
Normal demo activation used an owned private Xvfb display.
The host's glibc 2.36 could not satisfy this package's GLIBC_2.38 requirement.
Analysis therefore ran in a user-mapped private Ubuntu Base 24.04.5 namespace
with glibc 2.39, Qt6/X11 and embedded Python 3.12. The
[rootfs archive](https://cdimage.ubuntu.com/ubuntu-base/releases/24.04/release/ubuntu-base-24.04.5-base-amd64.tar.gz)
matched its official HTTPS checksum, SHA-256
`e77b6f10c2590cef872b33ee9f635a0e3fd1f57fb074c0e52b5c7f56147a0c86`;
its publisher signature was not independently verified. Related libraries were
installed only into that private image. Actual `rea setup` and vendor package
post-install scripts were not executed. Native Debian installation and other
operating systems remain unqualified.
| Artifact | Bytes | Independent oracle |
| ------------------------------------ | --------: | -------------------------------------------------------- |
| Small authored C ELF | 17,360 | Source `input * 7 + 13` and ELF symbol |
| Source-built conformance ELF | 22,584 | Fixture source, known literal bytes and symbol addresses |
| Shipped Debian `libsqlite3.so.0.8.6` | 1,437,848 | GNU objdump: version function returns `3040001` |
Artifact digests, compiler and flags are in the receipt. No target was executed.
The small ELF was a baseline setup/decompilation smoke test; the conformance
ELF had baseline/candidate semantic and CLI/MCP checks. SQLite supplied the
repeated performance cohort. A constant-return oracle does not establish
whole-program correctness, ABI inference or complex-investigation effectiveness.
## Completed task and correctness
Each of three baseline/candidate pairs used a fresh Hopper process and the
same public stdio MCP workflow, including catalog discovery and 17 tool calls:
1. Open the SQLite copy and inspect `binary_session`.
2. Search `sqlite_master` in case-sensitive literal mode, then repeat six times.
3. Read `list_strings` as a full-inventory validation oracle; compare all
matching records, including their metadata, with the selected result.
4. Check broader `sqlite` search, regex, case-insensitive and absent-pattern
queries against their expected native inventory scope.
5. Resolve `sqlite3_libversion_number`, decompile it, check its constant against
independent objdump, and close the binary and MCP transport.
6. Verify unchanged target bytes and cleanup of the owned process family.
There were 1,437 recognized string objects, 19 `sqlite_master` matches and 74
broader `sqlite` matches. Applicable decoded hit bytes were also checked
against file contents. All 42 Evidence payloads across the three pairs matched
on normalized and raw facts, identity, subject, provider/profile, authority,
confidence, limitations, relationship coverage, locations and evidence links.
Live environment observations were excluded from cross-session equality.
The real conformance workflows each completed 70 public calls, including six
expected errors. They exercised Unicode symbol identity, literal metacharacters,
case/regex modes, annotation cache invalidation, typed string fragments,
display escaping and source-byte checks using the existing real-provider
verifier. CLI `fragment_tail` search returned the same normalized facts and
Evidence ID as MCP on both revisions (2,293 stdout bytes each).
Native recognition remains qualified: the full 4,120-byte source literal and
some known UTF-8, ellipsis and Latin-1 literals were not recognized. Their file
bytes were verified, while decoded native-object coverage remains unverified.
The fragmented 549-byte source literal was recognized as separate objects;
matching does not pretend to join those fragments. Escaped text and literal
backslash-n were distinguished. Real UTF-16 provider decoding was not qualified;
the focused boundary fixture covers that representation separately. Empty
search results establish absence only within the native typed-object inventory.
## Measurements
Runs were serial and ordered B1/C1, C2/B2, B3/C3. C2 first stopped under the
host memory guard; its separate completed retry supplies the C2 row. OS caches
were not flushed. “Cold” means the first string query in a fresh provider;
“warm” means six repeats within that provider.
Medians across the three completed sessions per revision:
| Cost | Baseline | Candidate |
| ---------------------------------------- | ----------: | ----------: |
| Per-run median warm query | 14.849 ms | 12.628 ms |
| Six warm queries, total | 100.202 ms | 75.552 ms |
| Whole SDK workflow | 86.583 s | 90.786 s |
| Whole guarded workflow | 89.384 s | 93.630 s |
| Family CPU at payload exit | 88.333 s | 92.590 s |
| Kernel family peak, including file cache | 1,438.4 MiB | 1,440.0 MiB |
Warm-query medians were lower in all three pairs, although one baseline run
was particularly variable. Whole guarded elapsed was about 4.7% worse and CPU
about 4.8% worse. The first query accounted for 65.2–71.2 seconds on baseline
and 72.3–77.5 seconds on candidate; that interval includes native preparation.
Do not interpret this cohort as end-to-end acceleration or dismiss the
unfavorable rows.
A separate pair moved the **existing** `procedure_address` call before the
first string search, keeping the same 17 calls and equivalent facts/Evidence.
Most preparation cost then occurred in that unchanged lookup: 67.949 seconds
baseline versus 94.358 seconds candidate, before the changed search path ran.
The subsequent first string query took 329.254 versus 337.533 ms; total guarded
elapsed was 89.096 versus 113.917 seconds. This locates substantial cost outside
literal projection and preserves the negative whole-task result. It does not
prove its cause, establish a cold-query improvement or justify pooling the
reordered pair with the original cohort.
## Resource and context accounting
Every heavy task used an owned cgroup v2 family: 8 GiB hard limit, 7 GiB early
stop, zero swap, one CPU quota and affinity, 192 tasks, 3,072 MiB Node heap,
and one heavy job at a time. Host admission required 16 GiB available; tasks
stopped below 8 GiB. Later long runs added admission at 24 GiB sustained for
20 seconds without relaxing the family guard.
Family counters include the namespace, native engine, MCP client/runtime,
validation and cleanup, including charged file cache. SDK wall time includes
catalog discovery and correctness assertions. Admission wait is outside the
guarded time and recorded separately where available; older waits and outer
guard/systemd costs were not measured. Payload-exit CPU, kernel memory peak,
limit counters and owned cleanup were verified while an observer remained.
Final counters after the scope disappeared remain unknown. Completed paired
payloads observed zero memory-limit, OOM/OOM-kill and task-limit events.
The unchanged catalog advertised 207 tools, 3,158,927 serialized bytes,
SHA-256 `a1851aa1bfe3d72d6be6bec130519dbdfc1ee49288320cfac0144ced77755c61`.
Offline tiktoken 0.12.0 `cl100k_base` estimates for every completed SQLite
comparison were effectively unchanged (medians across three runs):
| Serialization counted once | Baseline estimate | Candidate estimate |
| -------------------------------------------------- | ----------------: | -----------------: |
| Full catalog page array | 805,330 | 805,330 |
| Named tool requests | 361 | 361 |
| Raw replies | 259,809 | 259,811 |
| Total above | 1,065,500 | 1,065,502 |
| Text reply blocks alone, overlapping the raw count | 126,832 | 126,833 |
Whole raw estimates ranged from 1,065,496–1,065,500 on baseline and
1,065,500–1,065,506 on candidate. The small variations include live environment
observations; there is no context reduction.
The full inventory and extra controls are validation overhead included in
these totals. Raw replies may contain text and structured copies. Actual model
usage, prompts, initialization/protocol framing, client filtering/rendering or
replay and independent-oracle context were not measured. The receipt separates
other tasks and the interrupted transcript's persisted lower bound; it does
not count an unrecorded in-flight request or reply as observed. No model-token
saving or agent-reasoning advantage is claimed.
## Failed attempts and verification
The receipt preserves setup, diagnostic, failed and completed costs separately:
- Initial private-rootfs configuration failed on an unmapped package GID, then
on the harness PATH; ordinary pending configuration completed successfully.
- One low-host-memory probe was refused before creating a payload.
- The first MCP harness used a relative path, correctly refused by the public
input boundary. A later custom-runtime launch lacked libXtst6, which the
production dependency list already includes. Both were harness/setup errors.
- Two unchanged-baseline launches timed out at bridge startup. An owned-display
observation showed completed native analysis but a Python bootstrap failure.
Adding only the missing embedded Python library made the baseline pass;
[#5015](https://github.com/morluto/rea/issues/5015) records the separate
installer dependency hypothesis and its unverified actual-installer scope.
- C2 stopped after 82.607 seconds when host available memory crossed the
unchanged stop threshold. Its sampled family peak was 1,517,019,136 bytes
and last observed CPU 78.255 seconds. Payload-exit/final counters are unknown;
it is incomplete and excluded from completed-run statistics.
- An initial `test:local` invocation rejected built boundary projects before
running tests. The documented `test:focused` invocation then passed all
35 tests in five files, covering string search, regex, bridge facade and
real-provider verifier behavior. Those local tests do not themselves qualify
a native engine; the public native workflows above provide that evidence.
`npm run check:fast` also passed (typecheck and lint both cached). Build and
metadata preparation passed before the native workflows. `npm run docs:check`
passed its cached metadata checks and all five README consistency tests.
Reproduction uses `node scripts/rea.mjs --mcp` with an explicitly configured
Hopper launcher and private display. Drive the named calls above with absolute
target paths, retain full replies and compare independently verified bytes,
facts and Evidence. For the source fixture, compile
`tests/conformance/c/fixture.c` with
`gcc -O0 -g -fno-inline -fno-omit-frame-pointer -fno-pie -no-pie`.
Debug build paths can change rebuilt artifact digests. The shipped SQLite
digest pins the measured artifact rather than every build of its package.
The focused local gate was:
```sh
npm run test:focused -- \
tests/boundary/providers/hopper/hopperStringSearch.test.ts \
src/hopper/HopperRegexSearch.test.ts \
tests/boundary/providers/hopper/hopperBridgeFacade.test.ts \
tests/conformance/providers/hopper/realHopperSearch.test.ts \
tests/conformance/providers/hopper/realHopperExhaustiveSearch.test.ts
```
@@ -0,0 +1,654 @@
{
"issue": "https://github.com/morluto/rea/issues/4810",
"baseline": "2c4338db1fdb7773e05376301c558cff2a0b4b80",
"candidate": "3930a640fb8387cbd3079eee13fb90f82d1881dc",
"units": {
"latency": "milliseconds",
"elapsed_cpu": "seconds",
"memory": "kernel cgroup memory.peak bytes, including charged file cache and descendants"
},
"scope": "Three alternating before/after pairs per authentic retained native/JavaScript/small workflow; fresh stdio servers, three traversals of three two-row pages; catalog/import/oracles/export/close included in whole cost. OS caches uncontrolled. No actual model trial.",
"resource_bounds": {
"cpu_count": 1,
"hard_memory_bytes": 8589934592,
"early_stop_bytes": 7516192768,
"swap_bytes": 0,
"tasks_max": 192,
"host_start_available_bytes_min": 17179869184,
"host_stop_available_bytes_min": 8589934592,
"observer_sha256": "6f089e645459eba80c5d73e39c21606c78173a44daf49fabc3b88c4631ce51c6",
"guard_sha256s": [
"760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992",
"d2047721e50dd244900eb514d07025386e60908f77bb546bee5684baa1da2f19"
],
"guard_observability_note": "The newer private guard only records existing host-available-memory readings and its own cgroup path. Resource thresholds, CPU affinity, observer and stop/cleanup logic are unchanged."
},
"resource_accounting": "Final complete corpus tasks exit0/cleanup verified/oom0 at payload exit while observer remains alive. Resource-stopped and earlier failed attempts are recorded separately; terminal whole-scope counters are unavailable. Weak cache metadata/private heap not measured independently.",
"catalog": {
"tools": 207,
"bytes": 3158368,
"sha256": "1d6c9a679b7c935318f5ea59d5362ef0a06945b3f4a4f210c86997ec15ba4f4c",
"equal_across_all_18_runs": true
},
"facts": {
"native": {
"answer_sha256": "4e28c2c2a25620576d27abe846a05835ec49386b889779e33410c31971523b54",
"calls": 25,
"query_structured_content_equal": true,
"original_records_preserved": true,
"closed_session_cleared": true
},
"javascript": {
"answer_sha256": "0fe3ad249eb1a7233a4966a56652c173667c48fdaf395b6c08fc6901ef3b46f7",
"calls": 28,
"query_structured_content_equal": true,
"original_records_preserved": true,
"closed_session_cleared": true
},
"small": {
"answer_sha256": "9ca5874ce7bb610e39632157304fe4f52b09401d5fbd97ec981ad0588b8da485",
"calls": 19,
"query_structured_content_equal": true,
"original_records_preserved": true,
"closed_session_cleared": true
}
},
"runs": [
{
"name": "topology-paired-after-javascript-1",
"first_page_ms": 2720.542831999999,
"eight_later_pages_ms": 82.69408900000417,
"elapsed_seconds": 20.713,
"family_cpu_seconds": 20.50093,
"family_peak_bytes": 1311358976,
"import_ms": 10970.411619,
"catalog_ms": 1194.7045099999996,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-paired-after-javascript-2",
"first_page_ms": 1978.732818999999,
"eight_later_pages_ms": 84.12934999999197,
"elapsed_seconds": 20.011,
"family_cpu_seconds": 19.733879,
"family_peak_bytes": 1349349376,
"import_ms": 10382.461203,
"catalog_ms": 1436.8567430000003,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-paired-after-javascript-4",
"first_page_ms": 1864.8931889999985,
"eight_later_pages_ms": 75.18833300000188,
"elapsed_seconds": 23.023,
"family_cpu_seconds": 22.22643,
"family_peak_bytes": 1410211840,
"import_ms": 10857.059245,
"catalog_ms": 2247.621502,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-paired-after-native-1",
"first_page_ms": 216.87685000000056,
"eight_later_pages_ms": 85.03580100000181,
"elapsed_seconds": 17.253,
"family_cpu_seconds": 17.002728,
"family_peak_bytes": 1003585536,
"import_ms": 10361.605091,
"catalog_ms": 1289.5255869999992,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-paired-after-native-2",
"first_page_ms": 209.0475239999996,
"eight_later_pages_ms": 89.01302899999973,
"elapsed_seconds": 14.383,
"family_cpu_seconds": 14.091764,
"family_peak_bytes": 1031806976,
"import_ms": 7696.751557,
"catalog_ms": 1175.233292,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-paired-after-native-3",
"first_page_ms": 203.10824999999932,
"eight_later_pages_ms": 65.1013469999998,
"elapsed_seconds": 14.061,
"family_cpu_seconds": 13.773228,
"family_peak_bytes": 1098002432,
"import_ms": 7967.397724,
"catalog_ms": 1246.0458209999997,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-paired-before-javascript-1",
"first_page_ms": 1681.2564180000008,
"eight_later_pages_ms": 10378.131188999992,
"elapsed_seconds": 31.213,
"family_cpu_seconds": 30.872607,
"family_peak_bytes": 1618685952,
"import_ms": 11051.493961999999,
"catalog_ms": 1508.7439510000004,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-paired-before-javascript-2",
"first_page_ms": 2441.075147000003,
"eight_later_pages_ms": 15534.410540000004,
"elapsed_seconds": 40.856,
"family_cpu_seconds": 40.485251,
"family_peak_bytes": 1364238336,
"import_ms": 15032.366213,
"catalog_ms": 1319.6895839999997,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-paired-before-javascript-4",
"first_page_ms": 2479.6895360000017,
"eight_later_pages_ms": 16864.908822999998,
"elapsed_seconds": 39.629,
"family_cpu_seconds": 39.267656,
"family_peak_bytes": 1403023360,
"import_ms": 12437.073842999998,
"catalog_ms": 1212.8024130000003,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-paired-before-native-1",
"first_page_ms": 170.1303939999998,
"eight_later_pages_ms": 469.8933869999928,
"elapsed_seconds": 19.996,
"family_cpu_seconds": 19.55106,
"family_peak_bytes": 1063051264,
"import_ms": 11242.171146,
"catalog_ms": 1922.7818150000003,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-paired-before-native-2",
"first_page_ms": 183.56196199999977,
"eight_later_pages_ms": 393.4744759999994,
"elapsed_seconds": 15.26,
"family_cpu_seconds": 15.008304,
"family_peak_bytes": 1058492416,
"import_ms": 8713.099498,
"catalog_ms": 1272.265849,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-paired-before-native-3",
"first_page_ms": 244.26586400000087,
"eight_later_pages_ms": 517.9172599999911,
"elapsed_seconds": 19.083,
"family_cpu_seconds": 18.752553,
"family_peak_bytes": 1109987328,
"import_ms": 9948.476274999999,
"catalog_ms": 1879.787958,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-after-small-1",
"first_page_ms": 226.6032009999999,
"eight_later_pages_ms": 57.69190299999718,
"elapsed_seconds": 12.312,
"family_cpu_seconds": 12.043895,
"family_peak_bytes": 1056452608,
"import_ms": 6572.925846000001,
"catalog_ms": 1173.0129960000004,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-after-small-2",
"first_page_ms": 556.2178050000002,
"eight_later_pages_ms": 96.23635600000307,
"elapsed_seconds": 16.246,
"family_cpu_seconds": 16.068419,
"family_peak_bytes": 1002749952,
"import_ms": 9666.640497,
"catalog_ms": 1821.1315130000003,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-after-small-4",
"first_page_ms": 111.79372199999852,
"eight_later_pages_ms": 62.58284999999887,
"elapsed_seconds": 11.901,
"family_cpu_seconds": 11.707784,
"family_peak_bytes": 976646144,
"import_ms": 6473.91882,
"catalog_ms": 1203.5203539999998,
"guard_sha256": "d2047721e50dd244900eb514d07025386e60908f77bb546bee5684baa1da2f19"
},
{
"name": "topology-before-small-1",
"first_page_ms": 242.57812199999898,
"eight_later_pages_ms": 299.467095,
"elapsed_seconds": 17.585,
"family_cpu_seconds": 17.312434,
"family_peak_bytes": 1066864640,
"import_ms": 9102.074585,
"catalog_ms": 1829.971928,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-before-small-2",
"first_page_ms": 133.3346359999996,
"eight_later_pages_ms": 122.92684500000178,
"elapsed_seconds": 14.302,
"family_cpu_seconds": 13.936122,
"family_peak_bytes": 1062400000,
"import_ms": 7254.973107,
"catalog_ms": 1170.888121,
"guard_sha256": "760d541c60f4c0538f9c015964196e3be7bba12316f6085903244354e11aa992"
},
{
"name": "topology-before-small-4",
"first_page_ms": 100.81227200000103,
"eight_later_pages_ms": 76.37957900000038,
"elapsed_seconds": 12.0,
"family_cpu_seconds": 11.765305,
"family_peak_bytes": 983314432,
"import_ms": 6614.461618999999,
"catalog_ms": 1138.6469730000003,
"guard_sha256": "d2047721e50dd244900eb514d07025386e60908f77bb546bee5684baa1da2f19"
}
],
"token_estimates": {
"tokenizer": "tiktoken",
"version": "0.12.0",
"encoding": "cl100k_base",
"kind": "offline raw transport serialization estimate; one complete catalog plus each call name/arguments/reply exactly once; excludes initialization/framing, prompts, client rendering/discovery/replay, continuations and actual model usage; not an agent-token measurement",
"runs": [
{
"run": "topology-paired-before-native-1",
"catalog_tokens_estimated": 805215,
"named_call_arguments_tokens_estimated": 1200,
"reply_tokens_estimated": 43321,
"total_tokens_estimated": 849736,
"calls": 25
},
{
"run": "topology-paired-after-native-1",
"catalog_tokens_estimated": 805215,
"named_call_arguments_tokens_estimated": 1200,
"reply_tokens_estimated": 43321,
"total_tokens_estimated": 849736,
"calls": 25
},
{
"run": "topology-paired-before-javascript-1",
"catalog_tokens_estimated": 805215,
"named_call_arguments_tokens_estimated": 1354,
"reply_tokens_estimated": 49815,
"total_tokens_estimated": 856384,
"calls": 28
},
{
"run": "topology-paired-after-javascript-1",
"catalog_tokens_estimated": 805215,
"named_call_arguments_tokens_estimated": 1354,
"reply_tokens_estimated": 49815,
"total_tokens_estimated": 856384,
"calls": 28
},
{
"run": "topology-before-small-1",
"catalog_tokens_estimated": 805215,
"named_call_arguments_tokens_estimated": 1118,
"reply_tokens_estimated": 33970,
"total_tokens_estimated": 840303,
"calls": 19
},
{
"run": "topology-after-small-1",
"catalog_tokens_estimated": 805215,
"named_call_arguments_tokens_estimated": 1118,
"reply_tokens_estimated": 33970,
"total_tokens_estimated": 840303,
"calls": 19
}
]
},
"mixed_verification": [
{
"scenario": "native",
"heads_checked": 64,
"pages": 32,
"revised_unknown_id": "unk_057c8f2dbf30ec98851a66ee054366bc6e2e168874581e6f99cb80673d0ff9b8",
"revision_checked": 2,
"stale_update_rejected": true,
"tampered_import_rejected_atomically": true,
"unknowns_after_close": 0,
"old_reference_refused": true
},
{
"scenario": "javascript",
"heads_checked": 64,
"pages": 32,
"revised_unknown_id": "unk_057c8f2dbf30ec98851a66ee054366bc6e2e168874581e6f99cb80673d0ff9b8",
"revision_checked": 2,
"stale_update_rejected": true,
"tampered_import_rejected_atomically": true,
"unknowns_after_close": 0,
"old_reference_refused": true
}
],
"cli_parity": [
{
"scenario": "native",
"exact_json_equal": true,
"exact_bytes_equal": true,
"bytes": 7316,
"sha256_before": "eada9068db3b499da332b2c5226fdd3a48909ebcaa290fd72166325e2f664fca",
"sha256_after": "eada9068db3b499da332b2c5226fdd3a48909ebcaa290fd72166325e2f664fca",
"evidence_id": "ev_521a58e81427bb4b2c01b6a291bdfd7698068ee0eba371696daa9cc5ab32f3f0",
"evidence_links": [
"ev_14b4582084e425b597bea6246f0df94ab4856ac3ab9502c96551147210ca9c8b"
]
},
{
"scenario": "javascript",
"exact_json_equal": true,
"exact_bytes_equal": true,
"bytes": 8876,
"sha256_before": "1dc023e5ece8f9c8cea736cb0db4d4f60c9418f1573e1e46ff0ac55a4273cb5a",
"sha256_after": "1dc023e5ece8f9c8cea736cb0db4d4f60c9418f1573e1e46ff0ac55a4273cb5a",
"evidence_id": "ev_97cac46d5139f6c48c3142798087814dcf36a37a9c99f7253668576bd3ae282a",
"evidence_links": [
"ev_dd2ffe5ab2faa6e07e422886f64a87f99e35a0a1dce1acb5351b7a81cb2c9a11"
]
},
{
"scenario": "small",
"exact_json_equal": true,
"exact_bytes_equal": true,
"bytes": 7181,
"sha256_before": "00dd070690e7b113e0cad73f9f7bcda6f42c515f8fdcc5173e8815bd3748b084",
"sha256_after": "00dd070690e7b113e0cad73f9f7bcda6f42c515f8fdcc5173e8815bd3748b084",
"evidence_id": "ev_3dcbcc5b2002f1e6caf7df005e3fcfd06a3afe14ccd72fff924c8e76d8498914",
"evidence_links": [
"ev_775d6cc6d0de96402b6e57a4258a0b78c337cfb1b7760aa22c39c3ee450c7dff"
]
}
],
"stopped_source_validation": {
"reason": "Started during initial before-javascript-3; stopped only the new owned validation scope, then retried serially. Baseline repetition3 retained but excluded from uncontended exploratory comparisons; all final cohort runs retained.",
"status": "incomplete, shell reported exit241; no payload-completion receipt",
"elapsed_seconds": 17.272,
"family_cpu_seconds_last_observed": 12.204013,
"peak_cgroup_bytes_sampled": 589766656,
"final_scope_counters": null
},
"exploratory_costs": {
"completed_tasks": 21,
"elapsed_seconds_total": 649.262,
"family_cpu_seconds_total": 599.762599,
"family_peak_bytes_max": 1741795328,
"comparison_status": "Earlier candidate and exploratory inputs; excluded from final comparison, raw individual reports retained in private audit cache.",
"contended_baseline_task": {
"name": "before-javascript-3",
"revision": "2c4338db1fdb7773e05376301c558cff2a0b4b80",
"status": "passed",
"elapsed_seconds": 100.722,
"family_cpu_seconds": 82.656181,
"family_peak_bytes": 1290514432,
"excluded_from_final_comparison": true
}
},
"runtime_entry_sha256": {
"before": "1586cea18f4d4702c949502cfc143a7dfd2c28414779e190ce8a42fedf90bd74",
"after": "e05c70bed21c680445a5c6e314a16cce6f22f3909f93388bf602338062e63d1a"
},
"inputs": {
"native": {
"bundle_sha256": "180c6fe6d3706d9272c8bb33503c2dca6f145d5061e102e3457dd5f2d754b5c9",
"bundle_bytes": 1745224,
"source_evidence_id": "ev_14b4582084e425b597bea6246f0df94ab4856ac3ab9502c96551147210ca9c8b"
},
"javascript": {
"bundle_sha256": "747ff602093a24d4876e3eb47da3f7ef68716a10ac7c09938f43c3be5c33e31d",
"bundle_bytes": 21058430,
"source_evidence_id": "ev_dd2ffe5ab2faa6e07e422886f64a87f99e35a0a1dce1acb5351b7a81cb2c9a11"
},
"small": {
"bundle_sha256": "44ca561c2455706897d2ae8f51f45693e7276badd5e8454ec31d8c1b0cfb77eb",
"bundle_bytes": 73051,
"source_evidence_id": "ev_775d6cc6d0de96402b6e57a4258a0b78c337cfb1b7760aa22c39c3ee450c7dff"
}
},
"validation": {
"source": {
"executed": "130 source tests across5files; check:fast; build:cached",
"elapsed_seconds": 334.264,
"family_cpu_seconds": 326.441674,
"family_peak_bytes": 4487696384,
"payload_exit_code": 0,
"payload_cleanup_verified": true,
"oom_events_at_payload_exit": 0
},
"compiled_boundary": {
"executed": "36 CLI/MCP tests across4files",
"elapsed_seconds": 93.343,
"family_cpu_seconds": 91.926502,
"family_peak_bytes": 2190270464,
"payload_exit_code": 0,
"payload_cleanup_verified": true,
"oom_events_at_payload_exit": 0
},
"full_checks": {
"source": "3930a640fb8387cbd3079eee13fb90f82d1881dc",
"executed": "npm run check; npm run docs:check (five README consistency tests)",
"elapsed_seconds": 45.552,
"family_cpu_seconds": 43.309041,
"family_peak_bytes": 1127768064,
"payload_exit_code": 0,
"payload_cleanup_verified": true,
"oom_events_at_payload_exit": 0
},
"integration_current": {
"source": "3930a640fb8387cbd3079eee13fb90f82d1881dc",
"executed": "npm run test:focused -- three latest-main integration files; default test deadlines; 27 passed",
"elapsed_seconds": 62.437,
"family_cpu_seconds": 61.506209,
"family_peak_bytes": 1846538240,
"payload_exit_code": 0,
"payload_cleanup_verified": true,
"oom_events_at_payload_exit": 0
}
},
"comparison_probe": {
"scope": "Candidate-only internal JSON-owner regression, not baseline public-provider reproduction. Reflect.ownKeys instrumentation aborts at10000 inspections rather than consuming exponential CPU.",
"objects_per_graph": 27,
"before_candidate": "e30a94a4de6a3c4ec7c577c1551d2b448d82081e",
"before_inspections": 10001,
"before_status": "probe inspection budget exhausted",
"after_candidate": "646312dad75e2cb2becb0dd4139b99a1c04d6bcc",
"after_inspections": 54,
"after_borrowed": true
},
"main_integration": {
"main_commit": "bb212ffecb47e129cc569b9867b2b6e7c9b65685",
"merge_commit": "71e0b2739a9cf9903e1cfa63dc5a5b576040fea7",
"production_files_unchanged_from_measured_candidate": true,
"scope": "Historical integration at71e0b2739 with production source646312dad; all attempts retained. Current source-specific checks are listed separately.",
"attempts": [
{
"case": "initial_feature",
"entrypoint": "npm run test:focused",
"test_timeout_override_ms": null,
"tests_passed": 26,
"tests_failed": 1,
"tests_skipped": 0,
"payload_exit_code": 1,
"elapsed_seconds": 139.805,
"family_cpu_seconds": 125.252141,
"family_peak_bytes": 1994223616,
"payload_cleanup_verified": true,
"oom_events_at_payload_exit": 0
},
{
"case": "isolated_main",
"entrypoint": "vitest run; one named test",
"test_timeout_override_ms": null,
"tests_passed": 1,
"tests_failed": 0,
"tests_skipped": 10,
"payload_exit_code": 0,
"elapsed_seconds": 25.96,
"family_cpu_seconds": 25.502365,
"family_peak_bytes": 1221394432,
"payload_cleanup_verified": true,
"oom_events_at_payload_exit": 0
},
{
"case": "direct_main",
"entrypoint": "vitest run; three files",
"test_timeout_override_ms": null,
"tests_passed": 27,
"tests_failed": 0,
"tests_skipped": 0,
"payload_exit_code": 0,
"elapsed_seconds": 68.868,
"family_cpu_seconds": 68.020337,
"family_peak_bytes": 1605603328,
"payload_cleanup_verified": true,
"oom_events_at_payload_exit": 0
},
{
"case": "extended_feature",
"entrypoint": "vitest run; three files",
"test_timeout_override_ms": 120000,
"tests_passed": 27,
"tests_failed": 0,
"tests_skipped": 0,
"payload_exit_code": 0,
"elapsed_seconds": 75.866,
"family_cpu_seconds": 75.193788,
"family_peak_bytes": 1937674240,
"payload_cleanup_verified": true,
"oom_events_at_payload_exit": 0
},
{
"case": "exact_main",
"entrypoint": "npm run test:focused",
"test_timeout_override_ms": null,
"tests_passed": 27,
"tests_failed": 0,
"tests_skipped": 0,
"payload_exit_code": 0,
"elapsed_seconds": 66.443,
"family_cpu_seconds": 65.304325,
"family_peak_bytes": 2055409664,
"payload_cleanup_verified": true,
"oom_events_at_payload_exit": 0
},
{
"case": "exact_feature",
"entrypoint": "npm run test:focused",
"test_timeout_override_ms": null,
"tests_passed": 27,
"tests_failed": 0,
"tests_skipped": 0,
"payload_exit_code": 0,
"elapsed_seconds": 66.878,
"family_cpu_seconds": 66.012242,
"family_peak_bytes": 1907380224,
"payload_cleanup_verified": true,
"oom_events_at_payload_exit": 0
}
],
"measured_production_commit": "646312dad75e2cb2becb0dd4139b99a1c04d6bcc"
},
"small_cache_diagnostic": {
"scope": "Additional real public MCP run with return-preserving WeakSet method instrumentation. Timings excluded from before/after comparison. Owner identified from captured add stack; raw trace retained privately.",
"format_owner": "safeParseOwnedBinaryLayout",
"source_objects": 1,
"successful_admissions": 1,
"misses": 1,
"hits": 8,
"queries": 9,
"original_records_preserved": true,
"closed_session_cleared": true,
"small_workflow_latency_regression_retained": true,
"measured_production_commit": "646312dad75e2cb2becb0dd4139b99a1c04d6bcc"
},
"previous_checkpoints": [
{
"production_commit": "e30a94a4de6a3c4ec7c577c1551d2b448d82081e",
"report_commit": "3f271efdef8d71020bdcfd7b2d3d9817bf0a6ad8",
"report_url": "https://github.com/morluto/rea/blob/3f271efdef8d71020bdcfd7b2d3d9817bf0a6ad8/experiments/analysis-efficiency/immutable-parent-validation.json",
"completed_paired_tasks": 18,
"elapsed_seconds_total": 498.234,
"family_cpu_seconds_total": 477.513448,
"family_peak_bytes_max": 1519980544,
"scope": "Historical candidate before shared-node comparison memoization; every result retained, including slow npm repetition3. Not the final comparison."
},
{
"production_commit": "646312dad75e2cb2becb0dd4139b99a1c04d6bcc",
"report_commit": "fc55be1e05555c6b295209ef5f354617f663b8f8",
"report_url": "https://github.com/morluto/rea/blob/fc55be1e05555c6b295209ef5f354617f663b8f8/experiments/analysis-efficiency/immutable-parent-validation.json",
"completed_paired_tasks": 18,
"elapsed_seconds_total": 483.511,
"family_cpu_seconds_total": 458.990461,
"family_peak_bytes_max": 1598119936,
"scope": "Historical candidate before shared-node comparison memoization; every result retained, including slow npm repetition3. Not the final comparison."
}
],
"review_normalization_fix": {
"comment": "https://github.com/morluto/rea/pull/4962#discussion_r4305886491",
"before_source": "646312dad75e2cb2becb0dd4139b99a1c04d6bcc",
"before_pr_head": "fc55be1e05555c6b295209ef5f354617f663b8f8",
"expected_failing_regressions": 4,
"after_source": "3930a640fb8387cbd3079eee13fb90f82d1881dc",
"source_tests_passed": 130,
"structural_fix": "Two-way node identity mapping visits preserved descendants; already-owned JavaScript graph path keeps parsed metadata and avoids whole-graph comparison. Only the expensive imported fallback admits the full-result cache.",
"red_probe_cost": {
"elapsed_seconds": 5.332,
"family_cpu_seconds": 4.412336,
"family_peak_bytes": 438231040,
"payload_exit_code": 1,
"payload_cleanup_verified": true,
"expected_failures": 4
},
"current_dag_probe": {
"source": "3930a640fb8387cbd3079eee13fb90f82d1881dc",
"objects_per_graph": 27,
"inspections": 54,
"borrowed": true
}
},
"resource_stops": [
{
"task": "topology-paired-after-javascript-3",
"status": "incomplete",
"reason": "host_available_memory_early_stop",
"elapsed_seconds": 15.048,
"family_cpu_seconds_last_observed": 14.048702,
"peak_cgroup_bytes_sampled": 947695616,
"payload_completion_counters": null,
"owned_scope_after_stop": "inactive/dead",
"replacement": "fresh JavaScript pair4, after then before; final pairs1,2,4"
},
{
"task": "topology-before-small-3",
"status": "incomplete",
"reason": "host_available_memory_early_stop",
"elapsed_seconds": 11.83,
"family_cpu_seconds_last_observed": 11.535779,
"peak_cgroup_bytes_sampled": 947818496,
"payload_completion_counters": null,
"replacement": "fresh small pair4 after memory recovered; final small pairs1,2,4"
}
],
"unpaired_completed_attempts": [
{
"task": "topology-paired-before-javascript-3",
"status": "passed",
"original_records_preserved": true,
"elapsed_seconds": 38.862,
"family_cpu_seconds": 38.570479,
"family_peak_bytes": 1390338048,
"reason_not_in_paired_summary": "Its paired candidate was resource-stopped; kept separately, with both sides rerun as pair4."
}
]
}
@@ -0,0 +1,249 @@
# Reuse successful immutable parent validation
This checkpoint addresses [#4810](https://github.com/morluto/rea/issues/4810),
found in the [retained-investigation audit](retained-investigation-workflows.md).
It changes the shared format interpretation used by CLI and MCP views, without
adding a tool, changing a schema, projecting away source data, or rerunning a
provider.
## Question, ownership, and compatibility
The task resumes authentic exported Evidence in a fresh production stdio MCP
server, discovers its source, reads six original symbols or modules in two-row
pages, repeats that traversal three times, queries the existing Unknowns,
exports the investigation, and closes it. The original source records must
survive the round trip exactly. Pages are compared to original retained facts.
Independent ELF byte decoding checks symbol names, values, and ranges; JavaScript
checks cover selected source bytes and the `lib/cli.js` module identity, rather
than independently proving the entire application inventory or semantic graph.
Imported JavaScript graphs lack the producer's realm-private format proofs.
Previously each view repeated full schema, graph/hash, and cross-graph binding
validation. Native layout views likewise parsed the entire layout for every
page. An immutable Evidence root alone was insufficient: its selected normalized
result did not carry the JSON owner's private sealing proof.
The JSON owner now transfers that proof to a selected own member without another
walk or per-node registration. Native layouts and imported JavaScript results
record a **successful full
validation of the exact immutable source** in their owning WeakSets. Already
owned JavaScript graphs keep the existing metadata normalization and binding
checks, returning parsed metadata with their original graph references. That
path avoids rewalking a large owned graph just to borrow its wrapper. There is
no second
retained parsed graph, strong cache, cross-process cache, or live-state cache.
The schema implementation is fixed for the process; a different source object
must validate independently. Weak entries do not keep Evidence alive, and session
lookup continues to gate access after close.
Cache admission follows full validation and requires that parsing preserved the
source representation. A shared iterative JSON comparison checks own data keys,
scalar values, prototypes, and enumerability without calling accessors. Object
member order is immaterial; array order remains exact. Two-way identity maps
visit preserved descendants once and reject source-node splits or merges. Both
comparison maps are temporary and discarded on return. Parser defaults,
hidden-field removal, or other normalization retain the parser's
result and do not cache the source. Writable/configurable descriptor differences
are immaterial: the source is sealed while the temporary parse is mutable.
The JSON sealing boundary rejects proxies before reflection, so arbitrary
mutable proxy behavior cannot acquire an immutable proof. Mutable, merely
Object.freeze'd, failed, and abandoned inputs do not qualify for successful
format reuse.
No Evidence identity, source linkage, coverage, unknown, omission, error, or
caller-selected page changes are intended. Complete source Evidence remains
accessible through the existing contracts. The first imported view still pays for full
validation and the representation comparison; a one-off CLI invocation cannot
benefit from a cache in a previous process.
## Inputs and measurement scope
Baseline: `2c4338db1fdb7773e05376301c558cff2a0b4b80` (REA 6.6.0).
Node 24.18.0, npm 11.16.0, Linux x86-64 (AMD EPYC 7B12, kernel 6.1.0-53-cloud).
The ELF producer reports pwntools 4.15.0, pyelftools 0.33, and Unicorn 2.1.2.
The baseline's built runtime was preserved
before production changes. Candidate and baseline use the same locked packages.
- SQLite `/usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6`: SHA-256
`2e6eef9a727f081f0d453b4e5e6cbd8b9ef8b6f86cbf7681cbad444d3b0b55c8`;
26 sections, 1,479 symbols, 2,963 relocations. Original history: 1,745,224 bytes.
- Shipped npm 11.16.0: inventory digest
`f8e576a7d162542c616168b25a95a5f62b9accf29467cc37e149905ad4b8e603`;
five explicitly selected paths (`package.json`, `bin/npm-cli.js`, `lib/cli.js`,
`lib/cli/entry.js`, `lib/commands/install.js`), 2,822 application nodes,
1,796 semantic nodes, 13,682 semantic unknowns. The 1,416 unselected files stay
unknown. Original history: 21,058,430 bytes.
- Small case `/usr/bin/true`: SHA-256
`c79bf44242829108e323378531f4ac839513ca1fba45efd6583643526e1e9fd2`;
31 sections, 53 symbols, 66 relocations. Produced through the real production
`inspect_binary_layout` MCP operation. An independent raw ELF reader checked
every symbol name, value, and source range plus section/relocation counts.
The two larger histories were produced and independently checked in the linked
previous audit. They are historical Evidence, not a claim of fresh provider
analysis during a resumed view. All tasks here are static; no target executable
is run.
Each completed comparison includes startup, the complete 207-tool catalog,
import, queries, oracle checks, export, close, receipt writing, and SDK cleanup.
RPC timings exclude subsequent client-side oracle/receipt work. Fresh servers
separate first-view validation from later pages; OS file caches are uncontrolled.
Runs alternate baseline/candidate order. One CPU, 8 GiB hard family memory,
7 GiB early stop, no swap, and a 192-task ceiling bound each serial task.
Resource counters are observed at payload exit while the observer remains alive;
final whole-scope counters are unavailable. Kernel cgroup peaks include charged
file cache and descendants, rather than just the server's JS heap.
## Results and executed validation
Candidate production code: `3930a640fb8387cbd3079eee13fb90f82d1881dc`.
The [curated receipt](immutable-parent-validation.json) retains every final run,
offline token estimates, compatibility checks, and costs of previous attempts.
Values below are medians with min–max ranges across three fresh alternating pairs.
| Source | First page, before → after (ms) | Eight later pages, before → after (ms) |
| ---------- | ----------------------------------------------------- | -------------------------------------------------- |
| SQLite ELF | 183.56 [170.13–244.27] → 209.05 [203.11–216.88] | 469.89 [393.47–517.92] → 85.04 [65.10–89.01] |
| npm | 2441.08 [1681.26–2479.69] → 1978.73 [1864.89–2720.54] | 15534.41 [10378.13–16864.91] → 82.69 [75.19–84.13] |
| Small ELF | 133.33 [100.81–242.58] → 226.60 [111.79–556.22] | 122.93 [76.38–299.47] → 62.58 [57.69–96.24] |
| Source / runtime | Whole elapsed (s) | Family CPU (s) | Kernel family peak (MiB) |
| ------------------- | ------------------- | ------------------- | ------------------------ |
| SQLite ELF / before | 19.08 [15.26–20.00] | 18.75 [15.01–19.55] | 1013.8 [1009.5–1058.6] |
| SQLite ELF / after | 14.38 [14.06–17.25] | 14.09 [13.77–17.00] | 984.0 [957.1–1047.1] |
| npm / before | 39.63 [31.21–40.86] | 39.27 [30.87–40.49] | 1338.0 [1301.0–1543.7] |
| npm / after | 20.71 [20.01–23.02] | 20.50 [19.73–22.23] | 1286.8 [1250.6–1344.9] |
| Small ELF / before | 14.30 [12.00–17.59] | 13.94 [11.77–17.31] | 1013.2 [937.8–1017.4] |
| Small ELF / after | 12.31 [11.90–16.25] | 12.04 [11.71–16.07] | 956.3 [931.4–1007.5] |
| Source | Paired warm-read ratio, before / after | Paired first-view change, after − before (ms) |
| ---------- | -------------------------------------- | --------------------------------------------- |
| SQLite ELF | 5.53× [4.42–7.96] | +25.49 [-41.16–+46.75] |
| npm | 184.65× [125.50–224.30] | -462.34 [-614.80–+1039.29] |
| Small ELF | 1.28× [1.22–5.19] | +10.98 [-15.97–+422.88] |
Each pair matches the before/after runs with the same repetition number.
The paired effect can differ from the ratio of marginal medians when the host
speed changes. Positive first-view changes mean higher latency.
The repeated-read benefit is measured per source and pair above. First-view
validation
also performs the representation comparison and can be more expensive. Whole
task, CPU and memory figures above are measured SDK workflow costs, not a
general provider-analysis or agent-investigation speedup. The previous e30
checkpoint had a slow npm repetition on both sides, including a 65-second
candidate task; its cause was not profiled. The original checkpoint and every
fresh run remain retained. The previous `646312dad` checkpoint also had slower
small-case warm reads in two of three pairs (135.54 → 373.14 ms marginal
medians). Those negative results remain available in its linked historical
receipt; the current cohort improves all three small pairs, without establishing
a general small-input or whole-task benefit. No model-token saving, general memory improvement,
or complex-software investigation advantage is established.
All 18 fresh workflow runs preserve original records and canonical answer
digests. Every corresponding query's structured result and complete catalog
is equal. The three public CLI source pairs are also byte-for-byte identical.
The two additional mixed-history tasks preserve all 97 original records, check
64 follow-up heads over 32 pages and revision two, reject stale updates and
tampered imports atomically, clear Unknowns on close, and refuse old references.
Offline `tiktoken` 0.12.0 / `cl100k_base` estimates for one pass over the complete
catalog, named-call arguments and replies are **unchanged** within each pair:
849,736 native, 856,384 JavaScript, and 840,303 small-case tokens. The catalog
contributes 805,215 tokens alone.
These are raw transport serialization estimates, not actual model context or
usage; initialization/framing, prompts, client discovery, rendering/replay,
and continuations are unmeasured. Metadata paths differ from the historical
checkpoint; compare equivalent runs within each checkpoint.
Executed checks at the final production code:
- `npm run check` and `npm run docs:check`: pass, including five README
consistency tests.
- Three latest-main integration files through `npm run test:focused`, using
default deadlines: 27 tests pass at the current production source.
- 130 source tests across immutable JSON, native/JavaScript format validation,
and the shared application view service; `npm run check:fast` and
`npm run build:cached` pass.
- Four compiled CLI/MCP files (`evidenceBundleInline`, `serverUnknownsMcp`,
`analysisViewMcp`, and `analysisViewCli`): 36 tests pass.
- Real public stdio MCP: 18 fresh paired tasks and two additional mixed tasks;
public CLI: six invocations, with three exact output pairs. These corpus
workflows and four-file boundary checks have exit zero, verified payload
cleanup and zero observed payload-exit OOM events.
Internal and automated review reproduced **candidate-only** defects before integration.
Generic deep equality ignored hidden fields removed by parsing; the JSON owner
comparison now preserves that normalization. Review also reproduced aliases crossing
preserved subtrees and cloned metadata; four regressions failed against the prior
source. The comparer now visits preserved descendants with two-way identity mapping.
Already-owned JavaScript graphs keep their parsed-metadata fast path, so the generic
comparison and full-result cache only apply to the expensive imported fallback. Its
initial iterative traversal
also repeatedly expanded shared nodes: a valid 27-object graph exhausted an
instrumented 10,000-inspection budget. Tracking source-to-parsed node pairs
reduces that same compiled probe to 54 inspections and successful borrowing.
A parser that splits or merges source nodes keeps its parsed result rather than
expanding repeated paths. Deterministic regressions enforce the inspection
budget instead of relying on timing or letting a regression consume exponential
CPU. These are internal JSON-owner probes, not claimed baseline public-provider
reproductions.
The initial exploratory cohort and historical e30 paired checkpoint are not
the final comparison. One earlier source-check attempt was mistakenly started
during an initial baseline run; the newly started owned scope was stopped after
17.27 s and that check remains incomplete (exit 241). Observed counters, the
contended baseline, subsequent successful retries, and prior checkpoints remain
retained; no OOM or terminal-counter claim is inferred from that stopped task.
Two later tasks stopped because the host-available-memory guard reported its
early-stop condition: candidate JavaScript repetition three and baseline small
repetition three. Both incomplete attempts and the unmatched completed
JavaScript baseline remain separate. After memory recovered, both sides were
rerun as fresh pair four; final JavaScript and small samples use pairs 1, 2, 4.
Neither interrupted task is a completed comparison. The guard later gained
read-only host-memory/cgroup receipt fields; all resource thresholds and its
observer/stop logic remained unchanged.
Real Ghidra, Hopper, JEB, fresh JavaScript producer performance, and actual
agent trials are outside this checkpoint. Private WeakSet metadata/heap retention
was not measured independently; the absence of a strong retained parsed graph
is source-derived. The comparison maps exist only during the first
interpretation; measured family
peaks include their temporary cost.
## Latest-main integration and an unexplained timeout
Merge `71e0b2739` brings in main `bb212ffec`'s three test/config/guide fixes.
The current source passes all 27 tests in those three integration files through
`npm run test:focused` with the default deadlines. The earlier `646312dad`
checkpoint initially passed 26 and timed out the live identity/catalog test at
30 seconds. Matching official-command controls subsequently passed all 27 on
both unmodified main and that candidate. Direct/extended-deadline diagnostics
are recorded separately. Their passing results do not establish the cause of
the original timeout, which remains preserved and unexplained. No test-policy
or product file was changed to obtain a pass.
## Reproduction and retained evidence
Use `retained-investigation.mjs` from this directory with an authentic exported
bundle and its original source Evidence ID. Build both selected runtime revisions
with the pinned toolchain, preserving a separate baseline. For each runtime run:
```sh
python3 experiments/analysis-efficiency/resource-run.py --observe-payload-exit -- \
node experiments/analysis-efficiency/retained-investigation.mjs \
--runtime-root /absolute/runtime --revision REVISION \
--bundle /absolute/history.json --evidence-id ORIGINAL_EVIDENCE_ID \
--scenario native --delivery focused --output /absolute/new-receipt-directory
```
Use `--scenario javascript` for the npm history, and `--verify-mixed` with an
actual mixed investigation. Reuse the same bytes and source identity on both
sides. Do not regenerate parent identities or synthesize bundle records.
The checked-in wrapper defaults to a 4 GiB hard / 3 GiB early stop. This
checkpoint used a private resource-only copy with 8 GiB / 7 GiB thresholds,
a 16 GiB available-memory start floor and 8 GiB host early stop. Its source
and unchanged observer hashes are recorded in the curated receipt. This local
resource policy does not change the public workflow or global wrapper defaults.
Raw histories, transcripts, oracle outputs, and resource logs stay in the private
local audit cache; only curated receipts are committed.
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,238 @@
# JEB Linux CE native workflow checkpoint
This checkpoint qualifies Linux CE setup and selected native reads for
[#4996](https://github.com/morluto/rea/issues/4996). It changes documentation;
it does not introduce a provider cache or claim a before/after speedup.
The existing shared CLI/MCP implementation returned consistent facts and
Evidence, with one metadata request per persistent MCP task. Further wrapper
caching is not justified by these measurements.
## Pinned inputs and scope
Baseline: REA 6.6.0 at `7c458f04b9155707c8ba406f8b455b10016f1b99`, Node 24.18.0,
npm 11.16.0, Temurin 21.0.12.1, Linux x86-64
`6.1.0-53-cloud-amd64`. All six final sessions used the same compiled MCP
runtime digest, recorded in the [curated receipt](jeb-linux-native.json).
The official CE archive was obtained through
<https://www.pnfsoftware.com/dl?jeb4ce>: 697,549,250 bytes, observed SHA-256
`709e7fe8e88bb0e9e2bc03b028f8b9fc78cec0289d04abe54fc26cda6369e175`.
HTTPS download and ZIP CRC checks completed; a publisher signature was not
independently verified. This distribution identifies as
`5.48.0.202610071539`, serving MCP 1.3.0. The installation and first-use
activation remained private; no engine binaries, keys or raw decompilation
are included here.
| Artifact | Bytes | Independent check |
| -------------------------------------------------------- | --------: | ----------------------------------------------------------------------------- |
| Authored C ELF, ET_EXEC | 17,360 | Source arithmetic and GNU `nm` symbol |
| Debian `libsqlite3.so.0.8.6`, package `3.40.1-2+deb12u2` | 1,437,848 | GNU `nm` and `objdump`: exported version function returns immediate `3040001` |
Target SHA-256 digests:
- Fixture: `1a6f55303712e096ff5196c7fd6e8acf75473fbf0f7467d7b315f96f50b3f841`.
- SQLite: `2e6eef9a727f081f0d453b4e5e6cbd8b9ef8b6f86cbf7681cbad444d3b0b55c8`.
Neither target was executed. The fixture's expected arithmetic was `input * 7 + 13`.
That check does not establish inferred ABI, signedness or equivalence for every
input. SQLite's constant-return oracle is also narrower than complete-program
correctness.
## Setup and item identity
The current official CE build successfully accepted `-c --mcp`, using
`--interface=127.0.0.1`, a dedicated port and `--infile` for the selected ELF.
This agrees with the [current upstream MCP manual](https://www.pnfsoftware.com/jeb/manual/mcp/).
The earlier documented licensed-build result used a programmatic launcher;
its CLI behavior should not be generalized to all 5.48 distributions.
Code-item references also need their owning representation. The CE native
`list_code_items` tool returned `sqlite3_libversion_number` for a filtered
method query. That exact reference succeeded through REA. Earlier raw ELF
address attempts did not complete successfully. A numeric reference did work
for the authored ET_EXEC pilot, so neither observation establishes a universal
numeric-address rule. Preserve the engine's reference and explicit unit path;
keep file offsets and independently obtained ELF addresses separate.
The native CE catalog advertised 27 tools. REA currently exposes four JEB
operations; native code-item discovery is not among them. The final tasks
therefore start with a known reference. This is a selected-read qualification,
not a complete method-discovery or provider-parity comparison.
## Completed workflow and accounting
Three alternating fresh-engine sessions per artifact completed the same task:
1. Start the private headless engine; prove that its child PID owns the
selected IPv4 or mapped-IPv6 loopback listener before connecting.
2. Connect the production stdio MCP runtime and discover its full catalog.
3. Inspect JEB, list all three units, then concatenate four one-item pages
including the empty remainder and compare with the original listing.
4. Decompile the selected method, check the independent oracle and complete
inline Evidence, then repeat it six times with identical facts and Evidence IDs.
5. Check a missing item returns an error; make one real CLI query and compare
its normalized facts, raw text and Evidence ID with MCP; close the client.
6. Verify target bytes are unchanged and the borrowed engine survived REA
cleanup, then stop the harness-owned engine.
Each task made 15 public MCP calls and one CLI parity query. Request tracing
observed one upstream catalog walk, one `get_client_information`, five
`list_units` and eight `decompile_code_item` calls. Explicit metadata refresh
and reconnect behavior were not part of this repeat-read measurement.
Tracing covered the production MCP child; the separate CLI query's upstream
requests were not instrumented.
Evidence retained `subject: null` and the artifact-identity limitation;
an independent native project-digest observation was not substituted for
identity atomically bound to each read.
All heavy work ran serially inside a cgroup v2 family with an 8 GiB hard cap,
7 GiB early stop, one CPU quota and affinity, and zero swap. Startup required
16 GiB host availability; a running task would stop below 8 GiB. The JVM used
`-Xmx1536m -XX:ActiveProcessorCount=1`; the production MCP child used a
2048 MiB Node heap, and the harness/CLI inherited a 3072 MiB Node heap limit.
These are audit settings, not general engine-size recommendations.
OS and vendor file caches were not flushed. “First” means the first selected
function read in a fresh JVM; “warm” means repeated reads in that same engine.
The private fetch observer recorded request names and byte counts without
cloning response bodies; its overhead is included.
Whole-task counters include the JVM, MCP client, production runtime, CLI
parity, native oracle and cleanup, including cgroup-charged file cache.
Host-admission wait is recorded separately. Outer guard/systemd-manager costs
were not measured. Payload-exit counters and cleanup were verified while an
observer remained alive; disappeared final whole-scope counters remain unknown.
## Measured costs
Medians with observed minimum–maximum across three completed sessions:
| Cost | Authored ELF | Shipped SQLite |
| ---------------------------------------- | -------------------------: | -------------------------: |
| First selected MCP read | 4.134 s (3.845–5.037) | 24.508 s (22.823–49.977) |
| Six warm MCP reads, total | 253.2 ms (113.4–842.9) | 190.0 ms (160.9–416.9) |
| Whole guarded task elapsed | 27.638 s (26.749–32.622) | 48.296 s (45.625–82.039) |
| Whole family CPU | 27.291 s (26.399–32.155) | 47.753 s (45.370–78.877) |
| Kernel family peak, including file cache | 1540.1 MiB (1531.5–1614.9) | 1799.6 MiB (1714.7–1865.8) |
The slower third sessions remain in the results. Their extra elapsed and CPU
costs are unexplained; no favorable resampling, stable latency improvement or
memory reduction is claimed. Warm reads are already short relative to first
reads. Adding another live-project cache would introduce identity and
invalidation obligations without a demonstrated bottleneck here.
All six completed payloads recorded zero memory-limit, task-limit, OOM and
OOM-kill events. This is a payload-exit observation, not a claim that missing
final counters equal zero.
## Context estimates
The unchanged production catalog contained 207 tools, 3,158,927 serialized
bytes, SHA-256
`a1851aa1bfe3d72d6be6bec130519dbdfc1ee49288320cfac0144ced77755c61`.
An offline tiktoken 0.12.0 `cl100k_base` count assigned 805,330 tokens to one
raw catalog page-array in every session.
| Estimated serialization | Authored ELF median | SQLite median |
| ---------------------------------------------------- | ------------------: | ------------: |
| Catalog + named MCP arguments + raw replies | 814,268 | 814,878 |
| Above, plus selected CLI arguments and parity stdout | 814,610 | 815,249 |
| MCP text reply blocks alone | 3,957 | 4,203 |
Raw replies contain both text and structured copies. These counts describe
the validation exchange, including its extra pagination, repeated and negative
queries. Actual model usage, prompts, protocol/initialization framing, client
filtering/rendering/replay, shell framing and context for independent oracles
were not measured. No model-token savings or complex-investigation advantage
is established. Catalog delivery is a shared concern; existing
[PR #3026](https://github.com/morluto/rea/pull/3026) already explores family
selection and is outside this checkpoint.
## Preserved attempts and verification limits
The JSON receipt retains costs and outcomes for all earlier attempts:
- Three host-memory refusals happened before scope/payload creation.
- First-use EULA and missing-key attempts exited before analysis. Although
JEB exited zero, the harness correctly reported failure.
- The 30-second raw-address SQLite attempt returned typed `provider_timeout`;
the 60-second raw-address attempt returned an upstream refusal. Neither is a
completed benchmark or proof of a REA defect.
- A producer-reference SQLite read succeeded, but the initial test oracle
rejected its valid C `L` integer suffix. The oracle was corrected before
the final cohort; that incomplete workflow and its cost remain recorded.
- Setup, diagnostic help, successful pilots, native discovery checks and
offline tokenizer work are recorded separately from the final cohort.
This audit does not qualify CE Java/Android decompilation, GUI project opening,
Windows/macOS, more than 100 units, real caller cancellation, or recovery after
engine restart. Existing reconnect/invalidation work is
[PR #3754](https://github.com/morluto/rea/pull/3754). The selected function and
constant checks do not establish broader software-analysis effectiveness.
## Release 6.7.0 integration control
Main advanced to `a25eb5fbb424197cb8e699e15a82a6ff869658aa` during review.
The branch rebased onto that release checkpoint, rebuilt, and passed
`docs:check` plus uncached typecheck/lint. Two additional fresh-engine public
workflows passed against `837718b1968b5fd90762c4c54895b11e9f5478fd`: one
authored ELF and one shipped SQLite, adding 30 MCP calls and two CLI parity
queries. They verify the rebuilt 6.7.0 runtime and remain separate from the
six-session performance cohort above. Their runtime/catalog digests and
process-family costs are recorded in the JSON receipt.
The first additional SQLite attempt was stopped after 28.244 seconds when
host available memory fell below the unchanged 8 GiB stop threshold. Final
scope limit/OOM counters were observed as zero; payload-exit counters were
unavailable, so that attempt is incomplete. Its sampled peak is not a kernel
peak claim. Target bytes remained unchanged. The successful retry used a
stricter 24 GiB admission wait with the original 8 GiB family cap, 7 GiB early
stop, one CPU and zero swap. No failed attempt was replaced or counted passed.
## Reproduction entrypoints
The small source fixture was compiled with `gcc -O1 -g -fno-pie -no-pie`:
```c
#include <stdio.h>
__attribute__((noinline)) int rea_probe_value(int input) { return input * 7 + 13; }
int main(void) { puts("rea_jeb_native_probe"); return rea_probe_value(4) == 41 ? 0 : 1; }
```
Its recorded digest pins the tested build; debug/source paths can change a
rebuilt binary's digest. The source expression and independently resolved
symbol remain the fixture oracle.
From the caller's JEB directory, after completing its official first-use setup
and selecting JDK 21 through `JAVA_HOME`:
```sh
"$JAVA_HOME/bin/java" -Xmx1536m -XX:ActiveProcessorCount=1 -jar bin/app/jeb.jar -c --mcp \
--interface=127.0.0.1 --port=18425 \
--infile=/usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6
```
In the pinned REA checkout, with the pinned Node toolchain and built runtime:
```sh
export REA_JEB_MCP_URL=http://127.0.0.1:18425/mcp
export REA_JEB_MCP_TIMEOUT_MS=60000
node scripts/rea.mjs inspect-jeb-client --json
node scripts/rea.mjs list-jeb-units --count 100 --json
node scripts/rea.mjs decompile-jeb-item sqlite3_libversion_number method \
--unit-path libsqlite3.so.0.8.6/libsqlite3.so.0.8.6/x86_64-image --json
nm -D --defined-only /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6
objdump -d --disassemble=sqlite3_libversion_number \
/usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6
```
The listed commands reproduce individual reads and the file oracle; the
full measurement also used the MCP sequence and process-family observer
described above. JVM heap flags alone do not impose its family/host guards.
Private raw transcripts and engine documents are excluded from the repository.
The baseline gate passed `npm run docs:check`, `npm run check:fast` and
`git diff --check`; its typecheck/lint were cache hits. The release integration
gate above also passed with uncached typecheck/lint. The first gate attempt was refused
before scope creation; the admitted gate passed under the unchanged bounds.
The runtime results above were executed against the pinned baseline.
@@ -0,0 +1,635 @@
{
"runtime_revision": "f4322b15ed1423d736bd2572cf7a8eadf2b466e1",
"host": "Linux x86-64",
"node": "24.18.0",
"npm": "11.16.0",
"codex_cli": "0.161.0",
"requested_model": "gpt-6.1-sol",
"reasoning": "high",
"resolved_model_identity": "unknown",
"code_mode": false,
"client_enabled_tools": [
"import_evidence_bundle",
"get_evidence_bundle",
"inspect_analysis_view",
"list_unknowns"
],
"catalog": {
"tools": 207,
"serialized_bytes": 3152125,
"sha256": "4f31d9d56c400bc48f5639a9dc4b4cdad7faf862e4be81641d94fa70552438e4"
},
"bounds": {
"cpu_quota_percent": 100,
"family_hard_mib": 8192,
"early_stop_mib": 7168,
"swap": false,
"tasks": 192
},
"counter_scope": "Payload-exit counters with observer alive; kernel family peaks include file cache; terminal whole-scope counters and remote model compute unknown",
"sources": {
"native": {
"target_sha256": "2e6eef9a727f081f0d453b4e5e6cbd8b9ef8b6f86cbf7681cbad444d3b0b55c8",
"sections": 26,
"symbols": 1479,
"relocations": 2963,
"all_symbol_locations_names_values_agree_with_independent_ELF_parser": true
},
"javascript": {
"package": "npm",
"version": "11.16.0",
"source_files": [
{
"path": "package.json",
"sha256": "60ff022e32b5d8291d3e09849fd0cee6bbbff4e4d8352ad258214b1adf070714"
},
{
"path": "bin/npm-cli.js",
"sha256": "8e5f6f3429f8cdbe693cdc29904e9d5a7b127a494bd15c804bd54c7403bfcbe7"
},
{
"path": "lib/cli.js",
"sha256": "67666f06479f9b0bbc01412c198caadd4287d34d5ed74a02871ea78f186451e7"
},
{
"path": "lib/cli/entry.js",
"sha256": "667a44c1fa8795fdbba8ad843736ca7f8f24e64511985e9a7060b002123560c6"
},
{
"path": "lib/commands/install.js",
"sha256": "f7a60e8b40ab1bece76a2441b8b15378d199f05c6050eebe455cd9961f67b816"
}
],
"lib_cli_module": {
"node_id": "jag_node_131257ad52f3333971c2a5ed325c64357e52604489e42ccc67a8849770cb5b10",
"kind": "javascript-module",
"path": "lib/cli.js"
},
"source_bytes_checked": true,
"inventory_completeness": "producer-relative, not independently established",
"unselected_sources": 1416
}
},
"sdk": [
{
"name": "sdk-native-complete-1",
"status": "passed",
"answer_sha256": "4e28c2c2a25620576d27abe846a05835ec49386b889779e33410c31971523b54",
"query_ms": 1328.7,
"query_reply_bytes": 11224227,
"rpc_count": 7,
"elapsed_seconds": 14.117,
"cpu_seconds": 13.915,
"peak_family_mib": 1160.8,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
},
"payload_cleanup_verified": true,
"response_capacity_refused": false,
"warm_page_ms": []
},
{
"name": "sdk-native-complete-2",
"status": "passed",
"answer_sha256": "4e28c2c2a25620576d27abe846a05835ec49386b889779e33410c31971523b54",
"query_ms": 1385.4,
"query_reply_bytes": 11224227,
"rpc_count": 7,
"elapsed_seconds": 14.722,
"cpu_seconds": 14.485,
"peak_family_mib": 1109.9,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
},
"payload_cleanup_verified": true,
"response_capacity_refused": false,
"warm_page_ms": []
},
{
"name": "sdk-native-focused-1",
"status": "passed",
"answer_sha256": "4e28c2c2a25620576d27abe846a05835ec49386b889779e33410c31971523b54",
"query_ms": 529.7,
"query_reply_bytes": 167985,
"rpc_count": 25,
"elapsed_seconds": 12.907,
"cpu_seconds": 12.679,
"peak_family_mib": 934.8,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
},
"payload_cleanup_verified": true,
"response_capacity_refused": false,
"warm_page_ms": [44.1, 59.6, 24.0, 30.8, 26.7, 47.4]
},
{
"name": "sdk-native-focused-2",
"status": "passed",
"answer_sha256": "4e28c2c2a25620576d27abe846a05835ec49386b889779e33410c31971523b54",
"query_ms": 572.2,
"query_reply_bytes": 167985,
"rpc_count": 25,
"elapsed_seconds": 13.316,
"cpu_seconds": 13.116,
"peak_family_mib": 1000.0,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
},
"payload_cleanup_verified": true,
"response_capacity_refused": false,
"warm_page_ms": [44.0, 64.6, 26.8, 33.2, 29.8, 50.4]
},
{
"name": "sdk-javascript-complete-1",
"status": "passed",
"answer_sha256": "0fe3ad249eb1a7233a4966a56652c173667c48fdaf395b6c08fc6901ef3b46f7",
"query_ms": 11241.5,
"query_reply_bytes": 212856,
"rpc_count": 31,
"elapsed_seconds": 26.3,
"cpu_seconds": 26.1,
"peak_family_mib": 1333.5,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
},
"payload_cleanup_verified": true,
"response_capacity_refused": true,
"warm_page_ms": [1124.6, 1073.8, 1474.7, 1074.7, 1081.6, 1109.5]
},
{
"name": "sdk-javascript-complete-2",
"status": "passed",
"answer_sha256": "0fe3ad249eb1a7233a4966a56652c173667c48fdaf395b6c08fc6901ef3b46f7",
"query_ms": 11938.1,
"query_reply_bytes": 212856,
"rpc_count": 31,
"elapsed_seconds": 27.105,
"cpu_seconds": 26.87,
"peak_family_mib": 1320.9,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
},
"payload_cleanup_verified": true,
"response_capacity_refused": true,
"warm_page_ms": [1155.4, 1096.2, 1489.3, 1121.3, 1088.3, 1484.6]
},
{
"name": "sdk-javascript-focused-2",
"status": "passed",
"answer_sha256": "0fe3ad249eb1a7233a4966a56652c173667c48fdaf395b6c08fc6901ef3b46f7",
"query_ms": 10967.3,
"query_reply_bytes": 208350,
"rpc_count": 28,
"elapsed_seconds": 25.708,
"cpu_seconds": 25.505,
"peak_family_mib": 1344.0,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
},
"payload_cleanup_verified": true,
"response_capacity_refused": false,
"warm_page_ms": [1342.7, 1085.1, 1055.0, 1034.6, 1082.7, 1440.7]
},
{
"name": "sdk-javascript-focused-3",
"status": "passed",
"answer_sha256": "0fe3ad249eb1a7233a4966a56652c173667c48fdaf395b6c08fc6901ef3b46f7",
"query_ms": 10990.4,
"query_reply_bytes": 208350,
"rpc_count": 28,
"elapsed_seconds": 26.197,
"cpu_seconds": 25.98,
"peak_family_mib": 1336.0,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
},
"payload_cleanup_verified": true,
"response_capacity_refused": false,
"warm_page_ms": [1338.1, 1088.5, 1069.1, 1038.3, 1087.5, 1483.0]
},
{
"name": "sdk-mixed-native",
"status": "passed",
"answer_sha256": "4e28c2c2a25620576d27abe846a05835ec49386b889779e33410c31971523b54",
"query_ms": 560.0,
"query_reply_bytes": 167991,
"rpc_count": 25,
"elapsed_seconds": 16.933,
"cpu_seconds": 16.714,
"peak_family_mib": 1261.4,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
},
"payload_cleanup_verified": true,
"response_capacity_refused": false,
"warm_page_ms": [46.9, 51.0, 36.3, 24.4, 38.6, 43.8]
},
{
"name": "sdk-mixed-javascript",
"status": "passed",
"answer_sha256": "0fe3ad249eb1a7233a4966a56652c173667c48fdaf395b6c08fc6901ef3b46f7",
"query_ms": 10904.5,
"query_reply_bytes": 208356,
"rpc_count": 28,
"elapsed_seconds": 26.5,
"cpu_seconds": 26.297,
"peak_family_mib": 1346.5,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
},
"payload_cleanup_verified": true,
"response_capacity_refused": false,
"warm_page_ms": [1321.9, 1063.3, 1070.8, 1309.9, 1041.7, 1074.2]
}
],
"model_trials": [
{
"name": "model-javascript-complete-1",
"facts_pass": true,
"elapsed_seconds": 76.49,
"cpu_seconds": 24.687,
"peak_family_mib": 818.7,
"input_tokens": 454491,
"cached_input_tokens": 396288,
"uncached_input_tokens": 58203,
"output_tokens": 2033,
"reported_reasoning_output_tokens": 207,
"mcp_calls_including_discovery": 9,
"payload_cleanup_verified": true,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
}
},
{
"name": "model-javascript-complete-2",
"facts_pass": true,
"elapsed_seconds": 58.335,
"cpu_seconds": 14.993,
"peak_family_mib": 971.4,
"input_tokens": 328066,
"cached_input_tokens": 280704,
"uncached_input_tokens": 47362,
"output_tokens": 1676,
"reported_reasoning_output_tokens": 129,
"mcp_calls_including_discovery": 9,
"payload_cleanup_verified": true,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
}
},
{
"name": "model-javascript-focused-1",
"facts_pass": false,
"elapsed_seconds": 34.206,
"cpu_seconds": 16.31,
"peak_family_mib": 811.9,
"input_tokens": 167470,
"cached_input_tokens": 136320,
"uncached_input_tokens": 31150,
"output_tokens": 633,
"reported_reasoning_output_tokens": 172,
"mcp_calls_including_discovery": 4,
"payload_cleanup_verified": true,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
}
},
{
"name": "model-javascript-focused-2",
"facts_pass": true,
"elapsed_seconds": 66.455,
"cpu_seconds": 14.337,
"peak_family_mib": 955.3,
"input_tokens": 339528,
"cached_input_tokens": 307456,
"uncached_input_tokens": 32072,
"output_tokens": 2051,
"reported_reasoning_output_tokens": 169,
"mcp_calls_including_discovery": 10,
"payload_cleanup_verified": true,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
}
},
{
"name": "model-javascript-guided-complete-1",
"facts_pass": true,
"elapsed_seconds": 69.206,
"cpu_seconds": 13.65,
"peak_family_mib": 888.8,
"input_tokens": 168862,
"cached_input_tokens": 121728,
"uncached_input_tokens": 47134,
"output_tokens": 2385,
"reported_reasoning_output_tokens": 737,
"mcp_calls_including_discovery": 6,
"payload_cleanup_verified": true,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
}
},
{
"name": "model-javascript-guided-complete-2",
"facts_pass": false,
"elapsed_seconds": 29.187,
"cpu_seconds": 15.105,
"peak_family_mib": 697.4,
"input_tokens": 28696,
"cached_input_tokens": 23296,
"uncached_input_tokens": 5400,
"output_tokens": 610,
"reported_reasoning_output_tokens": 379,
"mcp_calls_including_discovery": 0,
"payload_cleanup_verified": true,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
}
},
{
"name": "model-javascript-guided-focused-1",
"facts_pass": true,
"elapsed_seconds": 53.464,
"cpu_seconds": 12.059,
"peak_family_mib": 944.5,
"input_tokens": 124218,
"cached_input_tokens": 92416,
"uncached_input_tokens": 31802,
"output_tokens": 1746,
"reported_reasoning_output_tokens": 330,
"mcp_calls_including_discovery": 5,
"payload_cleanup_verified": true,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
}
},
{
"name": "model-javascript-guided-focused-2",
"facts_pass": true,
"elapsed_seconds": 58.526,
"cpu_seconds": 22.852,
"peak_family_mib": 924.2,
"input_tokens": 129134,
"cached_input_tokens": 97536,
"uncached_input_tokens": 31598,
"output_tokens": 1478,
"reported_reasoning_output_tokens": 69,
"mcp_calls_including_discovery": 5,
"payload_cleanup_verified": true,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
}
},
{
"name": "model-native-complete-1",
"facts_pass": true,
"elapsed_seconds": 52.103,
"cpu_seconds": 8.686,
"peak_family_mib": 1028.5,
"input_tokens": 287913,
"cached_input_tokens": 249984,
"uncached_input_tokens": 37929,
"output_tokens": 1724,
"reported_reasoning_output_tokens": 121,
"mcp_calls_including_discovery": 4,
"payload_cleanup_verified": true,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
}
},
{
"name": "model-native-complete-2",
"facts_pass": true,
"elapsed_seconds": 58.261,
"cpu_seconds": 9.102,
"peak_family_mib": 837.4,
"input_tokens": 348976,
"cached_input_tokens": 286976,
"uncached_input_tokens": 62000,
"output_tokens": 2009,
"reported_reasoning_output_tokens": 246,
"mcp_calls_including_discovery": 5,
"payload_cleanup_verified": true,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
}
},
{
"name": "model-native-focused-1",
"facts_pass": true,
"elapsed_seconds": 62.078,
"cpu_seconds": 10.198,
"peak_family_mib": 823.9,
"input_tokens": 335445,
"cached_input_tokens": 293120,
"uncached_input_tokens": 42325,
"output_tokens": 1924,
"reported_reasoning_output_tokens": 87,
"mcp_calls_including_discovery": 8,
"payload_cleanup_verified": true,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
}
},
{
"name": "model-native-focused-2",
"facts_pass": true,
"elapsed_seconds": 57.933,
"cpu_seconds": 8.058,
"peak_family_mib": 821.3,
"input_tokens": 286938,
"cached_input_tokens": 256384,
"uncached_input_tokens": 30554,
"output_tokens": 1831,
"reported_reasoning_output_tokens": 106,
"mcp_calls_including_discovery": 8,
"payload_cleanup_verified": true,
"memory_events": {
"low": 0,
"high": 0,
"max": 0,
"oom": 0,
"oom_kill": 0,
"oom_group_kill": 0
}
}
],
"failed_trials": {
"model-javascript-focused-1": "Wrong connector discovery; approval-policy refusal; no source facts established.",
"model-javascript-guided-complete-2": "Premature agent refusal with no REA RPC; asserted tool unavailability not established by a connection/discovery observation."
},
"pilot_failures": [
"Private pilot oracle read view.item instead of view.items; corrected before the committed SDK cohorts. No product failure inferred."
],
"decision": "Existing query APIs suffice for these bounded questions; no general token/time advantage established. Separate imported immutable-format validation optimization is tracked in #4810.",
"review_followup_verification": {
"review-mixed-native": {
"status": "passed",
"checks": {
"heads_checked": 64,
"pages": 32,
"revised_unknown_id": "unk_057c8f2dbf30ec98851a66ee054366bc6e2e168874581e6f99cb80673d0ff9b8",
"revision_checked": 2,
"stale_update_rejected": true,
"tampered_import_rejected_atomically": true,
"unknowns_after_close": 0,
"old_reference_refused": true
},
"original_records_preserved": true,
"elapsed_seconds": 18.444,
"cpu_seconds": 18.16515,
"peak_family_mib": 1401.6328125,
"oom_events_at_payload_exit": 0,
"payload_cleanup_verified": true
},
"review-mixed-javascript": {
"status": "passed",
"checks": {
"heads_checked": 64,
"pages": 32,
"revised_unknown_id": "unk_057c8f2dbf30ec98851a66ee054366bc6e2e168874581e6f99cb80673d0ff9b8",
"revision_checked": 2,
"stale_update_rejected": true,
"tampered_import_rejected_atomically": true,
"unknowns_after_close": 0,
"old_reference_refused": true
},
"original_records_preserved": true,
"elapsed_seconds": 27.617,
"cpu_seconds": 27.275299,
"peak_family_mib": 1444.30859375,
"oom_events_at_payload_exit": 0,
"payload_cleanup_verified": true
},
"deterministic_receipt_tests": {
"passed": 4,
"scope": "Rejected SDK call, protocol error, receipt-write failure, simultaneous call/write failure; not real-provider evidence"
},
"cleanup_receipt_regressions": {
"passed": 6,
"scope": "Real stream/file refusals, independent peer close, and injected partial publication at the filesystem boundary. Original failure and call costs survive; failed cleanup retains workspace ownership. Harness failure checks, not real-provider evidence.",
"baseline_reproduction": {
"revision": "b025a919b36ec091ca888339df6b24e78e89b79b",
"method": "Execute the prior committed finalization block with deterministic workspace or log rejection; not a production-provider reproduction.",
"workspace_error": {
"file_receipt_attempts": 0,
"stdout_receipt_attempts": 0
},
"log_error": {
"file_receipt_attempts": 0,
"stdout_receipt_attempts": 0
}
},
"partial_retry_baseline": {
"revision": "5d6259e658ee54fc9829b9143a8721a2ab426e80",
"regression_exit_code": 1,
"observed_saved_report": "partial",
"method": "Run the unchanged partial-write regression against the prior committed finalizer with deterministic filesystem-boundary failure injection."
}
}
}
}
@@ -0,0 +1,201 @@
# Retained investigation query checkpoint
[#3134](https://github.com/morluto/rea/issues/3134) measured existing retained
queries on Linux. Selected reads preserved the requested facts, original
Evidence and Unknown revisions, including a mixed investigation. Existing
contracts suffice for these questions; this checkpoint adds no production API,
cache, persistence or default change.
Imported JavaScript pages repeatedly validated their entire source graph. That
separate, observed bottleneck is owned by
[#4810](https://github.com/morluto/rea/issues/4810). Smaller replies did not
establish a general model-token or whole-task latency improvement.
The [curated measurements](retained-investigation-results.json) retain individual
SDK/model costs and unsuccessful attempts. Raw bundles, transcripts, profiles
and detailed receipts stay private and are not build inputs.
## Sources and questions
Runtime: `f4322b15ed1423d736bd2572cf7a8eadf2b466e1`, Linux x86-64,
Node 24.18.0/npm 11.16.0. The SDK discovered all 207 advertised tools
(3,152,125 serialized catalog bytes). Model trials used Codex CLI 0.161.0,
requested `gpt-6.1-sol`/high, direct MCP, and the same four enabled tool names:
`import_evidence_bundle`, `get_evidence_bundle`, `inspect_analysis_view`, and
`list_unknowns`. The resolved service-side model identity is unknown. These are
selected-client-tool trials, not an evaluation of full-catalog agent discovery.
Two public source workflows produced authentic bundles through production MCP:
- Native: `inspect_binary_layout` on Debian's `libsqlite3.so.0.8.6`, SHA-256
`2e6eef9a727f081f0d453b4e5e6cbd8b9ef8b6f86cbf7681cbad444d3b0b55c8`.
Pwntools 4.15.0/pyelftools 0.33/Unicorn 2.1.2 observed 26 sections, 1,479
symbols and 2,963 relocations. An independent ELF64 decoder checked section
and relocation counts and every symbol's table/entry index, value, raw name
bytes and source entry range against the original file.
- JavaScript: shipped npm 11.16.0, directory inventory digest
`f8e576a7d162542c616168b25a95a5f62b9accf29467cc37e149905ad4b8e603`.
`analyze_javascript_application` selected exactly `package.json`,
`bin/npm-cli.js`, `lib/cli.js`, `lib/cli/entry.js`, and
`lib/commands/install.js`. It parsed four JavaScript files; 1,416 other
relevant files remained unselected. The complete retained result contained
2,822 application nodes, 1,796 semantic nodes and 13,682 semantic unknowns.
Source-file digests and the `lib/cli.js` source-module identity were checked
against shipped bytes. Inventory/discovery completeness remains producer-relative.
Analyst-recorded Unknowns came from the actual source limitations: five native
and seven JavaScript questions. These registry heads are distinct from the
13,682 semantic-graph unknowns. The exported histories contained 15 and 17
records, respectively, and approximately 1.75 and 21.06 MB of canonical JSON.
No synthetic payload arrays were used.
The SDK task read the first six original symbol/module rows and the relevant
current Unknown heads. Complete delivery and selected delivery answered the
same question; selected delivery intentionally exercised two-row pages. Each
fresh server performed three traversals, exported again and closed. The model
task additionally requested native identity/counts, or the five JavaScript source
choices and exact `lib/cli.js` source module, with explicit runtime uncertainty.
Compare arms within each declared task, not SDK costs against model costs.
## Correctness, capacity and lifetime
Both fresh-server SDK repetitions passed in both delivery arms. Selected rows,
ordering and counts agreed with original records; all original records and
Unknown revisions survived export/import, including links, omitted fields,
nulls and scalar types. Query calls did not rerun either producer. The resumed
servers had no native producer configuration.
The JavaScript complete bundle exceeded the default 10 MiB receive-buffer
boundary. Its typed capacity refusal preserved the complete retained data and a
usable connection. Complete-arm costs include that refusal and subsequent
selected-view recovery; they are not timings for a successful complete transfer.
A mixed history combined both authentic investigations and promoted 64 actual
semantic unknowns to separately identified analyst follow-ups. One follow-up
was updated to investigating. It contained 97 records, 76 heads and 77 revisions.
Both source queries preserved all original records/revisions. Thirty-two
two-head pages verified every semantic-follow-up head, including revision two.
A stale update and a tampered bundle import were rejected without changing the
ledger. Export reproduced the complete original mixed bundle. Closing cleared
records/Unknowns and made the old reference unavailable; no implicit persistence
or producer restart was introduced.
Public CLI `inspect-evidence-bundle` summary and inline `inspect-analysis-view`
summary also passed on both authentic sources. Portable CLI input still requires
complete input admission/validation; small output does not remove that cost.
## SDK costs
Each row spans two fresh MCP servers. Query time is the sum of SDK RPC elapsed
times over three traversals. Local post-call contract validation, oracle checks
and transcript writes are included only in the whole harness, along with startup,
full discovery, file reads, import, export and close. OS caches were uncontrolled/warm. A fresh imported
session is not a cold native-analysis measurement.
| Source / arm | Three traversals | Query reply bytes | Whole elapsed | Local family CPU | Family peak |
| ------------------------------ | ---------------: | ----------------: | --------------: | ---------------: | --------------: |
| Native complete | 1.329–1.385 s | 11,224,227 | 14.117–14.722 s | 13.915–14.485 s | 1,110–1,161 MiB |
| Native selected | 0.530–0.572 s | 167,985 | 12.907–13.316 s | 12.679–13.116 s | 935–1,000 MiB |
| JavaScript complete + recovery | 11.242–11.938 s | 212,856 | 26.300–27.105 s | 26.100–26.870 s | 1,321–1,334 MiB |
| JavaScript selected | 10.967–10.990 s | 208,350 | 25.708–26.197 s | 25.505–25.980 s | 1,336–1,344 MiB |
Mixed-history selected tasks took 16.933 s native and 26.500 s JavaScript,
including the larger import and complete round-trip checks. Their family peaks
were 1,261 and 1,347 MiB. This does not establish scaling to thousands of
registry heads or every provider.
Original-session npm warm pages measured 8–31 ms; after import, repeated pages
cost about 1.1–1.4 s. Source inspection shows that imported immutable Evidence
does not carry the format owner's private graph proofs, so each view repeats
full validation. Native layout views also parse the complete layout on each
page. #4810 owns equivalent before/after verification of a correction; this
checkpoint claims no speedup from an unimplemented cache.
## Actual model tasks
All twelve attempts retained their costs. Ten supplied every checked fact and
current Unknown identity/status; runtime and unselected-source coverage stayed
unknown. One initial JavaScript selected attempt searched the wrong connector
and received an approval-policy refusal. One guided complete attempt stopped
without an REA RPC and asserted tool unavailability without a supporting
connection/discovery observation. Both are failed tasks, despite CLI exit zero.
| Cohort / arm | Successful tasks | Total input tokens | Elapsed |
| ------------------------------------- | ---------------: | -----------------------: | -----------------------: |
| Native complete | 2/2 | 287,913 / 348,976 | 52.103 / 58.261 s |
| Native selected, two-head pages | 2/2 | 335,445 / 286,938 | 62.078 / 57.933 s |
| JavaScript complete + recovery | 2/2 | 454,491 / 328,066 | 76.490 / 58.335 s |
| JavaScript selected, two-head pages | 1/2 | 167,470 failed / 339,528 | 34.206 failed / 66.455 s |
| JavaScript guided complete + recovery | 1/2 | 168,862 / 28,696 failed | 69.206 / 29.187 failed s |
| JavaScript guided selected | 2/2 | 124,218 / 129,134 | 53.464 / 58.526 s |
The separate guided JavaScript cohort named the exact configured tools and
allowed one sufficiently large Unknown page for this bounded question. Both
arms received the same discovery guidance. Its single completed complete-arm
sample is insufficient for a stable repeated-pair benefit claim. Native total
input/time overlapped; extra pages and model turns can consume the reply saving.
Do not pool failed tasks as fast answers or attribute guidance changes to REA.
The JSON report records total/cached/uncached input, output, local CPU and peak
memory per attempt. These are client-reported usage counters, not tokenizer
estimates; output includes the client's reported reasoning accounting without
adding it again. Schema/discovery, errors, retries and continuations remain in
the task. Remote model compute, full-catalog model behavior and other hosts were
not measured.
Heavy runs were serial, one CPU, 8 GiB family hard limit, 7 GiB early stop,
no swap. Kernel peaks include charged file cache. Counter observations were
taken at payload exit while the owned observer remained alive; terminal
whole-scope counters remain unknown. Observed payload OOM/capacity events were
zero, all payloads exited and cleanup was verified. The expected MCP response
refusal is a separate transport-capacity outcome.
## Reproduce
Build the pinned runtime, acquire the matching real artifacts and produce the
two authentic histories with the public operations above. Export before close.
Keep bundles, transcripts and model profiles private. For a known source ID:
```sh
node experiments/analysis-efficiency/retained-investigation.mjs \
--runtime-root /absolute/built-rea \
--revision f4322b15ed1423d736bd2572cf7a8eadf2b466e1 \
--bundle /absolute/authentic-history.json \
--evidence-id ev_ORIGINAL_SHA256 \
--scenario native --delivery focused \
--output /absolute/new-receipt-directory
```
Run under the existing process-family resource wrapper, with sufficient bounds
for the selected source. Repeat with `--delivery complete`; use
`--scenario javascript` for module rows. The task's Unknown domain is
`retained-native` or `retained-javascript`. Output is never overwritten.
`agent-trial.py --mode direct` supports the same four enabled names; its success
exit only establishes client completion. Grade original IDs/digests, exact
facts, coverage and Unknowns from the retained transcript and final answer.
For a privately supplied authentic mixed bundle, add `--verify-mixed`. Besides
the normal source query and original-record round trip, this pages every current
head in `javascript-semantic-followup`, checks the current updated revision,
submits a deliberately stale update and a tampered copy of the bundle, verifies
atomic refusal, then checks Unknown/reference lifetime after close. The bundle
must contain genuine follow-ups and at least one updated head. The checkpoint's
64-head bundle passed this mode for both source scenarios. Its extra verification
costs are separate from the original SDK comparison rows above.
Rejected SDK calls are recorded before propagating the original failure, with
request, phase and elapsed time. Reply bytes stay null when no usable reply was
received. Receipt-write failures remain distinct; simultaneous call/write
failures retain both causes. Deterministic failure tests run with
`python3 -m unittest discover -s experiments/analysis-efficiency -p test_retained_queries.py`.
Finalization independently attempts client/transport close, log completion and
both receipt outputs. Cleanup failures preserve the original task failure and
call costs, record the failing phase and retain the workspace for retry. A file
receipt refusal still permits stdout; a broken stdout write is recorded in a
file retry. Files publish through a sibling temporary file and rename; an
interrupted retry preserves the previous receipt. Failed publication files stay
in the owned output directory. Cleanup or receipt-output failures make the
command fail. Six additional regressions exercise stream/file errors, partial
publication and peer cleanup; these are harness failure checks, not real-provider
evidence.
@@ -0,0 +1,310 @@
/** Measure public retained queries against an authentic, previously exported bundle. */
import assert from "node:assert/strict";
import { createHash } from "node:crypto";
import { createWriteStream } from "node:fs";
import {
appendFile,
mkdir,
mkdtemp,
readFile,
writeFile,
} from "node:fs/promises";
import { tmpdir } from "node:os";
import { dirname, isAbsolute, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { parseArgs } from "node:util";
import { finished } from "node:stream/promises";
import canonicalize from "canonicalize";
import { Client } from "@modelcontextprotocol/client";
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
import {
requireMcpOperationResult,
requireMcpToolError,
} from "../../scripts/lib/mcp-verifier-results.mjs";
import { createRetainedQueryCaller } from "./retained-query-calls.mjs";
import { finalizeRetainedQueryReceipt } from "./retained-query-finalization.mjs";
import {
verifyMixedRetainedHistory,
verifyMixedRetainedClosure,
retainedUnknownHeads,
} from "./retained-mixed-verification.mjs";
const { values } = parseArgs({
options: {
"runtime-root": {
type: "string",
default: resolve(dirname(fileURLToPath(import.meta.url)), "../.."),
},
revision: { type: "string" },
bundle: { type: "string" },
"evidence-id": { type: "string" },
scenario: { type: "string" },
delivery: { type: "string" },
output: { type: "string" },
"verify-mixed": { type: "boolean", default: false },
},
});
for (const key of ["runtime-root", "bundle", "output"])
assert.ok(values[key] && isAbsolute(values[key]), `${key} must be absolute`);
assert.ok(values.revision && values["evidence-id"]);
assert.ok(["native", "javascript"].includes(values.scenario));
assert.ok(["complete", "focused"].includes(values.delivery));
const root = values["runtime-root"];
const output = values.output;
await mkdir(output, { recursive: false, mode: 0o700 });
const digest = (bytes) => createHash("sha256").update(bytes).digest("hex");
const sourceBytes = await readFile(values.bundle);
const original = JSON.parse(sourceBytes);
const source = original.records.find(
(record) => record.evidence_id === values["evidence-id"],
);
const operation =
values.scenario === "native"
? "inspect_binary_layout"
: "analyze_javascript_application";
assert.equal(source?.operation, operation);
const unknownDomain = `retained-${values.scenario}`;
const expectedUnknowns = retainedUnknownHeads(original.unknowns, unknownDomain);
// These oracles check selected original facts, not producer discovery completeness.
const expectedRows =
values.scenario === "native"
? source.normalized_result.symbols
: source.normalized_result.graph.nodes
.filter((node) =>
["javascript-asset", "javascript-module", "source-module"].includes(
node.kind,
),
)
.map((node) => {
const candidates = node.observations.flatMap((observation) => {
const property = observation.properties.path;
const where = observation.evidence.location;
return [
...(typeof property === "string" ? [property] : []),
...(where.available && where.value.kind === "artifact-path"
? [where.value.path]
: where.available && where.value.kind === "source-range"
? [where.value.source]
: []),
];
});
return {
node_id: node.node_id,
kind: node.kind,
path:
node.identity.strategy === "canonical-path"
? node.identity.path
: node.identity.strategy === "source-map-original"
? node.identity.original_source
: (candidates[0] ?? null),
};
});
assert.ok(expectedRows.length >= 6, "This task needs six original rows");
const runtimeEntrySha256 = digest(
await readFile(join(root, "dist/mcp/main.js")),
);
const account = await mkdtemp(join(tmpdir(), "rea-retained-query-"));
const transport = new StdioClientTransport({
command: process.execPath,
args: [join(root, "scripts/rea.mjs"), "mcp"],
env: {
PATH: process.env.PATH,
HOME: account,
NODE_OPTIONS: "--max-old-space-size=2048",
REA_LOG_LEVEL: "silent",
},
stderr: "pipe",
});
const serverLog = createWriteStream(join(output, "server.log"));
const serverLogFinished = finished(serverLog);
serverLogFinished.catch(() => {});
transport.stderr?.pipe(serverLog);
const client = new Client({
name: "retained-investigation-measurement",
version: "1",
});
const report = {
revision: values.revision,
runtime_entry_sha256: runtimeEntrySha256,
bundle_sha256: digest(sourceBytes),
bundle_bytes: sourceBytes.length,
source_evidence_id: source.evidence_id,
scenario: values.scenario,
delivery: values.delivery,
verify_mixed: values["verify-mixed"],
calls: [],
status: "running",
};
const call = createRetainedQueryCaller(client, async (receipt, event) => {
report.calls.push(receipt);
await appendFile(
join(output, "transcript.jsonl"),
JSON.stringify(event) + "\n",
);
});
const result = (reply, name) => requireMcpOperationResult(reply, name);
try {
await client.connect(transport);
const started = performance.now();
const catalog = await client.listTools();
report.catalog = {
elapsed_ms: performance.now() - started,
tools: catalog.tools.length,
bytes: Buffer.byteLength(JSON.stringify(catalog)),
sha256: digest(JSON.stringify(catalog)),
};
assert.equal(catalog.nextCursor, undefined);
await writeFile(join(output, "catalog.json"), JSON.stringify(catalog));
result(
await call("import_evidence_bundle", { path: values.bundle }, "import"),
"import_evidence_bundle",
);
const answers = [];
for (let repeat = 0; repeat < 3; repeat += 1) {
let answer;
if (values.delivery === "complete") {
const reply = await call("get_evidence_bundle", {}, `complete-${repeat}`);
if (reply.isError !== true) {
const bundle = result(reply, "get_evidence_bundle");
assert.deepEqual(
bundle.records.find(
(record) => record.evidence_id === source.evidence_id,
),
source,
);
assert.deepEqual(bundle.unknowns, original.unknowns);
answer = [expectedRows.slice(0, 6), expectedUnknowns];
} else {
// Keep capacity refusals and every recovery RPC in the completed task.
const failure = requireMcpToolError(reply);
assert.equal(failure.code, "resource_constraint");
assert.equal(failure.details?.resource, "transport");
report.complete_delivery_refused = true;
}
}
if (answer === undefined) {
const metadata = result(
await call(
"get_evidence_bundle",
{
detail: "summary",
filters: { evidence_id: source.evidence_id },
},
`discovery-${repeat}`,
),
"get_evidence_bundle",
);
assert.equal(metadata.matching_records, 1);
assert.equal(metadata.records[0].evidence_id, source.evidence_id);
const rows = [];
for (const offset of [0, 2, 4]) {
const view = result(
await call(
"inspect_analysis_view",
{
source: {
kind: "retained-evidence",
evidence_id: source.evidence_id,
},
view: {
kind: "page",
collection:
values.scenario === "native" ? "symbols" : "modules",
offset,
limit: 2,
},
},
`page-${repeat}-${offset}`,
),
"inspect_analysis_view",
);
assert.equal(view.parent_evidence_id, source.evidence_id);
assert.equal(view.coverage.total, expectedRows.length);
assert.equal(view.coverage.examined, 2);
assert.equal(
view.coverage.next_offset,
offset + 2 < expectedRows.length ? offset + 2 : null,
);
assert.deepEqual(view.items, expectedRows.slice(offset, offset + 2));
rows.push(...view.items);
}
const unknowns = [];
let offset = 0;
do {
const page = result(
await call(
"list_unknowns",
{ domain: unknownDomain, offset, limit: 2 },
`unknowns-${repeat}-${offset}`,
),
"list_unknowns",
);
assert.equal(page.total, expectedUnknowns.length);
assert.equal(page.offset, offset);
assert.deepEqual(
page.items,
expectedUnknowns.slice(offset, offset + 2),
);
assert.equal(
page.next_offset,
offset + 2 < expectedUnknowns.length ? offset + 2 : null,
);
unknowns.push(...page.items);
offset = page.next_offset;
} while (offset !== null);
assert.deepEqual(unknowns, expectedUnknowns);
answer = [rows, unknowns];
}
answers.push(digest(canonicalize(answer)));
}
assert.equal(new Set(answers).size, 1);
report.answer_sha256 = answers[0];
if (values["verify-mixed"])
report.mixed_verification = await verifyMixedRetainedHistory({
call,
original,
sourceId: source.evidence_id,
output,
});
const roundtrip = join(output, "roundtrip.json");
result(
await call("export_evidence_bundle", { path: roundtrip }, "export"),
"export_evidence_bundle",
);
const exported = JSON.parse(await readFile(roundtrip, "utf8"));
const exportedRecords = new Map(
exported.records.map((record) => [record.evidence_id, record]),
);
for (const record of original.records)
assert.deepEqual(exportedRecords.get(record.evidence_id), record);
assert.deepEqual(exported.unknowns, original.unknowns);
report.original_records_preserved = true;
result(await call("close_binary", {}, "close"), "close_binary");
const closed = result(
await call("get_evidence_bundle", { detail: "summary" }, "after-close"),
"get_evidence_bundle",
);
assert.equal(closed.total_retained_records, 0);
report.close_cleared_records = true;
if (values["verify-mixed"])
Object.assign(
report.mixed_verification,
await verifyMixedRetainedClosure(call, source.evidence_id),
);
assert.equal(digest(await readFile(values.bundle)), report.bundle_sha256);
report.status = "passed";
} catch (cause) {
report.status = "failed";
report.failure = { name: cause.name, message: cause.message };
} finally {
const finalized = await finalizeRetainedQueryReceipt({
report,
client,
transport,
account,
serverLog,
serverLogFinished,
output,
});
if (report.status !== "passed" || !finalized) process.exitCode = 1;
}
@@ -0,0 +1,163 @@
import assert from "node:assert/strict";
import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import {
requireMcpOperationResult as result,
requireMcpToolError,
} from "../../scripts/lib/mcp-verifier-results.mjs";
/** Expected current heads from the original exported revisions, not displayed pages. */
export const retainedUnknownHeads = (unknowns, domain) => {
const heads = new Map();
for (const unknown of unknowns) {
const previous = heads.get(unknown.unknown_id);
if (previous === undefined || previous.revision < unknown.revision)
heads.set(unknown.unknown_id, unknown);
}
return [...heads.values()]
.filter((unknown) => unknown.domain === domain)
.sort((a, b) =>
a.unknown_id < b.unknown_id ? -1 : a.unknown_id > b.unknown_id ? 1 : 0,
);
};
const verifyFollowupPages = async (call, original) => {
const expected = retainedUnknownHeads(
original.unknowns,
"javascript-semantic-followup",
);
assert.ok(
expected.length > 0,
"Supply an authentic mixed history with semantic follow-ups",
);
const revised = expected.find((unknown) => unknown.revision > 1);
assert.ok(revised, "Mixed verification requires a retained updated Unknown");
let offset = 0;
let pages = 0;
const observed = [];
do {
const page = result(
await call(
"list_unknowns",
{
domain: "javascript-semantic-followup",
offset,
limit: 2,
},
`mixed-heads-${offset}`,
),
"list_unknowns",
);
assert.equal(page.total, expected.length);
assert.equal(page.offset, offset);
assert.deepEqual(page.items, expected.slice(offset, offset + 2));
assert.equal(
page.next_offset,
offset + 2 < expected.length ? offset + 2 : null,
);
observed.push(...page.items);
offset = page.next_offset;
pages += 1;
} while (offset !== null);
assert.deepEqual(observed, expected);
return { revised, headsChecked: expected.length, pages };
};
const verifyMutationRefusals = async ({
call,
original,
sourceId,
output,
revised,
}) => {
const before = result(
await call(
"get_evidence_bundle",
{ detail: "summary" },
"mixed-before-refusals",
),
"get_evidence_bundle",
);
const stale = await call(
"update_unknown",
{
unknown_id: revised.unknown_id,
expected_revision: revised.revision - 1,
status: revised.status,
severity: revised.severity,
supporting_evidence_ids: revised.supporting_evidence_ids,
contradicting_evidence_ids: revised.contradicting_evidence_ids,
required_authority: revised.required_authority,
required_confidence: revised.required_confidence,
required_environment: revised.required_environment,
recommended_probes: revised.recommended_probes,
relationships: revised.relationships,
resolution: revised.resolution,
},
"mixed-stale-update",
);
assert.equal(requireMcpToolError(stale).code, "revision_conflict");
const tampered = structuredClone(original);
const target = tampered.records.find(
(record) => record.evidence_id === sourceId,
);
assert.ok(target);
target.normalized_result = { checkpoint_tampered: true };
const path = join(output, "tampered-import.json");
await writeFile(path, JSON.stringify(tampered), { flag: "wx" });
const rejected = await call(
"import_evidence_bundle",
{ path },
"mixed-tampered-import",
);
assert.equal(
requireMcpToolError(rejected).code,
"evidence_integrity_mismatch",
);
const after = result(
await call(
"get_evidence_bundle",
{ detail: "summary" },
"mixed-after-refusals",
),
"get_evidence_bundle",
);
assert.deepEqual(after, before);
};
/** Verify original mixed-history heads, CAS rejection and atomic import failure. */
export const verifyMixedRetainedHistory = async (options) => {
const { revised, headsChecked, pages } = await verifyFollowupPages(
options.call,
options.original,
);
await verifyMutationRefusals({ ...options, revised });
return {
heads_checked: headsChecked,
pages,
revised_unknown_id: revised.unknown_id,
revision_checked: revised.revision,
stale_update_rejected: true,
tampered_import_rejected_atomically: true,
};
};
/** Closing must neither retain old Unknowns nor rehydrate a closed source. */
export const verifyMixedRetainedClosure = async (call, sourceId) => {
const unknowns = result(
await call("list_unknowns", {}, "mixed-after-close-heads"),
"list_unknowns",
);
assert.equal(unknowns.total, 0);
const missing = await call(
"inspect_analysis_view",
{
source: { kind: "retained-evidence", evidence_id: sourceId },
view: { kind: "summary" },
},
"mixed-after-close-reference",
);
const failure = requireMcpToolError(missing);
assert.equal(failure.details?.reason, "missing");
return { unknowns_after_close: 0, old_reference_refused: true };
};
Loaded 100 of 1251 files, more files were not shown because too many files have changed in this diff. Show more