Compare commits

...
Author SHA1 Message Date
morluto f2cffbdfdc fix(pcap): preserve executable read failures 2026-10-22 06:09:50 +08:00
morluto 5e046bb374 fix(pcap): read historical capture evidence 2026-10-22 06:05:55 +08:00
morluto 4924706e25 fix(pcap): report missing selected tools clearly 2026-10-22 05:52:17 +08:00
morluto 211d4b2219 perf(pcap): retain compact executable identity 2026-10-22 05:47:11 +08:00
morluto cb6dc4f3ef fix(pcap): share selected tool identity verification 2026-10-22 05:40:52 +08:00
Kaoru0822andClaude Opus 5.5 658c29b7fc chore: restore main's copies of files the merge hook reformatted
The pre-commit oxlint --fix touched two files this PR does not change; keep them identical to main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 03:22:28 +00:00
Kaoru0822andClaude Opus 5.5 a22adc7809 Merge origin/main into refactor/tshark-single-owner
Resolve the node:fs/promises import conflict in pcapProviderCrossPlatform.test.ts by importing open, symlink and writeFile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 03:04:35 +00:00
morluto d0067ba34a fix(native)!: preserve Swift pointer nullability and import bindings
Resolve relative pointers using field-owned ABI encodings. Keep null, raw, rebased, imported and unknown targets distinct, and retain imported conformance rows with exact Mach-O binding provenance. Decode legacy rebase membership with source-derived memory and work bounds, preserving validated prefix facts when streams are incomplete.

Validation: check:ci, docs:check and build passed; 158 source tests and 20 schema/acceptance tests passed. Ten source-built Apple dispatch variants and four issue-specific CLI/MCP workflows passed without executing targets. Paired cold/warm CLI/MCP cost observations retained locally; model tokens and maximum-sized input runtime were not measured.

Closes #5683
Closes #5685

BREAKING CHANGE: Swift conformance type_name and protocol_name can be null when names cannot be resolved; consumers must use typed type_binding and protocol_binding evidence. MachoImportBinding replaces the former Objective-C-specific binding type and schema.
2026-10-21 08:17:12 +08:00
morluto 9258df02cc test(apple): compare asset catalogs from matching root workflows
Compare explicit bundle-resource CLI and MCP results at the positive empty-inventory offset. Preserve a separate binary-bound MCP assertion with the exact fixture executable digest and complete metadata payload.

Validation: reproduced the stale root-versus-binary parity failure on current main, then passed the macOS public CLI/MCP acceptance case across all five NIB fixtures. Focused lint, formatting and diff checks passed. No target code was executed.
2026-10-21 07:37:36 +08:00
morluto 1502cfbc8c fix(apple): resolve absolute dylib paths inside the selected root
Preserve load-command paths as evidence while passing a separate root-relative lookup path to the bounded tree resolver. Apply the same containment rule to absolute install names and rpath bases, including caller-selected root symlink spellings.

Validation: 140 source tests, full check:ci, docs and runtime build passed. Compiler-built literal, rpath and relative fixtures passed CLI/stdio MCP parity, preserved both dependency edges and left all bytes unchanged. External system paths stayed outside-target; relative control was unchanged. Fixtures were not executed, and actual dyld execution was not qualified.

Closes #5637
2026-10-21 07:37:15 +08:00
morluto 84c89d1107 test(javascript): separate heap pressure from graph admission proof
Match memory failures to the exact source identity instead of graph ordering. Preserve CLI parse, file-evidence, partial-result, later-source and unchanged-input checks across valid memory-pressure outcomes. Use a controlled parent heap envelope with a real owned analyzer to prove module retention and graph rejection independently of host GC timing.

Validation: full check:ci passed; 17 focused tests passed, with the final 4 changed tests rerun successfully. Independent test-strength and isolation review passed. The earlier hosted failure exposed missing graph-only fields; its exact alternate memory stage was not captured.
2026-10-21 07:26:20 +08:00
morluto 0bd14ca16c fix(browser): preserve uncertain main-frame navigation identity
Own CDP frame applicability and identity at the parsed event boundary. Preserve malformed or incomplete main-frame facts, recognize replacement roots, and carry the same document identity through captures, screenshots, timelines, and execution windows.

Validation: full check:ci and docs:check; 763 browser and dispatch tests passed, 6 skipped. Independent source and fixture-lifecycle review passed. Local real-Chrome behavior was not exercised.

Closes #5665
2026-10-21 07:16:47 +08:00
morluto 9dee989a79 fix(native): count Objective-C coverage by class object
Count each admitted unique class or metaclass object at its parsing owner. Preserve emitted metadata, independent class-list scan bounds, partial failures, and truncation.

Closes #5706
2026-10-21 07:01:17 +08:00
morluto f789fd1fd8 fix(native): count Swift vtable coverage in slot units
Count examined and decoded vtable slots in the same population, preserving all returned slots and partial descriptor failures. Document the coverage unit and retain malformed-sibling and unresolved-slot checks.

Closes #5681
2026-10-21 06:56:18 +08:00
morluto ccc7da309d test(mcp): retain distinct Objective-C class observations
Require both fixture addresses and unknown identity coverage when no selected-image binding proof permits coalescing.
2026-10-21 06:45:34 +08:00
morluto 56679dd2ae fix(files): preserve physical read provenance through cleanup
Keep raw physical read diagnostics alongside explicit operation provenance on the same cleanup owner. Preserve provenance after successful close retry for opted-in readers, restore legacy error projections, and prevent borrowed cleanup-shaped failures from authorizing foreign resource retries.

Refs #5686
2026-10-21 06:45:34 +08:00
morluto 52c84f6f58 test(cli): bound ADB MCP validation to the advertised tool
Reuse the exact selected advertised descriptor for SDK output validation instead of compiling the entire cached catalog for every fresh parity-test client. Retain actual catalog discovery, schema validation, and all result assertions under the existing worker heap limit.
2026-10-21 06:23:20 +08:00
morluto 4852c830af fix(native): preserve Mach-O names equal to version
Parse only documented compound otool field labels so valid segment and section names are retained at the owning boundary. Verified real Apple clang fixtures through compiled CLI and stdio MCP without executing the targets.

Closes #5680
2026-10-21 06:19:43 +08:00
morluto 949966712e fix(files): preserve physical read failures across late cancellation
Tag physical read outcomes at the owning boundary and preserve opaque caller cancellation reasons through JSON pipelines and reference imports. Share named bounded-read options across consumers and retain failed cleanup ownership for retry.

Closes #5686
2026-10-21 06:14:03 +08:00
morluto 4d7de00d4c fix(native): coalesce Objective-C class imports by binding identity
Join provider class observations only when selected-image identity and exact import bindings establish equivalence. Preserve distinct observations and unsupported coverage.

Refs #5607
2026-10-21 06:12:21 +08:00
morluto b231c28cf6 fix(hopper): own Mach-O preparation through cleanup retry
Preserve exact selected-image identity and descriptor ownership across preparation, final cleanup, and retries. Keep physical failures and failed cleanup leases observable through provider and launcher boundaries.

Closes #5688
2026-10-21 06:12:09 +08:00
morluto 7dd6941393 refactor(test): share browser and apktool fixture lifecycles 2026-10-21 05:50:50 +08:00
morluto 1bb2fa23de test(apple): match plist provenance to the selected workflow 2026-10-21 05:50:50 +08:00
morluto ab58edcdf5 fix(environment): retain tarball descriptor ownership during export
Use the shared positional reader for both tarball passes so early output refusal cannot close the descriptor ahead of its owner.

Closes #5684
2026-10-21 05:33:35 +08:00
morluto 60956c8c56 fix(ci): run cache retention from its trusted workflow revision 2026-10-21 05:28:08 +08:00
morluto 5518363aa6 test(artifacts): compare matching resource-root workflows 2026-10-21 05:28:03 +08:00
morluto 4108d1363a test(cli): align Kuna readiness and cancellation expectations 2026-10-21 05:27:56 +08:00
morluto 0bc2b42001 fix(browser)!: preserve unknown WebSocket frame facts
Keep malformed or missing CDP opcodes and payload facts unknown, retain observed zero and empty payloads, and avoid false capture differences while preserving independently known facts.

Validation: 59 source tests; compiled public CLI and stdio MCP fake-CDP acceptance; check:fast; docs:check; changed-file formatting. Real Chromium malformed-event behavior was not tested.

BREAKING CHANGE: WebSocket event opcode is nullable and numeric values are restricted to the four-bit protocol range.

Fixes #5666
2026-10-21 05:00:37 +08:00
c38f96fa69 test(cli): keep IPC trace input under the Linux spawn limit (#5673)
* test(cli): keep IPC trace input under the Linux spawn limit

The listener-callsite CLI builds one trace argument from the full
application Evidence document. On 4 KiB-page Linux that string exceeds
MAX_ARG_STRLEN, so spawn throws E2BIG before the command starts. Keep the
document in a file, require the spawned argv to fit the single-argument
budget, and lock that budget through the test process registry.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test(process): size the spawn ceiling from ARG_MAX and MAX_ARG_STRLEN

A payload at the single-string limit still fails execve with E2BIG when
the stack shrinks ARG_MAX below the rest of the image. Accept only the
bytes that fit both budgets, and skip that success spawn when the fixed
argv and environment already fill ARG_MAX.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* style(test): format files rejected by oxfmt in static checks

check:ci:fast failed format:check on the CLI fixture import and, after
merging main, on the admission test's new command-abort case.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-21 04:48:33 +08:00
Ulises Millán c4b6aa3061 fix(managed): treat extension-only module scopes as unknown identity (#5674)
Closes #5467
2026-10-21 04:35:45 +08:00
morluto dceefa22cb Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-21 04:22:27 +08:00
morluto 6a6adf703f fix(resources)!: inspect app resources without an executable
Add a read-only app resource session shared by CLI and MCP. Preserve resource-root provenance without inventing executable identity, reject binary-only snapshots and operations, and retain failed cleanup owners across switches and retries.

Keep filesystem admission failures typed and preserve cancellation ordering from observed cleanup facts. Document resource routing in the packaged investigation skill.

BREAKING CHANGE: resource-only observations may have a null Evidence subject and null executable target digests. Clients must use resource_root and reported per-resource provenance instead.

Refs #5589
2026-10-21 04:22:20 +08:00
de4579e993 fix(observation): keep incomplete cancellation observations (#5644)
* fix(observation): keep incomplete cancellation observations

Service projection treated a retained observation that failed the completed
schema as a malformed completed result. Cancellation became unreadable_output
and the partial was dropped. Incomplete observations now stay on the owner
error, including the exact abort reason.

* fix(observation): drop non-JSON incomplete observations

Keep a retained partial only when projectAnalysisError can serialize it.
Clear a non-JSON partial and record an AnalysisOutputError as a secondary
failure so cancellation and timeout stay the owner error.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(observation): validate incomplete partials without copying

jsonValueSchema.safeParse cloned a JSON-safe partial that projection
copies again. Use jsonValueValidationIssue so the gate only checks.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test(ida): expect non-retryable unresolved procedure lookups

Main stops treating invalid_request as retryable. An unchanged missing
procedure stays invalid_request and is not marked retryable.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test(observation): share incomplete-observation assertions

The new non-JSON cases repeated the same owner-error checks and pushed
duplication over the 3.5% limit. One expectation helper keeps those
checks without a second copy.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test(observation): keep the assertion helper out of the package

The helper imports Vitest. Rename it to a fixture so the production
build excludes it and dist does not import a dev dependency.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(observation): clear non-JSON partials on cleanup primaries

Projection can return the cleanup primary after retry. Clearing only
the wrapper left that primary's partial in place, so projectAnalysisError
threw. The gate now clears every non-JSON partial in the chain.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(observation): freeze retained incomplete observations

A JSON partial stayed a live provider object, so a later mutation could
make projection throw. The gate now keeps one frozen snapshot and still
drops a non-JSON partial without copying it.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* refactor(observation): share web runtime partial retention

Observe and inspect used the same promote-or-keep path. One helper
owns that sequence so the two operations cannot drift.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(observation): snapshot a shared partial once

A cleanup wrapper and its primary can hold the same partial object.
The gate now reuses the first frozen snapshot for that object.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(observation): parse a kept partial once

jsonValueSchema.safeParse validates and copies only a JSON partial.
The gate freezes that copy and no longer walks the same value first.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test(observation): share repeated observation fixtures

The incomplete-observation tests repeated the same provider setup and
an empty Electron coverage tail, which pushed duplication over 3.5%.
One coverage fixture and shared assertions bring the tree back under
the threshold.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-21 04:17:46 +08:00
6b101ff23b fix(errors): preserve caller abort reasons at admission (#5671)
* fix(errors): preserve caller abort reasons at admission

Keep the opaque caller reason on reverse, pcap, and SQLite cancellation,
and leave a recognized physical digest or command failure in place when a
late abort is also observed.

Fixes #5670

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(reverse): keep a foreign digest ABORT_ERR as an adapter failure

Treat ABORT_ERR as cancellation on the command boundary, where that code
already meant an aborted provider process. A digest or stat rejection with
the same code stays a physical adapter failure unless the caller signal
is aborted. Cover aborted command EACCES, ETIMEDOUT, and ABORT_ERR with
and without captured output.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-21 04:16:44 +08:00
morluto 6389e50337 Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-21 03:57:03 +08:00
morluto d23be5c089 fix(web): preserve static WebMCP schema property coverage
Reuse the shared object-member owner for literal spreads, retain known property names under unresolved membership, and distinguish complete, partial, unknown, and absent projections. Keep historical coverage omission unchanged and preserve own keys across prototype setters.

Refs #5075
2026-10-21 03:56:35 +08:00
c0cbbf8d50 perf(ci): keep fast built shards under ten minutes (#5652)
* test(acceptance): split competing loader ownership across files

The loader matrix was one 578-second file, which set the floor for any
shard that received it. Three files keep every CLI and MCP case and let
workers overlap them.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* perf(ci): run eight fast built shards under a ten-minute budget

Charge each Vitest project by its resolved worker width so serial
process-boundary files spread as tail time. Fast feedback uses eight
built shards. The npm download cache stays; node_modules is too large
to ship as a shared artifact.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(ci): keep each scheduled file on one worker lane

Dividing a file by maxWorkers dropped its own wall-time floor and could
pack a parallel file onto a serial tail. Place each file whole on a lane,
overlap peers only inside a sequence group, and add later groups after.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* docs(testing): separate the shard budget from workflow time

The ten-minute figure is the built shard job. Classification, build, and
the portable-test merge are measured separately on run 39451548945.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* docs(testing): match fast shard count to lane scheduling

Main still described five shards and half-duration weights. Fast
qualification uses eight shards, and each file keeps its full duration
on one worker.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(ci): seed split loader durations from pre-split history

Timings published before the file split still name one 578-second path.
Until a new file appears in that artifact, share the recorded duration
by the pre-split case counts.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-21 03:55:40 +08:00
morluto a7d13893a6 Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-21 03:50:44 +08:00
morluto 1bfa60ac20 fix(cli): preserve caller-selected JSON paths
Keep POSIX symlink-parent traversal at the shared JSON input boundary and forward the selected browser executable without a second lexical normalization. Verify Electron, browser, and Evidence-file consumers through registered commands and the built CLI.

Refs #5103
2026-10-21 03:50:14 +08:00
9d8e780332 ci: keep npm download caches from Turbo snapshot growth (#5655)
* ci: keep npm download caches from Turbo snapshot growth

Per-commit static and portable Turbo snapshots had filled the 10 GB Actions
cache, which is what makes warm npm ci cheap. Trusted static runs now keep two
generations and one download-cache writer per host.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(ci): declare cache retention types for strict checks

Typecheck imports cache-retention.mjs and needs a sibling declaration.
The generation count stays module-private so knip does not report it.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(ci): keep compatible caches and qualification read-only

Npm dedupe deletes a record only when another has the same key, version,
and ref. Cache deletion moves to a follow-up workflow so reusable
qualification can keep its read-only token.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(ci): retain caches after failed default-branch runs

Static and build save Turbo snapshots before later lanes finish. Retention
now follows a failed, timed-out, or cancelled trusted run, not only a green one.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test(cli): pass application trace input as a file

The CLI already reads workflow JSON from a path. Putting the full
application Evidence document on argv exceeds the runner argument limit.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(ci): retain deep and Knip snapshots without deleting a repeated id

Fast and deep static checks publish rea-static-deep-v1 and knip-meta-v1
entries per commit. Retention prunes those families with the same two-generation
rule. A cache id listed twice is one record; inconsistent repeats abort
before any delete.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-21 03:48:14 +08:00
40428da1dd perf(test): reuse one stdio MCP server per JavaScript application file (#5658)
* perf(test): reuse one stdio MCP server per JavaScript application file

Repeated analyzeJavaScriptDirectory MCP cases started a full server for
every case. Share one file-scoped server and compile cache so later cases
skip that startup while CLI cases still launch a fresh process.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(test): close in-flight shared MCP startup with the file

File teardown waits for a stdio session that is still starting, skips a
server once close has begun, and still closes one registered during that
wait. The later-case reuse test can run without the earlier case.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(test): keep a failed MCP handshake when cleanup fails

The shared session reports the startup error and carries the cleanup failure
as its cause. A cleanup that failed stays owned and is retried on close
without running a cleanup that already succeeded.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(test): fail shared MCP cleanup when the rejection has no reason

A cleanup rejection of undefined still fails the drain and stays owned.
Close caches completion only after every retained cleanup succeeds, so a
later close can release it.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(test): keep one MCP server while failed cleanup is retained

A later call retries retained cleanup before opening another server. The
new server starts only after that cleanup succeeds.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-21 03:46:14 +08:00
morlutoandCursor Agent ef59174c1e fix(errors): name fixed allowances in resource-constraint recovery (#5633)
* fix(errors): name fixed allowances in resource-constraint recovery

Fixed parser, count, report, input, and capture refusals inherited
host-memory, wait-and-retry, or retained-Evidence advice. Producers now
attach allowance-specific recovery, and deterministic capacity caps are
not retryable. IL2CPP reader occupancy stays retryable capacity.

Refs #5556, #5405, #5456, #5459, #5460, #5504, #5505, #5506, #5537, #5628, #5630, #5631, #5632

* fix(il2cpp): keep a closing metadata reader non-retryable

close() stops admission before the active inspection finishes. A second
inspect in that window was projected as retryable capacity. Closing and
closed readers now report capability_unavailable. Occupied readers that
remain open stay retryable.

* fix(errors): align fixed-cap recovery with retained facts

IL2CPP report refusals keep observed source facts instead of denying Evidence. Command-output caps use the capture allowance. Ghidra seed recovery names the limit that was exceeded.

* fix(errors): call byte caps a byte allowance

WASM representation limits and the IL2CPP Ghidra seed-file cap are byte budgets. Their recovery no longer says the exceeded allowance is a fixed count.

* test(ida): keep unresolved procedure lookups non-retryable

Main now treats an unchanged invalid request as non-retryable. The IDA lookup tests follow that projection.

* fix(errors): qualify capture recovery for live output

A fixed capture allowance still rejects the same output. Live captures such as adb logcat can change between requests, so recovery no longer says every unchanged request fails again.

* fix(adb): keep a truncated live capture retryable

Device output can shrink between calls, so an adb capture that exceeds the allowance stays retryable. Deterministic capture and version-output limits stay non-retryable.

* fix(adb): keep truncated mutations non-retryable

Only live observations opt into retrying a capture that exceeded the allowance. Push, install, uninstall, and other mutations stay non-retryable.

* fix(errors): keep live capture recovery off deterministic limits

Artifact-derived capture allowances again say the unchanged request fails. Only volatile adb observations use the live-output sentence.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-10-21 03:45:34 +08:00
53e0943223 fix(javascript): preserve path reasons, module coverage, and property provenance (#5651)
* fix(javascript): preserve selected path host resolution reasons

Classify ELOOP and ENAMETOOLONG while resolving the caller-selected input so the path and host code stay on the invalid-request issue.

Refs #5623

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(javascript): count summary coverage in module units

Use the module population for both examined and total counts. Non-module graph nodes remain in the application coverage section.

Refs #5464

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(javascript): connect direct property reads to return and argument flow

Record the unwrapped value expression and alias the object projection's read occurrence so a direct member read stays in backward provenance.

Refs #5585, #5648

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(javascript): count return wrappers against expression depth

Evaluate the original return expression so erased TypeScript and Flow wrappers stay inside the expression-depth budget. Keep the unwrapped node for identity and value ranges.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(javascript): describe ELOOP as unresolved symlink traversal

A host can return ELOOP for a cycle or for a chain past its traversal limit. Keep the selected path and code without asserting that a cycle exists.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test(javascript): skip symlink traversal fixtures on Windows

Keep the overlong-name case portable. Windows does not produce ELOOP for these fixtures, matching the other path-failure tests.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(javascript): describe ENAMETOOLONG as a path or component limit

realpath reports that code for a long component and for a long full path. Keep the selected path and host code without claiming only a filename was too long.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* style(javascript): format return-depth and object-read changes

oxfmt rejected the return-depth test and the object-read index. No behavior change.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test(ida): expect unchanged invalid requests to be nonretryable

The shared projector no longer marks invalid_request retryable. This lookup assertion was not updated with that contract.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-21 03:45:10 +08:00
b718ad166d fix(doctor): reject unusable Kuna caches and invalid native settings (#5647)
* fix(kuna): reject dangling cache roots in doctor

Treat a cache path as creatable only when no directory entry occupies it.
A dangling symbolic link, including one hidden by a trailing separator,
fails the cache check and clears provider availability while the installation
check and caller-selected registration settings remain.

Fixes #5554
Fixes #5105

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(doctor): admit the same settings native analysis rejects

Project parseConfig failures into scoped engine readiness. Invalid provider
preferences, startup timeouts, and other shared settings now fail the
selected provider and the full audit, while a JEB-only timeout stays outside
that admission.

Fixes #5454

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(doctor): report an invalid log level from doctor

The dispatcher rejected REA_LOG_LEVEL before every command, so doctor never
emitted its readiness check. Doctor now runs and names that setting; other
commands still stop before execution.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(doctor): require log-level failures in every scope

An invalid REA_LOG_LEVEL stops the executable and MCP server before a client
or skill can run, so those scopes now fail readiness too. Other native
admission failures stay limited to a selected provider.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(kuna): strip only the platform cache separator

On Darwin and Linux a trailing backslash is a filename character. Doctor now
removes only the selected platform separator before inspecting the cache path.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(doctor): fail every provider on an invalid Hopper timeout

REA_HOPPER_STARTUP_TIMEOUT_MS is rejected before any native engine starts.
A selected non-Hopper provider now includes the existing timeout check.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* style(doctor): format the Hopper timeout regression

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(doctor): fail client scopes on MCP startup errors

A registered client starts the MCP server, and parseConfig rejects every
native admission failure before that server starts. Client readiness now
includes those failures, not only REA_LOG_LEVEL.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-21 03:44:49 +08:00
morluto 690fc51854 fix(browser)!: preserve unknown console timestamps
Retain absent or invalid Runtime timestamps as null and mark console event coverage incomplete. Preserve observed finite timestamps, including zero, and document the epoch-millisecond clock.

BREAKING CHANGE: console event timestamps may now be null when the protocol does not provide a finite number.

Refs #5656
2026-10-21 03:43:20 +08:00
23196daa11 fix(apple): read LC_LAZY_LOAD_DYLIB_INFO dependency payloads (#5650)
* fix(apple): read LC_LAZY_LOAD_DYLIB_INFO dependency payloads

Parse the linkedit install name for lazy-load info commands, resolve those
edges without traversing them, and stop inspect-macho from treating an otool
dependency list as exhaustive when that payload is omitted.

Fixes #5551
Fixes #5649

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(apple): bound lazy-load payload reads and image offsets

Reuse identical LC_LAZY_LOAD_DYLIB_INFO ranges, cap their combined size,
and reject flag or chain-start offsets outside the slice VM range.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(apple): bound lazy-load string scans and contained reads

Reject payload strings that start in the 24-byte header, validate each
file-offset string once, and reuse payload bytes already read for a
containing range.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(apple): reject cached lazy-load strings outside a payload

Remember each cached string's terminating offset and require that NUL to
fall inside the payload being decoded.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(apple): bound lazy-load payload range lookups

Count containment checks across earlier payload reads and stop at the
existing 16 MiB work limit.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(apple): count every lazy-info string reference

Charge repeated and overlapping LC_LAZY_LOAD_DYLIB_INFO scans against the
16 MiB validation budget, and stop a scan once that budget is exhausted.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(apple): cap retained lazy-info dependency results

Stop after 1024 LC_LAZY_LOAD_DYLIB_INFO commands so a load-command region
full of identical commands cannot become a million traced edges.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(apple): reject a lazy-load path NUL in the final byte

dyld stops the load-path scan before the payload's last byte, so a
terminator in that byte leaves the image malformed.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(apple): keep may-be-missing lazy loads optional

A missing LC_LAZY_LOAD_DYLIB_INFO with the may-be-missing bit is weak, so the lazy finding says dyld continues on first use instead of failing.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(apple): cap lazy-info symbol string references

A payload of distinct one-byte symbol strings stayed under the byte budgets while caching one entry per offset. A slice now stops at 65536 symbol references.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-21 03:33:07 +08:00
0add6a5aae ci: split fast and deep static checks (#5634)
* ci: split fast and deep static checks

Fast PRs run typecheck, lint, and format before provider admission.
Knip, duplication, architecture guards, and Python stay on the full tier.
Shared-boundary fallbacks keep the Linux x64 baseline, and Turbo jobs
export remote-cache credentials when they are configured.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* ci: keep pull requests from writing the remote cache

Trusted default-branch runs still receive TURBO_TOKEN. Pull requests get an
empty token and remote read-only mode. Knip saves a per-commit cache key so
the next trusted full run can refresh the restored snapshot.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* ci: forward the release cache token and upload deep static reports

Release qualification now passes TURBO_TOKEN into the called workflow.
Labeled pull requests still do not. The deep static job records its task
context and uploads duplication reports after a failed gate.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* style: format the turbo cache policy test

Co-authored-by: morluto <morluto@users.noreply.github.com>

* ci: keep fast checks exclusive and trusted cache writes explicit

Declare the static artifact name and context script so typecheck matches the
implementations. Lock check:ci:fast around dist, and publish the remote cache
only for release qualification or default-branch push, schedule, and dispatch.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* ci: record static task graphs without nesting the artifacts lock

Keep check:ci:fast locked, and point graph recording at the unlocked
check:ci:fast:tasks script so check:pr and check:test can record hashes
while they already hold that lock.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* ci: keep unauthenticated Turbo runs on the local cache

Open pull requests do not receive TURBO_TOKEN, so a remote read mode cannot
authenticate. Those runs now use the local cache. Trusted runs still publish.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test(ida): treat unchanged invalid requests as nonretryable

Main already stopped marking invalid_request retryable. The pull request
merge runs that projector, while the IDA lookup tests still expected
retryable true. Match the merged behavior.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-21 03:29:31 +08:00
morluto 0dbc046ca6 Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-21 03:28:13 +08:00
morluto 2a0410f171 fix(browser)!: bind session timelines to the observation window
Sample the browser monotonic clock with observation already subscribed, filter historical lifecycle and network facts, and preserve scope and termination handling when event time is unknown.

Bound pre-arm retention using transport-owned wire bytes. Fail closed when the relevant-event buffer fills, and keep unrelated protocol payloads outside that budget.

BREAKING CHANGE: observe_web_session timeline timestamps can be null when the producer supplies no comparable timestamp. Consumers must handle unknown time explicitly.

Refs #5609
2026-10-21 03:27:31 +08:00
gensokyo-dev 4bfdadb7de perf(frida): add retained summaries for session status (#5661)
Add opt-in Frida session status summaries linked to complete retained Evidence. Share canonical session facts across contracts and preserve observed state, source identity and capture truncation.

Validated with native SDK/client workflows, default delivery compatibility, lifecycle and provenance tests. The completed large-history task uses 50.9% fewer estimated request tokens; no general CPU or latency improvement is claimed.

Fixes #5640
2026-10-21 03:21:30 +08:00
morluto 1629266e3c fix(errors): preserve canonical failures and correction details
Retain process input and unexpected failure diagnostics through the shared error projector. Preserve filesystem causes and firmware validation issues, and mark unchanged invalid requests nonretryable.

Use typed stat settlement and parse unknown command failures without losing null or undefined rejection causes.

Refs #5397, #5401, #5402, #5642
2026-10-21 02:03:17 +08:00
morluto b3aadaf474 fix(il2cpp): preserve recognized truncated metadata prefixes 2026-10-21 01:47:09 +08:00
morluto eb7acc70bf fix(native): verify signature snapshots and frame unsigned diagnostics
Bind and recheck the digest-verified snapshot used by codesign, retaining cleanup ownership when its identity changes. Classify unsigned only from the exact operand-framed diagnostic so echoed caller paths cannot turn unrelated failures into signature facts.

Closes #5636
2026-10-21 01:35:44 +08:00
morluto 998882045b Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-21 01:31:57 +08:00
morluto eb41f358cf fix(model): retain completed GGUF facts on interrupted reads
Keep parser-owned completed metadata and tensor declarations as typed partial Evidence on cancellation or physical read failure. Preserve unknown final identity and digests, exact caller inputs, primary failures, and retained cleanup owners; support inline and retained MCP error delivery.

Closes #5625
2026-10-21 01:31:17 +08:00
gensokyo-dev 17f581ff75 perf(reverse): add retained GDB and objdump summaries (#5614)
Add opt-in retained GDB and objdump summaries using the shared analysis-view layer. Preserve default complete Evidence, ordered records, provenance and completion facts.

Validate real Bash disassembly, whole-client context costs, CLI publication and cleanup; retain the original measured cohorts and explicit coverage limitations.

Closes #5584.
2026-10-21 01:20:52 +08:00
morluto edbd291a28 Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-21 01:13:13 +08:00
morluto 2b263a7fe9 fix(native): retain Mach-O facts when dyld rejects missing UUID
Admit only the corroborated missing-UUID validation diagnostic from header-stripped dyld stdout. Preserve readable load commands and nm exports with unknown dyld coverage, and keep unrelated process and tool failures typed.

Closes #5606
2026-10-21 01:12:51 +08:00
gensokyo-dev d98fc3859d test(evaluation): include native preparation in test deadlines (#5627)
Derive Darwin subprocess test budgets from the bounded ownership compiler budget while preserving short command deadlines. Always join the retained command scope after test failures.

Refs #5094.
2026-10-20 17:10:11 +00:00
morluto d0eca0517e Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-21 01:02:22 +08:00
Kaoru0822andClaude Opus 5.5 85b379c4ca test(evidence): assert the exact cancellation reason after staging cleanup fails (#5601)
52d1a72af made a cancelled write whose staging cleanup also fails carry the
caller's exact abort reason as its cause, with the cancellation retained as
cleanupPrimary and the staging directory as cleanup state. The boundary test
still expected the old wrapped cause, so it failed on main and in every PR
built on it; its finally block then masked the assertion with a cleanup
error. Assert the current contract.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 10:01:56 -07:00
morluto 22c84ce64a fix(hopper): recognize stripped Objective-C class labels
Classify legacy class-object names at the Hopper boundary and carry the typed fact into class discovery. Preserve exact labels, literal filtering, unrelated row metadata, and raw replies; derive classification from source text rather than incoming tags.

Closes #5617
2026-10-21 01:01:42 +08:00
morluto dd0015aaf1 fix(ida): own registration reads and bind selected configuration
Read bounded regular registrations asynchronously with retained descriptor cleanup. Carry the selected parsed configuration through provider factories and restoration, preserve exact cancellation reasons, and share workspace-parent resolution with doctor checks.

Closes #5561

Closes #5559

Closes #5604
2026-10-21 01:00:00 +08:00
morluto 7d6f90485e Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-21 00:53:09 +08:00
morluto 04ae07ab8c fix(kuna): bind version probes to stable executable identity
Compare executable fingerprints before and after the owned version probe, and capture the script prefix from the final hash stream. Preserve partial facts and failed-close ownership without claiming process interruption from a snapshot.

Closes #5611
2026-10-21 00:52:53 +08:00
gensokyo-dev 98f4072f1f feat(model): inspect GGUF and safetensors declarations (#5603) 2026-10-21 00:50:50 +08:00
morluto 5b676ba9f3 Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-21 00:32:49 +08:00
morluto 14cd78c322 fix(apple): retain unsupported NIB connectors in connection coverage
Recognize AppKit binding connectors as explicit unknown connection facts and
report partial semantic coverage rather than silently omitting them. Share
format-aware connector admission across keyed archives and NIBArchive.

Make the keyed archive table own parsed class and superclass facts for names,
array hierarchy traversal, inherited connectors, and class-table projection.
Preserve malformed class evidence and exclude unrelated custom class names.

Validation: 84 focused tests passed, including compiled CLI, filesystem,
MCP summary, and retained views; check:fast and test discovery passed.
Independent source review found no blocker. Production CLI and stdio MCP
replayed a read-only copy of Terminal 2.15's picker NIB: 13 connections with
partial unsupported-type coverage, versus baseline 9 with complete coverage.
Advertised schemas and retained coverage results validated with the SDK/Ajv.
No app, analysis target, or optional deep provider was executed.

Fixes #5590
2026-10-21 00:31:00 +08:00
gensokyo-dev 8716b52411 fix(evaluation): prepare and retain native ownership helpers (#5615)
Prepare native process ownership outside short command deadlines. Reuse the shared cleanup adapter and resource scope for direct/nested preparation failures and command cleanup.

Fixes #5094.
2026-10-20 16:29:46 +00:00
gensokyo-dev a35623707e fix(mcp): guide client and provider timeout recovery (#5608)
Teach client deadline recovery before REA results can be discarded, distinguish
producer-owned server budgets, and preserve Evidence/cleanup uncertainty.
Include actual Codex CLI recovery probes and CLI/MCP regression coverage.

Fixes #5598

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-21 00:16:44 +08:00
gensokyo-dev 2a6fc712eb fix(evaluation): join owned command cleanup before removing files (#5613)
Use shared owned command supervision for all evaluation helpers, join streamed output, and retain/retry incomplete cleanup before deleting run files.

Fixes #5094.
2026-10-20 16:16:29 +00:00
morluto 506400748e fix(electron): count bridge listener registrations by source callsite
Keep directly observed renderer listeners singular when bridge traversal
reaches them, while retaining separate paths for every exposed bridge member.
Preserve separate physical callsites and on/once operation identities.

Validation: 190 focused tests passed, including public CLI and stdio MCP
analysis and incoming feature tracing. Typecheck/lint and discovery passed.
The inert fixture was analyzed statically; no Electron target was executed.

Three alternating synthetic CLI tasks showed overlapping wall times (median
1.825s baseline, 1.808s current). Corrected bridge provenance increases serialized
task payload; no speed or context reduction is claimed. Actual model tokens
and full process-family CPU/peak memory were not measured.

Fixes #5586
2026-10-21 00:14:11 +08:00
morluto 57d64b6ba5 Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-21 00:09:56 +08:00
morluto ff78165978 fix(kuna): own version-probe processes through output and cleanup
Use the shared command supervisor for installation probes and retain exact
process cleanup owners through doctor, profile resolution, and session health.
Preserve exit status, bounded captured output, cancellation reasons, and live
cleanup facts. Block subsequent inspection until retained cleanup is retried.

Generalize the existing inspection resource scope and migrate its consumers,
including verifier scripts; remove the verifier's duplicate raw version probe.

Validation: 116 distinct focused tests passed, including built CLI doctor with
inherited output, cancellation/finalization, cleanup retry, and fake-provider
verifier workflows. Build, check:fast, and test discovery passed. No real Kuna
distribution or analysis target was executed.

Synthetic Darwin inspection timing: first-call median 707ms versus 5.79ms;
same-process repeat 37.9ms versus 3.08ms. First use includes ownership-helper
preparation. Family CPU and actual peak family memory remain unmeasured.

Fixes #5557
2026-10-21 00:09:34 +08:00
gensokyo-dev c3d7d0aafc fix(browser): honor long passive observation windows (#5605)
Reuse the cancellable segmented wait and settle observation termination through one cleanup owner. Preserve caller cancellation and release timers/listeners across early target end.

Fixes #3929.
2026-10-20 15:56:15 +00:00
morluto 90e433df06 fix(swift): retain uncertainty for unsupported nested identifiers
Stop inheriting an outer nominal category when a zero-prefixed identifier cannot be decoded. Preserve exact manglings in unresolved results under class and enum filters while retaining ASCII nominal controls.

Validated 39 source and in-memory MCP tests, typecheck/lint, and 22 compiler-produced code symbols from an inert Swift 6.3.2 object. No real Hopper inventory or target execution. Fixes #5553.
2026-10-20 23:41:16 +08:00
morluto 0ba4d6f43a fix(native): bind dispatch snapshots to the local reader profile
Retain native-only dispatch workflows without requiring a deep provider profile. Validate exact target, operation, and current reader bindings during open, import, recording, and export; preserve selected deep bindings and caller limits.

Validated public CLI and stdio MCP save/reopen, exact CLI replay, changed-limit cache partitioning, baseline failure and candidate success on an Apple-clang fixture, snapshot lifecycle regressions, typecheck and lint. No target or deep engine execution. Fixes #5529.
2026-10-20 23:31:45 +08:00
morluto 080c0e2b2b Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-20 23:15:43 +08:00
morluto 9eec57b469 fix(native): report record-local Objective-C budget omissions
Have method, property, ivar, and adopted-protocol list owners flag real budget omissions on returned class, protocol, and category records. Preserve known empty lists and existing decode reasons.

Validated 59 source tests, two built CLI controls, five static inspections of an Apple-clang fixture, and typecheck/lint. The target was never executed. Fixes #5543.
2026-10-20 23:15:05 +08:00
morluto 8d198d6ec7 fix(javascript): preserve unavailable scope uncertainty in comparisons
Classify wholly unknown or unavailable node observations at the version-item owner and retain their limitations across matched and unmatched comparisons. Preserve positive mixed observations and genuine additions/removals.

Validated source regressions and public CLI/stdout MCP workflows in the 103-test focused gate; typecheck and lint pass. Fixes #5534.
2026-10-20 23:14:47 +08:00
gensokyo-dev c2858d2aa0 perf(go): summarize build identity and query retained metadata (#5524)
Add opt-in Go build summaries and selected retained metadata pages while preserving complete Evidence and source identity.

Validated with 258 focused tests, full static/docs checks, real CLI/SDK workflows and native metadata oracles. CI baseline remediation assertions reproduce on unmodified main; fail-fast cancels two other shards. Owner authorized bypass with those coverage limits recorded in PR #5524.

Fixes #5499.
2026-10-20 23:09:10 +08:00
gensokyo-dev e52a71602d test: stabilize worker cancellation and trailer regressions (#5497) 2026-10-20 23:06:09 +08:00
HawkForge 8443692e2b fix(javascript): keep overflowing timer delays unknown (#3456)
Normalize non-finite timer literals to the existing unknown value at the semantic fact producer. Keep timers, source provenance, binding resolution and unrelated functions; preserve all finite delay values.

Qualify shared CLI/MCP behavior with precise regression oracles, 111 tests, actual source fixtures, real-package summary/fact/Evidence workflows and current-main integration.

Fixes #3400.
2026-10-20 15:02:38 +00:00
morluto 7b2087e449 test(kuna): separate composed doctor startup from cancellation timing
Allow the preceding Ghidra ownership preparation before waiting for the gated Kuna child. Keep the two-second cancellation join, exact reasons, reaping and cleanup assertions unchanged.

Refs #5568. A controlled startup delay reproduces the old failure; disabling cancellation forwarding still fails the retained join assertion. All 86 focused setup, doctor, helper and CLI checks passed on pinned Node 24.18.0/macOS arm64.
2026-10-20 22:57:21 +08:00
morluto f5d1012fab fix(setup): advertise only providers with passing readiness checks
Keep installation availability and full doctor inspection facts separate from the setup ready-provider list. A blocked Kuna cache no longer advertises deep analysis; passing unverified-version notes remain usable.

Refs #5105. All 16 focused setup and public CLI dry-run controls passed; typecheck and lint passed. Tests use a scripted Kuna version fixture and do not establish real-engine behavior. The pre-existing doctor cancellation startup-poll failure is tracked separately.
2026-10-20 22:49:13 +08:00
morluto d2a3269d0c Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-20 22:39:34 +08:00
morluto fd7da77fc0 fix(hopper): verify bookmark names and clear existing labels
Use the public rename API for an explicit empty existing name, retain omitted names and raw listing values, and verify fresh unnamed creation and explicit mutations by readback. Preserve independent verifier restorations and their primary failures.

Refs #5475. Focused bridge regressions and the complete real-Hopper suite passed on macOS arm64 with Hopper 6.6.0-demo 42.6316032. The verifier used a temporary unavailable Ghidra override to meet its sole-candidate prerequisite; reporter Hopper 6.1 remains unverified.
2026-10-20 22:39:23 +08:00
morluto 44521d3d75 refactor(macho): share thin header CPU interpretation
Give partial thin-header facts one domain owner and reuse them for standalone target admission and Mach-O load-command inspection. Preserve each consumer endianness policy and header/command checks; remove the FAT-only parser names.

Refs #5542. All 246 focused checks and six public CLI archive/image controls passed; typecheck and lint passed.
2026-10-20 22:37:25 +08:00
Sagar Kewat eac296a7da fix(browser): reject overflowing scenario timers (#3515)
Reject browser scenario waits and action deadlines beyond the underlying signed 32-bit timer interval in the shared input contract. Preserve maximum legal values and omitted deadlines; prevent unsupported input from opening a browser.

Strengthen the rejection oracle and verify public CLI/MCP canonical validation in both schema profiles, actual Chromium timing/cancellation/cleanup, Evidence export and compatibility with current main.

Fixes #3392.
2026-10-20 14:32:54 +00:00
gensokyo-dev 55cce6fc11 test(cli): retain recovery guidance in filtered failures (#5536)
Preserve typed input-contract recovery and source diagnostics through filtered CLI output in JSON, TOON, YAML and Markdown. Update legacy remediation-text assertions introduced by the concurrent main update.

Refs #5431 and #5470.
2026-10-20 22:26:57 +08:00
morluto 57e76599c0 Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-20 22:21:13 +08:00
morluto 498a667234 fix(javascript): retain source map section paths on declarations
Carry the parsed section path onto retained source nodes and contains edges. Refs #5466; validated with the same 50 focused source-map checks.
2026-10-20 22:19:35 +08:00
morluto 1195929fa5 test(browser): synchronize cancellation before the worker exits 2026-10-20 22:19:18 +08:00
morluto c4007f4542 Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-20 22:19:10 +08:00
morluto a74d859a19 fix(evm): probe the selected limiter before advertising availability
Share asynchronous executable selection between discovery and execution. Recheck it for default Linux x64 sessions, preserve caller-injected service policy and propagate cancellation through pending probes.

Refs #5086. Focused owner, inventory and MCP controls passed; Linux-specific discovery and execution cases were skipped on Darwin arm64 and remain unverified.
2026-10-20 22:18:52 +08:00
morluto 2b2e362a00 fix(javascript): retain partial indexed source map facts
Share section classification across declaration analysis and mapping parsing. Preserve external URLs, malformed section reasons, section paths and safe sibling declarations without fetching nested maps.

Refs #5466. All 50 focused tests passed, including real CLI and stdio MCP regressions; typecheck and lint passed.
2026-10-20 22:18:23 +08:00
morluto 497037e6e3 fix(macho): validate FAT slice format and CPU identity
Use observed thin-header facts before target architecture admission, reject archive payloads, and retain far-offset root inventory through bounded reads. Retry complete bounded FAT table reads.

Refs #5462, #5542. Focused native/filesystem checks passed (245 plus 70 after the table retry). Public MCP inventory parity and unchanged token estimates verified; no external analysis engine execution claimed.
2026-10-20 22:18:03 +08:00
morluto fa36657251 test(ci): deduplicate browser lifecycle fixtures and cover export ordering 2026-10-20 22:05:55 +08:00
morluto d43d3568f2 fix(evm): retain cancellation through final cleanup 2026-10-20 22:05:55 +08:00
morluto 25d3805e7f Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20 2026-10-20 22:04:00 +08:00
morluto 82902465c4 docs(errors): describe live JSON heap admission
Replace the superseded fixed 64 MiB process-input refusal with the shared reader diagnostic and recovery text. Restore CSV field boundaries in the adjacent import-limit catalogue entry.

Refs #5077. Verification is source consistency and CSV parsing, without a new large-file runtime claim.
2026-10-20 21:59:05 +08:00
Nitin Kushwaha cf5194f68e fix(firmware): separate analysis and publication deadlines (#4602)
Separate extraction/inventory and caller-selectable publication budgets in the shared firmware workflow. Preserve phase, selected timeout, verified progress, caller cancellation identity and committed observations through cleanup. Enforce monotonic expiry even before timer callbacks run.

Validated with 101 targeted tests, full static checks, documentation checks and real OpenWrt CLI/MCP workflows with digest and cleanup verification. Existing main CI failures are documented separately.

Fixes #4176.
2026-10-20 13:57:20 +00:00
JANG BYUNGKUN 52d1a72af0 feat(il2cpp): link native methods and export Ghidra seeds
Link IL2CPP metadata names to native addresses and types through shared CLI/MCP workflows, with bounded queries and atomic Ghidra seed export.

Preserve the original implementation by 8rulerstar and follow-up correctness, resource, provenance, and CI dependency repairs. Verified against real Windows/Android artifacts, independent references, actual Ghidra, and focused CLI/MCP tests.

Fixes #5112.
2026-10-20 21:56:54 +08:00
gensokyo-dev e50a271c72 fix(mcp): guide agents through tool error recovery (#5470)
Add shared, typed input-contract and timeout-state recovery guidance. Normalize SDK input failures within the actual MCP wire budget, preserve full diagnostics and protocol metadata, and retain original Evidence when normalized delivery would exceed the budget.

Fixes #5431.
2026-10-20 21:45:05 +08:00
Syed Rishad c374c2fe72 fix(ghidra): preserve partial dossiers on decompiler failure (#4650)
Preserve listing-backed facts and explicit unavailable decompiler facets when one function fails. Retain Evidence while excluding transient failures and derived workflows from snapshot reuse; keep healthy cache reuse and owned cleanup semantics.

Fixes #4644.
2026-10-20 12:08:08 +00:00
morluto 0c440bfc07 fix(cli): match listener recovery guidance to system failure
Classify listener errno and lifecycle phase at the transport owner. Preserve native cause and unknown codes while distinguishing host lookup, unavailable address, occupied port and permission recovery.

Refs #5455.
2026-10-20 19:54:56 +08:00
morluto a4dbb36d8e fix(javascript): retain uncertainty for missing source map mappings
Share the required mappings field contract and retain readable declarations across malformed indexed leaves while marking graph coverage partial.

Refs #5469.
2026-10-20 19:54:33 +08:00
morluto 0e83d92c58 fix(mcp): advertise existing absolute path constraints
Reuse the schema-visible host path owner across session, firmware, managed, browser, Electron and Evidence-file inputs. Keep existing runtime and CLI path semantics.

Refs #5493.
2026-10-20 19:54:14 +08:00
morluto ee12d517a2 fix(prompts): describe crash document without provider assumptions
Refs #5474. Use the existing provider-neutral document selector wording; public prompt list/render tests passed without starting providers.
2026-10-20 19:39:31 +08:00
morluto 9cf7a7cb0d fix(protobuf): preserve partial facts for malformed web trailers
Parse gRPC-Web trailer blocks with typed failures, enforce field values and lower-case names, and propagate unexpected decoder failures. Retain earlier fields and raw capture bytes across binary and text framing.

Refs #5386. Related control-value fix: #5422.
2026-10-20 19:39:18 +08:00
morluto 00a055be0f chore: merge latest main before publishing audit fixes 2026-10-20 19:29:26 +08:00
morluto 22278b20c0 chore: merge main into audited lifecycle fixes 2026-10-20 19:28:09 +08:00
morluto 3cf6206614 fix(mcp): require absolute evidence bundle paths 2026-10-20 19:26:17 +08:00
morluto 4714c7eaa3 fix(cli): preserve typed failures through output filters 2026-10-20 19:26:08 +08:00
morluto cec8f1e8f3 fix(providers): offer only admitted ambiguity choices 2026-10-20 19:25:59 +08:00
JANG BYUNGKUNandgensokyo-dev 21e0c580e7 feat(il2cpp): read member names, string literals and metadata versions 24 and 27 (#5326)
* feat(il2cpp): read member names, string literals and metadata versions 24 and 27

Adds field, property, event and parameter names with their owners, managed string literals, and the version 24 and 27 header layouts to inspect_il2cpp_metadata, with filtered pages for the new collections. Member decoding yields between row batches like the other row readers.

* fix(il2cpp): bound metadata expansion and query parameter owners

* test(il2cpp): cover nonempty property and event tables

---------

Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
2026-10-20 19:21:42 +08:00
morluto f01dccab77 fix(javascript): retain cancellation after observed worker failure 2026-10-20 19:13:06 +08:00
morluto 5f0bc86d1a docs(ko): describe update alias and bounded output 2026-10-20 19:05:50 +08:00
morluto f69332c94c test(process): bind capture watchdog cleanup to test lifetime 2026-10-20 19:05:44 +08:00
morluto 2e03251b61 fix(zip): retain raw filename provenance for legacy decoding 2026-10-20 19:05:38 +08:00
morluto 108c0e7e49 fix(macho): share width-specific load command alignment 2026-10-20 19:05:31 +08:00
morluto 266dd1d958 fix(go): reuse PE content spans for build metadata search 2026-10-20 19:05:24 +08:00
morluto cac12ae334 fix(workers): retain observed protocol failures across cancellation 2026-10-20 19:05:00 +08:00
morluto 861c11ec77 fix(evidence): preserve execution profiles in composed observations 2026-10-20 19:04:52 +08:00
morluto 9051809343 fix(adb): preserve empty string activity extras 2026-10-20 18:38:13 +08:00
morluto 9db5f1b276 fix(apple): keep empty asset catalog pages complete 2026-10-20 18:38:05 +08:00
morluto 3a9176098d fix(javascript): preserve observed worker failure ordering 2026-10-20 18:38:00 +08:00
morluto 483678bf9f fix(managed): retain operand-free instruction anchors 2026-10-20 18:37:56 +08:00
052956af34 fix(doctor): validate Hopper startup timeout in readiness checks (#3755)
Fixes #3306. Reuse the runtime timeout parser in doctor, preserve scope semantics and separate setting validation from provider configuration.

Co-authored-by: xiajiahang <xiajiahang82@gmail.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-20 10:32:12 +00:00
gensokyo-dev aa314ab682 ci(windows): run environment registration regressions (#5409)
Retain 13 Windows-only environment/setup regressions in the curated native lane. Select Windows qualification for both their three test files and their client configuration, registration and DSH production owner families. Guard membership and actual Git-diff classification; qualify all 60 target cases on hosted Windows.
2026-10-20 10:18:17 +00:00
gensokyo-devandKaoru0822 c23e161629 perf(mcp): record catalog identities for all schema profiles (#5415)
Share compiled schema conversion while recording all four built-in catalog profiles. Preserve canonical hashes, output validation and custom-budget fallback. Refs #723.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-20 10:09:28 +00:00
gensokyo-dev 1417bf943b feat(native): match retained function inventories across builds (#5390)
Match retained native inventories through shared CLI/MCP workflows with conservative symbol/byte correspondence, unresolved structural candidates, complete Evidence provenance and bounded paged reads.

Closes #5343.
2026-10-20 09:48:52 +00:00
ShuaixinHuang e84468c0bb fix(setup): preserve Windows environment override identity (#4946)
* fix(setup): preserve Windows environment override identity

* fix(setup): preserve selected platform and YAML alias metadata

* fix(setup): reconcile layered environment and projected YAML identities
2026-10-20 17:25:51 +08:00
ShuaixinHuang afde435c94 test(setup): use native Windows launcher in layered OpenCode fixture (#4947) 2026-10-20 17:25:38 +08:00
ShuaixinHuang e9fc8fb30c fix(javascript): preserve runtime path bytes and Electron ownership (#4941)
* fix(javascript): preserve literal percent runtime paths

* fix(javascript): ignore resolve prefixes before the final anchor

* fix(electron): retain application roots for loadFile declarations

* fix(electron): resolve loadFile from enclosing application package

* fix(electron): retain outer application root across package scopes

* fix(electron): derive application ownership from inventoried packages

* fix(electron): retain resolved package entrypoint ownership

* fix(electron): preserve competing application ownership

* fix(electron): retain invalid and omitted runtime ownership

* fix(electron): preserve omitted module ownership and runtime paths

* fix(electron): preserve proven roots before confining page paths

* fix(electron): retain possible owners behind missing imports

* fix(electron): distinguish absent imports and owned page candidates

* fix(electron): keep unavailable JSON out of owner gaps

* fix(electron): retain exact loader formats and default entry status

* fix(electron): retain unavailable entrypoint ownership candidates

* test(ghidra): preserve Windows Node probe prerequisites

* test(ghidra): assert cancellation during profile shutdown

* fix(electron): separate examined imports from frontend ownership

* fix(electron): retain unavailable directory entrypoint owners

* test(jeb): retain Linux ownership prerequisite in isolation

* fix(javascript): retain unchecked loader ownership and literal main paths

* fix(javascript): preserve runtime paths and call-site module aliases

* fix(javascript): bound module alias traversal and preserve projections

* fix(javascript): retain host module and nested artifact path boundaries

* fix(javascript): preserve ESM and archive module loader provenance

* test(javascript): distinguish unmapped containers from missing exports

* fix: retain default module aliases and Electron builtin imports

* fix: preserve host file URL and inward ASAR ownership

* fix: preserve CommonJS file URL classification in CI fixtures

* fix: retain bound module loaders and Windows entrypoint uncertainty

* fix: retain ASAR uncertainty and invalidate changed Electron app roots

* fix(javascript): retain ownership uncertainty across loader boundaries

* fix(javascript): preserve loader sources and bound alias queries

* fix(javascript): retain destructured loader sources

* fix(javascript): preserve loader uncertainty at resolution boundaries

* fix(javascript): preserve callable and package launch ownership

* fix(javascript): preserve captured values across member reads

* test(process): assert tagged filesystem cancellation failures

* fix(javascript): preserve inventory bases and invocation read timing

* fix(javascript): preserve ownership across indirect and unread loads

* test(javascript): order fixture directory creation on Windows

* test(javascript): share ordered filesystem fixture writer

* fix(javascript): unify loader provenance and package validation

* fix(javascript): preserve captured Node require loader values

* fix(javascript): preserve loader invocation authority

* fix(javascript): verify generic loader invocation authority

* fix(javascript): preserve conditional loader method alternatives

* fix(javascript): require proven factories for source association

* fix(javascript): honor replaced Electron app path setters

* fix(javascript): prove path and assignment source ownership

* fix(javascript): retain native delegate eligibility through shared writes

* fix(process): settle stale baseline errors after confirmed absence

* fix(javascript): preserve assignment and path boundary evidence

* fix(javascript): prove source-directory resolve anchors

* fix: preserve application path provenance and portable schemas

* fix(javascript): retain CommonJS exported setter effects

* fix: isolate Linux identity observations and retain native module exports

* fix(javascript): preserve published app and helper provenance

* fix(javascript): normalize typed stores and native path fixtures
2026-10-20 17:25:19 +08:00
morluto c284168c4b fix(objdump): scope debug-link limitations to DWARF requests 2026-10-20 17:18:21 +08:00
morluto be20ac3740 fix(source-maps): preserve failure priority and cancellation provenance 2026-10-20 17:18:20 +08:00
morluto cc73587ec4 fix(lldb): preserve observed failures through interrupted cleanup 2026-10-20 17:18:20 +08:00
morluto 98edca9f96 fix(pwndbg): clarify debugger context output limit message 2026-10-20 17:18:19 +08:00
morluto 98a5e56380 docs(ghidra): explain server-wide analyzer override scope 2026-10-20 17:18:19 +08:00
morluto 7c6142efdc fix(ghidra): retain stable Homebrew installation aliases 2026-10-20 17:18:18 +08:00
morluto 562dab00c5 fix(mcp): retain protocol envelopes when replacing oversized errors 2026-10-20 17:18:18 +08:00
morluto 3b02179560 fix(javascript): preserve uncertain call targets across activation boundaries 2026-10-20 17:18:18 +08:00
morluto 599fdac029 fix(browser): stop late navigation before releasing attached sessions 2026-10-20 17:18:17 +08:00
morluto 696832caa3 fix(gdb): gate readiness and retain caller cancellation through cleanup 2026-10-20 17:17:16 +08:00
morluto 459a356edb fix(evm): preserve cancellation and exact cleanup ownership 2026-10-20 17:17:16 +08:00
morluto 419502c8d0 fix(pcap): preserve cancellation and endpoint evidence through cleanup 2026-10-20 17:17:15 +08:00
morluto 1006714271 fix(sqlite): retain primary outcomes through cleanup retries 2026-10-20 17:17:15 +08:00
morluto e367750b1b fix(process): preserve observed command failures and native ownership 2026-10-20 17:17:14 +08:00
morluto cf3288d8cf fix(native): preserve Mach-O container framing across inspection 2026-10-20 17:16:44 +08:00
Liu Jieandgensokyo-dev d532b18123 fix(doctor): propagate Kuna cancellation and preserve partial observations (#5241)
Fixes #5106. Propagate the owned inspection signal, preserve typed cancellation and earlier failures, and retain completed installation observations through exact-owner cleanup retries.

Co-authored-by: Liu Jie <maxazure@gmail.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-20 09:15:09 +00:00
吴佳浩AlbenandXiaoBinGan 074768901f fix(pwndbg): separate the words in the debugger-context limit message (#5372)
The 64 MiB reply-budget refusal rendered as "exceeds64 MiB" because the
message word and the limit were joined. The pwntools sibling names the
same budget as "exceeds the 64 MiB reply budget"; use that wording.

The output-limit path had no producer regression, so the pwndbg suite
gains one that drives the real 64 MiB boundary, and the suite is now part
of test:python instead of running only when invoked by hand.

Co-authored-by: XiaoBinGan <XiaoBinGan@users.noreply.github.com>
2026-10-20 16:12:55 +08:00
gensokyo-devandKaoru0822 2538214e2c feat(analysis-view): add native inventory summaries and pages (#5378)
Add opt-in summaries and stable selected-field pages for native inventories through the shared CLI/MCP Evidence layer. Preserve complete source access, row identity, provenance, string qualifications and unknown discovery coverage.

Record real true/jq workflows and portable old-Evidence checks, including tokenizer proxy reductions, additional call/schema costs and observed latency/memory regressions.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-20 07:59:43 +00:00
gensokyo-dev b5d540f3a2 test(capture): split protobuf MCP acceptance scenarios (#5379)
Separate independent exclusion, partial-source, credential-preflight and descriptor-failure workflows so their costs do not accumulate under one test deadline. Reuse one worker-owned MCP connection with explicit awaited teardown, preserving sensitivity isolation and retained-Evidence checks.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-20 07:54:47 +00:00
gensokyo-devandakushonkamen 4eaf3a117b fix(mcp): retain protocol framing for oversized tool errors (#5371)
Preserve the SDK resultType when bounded error recovery replaces an oversized response. Verify both revisions through the public serving entry, retained Evidence and same-connection recovery.

Refs #5273

Co-authored-by: akushonkamen <akushonkamen@163.com>
2026-10-20 07:31:02 +00:00
0134732fcd feat(capture): decode selected protobuf and gRPC bodies (#5031)
Retain exact bounded wire facts and optional supplied-schema interpretations for selected historical captures. Share CLI/MCP views and preserve Evidence, partial coverage, credential exclusions and source provenance.

Fixes #4986

Co-authored-by: AayushJB03 <aayushjb14@gmail.com>
Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 07:10:54 +00:00
gensokyo-dev 799e8265b2 fix(verification): retain Hopper ownership evidence across owner exit (#5357)
Keep one ProcessOwnershipEvidenceOwner for each graceful/SIGKILL session and share it across active and terminal scoped scans. Require live token-verified evidence before stopping the owner, and retain structured cleanup failure diagnostics.

The real Ubuntu 24.04 Hopper clean-setup/CLI/MCP job passes, including owner exit, target reacquisition, idempotence and zero remaining descendants. Local verification passes 87 CI guards, 51 ownership controls, discovery of all 1,714 test files and full static checks.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
2026-10-20 05:52:06 +00:00
gensokyo-dev 4668cea246 fix(ghidra): explain server restart for timeout recovery (#5356)
Explain process-scoped startup settings in shared CLI/MCP timeout guidance and the bundled skill. Preserve Evidence and cleanup before restarting REA, reconnect MCP, and allow enough client request time.

Validated with focused tests, static/docs/package checks, real Ghidra CLI/MCP recovery, and a completed 591-second EXE analysis under CPU and memory limits.
2026-10-20 05:49:00 +00:00
gensokyo-devandKaoru0822 58d6043303 perf(ghidra): omit redundant raw results (#5355)
Keep ordinary Ghidra facts in normalized Evidence without repeating complete raw replies. Preserve distinct overview, attestation, file-offset and pre-overlay observations through shared CLI/MCP execution.

Record real application measurements, equivalent selected facts, response admission and explicit latency/coverage limits.

Fixes #5337.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-20 05:14:33 +00:00
gensokyo-dev d148ce0905 perf(environment): index observed-state write cutoffs (#5350)
Index parsed recorded-write roots once per state projection and reuse positive and negative type cutoffs. Preserve wildcard, ancestor/descendant, canonical timeline and Evidence semantics under the existing representation budget.

Follow-up to the final performance thread on #5319, which was merged while this optimization was being validated.

Validated with 508 relevant source tests, compiled state CLI/MCP cases, real Gitea HAR CRUD/search captures and Chromium captures, static/build/docs/catalog gates, and equivalent completed before/after projections.
2026-10-20 12:16:02 +08:00
3fca2e0ca6 feat(environment): extract the initial state a capture's reads observed (#5319)
* feat(environment): extract the initial state a capture's reads observed

Add the environment-state analysis view. From the parents the environment
manifest accepts, it extracts the data the capture's reads observed before
the first related write: entity types with an identity field (proved by a
path parameter or inferred from an identity name), entities with their
recorded values and provenance, documents for written non-entity paths, and
a render plan per read tool that is kept only when it reproduces the tool's
latest initial recordings from the state; every other read tool is a
recorded view with the reason. The Evidence is always inferred.

Response-body decoding moves to a domain owner shared with replay, exact
JSON parsing moves to the owner of the exact-number policy, the manifest and
state views share parent admission and record grouping, and
projectAnalysisView takes its accumulators as one object.

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

* fix(environment): bound state at redacted writes; infer identity only from items

A scenario write whose URL was redacted has no request line, so it was
dropped and reads after it counted as initial state. Such a successful
write now joins the timeline with an empty path, whose root relates to
every type, so it ends every type's state; a limitation counts them.

A list whose recordings were all empty passed the "every listed item
carries it" check vacuously and published an identity field nothing
showed; it now needs at least one item, else the view stays recorded
as no-identity.

A value that differed between two request lines of one item tool, such
as a query variant, was called volatile, and the gate then substituted
each recording's own value; only repeats of one request line now show
volatility, so differing lines go through fields-differ.

List membership is compared only while a list can still be the whole
collection, and merged entities are indexed by type and collection once,
so paged captures no longer cost pages times entities (8,000 pages of
40,000 entities: 5.7 s to 0.23 s).

Docs and the tool contract say scenario state keeps the capture's
redaction markers and how redacted writes bound it.

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

* fix(environment): keep first sightings, one list pointer and linear field unions

Entities took the order of the first plan observed, and item plans run
before list plans, so a complete list read before its detail reads came
out reordered and lost "all" membership; each entity now keeps its
earliest recorded sighting.

A list plan reused the first recording's pointer for later recordings,
so a later response that was itself an entity wrapping a list was read
as that list; every recording must now locate the same list.

The field union scanned its ordered list for every key, quadratic in an
object's width; a set now answers membership.

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

* fix(environment): keep post-write values and partial lists out of the initial state

A value that changed between repeats of one request line was named
volatile whenever no write under the type's own root lay between, so a
write under another root (for example POST /api/dashboards/db before a
second GET /api/search) left its effect in the initial state. Any
recorded write between the two observations now leaves every tool of the
type recorded with reason fields-differ instead.

A list was published with membership "all" even when a total or count
envelope member exceeded the number it listed. Such a counter now makes
the membership "recorded".

Also drop a stale doc comment on ObservedEntity.order.

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

* docs(environment): scope item-shaped and deleted written paths out of documents

State documents are held only for list-shaped paths a POST, PUT or PATCH
tool writes. Reads of item-shaped written paths and of paths that are only
deleted stay recorded views; the guide now says so and the spec defers them
to a later increment of #4933.

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

* fix(environment): count writes in flight when a value changes between reads

The volatility check compared write start positions with the two reads,
so a write already in flight when the earlier read started was missed and
its effect was named volatile. A write now counts when its interval
overlaps the span from the earlier read's start to the later read's end.

The check also ran once per changed field and scanned every write. It now
runs once per pair of observations, answered by a binary search over the
writes in timeline order and the latest end among each prefix.

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

* fix(environment): catch cross-tool changes across writes; read only item totals

A value that changed across a write was caught only between repeats of
one tool's request line, so a list read before a write and an item read
after it put the post-write value into the initial state. Changes are
now classified per entity in timeline order after observation: across
any recorded write, a change between repeats of a line or between two
lines of the type rewrites the type (every tool recorded as
fields-differ); with no write between, a repeat's change is volatile.
The classification lives in environmentStateMerge.ts.

Any numeric member whose name contained "total" or "count" counted as
an item total, so total_pages, account_id or page_count made complete
lists partial. Item totals are now members whose name tokens include
total or count and none of page, pages or per; a string of digits counts
as a number; and a set has_more, next or next-page token member also
marks the list partial.

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

* fix(environment): keep post-write observations out of initial state

* fix(environment): retain field provenance and bound state inference work

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
2026-10-19 20:33:46 -07:00
gensokyo-devandKaoru0822 4e716b0607 perf(analysis-view): reuse validated immutable captures (#5349)
Reuse the format owner's full validation for exact authenticated immutable captures across retained queries. Preserve ordinary mutable-input validation and per-request subject, coverage and budget checks.

Refs #3133.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-20 03:32:18 +00:00
gensokyo-dev d72021b0da fix(hopper): verify publisher before probing private display (#5346)
Return publisher refusal before unrelated private-display prerequisites can mask it. Retain display validation for admitted launchers, native launcher digest revalidation and owned cleanup.

Add a public CLI fault control using an unusable Python home, preserve the ordinary control and assert display selection for admitted versus refused launchers. Affected tests: 177 passes; 13 changed-file cases passed three additional repeats; full static checks pass.

Real-Hopper owner-exit identity revalidation fails identically on unchanged main and the PR; complete real-provider qualification is not passing. This pre-existing failure remains outside this focused correction.

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

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-20 02:41:14 +00:00
f93a0335a8 feat(analysis-view): project rich captures from Evidence files and template path pairs (#5293)
Project large local Evidence captures through the authenticated file-source boundary and add guarded opt-in sibling-pair path inference. Preserve request cancellation, resource ownership and file-relative validation diagnostics.

Validated relevant source and compiled CLI/MCP/environment boundaries, static/build/docs/catalog gates, and a real isolated Gitea 28.2.0 capture through CLI, default stdio MCP and HTTP replay. Current-head automated review passed; unrelated long-running platform jobs may still be pending.

Co-authored-by: Edgar Arakelyan <edgar.arakelyan@scale.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
2026-10-20 10:33:52 +08:00
5fa4defcbc feat(artifacts): inspect and extract Godot PCK with retained facts (#3634)
* feat(artifacts): read Godot PCK packs

Add a Godot Engine PCK artifact reader for standalone packs and packs
embedded behind an executable trailer (formats 2 and 3). Members are
uncompressed byte ranges verified against their declared MD5 on read.

Encrypted directories, sparse bundles, patch removal entries, unknown
flags and format 1 fail closed as unavailable; encrypted members are
reported without being read. inspect-artifact and extract-artifact
recognize standalone packs by their GDPC magic.

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

* fix(artifacts): bound Godot PCK metadata and own member streams

Cap member paths at 4096 bytes and the retained directory at 64 MiB
before allocation. Read members with positional chunk reads through
pipeline so cancellation is typed, abandoned consumers release their
source, and the shared descriptor stays reader-owned. Retain the root
descriptor for godot-pck inventory, as for ZIP and universal Mach-O.

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

* feat(artifacts): complete Godot PCK facts, integrity and selected views

* fix(artifacts): preserve atomic-root inventory Evidence

* fix(artifacts): bound aggregate PCK member expansion

---------

Co-authored-by: Samucahub <151155051+Samucahub@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-20 09:53:53 +08:00
JANG BYUNGKUNandgensokyo-dev 833136507d feat(il2cpp): inventory Unity IL2CPP global-metadata images, types and methods (#3807)
* feat(il2cpp): inventory IL2CPP global-metadata images, types and methods

Add inspect_il2cpp_metadata (CLI inspect-il2cpp-metadata), a read-only
in-process decoder for unencrypted Unity global-metadata.dat version 39.
It reports header sections, serialized index widths, images, type
definitions (nesting from the nestedTypes section) and method names.

Unrecognized magic and other versions are unsupported; damaged headers,
overlapping sections, inconsistent record sizes, out-of-range indices and
invalid strings fail with a reason code and no partial success. MCP
detail summary retains the complete Evidence and pages rows through
inspect_analysis_view kind il2cpp-metadata.

Adds an opt-in verify:il2cpp:metadata -- --metadata PATH check.

* feat(il2cpp): deliver metadata summaries by default over MCP

A 112,232-method file produced a 10.5 MB complete response, above the
10 MiB stdio budget. Default MCP delivery is now the retained summary;
detail complete stays available, and the one-shot CLI requests it.

* fix(il2cpp): reject shifted strings, nesting cycles and method owner drift

Review fuzzing showed that moving the strings section offset by one byte
silently renamed every image, type and method. Name indices must now start
a string, which also bounds total decoding by the section size.

Nesting cycles and methods whose declaring type disagrees with the owning
type range are rejected instead of returned. Adds service, shutdown and
index-width coverage, and moves environment-specific measurements out of
the public guide and tool description.

* feat(il2cpp): decode global-metadata versions 29 and 31

Unity 2022.3 writes version 29 or 31 metadata: a 256-byte header of
(offset, size) pairs, fixed 4-byte indices, type records with
elementTypeIndex, and method records that gained returnParameterToken in
version 31. Record counts come from section sizes and must be whole.

Sections report a null count for these versions and index widths report
fixed-width-version. Image, type and method rows keep the same shape, and
the string, nesting and method-ownership checks apply to every version.

* fix(il2cpp): bound report size before serializing and tighten coverage

Rows share decoded names, so a 130 KB file could expand into gigabytes of
JSON before the 64 MiB budget check, ending in an internal RangeError. The
provider now refuses from a lower bound on the serialized rows first.

The decoder also rejects non-empty sections inside the header, methods
outside their declaring type's range and overlapping image type ranges, and
keeps a leading byte order mark in names. Layouts now carry one indexing
mode instead of two coupled flags, and the tool description explains
nested_type_start.

* fix(il2cpp): refuse oversized metadata before decoding rows

Address review findings on the IL2CPP metadata inventory:

- check a lower bound from header row counts before any row object is
  allocated, so a large rejected file no longer builds every row first;
- validate sealed parent Evidence and count its rows once per report
  instead of on every inspect_analysis_view page;
- decode version 39 fixtures with 2- and 4-byte type-definition,
  generic-container and parameter indices.

* docs(il2cpp): attach the decoder comment to readIl2cppMetadata

* fix(il2cpp): deliver complete rows by default like the other inspection tools

inspect_il2cpp_metadata defaulted to detail summary, the only inspection
tool to do so. Omitted detail now returns every row inline, as
inspect_artifact, decode_interface_builder and the capture tools do;
summary stays one argument away and the guide, CLI reference and skill
reference say to select it first for large games, whose complete MCP
delivery is refused at the stdio budget with retained Evidence.

* test(il2cpp): cover narrow-width -1 sentinels and fix the skill's default

An empty image stores its type start as the all-ones value of a one- or
two-byte index; the decoder reads it as -1, but no fixture exercised it,
so removing either conversion passed the suite. The fixture can now append
an empty image, and both widths decode it. The skill still described a
summary default; it now says to select summary first, as the guide does.

* docs(il2cpp): request summary explicitly in the summary example

* chore(il2cpp): hash the verifier metadata through owned file resources

* fix(il2cpp): count escaped name length without building the escaped string

* fix(il2cpp): keep the verifier's check failure and small-table last page

* feat(domain): count JSON string length without building the escaped string

* fix(il2cpp): keep descriptor cleanup owners and share the JSON length count

* test(domain): give the backslash case real backslashes

* fix(il2cpp): select the CLI path and finish the command like the other tools

Follow main's absoluteCallerPath (#4067) and pass the command signal to finishAnalysisCommand.

* fix(il2cpp): select the verifier input path like the CLI

Use absoluteCallerPath (#4067) so a path with a symlink followed by .. names the same file the CLI and MCP inspect.

* feat(il2cpp): add compact composable metadata queries

Retain source-indexed Evidence for filtered batch and field queries. Bound representation growth before serialization, yield decoding for cancellation, and share CLI Evidence publication with desktop inspection. Verify public Unity metadata against independent byte and managed-DLL oracles and exercise actual stdio SDK workflows.

* fix(il2cpp): retain the validated metadata header magic

* test(il2cpp): remove obsolete execution wording exception

* fix(artifacts): preserve export selection and completed source facts

---------

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-20 07:20:47 +08:00
gensokyo-dev 82c76e2cba fix(ci): validate unindexed readiness heads with live PR metadata (#5316) 2026-10-20 07:19:58 +08:00
bf1eeee94f feat(environment): build environments from browser scenario captures (#5182)
Build an agent environment directly from retained capture_browser_scenario Evidence through the existing manifest, serve and export commands. Preserve request ordinals, source pointers, redaction markers, unavailable bodies, provenance and the default stdio MCP transport.

Followups admit copied/transformed text before body validation or decoding, avoid request-text allocation in replay, normalize portable file inventories, select dependent CI lanes, retain the author's redaction/body-budget corrections, and count body coverage over represented requests.

Validation: full pinned-toolchain static gate, source and public CLI/MCP regressions, canonical catalog checks, actual Chromium interactive and live GitHub API captures with exact HTTP replay and stdio parity, the generated non-root Docker image, and its smoke task through real agent-env 0.9.1334. Verification scopes, resource measurements and platform limits are recorded in the PR and feature verification document.

Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 06:07:15 +08:00
7a0c47bfa4 feat(environment): export an environment manifest as an agent environment bundle (#4999)
Export an authenticated capture and environment manifest as a pinned agentenv bundle with provenance, a replay verifier and smoke task.

Followups preserve immutable input ownership, bounded discovery, caller paths and numeric values; bind bundle writes and package copying to retained filesystem owners; verify POSIX modes; retain cleanup authority; and verify framework/npm executable selection. Default MCP remains stdio.

Validation: pinned Linux toolchain, typecheck/build/lint/format/docs/knip, 452 focused tests, ten product-catalog cases, real GitHub response replay in the generated non-root Docker image, and the real pinned agentenv framework smoke workflow. Platform and resource-measurement limits are recorded in the feature verification document.

Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-20 05:29:43 +08:00
gensokyo-dev b4938aed58 feat(artifacts): triage desktop installation directories (#5207)
* feat(artifacts): triage desktop installation directories

* fix(artifacts): retain completed probes through failed file cleanup

* perf(artifacts): decode only assembly reference names for desktop triage

* fix(artifacts): enforce exact signatures and responsive directory probes

* fix(artifacts): recognize Unity bundles and bound FORM chunks

* fix(artifacts): retain bounded desktop omission evidence

* fix(artifacts): select ASAR targets before inventory probes

* chore: preserve tested upstream HTTP owner during integration

* fix(artifacts): reuse Mach-O signatures for FAT64 desktop probes

* fix(artifacts): expose bounded desktop probe diagnostics

* fix(artifacts): derive desktop snapshots from observed source identities

* fix(artifacts): admit desktop facts before JSON expansion
2026-10-20 04:01:36 +08:00
gensokyo-dev 71ae02c6ef fix(process): retain child scope and bound native exit waits (#5280)
Retain original parent/child scope and prior native-generation proof across exit settlement and token retries. Keep historical scope separate from signal authority, count each supplied snapshot once, and share one existing native-exit deadline throughout cleanup.

Validated 387 affected tests (one Darwin-only skip), five controls repeated three times, and 30 synced-main integration tests (one platform skip). Synced-head static, architecture, docs and discovery checks pass; real GDB qualification passes 44 CLI/MCP cases. Native-observer edge controls are simulated.

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

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-19 19:27:43 +00:00
10f1994fe1 feat(environment): serve an environment manifest as a replay environment (#4975)
Serve retained capture Evidence as a bounded MCP replay environment with discovery.
Preserve default stdio, caller-selected facts and complete source Evidence.

Fix numeric fidelity, argument identity, startup cancellation and bounded discovery,
query/path matching and output metadata. Verify real recorded API data and public
CLI/MCP workflows; preserve explicit gaps for Windows and third-party hosts.

Co-authored-by: Edgar Arakelyan <edgar.arakelyan@scale.com>
Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 03:06:29 +08:00
gensokyo-devandKaoru0822 909b9f7b6b fix(rizin): keep protocol failures outside exit recovery (#5290)
Separate debugger exit-policy readback from process descriptor checks. Require the final native readback before considering inferior-end proof, and regress an ambiguous reply delivered as the real owned inferior exits. Preserve debugger ownership on failure.

Fixes #5282

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-20 02:56:41 +08:00
gensokyo-devandKaoru0822 e84e17e30f fix(rizin): accept proven inferior exit after detach (#5281)
Reuse the common Linux identity reader and retain the original PID/start-time pair throughout detach. After Rizin confirms no active descriptor, accept a proven end of that original process while preserving refusals for unresolved or live mismatched targets. Remove the duplicate proc parser and cover deterministic exit/live-redirect transitions with owned fixtures.

Fixes #5277

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-20 02:29:04 +08:00
gensokyo-dev 1c2c2f1e78 fix(process): settle native exit and repair ownership verification (#5249)
* 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)

* fix(ci): distinguish process inventory from historical PID lookups

* test(ci): verify decoded historical PID controls before tracing

* fix(ci): trace historical PID handles and signal probes

* 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)

* 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)

* fix(ci): reject priority access to historical PIDs

* 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)

* fix(ci): reject historical PID resource and scheduler calls

* fix(schema): preserve portable large base64 validation

* 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)

* fix(ci): classify I/O priority and qualify PID trace coverage

* fix(process): keep ownership retries on the native clock

* 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)

* fix(process): type native exit predicates and ownership fixtures precisely

* 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-20 02:01:00 +08:00
NoThingandKaoru0822 1b3ac94242 fix(rizin): bound recent history frames by UTF-8 byte budget (#5246)
Bound recent decoded history to complete UTF-8 prefixes and reuse the bounded capture implementation without changing command Evidence or wire queue accounting. Add deterministic Unicode and invalid-byte coverage, and document history retention.

Fixes #5091
Fixes #5242

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-20 01:41:46 +08:00
555aaditya e74e4d8f0b Merge remote-tracking branch 'origin/main' into refactor/tshark-single-owner 2026-10-14 16:28:29 +05:30
555aaditya f4eeba3654 fix(pcap): execute the TShark the shared locator selects
resolvePcapTools still returned bare tool names for PATH selections, so
the operating system could run a tool from a relative PATH entry while
the packet tools skipped that entry and selected a different install.

On POSIX hosts, resolve PATH selections through locateWiresharkTool and
run that absolute executable, failing with the existing tshark_missing or
capinfos_missing code when no absolute PATH entry holds the tool. Both
selections are validated before PATH is consulted, so a relative
environment value still reports its own configuration error. Windows
keeps PATH/PATHEXT resolution in the process launcher.

Refs #3403
2026-10-14 16:28:29 +05:30
555aaditya bbecf6fb05 refactor(pcap): give TShark selection and version admission one owner
The pcap and packet-capture families wrapped the same caller-supplied
TShark with diverging rules. inspect_pcap_* accepted an absolute
REA_TSHARK_COMMAND or tshark from PATH, while inspect_packet_* and the
server availability policy required an absolute REA_TSHARK_COMMAND and
parsed the version banner with a separate regex.

PcapConfiguration now owns the rule: selectWiresharkTool selects an
absolute environment path or the bare name on PATH and refuses relative
values; locateWiresharkTool resolves a PATH selection to the first
absolute PATH entry holding an executable file; parseWiresharkVersion
admits Wireshark 4.x banners for both providers. TsharkCaptureProvider
and the session availability policy consume these facts instead of
reinterpreting REA_TSHARK_COMMAND, so all four tools accept and refuse
the same configurations. inspect_packet_* still resolves, hashes and
rechecks the located executable, and records selection_source in its
tool Evidence.

Host support and resource bounds are unchanged; unifying them is the
next milestone in #3403.

Refs #3403
2026-10-14 15:05:58 +05:30
1255 changed files with 134293 additions and 8773 deletions

No files matched your search

@@ -2,7 +2,7 @@
name: reverse-engineer-anything
description: Reverse engineer native, managed, Electron/JavaScript, packaged, firmware, and browser targets with REA. Use shipped-artifact or requested runtime evidence to explain features, compare versions, decompile code, or guide a reconstruction. Skip REA for ordinary source-repository architecture analysis.
metadata:
version: "42"
version: "44"
---
# REA
@@ -30,6 +30,8 @@ unavailable, read [connection and recovery](references/connection-and-recovery.m
Diagnose the observed blocker, continue useful supported work, and resume the
original task after repair. Client approval, shell PATH, registration and engine
availability have different remedies; avoid repeating setup for all of them.
If the host times out without a REA result, do not repeat the unchanged call or
assume work stopped. Read the recovery guide's deadline distinction before retrying.
1. Diagnose without changing REA or client configuration. `npx` may download
the package and write to npm's cache. For Codex, run
@@ -92,6 +94,10 @@ explicit path or endpoint and do not need it.
- Archive/package member inventory (ZIP/APK/IPA/MSIX/AppX or DMG):
`open_binary` with the supplied local path; use `inspect_artifact` when its
graph and findings help answer the question.
- Apple app plist, Interface Builder, asset catalog, or keyed archive resources:
`open_bundle_resources`, then the selected resource tool. This does not
require `CFBundleExecutable` or a deep provider. Resource sessions have no
executable digest or binary snapshot; use `open_binary` for native code.
- Android APK code, classes, methods, or incoming references:
`inspect_android_package`, then focused Android tools when advertised.
Archive member inventory still uses the archive route above.
@@ -169,6 +175,26 @@ explicit path or endpoint and do not need it.
absent metadata does not prove a binary is not Go, and unparsed text records
remain explicit. See the
[Go binary guide](https://github.com/morluto/rea/blob/main/docs/go-binaries.md).
- Bundled GGUF or safetensors model declarations: `inspect_model_artifact`
with the explicit local file. Default header hashing leaves full-file identity
unknown; `hash: "full"` additionally reads all weights for SHA-256. MCP returns
retained summaries; optional `view` selects one page in the initial call. Use
`inspect_analysis_view` kind `model-artifact` for
batched metadata keys, tensor names or type totals, selected fields and pages.
Preserve header-scoped indices and array preview omissions; do not infer model
behavior from declared architecture or tensor types. See the
[model file guide](https://github.com/morluto/rea/blob/main/docs/model-artifacts.md).
- Unity IL2CPP names, member owners and string literals from `global-metadata.dat`:
`inspect_il2cpp_metadata` with the explicit local file; MCP defaults to compact
counts. Query sections, images, types, methods, fields, properties, events,
parameters or string_literals through `inspect_analysis_view`
with the returned `parent_evidence_id`, using exact filters, batch indices and
selected fields. Parameters accept `method_indices`, avoiding a scan of all
parameter pages. Missing collections in historical Evidence remain unknown.
Versions 24, 27, 29, 31 and 39; no Unity, IL2CPP
binary or disassembler is run. Unrecognized magic (possibly encrypted) and
other versions are unsupported. Optional matching `binary_path` enables static native addresses and type references; query `method_addresses` with indices or addresses/states, preserving every shared-body method and both artifact identities. Without a linked binary native counts remain unknown. Byte-pattern fallback is inferred; no runtime behavior or same-build pairing is proved. See the
[IL2CPP metadata guide](https://github.com/morluto/rea/blob/main/docs/il2cpp-metadata.md).
- Embedded cargo-auditable Rust dependency metadata: `inspect_rust_binary`
with the explicit local ELF, PE, or thin Mach-O file. This built-in
target-free inspection requires no Rust installation or disassembler. Preserve
@@ -247,6 +273,12 @@ Provider candidate facts describe possible providers, while top-level session
capabilities describe the current route and `analysis_provider_binding` names the
selected provider. Do not treat those scopes as interchangeable.
For a Ghidra startup timeout on a large native target, follow
[deadline recovery](references/native-and-artifacts.md#ghidra-startup-deadline-recovery)
before abandoning deep analysis or repeating the same cold import. The default
330 seconds is configurable; changing the server's environment requires a new
REA process.
## Work summary-first
Start with the default result and use its inline Evidence and graph context.
@@ -34,6 +34,47 @@ answers part of the question, and name the unavailable evidence separately.
Do not substitute another target. Label observations from ordinary shell tools
as such; only actual REA output supplies REA Evidence.
## Distinguish client and server deadlines
A host message such as `timed out awaiting tools/call` with no REA result means
the client's deadline expired before a result arrived. It does not establish
that REA finished, canceled successfully, or released all resources. Do not
repeat the unchanged analysis. Inspect available session/provider state and
retained Evidence only when useful; an idle `binary_session` is not proof that
every target-free operation stopped. Never invent a missing Evidence reference.
Allow the host tool deadline to cover execution, cancellation/cleanup, and
response delivery. In Codex, the setting is
`mcp_servers.<server-id>.tool_timeout_sec` in **seconds**, not
`startup_timeout_sec`. Select a value for the actual operation budget and
headroom, not a universal timeout. See the
[official MCP configuration reference](https://learn.chatgpt.com/docs/extend/mcp?surface=cli).
Apply configuration changes only within the authorized scope, preserving
unrelated entries and backups; reconnect/restart as required by the host.
When configuration is not editable, report the setting needed or use an
authorized CLI fallback. Do not silently broaden permissions or switch targets.
A returned REA `provider_timeout` instead means the **server/provider** reached
its deadline. Follow its `remediation.action`, reuse accessible partial Evidence,
and resolve reported incomplete cleanup before retrying. Raising only the
client deadline does not change this server budget. For static JavaScript,
`analysis_timeout_ms` (CLI `rea analyze-javascript-application <path>
--analysis-timeout-ms <milliseconds>`) controls each source's
startup, analysis and transfer deadline in **milliseconds**. Increase that
budget or reduce semantic work / select exact inventoried `source_paths` when
the task permits. Omit `source_paths` for all sources; `[]` is invalid.
`detail: "summary"` reduces delivery, not analysis work. A per-source budget
does not bound the elapsed time for an entire multi-source application.
Partial-Evidence inspection can avoid recomputation; an unavailable reader is
not itself a reason to block a corrected static-analysis retry.
The shorthand `rea analyze <path>` does not expose this timeout flag; use the
explicit JavaScript command when changing that budget.
For invalid arguments, use the connected tool's current input schema, or the
installed CLI's command help. Refresh the catalog if stale; do not guess fields
from an older skill or return the entire catalog to repair one field. Correct
all reported fields before retrying.
## Repair registration when needed
For Codex:
@@ -24,6 +24,17 @@ retain its complete source and receive that view immediately. Without that
advertised choice, keep the existing complete call. CLI inspection returns
portable complete Evidence; save it before projecting a selected inline view.
For native procedure/name/string inventories, select `detail: "summary"` when
the connected tool advertises it and the task needs counts or selected rows.
Use its parent Evidence ID with
`view: {kind: "native-inventory", offset: 0, limit: 32, fields: ["value"]}`.
Search tools retain the existing pattern/mode/case/document selection. Omit
`fields` for complete records; `record.address` and `source_index` remain on
selected rows. Selecting `value` keeps its string/decoding qualifications.
Parent Evidence ID plus source index preserves same-address
alternatives. Follow `coverage.next_offset` only as far as the question needs;
exhausting retained rows does not establish complete program discovery.
Use `record_unknown` to track unresolved questions in the user's investigation
and name the authority or environment still required. Supply supporting and
contradicting evidence IDs. It updates the session registry directly.
@@ -77,3 +88,9 @@ 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.
Use `view: {kind: "environment-state"}` with the manifest's `template_rules` to
extract the data those reads observed instead: entity types and identity
fields, entities with recorded values, documents, and per-tool render plans
checked against the recordings. The state comes only from reads before the
first related write; types, identity and list membership are inferences.
@@ -18,7 +18,8 @@ only selected files. The result and summary record `source_selection`; files
outside scope and their relationships remain unknown, so partial application
coverage does not mean the selected source failed. Use repeated `--source-path`
on either static application CLI route. Omit the selection when the question
requires complete application analysis. `detail: "summary"` reduces delivery
requires complete application analysis; `source_paths: []` is invalid, not an
unfiltered request. `detail: "summary"` reduces delivery
and does not by itself reduce analysis work.
Exact `#alias` specifiers resolve through the importer's
@@ -35,7 +36,9 @@ the complete application Evidence inline when it fits.
When the connected schema advertises `max_heap_mb` and `analysis_timeout_ms`,
these select the isolated source analyzer's old-space heap and per-source
deadline. Defaults are 1024 MiB and 300000 ms. They do not change the MCP
process heap. A Bun-hosted REA does not enforce the heap choice; on Windows it
process heap or the client's tool deadline. For a host timeout without REA
output, use the [deadline recovery guide](connection-and-recovery.md#distinguish-client-and-server-deadlines)
instead of raising the server budget. A Bun-hosted REA does not enforce the heap choice; on Windows it
instead limits the analyzer's committed memory to that choice plus a 512 MiB
runtime reserve.
Resource-limited analyses preserve completed static facts and
@@ -1,5 +1,48 @@
# Native, managed, and packaged artifacts
For release comparisons, export `list_procedures` Evidence from each target before
closing it. Close clears session records: import both bundles after collecting the
two targets, or supply portable inline Evidence. `match_native_functions` pairs unique exact names and, when supplied,
complete observed body bytes. Reuse optional same-context `list_names`,
`procedure_info`, `read_bytes` and existing `analyze_function` Evidence; avoid
decompiling every function merely to match it. Its summary retains a parent for
`inspect_analysis_view` `function-matches` collections `matches` and `functions`.
Select columns, batch IDs and page individual facts; aliases remain unresolved.
Unpaired observations do not prove additions/removals. Existing matched dossier
pairs include inputs for `compare_functions`; otherwise analyze just chosen pairs.
## Apple app resources
Use `open_bundle_resources` with the selected app path, then `inspect_plist`,
`decode_interface_builder`, `inspect_asset_catalog`, or `inspect_keyed_archive`.
The resource session reads the app without resolving `CFBundleExecutable` or
starting a deep provider. Preserve `resource_root` provenance, per-resource
hashes where reported, and null executable identity; a directory path is not
an executable digest. Export retained Evidence before closing or switching
roots. Binary analysis snapshots do not apply. Use `open_binary` to switch to
executable analysis, and `close_binary` to release either session kind.
The four matching CLI commands accept the app path directly. For an archive
inside the app, use `inspect-keyed-archive APP_PATH RELATIVE_ARCHIVE_PATH`.
Host requirements for plist and compiled asset/Interface Builder tooling still
apply; a resource-only session does not establish provider availability.
## Desktop installation directories
When an installation directory is supplied and its runtime is unknown, use
`inspect_desktop_application` with its absolute path. Default MCP summary
delivery retains complete Evidence. Read `files`, `omissions`, `candidates`, `components` or
`next_probes` with `inspect_analysis_view` kind `desktop-application`, selecting
exact paths, batched file/omission IDs or families and only needed fields and pages.
Summary `probe_issues` retains counts and bounded previews. Select files with
`has_issues: true` and fields `path`, `read_status`, `issues` to retrieve exact
failures directly; preview text is display data, while `file_id` selects full facts. Preserve source
coverage, read-range identity and unknowns; directory snapshot identity is not
a digest of every file's contents. Component path markers do not establish
runtime presence. For compact CLI output, use
`inspect-desktop-application PATH --detail summary --evidence_output BUNDLE`.
See [desktop installations](https://github.com/morluto/rea/blob/main/docs/desktop-applications.md).
## Go build metadata
Use `inspect_go_binary` for an explicit local ELF, PE or thin Mach-O when the
@@ -11,6 +54,34 @@ unparsed module-text line. A missing record is an unknown, not proof of a
non-Go binary; observed metadata does not authenticate its claims. Function,
source and type recovery remain a separate native-analysis question.
## Model files
Use `inspect_model_artifact` (`inspect-model-artifact PATH`) for local GGUF v2/v3
and safetensors declarations without a model runtime. Header-only mode does not
read weights or establish full-file identity. `hash: "full"` explicitly streams
all bytes. Retained `model-artifact` views page `metadata`, `tensors` and derived
`types`, with exact batch filters and selected fields. Arrays retain typed counts
and eight-element previews; omitted values, unknown types and runtime behavior
stay explicit. See [model files](https://github.com/morluto/rea/blob/main/docs/model-artifacts.md).
## IL2CPP metadata
Use `inspect_il2cpp_metadata` for an explicit local Unity `global-metadata.dat`
(versions 24, 27, 29, 31 and 39) when the question concerns assembly images,
names, member owners, string literals, namespaces or index ranges. No `open_binary`, Unity installation or target
execution is required. The CLI equivalent is `inspect-il2cpp-metadata PATH`.
MCP defaults to counts with complete retained Evidence. Query `sections`,
`images`, `types`, `methods`, `fields`, `properties`, `events`, `parameters` or
`string_literals` through `inspect_analysis_view`; use exact names,
batch indices and selected fields. Row indices are scoped by artifact SHA-256
and collection; page offsets count filtered matches. Parameters support batch
`method_indices` to read one method's parameters directly. Historical reports
without member collections retain unknown counts rather than empty inventories. Preserve
artifact SHA-256 and index widths. Unrecognized magic may mean encryption and
is unsupported, not decrypted. Linking names to `GameAssembly` or
`UnityFramework` code addresses remains a separate native-analysis question.
See [IL2CPP metadata](https://github.com/morluto/rea/blob/main/docs/il2cpp-metadata.md).
## Rust dependency metadata
Use `inspect_rust_binary` for an explicit local ELF, PE, or thin Mach-O when
@@ -124,6 +195,36 @@ 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.
## Ghidra startup deadline recovery
`provider_timeout` during the first Ghidra query can cover import, auto-analysis,
bridge startup, and readiness. The default 330,000 ms is configurable through
`REA_GHIDRA_STARTUP_TIMEOUT_MS`; a smaller query still needs the same cold import.
Preserve useful Evidence before closing the session or restarting REA. Check
`close_binary` and resolve reported cleanup failures. Set a larger startup budget
in the environment that launches REA, then restart REA and reconnect the MCP
client before reopening the same target. Closing and reopening a binary in the
existing server keeps its original configuration and starts import again.
Environment changes in an agent's shell do not update an already running MCP
server. If its launch configuration cannot be changed, report that constraint
and the exact retry setting instead of claiming a fixed technical limit.
The client's tool-call deadline must allow startup plus the requested query;
server settings and progress notifications cannot override it. CLI analysis
avoids the MCP client deadline, but retains the provider deadline. For example:
```sh
REA_GHIDRA_STARTUP_TIMEOUT_MS=1800000 rea analyze /absolute/path/to/app.exe --provider ghidra --json
```
Thirty minutes is an example budget, not a completion guarantee. Keep host CPU
and memory controls in place. Disable specific expensive analyzers only when
their missing coverage is acceptable and retain the resulting limitations.
Exported C and embedded resources remain useful independent evidence, but a
timeout does not establish complete analysis or absence of code. See the
[deadline and client guide](https://github.com/morluto/rea/blob/main/docs/mcp-contracts.md#ghidra-first-query-deadlines-and-recovery).
## Static memory and original file bytes
For Ghidra, `read_bytes` reads initialized analysis memory, including loader
@@ -295,3 +396,22 @@ with two complete inspection Evidence records (or current-session retained
references) and explicit scope. Preserve unknown types/duplicate names; static
interface equality is not runtime compatibility. CLI accepts complete inline
Evidence in `rea compare-wasm-interfaces input.json --json`.
## Godot PCK
For a standalone PCK, `open_binary` then `inspect_artifact` with
`detail: "summary"` retains the complete static inventory. Use the returned
`parent_evidence_id` with `inspect_analysis_view` inventory occurrences filtered
by exact `logical_paths` or `occurrence_ids`, and join `artifact_id` to nodes
filtered by `artifact_ids`. Select only needed fields; identity links remain.
Prefer `inspect-artifact --detail summary --evidence_output PATH` for CLI tasks;
the same CLI discovers embedded packs via their EOF trailer without opening a
native analysis provider. Normal native opening remains unchanged.
Distinguish declared MD5 from observed SHA-256 and graph/page completeness from
`source_coverage`. Encrypted directories and sparse bundles have unknown entry
coverage; encrypted members have unknown content identity. An empty filtered
page cannot prove absence in unknown coverage. Retained views are historical,
not fresh filesystem checks. No decryption, Godot resource decoding, GDScript
decompilation or target execution is provided. See
[Godot PCK](https://github.com/morluto/rea/blob/main/docs/godot-pck.md).
@@ -69,6 +69,12 @@ with `inspect_analysis_view` and `view: {kind: "capture", detail: "preview", off
Select complete record pages only for needed headers, metadata or payloads; views
read the historical parent without repeating capture decoding.
For selected protobuf/gRPC bodies, keep raw bytes as the source and use
`inspect_analysis_view` kind `protobuf`, collection `bodies`, `frames` or
`fields`. Batch exact record ordinals and field numbers/IDs, and select
`schema_value` or `text` only when needed. Supply a local descriptor set and
message type for schema interpretation; compressed payloads remain unknown.
Inspect native `.saz` snapshots with `inspect_web_network_capture` and
`format: "saz"`; encrypted archives are unsupported. For live
traffic analysis, connect Everywhere's separate MCP server and use its
+13 -3
View File
@@ -1,5 +1,10 @@
name: Cache npm package downloads
description: Restore npm's download cache and save it only from trusted default-branch events.
description: Restore npm's download cache. Trusted default-branch jobs that opt in may save it.
inputs:
save:
description: Save the shared download cache when this event is allowed to write it.
required: false
default: "false"
outputs:
can-save:
description: Whether this run may update the shared npm download cache.
@@ -23,20 +28,25 @@ runs:
can_save=true
fi
cache_key="npm-download-${RUNNER_OS}-${runtime_arch}-${LOCKFILES_HASH}"
# Same platform only. A lockfile change can reuse tarballs from the previous key.
restore_key="npm-download-${RUNNER_OS}-${runtime_arch}-"
{
printf 'can-save=%s\n' "${can_save}"
printf 'path=%s\n' "${cache_path}"
printf 'key=%s\n' "${cache_key}"
printf 'restore-key=%s\n' "${restore_key}"
} >> "${GITHUB_OUTPUT}"
- name: Restore and save npm package downloads
if: steps.context.outputs.can-save == 'true'
if: steps.context.outputs.can-save == 'true' && inputs.save == 'true'
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ steps.context.outputs.path }}
key: ${{ steps.context.outputs.key }}
restore-keys: ${{ steps.context.outputs.restore-key }}
- name: Restore npm package downloads without saving
if: steps.context.outputs.can-save != 'true'
if: steps.context.outputs.can-save != 'true' || inputs.save != 'true'
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ steps.context.outputs.path }}
key: ${{ steps.context.outputs.key }}
restore-keys: ${{ steps.context.outputs.restore-key }}
+64
View File
@@ -0,0 +1,64 @@
name: Cache retention
on:
workflow_run:
workflows: ["CI"]
types: [completed]
# Qualification calls ci.yml with actions: read. A nested workflow cannot raise
# that token, so cache deletion stays in this workflow.
permissions:
contents: read
actions: write
concurrency:
group: cache-retention-${{ github.event.workflow_run.head_sha }}
cancel-in-progress: false
jobs:
retain:
name: Retain Turbo snapshots and npm download caches
# Restrict the triggering-source checkout to same-repository default-branch
# CI events. The helper runs from this trusted workflow revision; triggering
# source is used only for cache identity and is never executed. Static and
# build save snapshots before later lanes finish, so failed, timed-out, or
# cancelled runs still retain those snapshots.
if: >-
(github.event.workflow_run.conclusion == 'success' ||
github.event.workflow_run.conclusion == 'failure' ||
github.event.workflow_run.conclusion == 'timed_out' ||
github.event.workflow_run.conclusion == 'cancelled') &&
github.event.workflow_run.head_repository.full_name == github.repository &&
github.event.workflow_run.head_branch == github.event.repository.default_branch &&
(github.event.workflow_run.event == 'push' ||
github.event.workflow_run.event == 'schedule' ||
github.event.workflow_run.event == 'workflow_dispatch')
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
ref: ${{ github.workflow_sha }}
path: trusted-retention
persist-credentials: false
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
ref: ${{ github.event.workflow_run.head_sha }}
path: triggering-source
persist-credentials: false
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: trusted-retention/.nvmrc
- name: Retain current Turbo snapshots and npm download caches
env:
GH_TOKEN: ${{ github.token }}
CI_REPOSITORY: ${{ github.repository }}
CACHE_PREFIX: rea-static-v1-${{ runner.os }}-${{ runner.arch }}-
CACHE_KEEP_KEY: rea-static-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('triggering-source/.nvmrc', 'triggering-source/.npmrc', 'triggering-source/package-lock.json') }}-${{ github.event.workflow_run.head_sha }}
CACHE_DEEP_PREFIX: rea-static-deep-v1-${{ runner.os }}-${{ runner.arch }}-
CACHE_DEEP_KEEP_KEY: rea-static-deep-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('triggering-source/.nvmrc', 'triggering-source/.npmrc', 'triggering-source/package-lock.json') }}-${{ github.event.workflow_run.head_sha }}
CACHE_KNIP_PREFIX: knip-meta-v1-${{ runner.os }}-
CACHE_KNIP_KEEP_KEY: knip-meta-v1-${{ runner.os }}-${{ hashFiles('triggering-source/knip.json', 'triggering-source/tsconfig.json', 'triggering-source/package.json', 'triggering-source/package-lock.json') }}-${{ github.event.workflow_run.head_sha }}
CACHE_PORTABLE_PREFIX: rea-portable-build-v2-${{ runner.os }}-${{ runner.arch }}-
DEDUPE_NPM_DOWNLOADS: "true"
run: node trusted-retention/scripts/ci/cache-retention.mjs
+145 -12
View File
@@ -15,6 +15,15 @@ on:
description: Exact qualification source; must match the caller revision.
required: true
type: string
remote_cache_write:
description: Trusted release qualification may publish the remote cache.
required: false
type: boolean
default: false
secrets:
TURBO_TOKEN:
description: Remote cache token. Only trusted release qualification passes it.
required: false
permissions:
contents: read
@@ -29,6 +38,15 @@ concurrency:
env:
HUSKY: "0"
# Set Actions secret TURBO_TOKEN and variable TURBO_TEAM. OIDC can mint
# TURBO_TOKEN via vercel/setup-turborepo-remote-cache-action; do not commit a token.
# A called workflow sees the caller event, so workflow_call is not an event
# name here. Release qualification sets remote_cache_write and passes the
# token. Open pull requests get an empty token and the local cache only.
# Remote reads need a credential, and pull requests do not receive one.
TURBO_TOKEN: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && 'local:rw,remote:rw' || 'local:rw' }}"
jobs:
changes:
@@ -59,6 +77,7 @@ jobs:
web_network: ${{ steps.plan.outputs.web_network }}
web_runtime: ${{ steps.plan.outputs.web_runtime }}
web_source_map: ${{ steps.plan.outputs.web_source_map }}
agentenv: ${{ steps.plan.outputs.agentenv }}
nativeaot: ${{ steps.plan.outputs.nativeaot }}
ghidra_bridge: ${{ steps.plan.outputs.ghidra_bridge }}
website: ${{ steps.plan.outputs.website }}
@@ -127,6 +146,9 @@ jobs:
- name: Cache npm package downloads
id: npm-cache
uses: ./.github/actions/npm-cache
with:
# Linux x64 writer. Parallel Linux jobs restore this key.
save: "true"
- run: npm ci
- name: Restore static task cache
if: needs.changes.outputs.code == 'true'
@@ -150,14 +172,10 @@ jobs:
if: needs.changes.outputs.code == 'true'
env:
CI_PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
CI_STATIC_CONTEXT_SCRIPT: check:ci:fast:tasks
run: npm run ci:static-context
- if: needs.changes.outputs.code == 'true'
run: npm run check:ci
- if: needs.changes.outputs.code == 'true'
run: npm run verify:test-discovery
- name: Check LLDB producer retention and launch contracts
if: needs.changes.outputs.code == 'true'
run: npm run test:python
run: npm run check:ci:fast
- if: needs.changes.outputs.code != 'true'
run: npm run format:check
- name: Save validated static task cache
@@ -179,6 +197,72 @@ jobs:
if-no-files-found: ignore
retention-days: 7
static-deep:
name: Deep static checks
needs: changes
# Full qualification only. Provider lanes wait on fast static, not this job.
if: needs.changes.outputs.tier == 'full' && needs.changes.outputs.code == 'true'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: .nvmrc
- name: Cache npm package downloads
id: npm-cache
uses: ./.github/actions/npm-cache
- run: npm ci
- name: Restore deep static task cache
id: static-cache
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: .turbo/cache/
key: rea-static-deep-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.nvmrc', '.npmrc', 'package-lock.json') }}-${{ github.sha }}
restore-keys: rea-static-deep-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.nvmrc', '.npmrc', 'package-lock.json') }}-
- name: Restore Knip analysis cache
id: knip-cache
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: node_modules/.cache/knip
# Each trusted commit publishes a new entry. Restore still matches the
# configuration prefix from the previous successful full run.
key: knip-meta-v1-${{ runner.os }}-${{ hashFiles('knip.json', 'tsconfig.json', 'package.json', 'package-lock.json') }}-${{ github.sha }}
restore-keys: knip-meta-v1-${{ runner.os }}-${{ hashFiles('knip.json', 'tsconfig.json', 'package.json', 'package-lock.json') }}-
- name: Record deep static task source and execution identity
continue-on-error: true
env:
CI_PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
CI_STATIC_CONTEXT_SCRIPT: check:ci:deep:tasks
run: npm run ci:static-context
- name: Run deep static checks
run: npm run check:ci:deep
- name: Save validated deep static task cache
if: >-
success() && steps.npm-cache.outputs.can-save == 'true' &&
steps.static-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: .turbo/cache/
key: ${{ steps.static-cache.outputs.cache-primary-key }}
- name: Save Knip analysis cache
if: >-
success() && steps.npm-cache.outputs.can-save == 'true' &&
steps.knip-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: node_modules/.cache/knip
key: ${{ steps.knip-cache.outputs.cache-primary-key }}
- name: Upload complete deep static diagnostics
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: static-deep-check-reports
path: .cache/static-checks/
include-hidden-files: true
if-no-files-found: ignore
retention-days: 7
test-source:
name: Source tests
needs: changes
@@ -218,9 +302,11 @@ jobs:
# every shard's diagnostics and coverage. Passing PRs run the full suite.
fail-fast: ${{ github.event_name == 'pull_request' && needs.changes.outputs.tier == 'fast' }}
matrix:
# Fast feedback spends the same six test jobs on one source group and
# five built groups; full qualification retains six complete shards.
shard: ${{ fromJSON(needs.changes.outputs.tier == 'fast' && '["1/5","2/5","3/5","4/5","5/5"]' || '["1/6","2/6","3/6","4/6","5/6","6/6"]') }}
# Fast feedback uses one source group and eight built groups so the
# slowest built shard job stays inside a ten-minute execution budget.
# Classification, build, and report merge sit outside that job.
# Full qualification retains six complete shards with coverage.
shard: ${{ fromJSON(needs.changes.outputs.tier == 'fast' && '["1/8","2/8","3/8","4/8","5/8","6/8","7/8","8/8"]' || '["1/6","2/6","3/6","4/6","5/6","6/6"]') }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
@@ -302,7 +388,8 @@ jobs:
needs.changes.outputs.recorded_crash == 'true' ||
needs.changes.outputs.web_network == 'true' ||
needs.changes.outputs.web_runtime == 'true' ||
needs.changes.outputs.web_source_map == 'true'
needs.changes.outputs.web_source_map == 'true' ||
needs.changes.outputs.agentenv == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
@@ -371,8 +458,9 @@ jobs:
retention-days: 7
sqlite-runtime:
# Preserve all selected coverage, but admit expensive host/provider work
# only after static validation. Portable tests still provide early feedback.
# Admit expensive host/provider work after fast static validation
# (typecheck, lint, format). Deep static does not gate these lanes.
# Portable tests still provide early feedback.
needs: [changes, static, build]
if: needs.changes.outputs.sqlite == 'true'
uses: ./.github/workflows/sqlite-runtime.yml
@@ -575,6 +663,9 @@ jobs:
- name: Cache npm package downloads
id: npm-cache
uses: ./.github/actions/npm-cache
with:
# ubuntu-latest is the Linux x64 writer above. Other hosts save their own key.
save: ${{ matrix.os != 'ubuntu-latest' }}
- name: Verify native runtime identity
env:
EXPECTED_CI_PLATFORM: ${{ matrix.platform }}
@@ -711,6 +802,8 @@ jobs:
- name: Cache npm package downloads
id: npm-cache
uses: ./.github/actions/npm-cache
with:
save: "true"
- run: npm ci
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
@@ -748,6 +841,9 @@ jobs:
tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts
tests/boundary/filesystem/setupUnavailableProvider.test.ts
tests/boundary/filesystem/windowsNpxRegistration.test.ts
tests/boundary/filesystem/clientConfigurationEnvironment.test.ts
tests/boundary/filesystem/clientConfigurationLayeredEnvironment.test.ts
tests/acceptance/setup/registrationRuntimeEnvironmentCli.test.ts
tests/boundary/android/workspaceGuardianRetry.test.ts
tests/acceptance/setup/homeDirectoryFallback.test.ts
tests/boundary/filesystem/javascriptApplicationWorkflows.test.ts
@@ -853,61 +949,96 @@ jobs:
skills/reverse-engineer-anything
if-no-files-found: error
# Provider lanes wait for fast static and the portable build, not deep static.
browser:
needs: [changes, static, build]
if: needs.changes.outputs.browser == 'true'
secrets:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
uses: ./.github/workflows/real-browser.yml
with:
build_cache_artifact: rea-build-cache
remote_cache_write: ${{ inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')) }}
binary_layout:
needs: [changes, static, build]
if: needs.changes.outputs.binary_layout == 'true'
secrets:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
uses: ./.github/workflows/real-binary-layout.yml
with:
build_cache_artifact: rea-build-cache
remote_cache_write: ${{ inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')) }}
evm:
needs: [changes, static, build]
if: needs.changes.outputs.evm == 'true'
secrets:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
uses: ./.github/workflows/real-evm-interface.yml
with:
build_cache_artifact: rea-build-cache
remote_cache_write: ${{ inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')) }}
javascript_recovery:
needs: [changes, static, build]
if: needs.changes.outputs.javascript_recovery == 'true'
secrets:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
uses: ./.github/workflows/real-javascript-recovery.yml
with:
build_cache_artifact: rea-build-cache
remote_cache_write: ${{ inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')) }}
recorded_crash:
needs: [changes, static, build]
if: needs.changes.outputs.recorded_crash == 'true'
secrets:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
uses: ./.github/workflows/real-recorded-crash.yml
with:
build_cache_artifact: rea-build-cache
remote_cache_write: ${{ inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')) }}
web_network:
needs: [changes, static, build]
if: needs.changes.outputs.web_network == 'true'
secrets:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
uses: ./.github/workflows/real-web-network-captures.yml
with:
build_cache_artifact: rea-build-cache
remote_cache_write: ${{ inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')) }}
web_runtime:
needs: [changes, static, build]
if: needs.changes.outputs.web_runtime == 'true'
secrets:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
uses: ./.github/workflows/real-web-runtime.yml
with:
build_cache_artifact: rea-build-cache
remote_cache_write: ${{ inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')) }}
web_source_map:
needs: [changes, static, build]
if: needs.changes.outputs.web_source_map == 'true'
secrets:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
uses: ./.github/workflows/real-web-source-map.yml
with:
build_cache_artifact: rea-build-cache
remote_cache_write: ${{ inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')) }}
agentenv:
needs: [changes, static, build]
if: needs.changes.outputs.agentenv == 'true'
secrets:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
uses: ./.github/workflows/real-agentenv.yml
with:
build_cache_artifact: rea-build-cache
remote_cache_write: ${{ inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')) }}
nativeaot:
needs: [changes, static]
@@ -932,6 +1063,7 @@ jobs:
[
changes,
static,
static-deep,
build,
reverse-tools-quality,
test-shard,
@@ -953,6 +1085,7 @@ jobs:
web_network,
web_runtime,
web_source_map,
agentenv,
nativeaot,
ghidra_bridge,
website,
+5
View File
@@ -14,6 +14,11 @@ concurrency:
env:
HUSKY: "0"
# Writes only on the default branch for push, schedule, manual dispatch,
# and workflow_call. Pull requests get an empty token and remote read-only mode.
TURBO_TOKEN: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && 'local:rw,remote:rw' || 'local:rw,remote:r' }}"
jobs:
mutation:
+98
View File
@@ -0,0 +1,98 @@
name: Real agentenv environment bundle
on:
workflow_dispatch:
workflow_call:
inputs:
build_cache_artifact:
description: Portable build cache artifact from the calling CI run.
required: false
type: string
default: ""
remote_cache_write:
description: Trusted release qualification may publish the remote cache.
required: false
type: boolean
default: false
secrets:
TURBO_TOKEN:
description: Remote cache token. Only trusted callers pass it.
required: false
permissions:
contents: read
env:
HUSKY: "0"
# A called workflow sees the caller event, so workflow_call is not an event
# name here. Writes when remote_cache_write is set, or on the default branch
# for push, schedule, and manual dispatch. Open pull requests stay empty-token
# and use the local cache only.
TURBO_TOKEN: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && 'local:rw,remote:rw' || 'local:rw' }}"
NODE_OPTIONS: --max-old-space-size=768
PIP_DISABLE_PIP_VERSION_CHECK: "1"
jobs:
real-agentenv:
name: Export and run an environment bundle with the agentenv runner
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: .nvmrc
- name: Cache npm package downloads
id: npm-cache
uses: ./.github/actions/npm-cache
- run: npm ci
- uses: ./.github/actions/portable-build-cache
with:
build_cache_artifact: ${{ inputs.build_cache_artifact }}
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
# Public ECR caps anonymous pulls by data per source IP and hosted runners share IPs, so the
# framework's image builds can fail here for hours. mirror.gcr.io serves the same Docker
# official images under the same digests, so each base image the pinned framework builds from
# is pulled there and named as its Dockerfile names it, as the framework's own CI does.
# Digest-pinned names are set in containerd, whose images Docker reads only on the containerd
# image store; switching stores restarts dockerd, so it happens before anything uses Docker.
- name: Use the containerd image store
run: |
[ -s /etc/docker/daemon.json ] || echo '{}' | sudo tee /etc/docker/daemon.json >/dev/null
jq '.features["containerd-snapshotter"] = true' /etc/docker/daemon.json > "$RUNNER_TEMP/daemon.json"
sudo mv "$RUNNER_TEMP/daemon.json" /etc/docker/daemon.json
sudo systemctl restart docker
docker info --format '{{json .DriverStatus}}' | grep -q io.containerd.snapshotter
- name: Acquire the pinned agentenv runner in isolated runner storage and check host Docker
shell: bash
run: |
runner_root="${RUNNER_TEMP}/rea-agentenv-runner"
python -m venv "${runner_root}"
"${runner_root}/bin/python" -m pip install --require-virtualenv --no-cache-dir 'agentenv-framework==0.9.1334'
"${runner_root}/bin/agent-env" --version
docker version --format '{{.Server.Version}}'
echo "REA_AGENT_ENV_COMMAND=${runner_root}/bin/agent-env" >> "${GITHUB_ENV}"
echo "REA_DOCKER_COMMAND=$(command -v docker)" >> "${GITHUB_ENV}"
- name: Pull the pinned framework's public ECR base images from mirror.gcr.io
shell: bash
run: |
package="$("${REA_AGENT_ENV_COMMAND%/agent-env}/python" -c 'import agent_env, pathlib; print(pathlib.Path(agent_env.__file__).parent)')"
grep -rhoE '^FROM +public\.ecr\.aws/docker/library/[^ ]+' --include='Dockerfile*' "${package}" | awk '{print $2}' | sort -u |
while read -r image; do
name=${image#public.ecr.aws/docker/library/}
source=mirror.gcr.io/library/$name
case $name in *@*) source=mirror.gcr.io/library/${name%%[:@]*}@${name#*@} ;; esac
for attempt in 1 2 3; do
docker pull --quiet "$source" && break
if [ "$attempt" = 3 ]; then echo "::warning::couldn't pull $source; $image's build will pull it"; continue 2; fi
sleep $((attempt * 10))
done
case ${name%@*} in *:*) docker tag "$source" "${image%@*}" ;; esac
case $image in *@*) sudo ctr --namespace moby images tag "$source" "$image" >/dev/null ;; esac
done
- name: Export a bundle from the source-owned capture and run it with the agentenv runner
run: npm run verify:agentenv:environment
+16
View File
@@ -14,6 +14,15 @@ on:
required: false
type: string
default: ""
remote_cache_write:
description: Trusted release qualification may publish the remote cache.
required: false
type: boolean
default: false
secrets:
TURBO_TOKEN:
description: Remote cache token. Only trusted callers pass it.
required: false
permissions:
contents: read
@@ -21,6 +30,13 @@ permissions:
env:
NODE_OPTIONS: --max-old-space-size=768
HUSKY: "0"
# A called workflow sees the caller event, so workflow_call is not an event
# name here. Writes when remote_cache_write is set, or on the default branch
# for push, schedule, and manual dispatch. Open pull requests stay empty-token
# and use the local cache only.
TURBO_TOKEN: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && 'local:rw,remote:rw' || 'local:rw' }}"
REA_VERIFY_LARGE_ELF_MCP: ${{ inputs.large_mcp && '1' || '0' }}
jobs:
+16
View File
@@ -8,10 +8,26 @@ on:
required: false
type: string
default: ""
remote_cache_write:
description: Trusted release qualification may publish the remote cache.
required: false
type: boolean
default: false
secrets:
TURBO_TOKEN:
description: Remote cache token. Only trusted callers pass it.
required: false
workflow_dispatch:
env:
HUSKY: "0"
# A called workflow sees the caller event, so workflow_call is not an event
# name here. Writes when remote_cache_write is set, or on the default branch
# for push, schedule, and manual dispatch. Open pull requests stay empty-token
# and use the local cache only.
TURBO_TOKEN: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && 'local:rw,remote:rw' || 'local:rw' }}"
permissions:
contents: read
+8
View File
@@ -8,6 +8,14 @@ on:
permissions:
contents: read
env:
HUSKY: "0"
# Writes only on the default branch for push, schedule, manual dispatch,
# and workflow_call. Pull requests get an empty token and remote read-only mode.
TURBO_TOKEN: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && 'local:rw,remote:rw' || 'local:rw,remote:r' }}"
jobs:
windows-native-artifact:
name: Build Windows bridge security boundary
+16
View File
@@ -9,6 +9,15 @@ on:
required: false
type: string
default: ""
remote_cache_write:
description: Trusted release qualification may publish the remote cache.
required: false
type: boolean
default: false
secrets:
TURBO_TOKEN:
description: Remote cache token. Only trusted callers pass it.
required: false
permissions:
contents: read
@@ -16,6 +25,13 @@ permissions:
env:
NODE_OPTIONS: --max-old-space-size=768
HUSKY: "0"
# A called workflow sees the caller event, so workflow_call is not an event
# name here. Writes when remote_cache_write is set, or on the default branch
# for push, schedule, and manual dispatch. Open pull requests stay empty-token
# and use the local cache only.
TURBO_TOKEN: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && 'local:rw,remote:rw' || 'local:rw' }}"
jobs:
real-evm-interface:
@@ -6,6 +6,11 @@ on:
env:
HUSKY: "0"
# Writes only on the default branch for push, schedule, manual dispatch,
# and workflow_call. Pull requests get an empty token and remote read-only mode.
TURBO_TOKEN: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && 'local:rw,remote:rw' || 'local:rw,remote:r' }}"
permissions:
contents: read
+5 -12
View File
@@ -13,20 +13,8 @@ on:
- "src/composition/go.ts"
- "src/cli/goCommands.ts"
- "src/server/registerGoTools.ts"
- "src/server/createServer.ts"
- "src/cli.ts"
- "src/cliCommandNames.ts"
- "src/contracts/toolContracts.ts"
- "src/contracts/toolEffects.ts"
- "src/artifacts/readStableArtifact*.ts"
- "src/artifacts/ArtifactReader.ts"
- "src/process/PrivateRuntimeRoot.ts"
- "scripts/verify-go-binary.mjs"
- "scripts/lib/mcp-verifier-results.mjs"
- "scripts/rea.mjs"
- "package.json"
- "package-lock.json"
- ".nvmrc"
permissions:
contents: read
@@ -38,6 +26,11 @@ concurrency:
env:
NODE_OPTIONS: --max-old-space-size=768
HUSKY: "0"
# Writes only on the default branch for push, schedule, manual dispatch,
# and workflow_call. Pull requests get an empty token and remote read-only mode.
TURBO_TOKEN: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && 'local:rw,remote:rw' || 'local:rw,remote:r' }}"
jobs:
real-go-binary:
+5
View File
@@ -5,6 +5,11 @@ on:
env:
HUSKY: "0"
# Writes only on the default branch for push, schedule, manual dispatch,
# and workflow_call. Pull requests get an empty token and remote read-only mode.
TURBO_TOKEN: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && 'local:rw,remote:rw' || 'local:rw,remote:r' }}"
permissions:
contents: read
+5
View File
@@ -5,6 +5,11 @@ on:
env:
HUSKY: "0"
# Writes only on the default branch for push, schedule, manual dispatch,
# and workflow_call. Pull requests get an empty token and remote read-only mode.
TURBO_TOKEN: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && 'local:rw,remote:rw' || 'local:rw,remote:r' }}"
permissions:
contents: read
@@ -8,6 +8,15 @@ on:
required: false
type: string
default: ""
remote_cache_write:
description: Trusted release qualification may publish the remote cache.
required: false
type: boolean
default: false
secrets:
TURBO_TOKEN:
description: Remote cache token. Only trusted callers pass it.
required: false
workflow_dispatch:
permissions:
@@ -15,6 +24,13 @@ permissions:
env:
HUSKY: "0"
# A called workflow sees the caller event, so workflow_call is not an event
# name here. Writes when remote_cache_write is set, or on the default branch
# for push, schedule, and manual dispatch. Open pull requests stay empty-token
# and use the local cache only.
TURBO_TOKEN: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && 'local:rw,remote:rw' || 'local:rw' }}"
NODE_OPTIONS: "--max-old-space-size=768"
RAYON_NUM_THREADS: "1"
+7 -11
View File
@@ -20,21 +20,17 @@ on:
- "src/composition/captures.ts"
- "src/cli/captureCommands.ts"
- "src/server/registerCaptureTools.ts"
- "src/server/createServer.ts"
- "src/server/sessionAvailabilityPolicy.ts"
- "src/application/CapabilityInventory.ts"
- "src/contracts/toolContracts.ts"
- "src/contracts/toolEffects.ts"
- "src/cli.ts"
- "src/cliCommandNames.ts"
- "src/process/**"
- "src/artifacts/readStableArtifact.ts"
- "scripts/verify-packet-capture.mjs"
- ".github/workflows/real-packet-capture.yml"
- "package*.json"
- ".nvmrc"
permissions:
contents: read
env:
HUSKY: "0"
# Writes only on the default branch for push, schedule, manual dispatch,
# and workflow_call. Pull requests get an empty token and remote read-only mode.
TURBO_TOKEN: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && 'local:rw,remote:rw' || 'local:rw,remote:r' }}"
concurrency:
group: real-packet-capture-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
+16
View File
@@ -9,6 +9,15 @@ on:
required: false
type: string
default: ""
remote_cache_write:
description: Trusted release qualification may publish the remote cache.
required: false
type: boolean
default: false
secrets:
TURBO_TOKEN:
description: Remote cache token. Only trusted callers pass it.
required: false
permissions:
contents: read
@@ -16,6 +25,13 @@ permissions:
env:
NODE_OPTIONS: --max-old-space-size=768
HUSKY: "0"
# A called workflow sees the caller event, so workflow_call is not an event
# name here. Writes when remote_cache_write is set, or on the default branch
# for push, schedule, and manual dispatch. Open pull requests stay empty-token
# and use the local cache only.
TURBO_TOKEN: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && 'local:rw,remote:rw' || 'local:rw' }}"
UV_CONCURRENT_BUILDS: "1"
UV_CONCURRENT_INSTALLS: "1"
UV_PYTHON_DOWNLOADS: never
+7 -11
View File
@@ -13,21 +13,17 @@ on:
- "src/composition/signals.ts"
- "src/cli/signalCommands.ts"
- "src/server/registerSignalTools.ts"
- "src/server/createServer.ts"
- "src/server/sessionAvailabilityPolicy.ts"
- "src/application/CapabilityInventory.ts"
- "src/contracts/toolContracts.ts"
- "src/contracts/toolEffects.ts"
- "src/cli.ts"
- "src/cliCommandNames.ts"
- "src/process/**"
- "src/artifacts/readStableArtifact.ts"
- "scripts/verify-signal-recording.mjs"
- ".github/workflows/real-signal-recording.yml"
- "package*.json"
- ".nvmrc"
permissions:
contents: read
env:
HUSKY: "0"
# Writes only on the default branch for push, schedule, manual dispatch,
# and workflow_call. Pull requests get an empty token and remote read-only mode.
TURBO_TOKEN: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && 'local:rw,remote:rw' || 'local:rw,remote:r' }}"
concurrency:
group: real-signal-recording-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
+5
View File
@@ -12,6 +12,11 @@ permissions:
env:
HUSKY: "0"
# Writes only on the default branch for push, schedule, manual dispatch,
# and workflow_call. Pull requests get an empty token and remote read-only mode.
TURBO_TOKEN: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && 'local:rw,remote:rw' || 'local:rw,remote:r' }}"
jobs:
real-termux:
@@ -9,12 +9,28 @@ on:
required: false
type: string
default: ""
remote_cache_write:
description: Trusted release qualification may publish the remote cache.
required: false
type: boolean
default: false
secrets:
TURBO_TOKEN:
description: Remote cache token. Only trusted callers pass it.
required: false
permissions:
contents: read
env:
HUSKY: "0"
# A called workflow sees the caller event, so workflow_call is not an event
# name here. Writes when remote_cache_write is set, or on the default branch
# for push, schedule, and manual dispatch. Open pull requests stay empty-token
# and use the local cache only.
TURBO_TOKEN: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && 'local:rw,remote:rw' || 'local:rw' }}"
NODE_OPTIONS: --max-old-space-size=768
jobs:
+16
View File
@@ -7,11 +7,27 @@ on:
required: false
type: string
default: ""
remote_cache_write:
description: Trusted release qualification may publish the remote cache.
required: false
type: boolean
default: false
secrets:
TURBO_TOKEN:
description: Remote cache token. Only trusted callers pass it.
required: false
workflow_dispatch:
permissions:
contents: read
env:
HUSKY: "0"
# A called workflow sees the caller event, so workflow_call is not an event
# name here. Writes when remote_cache_write is set, or on the default branch
# for push, schedule, and manual dispatch. Open pull requests stay empty-token
# and use the local cache only.
TURBO_TOKEN: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && 'local:rw,remote:rw' || 'local:rw' }}"
jobs:
real-web-runtime:
runs-on: ubuntu-latest
+16
View File
@@ -7,11 +7,27 @@ on:
required: false
type: string
default: ""
remote_cache_write:
description: Trusted release qualification may publish the remote cache.
required: false
type: boolean
default: false
secrets:
TURBO_TOKEN:
description: Remote cache token. Only trusted callers pass it.
required: false
workflow_dispatch:
permissions:
contents: read
env:
HUSKY: "0"
# A called workflow sees the caller event, so workflow_call is not an event
# name here. Writes when remote_cache_write is set, or on the default branch
# for push, schedule, and manual dispatch. Open pull requests stay empty-token
# and use the local cache only.
TURBO_TOKEN: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && 'local:rw,remote:rw' || 'local:rw' }}"
jobs:
real-web-source-map:
runs-on: ubuntu-latest
+9
View File
@@ -21,6 +21,12 @@ on:
env:
HUSKY: "0"
# Remote cache stays local when either value is empty.
# Writes only on the default branch for push, schedule, manual dispatch,
# and workflow_call. Pull requests get an empty token and remote read-only mode.
TURBO_TOKEN: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && secrets.TURBO_TOKEN || '' }}"
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && 'local:rw,remote:rw' || 'local:rw,remote:r' }}"
concurrency:
group: release-${{ inputs.release_branch || github.event.pull_request.merge_commit_sha || github.ref_name }}
@@ -301,8 +307,11 @@ jobs:
contents: read
actions: read
uses: ./.github/workflows/ci.yml
secrets:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
with:
source_sha: ${{ needs.merged-release.outputs.sha || needs.release-please.outputs.sha }}
remote_cache_write: true
rehearsal:
name: Rehearse qualified release on a clean runner
+29 -25
View File
@@ -174,31 +174,35 @@ CLI commands use the same workflows.
REA requires Node.js 22.x (>=22.19), 24.x (>=24.11), or 26+, plus npm.
Additional tools and host support depend on the target:
| Target | What REA returns | Requirements and guide |
| ---------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra or IDA; [native analysis](docs/native-investigation.md) |
| Offline ELF layout | Sections, segments, original symbols/relocations and static mitigation candidates | Caller-supplied pwntools on Linux x64; [binary diagnostics](docs/binary-diagnostics.md) |
| Go binaries | Embedded compiler version, modules, replacements and build settings | Built-in static ELF/PE/thin Mach-O inspection; no Go installation required |
| Rust binaries | Embedded cargo-auditable crate names, versions, sources and dependency edges | Built-in static ELF/PE/thin Mach-O inspection; [Rust binaries](docs/rust-binaries.md) |
| WASM artifact | Validation, sections, exact import/export WAT forms and decoded WAT | Caller-supplied WABT 1.0.42; `inspect_wasm_artifact` |
| EVM bytecode | Dispatch selectors, byte offsets, inferred arguments and mutability | Local raw/hex carrier on Linux x64; [offline EVM guide](docs/evm-bytecode.md) |
| SQLite databases | Tables, columns, indexes, views, triggers and selected ordinary-table rows | Local database/WAL snapshot; Node.js 24.x >=24.15 or 26+ with native SQLite limits |
| Recorded Linux crashes | Raw notes, every recorded thread's registers/signals and optional mapping candidates | Caller-supplied pwntools on Linux x64; optional GDB/pwndbg; [recorded crashes](docs/recorded-crashes.md) |
| JavaScript / Electron | Modules, imports, source maps, routes, IPC and native add-on relationships | Node.js and npm; Linux: procps-compatible `ps`; [application analysis](docs/javascript-application-workflows.md) |
| Websites | Page structure, scripts, network observations and requested screenshots | A Chrome-family browser; [browser analysis](docs/browser-observation.md) |
| Saved network captures | Requests, responses, exposed payloads and source locations | HAR or Fiddler Everywhere SAZ; mitmdump on Linux for native mitmproxy; [capture guide](docs/web-network-captures.md) |
| .NET assemblies | Metadata, CIL instructions, declared native dependencies and build comparisons | None (static only); [managed-code guide](docs/managed-code-analysis.md) |
| Android APKs | Manifest declarations, classes, decompiled methods and references | Headless JADX and a full JDK on Linux/macOS/Windows x64; [Android guide](docs/android-analysis.md) |
| Android devices | Devices, packages, processes, logs, dumps, screen captures, and APK/file transfers | Caller-supplied adb (emulator or hardware); [ADB guide](docs/adb-device-analysis.md) |
| JEB projects | Engine-backed project units, artifact digests and type/method pseudo-code | A caller-started JEB client serving MCP, selected with REA_JEB_MCP_URL; [JEB guide](docs/jeb-analysis.md) |
| Android resources | Decoded manifest, string tables, locales and version facts | Caller-supplied Apktool launcher; [resource guide](docs/apktool-resource-analysis.md) |
| Flutter apps | Dart snapshot hash, per-ABI library digests and engine build provenance | None (static APK parsing); [Flutter guide](docs/flutter-analysis.md) |
| Firmware | Regions, extraction results and native-analysis handoffs | Binwalk / Unblob on Linux; [firmware guide](docs/firmware-analysis.md) |
| Recorded packets | Selected fields, repeated values, filters and decode-as rules | Linux: TShark 4.x + prlimit; [capture guide](docs/packet-captures.md) |
| Packet summaries | Endpoints, DNS, TLS SNI, protocol distribution and HTTP requests | Caller-supplied tshark and capinfos (Linux-verified); [pcap guide](docs/pcap-analysis.md) |
| Recorded logic signals | Decoder annotations, sample ranges and diagnostics | Linux: sigrok-cli 0.7.2 + prlimit; [signal recordings](docs/signal-recordings.md) |
| Packages and resources | File inventories, digests, plists, Apple bundle anatomy and extracted resources | [Artifact and JavaScript guide](docs/javascript-artifact-reconstruction.md), [Apple applications](docs/apple-application-analysis.md) |
| Process behavior | Terminal output, interactions, exit and filesystem observations, and run comparisons | Linux/macOS with a native PTY; [process capture](docs/process-capture.md) |
| Target | What REA returns | Requirements and guide |
| ---------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| Desktop installations | Runtime candidates, supporting files, component markers and next probes | Built-in bounded directory/header inspection; [desktop applications](docs/desktop-applications.md) |
| Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra or IDA; [native analysis](docs/native-investigation.md) |
| Offline ELF layout | Sections, segments, original symbols/relocations and static mitigation candidates | Caller-supplied pwntools on Linux x64; [binary diagnostics](docs/binary-diagnostics.md) |
| Go binaries | Embedded compiler version, modules, replacements and build settings | Built-in static ELF/PE/thin Mach-O inspection; no Go installation required |
| Model artifacts | GGUF / safetensors metadata, tensor declarations and derived totals | Built-in header inspection; optional full-file hash; [model files](docs/model-artifacts.md) |
| IL2CPP metadata | Unity global-metadata.dat assembly images, type and method names and index ranges | Built-in static decoding of versions 24, 27, 29, 31 and 39; no Unity required |
| Godot PCK | Archive inventory and extraction, original header/directory facts and selected content identities | Built-in static formats 2, 3 and 4; no Godot required |
| Rust binaries | Embedded cargo-auditable crate names, versions, sources and dependency edges | Built-in static ELF/PE/thin Mach-O inspection; [Rust binaries](docs/rust-binaries.md) |
| WASM artifact | Validation, sections, exact import/export WAT forms and decoded WAT | Caller-supplied WABT 1.0.42; `inspect_wasm_artifact` |
| EVM bytecode | Dispatch selectors, byte offsets, inferred arguments and mutability | Local raw/hex carrier on Linux x64; [offline EVM guide](docs/evm-bytecode.md) |
| SQLite databases | Tables, columns, indexes, views, triggers and selected ordinary-table rows | Local database/WAL snapshot; Node.js 24.x >=24.15 or 26+ with native SQLite limits |
| Recorded Linux crashes | Raw notes, every recorded thread's registers/signals and optional mapping candidates | Caller-supplied pwntools on Linux x64; optional GDB/pwndbg; [recorded crashes](docs/recorded-crashes.md) |
| JavaScript / Electron | Modules, imports, source maps, routes, IPC and native add-on relationships | Node.js and npm; Linux: procps-compatible `ps`; [application analysis](docs/javascript-application-workflows.md) |
| Websites | Page structure, scripts, network observations and requested screenshots | A Chrome-family browser; [browser analysis](docs/browser-observation.md) |
| Saved network captures | Requests, responses, exposed payloads and source locations | HAR or Fiddler Everywhere SAZ; mitmdump on Linux for native mitmproxy; [capture guide](docs/web-network-captures.md) |
| .NET assemblies | Metadata, CIL instructions, declared native dependencies and build comparisons | None (static only); [managed-code guide](docs/managed-code-analysis.md) |
| Android APKs | Manifest declarations, classes, decompiled methods and references | Headless JADX and a full JDK on Linux/macOS/Windows x64; [Android guide](docs/android-analysis.md) |
| Android devices | Devices, packages, processes, logs, dumps, screen captures, and APK/file transfers | Caller-supplied adb (emulator or hardware); [ADB guide](docs/adb-device-analysis.md) |
| JEB projects | Engine-backed project units, artifact digests and type/method pseudo-code | A caller-started JEB client serving MCP, selected with REA_JEB_MCP_URL; [JEB guide](docs/jeb-analysis.md) |
| Android resources | Decoded manifest, string tables, locales and version facts | Caller-supplied Apktool launcher; [resource guide](docs/apktool-resource-analysis.md) |
| Flutter apps | Dart snapshot hash, per-ABI library digests and engine build provenance | None (static APK parsing); [Flutter guide](docs/flutter-analysis.md) |
| Firmware | Regions, extraction results and native-analysis handoffs | Binwalk / Unblob on Linux; [firmware guide](docs/firmware-analysis.md) |
| Recorded packets | Selected fields, repeated values, filters and decode-as rules | Linux: TShark 4.x + prlimit; [capture guide](docs/packet-captures.md) |
| Packet summaries | Endpoints, DNS, TLS SNI, protocol distribution and HTTP requests | Caller-supplied tshark and capinfos (Linux-verified); [pcap guide](docs/pcap-analysis.md) |
| Recorded logic signals | Decoder annotations, sample ranges and diagnostics | Linux: sigrok-cli 0.7.2 + prlimit; [signal recordings](docs/signal-recordings.md) |
| Packages and resources | File inventories, digests, plists, Apple bundle anatomy and extracted resources | [Artifact and JavaScript guide](docs/javascript-artifact-reconstruction.md), [Apple applications](docs/apple-application-analysis.md) |
| Process behavior | Terminal output, interactions, exit and filesystem observations, and run comparisons | Linux/macOS with a native PTY; [process capture](docs/process-capture.md) |
Static JavaScript and .NET inspection read the supplied files without running
the application. Runtime capture runs or interacts with the selected target
+44 -16
View File
@@ -458,6 +458,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
FunctionAnalysisObservation observation = analyzeFunctionObservation(request.params);
JsonObject result = functionObservation(observation.dossier(), observation.limitations());
result.add("relationship_coverage", observation.relationshipCoverage());
if (observation.decompilerFailed()) result.addProperty("cache_policy", "live");
yield result;
}
case "set_address_name", "set_addresses_names" -> {
@@ -1540,12 +1541,23 @@ public final class ReaGhidraBridge extends HeadlessScript {
requireKeys(params, Set.of("procedure"));
Function function = resolveProcedure(requireString(params, "procedure"));
InstructionScan scan = scanInstructions(function, Integer.MAX_VALUE);
DecompileResults decompilation = decompile(function);
DecompileResults decompilation;
String decompilerFailure = null;
try {
decompilation = decompile(function);
} catch (RequestFailure failure) {
// The listing, reference and CFG facts below do not depend on the
// native decompiler. Cancellation still ends the request.
if (!failure.code.equals("decompile_failed")) throw failure;
decompilation = null;
decompilerFailure = failure.getMessage().strip();
}
String pseudocode = decompiledText(decompilation);
JsonObject availability = new JsonObject();
availability.add("pseudocode", facetAvailability(
pseudocode != null,
function.isExternal() ? "Ghidra does not decompile external functions."
decompilerFailure != null ? decompilerFailure
: function.isExternal() ? "Ghidra does not decompile external functions."
: function.getBody().isEmpty() ? "Ghidra has no function body to decompile."
: "Ghidra completed decompilation without returning pseudocode."
));
@@ -1594,9 +1606,16 @@ public final class ReaGhidraBridge extends HeadlessScript {
result.add("basic_blocks", blocks);
result.add(
"native_api",
nativeApiBoundary(function, decompilation)
decompilerFailure == null
? nativeApiBoundary(function, decompilation)
: unavailableNativeApiBoundary(decompilerFailure)
);
result.add(
"native_value_flow",
decompilerFailure == null
? nativeValueFlow(decompilation)
: unavailableNativeValueFlow(decompilerFailure)
);
result.add("native_value_flow", nativeValueFlow(decompilation));
// Successful full queries distinguish collected empty sets from missing facts.
// Availability does not claim that Ghidra resolved every runtime relationship.
for (String facet : List.of("comments", "callers", "callees", "references", "strings_names", "cfg")) {
@@ -1643,6 +1662,12 @@ public final class ReaGhidraBridge extends HeadlessScript {
!decompilation.getErrorMessage().isBlank()) {
limitations.add("Ghidra decompiler diagnostic: " + decompilation.getErrorMessage());
}
if (decompilerFailure != null) {
limitations.add(
decompilerFailure + (decompilerFailure.endsWith(".") ? " " : ". ") +
"Pseudocode, the native API boundary and p-code value flow are unavailable for this procedure; assembly, comments, callers, callees, references, strings, names and basic blocks come from the Ghidra program listing and were still collected."
);
}
result.add("limitations", limitations);
monitor.checkCancelled();
int missingCallers = 0;
@@ -1651,25 +1676,16 @@ public final class ReaGhidraBridge extends HeadlessScript {
if (unrepresentedCaller(reference, callerFunctions)) missingCallers++;
}
return new FunctionAnalysisObservation(result, calls.limitations(),
callRelationshipCoverage(calls, missingCallers));
callRelationshipCoverage(calls, missingCallers), decompilerFailure != null);
}
private JsonObject nativeValueFlow(DecompileResults decompilation) throws Exception {
HighFunction highFunction =
decompilation == null ? null : decompilation.getHighFunction();
if (highFunction == null) {
JsonObject unavailable = new JsonObject();
unavailable.addProperty("available", false);
unavailable.addProperty(
"reason",
return unavailableNativeValueFlow(
"Ghidra has no HighFunction p-code model for this procedure"
);
JsonArray limitations = new JsonArray();
limitations.add(
"No p-code operations or def-use relationships were recovered for this procedure."
);
unavailable.add("limitations", limitations);
return unavailable;
}
List<PcodeOpAST> selected = new ArrayList<>();
@@ -2357,6 +2373,18 @@ public final class ReaGhidraBridge extends HeadlessScript {
return result;
}
private static JsonObject unavailableNativeValueFlow(String reason) {
JsonObject unavailable = new JsonObject();
unavailable.addProperty("available", false);
unavailable.addProperty("reason", reason);
JsonArray limitations = new JsonArray();
limitations.add(
"No p-code operations or def-use relationships were recovered for this procedure."
);
unavailable.add("limitations", limitations);
return unavailable;
}
private static JsonObject unavailableNativeApiBoundary(String reason) {
JsonObject unavailable = new JsonObject();
unavailable.addProperty("available", false);
@@ -4875,7 +4903,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
private record InventoryItem(Address address, String value, JsonObject facts) {}
private record AddressNameRequest(String inputAddress, Address address, String name) {}
private record FunctionEntry(Function function, InventoryItem item) {}
private record FunctionAnalysisObservation(JsonObject dossier, List<String> limitations, JsonObject relationshipCoverage) {}
private record FunctionAnalysisObservation(JsonObject dossier, List<String> limitations, JsonObject relationshipCoverage, boolean decompilerFailed) {}
private record CallBoundaryObservation(List<String> limitations, Integer unrepresentedCalleeCalls, JsonArray unresolvedCalls) {}
private record SwiftStringLiteralDecode(JsonArray literals, JsonArray omissions) {}
private record SwiftLiteralLayout(
+43 -3
View File
@@ -236,6 +236,15 @@ def _name_matches(document, address, name):
return observed == name or (not name and observed is None)
def _bookmark_name(document, address):
getter = getattr(document, "getBookmarkName", None)
if not callable(getter):
raise CapabilityUnavailableError(
"Hopper's public Python API does not expose getBookmarkName"
)
return getter(address)
def _address(document, value=None):
"""Keep explicit hexadecimal coordinates distinct from symbol names."""
if value is None:
@@ -994,15 +1003,46 @@ def _dispatch(method, params):
observed = getter(address)
return observed == comment or (comment == "" and observed is None)
if method == "list_bookmarks":
return [{"address": _hex(item), "name": document.getBookmarkName(item)} for item in document.getBookmarks()]
return [{"address": _hex(item), "name": _bookmark_name(document, item)} for item in document.getBookmarks()]
if method == "set_bookmark":
address = _address(document, params.get("address"))
_segment(document, address)
name = params.get("name")
if name is not None:
_api_text(name, "Bookmark name")
document.setBookmarkAtAddress(address, name)
return document.hasBookmarkAtAddress(address)
has_bookmark = getattr(document, "hasBookmarkAtAddress", None)
if not callable(has_bookmark):
raise CapabilityUnavailableError(
"Hopper's public Python API does not expose hasBookmarkAtAddress"
)
exists = has_bookmark(address)
if name is None and exists:
# Omission means preserve the existing bookmark and its name.
return True
if not callable(getattr(document, "getBookmarkName", None)):
raise CapabilityUnavailableError(
"Hopper's public Python API does not expose getBookmarkName"
)
if name == "" and exists:
rename = getattr(document, "renameBookmarkAtAddress", None)
if not callable(rename):
raise CapabilityUnavailableError(
"Hopper's public Python API does not expose renameBookmarkAtAddress"
)
rename(address, name)
else:
setter = getattr(document, "setBookmarkAtAddress", None)
if not callable(setter):
raise CapabilityUnavailableError(
"Hopper's public Python API does not expose setBookmarkAtAddress"
)
setter(address, name)
if not has_bookmark(address):
return False
observed = _bookmark_name(document, address)
if name is None:
return observed is None or observed == ""
return observed == name or (name == "" and observed is None)
if method == "unset_bookmark":
address = _address(document, params.get("address"))
# Permit removing a legacy orphan bookmark, but do not report success
+1 -1
View File
@@ -95,7 +95,7 @@ def main():
try:
encoded = json.dumps(reply, ensure_ascii=True, allow_nan=False).encode("utf-8")
if len(encoded) > OUTPUT_BYTES:
encoded = json.dumps({"ok": False, "reason": "output-limit", "message": "Complete debugger context exceeds64 MiB reply budget."}).encode("utf-8")
encoded = json.dumps({"ok": False, "reason": "output-limit", "message": "Complete debugger context exceeds the 64 MiB reply budget."}).encode("utf-8")
descriptor = os.open(request["reply_path"], os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
with os.fdopen(descriptor, "wb") as handle:
handle.write(encoded)
+11 -2
View File
@@ -14,7 +14,7 @@ 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"):
def inspect(self, failure=None, connection="core", symbols=None, architecture="x86_64-little-endian", objfile="recorded-executable"):
commands, reads, queries = [], [], []
state = {"executable": None, "symbols": None, "connection": None}
gdb = types.ModuleType("gdb")
@@ -50,7 +50,7 @@ class CoreContextTests(unittest.TestCase):
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")]
return [types.SimpleNamespace(start=4096, end=8192, offset=0, flags=5, objfile=objfile)]
pwndbg.aglib.vmmap.get = maps
modules = {module.__name__: module for module in [
@@ -104,6 +104,15 @@ class CoreContextTests(unittest.TestCase):
self.assertEqual(reads, [])
self.assertEqual(queries, [])
def test_output_limit_message_separates_the_words_and_names_the_limit(self):
result, _, reads, queries = self.inspect(objfile="m" * (64 * 1024 * 1024))
self.assertFalse(result["ok"])
self.assertEqual(result["reason"], "output-limit")
self.assertNotIn("exceeds64", result["message"])
self.assertEqual(result["message"], "Complete debugger context exceeds the 64 MiB reply budget.")
self.assertEqual(reads, [])
self.assertEqual(queries, ["maps"])
def test_wrong_connection_or_remaining_symbols_never_queries_mappings(self):
for options in [{"connection": "native"}, {"symbols": "unexpected-symbols"}]:
with self.subTest(options=options):
+4
View File
@@ -29,6 +29,8 @@ export default defineConfig({
items: [
{ text: "Native binaries", link: "/native-investigation" },
{ text: "Go build metadata", link: "/go-binaries" },
{ text: "IL2CPP metadata", link: "/il2cpp-metadata" },
{ text: "Model artifacts", link: "/model-artifacts" },
{ text: "Rust dependencies", link: "/rust-binaries" },
{
text: "JavaScript and Electron",
@@ -43,12 +45,14 @@ export default defineConfig({
text: "Web network captures",
link: "/web-network-captures",
},
{ text: "Agent environments", link: "/agent-environments" },
{ text: "Electron observation", link: "/electron-observation" },
{ text: "Electron fuses", link: "/electron-fuses" },
{ text: "Process capture", link: "/process-capture" },
{ text: ".NET assemblies", link: "/managed-code-analysis" },
{ text: "Android applications", link: "/android-analysis" },
{ text: "Apple applications", link: "/apple-application-analysis" },
{ text: "Desktop installations", link: "/desktop-applications" },
{ text: "Firmware", link: "/firmware-analysis" },
{ text: "SQLite databases", link: "/sqlite-databases" },
{ text: "Packet captures", link: "/packet-captures" },
+426
View File
@@ -0,0 +1,426 @@
# Agent environments from recorded captures
Use `rea environment-serve` to serve an environment manifest as an agent
environment: an MCP server whose tools answer from the records of one retained
web network capture, plus the environment card the agentenv framework reads to
discover it. Nothing is fetched from the recorded application; every answer is
retained Evidence. `rea environment-export` writes the same pair as a bundle
folder `agent-env run` builds and runs; see [Export a bundle](#export-a-bundle).
```sh
rea inspect-web-network-capture /absolute/session.har har --format json > capture.json
rea inspect-analysis-view view.json --format json > manifest.json
rea environment-serve manifest.json --evidence capture.json --port 8765
```
The first command inspects the capture; the second projects the
[environment manifest](web-network-captures.md#environment-manifest) view from
it, where `view.json` wraps the capture Evidence as the inline source:
```json
{
"source": { "kind": "inline", "evidence": { "evidence_id": "ev_…" } },
"view": {
"kind": "environment-manifest",
"template_rules": ["after-uid-literal", "opaque-token", "sibling-variance"]
}
}
```
The third command serves that manifest. Both served files are complete REA
Evidence JSON as the commands write it with `--format json`; the `evidence`
member of `view.json` is the whole of `capture.json`.
## From a browser scenario
The capture can also come from REA itself: a
[browser scenario](browser-scenario-contract.md) records a scripted session
in a browser REA launches, and its Evidence is a manifest parent like a HAR
inspection. Select the `network` event family and response bodies. A replayed
reply carries up to 256 KiB of a recorded body, but the scenario keeps at most
`max_network_body_bytes` of each body (64 KiB by default), and only within its
allocation budgets: base64 is charged about 11 bytes per body byte, and
redaction more the shorter a declared secret is (about 35 bytes per body byte
for a 12-character `admin_password`). A body over
`max_network_body_allocation_bytes` (1 MiB by default) is kept as `unavailable`
with that reason; one over `max_event_allocation_bytes` (4 MiB) or
`max_total_event_allocation_bytes` (16 MiB) loses its whole content event,
headers included, which the capture lists among its omissions. Either way its
tool replays no body. The example raises all four so that 256 KiB bodies are
kept when the declared secret has at least 12 characters:
```json
{
"browser": { "mode": "launch", "executable_path": "/usr/bin/chromium" },
"start_url": { "url": "http://127.0.0.1:5230/auth", "query": [] },
"secrets": [
{ "secret_id": "admin_password", "environment_variable": "APP_PASSWORD" }
],
"actions": [
{
"step_id": "user",
"action": "fill",
"locator": { "kind": "css", "selector": "input[name=username]" },
"value": { "source": "literal", "value": "admin" }
},
{
"step_id": "password",
"action": "fill",
"locator": { "kind": "css", "selector": "input[type=password]" },
"value": { "source": "secret", "secret_id": "admin_password" }
},
{
"step_id": "sign-in",
"action": "press",
"locator": { "kind": "css", "selector": "input[type=password]" },
"key": "Enter"
},
{
"step_id": "first-memo",
"action": "goto",
"destination": { "url": "http://127.0.0.1:5230/m/1", "query": [] },
"wait_until": "load"
}
],
"capture": {
"events": ["network"],
"network": {
"request_body": true,
"response_body": true,
"header_values": false
},
"limits": {
"max_network_body_bytes": 262144,
"max_network_body_allocation_bytes": 12582912,
"max_event_allocation_bytes": 12582912,
"max_total_event_allocation_bytes": 67108864
}
}
}
```
```sh
APP_PASSWORD=… rea capture-browser-scenario scenario.json --format json > capture.json
rea inspect-analysis-view view.json --format json > manifest.json # view.json wraps capture.json as before
rea environment-serve manifest.json --evidence capture.json --port 8765
```
Each network transaction becomes one record, in request order, and the
record's ordinal is its zero-based position; a transaction whose URL carried a
redacted secret is left unrepresented rather than templated, and one the
capture cannot attribute to a single request and response is left
unrepresented too. Tools are chosen by response media type, so a scenario that
selected neither response bodies nor header values is refused. The browser
scenario redacts credential headers and the secrets it declares; values the
application returns in response bodies, such as session tokens, are kept, and
the replayed body is the bytes the browser exposes for each response, with any
declared secret replaced by its redaction marker (a body that redaction had to
empty replays no body).
## What a manifest is
An environment manifest is a projection of one application's recorded request
lines into a tool surface: one tool per method and path template on the
primary origin, with inferred path parameters, observed query parameter
names, value-free body shapes and pointers to the parent records each tool
cites. It carries no bodies and no headers. The manifest's
`parent_evidence_id` names the capture Evidence it was projected from; the
serve command refuses a manifest whose parent is not the supplied `--evidence`
file with an `invalid_request` error naming both identifiers, so a manifest can
never be served from records it did not cite.
The MCP catalog and environment card use a 1 KiB UTF-8 budget for each
captured display sample. Observation, body-key and cited-record lists show
whole values with omission counts; long method, path and query-name displays
show a marked prefix. Complete values remain in manifest Evidence. Argument
names longer than 64 characters use collision-safe `path_<n>` or `query_<n>` aliases; replay maps
those aliases to the complete captured names.
Discovery is admitted as a complete catalog under a 1 MiB serialization
reservation before the listener binds. Reservation charges up to six bytes per
UTF-16 code unit for JSON escaping/UTF-8 expansion, plus schema overhead;
a catalog may therefore be refused even when its compact JSON is smaller.
This was calibrated with 1500 query fields and eight concurrent SDK discovery
requests (183,798-byte card, 507.27 MiB sampled process-family RSS). Over-capacity
catalogs return `resource_constraint`, retain complete input Evidence, and require
a smaller capture or manifest. Fields and tools are never silently omitted.
## What replay means and does not mean
Each MCP tool call selects one of the records its manifest tool cites and
returns that record's recorded response. Selection compares the supplied path
parameters against the record's path segments at the parameter indexes, then
the supplied query values against the record's query string, and keeps the
record with the most matches; ties keep manifest order. The result reports
where the answer came from:
```json
{
"status": 200,
"content_type": "application/json",
"body": { "id": 2, "login": "probe" },
"replay": {
"record_ordinal": 5,
"evidence_id": "ev_…",
"exact_match": true,
"recorded_path": "/api/users/2",
"recorded_query": null,
"recorded_line_truncated": false,
"body_recorded": true,
"body_encoding": "utf-8",
"truncated": false
}
}
```
`exact_match` is true when every supplied path parameter and query value
equals the recorded one; it says nothing about parameters the caller omitted.
Recorded query parsing runs only when supplied query arguments affect selection.
A path value matches a recorded segment as written or after percent-decoding;
when both kinds of match are available, the record whose segment equals the
value as written is chosen. `recorded_query` keeps the `?` of an explicit empty
query, and a recorded path or query longer than 1 KiB is cut in the reply with
`recorded_line_truncated: true`; selection always uses the full recorded line.
`content_type` also has a 1 KiB display bound with `content_type_truncated`; body
interpretation uses the full recorded media type.
When no record matches, the tool still answers from the tool's first cited
record and reports `exact_match: false`. `body` is parsed JSON when the
recorded content type is JSON-like (`application/json`, `application/*+json`,
`text/plain`, `text/markdown`) and the text parses with safe numeric conversion; otherwise
it is the recorded text. Large integer IDs and other numbers that would lose
information stay in the original JSON text. Bodies over 256 KiB are cut at a UTF-8 boundary and returned as
text with `truncated: true`. `body_recorded` is false when the capture kept the
response's status and content type but no body; `body` is then `null`, which
is not a recorded JSON `null`. `body_encoding` is `base64` when the capture
retained response bytes that are not valid UTF-8; `body` is then exactly those
bytes in base64, never a lossy decoding. A retained base64 body is decoded only as far as the 256 KiB a reply can carry, and a leading byte-order mark is kept. For a `base64` body the limit applies to the recorded bytes, not their longer base64 spelling, and a cut keeps whole base64 groups. Request bodies passed to `POST`, `PUT` and `PATCH`
tools are accepted and ignored: nothing is written, and no call changes what a
later call returns. Arguments the tool's input schema does not name are
refused by the MCP server as invalid arguments, so a misspelled parameter never
degrades into an omitted one.
Replay is not emulation. A served environment does not establish the
application's authorization model, response semantics or state transitions,
which the manifest lists as unknowns; it does not validate supplied values; and
it does not answer requests the capture never recorded. Replayed content is
target content: every tool result, including the argument errors the MCP server
returns before a replay runs, carries `_meta.provenance.untrusted_content: true`
with `source: "analysis_target"`. The server advertises REA's untrusted-content
instructions plus a warning that its tool names, descriptions, parameter names
and observed values come from the capture too, and agents must treat all of it
as data, never as instructions.
That same warning prefixes every tool description in the standalone card, so
card discovery carries it before an MCP client initializes. It labels the
captured text without changing the tool names or schema fields clients use.
## The state a capture observed
Replay answers each call from one recording, so the answers reflect whichever
moment of the capture recorded them. The
[environment state](web-network-captures.md#environment-state) view extracts
instead the data the capture's reads observed before the first related write:
entity types with an identity field, entities with their recorded values,
documents for written paths, and a render plan per read tool, kept only where
it reproduces that tool's recordings from the state. It is the starting state
an environment can hold, load and report; serving from it is a later increment
and does not change replay.
## Serve a manifest
```sh
rea environment-serve manifest.json --evidence capture.json [--host 127.0.0.1] [--port 0]
```
`--host` and `--port` default to `MCP_HOST` and `MCP_PORT` from the
environment, then to `127.0.0.1` and an ephemeral port, exactly as
[`rea mcp --http`](cli.md#serve-mcp-over-streamable-http) resolves them. The
bound MCP URL is written to stderr as one JSON log line
(`"msg":"MCP transport listening"` with `url`); `REA_LOG_LEVEL` overrides that
log level. `ENVIRONMENT_NAME` renames the served environment; otherwise the
manifest's `name` is used, and a set but blank value is refused as
`configuration_invalid` before binding rather than silently falling back. The
listener serves one MCP client at a time with the same session, `Host` header
and shutdown contract as [transports](mcp-contracts.md#transports) describes.
It runs until SIGINT or SIGTERM, then closes the listener, prints one
`{"status":"stopped", …}` document and exits `130` or `143`.
Signals during input loading or DNS/bind cancel the owning reader/listener before
a listening announcement;
that path returns a structured `cancelled` result instead of a stopped-listener
document, with the same signal exit status.
Three routes are served:
| Route | Answer |
| --------------------------------- | ---------------------------------------------------------------------- |
| `POST /mcp` | The MCP server: one tool per manifest tool, replaying retained records |
| `GET /.well-known/agent-env.json` | The environment card |
| `POST /agentenv` | JSON-RPC `-32601 method not found: <method>` for every method |
Numeric JSON-RPC IDs outside JavaScript's safe range or whose precision would
be lost are refused as invalid requests with a null ID. They are never echoed
as a different number.
The data plane at `/agentenv` is advertised by the card but carries no
operations in this release; the error names the requested method so a caller
can see that the method, not the transport, is unsupported. Its request body is
read within the same 4 MiB bound the MCP endpoint applies: a larger body is
answered `413` with a JSON-RPC `-32000` error before any of it is parsed, and a
body that is not JSON is answered `400` with `-32700`. A notification (no `id`)
gets `202` and no body, a batch gets one reply per request in it, and an empty
batch, a batch of more than 100 messages, or a message that is not a JSON-RPC
request (including an `id` that is not a string, number or null, or `params`
that are not an object or array) gets `-32600 invalid request`.
## The environment card
The card is the discovery document the agentenv framework reads before
connecting to `/mcp`:
```json
{
"name": "grafana-example",
"protocolVersion": "1.0",
"url": "/agentenv",
"preferredTransport": "JSONRPC",
"additionalInterfaces": [{ "url": "/mcp", "transport": "mcp" }],
"capabilities": {
"extensions": null,
"tools": [
{
"name": "get_users_by_id",
"description": "GET /api/users/{numeric}; replays retained records [5, 6]; evidence ev_…",
"inputSchema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Path segment 2 (numeric); observed: 2, 3"
}
},
"required": ["id"],
"additionalProperties": false
}
}
],
"operations": []
},
"children_environments": null
}
```
`capabilities.tools` lists the same names, descriptions and input schemas that
`tools/list` advertises over MCP. Path parameters are required strings whose
description names the segment index, the templating rule and the observed
values (sampled within the list budget above; the manifest keeps them all);
query parameter names are optional strings; write methods accept an
optional `body` object described by the recorded top-level key types. Each
input keeps its own argument: a query name equal to a path parameter's name is
advertised as `query_<name>`, a query name longer than 64 characters as
`query_<n>` (its position) with the captured name sampled in its description,
and the write body as `request_body` when a query parameter is named `body`. Every
schema closes with `additionalProperties: false`, a key the echo example's
schema does not carry.
`extensions`, `operations` and `children_environments` are fixed to `null`,
`[]` and `null`: a replay environment declares no extensions, no data-plane
operations and no children.
## Export a bundle
`rea environment-export` writes the same pair as a bundle folder the agentenv
framework runs directly, shaped like its own echo example:
```sh
rea environment-export manifest.json --evidence capture.json ./grafana-example --json
agent-env run ./grafana-example
```
```text
grafana-example/
README.md provenance, replay limits, run command, rights note
envs/grafana-example/Dockerfile pinned image: node:24.18.0-bookworm-slim + rea-agents@<this version>
envs/grafana-example/env.toml environment_name = "grafana-example"
envs/grafana-example/manifest.json byte-exact copy of manifest.json
envs/grafana-example/evidence.json byte-exact copy of capture.json
artifacts/check_grafana-example/verify.py the replay verifier
tasks/smoke.json deploy_env (local sandbox), then env_outcome_verifier
```
The command reads each file once, after checking that reading and parsing the
whole file, including sealing traversal, fits the process's live heap headroom (a file that does not is
refused as a `resource_constraint` before it is read), then authenticates and cross-checks the
pair as `environment-serve` does, so a manifest projected from another capture
is refused with the same `invalid_request` before anything is written, and the
bytes it copies are the bytes it authenticated. The bundle directory must be
absent or empty; an occupied directory is refused and nothing in it changes.
The complete tool catalog must also fit the server's advertised catalog budget
before any files are written. Privately parsed JSON is sealed once so authentication
and replay share immutable response trees rather than copying the capture repeatedly.
`--name` replaces the manifest's portable kebab-case name as the env folder and env id
(Windows device names such as `con` and `lpt1` are refused);
`--package-tarball <path>` copies a packed `rea-agents` tarball into the env
folder and makes the Dockerfile install it instead of the registry package and
remove it in the same layer, which is how a checkout rather than a release is
run. The command prints the
written files with their sizes and the pinned package source.
Export uses the shared output-tree owner to check directory identities around
exclusive creates, verify written bytes, and reject unowned entries before
reporting success. It does not delete an inspectable partial folder on failure.
Node's portable pathname APIs leave a syscall-boundary race, so the output's
parent directories must be trusted. On POSIX output files use mode `0600`;
Windows inherits ACLs and REA does not establish owner-only access there. Choose
an already private Windows destination when captured content needs it.
The Dockerfile sets `MCP_HOST=0.0.0.0` and `MCP_PORT=18765`, the port the
framework maps for an MCP server env; the framework's own deploy supplies
`MCP_HOST`, `MCP_PORT` and `ENVIRONMENT_NAME`, so the served card carries the
env's name. It installs Debian's `python3` because the framework's local
sandbox probes a container's readiness with `python3` inside it, which the slim
Node image lacks. It copies the two inputs owned by the image's non-root `node`
user, so a private host umask cannot leave them unreadable, runs as that user and starts
`rea environment-serve /env/manifest.json --evidence /env/evidence.json`. The
`env.toml` names the environment because the framework otherwise reads the
name from Python sources the image does not have.
`verify.py` is the framework's `async def verify(mcp_url)` shape over its
Python MCP client: it lists the tools and checks the count equals the
manifest's, calls the first `GET` tool without path parameters with no
arguments and checks the call did not fail and its replayed `status` equals the
recorded status of that tool's first cited record (an unknown recorded status
stays unknown; it is not borrowed from another record), and returns one
`replay` result whose description
reports both checks. A manifest with no such tool yields a verifier that checks
the count only and says so. `tasks/smoke.json` deploys the env on the local
sandbox and runs that verifier against the env's MCP endpoint; the first run
also builds the framework's own infrastructure, and the run tears everything
down when it ends.
The README written into the bundle records the capture artifact's SHA-256, the
capture and manifest Evidence ids, the manifest view digest, the tool count and
the package source, and states that the recorded content belongs to the
captured application and must not be published without the rights to it.
## Compatibility verification
`npm run verify:agentenv:environment` is the hosted `real-agentenv` lane
described in [testing](testing.md#exported-environment-bundles). It projects
the Grafana-shaped source-owned capture through the built CLI, packs the
checkout, exports a bundle with `--package-tarball`, runs it with the pinned
`agentenv-framework` release on the runner's Docker and requires the smoke task
to pass with no container left behind other than the framework's own
image-registry helper, which the receipt reports. It proves that one exported bundle runs
on one framework release; it does not claim any hosted platform or other
framework versions.
## Resource and lifecycle boundaries
Both Evidence files are read once at startup through the bounded JSON input
reader and authenticated as Evidence before the listener binds; a file that is
not Evidence, a manifest of another view kind, a capture of another format, or
a manifest projected from a different capture is refused before any port is
opened. Because authentication covers the capture's records, a manifest whose
parent check passes cites only records the capture retains. The server keeps
only the cited records' request lines and response text in memory. No outbound
network request is made, no process is launched and nothing is written to
disk. A listener that fails after binding is logged and ends the command with
a `resource_constraint` error and exit `1` instead of serving nothing.
+28 -7
View File
@@ -180,8 +180,21 @@ rea trace-dylib-resolution MyApp.app --root Contents/MacOS/MyApp --architecture
Load commands are parsed in TypeScript from Mach-O and FAT headers, including
the `dylib_use_command` encoding newer linkers emit for flags such as delayed
initialization. Nothing is executed and no Apple tool is required, so the tool
also works off macOS.
initialization, and `LC_LAZY_LOAD_DYLIB_INFO` (`0x3a`). That command stores its
install name in a linkedit payload rather than in the load command itself.
Its flag and chain-start image offsets must lie in the slice VM range, which
is dyld's one-page floor extended by every segment except `__LINKEDIT`,
measured from the `__TEXT` vmaddr. Payload strings must start after the 24-byte
header. The load-path NUL must occur before the payload's final byte, matching
dyld's scan. Distinct payload bytes and payload-range lookups stay within the 16 MiB
limit, and a file range already read is reused. String scanning and UTF-8
checks count every reference, including repeats and overlaps, and stop at that
same aggregate. A slice retains at most 1024 of these commands; further copies are
unsupported instead of becoming one traced edge each. Symbol references,
including repeats, stop at 65536 per slice. A larger table is unsupported
instead of caching one string per offset.
Nothing is executed and no Apple tool is required, so the tool also works off
macOS.
Resolution follows dyld:
@@ -215,15 +228,23 @@ root supplies. Every edge below it has `loader_conditional: true`, and a
request that reuses it by install name is `conditional` too. Findings on those
edges say that they apply only if the conditional image loads.
Absolute install names such as `/usr/lib/libSystem.B.dylib` are
`outside-target`. On macOS 11 and later most of them live in the dyld shared
cache rather than on disk, so REA does not check them against the host.
Absolute install names that name a path beneath the analyzed root are checked
within that root, with symlinks and `..` resolved by the same bounded tree
resolver. Absolute paths outside the root, such as
`/usr/lib/libSystem.B.dylib`, are `outside-target`; on macOS 11 and later most
system libraries live in the dyld shared cache rather than on disk, so REA does
not check them against the host. Mach-O path strings are not converted from
`file:` URLs or looked up through unrelated host paths.
`findings` are derived, not observed:
- `required-load-unresolved`, `weak-load-unresolved`, and `lazy-load-unresolved`.
`LC_LAZY_LOAD_DYLIB` dependencies are resolved but not traversed, because dyld
loads them on first use; an unresolved one is not a launch failure.
`LC_LAZY_LOAD_DYLIB` and `LC_LAZY_LOAD_DYLIB_INFO` dependencies are resolved
but not traversed, because dyld loads them on first use; an unresolved one is
not a launch failure. `LC_LAZY_LOAD_DYLIB_INFO` has no compatibility version,
so those fields are null. Its may-be-missing flag is reported as `weak`, and
an unresolved dependency with that flag is not a first-use failure: dyld
continues if the image is absent.
- `earlier-rpath-candidate-absent`: a compatible Mach-O placed at an earlier
modeled search path could take precedence, subject to unmodeled search inputs
and code-signing library validation. These findings do not establish which
+1 -1
View File
@@ -34,7 +34,7 @@ graph TD
GHIDRA["src/ghidra/<br/>Ghidra discovery, profile & function analysis<br/>snapshot, Unix/Windows transport, bounded lifecycle"]
IDA["src/ida/<br/>Upstream MCP contract adaptation<br/>live GUI binding or owned headless database"]
IDA_MCP["External ida-pro-mcp<br/>GUI proxy or database supervisor<br/>upstream installation and engine lifecycle"]
AUX["src/artifacts/ + src/native/<br/>artifact inventory and extraction<br/>format readers and native capabilities"]
AUX["src/artifacts/ + src/native/<br/>artifact inventory, bounded directory triage and extraction<br/>format readers and native capabilities"]
BROWSER["src/browser/<br/>CDP / Playwright capture<br/>captured scripts and native module resolution<br/>execution/: coverage, listener and source attribution"]
JS_CODEC["src/javascript/sourceMaps/<br/>pinned upstream map codec<br/>owned heap-limited Node process, complete point evidence"]
INSPECTOR["src/inspector/<br/>passive V8 Inspector discovery and capture<br/>script and target locations"]
+37 -2
View File
@@ -19,8 +19,24 @@ Inspect native SAZ or HAR 1.2 offline with REA, or connect Everywhere's separate
- `analyze_web_bundle` / `rea analyze-web-bundle` parses selected script artifacts without execution and derives chunk edges, route and endpoint candidates, vendor fingerprints, static WebMCP declarations, and optionally source-map/original-source evidence.
- `observe_web_session` / `rea observe-web-session` arms an observation window of the requested duration for an external user action and records ordered reload, SPA navigation, redirect, failure, lifecycle, and target-termination metadata.
- `discover_webmcp_tools` / `rea discover-webmcp-tools` uses the experimental CDP WebMCP domain to return every in-scope registration and its complete observed `input_schema` declaration and canonical `input_schema_sha256` digest inline. Declarations are untrusted JSON data, including declared types, required fields, enums, examples and reference URLs. REA does not resolve schema references. These fields replace `input_schema_shape`. Registrations with the same name and URL in distinct observed frames retain separate identities. `tool_key` includes the observed frame ID; it is not a stable identity across navigation or browser sessions. Same-frame registration updates replace that owner only, and removal leaves other owners intact. Declared `readOnly`, `untrustedContent`, `consequential`, and `autosubmit` annotation hints are reported per registration: `true`/`false` are declared values, `null` means the declaration did not provide the hint in that capture, and a missing `consequential` key means the hint was not recorded, either in a historical capture or because the observed annotation was invalid. Consult discovery completeness and exclusions to distinguish these cases. Malformed annotation values retain the registration with incomplete coverage and an `invalid_protocol_value` exclusion. Other malformed protocol payloads can fail discovery explicitly. REA never exposes `WebMCP.invokeTool`.
- `compare_web_captures` / `rea compare-web-captures` compares passive captures or exact-step-aligned browser scenarios. Scenario results commit reproducible literal normalization and expose alignment failures plus artifact-level action, screenshot, DOM, accessibility, URL, history, storage, and event differences. Missing or truncated evidence is never treated as equivalence.
For `analyze_web_bundle`, each `webmcp_declarations` entry's
`schema_property_names` is a source-derived projection of statically known own
property keys, not schema validation. `schema_property_names_coverage` reports
how complete that projection is: `complete` means a literal properties object
was fully enumerated (including an empty literal); `partial` means a literal
object was available but some computed or spread membership was unresolved,
and the name array retains keys that were known; `unknown` means the schema or
properties owner could not be enumerated as an object literal, including
explicit non-object values; `not_present` means no effective schema or own
`properties` member was present after the `inputSchema ?? input_schema` alias
selection. `not_present` describes this projection only: it does not validate a
schema or rule out properties expressed through other schema constructs. Older
observations may omit the coverage field; treat omission as `unknown` rather
than inferring completeness from the array.
Passive DOM comparison checks complete node inventories and complete frame
parent/child structure independently. Frame IDs and sibling enumeration order
are capture-local and do not establish a change; duplicate IDs, missing parents,
@@ -201,6 +217,11 @@ rea inspect-web-page http://127.0.0.1:9222 TARGET_ID \
--json
```
Passive observation honors the requested duration using cancellable waits within
the runtime's timer range. Long windows stay pending across successive waits;
caller cancellation, target termination or leaving the allowed origins ends
collection early. `window_elapsed` identifies completion of the requested wait.
Static bundle analysis and a user-driven observation window are separate operations:
```bash
@@ -283,6 +304,20 @@ Call `list_browser_targets` first because target IDs are browser-instance-specif
REA establishes a main-frame origin boundary before enabling Runtime, Debugger, or Network observation, rechecks it before document capture, and validates it again afterward. If the main frame navigates during final capture, REA discards the mixed result and returns `target_changed`.
The web-session timeline uses CDP monotonic seconds where the event producer
provides a comparable timestamp; absent or invalid timestamps are `null` rather
than a synthetic zero. Events buffered while REA samples the window boundary are
retained only when their timestamp places them after that boundary; older events
are excluded. A buffered event without a comparable timestamp may remain as
contextual evidence with `timestamp: null`, accompanied by a limitation stating
that it does not establish activity in the selected window. Main-frame scope
enforcement still applies to contextual navigation events. Network redirect
events retain their paired prior-hop response context when the timestamped
next-request event falls inside the window. The pre-arm timeline buffer is bounded
by original CDP message bytes. If clock sampling completes after that budget is
exhausted, the operation returns `payload_limit` instead of a partial window.
Cancellation and clock-request failures retain their own outcomes.
## Data minimization
The Link projection parses repeated CDP header field lines independently and
@@ -326,8 +361,8 @@ REA retains local observation data and removes only URL userinfo credentials, ex
WebSocket stream inventories and connection counts likewise require complete
WebSocket coverage. Redirect resource types use only shared known metadata:
an omitted type leaves equality unknown rather than proving a modification.
- Console observations with a stack source retain call type, argument types, timestamp, and source location. When console text capture is selected, already-delivered primitive values are retained verbatim; objects, getters, and remote properties are never expanded.
- WebSocket observations retain direction, opcode, and payload byte length. When shape capture is selected, text frames are classified as text or complete value-free JSON shape; binary bytes, hashes, prefixes, and raw frames are never retained.
- Console observations with a stack source retain call type, argument types, the CDP `Runtime.Timestamp` in milliseconds since Unix epoch, and source location. An absent or invalid timestamp is `null` and makes `console_events` incomplete; an observed zero remains zero. This epoch-millisecond clock is separate from the monotonic-second timestamps in `observe-web-session`. When console text capture is selected, already-delivered primitive values are retained verbatim; objects, getters, and remote properties are never expanded.
- WebSocket observations retain direction, opcode, and payload byte length. A missing or malformed CDP opcode is returned as `null`, with opcode-dependent payload byte length and shape also `null`, and marks `websocket_frames` incomplete. Missing or wrong-typed payload data is not treated as empty; its byte length is `null`, and a text payload shape is unknown. Numeric opcode `0` and an observed empty payload remain distinct from missing data. Opcode is nullable in the public inspection schema, so clients must handle unknown protocol values. When shape capture is selected, text messages are classified as text or complete value-free JSON shape; binary bytes, hashes, prefixes, and raw payloads are never retained.
- Storage observations always redact values. Key names, IndexedDB names, and cache names require `include_storage_keys`; stable content fingerprints require the additional `include_storage_fingerprints` selection. Cookie fingerprints cover cookies applicable to the current main-frame URL, including its path, rather than every cookie path on that origin. Other storage remains scoped to the origin. Cache fingerprints hash all decoded response bytes, including bodies above 64 KiB, subject to the [64 MiB per-message CDP limit](#request-boundary). Missing or undecodable cache bodies and partial IndexedDB remote objects make fingerprint coverage incomplete, so identical observations remain `unknown`.
- Unavailable or malformed storage inventories mark `storage_keys` unavailable, even without fingerprints. Comparisons suppress inferred key additions and removals while preserving modifications proven by complete fingerprints on both sides. Previously exported captures are not retroactively corrected; recapture them to obtain these coverage markers.
- Script metadata is included only when CDP supplies a URL on an allowed origin. Stable keys exclude transient CDP script IDs, and exact transient raw URLs are used only during script/resource reconciliation. URL-less scripts are excluded because their origin cannot be established. When CDP supplies an execution-context association, the accepted script retains its authorized frame ID for later attribution. Script metadata admission bounds retained identity and source-map strings to 8 MiB and 50,000 records. When a source-map URL cannot fit, the script identity remains and source-map coverage reports `resource_budget_exhausted`; rejected script observations are counted without retaining their IDs. Source content is omitted unless explicitly requested and is returned inline as a self-verifying artifact with its SHA-256 digest.
+5
View File
@@ -107,6 +107,11 @@ Through MCP, pass the same object as the `capture_browser_scenario` arguments.
The final step's DOM and accessibility artifacts retain the page state at that
capture time inline. REA still launches and cleans up the browser profile.
Action `timeout_ms` and `wait_for_timeout.duration_ms` accept integers from 1
through 2,147,483,647 milliseconds, matching the underlying timer representation.
Larger values receive an input error before browser launch. Omit `timeout_ms`
to keep an action pending until completion or request cancellation.
The click's `timeout_ms` covers the click action. A non-navigating `fetch` or
delayed render can finish later, so use `wait_for` to observe a page-specific
ready condition before final capture. A page that updates synchronously can
+129 -3
View File
@@ -30,6 +30,13 @@ jq -c '{source: {kind: "inline", evidence: .}, view: {kind: "summary"}}' app-evi
rea inspect-analysis-view app-view.json
```
The request can also name the saved file instead of embedding it:
`{"source": {"kind": "evidence-file", "path": "app-evidence.json"}, "view": {"kind": "summary"}}`.
The CLI resolves a relative path against the working directory; MCP clients
pass an absolute path. REA reads and authenticates the file, then projects it
like retained Evidence, so a large file is bounded by the file reader rather
than charged as inline input.
For example, a 334 MB Obsidian application Evidence file yields a summary view
of about 10 KB. Replace the view with
`{"kind": "page", "collection": "modules", "offset": 0, "limit": 32}` for a
@@ -58,8 +65,10 @@ assembly-wide inventory, so the output can still be large.
Choose the workflow from the artifact's contents rather than its `.exe` or
`.dll` extension. The managed parser requires PE/CLI metadata; it does not
unpack .NET single-file hosts or decode IL2CPP metadata. NativeAOT method bodies
require native analysis. See the [managed-code guide](managed-code-analysis.md)
unpack .NET single-file hosts or decode IL2CPP. For the image, type and method
names in a Unity `global-metadata.dat`, use
[IL2CPP metadata](il2cpp-metadata.md). NativeAOT method bodies require native
analysis. See the [managed-code guide](managed-code-analysis.md)
for supported deployment forms, selection semantics, and coverage limits.
## SQLite snapshots
@@ -83,6 +92,47 @@ The shared CLI/MCP workflow reports compiler version, modules, replacements,
build settings, original bytes and SHA-256. See [Go binaries](go-binaries.md)
for supported containers and absent or malformed metadata.
Inspect a Godot PCK without running the game:
```sh
rea inspect-artifact game.pck --detail summary --evidence_output evidence.json --json
rea extract-artifact game.pck --json
```
Formats 2, 3 and 4 retain header, directory and integrity facts. Compact delivery
keeps complete Evidence in the requested bundle. See [Godot PCK](godot-pck.md)
for embedded packs, batch queries and unknown encrypted coverage.
Inspect local model declarations without loading weights:
```bash
rea inspect-model-artifact /absolute/path/model.gguf --json
rea inspect-model-artifact /absolute/path/model.safetensors --hash full --json
```
Default hashing reads only headers and leaves full-file identity unknown.
`--hash full` streams the complete file for SHA-256. Both return typed metadata,
original tensor declarations and derived totals. MCP summaries retain complete
Evidence for filtered metadata, tensor and type-total pages; CLI compact delivery
uses `--detail summary --evidence_output FILE`. See [model files](model-artifacts.md).
Inspect Unity IL2CPP metadata names without Unity or a disassembler:
```bash
rea inspect-il2cpp-metadata /absolute/path/global-metadata.dat --json
```
The command decodes a version 24, 27, 29, 31 or 39 `global-metadata.dat` and reports assembly
images, type, method and member names, string literals, index ranges, header
sections and SHA-256. With `--binary PATH` it also reads the matching
`GameAssembly.dylib`, `GameAssembly.dll` or `libil2cpp.so` (never runs it) and
links each method to its code address; `--ghidra-seeds PATH` then writes Ghidra
function seeds. It does not decrypt metadata. MCP defaults to compact counts
with retained Evidence; query indexed rows with filters, batch indices and
selected fields. The CLI defaults to complete Evidence;
`--detail summary --evidence_output FILE` exports the full result to a new file
and returns a compact overview. See [IL2CPP metadata](il2cpp-metadata.md).
Inspect an embedded cargo-auditable Rust dependency list without installing
Rust or configuring a disassembler:
@@ -338,6 +388,58 @@ SIGINT or SIGTERM and does not stop when stdin closes. See
shutdown contract. Client registrations written by setup and the MCP registry
entry keep stdio.
## Serve an environment manifest
`rea environment-serve <manifest.json> --evidence <capture.json> [--host H]
[--port N]` serves an environment manifest projected by `inspect-analysis-view`
as an agent environment: an MCP server at `/mcp` with one tool per manifest
tool, each replaying the retained capture records it cites, the environment
card at `/.well-known/agent-env.json`, and a `/agentenv` data plane that
answers every method with JSON-RPC `-32601`. The manifest's
`parent_evidence_id` must equal the evidence file's `evidence_id`; otherwise
the command refuses with `invalid_request` before binding.
```sh
rea environment-serve manifest.json --evidence capture.json --port 8765
```
`--host` and `--port` resolve like `rea mcp --http`: flags, then `MCP_HOST` and
`MCP_PORT`, then `127.0.0.1` and an ephemeral port. `ENVIRONMENT_NAME` renames
the served environment; set but blank, it is refused as `configuration_invalid`
like a blank `MCP_HOST`. The bound URL is written to stderr as one JSON log line
(`"msg":"MCP transport listening"`). See
[agent environments](agent-environments.md) for what replay returns and does
not establish.
## Export an environment bundle
`rea environment-export <manifest.json> --evidence <capture.json> <dir>
[--package-tarball <path>] [--name <override>]` writes the same manifest and
capture pair as a bundle folder the agentenv framework runs with
`agent-env run <dir>`. It reads each file once, authenticates and cross-checks
the pair with the same checks as `environment-serve`, copies the bytes it
authenticated, refuses to write into a directory that exists and is not empty,
and never overwrites a file.
```sh
rea environment-export manifest.json --evidence capture.json ./grafana-example --json
```
The folder holds a `README.md` with the bundle's provenance, an env folder
`envs/<name>/` with a `Dockerfile` that installs this exact `rea-agents`
version and serves the copied `manifest.json` and `evidence.json` (written
with mode `0600` on POSIX; Windows retains inherited ACLs) with
`environment-serve`, a Python verifier under `artifacts/check_<name>/` and the
smoke task `tasks/smoke.json`. `--package-tarball` copies a packed `rea-agents`
tarball into the env folder and installs it instead of the registry package,
which is how the hosted lane proves a checkout rather than a release. `--name`
replaces the manifest's kebab-case name as the env folder and env id; a device
name Windows reserves (`con`, `nul`, `com1` and the like) is refused. The
command prints one JSON document listing the written files with their sizes
and the pinned package source. See
[agent environments](agent-environments.md#export-a-bundle) for the folder
layout and what the smoke task checks.
## Output and exit status
`rea mcp doctor --json` checks production MCP startup and reports child logs in
@@ -356,6 +458,11 @@ redirected, which keeps large results smaller for agents and scripts; pipe
through `jq .` for indented files. Output selection and formatting do not change
operation status.
`--filter-output` selects fields from successful command data. Classified failures
retain their complete typed diagnostic projection even when the selector matches
a field such as `code` or `message`, or names a missing field. `--full-output`
controls whether the outer `{ok, error, meta}` envelope is included.
For `cutter-command`, `--json-output` requests command-specific JSON from
Cutter when available. This is separate from `--format json`, which selects the
CLI result representation; the global `--json` flag selects that same CLI
@@ -376,6 +483,24 @@ output formatting.
`130` on SIGINT or `143` on SIGTERM after closing the listener, the session and
its providers, and `1` when that cleanup fails.
`rea environment-serve` is also long-running: it serves until SIGINT or
SIGTERM, closes the listener, then prints one structured
`{"status":"stopped", …}` document naming the URL, environment and tool count
and exits `130` or `143` through the shared cancellation handler below.
Refusals before binding (unreadable files, non-Evidence JSON, capture Evidence
in a format other than HAR, a manifest whose parent is not the supplied
evidence, an unbindable port) print a structured
error and exit `1`, as does a listener that fails after binding.
`rea environment-export` is one-shot: it prints the written files and exits
`0`, or prints a structured `invalid_request` error and exits `1` for the same
pair refusals, a non-empty or file-occupied directory, a missing package
tarball or a name that is not a kebab-case label or is a Windows device name,
writing nothing in each case.
A write that fails after the first file (a permission or disk-space failure
on a later path) propagates as the host's failure and leaves the partial
folder in place for inspection; remove it before retrying, since the next
attempt refuses the non-empty directory.
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
@@ -388,7 +513,8 @@ browser, web and Electron commands (including `analyze-web-bundle`,
`capture-electron-scenario`), and the platform and provider command families
for Android/ADB, Apktool/JEB/Flutter, firmware, PCAP and signal analysis,
WASM/EVM, Go/Rust and binary diagnostics, Frida instrumentation, the Cutter
command, objdump, Rizin and GDB. In these paths, a returned structured
command, objdump, Rizin and GDB, and the agent environment server
(`environment-serve`). In these paths, a returned structured
`cancelled` result can be printed before the wrapper assigns the
signal-derived status. This describes the current source routing; it is not a
claim that every command or provider runtime has been independently exercised.
+11 -2
View File
@@ -457,13 +457,22 @@ 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. Cleanup attempts the
after verification unless fixture retention is requested. Commands share the
owned-process supervisor: native ownership preparation has its own bounded
deadline before each short command budget, and timeouts join bounded process-tree
and output cleanup before returning. If cleanup remains incomplete, the lane retries its retained
owner and preserves the run directory (including disposable auth) rather than
removing files still in use; the error retains ownership and recovery details.
Command stderr is limited to 32 KiB and combined version output to 8 KiB;
exceeding these diagnostic budgets fails explicitly. Scenario JSON events stream
to the evaluator without retaining a second raw stdout copy. 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
is removed even with `REA_AGENT_EVAL_KEEP_FIXTURES=true`. No user configuration,
is removed after confirmed process cleanup even with
`REA_AGENT_EVAL_KEEP_FIXTURES=true`. No user configuration,
rules, plugins or history is copied; shell snapshots and additional agents are
disabled. Existing API-key environment authentication remains available.
The native missing-provider scenario preapproves only `open_binary` and
+150
View File
@@ -0,0 +1,150 @@
# Desktop installation directories
Use `inspect_desktop_application` when an installation directory is the target
and its runtime is unknown. It reads directory entries, selected headers and
bounded metadata, then reports runtime candidates, supporting files, component
path markers and concrete follow-up operations. No native provider or active
binary session is needed. It does not run the application, extract archives,
follow child symlinks, contact services or change target files.
## MCP
```json
{ "path": "/artifacts/MyApplication" }
```
Default `detail: "summary"` retains complete source Evidence in the session and
returns candidates with representative supporting paths, counts, coverage,
limitations and grouped next probes. `normalized_result.parent_evidence_id`
identifies the complete record. A server without Evidence retention refuses
summary delivery before reading the target; select `detail: "complete"` to
receive every retained fact inline.
Read exact files in one request:
```json
{
"source": {
"kind": "retained-evidence",
"evidence_id": "ev_<parent-sha256>"
},
"view": {
"kind": "desktop-application",
"collection": "files",
"paths": ["Game_Data/Managed/Assembly-CSharp.dll", "GameAssembly.dll"],
"fields": ["path", "read_status", "ranges", "facts", "issues"],
"offset": 0,
"limit": 16
}
}
```
Collections are `files`, `omissions`, `candidates`, `components` and `next_probes`.
Files and omissions accept exact `paths` and batched `file_ids` / `omission_ids`.
Files also accept `has_issues: true` to select probe diagnostics directly, or
`false` to select rows without reported issues. This filter uses the retained
issue facts; it does not re-read targets or infer that uninspected files are healthy.
When both are supplied, all filters apply; an empty selection returns no rows.
Omission records retain the observed path, kind and stable `omission_id`; their
payloads are not read, and other special-entry metadata remains unavailable.
`candidates` accepts exact `families`.
Omitted selectors match all retained rows; an empty selector matches none.
Every collection supports `fields`, `offset` and `limit`; its stable row ID is
always included. Selection changes delivery, not source inspection. Pages keep
source coverage and parent Evidence links. Page exhaustion does not establish
absence in a partial source. Complete Evidence remains accessible through
`get_evidence` and Evidence bundle export.
The summary's `probe_issues` counts files with reported issues and their retained
issue entries. It previews at most two such files, including stable `file_id`,
read status and the first issue. Path/reason previews use at most 256 UTF-16 units
each without splitting surrogate pairs; `text_truncated` marks shortened text,
and `preview_truncated` marks additional files. These are display prefixes;
full caller paths and all reasons remain in Evidence. Counts describe retained
observations, while source coverage still identifies partial inspection.
Use `inspect_analysis_view` with `collection: "files", has_issues: true` and
`fields: ["path", "read_status", "issues"]` for exact reasons, with the usual
paging and parent links. It intersects with exact paths and batched file IDs.
An ASAR inventory probe first selects its exact path with `open_binary`; then
call `inspect_artifact` on that active target. Directory inspection itself does
not select or replace the session target. The JavaScript application workflow
accepts its own selected path directly.
## CLI
The one-shot CLI returns complete Evidence by default. For compact output,
explicitly retain it in a bundle:
```bash
rea inspect-desktop-application /artifacts/MyApplication \
--detail summary --evidence_output /reports/application.evidence.json --json
```
This returns `summary` Evidence and an `evidence_bundle` publication receipt.
Existing output files are never overwritten. Summary delivery requires
`--evidence_output`, checked before analysis. `inspect-evidence-bundle` selects
saved records; an exact saved record can also feed `inspect-analysis-view`.
`--detail complete` returns source Evidence inline and can optionally write the
same bundle. Export writes only the caller-selected output file.
## Facts and uncertainty
| Family | Evidence used |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| .NET | A PE optional header declares a nonempty CLI directory. |
| Unity Mono | A managed assembly below `*_Data/Managed` or `Contents/Resources/Data/Managed` has an exact UnityEngine assembly reference. |
| Unity IL2CPP | A recognized IL2CPP metadata magic (with the raw version when complete) coexists with a conventionally named native `GameAssembly.dll`, `GameAssembly.so`, `GameAssembly.dylib` or `libil2cpp.so` image. Build correspondence remains unknown. |
| Godot | A `GDPC` header at file start or a validated executable trailer offset. |
| GameMaker | A bounded `FORM` container starts with a `GEN8` chunk. |
| Unreal | `Content/Paks` path conventions or an IoStore TOC signature; arbitrary `.pak` filenames are insufficient. |
| Electron | A `resources/app.asar` or `resources/default_app.asar` path convention; archive validity is unverified. |
When the four-byte metadata magic is present but version bytes are incomplete,
the fact retains `raw_version: null`; it does not offer an IL2CPP metadata
inspection probe. A complete magic/version prefix with supported raw version 29,
31 or 39 offers an
`inspect_il2cpp_metadata` follow-up at its admitted file path, including when no
native library was found. This probe does not establish full metadata validity
or correspondence to a native binary. See [IL2CPP metadata](il2cpp-metadata.md).
Candidates are derived or inferred from these facts and do not prove loading or
execution. BepInEx, MelonLoader, Easy Anti-Cheat and BattlEye labels identify
path conventions only; runtime presence stays unknown. No bypass is provided.
`file_id` includes the admitted root namespace, recorded path and available filesystem identity. The caller-selected root path and admitted canonical path/root identity are both retained; `local_path` identifies each observed file for follow-up operations. The selected root may be a symlink; child symlinks are not followed. Exact
metadata integers remain decimal strings. Read ranges have offsets, byte counts
and SHA-256 digests; typed facts expose CLI RVAs, metadata/pack versions and
assembly tokens. Directory and symlink identities unavailable from traversal
remain null.
The directory's `snapshot_sha256` commits to retained paths, omission kinds,
available metadata and range digests, composed through the admitted root,
entry and omission identities. Caller ceilings, coverage counters, diagnostic
wording and interpretation facts remain in Evidence, outside source identity.
The same observations under different generous limits share a snapshot digest;
Evidence IDs still preserve request parameters and reported coverage. Different
retained entries or read ranges change the source snapshot.
Omission records share the entry and representation budgets and can be fetched
independently through their view.
**It is not a digest of all file contents.** These are sequential stable entry
observations, not an atomic directory snapshot. Unread bytes remain unknown.
## Resource bounds and reuse
Defaults are 20,000 examined entries and 8 MiB of total probe reads. Callers may
select up to 100,000 entries and 64 MiB. A separate 32 MiB conservative
representation budget bounds retained paths and facts before growth. Limits
and failed probes produce partial coverage. Traversal and reads are serial.
Each reader admits one inspection at a time; overlapping requests receive a
retryable capacity refusal without cancelling the admitted caller.
Unity reference decoding stops after a witness in each `Data/Managed` directory;
other assemblies' references remain unexamined, while their headers are still
checked. AssemblyRef facts decode names and tokens only; they do not decode or
hash unrelated key/culture/hash payloads or establish runtime binding. Pack contents, encrypted data, metadata/address correspondence and
section-embedded PCKs without a trailer are separate capabilities.
Filesystem results are not cached across calls. Retained views reuse validated
immutable metadata without rescanning files or retaining another inventory.
+587 -17
View File
@@ -28,6 +28,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -64,6 +91,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -100,6 +154,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -136,6 +217,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -172,6 +280,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -208,6 +343,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -244,6 +406,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -280,6 +469,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -316,6 +532,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -352,6 +595,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -388,25 +658,82 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"properties": {
"logical_path": { "type": "string" },
"declared_sha256": {
"anyOf": [{ "type": "string" }, { "type": "null" }]
"anyOf": [
{
"type": "object",
"properties": {
"logical_path": { "type": "string" },
"declared_sha256": {
"anyOf": [{ "type": "string" }, { "type": "null" }]
},
"calculated_sha256": {
"anyOf": [{ "type": "string" }, { "type": "null" }]
},
"unpacked": { "type": "boolean" }
},
"required": [
"logical_path",
"declared_sha256",
"calculated_sha256",
"unpacked"
],
"additionalProperties": false
},
"calculated_sha256": {
"anyOf": [{ "type": "string" }, { "type": "null" }]
},
"unpacked": { "type": "boolean" }
},
"required": [
"logical_path",
"declared_sha256",
"calculated_sha256",
"unpacked"
],
"additionalProperties": false
{
"type": "object",
"properties": {
"logical_path": { "type": "string" },
"algorithm": { "type": "string", "const": "md5" },
"declared_md5": {
"type": "string",
"pattern": "^[a-f0-9]{32}$"
},
"calculated_md5": {
"anyOf": [
{ "type": "string", "pattern": "^[a-f0-9]{32}$" },
{ "type": "null" }
]
},
"unpacked": { "type": "boolean" }
},
"required": [
"logical_path",
"algorithm",
"declared_md5",
"calculated_md5",
"unpacked"
],
"additionalProperties": false
}
]
}
},
"required": [
@@ -446,6 +773,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -482,6 +836,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -518,6 +899,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -554,6 +962,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -590,6 +1025,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -626,6 +1088,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -662,6 +1151,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -698,6 +1214,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
@@ -734,6 +1277,33 @@
"required": ["action"],
"additionalProperties": false
},
"recovery": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_input_contract" },
"operation": { "type": "string", "minLength": 1 }
},
"required": ["kind", "operation"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "inspect_timeout_state" },
"operation": { "type": "string", "minLength": 1 },
"timeout_ms": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": ["kind", "operation", "timeout_ms"],
"additionalProperties": false
}
]
},
"details": {
"type": "object",
"propertyNames": { "type": "string" },
+11 -1
View File
@@ -158,7 +158,17 @@ tree semantics, vulnerability scanning, emulation or hardware runtime capture.
Supply a stable copy within the allowance. No in-place source modification.
- One queued heavy operation per provider instance; Binwalk one thread and
Unblob one worker. No automatic parallel extraction engines.
- **120-second** deadline; inherited **1 GiB per-process address-space** limit,
- **120-second** analysis deadline through inventory. Publication and final
cleanup start a separate **120-second** budget; select
`publication_timeout_ms` in MCP or `--publication-timeout-ms` in CLI for a slow
destination. Valid budgets are integers from 1 through 2,147,483,647 ms (the
timer representation limit). Publication timeouts identify their phase and
verified file progress; verified writes before atomic commit are not a claim
that output remains published after rollback. Caller cancellation applies to
both phases and final cleanup. Phase handoff, publication commit and final
completion also check monotonic elapsed time, so delayed timer callbacks
cannot revive an expired budget.
- Inherited **1 GiB per-process address-space** limit,
120 CPU seconds and zero core-dump allowance through `prlimit`.
- JSON reports: at most **8 MiB** and valid UTF-8; malformed encoding and
oversized reports fail without repairing or truncating producer data.
+16
View File
@@ -6,6 +6,22 @@ For remote devices, pass a host with an optional port (`host[:port]`; bracket IP
MCP exposes `list_frida_devices`, `list_frida_processes`, `start_frida_session`, `load_frida_script`, `resume_frida_session`, `unload_frida_script`, `frida_session_status`, and `close_frida_session`. A spawned process starts paused so scripts can load first. Closing unloads session scripts and detaches. If a spawn remains paused, REA resumes it only after script cleanup or session detach confirms the instrumentation is released; if both cleanup paths fail, the target stays paused and the cleanup error is retained. REA never kills the target. MCP sessions end with the server process. The one-shot CLI command `instrument-with-frida` accepts one inline script or script file, observes messages for a bounded duration, and returns Evidence with the source hash and captured messages.
For state and capture-coverage checks, pass `{"session_id":"SESSION_ID","detail":"summary"}` to `frida_session_status`. Each call reads the observed session state and retains the complete observation. The reply is an `inspect_analysis_view` Evidence summary with the session identity, state, scripts, `messages_retained`, and `messages_truncated`; message payloads remain in its `parent_evidence_id`. The count covers retained queued messages, not every target event. Omitted `detail` or `detail=complete` preserves the existing complete reply.
A summary's selected fields look like this (excerpt):
```json
{
"summary": {
"state": "running",
"messages_retained": 50,
"messages_truncated": false
}
}
```
Use `get_evidence_bundle` with `detail="summary"` and `filters={"evidence_id":"PARENT_ID"}` to discover parent metadata without message payloads. Filters apply only to summary delivery. Use `export_evidence_bundle` for the complete canonical bundle, then select the record whose `evidence_id` matches `normalized_result.parent_evidence_id` from the status summary. To use the existing CLI `inspect-analysis-view`, extract that record into a standalone Evidence JSON file and select it as an Evidence-file source with `view={"kind":"summary"}`. Reading retained Evidence does not refresh a live session or verify a process after exit or PID reuse.
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. 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.
+50
View File
@@ -19,6 +19,56 @@ requires an absolute filesystem path and preserves that exact selection:
}
```
For build identity and counts, select `detail: "summary"`. MCP retains the same
complete Evidence and returns `normalized_result.parent_evidence_id`. Read
selected dependency versions without reopening the file:
```json
{
"name": "inspect_analysis_view",
"arguments": {
"source": {
"kind": "retained-evidence",
"evidence_id": "ev_<parent digest>"
},
"view": {
"kind": "go",
"collection": "dependencies",
"paths": ["golang.org/x/crypto"],
"fields": ["path", "version", "replacement"],
"offset": 0,
"limit": 10
}
}
}
```
Go views support `dependencies` (exact `paths`) and `settings` (exact `keys`),
optional original `indices`, field selection, and pagination. Filters intersect;
empty filter arrays select no rows and `fields: []` returns only row identity.
Each row keeps its original `index`, scoped to the parent Evidence and collection;
duplicate module paths and setting keys keep distinct indices. Page offsets
count matching records. Exhausting retained rows does not establish complete
runtime dependencies. Original bytes, unknown lines and all complete metadata
remain in the parent and can be exported as an Evidence bundle.
One-shot CLI summaries save complete Evidence before returning the projection:
```bash
rea inspect-go-binary ./application --detail summary --evidence_output ./go-evidence.json --json
```
`--evidence_output` is required for CLI summary delivery and never overwrites an
existing file. The default CLI/MCP reply remains complete.
[Measured workflows](../experiments/analysis-efficiency/go-build-views.md) include
catalog repetition and extra calls. Identity/count questions benefit from a
single summary. In the tested Codex full-catalog configuration, a compound
question about identity and one dependency uses fewer tokens in captured request JSON with
one complete inspection than with a summary followed by a lookup. The complete
reply remains useful for that initial question; retained views support later
selected reads. Token figures are serialization estimates, not model usage.
## Observations
The inline Evidence result contains the artifact path, SHA-256, byte length,
+108
View File
@@ -0,0 +1,108 @@
# Godot PCK archives
`inspect-artifact` and `extract-artifact` read ordinary Godot PCK formats 2, 3
and 4 without running the game or requiring Godot. Official Godot 4.4.1, 4.6.1
and 4.7.1 produced these respective formats in verification; other engine
releases have not been verified. Format 1 is unsupported.
Inspection retains the original header and directory facts, including engine
version, flags, declared file count, source paths, offsets and declared MD5.
Observed plaintext bytes receive content-addressed SHA-256 identities. MD5 is a
container integrity claim, separate from the observed SHA-256. A mismatch fails
by default; `--integrity-policy record-and-continue` retains the observed bytes
and an explicit untrusted contradiction. An all-zero MD5 is an unknown claim,
not a verified digest.
## CLI
Start with a compact summary and keep the complete Evidence bundle:
```sh
rea inspect-artifact /artifacts/game.pck --detail summary \
--evidence_output /evidence/game.json --json
rea extract-artifact /artifacts/game.pck --json
```
Summary delivery requires `--evidence_output` and never overwrites that file.
The response contains `summary` Evidence and an `evidence_bundle` receipt.
Without `--detail summary`, inspection keeps its complete inline delivery.
Extraction creates a new temporary directory and returns its path. It rejects
unsafe paths and verifies container identity before creating output.
The same CLI commands locate a PCK at the beginning of a file or through its
12-byte EOF trailer in an executable carrier. They do not scan arbitrary
payloads or discover packs behind additional trailing signatures. The root
content SHA-256 covers the whole carrier; its content classification remains
native, while the inventory records the PCK role and exact pack bounds.
Ordinary native `open_binary` detection remains unchanged.
## MCP and selected facts
For a standalone pack, call `open_binary` with its absolute path, then
`inspect_artifact` with `{"detail":"summary"}`. The complete inspection and its
nested inventory stay in the session. Use the summary's
`normalized_result.parent_evidence_id` as the source of subsequent views:
```json
{
"name": "inspect_analysis_view",
"arguments": {
"source": {
"kind": "retained-evidence",
"evidence_id": "<parent_evidence_id>"
},
"view": {
"kind": "inventory",
"collection": "occurrences",
"logical_paths": ["scripts/main.gd", "project.binary"],
"fields": [
"logical_path",
"declared_integrity",
"hash_status",
"format_metadata"
],
"offset": 0,
"limit": 32
}
}
}
```
Occurrences retain `occurrence_id`, `artifact_id` and `parent_occurrence_id`
even when `fields` is empty. Batch occurrence IDs with `occurrence_ids`, or
join returned content IDs to `collection: "nodes"`, `artifact_ids: [...]` and
`fields: ["sha256", "size"]`. Filters intersect; an omitted filter selects all
available rows and an empty array selects none. Pagination follows the filtered
canonical order. Multiple occurrences may share one content ID.
Views reuse authenticated immutable inventory facts and lazy lookup indexes;
they do not reopen the source. These are historical observations, including
after the source changes or disappears. Close the target with `close_binary`
when finished. To read an exported bundle through the CLI, select its complete
inspection record as `source: {kind: "inline", evidence: ...}` in a JSON request
file for `rea inspect-analysis-view request.json --json`.
## Coverage and limits
PCK summaries expose root format metadata, available graph counts,
`available_hash_status_counts`, and `source_coverage`. Inventory pages preserve
producer coverage alongside page coverage. `source_complete` means all declared
retained graph rows are available; it does not establish that an encrypted or
otherwise unknown directory was examined. Missing matches in unknown coverage
are not evidence of absence.
Encrypted directories retain their header and declared file count with unknown
entry coverage. Individually encrypted members retain directory metadata with
unknown content identity; REA does not decrypt them. Sparse bundles likewise
retain header facts with unknown member coverage. Extraction refuses an
unreadable directory or encrypted member. This capability does not recover
keys, decode Godot resources, decompile GDScript bytecode, analyze signals,
apply patch/removal entries or execute targets.
Readable logical member bytes, including repeated physical ranges, share the ZIP
archive expansion policy: at most the larger of 256 MiB or 500 times the PCK's
encoded byte span. Embedded carrier bytes do not enlarge that budget. The full
directory is checked before any member is yielded, hashed or extracted. Encrypted
members are not read and do not consume this plaintext-work allowance. Small
bounded aliases remain valid. This is a processing/output resource bound, separate
from the directory metadata retention budget and format validity.
+419
View File
@@ -0,0 +1,419 @@
# IL2CPP metadata
`inspect_il2cpp_metadata` / `inspect-il2cpp-metadata` decodes one selected local
Unity IL2CPP `global-metadata.dat` file and returns its assembly images, type
definitions, methods and named members with their owners, plus managed string
literals, by stable index, namespace, range and count,
with the header sections and serialized index widths. It reads the file without
running it and requires no Unity installation, IL2CPP binary, active target,
Hopper, Ghidra or IDA.
Metadata versions 24, 27, 29, 31 and 39 are supported. For example, Unity 2019.4.41f2
wrote version 24, 2020.3.49f1 version 27, 2022.3.30f1
wrote version 29, 2022.3.62f3 wrote 31 and 6000.4.2f1 wrote 39; other Unity
releases that write these numbers have not been checked. Other versions are
rejected as unsupported. Version 24 decoding covers the 264-byte header layout
used by the cited Unity 2019.4 build; earlier 24.x layouts are not inferred from
the version number and are refused when their header or records differ. The path
must name a regular file; directories and symbolic links are rejected.
With `binary_path`, the tool also reads the matching native binary and links
each method to its code address. See [Native method addresses](#native-method-addresses).
## MCP
MCP defaults to a compact summary and retains the complete decoded Evidence in
the session. MCP requires an absolute filesystem path:
```json
{
"name": "inspect_il2cpp_metadata",
"arguments": {
"path": "/artifacts/Data/Managed/Metadata/global-metadata.dat"
}
}
```
The summary retains the complete decoded Evidence in the session and returns a
linked `inspect_analysis_view` overview: artifact identity, metadata version,
index widths and `counts` (`sections`, `images`, `types`, `methods`,
`nested_types`, `fields`, `properties`, `events`, `parameters` and
`string_literals`) without rows. Use `normalized_result.parent_evidence_id` to page
the original rows without reopening or decoding the file:
```json
{
"source": {
"kind": "retained-evidence",
"evidence_id": "<parent_evidence_id>"
},
"view": {
"kind": "il2cpp-metadata",
"collection": "types",
"offset": 0,
"limit": 64
}
}
```
Collections are `sections`, `images`, `types`, `methods`, `fields`,
`properties`, `events`, `parameters`, `string_literals`, `method_addresses`,
`return_types`, `field_types`, `parameter_types` and `code_gen_modules`. Every returned row includes
its source `index`, scoped by artifact SHA-256 and collection. All collections
accept batch `indices` and `fields`; collections whose rows have a `name` also
accept exact `names`. Types also accept `image_indices`, `namespaces` and
`declaring_types`; methods, fields, properties and events accept
`declaring_types`. Parameters accept exact `method_indices`, so a batch of
method indices retrieves their parameters without reading the entire parameter
table. `parameter_types` accepts the same `method_indices`, resolved through the
retained `parameters` owners; Evidence without `parameters` refuses that filter. Filters intersect, duplicate indices are returned once, and
rows retain metadata order. An empty filter selects no rows; `fields: []`
returns indices only. Omitted fields return the complete selected rows.
For example, after resolving a type index, retrieve selected method facts:
```json
{
"source": {
"kind": "retained-evidence",
"evidence_id": "<parent_evidence_id>"
},
"view": {
"kind": "il2cpp-metadata",
"collection": "methods",
"declaring_types": [1555],
"names": ["SendMessage"],
"fields": ["name", "declaring_type"]
}
}
```
After finding method indices, parameters can be requested directly:
```json
{
"source": {
"kind": "retained-evidence",
"evidence_id": "<parent_evidence_id>"
},
"view": {
"kind": "il2cpp-metadata",
"collection": "parameters",
"method_indices": [9785],
"fields": ["name", "method"],
"limit": 64
}
}
```
Historical Evidence that predates these member collections remains queryable.
A missing collection has an unknown (`null`) summary count, and requesting it
reports that it was not collected; it is never presented as an empty inventory. The same holds for Evidence that predates binary linking: its summary
omits `binary`, and `method_addresses`, `method_address_states`,
`return_types`, `field_types` and `parameter_types` counts are `null`.
Existing empty collections retain a zero count. Full Evidence is preserved.
`offset` counts matching rows, not source indices. `limit` defaults to 64;
`coverage.next_offset` continues that filtered page. Coverage describes retained
metadata facts only; runtime behavior and correspondence to native code remain
unknown. Each view preserves the parent Evidence link, artifact identity and
limitations. Queries work after the source file is removed. Select
`detail: "complete"` to return every row inline within the separate MCP response
budget.
## CLI
```bash
rea inspect-il2cpp-metadata /absolute/path/global-metadata.dat --json
```
The CLI defaults to complete Evidence. For compact delivery, explicitly preserve
the full Evidence in a new file:
```bash
rea inspect-il2cpp-metadata /absolute/path/global-metadata.dat \
--detail summary --evidence_output /tmp/metadata-evidence.json --json
jq -c '{source: {kind: "inline", evidence: .records[0]}, view: {kind: "il2cpp-metadata", collection: "methods", indices: [9785], fields: ["name", "declaring_type"]}}' \
/tmp/metadata-evidence.json > /tmp/metadata-query.json
rea inspect-analysis-view /tmp/metadata-query.json --json
```
Use the exported Evidence with the CLI's inline Evidence source format described
in [CLI and Evidence](cli.md#run-a-command). Compact delivery requires
`--evidence_output`; existing files are never overwritten. The full export
preserves every decoded row for subsequent queries without the original file.
`--binary PATH` links method addresses and `--architecture arm64|amd64` selects
the slice of a universal Mach-O.
## Observations
The result contains:
- `artifact`: path, SHA-256 and byte length;
- `magic`: unsigned little-endian header signature (`0xFAB11BAF`, delivered as a JSON number);
- `metadata_version`: `24`, `27`, `29`, `31` or `39`;
- `index_widths`: the serialized widths (1, 2 or 4 bytes) of
`type_definition`, `generic_container`, `parameter` and `type` indices, and
`type_width_source`. Version 39 derives the type index width from the
`interface-offsets-record` or the `type-definition-record`; versions 24, 27, 29
and 31 always use 4-byte indices (`fixed-width-version`);
- `sections`: all version-specific header sections in header order, each with `offset`, `size`
and `count`. Versions 24 to 31 record no counts, so `count` is `null` and
record counts come from the section sizes;
- `images`: `name`, `type_start` and `type_count`;
- `types`: `name`, `namespace`, `method_start`, `method_count`,
`nested_type_start`, `nested_type_count` and `declaring_type`;
- `methods`: `name` and `declaring_type`;
- `fields`, `properties` and `events`: `name` and `declaring_type`, the type
whose member range holds the row (`-1` when none does);
- `parameters`: `name` and `method`, the method whose parameter range holds it;
- `string_literals`: managed string literals as `value`, or `value_base64` with
the exact bytes when they are not valid UTF-8;
- `limitations`.
A row's position in its collection is its metadata index, so `type_start`,
`method_start` and `declaring_type` refer to positions in `types` or `methods`.
`nested_type_start` instead indexes the metadata's `nestedTypes` table, which is
not returned; each nested type's `declaring_type` carries that relationship.
A type's `declaring_type` is derived from the `nestedTypes` section and is `-1`
for top-level types. The start of an empty range can retain the original value
`-1`.
The complete inventory of a large game is several megabytes and can exceed
the MCP response budget. Summary delivery and filtered, projected pages keep
unneeded rows out of agent context without discarding the source Evidence.
## Native method addresses
`binary_path` names the native binary built with the metadata: macOS
`GameAssembly.dylib` (Mach-O), Windows `GameAssembly.dll` (64-bit PE) or
Android `libil2cpp.so` (64-bit ELF, AArch64 or x86-64). A
universal Mach-O needs `binary_architecture` (`arm64` or `amd64`); a thin binary
rejects it. The file is read, never loaded or executed.
A position-independent `libil2cpp.so` stores zero in most pointer slots and
keeps the value in `R_AARCH64_RELATIVE` or `R_X86_64_RELATIVE` relocations
(`DT_RELA`). The reader writes those values into a private copy before
searching it, so addresses are the link-time addresses and RVAs are relative to
the first loaded segment. Android packed
relocations (`DT_ANDROID_RELA`) are refused. No target code is executed.
The binary's `Il2CppCodeRegistration` points to one `Il2CppCodeGenModule` per
assembly image. Each module record starts with its module name, its method
pointer count and its method pointer array. The reader finds, for every metadata
image, the single record whose name pointer reaches that image's name string and
whose count equals the image's method count. It then requires exactly one
`codeGenModulesCount`/`codeGenModules` pair that lists exactly those records. No
symbols are needed, so stripped builds work. A method's token row id selects its
slot in the module's method pointer array.
Module records establish names through their declared NUL-terminated string pointers. NUL/0xFF padding, spaces, Unicode and suffix-shared storage are supported. A pointer to a longer string does not match just its suffix; a pointer directly into a shared suffix may name it. Exact reversed UTF-8 matching avoids rescanning the file for every name and retains duplicate-name owners until module records resolve them. A contributor investigated a Linux
`GameAssembly.so` from Unity 2023.2.13f1 whose static registration was not located. When no static pair is resolved on x86-64, the reader searches executable ranges for bytes consistent with RIP-relative LEA/MOV references to module-array candidates. Exactly one referenced array candidate must remain. `code_gen_modules_field` is then `null`, and Evidence is **inferred**: instruction boundaries, the absence of a static registration elsewhere, and runtime use were not verified. The module records and slots themselves remain file observations. Static-table associations are **derived**. Otherwise the result is `code-registration-not-found`.
The binary/metadata pair is caller-selected. Name/count/token agreement is structural evidence, not a cryptographic same-build proof. File-offset locations refer to the primary metadata artifact; linked virtual addresses refer to `binary.artifact`. Both SHA-256 identities remain available in compact native pages as `artifact` and `binary_source`.
Contributor-reported verification (not all rerun by the follow-up): macOS arm64 and x86_64 slices from Unity 2021.3.45f2, 2022.3.30f1, 2022.3.62f3 and
6000.0.84f1 against dSYM symbols; Android arm64 and x86-64 from 2022.3.62f3
against `libil2cpp.sym.so`; Windows x64 from 2023.2.13f1 (metadata version 29,
the MIT-licensed game Between Two Worlds 1.0.5, `GameAssembly.dll` SHA-256
`a3ae7f6ecd1f671297b7d98d12713ef024062d93cd7a4205298102656c93b67a`) against
Il2CppDumper, where all 43,198 linked methods share an address with a
same-named Il2CppDumper method and identical code folding groups 10,448 methods
into 1,735 addresses. A macOS x86_64 build from Unity 2020.3.49f1 (metadata version 27, which Il2CppDumper reads as 27.1) links 10,555 methods, all at addresses where Il2CppDumper names the same method; its other addresses are generic instances. A build from Unity 2021.1.28f1 (also read as 27.1) gives the same result: 10,345 methods linked, every address named the same by Il2CppDumper, and its other 3,486 addresses generic instances.
These checks compare addresses with symbols or with another static tool. They
do not establish that a linked address is the code the game runs (a runtime may
patch, hook or replace it), that builds from other Unity versions, compilers or
obfuscators link the same way, or that a method without an address has no code:
generic instances, adjustor thunks and invokers are not linked, and an
`unknown` row was not looked up at all.
The result adds:
- `binary`: artifact identity, `format`, `architecture`, `image_base`,
`code_gen_modules_field` (the address of `codeGenModulesCount`, or `null` as
described above), `code_gen_modules_array` (the module pointer array) and
`code_gen_modules` (`image`, record `address`, `method_pointer_count`);
- `method_addresses`: one row per method index with `state`, `address` and
`rva` (address minus `image_base`), both hexadecimal strings. `state` is
`code` when the module slot holds an unambiguously mapped executable address, `no-body` when an observed slot is zero,
as for abstract, extern and most generic methods, and `unknown` when no type
range in any image holds the method or a symbol relocation leaves its slot unresolved.
`address` and `rva` are `null` unless `state` is `code`. The summary counts
each state in `counts.method_address_states`. Ghidra seeds are written only
for `code` rows.
- `return_types`, `field_types` and `parameter_types`: one row per method,
field and parameter index with `type`, the index into the binary's
`Il2CppType` table, and `name`, rendered from that table: C# keywords for
primitives (`int`, `string`, `object`), `Namespace.Outer+Inner` for type
definitions, `T[]`, `T[,]` and `T*`, generic instances as
`System.Collections.Generic.List<string>` and generic parameters by their
metadata name (`TKey`). A trailing `&` marks a by-reference type. `name` is
`null` only for type index `-1`.
`binary` also records `types_field` and `types_count`: the address of
`Il2CppMetadataRegistration.typesCount` and its value. That record is found as
the single place whose `fieldOffsetsCount` and `typeDefinitionsSizesCount` both
equal the metadata type-definition count and whose type table is file mapped.
Without `binary_path`, `binary` is `null` and the four binary collections are
empty in the complete producer report to indicate unrequested observations. Their summary counts, including state counts, are `null`, and native page requests report unavailable observations. This does not establish an empty native inventory. Missing native fields in historical Evidence remain unknown too.
For metadata version 27, type names are `null` and only type indices are
reported: versions 27.0 to 27.2 share that header number but place the
Il2CppType byref flag in different bits, so a rendered name could gain or lose
`&` without warning.
The builds checked are listed after the module search rules above.
| Reason | Category | Meaning |
| --------------------------------- | ----------- | ------------------------------------------------------------------------------------------------- |
| `unsupported-container` | unsupported | Not a 64-bit little-endian Mach-O, PE or ELF image (ELF: AArch64 or x86-64 with dynamic section). |
| `slice-selection-required` | unsupported | A universal Mach-O was given without `binary_architecture`. |
| `slice-not-found` | unsupported | The requested slice is absent, or a thin binary was given an architecture. |
| `unsupported-pointer-encoding` | unsupported | Mach-O chained fixups or Android packed (APS2) ELF relocations; pointers not decoded. |
| `malformed-container` | input error | The container headers are damaged. |
| `code-gen-modules-not-found` | input error | An image has no module record; often a binary from a different build. |
| `ambiguous-code-gen-module` | input error | More than one module record matches an image. |
| `code-registration-not-found` | input error | No unique module table or executable-byte array candidate was resolved. |
| `invalid-method-token` | input error | A method token is not a method row inside its module's pointer count. |
| `invalid-method-pointer` | input error | A slot is unavailable or its nonzero address lacks unambiguous executable file coverage. |
| `metadata-registration-not-found` | input error | No single MetadataRegistration matches the type-definition count. |
| `invalid-type` | input error | A type index or `Il2CppType` record is out of range, unmapped or malformed. |
| `unsupported-type-kind` | unsupported | A valid type kind has no implemented rendering. |
Format and selection failures name `binary_path`; capacity refusals remain typed resource errors. Failed linking preserves the metadata source identity, validated counts, selected binary path/architecture and its SHA-256 when observed, plus prior producer observations. It never publishes an incomplete native table as complete. The binary input is bounded to1GiB.
Scans yield cooperatively in bounded batches. Name-address retention and reverse-trie construction are each limited to65,536 entries/nodes and fallback module-array candidates to64 (`native-index-capacity`); exceeding capacity does not prove absence. Rendered type text has a64MiB UTF-8 cache-workspace guard, separate from the64MiB encoded-report admission, and64 nested rendering frames (`native-type-text-capacity` / `type-nesting-capacity`). Genuine cycles are malformed; unsupported type kinds are explicit coverage failures. Native row/text admission runs before allocation or retention. Unused generic parameter names are read on demand from the same stable metadata snapshot. There is no cross-inspection file cache; validated immutable Evidence is reused for session views.
ELF RELATIVE writes into zero-fill are kept as a private virtual-pointer overlay. Unresolved supported-width symbol relocations, including RELA PLT entries, remain unknown; stored zeros never establish no-body. COPY, TLS descriptor, REL, packed APS2 and other unsupported relocation encodings fail closed. Input bytes are unchanged.
Native address queries batch exact64-bit hexadecimal `addresses` and `states` (`code`, `no-body`, `unknown`), intersecting indices and pagination. Numerically equal address spellings match; original row indices and every shared-body alternative survive:
```json
{
"source": {
"kind": "retained-evidence",
"evidence_id": "<parent_evidence_id>"
},
"view": {
"kind": "il2cpp-metadata",
"collection": "method_addresses",
"addresses": ["0x180c56ed0"],
"states": ["code"],
"fields": ["address", "rva"],
"offset": 0,
"limit": 64
}
}
```
## Ghidra function names
The CLI can turn a linked report into a
[`REA_GHIDRA_SEED_FILE`](installation.md) so Ghidra names every IL2CPP method
before auto-analysis:
```bash
rea inspect-il2cpp-metadata global-metadata.dat --binary libil2cpp.so \
--ghidra-seeds il2cpp-seeds.tsv --json > /dev/null
export REA_GHIDRA_SEED_FILE="$PWD/il2cpp-seeds.tsv"
```
Each linked method becomes one `function` seed named `Namespace.Type$$Method`
(nested types joined with `.`, whitespace replaced by `_`), the Il2CppDumper
convention. Seeds are at `seed-base + rva`. The default base is where Ghidra's
loaders place the binary: `0x100000` for an ELF linked at 0, and the link base
for Mach-O and PE; `--seed-base 0x...` overrides it for a different import. When
identical code folding gives several methods one address, the first method names
the function and a `# folded <address> <kept> also <names>` comment line after
the seeds lists the others, so the kept name is visibly one of several. Ghidra still names a seeded function that is a thunk after its
target. The file is atomically published with exclusive creation; an existing destination is never replaced. Failed staging retains its cleanup owner for retry. Source digest and link/seed-base comments make the mapping inspectable. Unknown slots are skipped separately from observed no-body slots. `--seed-base` requires `--ghidra-seeds`; overflowing rebased addresses and names/outputs beyond the existing Ghidra protocol limits (2,000 name characters,32MiB file,1,000,000 entries) are refused before publication. The CLI and reusable service use one formatter and owned output workflow; ordinary MCP inspection remains read-only.
## Failures
A file whose magic is not `0xFAB11BAF` fails as an unsupported target with
`unrecognized-magic`. The file may be encrypted or may not be IL2CPP metadata.
A version other than 24, 27, 29, 31 or 39 fails as an unsupported target with
`unsupported-version`.
Damaged metadata returns an input error (`invalid_format`) whose
message names one reason:
| Reason | Meaning |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `truncated-header` | The file is shorter than the header. |
| `unexpected-header-size` | `stringLiterals.offset` is not the header size: 264 bytes for version 24, 256 for 27, 29 and 31, 380 for 39. |
| `section-out-of-bounds` | A section extends beyond the file, or a non-empty section starts inside the header. |
| `section-overlap` | Two sections overlap. Zero-size sections are exempt and gaps are allowed. |
| `record-size-mismatch` | A section size does not divide into its records, or the record size differs from the one the index widths imply. |
| `type-index-width` | The record used to derive the type index width implies no 1, 2 or 4 byte width. |
| `index-out-of-range` | A serialized index or range points outside its target collection. |
| `nested-type-conflict` | A type is listed as nested in two types, in itself, or in a cycle of declaring types. |
| `declaring-type-mismatch` | A method inside a type's method range names a different type, or a method lies outside its type's range. |
| `image-range-overlap` | Two images claim the same type definitions. |
| `invalid-string` | A name index does not start a string, or the name is unterminated or not valid UTF-8. |
A version field that disagrees with the file's layout, for example a version
39 file relabeled as 29, usually surfaces as `unexpected-header-size` or
`record-size-mismatch`.
Two checks are stricter than the IL2CPP runtime: a name index must start a
string, and an empty range's start must lie between -1 and the collection size.
Every Unity-written file checked so far satisfies both; metadata rewritten by
other tools may be rejected.
An incomplete inventory is never reported as complete. Failures after a verified
snapshot retain partial source Evidence with its SHA-256, byte length and any
validated section row counts; these counts do not establish that names and
relationships were decoded. A file that changes during reading and a cancelled
request keep distinct errors. Decode checkpoints yield for cancellation, and
close waits for active work. Each reader admits one inspection at a time.
Resource guards bound the selected file to 256 MiB and the encoded complete
report to 64 MiB, checking row counts before allocation and JSON/UTF-8/base64 expansion during
decoding, before serialization. Names and identical literal spans are decoded
once within one stable file snapshot; no filesystem results are cached across
inspections. Ownership assignment also yields to cancellation. MCP also applies its
[response transport budget](mcp-contracts.md); a complete report within the
report limit can still require the summary and paging path.
## Outside this tool
- Decrypting or deobfuscating protected metadata.
- Linking Mach-O binaries that use chained fixups, ELF images with Android
packed (APS2) relocations, and 32-bit images; generic method instances,
adjustor thunks and invokers.
- Full method signatures beyond the rendered field, parameter and return type
names, generic method instances, and type names for metadata version 27.
- Running Ghidra or another disassembler. `--ghidra-seeds` only writes a seed
file for [`REA_GHIDRA_SEED_FILE`](installation.md); use the
[native workflow](native-investigation.md) for native code.
- Metadata versions other than 24, 27, 29, 31 and 39.
Names come from the metadata file only. They do not establish which methods
were compiled into the native binary or how they behave at runtime.
## Real producer verification
`npm run verify:il2cpp:metadata -- --metadata PATH` exercises a caller-supplied
`global-metadata.dat` through the public CLI and MCP. It is opt-in, like
`verify:pcap`, because no real game metadata ships with the repository. Normal
inspection does not need it.
The follow-up was checked against the public Cpp2IL
[`Simple_2022_3_35` sample](https://github.com/SamboyCoding/Cpp2IL/tree/b5ad444b82267cb1e4b88b8b373c008105bdea52/TestFiles/Simple_2022_3_35):
version 31, 1,892,268 bytes, SHA-256
`2441635a7c234a1a34deccc6a9906d6f5abcbdab078a38b2bf488a52a4962c48`.
An independent byte-layout oracle matched all 36 images, 2,468 types and 12,409
methods. Corresponding managed DLLs independently matched names and ownership
for 35 images, 2,463 types and 12,406 methods; the generated image has no matching
DLL. This does not establish real-producer coverage for versions 29 or 39.
Compact native summaries omit the `binary.code_gen_modules` table and keep its
count in `counts.code_gen_modules`. Query `collection: "code_gen_modules"`
with batch `image_indices` or source `indices`, selected `fields` and pagination.
Module row `index` is its retained collection position; `image` joins the
metadata image collection. Scalar registration facts and both source identities
remain inline. Complete Evidence retains the original full table.
+13 -11
View File
@@ -47,17 +47,19 @@ For runtime instrumentation, see the [Frida guide](./frida-instrumentation.md).
## Choose a guide
| Task | Guides |
| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Inspect native functions, references, or types | [Native binaries](native-investigation.md), [Go metadata](go-binaries.md), [Rust dependencies](rust-binaries.md), [offline ELF layout](binary-diagnostics.md), [recorded crashes](recorded-crashes.md) |
| Select a native provider or import format | [Ghidra semantics](ghidra-provider.md), [Windows](windows-ghidra-p0.md), [DOS](ghidra-dos.md), [raw bytes](raw-binary.md), [MIPS](ghidra-mips.md), [PSP](ghidra-psp.md), [NativeAOT](ghidra-nativeaot.md), [IDA](ida-provider.md), [Kuna](kuna-provider.md), [JEB](jeb-analysis.md) |
| Analyze JavaScript or Electron artifacts | [Static analysis](javascript-artifact-reconstruction.md), [tracing and comparisons](javascript-application-workflows.md), [application graph](javascript-application-graph.md), [source recovery](javascript-recovery.md) |
| Compare static JavaScript with runtime observations | [Runtime attribution](javascript-runtime-observation.md), [reconciliation](javascript-runtime-reconciliation.md), [Electron observation](electron-observation.md), [Electron fuses](electron-fuses.md) |
| Inspect assemblies, packages, or firmware | [.NET](managed-code-analysis.md), [Android](android-analysis.md), [Apktool resources](apktool-resource-analysis.md), [ADB acquisition](adb-device-analysis.md), [Apple](apple-application-analysis.md), [Harmony](harmony-analysis.md), [firmware](firmware-analysis.md), [WASM](wasm-artifacts.md), [EVM](evm-bytecode.md) |
| Observe or compare a browser scenario | [CDP observation](browser-observation.md), [scenarios](browser-scenario-contract.md), [runtime evidence](web-runtime.md), [historical captures](web-network-captures.md) |
| Trace captured website source | [Source locations](web-source-location.md), [module traces](website-module-trace.md), [script export](website-script-export.md) |
| Capture and compare a command | [Process capture](process-capture.md) |
| Use CLI/MCP and retain evidence | [CLI](cli.md), [MCP contracts](mcp-contracts.md), [agent prompts](mcp-prompts.md), [obligation ledgers](reconstruction-obligation-ledgers.md) |
| Task | Guides |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Identify a desktop installation | [Runtime candidates, evidence and follow-up files](desktop-applications.md) |
| Inspect native functions, references, or types | [Native binaries](native-investigation.md), [Go metadata](go-binaries.md), [Rust dependencies](rust-binaries.md), [offline ELF layout](binary-diagnostics.md), [recorded crashes](recorded-crashes.md) |
| Select a native provider or import format | [Ghidra semantics](ghidra-provider.md), [Windows](windows-ghidra-p0.md), [DOS](ghidra-dos.md), [raw bytes](raw-binary.md), [MIPS](ghidra-mips.md), [PSP](ghidra-psp.md), [NativeAOT](ghidra-nativeaot.md), [IDA](ida-provider.md), [Kuna](kuna-provider.md), [JEB](jeb-analysis.md) |
| Analyze JavaScript or Electron artifacts | [Static analysis](javascript-artifact-reconstruction.md), [tracing and comparisons](javascript-application-workflows.md), [application graph](javascript-application-graph.md), [source recovery](javascript-recovery.md) |
| Compare static JavaScript with runtime observations | [Runtime attribution](javascript-runtime-observation.md), [reconciliation](javascript-runtime-reconciliation.md), [Electron observation](electron-observation.md), [Electron fuses](electron-fuses.md) |
| Inspect assemblies, packages, or firmware | [Godot PCK](godot-pck.md), [.NET](managed-code-analysis.md), [Android](android-analysis.md), [Apktool resources](apktool-resource-analysis.md), [ADB acquisition](adb-device-analysis.md), [Apple](apple-application-analysis.md), [Harmony](harmony-analysis.md), [firmware](firmware-analysis.md), [WASM](wasm-artifacts.md), [EVM](evm-bytecode.md) |
| Observe or compare a browser scenario | [CDP observation](browser-observation.md), [scenarios](browser-scenario-contract.md), [runtime evidence](web-runtime.md), [historical captures](web-network-captures.md) |
| Serve recorded behavior as an agent environment | [Agent environments](agent-environments.md) |
| Trace captured website source | [Source locations](web-source-location.md), [module traces](website-module-trace.md), [script export](website-script-export.md) |
| Capture and compare a command | [Process capture](process-capture.md) |
| Use CLI/MCP and retain evidence | [CLI](cli.md), [MCP contracts](mcp-contracts.md), [agent prompts](mcp-prompts.md), [obligation ledgers](reconstruction-obligation-ledgers.md) |
For development, use [testing](testing.md), [client verification](client-verification.md),
[tool design](tool-design.md), and [releasing](releasing.md).
+33 -3
View File
@@ -340,6 +340,13 @@ A scoped report has `scope.mode: "explicit"`. Its `scope_checks` determine
`environment_healthy` summarizes the full audit. `--target` adds a target check,
but the report remains audit-wide unless a scope option is also supplied.
An invalid `REA_LOG_LEVEL` fails every scope, including one client or the
installed skill, because the executable rejects it before any command. A
selected client also fails for every other setting that MCP startup rejects,
including `REA_GHIDRA_STARTUP_TIMEOUT_MS` and `REA_HOPPER_STARTUP_TIMEOUT_MS`.
Those settings still fail a selected provider and the audit-wide result. A
skill-only report leaves them informational.
Follow the remediation for the failed check. If a native target has several
available providers, choose one with `--provider` on the CLI or `provider_id`
on `open_binary`. A `capability_unavailable` failure carries
@@ -987,6 +994,24 @@ can time out earlier even when Ghidra would complete within its startup deadline
See [Ghidra first-query deadlines and recovery](mcp-contracts.md#ghidra-first-query-deadlines-and-recovery)
for client options and the close/reopen recovery flow.
The 330-second default is configurable. Configuration is read when REA starts:
changing an environment variable in another shell, or closing and reopening a
binary in the same MCP server, does not change that server's startup allowance.
For a CLI retry with an example 30-minute allowance:
```sh
REA_GHIDRA_STARTUP_TIMEOUT_MS=1800000 rea analyze /absolute/path/to/app.exe --provider ghidra --json
```
For MCP, export useful Evidence before restarting, close the binary and resolve
any cleanup failure, update the environment in the client's REA server launch
configuration, then restart REA and reconnect before reopening the target. Allow
startup plus the query in the client's own tool-call deadline. Every retry uses
a fresh ephemeral import; smaller result requests do not reduce the prerequisite
auto-analysis. A larger time allowance does not raise the JVM heap limit or
guarantee completion. Keep [heap and host CPU controls](#ghidra-heap-and-cpu-controls)
appropriate for the machine.
One session contains exactly one imported Program; use `provider_id: "ghidra"`, `--provider ghidra`, or
`REA_ANALYSIS_PROVIDER=ghidra` when both Hopper and Ghidra support the target.
One persistent decompiler is owned by the Program, and a serial queue keeps
@@ -1089,9 +1114,14 @@ and hyphens; at most 32 names are admitted, each at most 120 characters.
Names must identify analyzers registered for the selected program. Unknown names
or options that remain enabled abort the headless import before auto-analysis
and the bridge, so an unsuccessful override cannot produce a session claiming
that the analyzer was disabled. For Windows PE resource analysis, the exact name
is `WindowsResourceReference`. Disabling an analyzer skips the facts it would
have produced.
that the analyzer was disabled. The setting applies to every import in the REA
server. A format-specific analyzer may not be registered for another target, so
the same override can prevent that target from opening. For mixed-target work,
omit the override or use a separate REA server configured for the affected
format. Changing the environment requires restarting the server; reopening a
target alone keeps the current setting. For Windows PE resource analysis, the
exact name is `WindowsResourceReference`. Disabling an analyzer skips the facts
it would have produced.
### Ghidra heap and CPU controls
+8
View File
@@ -13,6 +13,14 @@ rea doctor --provider kuna
Select it explicitly with `--provider kuna`, MCP's `open_binary.provider_id: "kuna"`, or `REA_ANALYSIS_PROVIDER=kuna`. With Kuna and another provider configured for the same target, `auto` reports `ambiguous` instead of choosing one.
Ordinary readiness cancellation returns `cancelled` (CLI SIGINT/SIGTERM exits
130/143); an earlier recorded timeout or physical failure keeps its diagnostic.
Completed version, hash and script observations remain in `kuna_installation`
with `status: "partial"` and `completed_hash` when available. Typed errors carry
this in `details.diagnostics`; doctor cleanup checks carry it in their `details`.
Omitted fields remain unobserved; availability remains unknown until readiness
completes. Cleanup retries keep both the observations and the exact file owner.
| Setting | Default | Meaning |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `REA_KUNA_COMMAND` | none (required) | Absolute path of the `kuna` executable. |
+5 -3
View File
@@ -119,9 +119,11 @@ returning an empty one.
The canonical parser admits PE/CLI bytes and their metadata/CIL without loading
an assembly. It reports observed implementation markers and unavailable facts;
it does not unpack .NET single-file hosts, decode IL2CPP metadata, or infer a
NativeAOT identity from an ordinary native PE. Inputs without admitted CLI
metadata do not become managed assemblies through naming or routing guesses.
it does not unpack .NET single-file hosts or infer a NativeAOT identity from an
ordinary native PE. It does not decode IL2CPP; use
[IL2CPP metadata](il2cpp-metadata.md) for the image, type and method names in a
Unity `global-metadata.dat`. Inputs without admitted CLI metadata do not
become managed assemblies through naming or routing guesses.
Inspect separately obtained components explicitly and preserve their identities.
A valid implementation marker establishes a candidate native boundary, not
+132 -5
View File
@@ -1,5 +1,9 @@
# MCP runtime contracts
For pairing native functions before comparing selected dossiers, see
[native function matching](native-function-matching.md). It operates on retained
inventories, preserves aliases/unknowns and exposes selected fact pages.
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 [transports](#transports)
@@ -22,6 +26,14 @@ directly to `compare_functions`, and `inspect_artifact` Evidence to
`compare_artifacts`. Use `get_evidence_bundle` when the task needs broader
retained session history or an explicit bundle for transfer.
Ghidra inventories and function replies use `raw_result: null` when their facts
are already preserved in `normalized_result`, limitations, locations and
relationship coverage. Distinct overview details, measured load-image
observations, file-offset selection roles and database types supplemented with
derived metadata keep their upstream representation. Read function results from
`normalized_result`; older retained Evidence keeps its original representation
and identity.
Artifact inventories declare `coverage.scope` (`root` or `container-entries`)
and `coverage.status` (`complete` or `unknown`) independently of diagnostic
wording. Comparison requires matching scopes, complete graph members and complete
@@ -59,7 +71,13 @@ Call comparison additionally retains the Evidence relationship coverage
checks. Ghidra and Hopper declare their observed dossier facets and complete
provider-observed caller/callee sets, including empty sets. Missing decompiler
output remains unavailable; complete call coverage does not claim every runtime
target. Hopper's unavailable reference-kind metadata and reported unresolved
target. When Ghidra's decompiler fails on one function, its dossier is still
returned: `pseudocode`, `native_api` and `native_value_flow` are unavailable
with the decompiler's failure as the reason, while the listing-backed facets
are collected as usual. These failed decompiler observations and workflows
derived from them retain Evidence but skip snapshot reuse, so a later request
can observe backend recovery; healthy dossiers keep their existing cache policy.
`procedure_pseudo_code` still fails for that function. Hopper's unavailable reference-kind metadata and reported unresolved
calls still prevent equality conclusions for those dimensions. Analysis profiles
version these declarations so older snapshots are not reused as current results.
IDA declares the facets its selected adapter cannot provide; an empty
@@ -72,13 +90,31 @@ metadata in the supported JSON payloads (`parameters`, `raw_result`,
Tool execution failures return `isError: true` and the complete canonical
`{ "error": ... }` diagnostic as JSON in text `content`. Read that diagnostic
for the error code, target details, partial observations, and remediation.
for the error code, target details, partial observations, remediation, and the
optional bounded `recovery` next step. `recovery.kind=inspect_input_contract`
names the rejected operation: re-read that operation's advertised input schema
(call `tools/list` if the catalog may be stale), correct the listed fields, and
do not repeat the unchanged call. `recovery.kind=inspect_timeout_state` names
the operation and the REA server/provider deadline; inspect partial Evidence
and reported cleanup state, then follow producer-specific remediation or reduce
supported work. Generic errors do not assume adjustable timeout controls. Raising
only the MCP client's deadline cannot extend this budget. These hints never
include the complete catalog or caller arguments.
Failures omit `structuredContent`, since each advertised `outputSchema`
describes successful results. Successful replies retain their schema-validated
structured data and matching text projection. Oversized errors are retained
as Evidence before delivery of a bounded diagnostic with an export reference;
if retention is unavailable or fails, the diagnostic reports that reason.
SDK-generated input validation failures are normalized into the same canonical
`invalid_request` text when the bounded diagnostic fits the response budget.
The complete field/type diagnostic is preserved when normalization fits the
response budget, including request-specific rejected fields and reasons. Oversized
SDK diagnostics keep the existing retained-Evidence recovery path. An unknown
tool remains an MCP JSON-RPC `-32602` error, but its message directs the caller
to `tools/list` and an advertised operation instead of repeating the unknown
name.
`get_call_graph` returns a `graph` keyed by traversal depth and a top-level
`limitations` array with deduplicated execution caveats. Each node keeps its
relationship coverage and read-specific `limitations`, alongside observed
@@ -93,8 +129,9 @@ unresolved relationship reads. Cancellation remains a tool error.
REA prepares complete MCP results within the pinned stdio client's 10 MiB
receive-buffer budget, including both text and structured representations and
room for the JSON-RPC envelope. Tool errors carry only their text
representation and `isError` flag, so only those count against the budget. Response budget settings are captured at startup;
room for the JSON-RPC envelope. Tool errors omit `structuredContent` from the
wire; their text, `isError`, provenance marker and negotiated protocol framing
count toward the wire budget. Response budget settings are captured at startup;
restart or recreate the server to apply changes. If a result cannot fit, REA returns
`resource_constraint` with `details.resource: "transport"` before constructing
a document-sized string. Analysis Evidence remains complete in the current
@@ -104,6 +141,52 @@ that reference for a summary, one section/module, or a stable page, or call
`export_evidence_bundle` with a destination path. Complete
bundle exports stream canonical JSON into an atomically published file.
On protocol revision `2026-07-28`, completed replies retain the SDK's
`resultType: "complete"`, including the replacement for an oversized error.
This marks completion of the MCP exchange; Evidence coverage, partial facts
and unknowns retain their separate meaning. Legacy replies keep their existing
framing.
`list_procedures`, `search_procedures`, `list_strings`, `search_strings` and
`list_names` accept `detail: "summary"`. Complete inline delivery remains the
default. Summary retains the original complete Evidence and returns its row
count, provider identity, analysis-profile digest, original query, parent Evidence
ID, limitations and explicit unknown discovery coverage. Delivery detail is excluded from provider arguments
and original Evidence identity.
Read selected rows with `inspect_analysis_view`:
```json
{
"source": {
"kind": "retained-evidence",
"evidence_id": "ev_<source digest>"
},
"view": {
"kind": "native-inventory",
"offset": 0,
"limit": 32,
"fields": ["value"]
}
}
```
Each row has `source_index` and `record`; parent Evidence ID plus source index
identifies same-address alternatives. Order is the original retained order.
Omit `fields` for complete records; a selected field list always retains
`record.address`. Selecting `value` also retains available `string` and
`decoding` qualifications, so native display text and unterminated fragments
remain distinguishable. Search tools apply their existing filters before retention.
Follow `coverage.next_offset`; exhaustion describes the retained list, not
complete discovery of all code or strings. An unbound source keeps
`artifact: null` and the derived Evidence keeps `subject: null`.
The CLI uses the same projector. For an original complete Evidence JSON file,
write `{"source":{"kind":"evidence-file","path":"/absolute/source.json"},"view":{"kind":"native-inventory","limit":32}}`
to `/absolute/view-request.json`, then run
`rea inspect-analysis-view /absolute/view-request.json --json`. This also reads
pre-summary source records without changing their identity; no live provider is started.
For oversized native function Evidence, `details.reported_limits.continuation`
contains a ready-to-call `inspect_analysis_view` request for the retained
pseudocode's first page. Use its `name` and `arguments` directly, then follow
@@ -112,6 +195,8 @@ limit is the view contract's default, not a guarantee that arbitrary source or
metadata fits; reduce the limit or export when needed. Continuations are
offered for completed `analyze_function` results only after session recording is
acknowledged; the complete result and its retention reference remain intact.
Oversized native inventories likewise include a ready-to-call first
`native-inventory` page. Reduce its limit or select fields when a row is large.
A broad follow-up or `get_evidence_bundle` can also exceed the response budget; exporting
preserves the complete session without sending it through a single MCP frame.
@@ -155,6 +240,23 @@ delivery for responses that fit that buffer and Node's single-string limit.
It does not change the client's buffer, analysis coverage, or retained content.
Ordinary responses keep their existing complete result contract.
### Error recovery and deadline ownership
Initialization instructions and the static JavaScript tool description teach
recovery before a host can discard a tool response. Invalid input calls should be corrected from the connected schema
(refresh `tools/list` only if stale), not retried unchanged. REA's returned
`provider_timeout` describes its server/provider deadline; provider-authored
remediation names the applicable controls and preserves partial Evidence and
cleanup uncertainty.
A host timeout without a REA result is different: execution and cleanup remain
unknown. Increasing an advertised `analysis_timeout_ms` cannot fix a shorter
client deadline. Configure the client's tool timeout with execution, cleanup
and delivery headroom, or report that change is needed when not authorized.
Session status does not establish that all target-free work stopped. Detailed
host settings and bounded retry guidance live in the shipped skill's
[recovery reference](https://github.com/morluto/rea/blob/main/.agents/skills/reverse-engineer-anything/references/connection-and-recovery.md#distinguish-client-and-server-deadlines).
### Untrusted target content
Strings, symbols, decompiled code and pseudocode, page text, script bodies,
@@ -218,13 +320,20 @@ 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
Evidence and `capture_browser_scenario` 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` also accepts `environment-state` for the same parents,
extracting the initial state the recorded reads observed: entity types with an
identity field, entities, documents for written non-entity paths, and a render
plan per read tool that reproduces its recordings from the state or names why it
cannot. Types and identity are inferences, so the Evidence is always inferred.
See [environment state](web-network-captures.md#environment-state).
`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,
@@ -419,6 +528,17 @@ concrete version, selection source, and complete analysis profile through
choices return typed selection details. A selected provider is never replaced
automatically after a runtime failure.
`open_bundle_resources` selects a separate read-only app resource session
without resolving `CFBundleExecutable`, including when it is absent or
unresolvable. `binary_session` reports `session_kind: "bundle_resources"` and the
caller and canonical resource-root paths; it does not report a binary target or
deep-provider binding. `inspect_plist`, `decode_interface_builder`,
`inspect_asset_catalog`, and `inspect_keyed_archive` retain resource-root
provenance and use a null Evidence subject when executable identity is unknown.
Binary-only operations and binary analysis snapshots do not apply in this
session. `open_binary` can switch back to executable analysis, and
`close_binary` retires either session kind.
Each provider client receives `binary_session.analysis_run.run_id` before any
provider startup, including clients whose startup fails. `process_lineage` is
`not_observed` until a dynamic provider starts, then becomes `snapshots` with
@@ -768,6 +888,13 @@ the current client, so it is not a fresh-start recovery. On the same connection:
`provider_id: "ghidra"`, then retry the first query with an appropriate client
deadline. The connection and selected provider do not need to change.
If REA's provider startup allowance also needs raising, preserve Evidence and
close as above, then update `REA_GHIDRA_STARTUP_TIMEOUT_MS` in REA's launch
environment and restart the server. Reconnect the MCP client before reopening
the target. Configuration is read at process startup; close/reopen on the same
connection cannot apply a changed environment. See the
[CLI retry example](installation.md#ghidra).
This close/reopen flow was exercised on one real Linux stdio connection after a
controlled startup timeout, followed by a successful overview and function
analysis. A separate Windows x64 stdio run with Ghidra 12.1.4, JDK 21 and Node
+145
View File
@@ -0,0 +1,145 @@
# Model file declarations
Use `inspect_model_artifact` (CLI: `inspect-model-artifact`) to inspect a local
GGUF v2/v3 or safetensors file. Detection uses content, including GGUF byte
order, rather than its extension. REA does not load a model, interpret weights,
run inference, import Python, open external-data references or use the network.
```bash
rea inspect-model-artifact /absolute/path/model.gguf --json
rea inspect-model-artifact /absolute/path/model.safetensors --hash full --json
```
The CLI defaults to complete Evidence. For compact delivery with portable access
to every retained observation:
```bash
rea inspect-model-artifact /absolute/path/model.gguf \
--detail summary --evidence_output /absolute/path/model-evidence.json --json
```
## Identity and reads
The default `hash: "header"` reads only the metadata and tensor directory. The
result records the exact selected path, file size, header length, header SHA-256,
bytes read and read scope. GGUF alignment padding is outside this prefix.
`artifact.sha256` and the Evidence subject are null: a header digest is not a
commitment to the weights. Different files can have identical headers and sizes.
`hash: "full"` additionally streams the remaining file bytes through SHA-256.
It returns a full-file digest and Evidence subject, while retaining the same
header digest. It uses bounded buffers and does not interpret tensor data, but
it does read the whole file. Cost therefore grows with file size. Both modes
check descriptor and selected-path identity and metadata before completion;
this detects observed replacement or modification, not adversarial modification
that defeats filesystem metadata checks.
## Facts and selected queries
GGUF reports version, byte order, alignment, typed metadata, and each tensor's
name, original type ID, dimensions, relative data offset, file offset and derived
byte length. Alignment accepts every positive UINT32 multiple of eight, including
non-powers of two. Metadata keys use ASCII lower-snake-case hierarchy components;
standard numeric components such as `general.base_model.0.name` are preserved.
Scalar metadata is complete. Arrays have declared element types,
counts and at most eight preview elements per array, with an explicit
`preview_complete` flag. This includes tokenizer vocabularies: omitted values
are not silently represented as a complete array. Strings are UTF-8; 64-bit
integer metadata and all shape dimensions use decimal strings without rounding.
Nonfinite floating metadata uses `NaN`, `+Infinity` or `-Infinity` with its
declared float type; negative zero is `"-0"`. Unknown tensor types retain their numeric IDs and null byte
lengths; affected totals and storage validation remain unknown.
Safetensors reports the header extent, exact string `__metadata__` values, dtype,
shape and declared data ranges. JSON duplicate keys, invalid UTF-8, out-of-file
ranges, overlaps, gaps, trailing unindexed data and known dtype/shape byte-length
contradictions are rejected with a typed `file_format_rejected` constraint (public code `target_unavailable`, category `unsupported_target`). Empty
tensors and scalar shapes are supported; packed sub-byte types require whole
byte storage. Unknown dtypes retain declared ranges and an explicit limitation
that shape-to-storage validation is unavailable. Each tensor records
`storage_validation: "consistent" | "unknown"`; `coverage.storage_sizes` remains
partial when that consistency cannot be checked. Tensor filters accept these
`storage_validation` states independently of dtype or name.
Parameter counts and per-type totals are **derived from declarations**, not
measurements of effective parameters or inference behavior. Shared or repeated
weights are not deduplicated. GGUF dimensions retain their original fastest-first
order; safetensors shapes retain JSON order. Safetensors tensor rows use name
order; GGUF rows use directory order. An index identifies a declaration within
its collection and header digest, not tensor contents or a cross-version match.
GGUF supports zero extents and scalar shapes, with at most four dimensions;
known quantized types still require complete blocks in the first dimension.
MCP defaults to a compact summary with counts, selected short headline metadata,
chat-template presence and derived totals. The full type histogram and all rows
remain in complete Evidence. Headline metadata uses short keys/types and scalar
values; long or compound values remain available through explicit metadata
queries. Use the returned `parent_evidence_id`:
```json
{
"source": {
"kind": "retained-evidence",
"evidence_id": "<parent_evidence_id>"
},
"view": {
"kind": "model-artifact",
"collection": "tensors",
"names": ["token_embd.weight", "output.weight"],
"fields": ["name", "type", "shape", "file_offset", "byte_length"],
"offset": 0,
"limit": 32
}
}
```
To answer a known question in the initial inspection, pass the same selection
without `kind` as `inspect_model_artifact`'s optional `view`, for example
`{"path":"/absolute/path/model.gguf","view":{"collection":"tensors","names":["token_embd.weight"],"fields":["type","shape","file_offset"]}}`.
This returns one selected page with compact model context and retains the full
source Evidence, avoiding another tool call. `view` requires summary delivery;
complete detail and a selection are rejected as conflicting choices.
CLI uses `--view '{"collection":"tensors","names":["token_embd.weight"]}'`
with `--detail summary --evidence_output FILE`.
Call `inspect_analysis_view` with the historical query object above for further pages. `collection: "metadata"` accepts
exact `keys`, indices, fields and paging; use it for `tokenizer.chat_template`
or tokenizer array previews. `collection: "types"` pages derived storage and
parameter totals and accepts exact `types`. Tensor pages also accept `types`.
Filters intersect; omitted filters mean all recorded rows and empty arrays mean
none. Every row retains its source-scoped index. Names, keys and type labels
follow field selection; `fields: []` returns only indices. Omitted fields return
all recorded columns. Compact warnings use the shared bounded view budget and
link to complete parent Evidence when messages are omitted. Page offsets count filtered
matches, while row indices retain their original scope. Each page carries source
identity, header coverage, array omissions, unknowns and parent Evidence links.
Pages read historical retained facts without reopening the model. Complete
Evidence can also be supplied inline or as a single authenticated Evidence JSON
record through `source: {"kind": "evidence-file", "path": "/absolute/path/model-record.json"}`.
CLI Evidence bundles contain a `records` array; import the bundle with
`import_evidence_bundle` before using retained queries, or save one complete
record as a standalone Evidence file. A bundle is not a single Evidence record.
The session owns validated indexes until that Evidence is released; there is no
live-file result cache or automatic freshness claim.
Imported reports must retain positional indices and unique names, keys and
type identities; malformed reports return a typed input error before indexing.
## Bounds and unsupported inputs
The reader admits one active inspection per provider. It enforces a 100,000,000
byte header ceiling (safetensors counts its declared JSON bytes separately from
the fixed eight-byte length prefix; GGUF counts the complete header) and a separate 32 MiB
retained representation budget before retaining rows or expanding strings.
Numeric products use exact integer arithmetic. GGUF follows its four-dimensional
tensor layout and limits metadata array nesting to 32 frames. Resource refusals
are typed, rather than returned as complete empty inventories. Cancellation
joins descriptor finalization; failed cleanup remains owned for retry.
PyTorch pickle and ZIP model deserialization are unsupported; convert using a
trusted external workflow and supply GGUF or safetensors. ONNX, TFLite, Core ML,
model execution and conversion are outside this operation.
Format references: [GGUF specification](https://github.com/ggml-org/ggml/blob/da8e2a54b919557b816b1c2beb432ccb766f7ce0/docs/gguf.md),
[ggml tensor layouts](https://github.com/ggml-org/ggml/blob/da8e2a54b919557b816b1c2beb432ccb766f7ce0/src/ggml-common.h),
[safetensors format](https://github.com/huggingface/safetensors/tree/e246a2560645b7525f5775669ed816eb57c5bcc8#format).
+120
View File
@@ -0,0 +1,120 @@
# Match native functions across builds
`match_native_functions` pairs two existing `list_procedures` Evidence inventories. Select `list_procedures` `detail: "summary"` to retain
complete source rows without transferring the entire inventory. Its
`parent_evidence_id` is the reference matching consumes.
Targets may be opened sequentially; matching never opens a target, rereads its
file, executes it or starts a provider. Preserve each inventory before closing its
target, or import its Evidence bundle later. `close_binary` clears session
records. Export each bundle before closing; after collecting both sides and
closing the last target, import both bundles, then use their references. Keeping
only an Evidence ID across close is insufficient. Complete inline Evidence and
CLI `source_bundle` inputs are portable alternatives. Pass Evidence or exact
session references as `left` and `right`:
```json
{
"left": { "kind": "retained-evidence", "evidence_id": "ev_<left digest>" },
"right": { "kind": "retained-evidence", "evidence_id": "ev_<right digest>" }
}
```
Unique exact reported names are paired first. Optional `list_names` Evidence
identifies dynamic/default names to exclude. If origin is unavailable, the
existing automatic-name exclusion rule applies and each function retains that
limitation. Exact names establish name correspondence, not unchanged code or
original-source identity.
For unmatched candidates, optionally supply `left_observations` and
`right_observations`. `procedure_info` or existing `analyze_function` Evidence
gives exact inclusive body ranges; `read_bytes` supplies memory bytes. Observations
must belong to the side's exact target/provider/profile and document context.
Adjacent, consistent overlapping and partially returned reads compose by their
observed extent; conflicting intervals remain gaps. A byte match requires every
body byte, equal total size, equal ordered range lengths, a unique SHA-256
fingerprint and the same known architecture. Extents are never guessed from the
next entry, and relocations are not normalized. A larger mapped read can serve
several observed bodies; only needed ranges need to be captured.
This first slice reuses existing range observations. Stripped builds can require
many lightweight range queries when those facts are not retained yet. Matching
does not hide that acquisition cost or silently start those queries. Full
decompilation is unnecessary.
Repeated candidates stay `unresolved` groups without a Cartesian pair expansion.
`only_left`/`only_right` mean no exact counterpart in the supplied observations;
renaming, inlining, stripping, changed bytes or incomplete discovery can explain
them. They do not prove source addition/removal. `source_coverage` explicitly keeps
inventory completeness unknown and separately counts known byte fingerprints and
resolved correspondence. Provider limitations remain accessible.
Default `detail: "summary"` retains complete matching Evidence in MCP and returns
counts, both identities and coverage. Query its `parent_evidence_id`:
```json
{
"source": {
"kind": "retained-evidence",
"evidence_id": "ev_<matching digest>"
},
"view": {
"kind": "function-matches",
"collection": "functions",
"states": ["matched"],
"sides": ["left"],
"fields": ["name", "body_sha256"],
"offset": 0,
"limit": 20
}
}
```
`collection: "matches"` returns relation identities, states, basis and member
counts. Large member lists are omitted by default; select `left`/`right` columns
explicitly or page individual `functions`. Batch `match_ids`/`function_ids`, exact function `names`, state
and side filters intersect. Mandatory identities and provenance survive column
selection. Page coverage covers selected retained facts. Function identity binds
inventory Evidence and the owning inventory’s `source_index`, preserving same-address alternatives.
One validation, lazy member index and bounded recent filter are retained per
immutable parent; no live target state is cached.
When both functions already have unambiguous `analyze_function` dossiers, a matched
relation includes `compare_functions_input` with directly usable retained
references. Otherwise analyze just the selected canonical addresses in their
respective targets, then compare those dossiers. Matching never claims behavioral
equivalence. Optional informative CFG/call/string fingerprints from supplied
dossiers connect unresolved candidate groups only. They require observed CFG,
callees and strings, complete observed call coverage, no unresolved calls, and
the same analysis-profile identity. Empty leaf-function buckets are excluded.
`structural_candidate_sha256` identifies that derived candidate signature; its
dossier link preserves the full supporting facts. Group membership does not
assert that every member pair is a candidate or equivalent.
CLI uses the same service and JSON input:
```bash
rea match-native-functions request.json \
--source_bundle left-bundle.json --source_bundle right-bundle.json \
--evidence_output matching-bundle.json --json
```
`source_bundle` resolves exact references from authenticated local bundles.
Default summary requires `evidence_output`, retaining full matching Evidence and
its selected source closure, including transitive Evidence links across supplied
bundles. Missing dependencies fail with an integrity error; unrelated records
are omitted. Publication never overwrites. Set `detail: "complete"`
in the JSON for all groups inline. Import the bundle into MCP for views, or
extract its matching Evidence record to a JSON file for the existing CLI
`inspect-analysis-view` `evidence-file` source. Input bundles are unchanged.
Representation admission is bounded at 96 MiB before cloning selected observations
and expanding matching indexes and repeated per-function source links. Work yields to cancellation. No worker/provider
concurrency is introduced; this budget is not a bound on total process RSS.
The self-owned source fixture is [nativeFunctionMatching.c](https://github.com/morluto/rea/blob/main/tests/fixtures/nativeFunctionMatching.c).
On Linux x86-64, compile with `cc -O2 -g0 -fno-pie -no-pie -DVERSION=1` and
`-DVERSION=2`; copy the second binary and run `strip --strip-all` on that copy.
It includes unchanged/changed code, a byte-identical rename, a removed/added
observation, an inlined function, identical-code aliases and a renamed changed
function with an observed call/string signature. Analyze without executing the
fixture. Full-provider verification still needs caller-supplied Ghidra and Java.
+31 -1
View File
@@ -425,10 +425,25 @@ complete observation.
vtable descriptors. Records include exact virtual addresses/file offsets and
artifact evidence. Vtable indexes are metadata word offsets; witness indexes
start after the conformance header. Names unavailable in metadata remain null.
The `swift_class_vtable_descriptors` coverage counters count examined vtable
slots and successfully decoded slots, rather than type-section entries.
The `objc_class_method_ivar_metadata` counters count admitted class and
metaclass objects and successfully decoded objects.
Pointers are decoded through the image's fixups:
- `LC_DYLD_CHAINED_FIXUPS` rebases and binds, including the authenticated
arm64e formats;
- legacy `LC_DYLD_INFO` bind opcodes.
- legacy `LC_DYLD_INFO` rebase and bind opcodes.
A Swift conformance whose type or protocol reference is an external bind
keeps its name as `null` and carries the raw dyld identity in
`type_binding` or `protocol_binding`; that record and its facet coverage are
partial. Consumers of this output must handle nullable conformance names
and use the typed binding fields instead of substituting a symbol as a
display name. Indirect relative-pointer records also retain their binding
identity. A decoded rebase to virtual address zero remains an address; only
an unfixed zero in a nullable ABI field is treated as null. Incomplete or
conflicting fixup streams keep affected pointers unresolved; coverage reports
parsing and resource limits while retaining validated prefix facts.
So an external superclass resolves from its `_OBJC_CLASS_$_` bind (for
example `NSObject`). The `pointer_fixups` coverage facet names the mechanism.
@@ -466,6 +481,21 @@ complete observation.
that operation is unavailable; runtime failures remain failures rather than
being replaced by symbol-only results.
`get_objc_classes` keeps names from the provider inventory. It coalesces rows
only when their exact selected-image pointer slots decode to the same class
import, including its binding stream, raw library ordinal, resolved library, weak status, and addend. A literal filter is
applied to the original names before that join; if the filter selects only an
alias, the output keeps that exact row. `identity_coverage` distinguishes a
complete selected-inventory scan from partial, unsupported, and unknown cases.
Recognized Mach-O formats outside the native metadata reader's support retain
the provider's class labels with unknown import identity; malformed headers and
read failures remain errors.
The join also requires matching whole-artifact digests and matching provider-
owned selected-image facts: container, byte range, full raw CPU type/subtype,
and FAT table digest when present. A missing or overridden loader selection
remains unknown; the result describes agreement on the selected artifact image,
not an atomic observation of a running process or whole-program class coverage.
## Native desktop observation
`observe_native_ui` captures one explicitly selected existing PID/window ID.
+9 -2
View File
@@ -10,10 +10,17 @@ Supply an existing TShark 4.x installation **on Linux**, with util-linux
`prlimit` available at `/usr/bin/prlimit`. Override its absolute path with
`REA_TSHARK_PRLIMIT_COMMAND` if required. Unsupported hosts, including macOS
and Windows, are refused before inspection because this integration requires
an enforced address-space limit:
an enforced address-space limit.
TShark selection follows the same rule as [`inspect_pcap_capture`](pcap-analysis.md):
an absolute `REA_TSHARK_COMMAND`, otherwise `tshark` from the first absolute
`PATH` entry that holds an executable file. A relative `REA_TSHARK_COMMAND` is
refused rather than looked up. Either way the selected executable is resolved,
hashed and rechecked after each run, and Evidence records its
`selection_source` (`environment` or `path`):
```sh
export REA_TSHARK_COMMAND=/absolute/path/to/tshark
export REA_TSHARK_COMMAND=/absolute/path/to/tshark # optional when tshark is on PATH
rea inspect-packet-capture /artifacts/device.pcapng \
--fields ip.addr --fields udp.port --fields data.data \
--display_filter 'udp' --format json
+10 -1
View File
@@ -17,7 +17,16 @@ rea inspect-pcap-capture /captures/session.pcapng --json
```
Without explicit tool commands, this family resolves them through PATH and
records that selection source. Client inspection reads no capture file. Capture
records that selection source. On Linux and macOS it runs the tool found in the
first absolute PATH entry holding an executable file, the same selection the
[packet capture tools](packet-captures.md) make; relative PATH entries are
skipped. Windows keeps PATH/PATHEXT resolution in the process launcher. Client
inspection reads no capture file; on hosts where PATH/PATHEXT does not expose
an absolute candidate, its executable digest and resolved path are reported as
unresolved. Otherwise the canonical executable path and SHA-256 are reported.
The pcap provider and packet tools share the selected-tool identity check, and
changes to a resolved executable during a run fail with artifact-changed
Evidence. Capture
inspection requires Linux with util-linux prlimit or Windows with owned Job
Objects. macOS capture inspection returns a capability gap because the new
native memory boundary is unverified; its version probes remain available.
+2
View File
@@ -146,6 +146,7 @@ npx rea-agents@latest setup
| شيفرة EVM البايتية | محددات التوجيه، وإزاحات البايتات، والمعاملات المستنتجة، وقابلية تغيير الحالة | مدخل محلي يحمل بايتات خامًا أو تمثيلًا سداسيًا عشريًا على Linux x64؛ [دليل EVM دون تشغيل](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| أعطال Linux المسجّلة | سجلات note الخام، ومسجّلات المعالج/الإشارات لكل خيط مسجّل، وترشيحات اختيارية لخرائط الذاكرة | pwntools يوفّره المستدعي على Linux x64؛ GDB/pwndbg اختياريان؛ [الأعطال المسجّلة](../recorded-crashes.md) |
| تثبيتات سطح المكتب | عائلات وقت التشغيل، والملفات الداعمة، وعلامات المكونات، والخطوات التالية | فحص محدود للملفات والترويسات;[تطبيقات سطح المكتب](../desktop-applications.md) |
| JavaScript / Electron | الوحدات، وعمليات الاستيراد، وخرائط المصدر، والمسارات، وIPC، وعلاقات إضافات الشيفرة الأصلية | Node.js وnpm؛ [تحليل التطبيقات](../javascript-application-workflows.md) |
| المواقع | بنية الصفحة، والسكربتات، وملاحظات الشبكة، ولقطات الشاشة المطلوبة | متصفح من عائلة Chrome؛ [تحليل المتصفح](../browser-observation.md) |
| تسجيلات الشبكة المحفوظة | الطلبات، والاستجابات، ومحتويات الحمولة المتاحة، ومواضعها في المصدر | HAR؛ وmitmdump على Linux لتسجيلات mitmproxy بصيغتها الأصلية؛ [دليل تسجيلات الشبكة](../web-network-captures.md) |
@@ -265,6 +266,7 @@ npx rea-agents@latest setup
- [التثبيت والإعداد](../installation.md): تسجيل الوكلاء، وتهيئة الموفّرين، والتحديثات، وإلغاء التثبيت.
- [الجاهزية واستكشاف الأخطاء](../installation.md#check-readiness-for-your-task): تشخيص وكيل أو محرك تحليل محدد.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI وEvidence](../cli.md): الأوامر، واختيار الموفّر، واللقطات، والاستيراد/التصدير، وحالات الخروج.
- [عقود MCP](../mcp-contracts.md) و[تعليمات الوكلاء](../mcp-prompts.md): نتائج الأدوات، والجلسات، والاستقصاءات الموجّهة.
- [كتالوج الأدوات](../mcp-contracts.md#generated-catalog): قائمة الأدوات والموفّرين وأوامر CLI المولّدة أثناء البناء.
+2
View File
@@ -146,6 +146,7 @@ REA benötigt Node.js 22.x (>=22.19), 24.x (>=24.11) oder 26+ sowie npm. Zusätz
| EVM-Bytecode | Dispatch-Selektoren, Byte-Offsets, abgeleitete Argumente und Veränderbarkeit des Zustands | Lokale Eingabe mit Rohbytes oder Hexdarstellung unter Linux x64; [Offline-EVM-Leitfaden](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Aufgezeichnete Linux-Abstürze | Unverarbeitete Note-Einträge, Register/Signale aller aufgezeichneten Threads und optionale Zuordnungskandidaten | Vom Aufrufer bereitgestelltes pwntools unter Linux x64; optional GDB/pwndbg; [aufgezeichnete Abstürze](../recorded-crashes.md) |
| Desktop-Installationen | Laufzeitkandidaten, Quelldateien, Komponenten und nächste Schritte | Begrenzte Verzeichnis- und Headerprüfung;[Desktop-Anwendungen](../desktop-applications.md) |
| JavaScript / Electron | Module, Imports, Source Maps, Routen, IPC und Beziehungen zu nativen Add-ons | Node.js und npm; [Anwendungsanalyse](../javascript-application-workflows.md) |
| Websites | Seitenstruktur, Skripte, Netzwerkbeobachtungen und angeforderte Screenshots | Ein Browser aus der Chrome-Familie; [Browseranalyse](../browser-observation.md) |
| Gespeicherte Netzwerkaufzeichnungen | Anfragen, Antworten, zugängliche Nutzdaten und Quellpositionen | HAR; mitmdump unter Linux für Aufzeichnungen im nativen mitmproxy-Format; [Leitfaden zu Netzwerkaufzeichnungen](../web-network-captures.md) |
@@ -263,6 +264,7 @@ Beginne mit den [praxisnahen Anleitungen](https://rea.tools/de/guides/) auf der
- [Installation und Einrichtung](../installation.md): Agentenregistrierung, Provider-Konfiguration, Updates und Deinstallation.
- [Bereitschaft und Fehlerbehebung](../installation.md#check-readiness-for-your-task): Diagnose eines bestimmten Agenten oder einer Analyse-Engine.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI und Evidence](../cli.md): Befehle, Provider-Auswahl, Snapshots, Import/Export und Exit-Status.
- [MCP-Kontrakte](../mcp-contracts.md) und [Agenten-Prompts](../mcp-prompts.md): Werkzeugergebnisse, Sitzungen und geführte Untersuchungen.
- [Werkzeugkatalog](../mcp-contracts.md#generated-catalog): Beim Build erzeugtes Inventar von Werkzeugen, Providern und CLI-Befehlen.
+2
View File
@@ -153,6 +153,7 @@ npx rea-agents@latest setup
| Bytecode EVM | Selectors επιλογής συνάρτησης, μετατοπίσεις σε bytes, εκτιμώμενα ορίσματα και δυνατότητα μεταβολής της κατάστασης | Τοπική είσοδος σε ακατέργαστα bytes ή δεκαεξαδική μορφή σε Linux x64· [οδηγός EVM χωρίς εκτέλεση](../evm-bytecode.md) |
| Βάσεις δεδομένων SQLite | Πίνακες, στήλες, ευρετήρια, όψεις, triggers και επιλεγμένες γραμμές κανονικών πινάκων | Τοπικό στιγμιότυπο βάσης δεδομένων/WAL· Node.js 24.x >=24.15 ή 26+ με εγγενή όρια SQLite |
| Καταγεγραμμένες καταρρεύσεις στο Linux | Ακατέργαστες εγγραφές notes, καταχωρητές/σήματα κάθε καταγεγραμμένου νήματος και προαιρετικές πιθανές αντιστοιχίσεις μνήμης | pwntools που παρέχει ο χρήστης σε Linux x64· προαιρετικά GDB/pwndbg· [καταγεγραμμένες καταρρεύσεις](../recorded-crashes.md) |
| Εγκαταστάσεις επιφάνειας εργασίας | Υποψήφια περιβάλλοντα εκτέλεσης, αρχεία τεκμηρίωσης, στοιχεία και επόμενα βήματα | Περιορισμένη επιθεώρηση καταλόγων και κεφαλίδων;[Εφαρμογές επιφάνειας εργασίας](../desktop-applications.md) |
| JavaScript / Electron | Modules, εισαγωγές, source maps, διαδρομές, IPC και σχέσεις με πρόσθετα κώδικα μηχανής | Node.js και npm· [ανάλυση εφαρμογών](../javascript-application-workflows.md) |
| Ιστότοποι | Δομή σελίδων, scripts, παρατηρήσεις δικτύου και ζητούμενα στιγμιότυπα οθόνης | Πρόγραμμα περιήγησης της οικογένειας Chrome· [ανάλυση μέσω προγράμματος περιήγησης](../browser-observation.md) |
| Αποθηκευμένες καταγραφές δικτύου | Αιτήματα, αποκρίσεις, διαθέσιμα δεδομένα φορτίου και θέσεις στην πηγή | HAR ή SAZ του Fiddler Everywhere· mitmdump σε Linux για την εγγενή μορφή mitmproxy· [οδηγός καταγραφών](../web-network-captures.md) |
@@ -276,6 +277,7 @@ npx rea-agents@latest setup
- [Εγκατάσταση και ρύθμιση](../installation.md): καταχώριση agents, ρύθμιση παρόχων ανάλυσης, ενημερώσεις και απεγκατάσταση.
- [Έλεγχος ετοιμότητας και αντιμετώπιση προβλημάτων](../installation.md#check-readiness-for-your-task): διάγνωση ενός agent ή μιας μηχανής ανάλυσης.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI και Evidence](../cli.md): εντολές, επιλογή παρόχου, στιγμιότυπα, εισαγωγή/εξαγωγή και κωδικοί εξόδου.
- [Προδιαγραφές MCP](../mcp-contracts.md) και [prompts για agents](../mcp-prompts.md): αποτελέσματα εργαλείων, συνεδρίες και καθοδηγούμενες διερευνήσεις.
- [Κατάλογος εργαλείων](../mcp-contracts.md#generated-catalog): αυτόματα παραγόμενος κατάλογος εργαλείων, παρόχων και εντολών CLI.
+2
View File
@@ -146,6 +146,7 @@ REA requiere Node.js 22.x (>=22.19), 24.x (>=24.11) o 26+, además de npm. Las h
| Bytecode EVM | Selectores de despacho, desplazamientos en bytes, argumentos inferidos y mutabilidad | Entrada local con bytes sin procesar o representación hexadecimal, en Linux x64; [guía de EVM sin ejecutar](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Fallos de Linux registrados | Registros note sin procesar, registros/señales de cada hilo registrado y posibles correspondencias de memoria opcionales | pwntools proporcionado por quien llama, en Linux x64; GDB/pwndbg opcionales; [fallos registrados](../recorded-crashes.md) |
| Instalaciones de escritorio | Posibles entornos de ejecución, archivos de evidencia, componentes y siguientes pasos | Inspección acotada de directorios y cabeceras;[Aplicaciones de escritorio](../desktop-applications.md) |
| JavaScript / Electron | Módulos, importaciones, mapas de código fuente, rutas, IPC y relaciones con complementos nativos | Node.js y npm; [análisis de aplicaciones](../javascript-application-workflows.md) |
| Sitios web | Estructura de la página, scripts, observaciones de red y capturas de pantalla solicitadas | Un navegador de la familia Chrome; [análisis del navegador](../browser-observation.md) |
| Capturas de red guardadas | Solicitudes, respuestas, contenido accesible de las cargas útiles y ubicaciones de origen | HAR; mitmdump en Linux para capturas en formato nativo de mitmproxy; [guía de capturas](../web-network-captures.md) |
@@ -263,6 +264,7 @@ Empieza con las [guías prácticas](https://rea.tools/es/guides/) del sitio web.
- [Instalación y configuración](../installation.md): registro de agentes, configuración de proveedores, actualizaciones y desinstalación.
- [Preparación y resolución de problemas](../installation.md#check-readiness-for-your-task): diagnóstico de un agente o motor de análisis concreto.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI y Evidence](../cli.md): comandos, selección de proveedores, instantáneas, importación/exportación y estados de salida.
- [Contratos de MCP](../mcp-contracts.md) y [prompts para agentes](../mcp-prompts.md): resultados de herramientas, sesiones e investigaciones guiadas.
- [Catálogo de herramientas](../mcp-contracts.md#generated-catalog): inventario de herramientas, proveedores y comandos de CLI generado durante la compilación.
+2
View File
@@ -138,6 +138,7 @@ REA به Node.js 22.x (>=22.19)، 24.x (>=24.11) یا 26+، به‌همراه np
| بایت‌کد EVM | selectorهای dispatch، offsetهای بایتی، آرگومان‌های استنباط‌شده و قابلیت تغییر وضعیت | دادهٔ خام/hex محلی روی Linux x64؛ [راهنمای EVM آفلاین](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| کرش‌های ثبت‌شدهٔ لینوکس | یادداشت‌های خام، رجیسترها/سیگنال‌های تمام threadهای ثبت‌شده و گزینه‌های احتمالی نگاشت | pwntools تأمین‌شده توسط فراخواننده روی Linux x64؛ GDB/pwndbg اختیاری؛ [کرش‌های ثبت‌شده](../recorded-crashes.md) |
| نصب‌های دسکتاپ | نامزدهای زمان اجرا، فایل‌های شاهد، نشانه‌های مؤلفه‌ها و مراحل بعدی | بررسی محدود پوشه‌ها و سرآیندها;[برنامه‌های دسکتاپ](../desktop-applications.md) |
| JavaScript / Electron | ماژول‌ها، importها، source mapها، مسیرها، IPC و ارتباط افزونه‌های بومی | Node.js و npm؛ [تحلیل برنامه](../javascript-application-workflows.md) |
| وب‌سایت‌ها | ساختار صفحه، اسکریپت‌ها، مشاهدات شبکه و اسکرین‌شات‌های درخواستی | مرورگر مبتنی بر Chrome؛ [تحلیل مرورگر](../browser-observation.md) |
| داده‌های ضبط‌شدهٔ شبکه | درخواست‌ها، پاسخ‌ها، payloadهای آشکارشده و مکان آن‌ها در منبع | HAR؛ ابزار mitmdump در لینوکس برای ضبط‌های بومی mitmproxy؛ [راهنمای ضبط شبکه](../web-network-captures.md) |
@@ -248,6 +249,7 @@ npx rea-agents@latest setup
- [نصب و راه‌اندازی](../installation.md): ثبت ایجنت، پیکربندی ارائه‌دهنده، به‌روزرسانی و حذف نصب.
- [آمادگی و رفع اشکال](../installation.md#check-readiness-for-your-task): عیب‌یابی یک ایجنت یا موتور تحلیل.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI و شواهد](../cli.md): دستورات، انتخاب ارائه‌دهنده، snapshotها، ورود/خروج داده و وضعیت‌های خروج.
- [قراردادهای MCP](../mcp-contracts.md) و [پرامپت‌های ایجنت](../mcp-prompts.md): نتایج ابزارها، نشست‌ها و بررسی‌های هدایت‌شده.
- [فهرست ابزارها](../mcp-contracts.md#generated-catalog): فهرست تولیدشده هنگام build از ابزارها، ارائه‌دهندگان و دستورات CLI.
+2
View File
@@ -150,6 +150,7 @@ REA nécessite Node.js 22.x (>=22.19), 24.x (>=24.11) ou 26+, ainsi que npm. Les
| Bytecode EVM | Sélecteurs de dispatch, offsets en octets, arguments inférés et mutabilité | Fichier local brut ou hexadécimal sous Linux x64 ; [guide EVM hors ligne](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Crashs Linux enregistrés | Notes brutes, registres et signaux de chaque thread enregistré, et correspondances de mappings facultatives | pwntools fourni par l'utilisateur sous Linux x64 ; GDB/pwndbg en option ; [crashs enregistrés](../recorded-crashes.md) |
| Installations de bureau | Environnements candidats, fichiers justificatifs, composants et étapes suivantes | Inspection bornée des répertoires et en-têtes;[Applications de bureau](../desktop-applications.md) |
| JavaScript / Electron | Modules, imports, source maps, routes, IPC et relations avec les modules natifs | Node.js et npm ; [analyse d'applications](../javascript-application-workflows.md) |
| Sites web | Structure des pages, scripts, observations réseau et captures d'écran demandées | Un navigateur de la famille Chrome ; [analyse du navigateur](../browser-observation.md) |
| Captures réseau enregistrées | Requêtes, réponses, payloads exposés et emplacements dans le code source | HAR ; mitmdump sous Linux pour les captures mitmproxy natives ; [guide des captures](../web-network-captures.md) |
@@ -267,6 +268,7 @@ Commencez par les [guides pas à pas](https://rea.tools/fr/guides/) du site web.
- [Installation et configuration](../installation.md) : enregistrement des agents, configuration des fournisseurs, mises à jour et désinstallation.
- [Vérification et dépannage](../installation.md#check-readiness-for-your-task) : diagnostiquer un agent ou un moteur d'analyse donné.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI et Evidence](../cli.md) : commandes, choix du fournisseur, snapshots, import/export et codes de sortie.
- [Contrats MCP](../mcp-contracts.md) et [prompts pour agents](../mcp-prompts.md) : résultats des outils, sessions et investigations guidées.
- [Catalogue des outils](../mcp-contracts.md#generated-catalog) : inventaire des outils, fournisseurs et commandes CLI, généré lors du build.
+2
View File
@@ -153,6 +153,7 @@ Alat tambahan dan dukungan sistem host bergantung pada target yang dianalisis:
| Bytecode EVM | Selector dispatch, offset byte, argumen yang disimpulkan, dan sifat mutabilitas | Pembawa data raw/hex lokal; [panduan EVM offline](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Crash Linux yang direkam | Catatan mentah, register/sinyal setiap thread yang direkam, dan kandidat pemetaan opsional | pwntools yang disediakan pemanggil; GDB/pwndbg opsional; [crash yang direkam](../recorded-crashes.md) |
| Instalasi desktop | Kandidat runtime, berkas pendukung, penanda komponen, dan langkah berikutnya | Pemeriksaan direktori dan header terbatas;[Aplikasi desktop](../desktop-applications.md) |
| JavaScript / Electron | Modul, impor, source map, rute, IPC, dan hubungan add-on native | Node.js dan npm; [analisis aplikasi](../javascript-application-workflows.md) |
| Situs web | Struktur halaman, skrip, pengamatan jaringan, dan tangkapan layar yang diminta | Peramban berbasis Chrome; [analisis peramban](../browser-observation.md) |
| Rekaman jaringan tersimpan | Permintaan, respons, payload yang terekspos, dan lokasi sumber | HAR; mitmdump di Linux untuk rekaman native mitmproxy; [panduan rekaman](../web-network-captures.md) |
@@ -288,6 +289,7 @@ Untuk mengetahui opsi, prasyarat, dan kontrak hasil secara tepat:
- [Instalasi dan penyiapan](../installation.md): pendaftaran agen, konfigurasi penyedia, pembaruan, dan penghapusan instalasi.
- [Kesiapan dan pemecahan masalah](../installation.md#check-readiness-for-your-task): mendiagnosis satu agen atau mesin analisis.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI dan Bukti](../cli.md): perintah, pemilihan penyedia, snapshot, impor/ekspor, dan status keluar.
- [Kontrak MCP](../mcp-contracts.md) dan [prompt agen](../mcp-prompts.md): hasil alat, sesi, dan investigasi terpandu.
- [Katalog alat](../mcp-contracts.md#generated-catalog): inventaris alat, penyedia, dan perintah CLI yang dibuat secara otomatis.
+2
View File
@@ -150,6 +150,7 @@ REA richiede Node.js 22.x (>=22.19), 24.x (>=24.11) o 26+, oltre a npm. Strument
| Bytecode EVM | Selettori di dispatch, offset dei byte, argomenti inferiti e mutabilità | Carrier raw/hex locale; [guida EVM offline](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Crash Linux registrati | Note grezze, registri/segnai di ogni thread registrato e candidati mapping opzionali | pwntools fornito dal chiamante; GDB/pwndbg opzionale; [crash registrati](../recorded-crashes.md) |
| Installazioni desktop | Runtime candidati, file di supporto, componenti e passi successivi | Ispezione limitata di directory e intestazioni;[Applicazioni desktop](../desktop-applications.md) |
| JavaScript / Electron | Moduli, import, source map, route, IPC e relazioni con add-on nativi | Node.js e npm; [analisi delle applicazioni](../javascript-application-workflows.md) |
| Siti web | Struttura della pagina, script, osservazioni di rete e screenshot richiesti | Un browser della famiglia Chrome; [analisi browser](../browser-observation.md) |
| Acquisizioni di rete salvate | Richieste, risposte, payload esposti e posizioni sorgente | HAR; mitmdump su Linux per acquisizioni mitmproxy native; [guida alle acquisizioni](../web-network-captures.md) |
@@ -267,6 +268,7 @@ Inizia dalle [guide pratiche](https://rea.tools/it/guides/) del sito web. Per op
- [Installazione e configurazione](../installation.md): registrazione agente, configurazione provider, aggiornamenti e disinstallazione.
- [Pronto all'uso e risoluzione dei problemi](../installation.md#check-readiness-for-your-task): diagnostica un agente o un motore di analisi.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI ed Evidence](../cli.md): comandi, selezione provider, snapshot, import/export e stati di uscita.
- [Contratti MCP](../mcp-contracts.md) e [prompt agente](../mcp-prompts.md): risultati degli strumenti, sessioni e indagini guidate.
- [Catalogo strumenti](../mcp-contracts.md#generated-catalog): inventario generato di strumenti, provider e comandi CLI.
+2
View File
@@ -146,6 +146,7 @@ REA には Node.js 22.x(>=22.19)、24.x(>=24.11)、または 26+ と npm
| EVM バイトコード | ディスパッチセレクター、バイトオフセット、推定された引数と状態変更の可否 | Linux x64 上のローカルの生バイト/16 進数の入力ファイル;[オフライン EVM ガイド](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| 記録済みの Linux クラッシュ | 生の note レコード、記録された全スレッドのレジスター/シグナル、任意のマッピング候補 | Linux x64 で利用者が用意する pwntools;GDB/pwndbg は任意;[記録済みクラッシュ](../recorded-crashes.md) |
| デスクトップのインストール先 | ランタイム候補、根拠ファイル、コンポーネントの目印、次の調査手順 | 上限付きのディレクトリ・ヘッダー検査;[デスクトップアプリ](../desktop-applications.md) |
| JavaScript / Electron | モジュール、インポート、ソースマップ、ルート、IPC、ネイティブアドオンの関係 | Node.js と npm;[アプリケーション分析](../javascript-application-workflows.md) |
| ウェブサイト | ページ構造、スクリプト、ネットワークの観測結果、依頼されたスクリーンショット | Chrome 系ブラウザー;[ブラウザー分析](../browser-observation.md) |
| 保存済みのネットワークキャプチャ | リクエスト、レスポンス、取得可能なペイロード、ソース内の位置 | HAR;mitmproxy ネイティブ形式のキャプチャには Linux 上の mitmdump;[キャプチャガイド](../web-network-captures.md) |
@@ -265,6 +266,7 @@ npx rea-agents@latest setup
- [インストールとセットアップ](../installation.md):エージェントの登録、プロバイダーの設定、更新、アンインストール。
- [準備状況の確認とトラブルシューティング](../installation.md#check-readiness-for-your-task):特定のエージェントや分析エンジンを診断。
- [GGUF / safetensors](../model-artifacts.md)
- [CLI と Evidence](../cli.md):コマンド、プロバイダーの選択、スナップショット、インポート/エクスポート、終了ステータス。
- [MCP 契約](../mcp-contracts.md)と[エージェント向けプロンプト](../mcp-prompts.md):ツールの結果、セッション、ガイド付き調査。
- [ツールカタログ](../mcp-contracts.md#generated-catalog):ビルド時に生成されるツール、プロバイダー、CLI コマンドの一覧。
+31 -25
View File
@@ -117,6 +117,10 @@ REA는 빠르게 바뀌며 새 릴리스에는 버그 수정이 자주 포함됩
rea update
```
`rea --update`는 이 검증된 업데이트 절차의 별칭이며 같은 전역 출력 플래그를 사용할 수 있습니다. 다른 명령 제어 옵션과 함께 사용할 때는 `rea update`를 사용하세요.
업데이트 명령은 stdout과 stderr를 합쳐 최대 4 MiB까지만 보관합니다. 한도를 넘긴 메타데이터 응답은 명령이 종료된 뒤 거부됩니다. 상세 출력을 사용하는 설치에서는 진단 정보를 한도 내에서만 보관하고 설치를 계속 진행합니다. 사람이 읽는 진행 출력은 터미널이 받아들이는 속도에 맞춰 전달되며, 이미 제출한 쓰기가 끝날 때까지 기다립니다.
Bun 전역 업데이트에는 Bun 1.2.17 이상이 필요합니다. 이전 버전의 Bun을 사용한다면 `rea update`를 실행하기 전에 Bun을 직접 업그레이드하세요.
에이전트 등록과 스킬을 갱신하려면 업데이트 과정에서 출력된 설정 명령을 실행하세요.
@@ -143,31 +147,32 @@ npx rea-agents@latest setup
REA에는 Node.js 22.x(>=22.19), 24.x(>=24.11) 또는 26+와 npm이 필요합니다. 추가 도구와 호스트 지원은 대상에 따라 다릅니다.
| 대상 | REA가 반환하는 내용 | 요구 사항 및 가이드 |
| --------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| 네이티브 바이너리 | 의사 코드, 어셈블리, 문자열, 심볼, 호출, 참조 | Hopper, Ghidra 또는 IDA; [네이티브 분석](../native-investigation.md) |
| 오프라인 ELF 레이아웃 | 섹션, 세그먼트, 원본 심볼/재배치 정보, 정적 분석으로 얻은 보안 완화 기법 후보 | Linux x64에서 호출자가 제공하는 pwntools; [바이너리 진단](../binary-diagnostics.md) |
| Go 바이너리 | 내장된 컴파일러 버전, 모듈, `replace` 지시어, 빌드 설정 | REA 내장 ELF/PE/thin Mach-O 정적 검사; Go 설치 불필요 |
| Rust 바이너리 | cargo-auditable이 내장한 크레이트 이름, 버전, 소스, 의존성 관계 | REA 내장 ELF/PE/thin Mach-O 정적 검사; [Rust 바이너리](../rust-binaries.md) |
| WASM 아티팩트 | 유효성 검사, 섹션, import/export의 정확한 WAT 형식, 디코딩된 WAT | 호출자 제공 WABT 1.0.42; `inspect_wasm_artifact` |
| EVM 바이트코드 | 디스패치 선택자, 바이트 오프셋, 추론한 인자와 상태 변경 가능 여부 | Linux x64의 로컬 원시 바이트/16진수 입력 파일; [오프라인 EVM 가이드](../evm-bytecode.md) |
| SQLite 데이터베이스 | 테이블, 열, 인덱스, 뷰, 트리거, 선택한 일반 테이블의 행 | 로컬 데이터베이스/WAL 스냅샷; Node.js 24.15 이상의 24.x 또는 26 이상(네이티브 SQLite 한도 적용) |
| 기록된 Linux 크래시 | 원시 note 레코드, 기록된 모든 스레드의 레지스터/시그널, 선택적 매핑 후보 | Linux x64에서 호출자가 제공하는 pwntools; GDB/pwndbg는 선택 사항; [기록된 크래시](../recorded-crashes.md) |
| JavaScript / Electron | 모듈, 임포트, 소스 맵, 라우트, IPC, 네이티브 애드온 관계 | Node.js와 npm; Linux: procps 호환 `ps`; [애플리케이션 분석](../javascript-application-workflows.md) |
| 웹사이트 | 페이지 구조, 스크립트, 네트워크 관찰 결과, 요청한 스크린샷 | Chrome 계열 브라우저; [브라우저 분석](../browser-observation.md) |
| 저장된 네트워크 캡처 | 요청, 응답, 접근 가능한 페이로드, 소스 위치 | HAR 또는 Fiddler Everywhere SAZ; mitmproxy 네이티브 캡처에는 Linux의 mitmdump; [캡처 가이드](../web-network-captures.md) |
| .NET 어셈블리 | 메타데이터, CIL 명령, 선언된 네이티브 의존성, 빌드 비교 | 별도 도구 불필요(정적 검사만); [관리 코드 가이드](../managed-code-analysis.md) |
| Android APK | 매니페스트 선언, 클래스, 디컴파일된 메서드, 참조 | Linux/macOS/Windows x64의 헤드리스 JADX와 전체 JDK; [Android 가이드](../android-analysis.md) |
| Android 기기 | 기기, 패키지, 프로세스, 로그, 덤프, 화면 캡처, APK/파일 전송 | 호출자 제공 adb(에뮬레이터 또는 실제 기기); [ADB 가이드](../adb-device-analysis.md) |
| JEB 프로젝트 | 엔진 기반 프로젝트 유닛, 아티팩트 해시, 타입/메서드 의사코드 | 호출자가 시작하고 MCP를 제공하는 JEB 클라이언트(REA_JEB_MCP_URL로 선택); [JEB 가이드](../jeb-analysis.md) |
| Android 리소스 | 디코딩된 매니페스트, 문자열 테이블, 로캘, 버전 정보 | 호출자 제공 Apktool 런처; [리소스 가이드](../apktool-resource-analysis.md) |
| Flutter 앱 | Dart 스냅샷 해시, ABI별 라이브러리 해시, 엔진 빌드 출처 | 없음 (정적 APK 파싱); [Flutter 가이드](../flutter-analysis.md) |
| 펌웨어 | 영역, 추출 결과, 네이티브 분석으로 전달할 정보 | Linux의 Binwalk / Unblob; [펌웨어 가이드](../firmware-analysis.md) |
| 기록된 패킷 | 선택 필드, 반복 값, 필터 및 디코딩 규칙 | Linux: TShark 4.x + prlimit; [캡처 가이드](../packet-captures.md) |
| 패킷 요약 | 엔드포인트, DNS, TLS SNI, 프로토콜 분포, HTTP 요청 | 호출자 제공 tshark 및 capinfos(Linux에서 검증됨); [pcap 가이드](../pcap-analysis.md) |
| 기록된 논리 신호 | 디코더 주석, 샘플 범위, 진단 정보 | Linux: sigrok-cli 0.7.2 + prlimit; [신호 기록 가이드](../signal-recordings.md) |
| 패키지 및 리소스 | 파일 목록, 다이제스트, plist, Apple 번들 구조, 추출한 리소스 | [아티팩트 및 JavaScript 가이드](../javascript-artifact-reconstruction.md), [Apple 애플리케이션](../apple-application-analysis.md) |
| 프로세스 동작 | 터미널 출력, 상호작용, 종료 및 파일 시스템 관찰 결과, 실행 비교 | 네이티브 PTY를 지원하는 Linux/macOS; [프로세스 캡처](../process-capture.md) |
| 대상 | REA가 반환하는 내용 | 요구 사항 및 가이드 |
| ---------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| 네이티브 바이너리 | 의사 코드, 어셈블리, 문자열, 심볼, 호출, 참조 | Hopper, Ghidra 또는 IDA; [네이티브 분석](../native-investigation.md) |
| 오프라인 ELF 레이아웃 | 섹션, 세그먼트, 원본 심볼/재배치 정보, 정적 분석으로 얻은 보안 완화 기법 후보 | Linux x64에서 호출자가 제공하는 pwntools; [바이너리 진단](../binary-diagnostics.md) |
| Go 바이너리 | 내장된 컴파일러 버전, 모듈, `replace` 지시어, 빌드 설정 | REA 내장 ELF/PE/thin Mach-O 정적 검사; Go 설치 불필요 |
| Rust 바이너리 | cargo-auditable이 내장한 크레이트 이름, 버전, 소스, 의존성 관계 | REA 내장 ELF/PE/thin Mach-O 정적 검사; [Rust 바이너리](../rust-binaries.md) |
| WASM 아티팩트 | 유효성 검사, 섹션, import/export의 정확한 WAT 형식, 디코딩된 WAT | 호출자 제공 WABT 1.0.42; `inspect_wasm_artifact` |
| EVM 바이트코드 | 디스패치 선택자, 바이트 오프셋, 추론한 인자와 상태 변경 가능 여부 | Linux x64의 로컬 원시 바이트/16진수 입력 파일; [오프라인 EVM 가이드](../evm-bytecode.md) |
| SQLite 데이터베이스 | 테이블, 열, 인덱스, 뷰, 트리거, 선택한 일반 테이블의 행 | 로컬 데이터베이스/WAL 스냅샷; Node.js 24.15 이상의 24.x 또는 26 이상(네이티브 SQLite 한도 적용) |
| 기록된 Linux 크래시 | 원시 note 레코드, 기록된 모든 스레드의 레지스터/시그널, 선택적 매핑 후보 | Linux x64에서 호출자가 제공하는 pwntools; GDB/pwndbg는 선택 사항; [기록된 크래시](../recorded-crashes.md) |
| 데스크톱 설치 디렉터리 | 런타임 후보, 근거 파일, 구성 요소 표시와 다음 조사 단계 | 범위가 제한된 디렉터리 및 헤더 검사;[데스크톱 애플리케이션](../desktop-applications.md) |
| JavaScript / Electron | 모듈, 임포트, 소스 맵, 라우트, IPC, 네이티브 애드온 관계 | Node.js와 npm; Linux: procps 호환 `ps`; [애플리케이션 분석](../javascript-application-workflows.md) |
| 웹사이트 | 페이지 구조, 스크립트, 네트워크 관찰 결과, 요청한 스크린샷 | Chrome 계열 브라우저; [브라우저 분석](../browser-observation.md) |
| 저장된 네트워크 캡처 | 요청, 응답, 접근 가능한 페이로드, 소스 위치 | HAR 또는 Fiddler Everywhere SAZ; mitmproxy 네이티브 캡처에는 Linux의 mitmdump; [캡처 가이드](../web-network-captures.md) |
| .NET 어셈블리 | 메타데이터, CIL 명령, 선언된 네이티브 의존성, 빌드 비교 | 별도 도구 불필요(정적 검사만); [관리 코드 가이드](../managed-code-analysis.md) |
| Android APK | 매니페스트 선언, 클래스, 디컴파일된 메서드, 참조 | Linux/macOS/Windows x64의 헤드리스 JADX와 전체 JDK; [Android 가이드](../android-analysis.md) |
| Android 기기 | 기기, 패키지, 프로세스, 로그, 덤프, 화면 캡처, APK/파일 전송 | 호출자 제공 adb(에뮬레이터 또는 실제 기기); [ADB 가이드](../adb-device-analysis.md) |
| JEB 프로젝트 | 엔진 기반 프로젝트 유닛, 아티팩트 해시, 타입/메서드 의사코드 | 호출자가 시작하고 MCP를 제공하는 JEB 클라이언트(REA_JEB_MCP_URL로 선택); [JEB 가이드](../jeb-analysis.md) |
| Android 리소스 | 디코딩된 매니페스트, 문자열 테이블, 로캘, 버전 정보 | 호출자 제공 Apktool 런처; [리소스 가이드](../apktool-resource-analysis.md) |
| Flutter 앱 | Dart 스냅샷 해시, ABI별 라이브러리 해시, 엔진 빌드 출처 | 없음 (정적 APK 파싱); [Flutter 가이드](../flutter-analysis.md) |
| 펌웨어 | 영역, 추출 결과, 네이티브 분석으로 전달할 정보 | Linux의 Binwalk / Unblob; [펌웨어 가이드](../firmware-analysis.md) |
| 기록된 패킷 | 선택 필드, 반복 값, 필터 및 디코딩 규칙 | Linux: TShark 4.x + prlimit; [캡처 가이드](../packet-captures.md) |
| 패킷 요약 | 엔드포인트, DNS, TLS SNI, 프로토콜 분포, HTTP 요청 | 호출자 제공 tshark 및 capinfos(Linux에서 검증됨); [pcap 가이드](../pcap-analysis.md) |
| 기록된 논리 신호 | 디코더 주석, 샘플 범위, 진단 정보 | Linux: sigrok-cli 0.7.2 + prlimit; [신호 기록 가이드](../signal-recordings.md) |
| 패키지 및 리소스 | 파일 목록, 다이제스트, plist, Apple 번들 구조, 추출한 리소스 | [아티팩트 및 JavaScript 가이드](../javascript-artifact-reconstruction.md), [Apple 애플리케이션](../apple-application-analysis.md) |
| 프로세스 동작 | 터미널 출력, 상호작용, 종료 및 파일 시스템 관찰 결과, 실행 비교 | 네이티브 PTY를 지원하는 Linux/macOS; [프로세스 캡처](../process-capture.md) |
정적 JavaScript 및 .NET 검사는 제공된 파일을 읽으며 애플리케이션을 실행하지 않습니다. 런타임 캡처는 사용자의 권한으로 선택한 대상을 실행하거나 대상과 상호작용합니다. 각 런타임 가이드에서 그 영향을 설명합니다.
@@ -274,6 +279,7 @@ npx rea-agents@latest setup
- [설치 및 설정](../installation.md): 에이전트 등록, 제공자 설정, 업데이트, 제거.
- [준비 상태 확인 및 문제 해결](../installation.md#check-readiness-for-your-task): 특정 에이전트 또는 분석 엔진 진단.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI 및 Evidence](../cli.md): 명령, 제공자 선택, 스냅샷, 가져오기/내보내기, 종료 상태.
- [MCP 계약](../mcp-contracts.md) 및 [에이전트 프롬프트](../mcp-prompts.md): 도구 결과, 세션, 안내에 따른 조사.
- [도구 카탈로그](../mcp-contracts.md#generated-catalog): 빌드 시 생성되는 도구, 제공자, CLI 명령 목록.
+2
View File
@@ -155,6 +155,7 @@ REA-യ്ക്ക് Node.js 22.x (>=22.19), 24.x (>=24.11), അല്ലെ
| 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) |
| ഡെസ്ക്ടോപ്പ് ഇൻസ്റ്റലേഷനുകൾ | റൺടൈം സാധ്യതകൾ, തെളിവ് ഫയലുകൾ, ഘടക സൂചനകൾ, തുടർ നടപടികൾ | പരിധിയുള്ള ഡയറക്ടറി, ഹെഡർ പരിശോധന;[ഡെസ്ക്ടോപ്പ് ആപ്ലിക്കേഷനുകൾ](../desktop-applications.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) |
@@ -281,6 +282,7 @@ npx rea-agents@latest setup
- [Installation and setup](../installation.md): agent registration, provider configuration, updates, uninstall.
- [Readiness and troubleshooting](../installation.md#check-readiness-for-your-task): ഒരു agent-ന്റെയോ analysis engine-ന്റെയോ പ്രശ്നങ്ങൾ കണ്ടെത്തുക.
- [GGUF / safetensors](../model-artifacts.md)
- [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 എന്നിവയുടെ സ്വയമേവ സൃഷ്ടിച്ച പട്ടിക.
+2
View File
@@ -146,6 +146,7 @@ REA wymaga Node.js 22.x (>=22.19), 24.x (>=24.11) lub 26+ oraz npm. Dodatkowe na
| Kod bajtowy EVM | Selektory wywołań, przesunięcia bajtowe, wywnioskowane argumenty i mutowalność | Lokalny plik z surowymi bajtami lub zapisem szesnastkowym w systemie Linux x64; [przewodnik EVM offline](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Zarejestrowane awarie systemu Linux | Surowe rekordy note, rejestry/sygnały każdego zarejestrowanego wątku i opcjonalni kandydaci na mapowania | pwntools dostarczone przez użytkownika w systemie Linux x64; opcjonalnie GDB/pwndbg; [zarejestrowane awarie](../recorded-crashes.md) |
| Instalacje desktopowe | Kandydaci środowisk uruchomieniowych, pliki źródłowe dowodów, komponenty i dalsze kroki | Ograniczona inspekcja katalogów i nagłówków;[Aplikacje desktopowe](../desktop-applications.md) |
| JavaScript / Electron | Moduły, importy, mapy źródeł, trasy, IPC i powiązania z natywnymi dodatkami | Node.js i npm; [analiza aplikacji](../javascript-application-workflows.md) |
| Strony internetowe | Struktura strony, skrypty, obserwacje sieciowe i zamówione zrzuty ekranu | Przeglądarka z rodziny Chrome; [analiza w przeglądarce](../browser-observation.md) |
| Zapisane przechwycenia ruchu sieciowego | Żądania, odpowiedzi, dostępne dane przesyłane i lokalizacje źródłowe | HAR; mitmdump w systemie Linux dla natywnych przechwyceń mitmproxy; [przewodnik przechwytywania](../web-network-captures.md) |
@@ -263,6 +264,7 @@ Zacznij od [przewodników z przykładami](https://rea.tools/pl/guides/) na stron
- [Instalacja i konfiguracja](../installation.md): rejestracja agentów, konfiguracja dostawców analizy, aktualizacje i odinstalowanie.
- [Gotowość i rozwiązywanie problemów](../installation.md#check-readiness-for-your-task): diagnostyka jednego agenta lub silnika analizy.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI i Evidence](../cli.md): polecenia, wybór dostawcy, migawki, import/eksport i kody zakończenia.
- [Kontrakty MCP](../mcp-contracts.md) i [prompty dla agentów](../mcp-prompts.md): wyniki narzędzi, sesje i prowadzone analizy.
- [Katalog narzędzi](../mcp-contracts.md#generated-catalog): generowany podczas kompilacji wykaz narzędzi, dostawców i poleceń CLI.
+2
View File
@@ -146,6 +146,7 @@ O REA requer Node.js 22.x (>=22.19), 24.x (>=24.11) ou 26+, além do npm. As fer
| Bytecode EVM | Seletores de despacho, offsets de bytes, argumentos inferidos e mutabilidade | Entrada local com bytes brutos ou representação hexadecimal no Linux x64; [guia de EVM sem execução](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Falhas do Linux registradas | Registros note brutos, registradores/sinais de cada thread registrada e candidatos opcionais a mapeamentos | pwntools fornecido pelo chamador no Linux x64; GDB/pwndbg opcionais; [falhas registradas](../recorded-crashes.md) |
| Instalações desktop | Ambientes candidatos, arquivos de evidência, componentes e próximos passos | Inspeção limitada de diretórios e cabeçalhos;[Aplicações desktop](../desktop-applications.md) |
| JavaScript / Electron | Módulos, importações, source maps, rotas, IPC e relações com complementos nativos | Node.js e npm; [análise de aplicativos](../javascript-application-workflows.md) |
| Sites | Estrutura da página, scripts, observações de rede e capturas de tela solicitadas | Um navegador da família Chrome; [análise do navegador](../browser-observation.md) |
| Capturas de rede salvas | Requisições, respostas, payloads acessíveis e localizações de origem | HAR; mitmdump no Linux para capturas no formato nativo do mitmproxy; [guia de capturas](../web-network-captures.md) |
@@ -263,6 +264,7 @@ Comece pelos [guias práticos](https://rea.tools/pt-BR/guides/) do site. Para op
- [Instalação e configuração](../installation.md): registro de agentes, configuração de provedores, atualizações e desinstalação.
- [Prontidão e solução de problemas](../installation.md#check-readiness-for-your-task): diagnóstico de um agente ou motor de análise específico.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI e Evidence](../cli.md): comandos, seleção de provedores, snapshots, importação/exportação e status de saída.
- [Contratos MCP](../mcp-contracts.md) e [prompts para agentes](../mcp-prompts.md): resultados das ferramentas, sessões e investigações guiadas.
- [Catálogo de ferramentas](../mcp-contracts.md#generated-catalog): inventário de ferramentas, provedores e comandos da CLI gerado durante o build.
+24 -22
View File
@@ -139,28 +139,29 @@ npx rea-agents@latest setup
REA требует Node.js 22.x (>=22.19), 24.x (>=24.11) или 26+, а также npm. Дополнительные инструменты и поддерживаемые системы зависят от цели:
| Цель | Что возвращает REA | Требования и руководство |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| Нативные бинарные файлы | Псевдокод, ассемблер, строки, символы, вызовы и ссылки | Hopper, Ghidra или IDA; [нативный анализ](../native-investigation.md) |
| Структура ELF без запуска | Секции, сегменты, исходные символы/релокации и возможные механизмы защиты по данным статического анализа | pwntools, предоставленный вызывающей стороной, в Linux x64; [диагностика бинарных файлов](../binary-diagnostics.md) |
| Байт-код EVM | Селекторы диспетчеризации, смещения байтов, предполагаемые аргументы и изменяемость состояния | Локальные необработанные байты или шестнадцатеричное представление в Linux x64; [руководство по EVM без запуска](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Записанные сбои Linux | Необработанные записи note, регистры/сигналы каждого записанного потока и необязательные кандидаты сопоставления с памятью | pwntools, предоставленный вызывающей стороной, в Linux x64; необязательные GDB/pwndbg; [записанные сбои](../recorded-crashes.md) |
| JavaScript / Electron | Модули, импорты, карты исходного кода, маршруты, IPC и связи с нативными дополнениями | Node.js и npm; [анализ приложений](../javascript-application-workflows.md) |
| Сайты | Структура страницы, скрипты, наблюдения за сетью и запрошенные снимки экрана | Браузер семейства Chrome; [анализ браузера](../browser-observation.md) |
| Сохранённые сетевые захваты | Запросы, ответы, доступные полезные данные и позиции в источнике | HAR; mitmdump в Linux для захватов в собственном формате mitmproxy; [руководство по сетевым захватам](../web-network-captures.md) |
| Сборки .NET | Метаданные, инструкции CIL, объявленные нативные зависимости и сравнения сборок | Статическое исследование; [руководство по управляемому коду](../managed-code-analysis.md) |
| Android APK | Объявления манифеста, классы, декомпилированные методы и ссылки | JADX без графического интерфейса и полный JDK в Linux/macOS/Windows x64; [руководство по Android](../android-analysis.md) |
| Устройства Android | Устройства, пакеты, процессы, журналы, дампы, снимки экрана и передача APK/файлов | adb, предоставленный вызывающей стороной (эмулятор или устройство); [руководство по ADB](../adb-device-analysis.md) |
| Проекты JEB | Единицы проекта от движка, дайджесты артефактов и псевдокод типов/методов | Запущенный вызывающей стороной клиент JEB с интерфейсом MCP, выбирается через REA_JEB_MCP_URL; [руководство по JEB](../jeb-analysis.md) |
| Ресурсы Android | Декодированный манифест, таблицы строк, языки и сведения о версии | Запуск Apktool, предоставленный вызывающей стороной; [руководство по ресурсам](../apktool-resource-analysis.md) |
| Приложения Flutter | Хеш снапшота Dart, дайджесты библиотек по ABI и происхождение сборки движка | Не требуется (статический разбор APK); [руководство по Flutter](../flutter-analysis.md) |
| Прошивки | Области, результаты извлечения и передача в нативный анализ | Binwalk / Unblob в Linux; [руководство по прошивкам](../firmware-analysis.md) |
| Записанные пакеты | Выбранные поля, повторяющиеся значения, фильтры и правила декодирования | Linux: TShark 4.x + prlimit; [руководство по захватам](../packet-captures.md) |
| Захват пакетов | Конечные точки, DNS, TLS SNI, распределение протоколов и HTTP-запросы | Предоставленные вызывающей стороной tshark и capinfos; [руководство по pcap](../pcap-analysis.md) |
| Записанные логические сигналы | Аннотации декодера, диапазоны отсчётов и диагностика | Linux: sigrok-cli 0.7.2 + prlimit; [руководство по сигналам](../signal-recordings.md) |
| Пакеты и ресурсы | Списки файлов, хеши, plist, структура пакетов Apple и извлечённые ресурсы | [Руководство по артефактам и JavaScript](../javascript-artifact-reconstruction.md), [приложения Apple](../apple-application-analysis.md) |
| Поведение процессов | Вывод терминала, взаимодействия, наблюдения за завершением и файловой системой, сравнения запусков | Linux/macOS с нативным PTY; [захват процессов](../process-capture.md) |
| Цель | Что возвращает REA | Требования и руководство |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| Нативные бинарные файлы | Псевдокод, ассемблер, строки, символы, вызовы и ссылки | Hopper, Ghidra или IDA; [нативный анализ](../native-investigation.md) |
| Структура ELF без запуска | Секции, сегменты, исходные символы/релокации и возможные механизмы защиты по данным статического анализа | pwntools, предоставленный вызывающей стороной, в Linux x64; [диагностика бинарных файлов](../binary-diagnostics.md) |
| Байт-код EVM | Селекторы диспетчеризации, смещения байтов, предполагаемые аргументы и изменяемость состояния | Локальные необработанные байты или шестнадцатеричное представление в Linux x64; [руководство по EVM без запуска](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Записанные сбои Linux | Необработанные записи note, регистры/сигналы каждого записанного потока и необязательные кандидаты сопоставления с памятью | pwntools, предоставленный вызывающей стороной, в Linux x64; необязательные GDB/pwndbg; [записанные сбои](../recorded-crashes.md) |
| Установленные настольные приложения | Возможные среды выполнения, файлы с доказательствами, компоненты и дальнейшие шаги | Ограниченная проверка каталогов и заголовков;[Настольные приложения](../desktop-applications.md) |
| JavaScript / Electron | Модули, импорты, карты исходного кода, маршруты, IPC и связи с нативными дополнениями | Node.js и npm; [анализ приложений](../javascript-application-workflows.md) |
| Сайты | Структура страницы, скрипты, наблюдения за сетью и запрошенные снимки экрана | Браузер семейства Chrome; [анализ браузера](../browser-observation.md) |
| Сохранённые сетевые захваты | Запросы, ответы, доступные полезные данные и позиции в источнике | HAR; mitmdump в Linux для захватов в собственном формате mitmproxy; [руководство по сетевым захватам](../web-network-captures.md) |
| Сборки .NET | Метаданные, инструкции CIL, объявленные нативные зависимости и сравнения сборок | Статическое исследование; [руководство по управляемому коду](../managed-code-analysis.md) |
| Android APK | Объявления манифеста, классы, декомпилированные методы и ссылки | JADX без графического интерфейса и полный JDK в Linux/macOS/Windows x64; [руководство по Android](../android-analysis.md) |
| Устройства Android | Устройства, пакеты, процессы, журналы, дампы, снимки экрана и передача APK/файлов | adb, предоставленный вызывающей стороной (эмулятор или устройство); [руководство по ADB](../adb-device-analysis.md) |
| Проекты JEB | Единицы проекта от движка, дайджесты артефактов и псевдокод типов/методов | Запущенный вызывающей стороной клиент JEB с интерфейсом MCP, выбирается через REA_JEB_MCP_URL; [руководство по JEB](../jeb-analysis.md) |
| Ресурсы Android | Декодированный манифест, таблицы строк, языки и сведения о версии | Запуск Apktool, предоставленный вызывающей стороной; [руководство по ресурсам](../apktool-resource-analysis.md) |
| Приложения Flutter | Хеш снапшота Dart, дайджесты библиотек по ABI и происхождение сборки движка | Не требуется (статический разбор APK); [руководство по Flutter](../flutter-analysis.md) |
| Прошивки | Области, результаты извлечения и передача в нативный анализ | Binwalk / Unblob в Linux; [руководство по прошивкам](../firmware-analysis.md) |
| Записанные пакеты | Выбранные поля, повторяющиеся значения, фильтры и правила декодирования | Linux: TShark 4.x + prlimit; [руководство по захватам](../packet-captures.md) |
| Захват пакетов | Конечные точки, DNS, TLS SNI, распределение протоколов и HTTP-запросы | Предоставленные вызывающей стороной tshark и capinfos; [руководство по pcap](../pcap-analysis.md) |
| Записанные логические сигналы | Аннотации декодера, диапазоны отсчётов и диагностика | Linux: sigrok-cli 0.7.2 + prlimit; [руководство по сигналам](../signal-recordings.md) |
| Пакеты и ресурсы | Списки файлов, хеши, plist, структура пакетов Apple и извлечённые ресурсы | [Руководство по артефактам и JavaScript](../javascript-artifact-reconstruction.md), [приложения Apple](../apple-application-analysis.md) |
| Поведение процессов | Вывод терминала, взаимодействия, наблюдения за завершением и файловой системой, сравнения запусков | Linux/macOS с нативным PTY; [захват процессов](../process-capture.md) |
Статическое исследование JavaScript и .NET читает предоставленные файлы, не запуская приложение. Захват во время выполнения запускает выбранную цель или взаимодействует с ней с правами вашего пользователя; соответствующие руководства описывают последствия.
@@ -263,6 +264,7 @@ npx rea-agents@latest setup
- [Установка и настройка](../installation.md): регистрация агентов, настройка провайдеров, обновление и удаление.
- [Готовность и устранение неполадок](../installation.md#check-readiness-for-your-task): диагностика конкретного агента или движка анализа.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI и Evidence](../cli.md): команды, выбор провайдера, снимки, импорт/экспорт и коды завершения.
- [Контракты MCP](../mcp-contracts.md) и [промпты агентов](../mcp-prompts.md): результаты инструментов, сеансы и исследования с подсказками.
- [Каталог инструментов](../mcp-contracts.md#generated-catalog): создаваемый при сборке перечень инструментов, провайдеров и команд CLI.
+2
View File
@@ -146,6 +146,7 @@ REA ต้องใช้ Node.js 22.x (>=22.19), 24.x (>=24.11) หรือ 26
| ไบต์โค้ด EVM | ตัวเลือกฟังก์ชันสำหรับการเรียก ออฟเซ็ตไบต์ อาร์กิวเมนต์และความสามารถในการเปลี่ยนสถานะที่อนุมานได้ | ไฟล์บนเครื่องที่มีไบต์ดิบหรือข้อมูลเลขฐานสิบหกบน Linux x64; [คู่มือ EVM แบบออฟไลน์](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| ข้อมูลการแครชของ Linux ที่บันทึกไว้ | ระเบียน note ดิบ รีจิสเตอร์/สัญญาณของทุกเธรดที่บันทึกไว้ และตัวเลือกการแมปเพิ่มเติม | pwntools ที่ผู้ใช้จัดเตรียมบน Linux x64; เลือกใช้ GDB/pwndbg เพิ่มเติมได้; [การแครชที่บันทึกไว้](../recorded-crashes.md) |
| ไดเรกทอรีติดตั้งแอปเดสก์ท็อป | รันไทม์ที่เป็นไปได้ ไฟล์หลักฐาน ตัวบ่งชี้ส่วนประกอบ และขั้นตอนถัดไป | ตรวจสอบไดเรกทอรีและส่วนหัวโดยจำกัดขอบเขต;[แอปเดสก์ท็อป](../desktop-applications.md) |
| JavaScript / Electron | โมดูล การนำเข้า ซอร์สแมป เส้นทาง IPC และความสัมพันธ์กับส่วนเสริมเนทีฟ | Node.js และ npm; [การวิเคราะห์แอปพลิเคชัน](../javascript-application-workflows.md) |
| เว็บไซต์ | โครงสร้างหน้า สคริปต์ ข้อมูลเครือข่ายที่สังเกตได้ และภาพหน้าจอที่ร้องขอ | เบราว์เซอร์ในตระกูล Chrome; [การวิเคราะห์ผ่านเบราว์เซอร์](../browser-observation.md) |
| ข้อมูลเครือข่ายที่บันทึกไว้ | คำขอ คำตอบ เพย์โหลดที่ปรากฏ และตำแหน่งต้นทาง | HAR; mitmdump บน Linux สำหรับข้อมูลที่บันทึกในรูปแบบเนทีฟของ mitmproxy; [คู่มือการบันทึกข้อมูล](../web-network-captures.md) |
@@ -263,6 +264,7 @@ npx rea-agents@latest setup
- [การติดตั้งและตั้งค่า](../installation.md): การลงทะเบียนเอเจนต์ การตั้งค่าผู้ให้บริการ การอัปเดต และการถอนการติดตั้ง
- [ความพร้อมใช้งานและการแก้ไขปัญหา](../installation.md#check-readiness-for-your-task): ตรวจวินิจฉัยเอเจนต์หรือเอนจินวิเคราะห์หนึ่งตัว
- [GGUF / safetensors](../model-artifacts.md)
- [CLI และ Evidence](../cli.md): คำสั่ง การเลือกผู้ให้บริการ สแนปช็อต การนำเข้า/ส่งออก และรหัสการสิ้นสุด
- [สัญญา MCP](../mcp-contracts.md) และ[พรอมป์ต์สำหรับเอเจนต์](../mcp-prompts.md): ผลลัพธ์เครื่องมือ เซสชัน และการตรวจสอบตามคำแนะนำ
- [แค็ตตาล็อกเครื่องมือ](../mcp-contracts.md#generated-catalog): รายการเครื่องมือ ผู้ให้บริการ และคำสั่ง CLI ที่สร้างระหว่างการบิลด์
+2
View File
@@ -151,6 +151,7 @@ REA; Node.js 22.x (>=22.19), 24.x (>=24.11) veya 26+ ve npm gerektirir. Ek araç
| EVM bayt kodu | Yönlendirme seçicileri, bayt ofsetleri, çıkarımla belirlenen argümanlar ve durum değiştirilebilirliği | Linux x64 üzerinde yerel ham bayt/onaltılık girdi; [çevrimdışı EVM rehberi](../evm-bytecode.md) |
| SQLite veritabanları | Tablolar, sütunlar, index'ler, view'lar, trigger'lar ve seçilen sıradan tablo satırları | Yerel database/WAL snapshot'ı; native SQLite sınırlarıyla Node.js 24.x >=24.15 veya 26+ |
| Kaydedilmiş Linux çökmeleri | Ham note kayıtları, kaydedilen her iş parçacığının yazmaçları/sinyalleri ve isteğe bağlı eşleme adayları | Linux x64 üzerinde çağıranın sağladığı pwntools; isteğe bağlı GDB/pwndbg; [kaydedilmiş çökmeler](../recorded-crashes.md) |
| Masaüstü kurulumları | Çalışma zamanı adayları, kanıt dosyaları, bileşen işaretleri ve sonraki adımlar | Sınırlı dizin ve başlık incelemesi;[Masaüstü uygulamaları](../desktop-applications.md) |
| JavaScript / Electron | Modüller, içe aktarmalar, kaynak haritaları, rotalar, IPC ve yerel eklenti ilişkileri | Node.js ve npm; [uygulama analizi](../javascript-application-workflows.md) |
| Web siteleri | Sayfa yapısı, betikler, ağ gözlemleri ve istenen ekran görüntüleri | Chrome ailesinden bir tarayıcı; [tarayıcı analizi](../browser-observation.md) |
| Kaydedilmiş ağ yakalamaları | İstekler, yanıtlar, erişilebilir yük içerikleri ve kaynak konumları | HAR veya Fiddler Everywhere SAZ; Linux'ta native mitmproxy için mitmdump; [ağ yakalama rehberi](../web-network-captures.md) |
@@ -268,6 +269,7 @@ Web sitesindeki [uygulamalı rehberlerden](https://rea.tools/tr/guides/) başlay
- [Yükleme ve kurulum](../installation.md): ajan kaydı, sağlayıcı yapılandırması, güncellemeler ve kaldırma.
- [Hazırlık ve sorun giderme](../installation.md#check-readiness-for-your-task): belirli bir ajanı veya analiz motorunu tanılama.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI ve Evidence](../cli.md): komutlar, sağlayıcı seçimi, anlık görüntüler, içe/dışa aktarma ve çıkış durumları.
- [MCP sözleşmeleri](../mcp-contracts.md) ve [ajan istemleri](../mcp-prompts.md): araç sonuçları, oturumlar ve yönlendirmeli araştırmalar.
- [Araç kataloğu](../mcp-contracts.md#generated-catalog): derleme sırasında oluşturulan araç, sağlayıcı ve CLI komutu envanteri.
+2
View File
@@ -146,6 +146,7 @@ REA потребує Node.js 22.x (>=22.19), 24.x (>=24.11) або 26+, а та
| Байт-код EVM | Селектори диспетчеризації, зміщення байтів, виведені припущення про аргументи та змінюваність стану | Локальні необроблені байти або шістнадцяткове представлення у Linux x64; [посібник EVM без запуску](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Записані аварійні завершення в Linux | Необроблені записи note, регістри/сигнали кожного записаного потоку й необов'язкові кандидати зіставлення пам'яті | pwntools, наданий стороною, що викликає інструмент, у Linux x64; необов'язкові GDB/pwndbg; [записані аварійні завершення](../recorded-crashes.md) |
| Встановлені настільні програми | Можливі середовища виконання, файли доказів, компоненти та наступні кроки | Обмежена перевірка каталогів і заголовків;[Настільні програми](../desktop-applications.md) |
| JavaScript / Electron | Модулі, імпорти, карти вихідного коду, маршрути, IPC і зв'язки з нативними доповненнями | Node.js і npm; [аналіз застосунків](../javascript-application-workflows.md) |
| Сайти | Структура сторінки, скрипти, мережеві спостереження й запитані знімки екрана | Браузер сімейства Chrome; [аналіз браузера](../browser-observation.md) |
| Збережені мережеві захоплення | Запити, відповіді, доступні корисні дані та місця в джерелі | HAR; mitmdump у Linux для захоплень у власному форматі mitmproxy; [посібник мережевих захоплень](../web-network-captures.md) |
@@ -263,6 +264,7 @@ npx rea-agents@latest setup
- [Встановлення й налаштування](../installation.md): реєстрація агентів, конфігурація провайдерів, оновлення та видалення.
- [Готовність та усунення неполадок](../installation.md#check-readiness-for-your-task): діагностика конкретного агента або рушія аналізу.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI та Evidence](../cli.md): команди, вибір провайдера, знімки, імпорт/експорт і статуси завершення.
- [Контракти MCP](../mcp-contracts.md) і [промпти агентів](../mcp-prompts.md): результати інструментів, сеанси й керовані дослідження.
- [Каталог інструментів](../mcp-contracts.md#generated-catalog): створюваний під час збірки перелік інструментів, провайдерів і команд CLI.
+24 -22
View File
@@ -139,28 +139,29 @@ Tác nhân gọi REA qua MCP để kiểm tra mục tiêu và lần theo mã li
REA yêu cầu Node.js 22.x (>=22.19), 24.x (>=24.11) hoặc 26+, cùng với npm. Công cụ bổ sung và nền tảng chạy REA được hỗ trợ tùy thuộc vào mục tiêu:
| Mục tiêu | REA trả về gì | Yêu cầu và hướng dẫn |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| Tệp nhị phân mã máy | Mã giả, hợp ngữ, chuỗi, ký hiệu, lời gọi và tham chiếu | Hopper, Ghidra hoặc IDA; [phân tích mã máy](../native-investigation.md) |
| Bố cục ELF ngoại tuyến | Các section, segment, ký hiệu/thông tin tái định vị gốc và các biện pháp giảm thiểu có thể có từ phân tích tĩnh | pwntools do bên gọi cung cấp trên Linux x64; [chẩn đoán tệp nhị phân](../binary-diagnostics.md) |
| Bytecode EVM | Bộ chọn điều phối, độ lệch byte, tham số suy luận và khả năng thay đổi trạng thái | Đầu vào cục bộ chứa byte thô hoặc dạng thập lục phân trên Linux x64; [hướng dẫn EVM ngoại tuyến](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Sự cố Linux đã ghi lại | Bản ghi note thô, thanh ghi/tín hiệu của mọi luồng được ghi lại và các ứng viên ánh xạ tùy chọn | pwntools do bên gọi cung cấp trên Linux x64; GDB/pwndbg tùy chọn; [sự cố đã ghi lại](../recorded-crashes.md) |
| JavaScript / Electron | Mô-đun, các khai báo import, source map, tuyến, IPC và quan hệ với tiện ích mở rộng mã máy | Node.js và npm; [phân tích ứng dụng](../javascript-application-workflows.md) |
| Trang web | Cấu trúc trang, script, quan sát mạng và ảnh chụp màn hình được yêu cầu | Trình duyệt thuộc họ Chrome; [phân tích trình duyệt](../browser-observation.md) |
| Bản ghi lưu lượng mạng đã lưu | Yêu cầu, phản hồi, payload có thể truy cập và vị trí nguồn | HAR; mitmdump trên Linux cho bản ghi định dạng gốc của mitmproxy; [hướng dẫn bản ghi mạng](../web-network-captures.md) |
| Bắt gói tin | Điểm cuối, DNS, TLS SNI, phân bố giao thức và yêu cầu HTTP | tshark và capinfos do nơi gọi cung cấp; [hướng dẫn pcap](../pcap-analysis.md) |
| Assembly .NET | Siêu dữ liệu, lệnh CIL, các phụ thuộc mã máy được khai báo và so sánh bản dựng | Kiểm tra tĩnh; [hướng dẫn mã được quản lý](../managed-code-analysis.md) |
| APK Android | Khai báo manifest, lớp, phương thức được dịch ngược và tham chiếu | JADX không giao diện đồ họa và JDK đầy đủ trên Linux/macOS/Windows x64; [hướng dẫn Android](../android-analysis.md) |
| Thiết bị Android | Thiết bị, gói, tiến trình, nhật ký, dump, ảnh chụp màn hình và truyền APK/tệp | adb do nơi gọi cung cấp (trình giả lập hoặc thiết bị); [hướng dẫn ADB](../adb-device-analysis.md) |
| Dự án JEB | Đơn vị dự án từ engine, hash của artifact và mã giả của kiểu/phương thức | Một ứng dụng JEB do nơi gọi khởi động, phục vụ MCP, chọn bằng REA_JEB_MCP_URL; [hướng dẫn JEB](../jeb-analysis.md) |
| Tài nguyên Android | Manifest đã giải mã, bảng chuỗi, ngôn ngữ và thông tin phiên bản | Trình khởi chạy Apktool do nơi gọi cung cấp; [hướng dẫn tài nguyên](../apktool-resource-analysis.md) |
| Ứng dụng Flutter | Băm snapshot Dart, hash thư viện theo ABI và nguồn gốc build engine | Không cần (phân tích APK tĩnh); [hướng dẫn Flutter](../flutter-analysis.md) |
| Phần sụn | Các vùng, kết quả trích xuất và dữ liệu chuyển sang phân tích mã máy | Binwalk / Unblob trên Linux; [hướng dẫn phần sụn](../firmware-analysis.md) |
| Gói tin đã ghi | Trường được chọn, giá trị lặp, bộ lọc và quy tắc giải mã | Linux: TShark 4.x + prlimit; [hướng dẫn bản ghi gói tin](../packet-captures.md) |
| Tín hiệu logic đã ghi | Chú thích bộ giải mã, phạm vi mẫu và chẩn đoán | Linux: sigrok-cli 0.7.2 + prlimit; [hướng dẫn tín hiệu](../signal-recordings.md) |
| Gói và tài nguyên | Danh sách tệp, giá trị băm, plist, cấu trúc bundle Apple và tài nguyên được trích xuất | [Hướng dẫn hiện vật phần mềm và JavaScript](../javascript-artifact-reconstruction.md), [ứng dụng Apple](../apple-application-analysis.md) |
| Hành vi tiến trình | Đầu ra terminal, tương tác, quan sát khi thoát và hệ thống tệp, cùng so sánh các lần chạy | Linux/macOS có PTY gốc; [ghi lại tiến trình](../process-capture.md) |
| Mục tiêu | REA trả về gì | Yêu cầu và hướng dẫn |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| Tệp nhị phân mã máy | Mã giả, hợp ngữ, chuỗi, ký hiệu, lời gọi và tham chiếu | Hopper, Ghidra hoặc IDA; [phân tích mã máy](../native-investigation.md) |
| Bố cục ELF ngoại tuyến | Các section, segment, ký hiệu/thông tin tái định vị gốc và các biện pháp giảm thiểu có thể có từ phân tích tĩnh | pwntools do bên gọi cung cấp trên Linux x64; [chẩn đoán tệp nhị phân](../binary-diagnostics.md) |
| Bytecode EVM | Bộ chọn điều phối, độ lệch byte, tham số suy luận và khả năng thay đổi trạng thái | Đầu vào cục bộ chứa byte thô hoặc dạng thập lục phân trên Linux x64; [hướng dẫn EVM ngoại tuyến](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Sự cố Linux đã ghi lại | Bản ghi note thô, thanh ghi/tín hiệu của mọi luồng được ghi lại và các ứng viên ánh xạ tùy chọn | pwntools do bên gọi cung cấp trên Linux x64; GDB/pwndbg tùy chọn; [sự cố đã ghi lại](../recorded-crashes.md) |
| Thư mục cài đặt ứng dụng máy tính | Các runtime có khả năng được dùng, tệp bằng chứng, dấu hiệu thành phần và bước tiếp theo | Kiểm tra thư mục và phần đầu tệp có giới hạn;[Ứng dụng máy tính](../desktop-applications.md) |
| JavaScript / Electron | Mô-đun, các khai báo import, source map, tuyến, IPC và quan hệ với tiện ích mở rộng mã máy | Node.js và npm; [phân tích ứng dụng](../javascript-application-workflows.md) |
| Trang web | Cấu trúc trang, script, quan sát mạng và ảnh chụp màn hình được yêu cầu | Trình duyệt thuộc họ Chrome; [phân tích trình duyệt](../browser-observation.md) |
| Bản ghi lưu lượng mạng đã lưu | Yêu cầu, phản hồi, payload có thể truy cập và vị trí nguồn | HAR; mitmdump trên Linux cho bản ghi định dạng gốc của mitmproxy; [hướng dẫn bản ghi mạng](../web-network-captures.md) |
| Bắt gói tin | Điểm cuối, DNS, TLS SNI, phân bố giao thức và yêu cầu HTTP | tshark và capinfos do nơi gọi cung cấp; [hướng dẫn pcap](../pcap-analysis.md) |
| Assembly .NET | Siêu dữ liệu, lệnh CIL, các phụ thuộc mã máy được khai báo và so sánh bản dựng | Kiểm tra tĩnh; [hướng dẫn mã được quản lý](../managed-code-analysis.md) |
| APK Android | Khai báo manifest, lớp, phương thức được dịch ngược và tham chiếu | JADX không giao diện đồ họa và JDK đầy đủ trên Linux/macOS/Windows x64; [hướng dẫn Android](../android-analysis.md) |
| Thiết bị Android | Thiết bị, gói, tiến trình, nhật ký, dump, ảnh chụp màn hình và truyền APK/tệp | adb do nơi gọi cung cấp (trình giả lập hoặc thiết bị); [hướng dẫn ADB](../adb-device-analysis.md) |
| Dự án JEB | Đơn vị dự án từ engine, hash của artifact và mã giả của kiểu/phương thức | Một ứng dụng JEB do nơi gọi khởi động, phục vụ MCP, chọn bằng REA_JEB_MCP_URL; [hướng dẫn JEB](../jeb-analysis.md) |
| Tài nguyên Android | Manifest đã giải mã, bảng chuỗi, ngôn ngữ và thông tin phiên bản | Trình khởi chạy Apktool do nơi gọi cung cấp; [hướng dẫn tài nguyên](../apktool-resource-analysis.md) |
| Ứng dụng Flutter | Băm snapshot Dart, hash thư viện theo ABI và nguồn gốc build engine | Không cần (phân tích APK tĩnh); [hướng dẫn Flutter](../flutter-analysis.md) |
| Phần sụn | Các vùng, kết quả trích xuất và dữ liệu chuyển sang phân tích mã máy | Binwalk / Unblob trên Linux; [hướng dẫn phần sụn](../firmware-analysis.md) |
| Gói tin đã ghi | Trường được chọn, giá trị lặp, bộ lọc và quy tắc giải mã | Linux: TShark 4.x + prlimit; [hướng dẫn bản ghi gói tin](../packet-captures.md) |
| Tín hiệu logic đã ghi | Chú thích bộ giải mã, phạm vi mẫu và chẩn đoán | Linux: sigrok-cli 0.7.2 + prlimit; [hướng dẫn tín hiệu](../signal-recordings.md) |
| Gói và tài nguyên | Danh sách tệp, giá trị băm, plist, cấu trúc bundle Apple và tài nguyên được trích xuất | [Hướng dẫn hiện vật phần mềm và JavaScript](../javascript-artifact-reconstruction.md), [ứng dụng Apple](../apple-application-analysis.md) |
| Hành vi tiến trình | Đầu ra terminal, tương tác, quan sát khi thoát và hệ thống tệp, cùng so sánh các lần chạy | Linux/macOS có PTY gốc; [ghi lại tiến trình](../process-capture.md) |
Kiểm tra tĩnh JavaScript và .NET đọc các tệp được cung cấp mà không chạy ứng dụng. Ghi lại khi chạy sẽ khởi chạy hoặc tương tác với mục tiêu đã chọn bằng quyền người dùng của bạn; từng hướng dẫn mô tả tác động của nó.
@@ -263,6 +264,7 @@ Bắt đầu với [hướng dẫn thực hành](https://rea.tools/vi/guides/) t
- [Cài đặt và thiết lập](../installation.md): đăng ký tác nhân, cấu hình trình phân tích, cập nhật và gỡ cài đặt.
- [Kiểm tra mức sẵn sàng và khắc phục sự cố](../installation.md#check-readiness-for-your-task): chẩn đoán một tác nhân hoặc bộ máy phân tích cụ thể.
- [GGUF / safetensors](../model-artifacts.md)
- [CLI và Evidence](../cli.md): lệnh, lựa chọn trình phân tích, ảnh chụp trạng thái, nhập/xuất và trạng thái thoát.
- [Hợp đồng MCP](../mcp-contracts.md) và [prompt cho tác nhân](../mcp-prompts.md): kết quả công cụ, phiên làm việc và điều tra có hướng dẫn.
- [Danh mục công cụ](../mcp-contracts.md#generated-catalog): danh sách công cụ, trình phân tích và lệnh CLI được tạo khi dựng dự án.
+2
View File
@@ -150,6 +150,7 @@ REA 需要 Node.js 22.x(>=22.19)、24.x(>=24.11)或 26+,以及 npm。
| EVM 位元組碼 | 分派選擇器、位元組偏移、推斷的參數和狀態可變性 | Linux x64 上的本地原始位元組/十六進位輸入載體;[離線 EVM 指南](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| 已記錄的 Linux 崩潰 | 原始 note 記錄、每個已記錄執行緒的暫存器/訊號及可選的對映候選項 | Linux x64 上由呼叫方提供的 pwntools;可選的 GDB/pwndbg;[已記錄崩潰](../recorded-crashes.md) |
| 桌面安裝目錄 | 執行階段候選、支持檔案、元件標記與後續操作 | 有界的目錄與檔頭檢查;[桌面應用](../desktop-applications.md) |
| JavaScript / Electron | 模組、匯入、source map、路由、IPC 和原生附加元件關係 | Node.js 和 npm;[應用分析](../javascript-application-workflows.md) |
| 網站 | 頁面結構、腳本、網路觀察結果和按請求獲取的螢幕擷取畫面 | Chrome 系瀏覽器;[瀏覽器分析](../browser-observation.md) |
| 已保存的網路擷取 | 請求、回應、可訪問的酬載和來源位置 | HAR;原生 mitmproxy 擷取需要 Linux 上的 mitmdump;[擷取指南](../web-network-captures.md) |
@@ -269,6 +270,7 @@ npx rea-agents@latest setup
- [安裝與設定](../installation.md):AI 代理註冊、提供者組態、更新和卸載。
- [就緒檢查與故障排查](../installation.md#check-readiness-for-your-task):診斷特定 AI 代理或分析引擎。
- [GGUF / safetensors](../model-artifacts.md)
- [CLI 與 Evidence](../cli.md):命令、提供者選擇、快照、匯入/匯出和退出狀態。
- [MCP 契約](../mcp-contracts.md)和[AI 代理提示詞](../mcp-prompts.md):工具結果、會話和引導式調查。
- [工具目錄](../mcp-contracts.md#generated-catalog):建置時生成的工具、提供者和 CLI 命令清單。
+2
View File
@@ -150,6 +150,7 @@ REA 需要 Node.js 22.x(>=22.19)、24.x(>=24.11)或 26+,以及 npm。
| EVM 字节码 | 分派选择器、字节偏移、推断的参数和状态可变性 | Linux x64 上的本地原始字节/十六进制输入载体;[离线 EVM 指南](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| 已记录的 Linux 崩溃 | 原始 note 记录、每个已记录线程的寄存器/信号及可选的映射候选项 | Linux x64 上由调用方提供的 pwntools;可选的 GDB/pwndbg;[已记录崩溃](../recorded-crashes.md) |
| 桌面安装目录 | 运行时候选、支持文件、组件标记和后续操作 | 有界的目录与文件头检查;[桌面应用](../desktop-applications.md) |
| JavaScript / Electron | 模块、导入、source map、路由、IPC 和原生扩展关系 | Node.js 和 npm;[应用分析](../javascript-application-workflows.md) |
| 网站 | 页面结构、脚本、网络观察结果和按请求获取的截图 | Chrome 系浏览器;[浏览器分析](../browser-observation.md) |
| 已保存的网络捕获 | 请求、响应、可访问的载荷和来源位置 | HAR;原生 mitmproxy 捕获需要 Linux 上的 mitmdump;[捕获指南](../web-network-captures.md) |
@@ -269,6 +270,7 @@ npx rea-agents@latest setup
- [安装与设置](../installation.md):智能体注册、提供方配置、更新和卸载。
- [就绪检查与故障排查](../installation.md#check-readiness-for-your-task):诊断特定智能体或分析引擎。
- [GGUF / safetensors](../model-artifacts.md)
- [CLI 与 Evidence](../cli.md):命令、提供方选择、快照、导入/导出和退出状态。
- [MCP 契约](../mcp-contracts.md)和[智能体提示词](../mcp-prompts.md):工具结果、会话和引导式调查。
- [工具目录](../mcp-contracts.md#generated-catalog):构建时生成的工具、提供方和 CLI 命令清单。
+22 -1
View File
@@ -105,6 +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. The syscall trace also rejects access to the still-present
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.
+3 -1
View File
@@ -45,10 +45,12 @@ close_gdb_session {"session_id":"…"}
## Rizin
`start_rizin_debug_session` and `rea debug-with-rizin` require an explicit `inferior_tty` on Linux. Rizin launches the target with stdout and stderr routed to that caller-selected TTY and `dbg.exitkills=false`; the target can therefore continue running and writing to the TTY after REA closes the debugger. This is a visible target output effect, and the caller is responsible for selecting a suitable terminal that remains available. Before closing, REA serializes after the active command, parses the structured `olj` descriptor list, detaches only a unique `ptrace://` descriptor, confirms its absence, reads back `dbg.exitkills=false`, and verifies `/proc/<pid>/fd/1` and `/proc/<pid>/fd/2` still identify the selected TTY by device and inode. Any malformed or ambiguous readback keeps the Rizin session owned for retry. Persistent Rizin debugger sessions are unavailable outside Linux because this verification depends on `/proc`.
`start_rizin_debug_session` and `rea debug-with-rizin` require an explicit `inferior_tty` on Linux. Rizin launches the target with stdout and stderr routed to that caller-selected TTY and `dbg.exitkills=false`; the target can therefore continue running and writing to the TTY after REA closes the debugger. This is a visible target output effect, and the caller is responsible for selecting a suitable terminal that remains available. Before closing, REA serializes after the active command, parses the structured `olj` descriptor list, detaches only a unique `ptrace://` descriptor, confirms its absence, reads back `dbg.exitkills=false`, and verifies `/proc/<pid>/fd/1` and `/proc/<pid>/fd/2` still identify the selected TTY by device and inode. If a previously identified inferior exits after Rizin confirms detach, REA verifies that the original process has ended instead of requiring output descriptors from an exited process. Unresolved identity or ambiguous readback keeps the Rizin session owned for retry. Persistent Rizin debugger sessions are unavailable outside Linux because this verification depends on `/proc`.
Persistent command Evidence retains the caller-selected and resolved startup paths in `parameters.launch_provenance`. These paths describe launch provenance, not the current target after unrestricted commands. `rizin_debug_session_status.output_invalid_utf8` reports whether lossy frame decoding has been observed during the session. Command Evidence sets `output_invalid_utf8` only when loss was observed in frames collected for that command, including retained partial output; earlier startup or command frames do not mark later valid output as lossy.
Session status retains up to 64 recent protocol frames. Each history entry keeps a complete-character UTF-8 prefix of at most 16 KiB, plus a truncation marker when needed; `recent_output_truncated` reports omitted history. This history budget also accounts for replacement characters from invalid UTF-8. It does not shorten command Evidence, which has its own 16 MiB output budget.
```sh
rea debug-with-rizin --inferior-tty /dev/pts/7 ./program dr
```
@@ -0,0 +1,25 @@
# Implementation plan
1. Extend `src/application/environment/environmentSource.ts` so
`loadEnvironmentSource` takes the reporting operation and retains the
capture artifact's SHA-256, letting the export reuse the serve command's
authentication and cross-check unchanged.
2. Add `environmentBundle.ts` to plan the bundle from the source alone: the
name rule, the Dockerfile for the registry and tarball package sources, the
verifier, the smoke task, the README and the copy targets.
3. Add `environmentExport.ts` to read each input once through the
regular-file reader, refuse an occupied directory, a missing tarball or an
unreadable input before writing, then write the planned files with
exclusive creation and copy the authenticated bytes and the tarball
byte-exact.
4. Register `environment-export` in `src/cli/environmentCommands.ts` beside
`environment-serve`, sharing the argument descriptions, and in
`CLI_COMMANDS`.
5. Add the `agentenv` scope, `real-agentenv.yml`, the package script and
`scripts/verify-agentenv-environment.mjs`, wire `ci.yml` and extend the
`ciRequiredLanes` and `ciChangeScope` tables.
6. Add services, conformance and cli-boundary tests; document the command in
`docs/cli.md`, the bundle and lane in `docs/agent-environments.md` and
`docs/testing.md`; record the spec.
No new dependency is introduced; the CLI inventory gains one command.
@@ -0,0 +1,116 @@
# Export an environment manifest as an agent environment bundle
Issue: https://github.com/morluto/rea/issues/4933
## Outcome
`rea environment-export <manifest.json> --evidence <capture.json> <dir>
[--package-tarball <path>] [--name <override>]` writes the manifest and
capture pair that `environment-serve` serves as a bundle folder the agentenv
framework runs with `agent-env run <dir>`: a README with provenance, an env
folder whose Dockerfile installs this exact `rea-agents` version and serves the
copied pair, a Python replay verifier and a smoke task. The hosted
`real-agentenv` lane exports such a bundle from the source-owned Grafana-shaped
capture through the built CLI, packs the checkout into the image and runs it
with the pinned framework release on the runner's Docker. This increment
completes the agent-environment work of the issue; serving came in the
previous increment.
## Requirements
- Read each of the two files once through the regular-file reader, parse it
from those bytes and authenticate and cross-check the pair with
`loadEnvironmentSource` as `environment-serve` does, so the bytes copied into
the bundle are the bytes that were authenticated; every refusal reports
operation `environment-export`, and a manifest projected from a different
capture is refused before anything is written.
- Refuse a bundle directory that exists and is not empty, or that names a file,
with an `invalid_request` whose issue path is `directory`; an absent or empty
directory is accepted. Write every file with the exclusive-create flag so
nothing is ever overwritten.
- Write `README.md`, `envs/<name>/Dockerfile`, `envs/<name>/env.toml`,
`envs/<name>/manifest.json` and `envs/<name>/evidence.json` as byte-exact
copies of the inputs (mode `0600` on POSIX; Windows retains inherited ACLs
and does not provide an owner-only guarantee), `artifacts/check_<name>/verify.py` and
`tasks/smoke.json`, where `<name>` defaults to the manifest's kebab-case name
and `--name` must be a kebab-case label of at most 64 characters that is not a
device name Windows reserves (`con`, `prn`, `aux`, `nul`, `com1`–`com9`,
`lpt1`–`lpt9`), since the env folder could not be created there.
- The Dockerfile reads `FROM node:24.18.0-bookworm-slim`, sets
`MCP_HOST=0.0.0.0` and `MCP_PORT=18765`, installs Debian's `python3` for the
framework's readiness probe, installs
`rea-agents@<PRODUCT_IDENTITY.packageVersion>` from the registry or, with
`--package-tarball`, copies the tarball as `rea-agents.tgz`, installs it
from `/tmp/` and removes it in the same layer, copies the pair to `/env/`,
switches to the image's `node` user
and runs `rea environment-serve /env/manifest.json --evidence
/env/evidence.json`.
- `verify.py` mirrors the framework's echo example: `async def verify(mcp_url)`
over `mcp.client.streamable_http`, lists the tools and checks the count
equals the manifest's, calls the first `GET` tool without path parameters
with no arguments and checks the replayed `status` equals the recorded status
of that tool's first cited record, prints the description and returns
`[{"id": "replay", "result": <bool>, "description": <both checks>}]`; with no
such tool it checks the count only and says so.
- `tasks/smoke.json` is `deploy_env` of `<name>` on the local sandbox followed
by `env_outcome_verifier` with `file_artifact_id` `check_<name>` and
`verifier_id` `replay`. The README records the capture artifact SHA-256, both
Evidence ids, the manifest view digest, the tool count and the package
source, states what replay does and does not establish, names the run
command as `agent-env run .` from the bundle root (the folder it sits in,
whatever the caller named it), and carries the rights note.
- Print one JSON document with `status: "exported"`, the directory, name, tool
count, both Evidence ids, the pinned `package_source` and the written files
with sizes. Register the flat `environment-export` command in the CLI
inventory; no MCP tool is added.
- Add the `agentenv` CI scope, the reusable `real-agentenv.yml` workflow
(`workflow_dispatch` and `workflow_call` with `build_cache_artifact`,
`ubuntu-24.04`, SHA-pinned actions, `setup-python` 3.12, a virtual
environment with `agentenv-framework==0.9.1334`, the runner's Docker, 30
minutes), the `verify:agentenv:environment` script and
`scripts/verify-agentenv-environment.mjs`, which requires absolute
`REA_AGENT_ENV_COMMAND` and `REA_DOCKER_COMMAND` like every other lane
verifier, runs `agent-env run <dir> --sandbox local` bounded to 15 minutes
and resolves nothing from `PATH`; wire `ci.yml` at the four spots and extend
the two CI guard tests.
## Acceptance and limits
Services tests cover the planned file set, the Dockerfile for both package
sources, the verifier text, the smoke task, the README, the name override and
its refusals, writing into an absent and an empty directory with byte-exact
copies and correct sizes, the tarball copy, and the refusals of a non-empty
directory, a file path, a missing tarball and an inline manifest. The
conformance test pins the registry install to the `package.json` version. The
cli-boundary test writes the folder from the fixture pair through the built
CLI, refuses a non-empty directory leaving it unchanged, and refuses a
mismatched pair without creating the directory. The CI guard tests enumerate
the new consumer, route and classification cases. The local end-to-end run
recorded in `verification.md` is the proof that one exported bundle runs under
`agent-env run` with the smoke task passed and no container left behind.
The export copies bytes and never inspects the tarball; it does not build or
run the image itself. Its writes are not transactional: a host failure after
the first file leaves the partial folder for inspection, as `docs/cli.md`
states. The verifier checks one replayed status and the tool count, not every
tool. The lane passes `--sandbox local` as designed although
`tasks/smoke.json` already pins `sandbox_type: local` on its deploy step, so
the flag restates what the task fixes. The lane verifier imports the
Grafana-shaped HAR builder from `tests/fixtures/historicalHar.ts` through
Node's type stripping rather than carrying a second copy under `scripts/`; the
`agentenv` scope lists that fixture so a change to it runs the lane. The lane
proves one framework release on one hosted runner and claims nothing about
any hosted platform. Three additions to the
designed Dockerfile and file set were needed by the framework, each found by
the local run: `MCP_PORT=18765` as the listener default for the port the
framework maps, Debian's `python3` because the framework's local sandbox
probes readiness with `python3 -c "import socket; …"` inside the container and
the slim Node image has none, and `env.toml` naming the environment, because
the framework otherwise reads the name from Python sources the Node image does
not have.
## Deferred issue criteria
This increment closes the agent-environment scope of #4933 together with the
previous three. Running the lane on the maintainer's CI and any follow-up on
hosted platforms are outside this PR.
@@ -0,0 +1,12 @@
# Tasks
- [x] Record the export contract, requirements and the lane.
- [x] Thread the operation name and capture digest through the source loader.
- [x] Plan the bundle: name rule, Dockerfile for both package sources, verifier, smoke task, README.
- [x] Write the bundle with directory, tarball and input refusals and exclusive creation.
- [x] Register the flat CLI command with described arguments and options.
- [x] Add the agentenv scope, workflow, package script and verifier; wire ci.yml; extend the guard tests.
- [x] Add services, conformance and cli-boundary coverage.
- [x] Document the command, the bundle and the lane; record the spec.
- [x] Run static, formatting, duplication, documentation and test gates and the local end-to-end run.
- [x] Repair the review findings (README run command, absolute tool paths, single read, tarball cleanup) and re-run the gates and the end-to-end run.
@@ -0,0 +1,362 @@
# Verification
The initial author record below describes the original macOS tree. The Linux
followup record at the end covers the integrated serve changes and subsequent
repairs in this PR. The two records have different toolchains and cache states.
Verified base: 24574576e4fa74ff56eda965ae287555b7552c03, the tip of the environment-serve increment on fetched main b83b9caf (this increment builds on it).
The worktree carries the manifest-view, streamable-HTTP and serve increments
as commits on upstream main b83b9caf; this increment's changes are uncommitted
edits on top. Every check below ran as written on this tree after the review
repairs; nothing is reported that did not run. Timings are macOS
`/usr/bin/time -l` command accounting (elapsed, user, system seconds and
maximum resident set size of the command and the children it waited for) on
macOS 26.5.1 with Node 22.23.1, npm 12.0.2, Docker 29.5.3 and a Python 3.12.12
virtual environment holding `agentenv-framework 0.9.1334`.
## Review findings addressed
An adversarial review of the first pass found two should-fix findings and
seven nits; each was repaired at its owning boundary before the gates below
ran.
- The bundle README told the reader to run `agent-env run <name>`, which only
works from the bundle's parent when the folder happens to carry the env's
name. The README now says `agent-env run .` from the bundle root and names
the folder's path for any other working directory; the services test
asserts the new block and the absence of the old command.
- The lane verifier resolved `agent-env` and `docker` from `PATH` when the
`REA_*` variables were unset. It now requires absolute
`REA_AGENT_ENV_COMMAND` and `REA_DOCKER_COMMAND`, throwing the standard
actionable message naming the npm script and that nothing is installed, and
checks both paths exist; the workflow exports `REA_DOCKER_COMMAND` from
`command -v docker` beside the virtual environment's `agent-env`;
`docs/testing.md` names both variables and drops the `PATH` default. No
Linux preflight was added, so the lane stays runnable on a macOS host.
- The brittle `assert.doesNotMatch(stdout, /failed/)` is gone; exit code `0`
and the `tasks/smoke.json v<n>: passed` summary already decide the case.
- The inner `agent-env run` timeout is 15 minutes inside the 30-minute job,
so a hung run ends with the verifier's failed receipt rather than the
runner's kill; `docs/testing.md` says so.
- The pair was read twice: parsed once for authentication and re-read from
disk for the byte-exact copies, so a file replaced between the reads was
copied unchecked. `readEnvironmentExportInputs` now reads each file once
through the regular-file reader, parses the value from those bytes with the
shared UTF-8 JSON parser, and the command passes the same buffers to the
export, which copies them; the refusals of inline JSON, a directory and a
file that is not JSON are typed by role, and the spec, plan and both guides
state the single read.
- The tarball Dockerfile left the 6 MB `rea-agents.tgz` in `/tmp` of the
image; the install layer now removes it (`&& rm /tmp/rea-agents.tgz`),
confirmed by listing `/tmp` in the built image below.
- The verifier passes `--sandbox local` as the design specifies; the spec
records that the task's `sandbox_type: local` already pins the provider and
the flag restates it.
- The verifier's import of the HAR builder from `tests/fixtures/` through
Node's type stripping is kept and recorded in the spec's limits with the
reason (no second copy under `scripts/`; the scope lists the fixture).
- Writes are not transactional; `docs/cli.md` now states that a host failure
after the first file leaves the partial folder for inspection and that the
next attempt refuses the non-empty directory, and the spec's limits say so.
## Setup
`npm ci` completed (exit 0; 373 top-level entries). `/usr/bin/time -l npm run
build` passed with 3 tasks successful in 7.60 s elapsed (14.81 s user, 2.69 s
sys, 3013410816 bytes); `/usr/bin/time -l npm run test:prepare` passed with 6
tasks successful, 3 cached, in 1.63 s (3.47 s user, 0.81 s sys, 400752640
bytes).
## Static gates
Every gate ran on the final tree after the last source edit, sequentially:
`npm run check:fast` (typecheck and lint with module boundaries; 2 tasks
successful; 5.28 s elapsed, 23.22 s user, 2.93 s sys, 4564680704 bytes);
`npm run format` rewrote nothing outside this increment's files ("Finished in
635ms on 4077 files"), and `npm run format:check` passed ("All matched files
use the correct format"; 0.87 s, 4.30 s user, 0.64 s sys, 224051200 bytes);
`npx knip` reported no findings (3.49 s, 5.04 s user, 0.72 s sys, 805191680
bytes); `npm run verify:test-discovery` reported "Discovered all 1597 test
files exactly once" (0.55 s, 0.38 s user, 0.14 s sys, 141492224 bytes);
`npm run check:ci:tasks` (typecheck, lint:built, format:check, knip,
metadata:check, jscpd, scan:todos) passed with 8 tasks successful, lint "3764
files, 0 errors, 1690 warnings" and jscpd "3171 files, 2587 clones, 3.34%
duplicated lines" under the 3.5% threshold (4.89 s elapsed, 15.19 s user,
3.86 s sys, 874627072 bytes); `npm run docs:check` passed including the README
consistency test (6 tasks, 5 tests; 4.00 s elapsed, 3.86 s user, 0.94 s sys,
290111488 bytes). `actionlint 1.7.7` (`-shellcheck= -pyflakes=`, from the
review's scratch virtual environment) reported no findings on
`.github/workflows/real-agentenv.yml` and `.github/workflows/ci.yml`. A
case-insensitive grep for the forbidden words and marker comments over the 23
new or modified files matched only the `scan:todos` script name in
`package.json` and this file.
## Test projects
Source group: `/usr/bin/time -l npx vitest run --project services --project
conformance` passed 122 files, 1524 tests in 11.08 s elapsed, 23.10 s user,
2.24 s sys, 1631240192 bytes. The increment's files are
`environmentBundle.test.ts` (7 tests: the planned file set and copy targets,
the registry Dockerfile pinned to `PACKAGE_METADATA.version` with the
readiness-probe layer, the tarball Dockerfile installing and removing
`/tmp/rea-agents.tgz`, the verifier text naming `get_annotations` as the
first parameterless `GET` tool with recorded status 200 of record 25, the
smoke task, the README's provenance, `agent-env run .` block and rights note,
the name override and six refused names), `environmentExport.test.ts` (6
tests: the reader returning each file's bytes and parsed value, its refusals
of inline JSON, a directory and malformed JSON by role, writing into an absent
directory with the read bytes copied unchanged and reported sizes, the
tarball copy, the refusals of a non-empty directory, a file path and a missing
tarball with nothing written, and an existing empty directory accepted),
`environmentSource.test.ts` (4 tests; the loader takes the reporting
operation) and the conformance test `environmentBundlePackagePin.test.ts` (1
test: the registry install line ends with `rea-agents@<package.json version>`
and never uses `latest` or a range).
Built group after `npm run test:prepare`: `/usr/bin/time -l npx vitest run
--project cli-boundary --project boundary` over `environmentExportCli` (3),
`ciChangeScope` (228), `ciRequiredLanes` (17), `workflowActionPinning` (5),
`ciCachePolicy` (6), `cliToolCoverage` (1), `cliStartupImports` (5) and
`ciTestProjects` (11) passed 8 files, 276 tests in 432.80 s elapsed, 303.47 s
user, 92.63 s sys, 422412288 bytes; `tests/boundary/filesystem/productCatalog`
passed separately (10 tests, 5.32 s). The cli-boundary file writes the folder
from the fixture pair through the built CLI and checks the seven written
paths, the byte-exact copies and the Dockerfile's first line and `CMD`;
refuses a non-empty directory leaving its one file in place; and refuses a
mismatched pair without creating the directory.
## Local end-to-end run
With the built CLI in this worktree, from a fresh scratch directory:
`inspect-web-network-capture grafana-like.har har --format json --json` wrote
capture Evidence `ev_4ee4759b…` (28 records); `inspect-analysis-view` with the
inline source and all three template rules wrote manifest Evidence
`ev_6553a8e5…` naming that parent, `grafana-example`, 19 tools, view digest
`8d1eb3ee…`. `npm pack --ignore-scripts` of the checkout produced
`rea-agents-6.6.0.tgz` (6039238 bytes). `environment-export manifest.json
--evidence capture.json <tmp>/grafana-example --package-tarball <tgz> --json`
exited 0 and printed `status: exported`, `tool_count: 19`, `package_source:
{kind: tarball}` and eight files: `README.md` (2076 bytes),
`envs/grafana-example/env.toml` (37), `envs/grafana-example/Dockerfile` (441),
`artifacts/check_grafana-example/verify.py` (1534), `tasks/smoke.json` (291),
`envs/grafana-example/manifest.json` (15701),
`envs/grafana-example/evidence.json` (58296) and
`envs/grafana-example/rea-agents.tgz` (6039238); `cmp` confirmed the two
Evidence copies and the tarball byte-identical to the inputs. The Dockerfile's
install line reads `RUN npm install -g --ignore-scripts --no-fund --no-audit
/tmp/rea-agents.tgz && rm /tmp/rea-agents.tgz`, and the README's run section
is the `agent-env run .` block.
`/usr/bin/time -l agent-env run <tmp>/grafana-example` exited 0 in 43.66 s
elapsed (5.19 s user, 3.26 s sys, 129318912 bytes), output
```text
[tasks/smoke.json] step 1/2 env done in 25.1s
[tasks/smoke.json] step 2/2 replay (env_outcome_verifier)
replay: listed 19 tools, expected 19; get_annotations replayed status 200, recorded 200
[tasks/smoke.json] passed in 25.1s
Tasks:
tasks/smoke.json v1: passed (replay: 1), 25.1s, instance @local/…/grafana-example/smoke-nwvvojs7
Tore down 1 sandbox.
```
`docker ps -aq` before and after the run listed the same three pre-existing
containers (a Grafana container, an exited container and the framework's
registry from earlier sessions, unrelated to this run); no container was
added, and the image count rose from 19 to 20 for the built env image
`5a5b3bf62aae`. `docker run --rm --entrypoint sh 5a5b3bf62aae -c 'ls -la
/tmp; rea --version; id -un'` listed only `node-compile-cache` in `/tmp` (no
`rea-agents.tgz`), printed `6.6.0` and ran as `node`.
`REA_AGENT_ENV_COMMAND=<venv>/bin/agent-env REA_DOCKER_COMMAND=$(command -v
docker) /usr/bin/time -l node scripts/verify-agentenv-environment.mjs` exited
0 in 37.24 s elapsed (10.42 s user, 4.45 s sys, 268533760 bytes) and printed
the receipt `status: passed`, `public_cases: 5`, `upstream: agentenv-framework
0.9.1334`, `runner: darwin arm64; host Docker`, `docker_before: {containers:
3, images: 20}`, `agent_env_run: {exit_code: 0, seconds: 32}` with the same
passed summary in its stdout tail, `docker_after: {containers: 3, images: 21,
new_containers: []}` and `process_lineage.status: verified` with no
descendants. The first hosted run of the lane, on a runner with no prior
framework state, created the framework's image-store helper `agentenv-registry`
(`registry:2`, container `b2e047f4c6cd`) during `agent-env run`; the run itself
passed (`exit_code: 0`, 354 s, `tasks/smoke.json v1: passed`, "Tore down 1
sandbox.") but the first form of the leak check counted the helper and failed.
The check now lists containers with their names, excludes
`agentenv-registry[-<port>]` and reports it under `image_store_helpers`; the
local receipt gained `image_store_helpers: []` because the helper already
existed before the run here. Public ECR's anonymous pull quota refused the
framework's `postgres:16-alpine` pull with `429 Too Many Requests, Data limit
exceeded` on two hosted runs out of six (the second and, after the stack was
rebuilt, the sixth); the verifier now retries the run once, after 90 seconds,
when the failure carries that registry's signature, and records
`attempts: 2` with `retried_for` in the receipt. The local receipt reports
`attempts: 1`. Removing that helper (`docker rm -f
agentenv-registry`) and running the verifier again reproduced the fresh-host
path locally: the run recreated it and the receipt passed with
`image_store_helpers: ["agentenv-registry"]`, `new_containers: []`
(`agent_env_run: {exit_code: 0, seconds: 33}`). Without `REA_DOCKER_COMMAND` the verifier exited 1 before
touching anything with "verify:agentenv:environment requires absolute
REA_DOCKER_COMMAND; see docs/testing.md. No dependencies are installed by this
verifier."; with a relative `REA_AGENT_ENV_COMMAND=agent-env` it exited 1 with
the same sentence naming that variable.
Refusals through the built CLI: exporting into the already written bundle
directory exited 1 with `invalid_request`, issue path `["directory"]` and the
message "is not empty (4 entries); choose an absent or empty directory";
exporting the manifest against the capture of one selected record
(`--record 0`, `ev_3249d233…`) exited 1 with `invalid_request`, issue path
`["evidence", "evidence_id"]` and "The manifest was projected from a
different capture than the supplied evidence file.", creating no directory;
a truncated `broken.json` as the evidence exited 1 with `invalid_request`,
issue path `["evidence"]`, reason `invalid_format` and "broken.json is not
valid JSON: Unexpected end of JSON input", creating no directory. An export
without `--package-tarball` wrote a Dockerfile whose install line is
`RUN npm install -g --ignore-scripts --no-fund --no-audit rea-agents@6.6.0`,
the `package.json` version, with no tarball beside it; the tarball variant
copies `rea-agents.tgz` and installs and removes `/tmp/rea-agents.tgz`.
## Independent review
The adversarial review of the first pass is the independent review of this
increment; its findings and their repairs are listed above. One further
observation surfaced while repairing them: the single-read helper routes the
export's input refusals through the export module rather than the CLI's
shared JSON-input parser, so the inline-JSON refusal is now a typed
`invalid_request` on the `manifest` or `evidence` issue path instead of the
parser's `input_path`/`input_reason` envelope; the cli-boundary tests did not
depend on that envelope.
## Scope and measurement limits
The framework readiness probe, the port variable default and the `env.toml`
name were found by running the bundle in the first pass, not by reading a
published contract; they are recorded in the spec as the three additions to
the designed file set. The local run and the verifier used the host's Docker
with the framework's gateway and service-database images already built from
earlier sessions, so the "first run also builds the infrastructure" path was
not timed here. The verifier's container check compares `docker ps -aq`
before and after; images built by the run remain by design and are only
counted. `npm pack --json` has the npm 12 object shape on this host and the
npm 11 array shape on the hosted runner; the verifier accepts both but only
the former was exercised locally. The hosted `real-agentenv` workflow was not
dispatched from this tree. The built projects ran on this host's Node 22.23.1
rather than the pinned 24.18.0. The `/usr/bin/time -l` figures account for
each command and the children it waited for; Docker's own work runs in the
daemon and is outside them. Windows was not run.
## Linux followup verification (2026-10-19)
The original PR was updated from main after #4955 and #4975 merged. The
followups retain the author's commits and portable-name checks, seal private
JSON parser output once for shared immutable authentication/replay, reserve
sealing work before reading, preflight the served catalog before exporting,
translate changed-file failures by input role, defer export imports during CLI
registration, and verify the supplied framework executable before attributing
its results. The default `rea mcp` transport remains stdio.
Executed on Linux x64 with Node 24.18.0, npm 11.16.0, Docker 20.10.24,
Python 3.12.13 and an isolated `agentenv-framework==0.9.1334` environment:
- `turbo run typecheck lint:built format:check docs:check:built knip metadata:check artifacts:skills --concurrency=1`: ten tasks passed, one cached, 289.315 s elapsed, 284.552 s CPU, 4450.18 MiB peak process-family RSS.
- The focused source/compiled CLI/SDK/lifecycle/configuration run passed 399 tests in 24 files. A later run passed the updated 231 CI-selection cases, three executable-identity cases and ten product-catalog cases. The latter needed its generated catalog first; its initial missing-file failure was preparation, not a passing check.
- Four previously recorded, unauthenticated real GitHub API responses were exported with the checkout tarball. The generated Dockerfile built unchanged. A fresh non-root container replayed every response twice through the official MCP SDK, matching body, status, Evidence ordinal/id and untrusted-content provenance. Discovery/card parity and tarball removal passed. The standalone test supplies `ENVIRONMENT_NAME` as the framework does. Runtime verification with the built image took 12.393 s / 6.002 s CPU / 313.11 MiB process-family RSS; image-build cost is excluded. A Docker stats sample was 250.5 MiB, not a measured container peak.
- The production `verify-agentenv-environment.mjs` observed `agent-env 0.9.1334`, exported its 28-record source-owned Grafana-shaped fixture, deployed it with the real framework and passed `tasks/smoke.json`. The receipt reported five public cases, one sandbox torn down, no new task containers and no supervised descendants. This successful run used already prepared infrastructure: 141.697 s / 101.971 s CPU / 501.61 MiB process-family RSS. Earlier attempts failed because this host's proxy environment required optional SOCKS support and its default home sandbox directory was unwritable. Only the test process's proxy variables were cleared; supported `XDG_STATE_HOME` and `AGENT_ENV_LOCAL_SANDBOX_DIR` pointed into temporary storage. The shared Docker daemon was not reconfigured or restarted. The framework's persistent registry helper and images remain as its documented behavior.
A matched public `environment-serve`/SDK task compared the pre-followup serve
build with the final implementation. Both used the same GitHub capture with
1,000 synthetic HAR-extension items (each containing additional containers),
one first call and twenty warm identical replays. Fixture generation was
excluded. This is controlled stress data, not newly observed application data.
Larger 25,000/75,000-item projection attempts returned the existing typed
representation-budget refusal; that budget was not relaxed.
| Measurement | Before | After |
| ----------------------- | ----------: | ----------: |
| Cold listener startup | 2189.064 ms | 2862.860 ms |
| First call | 76.950 ms | 45.265 ms |
| Twenty warm calls | 324.119 ms | 267.132 ms |
| Completed task elapsed | 3.229 s | 3.885 s |
| Completed task CPU | 3.196 s | 3.827 s |
| Peak process-family RSS | 466.43 MiB | 470.21 MiB |
These single completed samples do not establish an overall speed or memory
improvement. Separate identity regressions establish that large reported JSON
trees are shared rather than copied and that caller-owned mutable trees are
not frozen. Token usage was not measured. CPU is child user+system time;
process-family memory sums sampled descendant RSS every 50 ms and may count
shared pages twice. Docker daemon/container CPU and peaks are outside that
process-family measurement and remain unmeasured. Builds used one task at a
time, one CPU and a soft 3 GiB Go limit; Docker builds were serialized and
limited to one CPU/4 GiB, and the standalone replay container to one CPU/2 GiB.
Windows execution and the published registry package were not tested in this
followup; the checkout tarball proves the code before its release.
### Output ownership and final review followups
The output boundary now uses the existing `SafeOutputTree` owner instead of
separate directory admission and pathname writes. It checks the admitted root,
parents, file identities and complete entry inventory around publication, keeps
failed-close authority, and preserves an existing empty caller root on rollback.
The optional package is held as one regular-file descriptor before output
writes, streamed with hash/readback verification, and checked for changes before
release. POSIX file modes are set and verified as `0600` independently of umask;
newly owned directories are `0700`. Existing root permissions remain caller owned.
Windows privacy depends on the selected destination ACL; no owner-only Windows
ACL guarantee or Windows runtime validation is claimed. Portable pathname
operations still require a trusted destination and parents against concurrent
replacement.
A compiled CLI counterexample under umask `0400` failed before the mode fix and
succeeded afterward with every generated file readable at `0600` and exact
Evidence bytes. Public CLI coverage also verifies that `symlink/..` retains its
filesystem meaning for the destination and package path. Real-filesystem tests
exercise destination replacement, foreign entries, parent symlinks, read-only
permissions and admitted-tarball replacement. Controlled close failures exercise
post-publication recovery and persistent retained ownership.
The inventory owner accepts canonically equivalent Unicode directory listings
without collapsing distinct filenames: an NFC multiset comparison is followed
by the original path identity checks. Tests simulate decomposed `readdir`
spelling over a real owned file and create an extra distinct Linux decomposed
foreign file. These establish the boundary behavior, not actual HFS+ execution.
Manifest, Evidence and tarball descriptors use the shared resource scope's close
retry. Persistent failures retain the canonical cleanup lease and produce a
tagged `environment-export` error. The compiled JSON CLI regression injects a
persistent manifest close failure before any destination write.
The framework verifier reuses `execNpm` and honors selected `npm_execpath`.
Four process-boundary attribution cases pass, including a conflicting PATH npm.
Those controlled executables verify attribution only.
After merging main `b4938aed5`, the generated Dockerfile built unchanged with the
checkout package and replayed all four captured public GitHub API responses
twice through the official MCP SDK in a fresh non-root container. Input bytes,
status/body/Evidence/provenance, discovery/card parity and package removal passed.
Warm base-image build plus pack/export/runtime verification: **40.699 s elapsed,
8.274 s process CPU, 421.04 MiB peak process-family RSS**. The real pinned
`agent-env 0.9.1334` verifier then passed all five public cases and the smoke task,
tore down its sandbox, and reported no new task containers or supervised
descendants: **156.895 s / 102.871 s CPU / 500.34 MiB**. Framework infrastructure
was already prepared. The later Unicode, close-failure and npm-selection repairs
have separate boundary regressions; they do not establish new real-platform
coverage.
A matched export comparison before the main merge used the same manifest
(6,416 bytes), capture (98,519 bytes) and checkout tarball (6,221,957 bytes), with
all copied inputs byte-exact. Before/after the output-owner repair: **1.827/2.604
s elapsed, 1.807/2.545 s CPU, 316.43/334.11 MiB** peak process-family RSS. These are
single process samples with uncontrolled host filesystem cache; the additional
ownership checks increased measured cost. They do not establish a speed or
memory improvement.
All followup heavy work uses one CPU and one test/build task at a time. Docker
builds are limited to one CPU/4 GiB, standalone runtime containers one CPU/2 GiB.
Process-family RSS is sampled every 50 ms and may double-count shared pages.
Docker daemon/container CPU and peak memory, agent tokens and fresh-framework
infrastructure cost are unmeasured. The previously documented early catalog
heap refusal is not represented as a passing run.
Final focused verification on the reviewed source passed **452 tests in 33 files** (including 232 CI-selection cases and the compiled CLI regressions): **161.276 s elapsed / 159.900 s CPU / 1242.43 MiB** peak process-family RSS. The final typecheck/build/lint gate passed: **218.427 s / 218.130 s CPU / 4449.45 MiB**.
@@ -0,0 +1,36 @@
# Implementation plan
1. Add `src/application/environment/environmentSource.ts` to authenticate the
two Evidence files, require the manifest view kind and the capture
operation, refuse a parent mismatch, and reduce every cited record to its
request line, status, content type and retained response text through the
slice-1 request-line reader, so the server holds only what replay returns.
2. Add `environmentTools.ts` to map manifest tools to MCP tool definitions with
one hand-built JSON Schema per tool that both `registerTool` (through the
SDK's `fromJsonSchema`) and the card consume, and to build the card in the
echo example's key order.
3. Add `environmentReplay.ts` to score cited records by path-segment matches,
then query matches, keep manifest order on ties, and shape the replay result
with JSON-like parsing, UTF-8-safe truncation and the replay provenance
block; export the slice-1 JSON-like predicate instead of restating it.
4. Add `src/server/environment/serveEnvironment.ts` to build the `McpServer`
whose handlers attach REA's target-content `_meta`, the card and `/agentenv`
routes (the latter reading its body through the SDK's bounded reader), and
to serve them through the slice-2 `serveStreamableHttp` with its `routes`
and `onerror` seams; add `src/config/environmentName.ts` for
`ENVIRONMENT_NAME`.
5. Add `src/cli/environmentCommands.ts` registering `environment-serve` through
`withCommandCancellation` and `logCliCommand`, resolving host and port with
the slice-2 endpoint parser, reading files through `parseCliJsonInput`,
importing the listener lazily, awaiting the cancellation signal or a
listener failure and returning one `stopped` document or a typed error;
register the name in `CLI_COMMANDS` and the lazy module in the startup
import probe.
6. Share the fixture pair through `tests/fixtures/environmentServe.ts` and the
listener spawn through a generalised `startListeningProcess`; add services,
adapters, mcp-boundary, cli-boundary and process-boundary tests.
7. Document the command in `docs/cli.md`, add `docs/agent-environments.md` with
its sidebar and index entries, and record the spec.
No new dependency is introduced. REA's tool contracts, catalog digests and the
stdio transport are unchanged; the CLI inventory gains one command.
@@ -0,0 +1,133 @@
# Serve an environment manifest as a replay environment
Issue: https://github.com/morluto/rea/issues/4933
## Outcome
`rea environment-serve <manifest.json> --evidence <capture.json> [--host H]
[--port N]` serves an environment manifest, projected by `inspect-analysis-view`
from retained HAR capture Evidence, as an agent environment: an MCP server at
`/mcp` with one tool per manifest tool that replays the retained records the
tool cites, the environment card at `/.well-known/agent-env.json` in the shape
the agentenv framework's echo example publishes, and a `/agentenv` data plane
that answers every JSON-RPC method as not found. Nothing is fetched from the
recorded application; every answer is retained Evidence marked as target
content. This increment adds the serve command only; exporting a bundle is a
later increment.
## Requirements
- Read both files as bounded JSON input, authenticate each as REA Evidence and
require `inspect_analysis_view` Evidence of kind `environment-manifest` and
complete `inspect_web_network_capture` Evidence; refuse any other pair with an
`invalid_request` whose issue path names the offending file.
- Forward caller cancellation to file reads and check startup boundaries before
authentication/listener work; an already observed abort must not bind or
announce a listener.
- Refuse a manifest whose `parent_evidence_id` differs from the evidence file's
`evidence_id` before binding any port; Evidence authentication covers the
capture's records, so no further record-coverage refusal is defined.
- Build an `McpServer` from the manifest alone: each tool's input schema lists
every path parameter as a required string described by its segment index,
rule and observed values, every observed query name as an optional string,
and an optional `body` object for `POST`, `PUT` and `PATCH` (a query name
that collides with a path parameter becomes `query_<name>`, a query name
longer than 64 characters becomes `query_<n>`, and the body
becomes `request_body` when a query parameter is named `body`), closed with
`additionalProperties: false` so unknown arguments are refused; the
description reads `METHOD template; replays retained records [ordinals];
evidence ev_…`. The served catalog stays separate from REA's own tool
contracts and digests.
- Prefix tool descriptions with the shared captured-catalog warning so
standalone card readers receive the trust notice before MCP initialization.
- Bound each path-observation, body-key and cited-ordinal description sample to 1 KiB
of UTF-8 whole values before joining them, with a separate omitted-count and
manifest-Evidence notice. Keep complete arrays and replay semantics unchanged.
- Bound captured method, path and query-name prose to UTF-8-safe display prefixes
under the same budget, with an explicit full-value Evidence notice. Preserve
complete lookup values; long path and query names use collision-safe aliases.
- Parse a recorded query only when supplied query arguments can affect selection.
- Replay by selecting, among the tool's cited records, the one whose path
segments at the parameter indexes match the most supplied values, then the
most of those segments equal to the value as written rather than only after
percent-decoding, then the most supplied query values, keeping manifest order
on ties; return `status`,
`content_type`, `body` (parsed JSON for JSON-like content types with safe numeric conversion,
else text; bodies over 256 KiB cut at a UTF-8 boundary with
`truncated: true`) and `replay` with `record_ordinal`, `evidence_id`,
`exact_match`, `recorded_path` and `recorded_query` (each cut to 1 KiB, with
`recorded_line_truncated`; an explicit empty query is `?`), `body_recorded` (false
when the capture kept no response body, so a `null` body is not mistaken for
a recorded one), `body_encoding` (`base64` when the retained bytes are not
UTF-8, so they are returned exactly rather than decoded lossily) and
`truncated` (a large retained base64 body is decoded only up to that limit),
as both
structured content and text, with REA's existing target-content provenance
marker in `_meta`.
- Serve the card with exactly the echo example's keys and nesting: `name`
(`ENVIRONMENT_NAME` from the environment snapshot, else the manifest name; a
set but blank value is refused as `configuration_invalid`),
`protocolVersion` `1.0`, `url` `/agentenv`, `preferredTransport` `JSONRPC`,
`additionalInterfaces` `[{url: /mcp, transport: mcp}]`, `capabilities` with
`extensions: null`, the tools and `operations: []`, and
`children_environments: null`. Read the `/agentenv` body within the SDK's
4 MiB bound and answer `413` with JSON-RPC `-32000` beyond it.
- Resolve host and port as `rea mcp --http` does (flags, `MCP_HOST`/`MCP_PORT`,
then `127.0.0.1` and port `0`), announce the bound URL as one pino JSON line
on stderr, serve through the shared streamable HTTP listener, and run until
SIGINT or SIGTERM only, then close, print one `stopped` document and exit
`130` or `143` through the shared command cancellation handler; a signal
during loading returns `cancelled` before binding; a listener
failure after binding is logged and ends the command with a
`resource_constraint` error and exit `1`.
- Register the flat `environment-serve` command in the CLI inventory with
described arguments and no MCP tool contract; keep the CLI wiring thin, the
mapping and replay in the application layer and the server assembly in the
server layer; load the listener lazily so the command catalog registers
without it.
## Acceptance and limits
Services tests cover source loading and each refusal, tool mapping and schema
derivation, the card shape, exact and best-effort selection, query matching,
tie order, text and non-parsing bodies, truncation at a UTF-8 boundary and
base64 content. Adapters tests byte-compare the served card with the echo card
shape carrying the fixture tools, drive `/agentenv` including a body over the
bound, and call tools over the SDK streamable HTTP client with provenance and
the unknown-argument refusal asserted. The mcp-boundary test
spawns the built CLI on a manifest and capture produced from the slice-1
Grafana-shaped fixture and asserts tool count, an exact `get_users_by_id`
replay with `body.login === "probe"`, an inexact replay, the card under
`ENVIRONMENT_NAME` and the data-plane refusal; the cli-boundary test covers
the mismatched-parent refusal, the missing `--evidence` usage error and an
unreadable path; the process-boundary test asserts a `143` exit with a
released port. Replay validates no supplied values, performs no network
activity and establishes no authorization, response semantics or state
transitions. One MCP client is served at a time, as the shared listener
defines. Non-loopback binds relax the `Host` check and are not exercised; a
listener `error` after binding is wired but not provoked by a test.
## Resource and cancellation boundaries
- Whole discovery admission reserves at most 1 MiB using six bytes per UTF-16
unit plus schema overhead before retaining each schema property. Aggregate
tools, arguments and selected environment identity participate; oversized
catalogs fail with a non-retryable capacity error before bind. The calibration
used 1500 query fields with eight concurrent discovery requests; compact wire
size can be smaller than the conservative reservation.
- Query matching scans selected names one field at a time; path scoring scans
once and retains only supplied parameter coordinates. Native form-decoding
semantics, malformed escape handling and complete captured facts are preserved.
- Content-type display is bounded to 1 KiB and reports `content_type_truncated`;
complete media-type semantics remain available to body interpretation.
- Cancellation also owns DNS/listen startup; an observed abort closes the
listener before its URL is announced.
## Deferred issue criteria
Exporting a manifest and its evidence as an agent-environment bundle with a
verifier, and the hosted verification lane, are later independent increments
of #4933. This PR must reference rather than close the whole issue.
Numeric data-plane IDs that lose value through JSON number conversion are invalid
requests with null response IDs, rather than silently changed correlation values.
@@ -0,0 +1,12 @@
# Tasks
- [x] Record the serve contract, requirements and deferred increments.
- [x] Load and cross-check the manifest and capture Evidence with typed refusals.
- [x] Map manifest tools to MCP input schemas and the environment card.
- [x] Select and shape replayed records with exact-match, truncation and provenance.
- [x] Assemble the MCP server, card and data-plane routes on the shared listener.
- [x] Register the flat CLI command with host, port and environment-name resolution.
- [x] Add services, adapters, mcp-boundary, cli-boundary and process-boundary coverage.
- [x] Document the command and the agent environment page; record the spec.
- [x] Run static, formatting, duplication, documentation and test gates and the
built-CLI exchange with the Python MCP client.
@@ -0,0 +1,245 @@
# Verification
Verified base: cf4cc6faab0fb2c444ca054db8b98cb981bae6c9 (fetched main).
The worktree carries the manifest-view and streamable-HTTP increments as
commits on that base; this increment's changes are uncommitted edits on top.
Every check below ran as written on this tree in the review-response pass;
nothing is reported that did not run. Timings are macOS `/usr/bin/time -l`
command accounting (elapsed, user, system seconds and maximum resident set
size of the command and the children it waited for).
## Review findings addressed
An adversarial review of the first pass found one should-fix and six nits;
each was repaired at its owning boundary before the gates below ran.
- `POST /agentenv` read its body with `request.json()` on the streamed
`node:http` body, so a 60 MB payload was buffered before the `-32700`
answer. The route now reads through the SDK's `readRequestBody` with
`DEFAULT_MAX_REQUEST_BODY_SIZE`, answering `413` with JSON-RPC `-32000`
(`id: null`) before parsing, and parses within the bound through the
domain's `safeParseJson`. The JSON-RPC error helper of the shared listener
is exported as `jsonRpcErrorResponse` and reused rather than restated.
- A set but blank `ENVIRONMENT_NAME` refuses with `configuration_invalid`,
as a blank `MCP_HOST` does in the sibling parser; `docs/cli.md` and
`docs/agent-environments.md` now say so, and the spec records the
divergence from the design's `||` reading as deliberate.
- The record-coverage refusal in `loadEnvironmentSource` was unreachable for
authenticated pairs (the Evidence id is computed over `normalized_result`,
so a matching parent id implies identical records, each with a request
line by construction of the projector). The branch is gone: cited records
are indexed unconditionally, a record without a request line is left out
and the tool refuses at call time through the existing no-record path. The
claim was removed from `docs/agent-environments.md` and `spec.md`, and the
services test now asserts an empty manifest indexes nothing and a tampered
capture is refused by authentication.
- Every advertised input schema closes with `additionalProperties: false`,
so an unknown argument is refused as invalid arguments instead of silently
degrading to an omitted one. The agentenv framework's card consumers
(`verify_env_card.py`, the gateway's `tool.inputSchema` pass-through and
the spec-conformance normaliser) read `properties` and `required` only, so
the extra key does not disturb them; the guide names it as a key the echo
schema does not carry.
- The tool description now reads `METHOD template; replays retained records
[ordinals]; evidence ev_…`, as the design text specifies.
- `serveEnvironment` passes an `onerror` to the shared listener that logs
`{ error }` at `error` level and forwards to the caller; the command races
the cancellation signal against that failure and, on a listener failure
after binding, closes the listener and returns the same typed
`resource_constraint` error the bind failure returns (exit `1`) instead of
serving nothing. The two constructions share one `transportError` helper.
- `tests/boundary/cli/cliStartupImports.test.ts` lists
`dist/server/environment/serveEnvironment.js` as `environment-server` in
`DEFERRED_IMPORTS`, so the `--help` probe would fail if the serve command
ever imported the listener eagerly.
## Setup
`npm ci` exited 0 (540 packages added, 541 audited; 4.79 s elapsed, 3.46 s
user, 7.34 s sys, 880803840 bytes). After the edits above, `npm run build`
exited 0 (three turbo tasks; 4.61 s elapsed, 14.76 s user, 3.23 s sys,
3053060096 bytes) and `npm run test:prepare` exited 0 (six tasks; 1.28 s
elapsed, 2.94 s user, 0.67 s sys, 424935424 bytes), so every built-group run
and built-CLI check below used a `dist/` carrying the revised serve command.
## Static gates
Each exit 0 on the final tree: `npm run check:fast` (typecheck and lint,
2 tasks; 4.76 s elapsed, 23.36 s user, 2.56 s sys, 4458840064 bytes). `npm run
format` (4064 files; 0.93 s elapsed, 4.12 s user, 0.76 s sys, 226344960
bytes) then `npm run format:check` (all 4064 files formatted; 0.64 s elapsed,
4.19 s user, 0.66 s sys, 219906048 bytes). `npx knip` (no findings; 3.49 s
elapsed, 4.92 s user, 0.63 s sys, 871645184 bytes). `npm run check:ci:tasks`
(8 tasks successful, 2 served from the turbo cache; `lint:built` 3756 files,
0 errors; jscpd 3164 files, 2583 clones, 3.34% duplicated lines under the
3.5% threshold; the stray-marker scan; 7.16 s elapsed, 26.46 s user, 5.88 s
sys, 2939142144 bytes). `npm run verify:architecture-guards` passed across
1523 source files and `npm run verify:test-discovery` discovered all 1592
test files exactly once. `npm run docs:check` (six tasks plus the README
consistency test, 5 cases; 3.37 s elapsed, 3.49 s user, 0.84 s sys,
291618816 bytes). After the last edit of this record, `npm run format`,
`npm run format:check` and `npm run docs:check` were rerun (each exit 0) and
the same static set was rerun uncached as `npx turbo run typecheck lint:built
format:check knip metadata:check jscpd scan:todos --force` (8 tasks
successful, 0 cached, 3.34% duplication; 8.40 s elapsed, 48.82 s user, 7.77 s
sys, 4638474240 bytes). A case-insensitive grep for the forbidden words and
marker comments over all 28 new or modified files found nothing.
## Test projects
Source group on the final tree: `/usr/bin/time -l npx vitest run --project
services --project adapters` passed 343 files, 5196 tests with 8 skipped, in
99.55 s elapsed, 93.60 s user, 28.88 s sys, 1781055488 bytes. The increment's
files are `environmentSource.test.ts` (4 tests: pair authentication and
exchange indexing, parent mismatch as `invalid_request` with path
`["evidence","evidence_id"]`, other view kind, non-capture evidence and
non-Evidence JSON, an empty manifest indexing nothing with a tampered capture
refused by authentication), `environmentTools.test.ts` (5 tests: ordered
mapping and the `; evidence` description, required path parameters with rule,
observed values and `additionalProperties: false`, optional query strings
without a body for reads, a body object for writes, the card's key order),
`environmentReplay.test.ts` (7 tests, unchanged in this pass) and
`serveEnvironment.test.ts` (5 adapters tests: the card text byte-equal to the
echo card shape with the fixture tools, `/agentenv` answering `-32601` with
`-32700` for a malformed body, a route-level body of
`DEFAULT_MAX_REQUEST_BODY_SIZE` plus envelope answered `413` `-32000` with
`id: null`, a full listener driven by the SDK streamable HTTP client with
`_meta` equal to `TARGET_CONTENT_RESULT_META`, exact and inexact replays, an
argument-less call and an unknown argument both refused with `isError`, and
the `renamed` override with an oversized body answered `413` through
`node:http` and a released port).
Focused built group after `test:prepare`: `npx vitest run --project
cli-boundary --project mcp-boundary --project process-boundary --project
boundary` over `environmentServeCli`, `environmentServeMcp`,
`environmentServeShutdown`, `mcpHttpShutdown`, `streamableHttpMcp`,
`cliToolCoverage`, `cliStartupImports` (now carrying the `environment-server`
deferred import), `dispatcher`, `productCatalog`, `documentationFacts` and
`ciTestProjects` passed 11 files, 33 tests (16.38 s elapsed, 25.77 s user,
5.94 s sys, 941948928 bytes).
Full built-group projects ran one after another on the final `dist/` from a
background shell while the built-CLI exchange below ran in the foreground.
`/usr/bin/time -l npx vitest run --project mcp-boundary` passed 156 files
with 2 skipped, 914 tests with 7 skipped, in 166.23 s elapsed, 319.51 s user,
46.18 s sys, 4452171776 bytes. `/usr/bin/time -l npx vitest run --project
cli-boundary` exited 1: 109 files passed and 3 failed, 663 tests passed,
2 skipped and 7 failed, in 432.45 s elapsed, 725.28 s user, 213.32 s sys,
641597440 bytes. No failing file belongs to this increment.
`javascriptApplicationJsonOutput.test.ts` (4 cases) and
`javascriptApplicationProgress.test.ts` (2 cases) failed with the worker's
result-capacity constraint ("The parent's result capacity was exhausted
after retaining static facts for main.js"); rerun together on the idle host
after the chain they passed 2 files, 17 tests (17.05 s elapsed, 26.40 s user,
8.47 s sys, 282394624 bytes), the load classification the previous pass
recorded. `closedStdout.test.ts` "stops quietly when the reader closes during
streamed JSON" exits `1` instead of `141` with 1009 bytes received, alone as
well as in the project, the environmental failure the previous pass
reproduced on a clean clone (macOS, Node 22.23.1, npm 12.0.2).
`commandFinalizationCancellation.test.ts`, which the previous pass saw fail
on worker order, passed in this run.
`/usr/bin/time -l npx vitest run --project process-boundary` exited 1: 56
files passed, 2 skipped and 3 failed, 463 tests passed, 19 skipped and 5
failed, in 431.71 s elapsed, 148.34 s user, 114.81 s sys, 710000640 bytes.
`environmentServeShutdown.test.ts` and `mcpHttpShutdown.test.ts` passed inside
it. `jadxIntegration.test.ts` failed three cases at the 30 s test and 10 s
hook timeouts ("retires an idle engine", "completes large class inventories",
"close cancels active and queued work"), the lane the previous pass recorded
as moving between runs on this host. `releaseArtifactCanary.test.ts` fails
parsing `npm pack --json` ("expected tuple, received object"), the npm 12.0.2
shape the previous pass reproduced on a clean clone.
`processCaptureLifecycle.test.ts` "keeps the process deadline bounded when the
wall clock moves backward" failed with `expected false to be true` on
`result.ok`; rerun alone on the idle host it failed the same way with 23
passed (38.12 s elapsed, 9.84 s user, 18.07 s sys, 323076096 bytes). The file
and `src/process/` are untouched by this increment and the case mocks
`Date.now` around a real process capture with a 1.5 s fallback abort; it is
recorded as a host-dependent failure of that lane, not classified further
here.
## Built-CLI exchange on the prototype capture
`node scripts/rea.mjs inspect-web-network-capture grafana-like.har har
--format json` wrote capture Evidence `ev_4ee4759b…` with 28 records;
`inspect-analysis-view` with the inline source and all three template rules
wrote manifest Evidence `ev_6553a8e5…` naming that parent, `grafana-example`,
19 tools. `environment-serve manifest.json --evidence capture.json --port 0
--json < /dev/null` announced one stderr line
`{"transport":"streamable-http","url":"http://127.0.0.1:62305/mcp","msg":"MCP transport listening"}`
and nothing on stdout until shutdown.
`GET /.well-known/agent-env.json` returned a card whose top-level keys,
`capabilities` keys and tool keys equal the echo card's in order; its
`inputSchema` keys are `type`, `properties`, `required` and
`additionalProperties`, the echo card's three plus the closing key. Fixed
fields: `protocolVersion` `1.0`, `url` `/agentenv`, `preferredTransport`
`JSONRPC`, `additionalInterfaces` `[{url:/mcp,transport:mcp}]`, `extensions`
null, `operations` `[]`, `children_environments` null, 19 tools, with
`get_users_by_id` described as `GET /api/users/{numeric}; replays retained
records [5, 6]; evidence ev_4ee4759b…`.
The Python `mcp` 1.30.0 client (httpx 0.28.1) initialised against
`grafana-example 6.6.0` (protocol 2025-11-25), listed 19 tools, called
`get_users_by_id {"id":"2"}` and read `body.login == "probe"`,
`replay.exact_match == True`, `_meta.provenance.untrusted_content == True`
with `source == "analysis_target"`; `{"id":"999"}` gave `exact_match ==
False`; `get_folders_by_uid {"uid":"general"}` gave `recorded_path ==
"/api/folders/general"`; `get_search {"query":"probe","type":"dash-db"}`
returned a list body whose first title is `probe dashboard` with
`recorded_query == "?query=probe&type=dash-db"`; `get_users_by_id
{"id":"2","unknown":"x"}` returned `isError == True` with no structured
content.
`POST /agentenv {"jsonrpc":"2.0","id":1,"method":"data/reset"}` returned
`{"jsonrpc":"2.0","id":1,"error":{"code":-32601,"message":"method not found: data/reset"}}`.
A 60 MB non-JSON POST with a `Content-Length` header was answered `413`
`{"jsonrpc":"2.0","error":{"code":-32000,"message":"Request body must not exceed 4194304 bytes"},"id":null}`
after curl had sent 768332 bytes, in 1.4 ms, with the server's resident set
269024 KiB before and 269040 KiB after; the same file sent chunked without a
length was answered `413` after 5237311 bytes in 9.9 ms, resident set 267952
KiB before and 274208 KiB after, so the read stops at the bound on both
paths. A malformed body within the bound (`{`) was answered `400`
`{"jsonrpc":"2.0","error":{"code":-32700,"message":"parse error"},"id":null}`.
SIGTERM ended the process with status 143 after one stdout document
`{"status":"stopped","url":"http://127.0.0.1:62305/mcp","environment":"grafana-example","tools":19,"evidence_id":"ev_4ee4759b…","manifest_evidence_id":"ev_6553a8e5…"}`.
A restart with `ENVIRONMENT_NAME=renamed` served a card named `renamed`,
reported `"environment":"renamed"` in its stopped document and also exited 143. `ENVIRONMENT_NAME=` (set, blank) exited 1 before binding with
`{"code":"configuration_invalid","details":{"settings":[{"setting":"ENVIRONMENT_NAME",…}]}}`.
The manifest served against the capture of one selected record (`--record
0`, `ev_3249d233…`) was refused with exit 1 and
`{"code":"invalid_request","details":{"operation":"environment-serve","issues":[{"path":["evidence","evidence_id"],"reason":"invalid_value","expected":"ev_4ee4759b…",…}]}}`
whose message names both identifiers; omitting `--evidence` exited 1 with
Incur's `VALIDATION_ERROR` naming `evidence`. No `rea.mjs` process or
listener remained after these runs.
## Independent review
The adversarial review of the first pass is the independent review of this
increment; its findings and their repairs are listed above. One further
observation surfaced while repairing them: the byte-identical card assertion
in `serveEnvironment.test.ts` compares the `inputSchema` object exactly, so
closing the schema required extending that expectation as well as the
services tests, which is the intended coupling between the card and the
advertised MCP schema.
## Scope and measurement limits
The echo-card comparison is exact on keys, nesting and tool entries; the
property names inside `inputSchema.properties` necessarily differ from the
echo tool's single `text` property, and `inputSchema` carries one key the echo
schema does not. `exact_match` is defined over supplied values only; omitted
parameters cannot mismatch, and a call without arguments is exact on the
tool's first record. Request bodies on write tools are accepted and ignored.
The post-bind listener `error` path is wired and type-checked but not
provoked by a test, since the shared listener does not expose its
`node:http` server. Non-loopback binds and the relaxed `Host` check were not
exercised; the Python exchange, curl checks and every test used `127.0.0.1`.
Replay selection and body parsing were measured on the 28-record fixture
only; no large-capture timing was taken. Resident-set figures are `ps` samples
of the serving process before and after one request each. Token usage and
full process-family peak are unmeasured; the `/usr/bin/time -l` figures
account for each command and the children it waited for. Windows was not
run.
@@ -0,0 +1,18 @@
# Plan
1. Add the `evidence-file` source to `analysisViewSourceSchema`
(`src/domain/analysisView/analysisView.ts`).
2. Add `inspectAnalysisViewWithFiles` / `inspectAnalysisViewValidatedWithFiles`
to `AnalysisViewService`: read with `readJsonFile`, authenticate with
`parseEvidence`, then project through the retained path with a lookup that
returns the file's Evidence. The synchronous path refuses an unread file
source.
3. Route the CLI command (with `source.path` resolved against the working
directory) and the MCP tool through the file-aware entry point.
4. Add `sibling-pair-variance` to `TEMPLATE_RULES`, with its merge pass before
`sibling-variance`, its parameter names and its segment-limit limitation.
5. Document both in the tool contract, `docs/cli.md` and
`docs/web-network-captures.md`.
6. Tests: service (file equals inline; a capture refused inline is accepted
from a file; refusals), CLI and MCP boundaries, and the pair rule's merges
and non-merges.
@@ -0,0 +1,56 @@
# Rich captures for the environment manifest
Issue: https://github.com/morluto/rea/issues/4933
## Outcome
A capture large enough to hold a rich application state can be projected into
an environment manifest whose tool list stays within what model providers
accept. Two changes:
- `inspect_analysis_view` accepts a third source,
`{"kind": "evidence-file", "path": "<absolute path>"}`. REA reads one
completed Evidence JSON file, authenticates it, and projects it like retained
Evidence, so its strings are bounded by the file reader instead of being
charged as inline input.
- The environment-manifest view gains an opt-in template rule,
`sibling-pair-variance`, that templates two adjacent literal segments after a
plural literal, such as `/repos/{owner}/{repo}/…`.
## Requirements
- An `evidence-file` path must be absolute and free of NUL bytes; the CLI
resolves a relative path against the working directory before validation,
and MCP clients pass an absolute path.
- The file is read through the shared JSON file reader (regular file, heap and
string-length guards) and parsed as complete Evidence. A missing or unreadable
file is an `EvidenceFileError`; JSON that is not complete Evidence is invalid
input reported under `source.path`.
- Over MCP the read follows the request's cancellation and the server's
resource scope, so a failed descriptor close stays owned for retry; a request
cancelled before authentication, before projection or during projection
returns typed cancellation and records nothing. Before authentication, which
copies and hashes the parsed Evidence, REA checks that live heap headroom holds
those copies and otherwise returns `resource_constraint`.
- A file source projects exactly what the same Evidence projects inline or
retained, with the same parent Evidence ID, view parameters and result.
- The synchronous projection API refuses an unread `evidence-file` source with
a typed capability error; the CLI and MCP adapters read files first.
- `sibling-pair-variance` applies only when listed, before `sibling-variance`, so
a single-position merge cannot template one half of a pair first. It
compares groups equal in method, origin and segment count except at two
adjacent literal positions at index 2 or later that follow a plural literal
and precede another literal (a trailing pair, such as
`/users/alice/followers`, names a sub-resource rather than a namespace and
name), and merges a bucket only when it holds at least three distinct pairs and both
positions vary. Stop words and `v1`-style versions never qualify, and routes
of more than 32 segments are not compared, with a limitation saying so.
- Its parameters are named from the plural literal, singular plus `_namespace`
and then `_name`, and labelled `sibling-pair-variance`.
## Non-goals
- No change to the 96 MiB projection budget or to inline admission.
- No change to `sibling-variance`; pairs are a separate rule so every inferred
parameter keeps naming the rule that produced it.
- No inference of semantic names (`owner`, `repo`) beyond the plural literal.
@@ -0,0 +1,10 @@
# Tasks
- [x] Record the outcome, requirements and non-goals.
- [x] Add the `evidence-file` source and the file-aware service entry point.
- [x] Route the CLI command and the MCP tool through it.
- [x] Add the `sibling-pair-variance` rule, its names and its limitation.
- [x] Document both; extend the tool contract text.
- [x] Add service, CLI, MCP and rule tests.
- [x] Run static, formatting, duplication, documentation and test gates.
- [x] Rebuild a rich capture with both changes and record the results.
@@ -0,0 +1,104 @@
# Verification
Verified commit: a64367a9 on main 2dd5effe.
## Gates
Run on macOS 26.5.1 with Node 22.23.1 on that tree: `npm run typecheck`, `lint`
(oxlint plus `verify:module-boundaries`, 2172 files), `format:check`, `knip`,
`metadata:check`, `docs:check`, `jscpd` (3.43% duplicated lines), `scan:todos`
and `mcp-catalog:check` all exit 0. oxlint on the 12 changed TypeScript files
reports no finding that main does not already report for the same files.
`npm run test:prepare`, then `npm run test:changed` (the tests related to the
changed files): 84 files, 1531 passed, 3 skipped, 0 failed. They include:
- the service: an Evidence file projects exactly what the same Evidence projects
inline; a capture whose response text exceeds the inline budget is refused
inline with `resource_constraint` and projected from its file; a relative
path, a missing file and JSON that is not Evidence are refused; the
synchronous API refuses an unread file source;
- the compiled CLI: a request naming an Evidence file projects the same
manifest as the same Evidence inline;
- MCP: inline, retained and file sources give identical manifests, outputs
validate against the advertised schema, and a relative path is refused;
- the file source module: the size estimate, the authentication headroom
refusal, a cancelled request refused before reading, and a read within the
caller's resource scope; the service returns typed cancellation for a
cancelled file request; a request aborted while it runs, even after its read, returns typed
cancellation because the service yields before each check;
- the pair rule: three owner/repo pairs merge for collection and numeric detail
routes, while two pairs, or three pairs sharing one namespace, stay literal;
with `sibling-variance` also selected the pair still merges, because pairs
are merged first. Each pair parameter keeps its role when
`sibling-variance` later templates the segment before the pair.
## A rich capture
A Gitea 28.1.0 instance seeded through its API with an invented world (12
people, 4 organisations, 16 public repositories, 320 issues with about 600
comments, labels, milestones, commits, pull requests and releases) was read by
one `capture-browser-scenario` run of 1,217 API reads: 1,218 transactions in
24 s, 10.7 MB of Evidence, nothing dropped. Scenario parents are not on main,
so this run used this commit merged onto the scenario-capture change
(morluto/rea#5182) and packed for the host.
| | Inline source, previous rules | Evidence-file source with `sibling-pair-variance` |
| --------------------- | ------------------------------------- | ------------------------------------------------- |
| Manifest | `resource_constraint` (96 MiB budget) | built in 4.1 s, 459 MB maximum RSS |
| Tools | 446 (with the budget raised by hand) | 63 |
| Recorded exchanges | 1,218 | 1,218 |
| Tools with one record | 77% | 49% |
The pair rule templated 25 route families as `{repo_namespace}/{repo_name}`.
A model provider that accepts at most 128 tools refused every request for the
446-tool manifest with HTTP 400.
The 63-tool environment was then exported, and in the AgentEnv runner its
smoke task passed and twelve generated retrieval tasks scored 12/12 with
`openai/gpt-oss-120b` and 12/12 with `zai-org/GLM-5.3-Flash`, with no provider
errors. The 446-tool manifest had scored 0/12 and 8/12 on its own generated
tasks, the 0 being the provider's tool limit rather than the model.
Review then found that the rule as run here also merged one id's
sub-resources (`/users/alice/followers`, `/users/bob/following` and
`/users/carol/starred` became one tool), and a pair now qualifies only when a
literal follows it. The Gitea capture above predates that guard and has not
been projected with it: whether any of the 63 tools merged sub-resources this
way, and the tool count with bare `/repos/{owner}/{repo}` routes kept one per
pair, are not established here.
## Linux follow-up (2026-10-20)
Based on `dd2bf3565`, including main `5fa4defcb`, with Node 24.18.0 and npm
11.16.0. The file reader now owns authentication; invalid Evidence returns the
selected file path and file-relative `content_issues`. Service and advertised
MCP error-envelope regressions cover this boundary.
- Domain analysis views, application analysis views and error projection:
16 files, 298 tests passed.
- Compiled analysis-view CLI/MCP and environment serve/export boundaries:
5 files, 48 tests passed.
- Serial Turbo run: typecheck, lint, format, knip, package metadata and required
runtime/contract artifacts: 11 tasks passed. Documentation/catalog validation:
8 tasks passed. Architecture guards passed across 1,595 source files.
- Real Gitea 28.2.0 official Linux binary (published compressed SHA-256 checked),
isolated SQLite database, two users and three public repositories with large
issue bodies. Actual Chromium navigation captured nine API transactions,
45 events, no drops, 12,584,312 bytes of Evidence. Inline manifest projection
was refused with `resource_constraint`; file CLI and default stdio MCP
projections agreed on five tools with all template rules selected. The
three trailing user sub-resources stayed separate. Malformed file diagnostics
named the file's JSON root. HTTP SDK replay verified six complete small
responses and twelve exact 256 KiB prefixes of large responses, each marked
truncated. Owned Gitea, browser and replay-server processes were stopped.
One CPU and one test worker were used. Sampled sum of descendant RSS every
50 ms (shared pages can count twice): focused tests 15.834 s / 15.327 CPU s /
764.69 MiB peak; boundaries 194.916 s / 190.121 CPU s / 1,795.15 MiB;
static/build 266.311 s / 259.658 CPU s / 4,677.44 MiB; real Gitea workflow
31.631 s / 24.999 CPU s / 2,146.29 MiB. These are individual runs, not a
cold/warm comparison; model token usage was not measured. The first external
probe stopped at the expected CLI refusal because its driver rejected exit 1;
the driver was corrected and the complete workflow passed. No new macOS,
Windows, model-task scoring or AgentEnv runner verification is claimed here.
@@ -0,0 +1,20 @@
# Implementation plan
1. Add `src/domain/analysisView/scenarioCaptureRecords.ts`: index scenario
events by transaction, project each request event as a HAR-shaped
`WebNetworkCaptureRecord`, and admit a scenario parent for the manifest
view (clone budget, schema, network-content selection).
2. Route `projectEnvironmentManifestView` through one capture-parent gate that
selects the HAR or scenario admission by parent operation, and widen the
environment-manifest result's `parent_operation`.
3. Branch `parseCaptureEvidence` in `environmentSource.ts` on the Evidence
operation, carry the capture kind and digest on the source, and word the
bundle README and CLI help for both kinds.
4. Add a schema-valid scenario capture fixture and domain and services tests:
the record projection, the manifest from a scenario parent, the refusal,
replay of UTF-8 and binary bodies, and the bundle README.
5. Document scenario parents in `docs/agent-environments.md` and
`docs/web-network-captures.md`, extend the tool contract text, and record
the spec.
No new dependency is introduced and no command is added.
@@ -0,0 +1,65 @@
# Build environments from browser scenario captures
Issue: https://github.com/morluto/rea/issues/4933
## Outcome
The `environment-manifest` view, `environment-serve` and `environment-export`
accept `capture_browser_scenario` Evidence as the manifest's parent, in
addition to `inspect_web_network_capture` HAR Evidence. A session REA records
itself, in a browser it launches, with credential headers and declared secrets
redacted, becomes an agent environment without an external capture script or
HAR scrubbing step. The replay, the tool surface and the bundle layout do not
change.
## Requirements
- A scenario parent is admitted only when its scenario selected
`capture.network.response_body` or `header_values`, because tools are chosen
by response media type; otherwise the view refuses with
`unsupported_target`.
- Each network transaction becomes one record in request order; its ordinal
is the zero-based position of its `request` event, and its location is the
JSON pointer of that event in the capture. The record is shaped like a HAR
entry: request method and URL, the request body as `postData` when it was
captured and decodes as UTF-8, the response status, and the response media
type with its retained bytes as base64 content and a retained binary field.
- A transaction whose URL the scenario redacted keeps a null URL, so no path
template is formed from a redaction marker. A transaction that does not
resolve to exactly one request event, at most one response event and at most
one content event per phase keeps no request line. Both are counted as
unrepresented records, as HAR records without a usable request line are.
- The response media type is the captured body's `media_type`, or the
`content-type` header value when only headers were captured.
- The existing projection representation budget reserves, before schema body
validation or request-body decoding and for retained and file parents alike,
the scratch of validating the largest body (two bytes per base64 character)
and the decoded text of every request body; response bodies stay borrowed,
as HAR response text does, so a large capture read from its file is not
charged per character for them. Over-budget captures return
`resource_constraint` before those allocations. Replay projection omits the
request text used only for manifest body-shape inference; retained response
bytes and their integrity checks are unchanged.
- The manifest result names `parent_operation: "capture_browser_scenario"`,
carries an empty `artifact` (`path: ""`, `sha256: null`) and states, as
limitations, the ordinal rule, any dropped capture events, how many
transactions with a usable request line retained no response body (tools
citing them replay only the recorded status and content type, either of
which may be absent) and how many retained response bodies carry redaction
markers. A body that redaction emptied, because a declared secret could not
be cut out, is treated as not retained rather than replayed as an empty
reply.
- `environment-serve` and `environment-export` authenticate either parent
kind through the same loader, project scenario transactions through the same
adapter, and keep the cross-check that the manifest's parent is the supplied
Evidence. The bundle README names the capture kind and, for a scenario, the
SHA-256 of the scenario definition in place of a capture artifact digest.
## Non-goals
- No new browser action: scenarios still cover what the UI requests plus GET
reads through `goto`. A fetch or script action would be a new effect and
needs its own scope decision.
- No change to what the scenario redacts. Values the application returns in
response bodies are retained, as they are in HAR captures.
- The api-surface view keeps HAR parents only.
@@ -0,0 +1,10 @@
# Tasks
- [x] Record the scenario-parent contract, requirements and non-goals.
- [x] Project scenario transactions as HAR-shaped records and admit scenario parents.
- [x] Route the manifest view through one capture-parent gate and widen its result schema.
- [x] Load scenario Evidence in serve and export; name the capture kind in the README and help.
- [x] Add the scenario capture fixture and domain and services tests.
- [x] Document scenario parents and extend the tool contract text.
- [x] Run static, formatting, duplication, documentation and test gates.
- [x] Build environments from real browser scenario captures and record the results.
@@ -0,0 +1,144 @@
# Verification
Verified commit: 3c2a8db2, this increment on top of the environment-export increment (481c9883).
## Gates
Run on macOS 26.5.1 with Node 22.23.1 on that tree:
- `npx tsc --noEmit`: no errors.
- `oxfmt --check`: all files formatted. `oxlint` on the changed files: no new findings.
`npm run verify:module-boundaries`: 2133 files checked.
- `npm run jscpd`: 3.35% duplicated lines, unchanged. `npm run scan:todos`: none.
`npm run mcp-catalog:check`: passed. `npx knip`: one unresolved import that predates
this change (`#javascript-analysis-worker`).
- `npm run test:prepare`, then vitest over `src/domain/analysisView`, `src/application`,
`src/contracts`, `src/server/environment`, `tests/conformance` and the analysis-view,
environment-serve, environment-export and browser-scenario boundary tests: 1946 tests in
157 files, 1941 passed, 5 skipped, 0 failed.
## Real browser captures
`npm pack` of this commit (`rea-agents-6.7.0.tgz`) was installed on Ubuntu 24.04 amd64 hosts
(8 vCPU, 32 GB) with Chromium 155.0.8059.79 at `/snap/bin/chromium`, Node 24, Docker and
`agentenv-framework` 0.9.1334. Every capture below is `rea capture-browser-scenario` output;
no HAR was recorded, scoped or edited.
### Fixture
A loopback fixture served a page that lists photos from `/api/photos`, three PNG thumbnails, and
a form that POSTs JSON to `/api/albums`. The scenario waited for the list, opened
`/api/photos/1..3` with `goto`, filled and submitted the form.
- Capture: 14 transactions, 70 events, 0 dropped, authority `controlled-replay`.
- `environment-manifest`: `parent_operation` `capture_browser_scenario`, origin
`http://127.0.0.1:3199`, confidence `inferred`. Tools `get_photos` (records 1, 9),
`get_photos_by_id` (`{numeric}` id, records 5, 6, 7) and `post_albums` (record 13, body shape
`title: string`). The page and the three PNGs were excluded as `ui-page-or-asset`.
- `environment-serve`: `get_photos_by_id {id: "3"}` returned the recorded JSON with
`record_ordinal` 7 and `exact_match` true.
- The POST's response body was missing: the scenario ended at the action that sent it, the
transaction was still unfinished, and the observer does not read bodies of unfinished
responses. The manifest stated "1 of 14 scenario transactions retained no response body" and
`post_albums` replayed status 201 with no body. Ending the scenario with a 1.5 s
`wait_for_timeout` finished all 14 transactions and retained the body.
- `environment-export` of that capture wrote a README naming the browser scenario capture and the
scenario definition's SHA-256; `agent-env run <bundle> --task smoke` passed in 30.4 s.
### Five applications
Each environment ran manifest, export, the bundle's smoke task and 6 to 12 generated retrieval
tasks, with one run per task for two models through the Hugging Face router.
| Application | Capture | Actions | Transactions | Tools (rules / none) | Smoke | Retrieval tasks | gpt-oss-120b | GLM-5.3-Flash |
| ---------------------------- | ------------------------------------------------------------------ | ------- | ------------ | -------------------- | ------ | --------------- | ------------ | ------------- |
| PhotoPrism 261007 | self-hosted, no login (public mode) | 55 | 277 | 13 / 28 | passed | 10 | 10/10 | 10/10 |
| Lychee 6.10.4 | self-hosted, session cookie seeded from a declared secret | 152 | 134 | 15 / 27 | passed | 12 | 11/12 | 12/12 |
| Pinry 2.1.13 | self-hosted, session and CSRF cookies seeded from declared secrets | 148 | 568 | 12 / 12 | passed | 6 | 6/6 | 6/6 |
| Art Institute of Chicago API | public, `goto` per URL | 52 | 26 | 11 / 12 | passed | 12 | 11/12 | 12/12 |
| Library of Congress JSON API | public, `goto` per URL | 55 | 29 | 11 / 11 | passed | 12 | 11/12 | 12/12 |
Every scenario step completed and no capture dropped events. Each self-hosted capture includes
one create, one edit and one delete made through the application's own forms; all three became
tools with their recorded statuses, including a 204 DELETE without a content type. Declared
secrets did not appear in any capture; where the application echoed a declared value in a
response body (PhotoPrism's session reply, Pinry's owner token) the capture held the redaction
marker instead.
Two other targets were tried and replaced. The Met Collection API projected 3 tools: its data
paths are `/departments`, `/objects/{id}` and a search, and numeric object ids merge into one
tool. The NASA Image and Video Library projected 16 tools, but its Collection+JSON bodies nest
record fields deeper than the task generator reads, so no tasks could be derived.
## Observed limits
These were observed during the runs and are outside this increment:
- A scenario's last action can lose its response body unless the scenario ends with a wait
(above).
- Large asset bodies count against the analysis-view budget. One Pinry capture at
`max_network_body_bytes` 262144 held 12.5 MB of Evidence, mostly CSS and JavaScript reloaded
on 33 page loads, and the manifest view returned `resource_constraint`. A 20,000-byte body
limit kept it within budget. Scenarios have no per-origin or per-media-type body selection.
- Image responses outside an API path are excluded as UI assets, so their bytes are replayable
only when an API path serves them (PhotoPrism's `/api/v1/t/...` tiles became tools).
- With the default `max_total_event_allocation_bytes`, one PhotoPrism capture dropped its last
68 transactions, including all three writes, while the command exited 0; 64 MiB dropped none.
- Actions have no default deadline: two runs waited on a locator for 277 s and 7.5 min until
cancelled. Every scenario above sets `timeout_ms` on its actions.
- A redirect is its own transaction; Django's trailing-slash 301 produced a second tool
(`get_pins_by_id` and `get_pins_by_id_2`) for one resource.
## Linux followup verification (2026-10-19)
The original PR was merged with current main `7a0c47bfa`, after #4955, #4975
and #4999 merged. The export filesystem ownership, mode, tarball, cleanup and
caller-path fixes from main are retained. Default MCP remains stdio.
The retained-parent projection previously decoded every request body before
per-record budget checks. It now reserves copied/transformed text through the
shared admission owner before schema validation or decoding, including retained
parents. Replay projection omits request text used only for body-shape inference;
response bytes still undergo the producer schema's integrity validation. The
intermediate projected-array copy and unused capture wrapper were removed.
Windows test inventories normalize filesystem separators to the portable bundle
path representation. CI selects the agentenv lane for the new projection and its
shared admission dependencies.
Executed on Linux x64, Node 24.18.0 / npm 11.16.0, Chrome for Testing
156.0.8078.4:
- `turbo run typecheck lint:built format:check docs:check:built knip artifacts:skills artifacts:mcp-catalog --concurrency=1 --summarize`: eleven tasks passed, one cached, 210.023 s elapsed / 209.860 s CPU / 4562.07 MiB peak process-family RSS. This first complete gate preceded the final lint cleanup and CI-selection additions; later checks are reported on the PR.
- Initial source verification passed 111 tests in 13 files, including HAR/manifest regressions, scenario loading/replay/export and new capacity/replay-mode tests. CI-selection verification passed 235 cases.
- Real public CLI capture of the source-owned interactive browser network site: ten transactions, fifty events, two tools, no dropped events. Its POST response replayed twice through the official HTTP SDK with exact body/status/Evidence ordinal and untrusted-content provenance. Declared secrets and transport credentials were excluded; the ordinary selected `password` field value remained in retained body bytes.
- Real public CLI capture of three live GitHub API responses in Chromium, without a HAR: three transactions, fifteen events, three tools, no dropped events. Every response replayed twice through the HTTP SDK with exact body/status/Evidence/provenance. Explicit navigation waits let response-body capture settle. Complete two-scenario capture/projection/serve task: **22.527 s / 16.678 s CPU / 1397.93 MiB** peak process-family RSS, including owned browser processes. Both listeners exited 143 and newly owned browser profiles were gone.
- The same two actual captures produced identical manifest results through CLI and official SDK **stdio** MCP, with HTTP environment variables present: **2.795 s / 2.778 s CPU / 476.67 MiB**. This verifies adapter parity and default transport independently of explicit environment HTTP.
The first local probe mistakenly searched base64 body content for plaintext; its
assertion was corrected to inspect decoded retained bytes. A later SDK probe
initially imported stdio transport from the SDK root instead of its documented
subpath; the corrected probe passed. An early live navigation also reported one
`body-read-failed` response, which the projection preserved as unavailable. No
browser-provider behavior was changed; the successful run used explicit waits.
These earlier attempts are not counted as passing runs.
A matched retained-scenario projection comparison bundles the original helper
from `3aae3579e` and the followup helper, supplies the same 72,771-byte capture
with three JSON writes, and completes one cold plus 100 warm full manifest
projections. Both outputs have the same SHA-256
`990ac431670374ff68c77a20d77985f626e4681bb0e2f491e5af18f45ce79991`.
Before/after process totals: **0.970/0.876 s elapsed, 0.934/0.865 s CPU,
184.89/184.39 MiB** RSS. First task: **17.378/13.073 ms**; 100 warm tasks:
**261.419/236.131 ms**. Single samples do not establish a speed or memory
improvement. Bundle preparation is excluded; process totals include fixture
startup. CLI, provider and transport costs are excluded from this comparison.
Heavy work is serialized on one CPU with one test worker. RSS sums sampled
process descendants every 50 ms and can double-count shared pages. Agent token
usage is unmeasured. These followups do not rerun the author's five application
reconstruction/model tasks, nor establish Windows or macOS behavior. Historical
response replay does not reconstruct application state.
A retained-parent counterexample used a 128 KiB projection budget and one 16 KiB JSON request: the original helper admitted it and decoded once; the repaired helper returned `AnalysisResourceConstraintError` with zero UTF-8 decodes. The test intentionally uses a small budget without inducing an OOM. Final targeted verification passed 242 tests (including 235 CI-selection cases): 41.042 s / 40.666 s CPU / 644.37 MiB peak process-family RSS.
The broader d2416ca54 regression run passed 657 tests in 47 files plus ten product-catalog cases (295.763 s / 293.370 s CPU / 1921.69 MiB family RSS; catalog checked separately). The author then pushed 655e62334 with redaction/body-budget documentation and withheld-empty-body behavior. That commit was retained; the followup counts bodiless/redacted observations against represented transactions, preserving the complete request ordinals. The related source run passed 145 tests in 14 files (9.793 s / 9.618 s CPU / 688.66 MiB). Docker execution was held at this author-update checkpoint, so no earlier bundle is attributed to the new source. Final committed checks and actual scenario-container/framework results are reported on the PR.
@@ -0,0 +1,28 @@
# Implementation plan
1. Move response-body decoding from the environment source into
`recordedResponseBody.ts` with the caller's byte limit, and exact JSON
parsing into `exactJsonNumber.ts`, so replay and state extraction share one
owner each.
2. Add `environmentStateRules.ts` as pure helpers: write classification, API
bases and roots, entity location, identity names, JSON pointers of depth one,
value bytes and the entity and list renderers.
3. Add `EnvironmentStateExtraction.ts` for planning item and list tools,
observing entities and assembling the result, `environmentStateMerge.ts` for
merging observations, and `environmentStateGate.ts` for reproducing each
plan's recordings; every body is parsed through a budget callback and
released before the next.
4. Add `EnvironmentStateAccumulator.ts`, extending the manifest accumulator so
grouping is shared, retaining record lines and references to the admitted
records, and charging bodies and kept values.
5. Add `environmentStateView.ts` with the request schema (sharing the
manifest's `template_rules` schema), the result fields and the projector;
share capture admission and record grouping with the manifest view; register
the kind and pass accumulators to `projectAnalysisView` as one object;
always seal the result inferred.
6. Cover domain, service, MCP, CLI, catalog and acceptance behavior; document
the view in the capture guide, the agent environments guide, the contracts
reference and the authored skill.
No new tool, provider, side effect or network activity is introduced. The state
is a projection of already retained Evidence; serving it is deferred.
@@ -0,0 +1,74 @@
# Environment state view from captures
Issue: https://github.com/morluto/rea/issues/4933
## Outcome
`inspect_analysis_view` accepts `view: {"kind": "environment-state"}` for the
parents the environment manifest accepts and extracts the initial state the
capture's reads observed: entity types with an identity field, entities with
their recorded values, documents for written paths whose reads are not
entities, and a render plan per read tool that reproduces the tool's latest
initial recordings from the state, or a recorded view with the reason it
cannot. This increment adds the view kind only; serving from the state, loading
another state through the AgentEnv data plane and modelling write effects are
later increments.
## Requirements
- Accept `inspect_web_network_capture` HAR parents and
`capture_browser_scenario` parents that selected response bodies, with the
manifest's admission: the same format, subject and sensitive-value refusals.
- Group records exactly as the manifest does for the same `template_rules`, so
tool names match the manifest the state accompanies.
- Order primary-origin records by recorded start time, or by record order when
any start time is missing, and say which. Bound each type's state by the first
write under its root (API base, version segments, one segment); a query
`POST` is not a write, a read overlapping the write is left out, and a write
whose URL was redacted bounds every type, with a limitation counting it.
- Prove an item type's identity field from the requested path value its
responses repeat; otherwise infer it from a fixed list of identity names that
every listed item carries distinctly, which needs at least one listed item.
Never treat an envelope that is itself an entity as a list.
- Merge observations into one entity per collection and identity: item views'
latest values win over list views', differing views keep their own values,
and a value that changed between repeats of one request line with no recorded
write is volatile and keeps the latest; a change across a write under another
root, including between two tools of the type, leaves every tool of the type
recorded. Compare list membership, including empty lists, and field presence before selecting each request line's latest recording; a change across a write also leaves the type recorded. Different query strings remain distinct; omitted fields do not erase their earlier observations on other request lines.
- A list has `all` membership only when no item-total envelope member (`total`,
`count` and their compounds, not page counts) differs from the number of
entities it lists and no `has_more`, `next` or next-page token is set.
- Keep an item or list plan only when it reproduces each request line's latest
initial recording from the state, comparing JSON values without regard to
member order; otherwise record the tool with a reason. Parse bodies only when
JSON-like, UTF-8, at most 256 KiB, exactly representable and free of
`__proto__` members.
- Mark the Evidence inferred; state unknowns for authorization, response
semantics and write effects.
- Charge the manifest's admission and grouping, every record line, every body
as temporary bytes before decoding and parsing, and every kept value, within
the existing 96 MiB budget.
- Read response bodies through one domain owner shared with replay, and parse
exact JSON through the owner of the exact-number policy.
## Acceptance and limits
The Grafana-shaped HAR fixture with distinct start times drives domain,
service, MCP, CLI and acceptance coverage: folders merge their detail and list
views under a proved `uid`, the dashboard entity is read from its `/dashboard`
wrapper, and the annotation list after the annotation write has no initial
recording. Synthetic captures cover write bounds, volatile fields, complete
lists with counters, each recorded reason and documents; the scenario fixture
covers record order and the response-body requirement. The view performs no
network activity and serves nothing. Values copied outside entity objects,
derived values and cross-type effects are not tied to the state.
## Deferred issue criteria
Serving tool calls from the state, `data/reset`, `data/add` and `data/get` on
the environment data plane, exporting the state with a bundle, and write
effects are later increments of #4933. So are documents for item-shaped
written paths (one per identity rather than per template) and for paths that
are only deleted; until then their reads stay recorded. This PR must reference rather than
close the issue.
@@ -0,0 +1,12 @@
# Tasks
- [x] Record the view contract, requirements and deferred increments.
- [x] Move body decoding and exact JSON parsing to their domain owners without
changing replay.
- [x] Implement the extraction rules, merge, gate and accumulator.
- [x] Register the `environment-state` kind, result schema, service wiring and
confidence rule.
- [x] Add the timed Grafana-shaped fixture and synthetic captures.
- [x] Add domain, service, MCP, CLI, catalog and acceptance coverage.
- [x] Document the view in the guides, contracts reference and skill.
- [x] Run static, formatting, duplication, documentation and test gates.
@@ -0,0 +1,156 @@
# Verification
Verified base: bf1eeee9 (fetched main).
Executed on the implementation worktree after `npm ci` and `npm run
build:cached`; every check below ran as written in this pass, after the last
source change.
- `npm run check:fast`: typecheck and lint passed.
- `npm run format:check`: passed.
- `npx knip`: passed (exit 0).
- `npm run jscpd`: 3.40% duplicated lines over 3331 files, under the 3.5%
gate; no clone involves a file this change adds.
- `npm run scan:todos`: passed.
- `npm run docs:check`: the built documentation checks and the README
consistency conformance test (5 tests) passed.
- `npx vitest run --project domain --project services`: 338 files, 5830 tests
passed, 5 pre-existing skips.
- `npm run test:focused --` the analysis-view MCP and CLI boundaries, the
environment serve and export CLI boundaries, the environment serve MCP
boundary, the compact input-schema MCP budget, the analysis-detail and
advertised-input-example contracts and the qlog acceptance test: 9 files, 68
tests passed, 1 pre-existing skip.
Real captures (outside the test suite): the built view ran through the
application service on 44 recorded captures (39 HAR, 5 browser scenario) with
all three template rules, in 7 to 46 ms each. 42 produced a state: 568 types,
2,213 entities, 2 documents, and 710 of 1,258 read tools state-backed (211
item, 497 list, 2 document views). The other read tools are recorded views:
306 not entities (singletons, configuration and computed views), 129 without
an identity field, 32 with unusable bodies (most are Nomad bodies with
integers beyond exact native conversion), 31 lists and 7 items that do not
reproduce, 26 without an initial recording, 12 query `POST`s and 5 documents
read under several queries. The two browser-scenario captures that did not
produce a state are refused inline with `resource_constraint`, as the
environment manifest view refuses them on unchanged main.
Not covered here: serving tool calls from the state, the AgentEnv data plane
and write effects, which are later increments.
## Linux follow-up (2026-10-20)
Node 24.18.0 / npm 11.16.0, with the author's `47f8a27a9` main integration
preserved and main `d72021b0d` integrated. Eight regression cases failed across
two pre-fix runs: membership additions/removals across a write, field presence,
sparse field observations, and compact compound totals. The fixes compare
membership before selecting latest recordings, retain each field's observation
across sparse reads, and recognize `totalcount`/`itemcount`. API-base grouping
appends to its owned arrays; identity intersection uses a set and skips the
first response's self-intersection.
Executed checks:
- Relevant domain, application and contract suites: 39 files, 493 passed,
3 existing skips. Includes empty/stable lists, query variants, field additions
and removals, sparse reads, identity proof and deferred document paths.
- Broader compiled CLI/MCP/environment, compact schema and qlog acceptance:
7 files, 65 passed, 1 existing skip. After the final state fixes, both selected
compiled state CLI/MCP cases passed again (36 other cases deselected).
- Final serial static/build/artifact gate: 11 tasks passed. Typecheck, lint,
format, knip, package metadata and runtime/catalog generation all ran.
- Final documentation/catalog/format validation: 9 tasks passed; architecture
guards passed across 1,602 source files; README consistency: 5 tests passed.
Real Gitea 28.2.0 used an isolated SQLite database. An owned Node fetch HAR
recorder captured actual API exchanges, omitting transport credentials:
- Three exchanges: empty repository search, creation through `/user/repos`,
then the same search. On exactly the same authenticated Evidence, pre-fix
`29e745923` published one created repository as initial state; the final
source publishes none and keeps the search recorded with `fields-differ`.
- Eleven exchanges: initial issue list/details and topics, PATCH, PUT and
DELETE, then subsequent reads. The state keeps the two original issues
before ordinal 4 and the original topics document at ordinal 3. File CLI and
default stdio MCP agree; six HTTP SDK replays reproduce original responses.
- Actual Chromium `capture_browser_scenario`: two transactions, eight events,
zero dropped. The state uses record order, extracts one issue, and keeps list
and item plans; file CLI and default stdio MCP agree. The earlier 12.6 MB
real browser capture also projects, keeping oversized bodies recorded with
`body-unusable` rather than parsing them into state. Owned servers and browser
processes were stopped.
### Resource and performance measurements
One CPU and one worker. Process-family RSS sums were sampled every 50 ms and
may count shared pages twice. Final source suites: 39.669 s wall / 39.486 CPU s /
898.42 MiB peak; broader boundaries: 270.171 s / 267.136 CPU s / 2,130.78 MiB;
final static/build: 199.683 s / 199.523 CPU s / 4,689.07 MiB; final live HAR
workflow: 22.836 s / 19.880 CPU s / 1,072.43 MiB; actual browser-state workflow:
12.734 s / 10.941 CPU s / 1,549.80 MiB. The qlog acceptance lane intentionally
exhausts an isolated decoder heap and verifies that MCP remains usable; no
workspace OOM occurred.
The first follow-up benchmark used pre-fix `29e745923` and `6ad63bcc2`, the same
completed Evidence files, Node and CPU affinity. One fresh process per revision,
with a first call and two warm repeats; filesystem caches were not cleared.
Complete normalized output digests matched for both synthetic projection tasks.
| Work | Before: first / warm (ms) | After: first / warm (ms) |
| ----------------------------------------------- | ------------------------- | ------------------------ |
| Group 8,000 templates (helper only) | 320.08 / 81.01–81.46 | 11.89 / 3.88–4.33 |
| File-to-state projection, 2,000 collections | 1,321.57 / 732.00–939.57 | 1,268.76 / 781.34–811.05 |
| File-to-state projection, one 15,001-field item | 657.05 / 494.82–501.19 | 377.78 / 347.62–380.87 |
Combined benchmark processes, including imports, three helper calls, six
projections and the live-capture comparison: before 6.536 s wall / 6.496 CPU s /
370.82 MiB peak; after 5.077 s / 5.056 CPU s / 386.53 MiB. Grouping and wide
identity inference improved; the 2,000-collection projection has overlapping
warm timings, and peak memory did not decrease. These few runs do not establish
a general speedup. Model token usage was not measured; no model-task scoring
was run. Initial external probe attempts had incorrect CLI positional arguments
and assumed coverage counted records rather than grouped tools; those driver
errors were corrected before the successful complete runs.
No new macOS/Windows runtime, state serving, AgentEnv data-plane or write-effects
claim is made. A type first observed only after an unrelated-root write may
still lack the earlier observation needed to detect its effect. Item-shaped
and delete-only document paths remain recorded, as specified.
## Post-merge write-cutoff follow-up
Base `3fca2e0ca` includes #5319 and the validated immutable-capture reuse from
#5349. The remaining review finding was repeated write-root parsing for each
read type and again during output assembly. One admitted prefix/wildcard index
now owns parsed write roots, with per-projection positive/negative cutoff
caching. Backed type membership is collected once, replacing another plan scan.
The old linear matcher is removed. Prefix, parameter, redacted-root and timeline
semantics are preserved; no cross-request cache or new authority is introduced.
- Source checks: 41 files, 508 passed, 3 existing skips, including independent
matching-oracle and 12,000-segment iterative-lookup checks.
- Serial static/build/artifact gate: 11 tasks passed, 197.356 s wall /
197.195 CPU s / 4,744.92 MiB peak process-family RSS.
- Both selected compiled state CLI/MCP cases passed after rebuilding.
- Live Gitea HAR workflows and fresh actual Chromium capture passed again:
initial values, recorded fallbacks, CLI/default stdio parity and six exact
HTTP replays. HAR workflow: 22.834 s wall / 19.623 CPU s / 1,067.36 MiB;
browser workflow: 22.858 s / 20.912 CPU s / 1,546.59 MiB. Owned processes stopped.
The same completed Evidence with 1,000 collection reads and 1,000 unrelated
writes was projected before and after on one CPU. Two larger full-HAR inputs
(3,000/4,000 total records) were refused by the existing 96 MiB admission budget;
the limit was retained. One fresh process per revision, first call plus one
warm repeat, filesystem caches not cleared:
| Complete file-to-state projection | Main before | Follow-up |
| -------------------------------------------------------- | ------------------- | ------------------- |
| First call wall / CPU (ms) | 1,727.89 / 1,727.36 | 1,244.82 / 1,244.05 |
| Warm call wall / CPU (ms) | 1,300.84 / 1,300.42 | 624.01 / 623.89 |
| Process wall / CPU (s), including imports and both calls | 4.690 / 4.363 | 3.370 / 3.062 |
| Sampled process-family peak RSS (MiB) | 365.84 | 360.03 |
Parent Evidence IDs and complete normalized output digests were identical.
RSS sampling is every 50 ms, includes descendants and can double-count shared
pages; these few runs do not establish a general memory reduction. Model token
usage remains unmeasured. No workspace OOM occurred.
Loaded 100 of 1255 files, more files were not shown because too many files have changed in this diff. Show more