Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abd99a4ce7 | ||
|
|
4a4bbab3c3 | ||
|
|
e5d2805b42 | ||
|
|
6f28b3633b | ||
|
|
c0eb612780 | ||
|
|
27dc9735e4 | ||
|
|
51e0df97e9 | ||
|
|
292fd532c9 | ||
|
|
aa7d960ef5 | ||
|
|
0b7213c890 | ||
|
|
63fe0eb5db | ||
|
|
ddce4bb446 | ||
|
|
dd3497e133 | ||
|
|
4f54379831 | ||
|
|
d77bc0e8a0 | ||
|
|
527ade245a | ||
|
|
dbcec4cf56 | ||
|
|
34fd7bdf7d | ||
|
|
81ab0ddc95 | ||
|
|
306ca984bc | ||
|
|
dd46a13dec | ||
|
|
ce5bc8cb01 | ||
|
|
b88bdfccd2 | ||
|
|
34aa22d0aa | ||
|
|
719d56ebfe | ||
|
|
87c8086fc1 | ||
|
|
eab4e47916 | ||
|
|
db87917daa | ||
|
|
183b4d4e7e | ||
|
|
00819258a7 | ||
|
|
c465ff5a81 | ||
|
|
1ac7ce3f3b | ||
|
|
55f5c8db69 | ||
|
|
5b0373db11 | ||
|
|
73be86c39e | ||
|
|
8dbe92a4a3 | ||
|
|
5a28a147f1 | ||
|
|
13a8640204 | ||
|
|
09b29436f4 | ||
|
|
421d527bfe | ||
|
|
24bd2b989a | ||
|
|
b2fad362f2 | ||
|
|
247c8f4eab | ||
|
|
adfde012ec | ||
|
|
57fd3ea5d8 | ||
|
|
d8948efb81 | ||
|
|
3966c92c71 | ||
|
|
1fbfbf74ef | ||
|
|
2604059961 | ||
|
|
6b44e35bec | ||
|
|
20bf7d957f | ||
|
|
c9f95eaf90 | ||
|
|
a2805bc934 | ||
|
|
b7529304f0 | ||
|
|
22c4b528d2 | ||
|
|
1158dc2a94 | ||
|
|
2765fc12bb | ||
|
|
18669641e9 | ||
|
|
cdd718ffb0 | ||
|
|
c5c5ff45aa | ||
|
|
5da3b7c393 | ||
|
|
2451e187be | ||
|
|
5e6529521c | ||
|
|
7cec547ecc | ||
|
|
c1a0561bf3 | ||
|
|
fafc1881b5 | ||
|
|
a59abe932e | ||
|
|
452e3ccad1 | ||
|
|
8413ec08f7 | ||
|
|
603a7d022c | ||
|
|
b2dc45006d | ||
|
|
1828cf87a0 | ||
|
|
a73eac190b | ||
|
|
0e5c511c01 | ||
|
|
2e6b38cef0 | ||
|
|
d7ca93cc2c | ||
|
|
82e4e032df | ||
|
|
ca2ca16146 | ||
|
|
14c4c2a1d7 | ||
|
|
4842f23765 | ||
|
|
7721d59e1a | ||
|
|
76dbc32f39 | ||
|
|
f23066f0da | ||
|
|
cbbd317fb5 | ||
|
|
d54c4345d3 | ||
|
|
bdf0be87c6 | ||
|
|
0155b89953 | ||
|
|
166fb0820f | ||
|
|
3dbe314ada | ||
|
|
f5acf82a78 | ||
|
|
a721c42c07 | ||
|
|
087813fb88 | ||
|
|
4e28166626 | ||
|
|
7ffae5a791 | ||
|
|
2aadcf7d04 | ||
|
|
b0a554cc3a | ||
|
|
414ad52b20 | ||
|
|
3cfdc585b4 | ||
|
|
4fe88a7e3f | ||
|
|
f4cabe535f | ||
|
|
6bc4ec3a74 | ||
|
|
1dcaa77693 | ||
|
|
0da36910dc | ||
|
|
55c3129224 | ||
|
|
dbd556043c | ||
|
|
b28f6c0953 | ||
|
|
3220e17b8b | ||
|
|
cc4ed5b904 | ||
|
|
126b6e20d4 | ||
|
|
8fe8622e09 | ||
|
|
1a945ce9ff | ||
|
|
d8199ab6af | ||
|
|
f6e4e0296f | ||
|
|
4c20744f1c | ||
|
|
3dce8326c9 | ||
|
|
fd64b1c240 | ||
|
|
d2015e94f3 | ||
|
|
7fdf7a5b79 | ||
|
|
7cdf8bc5cf | ||
|
|
465e1a1f36 | ||
|
|
f3537db34f | ||
|
|
48e7470041 | ||
|
|
2947a77507 | ||
|
|
ae09e3fe70 | ||
|
|
67a6477f01 | ||
|
|
3dde9a5e1c | ||
|
|
07fd426e9a | ||
|
|
0583fc69be | ||
|
|
a0214e0e0e | ||
|
|
01788bac86 | ||
|
|
aa51e43439 | ||
|
|
01ee6551b4 | ||
|
|
d8a9673fc4 | ||
|
|
f86206535f | ||
|
|
8e3bf56e11 | ||
|
|
dc53c11f6d | ||
|
|
d4c637f4cf | ||
|
|
4dfa1c67dc | ||
|
|
1f92c77398 | ||
|
|
2319166c2e | ||
|
|
63b43b69bb | ||
|
|
c8d3f8f8ec | ||
|
|
4423b6fff2 | ||
|
|
5df59ee1fd | ||
|
|
6d356b8434 | ||
|
|
c538a843cb | ||
|
|
25e1a24a3e | ||
|
|
705058f3e2 | ||
|
|
35d6d5bb0a | ||
|
|
5b014a739e | ||
|
|
ce1f4b1bba | ||
|
|
d124809950 | ||
|
|
7f9a492a8d | ||
|
|
c2bee63e99 | ||
|
|
905cbaf239 | ||
|
|
33f912919d | ||
|
|
aa53c06538 | ||
|
|
bcfcd8b6e2 | ||
|
|
efab044f30 | ||
|
|
647717c050 | ||
|
|
c76edbebbe | ||
|
|
c324d31b45 | ||
|
|
5eebe2fdf8 | ||
|
|
ea3534759f | ||
|
|
19f2969c56 | ||
|
|
d9767eb48f | ||
|
|
f5410bdc4c | ||
|
|
f801b2fbfd | ||
|
|
5241597594 | ||
|
|
a5f982de8d | ||
|
|
ea24207b57 | ||
|
|
6b7d429491 | ||
|
|
5891bfb302 | ||
|
|
d672cc2399 | ||
|
|
25bea07b42 | ||
|
|
bd8d73ab1d | ||
|
|
0cfef92ae1 | ||
|
|
b81431d7ff | ||
|
|
4a7a4b5744 | ||
|
|
4dfe3464b2 | ||
|
|
c1e04bf8c0 | ||
|
|
a00e4ac363 | ||
|
|
d36cb61210 | ||
|
|
0ad42752d3 | ||
|
|
dcdab56acb | ||
|
|
5af8fe702b | ||
|
|
7d8e4e4338 | ||
|
|
7c6c25dda7 | ||
|
|
89b1941c8e | ||
|
|
71b696582b | ||
|
|
43ac3d1857 | ||
|
|
fa8b87c470 | ||
|
|
afa5da745e | ||
|
|
22d5a40a2e | ||
|
|
264862bf2e | ||
|
|
044f180222 | ||
|
|
3b67b362aa | ||
|
|
f1126ff7bf | ||
|
|
3a0e91dd91 | ||
|
|
90062c0922 | ||
|
|
70835d3d5f | ||
|
|
ccfaf520b7 | ||
|
|
bbbd208743 | ||
|
|
c19c2d6723 | ||
|
|
08f4ba99ce | ||
|
|
df8b4d8a5a | ||
|
|
00266efe13 | ||
|
|
335c042d16 |
No files matched your search
@@ -91,9 +91,15 @@ explicit path or endpoint and do not need it.
|
||||
|
||||
- ASAR or extracted JavaScript/Electron tree:
|
||||
`analyze_javascript_application`.
|
||||
- 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.
|
||||
- Archive/package member inventory (ZIP/APK/IPA/MSIX/AppX, DMG, or a PyInstaller
|
||||
executable): `open_binary` with the supplied local path; use `inspect_artifact`
|
||||
when its graph and findings help answer the question. A PyInstaller CArchive
|
||||
is the application layer; the bootloader is only the native prefix. Start with
|
||||
`detail: "summary"` for large inventories, then use retained inventory views
|
||||
for selected member fields/pages. A complete small inventory can cost less
|
||||
than extra calls and schemas. Runtime options are metadata, not files.
|
||||
Compact delivery still inventories and hashes members. See the
|
||||
[Python packaged applications guide](https://github.com/morluto/rea/blob/main/docs/python-packaged-applications.md).
|
||||
- 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
|
||||
@@ -161,7 +167,9 @@ explicit path or endpoint and do not need it.
|
||||
ambiguity. No implicit fetch or target execution; WAT is not original source.
|
||||
See the [WASM guide](https://github.com/morluto/rea/blob/main/docs/wasm-artifacts.md).
|
||||
- Explicit local EVM bytecode carrier: `inspect_evm_interface` with caller-selected
|
||||
`raw` or `hex` encoding. Preserve carrier/decoded digests and treat selectors,
|
||||
`raw` or `hex` encoding. The owned worker deadline is `timeout_ms` (default
|
||||
30000 ms, range 1..2147483647, next call). It does not raise the fixed byte,
|
||||
address-space, or CPU allowances. Preserve carrier/decoded digests and treat selectors,
|
||||
argument strings and mutability as inferred candidates; this performs no chain
|
||||
lookup or target execution. For the complete inferred interface without hex or
|
||||
duplicate stdout, discover support and select `detail: "summary"`; complete
|
||||
@@ -175,6 +183,8 @@ 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).
|
||||
- Embedded CUDA/HIP code objects: `inspect_gpu_code_objects`; inventory targets
|
||||
first, then decode selected payloads and query retained GPU Evidence.
|
||||
- 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
|
||||
@@ -201,6 +211,12 @@ explicit path or endpoint and do not need it.
|
||||
package order, dependency indices, and the section file range. A missing
|
||||
`.dep-v0` section is null metadata, not proof the binary has no dependencies.
|
||||
A rustc commit hash is an inference from a read-only `/rustc/<40-hex>/` path.
|
||||
For selected crates, use `view: {collection: "packages", names: [...],
|
||||
fields: ["name", "version", "source"]}` on the first call; explicitly include
|
||||
`dependencies` for direct index references. Use `detail: "summary"` for counts
|
||||
and ranges, or retained `inspect_analysis_view` Rust package/edge pages for
|
||||
subsequent filters. Keep the complete parent Evidence accessible; CLI compact
|
||||
delivery requires `--evidence_output`.
|
||||
See the
|
||||
[Rust binary guide](https://github.com/morluto/rea/blob/main/docs/rust-binaries.md).
|
||||
|
||||
|
||||
@@ -25,8 +25,9 @@ stdio. A full JDK, including `jdk.compiler`, is required on every host; Windows
|
||||
`JAVA_HOME` selects `bin\java.exe`. Consult the Android guide for actual host
|
||||
verification coverage. Calls use one worker and provider deadlines; optional
|
||||
`REA_JADX_HEAP_MIB` selects the JVM heap and `REA_JADX_OPERATION_TIMEOUT_MS`
|
||||
the per-operation deadline (default 120000 ms; the MCP client's tool timeout
|
||||
must also allow it). The APK is never launched,
|
||||
the per-operation deadline (integer milliseconds from 1 to 2147483647, default
|
||||
120000; a change applies on the next process start; the MCP client's tool
|
||||
timeout must also allow it). The APK is never launched,
|
||||
and no emulator is required.
|
||||
|
||||
Manifest entries and decompiled text are static observations, not execution or
|
||||
|
||||
@@ -94,3 +94,9 @@ 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.
|
||||
`rea environment-serve manifest.json --evidence capture.json` derives that
|
||||
state at startup, answers read tools from it and serves `data/reset`,
|
||||
`data/add` and `data/get` on `/agentenv`; write tools are not served. It
|
||||
replays the capture instead with `--replay-only` or when the state is
|
||||
unavailable (not derivable, or a catalog over the discovery budget), and its
|
||||
stopped document's `state` says which applied.
|
||||
@@ -22,6 +22,11 @@ requires complete application analysis; `source_paths: []` is invalid, not an
|
||||
unfiltered request. `detail: "summary"` reduces delivery
|
||||
and does not by itself reduce analysis work.
|
||||
|
||||
ASAR header/index admission is fixed at 16 MiB / 16777216 bytes for this
|
||||
release and has no runtime override. `source_paths`, `detail`, and
|
||||
`max_heap_mb` do not bypass or raise it. Analyze an extracted directory, or
|
||||
supply an archive whose header fits.
|
||||
|
||||
Exact `#alias` specifiers resolve through the importer's
|
||||
enclosing package `imports` map to package-local files; nested `node_modules`
|
||||
packages use their own map. Wildcard, recursive, and external-package import
|
||||
|
||||
@@ -345,8 +345,8 @@ every executable in the bundle. It also lists missing or weak loads and earlier
|
||||
`architecture`. System paths stay undetermined because the dyld shared cache
|
||||
provides them.
|
||||
|
||||
Use `extract_artifact` when materialized files are needed. It extracts the active
|
||||
target and accepts optional `integrity_policy`; see the [MCP contracts](https://github.com/morluto/rea/blob/main/docs/mcp-contracts.md).
|
||||
Use `extract_artifact` when materialized files from a supported format are needed.
|
||||
It extracts the active target and accepts optional `integrity_policy`; see the [MCP contracts](https://github.com/morluto/rea/blob/main/docs/mcp-contracts.md).
|
||||
It materializes all regular files into a fresh temporary directory chosen by
|
||||
REA. Symlinks and encrypted entries are inventory facts, not extractable files.
|
||||
The result reports the materialized directory; callers do not choose the
|
||||
@@ -355,8 +355,11 @@ destination. No separate permission grant is needed.
|
||||
Native DMG traversal automatically uses a read-only mount on supported macOS
|
||||
hosts, with an owned temporary mount directory and cleanup. It needs no approval
|
||||
flag. Unsupported hosts or mount failures remain explicit limitations; do not
|
||||
claim child inventory when only root identity is available. Extraction is a
|
||||
separate filesystem-writing operation.
|
||||
claim child inventory when only root identity is available. DMG extraction is
|
||||
unavailable through `extract_artifact`. To access DMG files on macOS, create a
|
||||
read-only mount with your own tools, select files from that mount for analysis,
|
||||
and detach the mount you created when finished. REA's inspection mount is
|
||||
temporary, not a retained export of the image's contents.
|
||||
|
||||
For headerless DOS COM, explicitly open with `format: "dos-com"` (CLI
|
||||
`--target-format dos-com`). Inspect the load image before trusting function
|
||||
|
||||
@@ -409,7 +409,9 @@ jobs:
|
||||
with:
|
||||
save: ${{ github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
|
||||
- run: npm run test:prepare
|
||||
- name: Find available trusted full-suite timing history
|
||||
# Fast and full shards measure different file costs. Download only the
|
||||
# matching history so one tier cannot pack the other with its weights.
|
||||
- name: Find available trusted timing history
|
||||
id: history
|
||||
continue-on-error: true
|
||||
env:
|
||||
@@ -417,13 +419,14 @@ jobs:
|
||||
CI_REPOSITORY: ${{ github.repository }}
|
||||
CI_REPOSITORY_ID: ${{ github.repository_id }}
|
||||
CI_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
|
||||
CI_TIMING_TIER: ${{ needs.changes.outputs.tier }}
|
||||
run: node scripts/ci/test-history.mjs
|
||||
- name: Download previous timing report
|
||||
if: steps.history.outputs.run-id != ''
|
||||
continue-on-error: true
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
with:
|
||||
name: test-timings
|
||||
name: ${{ steps.history.outputs.artifact-name }}
|
||||
run-id: ${{ steps.history.outputs.run-id }}
|
||||
github-token: ${{ github.token }}
|
||||
path: .cache/ci-test-history
|
||||
@@ -555,11 +558,22 @@ jobs:
|
||||
include-hidden-files: true
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
# Default-branch runs only. Pull-request artifacts share this name and
|
||||
# the lookup reads one page, so publishing them would hide main.
|
||||
- name: Publish successful timing history
|
||||
if: needs.changes.outputs.code == 'true' && needs.changes.outputs.tier == 'full' && success() && needs.test-shard.result == 'success'
|
||||
if: >-
|
||||
success() &&
|
||||
needs.changes.outputs.code == 'true' &&
|
||||
needs.test-shard.result == 'success' &&
|
||||
(
|
||||
needs.changes.outputs.tier == 'full' ||
|
||||
(needs.changes.outputs.tier == 'fast' && needs.test-source.result == 'success')
|
||||
) &&
|
||||
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
|
||||
(github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: test-timings
|
||||
name: test-timings-${{ needs.changes.outputs.tier }}
|
||||
path: .cache/ci-test-history/test-results.json
|
||||
include-hidden-files: true
|
||||
if-no-files-found: error
|
||||
@@ -805,6 +819,11 @@ jobs:
|
||||
with:
|
||||
save: "true"
|
||||
- run: npm ci
|
||||
- name: Typecheck with the official Windows compiler
|
||||
env:
|
||||
GOMAXPROCS: "2"
|
||||
GOMEMLIMIT: "3GiB"
|
||||
run: npm run typecheck -- --checkers 2
|
||||
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
with:
|
||||
name: rea-build-cache
|
||||
@@ -835,7 +854,11 @@ jobs:
|
||||
npx vitest run --coverage.enabled=false
|
||||
src/process/capture/FilesystemSnapshot.test.ts
|
||||
tests/process-global/filesystemSnapshotFallbackCancellation.test.ts
|
||||
tests/boundary/filesystem/typescriptCompiler.test.ts
|
||||
tests/boundary/filesystem/binaryTarget.test.ts
|
||||
src/contracts/sessionPathInputs.test.ts
|
||||
tests/boundary/filesystem/directAnalysisSnapshotReplay.test.ts
|
||||
tests/boundary/mcp/rawBinaryMcp.test.ts
|
||||
tests/boundary/filesystem/safeOutputTree.test.ts
|
||||
tests/boundary/providers/native/artifactProvider.archiveSafety.test.ts
|
||||
tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts
|
||||
|
||||
@@ -90,6 +90,12 @@ Setup supports Claude Code, Codex, Cursor, Gemini CLI, Grok Build and
|
||||
[installation and setup](docs/installation.md) for provider configuration and
|
||||
manual MCP registration.
|
||||
|
||||
MCP uses compact input schemas by default to reduce context overhead. Set
|
||||
`REA_MCP_INPUT_SCHEMA_PROFILE=full` in your MCP registration when you need the
|
||||
complete advertised field guidance and nested validation details. Both profiles
|
||||
keep the full tool set and canonical server validation. See
|
||||
"Compact input schema profile" in the MCP contracts guide.
|
||||
|
||||
### Ask your agent
|
||||
|
||||
```text
|
||||
@@ -174,35 +180,37 @@ 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 |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 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) |
|
||||
| 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 |
|
||||
| GPU code objects | CUDA/HIP targets, selected kernel parameters and resources, retained PTX text | Built-in static ELF/PE/fatbin/CUBIN/PTX inspection; [GPU code objects](docs/gpu-code-objects.md) |
|
||||
| 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) |
|
||||
| PyInstaller executables | CArchive members, Python version, entry scripts and extracted bytecode | None (static only); [Python packaged applications](docs/python-packaged-applications.md) |
|
||||
|
||||
Static JavaScript and .NET inspection read the supplied files without running
|
||||
the application. Runtime capture runs or interacts with the selected target
|
||||
|
||||
@@ -50,6 +50,10 @@ export default defineConfig({
|
||||
{ text: "Electron fuses", link: "/electron-fuses" },
|
||||
{ text: "Process capture", link: "/process-capture" },
|
||||
{ text: ".NET assemblies", link: "/managed-code-analysis" },
|
||||
{
|
||||
text: "Python packaged applications",
|
||||
link: "/python-packaged-applications",
|
||||
},
|
||||
{ text: "Android applications", link: "/android-analysis" },
|
||||
{ text: "Apple applications", link: "/apple-application-analysis" },
|
||||
{ text: "Desktop installations", link: "/desktop-applications" },
|
||||
|
||||
@@ -162,8 +162,9 @@ and during shutdown.
|
||||
APKs keep other names report the `unknown` role rather than guessing.
|
||||
- **Partial results keep facts.** Failed individual pulls return successful
|
||||
artifacts with `coverage: "partial"` and per-file `failures`. Listings
|
||||
that contain unrecognized lines report them as `unparsed_lines` and mark
|
||||
partial coverage instead of dropping rows.
|
||||
and package searches that contain unrecognized lines report the first ten
|
||||
as `unparsed_lines`, state the exact total in a limitation when more were
|
||||
seen, and mark partial coverage instead of dropping rows.
|
||||
- **Mutations are explicit.** `push_adb_file`, `install_adb_package`, and
|
||||
`uninstall_adb_package` declare `mutatesTarget` and never run implicitly:
|
||||
pushes check for existing device files before transfer and refuse them
|
||||
@@ -171,7 +172,9 @@ and during shutdown.
|
||||
transfer even with `overwrite`; only a clean `test -e` exit of 1 with no
|
||||
output is interpreted as absence. The check is not atomic, so a different
|
||||
process can create the path before `adb push` writes it. When available, the device's
|
||||
`sha256sum` verifies the transfer; installs preserve the
|
||||
`sha256sum` verifies the transfer. A missing command or output without a
|
||||
recognizable digest reports `device_digest_source: "unavailable"` with an
|
||||
unverified-transfer limitation; installs preserve the
|
||||
device's `Failure [...]` reason verbatim.
|
||||
- **Producer identity stays attached.** Every result embeds the producing
|
||||
adb client (`binary_path`, `path_source`, `version`, `installed_path`).
|
||||
@@ -183,9 +186,11 @@ and during shutdown.
|
||||
The app/activity lifecycle tools use `am start -W` and `am force-stop`.
|
||||
- Per-invocation budgets: client/devices 10-20 s, shell reads 20-60 s with
|
||||
64 KiB-8 MiB capture caps (logcat 4 MiB, screen 32 MiB), transfers and
|
||||
bugreports 600 s. Output capture overflow reports `resource_constraint`;
|
||||
deadline expiration, including the client-version probe, reports
|
||||
`provider_timeout`. Command cancellation preserves the caller's exact reason;
|
||||
bugreports 600 s. Output capture overflow reports `resource_constraint`
|
||||
and names the byte allowance. Deadline expiration, including the
|
||||
client-version probe, reports `provider_timeout` and names the effective
|
||||
milliseconds. This release has no runtime override for those deadlines or
|
||||
capture caps. Command cancellation preserves the caller's exact reason;
|
||||
a later abort does not replace an already completed command failure.
|
||||
- Pull and capture outputs are additive: the destination must not already
|
||||
exist. Re-running a completed pull refuses the existing directory instead
|
||||
|
||||
+325
-51
@@ -1,11 +1,15 @@
|
||||
# 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).
|
||||
environment: an MCP server whose tools answer from what one retained web
|
||||
network capture observed, plus the environment card the agentenv framework
|
||||
reads to discover it. By default the server derives the
|
||||
[state the capture observed](#the-state-a-capture-observed) at startup and
|
||||
answers read tools from it; `--replay-only` replays the capture's records
|
||||
instead. Nothing is fetched from the recorded application; every answer comes
|
||||
from 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
|
||||
@@ -27,9 +31,10 @@ it, where `view.json` wraps the capture Evidence as the inline source:
|
||||
}
|
||||
```
|
||||
|
||||
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`.
|
||||
The third command serves that manifest from the state it derives from the
|
||||
capture; see [Serve from the state](#serve-from-the-state). 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
|
||||
|
||||
@@ -110,7 +115,9 @@ 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
|
||||
selected neither response bodies nor header values is refused; one that
|
||||
selected header values but no response bodies yields a manifest but no state,
|
||||
so it is served by replay. 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
|
||||
@@ -144,10 +151,16 @@ 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.
|
||||
Served from the state, each description is longer and the card declares the
|
||||
data plane, so a catalog replay admits can exceed the reservation; the state
|
||||
is then unavailable and the server serves replay instead (see
|
||||
[Serve from the state](#serve-from-the-state)).
|
||||
|
||||
## What replay means and does not mean
|
||||
|
||||
Each MCP tool call selects one of the records its manifest tool cites and
|
||||
Replay answers every tool with `--replay-only` or when the state is unavailable,
|
||||
and, served from the state, each read tool whose view the state does not back.
|
||||
Each such 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
|
||||
@@ -202,7 +215,8 @@ 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
|
||||
it answers only from the capture's recordings and the state they observed or a
|
||||
caller loaded through `data/add`. 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
|
||||
@@ -220,17 +234,23 @@ 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.
|
||||
documents for reads that are not entities, 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 holds, loads and reports: `environment-serve`
|
||||
derives it from the capture at startup; see
|
||||
[Serve from the state](#serve-from-the-state). With `--replay-only`, replay is
|
||||
unchanged.
|
||||
|
||||
## Serve a manifest
|
||||
|
||||
```sh
|
||||
rea environment-serve manifest.json --evidence capture.json [--host 127.0.0.1] [--port 0]
|
||||
rea environment-serve manifest.json --evidence capture.json [--replay-only] [--host 127.0.0.1] [--port 0]
|
||||
```
|
||||
|
||||
The server derives the state from the capture before it binds and serves from
|
||||
it, or serves replay with `--replay-only` or when the state is unavailable;
|
||||
see [Serve from the state](#serve-from-the-state).
|
||||
|
||||
`--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
|
||||
@@ -242,7 +262,8 @@ manifest's `name` is used, and a set but blank value is refused as
|
||||
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`.
|
||||
`{"status":"stopped", …}` document whose `state` member says whether it served
|
||||
from the state, 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
|
||||
@@ -250,19 +271,19 @@ 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 |
|
||||
| Route | Answer |
|
||||
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `POST /mcp` | The MCP server: from the state, one tool per read tool, answering from the state where it backs them; in replay, one tool per manifest tool, replaying records |
|
||||
| `GET /.well-known/agent-env.json` | The environment card |
|
||||
| `POST /agentenv` | From the state, `data/reset`, `data/add` and `data/get`; in replay, 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
|
||||
In replay the data plane at `/agentenv` is advertised by the card but carries
|
||||
no operations; 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`)
|
||||
@@ -274,7 +295,7 @@ 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`:
|
||||
connecting to `/mcp`. A replay environment's card reads:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -288,7 +309,7 @@ connecting to `/mcp`:
|
||||
"tools": [
|
||||
{
|
||||
"name": "get_users_by_id",
|
||||
"description": "GET /api/users/{numeric}; replays retained records [5, 6]; evidence ev_…",
|
||||
"description": "Untrusted captured API catalog: … GET /api/users/{numeric}; returns a JSON object with fields \"id\", \"uid\", \"login\", \"email\"; recorded statuses 200; replays retained records [5, 6]; evidence ev_…",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -309,7 +330,38 @@ connecting to `/mcp`:
|
||||
```
|
||||
|
||||
`capabilities.tools` lists the same names, descriptions and input schemas that
|
||||
`tools/list` advertises over MCP. Path parameters are required strings whose
|
||||
`tools/list` advertises over MCP. After the catalog warning, each description
|
||||
names the method and path template, then what the tool returns, one level deep:
|
||||
`returns a JSON object with fields …`, `returns a JSON array of objects with
|
||||
fields …` or `returns a JSON object whose <member> lists objects with fields …`,
|
||||
where a list is an array of objects found by the
|
||||
[environment state](web-network-captures.md#environment-state)'s list rule (the
|
||||
root array, or the one array of objects an envelope carries). Field and member
|
||||
names are written as JSON strings, so a captured name cannot read as more of
|
||||
the description; a member name too long to show whole is a quoted prefix marked
|
||||
as truncated. The summary comes
|
||||
from the first cited `2xx` record that replay answers as JSON; only when none
|
||||
did, the first cited JSON record of another status gives it, labelled with that
|
||||
status (`status 401 returns …`). It describes one recorded response, not a
|
||||
contract. Field names are sampled within the same budget as other captured
|
||||
values, and the manifest's `statuses` for the tool follow; a tool with no JSON
|
||||
record states only its statuses. The description then lists the replayed
|
||||
records and the evidence ID, and the whole catalog stays within its
|
||||
serialization reservation, which the summaries and MCP annotations are charged
|
||||
to.
|
||||
|
||||
Over MCP, every tool also carries annotations: `readOnlyHint` is true for the
|
||||
safe methods (`GET`, `HEAD`, `OPTIONS` and `TRACE`) and for query `POST`s (a
|
||||
path segment such as `search` or `query`); `destructiveHint` is true for `DELETE` and left unset for other
|
||||
writes, so the MCP default (destructive) applies to them, and read-only tools
|
||||
omit it because clients ignore it there; `idempotentHint` is true for the safe
|
||||
methods, `PUT` and `DELETE`; and `openWorldHint` is false for every tool,
|
||||
because answers come from the capture rather than the captured application. The
|
||||
hints describe the captured method; replay itself changes nothing. The card
|
||||
keeps the `name`, `description` and `inputSchema` of the echo example's tool
|
||||
shape and carries no annotations.
|
||||
|
||||
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
|
||||
@@ -320,9 +372,207 @@ advertised as `query_<name>`, a query name longer than 64 characters as
|
||||
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.
|
||||
In replay, `extensions`, `operations` and `children_environments` are fixed to
|
||||
`null`, `[]` and `null`: a replay environment declares no extensions, no
|
||||
data-plane operations and no children. Served
|
||||
[from the state](#serve-from-the-state), the card declares the three data-plane
|
||||
operations and one intake extension instead, leaves write tools out and
|
||||
describes each tool as answering from the state where the state backs it.
|
||||
|
||||
## Serve from the state
|
||||
|
||||
```sh
|
||||
rea environment-serve manifest.json --evidence capture.json
|
||||
```
|
||||
|
||||
Before it binds, the server derives the
|
||||
[environment state](web-network-captures.md#environment-state) the capture
|
||||
observed: it runs the `environment-state` view on the capture in-process with
|
||||
the manifest's `template_rules` in the same order, exactly as
|
||||
`inspect-analysis-view` projects it from the same capture, so the state
|
||||
Evidence id it reports is the one that projection produces. The view's own
|
||||
budget and refusals apply, and the result is checked like the view's Evidence
|
||||
for this manifest: extracted from the served capture, with the manifest's
|
||||
rules, naming only manifest tools. The server keeps one live state, shared by
|
||||
every MCP session and the data plane, starting from the derived state.
|
||||
|
||||
A state that is unavailable does not stop the server: it logs a warning naming
|
||||
the error `code` and message before it binds, then serves replay. The state is
|
||||
unavailable when it cannot be derived, such as from a
|
||||
`capture_browser_scenario` capture that selected header values but no response
|
||||
bodies or over the view's budget, and when its catalog under the served name
|
||||
exceeds the [discovery reservation](#what-a-manifest-is). That check runs
|
||||
first, so no state is derived for it, and replay is then admitted exactly as
|
||||
with `--replay-only`. `--replay-only`
|
||||
serves replay without deriving anything; the card, tools and `/agentenv`
|
||||
answers are then exactly those of replay. The stopped document's `state`
|
||||
member reports which applied:
|
||||
|
||||
- `{"served": true, "evidence_id": "ev_…"}`: served from the derived state.
|
||||
- `{"served": false, "reason": "replay-only"}`: `--replay-only` was given.
|
||||
- `{"served": false, "reason": "unavailable", "code": "unsupported_target", "message": "…"}`:
|
||||
the state is unavailable; `code` and `message` are those of the refusal
|
||||
(`resource_constraint` for a catalog over the reservation), as the warning
|
||||
logged them.
|
||||
|
||||
Each read tool answers according to its view in the state:
|
||||
|
||||
| View | Answer |
|
||||
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `item` | The entity the path arguments name, rendered into the recorded envelope of `envelope_ordinal`. Arguments match as replay matches them: each collection segment equals the held collection's segment as written or after percent-decoding, and the identity is the last argument percent-decoded, then as written; values are never re-split on `/`. Any entity the state holds answers, including one `data/add` loaded; query arguments only decide `replay.exact_match`. An entity the state does not hold, or one lacking a field every recording carried, is a tool error; a body is never invented. |
|
||||
| `list` | When the arguments name one of the lines the view checked exactly (its latest recordings before the first related write; every path and query value equal to the recording's, and every recorded query parameter supplied), that recorded envelope with its array rendered from the state: every entity of the collection in state order for `membership: "all"`, or the recorded members still held. A member lacking a field every recording carried makes the call a tool error rather than a partial list. |
|
||||
| `document` | When the arguments name the document's checked line exactly, the state's value for it; a tool error when the state holds none. |
|
||||
| `recorded` | The recording, as replay answers it. |
|
||||
|
||||
A list or document call that names no checked line, including a line recorded
|
||||
after a write or with other query values, answers from the recording. Every
|
||||
answer has the replay shape plus `state`: `{"source": "state", "view": …}`
|
||||
naming the entity, collection or document path, or `{"source": "recording",
|
||||
"reason": …}` with the view's reason, `no-view` or `unrecorded-request`. A
|
||||
state answer carries the base record's status, content type and `replay`
|
||||
provenance with `truncated: false`; one whose JSON would exceed 256 KiB is
|
||||
refused as a `resource_constraint` tool error rather than cut. Extraction does
|
||||
not state-back a document whose rendered JSON exceeds 256 KiB; that read stays
|
||||
recorded (`rendered-oversize`) and replays the captured body. Serving is
|
||||
read-only: `POST`, `PUT`, `PATCH` and `DELETE` tools, other than query `POST`s,
|
||||
are not served, so nothing a call does changes the state. Query `POST`s stay
|
||||
served and answer from their recordings with the reason `query-body`.
|
||||
|
||||
The data plane serves three JSON-RPC methods:
|
||||
|
||||
| Method | Result |
|
||||
| ------------ | --------------------------------------------------------------------------------------------------------- |
|
||||
| `data/reset` | `{}` after restoring the state the Evidence holds |
|
||||
| `data/add` | `{}` after replacing the whole state with one valid `rea-state/v1` document |
|
||||
| `data/get` | `{"parts": [{"kind": "data", "data": <rea-state/v1 document>}]}` with `state_evidence_id` and the `types` |
|
||||
|
||||
Calls run one at a time in arrival order across requests. Every message of a
|
||||
batch is queued when the batch arrives, so another request's call never lands
|
||||
between them and each message sees the changes of those before it; a reset
|
||||
sent while a download is loading applies after that load. `data/add`
|
||||
takes exactly one part: a `data` part whose `data` is the document, or a
|
||||
`file` part whose `file` carries `bytes` (base64 of UTF-8 JSON) or a `uri`,
|
||||
either a `file://` URL of a local regular file, whose host is empty or
|
||||
`localhost`, or an `https://` URL fetched without following redirects and
|
||||
within 30 seconds, including reading the body; `mimeType`, when given, is
|
||||
`application/json`. A `file://` URL naming another host, or a UNC path such as
|
||||
`file:////server/share/state.json`, is refused before anything is opened, so a
|
||||
load never reaches a network share. A loaded document is at most 32
|
||||
MiB, and so is the state as `data/get` writes it back with the members a
|
||||
document may omit (`types`, `state_evidence_id`, record citations), so a
|
||||
reported state always loads again; an inline part also stays within the 4 MiB
|
||||
request body bound, so larger states arrive by `uri`. Anything else, including `{"parts": []}`, is `-32602
|
||||
invalid params`; a download that fails or answers a non-2xx status is
|
||||
`-32000`. Errors never echo the uri or the content; a file or download failure
|
||||
names its category in `error.data.reason`: `not-found`, `permission`,
|
||||
`not-regular-file`, `changed` or `read-failed` for files, `timeout`,
|
||||
`http-status` or `network` (connection, TLS or a refused redirect) for
|
||||
downloads, and `cancelled` for a download the server's stop or its caller's
|
||||
departure ended.
|
||||
|
||||
Stopping the server cancels every pending call, and a caller that leaves before
|
||||
its reply cancels its own: a download in progress ends, and calls not yet run
|
||||
are answered `-32000` with `error.data.reason` `cancelled` without running. A
|
||||
cancelled call leaves the state unchanged, and shutdown never waits for a
|
||||
download.
|
||||
|
||||
A `file://` state file whose close fails stays owned by the server, and
|
||||
the `data/add` gets `-32000`. The next `file://` load retries that close first
|
||||
and, while it still fails, answers `-32000` without reading another file;
|
||||
inline and `https://` documents still load. Closing the server retries it once
|
||||
more and fails with the unfinished close rather than dropping the descriptor.
|
||||
|
||||
One `/agentenv` response carries at most 64 MiB of replies, twice the 32 MiB
|
||||
a loaded document may hold: room for a `data/get` of a loaded state, while a
|
||||
batch of reads cannot multiply a large state into one body. Replies are
|
||||
measured in order as they are produced, in bounded parts and before they are
|
||||
assembled, and room is kept for every later reply's budget error and the
|
||||
batch's brackets and commas, so one that would take the response past the
|
||||
budget is never built whole and is answered instead with `-32000` whose `error.data` gives
|
||||
`max_response_bytes` and the `reply_bytes` it would have taken. That call still
|
||||
ran, so repeat such a read in another request. A reply no larger than that
|
||||
error, such as a write's `{}`, is always kept.
|
||||
|
||||
```json
|
||||
{
|
||||
"rea_state": {
|
||||
"version": 1,
|
||||
"entities": [
|
||||
{
|
||||
"type": "/api/users",
|
||||
"collection": "/api/users",
|
||||
"id": "2",
|
||||
"fields": { "id": 2, "login": "probe" }
|
||||
}
|
||||
],
|
||||
"documents": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each entity's `type` is a state type's `collection_template`, its `collection`
|
||||
matches that template segment by segment (a template parameter matches any one
|
||||
segment), its identity field's value is its `id`, and its type, collection and
|
||||
id are unique; `view_fields` is optional and names item or list views of its
|
||||
type. Views render their values over the entity's fields, so a view's values
|
||||
must not set the type's identity field to a value whose text differs from the
|
||||
entity's `id`. Spell a collection as requests spell it, as `data/get` reports it: list
|
||||
calls find entities under the checked line's recorded path. Each document
|
||||
names a `document` view once, at its initial document's `path`. The `version`,
|
||||
and the `state_evidence_id` and `types` that `data/get` reports, must match
|
||||
the served state, so a `data/get` result loads back unchanged. A number without
|
||||
an exact native value, or whose serialized spelling would not be read as exact
|
||||
(an integer from 2^53 below 1e21, such as `1e20`, in any spelling), or a
|
||||
`__proto__` member is refused rather than altered.
|
||||
An invalid document is `-32602` naming the first problem by JSON pointer, as in
|
||||
`/rea_state/entities/3/collection` (also in `error.data.path`); a problem
|
||||
inside caller data (`fields`, `value`, `types`) is located at that member, so
|
||||
the pointer never names the caller's keys. A refused document changes nothing;
|
||||
a valid one replaces the whole state at once. The order of `entities` is the
|
||||
state order lists use.
|
||||
|
||||
Record citations stay Evidence provenance. An entity's `record_ordinals` may
|
||||
be omitted or empty and a document's `record_ordinal` omitted; otherwise they
|
||||
must be the served Evidence's citations for that entity or document, or the
|
||||
document is refused. After loading, an entity or document whose values equal the Evidence's cites
|
||||
the Evidence's records, and one whose values were edited or added cites none
|
||||
(`record_ordinals: []`, no `record_ordinal`), so `data/get` never presents a
|
||||
loaded value as recorded.
|
||||
|
||||
The card declares the operations and what `data/add` accepts:
|
||||
|
||||
```json
|
||||
{
|
||||
"extensions": [
|
||||
{
|
||||
"uri": "urn:agentenv:intake/v1",
|
||||
"description": "data/add replaces the whole environment state with one rea-state/v1 document; data/get returns the current state in the same format.",
|
||||
"params": {
|
||||
"add": [
|
||||
{ "part": "data", "format": "rea-state/v1", "load": "replace" },
|
||||
{
|
||||
"part": "file",
|
||||
"format": "rea-state/v1",
|
||||
"mimeTypes": ["application/json"],
|
||||
"load": "replace"
|
||||
}
|
||||
],
|
||||
"get": [{ "part": "data", "format": "rea-state/v1" }]
|
||||
}
|
||||
}
|
||||
],
|
||||
"operations": ["data/reset", "data/add", "data/get"]
|
||||
}
|
||||
```
|
||||
|
||||
The state is a projection of recorded reads. List and document calls answer
|
||||
from the state only for the lines their views checked, and every recorded view
|
||||
answers from recordings; item calls answer for any held entity but render only
|
||||
the envelope one recording carried. Values copied outside entity objects,
|
||||
derived values and counters other than those that count a list stay as
|
||||
recorded; no write has an effect. An exported bundle carries no state file:
|
||||
its server derives the state at startup, as the export does to predict what it
|
||||
serves.
|
||||
|
||||
## Export a bundle
|
||||
|
||||
@@ -336,12 +586,12 @@ agent-env run ./grafana-example
|
||||
|
||||
```text
|
||||
grafana-example/
|
||||
README.md provenance, replay limits, run command, rights note
|
||||
README.md provenance, what it serves, 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
|
||||
artifacts/check_grafana-example/verify.py the verifier
|
||||
tasks/smoke.json deploy_env (local sandbox), then env_outcome_verifier
|
||||
```
|
||||
|
||||
@@ -352,8 +602,12 @@ 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
|
||||
After checking the bundle name, the export prepares the state from the capture
|
||||
exactly as the bundle's server will at startup under that name, to predict what
|
||||
the bundle serves; an unavailable state, including one whose catalog exceeds
|
||||
the discovery reservation, does not stop the export, and the bundle then
|
||||
serves replay. The complete tool catalog the bundle serves 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);
|
||||
@@ -361,7 +615,9 @@ and replay share immutable response trees rather than copying the capture repeat
|
||||
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.
|
||||
written files with their sizes, the pinned package source, the number of tools
|
||||
the bundle serves as `tool_count`, and in `state` whether it serves from the
|
||||
state, in the shape of the serve command's stopped document.
|
||||
|
||||
Export uses the shared output-tree owner to check directory identities around
|
||||
exclusive creates, verify written bytes, and reject unowned entries before
|
||||
@@ -383,21 +639,31 @@ user, so a private host umask cannot leave them unreadable, runs as that user an
|
||||
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
|
||||
Python MCP client: it lists the tools and checks the count equals the number
|
||||
the bundle serves (the manifest's read tools from the state, every manifest
|
||||
tool in replay), calls one tool with no arguments and checks the call did not
|
||||
fail and its `status` is the expected one, and returns one `serve` result
|
||||
whose description reports both checks. The tool is the first served `GET` tool
|
||||
without path parameters whose answer to no arguments is not an error, and the
|
||||
expected status is the status of that answer: the export calls the same answer
|
||||
function the server uses, from the derived state or by replay, so a state
|
||||
answer carries its base record's status and a replayed one its record's (an
|
||||
unknown recorded status stays unknown; it is not borrowed from another
|
||||
record). A bundle 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
|
||||
capture and manifest Evidence ids, the manifest view digest, the served tool
|
||||
count, the derived state's Evidence id or that no state is served, and the
|
||||
package source. It says what the environment serves: read tools from the state
|
||||
the capture observed, the `/agentenv` data plane on it and no write tools yet,
|
||||
replay when the state is unavailable, and `--replay-only` for pure replay; it
|
||||
says which applies to this bundle, with the error code and message when the
|
||||
state is unavailable, and that neither is emulation and served
|
||||
content is untrusted data. It states that the recorded content belongs to the
|
||||
captured application and must not be published without the rights to it.
|
||||
|
||||
## Compatibility verification
|
||||
@@ -414,13 +680,21 @@ framework versions.
|
||||
|
||||
## Resource and lifecycle boundaries
|
||||
|
||||
Both Evidence files are read once at startup through the bounded JSON input
|
||||
The 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
|
||||
opened. The state is derived once, in-process and before binding, from the
|
||||
already authenticated capture: it is projected as retained Evidence, so the
|
||||
capture's strings are not charged again as inline view input, and the view's
|
||||
96 MiB budget bounds the derivation. 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
|
||||
only the cited records' request lines and response text in memory, plus the
|
||||
live state when it serves from one: the derived initial state, or one
|
||||
validated document whose JSON was at most 32 MiB. Data-plane calls run one at a time, so
|
||||
at most one loaded document is being read and parsed at once; `data/get`
|
||||
serializes the held state whole. No process is launched and nothing is
|
||||
written to disk. No outbound network request is made unless a `data/add` call names an
|
||||
`https://` uri, which is fetched once within the limits above; a `file://` uri
|
||||
is read once. A listener that fails after binding is logged and ends the command with
|
||||
a `resource_constraint` error and exit `1` instead of serving nothing.
|
||||
@@ -335,9 +335,12 @@ export REA_JADX_OPERATION_TIMEOUT_MS=600000
|
||||
```
|
||||
|
||||
The value must be a decimal millisecond count from 1 to 2147483647; anything
|
||||
else is refused before Java starts. The same deadline bounds each upstream
|
||||
call, a timeout reports the selected value, and a passing JADX configuration
|
||||
check in `rea doctor` reports the effective `operation_timeout_ms`. Explicit
|
||||
else is refused before Java starts. REA reads it from the environment captured
|
||||
at process start. A change applies on the next process start; an already
|
||||
running server keeps the deadline it started with. The same deadline bounds
|
||||
each upstream call. A timeout names `REA_JADX_OPERATION_TIMEOUT_MS`, the
|
||||
effective milliseconds, and that range. A passing JADX configuration check in
|
||||
`rea doctor` reports the effective `operation_timeout_ms`. Explicit
|
||||
cancellation still ends the operation immediately, and partial observations
|
||||
and owned-process cleanup are unchanged. Raising the deadline does not extend
|
||||
the bridge's 30-second startup handshake or the upstream **90-second**
|
||||
|
||||
@@ -65,6 +65,7 @@ rea decode-android-resources /targets/Example.apk --locale de
|
||||
rea decode-android-resources /targets/Example.apk --locales de --locales pt-BR
|
||||
rea decode-android-resources /targets/Example.apk --locales de --locales pt-BR --string-tables-only
|
||||
rea decode-android-resources /targets/Example.apk --no-strings
|
||||
rea decode-android-resources /targets/Example.apk --decode-timeout-ms 900000
|
||||
```
|
||||
|
||||
Equivalent MCP methods are `inspect_apktool_client` and
|
||||
@@ -133,9 +134,14 @@ still suppresses all string projection, including in this mode.
|
||||
|
||||
## Resource and lifecycle limits
|
||||
|
||||
- The decode runs with a 600 s deadline and a 4 MiB output capture budget;
|
||||
a stopped decode reports `provider_timeout` and exceeded budgets report
|
||||
`resource_constraint`.
|
||||
- The decode wall clock is `decode_timeout_ms` (CLI `--decode-timeout-ms`).
|
||||
Omitted means 600000 ms. The integer range is 1 to 2147483647. A change
|
||||
applies on the next decode. It does not raise the 4194304-byte (4 MiB)
|
||||
output capture budget. That capture budget has no runtime override. A
|
||||
stopped decode reports `provider_timeout` and names the effective
|
||||
milliseconds; an exceeded capture budget reports `resource_constraint`.
|
||||
- The version probe waits 20000 ms and retains 65536 bytes. This release has
|
||||
no runtime override for that probe. `decode_timeout_ms` does not raise it.
|
||||
- Manifest reads are bounded to 512 KiB before decoding UTF-8. Strings XML
|
||||
reads are bounded to 8 MiB; larger documents are skipped with partial
|
||||
coverage and an explicit limit, rather than reported as missing.
|
||||
|
||||
@@ -213,20 +213,37 @@ Resolution follows dyld:
|
||||
Each edge lists every candidate path tried, with its outcome: `resolved`,
|
||||
`absent`, `not-mach-o`, `malformed`, `unsupported` (recognized Mach-O outside
|
||||
parser coverage, such as big-endian images), `architecture-missing`,
|
||||
`outside-target`, `escapes-target`, or `undetermined`. Slices follow dyld's
|
||||
graded architectures, so an `x86_64h` process also loads `x86_64`. The edge's `resolution` is one of:
|
||||
`not-loadable`, `platform-mismatch`, `outside-target`, `escapes-target`, or
|
||||
`undetermined`. `not-loadable` means a
|
||||
matching-architecture Mach-O image was found but it is not a dylib and cannot
|
||||
satisfy a dylib dependency. `platform-mismatch` means a matching-architecture
|
||||
dylib was found but its observed platform is incompatible with the process.
|
||||
These outcomes reject that candidate; dyld search may continue and resolve a
|
||||
later candidate. Candidate outcomes describe individual search paths, while
|
||||
`resolution.status` describes the final edge. Slices follow dyld's graded
|
||||
architectures, so an `x86_64h` process also loads `x86_64`. The edge's
|
||||
`resolution` is one of:
|
||||
|
||||
| Status | Meaning |
|
||||
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `resolved` | An image inside the analyzed root loads, and no earlier candidate was undeterminable. |
|
||||
| `conditional` | An image inside the root resolves, but an earlier candidate outside the root (for example `/usr/lib/swift`) would win if it exists on the running system. |
|
||||
| `unresolved` | Every candidate is definitively absent or unusable inside the root. |
|
||||
| `undetermined` | No candidate resolves inside the root, and some candidate lies outside it or depends on the environment. |
|
||||
| Status | Meaning |
|
||||
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `resolved` | An image inside the analyzed root loads, and no earlier candidate was undeterminable. |
|
||||
| `conditional` | An in-root image may load, but an earlier outside candidate, unmodeled environment input, or unknown platform compatibility can change which image dyld loads. |
|
||||
| `unresolved` | Every candidate is definitively absent or unusable inside the root. |
|
||||
| `undetermined` | No candidate resolves inside the root, and some candidate lies outside it or depends on the environment. |
|
||||
|
||||
A `conditional` image is still traced, because it is the image the analyzed
|
||||
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.
|
||||
A `conditional` image is still traced, because it is an in-root candidate
|
||||
that may load. Every edge below it has `loader_conditional: true`, and a
|
||||
request that reuses it by install name is `conditional` too. An in-root dylib
|
||||
with no platform load command remains unknown unless the root is an executable
|
||||
with observed macOS platform and the candidate’s CPU type is x86_64, i386, or arm64. In that macOS context,
|
||||
[Apple's dyld](https://github.com/apple-oss-distributions/dyld/blob/fd8d0c4d52320ebf64db34f3cb280310d905c5ae/mach_o/UnsafeHeader.cpp#L1137-L1145) supplies an implicit macOS platform to legacy dylibs on those CPU
|
||||
types. The candidate records `platform_basis: "macos-dyld-implicit"`; the
|
||||
reported slice fields `platform: null` and `platforms: []` remain the parsed
|
||||
facts. For other process contexts the platform remains unknown, coverage is
|
||||
partial, and the candidate is not treated as incompatible. If a later known
|
||||
candidate resolves, it remains the traced image with conditional resolution;
|
||||
the trace does not claim the unknown candidate's dependency graph. Findings on
|
||||
conditional edges say that they apply only if the conditional image loads.
|
||||
|
||||
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
|
||||
|
||||
+50
-30
@@ -18,7 +18,7 @@ Inspect native SAZ or HAR 1.2 offline with REA, or connect Everywhere's separate
|
||||
- `inspect_web_page` / `rea inspect-web-page` captures DOM structure, accessibility nodes, scripts, resources, safe response/DOM metadata, attach-window network and console metadata, WebSocket frame sizes, workers, quota, and optionally selected storage key names, redacted storage-content fingerprints, or script sources.
|
||||
- `analyze_web_bundle` / `rea analyze-web-bundle` parses selected script artifacts without execution and derives chunk edges, route and endpoint candidates, vendor fingerprints, static WebMCP declarations, and optionally source-map/original-source evidence.
|
||||
- `observe_web_session` / `rea observe-web-session` arms an observation window of the requested duration for an external user action and records ordered reload, SPA navigation, redirect, failure, lifecycle, and target-termination metadata.
|
||||
- `discover_webmcp_tools` / `rea discover-webmcp-tools` uses the experimental CDP WebMCP domain to return every in-scope registration and its complete 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`.
|
||||
- `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 or registration stacks 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.
|
||||
|
||||
@@ -125,14 +125,11 @@ bundle, for example
|
||||
`"/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"`. Fedora installs
|
||||
Chromium as `chromium-browser`.
|
||||
|
||||
REA needs the browser's HTTP discovery endpoint on a loopback port. A browser
|
||||
driven over `--remote-debugging-pipe` or a private channel, for example by an
|
||||
automation SDK, exposes no such endpoint, so `list_browser_targets` has nothing
|
||||
to attach to. Connection failures report `endpoint_unreachable`; a reachable
|
||||
HTTP service that returns a non-200 or non-JSON discovery response reports
|
||||
`invalid_endpoint_response`.
|
||||
Reproduce that flow in a Chromium-family browser started with
|
||||
`--remote-debugging-port`.
|
||||
REA attaches through the browser's HTTP discovery endpoint on a loopback port,
|
||||
or, for some passive tools, through a
|
||||
[browser socket](#browsers-without-http-discovery). Connection failures report
|
||||
`endpoint_unreachable`; a reachable HTTP service that returns a non-200 or
|
||||
non-JSON discovery response reports `invalid_endpoint_response`.
|
||||
|
||||
In a minimal Linux container, headed Chromium under Xvfb can keep running while
|
||||
its DevTools port never opens. Install the GLES, EGL, and Mesa DRI libraries
|
||||
@@ -184,7 +181,9 @@ file for you.
|
||||
the origins you are investigating.
|
||||
|
||||
A browser driven only through `--remote-debugging-pipe` or a vendor's private
|
||||
automation channel has neither endpoint, and REA cannot attach to it.
|
||||
automation channel has neither endpoint, and REA cannot attach to it. To
|
||||
inspect such a page, reproduce it in a Chromium-family browser started with
|
||||
`--remote-debugging-port`.
|
||||
|
||||
## Request boundary
|
||||
|
||||
@@ -361,7 +360,7 @@ 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, 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.
|
||||
- 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. Argument types are listed by CDP argument position. An absent or non-array argument inventory is `null`, and a malformed argument keeps its position as `unknown`; either makes `console_events` incomplete, while an observed empty inventory remains `[]`. A malformed stack or top stack frame is not replaced by its caller: the console event is excluded, and a request initiator location or WebMCP `registration_source` is `null`; each is reported as `invalid_protocol_value`. 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 with their original `argument_index`; objects, getters, and remote properties are never expanded. Text capture is `unavailable` when the argument inventory is unknown.
|
||||
- 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.
|
||||
@@ -386,7 +385,8 @@ section explicitly truncated.
|
||||
Disallowed-origin entries are filtered before retention.
|
||||
|
||||
Selected script-source collection shares a 32 MiB aggregate UTF-8 retention
|
||||
budget and a 20-second deadline across the capture. An oversized source is
|
||||
budget and the `command_timeout_ms` deadline (default 20000 ms) across the
|
||||
capture. The byte budget has no runtime override. An oversized source is
|
||||
omitted while later smaller sources may still fit. When the deadline expires,
|
||||
remaining source reads are skipped. Script metadata, per-item omission reasons,
|
||||
and `script_sources` completeness remain available. A single CDP response can
|
||||
@@ -394,19 +394,25 @@ still be materialized up to the separate 64 MiB transport limit before source
|
||||
admission; the retention budget does not bound that transient allocation.
|
||||
|
||||
Bundle parsing and semantic inspection run sequentially in an owned child,
|
||||
without executing captured code. `max_heap_mb` defaults to 1024 MiB V8
|
||||
old-space; `analysis_timeout_ms` defaults to 30000 per script, including startup
|
||||
and transfer. A failed or timed-out script becomes an explicit unknown while
|
||||
completed findings and later scripts remain available. `total_analysis_timeout_ms`
|
||||
defaults to 300000 across script analysis; expiry returns a typed timeout with
|
||||
partial Evidence and identifies unstarted scripts. These controls are also
|
||||
available as CLI flags with hyphenated names. Capture and optional source-map
|
||||
fetching have separate budgets.
|
||||
without executing captured code. These are separate phases. `max_heap_mb`
|
||||
defaults to 1024 MiB V8 old-space (range 128..16384). `analysis_timeout_ms`
|
||||
defaults to 30000 per script, including startup and transfer.
|
||||
`total_analysis_timeout_ms` defaults to 300000 across script analysis. A
|
||||
per-script deadline above the effective total is rejected. A failed or
|
||||
timed-out script becomes an explicit unknown while completed findings and later
|
||||
scripts remain available. Total-deadline expiry returns a typed timeout with
|
||||
partial Evidence and identifies unstarted scripts. `source_map_fetch_timeout_ms`
|
||||
defaults to 30000 and is an item limitation, not that analysis timeout. These
|
||||
controls are also available as CLI flags with hyphenated names. Worker protocol
|
||||
and result byte budgets have no runtime override.
|
||||
|
||||
One web-bundle capture/analysis is admitted per REA process at a time. Completed
|
||||
script results share an 8 MiB serialized transfer budget, with host heap
|
||||
reservation checked before decoding and validating another result.
|
||||
Exhausted result capacity stops further script launches and returns a typed
|
||||
When the host reservation is what reaches zero, the failure names that heap
|
||||
headroom and the remaining fixed budget. When the 8 MiB allowance itself is
|
||||
exhausted, the failure names that fixed budget and says it has no runtime
|
||||
override. Either stop ends further script launches and returns a typed
|
||||
resource failure with completed facts and explicit unstarted-script unknowns.
|
||||
Worker control frames are limited to 64 KiB. Cleanup must confirm child termination
|
||||
before releasing its private files; failed cleanup retains its exact owner and
|
||||
@@ -416,8 +422,10 @@ facts, including cancellation during final cleanup.
|
||||
The worker heap setting is not a process-family RSS limit. Node enforces V8
|
||||
old-space flags; Bun ignores them. Windows Bun instead uses an owned process
|
||||
commit limit with a 512 MiB runtime reserve; other Bun hosts have no enforced
|
||||
memory limit. These bounds do not establish an aggregate host-memory limit
|
||||
across other REA operations or external processes.
|
||||
memory limit. An allocation failure before that Windows limit is reported as
|
||||
reached still names the configured limit and says it was not reached. These
|
||||
bounds do not establish an aggregate host-memory limit across other REA
|
||||
operations or external processes.
|
||||
|
||||
Resource-tree inventories distinguish a valid empty `resources` array from a
|
||||
missing or malformed collection. Invalid resource entries are omitted with
|
||||
@@ -431,12 +439,24 @@ an invalid supplied size remains unknown with incomplete resource coverage while
|
||||
the resource's other facts are retained. Zero and nonnegative fractional sizes
|
||||
are preserved.
|
||||
|
||||
CDP discovery has a 10-second deadline. Each WebSocket handshake and command
|
||||
response has its own 20-second deadline, separate from the caller-selected
|
||||
observation window. A stalled handshake or command reports `provider_timeout`;
|
||||
caller cancellation still reports cancellation. WebSocket messages remain subject
|
||||
to the [64 MiB limit](#request-boundary). REA does not impose a message-count or
|
||||
pending-command quota. On cancellation, it closes only its own WebSocket,
|
||||
CDP discovery has a 10-second response deadline. HTTP discovery documents
|
||||
use an 8 MiB budget. Browser-socket discovery (`Browser.getVersion`,
|
||||
`Target.getTargets`) uses the 64 MiB protocol message budget. Neither budget
|
||||
nor the discovery deadline has a runtime override. `list_browser_targets` accepts no
|
||||
`command_timeout_ms`: HTTP discovery and browser-socket discovery
|
||||
(`Browser.getVersion`, `Target.getTargets`) stay on that fixed deadline, and
|
||||
the socket closes without a later command. Other CDP tools use
|
||||
`command_timeout_ms` (default 20000) for each WebSocket handshake and command
|
||||
response, separate from the caller-selected observation window, discovery, and
|
||||
the 5000 ms cleanup grace. A browser-level socket's handshake and the following
|
||||
`Target.attachToTarget` each receive that full deadline; they do not share one
|
||||
budget. A stalled handshake or command reports
|
||||
`provider_timeout` and names `command_timeout_ms` only when that operation
|
||||
accepts it; caller cancellation still reports cancellation. WebSocket messages
|
||||
remain subject to the [64 MiB limit](#request-boundary), which has no runtime
|
||||
override. REA does
|
||||
not impose a message-count or pending-command quota. On cancellation, it closes
|
||||
only its own WebSocket,
|
||||
waiting up to one second before terminating it. Malformed unsolicited events
|
||||
and malformed replies to pending commands poison the connection so later
|
||||
commands fail closed. A correlated reply's session ID must match the command's
|
||||
@@ -445,7 +465,7 @@ rejects it as unknown; other command rejections retain their reported failure.
|
||||
|
||||
Network and console coverage starts only after REA attaches and enables the relevant CDP domains. `prior_activity_available` is always `false`; absence from these arrays is not evidence that an event never occurred. Scripts are different: scripts the page parsed before REA attached are still reported under `scripts`. A page that loaded before attach can therefore list its scripts while `network.requests` lacks the requests that fetched them. If CDP reuses a request ID without supplying redirect metadata, REA retains the predecessor observation and marks network coverage incomplete.
|
||||
|
||||
Source maps are not fetched by inspection. Bundle analysis fetches them only when `fetch_source_maps` is selected, with exact-origin redirect checks and no credentials, cookies, or referrer. Each fetch operation has a 30-second deadline and a 64 MiB aggregate streamed-response budget across redirects. A deadline or byte-limit failure remains explicitly unavailable and makes bundle completeness partial. Source-map decoding also bounds raw resolved identities to 64 MiB and aggregate inline evidence to 32 MiB. Failed maps preserve their failure context when it fits; if another context cannot fit, collection stops with the full requested count, the returned processed count, and an explicit unknown-results limitation. Retained mappings and original sources are returned inline. See [source-location limits](web-source-location.md) for the structural decoder bounds. Original source artifacts with `.ts`, `.tsx`, `.mts`, or `.cts` suffixes carry `text/typescript`; other source names retain `text/javascript`.
|
||||
Source maps are not fetched by inspection. Bundle analysis fetches them only when `fetch_source_maps` is selected, with exact-origin redirect checks and no credentials, cookies, or referrer. Each fetch operation uses `source_map_fetch_timeout_ms` (default 30000) and a 64 MiB aggregate streamed-response budget across redirects. The byte budget has no runtime override. A fetch overrun is an item limitation, not a thrown analysis timeout. A deadline or byte-limit failure remains explicitly unavailable and makes bundle completeness partial. Source-map decoding also bounds raw resolved identities to 64 MiB and aggregate inline evidence to 32 MiB. Failed maps preserve their failure context when it fits; if another context cannot fit, collection stops with the full requested count, the returned processed count, and an explicit unknown-results limitation. Retained mappings and original sources are returned inline. See [source-location limits](web-source-location.md) for the structural decoder bounds. Original source artifacts with `.ts`, `.tsx`, `.mts`, or `.cts` suffixes carry `text/typescript`; other source names retain `text/javascript`.
|
||||
|
||||
source-map items retain the script's `declared_url` separately from the observed
|
||||
`effective_url`. successful maps use the latter as their source-resolution base.
|
||||
|
||||
@@ -23,9 +23,21 @@ that rejection does not roll back browser effects. REA removes its owned
|
||||
future-document scripts, restores live frame methods, then disconnects.
|
||||
Add secret declarations, storage seeds, and additional artifact or event
|
||||
capture only when needed. Action, secret, and storage counts are not capped.
|
||||
Duration, action, and navigation timeouts remain fixed provider-owned liveness
|
||||
limits. `capture.limits` controls retained event and network-content budgets;
|
||||
it does not change those liveness deadlines.
|
||||
Duration, action, and navigation timeouts remain separate from CDP command
|
||||
deadlines. `command_timeout_ms` (default 20000; omit it to keep that default
|
||||
and leave it out of Evidence) bounds launch startup, the connect-over-CDP
|
||||
handshake, target lookup, environment commands, and storage CDP commands,
|
||||
including replies from attached child targets. Set it in the scenario JSON.
|
||||
`capture-browser-scenario` has no `--command-timeout-ms` option.
|
||||
It does not change action `timeout_ms`, `wait_for_timeout.duration_ms`, or
|
||||
navigation. Service-worker restoration keeps a fixed 5000 ms grace and does
|
||||
not inherit a raised `command_timeout_ms`. CDP discovery stays on its own
|
||||
fixed deadline. When service workers are blocked, the registration check
|
||||
before discovery has its own fixed 10000 ms deadline; `command_timeout_ms`
|
||||
does not apply because discovery has not started. The discovery deadline
|
||||
covers endpoint discovery only. The following WebSocket handshake and
|
||||
`Target.attachToTarget` each use `command_timeout_ms`. `capture.limits` controls retained event and network-content
|
||||
budgets; it does not change those liveness deadlines.
|
||||
|
||||
## Minimal launch example
|
||||
|
||||
@@ -212,7 +224,9 @@ statements remain under the attached debugger client's control.
|
||||
The result is Evidence with an initial state followed by one record per
|
||||
declared action. Each step reports action status, elapsed time, sanitized URLs,
|
||||
event bounds, and independently typed capture states for screenshot, DOM,
|
||||
accessibility, URL, history, and storage. Console, page-error, network,
|
||||
accessibility, URL, history, and storage. Actions after a failed or cancelled
|
||||
action are not run and are recorded as `cancelled` with a not-executed error.
|
||||
Console, page-error, network,
|
||||
WebSocket, frame, worker, popup, and cancelled-download events are attributed to
|
||||
steps. Retained events and requested artifacts are returned inline; omitted
|
||||
events are counted by kind and identify affected network transactions.
|
||||
|
||||
+65
-25
@@ -63,6 +63,16 @@ or repeat it to select several types.
|
||||
Selection limits decoding to the selected types; member references remain an
|
||||
assembly-wide inventory, so the output can still be large.
|
||||
|
||||
Select `--detail summary --evidence-bundle /absolute/path/members.json` to
|
||||
receive identity, selection, coverage, limitations and collection counts while
|
||||
saving the complete original Evidence in a new bundle. Summary requires that
|
||||
explicit destination; existing files are preserved. Later
|
||||
`inspect-analysis-view` calls can page the exact parent from the saved bundle
|
||||
without reopening the assembly. See
|
||||
[CLI summary and saved member rows](managed-code-analysis.md#cli-summary-and-saved-member-rows)
|
||||
for the complete command sequence. Omitted or `--detail complete` retains the
|
||||
full inline response.
|
||||
|
||||
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. For the image, type and method
|
||||
@@ -204,7 +214,7 @@ The selected provider remains bound to the session until an explicit switch
|
||||
or close. Provider failures are returned with their original reason. For an
|
||||
`ambiguous` selection error, choose from `details.candidate_ids`; for
|
||||
`provider_unavailable`, follow `message`, `remediation.action`, and the original
|
||||
reasons in `details.rejections`. For Hopper, Ghidra, IDA, and JADX, run
|
||||
reasons in `details.rejections`. For Hopper, Ghidra, IDA, JADX, and Kuna, run
|
||||
`rea doctor --provider ID --json` to diagnose the selected engine. Other adapters,
|
||||
such as `pwntools-elf`, report their configuration requirements directly and are
|
||||
not accepted by `doctor --provider`. See
|
||||
@@ -279,7 +289,12 @@ Exports preserve an existing destination unless `--overwrite` is explicit.
|
||||
For application traces and version comparisons, see
|
||||
[JavaScript application workflows](javascript-application-workflows.md).
|
||||
MCP [retained Evidence references](mcp-contracts.md#retained-application-evidence-inputs)
|
||||
belong to one connection. Separate CLI calls consume full saved records.
|
||||
belong to one connection. Separate CLI calls can consume full saved records.
|
||||
`inspect-analysis-view REQUEST.json --evidence-bundle BUNDLE.json` resolves
|
||||
the request's `retained-evidence` source ID from that authenticated bundle,
|
||||
including bundles exported from an MCP session. The same view JSON works for
|
||||
every supported parent kind; no target is reopened and no record is selected
|
||||
by file order. Omit `--evidence-bundle` when the request supplies inline Evidence.
|
||||
|
||||
## Import historical source
|
||||
|
||||
@@ -390,14 +405,25 @@ 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.
|
||||
`rea environment-serve <manifest.json> --evidence <capture.json>
|
||||
[--replay-only] [--host H] [--port N]` serves an environment manifest
|
||||
projected by `inspect-analysis-view` as an agent environment: an MCP server at
|
||||
`/mcp`, the environment card at `/.well-known/agent-env.json`, and a
|
||||
`/agentenv` data plane. The manifest's `parent_evidence_id` must equal the
|
||||
evidence file's `evidence_id`; otherwise the command refuses with
|
||||
`invalid_request` before binding. Before binding it derives the
|
||||
`environment-state` view of the capture with the manifest's `template_rules`,
|
||||
as `inspect-analysis-view` would, and serves from it: read tools whose views
|
||||
are state-backed answer from a live state, write tools are not served, and
|
||||
`/agentenv` serves `data/reset`, `data/add` and `data/get`. When the state
|
||||
cannot be derived, or its catalog exceeds the discovery reservation, it logs a
|
||||
warning with the error code and message and serves replay; `--replay-only` serves replay without deriving. In replay every
|
||||
manifest tool replays the retained capture records it cites and `/agentenv`
|
||||
answers every method with JSON-RPC `-32601`. The stopped document's `state`
|
||||
member is `{"served": true, "evidence_id": …}`,
|
||||
`{"served": false, "reason": "replay-only"}` or
|
||||
`{"served": false, "reason": "unavailable", "code": …, "message": …}`; see
|
||||
[serve from the state](agent-environments.md#serve-from-the-state).
|
||||
|
||||
```sh
|
||||
rea environment-serve manifest.json --evidence capture.json --port 8765
|
||||
@@ -408,8 +434,8 @@ rea environment-serve manifest.json --evidence capture.json --port 8765
|
||||
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.
|
||||
[agent environments](agent-environments.md) for what the state and replay
|
||||
return and do not establish.
|
||||
|
||||
## Export an environment bundle
|
||||
|
||||
@@ -417,9 +443,11 @@ not establish.
|
||||
[--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.
|
||||
the pair with the same checks as `environment-serve`, checks the bundle name,
|
||||
then prepares the state under that name as the bundle's server will at startup
|
||||
to predict what the bundle serves (replay when the state is unavailable),
|
||||
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
|
||||
@@ -429,14 +457,16 @@ 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`
|
||||
`environment-serve` (from the state by default), a Python verifier under
|
||||
`artifacts/check_<name>/` that checks the served tool count and one served
|
||||
answer, 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
|
||||
command prints one JSON document listing the written files with their sizes,
|
||||
the pinned package source, the served `tool_count`, and `state` in the shape
|
||||
of the serve command's stopped document. See
|
||||
[agent environments](agent-environments.md#export-a-bundle) for the folder
|
||||
layout and what the smoke task checks.
|
||||
|
||||
@@ -488,18 +518,20 @@ 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
|
||||
in a format other than HAR, a manifest or state 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 write that fails after the first file (a permission, disk-space or
|
||||
pathname-length failure on a later path) propagates as the host's failure,
|
||||
naming its cause and, when it failed on one bundle file or the package
|
||||
tarball, that file. A failure while syncing the finished folder names only its
|
||||
cause. Either way the partial folder stays 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
|
||||
@@ -519,6 +551,14 @@ command, objdump, Rizin and GDB, and the agent environment server
|
||||
signal-derived status. This describes the current source routing; it is not a
|
||||
claim that every command or provider runtime has been independently exercised.
|
||||
|
||||
Commands with `--evidence_output` select their delivered view, then publish the
|
||||
complete Evidence bundle atomically. Cancellation before publication leaves no
|
||||
new file. A publication that has committed can win a later cancellation; the
|
||||
`cancelled` result then keeps the written path and byte count under
|
||||
`details.diagnostics.evidence_bundle`. If staging cleanup stays incomplete
|
||||
after commit, the `cleanup_incomplete` error reports the same file as
|
||||
`details.published_path` and `details.bytes`.
|
||||
|
||||
When the reader of piped output closes early, as `rea ... | head` does, the
|
||||
CLI stops writing, prints no error and exits `141` (`128 + 13`, the status of a
|
||||
SIGPIPE-terminated writer). The operation itself may have completed; only its
|
||||
|
||||
@@ -153,8 +153,8 @@ headroom. The default is 450000 ms, covering the default 330-second Ghidra
|
||||
startup; an explicit Ghidra startup timeout of 2700000 ms produces a 2820000 ms
|
||||
tool timeout. The startup allowance follows an explicitly selected Ghidra or
|
||||
Hopper provider, and otherwise uses the larger known Ghidra/Hopper deadline.
|
||||
An explicit `REA_JEB_MCP_TIMEOUT_MS` request budget also contributes to that
|
||||
maximum. For `ida` or `auto` selection, a valid IDA registration's parsed
|
||||
An explicit `REA_JEB_MCP_TIMEOUT_MS` deadline, shared by catalog discovery and
|
||||
each tools/call, also contributes to that maximum. For `ida` or `auto` selection, a valid IDA registration's parsed
|
||||
`timeoutMs` also contributes to that maximum; its default is 300000 ms.
|
||||
Setup forwards these explicitly selected REA deadlines and the input schema
|
||||
profile into the registration; unrelated process values are omitted. An
|
||||
|
||||
@@ -17,8 +17,8 @@ shared form would leave later fields unknown instead. The existing
|
||||
`REA_MCP_INPUT_SCHEMA_PROFILE=compact` profile lets callers stay below
|
||||
its character limit by advertising reduced nested validation structure, while
|
||||
REA continues to validate calls against the complete canonical input schema.
|
||||
Compact applies to the server's advertised inputs and is not an automatic
|
||||
full-profile fallback; see the [compact input schema profile](mcp-contracts.md#compact-input-schema-profile)
|
||||
Compact is the default for the server's advertised inputs; an explicit `full`
|
||||
choice is preserved. See the [compact input schema profile](mcp-contracts.md#compact-input-schema-profile)
|
||||
for details of its reduced forms.
|
||||
|
||||
Custom renderer hosts can raise `inputMaxChars` through `renderToolSignature` or
|
||||
|
||||
@@ -116,7 +116,9 @@ The CLI and MCP surfaces accept the same schema. For a JSON request file:
|
||||
rea capture-electron-scenario scenario.json --json
|
||||
```
|
||||
|
||||
The result records action status and targets, correlated app/window/WebContents,
|
||||
The result records one status and target per declared action; actions after a
|
||||
failed or cancelled action are not run and are recorded as `cancelled` with a
|
||||
not-executed error. It also records correlated app/window/WebContents,
|
||||
preload, session, navigation, shell, permission, popup, download, protocol,
|
||||
native-addon, process, and IPC timeline events. IPC channels and argument-shape
|
||||
metadata retain their observed lengths; payload values are never retained.
|
||||
@@ -243,4 +245,10 @@ application path and capture outcome to the static graph, while frames, scripts,
|
||||
workers, and execution claims remain unavailable until a separate passive runtime
|
||||
capture provides them.
|
||||
|
||||
ASAR observation reads the header through one open file handle, validates its declared lengths against the archive size, and limits encoded JSON headers to 16 MiB before parsing. The header cache also retains at most 16 MiB of encoded headers across eight archives. Oversized headers produce a scope refusal.
|
||||
ASAR observation reads the header through one open file handle and validates its
|
||||
declared lengths against the archive size. Header/index admission is the same
|
||||
fixed 16 MiB / 16777216 byte budget used by static ASAR reads. This release has
|
||||
no runtime override. An oversized header is not parsed; selecting a member path
|
||||
does not bypass admission, and the page stays unauthorized. The header cache
|
||||
separately retains at most 16 MiB of already-admitted encoded headers across
|
||||
eight archives. Evicting that cache does not raise admission.
|
||||
@@ -106,7 +106,11 @@ CLI keeps its existing complete result.
|
||||
|
||||
Inputs are limited to 4 MiB, complete replies to 16 MiB and combined diagnostic
|
||||
output to 1 MiB. An owned worker has a 256 MiB JavaScript heap, 3 GiB virtual
|
||||
address-space limit, 30 CPU seconds and a 30-second command deadline. Virtual
|
||||
address-space limit and 30 CPU seconds. The worker command deadline is
|
||||
`timeout_ms` (default 30000 ms, integer 1 through 2147483647) on the next call,
|
||||
or `--timeout-ms` on `rea inspect-evm-interface`. Omission keeps 30000 ms.
|
||||
Those byte, address-space, and CPU ceilings have no runtime override, and
|
||||
`timeout_ms` does not raise them. Virtual
|
||||
address space differs from resident memory. The worker retains inherited tighter
|
||||
soft/hard limits, reports its configured soft limits inline and leaves hard limits
|
||||
unchanged. WASM trap reservations are disabled
|
||||
|
||||
@@ -158,7 +158,13 @@ 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** analysis deadline through inventory. Publication and final
|
||||
- Analysis defaults to **120 seconds**, from tool resolution and input snapshot
|
||||
through inspection and its final private-workspace cleanup, or extraction
|
||||
through report consumption and inventory, excluding queue waiting and retained
|
||||
cleanup admission. Inspection has no publication phase. Select `analysis_timeout_ms` in either MCP operation or
|
||||
`--analysis-timeout-ms` in either CLI command for slower analysis. Current
|
||||
results retain the actual budget; an absent historical value means unknown.
|
||||
Extraction publication and its 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
|
||||
@@ -168,10 +174,18 @@ tree semantics, vulnerability scanning, emulation or hardware runtime capture.
|
||||
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.
|
||||
- Analysis timeout recovery names the selected budget and the analysis control,
|
||||
not the later publication control. Keep the client call timeout above analysis,
|
||||
publication and cleanup headroom; keep the input/range/question unchanged.
|
||||
Resolve any reported incomplete cleanup before retrying. Raising wall time
|
||||
does not raise fixed CPU, memory, report, diagnostic or input limits.
|
||||
- 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.
|
||||
Exit status 0 is not an empty result: a missing, empty, malformed or
|
||||
oversized report fails with `unreadable_output`, its `report_state`, the
|
||||
command, exit status and captured output. REA does not retry automatically.
|
||||
Diagnostic output is bounded with exact captured byte counts.
|
||||
- Default staging budget: **256 MiB** and **10,000 entries**, configurable using
|
||||
`max_output_bytes` / `max_output_files` (CLI `--max-output-bytes` /
|
||||
|
||||
@@ -24,6 +24,6 @@ Use `get_evidence_bundle` with `detail="summary"` and `filters={"evidence_id":"P
|
||||
|
||||
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.
|
||||
Frida scripts execute inside the selected target with that process's memory, filesystem, and network authority. Local device lookup waits 1000 ms. This release has no runtime override for that lookup; another REA timeout does not raise it. Remote endpoints do not use that lookup. Message capture is bounded to 16 MiB and reports truncation. Metadata, type, and text field caps, and the JSON node cap, are also fixed. Evidence names a cap when that observation actually dropped data. This release has no runtime override for those capture caps. Script source is not stored in Evidence; its selected path and SHA-256 digest are. For a file, `source_sha256` identifies the original selected bytes. Invalid UTF-8 continues to use replacement decoding; Evidence then records that limitation and `raw_result.source_representation` with the encoding, decoding mode, and `loaded_source_sha256` of the UTF-8 string passed to Frida. Valid UTF-8 files and inline scripts do not need this additional representation fact. Evidence retains non-authentication target selection such as device or endpoint, mode, program or PID, and spawn arguments. Authentication values remain excluded. Results report the observed session and messages, while unsupported platform metadata remains unknown. A request cancelled before a Frida operation starts has no provider effects. If cancellation arrives during a native Frida call, REA waits for that call to return, then closes any session it created and returns the observed session as a partial observation. A cancelled script load on an existing session releases only its new script before queued operations can run; the session and previously loaded scripts remain available. If cancellation is observed when the native call returns, partial Evidence retains the source identity and captured messages even if that call rejects, including messages emitted during awaited cleanup. The caller's cancellation reason remains primary and a native rejection is retained as a sanitized diagnostic. A failure already observed before cleanup stays primary if cancellation arrives during cleanup. The cancellation cutoff is REA's observation of native completion, rather than a claim about unobservable native event order. `script_id` is REA's load-attempt identity. When creation rejects without returning a handle, `script_cleanup: "no_handle"` means REA acquired no handle to unload; it does not prove that the engine performed no work. Once the provider commits a successful load, later request cancellation does not unload that script; use `unload_frida_script` to release it. If script cleanup fails, the script remains owned and a paused target cannot resume until the pending instrumentation is released. Queued script loads, resumes, and unloads check cancellation before dispatching native effects. Cancellation Evidence separately reports whether a target resume was observed, whether instrumentation cleanup completed, and that final target liveness remains unknown. REA does not kill the target. Remote discovery retains its observations and reports a separate cleanup error if the temporary connection cannot be removed.
|
||||
|
||||
The [Frida Core API](https://frida.re/docs/frida-core-api/) documents device management, sessions, and script loading; the [JavaScript API](https://frida.re/docs/javascript-api/) documents target-side instrumentation. [Luma](https://luma.frida.re/) is Frida's standalone GUI; REA does not automate or control it. `npm run verify:frida` requires a Linux host with the optional Frida binding and uses a short-lived local Node.js fixture created by the verifier. Add `-- --address HOST:PORT --pid PID` to run the separate remote attach lane against a caller-selected target. Mock tests do not establish real device/server compatibility.
|
||||
@@ -0,0 +1,166 @@
|
||||
# Static CUDA and HIP code objects
|
||||
|
||||
`inspect_gpu_code_objects` answers which GPU targets and kernel declarations a
|
||||
local artifact carries. It reads ELF/PE sections, standalone CUDA fatbins,
|
||||
CUBIN/PTX and Clang HIP bundles, including CCOB v1/v2/v3. It neither executes the
|
||||
artifact nor invokes CUDA/ROCm tools. GPU execution, SASS disassembly and host
|
||||
launch correlation remain outside coverage.
|
||||
|
||||
Start with a target inventory:
|
||||
|
||||
```json
|
||||
{ "path": "/artifacts/library.so", "view": { "collection": "targets" } }
|
||||
```
|
||||
|
||||
Target rows aggregate inventoried payloads and distinguish an unrequested kernel
|
||||
analysis from a complete or partial one. `objects` pages expose exact object
|
||||
IDs, compression declarations and encoded/header locations. Fields, exact
|
||||
filters, batch IDs and stable pagination select the facts delivered to the
|
||||
caller. IDs are positional within the recorded artifact SHA-256. Selecting `object_ids`
|
||||
in a new inspection requires `expected_sha256` from that inventory; a changed
|
||||
file is rejected before parsing selected payloads.
|
||||
|
||||
`target` is the inventory declaration used for selection; `payload_target` is
|
||||
the independently observed inner declaration when available. Object pages keep
|
||||
both values, their kind, `target_consistency` and inspection coverage even with
|
||||
selected fields.
|
||||
Conflicting base architectures retain both values, mark object/report/target
|
||||
coverage partial and annotate the affected kernels. CUBIN flags establish a base
|
||||
architecture: `base-only` explicitly leaves feature-profile agreement unknown,
|
||||
including `a` variants. A standalone declaration is `single-source`, and
|
||||
unexamined payloads remain `unexamined`. An exact AMDGPU target is normalized at
|
||||
its note owner for comparison with a Clang bundle declaration; raw values remain
|
||||
intact. Unresolved feature comparisons stay `unknown`.
|
||||
|
||||
`cuda_target_header` retains the OS ABI, normalized raw `e_flags` and exact
|
||||
header location. CUDA OS ABI `0x33` and the observed `0x41` flags layout use
|
||||
different architecture fields; they are decoded at one ABI-aware owner.
|
||||
Unrecognized layouts keep the header and an unknown target instead of
|
||||
inventing an SM label. Header provenance is validated against its CUBIN object.
|
||||
|
||||
Target filters select inventory declarations. An unselected payload's inner
|
||||
target remains unexamined; an empty filtered result does not establish that
|
||||
no enclosed code declares that target. Discovering every inner declaration
|
||||
requires decoding those payloads.
|
||||
|
||||
HIP IDs with one or two separators before the architecture retain the declared
|
||||
target. If a recognized AMDGPU bundle ID does not expose a target, the same
|
||||
bounded note-discovery owner used for standalone AMDGPU files establishes it
|
||||
before filtering. Those directory/note reads share the inspection work budget;
|
||||
successive queries can select the target returned by inventory.
|
||||
|
||||
Decode selected targets and return a kernel page in the same call:
|
||||
|
||||
```json
|
||||
{
|
||||
"path": "/artifacts/library.so",
|
||||
"analysis": "kernels",
|
||||
"targets": ["sm_100"],
|
||||
"view": {
|
||||
"collection": "kernels",
|
||||
"names": ["kernel_name"],
|
||||
"fields": [
|
||||
"name",
|
||||
"parameter_count",
|
||||
"parameter_bytes",
|
||||
"parameters",
|
||||
"registers",
|
||||
"shared_bytes"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Only selected payloads are decoded. Other inventory entries remain present with
|
||||
`not-selected` states, and overall payload coverage remains partial. An empty
|
||||
kernel page proves no matching retained fact; it does not establish that an
|
||||
unexamined payload contains no kernel. Missing fields remain null.
|
||||
|
||||
Kernel representations have different meanings:
|
||||
|
||||
- PTX reports parameter declarations and virtual registers. Shared bytes cover
|
||||
supported static declarations inside that entry; they do not establish module
|
||||
shared memory, dynamic allocation or physical device resources.
|
||||
Scalar register declarations count each bare or percent-prefixed name and
|
||||
each parameterized range. Unsupported declaration forms or overflowing totals
|
||||
retain an unknown count and partial decoding coverage. Unsupported parameter
|
||||
layouts and unknown shared-memory declarations likewise retain their known
|
||||
facts, explicit limitations and partial coverage through retained pages.
|
||||
- CUBIN identifies CUDA entry symbols and reads numeric `nv.info` records and
|
||||
native section declarations. Global register declarations also cover compiler
|
||||
versions that leave the older text-section register field empty.
|
||||
- AMDGPU reads v3+ MessagePack notes. Argument counts include hidden ABI arguments
|
||||
when present; SGPR/VGPR counts and fixed group/private segment sizes retain
|
||||
their declared meanings. Legacy YAML metadata remains unsupported.
|
||||
|
||||
Each selected PTX payload becomes a retained UTF-8 text artifact with a SHA-256,
|
||||
byte length and source coordinates. It is omitted from compact replies. Read it
|
||||
with `inspect_analysis_view` and the parent Evidence ID returned by the compact
|
||||
receipt:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": { "kind": "retained-evidence", "evidence_id": "ev_..." },
|
||||
"view": {
|
||||
"kind": "gpu-code-objects",
|
||||
"collection": "ptx",
|
||||
"object_id": "...",
|
||||
"offset": 0,
|
||||
"limit": 4096
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Text offsets use UTF-16 code units and must fall on Unicode scalar boundaries.
|
||||
Complete Evidence retains the selected text; `export_evidence_bundle` provides
|
||||
its portable source record. Historical pages never reopen the input file.
|
||||
|
||||
A location with `container_id: null` uses original file offsets. Other locations
|
||||
use that inventoried object's decoded byte coordinates. Follow its parent,
|
||||
encoded location and digest to trace decompressed metadata back to a native
|
||||
section and the original file. Decoded offsets are never presented as physical
|
||||
file offsets.
|
||||
|
||||
The CLI uses the same service and contracts:
|
||||
|
||||
```sh
|
||||
rea inspect-gpu-code-objects /artifacts/library.so --analysis kernels \
|
||||
--targets '["sm_100"]' --detail summary \
|
||||
--view '{"collection":"kernels","names":["kernel_name"]}' \
|
||||
--evidence_output /analysis/library-gpu.evidence.json --json
|
||||
```
|
||||
|
||||
A full-file SHA-256 always streams every byte. Inventory then reads bounded
|
||||
native directories and bundle headers; CCOB requires decompression to discover
|
||||
its inner directory. Kernel analysis reads selected payloads. `bytes_read`
|
||||
includes hashing and subsequent descriptor reads, so this is not a header-only
|
||||
hashing workflow.
|
||||
|
||||
CUDA raw LZ4 blocks and Zstd, and CCOB zlib/Zstd are supported. Unknown versions
|
||||
or codecs retain declarations with explicit limitations. Lengths are checked
|
||||
before decoding, and CCOB's truncated MD5 is verified against decoded bytes.
|
||||
Resource limits are one active inspection, 128 MiB per input/output buffer,
|
||||
512 MiB of payload input, decoded output and AMD note-read work per inspection,
|
||||
and 16 MiB retained facts including selected PTX. Payload work is reserved before
|
||||
reading or allocating; a capacity refusal does not reread an aliased payload.
|
||||
Native tables and decoded section names each have a 16 MiB structural budget;
|
||||
AMDGPU ELF note discovery admits at most 8 MiB of source note bytes, with
|
||||
bounded depth and container/string allocations. Standalone AMD targets are read
|
||||
from those notes before target selection; selected kernel analysis reuses the
|
||||
same parsed declarations. Pages have a
|
||||
1 MiB response budget. Resource refusals and interrupted observations preserve
|
||||
known facts and explicit uncertainty.
|
||||
|
||||
CUDA ELF parsing additionally shares a 262,144 record/symbol visit limit,
|
||||
128 MiB of cumulative metadata section reads, and a 16 MiB serialized-size
|
||||
accounting budget for temporary index facts. These limits are checked before
|
||||
index growth; they are not claims about JavaScript heap size. Equivalent scoped
|
||||
metadata byte ranges and repeated equal register declarations are coalesced;
|
||||
conflicting values remain unknown. Parameter sections are parsed once per ELF.
|
||||
|
||||
Missing CUBIN symbol tables or unresolved section names produce `partial`
|
||||
object, report and target coverage even when some kernel facts survive. AMD note
|
||||
failures preserve earlier successfully parsed declarations and the original
|
||||
failure reason. Standalone PTX recognition tries a small header first, then
|
||||
continues within the existing 16 MiB text budget when leading comments or
|
||||
whitespace obscure its directives; admitted full-file probe bytes are reused.
|
||||
+10
-1
@@ -41,6 +41,15 @@ rea function /absolute/path/to/program main --json
|
||||
rea decompile /absolute/path/to/program main --json
|
||||
```
|
||||
|
||||
If the registration cannot be read or validated, provider diagnostics retain its
|
||||
selected `registration_path` and the configuration owner's setting/constraint
|
||||
facts in `configuration_details.settings`, plus `configuration_remediation`.
|
||||
`configured` means a path was selected, not that it is valid or an IDA connection
|
||||
was established; failed registrations remain unavailable. Correct
|
||||
`REA_IDA_MCP_CONFIG` in the next CLI invocation's environment or the MCP server's
|
||||
launch environment. Restart/reconnect that server after changing its environment;
|
||||
an export in another shell does not update a running server.
|
||||
|
||||
Open the **original input binary** in REA, not an `.idb` or `.i64` database. Its SHA-256 must match IDA's recorded input hash. REA checks the attached identity and image base around each analysis request. A mismatch or target switch fails with recovery guidance. The original input must remain readable by REA; WSL can use its mounted alias while the GUI runs on Windows. Attached profiles, including native mode, refuse universal Mach-O inputs at admission: every slice shares the recorded whole-file hash, so REA cannot verify which slice the GUI loaded. Open a thin file extracted with `lipo -thin` in both IDA and REA, or use headless mode, which analyzes the selected slice.
|
||||
|
||||
REA's close operation releases its MCP connection or proxy. It never saves or closes the existing GUI database. External edits remain visible because results are live and are not replayed from snapshots. These checks do not lock the GUI or prove that the database is unpatched.
|
||||
@@ -133,7 +142,7 @@ Use a package version that actually includes this adapter; repository main can b
|
||||
{"name":"close_binary","arguments":{}}
|
||||
```
|
||||
|
||||
Opening an MCP target starts its selected provider session; headless opening waits for auto-analysis. Set the agent's MCP request deadline long enough for the target. The registration's optional `timeoutMs` defaults to 300000 for upstream requests. An upstream SDK request that reaches this limit returns `provider_timeout` with its operation and actual request budget. A freshly opened headless worker can briefly report `status: "busy"` from `server_health`; REA re-reads health every 100 ms until the worker answers, the caller cancels, or `timeoutMs` has elapsed since the first read. Each health request is capped by the time remaining in that overall wait, so a stalled read cannot extend the readiness deadline by another full request timeout. Expiry while the worker is still busy produces a retryable `provider_timeout`; no further read is started after the deadline. That error names the busy tool from the last observation, or `unknown` when the worker reported none or a value that is not tool-name-shaped. If a health request itself consumes the remaining wait budget, the same last-busy timeout is returned with the stalled request's captured output. Cancellation during the wait produces `cancelled`. Any other unexpected health payload, including a busy payload with an invalid shape, remains `unreadable_output`. Cancellation drains the current upstream request before cleanup; it does not force-stop GUI analysis. An open request that times out without a completed response retains the private workspace because worker inventory alone cannot prove the request has stopped. `binary_session` reports actual tool availability. Repeated doctor/setup calls are unnecessary when the registration already works.
|
||||
Opening an MCP target starts its selected provider session; headless opening waits for auto-analysis. Set the agent's MCP request deadline long enough for the target. The registration JSON named by `REA_IDA_MCP_CONFIG` has an optional `timeoutMs` integer from 1 to 2147483647. Omitted means 300000. REA applies an edited value on the next IDA connection after it re-reads that file; an already open session keeps the timeout it connected with. Changing the `REA_IDA_MCP_CONFIG` path itself is read at process start. An upstream SDK request that reaches this limit returns `provider_timeout` naming the effective milliseconds and `timeoutMs`. A shorter inner request is the time remaining inside that ceiling, and the error names both when they differ. A freshly opened headless worker can briefly report `status: "busy"` from `server_health`; REA re-reads health every 100 ms until the worker answers, the caller cancels, or `timeoutMs` has elapsed since the first read. Each health request is capped by the time remaining in that overall wait, so a stalled read cannot extend the readiness deadline by another full request timeout. Expiry while the worker is still busy produces a retryable `provider_timeout`; no further read is started after the deadline. That error names the busy tool from the last observation, or `unknown` when the worker reported none or a value that is not tool-name-shaped. If a health request itself consumes the remaining wait budget, the same last-busy timeout is returned with the stalled request's captured output. Cancellation during the wait produces `cancelled`. Any other unexpected health payload, including a busy payload with an invalid shape, remains `unreadable_output`. Cancellation drains the current upstream request before cleanup; it does not force-stop GUI analysis. An open request that times out without a completed response retains the private workspace because worker inventory alone cannot prove the request has stopped. `binary_session` reports actual tool availability. Repeated doctor/setup calls are unnecessary when the registration already works.
|
||||
|
||||
For guided registration, set `REA_IDA_MCP_CONFIG` before `rea setup --client <client>`. Setup includes that file reference in its reviewed plan and preserves it after approval; it does not copy upstream credentials into the agent configuration. For `ida` or `auto` selection, Codex/Kimi setup and doctor use the effective client registration's parsed `timeoutMs` (default 300000 ms) when recommending the agent's per-tool deadline. Existing positive client deadlines remain caller choices. `rea doctor --provider ida --json` validates the registration without starting IDA and explicitly leaves runtime compatibility and target binding for analysis.
|
||||
|
||||
|
||||
+13
-13
@@ -47,19 +47,19 @@ For runtime instrumentation, see the [Frida guide](./frida-instrumentation.md).
|
||||
|
||||
## Choose a guide
|
||||
|
||||
| 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) |
|
||||
| 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), [Python packages](python-packaged-applications.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).
|
||||
|
||||
@@ -24,6 +24,10 @@ Restart the agents named in the completion message. Quit Claude Desktop fully
|
||||
before approving, because a running app can overwrite the registration; on
|
||||
Windows, see [where Claude Desktop reads its configuration](client-configuration.md#claude-desktop).
|
||||
|
||||
During package resolution, npm may print a deprecation warning for `prebuild-install`
|
||||
from transitive native dependencies (such as Frida). This warning originates from
|
||||
the upstream dependency tree and does not affect REA or indicate setup failure.
|
||||
|
||||
For the latest published release, use `npx rea-agents@latest setup`.
|
||||
[Package-runner and global-installation options](#package-runners-and-global-installation)
|
||||
cover explicit versions, Bun, runtime requirements, and the curl wrapper.
|
||||
@@ -1189,8 +1193,10 @@ truncation markers. Darwin ownership-helper compilation failures also retain
|
||||
the compiler outcome, exit code or signal, and bounded stderr; a timed-out
|
||||
compiler remains distinguishable from a compiler that exited with an error.
|
||||
The helper compile deadline defaults to 120,000 ms; set
|
||||
`REA_SWIFTC_COMPILE_TIMEOUT_MS` to an integer between 1 and 2,147,483,647 when
|
||||
a busy host needs longer.
|
||||
`REA_SWIFTC_COMPILE_TIMEOUT_MS` to an integer between 1 and 2,147,483,647 in
|
||||
the environment that starts REA when a busy host needs longer. Restart REA to
|
||||
apply a change; the next ownership-helper compile uses the new value. A
|
||||
timeout names that effective deadline.
|
||||
On macOS, the Java prerequisite probe waits for this independently bounded
|
||||
preparation before starting its five-second command deadline. Caller cancellation
|
||||
still interrupts preparation, and failed helper cleanup remains owned for retry.
|
||||
|
||||
@@ -106,6 +106,15 @@ only reduces delivery; source selection reduces text acquisition and analysis.
|
||||
Explicit native provider or snapshot routing rejects `--source-path` rather
|
||||
than ignoring it.
|
||||
|
||||
ASAR header/index admission is a fixed 16 MiB / 16777216 bytes for this
|
||||
release. There is no runtime override. The archive index is read before any
|
||||
member can be selected, so `source_paths`, `--source-path`, `detail:
|
||||
"summary"`, `max_heap_mb`, and available host memory do not bypass or raise
|
||||
it. When the header exceeds that allowance, the failure names this budget.
|
||||
Analyze an extracted application directory, which does not admit an ASAR
|
||||
header, or supply an archive whose header fits. Repeating the unchanged
|
||||
request fails the same way.
|
||||
|
||||
## Read the analysis
|
||||
|
||||
`analyze_javascript_application` returns the complete analysis Evidence by
|
||||
@@ -172,7 +181,8 @@ for the tool-result contract.
|
||||
|
||||
Use MCP `detail: "summary"` for a large application, then read selected views of
|
||||
the retained analysis. Summary changes delivery only. To reduce source parsing,
|
||||
select exact [source paths](#select-sources-before-analysis).
|
||||
select exact [source paths](#select-sources-before-analysis). Source selection
|
||||
does not bypass ASAR header/index admission.
|
||||
|
||||
If a complete response exceeds the transport budget, use its retained Evidence
|
||||
ID for a summary, module page, or item, or export the bundle. See
|
||||
@@ -371,7 +381,15 @@ Recognized literal module-table bootstraps also support bounded lexical
|
||||
substitution through module exports, import helper bodies, local wrapper calls,
|
||||
returned closures, object spreads, and callback parameters. Recovered Electron
|
||||
paths retain source ranges, module identities, literal channels and branch
|
||||
conditions as static candidates. Unknown spreads, reassigned bindings, accessors,
|
||||
conditions as static candidates. A channel the IPC call site itself
|
||||
determines, such as a local constant, resolves that call's observation rather
|
||||
than adding a second one. A channel or registration handler supplied through
|
||||
a wrapper argument is a candidate beside the call's own unresolved
|
||||
observation, because callers outside the traced paths may pass other values.
|
||||
A wrapper call that is both its own entry and reached through another entry
|
||||
is recorded once when both paths find the same facts; calls that supply
|
||||
different handlers or channels stay distinct.
|
||||
Unknown spreads, reassigned bindings, accessors,
|
||||
dynamic channels and unsupported syntax do not become exact implementations.
|
||||
This pass neither executes the bundle nor proves that runtime guards pass.
|
||||
An ambiguous or unresolved handler retains its channel registration but does
|
||||
@@ -589,8 +607,9 @@ The default semantic capacities are 100000 nodes across the application and
|
||||
`--max-semantic-nodes-per-file`), each from 1 to 1000000. The per-file offer is
|
||||
also bounded by the remaining application capacity. Raising these controls does
|
||||
not bypass worker heap, execution deadline or parent result admission. Truncated
|
||||
coverage reports both effective node ceilings; omitted relationships remain
|
||||
unknown.
|
||||
coverage lists both effective ceilings, `max_semantic_nodes` and
|
||||
`max_semantic_nodes_per_file`. The limitation names only the ceiling that
|
||||
stopped retention. Omitted relationships remain unknown.
|
||||
|
||||
Unknown records have independent defaults of 100000 across the application and
|
||||
20000 per source. Select `max_semantic_unknowns` and
|
||||
@@ -598,8 +617,10 @@ Unknown records have independent defaults of 100000 across the application and
|
||||
`--max-semantic-unknowns-per-file`), each from 1 to 1000000. The parent offers the
|
||||
remaining capacity to the worker, and rejects excess records before adoption.
|
||||
Unknown admission happens before canonical identity and provenance construction.
|
||||
When capacity is exhausted, coverage is partial and truncated and names both
|
||||
effective unknown ceilings. `coverage.omitted_unknown_occurrences` counts examined
|
||||
When capacity is exhausted, coverage is partial and truncated. Coverage lists
|
||||
both effective unknown ceilings, `max_semantic_unknowns` and
|
||||
`max_semantic_unknowns_per_file`. The limitation names only the ceiling that
|
||||
stopped retention. `coverage.omitted_unknown_occurrences` counts examined
|
||||
emission occurrences by family and reason, including repeated emissions. It does
|
||||
not claim distinct discarded identities or count frontiers in unexamined source.
|
||||
Omitted unknown provenance and IDs are not retained. Existing source, node,
|
||||
@@ -612,12 +633,35 @@ checkpoint at its 8 MiB bound with the same 6x retention expansion used at
|
||||
admission. Earlier checkpoints are already charged to retained bytes; the
|
||||
remaining inventory does not multiply the reserve. Streamed file transfers keep the default 512 MiB
|
||||
allowance, and can grow with the parent's offered retention budget (8x byte
|
||||
expansion), up to 2 GiB. Individual records remain bounded to 8 MiB. The parent
|
||||
expansion), up to 2 GiB. Individual records remain bounded to 8 MiB. The 8 MiB
|
||||
record ceiling and the 2 GiB file maximum have no runtime override, and raising
|
||||
`max_heap_mb` does not raise them. The effective file ceiling follows the
|
||||
parent's offered result budget. On Node, a larger CLI/MCP process heap
|
||||
(`NODE_OPTIONS`, for example `--max-old-space-size=<MiB>`, after restarting that
|
||||
process) can raise it up to 2 GiB. Selecting fewer `source_paths` can also
|
||||
raise that effective allowance, because the reserve for remaining sources and
|
||||
earlier retained results reduce the offered budget. Neither change raises the
|
||||
record ceiling or the 2 GiB maximum. The parent
|
||||
still independently checks actual bytes, record overhead, digests and source
|
||||
identities before adopting results.
|
||||
|
||||
A source that exhausts the analyzer heap does not terminate the CLI/MCP
|
||||
process. Completed static facts are retained, other files can still be analyzed,
|
||||
process. On Node, the failure names `max_heap_mb` (CLI `--max-heap-mb`), the
|
||||
effective mebibytes, the inclusive range 128 to 16384, and the 1024 MiB
|
||||
default. A changed value applies on the next analysis, which starts a new
|
||||
worker. It does not change a worker that is already running and does not
|
||||
require restarting the REA server. On Bun, the same heap-exhaustion diagnostic
|
||||
is not attributed to that V8 old-space limit, because Bun ignores the flag.
|
||||
Raising `max_heap_mb` does not raise the parent result budget,
|
||||
the transfer record ceiling, the 2 GiB transfer file maximum, the CLI/MCP
|
||||
process heap, or fixed parser limits. The parent result budget follows that
|
||||
process heap. On Node, set `NODE_OPTIONS` (for example `--max-old-space-size=<MiB>`)
|
||||
in the environment that starts the CLI or MCP server, then restart that
|
||||
process, to raise the parent heap and the result budget. A completed static
|
||||
checkpoint that does not fit the parent's remaining heap names that parent
|
||||
process heap. Increasing `max_heap_mb` does not raise it. On Node, the same
|
||||
`NODE_OPTIONS` restart can raise the parent heap and admit the checkpoint.
|
||||
Completed static facts are retained, other files can still be analyzed,
|
||||
and unexamined semantic relationships remain explicit unknowns. The parent
|
||||
also checks transfer expansion and accumulated results against its remaining
|
||||
heap before accepting semantic facts. A resource-limited result has partial
|
||||
|
||||
@@ -129,10 +129,15 @@ equivalence remain unknown. No network fetching occurs.
|
||||
|
||||
## Resource policy and verification
|
||||
|
||||
Each operation uses one worker, a 1 GiB address-space ceiling and a 120-second
|
||||
deadline; it accepts up to 64 MiB of total input across all selected files and
|
||||
128 MiB/10000 entries of staged
|
||||
output, with 8 MiB per diagnostic/report stream. Exceeding a limit is an explicit
|
||||
Each operation uses one worker, a 1 GiB address-space ceiling and a 120000 ms
|
||||
deadline. That deadline has no runtime override: raising `analysis_timeout_ms`
|
||||
or `max_heap_mb` does not raise it. An unchanged retry may hit the deadline
|
||||
again. The operation accepts up to 64 MiB of total
|
||||
input across all selected files and 128 MiB/10000 entries of staged output,
|
||||
with 8 MiB per diagnostic/report stream. A `provenance.json` over that report
|
||||
allowance names the fixed limit: this release has no runtime override, and
|
||||
raising `max_heap_mb` or `analysis_timeout_ms` does not raise it. Malformed
|
||||
reports stay distinct from that size refusal. Exceeding a limit is an explicit
|
||||
failure with rollback. Selected inputs beyond the total input allowance return a
|
||||
non-retryable `resource_constraint` with `resource: "file-size"` and
|
||||
`reported_limits.maximum_input_bytes`/`remaining_input_bytes`; input that is not
|
||||
|
||||
@@ -106,7 +106,11 @@ nodes. REA evaluates compatible static candidates conservatively:
|
||||
that disagreement. If a mapped candidate's digest is unavailable and no
|
||||
mapped content match is known, the comparison remains `unknown`.
|
||||
6. Missing authorization mappings and incomplete or truncated input coverage
|
||||
remain unknown or truncated rather than becoming absence claims.
|
||||
remain unknown or truncated rather than becoming absence claims. A runtime
|
||||
location with no automatic artifact-root or caller-declared mapping into
|
||||
any layer, and no unique content match, is `unknown` with
|
||||
`no-authorized-location-mapping`, with or without captured bytes. Only a
|
||||
mapped location can be `unmatched` with `no-static-content-match`.
|
||||
|
||||
Every successful cross-layer `observed_as` edge has
|
||||
`authority: cross-layer-reconciliation` and `state: inferred`. The underlying
|
||||
|
||||
+12
-10
@@ -28,17 +28,19 @@ JEB service is reachable or that a project is open; use the existing
|
||||
MCP `binary_session` probes the live JEB service and its advertised tool catalog.
|
||||
Availability is reported per operation: a reachable headless client can support
|
||||
inspection and decompilation while refusing `open_jeb_project`. Catalog discovery
|
||||
uses one 60-second deadline across connection and pagination; a responsive server
|
||||
cannot keep discovery running indefinitely by returning more pages.
|
||||
is one deadline across connection and pagination; a responsive server cannot keep
|
||||
discovery running indefinitely by returning more pages.
|
||||
|
||||
Each upstream tool call has an absolute 60-second request deadline by default.
|
||||
Set `REA_JEB_MCP_TIMEOUT_MS` to a positive decimal number of milliseconds to
|
||||
select a different per-request budget, for example `REA_JEB_MCP_TIMEOUT_MS=300000`
|
||||
for a five-minute decompilation. This budget starts after discovery and applies
|
||||
to each individual `tools/call`; it does not extend the separate catalog deadline
|
||||
or establish one end-to-end deadline across a whole CLI or MCP operation. A
|
||||
request that reaches its budget returns a typed timeout, while caller
|
||||
cancellation remains a cancellation.
|
||||
Catalog discovery and each `tools/call` share `REA_JEB_MCP_TIMEOUT_MS`. Set it
|
||||
in REA's launch environment to an integer from 1 to 2147483647 milliseconds,
|
||||
for example `REA_JEB_MCP_TIMEOUT_MS=300000` for a five-minute budget. Omitted
|
||||
means the pinned MCP client SDK default of 60000 ms (`@modelcontextprotocol/client`
|
||||
2.3.1). Restart REA and reconnect to apply a change. Raising the setting raises
|
||||
both phases. It does not make one end-to-end deadline across a whole CLI or MCP
|
||||
operation: discovery and each `tools/call` each get that budget. A request that
|
||||
reaches its budget returns a typed timeout naming the phase and the effective
|
||||
milliseconds, while caller cancellation remains a cancellation. Allow execution,
|
||||
cleanup, and delivery headroom in the outer MCP client deadline.
|
||||
|
||||
Earlier verification used JEB 5.48.0 (Linux x64, licensed build) serving `jeb-mcp-server` 1.3.0 over streamable HTTP. The official Linux x64 CE build `5.48.0.202610071539` was also verified through real CLI and production stdio MCP native-code workflows; see the [Linux CE audit](../experiments/analysis-efficiency/jeb-linux-native.md) for measurements and limits. CE verification does not establish licensed/Demo Android decompilation or GUI behavior.
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ The background export belongs to the session. `close_binary`, or the end of a CL
|
||||
|
||||
The assembly label index is scanned once per export reader. Cancelling a request stops its wait without interrupting other readers; closing the session aborts and drains the shared scan before releasing its files.
|
||||
|
||||
Regex procedure and string search uses ECMAScript Unicode matching in a cancellable worker with a five-second matching deadline. Literal matching remains the default. Cancellation or a matching deadline leaves the session available.
|
||||
Regex procedure and string search uses ECMAScript Unicode matching in a cancellable worker with a five-second matching deadline and a worker old-generation heap. Literal matching remains the default. Cancellation or a matching deadline leaves the session available. This release has no runtime override for that deadline. The worker requests 128 MiB. A positive Node.js `--max-old-space-size` on the process that starts REA, including `NODE_OPTIONS`, overrides that request and sets the effective heap. `--max-old-space-size-percentage` takes precedence over that flag in either order. REA does not turn the percentage into a MiB, so the effective heap stays unestablished instead of the 128 MiB request or the absolute flag. The reported `NODE_OPTIONS` value is the process initial environment when that block can be read. A later edit to the environment is not the value Node applied, and an unreadable initial value leaves the effective heap unestablished. The launch Node options are the initial command line on Linux when that buffer still has a program entry, not a later edit to `process.execArgv`. A preload can clear that array after V8 has applied the flags. Setting `process.title` or `--title` overwrites the command line, so a buffer without a program entry leaves the effective heap unestablished. `--env-file` or `--env-file-if-exists` can supply `NODE_OPTIONS` when the initial environment has none. That file is not part of the initial environment block, so the effective heap stays unestablished instead of the 128 MiB request. An initial `NODE_OPTIONS` is still used, because Node does not let the file replace it. A positive `--max-heap-size`, including the underscore form and launch `NODE_OPTIONS` on Node versions that allow it, sets the total heap rather than the old generation and can be lower than the 128 MiB request. The effective old generation stays unestablished while that value is in effect. A zero or empty value clears it. `--experimental-config-file` or `--experimental-default-config-file` can set `nodeOptions`, including a heap percentage, from a file that is not read back. The effective heap stays unestablished when either flag is present, including when an absolute `--max-old-space-size` is also on the command line or in the recovered `NODE_OPTIONS`. Node accepts the config path as `=` or the next argument.
|
||||
|
||||
Single-function subprocess output and each cached source facet share a 16 MiB buffered-text capacity. Cached spans are checked before allocation; larger text remains in the local export and the error identifies the file and range. `analyze_function` initially returns the complete dossier, which can still be large; later retained views do not remove that first transfer. Prefer the individual text tools for a focused question.
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ rejects selected summary before analysis; complete delivery remains available.
|
||||
|
||||
Complete `inspect_managed_members` delivery always includes the assembly-wide
|
||||
`member_refs` and `exported_types`, which `type_names` does not narrow, so even
|
||||
one selected or unmatched type can return megabytes. Select
|
||||
one selected or unmatched type can return megabytes. In MCP, select
|
||||
`{"path":"/absolute/path/Assembly.dll","type_names":["Namespace.Type"],"detail":"summary"}`
|
||||
to keep the complete source in the session and receive identity, metadata
|
||||
status, the selection with its unmatched names, coverage/issues, the separate
|
||||
@@ -115,6 +115,49 @@ literal pool's own coverage. Older Evidence that never examined exported types
|
||||
or user strings reports a null count and refuses those pages rather than
|
||||
returning an empty one.
|
||||
|
||||
#### CLI summary and saved member rows
|
||||
|
||||
The CLI accepts the same `complete` and `summary` detail choices. Omitted or
|
||||
`--detail complete` returns complete Evidence. To receive a summary, choose a
|
||||
new Evidence bundle destination so its original complete parent remains
|
||||
available after the command exits:
|
||||
|
||||
```bash
|
||||
rea inspect-managed-members /absolute/path/Assembly.dll --type Namespace.Type \
|
||||
--detail summary --evidence-bundle /absolute/path/evidence/members.json --json
|
||||
```
|
||||
|
||||
`--evidence-bundle` writes the complete original Evidence in REA's canonical
|
||||
bundle format. Its parent directory must exist, and it never replaces an
|
||||
existing path. Relative paths resolve against the command's working directory.
|
||||
The option also works with complete delivery when a saved bundle is useful.
|
||||
Summary without a destination is rejected before analysis. A publication failure
|
||||
returns a typed error with the completed Evidence under
|
||||
`details.partial_observation`; it does not report successful summary delivery.
|
||||
Cancellation before publication prevents the new output. Once atomic
|
||||
publication has started, it can complete despite cancellation; a cancelled
|
||||
delivery then retains the committed path and byte count under
|
||||
`details.diagnostics.evidence_bundle`.
|
||||
|
||||
Copy `normalized_result.parent_evidence_id` from the summary into the
|
||||
`source.evidence_id` field of the `managed-members` request above, then save that
|
||||
small request as `members-page.json` and run:
|
||||
|
||||
```bash
|
||||
rea inspect-analysis-view /absolute/path/evidence/members-page.json \
|
||||
--evidence-bundle /absolute/path/evidence/members.json --json
|
||||
```
|
||||
|
||||
The view command authenticates the selected bundle and resolves that exact
|
||||
parent ID. It does not reopen the assembly, so the original target may have
|
||||
been moved or removed. Subsequent calls can select another collection or use
|
||||
the returned `coverage.next_offset` to continue the same collection. An inline
|
||||
source already includes its parent and cannot also select `--evidence-bundle`.
|
||||
|
||||
Summary changes delivery, while type selection still controls decoding and the
|
||||
same inspection resource limits apply. Each separate CLI page reads and
|
||||
authenticates the saved bundle; the full source is retained on disk.
|
||||
|
||||
## Shipped scope
|
||||
|
||||
The canonical parser admits PE/CLI bytes and their metadata/CIL without loading
|
||||
@@ -622,6 +665,9 @@ which managed methods executed or how the CLR resolved them.
|
||||
|
||||
Managed member comparisons report a `metadata` dimension when an observed
|
||||
MethodDef flags or implementation flags value differs, including accessibility
|
||||
or synchronization changes. This is separate from the CIL/signature matching
|
||||
tiers: identical instructions do not establish unchanged method metadata. The
|
||||
reported difference is static metadata evidence, not proof of runtime behavior.
|
||||
or synchronization changes. Observed method-body `init_locals` and `max_stack`
|
||||
differences also contribute to `metadata`, even when CIL decoding is incomplete.
|
||||
An unavailable header value keeps body coverage unknown rather than establishing
|
||||
equality or a difference. These comparisons are separate from the CIL/signature
|
||||
matching tiers: identical instructions do not establish unchanged method metadata.
|
||||
The reported difference is static metadata evidence, not proof of runtime behavior.
|
||||
+56
-20
@@ -234,11 +234,14 @@ The destination changes only when a complete export is atomically published.
|
||||
|
||||
Clients that explicitly configure a larger receive buffer can set the REA
|
||||
server's `REA_MCP_MAX_RESPONSE_BYTES` environment variable to the same byte
|
||||
count. This setting must be a safe decimal integer at least 10485760; REA
|
||||
reserves 1024 bytes for the envelope. Raising it restores complete inline
|
||||
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.
|
||||
count. This setting must be a safe decimal integer at least 10485760 (10 MiB);
|
||||
REA reserves 1024 bytes for the envelope. The value is read when the REA
|
||||
process starts, so a change requires a restart and a matching client receive
|
||||
buffer. Raising it restores complete inline delivery for responses that fit
|
||||
that buffer. It does not raise REA's reserved single-string limit, which is
|
||||
1024 UTF-16 code units below Node's single-string ceiling, and it does not
|
||||
raise that Node ceiling. It does not change analysis coverage or retained
|
||||
content. Ordinary responses keep their existing complete result contract.
|
||||
|
||||
### Error recovery and deadline ownership
|
||||
|
||||
@@ -329,7 +332,7 @@ 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
|
||||
identity field, entities, documents for non-entity reads, 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).
|
||||
@@ -352,10 +355,41 @@ application and semantic coverage. The result carries a digest of the selected
|
||||
facts. Actual serialized size determines MCP transport admission: reduce the
|
||||
page size or export retained Evidence if the view is too large.
|
||||
|
||||
`compare_source_to_bundle` accepts the committed historical graph inline or as
|
||||
`reference: {"kind":"file","path":"/absolute/reference.json"}`. The shared
|
||||
reader checks resource bounds and the graph's root commitment on every read. File-backed
|
||||
comparison Evidence records `parameters.reference_source`: the exact
|
||||
`requested_path` and the reader's absolute selected `path`, preserving POSIX
|
||||
`..`/symlink semantics. Normalized comparison facts and mapping identities agree
|
||||
with inline input; Evidence IDs distinguish caller-selected file origins.
|
||||
Omitting `view` preserves the complete comparison. For a compact initial reply,
|
||||
select `view: {"kind":"summary"}` or a `source-to-bundle` page; the session retains
|
||||
the complete comparison before delivery. Later calls use `inspect_analysis_view`
|
||||
with the returned `parent_evidence_id`.
|
||||
|
||||
A `source-to-bundle` view selects `collection: "mappings"` or `"candidates"` with
|
||||
exact `source_paths`, `mapping_ids`, `statuses`, `fields`, `offset` and `limit`.
|
||||
Omitted filters select all; empty arrays select none. The default mapping fields
|
||||
include status, confidence, source digest/language and candidate/mapped counts.
|
||||
Candidate defaults include kind, score and confidence; request `signals` for exact
|
||||
supporting values. Mapping identity and `source_index` always remain; candidates
|
||||
also retain `current_node_id`, `candidate_index` and whether they were actually
|
||||
mapped. Indices refer to the complete comparison's item array and that item's
|
||||
candidate array. All classifications are computed before selection. The original
|
||||
`source_coverage` remains separate from page `coverage`; exhausting a page never
|
||||
turns unknown correspondence into absence or proves behavioral equivalence.
|
||||
|
||||
The CLI accepts the same reference-file alternative (relative paths resolve from
|
||||
the working directory). Save its complete `--json` Evidence, then use
|
||||
`inspect-analysis-view` with an `evidence-file` source and the same view. Neither
|
||||
adapter executes the target or repeats analysis for retained queries.
|
||||
|
||||
Completed `inspect_artifact` and atomic `inventory_artifact` Evidence also
|
||||
support summary and inventory views. A summary reports the manifest's expected
|
||||
counts separately from available record counts, observed entry kinds, inventory
|
||||
Evidence IDs and inspection coverage. An inventory view selects `nodes`,
|
||||
Evidence IDs, the inventory producer's traversal `source_coverage` and
|
||||
inspection coverage. Inspection coverage is `partial` when that traversal
|
||||
coverage is unknown. An inventory view selects `nodes`,
|
||||
`occurrences`, `edges`, or `integrity_contradictions`, with `offset` and `limit`
|
||||
defaulting to 0 and 64. For occurrences, optional `logical_paths` matches exact
|
||||
recorded strings: omission selects all available records; `[]` selects none.
|
||||
@@ -805,13 +839,13 @@ auto-analysis, bridge connection, and health readiness before returning analysis
|
||||
|
||||
These deadlines have different owners:
|
||||
|
||||
| Deadline | Owner and effect |
|
||||
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| MCP initialize | The client bounds transport/REA connection startup, before any target query. |
|
||||
| Hopper startup | REA allows 120,000 ms by default; `REA_HOPPER_STARTUP_TIMEOUT_MS` accepts decimal integers from 1–2,147,483,647 ms. Invalid values fail configuration validation. Startup failure is reported by the first provider query. |
|
||||
| Ghidra startup | REA allows 330,000 ms by default; `REA_GHIDRA_STARTUP_TIMEOUT_MS` accepts decimal integers from 1–2,147,483,647 ms. Invalid supplied values fail configuration validation. Startup failure is reported by the first provider query. |
|
||||
| Darwin swiftc helper | REA allows 120,000 ms by default for ownership-helper compilation; `REA_SWIFTC_COMPILE_TIMEOUT_MS` accepts decimal integers from 1–2,147,483,647 ms. Invalid values fail configuration validation. |
|
||||
| Individual tool call | The client bounds its wait, including cold engine startup. The pinned client SDK 2.3.1 defaults to 60,000 ms and can cancel earlier than REA's startup deadline. |
|
||||
| Deadline | Owner and effect |
|
||||
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| MCP initialize | The client bounds transport/REA connection startup, before any target query. |
|
||||
| Hopper startup | REA allows 120,000 ms by default; `REA_HOPPER_STARTUP_TIMEOUT_MS` accepts decimal integers from 1–2,147,483,647 ms. Invalid values fail configuration validation. Startup failure is reported by the first provider query. |
|
||||
| Ghidra startup | REA allows 330,000 ms by default; `REA_GHIDRA_STARTUP_TIMEOUT_MS` accepts decimal integers from 1–2,147,483,647 ms. Invalid supplied values fail configuration validation. Startup failure is reported by the first provider query. |
|
||||
| Darwin swiftc helper | REA allows 120,000 ms by default for ownership-helper compilation; `REA_SWIFTC_COMPILE_TIMEOUT_MS` accepts decimal integers from 1–2,147,483,647 ms. Invalid values fail configuration validation. Set it in the environment that starts REA and restart REA; the next ownership-helper compile uses the new value. |
|
||||
| Individual tool call | The client bounds its wait, including cold engine startup. The pinned client SDK 2.3.1 defaults to 60,000 ms and can cancel earlier than REA's startup deadline. |
|
||||
|
||||
For [Codex and Kimi registrations](client-configuration.md), setup supplies
|
||||
missing tool deadlines from the known provider allowance plus 120 seconds of
|
||||
@@ -819,7 +853,8 @@ operation headroom: 450 seconds with the default Ghidra allowance, or 2820
|
||||
seconds with `REA_GHIDRA_STARTUP_TIMEOUT_MS=2700000`. Positive caller-selected
|
||||
deadlines remain unchanged. Doctor reports an informational recommendation
|
||||
when a configured deadline is shorter than the known provider allowance. An
|
||||
explicit JEB upstream request budget also contributes to that allowance.
|
||||
explicit JEB upstream deadline (`REA_JEB_MCP_TIMEOUT_MS`, shared by catalog
|
||||
discovery and each tools/call) also contributes to that allowance.
|
||||
|
||||
For an already connected client using the pinned SDK, request options are the
|
||||
**second** argument of `callTool`:
|
||||
@@ -1018,14 +1053,15 @@ verify the compact advertisement through the same client boundary.
|
||||
|
||||
Some function-calling providers reject a request while any single tool's
|
||||
`parameters` schema exceeds a literal serialized size cap; Moonshot clients
|
||||
such as kimi-cli fail every request while the default catalog is attached
|
||||
such as kimi-cli have reported failures with the full catalog attached
|
||||
([#1484](https://github.com/morluto/rea/issues/1484)). Setting the server's
|
||||
`REA_MCP_INPUT_SCHEMA_PROFILE` environment variable to `compact` renders every
|
||||
advertised input schema within a 13,312-byte budget, measured to sit below
|
||||
`REA_MCP_INPUT_SCHEMA_PROFILE` environment variable to `compact` (the default)
|
||||
renders every advertised input schema within a 13,312-byte budget, measured to sit below
|
||||
Moonshot's observed cap (community measurements: a 13.7 KB schema is accepted
|
||||
while a ~15 KB one is rejected). The setting is read at startup; restart the
|
||||
server to apply changes, as with `REA_MCP_MAX_RESPONSE_BYTES`. The default
|
||||
value `full` keeps the complete advertisement unchanged. Compact presentation
|
||||
server to apply changes, as with `REA_MCP_MAX_RESPONSE_BYTES`. Explicitly select
|
||||
`full` to retain complete advertised input guidance and nested validation detail.
|
||||
Existing explicit profile choices are preserved. Compact presentation
|
||||
also reduces schemas whose expanded JSON tree exceeds ten levels, the limit
|
||||
reported by strict-depth MCP clients in [#2813](https://github.com/morluto/rea/issues/2813).
|
||||
WorkBuddy/CodeBuddy gateways have also rejected full REA catalogs with an
|
||||
|
||||
@@ -5,6 +5,11 @@ 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.
|
||||
|
||||
Unsupported GGUF versions remain refused. Their diagnostic preserves the four
|
||||
version bytes and both UINT32 interpretations with byte order unknown, rather
|
||||
than inferring big-endian from an unrecognized little-endian value. Little-endian
|
||||
v2/v3 and big-endian v3 remain supported; big-endian v2 remains refused.
|
||||
|
||||
```bash
|
||||
rea inspect-model-artifact /absolute/path/model.gguf --json
|
||||
rea inspect-model-artifact /absolute/path/model.safetensors --hash full --json
|
||||
|
||||
@@ -202,8 +202,38 @@ Function dossiers retain this same string evidence. Native call edges retain
|
||||
Hopper's partial `CallReference` classification and exact endpoints; detailed
|
||||
reference flags remain unavailable rather than being invented.
|
||||
Regex searches use ECMAScript Unicode syntax in a cancellable worker with a
|
||||
five-second matching deadline. Deadline or cancellation stops matching while
|
||||
leaving the Hopper API available. Literal mode retains Unicode casefold matching.
|
||||
five-second matching deadline and a worker old-generation heap. Deadline or
|
||||
cancellation stops matching while leaving the Hopper API available. This
|
||||
release has no runtime override for that deadline. The worker requests 128
|
||||
MiB. A positive Node.js `--max-old-space-size` on the process that starts
|
||||
REA, including `NODE_OPTIONS`, overrides that request and sets the effective
|
||||
heap. `--max-old-space-size-percentage` takes precedence over that flag in
|
||||
either order. REA does not turn the percentage into a MiB, so the effective
|
||||
heap stays unestablished instead of the 128 MiB request or the absolute flag.
|
||||
The reported `NODE_OPTIONS` value is the process initial environment when that
|
||||
block can be read. A later edit to the environment is not the value Node
|
||||
applied, and an unreadable initial value leaves the effective heap
|
||||
unestablished. The launch Node options are the initial command line on Linux
|
||||
when that buffer still has a program entry, not a later edit to
|
||||
`process.execArgv`. A preload can clear that array after V8 has applied the
|
||||
flags. Setting `process.title` or `--title` overwrites the command line, so a
|
||||
buffer without a program entry leaves the effective heap unestablished.
|
||||
`--env-file` or `--env-file-if-exists` can supply `NODE_OPTIONS`
|
||||
when the initial environment has none. That file is not part of the initial
|
||||
environment block, so the effective heap stays unestablished instead of the
|
||||
128 MiB request. An initial `NODE_OPTIONS` is still used, because Node does
|
||||
not let the file replace it. A positive `--max-heap-size`, including the
|
||||
underscore form and launch `NODE_OPTIONS` on Node versions that allow it,
|
||||
sets the total heap rather than the old generation and can be lower than the
|
||||
128 MiB request. The effective old generation stays unestablished while that
|
||||
value is in effect. A zero or empty value clears it.
|
||||
`--experimental-config-file` or `--experimental-default-config-file` can set
|
||||
`nodeOptions`, including a heap percentage, from a file that is not read
|
||||
back. The effective heap stays unestablished when either flag is present,
|
||||
including when an absolute `--max-old-space-size` is also on the command
|
||||
line or in the recovered `NODE_OPTIONS`. Node accepts the config path as
|
||||
`=` or the next argument.
|
||||
Literal mode retains Unicode casefold matching.
|
||||
|
||||
## Bounded static traces
|
||||
|
||||
@@ -298,13 +328,25 @@ markup, including UTF-8 and BOM-marked UTF-16 sources. Unidentified text and
|
||||
OpenStep plists, including a data-only value such as `<deadbeef>`, report
|
||||
`unknown` even when plutil decodes their values through an XML conversion.
|
||||
|
||||
Binary plist inspection reads the original bytes through an owned file descriptor,
|
||||
so conversion cannot erase control characters, fractional dates, negative zero,
|
||||
or the high word of a 128-bit integer. It accepts at most 64 MiB of input and
|
||||
reserves an estimated 64 MiB decode budget before parsing; this estimate is not
|
||||
a hard process-memory bound. A refused input reports non-retryable
|
||||
`resource_constraint` with `reported_limits.maximum_input_bytes`,
|
||||
`maximum_decoded_bytes` or, for nesting deeper than 128 levels,
|
||||
`maximum_nesting_depth`. These are fixed allowances: worker limits and host
|
||||
memory do not raise them, and the unchanged request fails the same way.
|
||||
Binary-source provenance records the `file` classification without claiming a
|
||||
`plutil` conversion.
|
||||
|
||||
A plist explicitly selected through the path input or as the active plist target
|
||||
reports an unreadable or malformed selection as `invalid_request`. A missing or
|
||||
unreadable default plist of another target reports `capability_unavailable`.
|
||||
Permission failures remain `access_denied`; output and cleanup failures retain
|
||||
their own error categories.
|
||||
|
||||
A plist decode refusal includes plutil's diagnostic from either output stream.
|
||||
A conversion refusal includes plutil's diagnostic from either output stream.
|
||||
`details.captured_output` retains bounded stdout/stderr excerpts, observed byte
|
||||
totals and exit status. `truncated: true` means those excerpts are incomplete.
|
||||
|
||||
@@ -444,6 +486,13 @@ complete observation.
|
||||
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.
|
||||
Conformance records preserve the raw three-bit `type_reference_kind`. Kinds
|
||||
0 and 1 identify direct and indirect nominal descriptors; kind 2 preserves
|
||||
the inline Objective-C class name and its source location. Kind 3 preserves
|
||||
an imported class binding or the local class-object address when available,
|
||||
but class metadata/name recovery requiring the Objective-C runtime remains
|
||||
partial. Unknown kinds retain the raw kind and reference location without
|
||||
being treated as absent or assigned a guessed type name.
|
||||
|
||||
So an external superclass resolves from its `_OBJC_CLASS_$_` bind (for
|
||||
example `NSObject`). The `pointer_fixups` coverage facet names the mechanism.
|
||||
@@ -518,8 +567,10 @@ cleanup. A later abort does not replace an earlier helper or output failure.
|
||||
Cleanup failures retain their runtime owner until a confirmed cleanup retry.
|
||||
|
||||
Scenarios accept caller-selected action lists and accessibility node counts.
|
||||
Individual waits cannot exceed the operation's 180-second deadline, and the
|
||||
complete scenario result has a 64 MiB output budget. Screenshots are scaled to
|
||||
One wait step stays capped at 180000 ms. That cap has no runtime override.
|
||||
The operation deadline is `native_ui_deadline_ms` (omitted means 180000 ms)
|
||||
and does not raise the wait-step cap. The complete scenario result has a
|
||||
64 MiB output budget. Screenshots are scaled to
|
||||
at most 2,048 pixels and captured only for the selected window. REA compiles one
|
||||
owned helper per scenario, removes its temporary compiler cache and stops its
|
||||
helper on cancellation. It does not launch or own the selected application. UI
|
||||
@@ -714,7 +765,13 @@ leap seconds) and out-of-range dates remain explicit unknowns. REA does not
|
||||
emulate CoreFoundation's normalization of overflowing calendar fields. Invalid
|
||||
dates returned by other decoders retain `{ "$plist_type": "date", "iso8601": null }`
|
||||
with a counted limitation. `inspect_plist` and Interface Builder decoding use
|
||||
the same projection.
|
||||
the same projection. Binary plist decoding refuses a reachable date whose marker
|
||||
is not `0x33`; date and numeric payloads must end before the offset table.
|
||||
Valid overlapping object records retain their independent source values. A valid `0x33` date is
|
||||
reported with an ISO-8601 timestamp only when its float64 seconds are exactly
|
||||
the canonical encoding of that millisecond instant. Any other finite binary
|
||||
date uses `{ "$plist_type": "date", "iso8601": null }` and the counted
|
||||
limitation; the archive bytes remain the source of the instant.
|
||||
|
||||
A negative-zero real is reported as `{ "$plist_type": "real", "value": "-0" }`
|
||||
because a JSON number cannot carry the sign of zero. `inspect_plist` and
|
||||
|
||||
@@ -67,7 +67,11 @@ Addresses count once per packet, including loopback and nested IP occurrences.
|
||||
DNS addresses are associated only with one question in the same response packet;
|
||||
additional records may be included, so this does not prove final resolution.
|
||||
Ambiguous addresses remain in a separate inventory. Protocol distribution counts
|
||||
exact `frame.protocols` stack strings. TLS SNI is recorded handshake metadata,
|
||||
exact nonempty `frame.protocols` stack strings. Frames for which TShark reports
|
||||
an empty stack, including zero-length packets, still contribute to the packet
|
||||
count without adding a protocol row. An all-empty stack inventory can have
|
||||
complete examined coverage; it does not establish the absence of network traffic.
|
||||
TLS SNI is recorded handshake metadata,
|
||||
not process identity or proof of the destination's authenticity.
|
||||
|
||||
All examined inventories are retained within the resource budget; no fixed
|
||||
|
||||
+36
-1
@@ -461,7 +461,33 @@ selected roots; it is not a per-file allowance. File contents are read in
|
||||
|
||||
Ownership inspections bind run-token reads to native start identities and retain
|
||||
related generations through reparenting, group changes, omitted rows, and cleanup
|
||||
retries. The captured run keeps one evidence owner through settlement and cleanup.
|
||||
retries. A host without native identity reads still token-checks process-table
|
||||
rows that appear only in a launcher-exit refresh before reporting that group
|
||||
clean or publishing an empty lineage. A matching token authorizes a signal only
|
||||
for a group whose leader carries the same token. A matching token whose leader
|
||||
is absent, or an unreadable token for a still-live new row, stays unresolved. A
|
||||
readable foreign token is not signaled. An unreadable row that has exited by
|
||||
the confirmation read does not hide a new row in that confirmation table, and a
|
||||
group proven while revalidating another owned group is signaled in the same
|
||||
cleanup. A matched row that changes parent or group on the confirmation read
|
||||
is token-checked again. A PID whose token was already read is read again
|
||||
on the next confirmation even when its parent and group return to the
|
||||
pre-exit values. A PID whose first token was foreign is read again
|
||||
on that table, because the PID alone does not identify the process. A PID
|
||||
from the pre-exit table is read again when its parent or group changes, and
|
||||
an unchanged pre-existing row that was never token-read stays unread. Lineage
|
||||
publishes one row for each PID. Confirmation reads are bounded; a table that keeps producing unreadable
|
||||
replacements stays unresolved. That refresh does not retain a ledger
|
||||
for a later attempt that never observes the launcher. Lineage reads a row again
|
||||
when its parent, group, or launcher-tree membership changes, and it reads a
|
||||
token again on the next refresh even when those fields are unchanged. The
|
||||
launcher is read on every lineage refresh; a missing, unowned, or
|
||||
relation-changed launcher PID is not published as a verified lineage. A
|
||||
descendant absent from the latest refresh is omitted. An
|
||||
ancestor move cannot leave a foreign descendant inside a verified result. A
|
||||
group that reappears after cleanup already processed it is revalidated once;
|
||||
another appearance stays unresolved. The captured run keeps
|
||||
one evidence owner through settlement and cleanup.
|
||||
An absent or changed token leaves a previously related generation unresolved;
|
||||
current token proof is still required before signaling. Swept cleanup verifies the
|
||||
remaining family after its group signals. Coverage is bounded by the native
|
||||
@@ -519,6 +545,15 @@ missing or relative SDK/compiler path fails with an actionable prerequisite
|
||||
error before compilation. An incompatible installation reports the compiler's
|
||||
bounded diagnostics; REA does not repair or replace the toolchain.
|
||||
|
||||
The compile deadline is `REA_SWIFTC_COMPILE_TIMEOUT_MS`. An omitted value is
|
||||
120,000 ms, and accepted values are integers from 1 to 2,147,483,647. REA reads
|
||||
the variable from the environment that starts the process and keeps that
|
||||
deadline for every helper compile in that process. Restart REA to apply a
|
||||
change; the next ownership-helper compile uses the new value. A timeout names
|
||||
the effective milliseconds. Invalid values fail configuration validation at
|
||||
startup. Embedded compiler diagnostics are cut at 512 bytes, and this release
|
||||
has no runtime override for that excerpt.
|
||||
|
||||
For example, select paths from your existing Xcode or Command Line Tools
|
||||
installation **before** entering an enforced write boundary:
|
||||
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
# Python packaged applications
|
||||
|
||||
REA statically inventories PyInstaller executables with an appended CArchive.
|
||||
`inspect_artifact` and `extract_artifact` share the same reader through CLI and
|
||||
MCP. They read archive bytes without launching the application. Bytecode
|
||||
source decompilation, encrypted PYZ recovery, zipapp and PEX analysis are outside
|
||||
this capability.
|
||||
|
||||
## Facts and focused queries
|
||||
|
||||
The root occurrence's `format_metadata` records the CArchive layout (2.0 or
|
||||
2.1), archive and cookie offsets, table extent, entry count, raw Python version,
|
||||
normalized major/minor when known, library name and encryption marker. Member
|
||||
metadata retains the original name, table index, type, compression flag,
|
||||
relative offset and known directory record extent. Logical paths use archive
|
||||
path rules; the source name retains its spelling, including backslashes.
|
||||
`relative_offset` is relative to the CArchive start for CArchive rows, or to
|
||||
the decoded PYZ image for PYZ rows. A CArchive directory record starts at
|
||||
`archive_start + toc_offset + directory_record_offset`; its size is
|
||||
`directory_record_size`. PYZ row directory extents remain unknown.
|
||||
|
||||
Namespace packages remain directories. Their `relative_offset` and
|
||||
`compressed_size` preserve any payload declared by older producers, while
|
||||
`declared_size` is zero because no bytecode is materialized for a namespace.
|
||||
Every declared span must end before the PYZ table of contents.
|
||||
PYZ `compression_flag` is derived from storage: nonempty payloads are compressed,
|
||||
including legacy namespaces; an empty namespace has no compressed payload.
|
||||
|
||||
CArchive type `o` entries are runtime options. They are metadata occurrences,
|
||||
with no content artifact or extractable file. Their query paths are
|
||||
`__pyinstaller__/runtime-options/<table index>`; the option text is
|
||||
`format_metadata.source_name`. Repeated declarations retain distinct occurrence
|
||||
identities. These paths do not claim output filesystem names.
|
||||
|
||||
Type `d` entries are multipackage dependencies. They are also metadata, under
|
||||
`__pyinstaller__/dependencies/<table index>`, and never materialize an empty file.
|
||||
The reader preserves the raw reference and splits its first colon into
|
||||
`dependency_archive` and `dependency_member`. `dependency_status` remains
|
||||
`unresolved`, or `invalid-reference` with unknown parts for malformed references.
|
||||
`external_dependency_count` summarizes these declarations. REA does not open
|
||||
another executable or claim its contents are available. A real file with the
|
||||
same logical path as metadata remains independently extractable.
|
||||
Both declaration types require empty payloads and no compression. Their query
|
||||
paths do not participate in filesystem collision checks, directory ancestry or
|
||||
source-map target lookup; their parent identifies the declaring container.
|
||||
Complete authenticated inventory page sets preserve producer identities in any
|
||||
merge order, including metadata/file aliases. Malformed TOC diagnostics name the
|
||||
table index; original names remain available in the supplied artifact.
|
||||
Path failures use bounded escaped previews and report the original length;
|
||||
accepted paths and retained source names are not shortened.
|
||||
|
||||
Request `detail: "summary"` for a compact inspection, then query retained
|
||||
Evidence with `inspect_analysis_view`. An inventory view can select
|
||||
`collection: "occurrences"`, `entry_kinds: ["metadata"]`, exact logical paths or
|
||||
occurrence IDs, requested `fields`, and `offset`/`limit`. Filters intersect;
|
||||
identities, parent Evidence and coverage survive projection. Full inventory
|
||||
Evidence remains available for export. A compact reply reduces returned context;
|
||||
it still performs the complete member inventory and hashing work.
|
||||
Focused views add calls and tool-schema costs. A complete small inventory can
|
||||
cost less overall; prefer compact delivery when the full member graph would
|
||||
overwhelm the answer.
|
||||
|
||||
```bash
|
||||
rea inspect-artifact /absolute/path/hello --detail summary --evidence_output /absolute/new/evidence.json --json
|
||||
rea extract-artifact /absolute/path/hello --json
|
||||
```
|
||||
|
||||
## Decoding and evidence limits
|
||||
|
||||
Inventory hashes members individually through bounded streams. Stored PYZ
|
||||
images use descriptor ranges; outer-compressed images stream to private files,
|
||||
which the reader owns through cleanup and any cleanup retry. Extraction binds
|
||||
the selected carrier to its inventoried digest and checks source identity and
|
||||
state before and after reading. It does not retain expanded module bodies.
|
||||
Opaque outer-compressed images reuse that verified private image when opened,
|
||||
instead of inflating the carrier again. Direct source spans describe stored
|
||||
CArchive bytes; decompressed content has no direct span even when its encoded
|
||||
and decoded sizes coincide. Original offsets and compression remain metadata.
|
||||
|
||||
Only the PYZ header and marshal directory are loaded for listing. PYZ tables
|
||||
have a 16 MiB budget; CArchive tables have a 32 MiB budget. Parsed facts have a
|
||||
32 MiB serialized budget. Projected entries share a 64 MiB retained budget,
|
||||
including metadata, bookkeeping and conservative reservations for namespace
|
||||
objects and possible case-collision annotations at each path component. These
|
||||
reservations happen before normalization or trie allocation.
|
||||
Outer-compressed PYZ images have a separate per-reader capacity of 128 private
|
||||
files, bounding retained inodes and image identities. The complete image count
|
||||
is admitted before any temporary file is created; excess images return a
|
||||
capacity failure. This is a resource policy, not a PyInstaller format limit.
|
||||
Only a zero-byte read establishes EOF; short successful descriptor reads fill
|
||||
the bounded range. Compressed members must consume their complete declared
|
||||
input span; trailing junk and concatenated streams are refused.
|
||||
Plaintext expansion has an aggregate archive-derived budget. Exceeding a budget
|
||||
returns a resource failure.
|
||||
|
||||
Supported final Python bytecode magic values cover Python 3.7 through 3.14.
|
||||
Supported marshal directory values are lists, tuples, strings, integers and
|
||||
bytes. An unsupported magic or directory stays an opaque member with a
|
||||
limitation and `pyz_status: "opaque"`; its module contents remain unknown.
|
||||
Any opaque PYZ makes producer traversal coverage unknown, including retained
|
||||
summaries and exhausted queries. Per-archive reasons remain on the opaque
|
||||
occurrences; the coverage observation summarizes their count without repeating
|
||||
every limitation. An empty result does not establish module absence.
|
||||
Observed `pyz_python_magic` bytes remain available even when their Python version
|
||||
is unknown.
|
||||
The directory declares compressed module lengths, so uncompressed declared
|
||||
sizes and source spans inside decoded data remain unknown.
|
||||
|
||||
PYZ modules receive a derived 16-byte `.pyc` header from their own supported
|
||||
magic. CArchive bytecode receives that header only when every sibling PYZ magic
|
||||
and the cookie's Python version agree. Otherwise it retains its original bytes
|
||||
and `bytecode_header: "unknown"`. `bytecode_magic` and graph derivation edges
|
||||
identify synthesized headers; member digests cover the resulting derived files.
|
||||
These headers do not establish successful execution or decompilation.
|
||||
|
||||
The nonempty CArchive Python module `pyimod00_crypto_key` (`m`/`M`) is recorded
|
||||
as an encryption marker; a same-named data file or script is not. Affected
|
||||
PYZ blobs are reported without decoding; extraction refuses encrypted entries.
|
||||
The raw PYZ container remains readable and hashable, including when its module
|
||||
table is opaque. Its marker stays in metadata and opaque child coverage stays
|
||||
unknown; extracting the container does not decrypt its payloads.
|
||||
The marker also applies to nonempty legacy namespace payloads. Empty namespaces
|
||||
have no payload to encrypt and retain a null encryption source.
|
||||
|
||||
Detection searches the last 16 MiB for a cookie, allowing a trailing macOS code
|
||||
signature within that bound. Member offsets are relative to the archive start:
|
||||
cookie position plus cookie size minus package length. Native bootloader
|
||||
analysis remains available through the native tools.
|
||||
@@ -152,6 +152,7 @@ npx rea-agents@latest setup
|
||||
| تسجيلات الشبكة المحفوظة | الطلبات، والاستجابات، ومحتويات الحمولة المتاحة، ومواضعها في المصدر | HAR؛ وmitmdump على Linux لتسجيلات mitmproxy بصيغتها الأصلية؛ [دليل تسجيلات الشبكة](../web-network-captures.md) |
|
||||
| التقاط الحزم | نقاط النهاية وDNS وTLS SNI وتوزيع البروتوكولات وطلبات HTTP | tshark وcapinfos يوفّرهما المُستدعي؛ [دليل pcap](../pcap-analysis.md) |
|
||||
| تجميعات .NET | البيانات الوصفية، وتعليمات CIL، واعتماديات الشيفرة الأصلية المعلنة، ومقارنات البناء | فحص ثابت؛ [دليل الشيفرة المُدارة](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
| حزم Android APK | تصريحات ملف manifest، والأصناف، والدوال الناتجة عن فك الترجمة، والمراجع | 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) |
|
||||
@@ -266,6 +267,7 @@ npx rea-agents@latest setup
|
||||
|
||||
- [التثبيت والإعداد](../installation.md): تسجيل الوكلاء، وتهيئة الموفّرين، والتحديثات، وإلغاء التثبيت.
|
||||
- [الجاهزية واستكشاف الأخطاء](../installation.md#check-readiness-for-your-task): تشخيص وكيل أو محرك تحليل محدد.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [GGUF / safetensors](../model-artifacts.md)
|
||||
- [CLI وEvidence](../cli.md): الأوامر، واختيار الموفّر، واللقطات، والاستيراد/التصدير، وحالات الخروج.
|
||||
- [عقود MCP](../mcp-contracts.md) و[تعليمات الوكلاء](../mcp-prompts.md): نتائج الأدوات، والجلسات، والاستقصاءات الموجّهة.
|
||||
|
||||
@@ -152,6 +152,7 @@ REA benötigt Node.js 22.x (>=22.19), 24.x (>=24.11) oder 26+ sowie npm. Zusätz
|
||||
| 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) |
|
||||
| Paketerfassungen | Endpunkte, DNS, TLS SNI, Protokollverteilung und HTTP-Anfragen | Vom Aufrufer bereitgestellte tshark- und capinfos-Binaries; [pcap-Leitfaden](../pcap-analysis.md) |
|
||||
| .NET-Assemblies | Metadaten, CIL-Anweisungen, deklarierte native Abhängigkeiten und Build-Vergleiche | Statische Untersuchung; [Leitfaden für verwalteten Code](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
| Android-APKs | Manifest-Deklarationen, Klassen, dekompilierte Methoden und Verweise | JADX ohne grafische Oberfläche und ein vollständiges JDK unter Linux/macOS/Windows x64; [Android-Leitfaden](../android-analysis.md) |
|
||||
| Android-Geräte | Geräte, Pakete, Prozesse, Logs, Dumps, Bildschirmaufnahmen sowie APK- und Dateiübertragungen | Vom Aufrufer bereitgestelltes adb (Emulator oder Gerät); [ADB-Leitfaden](../adb-device-analysis.md) |
|
||||
| JEB-Projekte | Engine-gestützte Projekteinheiten, Artefakt-Prüfsummen und Pseudokode von Typen/Methoden | Ein vom Aufrufer gestarteter JEB-Client mit MCP, ausgewählt über REA_JEB_MCP_URL; [JEB-Leitfaden](../jeb-analysis.md) |
|
||||
@@ -264,6 +265,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.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [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.
|
||||
|
||||
@@ -158,6 +158,7 @@ npx rea-agents@latest setup
|
||||
| Ιστότοποι | Δομή σελίδων, scripts, παρατηρήσεις δικτύου και ζητούμενα στιγμιότυπα οθόνης | Πρόγραμμα περιήγησης της οικογένειας Chrome· [ανάλυση μέσω προγράμματος περιήγησης](../browser-observation.md) |
|
||||
| Αποθηκευμένες καταγραφές δικτύου | Αιτήματα, αποκρίσεις, διαθέσιμα δεδομένα φορτίου και θέσεις στην πηγή | HAR ή SAZ του Fiddler Everywhere· mitmdump σε Linux για την εγγενή μορφή mitmproxy· [οδηγός καταγραφών](../web-network-captures.md) |
|
||||
| Assemblies .NET | Μεταδεδομένα, εντολές CIL, δηλωμένες εξαρτήσεις από κώδικα μηχανής και συγκρίσεις builds | Καμία πρόσθετη απαίτηση (μόνο στατική ανάλυση)· [οδηγός διαχειριζόμενου κώδικα](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
| APK Android | Δηλώσεις manifest, κλάσεις, απομεταγλωττισμένες μέθοδοι και αναφορές | JADX χωρίς γραφικό περιβάλλον και πλήρες JDK σε Linux/macOS/Windows x64· [οδηγός Android](../android-analysis.md) |
|
||||
| Συσκευές Android | Συσκευές, πακέτα, διεργασίες, logs, dumps, στιγμιότυπα οθόνης και μεταφορές APK/αρχείων | adb που παρέχει ο χρήστης (εξομοιωτής ή φυσική συσκευή)· [οδηγός ADB](../adb-device-analysis.md) |
|
||||
| Έργα JEB | Μονάδες έργου από τη μηχανή ανάλυσης, ψηφιακά αποτυπώματα αρχείων και ψευδοκώδικα τύπων/μεθόδων | Client JEB που έχει ξεκινήσει ο χρήστης και παρέχει MCP, επιλεγμένος μέσω REA_JEB_MCP_URL· [οδηγός JEB](../jeb-analysis.md) |
|
||||
@@ -277,6 +278,7 @@ npx rea-agents@latest setup
|
||||
|
||||
- [Εγκατάσταση και ρύθμιση](../installation.md): καταχώριση agents, ρύθμιση παρόχων ανάλυσης, ενημερώσεις και απεγκατάσταση.
|
||||
- [Έλεγχος ετοιμότητας και αντιμετώπιση προβλημάτων](../installation.md#check-readiness-for-your-task): διάγνωση ενός agent ή μιας μηχανής ανάλυσης.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [GGUF / safetensors](../model-artifacts.md)
|
||||
- [CLI και Evidence](../cli.md): εντολές, επιλογή παρόχου, στιγμιότυπα, εισαγωγή/εξαγωγή και κωδικοί εξόδου.
|
||||
- [Προδιαγραφές MCP](../mcp-contracts.md) και [prompts για agents](../mcp-prompts.md): αποτελέσματα εργαλείων, συνεδρίες και καθοδηγούμενες διερευνήσεις.
|
||||
|
||||
@@ -152,6 +152,7 @@ REA requiere Node.js 22.x (>=22.19), 24.x (>=24.11) o 26+, además de npm. Las h
|
||||
| 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) |
|
||||
| Capturas de paquetes | Endpoints, DNS, TLS SNI, distribución de protocolos y solicitudes HTTP | tshark y capinfos suministrados por el autor de la llamada; [guía pcap](../pcap-analysis.md) |
|
||||
| Ensamblados .NET | Metadatos, instrucciones CIL, dependencias nativas declaradas y comparaciones de compilaciones | Inspección estática; [guía de código administrado](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
| APK de Android | Declaraciones del manifiesto, clases, métodos descompilados y referencias | JADX sin interfaz gráfica y un JDK completo en Linux/macOS/Windows x64; [guía de Android](../android-analysis.md) |
|
||||
| Dispositivos Android | Dispositivos, paquetes, procesos, registros, volcados, capturas de pantalla y transferencias de APK/archivos | adb suministrado por el autor de la llamada (emulador o dispositivo); [guía de ADB](../adb-device-analysis.md) |
|
||||
| Proyectos JEB | Unidades de proyecto del motor, resúmenes de artefactos y pseudocódigo de tipos/métodos | Un cliente JEB iniciado por el autor de la llamada que sirve MCP, seleccionado con REA_JEB_MCP_URL; [guía de JEB](../jeb-analysis.md) |
|
||||
@@ -264,6 +265,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.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [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.
|
||||
|
||||
@@ -143,6 +143,7 @@ REA به Node.js 22.x (>=22.19)، 24.x (>=24.11) یا 26+، بههمراه np
|
||||
| وبسایتها | ساختار صفحه، اسکریپتها، مشاهدات شبکه و اسکرینشاتهای درخواستی | مرورگر مبتنی بر Chrome؛ [تحلیل مرورگر](../browser-observation.md) |
|
||||
| دادههای ضبطشدهٔ شبکه | درخواستها، پاسخها، payloadهای آشکارشده و مکان آنها در منبع | HAR؛ ابزار mitmdump در لینوکس برای ضبطهای بومی mitmproxy؛ [راهنمای ضبط شبکه](../web-network-captures.md) |
|
||||
| اسمبلیهای .NET | فراداده، دستورالعملهای CIL، وابستگیهای بومی اعلامشده و مقایسهٔ buildها | بررسی ایستا؛ [راهنمای کد مدیریتشده](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
| فایلهای APK اندروید | تعاریف Manifest، کلاسها، متدهای دیکامپایلشده و ارجاعات | JADX بدون رابط گرافیکی و JDK کامل در Linux/macOS/Windows x64؛ [راهنمای اندروید](../android-analysis.md) |
|
||||
| دستگاههای اندروید | دستگاهها، بستهها، فرایندها، لاگها، دامپها، اسکرینشاتها و انتقال APK/فایل | adb تأمینشده توسط فراخوانکننده (شبیهساز یا دستگاه)؛ [راهنمای ADB](../adb-device-analysis.md) |
|
||||
| پروژههای JEB | واحدهای پروژه از موتور، هشهای مصنوع و شبهکدِ نوع/متد | یک کلاینت JEB که توسط فراخوانکننده اجرا شده و MCP ارائه میدهد و با REA_JEB_MCP_URL انتخاب میشود؛ [راهنمای JEB](../jeb-analysis.md) |
|
||||
@@ -249,6 +250,7 @@ npx rea-agents@latest setup
|
||||
|
||||
- [نصب و راهاندازی](../installation.md): ثبت ایجنت، پیکربندی ارائهدهنده، بهروزرسانی و حذف نصب.
|
||||
- [آمادگی و رفع اشکال](../installation.md#check-readiness-for-your-task): عیبیابی یک ایجنت یا موتور تحلیل.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [GGUF / safetensors](../model-artifacts.md)
|
||||
- [CLI و شواهد](../cli.md): دستورات، انتخاب ارائهدهنده، snapshotها، ورود/خروج داده و وضعیتهای خروج.
|
||||
- [قراردادهای MCP](../mcp-contracts.md) و [پرامپتهای ایجنت](../mcp-prompts.md): نتایج ابزارها، نشستها و بررسیهای هدایتشده.
|
||||
|
||||
@@ -156,6 +156,7 @@ REA nécessite Node.js 22.x (>=22.19), 24.x (>=24.11) ou 26+, ainsi que npm. Les
|
||||
| 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) |
|
||||
| Captures de paquets | Points de terminaison, DNS, TLS SNI, distribution des protocoles et requêtes HTTP | tshark et capinfos fournis par l'appelant ; [guide pcap](../pcap-analysis.md) |
|
||||
| Assemblys .NET | Métadonnées, instructions CIL, dépendances natives déclarées et comparaisons de builds | Inspection statique ; [guide du code managé](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
| APK Android | Déclarations du manifeste, classes, méthodes décompilées et références | JADX headless et un JDK complet sous Linux/macOS/Windows x64 ; [guide Android](../android-analysis.md) |
|
||||
| Appareils Android | Appareils, paquets, processus, journaux, dumps, captures d'écran et transferts d'APK/fichiers | adb fourni par l'appelant (émulateur ou appareil) ; [guide ADB](../adb-device-analysis.md) |
|
||||
| Projets JEB | Unités de projet fournies par le moteur, condensés d'artefacts et pseudo-code de types/méthodes | Un client JEB démarré par l'appelant servant MCP, sélectionné via REA_JEB_MCP_URL ; [guide JEB](../jeb-analysis.md) |
|
||||
@@ -268,6 +269,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é.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [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.
|
||||
|
||||
@@ -159,6 +159,7 @@ Alat tambahan dan dukungan sistem host bergantung pada target yang dianalisis:
|
||||
| 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) |
|
||||
| Capturan paket | Endpoint, DNS, TLS SNI, distribusi protokol, dan permintaan HTTP | tshark dan capinfos buatan pemanggil; [panduan pcap](../pcap-analysis.md) |
|
||||
| Assembly .NET | Metadata, instruksi CIL, dependensi native yang dideklarasikan, dan perbandingan build | Tidak ada (hanya analisis statis); [panduan kode terkelola](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
| APK Android | Deklarasi manifest, kelas, metode hasil dekompilasi, dan referensi | JADX mode headless dan JDK lengkap di Linux/macOS/Windows x64; [panduan Android](../android-analysis.md) |
|
||||
| Perangkat Android | Perangkat, paket, proses, log, dump, tangkapan layar, serta transfer APK/berkas | adb buatan pemanggil (emulator atau perangkat); [panduan ADB](../adb-device-analysis.md) |
|
||||
| Proyek JEB | Unit proyek bertenaga mesin, hash artefak, dan pseudokode tipe/metode | Klien JEB yang dijalankan pemanggil dan menyajikan MCP, dipilih dengan REA_JEB_MCP_URL; [panduan JEB](../jeb-analysis.md) |
|
||||
@@ -289,6 +290,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.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [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.
|
||||
|
||||
@@ -156,6 +156,7 @@ REA richiede Node.js 22.x (>=22.19), 24.x (>=24.11) o 26+, oltre a npm. Strument
|
||||
| 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) |
|
||||
| Captured di pacchetti | Endpoint, DNS, TLS SNI, distribuzione dei protocolli e richieste HTTP | tshark e capinfos forniti dal chiamante; [guida pcap](../pcap-analysis.md) |
|
||||
| Assembly .NET | Metadati, istruzioni CIL, dipendenze native dichiarate e confronti di build | Nessuno (solo statico); [guida managed-code](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
| APK Android | Dichiarazioni manifest, classi, metodi decompilati e riferimenti | JADX headless e un JDK completo su Linux/macOS/Windows x64; [guida Android](../android-analysis.md) |
|
||||
| Dispositivi Android | Dispositivi, pacchetti, processi, log, dump, screenshot e trasferimenti APK/file | adb fornito dal chiamante (emulatore o hardware); [guida ADB](../adb-device-analysis.md) |
|
||||
| Progetti JEB | Unità di progetto dal motore, digest degli artifact e pseudocodice di tipi/metodi | Client JEB avviato dal chiamante via MCP, selezionato con REA_JEB_MCP_URL; [guida JEB](../jeb-analysis.md) |
|
||||
@@ -268,6 +269,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.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [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.
|
||||
|
||||
@@ -152,6 +152,7 @@ REA には Node.js 22.x(>=22.19)、24.x(>=24.11)、または 26+ と npm
|
||||
| 保存済みのネットワークキャプチャ | リクエスト、レスポンス、取得可能なペイロード、ソース内の位置 | HAR;mitmproxy ネイティブ形式のキャプチャには Linux 上の mitmdump;[キャプチャガイド](../web-network-captures.md) |
|
||||
| パケットキャプチャ | エンドポイント、DNS、TLS SNI、プロトコル分布、HTTPリクエスト | 呼び出し側が用意した tshark と capinfos;[pcapガイド](../pcap-analysis.md) |
|
||||
| .NET アセンブリ | メタデータ、CIL 命令、宣言されたネイティブ依存関係、ビルドの比較 | 静的な検査;[マネージドコードのガイド](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.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) |
|
||||
@@ -266,6 +267,7 @@ npx rea-agents@latest setup
|
||||
|
||||
- [インストールとセットアップ](../installation.md):エージェントの登録、プロバイダーの設定、更新、アンインストール。
|
||||
- [準備状況の確認とトラブルシューティング](../installation.md#check-readiness-for-your-task):特定のエージェントや分析エンジンを診断。
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [GGUF / safetensors](../model-artifacts.md)
|
||||
- [CLI と Evidence](../cli.md):コマンド、プロバイダーの選択、スナップショット、インポート/エクスポート、終了ステータス。
|
||||
- [MCP 契約](../mcp-contracts.md)と[エージェント向けプロンプト](../mcp-prompts.md):ツールの結果、セッション、ガイド付き調査。
|
||||
|
||||
@@ -173,6 +173,7 @@ REA에는 Node.js 22.x(>=22.19), 24.x(>=24.11) 또는 26+와 npm이 필요합니
|
||||
| 기록된 논리 신호 | 디코더 주석, 샘플 범위, 진단 정보 | 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) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
|
||||
정적 JavaScript 및 .NET 검사는 제공된 파일을 읽으며 애플리케이션을 실행하지 않습니다. 런타임 캡처는 사용자의 권한으로 선택한 대상을 실행하거나 대상과 상호작용합니다. 각 런타임 가이드에서 그 영향을 설명합니다.
|
||||
|
||||
@@ -279,6 +280,7 @@ npx rea-agents@latest setup
|
||||
|
||||
- [설치 및 설정](../installation.md): 에이전트 등록, 제공자 설정, 업데이트, 제거.
|
||||
- [준비 상태 확인 및 문제 해결](../installation.md#check-readiness-for-your-task): 특정 에이전트 또는 분석 엔진 진단.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [GGUF / safetensors](../model-artifacts.md)
|
||||
- [CLI 및 Evidence](../cli.md): 명령, 제공자 선택, 스냅샷, 가져오기/내보내기, 종료 상태.
|
||||
- [MCP 계약](../mcp-contracts.md) 및 [에이전트 프롬프트](../mcp-prompts.md): 도구 결과, 세션, 안내에 따른 조사.
|
||||
|
||||
@@ -160,6 +160,7 @@ REA-യ്ക്ക് Node.js 22.x (>=22.19), 24.x (>=24.11), അല്ലെ
|
||||
| Websites | Page structure, scripts, network observations, ആവശ്യപ്പെട്ട screenshots | Chrome-family browser; [browser analysis](../browser-observation.md) |
|
||||
| Saved network captures | Requests, responses, പുറത്തുകാണുന്ന payload-ുകൾ, source locations | HAR അല്ലെങ്കിൽ Fiddler Everywhere SAZ; native mitmproxy-നായി Linux-ൽ mitmdump; [capture guide](../web-network-captures.md) |
|
||||
| .NET assemblies | Metadata, CIL instructions, പ്രഖ്യാപിച്ച native dependencies, build comparisons | ഒന്നും ആവശ്യമില്ല (static മാത്രം); [managed-code guide](../managed-code-analysis.md) |
|
||||
| Python packaged apps | CArchive/PYZ entries, Python version, bytecode, resources and runtime options | Static PyInstaller parsing; [Python guide](../python-packaged-applications.md) |
|
||||
| Android APKs | Manifest declarations, classes, decompiled methods, references | Linux/macOS/Windows x64-ൽ Headless JADX-ഉം full JDK-ഉം; [Android guide](../android-analysis.md) |
|
||||
| Android devices | Devices, packages, processes, logs, dumps, screen captures, APK/file transfers | Caller നൽകുന്ന adb (emulator അല്ലെങ്കിൽ hardware); [ADB guide](../adb-device-analysis.md) |
|
||||
| JEB projects | Engine-backed project units, artifact digests, type/method pseudo-code | MCP സേവനം നൽകുന്ന caller ആരംഭിച്ച JEB client; REA_JEB_MCP_URL ഉപയോഗിച്ച് തിരഞ്ഞെടുക്കുക; [JEB guide](../jeb-analysis.md) |
|
||||
@@ -282,6 +283,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-ന്റെയോ പ്രശ്നങ്ങൾ കണ്ടെത്തുക.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [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.
|
||||
|
||||
@@ -152,6 +152,7 @@ REA wymaga Node.js 22.x (>=22.19), 24.x (>=24.11) lub 26+ oraz npm. Dodatkowe na
|
||||
| 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) |
|
||||
| Przechwytywanie pakietów | Punkty końcowe, DNS, TLS SNI, dystrybucja protokołów i żądania HTTP | Dostarczone przez wywołującego tshark i capinfos; [przewodnik pcap](../pcap-analysis.md) |
|
||||
| Zestawy .NET | Metadane, instrukcje CIL, zadeklarowane zależności natywne i porównania kompilacji | Analiza statyczna; [przewodnik kodu zarządzanego](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
| Pakiety APK dla Androida | Deklaracje manifestu, klasy, zdekompilowane metody i odwołania | JADX bez interfejsu graficznego i pełny JDK w systemach Linux/macOS/Windows x64; [przewodnik Androida](../android-analysis.md) |
|
||||
| Urządzenia z Androidem | Urządzenia, pakiety, procesy, logi, zrzuty, zrzuty ekranu oraz transfery APK/plików | adb dostarczony przez wywołującego (emulator lub urządzenie); [przewodnik ADB](../adb-device-analysis.md) |
|
||||
| Projekty JEB | Jednostki projektu obsługiwane przez silnik, skróty artefaktów i pseudokod typów/metod | Uruchomiony przez wywołującego klient JEB udostępniający MCP, wybrany przez REA_JEB_MCP_URL; [przewodnik JEB](../jeb-analysis.md) |
|
||||
@@ -264,6 +265,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.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [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.
|
||||
|
||||
@@ -152,6 +152,7 @@ O REA requer Node.js 22.x (>=22.19), 24.x (>=24.11) ou 26+, além do npm. As fer
|
||||
| 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) |
|
||||
| Capturas de pacotes | Endpoints, DNS, TLS SNI, distribuição de protocolos e requisições HTTP | tshark e capinfos fornecidos pelo chamador; [guia pcap](../pcap-analysis.md) |
|
||||
| Assemblies .NET | Metadados, instruções CIL, dependências nativas declaradas e comparações de builds | Inspeção estática; [guia de código gerenciado](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
| APKs Android | Declarações do manifesto, classes, métodos descompilados e referências | JADX sem interface gráfica e um JDK completo no Linux/macOS/Windows x64; [guia de Android](../android-analysis.md) |
|
||||
| Dispositivos Android | Dispositivos, pacotes, processos, logs, despejos, capturas de tela e transferências de APK/arquivos | adb fornecido pelo chamador (emulador ou aparelho); [guia de ADB](../adb-device-analysis.md) |
|
||||
| Projetos JEB | Unidades de projeto do motor, hashes de artefatos e pseudocódigo de tipos/métodos | Um cliente JEB iniciado pelo chamador servindo MCP, selecionado com REA_JEB_MCP_URL; [guia de JEB](../jeb-analysis.md) |
|
||||
@@ -264,6 +265,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.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [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.
|
||||
|
||||
@@ -162,6 +162,7 @@ REA требует Node.js 22.x (>=22.19), 24.x (>=24.11) или 26+, а так
|
||||
| Записанные логические сигналы | Аннотации декодера, диапазоны отсчётов и диагностика | 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) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
|
||||
Статическое исследование JavaScript и .NET читает предоставленные файлы, не запуская приложение. Захват во время выполнения запускает выбранную цель или взаимодействует с ней с правами вашего пользователя; соответствующие руководства описывают последствия.
|
||||
|
||||
@@ -264,6 +265,7 @@ npx rea-agents@latest setup
|
||||
|
||||
- [Установка и настройка](../installation.md): регистрация агентов, настройка провайдеров, обновление и удаление.
|
||||
- [Готовность и устранение неполадок](../installation.md#check-readiness-for-your-task): диагностика конкретного агента или движка анализа.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [GGUF / safetensors](../model-artifacts.md)
|
||||
- [CLI и Evidence](../cli.md): команды, выбор провайдера, снимки, импорт/экспорт и коды завершения.
|
||||
- [Контракты MCP](../mcp-contracts.md) и [промпты агентов](../mcp-prompts.md): результаты инструментов, сеансы и исследования с подсказками.
|
||||
|
||||
@@ -152,6 +152,7 @@ REA ต้องใช้ Node.js 22.x (>=22.19), 24.x (>=24.11) หรือ 26
|
||||
| ข้อมูลเครือข่ายที่บันทึกไว้ | คำขอ คำตอบ เพย์โหลดที่ปรากฏ และตำแหน่งต้นทาง | HAR; mitmdump บน Linux สำหรับข้อมูลที่บันทึกในรูปแบบเนทีฟของ mitmproxy; [คู่มือการบันทึกข้อมูล](../web-network-captures.md) |
|
||||
| การจับแพ็กเก็ต | จุดเชื่อมต่อ, DNS, TLS SNI, การกระจายโปรโตคอล และคำขอ HTTP | tshark และ capinfos ที่ผู้เรียกจัดเตรียม; [คู่มือ pcap](../pcap-analysis.md) |
|
||||
| แอสเซมบลี .NET | เมทาดาทา คำสั่ง CIL การพึ่งพาเนทีฟที่ประกาศไว้ และการเปรียบเทียบผลการบิลด์ | การตรวจสอบแบบสถิต; [คู่มือโค้ดแบบจัดการ](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
| APK ของ Android | การประกาศใน manifest คลาส เมธอดที่ดีคอมไพล์ และการอ้างอิง | JADX แบบไม่มี GUI และ 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) |
|
||||
@@ -264,6 +265,7 @@ npx rea-agents@latest setup
|
||||
|
||||
- [การติดตั้งและตั้งค่า](../installation.md): การลงทะเบียนเอเจนต์ การตั้งค่าผู้ให้บริการ การอัปเดต และการถอนการติดตั้ง
|
||||
- [ความพร้อมใช้งานและการแก้ไขปัญหา](../installation.md#check-readiness-for-your-task): ตรวจวินิจฉัยเอเจนต์หรือเอนจินวิเคราะห์หนึ่งตัว
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [GGUF / safetensors](../model-artifacts.md)
|
||||
- [CLI และ Evidence](../cli.md): คำสั่ง การเลือกผู้ให้บริการ สแนปช็อต การนำเข้า/ส่งออก และรหัสการสิ้นสุด
|
||||
- [สัญญา MCP](../mcp-contracts.md) และ[พรอมป์ต์สำหรับเอเจนต์](../mcp-prompts.md): ผลลัพธ์เครื่องมือ เซสชัน และการตรวจสอบตามคำแนะนำ
|
||||
|
||||
@@ -156,6 +156,7 @@ REA; Node.js 22.x (>=22.19), 24.x (>=24.11) veya 26+ ve npm gerektirir. Ek araç
|
||||
| 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) |
|
||||
| .NET derlemeleri | Meta veriler, CIL talimatları, bildirilmiş yerel bağımlılıklar ve derleme karşılaştırmaları | Statik inceleme; [yönetilen kod rehberi](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.md) |
|
||||
| Android APK'leri | Manifest bildirimleri, sınıflar, tersine derlenmiş metotlar ve referanslar | Linux/macOS/Windows x64 üzerinde arayüzsüz JADX ve tam bir JDK; [Android rehberi](../android-analysis.md) |
|
||||
| Android cihazları | Cihazlar, paketler, süreçler, günlükler, dökümler, ekran görüntüleri ve APK/dosya aktarımları | Çağıranın sağladığı adb (emülatör veya cihaz); [ADB rehberi](../adb-device-analysis.md) |
|
||||
| JEB projeleri | Motor destekli proje birimleri, artefakt özetleri ve tür/metot sözdekodu | Çağıranın başlattığı, MCP sunan bir JEB istemcisi, REA_JEB_MCP_URL ile seçilir; [JEB rehberi](../jeb-analysis.md) |
|
||||
@@ -269,6 +270,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.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [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.
|
||||
|
||||
@@ -152,6 +152,7 @@ REA потребує Node.js 22.x (>=22.19), 24.x (>=24.11) або 26+, а та
|
||||
| Збережені мережеві захоплення | Запити, відповіді, доступні корисні дані та місця в джерелі | HAR; mitmdump у Linux для захоплень у власному форматі mitmproxy; [посібник мережевих захоплень](../web-network-captures.md) |
|
||||
| Захоплення пакетів | Кінцеві точки, DNS, TLS SNI, розподіл протоколів та HTTP-запити | Надані викликаючою стороною tshark та capinfos; [підручник pcap](../pcap-analysis.md) |
|
||||
| Збірки .NET | Метадані, інструкції CIL, оголошені нативні залежності й порівняння збірок | Статична перевірка; [посібник керованого коду](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.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) |
|
||||
@@ -264,6 +265,7 @@ npx rea-agents@latest setup
|
||||
|
||||
- [Встановлення й налаштування](../installation.md): реєстрація агентів, конфігурація провайдерів, оновлення та видалення.
|
||||
- [Готовність та усунення неполадок](../installation.md#check-readiness-for-your-task): діагностика конкретного агента або рушія аналізу.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [GGUF / safetensors](../model-artifacts.md)
|
||||
- [CLI та Evidence](../cli.md): команди, вибір провайдера, знімки, імпорт/експорт і статуси завершення.
|
||||
- [Контракти MCP](../mcp-contracts.md) і [промпти агентів](../mcp-prompts.md): результати інструментів, сеанси й керовані дослідження.
|
||||
|
||||
@@ -162,6 +162,7 @@ REA yêu cầu Node.js 22.x (>=22.19), 24.x (>=24.11) hoặc 26+, cùng với np
|
||||
| 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) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.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ó.
|
||||
|
||||
@@ -264,6 +265,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ể.
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [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.
|
||||
|
||||
@@ -156,6 +156,7 @@ REA 需要 Node.js 22.x(>=22.19)、24.x(>=24.11)或 26+,以及 npm。
|
||||
| 已保存的網路擷取 | 請求、回應、可訪問的酬載和來源位置 | HAR;原生 mitmproxy 擷取需要 Linux 上的 mitmdump;[擷取指南](../web-network-captures.md) |
|
||||
| 封包擷取 | 端點、DNS、TLS SNI、通訊協定分佈和 HTTP 請求 | 呼叫端提供的 tshark 和 capinfos;[pcap 指南](../pcap-analysis.md) |
|
||||
| .NET 程式集 | 中繼資料、CIL 指令、聲明的原生依賴和建置對比 | 靜態檢查;[托管程式碼指南](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.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) |
|
||||
@@ -270,6 +271,7 @@ npx rea-agents@latest setup
|
||||
|
||||
- [安裝與設定](../installation.md):AI 代理註冊、提供者組態、更新和卸載。
|
||||
- [就緒檢查與故障排查](../installation.md#check-readiness-for-your-task):診斷特定 AI 代理或分析引擎。
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [GGUF / safetensors](../model-artifacts.md)
|
||||
- [CLI 與 Evidence](../cli.md):命令、提供者選擇、快照、匯入/匯出和退出狀態。
|
||||
- [MCP 契約](../mcp-contracts.md)和[AI 代理提示詞](../mcp-prompts.md):工具結果、會話和引導式調查。
|
||||
|
||||
@@ -156,6 +156,7 @@ REA 需要 Node.js 22.x(>=22.19)、24.x(>=24.11)或 26+,以及 npm。
|
||||
| 已保存的网络捕获 | 请求、响应、可访问的载荷和来源位置 | HAR;原生 mitmproxy 捕获需要 Linux 上的 mitmdump;[捕获指南](../web-network-captures.md) |
|
||||
| 数据包捕获 | 端点、DNS、TLS SNI、协议分布和 HTTP 请求 | 调用方提供的 tshark 和 capinfos;[pcap 指南](../pcap-analysis.md) |
|
||||
| .NET 程序集 | 元数据、CIL 指令、声明的原生依赖和构建对比 | 静态检查;[托管代码指南](../managed-code-analysis.md) |
|
||||
| PyInstaller | CArchive, PYZ, Python bytecode | Static inspection; [Python packaged applications](../python-packaged-applications.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) |
|
||||
@@ -270,6 +271,7 @@ npx rea-agents@latest setup
|
||||
|
||||
- [安装与设置](../installation.md):智能体注册、提供方配置、更新和卸载。
|
||||
- [就绪检查与故障排查](../installation.md#check-readiness-for-your-task):诊断特定智能体或分析引擎。
|
||||
- [CUDA / HIP](../gpu-code-objects.md)
|
||||
- [GGUF / safetensors](../model-artifacts.md)
|
||||
- [CLI 与 Evidence](../cli.md):命令、提供方选择、快照、导入/导出和退出状态。
|
||||
- [MCP 契约](../mcp-contracts.md)和[智能体提示词](../mcp-prompts.md):工具结果、会话和引导式调查。
|
||||
|
||||
@@ -320,6 +320,13 @@ close a `packaged-process` obligation. A static-only source cannot close a
|
||||
runtime or process claim. Marking a claim `blocked` or `out-of-scope` records the
|
||||
disposition but does not silently count it as verified.
|
||||
|
||||
The `summary` counts obligations. `by_status`, `by_application_layer`, and
|
||||
`by_source_state` place each obligation in exactly one bucket.
|
||||
`by_evidence_authority` groups obligations by the Evidence `authority` of their
|
||||
`authority_references`: an obligation counts once under each distinct authority
|
||||
it cites, so those counts can exceed `total`. A reference's own `state` and the
|
||||
obligation's `source_state` do not affect its authority bucket.
|
||||
|
||||
The tool returns every obligation inline. Its `ledger_id` and `closure_digest`
|
||||
identify the complete result, including summaries, reports, ownership and
|
||||
dependency graphs, Evidence links, and limitations.
|
||||
|
||||
@@ -27,11 +27,13 @@ rea inspect-with-objdump ./program dwarf
|
||||
rea inspect-with-objdump ./program dwarf --follow-debug-links
|
||||
```
|
||||
|
||||
Captured stdout and stderr are retained up to a 16 MiB combined limit; `output_truncated` marks output beyond that limit.
|
||||
Captured stdout and stderr are retained up to a 16 MiB combined limit; `output_truncated` marks output beyond that limit. That cap has no runtime override.
|
||||
|
||||
`inspect_with_objdump`, `rea list-objdump-architectures`, and one-shot `execute_rizin_command` accept `command_timeout_ms` (CLI: `--command-timeout-ms`). Omitted means 120000. The integer range is 1 to 2147483647. Target preflight shares one budget across stat and digest. The one-shot command receives that budget again. It applies on the next call; no restart is required. It does not raise the 16 MiB cap, a Ghidra or Hopper startup deadline, or a debugger session deadline.
|
||||
|
||||
## GDB
|
||||
|
||||
Persistent GDB sessions, including the MCP workflow and one-shot `rea debug-with-gdb` CLI, are available only on Linux. REA verifies a live inferior's output descriptors through `/proc` before detaching it; it does not claim equivalent descriptor verification on macOS. Windows is also unsupported because owned Job Object cleanup can terminate debugger inferiors. On supported Linux hosts, `start_gdb_session`, `gdb_console`, `gdb_session_status`, and `close_gdb_session` manage a persistent GDB/MI session in MCP. The one-shot CLI requires a caller-selected durable TTY: `rea debug-with-gdb --inferior-tty /dev/pts/7 'file ./program'`. The TTY must remain available after GDB exits so a detached inferior can continue writing. MCP starts GDB with `--nx --quiet --interpreter=mi3`, retries initialization with MI2 if MI3 initialization returns an error and cleanup succeeds, waits for its prompt, and disables auto-loading. Pass optional `inferior_tty` to select the terminal that future inferior runs use; REA configures it before the session becomes ready and checks the exact value with GDB/MI. `gdb_session_status` reports the selected path, whether REA still considers the configuration verified, and whether invalid UTF-8 has been observed in MI bytes (`mi_invalid_utf8`) or stderr (`stderr_invalid_utf8`). Commands that can change the inferior TTY or redirect a run revoke that verification permanently for the session, so close retains GDB ownership if a live inferior remains. Closing a session with one live inferior and a verified TTY automatically detaches the target, which can resume execution; MCP clients receive destructive-operation annotations for this behavior. The console remains unrestricted and can run shell commands, change target state, access files, and use network in the REA process user's security context. Raw MI records and console/target/log streams are returned with Evidence; command output is retained up to 16 MiB and explicitly marked when truncated.
|
||||
Persistent GDB sessions, including the MCP workflow and one-shot `rea debug-with-gdb` CLI, are available only on Linux. REA verifies a live inferior's output descriptors through `/proc` before detaching it; it does not claim equivalent descriptor verification on macOS. Windows is also unsupported because owned Job Object cleanup can terminate debugger inferiors. On supported Linux hosts, `start_gdb_session`, `gdb_console`, `gdb_session_status`, and `close_gdb_session` manage a persistent GDB/MI session in MCP. The one-shot CLI requires a caller-selected durable TTY: `rea debug-with-gdb --inferior-tty /dev/pts/7 'file ./program'`. The TTY must remain available after GDB exits so a detached inferior can continue writing. MCP starts GDB with `--nx --quiet --interpreter=mi3`, retries initialization with MI2 if MI3 initialization returns an error and cleanup succeeds, waits for its prompt, and disables auto-loading. Pass optional `inferior_tty` to select the terminal that future inferior runs use; REA configures it before the session becomes ready and checks the exact value with GDB/MI. `gdb_session_status` reports the selected path, whether REA still considers the configuration verified, and whether invalid UTF-8 has been observed in MI bytes (`mi_invalid_utf8`) or stderr (`stderr_invalid_utf8`). Commands that can change the inferior TTY or redirect a run revoke that verification permanently for the session, so close retains GDB ownership if a live inferior remains. Closing a session with one live inferior and a verified TTY automatically detaches the target, which can resume execution; MCP clients receive destructive-operation annotations for this behavior. The console remains unrestricted and can run shell commands, change target state, access files, and use network in the REA process user's security context. Raw MI records and console/target/log streams are returned with Evidence; command output is retained up to 16 MiB and explicitly marked when truncated. GDB startup waits 10000 ms and each MI command waits 120000 ms. This release has no runtime override for those deadlines, the 16 MiB command output budget, session capacity, or the pending-command queue. `command_timeout_ms` does not change them.
|
||||
|
||||
Before a normal close, REA checks for live GDB thread groups. If one remains and a durable `inferior_tty` is verified, REA asks GDB to detach it and confirms the detach before stopping the debugger. Without that sink, select and apply a disposition to each inferior through `gdb_console` (for example, detach or kill as appropriate), then retry close. REA never infers target ownership from a PID or path. When the MCP server shuts down, REA terminates only its directly owned GDB process after confirming no inferior or a sink-backed detach; otherwise it retains the process and its output streams for retry.
|
||||
|
||||
@@ -49,7 +51,7 @@ close_gdb_session {"session_id":"…"}
|
||||
|
||||
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.
|
||||
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. Rizin debug startup waits 30000 ms and each command frame waits 120000 ms. This release has no runtime override for those deadlines, the 16777216 byte frame cap, the 16777216 byte command-output cap, the 4096 frame command cap, session capacity, or the pending-command queue. Evidence names the cap that stopped the command. The one-shot `command_timeout_ms` setting does not change a debug session.
|
||||
|
||||
```sh
|
||||
rea debug-with-rizin --inferior-tty /dev/pts/7 ./program dr
|
||||
@@ -61,7 +63,7 @@ rea debug-with-rizin --inferior-tty /dev/pts/7 ./program dr
|
||||
rea execute-rizin-command ./program iI
|
||||
```
|
||||
|
||||
Captured stdout and stderr are retained up to a 16 MiB combined limit; `output_truncated` marks output beyond that limit.
|
||||
Captured stdout and stderr are retained up to a 16 MiB combined limit; `output_truncated` marks output beyond that limit. One-shot commands use the `command_timeout_ms` budget described above. That 16 MiB cap has no runtime override.
|
||||
|
||||
## Cutter bridge
|
||||
|
||||
@@ -70,8 +72,11 @@ The client and plugin must support the current v2 handshake; older peers are
|
||||
rejected before dispatch because they cannot preserve cross-caller recovery proof.
|
||||
The client checks the final encoded request against the bridge's 16 MiB frame
|
||||
limit before dispatch; an oversized command does not retain a cleanup owner.
|
||||
Discovery admits at most 256 descriptor candidates and reads and probes at most
|
||||
eight concurrently. A larger directory reports `bridge_directory_capacity_exceeded`.
|
||||
Each bridge request waits 25000 ms. Discovery admits at most 256 descriptor
|
||||
candidates and reads and probes at most eight concurrently. A larger directory
|
||||
reports `bridge_directory_capacity_exceeded`. This release has no runtime
|
||||
override for the 25000 ms request deadline, the 16777216 byte frame, or the
|
||||
256-candidate discovery budget.
|
||||
|
||||
Terminal receipts are recovered before another command, including from a new CLI
|
||||
invocation. A signed status response also confirms completion of older bridge
|
||||
|
||||
@@ -21,6 +21,67 @@ requires an absolute filesystem path and preserves that exact selection:
|
||||
|
||||
## Observations
|
||||
|
||||
Complete delivery remains the default. For a dependency question, select the
|
||||
needed records on the first call instead of returning the complete graph:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "inspect_rust_binary",
|
||||
"arguments": {
|
||||
"path": "/artifacts/application",
|
||||
"view": {
|
||||
"collection": "packages",
|
||||
"names": ["serde", "serde_derive"],
|
||||
"fields": ["name", "version", "source", "dependencies"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`detail: "summary"` returns section ranges, root index, package/edge/cycle counts
|
||||
and compiler-hash count. A `view` selects compact delivery automatically;
|
||||
combining it with explicit `detail: "complete"` is an input error. The complete
|
||||
parent Evidence is retained in the MCP session and remains exportable. Subsequent
|
||||
`inspect_analysis_view` calls accept that `parent_evidence_id`, or its portable
|
||||
Evidence file, without reopening the binary:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"kind": "retained-evidence",
|
||||
"evidence_id": "ev_<parent digest>"
|
||||
},
|
||||
"view": {
|
||||
"kind": "rust",
|
||||
"collection": "edges",
|
||||
"from_indices": [12],
|
||||
"limit": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Package filters accept exact `names`, `versions` and original `indices`; edge
|
||||
filters accept original edge `indices`, `from_indices` and `to_indices`.
|
||||
Filters intersect, and an empty filter array selects nothing. `offset` counts
|
||||
matching records; `limit` defaults to 64. Pages retain original indices scoped
|
||||
to the parent Evidence, selected fields, examined coverage and the next offset.
|
||||
Default package fields omit dependency vectors; explicitly select
|
||||
`dependencies` to obtain direct references. No dependency path is traversed.
|
||||
|
||||
The CLI uses the same views and requires an exclusive output bundle for compact
|
||||
delivery so the complete Evidence survives process exit:
|
||||
|
||||
```bash
|
||||
rea inspect-rust-binary /artifacts/application --json \
|
||||
--view '{"collection":"packages","names":["serde"],"fields":["name","version"]}' \
|
||||
--evidence_output /artifacts/rust-evidence.json
|
||||
```
|
||||
|
||||
Compact results distinguish complete embedded-record coverage from unknown
|
||||
runtime dependency coverage. A missing section remains unknown rather than an
|
||||
empty dependency set. Retained views describe the captured artifact digest;
|
||||
they do not assert that the current file or running application is unchanged.
|
||||
|
||||
The inline Evidence result contains the artifact path, SHA-256, byte length,
|
||||
container format, architecture, word size, and byte order. When a `.dep-v0`
|
||||
section is present, `auditable_metadata` contains:
|
||||
|
||||
@@ -126,6 +126,9 @@ matching help retains original one-based line numbers. Empty query selects all.
|
||||
returns all remaining matches; CLI `--all` and `--limit` conflict.
|
||||
The window reports examined, matching and returned records and `has_more`.
|
||||
A filtered empty page is not evidence that the installation has no decoders.
|
||||
When sigrok reports a selected decoder ID as not installed, help and decoding
|
||||
return `invalid_request` naming `decoder` or `decoders`; omit `decoder` to list
|
||||
installed IDs. An installed decoder that fails to load remains an execution failure.
|
||||
|
||||
Discovery refuses more than 65,535 line separators before constructing record
|
||||
objects (65,536-line representation budget), in addition to the 4 MiB output cap.
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Plan
|
||||
|
||||
1. Move tool naming (`parameterNames`, `pathTemplate`, `toolName`,
|
||||
`compareTools`) from `environmentManifestRules.ts` to a new
|
||||
`environmentManifestNames.ts`, so the rules module has room for the rule.
|
||||
2. Add `prefix-variance` to `TEMPLATE_RULES`. A `prefix-variance` parameter
|
||||
records the rule it shares (`sharedRule`), which names it and keys it.
|
||||
3. Add the pass after `sibling-variance`: walk positions in order, index the
|
||||
opt-in parameters at each position by their preceding parts, template
|
||||
qualifying literals, then rebucket by naming key, keeping a tool's own rule
|
||||
for each merged position.
|
||||
4. Share the 32-segment split between the three comparing passes and list the
|
||||
segment-limited rules once for the limitation.
|
||||
5. Document the rule in the view schema description and in
|
||||
`docs/web-network-captures.md`.
|
||||
6. Tests: shared positions across methods and depths, the spelling condition,
|
||||
merges that keep a tool's own rule, pairs, format-rule positions and the
|
||||
segment limit.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Share templated positions across tools
|
||||
|
||||
Issue: https://github.com/morluto/rea/issues/4933
|
||||
|
||||
## Outcome
|
||||
|
||||
A session usually edits one scratch entity: it creates it, then updates and
|
||||
deletes it at a fixed path such as `/api/v1/collections/0RZ576QZQA5KG`. The
|
||||
manifest templates a segment only when sibling routes of the same method vary
|
||||
there, so those writes stay literal tools (`patch_collections_0rz576qzqa5kg`)
|
||||
even though the reads of the same collection were templated as
|
||||
`/api/v1/collections/{collection_id}`. A literal write tool addresses one
|
||||
entity that may not exist in a later state, and nothing can model its effect.
|
||||
|
||||
A new opt-in template rule, `prefix-variance`, templates such a literal with
|
||||
the parameter another tool already uses at that position, so the write becomes
|
||||
`patch_collections_by_collection_id` on the same template as the read.
|
||||
|
||||
## Requirements
|
||||
|
||||
- `prefix-variance` applies only when listed, after every other opt-in rule, so
|
||||
it can share the parameters they produce.
|
||||
- A literal at position `p` is templated when another tool on the same origin,
|
||||
of any method and any segment count, has a parameter at `p` from one of the
|
||||
other opt-in rules, after the same preceding parts. Parameters in the
|
||||
preceding parts compare by the rule that names them, so a position templated
|
||||
by `prefix-variance` matches the parameter it shares.
|
||||
- The literal qualifies when it is one of the values such a parameter
|
||||
observed at that position, when it carries a digit and has the length and
|
||||
character classes (digits, lower case, upper case, each other character) of
|
||||
one of them, or when every value the parameter observed, one or more, has one
|
||||
length of eight or more characters, as generated identifiers often do, and
|
||||
the literal has that length and uses only their character classes, so an
|
||||
identifier that happens to hold no digit still qualifies. An empty literal, a
|
||||
stop word or a `v1`-style version never qualifies. Each parameter's spelling
|
||||
is summarised once, so a literal is checked without rescanning its values,
|
||||
and a value longer than 128 characters is compared only exactly, so a huge
|
||||
segment costs no classification.
|
||||
- Positions templated by the four format rules are never shared, so
|
||||
`/api/teams/{numeric}` still absorbs no literal.
|
||||
- Values stay with the parameter that observed them: when parameters of
|
||||
different rules share a position, the literal shares the one that observed
|
||||
it, else the earliest one it is spelled like.
|
||||
- The parameter takes the name of the parameter it shares (`collection_id`,
|
||||
`uid`, a pair's `_namespace` and `_name`) and is labelled `prefix-variance`.
|
||||
- Tools whose routes now match, by method and by the rule that names each
|
||||
parameter, merge. A merged parameter keeps the rule of a tool that templated
|
||||
that position itself, when one did.
|
||||
- Like the sibling rules, it compares routes of at most 32 segments and says so
|
||||
in a limitation when a longer route exists.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- No change to the default rules or to any other rule: manifests that do not
|
||||
list `prefix-variance` are byte-for-byte unchanged.
|
||||
- No templating from response bodies, such as an id a create returned; the
|
||||
manifest reads request lines only.
|
||||
- No change to which groups are excluded: a write whose response has no body
|
||||
or content type outside `/api/` is still excluded as `non-json`.
|
||||
@@ -0,0 +1,10 @@
|
||||
# Tasks
|
||||
|
||||
- [x] Record the outcome, requirements and non-goals.
|
||||
- [x] Move tool naming into its own module.
|
||||
- [x] Add the `prefix-variance` rule, its names, its merge and its limitation.
|
||||
- [x] Document the rule in the schema and the capture guide.
|
||||
- [x] Add rule tests.
|
||||
- [x] Run static, formatting, duplication, documentation and test gates.
|
||||
- [x] Project the 51 corpus captures with and without the rule and record the results.
|
||||
- [x] Rebuild five randomly drawn environments end to end and compare them with their published versions and the live applications.
|
||||
@@ -0,0 +1,149 @@
|
||||
# Verification
|
||||
|
||||
Verified base: 33b0643e on main 1629266e (the rule, the alias removal `knip`
|
||||
asked for, and the fixed-length clause the end-to-end runs below led to). Executed on macOS with Node v22.23.1 (the repository pins
|
||||
24.18.0 in `.nvmrc`, which was not installed).
|
||||
|
||||
## Gates
|
||||
|
||||
- `npm run build:cached`, `npm run check:fast` (typecheck and lint),
|
||||
`npm run format:check`, `npx knip`, `npm run scan:todos`,
|
||||
`npm run docs:check`, `npm run verify:test-discovery` and
|
||||
`npm run mcp-catalog:check`: passed.
|
||||
- `npm run jscpd`: 3.49% duplicated lines over 3561 files with 3067 clones;
|
||||
main measures 3.49% with 3068, since the shared segment-limit split removes
|
||||
one clone.
|
||||
- oxlint reports no new finding on the changed files. The manifest accumulator
|
||||
keeps main's three warnings (file length, and the complexity and parameter
|
||||
count of its record append), one line longer.
|
||||
- `npx vitest run --project domain --project services`: 7119 passed, 5
|
||||
pre-existing skips.
|
||||
- `npm run test:prepare`, then `npm run test:focused --` the analysis-view MCP
|
||||
and CLI boundaries, the compact input schema and tool schema validity
|
||||
boundaries, and the environment serve and export boundaries:
|
||||
7 files, 76 passed.
|
||||
|
||||
New tests in `environmentManifestView.test.ts` cover:
|
||||
|
||||
- a literal shared across methods and depths, and the same capture without the rule;
|
||||
- the spelling condition: same classes and length, case, missing digit, a colon word, a version;
|
||||
- a digit-free member of a fixed-length identifier family, against a shorter word, a hyphenated
|
||||
value and a family shorter than eight characters;
|
||||
- merges that keep a tool's own rule, including a sibling-variance parameter under a shared one;
|
||||
- both halves of a templated pair;
|
||||
- format-rule positions and the segment limit.
|
||||
|
||||
## The showcase captures
|
||||
|
||||
The 50 showcase captures (45 HAR inspections and 5 `capture_browser_scenario`
|
||||
captures) were projected with main's build and this branch's.
|
||||
|
||||
- Without the rule, both builds give identical results for every capture: the
|
||||
manifest with no rules, the manifest with `after-uid-literal`,
|
||||
`opaque-token`, `sibling-variance` and `sibling-pair-variance`, and the
|
||||
environment-state view. 150 of 150 outputs hash equal.
|
||||
- With `prefix-variance` added to `after-uid-literal`, `opaque-token` and
|
||||
`sibling-variance`, 69 literal tools in 10 captures are templated, 25 of them
|
||||
writes:
|
||||
- Komga: collection and readlist `PATCH` and `DELETE`, book pages.
|
||||
- n8n: workflow `PATCH`, `DELETE` and archive, and the reads of a workflow
|
||||
whose id holds no digit.
|
||||
- Memos: memo `PATCH` and `DELETE`, user settings reads, and the reads of
|
||||
two memos whose ids hold no digit.
|
||||
- Navidrome: playlist `PUT` and `DELETE`.
|
||||
- Mealie: recipe `PATCH` and `DELETE`.
|
||||
- Grist: document `PATCH` and `DELETE`, and table record writes.
|
||||
- Redpanda Console: subject and topic writes.
|
||||
- Sentry: release `PUT` and `DELETE`.
|
||||
- Shlink: short URL `PATCH`.
|
||||
- Mattermost: `me` reads, which `sibling-variance` already folds into the
|
||||
user parameter.
|
||||
|
||||
Tools go from 1591 to 1578, because Redpanda Console's per-subject reads and
|
||||
the per-memo and per-workflow reads merge.
|
||||
|
||||
- Literals the rule leaves alone, as intended, include Espo CRM `layout`,
|
||||
Federal Register `facets`, Ghost `slug`, Shlink `stats`, Lychee
|
||||
`Metrics::photo` and Vault's path names.
|
||||
- The environment-state view succeeds on every capture with the rule. Its types
|
||||
move to the templated collections (531 become 526 as literal ones merge); the
|
||||
one fewer item view is the Redpanda Console merge.
|
||||
|
||||
With the write plans of #5600 (its branch with this commit and main merged in,
|
||||
locally):
|
||||
|
||||
- Served write tools rise from 33 to 39: Komga collection create, update and
|
||||
delete; n8n workflow delete; Sentry release update and delete.
|
||||
- Write tools with no state target fall from 102 to 87.
|
||||
- The newly modelled tools that stay unserved are limited by the capture:
|
||||
- no read after the write: Komga readlists, Mealie, Navidrome, Redpanda Console;
|
||||
- n8n's item read shows an expanded `shared` relation its create response
|
||||
never returned;
|
||||
- Shlink returns `tags` sorted while the update echoes the request's order.
|
||||
|
||||
## Five environments end to end
|
||||
|
||||
Five of the ten environments the rule changes were drawn at random, redrawing
|
||||
until the draw held one whose new writes are served: Komga, Mealie, n8n,
|
||||
Sentry and Shlink. Each was rebuilt on its own Linux VM with `npm pack` of
|
||||
#5600, main and this branch merged locally, from the same scoped HAR as its
|
||||
published version: manifest with `prefix-variance`, exported bundle, smoke
|
||||
task, the generated retrieval tasks for `gpt-oss-120b` and `GLM-5.3-Flash`, and
|
||||
a dry-run dataset. Where writes are served, hand-written write tasks ask for a
|
||||
change in plain language and are graded from the environment's state through
|
||||
`data/get`. The first n8n run found that a digit-free workflow id stayed
|
||||
literal; the fixed-length clause fixed it, and n8n was rebuilt.
|
||||
|
||||
| Environment | Tools (published → rebuilt) | Served from state (reads / writes) | Retrieval gpt-oss | Retrieval GLM | Writes gpt-oss | Writes GLM |
|
||||
| ----------- | --------------------------- | ---------------------------------- | ----------------- | ------------- | -------------- | ---------- |
|
||||
| Komga | 42 → 46 | 26 / 3 | 12/12 (was 11/12) | 12/12 (11/12) | 3/4 | 4/4 |
|
||||
| Mealie | 39 → 39 | 36 / 0 | 12/12 (12/12) | 12/12 (12/12) | – | – |
|
||||
| n8n | 30 → 33 | 17 / 1 | 9/9 (9/9) | 9/9 (9/9) | 2/2 | 2/2 |
|
||||
| Sentry | 34 → 34 | 26 / 3 | 12/12 (12/12) | 11/12 (12/12) | 2/4, rerun 0/4 | 4/4 |
|
||||
| Shlink | 17 → 17 | 5 / 0 | 5/7, rerun 7/7 | 7/7 (7/7) | – | – |
|
||||
|
||||
Every smoke task passed. The misses:
|
||||
|
||||
- Sentry writes with gpt-oss: every failed episode passed `id: "sentry"` for
|
||||
the `/api/0/` segment the tool schema describes as `observed: 0`, so its calls
|
||||
addressed `/api/sentry/…`; every passing episode, and every GLM episode, passed
|
||||
`0`. The served tools work; the format-rule parameter for a segment that only
|
||||
ever held `0` invites the guess.
|
||||
- Komga update with gpt-oss and Shlink's first gpt-oss run: the model provider
|
||||
rejected tool calls the model generated (`null` and `undefined` for optional
|
||||
query arguments) before the environment saw them.
|
||||
- Sentry `qa-03` with GLM: the model never called the alert-rules tool.
|
||||
|
||||
The same calls were also replayed against the live applications, seeded by
|
||||
the same scripts (ids differ, so each side maps its ids to names):
|
||||
|
||||
- Komga 1.29.1, 9 of 12 steps equal: create, update and delete of a
|
||||
collection and the reads after them agree except for the generated id. The
|
||||
collection list after a create omits the new collection, because that list
|
||||
keeps its recorded membership, and the 404 for a deleted collection replays
|
||||
the recorded body with its path and timestamp.
|
||||
- n8n 1.123.85, 3 of 8 steps equal: n8n refuses to delete a workflow that is
|
||||
not archived (400) and the environment deletes it; the workflow list replays
|
||||
its recorded response, so a delete does not show in it; archiving is not
|
||||
served. The read of the digit-free workflow failed in the first build (the
|
||||
state held only its list fields) and agrees in the second, apart from ids the
|
||||
seed generates.
|
||||
|
||||
## After the review round
|
||||
|
||||
The branch merged main at 52c84f6f, then kept each shared position's values
|
||||
with the parameter that observed them (one donor per naming rule, the literal
|
||||
taking the donor that observed it, else the earliest it is spelled like),
|
||||
summarised each donor's spelling once, and let one observation form a
|
||||
fixed-length family, as the requirement states. Two new tests, a mixed-rule
|
||||
position and a single observed workflow id, fail on the previous head and pass
|
||||
here. The gates above passed again (domain and services 7255 passed with 5
|
||||
pre-existing skips; the focused boundaries 76; `jscpd` 3.49%). Over the 50
|
||||
showcase captures the tools with and without `prefix-variance` are unchanged,
|
||||
name for name: 69 literal tools templated, 25 of them writes.
|
||||
|
||||
A second review round bounded the spelling summary: characters are classified
|
||||
in one pass, and a value longer than 128 characters is compared only exactly.
|
||||
Its test fails on the previous head, the gates passed again (domain and
|
||||
services 7257, focused boundaries 76, `jscpd` 3.49%), and the census over the 50
|
||||
captures is again unchanged.
|
||||
@@ -0,0 +1,32 @@
|
||||
# Implementation plan
|
||||
|
||||
1. In `environmentStateRules.ts`, parse pointers into tokens and let `at` and
|
||||
`replaceAt` read and replace element 0 of a one-element array at the root
|
||||
or in one member; extend `locateItem` with those forms after the object
|
||||
forms, requiring an identity name there; add `identityCandidates`, the
|
||||
identity names then suffix-named fields, and let `locateList` prefer arrays
|
||||
identified by name, then arrays of two or more items identified by suffix.
|
||||
2. In `EnvironmentStateExtraction.ts`, plan lists with the shared candidates,
|
||||
treat an empty recording as unconstraining, accept a suffix-named field only
|
||||
once a recording shows it distinct across two or more items, leave reads
|
||||
without a list or identity to documents, drop the written-path requirement
|
||||
and the `not-entity` fallback, record `path-varies` apart from
|
||||
`query-varies`, and keep each entity's earliest sighting;
|
||||
`environmentStateMerge.ts` cites records in timeline order. Remove
|
||||
`not-entity` from the reason type and result schema, add `path-varies`, and
|
||||
describe the new pointer forms and `field-name` basis.
|
||||
3. Move the classification of retained bodies (none, base64, cut, JSON, text)
|
||||
into `replayedBody` in `environmentSource.ts`, which owns recorded
|
||||
exchanges; replay renders from it and tool descriptions read its JSON case.
|
||||
4. Make `environmentToolDefinitions` take the `EnvironmentSource`; describe the
|
||||
first `2xx` JSON record, else the first JSON record labelled with its status,
|
||||
one level deep with the state's list rule and the existing sample budget;
|
||||
list the manifest tool's statuses; and charge the whole description and the
|
||||
tool's MCP annotations to the catalog reservation. Update the serve and
|
||||
bundle callers.
|
||||
5. Let the tool definitions own the MCP annotations derived from the method and
|
||||
the query-`POST` rule; `serveEnvironment.ts` registers them and the card
|
||||
leaves them out.
|
||||
6. Cover domain, services, adapters and the compiled MCP boundary; document the
|
||||
rules in the capture guide, descriptions and hints in the agent environments
|
||||
guide, and the contract text.
|
||||
@@ -0,0 +1,99 @@
|
||||
# Wider environment state coverage and tool descriptions
|
||||
|
||||
Issue: https://github.com/morluto/rea/issues/4933
|
||||
|
||||
## Outcome
|
||||
|
||||
The `environment-state` view backs more read tools with state, and a served
|
||||
environment tells agents more about each tool. Read-only paths whose responses
|
||||
are not entities become documents, listed items may be identified by an
|
||||
`…Id` or `…_id` field, an item wrapped in a one-element array is located
|
||||
inside it, and reads that vary by path get their own recorded reason. Each tool description says what the tool returns and which statuses
|
||||
were recorded, and every MCP tool carries method hints. This increment adds no
|
||||
tool, view kind, provider, network activity or write effect.
|
||||
|
||||
## Requirements
|
||||
|
||||
- A `GET` list tool (its template does not end in a parameter) that yields no
|
||||
item or list plan holds its latest initial value as a `document` when its
|
||||
initial reads have one request line, whether or not the capture writes its
|
||||
path, unless its value changed between two of those reads across any
|
||||
recorded write (even under another root), which leaves it `fields-differ`. A
|
||||
value whose rendered JSON exceeds 256 KiB stays `rendered-oversize` and is
|
||||
replayed from the recorded body, which itself fit. More request lines give
|
||||
`path-varies` when they differ by path (a template with a parameter before
|
||||
its end) and `query-varies` when they share one path. With every such read
|
||||
now a document, `path-varies`, `query-varies`, `body-unusable` or
|
||||
`rendered-oversize`, the unreachable `not-entity` reason leaves the result
|
||||
schema, and `no-identity` names item tools only. A document holds the value
|
||||
of its one `path`.
|
||||
- When no path parameter proves an identity and no identity name identifies
|
||||
the listed items, the `field-name` identity is the first key of the first
|
||||
listed item, in its order, whose name ends in `Id` or `_id`, that every item
|
||||
carries as a distinct string or number, and that at least one initial
|
||||
recording shows distinct across two or more items. The last condition goes
|
||||
beyond "every item carries it distinctly": one item satisfies that
|
||||
vacuously, and a lone item's suffix-named fields are often foreign keys (a
|
||||
reaction keyed by its user, a comment by its post), so a list that only ever
|
||||
held one item stays a document. Empty recordings constrain no field.
|
||||
Identity names keep precedence, also when choosing among an envelope's
|
||||
arrays, where a suffix-named field identifies only an array of two or more
|
||||
items.
|
||||
- An item response that is a root array of exactly one object, or an object
|
||||
with one member holding such an array, locates its entity at `/0` or
|
||||
`/<member>/0` when one of the identity names in that object repeats the path
|
||||
value. Objects at the root or in one member keep precedence. `at` and
|
||||
`replaceAt` read and replace exactly these forms besides the root and one
|
||||
member, so the gate and renderers run unchanged.
|
||||
- An entity's state order is its earliest sighting on the timeline and it cites
|
||||
its records in timeline order, whichever plan observed it first.
|
||||
- Each tool description reads `METHOD template; <returns>; recorded statuses
|
||||
…; replays retained records […]; evidence ev_…` after the untrusted-catalog
|
||||
warning. `<returns>` describes one level deep the first cited `2xx` record
|
||||
replay answers as JSON: an object's fields, an array of objects' fields, or
|
||||
an envelope whose member lists objects, where a list is an array of objects
|
||||
found by the state's list rule; an empty field set reads `with no fields`.
|
||||
Only when no `2xx` record replays as JSON does the first cited JSON record of
|
||||
another status give it, labelled `status <code> returns …`; with no JSON
|
||||
record it is omitted. The statuses are the manifest tool's `statuses`, the
|
||||
one owner of that set (`no recorded status` when it is empty). Field names
|
||||
and statuses are sampled within the description sample budget and charged
|
||||
with the whole description to the catalog reservation before it is retained.
|
||||
One owner in the environment source classifies each retained body as none,
|
||||
base64, cut, JSON or text; replay answers from that classification and
|
||||
descriptions read only its JSON case.
|
||||
- MCP tools carry `readOnlyHint` (true for the safe methods `GET`, `HEAD`,
|
||||
`OPTIONS` and `TRACE`, and for query `POST`s),
|
||||
`destructiveHint: true` for `DELETE` (unset for other writes, so the MCP
|
||||
default applies, and for reads, where clients ignore it), `idempotentHint`
|
||||
(true for the safe methods, `PUT` and `DELETE`) and `openWorldHint: false`. The
|
||||
tool definitions own the hints and charge them to the catalog reservation;
|
||||
the environment card keeps its `name`, `description`, `inputSchema` tool
|
||||
shape.
|
||||
|
||||
## Acceptance and limits
|
||||
|
||||
Synthetic captures cover read-only documents, `path-varies` and
|
||||
`query-varies`, suffix-named identities with their key order, their
|
||||
two-item proof, empty first recordings and their precedence (including the
|
||||
choice between an envelope's arrays), a Ghost-like `{"posts":[...]}` item under
|
||||
a trailing-slash path merging with its list view, a root one-element array, a
|
||||
one-element filtered list that stays unidentified, and the pointer forms. The
|
||||
Grafana-shaped fixture covers documents for its read-only paths (its one-member
|
||||
team list among them) and object, array and enveloped-list descriptions;
|
||||
synthetic sources cover the `2xx` preference over an earlier error body, the
|
||||
first of several JSON records, the labelled fallback, the manifest's statuses,
|
||||
empty, scalar and fieldless bodies, a truncated member name, a name whose
|
||||
JSON quoting exceeds the sample, a recorded body under 256 KiB whose rendered
|
||||
JSON exceeds it, non-JSON bodies and the catalog budget; the in-process and
|
||||
compiled MCP servers advertise the
|
||||
hints. A filtered list may still answer with one element whose identity name
|
||||
repeats the requested value; list filters, pagination, lossless big integers
|
||||
and cross-endpoint entity linking remain out of scope. Documents inline whole
|
||||
recorded values and enlarge the state result; agent tokens, CPU time and peak
|
||||
memory of the state and description build were not measured.
|
||||
|
||||
## Deferred issue criteria
|
||||
|
||||
Serving from the state, the AgentEnv data plane and write effects remain later
|
||||
increments of #4933. This PR must reference rather than close the issue.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Tasks
|
||||
|
||||
- [x] Record the coverage and description contract and its limits.
|
||||
- [x] Extend pointers, item location and identity candidates.
|
||||
- [x] Require two distinct items before a suffix-named field identifies a list.
|
||||
- [x] Hold read-only non-entity reads as documents, retire `not-entity` and
|
||||
separate `path-varies` from `query-varies`.
|
||||
- [x] Order entities by earliest sighting and cite records in timeline order.
|
||||
- [x] Classify retained bodies in one owner and describe tool responses,
|
||||
preferring `2xx` records, with the manifest's statuses.
|
||||
- [x] Advertise MCP tool annotations, charged to the catalog, without changing
|
||||
the card.
|
||||
- [x] Add domain, services, adapters and compiled-boundary coverage.
|
||||
- [x] Document the rules, descriptions and hints; update the contract text.
|
||||
- [x] Run static, formatting, duplication, documentation and test gates and the
|
||||
real-capture measurement.
|
||||
@@ -0,0 +1,123 @@
|
||||
# Verification
|
||||
|
||||
Verified base: 7a668b73f4783b42eb0e8ce1eeff079f86d53e22 (the environment-state
|
||||
view branch).
|
||||
|
||||
Executed on the implementation worktree with its existing locked installation
|
||||
under Node.js v22.23.1 (the repository pins 24.18.0, which was not available);
|
||||
every check below ran as written in this pass, after the last source change.
|
||||
|
||||
- `npm run format` then `npm run format:check`: passed.
|
||||
- `npm run check:fast`: typecheck and lint passed (3959 files, no errors). The
|
||||
touched files carry two lint warnings, both present on the base: `max-params`
|
||||
in `environmentReplay.ts` and an unused `_` in `environmentCapacity.test.ts`.
|
||||
- `npx knip`: passed (exit 0).
|
||||
- `npm run jscpd`: 3.40% duplicated lines over 3348 files, under the 3.5%
|
||||
gate. The three clones that touch changed test files pair the same blocks as
|
||||
on the base; none involves code this change adds.
|
||||
- `npm run scan:todos`: no markers.
|
||||
- `npm run docs:check`: the built documentation checks and the README
|
||||
consistency conformance test (5 tests) passed.
|
||||
- `npx vitest run --project domain --project services`: 341 files, 5859 tests
|
||||
passed, 5 pre-existing skips.
|
||||
- `npm run build:cached`: passed.
|
||||
- `npm run test:focused --` the environment serve adapters and capacity tests,
|
||||
the environment serve MCP boundary, the environment serve and export CLI
|
||||
boundaries, the environment serve shutdown process boundary, the
|
||||
analysis-view MCP and CLI boundaries, the compact input-schema contract and
|
||||
MCP boundary, the tool-schema validity boundary, the analysis-detail and
|
||||
advertised-input-example contracts and the qlog acceptance test: 14 files,
|
||||
113 tests passed, 1 pre-existing skip.
|
||||
|
||||
Real captures (outside the test suite): the built view ran through the
|
||||
application service on the same 44 recorded captures (39 HAR, 5 browser
|
||||
scenario) with all three template rules, in 7 to 50 ms each. 42 produced a
|
||||
state, and the same two browser-scenario captures are refused with
|
||||
`resource_constraint` as on the base. The base column is the brief's baseline,
|
||||
which the same script reproduced on the base build in an earlier pass; this
|
||||
pass did not rebuild the base.
|
||||
|
||||
| Measure | Base | This change |
|
||||
| ---------------------------------- | ----- | ----------- |
|
||||
| Types | 568 | 576 |
|
||||
| Entities | 2,213 | 2,246 |
|
||||
| Documents | 2 | 299 |
|
||||
| Item views | 211 | 213 |
|
||||
| List views | 497 | 504 |
|
||||
| Document views | 2 | 299 |
|
||||
| State-backed read tools (of 1,258) | 710 | 1,016 |
|
||||
| Recorded: `not-entity` | 306 | (retired) |
|
||||
| Recorded: `no-identity` | 129 | 32 |
|
||||
| Recorded: `path-varies` | (new) | 32 |
|
||||
| Recorded: `query-varies` | 5 | 69 |
|
||||
| Recorded: `body-unusable` | 32 | 32 |
|
||||
| Recorded: `list-differs` | 31 | 31 |
|
||||
| Recorded: `no-init-recording` | 26 | 26 |
|
||||
| Recorded: `query-body` | 12 | 12 |
|
||||
| Recorded: `fields-differ` | 3 | 4 |
|
||||
| Recorded: `envelope-varies` | 4 | 4 |
|
||||
|
||||
Seven list types gained a suffix-named identity (`permissionId`, `product_id`,
|
||||
`ItemId`, `user_id`, `channel_id`, `spl_id` and `eventId`). Seven more had one
|
||||
before the two-item proof and lost it, because every initial response listed a
|
||||
single item: an Airbyte organization, a Mattermost reaction and team
|
||||
membership, and a Redpanda broker and schema reference became documents; a
|
||||
NOAA station read is `query-varies` and a Redpanda consumer read
|
||||
`path-varies`. Two Ghost item tools render from `/members/0` and `/tags/0`. A
|
||||
third Ghost item tool is located at `/posts/0` but stays `fields-differ`: its
|
||||
recordings differ by an `include` query.
|
||||
|
||||
State result size, as the JSON length of each Evidence summed over the 42
|
||||
states: 2,677 KiB on the base and 3,196 KiB now (+19%), measured by the same
|
||||
script. The largest growth per capture is Metabase (133 to 236 KiB), Directus
|
||||
(21 to 93), Redpanda Console (26 to 68) and Vault (9 to 43). Documents take
|
||||
492,516 of the 3,274,243 UTF-8 bytes of the results now; the base held two.
|
||||
Agent tokens, CPU time and peak memory of the state view were not measured.
|
||||
|
||||
Tool descriptions on the 44 captures' manifests: all 44 catalogs were admitted
|
||||
within their reservation. 1,336 of 1,400 tools state what they return: 1,333
|
||||
from a `2xx` record and three labelled with another status (Miniflux and
|
||||
NocoDB 404, Shlink 501), because none of their records succeeded as JSON. The
|
||||
summaries add 261,502 bytes to a 1,185,893-byte catalog of names, descriptions
|
||||
and input schemas (median 136, 95th percentile 554, maximum 1,133 bytes per
|
||||
tool); five reached the field sample bound (one Keycloak, one Lychee and three
|
||||
Sentry tools with 46 to 105 fields). The MCP annotations add 113,182 bytes to
|
||||
`tools/list` and none to the card. Building a catalog took a median 1.6 ms and
|
||||
at most 7.6 ms (Metabase), after the source was loaded. Agent tokens, CPU time
|
||||
and peak memory of the description build were not measured.
|
||||
|
||||
After merging the environment state view's review fixes (its branch at
|
||||
6ad63bcc, which also brings main's evidence-file sources), every gate ran
|
||||
again on the merged tree: `npm run check:fast`, `npm run format:check`,
|
||||
`npx knip`, `npm run scan:todos` and `npm run docs:check` passed; `npm run
|
||||
jscpd`: 3.39% duplicated lines over 3362 files; `npx vitest run --project
|
||||
domain --project services`: 344 files, 5914 tests passed, 5 pre-existing
|
||||
skips; `npm run build:cached`, then `npm run test:focused --` the serve and
|
||||
tool-definition adapters, the serve MCP and CLI boundaries, the export CLI
|
||||
boundary, the analysis-view MCP and CLI boundaries, the compact input-schema
|
||||
budget and the analysis-detail and advertised-input-example contracts: 10
|
||||
files, 98 tests passed.
|
||||
|
||||
The real-capture comparison was repeated on the merged code, with the base
|
||||
measured on the merged state view without this change: all 44 captures now
|
||||
produce a state, and 1,011 of 1,277 read tools are state-backed against 625
|
||||
on the base (216 item, 416 list and 379 document views against 214, 409 and
|
||||
2). Recorded reasons: `no-identity` 216 to 32 and `not-entity` 310 to none;
|
||||
`query-varies` 5 to 76 and `path-varies` 36 are document reads under more
|
||||
than one query or path; `list-differs` 35, `body-unusable` 33,
|
||||
`no-init-recording` 28, `query-body` 12, `envelope-varies` 4 are unchanged,
|
||||
and `fields-differ` is 9 to 10.
|
||||
|
||||
Not covered here: serving from the state, the AgentEnv data plane and write
|
||||
effects, which are later increments.
|
||||
|
||||
## After the squash onto main
|
||||
|
||||
The branch was squashed onto main once the state-serve branch merged (166fb082). Against a merge of the previous head
|
||||
into that main, the squash keeps both sides of every conflict and drops nothing of this branch. Two tests then failed
|
||||
on it and were refitted with the oversized-document fix in 2a926a0a: the bundle test of a state catalog over the
|
||||
discovery budget uses 300 read tools, inside the window where the state's catalog is refused and replay's, with its
|
||||
response summaries, still fits (280–320 by a probe), and the rea-state validation test names the pushed document by
|
||||
the count of documents the state holds. The replay-only card test pinned main's 11,131-byte card; it now pins this
|
||||
branch's 12,818-byte card, whose descriptions name each tool's recorded responses. The branch then merged main at
|
||||
d7ca93cc without conflicts.
|
||||
@@ -0,0 +1,44 @@
|
||||
# Implementation plan
|
||||
|
||||
1. Export the Evidence file authenticator from `environmentSource.ts` with a
|
||||
`state` role, and validate a HAR capture there with the owned borrowing
|
||||
parse so later views reuse it. Add `environmentState.ts` to check state
|
||||
Evidence against a loaded source, build the served catalog (the tools a
|
||||
state serves and the data plane its card declares), derive the state from
|
||||
the capture through the analysis view service with the capture as retained
|
||||
Evidence, and prepare it: unavailable when its catalog exceeds the
|
||||
discovery budget under the served name or it cannot be derived.
|
||||
2. Add `environmentStateDocument.ts` to validate `rea-state/v1` documents
|
||||
against the served types and views, and `environmentStateStore.ts` for the
|
||||
live store with reset, atomic replace and the `data/get` snapshot.
|
||||
3. Export `selectsRecordedLine`, the body-taking `replayAnswer` and the path
|
||||
rule `pathValueMatches` from `environmentReplay.ts`, export one recorded-body
|
||||
predicate `stateBodyJson` from the state accumulator and `changesState` from
|
||||
the state rules, and widen `collectionPathOf` to any value with a path, so
|
||||
state answers reuse selection, matching, body and write rules.
|
||||
4. Add `environmentStateAnswer.ts` for item, list and document answers, the
|
||||
recorded fallback and the answer function serve and export share.
|
||||
5. Declare the state data plane on the card in `environmentTools.ts`, taking
|
||||
the data plane in an options object so the discovery budget reserves the
|
||||
card and descriptions actually served.
|
||||
6. Add `stateIntake.ts` for parts, files on this host and downloads
|
||||
(injectable fetcher and timeout, cancellation, coarse failure categories)
|
||||
and `environmentDataPlane.ts` for the three methods, run one at a time in
|
||||
arrival order and cancelled by the server's stop or the caller's
|
||||
departure; let `serveEnvironment.ts` serve the shared catalog and answer
|
||||
function, queue every message of a batch at arrival, bound the replies of
|
||||
one response and stop the data plane before closing the listener.
|
||||
7. Make `environment-serve` prepare the state under its served name after
|
||||
loading the source, add `--replay-only`, log an unavailable state as a
|
||||
warning before binding, and report `state` in the stopped document.
|
||||
8. Let `environment-export` prepare the state the same way under the bundle
|
||||
name, only after the name checks, and plan the served
|
||||
tool count, the verifier check from the shared answer function, the `serve`
|
||||
verifier and the README's serving section from it; report `state` in the
|
||||
export output and expect the served count in the hosted-lane script.
|
||||
9. Cover services, adapters, cli-boundary, mcp-boundary and process-boundary
|
||||
behaviour; document default serving, `--replay-only`, the fallback, the
|
||||
answers, the data plane, the card and the export.
|
||||
|
||||
No dependency, provider or REA tool contract changes. The only new network
|
||||
activity is an `https://` download that a `data/add` call names.
|
||||
@@ -0,0 +1,196 @@
|
||||
# Serve the environment from its state by default
|
||||
|
||||
Issue: https://github.com/morluto/rea/issues/4933
|
||||
|
||||
## Outcome
|
||||
|
||||
`rea environment-serve <manifest> --evidence <capture>` serves the environment
|
||||
from the initial state the capture observed, with nothing else to supply: at
|
||||
startup it derives the `environment-state` view of the capture in-process with
|
||||
the manifest's `template_rules`. Read tools whose views are state-backed answer
|
||||
from one live state, the `/agentenv` data plane implements `data/reset`,
|
||||
`data/add` and `data/get` against it, and the card advertises those operations
|
||||
and an intake declaration. `--replay-only` serves exactly the stateless replay
|
||||
main serves: every manifest tool replays its recordings, `/agentenv` answers every method as not found and the card is
|
||||
byte-identical. A state that cannot be derived, or whose catalog exceeds the
|
||||
discovery budget, starts the server in replay mode, logs why and reports it. Exported bundles serve the state by default,
|
||||
and their verifier and README match what they serve. Serving is read-only in
|
||||
this increment: write tools are not served from the state.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Derive the state in the application layer, shared by serve and export:
|
||||
`deriveEnvironmentState(source, capture, operation)` authenticates the
|
||||
capture value the command already read (an owned snapshot authenticated by
|
||||
the source load is reused, not parsed again), projects the
|
||||
`environment-state` view with the manifest's `template_rules` through
|
||||
`inspectAnalysisViewValidated` with the capture as retained Evidence (the
|
||||
Evidence id equals that of a projection by hand, and the capture's strings
|
||||
are not charged again as inline input, which refuses captures of a few MiB),
|
||||
then applies `loadEnvironmentState`: `inspect_analysis_view` Evidence of kind
|
||||
`environment-state`, its `parent_evidence_id` equal to the capture's, its
|
||||
`template_rules` equal to the manifest's in the same order, and every view
|
||||
naming a manifest tool, refusing otherwise with `invalid_request` whose issue
|
||||
path starts with `state`. The source validates a HAR capture with the owned
|
||||
borrowing parse, so the view reuses that validation.
|
||||
- `prepareServedState(source, capture, {name, operation})` first builds the
|
||||
state catalog under the served name, then derives the state, and reports
|
||||
`{served: true, evidence_id}` or
|
||||
`{served: false, reason: "unavailable", code, message}` with the refusal's
|
||||
projected code and message: a state catalog over the discovery budget is
|
||||
unavailable with `resource_constraint`, and no state is derived for it. A
|
||||
derived state whose catalog fits always serves from the state. The CLI
|
||||
reports `{served: false, reason: "replay-only"}` itself for `--replay-only`
|
||||
and derives nothing.
|
||||
- Keep one state store per server process, shared by every MCP session and the
|
||||
data plane: entities keyed by type, collection and id with per-collection
|
||||
order taken from the entities array, documents keyed by tool. `reset`
|
||||
restores the Evidence state, `replace` installs a validated document whole,
|
||||
and mutations are synchronous.
|
||||
- Answer item views by rendering the entity the path arguments name into the
|
||||
recorded envelope of `envelope_ordinal`. Match arguments as replay does: a
|
||||
held collection segment equal to the argument as written or after
|
||||
percent-decoding, preferring verbatim spellings, and the identity as the last
|
||||
argument percent-decoded, then as written, never re-split on `/`. Any held
|
||||
entity answers, and query arguments only set `replay.exact_match`. Refuse an
|
||||
entity the state does not hold, or one lacking a required field, as a tool
|
||||
error and never invent a body.
|
||||
- Answer list views from the state only when the arguments name one of the
|
||||
view's `checked_record_ordinals` exactly (every path and query value equal and
|
||||
no recorded query parameter unsupplied), choosing among them as replay
|
||||
chooses: every collection entity in state order for `membership: "all"`,
|
||||
otherwise the recorded members the state still holds. A member lacking one
|
||||
of the view's `required_fields` makes the call a tool error stating that the
|
||||
state holds no complete member, never a partial body, as for items. Lines
|
||||
recorded after a write or with other filters were never checked and answer
|
||||
from recordings.
|
||||
- Answer document views with the state's value when the arguments name the
|
||||
document's checked line exactly.
|
||||
- Answer recorded views, tools without a view and unrecorded requests from the
|
||||
recording, labelled `state: {source: "recording", reason}`; label state
|
||||
answers `state: {source: "state", view, …}` with the base record's replay
|
||||
provenance and `truncated: false`; refuse a state answer over 256 KiB as a
|
||||
tool error rather than cut it.
|
||||
- Serve `data/reset` (`{}`), `data/add` with exactly one `data` or `file` part
|
||||
(`bytes`, a `file://` regular file or an `https://` download with a 30 s
|
||||
timeout covering the body, no redirects and a streamed 32 MiB cap;
|
||||
`mimeType` when given is `application/json`) and `data/get` (`{parts:
|
||||
[{kind: "data", data: rea_state}]}`). A `file://` uri whose host is neither
|
||||
empty nor `localhost`, or whose path is a UNC path, is `-32602` before
|
||||
anything is opened. A document that `data/get` would write back past 32 MiB,
|
||||
once it adds the members a document may omit, is `-32602`, so a reported
|
||||
state always loads again. Anything else is `-32602`, including empty `parts`; a
|
||||
failed download is `-32000`; errors never echo a uri or content and name a
|
||||
coarse failure category in `error.data.reason`. Calls run one at a time in
|
||||
arrival order across requests; every message of a batch is queued when the
|
||||
batch arrives, so no other request's call lands between them, and
|
||||
notifications run without a reply.
|
||||
- Stopping the server (`close` or `prepareShutdown`) aborts the data plane's
|
||||
stop signal, and a request's own signal aborts when its client leaves: the
|
||||
download in progress ends with reason `cancelled`, queued calls are answered
|
||||
`-32000` with reason `cancelled` without running, and a `data/add` whose
|
||||
file read finished after the cancellation does not replace the state.
|
||||
- A `file://` read whose descriptor close fails answers `-32000` and keeps the
|
||||
descriptor in a server-lifetime owner. The next file read retries the close
|
||||
first and, while it still fails, answers `-32000` without opening the file.
|
||||
`close` retries it again and rejects while it is still open.
|
||||
- Bound one `/agentenv` response to 64 MiB of replies (twice the intake
|
||||
limit). Each reply is measured in bounded JSON parts as it is produced, in
|
||||
message order, and assembled only when it fits, so a reply past the budget is
|
||||
counted but never serialized whole. Room is kept for every later reply's
|
||||
budget error and for a batch's brackets and commas, so the body never
|
||||
passes the budget; a reply that does not fit is replaced by `-32000` with
|
||||
`data: {max_response_bytes, reply_bytes}`, unless that error is no smaller
|
||||
than the reply, so the body is never built past the budget and small write
|
||||
replies are kept.
|
||||
- Validate `rea-state/v1` documents against the served types and views: known
|
||||
types, collections that instantiate their template, ids equal to the identity
|
||||
field, unique keys, `view_fields` naming item or list views of the type
|
||||
without setting the type's identity field to a value whose scalar text
|
||||
differs from the entity's id (refused at that view's `fields`),
|
||||
documents naming document views once at the initial path, and the optional
|
||||
`state_evidence_id` and `types` that `data/get` reports equal to the served
|
||||
ones. Refuse numbers without an exact native value and `__proto__` members.
|
||||
Name the first problem by JSON pointer, never deeper than a caller-data
|
||||
member (`fields`, `value`, `types`), and leave the state unchanged.
|
||||
- Keep record citations Evidence provenance: refuse `record_ordinals` or a
|
||||
`record_ordinal` other than the Evidence's for that entity or document, and
|
||||
hold the Evidence's citations only for loaded values equal to the Evidence's;
|
||||
edited or added values cite none.
|
||||
- In state mode, declare `operations: ["data/reset", "data/add", "data/get"]`
|
||||
and the `urn:agentenv:intake/v1` extension, describe tools as answering from
|
||||
the state where it backs them, and leave out `POST`, `PUT`, `PATCH` and
|
||||
`DELETE` tools other than query `POST`s. The discovery budget reserves the
|
||||
card and descriptions actually served (`servedCatalog` returns the tools and
|
||||
the data plane the card declares). A state catalog can exceed the budget a
|
||||
replay catalog fits, so such a state is unavailable and the environment and
|
||||
its export serve replay: everything main served and exported is still
|
||||
served and exported.
|
||||
- The CLI has no `--state`; `--replay-only` (default false) serves replay
|
||||
without deriving. Otherwise it prepares the state under the name it serves
|
||||
(`ENVIRONMENT_NAME` or the manifest's). When the state is unavailable the
|
||||
command logs a warning with the code and message through its listener logger
|
||||
before binding, and serves replay. The stopped document's `state` member is
|
||||
the report. `serveEnvironment` keeps taking an optional prepared state and
|
||||
serves replay without one; the served catalog (`servedCatalog`) and the
|
||||
answer function (`environmentToolAnswer`) are shared with export.
|
||||
- `environment-export` keeps the bundle command
|
||||
`rea environment-serve /env/manifest.json --evidence /env/evidence.json` and,
|
||||
after its name checks, prepares the state under the bundle name as that
|
||||
server will, to predict what it serves, so a refused `--name` derives
|
||||
nothing; its report is served or unavailable, never replay-only. The
|
||||
verifier's `TOOL_COUNT` and the command's `tool_count` are the served tool
|
||||
count, and its check tool and expected status come from calling the server's
|
||||
answer function with `{}` on the first served `GET` tool without path
|
||||
parameters whose answer is not an error. The verifier and smoke task use the
|
||||
id `serve`. The README's "What the environment serves" section describes
|
||||
serving from the state, the replay fallback and `--replay-only`, says which
|
||||
applies to the bundle (with the code and message when the state is
|
||||
unavailable), and keeps the not-emulation and untrusted-content caveats. The
|
||||
export output adds `state`. The hosted-lane verifier script expects the
|
||||
served count.
|
||||
|
||||
## Acceptance and limits
|
||||
|
||||
Services tests cover derivation (the by-hand Evidence id and state, a capture
|
||||
the manifest was not projected from, a capture inline admission refuses),
|
||||
the prepared reports (served, unavailable for a `capture_browser_scenario`
|
||||
capture with header values but no response bodies, unavailable with
|
||||
`resource_constraint` for a 350-tool read-only manifest whose replay catalog
|
||||
fits), bundle plans served from the state and in replay (tool count, check tool
|
||||
and status, a check whose state answer differs from replay's in record and
|
||||
status, a check that skips a tool the server cannot answer, the replay fallback
|
||||
of that 350-tool manifest, name refusals before any preparation, a manifest
|
||||
neither mode admits, verifier, smoke task and README wording), the loader
|
||||
refusals, store reset, order, round trip and
|
||||
atomic replace, the first-problem pointers, citation provenance after a load and
|
||||
every answer path: item (including percent-encoded collection segments and
|
||||
ids), list `all`, list `recorded`, lines recorded after a write or with other
|
||||
filters, a line replay's tie-break would not pick, document, recorded view, tool
|
||||
without a view, unrecorded request, missing entity, missing required field and
|
||||
the body limit, a view value that changes an entity's identity, and a list
|
||||
member missing a required field. Adapters tests cover the data-plane shapes,
|
||||
`-32602` for empty and malformed parts and invalid documents, inexact numbers,
|
||||
bytes, `file://` and its failure categories, `file://` uris naming another
|
||||
host or a UNC path, injected https downloads (status, declared and streamed
|
||||
size, the timeout whether or not the fetcher honours its signal), the default
|
||||
fetch's refused redirects, arrival-order application across requests, a batch
|
||||
another request's reset cannot split, cancellation by the server's stop and by
|
||||
a departed caller, a server that closes while a download is stalled, a
|
||||
retained state-file close that the next file read and `close` retry, the
|
||||
response budget, batches and notifications, the card declaration, absent write
|
||||
tools, a served query `POST`, the per-mode discovery reservation and a
|
||||
`data/add` that changes the next tool answer over MCP. The mcp-boundary tests serve the state the
|
||||
built CLI derives from only a manifest and a capture, and `--replay-only` with
|
||||
every manifest tool, `-32601` data-plane answers and a card whose SHA-256
|
||||
equals that of the card main serves for the fixture; the process-boundary test checks the stopped document's
|
||||
`state` for a derived state, `--replay-only` and an unavailable state, and the
|
||||
warning logged before binding; the cli-boundary export test checks the served
|
||||
tool count, the verifier and the README of an exported bundle. No test reaches
|
||||
an external network. Write effects, list filters beyond recorded lines and
|
||||
`tables` in the intake declaration are out of scope.
|
||||
|
||||
## Deferred issue criteria
|
||||
|
||||
Write effects are a later increment of #4933. This PR must reference rather
|
||||
than close the issue.
|
||||
@@ -0,0 +1,32 @@
|
||||
# Tasks
|
||||
|
||||
- [x] Record the serving contract, requirements and deferred increments.
|
||||
- [x] Load and cross-check state Evidence for a served source.
|
||||
- [x] Add the store, the document validator and the snapshot.
|
||||
- [x] Answer item, list and document views from the state with recorded
|
||||
fallbacks.
|
||||
- [x] Serve the data plane and declare it on the card; leave write tools out.
|
||||
- [x] Address review: answer lists and documents only from checked lines,
|
||||
match item arguments as replay does, reserve the served card only, keep
|
||||
record citations Evidence provenance, and run data-plane calls in arrival
|
||||
order with a tested download timeout.
|
||||
- [x] Derive the state from the capture at startup, as retained Evidence, with
|
||||
the loader's checks; reuse the capture's validation.
|
||||
- [x] Replace `--state` with `--replay-only`, fall back to replay with a logged
|
||||
warning when no state can be derived, and report `state` when stopped.
|
||||
- [x] Derive the state in `environment-export` to plan the served tool count,
|
||||
the verifier check and the README; report `state` in its output.
|
||||
- [x] Add services, adapters and boundary coverage; remove the `--state` flag
|
||||
tests.
|
||||
- [x] Document default serving, `--replay-only`, the fallback, answers, data
|
||||
plane, document format, card and export.
|
||||
- [x] Address review: serve and export replay when the state's catalog
|
||||
exceeds the discovery budget, check the bundle name before preparing the
|
||||
state, keep replay-only out of export plans, test a check the state
|
||||
answers differently from replay, and pin main's replay card digest.
|
||||
- [x] Address review: bound one `/agentenv` response's replies, queue a
|
||||
batch's messages together at arrival, cancel the running download and
|
||||
queued calls when the server stops or the caller leaves, refuse
|
||||
`file://` uris naming another host or a UNC path, refuse view values
|
||||
that change an entity's identity, and apply list views' required fields.
|
||||
- [x] Run static, formatting, duplication, documentation and test gates.
|
||||
@@ -0,0 +1,79 @@
|
||||
# Verification
|
||||
|
||||
Verified base: 6676582675e08574146a812ae58cff67e2e53282 (this branch's head),
|
||||
with the review fixes of this pass uncommitted.
|
||||
|
||||
Executed on the implementation worktree on macOS with Node v22.23.1 (the
|
||||
repository pins 24.18.0 in `.nvmrc`, which was not installed). Every check
|
||||
below ran as written after the last source change, in this order.
|
||||
|
||||
- `npm run format` then `npm run format:check`: passed (4330 files).
|
||||
- `npm run check:fast`: typecheck and lint passed. The lint report holds 0
|
||||
errors and no diagnostic in any file this pass touches.
|
||||
- `npx knip`: passed (exit 0, no findings).
|
||||
- `npm run jscpd`: 3.37% duplicated lines over 3373 files (2800 clones), under
|
||||
the 3.5% gate; no clone involves a file this pass changed.
|
||||
- `npm run scan:todos`: passed, no markers.
|
||||
- `npm run docs:check`: the built documentation checks (6 tasks) and the README
|
||||
consistency conformance test (5 tests) passed.
|
||||
- `npx vitest run --project domain --project services`: 347 files, 5948 tests
|
||||
passed, 5 pre-existing skips.
|
||||
- `npm run build:cached` (the built output already included this pass's
|
||||
sources), then `npm run test:focused --` the serve CLI, MCP and process
|
||||
boundaries, the export CLI boundary, the CLI startup imports, the agentenv
|
||||
verifier identity boundary, the bundle package pin conformance test, the CI
|
||||
change scope boundary, the analysis-view CLI and MCP boundaries, and the
|
||||
`serveEnvironment`, `serveEnvironmentState`, `environmentCapacity` and
|
||||
`stateIntake` adapters tests: 14 files, 335 tests passed.
|
||||
- After this file was written: `npm run format`, `npm run format:check`,
|
||||
`npm run scan:todos` and `npm run docs:check` passed again.
|
||||
|
||||
The review fixes are covered by these tests, all passing in the runs above:
|
||||
|
||||
- Response budget: a batch of four `data/get`s over a loaded state of about a
|
||||
third of the budget keeps two results, answers the other two with `-32000`
|
||||
and `max_response_bytes`, keeps the trailing reset's `{}`, and its body stays
|
||||
within the budget.
|
||||
- Batch order: a batch `[data/add (gated download), data/get]` with a
|
||||
`data/reset` from another request sent while the download is held reports
|
||||
the loaded state from its `data/get`, and the reset applies last.
|
||||
- Cancellation: aborting the data plane's stop signal ends a stalled download
|
||||
(its fetcher's signal is aborted) and answers the queued reset as
|
||||
`cancelled` without running it; a call made after the stop does not run; a
|
||||
caller whose request signal aborts gets `cancelled` and the state is
|
||||
unchanged. Over loopback HTTP, `close()` of a served state returned while a
|
||||
download that never answers was in progress, and that download's signal was
|
||||
aborted.
|
||||
- File closes: with an injected close failure, `data/add` of a `file://` uri
|
||||
answered `-32000` without echoing the uri. The descriptor stayed open, and
|
||||
the next file load closed it before loading. While the close kept failing,
|
||||
over loopback HTTP the next file load answered `-32000` ("still open") and
|
||||
an inline `data` part still loaded. `close()` rejected with the unfinished
|
||||
close, then resolved and closed the descriptor once the close succeeded.
|
||||
Both tests fail on the previous head, which dropped the descriptor.
|
||||
- File hosts: `file://remote.example.test/...` and
|
||||
`file:////remote.example.test/...` are refused with the network-share
|
||||
message and no failure category; a `file://localhost/...` uri loads.
|
||||
- Loaded identity: `view_fields` setting `id` to `3`, `"3"` or `null` on user 2
|
||||
is refused at `/rea_state/entities/7/view_fields/0/fields`; `"2"` loads.
|
||||
- List required fields: a folder without `title` makes `get_folders` a tool
|
||||
error naming the incomplete entity.
|
||||
|
||||
That each test fails without its fix is source-derived; the fixes were not
|
||||
reverted to show it.
|
||||
|
||||
Not covered here: a Windows host (the UNC refusal ran on macOS, where
|
||||
`file:////host/share` converts to `//host/share`; the host check runs before
|
||||
any path conversion on every platform), a real `https://` download (tests
|
||||
inject the fetcher), the memory and time of a budgeted batch (not measured),
|
||||
agent token usage, a real AgentEnv framework run, a real-world capture, and
|
||||
write effects, which are a later increment.
|
||||
|
||||
After refusing bodies too deep for the state's own nesting (a recorded body
|
||||
must nest at most the JSON depth limit minus 16 levels to enter the state):
|
||||
`npm run check:fast`, `npm run format:check`, `npx knip`, `npm run scan:todos`
|
||||
passed; `npm run jscpd`: 3.37% over 3373 files; `npx vitest run --project
|
||||
domain --project services`: 347 files, 5950 tests passed, 5 pre-existing
|
||||
skips; `npm run build:cached`, then `npm run test:focused --` the serve CLI,
|
||||
MCP and process boundaries, the export CLI boundary and the two serve adapter
|
||||
tests: 6 files, 48 tests passed.
|
||||
@@ -57,7 +57,12 @@ triggers or arbitrary SQL.
|
||||
Rows are optional. `table` selects one exact ordinary-table name. `columns`
|
||||
(CLI repeated `--column`) selects exact visible column names in the requested
|
||||
order; omission selects all visible columns, including generated columns.
|
||||
Unselected cells are not evaluated or projected. Malformed column-name bytes
|
||||
Unselected cells are not evaluated or projected. A selected virtual generated
|
||||
column whose expression needs a function REA's connection lacks (extensions and
|
||||
application functions are not loaded), or raises an SQL error for a sampled
|
||||
row, is refused as `capability_unavailable`. The error names the table and
|
||||
each failing selected column with SQLite's message, and recommends only columns
|
||||
whose sampled values were read; stored and other generated cells stay readable. Malformed column-name bytes
|
||||
cause a format refusal when all columns are requested. In inventory scope, an explicit valid subset can
|
||||
still be sampled without decoding unrelated malformed column names.
|
||||
Column selection requires a
|
||||
@@ -102,8 +107,29 @@ bounds simultaneous input buffering and private snapshot/worker counts.
|
||||
|
||||
The database and WAL together are limited to 256 MiB. SQLite values/records,
|
||||
SQL statements and the complete worker JSON reply each have a 16 MiB limit.
|
||||
The owned worker has a 256 MiB JavaScript heap limit and a 30-second inspection
|
||||
deadline. SQLite native allocations are separate from the JavaScript heap;
|
||||
The owned worker has a 256 MiB JavaScript heap limit and defaults to a 30,000 ms
|
||||
deadline. Select optional MCP `worker_timeout_ms`, or CLI
|
||||
`--worker-timeout-ms <milliseconds>`, to change the budget for that call. Values
|
||||
must be integer milliseconds from 1 to 2,147,483,647 (the runtime timer range).
|
||||
It covers worker startup, queries and reply writing, **not** DB/WAL snapshot
|
||||
acquisition, final reply reads, cleanup or delivery. Allow corresponding headroom
|
||||
in the MCP client's whole-call deadline; increasing only that deadline does not
|
||||
change the worker budget. No server restart is needed.
|
||||
|
||||
The result's `worker_timeout_ms` reports the actual parent-supervised budget,
|
||||
including the default. Historical Evidence without this field has unknown
|
||||
execution settings, not an inferred default. Explicit input selection is also
|
||||
retained in Evidence parameters; omission stays omitted. Completed observations
|
||||
retained under cancellation or cleanup failure keep the same budget facts.
|
||||
Timeout errors name the selected milliseconds, exact CLI/MCP controls, and
|
||||
cleanup-before-retry requirements. Incomplete cleanup remains a blocker even
|
||||
when a larger budget is available.
|
||||
|
||||
For example, `rea inspect-sqlite-database ./application.sqlite
|
||||
--worker-timeout-ms 60000 --json` selects 60 seconds; equivalent MCP input is
|
||||
`{"path":"/artifacts/application.sqlite","worker_timeout_ms":60000}`.
|
||||
|
||||
SQLite native allocations are separate from the JavaScript heap;
|
||||
overall native heap and total resident memory are not capped. Row limits do not
|
||||
override these byte and resource limits. Resource-limit failures do not return
|
||||
an incomplete schema as successful complete evidence.
|
||||
|
||||
+135
-17
@@ -46,7 +46,37 @@ without executing tests or building. A missing Git base reports how to fetch
|
||||
it or select another revision.
|
||||
|
||||
Source typechecking needs no compiled runtime or generated test metadata.
|
||||
Typecheck, runtime compilation, and Frida binding verification share
|
||||
`scripts/run-typescript.mjs`. The pinned tsrs package supplies Linux x64/arm64
|
||||
(GNU and musl) and macOS arm64 compilers. Windows and other unsupported hosts
|
||||
retain the existing stable official TypeScript compiler. Its upstream version
|
||||
can differ from tsrs, so both compiler tasks hash the selected package and version
|
||||
through `scripts/run-turbo.mjs` before cache lookup. Outputs from different
|
||||
compilers occupy different cache entries. Repository npm scripts and focused-test
|
||||
preparation use that entrypoint; a raw Turbo compiler task without matching
|
||||
identity fails instead of publishing an ambiguous successful cache entry.
|
||||
A missing binary on a supported host also fails without silently falling back.
|
||||
|
||||
The Rust compiler defaults to at most two checker threads. For `--noEmit` checks,
|
||||
`--maxMemory 3G` also sets a soft memory target; emit builds do not use that target.
|
||||
Explicit compiler arguments can override the defaults. These controls do not
|
||||
impose a process-family memory limit. Termux's explicit build, Stryker's compiler
|
||||
API dependency, and independent fixture compiler oracles keep their existing
|
||||
TypeScript versions.
|
||||
|
||||
`npm run build:cached` compiles the CLI/MCP runtime and its packaged skill.
|
||||
The build also records `dist/mcp-catalog.json` (compact inputs) and
|
||||
`dist/mcp-catalog-full.json` from the canonical SDK registrations and binds
|
||||
each to the runtime with its own SHA-256 digest. These are
|
||||
runtime artifacts, separate from the test catalog below. Default target-free
|
||||
MCP startup serves its schemas without constructing analysis validators;
|
||||
the first tool or guided-workflow request materializes the canonical runtime
|
||||
on that same SDK server. Explicit compact/full input selections preserve
|
||||
their advertised schemas throughout materialization. Initial-target,
|
||||
HTTP and output-schema-off startup keep the eager path; source runs without
|
||||
recorded artifacts also use eager composition. Compare memory both after discovery and after a completed
|
||||
request; report diagnostic GC separately from normal resident memory.
|
||||
|
||||
Turbo's strict task environment preserves caller-selected `GOMAXPROCS`,
|
||||
`GOMEMLIMIT`, and `UV_THREADPOOL_SIZE` for resource-constrained builds and
|
||||
checks. These execution controls do not change artifact content, so changing
|
||||
@@ -78,8 +108,9 @@ without the artifacts lock, so it can record hashes while `check:pr` or
|
||||
`check:test` already holds that lock. The CI jobs still run the locked
|
||||
`check:ci:fast` and `check:ci:deep` commands.
|
||||
Use `npm run lint:details` or `npm run jscpd:details` for all console diagnostics.
|
||||
Both duplicate commands scan production and test code with the same 3% limit;
|
||||
the summary commands preserve checker failures and restore reports from cached
|
||||
Both duplicate commands scan production and test code using the limit in
|
||||
[`.jscpd.json`](https://github.com/morluto/rea/blob/main/.jscpd.json).
|
||||
The summary commands preserve checker failures and restore reports from cached
|
||||
static tasks. Both lint caches include the website, documentation configuration,
|
||||
and experiment code scanned by the checker; a regression compares the actual
|
||||
lint inventory with Turbo's resolved inputs.
|
||||
@@ -155,7 +186,27 @@ rejection without a reason. That cleanup stays owned until a later close or
|
||||
call releases it. Another server does not open while the cleanup remains, and
|
||||
a cleanup that already succeeded is not run again. Pass
|
||||
`mcpCall` when a case needs its own server, environment, or lifecycle. CLI
|
||||
cases still start a fresh process.
|
||||
cases for that helper share one compiled CLI process per child environment.
|
||||
The first case pays process startup; later cases reuse the loaded runtime.
|
||||
The process restarts when the environment changes, after 32 commands, or when
|
||||
the worker reports a resident set of at least 1 GiB. A fatal worker failure
|
||||
or a broken session frame retires that process and waits for it to exit before
|
||||
the next command starts.
|
||||
`cli.run` still starts a fresh process, including stdin and explicit deadlines.
|
||||
`runFileCli` uses the file session for commands that have neither. Go binary,
|
||||
IL2CPP metadata, and dylib-resolution commands use that session. File teardown
|
||||
stops the shared CLI process, including startup still in flight, and does not
|
||||
open another after close.
|
||||
`exportedFunctionBindingsCli.test.ts` keeps its own compiled CLI parity
|
||||
process for the file and still compares that process's JSON command results
|
||||
with the MCP session. A command that does not respond is rejected. That
|
||||
process stays owned until it exits, and another process does not start while
|
||||
it remains. A process that stays running after SIGKILL remains owned so a
|
||||
later close can retry. Closing the session reports a failure when the process
|
||||
does not exit after stdin closes, once the child has been stopped.
|
||||
`applicationWorkflowCli.test.ts` keeps one compiled CLI process for its JSON
|
||||
commands, including a non-zero status whose stdout is still a JSON document,
|
||||
and closes that process after the file.
|
||||
|
||||
The Apple artifact verifier step shares a job-temporary bytecode cache among
|
||||
its fresh CLI/MCP children via `REA_ARTIFACT_NODE_COMPILE_CACHE`. The artifact
|
||||
@@ -212,6 +263,27 @@ and retain representative compiled CLI parity checks. Every distinct source
|
||||
scenario still runs through the public workflow; session-lifecycle scenarios
|
||||
need their own sessions and cleanup assertions.
|
||||
|
||||
When a matrix already holds a named tool definition from live `tools/list`,
|
||||
pass that definition through the SDK's `toolDefinition` call option. This keeps
|
||||
the selected output-schema validation without eagerly compiling unrelated
|
||||
catalog schemas. Re-read definitions if the server advertises a changed list.
|
||||
|
||||
Artifact verification uses `artifactMcpCall` for both lifecycle and analysis
|
||||
calls. A fresh SDK client has no held tool listing, so a bare `callTool` can
|
||||
skip output-schema validation. The helper discovers actual advertised
|
||||
definitions, rejects missing or ambiguous schemas, and validates the requested
|
||||
tool without compiling unrelated catalog schemas. REA registers process-static
|
||||
tool contracts; bindings share one discovery per negotiated connection and are
|
||||
discarded on reconnect or failed discovery. Keep raw artifact calls on this
|
||||
shared path and retain explicit request options such as timeouts.
|
||||
Caller-supplied tool definitions are rejected: the helper owns selection from
|
||||
the advertised catalog so a stale or permissive schema cannot bypass it.
|
||||
|
||||
The regression fixture changes only `canonical_path` in a real stdio response
|
||||
to a number. The old helper accepts that response; the named schema must reject
|
||||
it. This client-boundary fault injection does not establish native Apple
|
||||
behavior, which remains covered by the macOS verification lane.
|
||||
|
||||
Report unavailable authority as a named skip. Await owned cleanup before a
|
||||
verifier reports success. Native process inspectors are released at Vitest
|
||||
worker teardown; fork termination does not run Node exit hooks, and per-file
|
||||
@@ -271,7 +343,23 @@ termination. Simulated Windows controls do not establish native Windows behavior
|
||||
Native process-ownership controls distinguish start identity, zombie lifecycle,
|
||||
current parent/group relation, and token-read evidence. Retain generation-bound
|
||||
candidates through smaller lineage observations, table omissions, reparenting,
|
||||
group changes, and failed cleanup retries. A readable token with unavailable
|
||||
group changes, and failed cleanup retries. Identityless exit-refresh controls
|
||||
cover a replacement row that is not linked to the prior descendant set: a
|
||||
matching token on its own group is signaled, a foreign or absent token is not,
|
||||
an unreadable live token stays unresolved, a replacement that appears only in
|
||||
the confirmation table is still token-checked, a group discovered during
|
||||
revalidation is signaled before cleanup succeeds, a member that changes groups
|
||||
during confirmation is signaled in its new group, a PID first seen with a
|
||||
foreign token is read again on the confirmation table, a PID whose token was
|
||||
already read is read again even when its parent and group return to the
|
||||
pre-exit values, a pre-existing PID is read again when its parent or group
|
||||
changes, an unchanged pre-existing row that was never token-read stays unread,
|
||||
an unbounded confirmation
|
||||
chain stays unresolved, lineage reads a row again when its launcher-tree
|
||||
membership changes, a cached lineage token is read again on the next refresh, an initial descendant whose token already matched is read again on a later refresh, the launcher is read again on that refresh and a missing, unowned, or relation-changed launcher PID stays unavailable, a descendant absent from the latest refresh is omitted,
|
||||
a group that reappears after it was processed is revalidated once, a further
|
||||
reappearance stays unresolved, lineage publishes one row per PID, and lineage does not publish a
|
||||
verified empty descendant list while that row remains unexamined. A readable token with unavailable
|
||||
identity stays unresolved. Native UID facts, rather than an earlier process-table
|
||||
row, determine whether a token denial concerns another user. Darwin tests compile
|
||||
the helper and exercise snapshot growth, absence, lifecycle, and UID observations;
|
||||
@@ -484,9 +572,15 @@ reports even when a shard fails, uploads available diagnostics, and writes the
|
||||
slowest files to the workflow summary. Partial reports are marked diagnostic
|
||||
only. Failed, cancelled, or missing selected shards still fail the required gate,
|
||||
and aggregate coverage thresholds remain enforced in full qualification.
|
||||
Only successful complete full-tier merges publish the small `test-timings` artifact, with
|
||||
checkout-relative paths; the build job downloads that artifact for the sequencer
|
||||
instead of the coverage/JUnit bundle. Timing weights come from Vitest module
|
||||
Only a successful complete merge on the default branch publishes shard history,
|
||||
and only from a push, schedule, or manual run. Fast runs publish
|
||||
`test-timings-fast`. Full runs publish `test-timings-full`. Pull requests do not
|
||||
publish it: the lookup reads one unpaginated artifact page, and pull-request
|
||||
artifacts would crowd out the default branch. The build job downloads the
|
||||
artifact that matches its tier, so fast shards use durations measured without
|
||||
coverage and full shards keep coverage-weighted durations. A tier with no
|
||||
qualifying artifact leaves history unset. The download is that small
|
||||
checkout-relative timing file, not the coverage/JUnit bundle. Timing weights come from Vitest module
|
||||
diagnostics and include tests and hooks, worker preparation, environment,
|
||||
imports, and setup. Import timings already include transform waits, which are
|
||||
not added again. The weights describe file costs under the measured worker and
|
||||
@@ -605,11 +699,22 @@ missing entries are omitted as whole entries, and consumers rebuild cache misses
|
||||
including when every entry is unavailable. Malformed plans, non-file entries,
|
||||
and I/O errors other than disappearance still fail publication. After a trusted
|
||||
static run, superseded cross-run Turbo snapshots for that OS and architecture
|
||||
are deleted down to the two newest generations. The Windows lane relies on the Linux static job for typechecking. They retain the normal build and prepack
|
||||
commands, which restore matching outputs or rebuild on a cache miss. Native
|
||||
are deleted down to the two newest generations. The Windows lane also runs the
|
||||
official compiler's complete source typecheck with two checker threads,
|
||||
independently of the accelerated Linux checker. Both lanes retain the normal
|
||||
build and prepack commands, which restore matching outputs or rebuild on a cache
|
||||
miss. Native
|
||||
artifacts, dependency installs, package archives, and runtime verification remain
|
||||
host-local. Keep platform-dependent outputs out of this shared cache.
|
||||
|
||||
The Windows native verifier's private-runtime ACL observer reads SID rules once
|
||||
for both trustee validation and counting. It deliberately rejects the convenience
|
||||
`Access` property, which resolves account names. Its `private-runtime-acl` stderr
|
||||
markers report completed phases and elapsed time; inspect these on a timeout
|
||||
before attributing it to startup, ACL reads, or identity lookup. The original
|
||||
15-second deadline and all ownership, DACL, and readonly assertions remain in
|
||||
force. A passing retry alone does not explain a previous timeout.
|
||||
|
||||
Record cold and warm preparation separately from fresh test execution when
|
||||
benchmarking the optional `npm run check:pr` gate. Compare multiple runs on the
|
||||
same host, including subprocess and queue costs; a cached pass is not a test
|
||||
@@ -1353,11 +1458,22 @@ catalog, and managed-conformance metadata. Each shard still installs the locked
|
||||
dependencies and runs its assigned tests; full qualification enables coverage. It no longer
|
||||
regenerates the same metadata independently.
|
||||
|
||||
The build job also finds an available `test-timings` artifact from a successful
|
||||
trusted default-branch scheduled or manual qualification and includes that same
|
||||
report in each shard's snapshot. The bounded lookup verifies the artifact's
|
||||
producer; newer schedules that reuse qualification without producing timings do
|
||||
not hide the last full run's artifact.
|
||||
The build job finds the newest trusted timing artifact for its tier
|
||||
(`test-timings-fast` or `test-timings-full`) from a successful default-branch
|
||||
push, schedule, or manual CI run, and includes that same report in each shard's
|
||||
snapshot. The bounded lookup verifies the producer. Pull-request runs and other
|
||||
branches are not producers. A tier with no qualifying artifact leaves history
|
||||
unset, and Vitest uses its own assignment. A later schedule that reuses
|
||||
qualification without uploading timings leaves the previous artifact in place.
|
||||
|
||||
On 2026-10-21 the newest full history was run
|
||||
`39545047294`, recorded before compiled-CLI session reuse. Fast run
|
||||
`39552964873` packed its eight built shards from that history, and those shard
|
||||
jobs executed for 319–591 seconds. Replaying that run's file durations through
|
||||
the sequencer's two-worker schedule balances every shard at about 404 seconds
|
||||
of file time. The same replay with the stale history weights leaves the slowest
|
||||
shard near 547 seconds and the fastest near 293. That spread is file-schedule
|
||||
time, not runner queue, which is why each tier keeps its own history.
|
||||
CI assigns discovered files by historical duration, with a deterministic
|
||||
fallback weight for new files, rather than dividing only by file count.
|
||||
Each file keeps its full duration on one worker. Extra workers overlap other
|
||||
@@ -1700,9 +1816,11 @@ projects the `environment-manifest` view with all three template rules through
|
||||
the built CLI, packs the checkout with `npm pack`, exports the bundle with
|
||||
`--package-tarball` so the image installs this checkout rather than the
|
||||
registry package, and runs `agent-env run` on the bundle. It checks that the
|
||||
export reports the planned file set with the inputs copied byte-exact, that
|
||||
the runner exits `0` with `tasks/smoke.json` reported as passed and the
|
||||
verifier's description naming the tool count, and that no container exists
|
||||
export reports the planned file set with the inputs copied byte-exact and a
|
||||
bundle served from the derived state, which serves fewer tools than the
|
||||
manifest because write tools are not served, that the runner exits `0` with
|
||||
`tasks/smoke.json` reported as passed and the verifier's description naming
|
||||
that served tool count, and that no container exists
|
||||
after the run that did not exist before; the container inventory runs even when
|
||||
the run fails or times out, so a failed receipt still lists what it left. The one exception is the framework's
|
||||
own image-store helper, `agentenv-registry` (or `agentenv-registry-<port>`),
|
||||
|
||||
@@ -59,7 +59,7 @@ harm_rank,location,trigger,current_copy,user_risk,proposed_replacement,implement
|
||||
46,src/application/Uninstall.ts:removeManagedPath symlink,Managed cache/state/skill path is a symbolic link,Refused to follow symlink {path}.,Exposes local path and does not explain manual safety check,"REA did not remove this item because its managed path is a symbolic link. Verify the link target before removing it manually.",implemented,focused assertion passed
|
||||
47,src/application/Uninstall.ts:removeManagedPath failure,Managed item removal fails,{path} could not be removed.,Exposes local path and gives no recovery,"This item could not be removed. Check file permissions, then rerun uninstall.",implemented,verified by injected managed-path removal failure test
|
||||
48,src/application/DoctorDiagnostics.ts:node,Runtime version is outside supported ranges,"Install Node.js 22.x (>=22.19), 24.x (>=24.11), or 26+.",Low risk; exact dependency recovery,Keep current copy,unchanged,verified by doctor unit test
|
||||
49,src/application/Doctor.ts:host,Host OS/distribution is unsupported,"REA supports macOS 12+, Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, and CachyOS.",Low risk; clearly states supported choices,Keep current copy,unchanged,verified by doctor unit tests
|
||||
49,src/application/DoctorDiagnostics.ts:host,Host OS/distribution is unsupported,"REA supports macOS 12+, Linux distributions with a recognized apt, dnf, or pacman package family, and the experimental Windows x64 Ghidra P0 boundary; automated Hopper setup additionally requires Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, CachyOS, or Omarchy.",Low risk; clearly states supported choices,Keep current copy,unchanged,verified by doctor unit tests
|
||||
50,src/application/Doctor.ts:analysis engine,Optional deep-analysis executable cannot be found,"Run rea setup to install Hopper, or set HOPPER_LAUNCHER_PATH.",Low risk in setup-specific diagnostic; exact recovery paths,Keep current copy,unchanged,verified by doctor unit tests
|
||||
51,src/application/Doctor.ts:target,Optional target path fails shared validation,Supply a readable local app or program path.,Low risk; tells caller valid target class,Keep current copy,unchanged,verified by doctor unit test
|
||||
52,src/application/Setup.ts:approval,Setup plan lacks approval,"Review the setup plan, then rerun interactively or with --yes.",Low risk; exact authorization recovery,Keep current copy,unchanged,verified by setup unit tests
|
||||
@@ -70,7 +70,7 @@ harm_rank,location,trigger,current_copy,user_risk,proposed_replacement,implement
|
||||
57,src/application/Setup.ts:unsupported platform,Platform is neither macOS nor Linux,REA supports Hopper on macOS and selected 64-bit Linux distributions.,Low risk; states support boundary,Keep current copy,unchanged,verified by setup unit test
|
||||
58,src/application/SetupHost.ts:unsupported Node,Runtime version cannot run setup,"Install Node.js 22.x (>=22.19), 24.x (>=24.11), or 26+ and rerun setup.",Low risk; exact dependency and retry,Keep current copy,unchanged,verified by setup host tests
|
||||
59,src/application/Setup.ts:unsupported macOS,macOS version is missing or older than 12,Upgrade to macOS 12 or newer.,Low risk; exact support floor,Keep current copy,unchanged,verified by setup host tests
|
||||
60,src/application/Setup.ts:unsupported Linux,Linux distribution is outside supported set,"REA supports Hopper on Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, and CachyOS.",Low risk; exact supported alternatives,Keep current copy,unchanged,verified by setup unit test
|
||||
60,src/application/SetupHost.ts:unsupported Linux,Linux distribution is outside supported set,"Automated Hopper setup supports Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, CachyOS, and Omarchy; configure an existing supported provider instead.",Low risk; exact supported alternatives,Keep current copy,unchanged,verified by setup unit test
|
||||
61,src/application/process/ProcessCli.ts:readJson read,Process scenario or evidence file cannot be read,Raw filesystem exception through CLI framework,Can expose local paths/codes and no recovery,"Process input file could not be read. Check that the path exists and is readable.",implemented,verified by focused CLI test
|
||||
62,src/application/JsonInputFile.ts:memory admission,Projected process JSON value exceeds available heap headroom,Insufficient heap headroom to materialize the complete JSON value,Heap admission depends on live runtime capacity rather than a fixed 64 MiB file limit,"Provide a smaller valid JSON value. For Evidence workflows, re-analyze a smaller selection of the original target and use its complete Evidence; splitting JSON text or trimming Evidence fields does not produce valid workflow input.",implemented,Source verified against shared JSON reader and recovery constant; former fixed-size refusal is superseded
|
||||
63,src/application/process/ProcessCli.ts:readJson parse,Process scenario or evidence file is malformed JSON,Raw JSON parser exception through CLI framework,Can expose parser implementation and lacks recovery,"Process input file is not valid JSON. Repair the file, then try again.",implemented,verified by focused CLI test
|
||||
|
||||
|
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,286 @@
|
||||
# Static GPU code-object verification
|
||||
|
||||
The [receipts](gpu-code-objects-2026-10-21.json) pin the measured runtime tree,
|
||||
publisher URLs/digests, actual commands, completed answers and resource costs.
|
||||
Downloaded binaries, toolchains and complete Evidence bundles remain outside Git.
|
||||
|
||||
## Correctness
|
||||
|
||||
NVIDIA CUDA 12.9.1 redistribution archives were verified against their publisher
|
||||
manifest. nvcc 12.9.86 compiled a small owned kernel for sm_80 and sm_90a with
|
||||
uncompressed, size-compressed and speed-compressed fatbins. cuobjdump 12.9.82
|
||||
independently confirmed two parameters at offsets 0/8 with sizes 8/4, 12 parameter
|
||||
bytes, 10 physical registers and architecture-dependent shared memory. Separate
|
||||
PTX/CUBIN and a host ELF object exercised the same parser boundaries.
|
||||
|
||||
Clang 14 produced a gfx900 HIP bundle and AMDGPU ELF object; llvm-readelf supplied
|
||||
the MessagePack metadata oracle. An LLVM 19 offload bundler produced a real CCOB
|
||||
v2 Zstd bundle. All nine producer artifacts were reread on the final runtime
|
||||
source with complete payload coverage. CCOB v1/v3 and zlib have portable boundary
|
||||
fixtures, rather than real producer verification.
|
||||
|
||||
Released Linux and Windows nvJPEG 12.4.0.76 artifacts each contain 165 CUBIN and
|
||||
10 PTX payloads, with 3,968 kernel declarations across 15 target declarations.
|
||||
Independent extraction matched all 165 decoded CUBIN hashes and all 10 PTX byte
|
||||
sequences; cuobjdump resource output matched all 3,720 native kernel
|
||||
name/register/shared-memory tuples. Pre-review MCP workflows rechecked the Linux
|
||||
sm_100 subset's 248 complete kernel facts against those prior oracle facts.
|
||||
The pre-review public CLI analyzed the entire Windows DLL, exported complete
|
||||
Evidence, and reproduced all previously verified facts exactly.
|
||||
|
||||
Windows validation ran on Linux: LLVM independently identified the PE section
|
||||
coordinates, and cuobjdump consumed its extracted fatbin. cuobjdump did not
|
||||
recognize the DLL directly. This does not establish Windows runtime behavior,
|
||||
GPU execution, host launch correlation or legacy AMDGPU YAML support.
|
||||
|
||||
## Initial completed MCP workflows
|
||||
|
||||
Both fresh stdio MCP sessions analyzed only `sm_100` in the same Linux library,
|
||||
retained 176 inventory objects and 248 kernel facts, queried the same named
|
||||
kernel, exported Evidence, and repeated the historical query three times.
|
||||
The complete variant returned the selected-target report; the selected variant
|
||||
returned a same-call kernel page. Both preserved the exact answer: one parameter
|
||||
of 168 bytes, 31 physical registers and 9,216 shared bytes.
|
||||
|
||||
| Cost | Complete report | Selected page |
|
||||
| --------------------------------------------------------------- | ----------------: | -----------------: |
|
||||
| Used input declarations + three primary calls, estimated tokens | 406,862 | 26,106 |
|
||||
| All input declarations + primary calls, estimated tokens | 635,381 | 254,625 |
|
||||
| Full advertised catalog + all six calls, estimated tokens | 1,475,258 | 1,094,502 |
|
||||
| Process-family elapsed seconds | 15.492 | 15.443 |
|
||||
| Process-family CPU seconds | 18.220 | 18.074 |
|
||||
| Sampled peak family RSS bytes | 1,139,601,408 | 1,321,566,208 |
|
||||
| First inspection milliseconds | 8,572 | 8,810 |
|
||||
| Three warm retained-page calls, milliseconds | 10.7 / 10.6 / 9.8 | 12.0 / 11.4 / 10.6 |
|
||||
|
||||
Tokenx estimates include advertised schemas, arguments and full SDK replies;
|
||||
they are not actual model usage. Text and structured reply representations are
|
||||
both counted. Initialization and JSON-RPC envelopes are unmeasured. Complete
|
||||
catalog discovery substantially reduces the overall percentage saving.
|
||||
|
||||
These are workflow variants on the same implementation, not a before/after
|
||||
parser speed benchmark. Node compile caching was disabled, but OS caches and
|
||||
unrelated host load were uncontrolled. No general latency, CPU or memory
|
||||
improvement is established. The selected workflow used more peak memory in this
|
||||
pair. An earlier all-target complete reply exceeded the existing transport guard;
|
||||
that incomplete attempt is excluded from the completed comparison.
|
||||
|
||||
The full Windows DLL CLI task took 4.064 seconds / 4.909 CPU seconds /
|
||||
503,459,840 peak family RSS bytes. All profiled completed tasks stayed within
|
||||
the 8 GiB and 420 second guards, using two CPU affinities. Peak RSS sums payload
|
||||
descendants every 20 ms and is approximate; the observer is excluded.
|
||||
|
||||
## Regression checks
|
||||
|
||||
- The initial focused run passed 265 tests in 19 files: GPU domain/codec/parser
|
||||
cases, public CLI/MCP, retained views, output profiles, cancellation and cleanup,
|
||||
plus shared ELF/PE Go, Rust and IL2CPP consumers.
|
||||
- Full static checks passed before the catalog/docs-only follow-up; its receipt
|
||||
records 6,866,296,832 peak family RSS bytes. The final CI run qualifies the PR.
|
||||
- Documentation/catalog/license checks passed after fixing missing catalog
|
||||
ownership, translated README links and the new MessagePack dependency notices.
|
||||
- An earlier combined schema run hit two 30 second timeouts on two CPUs. The
|
||||
isolated canonical schema suite passed all 15 cases without increasing limits.
|
||||
This is recorded as a successful isolation, not a proven baseline failure.
|
||||
|
||||
Retention caches are scoped to immutable Evidence through a WeakMap; historical
|
||||
pages do not reopen files. Live inspections always stream a fresh full-file hash
|
||||
and revalidate the descriptor/path. No live-state freshness cache is claimed.
|
||||
|
||||
## Review follow-up
|
||||
|
||||
At `36b87ed`, the public CLI reproduced both review findings: selecting
|
||||
`amdgcn-amd-amdhsa--gfx900` in the real Clang-produced standalone object returned
|
||||
zero kernels with an unknown target, and malformed `--targets` JSON was reported
|
||||
at the `view` issue path.
|
||||
|
||||
At `09c6062`, AMD ELF note parsing owns target discovery and prepared kernel
|
||||
declarations. Inventory reads those bounded notes before selection; selected
|
||||
analysis reuses them without decoding MessagePack twice. Aggregate encoded note
|
||||
bytes are limited to 8 MiB before reads, with existing per-value/depth limits;
|
||||
the parsed JavaScript representation expands beyond that source-byte count.
|
||||
The prepared declarations live only for the current payload inspection. Named
|
||||
CLI option parsing also supplies the actual parsed input to schema diagnostics.
|
||||
|
||||
The real public CLI now inventories the gfx900 target, returns the producer's
|
||||
one kernel/two parameters/12-byte parameter area/6 SGPR/2 VGPR when selected,
|
||||
and preserves an unselected object without kernel facts for a different target.
|
||||
Those three complete CLI tasks together took 5.974 seconds / 6.951 CPU seconds /
|
||||
383,623,168 sampled peak family RSS bytes, including the Python task driver.
|
||||
All nine producer artifacts were reread with complete payload coverage.
|
||||
|
||||
The review regression run passed 35 cases in four files, including public CLI,
|
||||
MCP, metadata capacity and cleanup. A further 10 product-catalog cases passed
|
||||
after adding the missing CLI `analysis` option description identified by CI.
|
||||
The earlier paired nvJPEG measurements remain pinned to their original runtime;
|
||||
these follow-ups do not establish a new CUDA performance result.
|
||||
|
||||
## Bounded metadata and partial-fact review
|
||||
|
||||
The latest qualification at `ad1e17a` rebases onto main `5241597`, preserving
|
||||
both Rust and GPU retained views. All 70 focused cases in nine files passed,
|
||||
including both public CLI/MCP workflows; the separate SDK-converted canonical
|
||||
schema suite passed all 15 cases.
|
||||
|
||||
CUDA parsing shares an aggregate 262,144 record/symbol visit budget, 128 MiB
|
||||
section-read budget and 16 MiB serialized-size accounting budget for index facts.
|
||||
Equal scoped byte ranges and duplicate register values are coalesced before
|
||||
index growth; conflicting values survive. Parsed parameter metadata is reused.
|
||||
The public CLI completed an 861,896-byte CUBIN containing 1,024 headers aliasing
|
||||
65,536 records and retained the correct physical count. The old 67-million-entry
|
||||
expansion is source-derived; it was not run to exhaustion.
|
||||
|
||||
Decoder coverage now reaches object, report and target pages: absent CUBIN
|
||||
symbol tables and unknown section names remain partial. AMD note parsing uses
|
||||
a tagged Result that retains earlier parsed notes on later malformed, capacity,
|
||||
unsupported or interrupted reads; retained kernel facts are emitted before the
|
||||
original failure is propagated. Standalone PTX recognition continues beyond the
|
||||
64 KiB fast path up to its actual 16 MiB text budget and reuses complete probe
|
||||
bytes. Unsupported/overflowing register counts stay null instead of low totals.
|
||||
|
||||
The public CLI verified an AMD valid-note/truncated-note input and a PTX file
|
||||
with a 70 KiB leading comment, in addition to the alias case. Those three tasks
|
||||
together took 5.132 seconds / 6.222 CPU seconds / 405,835,776 peak family RSS
|
||||
bytes, including the Python driver. Regression cases additionally cover invalid
|
||||
MessagePack and unsupported extensions in standalone and bundled AMD objects.
|
||||
|
||||
The revised Windows DLL workflow preserved all 165 decoded CUBIN hashes, all
|
||||
10 PTX byte identities and all 3,720 native kernel facts. Independently counting
|
||||
register declarations in cuobjdump-extracted PTX verified all 248 PTX kernels;
|
||||
20 kernel totals now correctly include previously missed declarations. This
|
||||
is a virtual-declaration oracle, not physical allocation or GPU execution.
|
||||
The Linux sm_100 workflows still match all 248 independently checked native
|
||||
kernel facts. All nine real producer artifacts retain complete payload coverage.
|
||||
|
||||
The latest complete/selected MCP pair performed the same six calls and answered
|
||||
the same question as the initial pair. Receipts retain both measurement stages.
|
||||
|
||||
| Cost | Complete report | Selected page |
|
||||
| --------------------------------------------------------- | --------------: | ------------: |
|
||||
| Used input declarations + primary calls, estimated tokens | 407,368 | 26,612 |
|
||||
| All input declarations + primary calls, estimated tokens | 636,495 | 255,739 |
|
||||
| Full catalog + all six calls, estimated tokens | 1,480,698 | 1,099,942 |
|
||||
| Process-family elapsed seconds | 15.487 | 15.923 |
|
||||
| Process-family CPU seconds | 18.404 | 18.760 |
|
||||
| Peak family RSS bytes | 1,251,254,272 | 1,201,774,592 |
|
||||
|
||||
These remain tokenizer estimates and same-code workflow variants. The single
|
||||
latest pair establishes no general latency/CPU/memory improvement; OS caches
|
||||
and host contention remain uncontrolled. The Windows CLI rerun completed in
|
||||
4.078 seconds / 4.880 CPU seconds / 498,380,800 peak family RSS bytes.
|
||||
|
||||
Main CI independently reproduced the browser termination and WASM optional-input
|
||||
assertion failures without GPU changes. Cancelled fail-fast shards are not
|
||||
counted as passing. Those baseline failures are outside this feature's fixes.
|
||||
|
||||
## Target declaration and CUDA ABI qualification
|
||||
|
||||
The latest code `f5be46f` is based on main `f801b2f`. Inventory and payload
|
||||
target declarations remain separate, with typed consistency and inspection
|
||||
coverage preserved in object pages even with selected fields. A mismatched
|
||||
outer/inner base target remains partial and annotates affected kernels; CUDA
|
||||
base-only agreement does not establish agreement on a feature profile. Target
|
||||
filters select inventory declarations, and unexamined inner targets stay unknown.
|
||||
|
||||
Standalone and unknown-ID bundled AMDGPU files use the same bounded target
|
||||
discovery owner before filtering. Portable controls wrap the same real Clang
|
||||
ELF with two-separator, one-separator and opaque HIP IDs. All three inventory
|
||||
then exact-target CLI workflows retain the verified kernel. They are alternate
|
||||
wrapper controls, not verification of an actual legacy compiler producer.
|
||||
|
||||
The shared fixed ELF header owner now retains OS ABI. NVIDIA's released CUBINs
|
||||
include distinct `0x33` and `0x41` flag layouts. The earlier low-byte-only
|
||||
interpretation falsely produced `sm_2` for 55 modern payloads; that attempted
|
||||
target-check implementation and its timings are superseded diagnostic evidence,
|
||||
not a correctness-qualified benchmark. The ABI-qualified decoder retains raw
|
||||
flags and exact fixed-header coordinates, and leaves unrecognized patterns unknown.
|
||||
Header ownership is checked when importing portable Evidence.
|
||||
|
||||
All 165 released Windows CUBIN targets and header values were checked against
|
||||
cuobjdump-extracted files: 110 use OS ABI `0x33`, 55 use `0x41`; no false conflicts
|
||||
remain. All 3,968 corrected kernel facts and 10 PTX byte identities match the
|
||||
prior independent oracle. The nine real producer artifacts retain complete
|
||||
payload coverage. Unsupported layout controls retain their headers and make
|
||||
unknown target discovery partial in the default MCP summary.
|
||||
|
||||
After the shared-header change, 251 cases in nine files passed, including
|
||||
Go/Rust/IL2CPP consumers, GPU CLI/MCP and provenance forgery. The last uncertainty
|
||||
propagation check passed 46 public/boundary cases. The separate SDK-converted
|
||||
canonical schema suite passed all 15 cases on the current base.
|
||||
|
||||
The latest qualified complete/selected pair retains the same sm_100 question,
|
||||
answer and six-call workflow. It runs at `21eaa0d`, before the final unresolved-
|
||||
discovery-only guard.
|
||||
|
||||
| Cost | Complete report | Selected page |
|
||||
| --------------------------------------------------------- | --------------: | ------------: |
|
||||
| Used input declarations + primary calls, estimated tokens | 418,967 | 26,653 |
|
||||
| All input declarations + primary calls, estimated tokens | 648,242 | 255,928 |
|
||||
| Full catalog + all six calls, estimated tokens | 1,493,041 | 1,100,727 |
|
||||
| Process-family elapsed seconds | 21.307 | 24.604 |
|
||||
| Process-family CPU seconds | 23.538 | 26.454 |
|
||||
| Peak family RSS bytes | 1,146,519,552 | 1,341,333,504 |
|
||||
|
||||
Selected replies save context but do not establish faster analysis. The latest
|
||||
pair used more elapsed/CPU time and peak memory for selected delivery; variability
|
||||
is visible across the preserved trials. Fresh process lifetime is controlled;
|
||||
OS caches, frequency and unrelated load are not. A same-code diagnostic timing
|
||||
repeat varied substantially, and no cause or persistent speedup is inferred.
|
||||
The tokenizer/client scope and omitted initialization costs remain as above.
|
||||
|
||||
The final Windows CLI task took 5.446 seconds / 5.916 CPU seconds / 498,192,384
|
||||
peak family RSS bytes. The six HIP wrapper CLI tasks took 15.696 seconds /
|
||||
16.427 CPU seconds / 382,410,752 peak family RSS bytes. All completed tasks stayed
|
||||
within the 8 GiB family guard.
|
||||
|
||||
## Payload admission and PTX uncertainty follow-up
|
||||
|
||||
At `893e04d`, PTX parsing owns typed per-kernel coverage and limitations for
|
||||
unknown parameter layouts, shared declarations and virtual register counts.
|
||||
Inventory forwards that coverage to objects, reports and historical pages.
|
||||
The old register-only interpretation in inventory was removed.
|
||||
|
||||
A 67-case focused run passed across five files, including parser, public CLI/MCP,
|
||||
provider boundary and lifecycle tests. Three source admission cases also passed
|
||||
(one overlaps the focused run). NVIDIA `ptxas 12.9.86` accepted a pointer-parameter
|
||||
PTX control; the public CLI retained its unknown layout and reported partial
|
||||
coverage. A released nvJPEG example independently extracted by cuobjdump uses
|
||||
`.param .u64 .ptr .align 1`; this remains outside supported layout interpretation.
|
||||
|
||||
The revised Windows DLL report retains all 176 object factual fields, all 3,968
|
||||
kernel factual fields and all 10 exact PTX byte identities. Eight PTX objects and
|
||||
59 kernels now expose their pre-existing unknown parameter layouts with partial
|
||||
coverage and added limitations. The earlier complete payload-coverage claim for
|
||||
those PTX objects is superseded; decoded numerical facts are unchanged. Nine real
|
||||
producer artifacts still retain complete payload coverage.
|
||||
|
||||
The shared work owner now reserves uncompressed payload input once, and compressed
|
||||
input plus decoded output atomically, before reading/allocating. CCOB uses the
|
||||
same admission owner as payload analysis and AMD note reads. The allowance is
|
||||
512 MiB of that work, with 128 MiB per input/output buffer. Admitted failed work
|
||||
remains charged. A real sparse HIP file contains twelve aliases of one 128 MiB
|
||||
ELF payload: file-read instrumentation observed four full payload reads and eight
|
||||
capacity refusals with no payload read or decoded digest; the earlier four kernel
|
||||
facts survive. CUDA and CCOB oversized-output controls likewise prove refusal
|
||||
before the compressed input read. Old rejected-alias rereads are source-derived;
|
||||
they were not run to exhaustion.
|
||||
|
||||
The nine-producer pass took 1.148 seconds / 1.100 CPU seconds / 122,732,544 peak
|
||||
family RSS bytes. The pointer-PTX and released-DLL public CLI tasks together took
|
||||
10.102 seconds / 11.302 CPU seconds / 512,335,872 peak family RSS bytes. The focused
|
||||
run took 142.441 seconds / 211.528 CPU seconds / 3,478,200,320 peak family RSS bytes,
|
||||
including the required artifact build. No resource guard stopped these tasks.
|
||||
The earlier MCP cost pairs remain pinned to their measured revisions; no new
|
||||
speedup is inferred from this follow-up.
|
||||
|
||||
Three verifier attempts are retained as unsuccessful in the JSON record: an
|
||||
incorrect bare-record assumption for the Evidence bundle, refusal to overwrite
|
||||
an existing export, and a stale expectation that the now-corrected PTX coverage
|
||||
would stay complete. The successful comparison requires all factual values and
|
||||
PTX bytes to match while checking the intended uncertainty changes explicitly.
|
||||
|
||||
`npm run check` passed at this source revision, including type/lint/format, module
|
||||
boundaries and architecture guards: 135.345 seconds / 266.563 CPU seconds /
|
||||
5,371,879,424 sampled peak family RSS bytes; no resource guard stop.
|
||||
|
||||
`npm run docs:check` also passed, including all five README conformance cases.
|
||||
+32
-1
@@ -26,6 +26,17 @@ execution validates tool files and version banners. Host process-ownership and
|
||||
private-workspace controls must also be available. The real-tool profile has
|
||||
been exercised on macOS arm64; other hosts require their own verification.
|
||||
|
||||
Configuration failures do not establish anything about the selected WASM bytes.
|
||||
For a rejected version probe, `details.diagnostics` identifies the executable,
|
||||
tool, expected version and configuration key; `details.captured_output` preserves
|
||||
its actual stdout and stderr, including empty banners or warnings. Fix the
|
||||
reported directory, executable access or release rather than changing the module
|
||||
or repeating an unchanged call. All three tools must report 1.0.42 on stdout with
|
||||
empty stderr. For CLI calls, set the environment before the next invocation. For
|
||||
MCP, change the server's launch environment and restart/reconnect that server;
|
||||
exporting a variable in a different shell does not update a running server.
|
||||
REA never installs tools or relaxes version admission to recover.
|
||||
|
||||
```bash
|
||||
REA_WABT_BIN_DIRECTORY=/absolute/wabt/bin rea inspect-wasm-artifact \
|
||||
/artifacts/module.wasm --glue_paths /artifacts/glue.js \
|
||||
@@ -64,7 +75,27 @@ The tool profile preserves upstream release/source identity, resolved executable
|
||||
paths, executable digests, exact banners and arguments. Executable digests are
|
||||
checked again after each command. Caller-supplied tools are trusted programs;
|
||||
version and digest recording are not publisher authentication or an OS sandbox.
|
||||
Each subprocess has a 30-second deadline and 32 MiB combined output budget.
|
||||
Each WABT version/analysis command defaults to a 30,000 ms deadline. Set optional
|
||||
MCP `command_timeout_ms`, or CLI `--command-timeout-ms <milliseconds>`, to select a
|
||||
positive integer up to 2,147,483,647 ms (the runtime timer range) for that call.
|
||||
The selected deadline is retained as `tool_profile.timeout_ms` and, when supplied,
|
||||
in Evidence parameters. It applies separately to each command, not the whole
|
||||
inspection, file admission or cleanup. The MCP client must allow time for all
|
||||
commands, file checks, cleanup and delivery. A provider timeout reports the
|
||||
actual selected deadline and these recovery controls; increasing only the client
|
||||
deadline does not change the provider budget. No server restart is required to
|
||||
change this per-call setting. Resolve incomplete cleanup before another attempt.
|
||||
|
||||
For example, `rea inspect-wasm-artifact /artifacts/module.wasm
|
||||
--command-timeout-ms 60000 --format json` uses a 60-second per-command deadline;
|
||||
the equivalent MCP input is `{"path":"/artifacts/module.wasm",
|
||||
"command_timeout_ms":60000,"detail":"summary"}`. Summary delivery retains the
|
||||
complete Evidence but does not reduce WABT analysis work.
|
||||
|
||||
The 8 MiB input allowance and 32 MiB combined command-output budget remain fixed;
|
||||
increasing `command_timeout_ms`, host memory or the client deadline does not raise
|
||||
them. Do not truncate required module bytes to fit. Select another suitable
|
||||
complete artifact only if it answers the question, otherwise report the limit.
|
||||
Inspection output past the budget fails with `resource_constraint`; an oversized
|
||||
`--version` probe still reports `unreadable_output`. Both streams share the
|
||||
budget, so a stream that starts after the other has filled it retains nothing.
|
||||
|
||||
@@ -120,6 +120,8 @@ HTTP fields and ordered duplicate headers are retained, with stored body bytes
|
||||
in binary sidecars. Bodies are not dechunked or decompressed. Metadata is an
|
||||
XML node tree; optional `_w.txt` and `_g.txt` files retain opaque WebSocket and
|
||||
gRPC message bytes. Missing members remain null, distinct from empty bodies.
|
||||
A zero-byte `_c.txt` or `_s.txt` member, which Fiddler writes for a session
|
||||
without that message, is also null and adds a record limitation.
|
||||
See Telerik's [SAZ format reference](https://www.telerik.com/fiddler/fiddler-everywhere/documentation/knowledge-base/fiddler-archives).
|
||||
|
||||
## Protobuf and gRPC bodies
|
||||
@@ -178,6 +180,9 @@ sanitized source even with explicit sensitivity options. If that source pass
|
||||
is interrupted, unchecked bodies are not published as partial Evidence.
|
||||
Framing overrides apply only to format-owned body coordinates and preserve
|
||||
exclusions for the transport declared in MIME metadata.
|
||||
Explicitly excluded or conflicting MIME metadata is not treated as absent:
|
||||
automatic framing leaves such a non-empty body uninterpreted, adds a record
|
||||
limitation and keeps `protobuf_coverage` partial unless `framing` is selected.
|
||||
Unknown or explicitly excluded HTTP coding metadata is not treated as absent:
|
||||
SAZ/native bodies remain opaque until identity coding is established. Raw
|
||||
header values and retained body bytes remain available in source Evidence.
|
||||
@@ -449,12 +454,13 @@ template and `params` carry the four format rules with names `id`, `uuid`,
|
||||
only when listed, each at most once (a repeated rule is an `invalid_request`),
|
||||
in this order:
|
||||
|
||||
| Rule | Applies to | Parameter |
|
||||
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------- |
|
||||
| `after-uid-literal` | The literal segment right after a literal `uid`, unless it is a stop word | `uid` |
|
||||
| `opaque-token` | A lowercase alphanumeric segment of twelve or more characters mixing letters and digits that is not a `v1`-style version | `uid` |
|
||||
| `sibling-pair-variance` | Groups equal in method, origin and segment count that differ in two adjacent literals right after a plural literal at index 2 or later and followed by a literal, with at least three distinct pairs and both positions varying (`/repos/{owner}/{repo}/issues`); stop words and `v1`-style versions never qualify | singular plural literal plus `_namespace`, then `_name` |
|
||||
| `sibling-variance` | Groups equal in method, origin and segment count that differ in one literal at index 2 or later; the siblings whose literal is identifier-like (a digit or `:`, or three or more hyphenated names under a plural literal) merge, never a stop word, and the other literals stay their own tools | singular previous literal plus `_id`, else `id` |
|
||||
| Rule | Applies to | Parameter |
|
||||
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
|
||||
| `after-uid-literal` | The literal segment right after a literal `uid`, unless it is a stop word | `uid` |
|
||||
| `opaque-token` | A lowercase alphanumeric segment of twelve or more characters mixing letters and digits that is not a `v1`-style version | `uid` |
|
||||
| `sibling-pair-variance` | Groups equal in method, origin and segment count that differ in two adjacent literals right after a plural literal at index 2 or later and followed by a literal, with at least three distinct pairs and both positions varying (`/repos/{owner}/{repo}/issues`); stop words and `v1`-style versions never qualify | singular plural literal plus `_namespace`, then `_name` |
|
||||
| `sibling-variance` | Groups equal in method, origin and segment count that differ in one literal at index 2 or later; the siblings whose literal is identifier-like (a digit or `:`, or three or more hyphenated names under a plural literal) merge, never a stop word, and the other literals stay their own tools | singular previous literal plus `_id`, else `id` |
|
||||
| `prefix-variance` | A literal at a position that another tool, of any method or segment count, templates by one of the rules above after the same preceding segments, when the literal is one of that parameter's observed values, carries a digit and has the length and character classes (digits, lower case, upper case, each other character) of one, or has the single length of eight or more characters every observed value has and only their character classes; stop words and `v1`-style versions never qualify, and tools that now match merge | the name of the parameter it shares |
|
||||
|
||||
With `sibling-variance` selected, literal siblings within its comparison scope
|
||||
fold into existing opt-in parameters as observed values unless they are stop words.
|
||||
@@ -471,7 +477,17 @@ cut to their first label, `_by_<params>` appended when parameters exist,
|
||||
sanitized to `[a-z0-9_]`, at most 60 characters and made unique with numeric
|
||||
suffixes: `get_dashboards_by_uid`, `get_plugins_settings_by_plugin_id`.
|
||||
|
||||
`sibling-variance` and `sibling-pair-variance` compare routes of at most 32 segments; longer routes keep
|
||||
`prefix-variance` runs last so it can share the parameters the other rules
|
||||
produce: with `sibling-variance`, a `PATCH` or `DELETE` of the one entity a
|
||||
session edited, `/api/v1/collections/0RZ576QZQA5KG`, becomes
|
||||
`/api/v1/collections/{collection_id}` beside the reads that varied there, and
|
||||
so do deeper routes such as `/api/v1/collections/{collection_id}/books`. Its
|
||||
parameter is labelled `prefix-variance`, unless a merged tool templated the
|
||||
position by its own rule. When parameters of different rules share a position,
|
||||
a literal shares the one that observed it, else the earliest one it is spelled
|
||||
like.
|
||||
|
||||
`sibling-variance`, `sibling-pair-variance` and `prefix-variance` compare routes of at most 32 segments; longer routes keep
|
||||
their grouped templates and the manifest says so in a limitation. `body_shape`
|
||||
is derived for `POST`, `PUT` and `PATCH` from the tool's earliest record when it
|
||||
carries an `application/json` or `application/*+json` request body: top-level
|
||||
@@ -506,9 +522,9 @@ Pass the same parent to `inspect_analysis_view` with
|
||||
`view: {"kind":"environment-state"}` to extract the initial state the
|
||||
capture's reads observed, and a render plan per read tool that reproduces those
|
||||
reads from it. Where the environment manifest names an application's tools, the
|
||||
state holds its data: entities by type and identity, plus documents for written
|
||||
paths whose reads are not entities. Use the `template_rules` of the manifest the
|
||||
state accompanies so tool names match; the view groups records the same way.
|
||||
state holds its data: entities by type and identity, plus documents for reads
|
||||
that are not entities. Use the `template_rules` of the manifest the state
|
||||
accompanies so tool names match; the view groups records the same way.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -544,13 +560,27 @@ refused for them, as the manifest is not.
|
||||
|
||||
Each `GET` tool whose template ends in a parameter is an item tool, and its
|
||||
type's `collection_template` is the template without that parameter; any other
|
||||
`GET` tool is a list tool of its own template. An item tool proves its type's
|
||||
`GET` tool is a list tool of its own template. Empty segments are ignored, so a
|
||||
trailing slash names the same collection. An item tool proves its type's
|
||||
`id_field` when every initial response carries the requested path value in the
|
||||
same field, at the root or in one wrapper member (`id_basis: "path-parameter"`).
|
||||
Otherwise the field is the first of `id`, `uid`, `uuid`, `_id`, `ID`, `UID`,
|
||||
`Id`, `guid`, `key`, `slug` and `name` that every listed item carries as a
|
||||
distinct string or number (`id_basis: "field-name"`). A list is the response
|
||||
array, or the one array of objects in an envelope that is not itself an entity.
|
||||
same field of one entity object (`id_basis: "path-parameter"`). The object is
|
||||
the response itself or one wrapper member; failing both, it is the only element
|
||||
of a one-element array at the root (pointer `/0`) or in one member
|
||||
(`/<member>/0`), as in `{"posts":[{...}]}` or `{"data":[{...}]}`, provided one
|
||||
of the identity names below repeats the value, since a filtered list may also
|
||||
answer with one element that repeats its parent's value. Otherwise the field is
|
||||
the first of `id`, `uid`, `uuid`, `_id`, `ID`, `UID`, `Id`, `guid`, `key`,
|
||||
`slug` and `name` that every listed item carries as a distinct string or
|
||||
number; when none does, it is the first key of the first listed item, in its
|
||||
order, whose name ends in `Id` or `_id` (such as `orgId` or `user_id`), that
|
||||
every item carries as a distinct string or number, and that at least one
|
||||
initial response shows distinct across two or more items
|
||||
(`id_basis: "field-name"`). A single listed item is distinct from nothing, and
|
||||
its suffix-named fields are often foreign keys, so a list that only ever held
|
||||
one item is left to a document. Empty initial lists constrain no field. A list
|
||||
is the response array, or the one array of objects in an envelope that is not
|
||||
itself an entity, preferring an array whose items an identity name identifies,
|
||||
then an array of two or more items a suffix-named field identifies.
|
||||
|
||||
`entities` merge every initial observation of one identity within one
|
||||
collection path: an item view's latest values win over a list view's, a view
|
||||
@@ -567,9 +597,9 @@ Every entity cites its `record_ordinals`.
|
||||
|
||||
| Shape | Plan |
|
||||
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `item` | The entity object at `pointer` (the root or one member), the ordered `fields` the view shows and the `required_fields` every recording had, and `envelope_ordinal`: the recording whose response, with the entity replaced, every item response shares |
|
||||
| `item` | The entity object at `pointer` (the root, one member, or `/0` or `/<member>/0`), the ordered `fields` the view shows and the `required_fields` every recording had, and `envelope_ordinal`: the recording whose response, with the entity replaced, every item response shares |
|
||||
| `list` | The array at `pointer`, its `fields`, `membership` (`all`: every entity of the collection in state order, when each recording listed exactly that, had no query, no item-total member (`total`, `count`, `totalCount`, `item_count`, `totalcount`, `itemcount`, but not `total_pages` or `per_page`; a number or a string of digits) differing from the number listed, and no `has_more`, `next` or next-page token member set; `recorded`: the entities each recording listed) and `counters` that equal the number listed |
|
||||
| `document` | The path's latest initial value, held in `documents` |
|
||||
| `document` | The latest initial value of a list tool whose responses hold no identified list, when its initial reads share one request line; held in `documents` with that `path`, whether or not the capture writes it, unless its value changed across any recorded write between those reads (`fields-differ`) |
|
||||
| `recorded` | A `reason` the tool replays its recordings instead |
|
||||
|
||||
An item or list plan is kept only when it reproduces the latest initial
|
||||
@@ -578,11 +608,13 @@ regard to member order; a volatile field compares its recorded value. Each
|
||||
plan lists the `checked_record_ordinals`. Otherwise the tool is a recorded view
|
||||
with reason `envelope-varies`, `fields-differ` or `list-differs`; the other
|
||||
reasons are `query-body` (a query `POST`), `no-init-recording`,
|
||||
`body-unusable`, `not-entity`, `no-identity` and `query-varies` (a document
|
||||
read under several queries). Documents are held only for list-shaped paths
|
||||
that a `POST`, `PUT` or `PATCH` tool writes: a non-entity read of an item path
|
||||
such as `/api/files/{id}`, or of a path that is only deleted, stays recorded
|
||||
with `no-identity` or `not-entity`. A body is usable when its content type is
|
||||
`body-unusable`, `no-identity` (an item read without a proved identity),
|
||||
`path-varies` (another read under more than one path, as a template with a
|
||||
parameter before its end), `query-varies` (another read of one path under
|
||||
more than one query) and `rendered-oversize` (a document value whose JSON
|
||||
renders to more than 256 KiB). A document holds the value of its one `path`, so for such
|
||||
a template it says nothing about the template's other paths. A body is usable
|
||||
when its content type is
|
||||
JSON-like, it is UTF-8 text of at most 256 KiB, every number survives native
|
||||
conversion exactly, and no member is named `__proto__`.
|
||||
|
||||
@@ -594,19 +626,25 @@ that the state establishes no authorization model, no way the application
|
||||
computes responses or derived values, and no effects of writes. The state
|
||||
accumulator charges the manifest's admission and grouping, every record line,
|
||||
each body as temporary bytes before it is decoded and parsed, and every value
|
||||
it keeps, within the same 96 MiB budget. The view performs no network activity
|
||||
and serves nothing.
|
||||
it keeps, within the same 96 MiB budget. Documents hold whole recorded response
|
||||
values whose recorded text and rendered JSON are each at most 256 KiB, so a
|
||||
capture with many read-only paths yields a correspondingly larger state result. The view performs no network activity
|
||||
and serves nothing; `rea environment-serve` derives it from the capture at
|
||||
startup, serves read tools from it and loads replacement states through the
|
||||
AgentEnv data plane, as
|
||||
[serve from the state](agent-environments.md#serve-from-the-state) describes.
|
||||
|
||||
## Resource and lifecycle boundaries
|
||||
|
||||
Complete evidence has a 32 MiB input, 96 MiB decoder reply and 64-level nesting
|
||||
budget. Exceeding a budget returns no partial success.
|
||||
budget. Those budgets have no runtime override. `capture_timeout_ms` does not
|
||||
raise them. Exceeding a budget returns no partial success.
|
||||
Oversized selected captures return an input error identifying `capture_path`
|
||||
and the byte budget; owned reply/output failures remain output or provider errors.
|
||||
HAR, SAZ and qlog run in an owned
|
||||
192 MiB Node old-generation heap with one V8 worker. Mitmproxy decoding applies
|
||||
Linux limits of 768 MiB address space, 30 seconds CPU and 96 MiB file output;
|
||||
both commands have a 30-second wall deadline and independently supervised
|
||||
both commands use `capture_timeout_ms` (default 30000) and independently supervised
|
||||
process cleanup. Owned decoder diagnostics retain at most 1 MiB across stdout
|
||||
and stderr; the collector drops overflow as it arrives, reports the limit
|
||||
failure and verifies cleanup. Heap limits alone do not establish aggregate RSS limits.
|
||||
|
||||
+4
-2
@@ -32,7 +32,9 @@ A document replacement ends the window; final coverage then remains unavailable.
|
||||
|
||||
Same-document navigation such as `history.pushState()` remains valid when the frame and known loader identity stay stable and the current origin is allowed. Unknown loader identity retains a conservative URL check; newly reported or replaced loaders are rejected. Malformed producer events end an armed window immediately and trigger cleanup, independently of the selected duration.
|
||||
|
||||
Target detachment ends the window even when the browser's root connection stays open. When the closed session cannot acknowledge cleanup, the operation returns a failure with the selected target, failed commands and original producer reason; it does not claim successful cleanup.
|
||||
Target detachment ends the window with `session_detached`, even when the browser's root connection stays open. An `Inspector.targetCrashed` event ends it with `target_terminated`. A lost transport records `transport_disconnected` in browser observation; execution capture returns the typed transport failure. These outcomes retain the selected target and the observed lifecycle fact.
|
||||
|
||||
When an ended session cannot acknowledge cleanup, the operation returns a failure with the failed commands and original typed producer reason. A coverage-stop failure also retains the observed window's end reason in its diagnostics; cleanup remains unconfirmed until the owning session can resolve it.
|
||||
|
||||
Child frames, workers, service workers, WebAssembly, chronological execution order and framework-specific causal interpretation are outside this operation. Script ownership comes from frame/context metadata, never URL equality. Repeated URLs and synthetic names therefore retain separate identities.
|
||||
|
||||
@@ -50,7 +52,7 @@ The result contains directly registered listener types/flags, callback coordinat
|
||||
|
||||
## Bounds and verification
|
||||
|
||||
Each protocol message has a 64 MiB budget; script/context metadata and request metadata each have an 8 MiB retained budget. Complete retained source text has a 32 MiB budget. Oversized or malformed evidence returns no partial successful result. Each command and the complete inspection/source-join phase have a 20-second deadline; cleanup has a separate 5-second command deadline plus transport closure. The selected observation duration must fit the host timer's positive 32-bit millisecond range. REA does not control the externally owned browser's CPU or memory.
|
||||
Each protocol message has a 64 MiB budget; script/context metadata and request metadata each have an 8 MiB retained budget. Complete retained source text has a 32 MiB budget. Oversized or malformed evidence returns no partial successful result. Each command and the complete inspection/source-join phase use `command_timeout_ms` (default 20000). Cleanup uses a separate 5000 ms grace; `command_timeout_ms` does not raise or shorten it, and this release has no runtime override for that grace. Transport closure follows the grace. The selected observation duration must fit the host timer's positive 32-bit millisecond range. REA does not control the externally owned browser's CPU or memory.
|
||||
|
||||
`npm run verify:browser:runtime` uses caller-supplied `REA_BROWSER_EXECUTABLE` and the native `ps` command on Linux/macOS against an owned synthetic fixture, through real public CLI and stdio MCP. It checks exact Unicode/CRLF text/digests, same-URL identities, same-document navigation, inert declared names, executed and zero-count branches, function-only unknowns on repeated observation, listener selection, initiator association, actual arming and preservation of the external page. A separate fixture page closes during an armed MCP window to verify prompt termination and inline cleanup diagnostics. The optional positional entrypoint to `scripts/verify-browser-runtime.mjs` permits the same checks against an isolated installed tarball.
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ implement every current source-map extension.
|
||||
One owned Node subprocess decodes the map. Its private request directory is
|
||||
removed before success is returned. Only this child's inherited `NODE_OPTIONS`
|
||||
is removed; explicit V8 flags set a 192 MiB old-generation and 8 MiB semi-space
|
||||
budget, one V8 worker and a 20-second deadline. Reported actual V8 heap limits
|
||||
budget, one V8 worker and `decode_timeout_ms` (default 20000). The codec heap, map budget, and reply budget have no runtime override. Reported actual V8 heap limits
|
||||
are checked. These are heap limits, not an aggregate process RSS limit. When
|
||||
REA runs on Bun, the subprocess is Bun, which ignores these V8 flags: `runtime`
|
||||
records `id: "bun"`, the Bun version, its Node.js compatibility version and a
|
||||
@@ -86,7 +86,8 @@ cleanup overrides success with `cleanup_incomplete` and the owning
|
||||
operation/resources.
|
||||
|
||||
Complete evidence is bounded by a 4 MiB map, 32 MiB codec reply, 262144 decoded
|
||||
rows/segments and 64 nested section levels. Exceeding a budget returns an explicit
|
||||
rows/segments and 64 nested section levels. Those structural budgets and the
|
||||
192 MiB codec heap have no runtime override. Exceeding a budget returns an explicit
|
||||
failure, without partial results. The existing 32 MiB manifest and 16 MiB selected
|
||||
script boundaries also apply. No global toolchain or browser configuration changes
|
||||
are made.
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# Analysis efficiency measurements
|
||||
|
||||
The [2026-10-21 coverage reconciliation](coverage-review-20261021.md) maps all
|
||||
46 source directories to concrete workflow evidence, including original feature
|
||||
PRs, historical no-benefit results and remaining verification boundaries.
|
||||
|
||||
The [GGUF validation checkpoint](model-utf8-validation.md) removes decoding of
|
||||
omitted strings while retaining full UTF-8 validation. It records real-model
|
||||
phase gains, unchanged task token costs and the higher main-task memory peak.
|
||||
|
||||
The [WAT framing checkpoint](wasm-string-framing.md) measures structural scanning
|
||||
on real SQLite and VS Code components, with unchanged Evidence and token costs,
|
||||
small whole-task timing gains and no memory improvement.
|
||||
|
||||
The [native inventory view checkpoint](native-inventory-views.md) compares
|
||||
complete delivery with summaries and selected rows on real `true` and jq
|
||||
inventories, including oversized-response recovery, portable old Evidence,
|
||||
|
||||
@@ -433,6 +433,38 @@
|
||||
"members": 315,
|
||||
"expanded_bytes": 1301927
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "alpine-ripgrep-rust",
|
||||
"file": "ripgrep",
|
||||
"bytes": 3416168,
|
||||
"sha256": "78387bbe12b2110df8d2ce364390a00c190f4543a2f40b8279e49f6c5c85af9c",
|
||||
"provenance": {
|
||||
"project": "ripgrep",
|
||||
"version": "14.1.1-r0",
|
||||
"upstreamFile": "ripgrep-14.1.1-r0.apk",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.21/community/x86_64/ripgrep-14.1.1-r0.apk",
|
||||
"transport_sha256": "213dd0b047163f6627cc2fdd6fbfe205009476eb4fc48c352a3f5b9ab647f6d4",
|
||||
"transport_bytes": 1422830,
|
||||
"aports_revision": "4e899d119e4c983a938436d6f397a509521225d1",
|
||||
"derivation": "selected regular APK tar member usr/bin/rg; read-only static inspection; never executed"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "alpine-zellij-rust",
|
||||
"file": "zellij",
|
||||
"bytes": 17151864,
|
||||
"sha256": "9a86e9ca47902a869fdf1886f4cf17714f4fa5655427128beadff498cfb392db",
|
||||
"provenance": {
|
||||
"project": "zellij",
|
||||
"version": "0.40.0-r0",
|
||||
"upstreamFile": "zellij-0.40.0-r0.apk",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.21/community/x86_64/zellij-0.40.0-r0.apk",
|
||||
"transport_sha256": "575075945415b221857563e19c5f4c661af9f98bbba54f0994c7385c0e432432",
|
||||
"transport_bytes": 6722129,
|
||||
"aports_revision": "3be26a3a26e76e1bf3eff784bffe3956d29d77a0",
|
||||
"derivation": "selected regular APK tar member usr/bin/zellij; read-only static inspection; never executed"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
# Workflow coverage reconciliation, 2026-10-21
|
||||
|
||||
The checked snapshot is main `264862bf2`, with **46 first-level `src/`
|
||||
directories and 212 production stdio MCP tools**. Directory counts and tool
|
||||
counts are different inventories: one application workflow can cross several
|
||||
directories, and one provider can expose many independently costly operations.
|
||||
This is a source/history review, not a new runtime qualification of all tools.
|
||||
|
||||
The search includes this experiment directory, owning contracts and source
|
||||
history, original feature PRs and related open/closed issues. Missing experiment
|
||||
files do not establish missing audits. In particular, the model and IL2CPP
|
||||
feature PRs contain substantial real-task evidence absent from this directory.
|
||||
Historical measurements retain their original revisions, platforms and limits.
|
||||
|
||||
| Directories / workflow | Evidence already present | Remaining coverage boundary |
|
||||
| ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `kuna`, `ghidra` | Earlier native entry work and [Ghidra projection](ghidra-evidence-projection.md) | Selected questions only; database reuse is a separate [research issue #3136](https://github.com/morluto/rea/issues/3136). |
|
||||
| `ida` | [Windows native correctness and completed-task costs](ida-native-windows.md), including real `whoami.exe` | Warm selected-task gains do not establish cold analysis, all string formats, all operations or other IDA platforms. |
|
||||
| `hopper`, `jeb` | [Hopper string records](hopper-string-records.md), [Linux runtime](hopper-linux-python-runtime.md), [real JEB CE](jeb-linux-native.md) | Preserve negative whole-task results; other editions, platforms and workflows are separate scopes. |
|
||||
| `rizin`, `cutter` | Existing command/session adapters and lifecycle fixes | No comparable dedicated real completed-task performance record located in the searched records. Actual engine/GUI availability must be established before selecting a task. |
|
||||
| `gdb`, `objdump` | [Real Bash command observations](command-observation-views.md) | Selected read-only disassembly is measured; other commands, large outputs and running-target observation are separate tasks. |
|
||||
| `adb`, `frida`, `inspector` | [Frida native status/history experiment](frida-status-views.md) | Frida status does not qualify arbitrary scripts, ADB/device transfers, browser Inspector events or live target freshness. |
|
||||
| `go`, `rust` | [Go build/dependency selection on real binaries](go-build-views.md); Rust cargo-auditable support [#2456](https://github.com/morluto/rea/pull/2456) | Go is already measured. No comparable dedicated Rust dependency-investigation cost record located in this review. |
|
||||
| `javascript`, `browser`, `electron` | [Agent fact workflow](javascript-facts-agent-history.json), lifecycle experiments and [#4415](https://github.com/morluto/rea/issues/4415) | Real Joplin preparation remains exploratory. Individual JS features and browser/runtime workflows need their own evidence. |
|
||||
| `android`, `apktool` | [Package summary](android-package-summary.md), [three-APK shared resource decoding](apktool-string-tables.md) | These do not qualify all JADX class/method/reference operations or physical-device workflows. #4777 is already fixed. |
|
||||
| `dotnet`, `il2cpp` | [Managed summaries/pages](managed-artifact-summary.md), IL2CPP metadata [#3807](https://github.com/morluto/rea/pull/3807) and native links/seeds [#5327](https://github.com/morluto/rea/pull/5327) | IL2CPP already has real Windows/Android row comparisons, task costs and Ghidra import. Unsupported versions/generics/platforms remain separate correctness and coverage work. |
|
||||
| `model` | GGUF/safetensors [#5603](https://github.com/morluto/rea/pull/5603): real models, independent readers and complete-task costs | Existing delivery is already audited. [#5774](https://github.com/morluto/rea/issues/5774) isolates omitted-string validation cost within that producer. |
|
||||
| `native`, `artifacts` | [Native inventory](native-inventory-views.md), [entry views](native-entry-views.md); real NIB output reductions [#1460](https://github.com/morluto/rea/pull/1460), [#1477](https://github.com/morluto/rea/pull/1477) | Inventory does not qualify Apple UI/resource, signatures, dyld or runtime traces. NIB byte reductions alone do not establish token, time, CPU or memory savings for a completed question. |
|
||||
| `firmware` | Region pilot plus real full OpenWrt extraction/publication [#4602](https://github.com/morluto/rea/pull/4602) | Extraction is already measured; noisy timings establish no general speedup. Other image layouts, extraction trees and publication filesystems remain unqualified. |
|
||||
| `flutter`, `sqlite`, `wasm`, `evm`, `pcap`, `signals` | [Dart AOT](flutter-aot-summary.md), [SQLite controls](sqlite-existing-controls.md), [WAT framing](wasm-string-framing.md), [EVM](evm-interface-summary.md), [PCAP](pcap-small-captures.md), [signals](signal-selection-workflows.md) | Extend a specific question. Preserve cases where existing controls suffice and small tasks regress; these records do not qualify each format or tool exhaustively. |
|
||||
| `application`, `domain`, `server`, `cli`, `contracts` | [Mixed retained investigations](retained-investigation-workflows.md), [immutable parent validation](immutable-parent-validation.md), [capture validation](retained-capture-validation.md) | Shared selected-query paths are already optimized. Reconstruction/environment composition and new fact families require their own end-to-end questions. |
|
||||
| `browser` / recorded captures | [SAZ selection](saz-selection-workflows.md) and [real qlog producer/retained reads](retained-capture-validation.md) | [#3133](https://github.com/morluto/rea/issues/3133) still includes actual model/task questions; producer measurements do not close those requirements. |
|
||||
| `filesystem`, `process`, `reference`, `providers`, `captures`, `windows`, `main`, `composition`, `config`, `evaluation` | Cross-workflow resource/cleanup checks, [process traces](process-trace-validation.md), [MCP profile](mcp-profile-identity.md) and Windows lifecycle checkpoints | Infrastructure coverage follows the exercised workflow. No blanket startup/resource claim; reference imports and `compare_source_to_bundle` need a dedicated completed source-tree question. |
|
||||
|
||||
Every one of the 46 directories appears above; repeated `browser` highlights a
|
||||
distinct workflow, not another directory. The table records located evidence,
|
||||
not proof that every historical PR was inspected. Open issue state by itself
|
||||
does not prove missing implementation or absent measurements.
|
||||
|
||||
## Three bounded follow-up questions
|
||||
|
||||
1. **Rust dependency identity:** inspect a public cargo-auditable binary, find
|
||||
exact dependency/version edges and retain complete source Evidence. Compare
|
||||
existing delivery first; independently decode its auditable section. Include
|
||||
a small binary and account for all discovery, queries and serialization.
|
||||
2. **Apple UI graph lookup:** on macOS, locate a specific control/outlet in a
|
||||
real Transmission/XLD NIB graph using existing summary/document pages.
|
||||
Compare equivalent complete questions and independently check archive
|
||||
records. Historical byte reductions alone are not the completion criterion.
|
||||
3. **Reference/source comparison:** import a pinned public source tree and
|
||||
answer one source-to-bundle identity question through existing workflows.
|
||||
Independently check file manifests, symlink/unknown semantics and selected
|
||||
matches; measure repeated traversal and retained representation before
|
||||
proposing an index or cache.
|
||||
|
||||
Each lane stops with a measured benefit, an evidenced no-change decision, or an
|
||||
explicit unavailable prerequisite. Rizin/Cutter and device/live workflows stay
|
||||
visible as additional gaps; no new execution, injection or mutation authority is
|
||||
implied by this review. No all-provider run or new API is justified by counts.
|
||||
@@ -0,0 +1,50 @@
|
||||
"""Read archived AppKit connector UIDs independently with Python's plistlib."""
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import plistlib
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--bundle', type=Path, required=True)
|
||||
parser.add_argument('--document', required=True)
|
||||
parser.add_argument('--baseline', type=Path, required=True,
|
||||
help='Complete pre-change 64-document Evidence; equality control, not the oracle')
|
||||
parser.add_argument('--small-baseline', type=Path, required=True,
|
||||
help='Complete pre-change 1-document Evidence')
|
||||
parser.add_argument('--output', type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
data = (args.bundle / args.document).read_bytes()
|
||||
objects = plistlib.loads(data)['$objects']
|
||||
connections = []
|
||||
for index, value in enumerate(objects):
|
||||
if not isinstance(value, dict) or not {'NSSource', 'NSLabel'} <= value.keys():
|
||||
continue
|
||||
classname = objects[value['$class'].data]['$classname']
|
||||
if classname not in ('NSNibOutletConnector', 'NSNibControlConnector'):
|
||||
continue
|
||||
connections.append({
|
||||
'archive_index': index,
|
||||
'kind': 'outlet' if classname == 'NSNibOutletConnector' else 'action',
|
||||
'name': objects[value['NSLabel'].data],
|
||||
'source': str(value['NSSource'].data),
|
||||
'destination': str(value['NSDestination'].data),
|
||||
})
|
||||
if not connections:
|
||||
raise ValueError('No supported archived connectors; choose a keyed AppKit document')
|
||||
args.output.write_text(json.dumps({
|
||||
'document': args.document,
|
||||
'archive_sha256': hashlib.sha256(data).hexdigest(),
|
||||
'connections': connections,
|
||||
'complete_result_paths': {
|
||||
'1': str(args.small_baseline.resolve()),
|
||||
'64': str(args.baseline.resolve()),
|
||||
},
|
||||
}, indent=2) + '\n')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,225 @@
|
||||
# Retained Interface Builder graph validation
|
||||
|
||||
Issue #5855. Baseline `f801b2fbfd28f4e3713adefddc7bd73db44c284c`, Linux
|
||||
x86_64 / AMD EPYC 7B12 / Node 24.18.0 / npm 11.16.0. This is static archive
|
||||
analysis on Linux, without executing an app or using ibtool or a native
|
||||
analysis provider.
|
||||
|
||||
## Question and oracle
|
||||
|
||||
Identify the AAC settings outlets and VBR action in the official
|
||||
[XLD 20250302 app](https://tmkk.undo.jp/xld/index_e.html), including archive
|
||||
source/destination object identities, connection evidence and limitations.
|
||||
|
||||
- [Official DMG](https://tmkk.undo.jp/xld/xld-20250302.dmg) SHA-256:
|
||||
`0032a5470ea4e32a11a35b8077ebf4986102891f8eb82743094f2c6621ad8aeb`.
|
||||
- Selected document:
|
||||
`Contents/PlugIns/XLDAacOutput.bundle/Contents/Resources/English.lproj/XLDAacOutput.nib`.
|
||||
- Archive SHA-256:
|
||||
`4fdbfba451ee64b1d333c96a4f3d1a0c4b543a36b9b3686e1151b51e4dd14c72`.
|
||||
- Python's independent `plistlib` reads the actual `$objects` table and
|
||||
`NSNibOutletConnector` / `NSNibControlConnector` records. Observed connections:
|
||||
|
||||
| Kind | Label | Source UID | Destination UID |
|
||||
| ------ | ------------- | ---------- | --------------- |
|
||||
| outlet | o_bitrate | 2 | 10 |
|
||||
| outlet | o_gaplessFlag | 2 | 41 |
|
||||
| outlet | o_prefPane | 2 | 53 |
|
||||
| outlet | o_quality | 2 | 62 |
|
||||
| outlet | o_useVBR | 2 | 58 |
|
||||
| action | vbrChecked: | 58 | 2 |
|
||||
|
||||
The benchmark checks each connector, both endpoint records, relationship kinds,
|
||||
archive path/digest and page coverage against these independent facts. It also
|
||||
compares all returned document rows with the exported complete parent; all
|
||||
64-document normalized results match the pre-change complete CLI Evidence.
|
||||
The complete exported parent Evidence is equal across versions for both
|
||||
admission sizes. The reproduction oracle requires a separate pre-change
|
||||
complete Evidence file for each size, and the harness compares the entire
|
||||
parent, including its identity and parameters, for the selected limit. Equality is a preservation control, not an independent proof
|
||||
of every decoded fact.
|
||||
|
||||
The default 64-document report contains 6,528 nodes and 1,378 edges. The small
|
||||
control admits one document from the same unmodified real app, with 80 nodes
|
||||
and 13 edges. Both reports retain truncation and hierarchy limitations. Resource
|
||||
sessions have no executable subject or executable digest; archive identities
|
||||
must not be promoted to executable identity.
|
||||
|
||||
## Completed workflow and accounting
|
||||
|
||||
`interface-builder-views.mjs` uses the real SDK and compiled stdio MCP server:
|
||||
connect, discover the full catalog, open bundle resources, decode with summary
|
||||
delivery, exhaust three 32-row node pages and one edge page for the selected
|
||||
document, repeat those same four pages as a warm query diagnostic, export the
|
||||
complete Evidence, verify the answer and complete parent, and await cleanup.
|
||||
The repeat is included in all whole-task costs. Each run starts a fresh server
|
||||
and isolated account. Decoding is the first decode in that server; retained
|
||||
queries follow the summary's first validation. OS caches were not flushed, so
|
||||
these are not disk-cold measurements.
|
||||
|
||||
Artifact acquisition/extraction, build time and independent oracle preparation
|
||||
are outside this analysis task. No actual model session or billed model token
|
||||
usage was measured. The SDK benchmark answers a fixed factual question; it does
|
||||
not establish agent usability or general provider performance.
|
||||
|
||||
Experiments ran serially using `resource-run.py --observe-payload-exit`: one CPU
|
||||
(affinity 15), 100% quota, 4 GiB hard memory / 3 GiB early stop, no swap and a
|
||||
192-task ceiling. CPU and peak memory cover the SDK, server and observer family.
|
||||
Peak is cgroup memory.peak, including charged page cache, rather than summed RSS.
|
||||
Payload-exit cgroup counters are authenticated and cleanup is verified; final
|
||||
whole-scope counters are unavailable after the transient scope disappears.
|
||||
Every accepted and failed task has exit/cleanup verification and zero observed
|
||||
memory high/max/OOM/OOM-kill and PID-limit events. Missing final counters are
|
||||
not interpreted as zero.
|
||||
|
||||
## Observations
|
||||
|
||||
Medians across all accepted baseline runs and the measured optimized
|
||||
production-source cohort. The later harness-only review fix does not change
|
||||
those production files; its revalidation is recorded separately. Five
|
||||
earlier candidate runs remain labeled pre-review diagnostics and are excluded
|
||||
from the final-source medians. One failed initial harness run is also retained.
|
||||
All individual runs, phase timings, token estimates and raw receipt hashes are
|
||||
in `interface-builder-views.json`.
|
||||
|
||||
| Admitted documents | Revision | Runs | Whole wall s | Family CPU s | Family peak MiB | First four pages ms | Repeated four pages ms |
|
||||
| ------------------ | -------- | ---- | ------------ | ------------ | --------------- | ------------------- | ---------------------- |
|
||||
| 64 | baseline | 5 | 30.798 | 30.532 | 1614.7 | 2606.3 | 1817.8 |
|
||||
| 64 | final | 5 | 27.683 | 27.424 | 1551.1 | 338.8 | 94.3 |
|
||||
| 1 | baseline | 4 | 15.702 | 15.456 | 952.6 | 389.5 | 101.0 |
|
||||
| 1 | final | 4 | 18.101 | 17.822 | 944.8 | 367.5 | 101.7 |
|
||||
|
||||
The larger sampled task has about 10% lower whole wall/CPU medians and 94.8%
|
||||
lower repeated-page latency. Whole-task ranges overlap substantially:
|
||||
27.420–51.481 s baseline and 25.247–45.451 s final. Startup/initial decoding
|
||||
vary independently of the retained-query change; these observations do not
|
||||
establish a general whole-task speedup or stable memory reduction. Both
|
||||
versions' slow first runs remain included.
|
||||
|
||||
The small sampled task is slower overall (15.3% wall), with no repeat-page
|
||||
benefit. In the two later interleaved small pairs, baseline took 16.883/18.317 s
|
||||
and final took 16.988/20.276 s. Do not interpret the earlier unpaired small
|
||||
measurements as evidence of a cold-start improvement. Startup variance remains
|
||||
unexplained; this optimization is justified by repeated large-parent queries,
|
||||
not a claim that every completed task becomes faster.
|
||||
|
||||
An additional production-boundary diagnostic isolates the changed projection
|
||||
from startup, decoding and transport. It imports both compiled owners, seals
|
||||
separate clones of the actual exported parent with each owner's snapshot
|
||||
module, and alternates version order for three epochs. Each epoch projects a
|
||||
summary and the same eight pages; every resulting payload is equal. Median
|
||||
projection CPU falls from 157.4 to 30.3 ms for the one-document parent and
|
||||
6003.5 to 914.7 ms for the 64-document parent. Snapshot preparation, Evidence
|
||||
authentication and all adapters are excluded from this diagnostic; the public
|
||||
tasks above account for their whole costs. First large-summary CPU rises from
|
||||
620.2 to 879.8 ms because representation comparison is paid up front. This is a
|
||||
reuse tradeoff, not a faster first decode. The diagnostic source/receipt hashes,
|
||||
per-call wall/CPU times and bounded process-family counters are retained in the
|
||||
JSON; it does not replace real public workflow evidence.
|
||||
|
||||
Selection still scans retained rows to count every match; no additional
|
||||
per-document index is retained. The whole original graph and serialization
|
||||
costs still exist.
|
||||
|
||||
Public input/output contracts and complete parent Evidence are unchanged.
|
||||
Tokenizer estimates count the entire 212-tool input catalog once, every RPC's
|
||||
arguments and text response, including warm diagnostics and export. The raw SDK
|
||||
catalog, including output schemas, is reported separately. Structured content
|
||||
and model-specific discovery/exposure may incur different costs. The 64-document task estimates are 282,885 baseline and 282,887 for the
|
||||
initial candidate (198,492 input-catalog tokens in each); the two-token change
|
||||
comes solely from the export destination. The first ten RPC requests and
|
||||
replies are exactly equal. Raw SDK catalog exposure estimates 891,652 tokens
|
||||
including output schemas. Final-source values and every run are retained in
|
||||
the JSON. There is no claimed token reduction.
|
||||
|
||||
## Ownership and reuse
|
||||
|
||||
The Interface Builder view owner validates an unknown normalized result with
|
||||
its existing schema. Reuse requires the application's seal plus exact owned
|
||||
immutable snapshot identity and representation-preserving comparison against
|
||||
the parsed result. A weak set records only successful snapshots. It retains no
|
||||
second graph, file-path cache, index, transient errors or failed subject
|
||||
bindings. Every view still checks its current parent's target binding and
|
||||
constructs current parent provenance and limitations. Different results,
|
||||
mutable imports, forged seals and schema normalization revalidate normally.
|
||||
|
||||
Document selection uses the shared matching pager to count all matching rows
|
||||
while retaining only the requested page. Unfiltered requests keep direct
|
||||
slicing. Row IDs, ordering, provenance, decoder truncation and unknowns remain
|
||||
unchanged. CLI and MCP share the same application/domain implementation.
|
||||
|
||||
The snapshot comparison helper's type accepts owning schemas with optional
|
||||
undefined members; its runtime comparison is unchanged and refuses a parsed
|
||||
representation that actually adds an undefined field.
|
||||
|
||||
## Reproduction and limits
|
||||
|
||||
Extract the official app without running it. On the baseline, save complete
|
||||
CLI JSON with `rea decode-interface-builder <XLD.app> --format json` and a
|
||||
separate control with `rea decode-interface-builder <XLD.app> --max-documents 1
|
||||
--format json` (without profiler logging mixed into either JSON). Then:
|
||||
|
||||
```sh
|
||||
python3 experiments/analysis-efficiency/interface-builder-oracle.py \
|
||||
--bundle '<XLD.app>' \
|
||||
--document 'Contents/PlugIns/XLDAacOutput.bundle/Contents/Resources/English.lproj/XLDAacOutput.nib' \
|
||||
--baseline '<complete-64-document-evidence.json>' \
|
||||
--small-baseline '<complete-1-document-evidence.json>' --output '<oracle.json>'
|
||||
python3 experiments/analysis-efficiency/resource-run.py --observe-payload-exit -- \
|
||||
node experiments/analysis-efficiency/interface-builder-views.mjs \
|
||||
--runtime '<absolute baseline or candidate checkout>' --input '<XLD.app>' \
|
||||
--oracle '<oracle.json>' --output '<new output directory>' --documents 64
|
||||
```
|
||||
|
||||
Repeat with `--documents 1`. Paths must be absolute. The oracle uses standard
|
||||
Python only; token estimates use offline tiktoken 0.12.0 / cl100k_base. Count
|
||||
compact JSON tool name/description/inputSchema entries once, compact
|
||||
`{name,arguments}` for every transcript event, and every returned text block;
|
||||
these are estimates, not actual model usage.
|
||||
|
||||
Failed attempts remain visible. `base64-a` completed all eight page RPCs but the
|
||||
first harness incorrectly expected an action-source `contains` edge. Production
|
||||
correctly returned `target_action`; the harness was corrected before accepted
|
||||
runs. That failure's costs/receipt remain in the JSON. An initial typecheck
|
||||
refused the snapshot helper's unnecessarily narrow generic constraint for the
|
||||
optional resource root; the constraint was corrected without changing runtime
|
||||
comparison. Build resource observations with a still-exiting Turbo child are
|
||||
not qualified task measurements.
|
||||
|
||||
KeepingYouAwake 1.6.8 (official ZIP SHA-256
|
||||
`8001a149b4490c008fdac19898bce9902d516c4aa6412a7eb0f9a37443b15c6b`)
|
||||
was also downloaded and smoke-decoded through the real CLI
|
||||
(17 documents, 1,369 nodes, 542 edges), but its NIBArchive records cannot be read
|
||||
by this plistlib oracle. It is not a comparative benchmark or independent NIB
|
||||
correctness claim. macOS ibtool, runtime UI, other archive variants, globally
|
||||
complete hierarchy/class interpretation, #5720/#5721 and the remaining source
|
||||
decoder issues are unverified or unchanged here.
|
||||
|
||||
## Integration verification
|
||||
|
||||
The measured comparison above was pinned to `f801b2fbf`. The branch was then
|
||||
rebased onto `f5410bdc4` (the separate #5806 scalar-record fix). All six recorded owned-source
|
||||
fingerprints remained identical across that rebase. On the rebased runtime both real SDK
|
||||
tasks passed again, with the complete retained parent equal to the original
|
||||
baseline for both admission sizes. The complete real CLI Evidence and portable
|
||||
CLI page also equal the baseline/MCP results. These integration runs are recorded
|
||||
separately in the JSON and excluded from the pinned comparison medians.
|
||||
|
||||
The relevant 12-file suite passed 204 tests after the paging refactor. After
|
||||
rebasing, another six-file run passed 78 tests covering scalar source facts,
|
||||
keyed archive number metadata, Interface Builder views, production MCP summary
|
||||
paging and compiled CLI numeric/hierarchy boundaries. Both cohorts verified
|
||||
owned cleanup with no observed memory/PID limit events; tests used the bounded
|
||||
two-CPU, 4 GiB guard. Native ibtool/macOS runtime behavior is not established by
|
||||
these tests.
|
||||
|
||||
Greptile identified that the original script only enforced the pre-change
|
||||
comparison for 64 documents; the one-document equality above had been checked
|
||||
manually. The oracle now requires both baseline files and the harness compares
|
||||
the selected complete parent, including its Evidence ID and parameters, for
|
||||
either limit. Both real workflows passed again. An intentional wrong baseline
|
||||
(the 64-document parent supplied for the 1-document task) is rejected after all
|
||||
other real-task checks succeed, with cleanup verified. These review checks and
|
||||
updated harness fingerprints are recorded separately. Production source and
|
||||
original comparison medians are unchanged; original measured fingerprints are
|
||||
preserved rather than relabeled as the new harness.
|
||||
@@ -0,0 +1,238 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { createHash } from "node:crypto";
|
||||
import { createWriteStream } from "node:fs";
|
||||
import { mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises";
|
||||
import { createRequire } from "node:module";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join, resolve } from "node:path";
|
||||
import { finished } from "node:stream/promises";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { parseArgs } from "node:util";
|
||||
import { createRetainedQueryCaller } from "./retained-query-calls.mjs";
|
||||
import { finalizeRetainedQueryReceipt } from "./retained-query-finalization.mjs";
|
||||
|
||||
const { values } = parseArgs({
|
||||
options: {
|
||||
runtime: { type: "string" },
|
||||
input: { type: "string" },
|
||||
oracle: { type: "string" },
|
||||
output: { type: "string" },
|
||||
documents: { type: "string", default: "64" },
|
||||
},
|
||||
});
|
||||
for (const key of ["runtime", "input", "oracle", "output"])
|
||||
assert.equal(values[key], resolve(values[key]));
|
||||
const maxDocuments = Number(values.documents);
|
||||
assert.ok([1, 64].includes(maxDocuments));
|
||||
const oracle = JSON.parse(await readFile(values.oracle, "utf8"));
|
||||
const baselinePath = oracle.complete_result_paths?.[String(maxDocuments)];
|
||||
assert.equal(
|
||||
typeof baselinePath,
|
||||
"string",
|
||||
"Provide a pre-change baseline for the selected document limit.",
|
||||
);
|
||||
assert.equal(baselinePath, resolve(baselinePath));
|
||||
const sha256 = (bytes) => createHash("sha256").update(bytes).digest("hex");
|
||||
assert.equal(
|
||||
sha256(await readFile(join(values.input, oracle.document))),
|
||||
oracle.archive_sha256,
|
||||
);
|
||||
const require = createRequire(join(values.runtime, "package.json"));
|
||||
const { Client } = await import(
|
||||
pathToFileURL(require.resolve("@modelcontextprotocol/client"))
|
||||
);
|
||||
const { StdioClientTransport } = await import(
|
||||
pathToFileURL(require.resolve("@modelcontextprotocol/client/stdio"))
|
||||
);
|
||||
await mkdir(values.output, { mode: 0o700 });
|
||||
const account = await mkdtemp(join(tmpdir(), "rea-interface-builder-views-"));
|
||||
const report = {
|
||||
question:
|
||||
"Identify archived AAC settings outlets and the VBR action with source/destination object identities, coverage and complete Evidence access.",
|
||||
max_documents: maxDocuments,
|
||||
calls: [],
|
||||
};
|
||||
const client = new Client({
|
||||
name: "rea-interface-builder-views",
|
||||
version: "1",
|
||||
});
|
||||
const transport = new StdioClientTransport({
|
||||
command: process.execPath,
|
||||
args: [join(values.runtime, "scripts/rea.mjs"), "mcp"],
|
||||
env: {
|
||||
HOME: account,
|
||||
PATH: process.env.PATH,
|
||||
NODE_OPTIONS: "--max-old-space-size=2048",
|
||||
UV_THREADPOOL_SIZE: "1",
|
||||
REA_LOG_LEVEL: "silent",
|
||||
},
|
||||
stderr: "pipe",
|
||||
});
|
||||
const serverLog = createWriteStream(join(values.output, "server.log"));
|
||||
const serverLogFinished = finished(serverLog);
|
||||
serverLogFinished.catch(() => {});
|
||||
transport.stderr?.pipe(serverLog);
|
||||
const transcript = [];
|
||||
const call = createRetainedQueryCaller(client, (receipt, event) => {
|
||||
report.calls.push(receipt);
|
||||
transcript.push(event);
|
||||
});
|
||||
async function result(name, input, phase = name) {
|
||||
const reply = await call(name, input, phase);
|
||||
assert.ok(!reply.isError, JSON.stringify(reply));
|
||||
assert.ok(reply.structuredContent);
|
||||
assert.equal(reply.content.length, 1);
|
||||
assert.equal(reply.content[0].type, "text");
|
||||
assert.deepEqual(JSON.parse(reply.content[0].text), reply.structuredContent);
|
||||
return reply.structuredContent;
|
||||
}
|
||||
try {
|
||||
await client.connect(transport);
|
||||
const catalog = await client.listTools();
|
||||
assert.equal(catalog.nextCursor, undefined);
|
||||
report.catalog_tools = catalog.tools.length;
|
||||
await writeFile(join(values.output, "catalog.json"), JSON.stringify(catalog));
|
||||
await result("open_bundle_resources", { path: values.input });
|
||||
const initial = await result("decode_interface_builder", {
|
||||
max_documents: maxDocuments,
|
||||
detail: "summary",
|
||||
});
|
||||
const summary = initial.normalized_result;
|
||||
report.parent_evidence_id = summary.parent_evidence_id;
|
||||
assert.equal(summary.resource_root.executable_sha256, null);
|
||||
assert.equal(summary.artifact.sha256, null);
|
||||
assert.equal(summary.summary.truncated, true);
|
||||
assert.ok(
|
||||
summary.summary.documents.some(
|
||||
(d) =>
|
||||
d.relative_path === oracle.document &&
|
||||
d.archive_sha256 === oracle.archive_sha256,
|
||||
),
|
||||
);
|
||||
const collections = {};
|
||||
for (const pass of ["first", "warm"]) {
|
||||
for (const collection of ["nodes", "edges"]) {
|
||||
const rows = [];
|
||||
let offset = 0;
|
||||
for (;;) {
|
||||
const selected = await result(
|
||||
"inspect_analysis_view",
|
||||
{
|
||||
source: {
|
||||
kind: "retained-evidence",
|
||||
evidence_id: report.parent_evidence_id,
|
||||
},
|
||||
view: {
|
||||
kind: "interface-builder",
|
||||
collection,
|
||||
document: oracle.document,
|
||||
offset,
|
||||
limit: 32,
|
||||
},
|
||||
},
|
||||
`retained:${pass}:${collection}:${offset}`,
|
||||
);
|
||||
const page = selected.normalized_result;
|
||||
assert.equal(page.parent_evidence_id, report.parent_evidence_id);
|
||||
assert.equal(page.source_truncated, true);
|
||||
assert.ok(page.unknowns.length > 0);
|
||||
rows.push(...page.items);
|
||||
if (page.coverage.exhausted) {
|
||||
assert.equal(rows.length, page.coverage.total);
|
||||
break;
|
||||
}
|
||||
assert.ok(page.items.length > 0);
|
||||
offset += page.items.length;
|
||||
}
|
||||
if (pass === "warm") assert.deepEqual(rows, collections[collection]);
|
||||
else collections[collection] = rows;
|
||||
}
|
||||
}
|
||||
const byId = new Map(collections.nodes.map((n) => [n.id, n]));
|
||||
for (const expected of oracle.connections) {
|
||||
const connector = collections.nodes.find(
|
||||
(n) => n.kind === expected.kind && n.name === expected.name,
|
||||
);
|
||||
assert.ok(connector);
|
||||
const sourceRelation =
|
||||
expected.kind === "outlet" ? "contains" : "target_action";
|
||||
const source = collections.edges.find(
|
||||
(e) => e.to === connector.id && e.relation === sourceRelation,
|
||||
);
|
||||
assert.equal(
|
||||
byId.get(source.from).attributes.interface_builder_object_id,
|
||||
expected.source,
|
||||
);
|
||||
const relation = expected.kind === "outlet" ? "outlet_to" : "target_action";
|
||||
const destination = collections.edges.find(
|
||||
(e) =>
|
||||
e.from === connector.id &&
|
||||
e.relation === relation &&
|
||||
byId.get(e.to)?.attributes.interface_builder_object_id ===
|
||||
expected.destination,
|
||||
);
|
||||
assert.equal(
|
||||
byId.get(destination.to).attributes.interface_builder_object_id,
|
||||
expected.destination,
|
||||
);
|
||||
for (const row of [connector, source, destination])
|
||||
assert.ok(
|
||||
row.evidence.some(
|
||||
(e) =>
|
||||
e.artifact_path === oracle.document &&
|
||||
e.artifact_sha256 === oracle.archive_sha256,
|
||||
),
|
||||
);
|
||||
}
|
||||
report.answer = oracle.connections;
|
||||
await result("export_evidence_bundle", {
|
||||
path: join(values.output, "evidence.json"),
|
||||
});
|
||||
const bundle = JSON.parse(
|
||||
await readFile(join(values.output, "evidence.json"), "utf8"),
|
||||
);
|
||||
const parent = bundle.records.find(
|
||||
(e) => e.evidence_id === report.parent_evidence_id,
|
||||
);
|
||||
assert.equal(parent.subject, null);
|
||||
assert.equal(parent.operation, "decode_interface_builder");
|
||||
const full = parent.normalized_result;
|
||||
for (const collection of ["nodes", "edges"])
|
||||
assert.deepEqual(
|
||||
collections[collection],
|
||||
full.graph[collection].filter((r) =>
|
||||
r.evidence.some((e) => e.artifact_path === oracle.document),
|
||||
),
|
||||
);
|
||||
const baselineBytes = await readFile(baselinePath, "utf8");
|
||||
const expectedParent = JSON.parse(baselineBytes);
|
||||
report.baseline_sha256 = sha256(baselineBytes);
|
||||
report.baseline_evidence_id = expectedParent.evidence_id;
|
||||
const mismatch = `Complete retained Evidence differs from the pre-change ${maxDocuments}-document baseline.`;
|
||||
assert.equal(parent.evidence_id, expectedParent.evidence_id, mismatch);
|
||||
assert.deepEqual(parent, expectedParent, mismatch);
|
||||
report.available_counts = {
|
||||
nodes: full.graph.nodes.length,
|
||||
edges: full.graph.edges.length,
|
||||
};
|
||||
report.oracle_sha256 = sha256(await readFile(values.oracle));
|
||||
report.status = "passed";
|
||||
} catch (cause) {
|
||||
report.status = "failed";
|
||||
report.failure = String(cause?.stack ?? cause);
|
||||
process.exitCode = 1;
|
||||
} finally {
|
||||
if (
|
||||
!(await finalizeRetainedQueryReceipt({
|
||||
report,
|
||||
client,
|
||||
transport,
|
||||
account,
|
||||
serverLog,
|
||||
serverLogFinished,
|
||||
output: values.output,
|
||||
transcript,
|
||||
}))
|
||||
)
|
||||
process.exitCode = 1;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
"""Summarize completed CLI trials; token counts are estimates, not model usage."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import statistics
|
||||
from pathlib import Path
|
||||
import tiktoken
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('root', type=Path)
|
||||
parser.add_argument('--output', type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
root = args.root
|
||||
inputs = json.loads((root / 'measurement-inputs.json').read_text())
|
||||
expected = inputs['expected_runtime_bindings']
|
||||
assert expected['complete']['git_revision'] == inputs['baseline_revision']
|
||||
assert expected['selected']['git_revision'] == inputs['feature_parent_revision']
|
||||
assert expected['complete']['root'] != expected['selected']['root']
|
||||
assert expected['complete']['compiled_cli_sha256'] != expected['selected']['compiled_cli_sha256']
|
||||
assert expected['complete']['source_diff_sha256'] == hashlib.sha256(b'').hexdigest()
|
||||
assert expected['complete']['untracked_source_sha256'] == hashlib.sha256(b'[]').hexdigest()
|
||||
enc = tiktoken.get_encoding('cl100k_base')
|
||||
count = lambda text: len(enc.encode(text, disallowed_special=()))
|
||||
compact = lambda obj: json.dumps(obj, ensure_ascii=False, separators=(',', ':'))
|
||||
runs = []
|
||||
for case in sorted(root.glob('pair-*')):
|
||||
if not case.is_dir():
|
||||
continue
|
||||
report = json.loads((case / 'report.json').read_text())
|
||||
assert report['status'] == 'passed' and report['cleanup_verified']
|
||||
assert report['runtime_binding_verified']
|
||||
assert report['runtime_binding'] == expected[report['mode']], case.name
|
||||
assert str(Path(report['runtime']).resolve()) == report['runtime_binding']['root']
|
||||
receipt = next(json.loads(line) for line in reversed(case.with_name(case.name + '.log').read_text().splitlines()) if line.startswith('{"resource_scope":'))
|
||||
obs = receipt['payload_resource_observation']
|
||||
assert receipt['abort'] is None and receipt['payload_resource_observation_verified']
|
||||
assert obs['payload_exit_code'] == 0 and obs['payload_cleanup_verified']
|
||||
assert obs['resource_events']['memory.events']['oom_kill'] == 0
|
||||
tokens = {'question_and_recipe': count(report['question'] + '\n' + report['recipe']),
|
||||
'arguments': sum(count(compact(call['arguments'])) for call in report['calls']),
|
||||
'help_and_replies': sum(count((case / call['stdout_file']).read_text()) for call in report['calls'])}
|
||||
tokens['whole_task'] = sum(tokens.values())
|
||||
runs.append({'case': case.name, 'mode': report['mode'], 'cache': report['cache'], 'runtime': report['runtime'], 'runtime_binding': report['runtime_binding'], 'runtime_binding_audit_ms': report['runtime_binding_audit_ms'],
|
||||
'wall_seconds': receipt['elapsed_seconds'], 'cpu_seconds': obs['cpu_stat']['usage_usec'] / 1e6,
|
||||
'peak_process_family_bytes_including_page_cache': obs['memory_peak_bytes'],
|
||||
'tokens_estimated': tokens, 'calls': report['calls'],
|
||||
'parent_evidence_id': report['parent_evidence_id'], 'parent_semantic_sha256': report['parent_semantic_sha256'],
|
||||
'answer_sha256': report['answer_sha256'], 'oracle_verified': report['oracle_verified'],
|
||||
'cleanup_verified': True, 'resource_events': obs['resource_events']})
|
||||
assert len(runs) == 12
|
||||
for key in ['answer_sha256', 'parent_semantic_sha256', 'parent_evidence_id']:
|
||||
assert len({row[key] for row in runs}) == 1, key
|
||||
summary = {}
|
||||
for cache in ['cold', 'warm']:
|
||||
summary[cache] = {}
|
||||
for mode in ['complete', 'selected']:
|
||||
rows = [r for r in runs if r['mode'] == mode and r['cache'] == cache]
|
||||
assert len(rows) == 3
|
||||
summary[cache][mode] = {key: {'median': statistics.median(r[key] for r in rows), 'min': min(r[key] for r in rows), 'max': max(r[key] for r in rows)} for key in ['wall_seconds', 'cpu_seconds', 'peak_process_family_bytes_including_page_cache']}
|
||||
summary[cache][mode]['whole_task_tokens_estimated'] = [r['tokens_estimated']['whole_task'] for r in rows]
|
||||
result = {'status': 'passed', 'tokenizer': 'tiktoken==0.12.0/cl100k_base; estimates, not model usage',
|
||||
'context_scope': 'Question, supplied command recipe, actual selected-command help, all logical CLI argv and all stdout. No model invoked; reasoning, framing, irrelevant tool discovery and actual native-agent usage unmeasured.',
|
||||
'cache_scope': 'cold disables Node compile cache; warm primes the identical workflow once per runtime/mode before timing. Fresh processes and isolated HOME each trial; OS page cache uncontrolled.',
|
||||
'resource_scope': 'Whole task driver plus all CLI children; includes pre/post source-and-compiled-runtime binding verification, bundle publication/authentication, help, extra calls and local answer/oracle checking. Kernel cgroup peak includes file cache; not sampled RSS. Download/build/oracle preparation and priming excluded.',
|
||||
'acquisition': json.loads((root / 'acquisition.json').read_text()), 'measurement_inputs': inputs,
|
||||
'summary': summary, 'runs': runs}
|
||||
native = root / 'native-control'
|
||||
if native.exists():
|
||||
binding = json.loads((native / 'runtime-binding.json').read_text())
|
||||
assert binding['runtime_binding_verified'] and binding['runtime_binding'] == expected['complete']
|
||||
assert str(Path(binding['runtime']).resolve()) == binding['runtime_binding']['root']
|
||||
receipt = next(json.loads(line) for line in reversed((root / 'native-control.log').read_text().splitlines()) if line.startswith('{"resource_scope":'))
|
||||
obs = receipt['payload_resource_observation']
|
||||
assert receipt['abort'] is None and receipt['payload_resource_observation_verified'] and obs['payload_exit_code'] == 0 and obs['payload_cleanup_verified']
|
||||
baseline_case = root / next(run['case'] for run in runs if run['mode'] == 'complete')
|
||||
assert json.loads((native / 'answer.json').read_text()) == json.loads((baseline_case / 'answer.json').read_text())
|
||||
control_source = Path(__file__).with_name('managed-cli-local-control.py').read_text()
|
||||
result['existing_native_control'] = {'runtime': binding['runtime'], 'runtime_binding': binding['runtime_binding'], 'runtime_binding_audit_ms': binding['runtime_binding_audit_ms'], 'repetitions': 1,
|
||||
'tokens_estimated_script_plus_help_plus_answer': count(control_source) + count((native / 'help.txt').read_text()) + count((native / 'answer.json').read_text()),
|
||||
'token_scope': 'Projection source, original CLI help and returned answer; excludes shared question and launcher argv. No actual model usage measured.',
|
||||
'wall_seconds': receipt['elapsed_seconds'], 'cpu_seconds': obs['cpu_stat']['usage_usec'] / 1e6,
|
||||
'peak_process_family_bytes_including_page_cache': obs['memory_peak_bytes'], 'answer_matches': True, 'cleanup_verified': True}
|
||||
args.output.write_text(json.dumps(result, indent=2) + '\n')
|
||||
print(json.dumps(summary, indent=2))
|
||||
@@ -0,0 +1,44 @@
|
||||
"""Existing native code-composition control: save complete stdout, return selected facts."""
|
||||
import argparse
|
||||
import json
|
||||
import subprocess
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('runtime', type=Path)
|
||||
parser.add_argument('target', type=Path)
|
||||
parser.add_argument('output', type=Path)
|
||||
parser.add_argument('--measurement-inputs', type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
args.output.mkdir()
|
||||
node = 'node'
|
||||
inputs = json.loads(args.measurement_inputs.read_text())
|
||||
expected = inputs['expected_runtime_bindings']['complete']
|
||||
assert expected['git_revision'] == inputs['baseline_revision']
|
||||
helper = Path(__file__).with_name('managed-cli-runtime.mjs')
|
||||
def capture_binding():
|
||||
return json.loads(subprocess.check_output([node, str(helper), str(args.runtime)], text=True))
|
||||
binding_started = time.monotonic()
|
||||
binding = capture_binding()
|
||||
binding_audit_ms = {'before': (time.monotonic() - binding_started) * 1000}
|
||||
assert binding == expected
|
||||
|
||||
entry = str(args.runtime / 'scripts/rea.mjs')
|
||||
help_result = subprocess.run([node, entry, 'inspect-managed-members', '--help'], check=True, capture_output=True, text=True)
|
||||
(args.output / 'help.txt').write_text(help_result.stdout)
|
||||
with (args.output / 'parent.json').open('w') as file:
|
||||
subprocess.run([node, entry, 'inspect-managed-members', str(args.target), '--type', 'Newtonsoft.Json.JsonConvert', '--json'], check=True, stdout=file)
|
||||
parent = json.loads((args.output / 'parent.json').read_text())
|
||||
data = parent['normalized_result']
|
||||
answer = {'parent_evidence_id': parent['evidence_id'], 'artifact_sha256': data['artifact']['sha256'],
|
||||
'selection': data['selection'], 'source_coverage': data['coverage'],
|
||||
'total_methods': len(data['methods']), 'total_member_refs': len(data['member_refs']),
|
||||
'methods': data['methods'][:8], 'member_refs': data['member_refs'][:16],
|
||||
'limitation': 'MemberRef rows are assembly-wide; methods are selected-type rows. Page exhaustion is not an absence claim.'}
|
||||
(args.output / 'answer.json').write_text(json.dumps(answer))
|
||||
binding_finished = time.monotonic()
|
||||
assert capture_binding() == binding
|
||||
binding_audit_ms['after'] = (time.monotonic() - binding_finished) * 1000
|
||||
(args.output / 'runtime-binding.json').write_text(json.dumps({'runtime': str(args.runtime), 'runtime_binding': binding, 'runtime_binding_verified': True, 'runtime_binding_audit_ms': binding_audit_ms}))
|
||||
print(json.dumps(answer))
|
||||
@@ -0,0 +1,18 @@
|
||||
import json,hashlib,argparse
|
||||
from pathlib import Path
|
||||
import dnfile
|
||||
parser=argparse.ArgumentParser();parser.add_argument('root',type=Path);root=parser.parse_args().root;path=root/'Newtonsoft.Json.dll'
|
||||
pe=dnfile.dnPE(str(path));assert pe.net is not None
|
||||
counts={name:len(getattr(pe.net.mdtables,name).rows) if getattr(pe.net.mdtables,name,None) else 0 for name in ['TypeDef','MethodDef','MemberRef','Field','Property','Event','Param','StandAloneSig','TypeSpec','ExportedType']}
|
||||
selected=[]
|
||||
for index,row in enumerate(pe.net.mdtables.TypeDef.rows,1):
|
||||
name=(str(row.TypeNamespace)+'.' if str(row.TypeNamespace) else '')+str(row.TypeName)
|
||||
if name!='Newtonsoft.Json.JsonConvert':continue
|
||||
selected.append({'token':f'0x{0x02000000|index:08x}','name':name,'methods':[{'token':f'0x{0x06000000|m.row_index:08x}','name':str(m.row.Name),'rva':m.row.Rva,'signature_hex':m.row.Signature.value.hex()} for m in row.MethodList]})
|
||||
assert len(selected)==1
|
||||
refs=[{'token':f'0x{0x0a000000|i:08x}','name':str(row.Name),'signature_hex':row.Signature.value.hex()} for i,row in enumerate(pe.net.mdtables.MemberRef.rows[:16],1)]
|
||||
assembly=pe.net.mdtables.Assembly.rows[0]
|
||||
oracle={'decoder':'dnfile==0.18.0 (independent Python PE/CLI parser)','assembly_sha256':hashlib.sha256(path.read_bytes()).hexdigest(),'assembly_name':str(assembly.Name),'assembly_version':'.'.join(str(getattr(assembly,k)) for k in ['MajorVersion','MinorVersion','BuildNumber','RevisionNumber']),'row_counts':counts,'selected_types':selected,'member_refs_first_16':refs,'target_execution':False}
|
||||
(root/'oracle.json').write_text(json.dumps(oracle,indent=2)+'\n')
|
||||
print(json.dumps({'assembly':oracle['assembly_name'],'version':oracle['assembly_version'],'row_counts':counts,'selected_type':selected[0]['name'],'selected_methods':len(selected[0]['methods']),'target_execution':False}))
|
||||
pe.close()
|
||||
@@ -0,0 +1,106 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { createHash } from "node:crypto";
|
||||
import { readFile, readdir, realpath } from "node:fs/promises";
|
||||
import { join, relative } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
const sha = (value) => createHash("sha256").update(value).digest("hex");
|
||||
|
||||
/** Bind a trial to its source checkout and compiled runtime, including deferred assets. */
|
||||
export const captureRuntimeBinding = async (runtime, kind = "cli") => {
|
||||
assert.ok(kind === "cli" || kind === "mcp", "Unknown runtime entry");
|
||||
const root = await realpath(runtime);
|
||||
const git = (args) =>
|
||||
execFileSync("git", args, { cwd: root, maxBuffer: 16 * 1024 * 1024 });
|
||||
const gitRevision = git(["rev-parse", "HEAD"]).toString().trim();
|
||||
const sourcePaths = ["src", "scripts", "package.json", "package-lock.json"];
|
||||
const sourceDiff = git([
|
||||
"diff",
|
||||
"--no-ext-diff",
|
||||
"--no-textconv",
|
||||
"--binary",
|
||||
"HEAD",
|
||||
"--",
|
||||
...sourcePaths,
|
||||
]);
|
||||
const untracked = git([
|
||||
"ls-files",
|
||||
"--others",
|
||||
"--exclude-standard",
|
||||
"-z",
|
||||
"--",
|
||||
...sourcePaths,
|
||||
])
|
||||
.toString()
|
||||
.split("\0")
|
||||
.filter(Boolean)
|
||||
.sort();
|
||||
const untrackedEntries = [];
|
||||
for (const name of untracked)
|
||||
untrackedEntries.push([name, sha(await readFile(join(root, name)))]);
|
||||
const files = ["scripts/rea.mjs", "package.json", "package-lock.json"];
|
||||
const visit = async (directory) => {
|
||||
const entries = await readdir(directory, { withFileTypes: true });
|
||||
for (const entry of entries.sort((a, b) =>
|
||||
a.name < b.name ? -1 : a.name > b.name ? 1 : 0,
|
||||
)) {
|
||||
const path = join(directory, entry.name);
|
||||
assert.ok(!entry.isSymbolicLink(), `Unbound compiled CLI link: ${path}`);
|
||||
if (entry.isDirectory()) await visit(path);
|
||||
else if (entry.isFile() && /\.(?:[cm]?js|json)$/.test(entry.name))
|
||||
files.push(relative(root, path));
|
||||
}
|
||||
};
|
||||
// MCP materializes additional workers and reads build-owned JSON after
|
||||
// discovery. Bind every compiled JS/JSON asset, rather than only its entry.
|
||||
await visit(join(root, kind === "mcp" ? "dist" : "dist/cli-runtime"));
|
||||
assert.ok(
|
||||
files.includes(
|
||||
kind === "mcp"
|
||||
? join("dist", "mcp", "main.js")
|
||||
: join("dist", "cli-runtime", "cli.js"),
|
||||
),
|
||||
"Missing compiled runtime entry",
|
||||
);
|
||||
const hash = createHash("sha256");
|
||||
let bytes = 0;
|
||||
for (const name of files.sort()) {
|
||||
const value = await readFile(join(root, name));
|
||||
bytes += value.length;
|
||||
hash.update(JSON.stringify([name, value.length, sha(value)]) + "\n");
|
||||
}
|
||||
return {
|
||||
binding_version: kind === "mcp" ? 2 : 1,
|
||||
root,
|
||||
node: process.version,
|
||||
git_revision: gitRevision,
|
||||
source_diff_sha256: sha(sourceDiff),
|
||||
untracked_source_sha256: sha(JSON.stringify(untrackedEntries)),
|
||||
...(kind === "mcp"
|
||||
? {
|
||||
compiled_runtime_sha256: hash.digest("hex"),
|
||||
compiled_runtime_files: files.length,
|
||||
compiled_runtime_bytes: bytes,
|
||||
}
|
||||
: {
|
||||
compiled_cli_sha256: hash.digest("hex"),
|
||||
compiled_cli_files: files.length,
|
||||
compiled_cli_bytes: bytes,
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
export const assertRuntimeBinding = (actual, expected, mode) => {
|
||||
assert.ok(expected, `Missing expected runtime binding for ${mode}`);
|
||||
assert.deepEqual(actual, expected, `Runtime binding differs for ${mode}`);
|
||||
};
|
||||
|
||||
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
await captureRuntimeBinding(process.argv[2], process.argv[3]),
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"scope": "Single completed SDK regression after shared JSON reader/admission changes; not a new paired source-to-bundle performance comparison. Existing semantic-node cap one answers static correspondence only; no equal semantic-graph coverage claim. Corpus/reference preparation performed earlier and excluded.",
|
||||
"artifact": {
|
||||
"name": "Redux Toolkit 2.2.7",
|
||||
"tarball_sha256": "f2517c466b50424b661a27e48039f15db7783e5822f46b5c7d39f20104ac67a9"
|
||||
},
|
||||
"runtime_parent_revision": "4fab2dfda16236dc407aa179920780d6a970dda3",
|
||||
"production_manifest": "managed-cli.json#measurement_inputs.production_sources_sha256",
|
||||
"input_schema_profile": "default compact",
|
||||
"output_schema_profile": "full",
|
||||
"tokens_estimated": {
|
||||
"input_catalog_once": 49054,
|
||||
"arguments": 307,
|
||||
"text_replies": 7017,
|
||||
"whole_task": 56378
|
||||
},
|
||||
"token_scope": "tiktoken==0.12.0/cl100k_base; one name/description/input-schema catalog plus actual arguments and MCP text replies; excludes output schemas, framing, model prompts/reasoning and actual model usage. Not actual native-agent token usage.",
|
||||
"actual_model_usage": null,
|
||||
"wall_seconds": 21.38,
|
||||
"cpu_seconds": 21.022683,
|
||||
"peak_process_family_bytes_including_page_cache": 974041088,
|
||||
"calls": [
|
||||
{
|
||||
"name": "analyze_javascript_application",
|
||||
"elapsed_ms": 9837.265845000002,
|
||||
"is_error": false,
|
||||
"reply_bytes": 25941
|
||||
},
|
||||
{
|
||||
"name": "compare_source_to_bundle",
|
||||
"elapsed_ms": 256.3669919999993,
|
||||
"is_error": false,
|
||||
"reply_bytes": 13199
|
||||
},
|
||||
{
|
||||
"name": "inspect_analysis_view",
|
||||
"elapsed_ms": 3012.057904000001,
|
||||
"is_error": false,
|
||||
"reply_bytes": 19393
|
||||
},
|
||||
{
|
||||
"name": "export_evidence_bundle",
|
||||
"elapsed_ms": 148.9011160000009,
|
||||
"is_error": false,
|
||||
"reply_bytes": 364
|
||||
}
|
||||
],
|
||||
"independent_proof": {
|
||||
"status": "passed",
|
||||
"method": "Independent Python JSON/SHA-256/POSIX path and basename joins; no REA parser or matcher.",
|
||||
"source_files": 180,
|
||||
"embedded_nodes": 99,
|
||||
"candidate_relations": 210,
|
||||
"strong_location_rows": 33,
|
||||
"limitation": "Static multiple-location projections; no semantic-equivalence or removal claim."
|
||||
},
|
||||
"resource_events": {
|
||||
"memory.events": {
|
||||
"low": 0,
|
||||
"high": 0,
|
||||
"max": 0,
|
||||
"oom": 0,
|
||||
"oom_kill": 0,
|
||||
"oom_group_kill": 0
|
||||
},
|
||||
"pids.events": {
|
||||
"max": 0
|
||||
}
|
||||
},
|
||||
"cleanup_verified": true
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
import {
|
||||
captureRuntimeBinding,
|
||||
assertRuntimeBinding,
|
||||
} from "./managed-cli-runtime.mjs";
|
||||
import assert from "node:assert/strict";
|
||||
import { execFile } from "node:child_process";
|
||||
import { promisify } from "node:util";
|
||||
import { createHash } from "node:crypto";
|
||||
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
||||
import { join, resolve } from "node:path";
|
||||
const execute = promisify(execFile);
|
||||
const [runtime, root, output, mode, cache = "cold"] = process.argv.slice(2);
|
||||
for (const value of [runtime, root, output])
|
||||
assert.equal(resolve(value), value);
|
||||
assert.ok(["complete", "selected"].includes(mode));
|
||||
assert.ok(["cold", "warm"].includes(cache));
|
||||
await mkdir(output);
|
||||
await mkdir(join(output, "tmp"));
|
||||
const oracle = JSON.parse(await readFile(join(root, "oracle.json"), "utf8"));
|
||||
const target = join(root, "Newtonsoft.Json.dll");
|
||||
const hash = (value) => createHash("sha256").update(value).digest("hex");
|
||||
assert.equal(hash(await readFile(target)), oracle.assembly_sha256);
|
||||
const stable = (value) =>
|
||||
Array.isArray(value)
|
||||
? value.map(stable)
|
||||
: value !== null && typeof value === "object"
|
||||
? Object.fromEntries(
|
||||
Object.keys(value)
|
||||
.sort()
|
||||
.map((key) => [key, stable(value[key])]),
|
||||
)
|
||||
: value;
|
||||
const report = {
|
||||
status: "incomplete",
|
||||
runtime,
|
||||
mode,
|
||||
cache,
|
||||
node: process.version,
|
||||
question:
|
||||
"Report identity/selection/source coverage for JsonConvert, its total method count and the first eight complete method records, plus the first sixteen assembly-wide MemberRef records and continuation coverage.",
|
||||
recipe:
|
||||
mode === "selected"
|
||||
? "Use --detail summary --evidence-bundle FILE; pass the exact parent_evidence_id to inspect-analysis-view --evidence-bundle FILE with source kind retained-evidence and view {kind:managed-members,collection:methods|member_refs,offset:0,limit:8|16}."
|
||||
: "Use inspect-managed-members --type Newtonsoft.Json.JsonConvert; the completed full Evidence supplies the requested rows and remains accessible.",
|
||||
calls: [],
|
||||
cleanup_verified: false,
|
||||
};
|
||||
const began = performance.now();
|
||||
const environment = {
|
||||
PATH: process.env.PATH,
|
||||
HOME: output,
|
||||
TMPDIR: join(output, "tmp"),
|
||||
LANG: "C.UTF-8",
|
||||
REA_LOG_LEVEL: "silent",
|
||||
UV_THREADPOOL_SIZE: "1",
|
||||
NODE_OPTIONS: "--max-old-space-size=2048",
|
||||
...(cache === "cold"
|
||||
? { NODE_DISABLE_COMPILE_CACHE: "1" }
|
||||
: { NODE_COMPILE_CACHE: join(root, `compile-cache-${mode}`) }),
|
||||
};
|
||||
const call = async (label, args, json = true) => {
|
||||
const started = performance.now();
|
||||
const result = await execute(
|
||||
process.execPath,
|
||||
[join(runtime, "scripts/rea.mjs"), ...args],
|
||||
{
|
||||
cwd: output,
|
||||
env: environment,
|
||||
maxBuffer: 16 * 1024 * 1024,
|
||||
timeout: 120000,
|
||||
},
|
||||
);
|
||||
await writeFile(join(output, label + ".stdout"), result.stdout);
|
||||
await writeFile(join(output, label + ".stderr"), result.stderr);
|
||||
report.calls.push({
|
||||
label,
|
||||
arguments: ["rea", ...args],
|
||||
elapsed_ms: performance.now() - started,
|
||||
stdout_bytes: Buffer.byteLength(result.stdout),
|
||||
stdout_file: label + ".stdout",
|
||||
});
|
||||
return json ? JSON.parse(result.stdout) : result.stdout;
|
||||
};
|
||||
let parent, summary, methods, refs;
|
||||
try {
|
||||
const inputs = JSON.parse(
|
||||
await readFile(join(root, "measurement-inputs.json"), "utf8"),
|
||||
);
|
||||
const expected = inputs.expected_runtime_bindings?.[mode];
|
||||
assert.ok(expected, `Missing expected runtime for ${mode}`);
|
||||
assert.equal(
|
||||
expected.git_revision,
|
||||
mode === "complete"
|
||||
? inputs.baseline_revision
|
||||
: inputs.feature_parent_revision,
|
||||
);
|
||||
assert.notEqual(
|
||||
inputs.expected_runtime_bindings.complete.root,
|
||||
inputs.expected_runtime_bindings.selected.root,
|
||||
);
|
||||
assert.notEqual(
|
||||
inputs.expected_runtime_bindings.complete.compiled_cli_sha256,
|
||||
inputs.expected_runtime_bindings.selected.compiled_cli_sha256,
|
||||
);
|
||||
const bindingStarted = performance.now();
|
||||
report.runtime_binding = await captureRuntimeBinding(runtime);
|
||||
report.runtime_binding_audit_ms = {
|
||||
before: performance.now() - bindingStarted,
|
||||
};
|
||||
assertRuntimeBinding(report.runtime_binding, expected, mode);
|
||||
await call("help-members", ["inspect-managed-members", "--help"], false);
|
||||
if (mode === "complete") {
|
||||
parent = await call("complete", [
|
||||
"inspect-managed-members",
|
||||
target,
|
||||
"--type",
|
||||
"Newtonsoft.Json.JsonConvert",
|
||||
"--json",
|
||||
]);
|
||||
methods = parent.normalized_result.methods.slice(0, 8);
|
||||
refs = parent.normalized_result.member_refs.slice(0, 16);
|
||||
} else {
|
||||
await call("help-view", ["inspect-analysis-view", "--help"], false);
|
||||
const bundlePath = join(output, "parent.json");
|
||||
summary = await call("summary", [
|
||||
"inspect-managed-members",
|
||||
target,
|
||||
"--type",
|
||||
"Newtonsoft.Json.JsonConvert",
|
||||
"--detail",
|
||||
"summary",
|
||||
"--evidence-bundle",
|
||||
bundlePath,
|
||||
"--json",
|
||||
]);
|
||||
const id = summary.normalized_result.parent_evidence_id;
|
||||
assert.ok(id);
|
||||
const bundle = JSON.parse(await readFile(bundlePath, "utf8"));
|
||||
assert.equal(bundle.records.length, 1);
|
||||
parent = bundle.records[0];
|
||||
assert.equal(parent.evidence_id, id);
|
||||
for (const [collection, limit] of [
|
||||
["methods", 8],
|
||||
["member_refs", 16],
|
||||
]) {
|
||||
const value = await call(collection, [
|
||||
"inspect-analysis-view",
|
||||
JSON.stringify({
|
||||
source: { kind: "retained-evidence", evidence_id: id },
|
||||
view: { kind: "managed-members", collection, offset: 0, limit },
|
||||
}),
|
||||
"--evidence-bundle",
|
||||
bundlePath,
|
||||
"--json",
|
||||
]);
|
||||
const page = value.normalized_result;
|
||||
assert.equal(page.parent_evidence_id, id);
|
||||
assert.deepEqual(page.source_coverage, parent.normalized_result.coverage);
|
||||
assert.deepEqual(
|
||||
page.page.rows,
|
||||
parent.normalized_result[collection].slice(0, limit),
|
||||
);
|
||||
assert.equal(
|
||||
page.coverage.total,
|
||||
parent.normalized_result[collection].length,
|
||||
);
|
||||
assert.equal(page.coverage.next_offset, limit);
|
||||
assert.equal(page.coverage.exhausted, false);
|
||||
if (collection === "methods") methods = page.page.rows;
|
||||
else refs = page.page.rows;
|
||||
}
|
||||
}
|
||||
const data = parent.normalized_result;
|
||||
assert.equal(data.artifact.sha256, oracle.assembly_sha256);
|
||||
assert.equal(data.methods.length, 72);
|
||||
assert.equal(data.member_refs.length, 2149);
|
||||
assert.equal(data.types.length, 1);
|
||||
assert.equal(data.types[0].token, oracle.selected_types[0].token);
|
||||
for (let i = 0; i < data.methods.length; i++) {
|
||||
const row = data.methods[i],
|
||||
wanted = oracle.selected_types[0].methods[i];
|
||||
assert.equal(row.token, wanted.token);
|
||||
assert.equal(row.name, wanted.name);
|
||||
assert.equal(row.rva, wanted.rva);
|
||||
assert.equal(
|
||||
row.signature.raw_sha256,
|
||||
hash(Buffer.from(wanted.signature_hex, "hex")),
|
||||
);
|
||||
}
|
||||
for (let i = 0; i < refs.length; i++) {
|
||||
const row = refs[i],
|
||||
wanted = oracle.member_refs_first_16[i];
|
||||
assert.equal(row.token, wanted.token);
|
||||
assert.equal(row.name, wanted.name);
|
||||
assert.equal(
|
||||
row.signature.raw_sha256,
|
||||
hash(Buffer.from(wanted.signature_hex, "hex")),
|
||||
);
|
||||
}
|
||||
assert.equal(methods.length, 8);
|
||||
assert.equal(refs.length, 16);
|
||||
if (summary) {
|
||||
assert.equal(summary.normalized_result.summary.reported_counts.methods, 72);
|
||||
assert.equal(
|
||||
summary.normalized_result.summary.reported_counts.member_refs,
|
||||
2149,
|
||||
);
|
||||
assert.deepEqual(summary.normalized_result.summary.coverage, data.coverage);
|
||||
assert.deepEqual(
|
||||
summary.normalized_result.summary.selection,
|
||||
data.selection,
|
||||
);
|
||||
}
|
||||
const answer = {
|
||||
parent_evidence_id: parent.evidence_id,
|
||||
artifact_sha256: oracle.assembly_sha256,
|
||||
selection: data.selection,
|
||||
source_coverage: data.coverage,
|
||||
total_methods: data.methods.length,
|
||||
total_member_refs: data.member_refs.length,
|
||||
methods,
|
||||
member_refs: refs,
|
||||
limitation:
|
||||
"MemberRef rows are assembly-wide; methods are selected-type rows. Page exhaustion is not an absence claim.",
|
||||
};
|
||||
report.parent_evidence_id = parent.evidence_id;
|
||||
report.parent_semantic_sha256 = hash(JSON.stringify(stable(parent)));
|
||||
report.answer_sha256 = hash(JSON.stringify(stable(answer)));
|
||||
report.oracle_verified = {
|
||||
all_selected_method_metadata: 72,
|
||||
returned_methods: 8,
|
||||
returned_member_refs: 16,
|
||||
};
|
||||
const bindingFinished = performance.now();
|
||||
assertRuntimeBinding(
|
||||
await captureRuntimeBinding(runtime),
|
||||
report.runtime_binding,
|
||||
mode,
|
||||
);
|
||||
report.runtime_binding_audit_ms.after = performance.now() - bindingFinished;
|
||||
report.runtime_binding_verified = true;
|
||||
report.status = "passed";
|
||||
await writeFile(join(output, "parent-evidence.json"), JSON.stringify(parent));
|
||||
await writeFile(join(output, "answer.json"), JSON.stringify(answer));
|
||||
} finally {
|
||||
report.elapsed_ms = performance.now() - began;
|
||||
report.cleanup_verified = true;
|
||||
await writeFile(
|
||||
join(output, "report.json"),
|
||||
JSON.stringify(report, null, 2) + "\n",
|
||||
);
|
||||
}
|
||||
console.log(
|
||||
JSON.stringify({
|
||||
status: report.status,
|
||||
mode,
|
||||
cache,
|
||||
parent: report.parent_evidence_id,
|
||||
answer: report.answer_sha256,
|
||||
calls: report.calls.map((c) => ({
|
||||
label: c.label,
|
||||
elapsed_ms: c.elapsed_ms,
|
||||
bytes: c.stdout_bytes,
|
||||
})),
|
||||
}),
|
||||
);
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,219 @@
|
||||
# Portable managed CLI member views
|
||||
|
||||
Issue #5148 / PR #5167. Baseline `main@3dbe314ada9f6dcc994ca4655dc0faf082503847`;
|
||||
feature integrates the original `7b3ed4d025edd24d062cde0327a53bd311e174fc`.
|
||||
The measured production-file SHA-256 manifest is in [managed-cli.json](managed-cli.json).
|
||||
These are working-tree measurements. Each trial verifies both source and the
|
||||
complete compiled CLI graph before and after execution against its explicitly
|
||||
selected build. The two roles have distinct checkout roots and compiled digests.
|
||||
Identity-audit time is included in whole-task costs and recorded separately.
|
||||
The audit reads compiled files before timing individual CLI calls, warming those
|
||||
filesystem pages; cold means disabled Node compile cache, not disk-cold startup.
|
||||
|
||||
## Question and independent checks
|
||||
|
||||
Report identity, selected type, source coverage, the total method count, the first
|
||||
eight complete method records, and the first sixteen assembly-wide MemberRef
|
||||
records, including continuation coverage. Keep complete original Evidence available.
|
||||
The question deliberately does not ask for every method or reference.
|
||||
|
||||
Public artifact: [Newtonsoft.Json 13.0.3](https://www.nuget.org/packages/Newtonsoft.Json/13.0.3),
|
||||
from the NuGet flat-container archive. The 2,441,966-byte archive SHA-256 is
|
||||
`872fc189e638ab1056555b03aaa38f68bcb54286e221aa646eb1129babf63c77`.
|
||||
Selected member `lib/net6.0/Newtonsoft.Json.dll`, 712,464 bytes, SHA-256
|
||||
`22c649f75fce5be7c7ccda8880473b634ef69ecf33f5d1ab8ad892caf47d5a07`.
|
||||
Package version 13.0.3 is distinct from metadata assembly version 13.0.0.0.
|
||||
No library code is executed; REA parses PE/CLI statically.
|
||||
|
||||
An independent Python oracle uses `dnfile==0.18.0` and `pefile==2024.8.26`.
|
||||
It finds 494 TypeDefs, 4,208 MethodDefs and 2,149 MemberRefs. The selected
|
||||
`Newtonsoft.Json.JsonConvert` has 72 methods. Every trial checks all 72 method
|
||||
tokens, names, RVAs and original signature hashes, plus the sixteen returned
|
||||
MemberRef tokens, names and signature hashes, against this oracle. This does
|
||||
not independently establish complete CIL semantics or opcode correctness.
|
||||
The full parent Evidence and requested answers are identical across all twelve
|
||||
trials; returned rows equal the exact parent slices. Selection and source
|
||||
coverage remain distinct from page exhaustion. MemberRefs remain assembly-wide.
|
||||
|
||||
## Completed-task cost
|
||||
|
||||
Linux x64, Node 24.18.0/npm 11.16.0. Three alternating pairs per cache condition,
|
||||
serial, one CPU; 4 GiB hard / 3 GiB early-stop family guard, no swap, 192-task
|
||||
ceiling. Every task includes actual selected-command help, all CLI calls,
|
||||
provider parsing, bundle publication/authentication, local answer extraction
|
||||
and oracle comparisons, plus both runtime-identity audits. Build, download, oracle preparation and warm priming
|
||||
are excluded. OS page cache is uncontrolled. No build/test overlapped timing.
|
||||
|
||||
Complete mode starts two CLI processes (help plus analysis). Selected mode starts
|
||||
five (two help commands, summary/publication, methods page, MemberRef page).
|
||||
Cold disables the Node compile cache; warm primes the exact workflow once per
|
||||
runtime/mode, then still starts fresh processes with isolated HOME each trial.
|
||||
All trials complete with verified process cleanup and no OOM/resource-stop event.
|
||||
|
||||
| Whole task, median | Complete | Summary + two pages |
|
||||
| ----------------------------------------------- | -------: | ------------------: |
|
||||
| Estimated context tokens, both cache conditions | 451,373 | 13,078 |
|
||||
| Cold wall seconds | 9.969 | 14.801 |
|
||||
| Cold family CPU seconds | 9.743 | 14.555 |
|
||||
| Cold kernel family peak MiB | 393.281 | 400.098 |
|
||||
| Warm wall seconds | 10.339 | 24.141 |
|
||||
| Warm family CPU seconds | 10.097 | 23.842 |
|
||||
| Warm kernel family peak MiB | 401.809 | 407.164 |
|
||||
|
||||
Context estimates include the question, supplied command recipe, all logical
|
||||
argv, actual help and stdout. Tokenizer `tiktoken==0.12.0`, `cl100k_base`.
|
||||
The reduction is 97.1% for this fixed task. There is no model invocation;
|
||||
actual billed/native-agent usage, reasoning and transport framing are unmeasured.
|
||||
The memory counter is the kernel cgroup process-family peak including file
|
||||
cache, not sampled RSS. Ranges and individual receipts are in the JSON.
|
||||
|
||||
This is an opt-in context/portability improvement with extra latency and CPU,
|
||||
not a speed or memory optimization. Complete provider parsing and full authentication of file-supplied bundles
|
||||
remain. Fresh managed Evidence is sealed at its producing factory and reused
|
||||
without another payload clone, including low-headroom error projection. Complete output remains the default and is preferable
|
||||
for small outputs or questions requiring every row. No cache or parser cap
|
||||
was introduced.
|
||||
|
||||
## Existing native code composition
|
||||
|
||||
The unchanged baseline can already redirect full stdout to a file and select
|
||||
rows in code. [The measured control](managed-cli-local-control.py) returns the
|
||||
identical answer and retains the complete original Evidence. One cold run:
|
||||
11.249 s wall, 11.000 s family CPU,
|
||||
375.3 MiB kernel peak. Projection source,
|
||||
original help and returned answer together estimate 10,555 tokens; the shared
|
||||
question and launcher argv are excluded. This single-run control does not
|
||||
establish stable performance or actual native-agent usage. It does demonstrate
|
||||
that raw CLI reply savings are not universal savings over code composition.
|
||||
The additive interface supplies authenticated reusable projections through the
|
||||
same application/domain owner as MCP, without caller-maintained JSON slicing.
|
||||
|
||||
## Correctness and resource boundaries
|
||||
|
||||
The public CLI regression pages all eight managed collections after process
|
||||
exit, target deletion and a working-directory change. Complete parent identity,
|
||||
original row order, signatures, source/page coverage and unknowns survive.
|
||||
Existing outputs are not replaced; failed publication retains completed facts.
|
||||
|
||||
The Evidence factory parses mutable caller data into independent trees, computes
|
||||
identity, then seals its fresh owned snapshot with active ancestry/iterators.
|
||||
It does not retain a set/array of every completed object. Existing sealed roots
|
||||
can be shared; mutable input aliases are cloned independently. General graph
|
||||
sealing keeps its separate cycle, sharing, hidden-field and atomic-failure rules.
|
||||
Managed and derived-view factories seal their own completed Evidence, so CLI
|
||||
error projection can borrow it without reauthentication or another payload copy.
|
||||
The view owner retains strict JSON normalization for optional-field contracts;
|
||||
the CLI no longer copies its already validated completed projection again.
|
||||
|
||||
Shared heap admission traverses by depth rather than queueing every report row
|
||||
or allocating an entries array. It reserves parsed working copies and actual
|
||||
escaping expansion before cloning/hashing, reporting UTF-16 storage explicitly.
|
||||
Canonical bundle equality streams existing ordinary JSON encoder parts, preserving
|
||||
native key order, omission, negative zero and Unicode semantics without two
|
||||
whole-document strings. All production bundle readers explicitly pass their
|
||||
operation: CLI import/export/compare/inspection, retained views, MCP import/
|
||||
comparison and both native-matching read passes. Errors retain the original
|
||||
cause, cleanup primary and lease through retry.
|
||||
|
||||
One process primitive dispatches queued callbacks and then their OS signal
|
||||
notifications. The managed producer checks it before accepting complete Evidence.
|
||||
Publication/read stages use it before their final checks. Inline, file and bundle
|
||||
CLI views share the existing command finalizer and actual resource scope; the
|
||||
finalizer checks interruption after close while preserving any primary/cleanup
|
||||
failure. Existing inline error labels remain intact. Synchronous analysis is
|
||||
cooperatively cancellable between stages, not preemptible.
|
||||
|
||||
Four compiled publication cases (SIGINT/SIGTERM × event/actual POSIX signal)
|
||||
fail without their checkpoint and pass restored. Eight additional compiled
|
||||
completion cases cover default complete delivery and inline projection; all fail
|
||||
with only their new completion checkpoints removed and pass restored. Fixture
|
||||
hooks match the selected target path or exact parent ID. Two real Newtonsoft
|
||||
publication runs and four real default/inline completion runs retain the identical
|
||||
parent or independently checked selected summary, exit 130/143 and preserve
|
||||
committed receipts where applicable. No target library code is executed.
|
||||
|
||||
All 556 focused tests across 36 files pass, including direct
|
||||
finalizer/cleanup ownership, WASM/Android cancellation and native matching.
|
||||
All six `npm run check` tasks plus architecture guards, and all six
|
||||
`npm run docs:check` tasks plus five README tests pass. The expanded domain
|
||||
project passes 5,617 tests in 287 files with
|
||||
3 skipped cases; this overlaps the focused gate. Its first
|
||||
batched shard hit two existing 30-second timeouts in unchanged large synthetic
|
||||
tests. Both passed isolated and in the fresh shard rerun under the same timeout;
|
||||
the cause of the batch variation is unverified. No production/timeout change
|
||||
was made for those cases. An earlier unsplit expansion was manually stopped
|
||||
before its heap ceiling; that incomplete attempt is not counted as a pass.
|
||||
|
||||
Eight producing/operation negative controls also catch graph-sized sealing/
|
||||
admission scratch and wrong operation attribution, including native reload.
|
||||
Native built-in instrumentation is confined to the isolated process-global lane.
|
||||
Initial test-only spy/probe/schema-import issues were corrected before these
|
||||
passing gates. No actual heap exhaustion is induced. Simulated providers do not
|
||||
qualify foreign engines; Windows OS signals remain unverified locally.
|
||||
|
||||
## Shared-reader real-artifact regression
|
||||
|
||||
The existing Redux Toolkit 2.2.7 source/bundle task also completes through the
|
||||
updated reader with default full output schemas and compact input schemas.
|
||||
An independent Python SHA-256/path oracle verifies 180 historical files,
|
||||
99 embedded source nodes and 210 candidate relations (33 strong-location rows,
|
||||
147 unknown). Original signals and partial source coverage remain visible.
|
||||
This uses the existing explicit semantic-node cap of one for static correspondence;
|
||||
it does not establish equivalent semantic-graph coverage or behavioral equivalence.
|
||||
|
||||
One completed task: 21.380 s wall,
|
||||
21.023 s family CPU,
|
||||
928.9 MiB kernel family peak,
|
||||
56,378 estimated context tokens (one input catalog,
|
||||
all arguments and MCP text replies; excludes output schemas, framing and model
|
||||
reasoning). Corpus/reference preparation was performed earlier and excluded.
|
||||
This is a regression verification with resource observation, not a new paired
|
||||
performance comparison. Actual model usage remains unmeasured. Details:
|
||||
[managed-cli-shared-read.json](managed-cli-shared-read.json).
|
||||
|
||||
## Reproduction
|
||||
|
||||
Extract the selected DLL to a private lab as `Newtonsoft.Json.dll`. Create an
|
||||
`acquisition.json` containing the URL, hashes, sizes and selected ZIP member
|
||||
shown above; never commit the DLL. Prepare the independent oracle:
|
||||
|
||||
```bash
|
||||
uv run --no-project --with dnfile==0.18.0 --with pefile==2024.8.26 python \
|
||||
experiments/analysis-efficiency/managed-cli-oracle.py /absolute/lab
|
||||
```
|
||||
|
||||
Build baseline and feature separately with the pinned toolchain. Run each under
|
||||
the shared resource guard, alternating complete/selected, selected/complete,
|
||||
complete/selected for cold and warm. Use a new output directory for every run:
|
||||
|
||||
```bash
|
||||
python3 experiments/analysis-efficiency/resource-run.py --observe-payload-exit -- \
|
||||
node experiments/analysis-efficiency/managed-cli-task.mjs \
|
||||
/absolute/runtime /absolute/lab /absolute/lab/pair-cold-1-selected selected cold
|
||||
```
|
||||
|
||||
Save each guard output to the adjacent `pair-*.log`. Warm mode uses the lab's
|
||||
mode-specific compile-cache directory; prime each identical workflow once first.
|
||||
Supply a `measurement-inputs.json` with exact revisions and production hashes,
|
||||
plus `expected_runtime_bindings.complete` and `.selected`. Capture each with
|
||||
`node experiments/analysis-efficiency/managed-cli-runtime.mjs /absolute/runtime`
|
||||
after building. Bind complete to the clean baseline revision, selected to the
|
||||
feature parent revision plus tracked/untracked source digests, with different
|
||||
roots and compiled-graph digests. The collector rejects a wrong build before any
|
||||
CLI call, rechecks it afterward, and aggregation independently enforces identity.
|
||||
A real wrong-runtime attempt is rejected before analysis. A copied trial with a
|
||||
tampered revision fails aggregation; removing only that consumer guard accepts it.
|
||||
The twelve-trial aggregation reproduces without private pilots. The native
|
||||
control also requires `--measurement-inputs /absolute/lab/measurement-inputs.json`
|
||||
and performs the same before/after identity checks.
|
||||
Then aggregate with:
|
||||
|
||||
```bash
|
||||
uv run --no-project --with tiktoken==0.12.0 python \
|
||||
experiments/analysis-efficiency/managed-cli-costs.py /absolute/lab \
|
||||
--output /absolute/results.json
|
||||
```
|
||||
|
||||
The original issue reporter's executable, foreign operating systems and actual
|
||||
model sessions remain unverified. Setup pilots and earlier unbound cohorts, including one failed setup run
|
||||
while compiled artifacts were absent after a typecheck failure, are excluded.
|
||||
@@ -0,0 +1,90 @@
|
||||
"""Account for catalog, complete SDK tasks and separately recorded model trials."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import tiktoken
|
||||
|
||||
|
||||
def compact(value):
|
||||
return json.dumps(value, ensure_ascii=False, separators=(",", ":"), allow_nan=False)
|
||||
|
||||
|
||||
def resource(case):
|
||||
path = case.with_name(case.name + ".log")
|
||||
scope = next(json.loads(line) for line in reversed(path.read_text().splitlines())
|
||||
if line.startswith('{"resource_scope":'))
|
||||
observation = scope["payload_resource_observation"]
|
||||
assert scope["abort"] is None and scope["payload_resource_observation_verified"]
|
||||
assert observation["payload_cleanup_verified"] and observation["payload_exit_code"] == 0
|
||||
assert all(observation["resource_events"]["memory.events"][key] == 0
|
||||
for key in ["high", "max", "oom", "oom_kill"])
|
||||
return {"wall_seconds": scope["elapsed_seconds"],
|
||||
"cpu_seconds": observation["cpu_stat"]["usage_usec"] / 1e6,
|
||||
"kernel_family_peak_bytes_including_page_cache": observation["memory_peak_bytes"],
|
||||
"resource_stop": scope["abort"], "cleanup_verified": True,
|
||||
"final_whole_scope_counters": scope["resource_events_final"],
|
||||
"guard_sources_sha256": scope["payload_observer_sources_sha256"],
|
||||
"log_sha256": hashlib.sha256(path.read_bytes()).hexdigest()}
|
||||
|
||||
|
||||
def sdk(case, count):
|
||||
report = json.loads((case / "report.json").read_text())
|
||||
assert report["status"] == "passed" and report["cleanup_verified"]
|
||||
catalog = json.loads((case / "catalog.json").read_text())
|
||||
calls = json.loads((case / "transcript.json").read_text())
|
||||
inputs = [{key: tool[key] for key in ["name", "description", "inputSchema"]}
|
||||
for tool in catalog["tools"]]
|
||||
arguments = sum(count(compact({"name": call["name"], "arguments": call["arguments"]}))
|
||||
for call in calls)
|
||||
text = sum(count(block["text"]) for call in calls for block in call["reply"]["content"]
|
||||
if block["type"] == "text")
|
||||
return {"case": case.name, "kind": "SDK", "profile": report["profile"],
|
||||
"artifact_sha256": report["artifact_sha256"],
|
||||
"tool_count": len(catalog["tools"]), "calls": report["calls"],
|
||||
"parent_evidence_id": report["parent_evidence_id"],
|
||||
"parent_semantic_sha256": report["parent_semantic_sha256"],
|
||||
"token_estimates": {"input_catalog_once": count(compact(inputs)),
|
||||
"arguments": arguments, "text_replies": text,
|
||||
"whole_task": count(compact(inputs)) + arguments + text,
|
||||
"raw_catalog_including_output_schemas": count(compact(catalog))},
|
||||
"actual_model_usage": None, **resource(case),
|
||||
"receipt_sha256": {name: hashlib.sha256((case / name).read_bytes()).hexdigest()
|
||||
for name in ["report.json", "catalog.json", "transcript.json"]}}
|
||||
|
||||
|
||||
def model(case):
|
||||
summary = json.loads((case / "summary.json").read_text())
|
||||
assert summary["exit_code"] == 0 and not summary["timeout"]
|
||||
assert summary["selected_artifact_bytes_unchanged"]
|
||||
assert json.loads((case / "cleanup.json").read_text())["profile_removed"]
|
||||
return {"case": case.name, "kind": "model", "client": summary["codex_version"],
|
||||
"requested_model": summary["requested_model"], "reasoning": summary["reasoning"],
|
||||
"model_identity_scope": summary["model_identity_scope"],
|
||||
"actual_model_usage": summary["usage"],
|
||||
"artifact_sha256": summary["selected_artifact_sha256_before"],
|
||||
"calls": summary["completed_mcp_calls"],
|
||||
"factual_correctness": "requires independent oracle and answer review",
|
||||
**resource(case),
|
||||
"receipt_sha256": {name: hashlib.sha256((case / name).read_bytes()).hexdigest()
|
||||
for name in ["summary.json", "answer.txt", "events.jsonl",
|
||||
"trial-settings.json", "context-receipt.json"]}}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--output", type=Path, required=True)
|
||||
parser.add_argument("cases", type=Path, nargs="+")
|
||||
args = parser.parse_args()
|
||||
encoding = tiktoken.get_encoding("cl100k_base")
|
||||
count = lambda value: len(encoding.encode(value, disallowed_special=()))
|
||||
result = {"tokenizer": f"tiktoken {tiktoken.__version__}", "encoding": encoding.name,
|
||||
"estimate_scope": "One complete name/description/input-schema catalog, every RPC argument and text reply; raw output-schema transport counted separately. Model usage is separate and is not inferred from estimates.",
|
||||
"records": [sdk(case, count) if (case / "report.json").exists() else model(case)
|
||||
for case in args.cases]}
|
||||
args.output.write_text(json.dumps(result, indent=2) + "\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,54 @@
|
||||
"""Independent ELF64 little-endian / zlib oracle for the pinned Alpine corpus."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import struct
|
||||
import zlib
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("artifact", type=Path)
|
||||
parser.add_argument("output", type=Path)
|
||||
args = parser.parse_args()
|
||||
assert args.artifact.stat().st_size <= 256 * 1024 ** 2
|
||||
binary = args.artifact.read_bytes()
|
||||
assert binary[:6] == b"\x7fELF\x02\x01"
|
||||
table = struct.unpack_from("<Q", binary, 40)[0]
|
||||
stride, count, strings_index = struct.unpack_from("<HHH", binary, 58)
|
||||
assert stride == 64 and 0 < count < 65535 and strings_index < count
|
||||
sections = [struct.unpack_from("<IIQQQQIIQQ", binary, table + index * stride)
|
||||
for index in range(count)]
|
||||
string_row = sections[strings_index]
|
||||
names = binary[string_row[4]:string_row[4] + string_row[5]]
|
||||
matches = [row for row in sections
|
||||
if names[row[0]:names.index(b"\0", row[0])] == b".dep-v0"]
|
||||
assert len(matches) == 1
|
||||
row = matches[0]
|
||||
assert row[5] <= 1024 ** 2
|
||||
compressed = binary[row[4]:row[4] + row[5]]
|
||||
decoder = zlib.decompressobj()
|
||||
decoded = decoder.decompress(compressed, 8 * 1024 ** 2 + 1)
|
||||
assert len(decoded) <= 8 * 1024 ** 2 and decoder.eof
|
||||
assert not decoder.unconsumed_tail and not decoder.unused_data
|
||||
raw = json.loads(decoded)
|
||||
packages = [{"name": item["name"], "version": item["version"],
|
||||
"source": item.get("source"), "kind": item.get("kind"),
|
||||
"dependencies": item.get("dependencies", []), "root": item.get("root", False)}
|
||||
for item in raw["packages"]]
|
||||
result = {
|
||||
"artifact_sha256": hashlib.sha256(binary).hexdigest(),
|
||||
"section_sha256": hashlib.sha256(compressed).hexdigest(),
|
||||
"json_sha256": hashlib.sha256(decoded).hexdigest(),
|
||||
"packages": packages,
|
||||
"edges": [{"from_index": index, "to_index": destination}
|
||||
for index, item in enumerate(packages) for destination in item["dependencies"]],
|
||||
"serde_rows": [{"index": index, **{key: item[key] for key in ["name", "version", "kind"]}}
|
||||
for index, item in enumerate(packages) if item["name"] == "serde"],
|
||||
}
|
||||
args.output.write_text(json.dumps(result, indent=2) + "\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loaded 100 of 1282 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user