mirror of
https://github.com/morluto/rea.git
synced 2026-11-13 18:49:25 -10:00
Compare commits
509
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
756a588477 | ||
|
|
e1d229cd6b | ||
|
|
01fcf8e3d7 | ||
|
|
0a3368a6a9 | ||
|
|
3986bf9f8e | ||
|
|
bddbd80afb | ||
|
|
f1e250ee76 | ||
|
|
71712f27f7 | ||
|
|
fcc0a8c454 | ||
|
|
243e4015cb | ||
|
|
4a4e959513 | ||
|
|
4e1e9b62a7 | ||
|
|
54677ec1d6 | ||
|
|
1abd327913 | ||
|
|
186b2c352c | ||
|
|
827b31c128 | ||
|
|
ee339e5db5 | ||
|
|
6ce708cfde | ||
|
|
884b683a94 | ||
|
|
8930dd8c31 | ||
|
|
5815178a8d | ||
|
|
87743d67f5 | ||
|
|
d3efeb0c36 | ||
|
|
46728ca41d | ||
|
|
62798fa8b0 | ||
|
|
5bad48e122 | ||
|
|
cc7d73d23a | ||
|
|
da91bbd4eb | ||
|
|
3403338ea0 | ||
|
|
4566e483ab | ||
|
|
bf63760cb4 | ||
|
|
3b006841e2 | ||
|
|
3cb75d46bf | ||
|
|
b67c1e8ce6 | ||
|
|
cdc4541ef7 | ||
|
|
4b26f38d6f | ||
|
|
e841fb16e4 | ||
|
|
26b70c8ea4 | ||
|
|
5d046b9ad7 | ||
|
|
c4cec6373d | ||
|
|
02a33a8f58 | ||
|
|
ea101dbe30 | ||
|
|
fd3e613d23 | ||
|
|
adf8bdf833 | ||
|
|
cd96c5e9eb | ||
|
|
617e4cbfb3 | ||
|
|
bbe2bcc979 | ||
|
|
5cddc69c51 | ||
|
|
b2c4635a36 | ||
|
|
15a2de737c | ||
|
|
c2ca3819e5 | ||
|
|
54906fdb1f | ||
|
|
0084810ef7 | ||
|
|
feca30c72c | ||
|
|
913b029c96 | ||
|
|
bfecbb1d48 | ||
|
|
070cfce443 | ||
|
|
0c01517cc0 | ||
|
|
7c9d65fe97 | ||
|
|
9c86465d47 | ||
|
|
c836f57b7d | ||
|
|
6878a84796 | ||
|
|
937d10df1c | ||
|
|
c19d319929 | ||
|
|
966bde3780 | ||
|
|
4d15b7f509 | ||
|
|
50d4f7bea4 | ||
|
|
594d73985c | ||
|
|
418e3f5e91 | ||
|
|
0f5ac9d5f3 | ||
|
|
7559e06740 | ||
|
|
9d32836d37 | ||
|
|
02ebd3e02d | ||
|
|
a8527d43b8 | ||
|
|
edc9304669 | ||
|
|
bed3f0bcb5 | ||
|
|
653c49419e | ||
|
|
5eef239dfd | ||
|
|
d74549e495 | ||
|
|
3a36b3e6d6 | ||
|
|
58a0511660 | ||
|
|
a01674377f | ||
|
|
047d75a498 | ||
|
|
9cffd5a334 | ||
|
|
fadfdf13e6 | ||
|
|
6b2f991808 | ||
|
|
4505477903 | ||
|
|
4a5b24c3fa | ||
|
|
9ba61e8949 | ||
|
|
dae1551403 | ||
|
|
166cba488a | ||
|
|
0c9ae2f783 | ||
|
|
bbef46e783 | ||
|
|
04c622f6e9 | ||
|
|
d6c6b1553d | ||
|
|
81b305bd1a | ||
|
|
c5c1ff45fa | ||
|
|
ab84ba6839 | ||
|
|
e966bc06ad | ||
|
|
f668c86271 | ||
|
|
7f920465c5 | ||
|
|
aa017c61ff | ||
|
|
4821aaf34b | ||
|
|
db5078b0c3 | ||
|
|
0909d89c96 | ||
|
|
2fe0c9eb6a | ||
|
|
dcdae13543 | ||
|
|
7aca4cef64 | ||
|
|
5fde39454e | ||
|
|
69630c0362 | ||
|
|
12bf103367 | ||
|
|
b6820d5794 | ||
|
|
be6ec3f164 | ||
|
|
4dedf3e865 | ||
|
|
437109e574 | ||
|
|
b384e95417 | ||
|
|
1b36fc2d50 | ||
|
|
40d9f1a5e8 | ||
|
|
fbbf94a2c4 | ||
|
|
4a17bf76ed | ||
|
|
04042cf540 | ||
|
|
2127cff82d | ||
|
|
1dc54783ef | ||
|
|
48357cb34c | ||
|
|
ab8e31dc76 | ||
|
|
03610972f7 | ||
|
|
44bbd13b55 | ||
|
|
86fb3e757d | ||
|
|
66e85df5c5 | ||
|
|
5bb34ce522 | ||
|
|
f4867e60fa | ||
|
|
ef754ce717 | ||
|
|
64d1a57aef | ||
|
|
47bcd9c129 | ||
|
|
11bc738198 | ||
|
|
6b102e61b3 | ||
|
|
73ee767656 | ||
|
|
2aa5ba836d | ||
|
|
c4e3e48574 | ||
|
|
527c7c5d8b | ||
|
|
3ccb35a8b5 | ||
|
|
e675f9b29d | ||
|
|
4361cad981 | ||
|
|
925df00caa | ||
|
|
e8908507c8 | ||
|
|
40b6f1ab21 | ||
|
|
0bf161f1bc | ||
|
|
5ba464527b | ||
|
|
125de0bdc4 | ||
|
|
b3dcddc115 | ||
|
|
57dd7f26b1 | ||
|
|
b9be864801 | ||
|
|
6ebd033dff | ||
|
|
559f725509 | ||
|
|
db5a0e0f4a | ||
|
|
aefdacd697 | ||
|
|
e0dcdab1a9 | ||
|
|
2bac42cde5 | ||
|
|
1613f2b777 | ||
|
|
649b9c089c | ||
|
|
b0541c80b3 | ||
|
|
9924bf3445 | ||
|
|
91b11f62c9 | ||
|
|
1626461ec1 | ||
|
|
dc521dc0d9 | ||
|
|
804784720a | ||
|
|
6194524d00 | ||
|
|
88202cbf67 | ||
|
|
073dda2a0a | ||
|
|
0ae186e196 | ||
|
|
58a1216a57 | ||
|
|
9bcc95a801 | ||
|
|
be20bdfb26 | ||
|
|
aee1178839 | ||
|
|
cc6c52b886 | ||
|
|
3ac05e14ba | ||
|
|
3038caad2b | ||
|
|
d65cd41b78 | ||
|
|
3769fe8077 | ||
|
|
021b5de719 | ||
|
|
6e2e5a0aca | ||
|
|
694e8c4f7b | ||
|
|
729d1a2138 | ||
|
|
bc01caea10 | ||
|
|
646daa1d29 | ||
|
|
3f0c77c1f5 | ||
|
|
a24e0156fe | ||
|
|
ead6cc83d2 | ||
|
|
07d6fad807 | ||
|
|
157d495029 | ||
|
|
575a6c486e | ||
|
|
b1f8a9bba8 | ||
|
|
7fe465505f | ||
|
|
f2d55aba7b | ||
|
|
710d2af41c | ||
|
|
3b39991b02 | ||
|
|
0e0af455f2 | ||
|
|
3ad2e214be | ||
|
|
c1c7a78117 | ||
|
|
84041fff23 | ||
|
|
4a3bc37b76 | ||
|
|
a16f5f4b5d | ||
|
|
8a2eb4ab61 | ||
|
|
d36ba58971 | ||
|
|
2d80427422 | ||
|
|
94dd7b72f8 | ||
|
|
20aeaf110f | ||
|
|
15d08235e1 | ||
|
|
e9f12d212c | ||
|
|
12a916b255 | ||
|
|
c80e6cd845 | ||
|
|
ca268ead0a | ||
|
|
073b4dcc41 | ||
|
|
87cd7070b6 | ||
|
|
3dced80300 | ||
|
|
a77e02788e | ||
|
|
47704ab093 | ||
|
|
930c56d670 | ||
|
|
cb17828dd1 | ||
|
|
d9537fc75c | ||
|
|
34025d2fcd | ||
|
|
98f796c991 | ||
|
|
389b69d097 | ||
|
|
913c9fe194 | ||
|
|
3eb502ae5d | ||
|
|
b4d501e714 | ||
|
|
50740bb05e | ||
|
|
fd9d362d98 | ||
|
|
2f87d3edb8 | ||
|
|
01707fcbde | ||
|
|
5b5990f7a9 | ||
|
|
61e3eb3ca7 | ||
|
|
a14a0c20ed | ||
|
|
d1895841a4 | ||
|
|
f7d564f436 | ||
|
|
0ece957589 | ||
|
|
66acbb3421 | ||
|
|
cb048c3ed5 | ||
|
|
dc5527b0bc | ||
|
|
8052f8daf0 | ||
|
|
3c0e9d8a02 | ||
|
|
01e8c6447a | ||
|
|
8cc2a1ae6e | ||
|
|
c71aded3ee | ||
|
|
b00138be64 | ||
|
|
9f5f9c1289 | ||
|
|
a896e35c47 | ||
|
|
37d2d207d2 | ||
|
|
67f74c5fb9 | ||
|
|
83f0a4d238 | ||
|
|
654feeef9c | ||
|
|
eff195d6aa | ||
|
|
13abfdadff | ||
|
|
2bb266b39b | ||
|
|
fcf8b99a77 | ||
|
|
7c0a658cb4 | ||
|
|
d3eb3f6478 | ||
|
|
b4654b493d | ||
|
|
65765eb495 | ||
|
|
46d79ecd78 | ||
|
|
e5fe737677 | ||
|
|
6151e13835 | ||
|
|
dd928466cb | ||
|
|
4d0f6d9b42 | ||
|
|
f6e31acd74 | ||
|
|
59e36cf86e | ||
|
|
e504e09aeb | ||
|
|
ea00ca2d46 | ||
|
|
aece2e7e16 | ||
|
|
1c7d7b6cc3 | ||
|
|
d54a41152e | ||
|
|
9e79188ba8 | ||
|
|
e7c4a26316 | ||
|
|
12a32d934a | ||
|
|
38a0dafa76 | ||
|
|
df25c923c4 | ||
|
|
3896f72552 | ||
|
|
44ef32c1c0 | ||
|
|
5b02119b69 | ||
|
|
7f0555b75e | ||
|
|
4812843e5b | ||
|
|
e55ce72d9d | ||
|
|
34d844dcad | ||
|
|
98bc82f1e1 | ||
|
|
f2e73ca8b6 | ||
|
|
876bc145a7 | ||
|
|
bb200646e5 | ||
|
|
17b91a9853 | ||
|
|
fcd364069a | ||
|
|
e9e106f580 | ||
|
|
fcc353518a | ||
|
|
2b570ae194 | ||
|
|
66498b4f7c | ||
|
|
e6114e81dc | ||
|
|
ecf6ac9f8d | ||
|
|
550b7df262 | ||
|
|
ca7c263dd6 | ||
|
|
2e67d57d0f | ||
|
|
81d4f6b42a | ||
|
|
dd522bf9a7 | ||
|
|
55c746afaf | ||
|
|
08d943ea29 | ||
|
|
27ced7bdef | ||
|
|
979552aa5c | ||
|
|
36334402de | ||
|
|
ba4fb6a806 | ||
|
|
4073cfc932 | ||
|
|
827b808248 | ||
|
|
4de8020745 | ||
|
|
9cd1eadfb7 | ||
|
|
8c40ba78de | ||
|
|
4a02ca95de | ||
|
|
c7a4869eb9 | ||
|
|
528c46ae92 | ||
|
|
626c705c99 | ||
|
|
c9e7aaca27 | ||
|
|
914363fbfb | ||
|
|
77100250de | ||
|
|
a7ec7271d6 | ||
|
|
a08e40b924 | ||
|
|
1f2a869e5b | ||
|
|
8e11a430cf | ||
|
|
ca70cdfcc0 | ||
|
|
ada8fcfe82 | ||
|
|
30f96aef39 | ||
|
|
b94d811500 | ||
|
|
2b1f725221 | ||
|
|
91456101f1 | ||
|
|
a2aea3f4c6 | ||
|
|
19f7eef513 | ||
|
|
43588f07ab | ||
|
|
e8fc501e06 | ||
|
|
42a02b846d | ||
|
|
10a5a60000 | ||
|
|
310993d4cb | ||
|
|
160d2ecdb5 | ||
|
|
1de3298eeb | ||
|
|
ff86e19e23 | ||
|
|
574aca127f | ||
|
|
1544fe8803 | ||
|
|
e33a207749 | ||
|
|
0e88049d59 | ||
|
|
6d8c71f8b3 | ||
|
|
4e96d64189 | ||
|
|
04e9654e11 | ||
|
|
4546673eec | ||
|
|
b99a7b6a21 | ||
|
|
5934ba1bf9 | ||
|
|
b3bab01b22 | ||
|
|
428590e9f2 | ||
|
|
1e80a96094 | ||
|
|
abc4f0f8b2 | ||
|
|
5c2917266d | ||
|
|
1371ba1e07 | ||
|
|
faf42f8f13 | ||
|
|
bf671f20a2 | ||
|
|
6de105bc60 | ||
|
|
7aaff2e4e4 | ||
|
|
a54e848302 | ||
|
|
6a2b690440 | ||
|
|
bae4ec0cda | ||
|
|
a8cd7cadc0 | ||
|
|
22a3ba263e | ||
|
|
09f58bf044 | ||
|
|
1a8a9b749a | ||
|
|
1f20c57627 | ||
|
|
c51ac43f9c | ||
|
|
e5a92d1848 | ||
|
|
710c353bff | ||
|
|
96086e9c1f | ||
|
|
f8ed4d16a0 | ||
|
|
699cb72c48 | ||
|
|
411804afbf | ||
|
|
81c09773be | ||
|
|
25d46f3a58 | ||
|
|
75871ebb8b | ||
|
|
40239b31e7 | ||
|
|
ffac2e0c99 | ||
|
|
fc9585a44f | ||
|
|
7771fb7123 | ||
|
|
2847464189 | ||
|
|
58edc31638 | ||
|
|
114b57678f | ||
|
|
4a8b157a28 | ||
|
|
f3629bae94 | ||
|
|
48ee3f02fd | ||
|
|
6e8cd0bc5e | ||
|
|
3c54f3ce4e | ||
|
|
55f344a77b | ||
|
|
01a7e2c3b7 | ||
|
|
2e34aa0433 | ||
|
|
c0b3c18b8a | ||
|
|
afed309f0f | ||
|
|
a3ff69f5ba | ||
|
|
a44d457745 | ||
|
|
2be301f894 | ||
|
|
73bc95d23f | ||
|
|
a18867e623 | ||
|
|
d3899717b2 | ||
|
|
755d58d29a | ||
|
|
b725586fbf | ||
|
|
e2bdfcee75 | ||
|
|
647ebc2645 | ||
|
|
5d0391b06e | ||
|
|
3eae278da5 | ||
|
|
133a849b2e | ||
|
|
a6e02657e6 | ||
|
|
72b07c58d4 | ||
|
|
4d711acffd | ||
|
|
5821506eb2 | ||
|
|
3c736dfe11 | ||
|
|
82abd9e6ca | ||
|
|
29b41a7d94 | ||
|
|
41bd808c1f | ||
|
|
847d59c947 | ||
|
|
d39699ad0c | ||
|
|
281db61890 | ||
|
|
2885347cde | ||
|
|
a6a2527ade | ||
|
|
f8fc572e4a | ||
|
|
ab9e5fa204 | ||
|
|
8d45cb45c4 | ||
|
|
7712e3185e | ||
|
|
466149169e | ||
|
|
1c2626edbd | ||
|
|
b16d18f198 | ||
|
|
14030e2f11 | ||
|
|
9505c73824 | ||
|
|
1a446cdade | ||
|
|
1ef7f02cae | ||
|
|
7b86474be7 | ||
|
|
5d10337709 | ||
|
|
8eadb872f2 | ||
|
|
f170175ec8 | ||
|
|
fbe09f84df | ||
|
|
ebb480ba22 | ||
|
|
da1f029c2f | ||
|
|
4db9c166ef | ||
|
|
29fd6a7d03 | ||
|
|
d7338876d6 | ||
|
|
9df3f7174f | ||
|
|
79e476204f | ||
|
|
9c95218374 | ||
|
|
d9d2641981 | ||
|
|
e2585aa7ce | ||
|
|
1d1c7f98ff | ||
|
|
b1f1b3eff3 | ||
|
|
c1d0f2bb45 | ||
|
|
04de5f3200 | ||
|
|
fe791ff159 | ||
|
|
4082375e73 | ||
|
|
dcee59f273 | ||
|
|
31018cf037 | ||
|
|
17f0c6944c | ||
|
|
360cd6f438 | ||
|
|
b129d39ac9 | ||
|
|
fbb785293b | ||
|
|
1b8a7ee7f6 | ||
|
|
86b1b1431a | ||
|
|
d5e2d59eb6 | ||
|
|
03e43c0f1b | ||
|
|
724211b468 | ||
|
|
fe1a5b1498 | ||
|
|
fc3f18b748 | ||
|
|
0a66fb2acf | ||
|
|
56d2ba36b8 | ||
|
|
0ea642843a | ||
|
|
0c37c22d51 | ||
|
|
b32da4aefa | ||
|
|
c8a52fd478 | ||
|
|
67f402fb81 | ||
|
|
1ef28be5bc | ||
|
|
de0c50ead7 | ||
|
|
fe4105187d | ||
|
|
b05f472592 | ||
|
|
38286d4bc3 | ||
|
|
15e3a73ba6 | ||
|
|
38dc9d246b | ||
|
|
6736b78693 | ||
|
|
b179755e4f | ||
|
|
42f61205c3 | ||
|
|
b4c8799123 | ||
|
|
fd584d4495 | ||
|
|
3c4be703cd | ||
|
|
439c197c3f | ||
|
|
a8e815d664 | ||
|
|
c1e3d7dc6e | ||
|
|
8661bb38d5 | ||
|
|
0ec73a8102 | ||
|
|
93dc8d044d | ||
|
|
6377a1831f | ||
|
|
a9882a58b2 | ||
|
|
25f50eea02 | ||
|
|
b899c35419 | ||
|
|
a4b4957346 | ||
|
|
ddb8abf855 | ||
|
|
99e79026c5 | ||
|
|
b4c3a028fe | ||
|
|
5e4055b39e | ||
|
|
5b34c4d3f5 | ||
|
|
db6400d775 | ||
|
|
dc7594e85f | ||
|
|
3345019fe1 | ||
|
|
9dfec80e93 | ||
|
|
005435ca78 | ||
|
|
dbfab4a65d | ||
|
|
b2f3dc81fa | ||
|
|
a4da4e7230 | ||
|
|
433fd9486d |
No files matched your search
@@ -9,7 +9,7 @@
|
||||
"source": {
|
||||
"source": "npm",
|
||||
"package": "rea-agents",
|
||||
"version": "6.8.0"
|
||||
"version": "6.9.0"
|
||||
},
|
||||
"policy": {
|
||||
"installation": "AVAILABLE",
|
||||
|
||||
@@ -17,9 +17,9 @@ readiness or provider commands.
|
||||
|
||||
Installing this skill supplies instructions; it does not register the REA MCP
|
||||
server, install analysis engines, or add tools to an already-running agent.
|
||||
The exception is a Claude Code or Codex plugin install: the plugin bundles
|
||||
this skill and registers its own `rea` server, outside the state that
|
||||
`rea setup` and `rea doctor` manage.
|
||||
The exception is a Claude Code, Codex, or Cursor Marketplace plugin install:
|
||||
the plugin bundles this skill and registers its own `rea` server, outside the
|
||||
state that `rea setup` and `rea doctor` manage.
|
||||
|
||||
If REA tools are available and their registration is not known to be stale,
|
||||
proceed directly to the target. Do not run diagnostics or setup before every
|
||||
@@ -168,6 +168,7 @@ explicit path or endpoint and do not need it.
|
||||
Facts retain all-recorded-events-before-selection scope. Other qlog layouts
|
||||
and PCAP correlation are unsupported.
|
||||
- User-owned Electron runtime already open: `list_electron_targets`. Before an electron-main Inspector attempt, check packaged fuses with `inspect_electron_fuses`; disabled `EnableNodeCliInspectArguments` means the app ignores `--inspect`.
|
||||
- Shipped application exposure for a local `.app`, install directory, ASAR, or executable: `audit_release_exposure` / `rea audit-release-exposure`. Each check has a stable id, a status, and fixed remediation. Unknown and unassessed checks stay in the report. This does not establish that an application is secure. Credential-marker hits report the rule id and location only. See [release exposure](https://github.com/morluto/rea/blob/main/docs/release-exposure.md).
|
||||
- Packet-field discovery: `inspect_packet_fields` searches installed protocols
|
||||
and field names/types before choosing fields for `inspect_packet_capture`.
|
||||
Query/page the relevant records; registrations do not establish observed traffic.
|
||||
@@ -211,8 +212,10 @@ explicit path or endpoint and do not need it.
|
||||
See the [APK signature guide](https://github.com/morluto/rea/blob/main/docs/apk-signature.md).
|
||||
- Explicit local EVM bytecode carrier: `inspect_evm_interface` with caller-selected
|
||||
`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,
|
||||
30000 ms, range 1..2147483647, next call). Select byte, address-space and CPU
|
||||
allowances separately through `producer_limits`; tighter inherited OS limits
|
||||
remain enforced, and the 256 MiB worker heap is independent. 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
|
||||
@@ -336,7 +339,9 @@ explicit path or endpoint and do not need it.
|
||||
exception facts, lossless integer registers, usedImages UUIDs, and
|
||||
documented classification matches. Only `bug_type` `"309"` yields a crash
|
||||
body; other types, including `"288"` stackshots, return no crash result.
|
||||
Opened Mach-O and dSYM UUID joins remain unobserved. See the
|
||||
Select an optional `join_path` for UUID-and-architecture matching to one
|
||||
local Mach-O or dSYM; preserve slice identity and unjoined reasons. Joined
|
||||
static addresses do not resolve function names or dSYM symbols. See the
|
||||
[Apple IPS guide](https://github.com/morluto/rea/blob/main/docs/apple-ips.md).
|
||||
- Linux kernel module metadata: `inspect_kernel_module` with the explicit local
|
||||
ELF32/ELF64 relocatable file. This built-in target-free inspection requires
|
||||
|
||||
@@ -108,29 +108,34 @@ is not a recommendation to change it. Do not invent a setting. Host memory and
|
||||
- Capacity, when the result is `resource_constraint` and `retryable` is true:
|
||||
wait for the active admission to finish, then retry within the reported
|
||||
limits. Do not restart REA to free the slot.
|
||||
- `configuration_invalid`: correct the named setting in the environment that
|
||||
starts REA (the shell or the MCP registration), then restart REA. Run
|
||||
`rea doctor` to see the `runtime-configuration:` check. Re-run `rea setup`
|
||||
for that client when the registration must carry the new setting, then
|
||||
reconnect.
|
||||
- `configuration_invalid`: when the error reports `update_mode: "runtime"`,
|
||||
call `update_analysis_settings` for that setting. When it reports
|
||||
`update_mode: "parameter"`, change that call's argument; the setter does not
|
||||
accept it. Otherwise correct the named setting in the environment that starts
|
||||
REA (the shell or the MCP registration) and start REA again. Run `rea doctor`
|
||||
to see the `runtime-configuration:` check. Re-run `rea setup` for that client
|
||||
when the registration must carry the new setting, then reconnect.
|
||||
- `invalid_request`: correct the reported fields from the current schema. Do
|
||||
not repeat the unchanged call.
|
||||
|
||||
## REA installed as a client plugin
|
||||
|
||||
A Claude Code or Codex plugin owns its `rea` server and this skill. Doctor's
|
||||
`--client` and `--skill` checks and `rea setup` read and write only
|
||||
setup-owned state, so for a plugin-only install they report `missing`, and
|
||||
applying setup would add a second `rea` server. If this skill was loaded from
|
||||
a plugin, or the client lists a `rea` plugin, do not prepare a setup plan for
|
||||
missing tools. Instead:
|
||||
A Claude Code, Codex, or Cursor Marketplace plugin owns its `rea` server and
|
||||
this skill. Doctor's `--client` and `--skill` checks and `rea setup` read and
|
||||
write only setup-owned state, so for a plugin-only install they report
|
||||
`missing`, and applying setup would add a second `rea` server. If this skill
|
||||
was loaded from a plugin, or the client lists a `rea` plugin, do not prepare a
|
||||
setup plan for missing tools. Instead:
|
||||
|
||||
- Check that the plugin is installed and enabled with the client's own
|
||||
listing: `claude plugin list` and `/mcp` in Claude Code, `codex plugin list`
|
||||
in Codex.
|
||||
in Codex, and Cursor's plugin settings for a Marketplace install.
|
||||
- Restart or reconnect the client, then read its launch error for the `rea`
|
||||
server if tools are still absent. The plugin starts its bundled runtime; a missing build or version mismatch
|
||||
requires a reinstall, or a fresh build when developing from source.
|
||||
server if tools are still absent. Claude Code and Codex start the plugin's
|
||||
bundled runtime; a missing build or version mismatch requires a reinstall,
|
||||
or a fresh build when developing from source. A Cursor Marketplace install
|
||||
starts `npx` at the version pinned in the plugin's `mcp.json`. A failed
|
||||
download needs network access to that published version.
|
||||
- Check analysis engines through the connected server's
|
||||
`binary_session.result.tool_availability`. `rea doctor --provider <id> --json`
|
||||
from a shell reports that shell's environment, which can differ from the
|
||||
|
||||
@@ -62,6 +62,16 @@ runtime presence. For compact CLI output, use
|
||||
`inspect-desktop-application PATH --detail summary --evidence_output BUNDLE`.
|
||||
See [desktop installations](https://github.com/morluto/rea/blob/main/docs/desktop-applications.md).
|
||||
|
||||
## Release exposure
|
||||
|
||||
Use `audit_release_exposure` (`rea audit-release-exposure PATH`) when the question is what static analysis of a shipped `.app`, install directory, ASAR, or executable recovers. Each check has a stable id, a status, the observation behind it, and fixed remediation. Unknown and unassessed checks stay in the report. The report does not establish that the application is secure.
|
||||
|
||||
`text.credential_markers` reports a rule id and location only. Matched bytes, previews, lengths, and hashes of matched bytes are omitted.
|
||||
|
||||
`native.hardening`, `macho.hardened_runtime`, and `android.manifest` are not assessed here. Their next probes are `inspect_binary_hardening`, `inspect_signature`, and `inspect_android_package`.
|
||||
|
||||
See [release exposure](https://github.com/morluto/rea/blob/main/docs/release-exposure.md).
|
||||
|
||||
## Go build metadata
|
||||
|
||||
Use `inspect_go_binary` for an explicit local ELF, PE or Mach-O (universal
|
||||
@@ -238,7 +248,10 @@ Xcode, atos, or target execution is required. The CLI equivalent is
|
||||
`inspect-apple-ips PATH`. Preserve artifact SHA-256, `bug_type` as a string,
|
||||
uppercase image UUIDs, and integer literals that exceed IEEE-754 range. Only
|
||||
`bug_type` `"309"` yields a crash body; other DiagnosticReports types return
|
||||
no crash result. Opened Mach-O and dSYM UUID joins remain unobserved. See
|
||||
no crash result. Select `join_path` for one local Mach-O or dSYM to match
|
||||
report images to slices by UUID and architecture. Preserve the selected
|
||||
artifact identity, slice facts and unjoined reasons; a joined static address
|
||||
does not resolve function names or dSYM symbols. See
|
||||
[Apple IPS crash reports](https://github.com/morluto/rea/blob/main/docs/apple-ips.md).
|
||||
|
||||
## Linux kernel modules
|
||||
@@ -536,8 +549,7 @@ the framing LF still fits. Cutter measures, signs, and writes a fitting
|
||||
response in bounded chunks. The bridge searches only the newly read bytes
|
||||
for the framing LF. The client unescapes each socket chunk into one response
|
||||
string before parsing it, so this ceiling does not keep the paged wire frame
|
||||
and another concatenated copy. Invalid values are configuration errors and do not fall back to 16777216. Set the variable in the environment that starts REA, restart REA,
|
||||
and start Hopper or Cutter from that same environment. An out-of-band bridge
|
||||
and another concatenated copy. Invalid values are configuration errors and do not fall back to 16777216. `bridge.max_request_bytes` can be changed at runtime with `update_analysis_settings`. The launch seed is `REA_BRIDGE_MAX_REQUEST_BYTES`. Start Hopper or Cutter from that same environment so the bridge keeps the ceiling it started with until that bridge starts again. An out-of-band bridge
|
||||
without the setting stays at 16777216 bytes. The client reports that mismatch
|
||||
during discovery only after the hello proves a live authenticated bridge, and
|
||||
does not send a status request or the command. A stale descriptor is ignored.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"source": {
|
||||
"source": "npm",
|
||||
"package": "rea-agents",
|
||||
"version": "6.8.0"
|
||||
"version": "6.9.0"
|
||||
},
|
||||
"category": "development"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "rea",
|
||||
"version": "6.8.0",
|
||||
"version": "6.9.0",
|
||||
"description": "Reverse engineer anything with agents, from app behavior down to native binaries.",
|
||||
"author": {
|
||||
"name": "morluto",
|
||||
@@ -21,7 +21,7 @@
|
||||
"command": "node",
|
||||
"args": [
|
||||
"${CLAUDE_PLUGIN_ROOT}/scripts/plugin-mcp-launcher.mjs",
|
||||
"6.8.0"
|
||||
"6.9.0"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"command": "node",
|
||||
"args": [
|
||||
"./scripts/plugin-mcp-launcher.mjs",
|
||||
"6.8.0"
|
||||
"6.9.0"
|
||||
],
|
||||
"cwd": ".",
|
||||
"startup_timeout_sec": 30
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "rea",
|
||||
"version": "6.8.0",
|
||||
"version": "6.9.0",
|
||||
"description": "Reverse engineer anything with agents, from app behavior down to native binaries.",
|
||||
"author": {
|
||||
"name": "morluto",
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "rea",
|
||||
"version": "6.9.0",
|
||||
"description": "Reverse engineer anything with agents, from app behavior down to native binaries.",
|
||||
"author": {
|
||||
"name": "morluto",
|
||||
"url": "https://github.com/morluto"
|
||||
},
|
||||
"homepage": "https://rea.tools/",
|
||||
"repository": "https://github.com/morluto/rea",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"reverse-engineering",
|
||||
"binary-analysis",
|
||||
"decompiler",
|
||||
"mcp-server"
|
||||
],
|
||||
"skills": ".cursor-plugin/skills",
|
||||
"logo": "assets/rea-plugin.png"
|
||||
}
|
||||
@@ -0,0 +1,608 @@
|
||||
---
|
||||
name: reverse-engineer-anything
|
||||
description: Reverse engineer native, managed, Electron/JavaScript, packaged, firmware, and browser targets with REA, and build agent environments (AgentEnv bundles) of web applications from a live instance or a capture, and of Linux desktop apps with a task from a request. Use shipped-artifact or requested runtime evidence to explain features, compare versions, decompile code, or guide a reconstruction. Skip REA for ordinary source-repository architecture analysis.
|
||||
metadata:
|
||||
version: "62"
|
||||
---
|
||||
|
||||
# REA
|
||||
|
||||
Use REA when a claim depends on a shipped binary or package, decompilation,
|
||||
requested runtime evidence, or comparison with
|
||||
behavior not established by available source. For ordinary analysis of a
|
||||
complete source repository, use normal repository tools and do not run REA
|
||||
readiness or provider commands.
|
||||
|
||||
## Connect only when needed
|
||||
|
||||
Installing this skill supplies instructions; it does not register the REA MCP
|
||||
server, install analysis engines, or add tools to an already-running agent.
|
||||
The exception is a Claude Code, Codex, or Cursor Marketplace plugin install:
|
||||
the plugin bundles this skill and registers its own `rea` server, outside the
|
||||
state that `rea setup` and `rea doctor` manage.
|
||||
|
||||
If REA tools are available and their registration is not known to be stale,
|
||||
proceed directly to the target. Do not run diagnostics or setup before every
|
||||
investigation. Use the connected server's actual tool list and input schemas;
|
||||
a skill installed from repository main may describe capabilities absent from
|
||||
an older npm release. Keep complete inline Evidence when that server does not
|
||||
advertise retained references.
|
||||
|
||||
If tools are absent, a call is blocked by the client, or a required provider is
|
||||
unavailable, read [connection and recovery](references/connection-and-recovery.md).
|
||||
Diagnose the observed blocker, continue useful supported work, and resume the
|
||||
original task after repair. Client approval, shell PATH, registration and engine
|
||||
availability have different remedies; avoid repeating setup for all of them.
|
||||
If the host times out without a REA result, do not repeat the unchanged call or
|
||||
assume work stopped. Read the recovery guide's deadline distinction before retrying.
|
||||
If the MCP connection drops, retry that call once only when it is safe to
|
||||
repeat or known not to have started. If it may already have changed the
|
||||
target, or it fails again, tell the user and ask them to restart the MCP
|
||||
client. If REA could not start its connection, retry once, then tell the user
|
||||
and ask them to restart the MCP client. Do not retry a startup failure that
|
||||
returns the same unchanged result. For plugin installs, follow
|
||||
[plugin recovery](references/connection-and-recovery.md#rea-installed-as-a-client-plugin).
|
||||
For setup-owned registrations, run `rea doctor` when REA could not start
|
||||
or tools stay missing after that restart. For `cleanup_incomplete`, a retryable
|
||||
capacity limit, or `configuration_invalid`, follow the recovery guide's ladder
|
||||
before asking for a restart. Read that guide before a second repair attempt.
|
||||
|
||||
Choose the installation owner before repairing registration. Plugin installs use
|
||||
[plugin recovery](references/connection-and-recovery.md#rea-installed-as-a-client-plugin);
|
||||
only setup-owned registrations use the guide's
|
||||
[registration repair plan](references/connection-and-recovery.md#repair-registration-when-needed).
|
||||
A plugin-only doctor result of `missing` does not call for `rea setup`.
|
||||
|
||||
REA setup never installs or upgrades Node.js, npm, Homebrew, Java, Ghidra, IDA,
|
||||
JADX, Kuna, Binwalk, or Unblob. Use existing prerequisites; do not install unrelated
|
||||
software to repair MCP registration. For an unsupported client, use manual stdio
|
||||
registration with an existing installation’s absolute runtime and entry script, or continue through the CLI.
|
||||
|
||||
A concrete CLI fallback for an operator-supplied JavaScript tree or ASAR is:
|
||||
|
||||
```bash
|
||||
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
|
||||
```
|
||||
|
||||
No MCP registration or native engine is required. Read the returned Evidence,
|
||||
graph, limitations, and unknowns with the same care as an MCP result; the CLI
|
||||
returns the Evidence record directly. This fallback does not establish that
|
||||
MCP is configured. Native CLI tasks still require their selected engine.
|
||||
Prefer an existing `rea` CLI. When none is installed and REA package acquisition
|
||||
is within the authorized scope, use `npx -y rea-agents@latest` in its place from a
|
||||
trusted directory outside the target project, with absolute target paths. Managed
|
||||
setup binds the current installation directly; retain its runtime and package
|
||||
cache entry, or restore that installation before repairing its registration.
|
||||
For setup-owned registration, configuration repair starts with a read-only setup plan; show paths, backups and
|
||||
skill replacement before applying authorized changes. Preserve existing approval
|
||||
and target-execution boundaries.
|
||||
|
||||
## Route the target first
|
||||
|
||||
Choose the first tool from the target the user supplied. Use `open_binary` for
|
||||
active-target native or archive workflows; target-free tools take their own
|
||||
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, 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).
|
||||
- Bun `--compile` executable: `open_binary`, then `inspect_artifact`; the Bun
|
||||
module graph is the application layer. Extract stored modules and analyze the
|
||||
JavaScript. See [Bun standalone executables](https://github.com/morluto/rea/blob/main/docs/bun-standalone.md).
|
||||
- Deno `deno compile` executable: `open_binary`, then `inspect_artifact`; the
|
||||
embedded virtual filesystem is the application layer. Extract stored files and
|
||||
analyze compatible JavaScript. Environment-file values and CA certificate bytes
|
||||
are retained in local Evidence with their counts and byte lengths. The npm
|
||||
snapshot length is reported and not decoded, and the executable is not run. See
|
||||
[Deno compile executables](https://github.com/morluto/rea/blob/main/docs/deno-standalone.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
|
||||
executable digest or binary snapshot; use `open_binary` for native code.
|
||||
- Android APK code, classes, methods, or incoming references:
|
||||
`inspect_android_package`, then focused Android tools when advertised.
|
||||
Archive member inventory still uses the archive route above.
|
||||
- Managed PE/CLI assembly: `inspect_managed_artifact`.
|
||||
- Firmware image: `inspect_firmware_regions` when advertised. Use
|
||||
`extract_firmware` when extraction is requested, with a caller-selected new
|
||||
absolute output directory. These tools use caller-supplied Binwalk/Unblob on
|
||||
Linux; see the [firmware guide](https://github.com/morluto/rea/blob/main/docs/guides/firmware/firmware-analysis.md).
|
||||
- ESP32-family app or bootloader image (`0xE9` magic): `inspect_artifact`
|
||||
without a provider; see the ESP section of `references/native-and-artifacts.md`.
|
||||
- .NET NativeAOT PE/ELF: native Ghidra analysis. Native code can yield pseudocode;
|
||||
consult the NativeAOT workflow in `references/native-and-artifacts.md` for
|
||||
optional metadata recovery and its supported host/layout boundary.
|
||||
- Native program behavior, live calls, instrumentation, or command-run effects:
|
||||
choose the matching [native runtime workflow](references/runtime-observation.md#native-runtime-questions).
|
||||
`open_binary` and `trace_native_values` establish static facts; they do not
|
||||
observe execution. Runtime tools have distinct launch, attach, mutation and
|
||||
cleanup effects, and do not require a preliminary static session unless their
|
||||
own contract says so.
|
||||
- User-owned browser page already open: `list_browser_targets`.
|
||||
- Passive traffic capture of a SPA: the default scope is the page's own origin,
|
||||
and data APIs usually live on another origin. Discover API origins from
|
||||
absolute URLs in loaded bundles or script text via JavaScript analysis tools
|
||||
(another passive capture without those origins still scopes to the page
|
||||
origin, and `completeness.excluded` counts lack URLs). Pass both the page
|
||||
origin and those API origins in `allowed_origins` — the list replaces the
|
||||
default scope — and read `completeness.excluded` before reporting that an
|
||||
API is absent. For long captures with body shapes, use
|
||||
`export_evidence_bundle` instead of expecting an inline result.
|
||||
- Browser action the agent must perform (click, type, navigate):
|
||||
`capture_browser_scenario` with declared actions. See
|
||||
[runtime observation](references/runtime-observation.md) for connect/launch
|
||||
and the focused follow-up browser tools.
|
||||
- Agent environment (AgentEnv bundle) of a web application: read
|
||||
[environments](references/environments.md) before recording; it records with
|
||||
`capture_browser_scenario` and writes the bundle with `export_environment_bundle`.
|
||||
- Task for a desktop application's exported environment, from a
|
||||
`capture-desktop-application` folder: read
|
||||
[desktop application tasks](references/environments.md#tasks-for-a-desktop-application-environment).
|
||||
- Environment of a Linux desktop app with a task, from a request such as
|
||||
"build me an Inkscape environment where the agent changes a poster's
|
||||
headline": read [desktop builds](references/desktop-build.md). You drive the
|
||||
app on a build computer from `start_build_computer`, then export and witness.
|
||||
- Fiddler Everywhere traffic or a native `.saz` capture: read the
|
||||
[Fiddler workflow](references/runtime-observation.md#fiddler-everywhere-traffic-debugging).
|
||||
Inspect saved SAZ with `inspect_web_network_capture` and `format: "saz"`;
|
||||
connect Everywhere's separate MCP server for live traffic.
|
||||
- Retained HAR/SAZ/native mitmproxy/aioquic qlog capture: `inspect_web_network_capture`. Select
|
||||
original record ordinals when useful; inspect producer fields and byte/number
|
||||
sidecars without fetching recorded URLs or claiming live attribution. HAR/SAZ/qlog
|
||||
old-generation heap is `REA_CAPTURE_DECODER_OLD_GENERATION_MIB` (default 192 MiB,
|
||||
floor 8, maximum 16384), set where REA starts. Host memory and `NODE_OPTIONS` do not
|
||||
raise it. See
|
||||
[historical captures](https://github.com/morluto/rea/blob/main/docs/guides/web/web-network-captures.md) for the exact upstream
|
||||
profile and credential exclusions. Qlog support starts with aioquic 1.5.0
|
||||
JSON 0.3; stream coverage and endpoint loss declarations do not recover bodies
|
||||
or establish network loss. Prefer detail summary, then kind qlog trace/stream
|
||||
pages; select one trace, stream ID and direction for contribution/range pages.
|
||||
Facts retain all-recorded-events-before-selection scope. Other qlog layouts
|
||||
and PCAP correlation are unsupported.
|
||||
- User-owned Electron runtime already open: `list_electron_targets`. Before an electron-main Inspector attempt, check packaged fuses with `inspect_electron_fuses`; disabled `EnableNodeCliInspectArguments` means the app ignores `--inspect`.
|
||||
- Shipped application exposure for a local `.app`, install directory, ASAR, or executable: `audit_release_exposure` / `rea audit-release-exposure`. Each check has a stable id, a status, and fixed remediation. Unknown and unassessed checks stay in the report. This does not establish that an application is secure. Credential-marker hits report the rule id and location only. See [release exposure](https://github.com/morluto/rea/blob/main/docs/release-exposure.md).
|
||||
- Packet-field discovery: `inspect_packet_fields` searches installed protocols
|
||||
and field names/types before choosing fields for `inspect_packet_capture`.
|
||||
Query/page the relevant records; registrations do not establish observed traffic.
|
||||
- Recorded packet captures: `inspect_packet_capture` with selected TShark fields,
|
||||
display filters and decode-as rules. Requires Linux, util-linux prlimit and
|
||||
TShark 4.x on an absolute `PATH` entry or via the optional absolute
|
||||
`REA_TSHARK_COMMAND` override; see
|
||||
[capture guide](https://github.com/morluto/rea/blob/main/docs/guides/data/packet-captures.md).
|
||||
Packet limits count input packets before filtering. Output defaults to 50 matching
|
||||
frames; use `match_offset` / `match_limit` for later pages, or explicit null
|
||||
limit for complete matching output. Preserve the source digest across pages.
|
||||
This does not perform live capture.
|
||||
For address/DNS/SNI/protocol summaries use `inspect_pcap_capture` with MCP
|
||||
detail summary, then retained kind pcap pages. Requires Wireshark 4.x tshark
|
||||
and capinfos, with Linux prlimit or Windows Job Objects; see
|
||||
[packet summaries](https://github.com/morluto/rea/blob/main/docs/guides/data/pcap-analysis.md).
|
||||
Select an exact DNS question for address pages; page exhaustion does not prove
|
||||
network completeness. This reads recordings and does not acquire traffic.
|
||||
- Decoder discovery: `inspect_signal_decoders` searches installed decoder IDs
|
||||
or selected decoder help, including channels and options. Query and page the
|
||||
relevant details before choosing settings; this does not scan hardware.
|
||||
- Recorded logic/signal traces: `decode_signal_recording` with explicit decoder,
|
||||
channel and protocol settings. On Linux with util-linux prlimit, supply sigrok-cli 0.7.2 through
|
||||
`REA_SIGROK_COMMAND`; see [recording guide](https://github.com/morluto/rea/blob/main/docs/guides/signals/signal-recordings.md).
|
||||
Output defaults to 50 literal lines; select annotation classes and page with
|
||||
`line_offset` / `line_limit`, or explicit null for all remaining output.
|
||||
Window counts are display lines, not annotations or samples. Preserve source digests across pages.
|
||||
This reads existing files; it does not acquire hardware signals.
|
||||
- Explicit local WebAssembly artifact: `inspect_wasm_artifact`. Supply WABT 1.0.42
|
||||
through `REA_WABT_BIN_DIRECTORY`; retain exact byte/tool identity and decoded WAT.
|
||||
Select JavaScript glue and candidate paths explicitly and preserve URL/path
|
||||
ambiguity. No implicit fetch or target execution; WAT is not original source.
|
||||
See the [WASM guide](https://github.com/morluto/rea/blob/main/docs/guides/wasm/wasm-artifacts.md).
|
||||
- Explicit local Android APK (or ZIP/AAB) signing: `inspect_apk_signature`.
|
||||
Prefer its summary or selected signer/digest/lineage page; retain complete
|
||||
Evidence and use `inspect_analysis_view` kind `apk-signature` for follow-ups.
|
||||
Reports which schemes are present (v1 JAR, v2, v3, v3.1), each signer's
|
||||
certificate SHA-256 fingerprint (v1 included, from its PKCS#7 block), v3 key-rotation lineage, source stamp, and
|
||||
whether each signed digest still matches the bytes (self-consistency). This
|
||||
is identity and integrity, not a trust or authenticity verdict.
|
||||
See the [APK signature guide](https://github.com/morluto/rea/blob/main/docs/apk-signature.md).
|
||||
- Explicit local EVM bytecode carrier: `inspect_evm_interface` with caller-selected
|
||||
`raw` or `hex` encoding. The owned worker deadline is `timeout_ms` (default
|
||||
30000 ms, range 1..2147483647, next call). Select byte, address-space and CPU
|
||||
allowances separately through `producer_limits`; tighter inherited OS limits
|
||||
remain enforced, and the 256 MiB worker heap is independent. 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
|
||||
Evidence stays retained under its original identity. Use the returned
|
||||
`parent_evidence_id` for exact function or `bytecode_hex`/stdout/stderr pages.
|
||||
Candidate coverage does not establish interface completeness. See the
|
||||
[EVM bytecode guide](https://github.com/morluto/rea/blob/main/docs/guides/evm/evm-bytecode.md).
|
||||
- Embedded Go compiler, module, build-setting metadata, or static `(ptr, len)`
|
||||
string literals: `inspect_go_binary` with the explicit local file (pass
|
||||
`include_string_literals: true` and optional `max_string_literals` for bounded
|
||||
inferred static string-header recovery, and page retained rows with
|
||||
`inspect_analysis_view` kind `go` collection `string_literals`). This built-in
|
||||
target-free inspection requires no Go installation or disassembler. Preserve
|
||||
raw module bytes and source ranges; absent metadata does not prove a binary is
|
||||
not Go, static string recovery excludes compiler-inlined stack or immediate
|
||||
strings, and unparsed text records remain explicit. See the
|
||||
[Go binary guide](https://github.com/morluto/rea/blob/main/docs/guides/native/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
|
||||
retained summaries; optional `view` selects one page in the initial call. Use
|
||||
`inspect_analysis_view` kind `model-artifact` for
|
||||
batched metadata keys, tensor names or type totals, selected fields and pages.
|
||||
Preserve header-scoped indices and array preview omissions; do not infer model
|
||||
behavior from declared architecture or tensor types. See the
|
||||
[model file guide](https://github.com/morluto/rea/blob/main/docs/model-artifacts.md).
|
||||
- Unity IL2CPP names, member owners and string literals from `global-metadata.dat`:
|
||||
`inspect_il2cpp_metadata` with the explicit local file; MCP defaults to compact
|
||||
counts. Query sections, images, types, methods, fields, properties, events,
|
||||
parameters or string_literals through `inspect_analysis_view`
|
||||
with the returned `parent_evidence_id`, using exact filters, batch indices and
|
||||
selected fields. Parameters accept `method_indices`, avoiding a scan of all
|
||||
parameter pages. Missing collections in historical Evidence remain unknown.
|
||||
Versions 24, 27, 29, 31 and 39; no Unity, IL2CPP
|
||||
binary or disassembler is run. Unrecognized magic (possibly encrypted) and
|
||||
other versions are unsupported. Optional matching `binary_path` enables static native addresses and type references; query `method_addresses` with indices or addresses/states, preserving every shared-body method and both artifact identities. Without a linked binary native counts remain unknown. Byte-pattern fallback is inferred; no runtime behavior or same-build pairing is proved. See the
|
||||
[IL2CPP metadata guide](https://github.com/morluto/rea/blob/main/docs/il2cpp-metadata.md).
|
||||
- Embedded cargo-auditable Rust dependency metadata: `inspect_rust_binary`
|
||||
with the explicit local ELF, PE, or thin Mach-O file. This built-in
|
||||
target-free inspection requires no Rust installation or disassembler. Preserve
|
||||
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).
|
||||
- PE Authenticode certificate table: `inspect_pe_certificates` with the explicit
|
||||
local PE32/PE32+ file. This built-in target-free inspection requires no
|
||||
Windows SDK. Preserve WIN_CERTIFICATE ranges, types, payload SHA-256, and
|
||||
PKCS#7 signer/X.509 identity fields, including `subject_key_identifier_hex`
|
||||
when the signer uses that form. A missing security directory is observed
|
||||
absence of that table, not proof the image is unsigned in every catalog sense.
|
||||
Signatures are not verified. See the
|
||||
[PE certificate guide](https://github.com/morluto/rea/blob/main/docs/pe-certificates.md).
|
||||
- PE import and delay-load tables: `inspect_pe_imports` with the explicit
|
||||
local PE32/PE32+ file. This built-in target-free inspection requires no
|
||||
Windows SDK. Preserve DLL names, named and ordinal functions, ILT/IAT RVAs,
|
||||
delay-load descriptors, and the pefile import hash of the standard import
|
||||
table. A missing import directory is observed absence of that table, not
|
||||
proof the image never imported APIs through another table. Bound snapshots
|
||||
and loaded IAT contents remain unobserved. See the
|
||||
[PE import guide](https://github.com/morluto/rea/blob/main/docs/pe-imports.md).
|
||||
- Windows Shell Link shortcuts: `inspect_windows_shortcut` with the explicit
|
||||
local `.lnk` file. This built-in target-free inspection requires no Windows
|
||||
SDK or COM. Preserve header flags and FILETIMEs, IDList items, LinkInfo
|
||||
volume and network names, StringData arguments and icon location, ExtraData
|
||||
signatures, and Tracker droid facts labelled derived. Unknown IDList items
|
||||
and ExtraData signatures stay raw with SHA-256. The target path is not
|
||||
resolved or executed. See the
|
||||
[Windows shortcut guide](https://github.com/morluto/rea/blob/main/docs/guides/native/windows-shortcut.md).
|
||||
- PE TLS callbacks and load configuration: `inspect_pe_load_config` with the
|
||||
explicit local PE32/PE32+ file. This built-in target-free inspection requires
|
||||
no Windows SDK. Preserve callback VAs as strings with their RVA, file offset
|
||||
and section, and the size-covered security cookie, SafeSEH, CFG,
|
||||
EH-continuation and XFG fields. Guard-flag mitigation claims are inferred
|
||||
linker declarations, not proof of enforcement. A missing directory is observed
|
||||
absence of that declaration. See the
|
||||
[PE load configuration guide](https://github.com/morluto/rea/blob/main/docs/pe-load-config.md).
|
||||
- ELF, PE, and Mach-O hardening: `inspect_binary_hardening` with the explicit
|
||||
local file. This built-in target-free inspection requires no pwntools or other
|
||||
host tool. One image per Mach-O slice. Each property is `enabled`, `disabled`,
|
||||
`partial`, `unknown`, or `not_applicable`, with the header field or import
|
||||
behind it. A missing stack-protector or fortify import is `unknown`, not
|
||||
proof the protection was omitted. Authenticode and Mach-O code signatures
|
||||
report presence, not validity. Hardened runtime stays unknown and names
|
||||
`inspect_signature`. The image is not executed. See the
|
||||
[binary hardening guide](https://github.com/morluto/rea/blob/main/docs/binary-hardening.md).
|
||||
- ELF note tables: `inspect_elf_notes` with the explicit local ELF32/ELF64
|
||||
file. This built-in target-free inspection requires no disassembler. Preserve
|
||||
PT_NOTE and SHT_NOTE ranges, owners, types, descriptor SHA-256, and GNU
|
||||
build-id or ABI-tag fields. A missing table is observed absence of those
|
||||
declarations, not proof the image never carried notes. See the
|
||||
[ELF notes guide](https://github.com/morluto/rea/blob/main/docs/elf-notes.md).
|
||||
- Code that runs before `main` or at exit in ELF or Mach-O:
|
||||
`inspect_native_initializers` with the explicit local file (and
|
||||
`architecture` for a universal Mach-O). This built-in inspection requires no
|
||||
disassembler. Preserve slot and target addresses, the `resolution` of each
|
||||
entry, and its limitations. An `unresolved` slot is not a zero pointer, and a
|
||||
missing table is not proof that no constructor exists. See the
|
||||
[initializer guide](https://github.com/morluto/rea/blob/main/docs/guides/native/native-initializers.md).
|
||||
|
||||
- ELF unwind function ranges: `inspect_elf_unwind_ranges` with the explicit
|
||||
local ELF32/ELF64 file. This built-in target-free inspection requires no
|
||||
disassembler. Preserve FDE start, end, size, containing section, exact
|
||||
symbol name, CIE index, LSDA, and personality. Page with `offset` and
|
||||
`limit`. A missing `.eh_frame` is observed absence of that declaration,
|
||||
not proof the image has no functions. `.debug_frame` is reported present
|
||||
or absent and is not decoded. CFA instructions are counted and not
|
||||
evaluated. See the
|
||||
[ELF unwind ranges guide](https://github.com/morluto/rea/blob/main/docs/guides/native/elf-unwind-ranges.md).
|
||||
- Apple `.ips` crash reports: `inspect_apple_ips` with the explicit local
|
||||
file. This built-in target-free inspection requires no Xcode, atos, or
|
||||
pwntools. Preserve first-line metadata, `bug_type` as a string, process and
|
||||
exception facts, lossless integer registers, usedImages UUIDs, and
|
||||
documented classification matches. Only `bug_type` `"309"` yields a crash
|
||||
body; other types, including `"288"` stackshots, return no crash result.
|
||||
Select an optional `join_path` for UUID-and-architecture matching to one
|
||||
local Mach-O or dSYM; preserve slice identity and unjoined reasons. Joined
|
||||
static addresses do not resolve function names or dSYM symbols. See the
|
||||
[Apple IPS guide](https://github.com/morluto/rea/blob/main/docs/apple-ips.md).
|
||||
- Linux kernel module metadata: `inspect_kernel_module` with the explicit local
|
||||
ELF32/ELF64 relocatable file. This built-in target-free inspection requires
|
||||
no Linux host or `modinfo`. Preserve `.modinfo` key order and duplicate keys,
|
||||
`__versions` CRC hex, section file ranges, and the appended signature
|
||||
trailer's PKCS#7 SHA-256. A missing section is observed absence when section
|
||||
names are known, not proof the module never carried that metadata.
|
||||
`struct module` is not decoded. The signature is not validated. gzip, xz, and
|
||||
zstd containers are unsupported; decompress into a separate file with an
|
||||
external codec utility, then inspect the decompressed `ET_REL` image. See the
|
||||
[kernel module guide](https://github.com/morluto/rea/blob/main/docs/kernel-modules.md).
|
||||
- Linux kernel version and build config (`CONFIG_*` options such as
|
||||
`CONFIG_SECURITY_SELINUX`): `inspect_kernel_build_config` with the explicit
|
||||
local `vmlinux`, raw `Image`, x86 `bzImage`, or `configs.ko`. This built-in
|
||||
target-free inspection requires no Linux host or `extract-ikconfig`. Preserve
|
||||
the banner version, config SHA-256, option count, and value kinds; use `name`
|
||||
for one option. An `IKCFG_ST` string is a config only with a valid gzip member
|
||||
and `IKCFG_ED`. An absent config may mean the kernel was built without
|
||||
`CONFIG_IKCONFIG`. Non-gzip payloads are unsupported; decompress externally,
|
||||
then inspect the result. See the
|
||||
[kernel build config guide](https://github.com/morluto/rea/blob/main/docs/guides/native/kernel-build-config.md).
|
||||
- CPython 3.7–3.13 `.pyc` header, nested marshal code objects and bytecode
|
||||
identity: `inspect_python_pyc` with the explicit local file. This built-in
|
||||
target-free inspection requires no Python installation. Preserve magic,
|
||||
PEP 552 hash or mtime/size, nested names, and bytecode SHA-256. Bytecode is
|
||||
not decompiled, and a decoded header does not prove the matching `.py` is
|
||||
present. See the
|
||||
[CPython pyc guide](https://github.com/morluto/rea/blob/main/docs/python-pyc.md).
|
||||
- Erlang BEAM IFF container: `inspect_erlang_beam` with the explicit local
|
||||
`.beam` file. This built-in target-free inspection requires no Erlang
|
||||
installation. Preserve chunk names, atom order, export/import/lambda tables,
|
||||
and the Code header. For selected facts, prefer `detail: "summary"` plus a
|
||||
`beam` view (collection, names/indices, fields and paging), retaining the full
|
||||
Evidence. CLI summary requires `--evidence_output`. Missing table counts stay
|
||||
null; decoded empty tables count zero. Bytecode is not executed. See the
|
||||
[Erlang BEAM guide](https://github.com/morluto/rea/blob/main/docs/erlang-beam.md).
|
||||
|
||||
- Explicit local SQLite database snapshot: `inspect_sqlite_database`. Inspect
|
||||
with Node.js 24.x >=24.15 or 26+ providing native SQLite limits. Read schema
|
||||
first (compact inventory by default), or select an exact ordinary table
|
||||
and `columns` when rows are needed. Defaults are selected-table schema and
|
||||
20 rows; request `schema_scope: "database"` for the complete stored schema. Preserve both database and existing sibling WAL identity; row samples
|
||||
report truncation and have unspecified order. Use a quiescent snapshot rather
|
||||
than assuming a live database/WAL pair was copied atomically. See the
|
||||
[SQLite guide](https://github.com/morluto/rea/blob/main/docs/guides/data/sqlite-databases.md).
|
||||
- Explicit Linux ELF file for offline layout, symbols, relocations or static
|
||||
mitigation evidence: `inspect_binary_layout`. This target-free operation uses
|
||||
caller-supplied pwntools without opening a disassembler database. Preserve its
|
||||
raw locations and inference/coverage limits; see the
|
||||
[offline binary guide](https://github.com/morluto/rea/blob/main/docs/guides/native/binary-diagnostics.md).
|
||||
- Supplied Linux x86-64 ELF core: `inspect_recorded_crash`. Read every recorded
|
||||
thread, raw note and source-bound register without opening a live target.
|
||||
Historical PIDs do not select live processes. Request `include_debugger_context`
|
||||
only when core-only mapping candidates help; see the
|
||||
[recorded crash guide](https://github.com/morluto/rea/blob/main/docs/guides/native/recorded-crashes.md).
|
||||
- PE resource type/name/language trees and static icon group references:
|
||||
`inspect_pe_resources` with an explicit path. This portable operation requires
|
||||
no active target or engine; opaque payloads retain file ranges and SHA-256.
|
||||
- PE export directories and ELF dynamic-symbol exports: `inspect_native_exports`
|
||||
with an explicit path; portable, no active target or engine.
|
||||
- Native executable, library, or analysis database: `open_binary`, then
|
||||
use focused analysis tools directly; call `binary_overview` when metadata or
|
||||
inventory context is useful and available from the selected provider.
|
||||
|
||||
For an existing IDA MCP configuration, use `open_binary` with the original
|
||||
input binary and `provider_id: "ida"`; do not pass an `.idb` or `.i64` database.
|
||||
The legacy attached profile binds the already-open GUI input by SHA-256 and
|
||||
leaves its database open. The modern headless profile creates and closes an
|
||||
owned private database without saving. Installation and registration reuse
|
||||
[mrexodia/ida-pro-mcp](https://github.com/mrexodia/ida-pro-mcp); see the
|
||||
[IDA provider guide](https://github.com/morluto/rea/blob/main/docs/providers/ida-provider.md).
|
||||
For migration to the separate native IDA MCP plugin, follow the guide's
|
||||
[legacy attached migration](https://github.com/morluto/rea/blob/main/docs/providers/ida-provider.md#migrate-a-legacy-attached-registration).
|
||||
Replace the upstream registration explicitly; modern mrexodia tools are not the
|
||||
native profile. Native attachment preserves the database but does not provide
|
||||
direct callers; check session availability and the guide's verification limits.
|
||||
Proceed directly to `analyze_function`, pseudocode, or function/string searches
|
||||
after opening; IDA does not supply `binary_overview`. Consult session availability
|
||||
when composing broader workflows. Modern direct callers and unsupported dossier
|
||||
facets remain unknown; live IDA results are not replayed from snapshots.
|
||||
|
||||
With `REA_KUNA_COMMAND` configured, `provider_id: "kuna"` answers procedure
|
||||
lists, lookups, pseudocode, assembly and `analyze_function` from Kuna's cached
|
||||
whole-program export. Callers/callees use a separate body-free graph shared by
|
||||
the session; `xrefs` returns exact-address incoming sites and filters forwarding
|
||||
aliases. These queries and inventory lookups do not trigger a C export. Indirect
|
||||
targets remain unknown and can make relationship coverage partial. Reference
|
||||
caches expire on close; a fresh CLI process repeats the native reference walk.
|
||||
Typed references, CFG, raw-memory tools and annotations remain unsupported. A cold first
|
||||
answer can come from a single-function run (its limitations say so); assembly
|
||||
waits for the export. For pseudocode and assembly, `raw_result.source` names the
|
||||
cached `.c`/`.asm` file and byte span, which you may search directly instead of
|
||||
calling per function. See the
|
||||
[Kuna provider guide](https://github.com/morluto/rea/blob/main/docs/kuna-provider.md).
|
||||
|
||||
If the user says only "my app" without a name, path, or target already selected
|
||||
for this task, ask which app before searching for artifacts. Paths in unrelated
|
||||
saved reports and nearby test fixtures do not select the user's target. Resolve
|
||||
an actual human-readable app name to one clear installed artifact when possible;
|
||||
ask when matches are ambiguous. Never choose an example app on the user's behalf.
|
||||
|
||||
In a target-free session, use `open_binary` to bind any archive/package or
|
||||
native target whose analysis tool operates on the active target. Do not call an
|
||||
unadvertised tool; inspect `binary_session` with `{}` and its
|
||||
`result.tool_availability` for availability reasons and remediation. Expand each
|
||||
group's `names` into entries, inheriting the inventory-level client requirements
|
||||
unless the group overrides them. The grouped name union is the complete tool
|
||||
inventory; use `tools/list` for canonical tool schemas. The default summary keeps
|
||||
each provider candidate's availability and target-support status, code and
|
||||
reason; `omitted_fields` lists what it leaves out. Request `{"detail": "complete"}`
|
||||
only when you need an unavailable candidate's remediation, provider
|
||||
diagnostics, candidate capability sets, or tool surface, effect and annotation
|
||||
flags; in those closed flag vocabularies, listed
|
||||
flags are true and omitted known flags are false. Provider candidate facts
|
||||
describe possible providers, while top-level session capabilities describe the
|
||||
current route and `analysis_provider_binding` names the selected provider. Do
|
||||
not treat those scopes as interchangeable.
|
||||
|
||||
For editable Ghidra analysis that must survive a later agent process, select
|
||||
the [owned Program checkpoint workflow](references/native-and-artifacts.md#continue-editable-ghidra-analysis-across-processes)
|
||||
before making metadata edits. It is separate from Evidence/Unknown persistence.
|
||||
|
||||
For a Ghidra startup timeout on a large native target, follow
|
||||
[deadline recovery](references/native-and-artifacts.md#ghidra-startup-deadline-recovery)
|
||||
before abandoning deep analysis or repeating the same cold import. The default
|
||||
330 seconds can be changed for new startup attempts through
|
||||
`update_analysis_settings` using `ghidra.startup_timeout_ms`. Changing the
|
||||
server's launch environment instead requires a new REA process.
|
||||
|
||||
## Work summary-first
|
||||
|
||||
Start with the default result and use its inline Evidence and graph context.
|
||||
For a JavaScript application or ELF layout whose size is unknown or large,
|
||||
call `analyze_javascript_application` or `inspect_binary_layout` with
|
||||
`"detail": "summary"`, then inspect the retained `parent_evidence_id` with
|
||||
`inspect_analysis_view`. Over MCP, `analyze_function` is summary-first without
|
||||
a flag: its default reply is the summary, and the complete dossier stays
|
||||
retained under `parent_evidence_id` for facet paging. Pass that ID as a
|
||||
`retained-evidence` reference to `compare_functions`, or inside
|
||||
`match_native_functions` `left_observations`/`right_observations` or
|
||||
`build_call_path.functions`; request `"detail": "complete"` only when the
|
||||
dossier must travel inline.
|
||||
Use the same exact-reference form in other advertised logical Evidence inputs,
|
||||
including optional sources, arrays and nested sources across domains. Each
|
||||
source can independently be inline or retained; preserve its source identity,
|
||||
coverage, partial facts and unknowns. A summary or inspection page has its own
|
||||
Evidence ID: use `normalized_result.parent_evidence_id` when the consumer needs
|
||||
the complete source. For portable CLI follow-ups, commands advertising
|
||||
`--evidence-bundle` resolve references from that selected exported bundle.
|
||||
See [Evidence composition](references/evidence-workflows.md) for scope and
|
||||
recovery; file selectors are supported only where explicitly advertised.
|
||||
Page module identities and select the returned `node_id` before requesting an
|
||||
item; a single file path can represent several graph roles. Do not repeat an
|
||||
identical analysis or rejected call without a changed input or resolved blocker.
|
||||
Recheck session state when a lifecycle change makes that status useful.
|
||||
Make a focused follow-up only when the
|
||||
returned result leaves a specific question unanswered.
|
||||
|
||||
If MCP reports `resource_constraint` with `details.resource: "transport"`, call
|
||||
`inspect_analysis_view` with its reported same-session Evidence reference for a
|
||||
summary, one section/module, or a stable page. Use `trace_application_feature`
|
||||
once a seed is known, or call `export_evidence_bundle` to write the complete
|
||||
session to a selected path. The analysis remains complete in the ledger; avoid
|
||||
repeating it merely to request the same oversized response. Complete CLI JSON
|
||||
output also streams without a single MCP frame.
|
||||
|
||||
When the retained parent ID is unknown, use `get_evidence_bundle` with
|
||||
`detail: "summary"` and exact filters for operation, target SHA-256,
|
||||
analysis-profile digest or canonical procedure address. Select its returned
|
||||
Evidence ID for the next view instead of requesting the complete bundle. When
|
||||
that record has no supported view (for example an annotation), read it with
|
||||
`detail: "records"` and an `evidence_id` filter; `missing_evidence_links`
|
||||
names linked sources this session does not retain.
|
||||
`retention: "complete-record"` means the whole record is stored; native
|
||||
value-flow truncation and unknown metadata remain separate. For an exported
|
||||
portable bundle, use `rea inspect-evidence-bundle` with JSON containing `path`,
|
||||
`detail: "summary"` and the same `filters`. Reading that file still requires
|
||||
validating its full contents within the local memory budget.
|
||||
|
||||
A client can also truncate a successful tool result without a REA transport
|
||||
error. Treat that preview as incomplete; use the retained parent ID for smaller
|
||||
views or export when the full record is needed. Do not parse the preview as
|
||||
canonical JSON or repeat the producer. For JavaScript, read the
|
||||
[module-view and trace recipes](references/javascript-applications.md) before
|
||||
drilling into a large graph; a broad bidirectional trace can expand unrelated
|
||||
containment relationships even after summary analysis.
|
||||
|
||||
Every conclusion must distinguish observations, inferences, and unknowns. Cite
|
||||
Evidence IDs, preserve limitations and incomplete coverage, and never imply
|
||||
that static analysis observed execution. Runtime requests execute the declared
|
||||
target and lifecycle; do not broaden the target or action beyond those fields.
|
||||
|
||||
Within the user's requested investigation, call available analysis tools
|
||||
directly. REA does not require permission grants or per-call approval flags.
|
||||
The agent client can independently require approval. Follow the declared request
|
||||
scope and the host's actual access requirements; use the recovery guide for an
|
||||
observed client-policy rejection.
|
||||
|
||||
## Plan broader investigations
|
||||
|
||||
For requests that span multiple features or subsystems, use a staged workflow:
|
||||
|
||||
1. Turn the request into a checklist of questions and the evidence each answer
|
||||
needs. Resolve target identity and constraints from the conversation and
|
||||
workspace before asking for information again.
|
||||
2. Inspect the current REA session, artifact identity, saved analysis database,
|
||||
bookmarks, and prior evidence. Reuse matching state; do not open duplicate
|
||||
sessions or repeat identical analysis.
|
||||
3. Start with the smallest useful overview or inventory. Follow each question
|
||||
from its entry point through relevant data and state changes to its result.
|
||||
Batch related operations around a specific hypothesis, then expand only when
|
||||
the returned evidence leaves a concrete gap.
|
||||
4. Inspect relevant packaged resources and configuration alongside code when
|
||||
they affect the question. Use format-aware inventory and parsers; do not
|
||||
infer behavior from filenames, strings, or layout alone.
|
||||
5. Corroborate a conclusion with the evidence type it requires. Use runtime
|
||||
observation only when static evidence cannot answer the question and the
|
||||
required host runtime and OS access are available. For JavaScript behavior,
|
||||
run probes against the actual app through the available browser, Electron,
|
||||
or process capture workflow.
|
||||
6. Decompose work into independent questions. When parallel workers are
|
||||
available and the questions do not depend on one another, assign distinct
|
||||
scopes, point workers to existing evidence, and ask them to return sources,
|
||||
conclusions, and unresolved gaps. Otherwise, work sequentially.
|
||||
7. Keep a concise finding ledger linking each conclusion to Evidence IDs,
|
||||
confidence/evidence type, search boundary, and remaining unknowns. Update
|
||||
the shared index or investigation report so later passes can reuse results.
|
||||
|
||||
Before finishing, revisit the original checklist. Mark each question as
|
||||
answered, partially answered, or unresolved based on its evidence; keep
|
||||
bounded negative searches bounded, and do not describe a broad investigation
|
||||
as complete while required questions remain open.
|
||||
|
||||
## Read only the relevant guide
|
||||
|
||||
- Native binaries, managed assemblies, archives, and extraction:
|
||||
[references/native-and-artifacts.md](references/native-and-artifacts.md)
|
||||
- ASARs, extracted JavaScript, feature tracing, and version comparison:
|
||||
[references/javascript-applications.md](references/javascript-applications.md)
|
||||
- Android APK declarations, classes, methods, and static references:
|
||||
[references/android-applications.md](references/android-applications.md)
|
||||
- Native instrumentation, debugger and process capture; browser/Electron
|
||||
observation; static/runtime comparison:
|
||||
[references/runtime-observation.md](references/runtime-observation.md)
|
||||
- Evidence paging, comparisons, residual unknowns, and verification:
|
||||
[references/evidence-workflows.md](references/evidence-workflows.md)
|
||||
- Agent environments (AgentEnv bundles) of a web application, recorded from
|
||||
a live instance or a HAR:
|
||||
[references/environments.md](references/environments.md)
|
||||
- Tasks for a desktop application's exported environment:
|
||||
[references/environments.md](references/environments.md#tasks-for-a-desktop-application-environment)
|
||||
- A desktop app environment from a request, built and witnessed on build
|
||||
computers: [references/desktop-build.md](references/desktop-build.md)
|
||||
|
||||
## Finish the task
|
||||
|
||||
Explain findings in plain language and tie them to returned evidence. When the
|
||||
user asks to build something, use normal coding tools and separate observed
|
||||
behavior from design choices. Close an opened native session with
|
||||
`close_binary` when its engine is no longer needed. Evidence references and Unknown
|
||||
history remain in memory on the same MCP connection. End the investigation with
|
||||
`reset_investigation`; supply `save_path` to checkpoint the complete bundle before
|
||||
clearing. Import the saved bundle to restore original references and Unknown
|
||||
history in a new process. Retention is bounded and is not automatic persistence.
|
||||
@@ -0,0 +1,63 @@
|
||||
# Android application artifacts
|
||||
|
||||
Use the connected server's advertised Android tools. Repository main and npm
|
||||
4.1.0 include this family. A skill installation alone cannot add it to an
|
||||
older server.
|
||||
|
||||
Start with `inspect_android_package` on the caller's APK path for package
|
||||
identity, manifest declarations, coverage, and inline Evidence. Use
|
||||
`search_android_classes` to find candidates, `inspect_android_class` for one
|
||||
class's members, `inspect_android_method` for decompilation, and
|
||||
`trace_android_references` for incoming static references. Each call takes its
|
||||
own APK path and explicit selectors; do not open a native session first.
|
||||
Choose an `overload_index` from the class inventory when methods are ambiguous
|
||||
instead of guessing.
|
||||
|
||||
For JNI implementations, discover `inspect_android_jni_bindings`. Select raw
|
||||
DEX class/method identities and optional descriptors, ABI or logical library
|
||||
paths. Prefer `detail: "summary"`; complete Evidence remains retained and
|
||||
`android-jni` views page declarations, libraries, candidates or binding rows
|
||||
with exact fields. Global native-pair ambiguity survives class selection.
|
||||
Preserve slot/relocation provenance and source coverage: matched means observed
|
||||
candidate presence; partial scans do not establish uniqueness or absence.
|
||||
This reads DEX/ELF bytes without loading the APK into the decompiler or executing
|
||||
target code. Runtime registration and loading remain unknown. See the
|
||||
[JNI guide](https://github.com/morluto/rea/blob/main/docs/guides/android/android-analysis.md#link-native-declarations-to-jni-candidates).
|
||||
|
||||
For an R8/ProGuard release build with its `mapping.txt`, pass the absolute
|
||||
`mapping_path` to `inspect_android_class` or `inspect_android_method`. Prefer
|
||||
`detail: "summary"` to receive normalized symbols or the selected body without
|
||||
duplicate raw class metadata. Complete Evidence stays retained under the linked
|
||||
parent ID and can be exported; CLI summary delivery requires `--evidence_output`.
|
||||
Omitted or complete detail preserves the full inline response. Keep
|
||||
selecting by observed names; the separate `mapping` block reports each symbol
|
||||
as `mapped`, `ambiguous` or `unmapped` after checking DEX types and prototypes.
|
||||
REA does not verify that the mapping belongs to the APK build.
|
||||
|
||||
The provider requires a separately supplied headless JADX MCP JAR 0.7.1 and
|
||||
Java 17 or newer. `REA_JADX_MCP_JAR` selects the absolute JAR path; `JAVA_HOME`
|
||||
can select Java. Use `rea doctor --provider jadx --json` to check the JADX
|
||||
configuration and obtain remediation for missing prerequisites. Java and the
|
||||
headless JADX MCP JAR remain caller-supplied; REA setup does not install or
|
||||
configure them. Configuration readiness does not establish successful analysis
|
||||
of a particular APK.
|
||||
|
||||
Linux and macOS use the POSIX owned-process boundary. Windows x64 requires the
|
||||
matching bundled native controls and uses an owned Job Object with bidirectional
|
||||
stdio. A full JDK, including `jdk.compiler`, is required on every host; Windows
|
||||
`JAVA_HOME` selects `bin\java.exe`. Consult the Android guide for actual host
|
||||
verification coverage. Calls use one worker and provider deadlines; optional
|
||||
`REA_JADX_HEAP_MIB` selects the JVM heap and `REA_JADX_OPERATION_TIMEOUT_MS`
|
||||
the per-operation deadline (integer milliseconds from 1 to 2147483647, default
|
||||
120000). To change that deadline on a running MCP server, set
|
||||
`jadx.operation_timeout_ms` through `update_analysis_settings`, then retry after
|
||||
work and cleanup settle. Newly accepted operations use the override; accepted
|
||||
work keeps its budget. Changing the launch environment requires a new process.
|
||||
The MCP client's tool timeout must also allow the selected deadline. The APK is never launched,
|
||||
and no emulator is required.
|
||||
|
||||
Manifest entries and decompiled text are static observations, not execution or
|
||||
policy enforcement. Incoming references are recovered static relationships;
|
||||
reflection, dynamic loading, and unresolved calls remain unknown. Preserve
|
||||
artifact digests, locations, diagnostics, and incomplete coverage. For archive
|
||||
members rather than code analysis, use `open_binary` and `inspect_artifact`.
|
||||
+254
@@ -0,0 +1,254 @@
|
||||
# Connection and task recovery
|
||||
|
||||
Read this guide only for an observed connection, command, approval or provider
|
||||
blocker. Keep the user's target and question in view. Explain what prevented the
|
||||
operation and the next useful step; after repair, continue the investigation.
|
||||
|
||||
Commands below use an installed `rea`. If none is available, use the package
|
||||
invocation in `SKILL.md` when acquiring REA is authorized. Follow the connected
|
||||
server's schemas and the installed CLI's help rather than assuming repository
|
||||
main and an older release expose the same arguments. Tool-name prefixes belong
|
||||
to the client: find the canonical REA operation in its actual tool listing and
|
||||
server association before concluding that it is absent. A shared prefix alone
|
||||
does not establish which server an approval wildcard covers. See
|
||||
[client tool names and discovery](https://github.com/morluto/rea/blob/main/docs/getting-started/client-configuration.md#client-tool-names-and-discovery).
|
||||
|
||||
## Choose the remedy from the observed failure
|
||||
|
||||
| Observation | Meaning and next step |
|
||||
| --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| No REA tools in the active session | If REA was installed as a client plugin, follow the plugin section below. Otherwise inspect registration with `rea doctor --client codex --json`. A skill installation alone does not register MCP. |
|
||||
| Missing, malformed or stale registration | Prepare a scoped setup plan; apply only authorized changes with backups. |
|
||||
| Aligned registration, but no connected tools | Restart/reconnect the client. Doctor checks registration; it cannot establish the current agent's connection. Inspect the client's launch error if reconnection fails. |
|
||||
| MCP connection dropped or REA could not start | If the connection drops, retry that call once only when it is safe to repeat or known not to have started. If it may already have changed the target, or the same failure returns, tell the user REA's connection failed and ask them to restart the MCP client. If REA could not start its connection, retry once, then tell the user and ask them to restart the MCP client. Do not retry a startup failure that returns the same unchanged result. Run `rea doctor` when REA could not start or tools stay missing after restart. Doctor cannot restore a live connection by itself. |
|
||||
| `MCP tool call requires approval, but approval policy is never` | Codex rejected the call before REA executed it. Do not install an engine or repeat setup to solve this client-policy decision. See the approval section below. |
|
||||
| REA returns `provider_unavailable` or an unavailable tool entry | Read that operation's provider diagnostics or `binary_session.result.tool_availability`. Expand each group's tool names and inherit the shared client requirements unless overridden. Use the operation's availability, reason, and remediation; a complete tool catalog does not imply every operation is available. Request `{"detail": "complete"}` only for provider diagnostics. |
|
||||
| `rea` is missing in a child shell, or Node is incompatible | Inspect the actual shell PATH and launcher/runtime. A prefix installation may be absent from a login shell's PATH; this does not establish a broken MCP registration. |
|
||||
|
||||
If the client cannot launch its shell/sandbox helper or read the installed skill,
|
||||
inspect its launch diagnostic. For example, Codex can refuse helper aliases when
|
||||
CODEX_HOME is under `/tmp`; use an authorized profile outside the OS temporary
|
||||
directory. REA setup cannot repair the client's executor. Preserve the sandbox
|
||||
instead of silently disabling it to make an analysis command work.
|
||||
|
||||
Static JavaScript and ordinary ZIP inventory need neither Hopper nor Ghidra.
|
||||
HAR inspection is offline and does not require a live browser. Native
|
||||
decompilation, Android analysis and firmware extraction have their own
|
||||
bring-your-own prerequisites. Use supported inventory/static evidence when it
|
||||
answers part of the question, and name the unavailable evidence separately.
|
||||
Do not substitute another target. Label observations from ordinary shell tools
|
||||
as such; only actual REA output supplies REA Evidence.
|
||||
|
||||
## Distinguish client and server deadlines
|
||||
|
||||
A host message such as `timed out awaiting tools/call` with no REA result means
|
||||
the client's deadline expired before a result arrived. It does not establish
|
||||
that REA finished, canceled successfully, or released all resources. Do not
|
||||
repeat the unchanged analysis. Inspect available session/provider state and
|
||||
retained Evidence only when useful; an idle `binary_session` is not proof that
|
||||
every target-free operation stopped. Never invent a missing Evidence reference.
|
||||
|
||||
Allow the host tool deadline to cover execution, cancellation/cleanup, and
|
||||
response delivery. In Codex, the setting is
|
||||
`mcp_servers.<server-id>.tool_timeout_sec` in **seconds**, not
|
||||
`startup_timeout_sec`. Select a value for the actual operation budget and
|
||||
headroom, not a universal timeout. See the
|
||||
[official MCP configuration reference](https://learn.chatgpt.com/docs/extend/mcp?surface=cli).
|
||||
Apply configuration changes only within the authorized scope, preserving
|
||||
unrelated entries and backups; reconnect/restart as required by the host.
|
||||
When configuration is not editable, report the setting needed or use an
|
||||
authorized CLI fallback. Do not silently broaden permissions or switch targets.
|
||||
|
||||
A returned REA `provider_timeout` instead means the **server/provider** reached
|
||||
its deadline. Follow its `remediation.action`, reuse accessible partial Evidence,
|
||||
and resolve reported incomplete cleanup before retrying. Change a request
|
||||
field or a `REA_*` setting only when the returned remediation explicitly
|
||||
recommends that change. Restart REA when that text says the value is read at
|
||||
startup. A mention that a control does not raise the deadline is not a
|
||||
recommendation to change it. Do not invent a setting the remediation does not
|
||||
name. Raising only the client deadline does not change
|
||||
this server budget. For static JavaScript,
|
||||
`analysis_timeout_ms` (CLI `rea analyze-javascript-application <path>
|
||||
--analysis-timeout-ms <milliseconds>`) controls each source's
|
||||
startup, analysis and transfer deadline in **milliseconds**. Increase that
|
||||
budget or reduce semantic work / select exact inventoried `source_paths` when
|
||||
the task permits. Omit `source_paths` for all sources; `[]` is invalid.
|
||||
`detail: "summary"` reduces delivery, not analysis work. A per-source budget
|
||||
does not bound the elapsed time for an entire multi-source application.
|
||||
Partial-Evidence inspection can avoid recomputation; an unavailable reader is
|
||||
not itself a reason to block a corrected static-analysis retry.
|
||||
The shorthand `rea analyze <path>` does not expose this timeout flag; use the
|
||||
explicit JavaScript command when changing that budget.
|
||||
|
||||
For invalid arguments, use the connected tool's current input schema, or the
|
||||
installed CLI's command help. Refresh the catalog if stale; do not guess fields
|
||||
from an older skill or return the entire catalog to repair one field. Correct
|
||||
all reported fields before retrying.
|
||||
|
||||
## Recovery ladder
|
||||
|
||||
Follow the returned remediation. Change a request field or a `REA_*` setting
|
||||
only when that text explicitly recommends the change. Restart REA when it says
|
||||
the value is read at startup. A mention that a control does not raise a limit
|
||||
is not a recommendation to change it. Do not invent a setting. Host memory and
|
||||
`NODE_OPTIONS` do not raise a REA admission unless that remediation says so.
|
||||
|
||||
- MCP connection dropped: retry that call once only when it is safe to repeat
|
||||
or known not to have started. If it may already have changed the target, or
|
||||
it fails again, tell the user REA's connection failed and ask them to restart
|
||||
the MCP client. Do not run `rea doctor` for the drop itself.
|
||||
- REA could not start its connection: retry once, then tell the user and ask
|
||||
them to restart the MCP client. Run `rea doctor` when REA could not start or
|
||||
tools stay missing after that restart. Do not retry a startup failure that
|
||||
returns the same unchanged result.
|
||||
- `cleanup_incomplete`, or retained cleanup owners in the error details: retry
|
||||
that exact cleanup owner. Do not start new work that needs those resources
|
||||
until that owner confirms release. Repeating the original call is not that
|
||||
retry.
|
||||
- Capacity, when the result is `resource_constraint` and `retryable` is true:
|
||||
wait for the active admission to finish, then retry within the reported
|
||||
limits. Do not restart REA to free the slot.
|
||||
- `configuration_invalid`: when the error reports `update_mode: "runtime"`,
|
||||
call `update_analysis_settings` for that setting. When it reports
|
||||
`update_mode: "parameter"`, change that call's argument; the setter does not
|
||||
accept it. Otherwise correct the named setting in the environment that starts
|
||||
REA (the shell or the MCP registration) and start REA again. Run `rea doctor`
|
||||
to see the `runtime-configuration:` check. Re-run `rea setup` for that client
|
||||
when the registration must carry the new setting, then reconnect.
|
||||
- `invalid_request`: correct the reported fields from the current schema. Do
|
||||
not repeat the unchanged call.
|
||||
|
||||
## REA installed as a client plugin
|
||||
|
||||
A Claude Code, Codex, or Cursor Marketplace plugin owns its `rea` server and
|
||||
this skill. Doctor's `--client` and `--skill` checks and `rea setup` read and
|
||||
write only setup-owned state, so for a plugin-only install they report
|
||||
`missing`, and applying setup would add a second `rea` server. If this skill
|
||||
was loaded from a plugin, or the client lists a `rea` plugin, do not prepare a
|
||||
setup plan for missing tools. Instead:
|
||||
|
||||
- Check that the plugin is installed and enabled with the client's own
|
||||
listing: `claude plugin list` and `/mcp` in Claude Code, `codex plugin list`
|
||||
in Codex, and Cursor's plugin settings for a Marketplace install.
|
||||
- Restart or reconnect the client, then read its launch error for the `rea`
|
||||
server if tools are still absent. Claude Code and Codex start the plugin's
|
||||
bundled runtime; a missing build or version mismatch requires a reinstall,
|
||||
or a fresh build when developing from source. A Cursor Marketplace install
|
||||
starts `npx` at the version pinned in the plugin's `mcp.json`. A failed
|
||||
download needs network access to that published version.
|
||||
- Check analysis engines through the connected server's
|
||||
`binary_session.result.tool_availability`. `rea doctor --provider <id> --json`
|
||||
from a shell reports that shell's environment, which can differ from the
|
||||
environment the client gave the plugin server. If you still run it through
|
||||
the package runner, use the version pinned in the plugin manifest's server
|
||||
entry (`rea-agents@<version>`), not `@latest`, so it matches the server the
|
||||
plugin starts.
|
||||
|
||||
Use the setup repair below only when the user wants a setup-owned registration
|
||||
instead of the plugin, and remove or disable the plugin first.
|
||||
|
||||
## Repair registration when needed
|
||||
|
||||
For Codex:
|
||||
|
||||
```bash
|
||||
rea doctor --client codex --json
|
||||
rea setup --client codex --dry-run --json
|
||||
```
|
||||
|
||||
Use the current supported client's ID: `claude_code`, `claude_desktop`, `codex`,
|
||||
`cursor`, `gemini_cli`, `windsurf`, `devin`, `opencode`, `antigravity`,
|
||||
`copilot_cli`, `commandcode`, `qwen_code`, `vscode`, `trae`, `grok_build`, `omp`, `pi`,
|
||||
`hermes`, `qoder`, `droid`, `zcode`, `dsh`, `freebuff`, or `grok_bot`. If unknown, inspect `doctor --json` before choosing a
|
||||
scope. `grok_bot` uses a chat registration step rather than local `mcp.json`.
|
||||
For unsupported clients, use manual stdio registration with the selected
|
||||
installation’s absolute runtime and entry script, or continue through the CLI.
|
||||
Acquire packages from a trusted directory outside the target project. Keep a
|
||||
package-runner installation and its runtime available while registrations use it.
|
||||
|
||||
Show the plan's exact paths, backups, changes and bundled-skill replacement.
|
||||
Obtain approval for writes when that concrete scope is not already authorized,
|
||||
then apply the same scope with `rea setup --client codex --yes`. Add
|
||||
`--install-hopper` only when separately needed and explicitly approved. Do not
|
||||
install or upgrade unrelated prerequisites. Restart/reconnect, verify tools
|
||||
actually appear, and resume the original task. If they remain absent, inspect
|
||||
the launch failure rather than looping through setup.
|
||||
|
||||
## Codex tool approval is separate from REA readiness
|
||||
|
||||
REA tools have no permission-grant handshake. Codex can still require approval
|
||||
because an operation creates owned resources, launches a helper or has cleanup
|
||||
effects. An advertised tool or successful doctor result does not override that
|
||||
client policy. `workspace-write` alone does not resolve an MCP approval
|
||||
rejection, and `approval_policy = "never"` does not mean every MCP tool is
|
||||
preapproved.
|
||||
|
||||
When interactive approval is available, use the client's approval flow for the
|
||||
requested operation. In an unattended run, continue through an authorized CLI
|
||||
workflow if the execution environment permits it, or report the blocked
|
||||
operation and the approval needed to proceed. Do not retry the same rejected
|
||||
call, silently broaden approvals, or rewrite MCP effects as read-only.
|
||||
|
||||
For an operator who explicitly wants to preapprove named operations in a
|
||||
disposable Codex profile, current Codex supports per-tool configuration. For
|
||||
example, opening and closing an analysis session can be scoped independently:
|
||||
|
||||
```toml
|
||||
[mcp_servers.rea.tools.open_binary]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.rea.tools.close_binary]
|
||||
approval_mode = "approve"
|
||||
```
|
||||
|
||||
Use the actual server ID and only the operations whose effects were approved;
|
||||
this example does not approve inspection, extraction or runtime execution.
|
||||
Show the proposed config edit and preserve unrelated entries and backups before
|
||||
writing. Managed policy can constrain client settings. Consult the
|
||||
[Codex configuration reference](https://learn.chatgpt.com/docs/config-file/config-reference)
|
||||
for the installed client's supported settings. This is an optional recovery
|
||||
choice, not a prerequisite for every REA task.
|
||||
|
||||
## Repair an editable REA limit
|
||||
|
||||
If `details.limit` names an editable setting and its bounds, call
|
||||
`update_analysis_settings` directly with a `changes` entry containing `setting`,
|
||||
`action: "set"` and `value`. `inspect_analysis_settings` is optional when those
|
||||
facts are already present. Retry the same input after work and cleanup settle.
|
||||
Runtime defaults affect new work only; explicit per-call arguments take
|
||||
precedence and must be corrected directly when selected. Reset restores launch
|
||||
values. Updates survive target close/open but disappear on REA restart. They do
|
||||
not edit host deadlines, response buffers, registrations or fixed limits.
|
||||
|
||||
## Continue through an installed CLI
|
||||
|
||||
Check the command environment only if the launcher fails:
|
||||
|
||||
```bash
|
||||
command -v rea
|
||||
command -v node
|
||||
node --version
|
||||
rea --version
|
||||
```
|
||||
|
||||
Use the public launcher at its known installation path with a supported existing
|
||||
Node on PATH when the child shell loses a prefix installation. Avoid internal
|
||||
`dist/cli.js` entrypoints or global toolchain changes. MCP may have its own valid
|
||||
launcher even when a shell cannot resolve `rea`.
|
||||
|
||||
For a user-supplied JavaScript tree or ASAR, select output files in the authorized
|
||||
workspace and save complete Evidence before reading a view:
|
||||
|
||||
```bash
|
||||
rea analyze-javascript-application /absolute/path/to/app --json > app-evidence.json
|
||||
jq -c '{source: {kind: "inline", evidence: .}, view: {kind: "summary"}}' app-evidence.json > app-view.json
|
||||
rea inspect-analysis-view app-view.json
|
||||
```
|
||||
|
||||
These commands do not register MCP or install an analysis engine. CLI JavaScript
|
||||
JSON is complete and can be very large; redirect it rather than loading it into
|
||||
context. Use an existing JSON processor if `jq` is absent, without installing
|
||||
one just for this recipe. Inspect a module page or item using the same inline
|
||||
source and the [JavaScript recipes](javascript-applications.md). Preserve graph
|
||||
coverage, limitations and unknowns. Native CLI analysis still requires its
|
||||
selected engine, and all CLI operations retain the host's execution permissions.
|
||||
@@ -0,0 +1,860 @@
|
||||
# Desktop app environments from a request
|
||||
|
||||
Use this when someone asks for an environment of a Linux desktop app with a
|
||||
task, such as "Build me an Inkscape environment where the agent changes a
|
||||
poster's headline and saves it". You are the building agent: you drive the
|
||||
app on a build computer through REA's MCP tools, write the task, export the
|
||||
bundle and witness it in a fresh computer. REA runs no model. The tools are
|
||||
MCP-only and need a Linux host with Docker, agentenv and REA's packed
|
||||
runtime. When a start reports one missing, tell the person to run
|
||||
`rea doctor --provider desktop_build` and apply its fixes, or
|
||||
`rea setup --client <client> --desktop-build` and restart the client, and
|
||||
stop.
|
||||
|
||||
For the whole build:
|
||||
|
||||
- Drive the app only with `act_on_build_computer`. Never script it, run
|
||||
commands in the computer or write its files another way. The one command
|
||||
you write for the computer is a task's reader, which REA runs to check a
|
||||
file; it never makes the seed or the edit.
|
||||
- Ask the upfront questions once, then work on your own. Pause only when
|
||||
blocked.
|
||||
- The seed's content is synthetic. Never put real personal data in it.
|
||||
- Close every computer you start, on success and on failure.
|
||||
- Note the time you start; the report gives the build time.
|
||||
|
||||
## Ask once, upfront
|
||||
|
||||
In one message, ask only what the request leaves open, and keep the list for
|
||||
the report. Skip each question the request answers; when it answers them all,
|
||||
start without asking:
|
||||
|
||||
1. The app and the task, if either is unclear: what changes, in which
|
||||
document.
|
||||
2. Whether they have a starting file of their own; otherwise you make one.
|
||||
3. Whether they want the tasks measured after the witness: with which
|
||||
model, within which budget, and whether to harden a task until it lands
|
||||
in the band.
|
||||
4. If so, whether they want to review the tasks before those solves.
|
||||
|
||||
When you cannot ask, as in a headless `claude -p` run, do not stop: take
|
||||
these defaults for whatever the request leaves open, say which you took in
|
||||
your first message and in the report, and go on. Install from the Ubuntu
|
||||
archive, make a synthetic seed, skip the review, and measure each task
|
||||
within $4 in all, with the model the request names, without hardening.
|
||||
|
||||
## When you are blocked
|
||||
|
||||
Stop, say what you need and wait only for:
|
||||
|
||||
- a licence the app or its installer asks someone to accept: never accept it
|
||||
on your own; name it and where to read it, and go on only once the person
|
||||
says they accept it. Then record their words with `record_build_consent`,
|
||||
kind `licence`, and accept it on their behalf;
|
||||
- credentials: ask the person to write each secret, and nothing else, in a
|
||||
file named after a handle you choose, such as `keepassxc-master`, in
|
||||
`~/.config/rea/build-secrets/` on this host (under `$XDG_CONFIG_HOME` when
|
||||
it is set), readable only by them (`chmod 600`), and wait until they say it
|
||||
is there; then type it with `type_secret` (see Drive the app). Never ask
|
||||
for a password or key in chat, and never read, list or print that folder;
|
||||
- a signed-in state in the seed: by default the export withholds it (see
|
||||
Sign-in and licence state). Seed it only when the person says the bundle
|
||||
may hold it: record their words with `record_build_consent`, kind
|
||||
`seed_sign_in`, and export with `seed_sign_in: true`;
|
||||
- an install this flow cannot do, below.
|
||||
|
||||
Decide everything else yourself and note it in the report.
|
||||
|
||||
## Sign-in and licence state
|
||||
|
||||
What an app writes when someone signs in or activates a licence is withheld
|
||||
from the seed: the bundle's receiver supplies their own. Mark
|
||||
`pre-sign-in` with `mark_build_checkpoint` just before the sign-in or
|
||||
activation and `post-sign-in` just after, both before `seed`: every file
|
||||
under the owned paths that changed between them is withheld, and the draft
|
||||
leaves it out. A file the app writes at first launch, such as a trial's
|
||||
licence file, changes before you can mark anything: name it in
|
||||
`export_build_environment`'s `withhold`. The export lists each withheld file
|
||||
in `withheld_files` with the environment variable a deploy reads it from and
|
||||
the handle of the secret REA keeps its bytes in; a check may not name one.
|
||||
The export refuses a seed file holding a withheld file's exact bytes, such as
|
||||
a `.bak` copy, but a backup that differs from it is not caught: trash backups
|
||||
before `seed`.
|
||||
Explicitly withhold any other files the person identifies as sensitive;
|
||||
REA does not infer secrecy from a value's shape or a file name.
|
||||
|
||||
## Choose the install
|
||||
|
||||
The computer is Ubuntu 24.04 (noble) on this host's architecture only. Use
|
||||
the first source that has the app:
|
||||
|
||||
| Source | `install` |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------- |
|
||||
| Ubuntu archive | `{"kind": "archive", "package": "inkscape"}` |
|
||||
| PPA or vendor apt repository | `{"kind": "apt_repository", "package", "uri", "suite", "components", "key_file"}` |
|
||||
| `.deb` by URL | `{"kind": "package_file", "url", "sha256", "architecture", "dependencies"}` |
|
||||
| AppImage by URL | `{"kind": "appimage", "url", "sha256", "architecture", "extra_packages"}` |
|
||||
| Tarball by URL | `{"kind": "tarball", "url", "sha256", "architecture", "program", "name", "extra_packages"}` |
|
||||
|
||||
- A PPA's `uri` is `https://ppa.launchpadcontent.net/OWNER/NAME/ubuntu`,
|
||||
`suite` `noble`, `components` `["main"]`. `key_file` is the repository's
|
||||
signing key saved on this host; for a PPA, fetch it from
|
||||
keyserver.ubuntu.com by the fingerprint its Launchpad page shows.
|
||||
- When the app exits at launch for want of a runtime piece its package does
|
||||
not install, start a new build computer with that package in
|
||||
`extra_packages`, up to 16 archive names; the export installs them too.
|
||||
MyPaint needs
|
||||
`{"kind": "archive", "package": "mypaint", "extra_packages": ["librsvg2-common"]}`
|
||||
for its SVG icons, and Freeplane `["openjdk-17-jre"]`, since its launcher
|
||||
refuses noble's Java 21. Name one up front, too, when a package the app
|
||||
only recommends holds its content, such as QElectroTech's element library
|
||||
`qelectrotech-data`, without which no component can be placed.
|
||||
- Take the `.deb` path only when the app is not in the archive at all, not
|
||||
to add a package. Ask the requester for its URL and SHA-256; do not fetch
|
||||
a vendor's download page yourself. List its `Depends` as `dependencies`,
|
||||
with any runtime piece it lacks: it installs with the network off.
|
||||
- Take an AppImage or a tarball only when no package has the app. Pin it by
|
||||
the release file's URL for this host's architecture and the SHA-256 its
|
||||
project publishes, such as a GitHub release asset's digest or the
|
||||
release's `SHA256SUMS`; ask the requester when the project publishes none.
|
||||
The computer downloads it when the bundle is put, refuses other bytes, and
|
||||
unpacks it under `/opt/rea-apps/<desktop_entry>` with the network off; the
|
||||
export downloads the same file.
|
||||
- An AppImage installs its own desktop entry, so `desktop_entry` is the
|
||||
`.desktop` file at the top of the image, such as FreeCAD's
|
||||
`org.freecad.FreeCAD`. A wrong name fails the start with the entries the
|
||||
image has: start again with one of them. The image brings its libraries,
|
||||
so `extra_packages` is rarely needed; FreeCAD 1.1.4's needs none.
|
||||
- A tarball has no entry of its own. `program` is the program's path inside
|
||||
the archive, such as `firefox/firefox`; REA writes an entry named
|
||||
`desktop_entry` that runs it with the files it opens, and `name` is what
|
||||
the Applications menu shows. A tarball uses the computer's libraries: name
|
||||
what its program lacks in `extra_packages`. gzip, bzip2 and xz archives
|
||||
are read, zstd ones are not.
|
||||
- Flatpak and snaps are not supported: say so and stop. Flatpak's sandbox
|
||||
needs user namespaces the computer's container does not grant, so a
|
||||
Flathub app installs but never opens; ask for the project's AppImage,
|
||||
tarball or `.deb` when it ships one. An archive package that only installs
|
||||
a snap, such as noble's `firefox`, counts as a snap. A package with no
|
||||
build for this host's architecture (some PPAs are amd64 only) cannot be
|
||||
installed either.
|
||||
- `desktop_entry` is the package's `.desktop` file name under
|
||||
`/usr/share/applications` without `.desktop`, such as
|
||||
`org.inkscape.Inkscape`. Add `window_class` when you know it; Inkscape's
|
||||
is `Inkscape`. AbiWord's entry is `abiword` and its class `Abiword`.
|
||||
- To find the entry, read the package's file list: its page on
|
||||
packages.ubuntu.com, or `apt-get download PKG && dpkg -c PKG_*.deb` where
|
||||
apt runs. The entry may ship in a companion `-data` or `-common` package,
|
||||
as Planner's in `planner-data`: read that package's list too. The entry's `StartupWMClass` may not be the window's real
|
||||
class, so do not take `window_class` from it: MuseScore 3's says
|
||||
`mscore3`, its window's is `MuseScore3`. The export uses the class the
|
||||
capture saw.
|
||||
|
||||
## Drive the app
|
||||
|
||||
- Pass `computer_id` and the action's fields at the top level: click
|
||||
`{x, y, count}`, scroll `{x, y, direction, amount}`, a screenshot region
|
||||
`[x0, y0, x1, y1]`. The rest are in
|
||||
[the build-computer guide](https://github.com/morluto/rea/blob/main/docs/desktop-build-computer.md).
|
||||
- Take a `screenshot` before pointing: points are pixels of the latest
|
||||
frame. If a response is too large, ask for a `region`, or `jpeg` with a
|
||||
lower `quality`. A screenshot with `region` does not capture the screen
|
||||
again; it crops the latest frame, so take a full screenshot, or a `wait`
|
||||
with `screenshot: true`, first. The crop then becomes the latest frame:
|
||||
take a full screenshot before pointing again.
|
||||
- A drawn caret does not prove keyboard focus. After using a toolbar
|
||||
control, click into the document, then type a few characters and look
|
||||
before a long text.
|
||||
- Confirm a dialog with `key` Return, not a trailing `\n` in `type`.
|
||||
- An action's own screenshot is taken at once. After opening a menu, a
|
||||
dialog or a window, look with
|
||||
`{"action": "wait", "ms": 500, "screenshot": true}`.
|
||||
- On a computer started from a request the app is not open at first, and
|
||||
`start_build_capture` opens it: never open it yourself before that. Do not
|
||||
close it while capturing; the capture ends when the app exits. When the
|
||||
app is closed at any other time, open it from Applications → Other → the
|
||||
environment's name.
|
||||
- Type a secret with `{"action": "type_secret", "secret": "<handle>"}`,
|
||||
only into a field that masks what is typed: check in a screenshot that it
|
||||
is a password field, which shows dots. A screenshot shows any field that
|
||||
shows its text, such as many licence-key boxes, so never type a secret into
|
||||
one: say the app needs a secret the build cannot type unseen, and stop.
|
||||
`type_secret` takes no `screenshot`; look with a `wait` after it. A refusal
|
||||
names the secret's file and what is wrong with it: tell the person, never
|
||||
the value.
|
||||
- Prefer shortcuts and typing to long pointer paths: `key` takes `keys`, an
|
||||
array holding one chord's keys, such as
|
||||
`{"action": "key", "keys": ["Control", "s"]}`, and `type` turns `\n` into
|
||||
Enter.
|
||||
- Before `type`, check in a screenshot that a text cursor or a focused
|
||||
field is there. In apps with single-key shortcuts, such as Inkscape, text
|
||||
typed without one runs as commands.
|
||||
- Save As differs by app. Check the dialog's current folder first: most
|
||||
open in the home, so click Documents in the sidebar, but Scribus opens in
|
||||
`~/Documents` and its sidebar has no Documents entry. Type only the file
|
||||
name. A dialog taller than the 1280×800 screen hides its buttons:
|
||||
maximize it from its title bar, or confirm it with `key` Return, as when
|
||||
HomeBank's Save button is off-screen. When a GTK Save dialog ignores
|
||||
clicks or runs off the screen, type `~/Documents/<name>` in its Name field
|
||||
and press Return.
|
||||
- Answer the app's save questions, such as keeping the format, then check
|
||||
the saved path in the title or status bar, or the dialog's folder when
|
||||
the app shows only the name, and that it shows no unsaved mark, before
|
||||
you mark a checkpoint or check. Where the title never shows one, as in
|
||||
HomeBank, a greyed Save or Revert, or the file reopened from recent
|
||||
files, confirms the save.
|
||||
- Qt spin boxes change their value on scroll: move the pointer off them
|
||||
before you scroll.
|
||||
- gLabels edits an object's text in Object properties → Text, not on the
|
||||
canvas.
|
||||
- In Grisbi's transaction form Return moves to the next field; only Return
|
||||
in the last field, Notes, records the transaction.
|
||||
- ghostwriter autosaves a new document as `~/Documents/untitled-1.md`: name
|
||||
it with File → Rename, not Save As; Ctrl+Shift+S does nothing, and Enter
|
||||
after a checklist item starts another `- [ ]` item.
|
||||
- KMyMoney's first launch opens the New File Setup wizard; Finish asks for a
|
||||
storage type (XML), then a Save As where typing `Documents/<name>.kmy`
|
||||
works. Its date field is a sectioned Qt editor: double-click the month and
|
||||
type each part, since Ctrl+A garbles it. A new transaction's payee comes
|
||||
prefilled and selected. Amounts are saved as reduced fractions, such as
|
||||
`-1749/20`, so compare them exactly. Untick Help → Tip of the Day → "Show
|
||||
tips on startup" before `seed`, or the tip appears at every boot.
|
||||
- QElectroTech: an element dropped from Collections follows the pointer until
|
||||
a click on the folio places it. Its title shows only the app, so it needs
|
||||
`state_paths`; its settings are in `~/.qet`.
|
||||
- Rosegarden: after a dialog its Transport window can take keyboard focus,
|
||||
so save with File → Save.
|
||||
- Pencil2D: the Tools dock is too narrow for its buttons, so use shortcuts
|
||||
(B for the brush); double-click a layer's name to rename it.
|
||||
- Umbrello: the title shows no unsaved mark, so confirm a save with a probe
|
||||
checkpoint. An Untitled document autosaves `~/autosave.xmi`: delete it
|
||||
before `seed`. Add attributes from the tree: right-click the class → New →
|
||||
Attribute.
|
||||
- Hydrogen: the computer has no audio device, so Hydrogen falls back to a
|
||||
null driver and its BPM field snaps back to 120 within about 100 ms.
|
||||
Before `seed`, set Preferences → Audio System → ALSA with device `null`
|
||||
and click "Apply and restart output", which `~/.hydrogen/hydrogen.conf`
|
||||
keeps for the seed; also set autosaves per hour to 0, and dismiss the
|
||||
development-version dialog with "Don't show again". `pulseaudio` as an
|
||||
extra package does not help.
|
||||
- Poedit cannot add entries by hand. Use File → New, pick the language and
|
||||
save to `Documents` first (Sources Paths stays locked until then), then
|
||||
Properties → Sources Paths → + → Add Files with a source such as
|
||||
`/usr/lib/python3.12/argparse.py`. It writes `fr.mo` beside the `.po`, and
|
||||
the language box's autocomplete popup takes the first OK click.
|
||||
- CherryTree: its first-run autosave "Choose Storage Type" dialog swallows
|
||||
keys, so save once early as `.ctd` and untick autosave.
|
||||
- VSCodium (its tarball, with `extra_packages: ["libnss3",
|
||||
"libasound2t64"]`) runs on outside REA's reach, so `stop_build_capture`
|
||||
fails to clean it up: after `end`, quit it with Ctrl+Q, then stop. Enter
|
||||
accepts its word suggestions, so press Escape after typing a line.
|
||||
- Glade: a new widget's id is empty until you set it, and a second save
|
||||
writes a `.glade~` backup, which shows in the draft as an unrelated
|
||||
change. A backup present at `seed` is seeded with the document, so trash
|
||||
it before `seed`. The draft names a button's `<child>` by the id
|
||||
its widget carries, `[name=child][>object@id=submit_button]`, which moving
|
||||
the button keeps; give the widget an id before `seed` so it can.
|
||||
- VYM: the title never names the map, so pass `Documents/<map>.vym` in
|
||||
`state_paths`. Its settings live in `.config/InSilmaril` and are written
|
||||
only at a clean exit. It writes `<map>.vym.lock` while a map is open, so
|
||||
close the map before `seed`. Press A only after clicking a branch on the
|
||||
canvas: keys typed in the tree editor run other shortcuts.
|
||||
- KmPlot: Create → Cartesian Plot, then edit the formula in the Function
|
||||
tab and press Return. It stores minus as U+2212 (`−`). Its file:// title
|
||||
still names the file.
|
||||
- RedNotebook keeps each month in `~/.rednotebook/data/YYYY-MM.txt`, YAML
|
||||
read as text, folded at about column 80: pick check phrases the fold keeps
|
||||
on one line.
|
||||
- Qt5 apps saving with QDom, such as KmPlot, write attributes in a random
|
||||
order in each process, so check their XML by element, never by whole line.
|
||||
- Gnumeric's desktop entry is `org.gnumeric.gnumeric`. Its Save As dialog
|
||||
runs off the 1280×800 screen: type `~/Documents/<name>` in Name and press
|
||||
Return. Rename a sheet with right-click on its tab, then Rename….
|
||||
- Parley's title shows the collection's title, so name the file in
|
||||
`state_paths`. File → New opens the new collection's Properties dialog:
|
||||
confirm it with OK, since Cancel keeps the old collection and its autosave
|
||||
lock open. A new collection starts with 15 blank entries: delete them.
|
||||
Pick languages from the dropdown; a typed name keeps the previous locale.
|
||||
While a document is open KDE keeps an autosave and its `.lock` in
|
||||
`~/.local/share/stalefiles/parley/`, and there is no File → Close: before
|
||||
`seed`, use File → New, then reopen the collection from Open Recent.
|
||||
- Sigil: pass `extra_packages: ["libqt5svg5"]`, or its SVG toolbar icons are
|
||||
blank. Its title names the book, so it needs no `state_paths`. It unpacks
|
||||
the open book into `.local/share/sigil-ebook/sigil/workspace/Sigil-XXXXXX/`
|
||||
and deletes it on exit, so never name the whole `sigil-ebook` folder: that
|
||||
seeds the stale copy.
|
||||
- What the app saved under the home before `seed`, such as a document in
|
||||
`~/Documents` or its settings, is part of the seed. A file you move to the
|
||||
Trash is left out, and the export lists it in `limitations`. Trash a stray
|
||||
file rather than starting over. JabRef 3.8 writes `<file>.bak` and
|
||||
`<file>.sav` beside a `.bib` it saves; in the owned folder they are seeded
|
||||
and show in the draft as noise, so trash them before `seed` if they should
|
||||
not ship.
|
||||
- Dismiss first-run dialogs, such as a welcome screen, before `seed`. A
|
||||
choice the app saves only later, such as Inkscape's "show this every
|
||||
time", may not reach the seed, so expect the dialog in the witness too.
|
||||
- Some apps write their settings late: Freeplane writes
|
||||
`~/.config/freeplane/1.7.x/auto.properties` only once Preferences is
|
||||
confirmed, and a seed without it reopens its documentation map. Before
|
||||
`seed`, open the app's preferences and confirm them, then read a probe
|
||||
checkpoint's `changed_files` to see the settings file written.
|
||||
- Before `seed`, click into the document to clear any selection the app
|
||||
would save: Gnote saves its cursor and selection with the note.
|
||||
- An app whose state folder is named after it, such as
|
||||
`~/.local/share/gnote`, or after it and its version, such as TreeLine's
|
||||
`~/.treeline-3.1`, is found without `state_paths`.
|
||||
- TreeLine: File → New opens a template window. Book List's CATEGORY makes
|
||||
AUTHOR children by default; change it under Data → Configure Data Types →
|
||||
Default Child Type. A new child opens an inline rename showing "", so
|
||||
press Escape and fill its fields in the Data Edit tab. Ctrl+A adds a child
|
||||
node even while a field has focus. Clicking a node already selected starts
|
||||
an inline rename, so Ctrl+X then cuts its text: cut a node from its
|
||||
context menu. It saves nodes sorted by their
|
||||
generated uid1, so their order changes from run to run. The draft names a
|
||||
new node by its format and a field of its `data`,
|
||||
`/nodes/[format=BOOK][>data~1Title=The Silk Roads]`, and checks its other
|
||||
fields through that, so give each new node a title no other node has.
|
||||
- After an app crashes, capture again on a fresh computer, so the seed
|
||||
carries no crash-recovery state, such as MyPaint's "Recover interrupted
|
||||
work?".
|
||||
- Give what the task changes a stable name where the app has one, such as an
|
||||
id in Inkscape's Object Properties, so a check can select it.
|
||||
- Expect apps to split text into runs: Writer's revision ids split an
|
||||
edited paragraph into spans and may give it an automatic style such as
|
||||
`P1`, and AbiWord wraps each insertion in `<c>`. Check such text whole
|
||||
with `text_equals` (see Write the task), and find the paragraph by
|
||||
something the edit keeps, such as AbiWord's `xid`.
|
||||
- Freeplane's first launch opens a documentation map: close it with Ctrl+W.
|
||||
Its Ctrl+N asks for a template.
|
||||
- MyPaint 2.0.1 crashes on brush strokes on the build computer: build its
|
||||
seed with flood fill and layer operations.
|
||||
- GnuCash's Ctrl+S on a new book opens a Save dialog with no format choice:
|
||||
use File > Save As to pick XML. Close the book (File > New File) before
|
||||
`seed`, so its `.LCK` lock is not seeded.
|
||||
|
||||
## Build the seed and the edit
|
||||
|
||||
1. `start_build_computer` with
|
||||
`{"source": {"kind": "request", "desktop_entry": ..., "install": ...}}`.
|
||||
The first start of an app builds its image, and starts at the same time
|
||||
on this host wait for each other; either can take minutes. A failed
|
||||
start returns the build's error: fix the request, or stop when the
|
||||
install cannot work, and close any `computer_id` the error names.
|
||||
2. `start_build_capture`. It returns once the app's window is open. A
|
||||
`package_lists_error` may stop the capture finding the package's
|
||||
sources; the export says when that matters. When the app exits before
|
||||
its window opens, the error gives its exit code and the end of its
|
||||
stderr, which may name what it lacks, such as an icon loader or a Java
|
||||
runtime: close the computer and start a new one with that package in
|
||||
`extra_packages` (see Choose the install), or stop as for an install
|
||||
this flow cannot do.
|
||||
- REA counts a file as the app's document only when the app's window
|
||||
title shows its file name or `~/` path. When the title shows something
|
||||
else, such as MuseScore's score title, pass the path you will save the
|
||||
document at in `state_paths`, relative to the home:
|
||||
`{"computer_id": ..., "state_paths": ["Documents/MuseScore3/Scores/Morning_Song.mscz"]}`.
|
||||
It need not exist yet. Add the app's settings folder when its name
|
||||
differs from the app's, such as `.config/MuseScore`, so the seed keeps
|
||||
the dismissed first-run dialogs. Do not pass the document as a launch
|
||||
argument to make REA see it: `state_paths` is the way. gLabels' title
|
||||
leaves out the file's extension and Grisbi's shows the entity's name,
|
||||
so both need it.
|
||||
- An app whose document is a folder of pages, such as a Zim notebook
|
||||
(`Notebooks/Notes`, a `.txt` file per page), never shows a file in its
|
||||
title: pass the folder in `state_paths`. Every page in it is then a
|
||||
document, so the bundle opens none at launch and the app starts where
|
||||
it keeps its place; check the page the task changes.
|
||||
3. Make the seed through the app and save it from the app under
|
||||
`~/Documents`: build the document in the app, or write its source where
|
||||
the app edits its format as text, then save it again from the app. Make
|
||||
it look real but synthetic: the thing the task changes, plus a few things
|
||||
the change must leave alone. Keep it to one document: the bundle's app
|
||||
opens the seed's document at launch only when there is exactly one, and
|
||||
otherwise starts on its own screen. For a starting file of the requester's,
|
||||
read it here and rebuild it in the app with synthetic data in place of
|
||||
personal data; REA cannot copy a file into the computer.
|
||||
- An app that keeps its own data and saves after every change, such as
|
||||
Osmo's contacts in `~/.local/share/osmo/contacts_records.xml`, has no
|
||||
document: that state is the seed. Build it in the app and mark `seed`
|
||||
once the app has written. To see whether it has, mark a throwaway
|
||||
checkpoint, such as `probe-1`, and read its `changed_files`: up to ten
|
||||
files that changed since the checkpoint before, those a window title
|
||||
named first, then those under `state_paths` and those the app held
|
||||
open, caches last, with `more_changed_files` counting the rest.
|
||||
- The app's own compressed format works when it is gzip, such as
|
||||
Gnumeric's `.gnumeric`, Dia's `.dia` or Inkscape's `.svgz`: REA reads
|
||||
the document inside, and checks point into it as into the same
|
||||
document uncompressed. Compression may be off by default: Dia's
|
||||
"Compress diagram files" is unticked, which REA reads as plain XML. A format REA reads as binary, such as one
|
||||
compressed with xz, has no view: save in a format the app offers that
|
||||
REA reads, then reopen the file once and check that a plain Ctrl+S
|
||||
keeps that format. When the task is about the app's own binary
|
||||
format, such as GIMP's `.xcf` or Blender's `.blend`, keep it and check
|
||||
it through a reader (see Read a binary file with a reader).
|
||||
4. Only once the seed is saved, `mark_build_checkpoint` with name `seed`.
|
||||
5. Make the change the task asks for, as a user would, and save it.
|
||||
6. Only once the change is saved, `mark_build_checkpoint` with name `end`.
|
||||
For more tasks in this environment, make each next task's change on top
|
||||
of the last as a user would, save it, and mark `end-<task name>`, such as
|
||||
`end-add-bread`. Each task is checked at its own end, so its checks must
|
||||
not read what a later task changes, and a solving agent starts each from
|
||||
the seed, so a task must not need an earlier one done first.
|
||||
Then, for each task you can, make a near miss of its change on top, a
|
||||
plausible wrong edit such as a typo or a wrong number, save it and mark
|
||||
`near-<task name>`: the export refuses a task whose near miss passes every
|
||||
check. Take the near misses after the last end, since each later draft
|
||||
starts from the end before it.
|
||||
7. `stop_build_capture`. Read `draft.files` (each file that changed, with
|
||||
its net change and its `values`), `draft.task.checks` (suggested
|
||||
checks), `draft.guards`, `draft.notes` and `limitations`; each
|
||||
`later_drafts` entry is the same for one later task, from the end
|
||||
checkpoint before its own, so it shows only that task's change. When
|
||||
`draft` is null, read `draft_refusal` first: a missing `seed` or `end`
|
||||
checkpoint means capturing again on a new build computer, while a failed
|
||||
draft command names its own cause to fix. If a declared secret was used,
|
||||
automatic drafting is withheld: write the task manually and export it.
|
||||
When `draft.files` is empty,
|
||||
`draft.notes` says why:
|
||||
- `no_change`: nothing was saved between `seed` and `end`. Capture again
|
||||
on a new build computer, and save before marking `end`. When the app
|
||||
keeps the task's state only on screen, such as a calculator's result,
|
||||
judge the screen instead (see Judge the screen).
|
||||
- `unowned_changes` with `no_document`: the app saved your document
|
||||
where REA did not count it as the app's. Its `files` list what changed,
|
||||
with their roles; the document is among them. Close the computer and
|
||||
capture again on a new one with that path in `state_paths`; the export
|
||||
refuses a check on a file outside the owned paths.
|
||||
- `uncheckable_changes`: the app saved the change in dconf, as gedit does
|
||||
its preferences, and no check reads dconf. Saving again does not help:
|
||||
choose a change the app saves in a file, and capture again on a new
|
||||
build computer, or judge the screen (see Judge the screen).
|
||||
- `unreadable_changes`: a dconf database changed but REA could not read
|
||||
it; `error` says why. This is not evidence the app saved there: report
|
||||
the error rather than changing the task.
|
||||
|
||||
A note with a `file` says why that file's suggestions are thin:
|
||||
- `by_position`: only position names what changed; its `elements` lack
|
||||
a naming attribute. Name a record that keeps its fields as child
|
||||
elements by one of them, as Osmo's contact by
|
||||
`[name=contact][>first_name=Delphine]`, a JSON record by a field
|
||||
inside it, `[>data/Title=…]` (`~1` for the `/` inside a pointer), or
|
||||
an element by an id its child carries, `[>object@id=…]`; count records
|
||||
with `member_count`, `matching` `[name=contact]`; otherwise check an
|
||||
ancestor's text, or give the element an id in the app and capture again.
|
||||
- `view_state_only`: every change is view state, a renumbered id or a
|
||||
time the app stamps, and its `pointers` are the checks kept. The edit
|
||||
was likely not saved: capture again and save it before `end`.
|
||||
- `long_text`: the element's text is too long to check whole; check a
|
||||
phrase in it with `text_contains`.
|
||||
- `cut_view` or `unreadable_view`: REA's view holds only part of the
|
||||
file, or none a check can read, such as a binary format (step 3). For
|
||||
a binary file, read it with a reader (see Read a binary file with a
|
||||
reader).
|
||||
|
||||
## Write the task
|
||||
|
||||
Write `{"name", "prompt", "checks"}` from the draft and what you did, one
|
||||
per task, each with its own name.
|
||||
|
||||
- `name`: lowercase letters, digits and hyphens, not `smoke`.
|
||||
- `prompt`: what the requester wants, in their words and the app's terms,
|
||||
starting with the app's name, naming the document as a user would and
|
||||
ending with saving it: "In Inkscape, change the poster's headline in
|
||||
Documents/poster.svg to Summer Bake Sale and save it." Name the app: the
|
||||
solving agent's own shell cannot see the computer's files, and the app's
|
||||
name sends it to the screen. Leave saving out for an app that saves on its own, after every change
|
||||
or a few seconds after the last one, such as Osmo or Gnote: grading waits
|
||||
until the app's files have held for 3 s, so the solving agent need not
|
||||
wait for the save. A save more than 3 s after the agent stops is still
|
||||
missed; name such an app in the report. Never say how the file stores it,
|
||||
and never give the checks.
|
||||
- Checks are file-based: content checks that prove the edit, never only that
|
||||
a file exists or changed. Start from the suggestions; keep those that say
|
||||
what the user did and drop what follows from how the app saves.
|
||||
- Compare exact values, so a typo or a wrong number fails.
|
||||
- Read each file's `values` before writing checks: every value the change
|
||||
added, changed and removed, with `before` and `after` (an uncut scalar, or
|
||||
a preview cut at 600 characters) at the pointer a check names it by. Copy
|
||||
the pointer. Copy `after` into `value` only when it is an uncut scalar: a
|
||||
string without a trailing `…`, a number, or a boolean. Compact XML and a
|
||||
JSON array or object are preview strings, so a `value_equals` check needs
|
||||
the structured value from the file's view, and element text uses
|
||||
`text_equals` or `text_contains`.
|
||||
Only XML files, archives, JSON and key files have values: a text file's
|
||||
or SQLite database's `change` already lists its lines and rows.
|
||||
`refers_to` says what a number or id stands for, such as `category="44"`
|
||||
naming `<cat key="44" name="Groceries"/>`, or a new KMyMoney
|
||||
transaction's splits naming their account and payee; use it for the
|
||||
prompt's words. `alternatives` gives a changed value's pointer by the
|
||||
element's other names, such as a label beside an id, to pick another key
|
||||
without another export.
|
||||
Skip entries whose `note` is `by_position` (no check can use that
|
||||
pointer) or noise (`view_state`, `renumbered`, `volatile`,
|
||||
`timestamp`, `upkeep`, `layout`). `values_cut` means a limit left some out.
|
||||
- Select elements by what they hold, never by position: SVG text by id,
|
||||
`/root/children/[name=g][@inkscape:label=Layer 1]/children/[name=text][@id=headline]/children/[name=tspan]/children/0`,
|
||||
or an ODF paragraph by style,
|
||||
`/entries/[name=content.xml]/view/root/children/[name=office:body]/children/[name=office:text]/children/[name=text:p][@text:style-name=Title]/children/0`.
|
||||
A selector must match exactly one element, so give the target a unique id
|
||||
or style in the seed. The draft's pointers already do this: a name-like
|
||||
attribute such as Scribus's `ANNAME` before a coordinate, and two
|
||||
attributes together where one is not enough, as a spreadsheet cell's
|
||||
`[@Col=3][@Row=2]`. Only an element's text is read by position, as
|
||||
`children/0`.
|
||||
- When an app may split an element's text into runs, check it whole:
|
||||
`text_equals` (or `text_contains` for a value inside a sentence) on the
|
||||
element compares all its text, however it is split. Add
|
||||
`normalize_whitespace: true` when the app may reflow spaces. Example, an
|
||||
AbiWord paragraph by its stable id:
|
||||
`{"kind": "text_contains", "file": "Documents/memo.abw", "pointer": "/root/children/[name=section]/children/[name=p][@xid=6]", "value": "at 3:30 PM"}`.
|
||||
Point a text check at the paragraph or another element the edit keeps,
|
||||
never at a run such as AbiWord's `[name=c]`: a reopened document splits
|
||||
the text into several runs. The draft lists only what changed; an
|
||||
unchanged element is in `draft.guards` when it is a like sibling of a
|
||||
changed one, and otherwise use the app's usual numbering, such as another
|
||||
paragraph's `xid`, and let the export confirm it.
|
||||
- In an ODS spreadsheet no attribute names a row: the draft names it by its
|
||||
label cell, `[name=table:table-row][>table:table-cell=February]`. Where no
|
||||
cell names it alone, name the sheet in the seed, and check its whole
|
||||
text: `text_equals` on
|
||||
`/entries/[name=content.xml]/view/root/children/[name=office:body]/children/[name=office:spreadsheet]/children/[name=table:table][@table:name=Q1 Sales]`,
|
||||
or a stretch of it with `text_contains`. Cell texts join with nothing
|
||||
between, so a row reads `February23100`.
|
||||
- For a line added to free text, such as an item on a note's list, the
|
||||
draft compares the whole text with `text_equals`. This rejects longer or
|
||||
negated items, but can reject a correct edit with different ordering or
|
||||
spacing. Report that limitation when the task permits such variations.
|
||||
- For a note placed by its own `x` and `y`, such as Xournal++'s `<text>`
|
||||
on a layer, the draft checks its text on the layer with `text_contains`,
|
||||
which passes wherever the user puts it, and guards each note it kept.
|
||||
- Some apps keep text in an attribute, one element per run, such as
|
||||
Scribus's `<ITEXT CH=...>`: add `"text_attribute": "CH"` to `text_equals`
|
||||
or `text_contains` on the frame,
|
||||
`/root/children/[name=DOCUMENT]/children/[name=PAGEOBJECT][@ANNAME=Headline]`,
|
||||
to read its runs' values joined.
|
||||
- When the draft shows no values or no checks, a scratch export can expose
|
||||
`envs/<env>/seed/` only after the task has at least one valid check: it must
|
||||
pass on the captured end state and fail on the seed. Before the first
|
||||
successful export, use `act_on_build_computer` to open the saved file in an
|
||||
available GUI text editor or viewer and inspect its actual representation
|
||||
without changing it. Use the visible saved content and the task's edit to
|
||||
write a check; an export refusal can also name the end state's value, such
|
||||
as `is "44", not "1"`. If the file cannot be inspected or expressed by a
|
||||
supported check, report the limitation instead of guessing a check.
|
||||
- Where easy, add one check that the rest is untouched, such as another
|
||||
text's value the edit must leave alone. `draft.guards` offers them at
|
||||
their seed values, which the end holds too: a field on the nearest like
|
||||
siblings, one the user sets, such as Planner's `work`, before a default
|
||||
they all share; the text an addition kept; a text file's lines beside its
|
||||
new one. Copy one or two into `checks`; they pass on the seed, which is
|
||||
fine, since the export needs only one check to fail there.
|
||||
- The draft suggests a decimal the app writes as text, such as `146.83`,
|
||||
as a number with `tolerance: 0.001`; keep the tolerance for any number
|
||||
you check that way.
|
||||
- When the draft shows an XML document's changes as `lines`, REA read it
|
||||
as text, for example because its DOCTYPE declares entities. Selectors are
|
||||
impossible there, and `line_count` with `contains` only approximates a
|
||||
value: `3:30` also matches `13:30`. Bound it with neighbouring text and
|
||||
name the check as approximate in the report's limitations.
|
||||
- Some apps save a document reloaded from disk differently from one typed
|
||||
in the same session: AbiWord wraps each new insertion in its own markup.
|
||||
Your build's end state hides this, which is why whole-text checks matter;
|
||||
expect the witness to show the real format.
|
||||
|
||||
The kinds and pointer rules are in
|
||||
[the desktop tasks section](environments.md#pick-the-checks).
|
||||
|
||||
### Read a binary file with a reader
|
||||
|
||||
When the draft notes `unreadable_view` on a binary document, add a reader to
|
||||
the task: the app's own headless command, which REA runs in the computer on a
|
||||
private copy of the file, and whose output a check reads instead of the file.
|
||||
Write it in the app's scripting mode, print each fact on a line starting
|
||||
with `REA ` (with the space), and name the copy `{file}`:
|
||||
|
||||
- GIMP `.xcf`, layer names, as `lines`:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "layers",
|
||||
"file": "Documents/poster.xcf",
|
||||
"argv": ["gimp-console-2.10", "-i", "-d", "-f", "-b", "-"],
|
||||
"stdin": "(let ((image (car (gimp-file-load RUN-NONINTERACTIVE \"{file}\" \"{file}\")))) (for-each (lambda (layer) (display \"\\nREA layer \") (display (car (gimp-item-get-name layer)))) (vector->list (cadr (gimp-image-get-layers image)))) (newline))\n(gimp-quit 0)\n",
|
||||
"output": "lines"
|
||||
}
|
||||
```
|
||||
|
||||
checked with `{"kind": "lines_present", "file": "Documents/poster.xcf", "reader": "layers", "lines": ["layer Summer Sale"]}`.
|
||||
Script-Fu's prompt `ts> ` starts a line, so print a newline before each
|
||||
marked line, as `\nREA` does. A text layer's text is
|
||||
`(car (gimp-text-layer-get-text layer))`.
|
||||
|
||||
- Blender `.blend`, objects with their type and location, as `json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "objects",
|
||||
"file": "Documents/scene.blend",
|
||||
"argv": [
|
||||
"blender",
|
||||
"-b",
|
||||
"--factory-startup",
|
||||
"{file}",
|
||||
"--python-expr",
|
||||
"import bpy, json; print('REA ' + json.dumps({o.name: {'type': o.type, 'location': [round(v, 4) for v in o.location]} for o in bpy.data.objects}, sort_keys=True))"
|
||||
],
|
||||
"output": "json"
|
||||
}
|
||||
```
|
||||
|
||||
checked with `{"kind": "value_equals", "file": "Documents/scene.blend", "reader": "objects", "pointer": "/Crate/location/0", "value": 2, "tolerance": 0.001}`.
|
||||
Print every value a check compares as a number or string a check can
|
||||
name, rounded where the app stores floats.
|
||||
Blender 4 shows its Quick Setup splash at every launch until its
|
||||
preferences are saved: with `.config/blender` in `state_paths`, confirm
|
||||
Quick Setup with Continue, save the preferences (Edit → Preferences, then
|
||||
Save Preferences in the menu at its bottom left), and read a probe
|
||||
checkpoint's `changed_files` for `.config/blender/4.0/config/userpref.blend`
|
||||
before `seed`, so solves start on the scene. Blender often takes the first click on a
|
||||
menu or a dialog's button only to focus it: click again.
|
||||
|
||||
- A format LibreOffice opens but REA cannot read, such as a legacy `.xls`,
|
||||
converted with `--convert-to`:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "cells",
|
||||
"file": "Documents/budget.xls",
|
||||
"argv": [
|
||||
"sh",
|
||||
"-c",
|
||||
"soffice --headless --convert-to csv --outdir out \"$1\" >/dev/null && sed 's/^/REA /' out/*.csv",
|
||||
"sh",
|
||||
"{file}"
|
||||
],
|
||||
"output": "lines",
|
||||
"timeout_s": 120
|
||||
}
|
||||
```
|
||||
|
||||
Pass `{file}` to `sh -c` as an argument, as here, rather than inside the
|
||||
script.
|
||||
|
||||
The reader runs without the display, in a fresh home with the app's default
|
||||
settings, so use the app's headless or batch mode; set `display: true` only
|
||||
for an app that has none. It must exit 0 within `timeout_s` (60 s by
|
||||
default, at most 300) and print at most 1 MiB. Pick facts the change sets and
|
||||
the near miss gets wrong, such as a name or a number, not the app's whole
|
||||
output.
|
||||
|
||||
Give the task the reader in `readers`, and each check through it `reader`
|
||||
and the reader's `file`. `json` readers serve `value_equals`, `value_absent`
|
||||
and `member_count`; `lines` readers `lines_present`, `lines_absent` and
|
||||
`line_count`. The export runs the reader in the build computer on the seed
|
||||
and the end: when a check through it fails on the end, the refusal shows
|
||||
what the reader printed, and a reader that fails shows its error and the end
|
||||
of its stderr. Fix the reader or the check from that and export again.
|
||||
|
||||
### Judge the screen
|
||||
|
||||
Only when no file shows the change, as when the draft notes `no_change`
|
||||
because the app keeps its state on screen, write the task's checks as
|
||||
screen judges: `{"id": "shown", "kind": "screen_judge", "question": "Does the
|
||||
calculator's display show 8.568?"}`. A model, the judge, answers the question
|
||||
on a screenshot three times, and the check passes when most answers are yes.
|
||||
|
||||
- REA keeps a screenshot at each checkpoint. Mark `seed` with the screen
|
||||
showing the state before the task, where the answer is no, and `end` with
|
||||
the change showing, where it is yes: the bundle ships both as the judge's
|
||||
examples.
|
||||
- Ask about what the change makes visible, with exact values, so the near
|
||||
miss is a no: a result, a label, a selected item. Avoid what a window
|
||||
moved or a cursor blinking can change.
|
||||
- The prompt asks to leave the result showing, since the judge sees only
|
||||
the screen when the agent stops.
|
||||
- A task with screen judges holds only screen judges and no readers. The
|
||||
export refuses one when a file shows the change, and checks none of its
|
||||
questions: the witness does, running the bundle's own judge with the
|
||||
runner's model endpoint (`LITELLM_BASE_URL` and `LITELLM_API_KEY`, or
|
||||
`[model]` in `.agentenv/config.toml`) on a fresh screenshot at each stage.
|
||||
Without an endpoint the witness's check fails: say what to set and stop.
|
||||
- The judge's model is `[model.roles] judge`, else `[model] default`, else
|
||||
`anthropic/claude-sonnet-5-5`. `agent-env run --judge-model` does not
|
||||
reach it. Each grade costs about $0.02.
|
||||
|
||||
## Export
|
||||
|
||||
`export_build_environment` with `tasks` and `directory`, the absolute path of
|
||||
a new or empty folder here, such as `<home>/rea-builds/poster/bundle`. Each
|
||||
entry of `tasks` is `{"task": ..., "end_checkpoint": ...}`: leave
|
||||
`end_checkpoint` out for the task checked at `end`, and give
|
||||
`end-<task name>` for each later one. The
|
||||
export seeds what was saved at `seed`, replaces the computer's host name,
|
||||
`user@host` and home path (a bare user name, such as AbiWord's author
|
||||
`user`, stays), and checks each task against `seed`, its own end and its
|
||||
`near-<task name>` when you took one. It refuses a task
|
||||
unless at least one check fails on the seed, every check passes at its
|
||||
end and one fails at its near miss, and says which task and why, such as a
|
||||
pointer that names nothing at the end. A
|
||||
check that the rest is untouched passes on the seed too, which is fine. On
|
||||
a refusal, fix the task and export again, into another folder if that one
|
||||
is no longer empty. The bundle's eval lists every task, so a run of the
|
||||
bundle runs them all. A refusal naming a secret's handle means a file of the
|
||||
bundle holds that secret, most often an app's sign-in or licence state in
|
||||
the seed: do not work around it, but report it and stop. Keep
|
||||
`seed_files`, `scrubbed_files`, `unscrubbed_files` and `limitations` for the
|
||||
report.
|
||||
|
||||
The limitations name the folders the app wrote that the bundle neither owns
|
||||
nor seeds, such as `~/.config/MuseScore`, so the app starts without them:
|
||||
expect its first-run wizard, a tour or a "restore session?" question at every
|
||||
boot. If the witness shows one, capture again on a new build computer with
|
||||
those folders in `state_paths`, and dismiss the dialogs before `seed`. Lock
|
||||
files the app holds while it runs, such as LibreOffice's `.lock` and
|
||||
`.~lock.<name>#`, GnuCash's `<book>.LCK` or Grisbi's `.<file>.lock`, are
|
||||
left out of the seed and listed after "Left out of the seed". An app can
|
||||
still start fine yet refuse every save when a lock was seeded, so close the
|
||||
document before `seed` where the app lets you (apps other than LibreOffice,
|
||||
such as Rosegarden, also write `.~lock.<name>#` and autosaves beside a
|
||||
document, and closing it covers them too), and treat "file is locked"
|
||||
on a save in the witness as a seeded lock: delete it from the bundle's seed
|
||||
and witness again in a new computer. In LibreOffice, own the profile
|
||||
(`state_paths: [".config/libreoffice"]`) for a clean boot, and close the
|
||||
document before `seed`, then reopen it from Recent Documents to make the
|
||||
change: the export also leaves out the recovery list LibreOffice writes while
|
||||
a document is open, which would start the bundle into document recovery. A
|
||||
limitation naming `~/.config/dconf/user` as unread means the app's dconf
|
||||
settings, such as a first-run tip you turned off, are not seeded: capture
|
||||
again on a new build computer. The limitations also name seeded WebKit,
|
||||
Chromium or QtWebEngine storage and caches; when the witness's boot is clean,
|
||||
list them in the report.
|
||||
|
||||
Keep the build computer open until the witness holds: a task fix exports
|
||||
again from it.
|
||||
|
||||
## Witness
|
||||
|
||||
Witness each task in its own fresh computer of the bundle, from the prompt,
|
||||
as a solving agent would; a computer is witnessed once, so the steps below
|
||||
repeat for each task, each with its own record folder. Do not replay the build's actions or coordinates, and do not
|
||||
check between stages to steer the edit: a solving agent never sees the
|
||||
checks. Give every `check_build_task` the task exactly as exported.
|
||||
|
||||
1. `start_build_computer` with
|
||||
`{"source": {"kind": "bundle", "path": "<bundle>"}}`, adding
|
||||
`"settings": {"<variable>": "<handle>"}` for each of the export's
|
||||
`withheld_files`, or the deploy is refused for want of them, and agentenv
|
||||
keeps that bundle's build failed, so start from a fresh copy of it. The app starts
|
||||
with the seed's files in place and opens the seed's document when the
|
||||
seed holds exactly one and the app takes a file. When the export's
|
||||
`limitations` say it opens no document, open it from the prompt's path,
|
||||
as a solving agent would. Take a `wait` screenshot first, since the
|
||||
desktop may not have drawn yet. When the start fails because the
|
||||
computer never got ready, and its error names lock files in the bundle's
|
||||
seed, delete them from the bundle and start again.
|
||||
2. `check_build_task` with `stage: "seed"` and `directory`, the absolute
|
||||
path of a new or empty folder for the record. A check must fail.
|
||||
Recording starts. Later stages take no `directory`.
|
||||
3. Do the task from the prompt with `act_on_build_computer` and save.
|
||||
`check_build_task` with `stage: "after_edit"`: every check must pass.
|
||||
Each check waits until the app's files have held for 3 s, as the
|
||||
bundle's verifier does, so an app that saves on its own needs no wait of
|
||||
yours. A result with `settled: false` means the files were still
|
||||
changing at the 15 s bound, and `read_cut: true` that a slow read was
|
||||
still running there.
|
||||
4. Make a near miss on top of it: a plausible wrong edit, such as a typo or
|
||||
a wrong number, and save. `check_build_task` with `stage: "near_miss"`:
|
||||
a check must fail.
|
||||
5. `act_on_build_computer` with `action: "reset"`, then `check_build_task`
|
||||
with `stage: "after_reset"`: a check must fail again.
|
||||
6. The last stage ends the witness: `witness.record` has the verdict, the
|
||||
path of `witness.json` and the recording's segments in `directory`.
|
||||
`close_build_computer` on the witness computer.
|
||||
|
||||
A stage that does not hold ends the witness as `failed`. Read each check's
|
||||
result and decide:
|
||||
|
||||
- `after_edit` failed though the saved file is right: the check is brittle.
|
||||
Fix it, export again and witness in a new computer.
|
||||
- `after_edit` failed because your edit was wrong: witness again in a new
|
||||
computer; a computer is witnessed once.
|
||||
- `near_miss` passed: the checks are too loose. Tighten them, export again
|
||||
and witness again.
|
||||
- `after_reset` passed: the reset did not restore the seed. Report it as a
|
||||
limitation.
|
||||
|
||||
Stop after three witnesses of a task and report what still fails.
|
||||
|
||||
## Measure
|
||||
|
||||
Only if the requester asked for it, or by the headless default above. If
|
||||
they wanted to review the tasks first, show them each prompt and checks and
|
||||
wait for their approval. Then `measure_build_task` each task with `bundle`,
|
||||
`task`, `model` and `budget_usd`, its share of the budget. It runs the task
|
||||
in fresh computers, 3 times, then 2 more unless they passed none or all, and
|
||||
keeps a task that passes 1 to 3 of 5 (`band: "in_band"`). It stops before a
|
||||
solve the largest cost so far would take past the budget, and writes the
|
||||
record into the bundle's `difficulty.json` and README. The solver needs a
|
||||
model endpoint where REA starts: `LITELLM_BASE_URL` and `LITELLM_API_KEY`, or
|
||||
`base_url` and `api_key` under `[model]` in `.agentenv/config.toml`; when the
|
||||
measure says a solve did not run for want of one, tell the person what to
|
||||
set and stop. Read the result's `failures_per_check` and each solve's
|
||||
`failed_checks` before calling a task hard: a check that fails in most failed
|
||||
solves while the app shows the right change is brittle, so fix the check,
|
||||
export and witness again, rather than count it as difficulty.
|
||||
|
||||
## Harder tasks
|
||||
|
||||
When the requester wants tasks worth evaluating or training on, harden a
|
||||
task that came out `too_easy` and measure it again, within the budget. The
|
||||
solver sees and fixes its slips on screen, so one edit with the value in the
|
||||
prompt is solved almost every time; so far, on TreeLine with Sonnet 5.5, so
|
||||
were one more dialog, a conditional move of seven records, and ten
|
||||
corrections read from a second document and applied across the list. Try,
|
||||
one at a time, measuring each:
|
||||
|
||||
- A longer chain of exact edits than that, each a value the checks compare
|
||||
whole, so one slip in the chain fails the task.
|
||||
- Facts read in one view and used in another: values the solver must read
|
||||
from a second document the app opens, or from another record, rather than
|
||||
from the prompt, such as "the same year as The Quiet Glacier's".
|
||||
- Distractors beside each target: records with near-identical names or
|
||||
values, and a guard check on each that it stays as it was.
|
||||
- Mistakes that do not show once saved: a value the app displays rounded or
|
||||
formatted unlike what it stores, or an edit the app keeps only when its
|
||||
field loses focus.
|
||||
|
||||
Stop when the budget left cannot cover 3 solves of the hardened task, and
|
||||
report the bands measured.
|
||||
|
||||
Each hardened task stays sound: its checks still fail on the seed and pass on
|
||||
its end, its near miss fails, and another valid way of doing it passes, so
|
||||
check values, never the order or method the solver used. Put the second
|
||||
document in the seed. Count records with `member_count` and check each
|
||||
value by a selector that names its record, since no check joins two records.
|
||||
|
||||
## Close and report
|
||||
|
||||
`close_build_computer` on every computer still open, also after a failure.
|
||||
If a close fails, call it again; if it still fails, tell the requester what
|
||||
is left.
|
||||
|
||||
Report:
|
||||
|
||||
- the bundle path and the environment name;
|
||||
- each task's name, prompt and end checkpoint;
|
||||
- each check, and why it proves the edit and fails the near miss, and each
|
||||
reader's command;
|
||||
- each task's witness stages with their results, the verdict, and the paths of
|
||||
`witness.json` and the recording;
|
||||
- the seed's contents: `seed_files` and what each holds;
|
||||
- `scrubbed_files` and `unscrubbed_files`; an unscrubbed file still names
|
||||
the host or user, so it needs review before sharing. `recompressed_files`
|
||||
are gzip seeds whose headers were cleared, their content unchanged: give
|
||||
their count;
|
||||
- limitations: the capture's, the export's and anything you could not do;
|
||||
- each measured task's band, passes of finished solves, turns, cost and
|
||||
failures per check, from `difficulty.json`;
|
||||
- the build time and the questions you asked.
|
||||
|
||||
Never publish or share the bundle yourself.
|
||||
@@ -0,0 +1,399 @@
|
||||
# Agent environments from a live application
|
||||
|
||||
Use this when the user asks for an agent environment (an AgentEnv bundle) of a
|
||||
web application: a folder `agent-env` deploys, whose MCP tools answer from what
|
||||
one recording of the application observed and serve the writes that recording
|
||||
confirmed. The workflow records the application once with
|
||||
`capture_browser_scenario`, checks what the environment would serve, records
|
||||
again if a hint names a gap, then writes the bundle with
|
||||
`export_environment_bundle`. For a HAR the user already has, skip to
|
||||
[export](#export-and-hand-off) through `inspect_web_network_capture`, or use
|
||||
`rea environment-build <capture.har> <dir>`. For a task in a desktop
|
||||
application's exported environment, read
|
||||
[its section](#tasks-for-a-desktop-application-environment).
|
||||
|
||||
## Before recording
|
||||
|
||||
- Record only against an instance the user says is disposable or seeded for
|
||||
this purpose: every write step creates, edits or deletes its data. If the
|
||||
user has not said so, ask before any scenario that writes. REA does not
|
||||
start, seed or reset applications.
|
||||
- Credentials come from environment variables the user names. Declare each as a
|
||||
scenario secret, `{secret_id, environment_variable}`; the variable must be set
|
||||
in the environment REA's MCP server started with. Never ask for a password in
|
||||
chat. Declared secrets are redacted as the capture records.
|
||||
- Map the application first with `inspect_web_page` (and `capture_web_screenshot`
|
||||
when layout matters): the login form's locators, and the API calls behind the
|
||||
pages that list and edit the entities the user asked about.
|
||||
- `inspect_web_page` cannot sign in. To see pages behind sign-in, run a short
|
||||
`capture_browser_scenario` that signs in and opens them, with
|
||||
`"capture": {"after_each_step": ["accessibility"]}` (`"dom"` for markup).
|
||||
Read a step's tree with `inspect_analysis_view`, `view: {kind:
|
||||
"browser-scenario", collection: "text", step_index, artifact:
|
||||
"accessibility", offset: 0, limit: 2048}`, paging with `offset`. Capture
|
||||
options are only `after_each_step`, `at_end`, `events`, `network` and
|
||||
`limits`.
|
||||
|
||||
## Record a session an environment can learn writes from
|
||||
|
||||
One `capture_browser_scenario` records the whole session. Start from this
|
||||
shape, with the application's own locators, paths and headers:
|
||||
|
||||
```json
|
||||
{
|
||||
"browser": { "mode": "launch", "executable_path": "/usr/bin/chromium" },
|
||||
"start_url": { "url": "http://127.0.0.1:3000/login" },
|
||||
"secrets": [
|
||||
{ "secret_id": "admin_password", "environment_variable": "APP_PASSWORD" }
|
||||
],
|
||||
"capture": {
|
||||
"network": {
|
||||
"request_body": true,
|
||||
"response_body": true,
|
||||
"header_values": true
|
||||
}
|
||||
},
|
||||
"actions": [
|
||||
{
|
||||
"step_id": "user",
|
||||
"action": "fill",
|
||||
"timeout_ms": 15000,
|
||||
"locator": { "kind": "css", "selector": "input[name=username]" },
|
||||
"value": { "source": "literal", "value": "admin" }
|
||||
},
|
||||
{
|
||||
"step_id": "password",
|
||||
"action": "fill",
|
||||
"timeout_ms": 15000,
|
||||
"locator": { "kind": "css", "selector": "input[name=password]" },
|
||||
"value": { "source": "secret", "secret_id": "admin_password" }
|
||||
},
|
||||
{
|
||||
"step_id": "sign-in",
|
||||
"action": "press",
|
||||
"timeout_ms": 15000,
|
||||
"locator": { "kind": "css", "selector": "input[name=password]" },
|
||||
"key": "Enter"
|
||||
},
|
||||
{
|
||||
"step_id": "signed-in",
|
||||
"action": "wait_for",
|
||||
"timeout_ms": 15000,
|
||||
"locator": { "kind": "css", "selector": "nav a[href='/settings']" },
|
||||
"state": "visible"
|
||||
},
|
||||
{
|
||||
"step_id": "folders-1",
|
||||
"action": "request",
|
||||
"timeout_ms": 15000,
|
||||
"method": "GET",
|
||||
"path": "/api/folders",
|
||||
"expected_status": [200]
|
||||
},
|
||||
{
|
||||
"step_id": "new-folder-1",
|
||||
"action": "click",
|
||||
"timeout_ms": 15000,
|
||||
"locator": { "kind": "role", "role": "button", "name": "New folder" }
|
||||
},
|
||||
{
|
||||
"step_id": "folder-title-1",
|
||||
"action": "fill",
|
||||
"timeout_ms": 15000,
|
||||
"locator": { "kind": "css", "selector": "input[name=title]" },
|
||||
"value": { "source": "literal", "value": "Scratch folder 1" }
|
||||
},
|
||||
{
|
||||
"step_id": "create-folder-1",
|
||||
"action": "click",
|
||||
"timeout_ms": 15000,
|
||||
"locator": { "kind": "role", "role": "button", "name": "Create" },
|
||||
"save_response": {
|
||||
"method": "POST",
|
||||
"path": "/api/folders",
|
||||
"save": [{ "name": "folder_1", "json_pointer": "/id" }]
|
||||
}
|
||||
},
|
||||
{
|
||||
"step_id": "read-folder-1",
|
||||
"action": "request",
|
||||
"timeout_ms": 15000,
|
||||
"method": "GET",
|
||||
"path": "/api/folders/{saved:folder_1}",
|
||||
"expected_status": [200]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Give each step that accepts `timeout_ms` a deadline. Without one, a step waits
|
||||
until it completes or the scenario is cancelled, so a locator that never
|
||||
matches hangs the capture and the client with it. The `wait_for_timeout` pause
|
||||
instead uses `duration_ms` and does not accept `timeout_ms`. Match `wait_for`
|
||||
locators to exactly one element.
|
||||
|
||||
1. Sign in through the UI: `fill` the user and password fields (the password
|
||||
as a secret reference), submit, then `wait_for` an element only a signed-in
|
||||
user sees.
|
||||
2. Read with `request` steps: each collection the environment needs, twice
|
||||
before any write, so fields that change on their own show up; then each
|
||||
object a list shows by id, up to ten per collection. An object known only
|
||||
from a list that leaves out fields its own read shows cannot be read by id
|
||||
or updated in the environment.
|
||||
3. Write the way the application's UI does: fill its forms and click its
|
||||
buttons, so each request carries the fields the UI sends, including ones
|
||||
the server would otherwise derive. Give the click or key press that submits
|
||||
a create `save_response` to keep the new object's ID, then `goto` its page
|
||||
(`/items/{saved:item_1}`) or read it with a `request` step. Never guess an
|
||||
ID, and never create a probe object to learn the next one. Write with
|
||||
`request` steps instead only when the UI cannot reach the operation (an
|
||||
API-only resource, or a UI that does not call the JSON API), or when coverage
|
||||
withholds the UI-shaped write as `unexplained-change` or `contradicted`;
|
||||
that counts as one of the two re-recordings. A `request` step write that
|
||||
coverage withholds that way usually lacks fields the UI sends: record it
|
||||
through the UI instead. If a journey cannot be scripted, leave the write
|
||||
unserved and report the limitation.
|
||||
Record two numbered scratch objects per write type,
|
||||
with varied free text. After each write, and before the next one, read the
|
||||
object back by id and then its list: create 1, read 1, list, create 2,
|
||||
read 2, list; never several writes before their reads.
|
||||
4. Leave more than a second between two creates and between a create and its
|
||||
first edit (`wait_for_timeout` with `duration_ms: 1100`), so lists sorted
|
||||
by creation time show them in order.
|
||||
5. Update both objects and read each back, changing the fields a person
|
||||
would change (a name, an email address, a status, a due date) rather than
|
||||
only a description: a served update accepts only the members a recorded
|
||||
update stored. Run an action that turns something on or off (star,
|
||||
bookmark, archive) twice in a row on one object, reading it back after
|
||||
each: the second call shows whether it sets or flips the field, and the
|
||||
environment serves the action only once a call has shown it. Delete both
|
||||
and read each back (expect 404, or the object marked deleted) and the list.
|
||||
6. Vary what the two creates send, however you write them: the first every
|
||||
field the application takes, the second only what a person must give (its
|
||||
title or name), with the other fields left out or empty. A served create
|
||||
requires each member both creates filled in and lets a caller leave out one
|
||||
a create left out or sent empty, so an agent that names only a title is not
|
||||
refused for fields it had no reason to set.
|
||||
|
||||
About `request` steps:
|
||||
|
||||
- `path` is on the start URL's origin; the page must be on that origin.
|
||||
- Header values are literals, declared secrets, a cookie the browser holds
|
||||
(`{source: "cookie", name}`), a local storage entry
|
||||
(`{source: "local_storage", key, json_pointer}`), a saved value
|
||||
(`{source: "saved", name}`), or Basic credentials
|
||||
(`{source: "basic_credentials", parts: [username, password]}`, sent as the
|
||||
base64 of `username:password` and redacted), with an optional `prefix` such as
|
||||
`"Bearer "` or `"Basic "`. Each credential part is a literal, secret, saved
|
||||
value, cookie or local storage entry, so a header the frontend builds from a
|
||||
login token (the username and the token) can be copied too; the password is
|
||||
a secret or saved value, never a literal. Copy the
|
||||
headers the application's own requests send (a CSRF header such as
|
||||
`X-CSRFToken` from the `csrftoken` cookie, a bearer token). Values read from the page are redacted from records made after they
|
||||
are read, not from the login response that returned them, and values
|
||||
shorter than 8 characters are not redacted at all.
|
||||
- `save: [{name, json_pointer, secret}]` keeps a string or number from the
|
||||
step's JSON response, such as the created object's `/id`, for later steps;
|
||||
`secret: true` redacts it, as for a token the API returns, so mark every
|
||||
saved token, key or session value secret. This also protects the selected
|
||||
source response before its body or headers are retained. Compressed or
|
||||
unknown-size UI responses cannot supply saved values. On a `click` or `press`,
|
||||
`save_response: {method, path, save}` keeps values from the response to the
|
||||
new request observed while the step waits (`{*}` in `path` matches one segment).
|
||||
Matching does not prove UI causality: choose a path distinct from polling;
|
||||
multiple observed matches fail as ambiguous. The step
|
||||
fails unless a 2xx JSON response arrives before its `timeout_ms`. Later
|
||||
steps send a saved value as `{saved:name}` in a request `path` (and its
|
||||
query) or a `goto` URL; in the `json` body, where a string that is only
|
||||
`{saved:name}` keeps the saved JSON type; or as `{source: "saved", name}` in
|
||||
a header or credential part.
|
||||
- Reading a page value makes later bodies costlier to keep: after a CSRF
|
||||
token, bodies over about 47 KiB are kept as `unavailable`. When the API
|
||||
returns larger responses, raise `capture.limits`
|
||||
(`max_network_body_allocation_bytes`, `max_total_event_allocation_bytes`).
|
||||
- Request steps follow no redirects: a redirect fails the step, and
|
||||
`expected_status` cannot name a 3xx status. Use the path the redirect names,
|
||||
such as the one with the trailing slash.
|
||||
- Set `expected_status` on every step, so a refused call fails its step and
|
||||
the later steps report not having run, instead of recording read-backs of
|
||||
nothing.
|
||||
|
||||
Keep it to about 60 to 160 requests. A scenario with no `request` step is
|
||||
recorded exactly as before.
|
||||
|
||||
The capture returns its whole Evidence, every recorded body included, which is
|
||||
often more than a client shows inline. Before checking coverage, confirm that
|
||||
every entry of `normalized_result.steps` has `status: "completed"`; if the
|
||||
client saved the result to a file, search it for `"status":"failed"` and read
|
||||
that step's `error`. A failed sign-in or write cancels every step after it.
|
||||
Use the result's `evidence_id` for coverage and export; do not paste the
|
||||
Evidence back into another tool.
|
||||
|
||||
## Check coverage
|
||||
|
||||
`inspect_analysis_view` with `source: {kind: "retained-evidence",
|
||||
evidence_id}` (the capture's id) and `view: {kind: "environment-coverage",
|
||||
template_rules: ["after-uid-literal", "opaque-token", "sibling-variance",
|
||||
"prefix-variance"]}`. It reports read tools
|
||||
answered from the state or replayed (`reads.recorded_reasons`), the served write
|
||||
tools, and each withheld write with its `reason` and `hint`. It does not apply
|
||||
the serve-time catalog and state size checks; the export reports those.
|
||||
|
||||
Re-record a withheld write at most twice, and only for a recording gap. Stop at
|
||||
once when the reason is application behaviour, and report the write as
|
||||
withheld with its hint:
|
||||
|
||||
| Reason | What to do |
|
||||
| --------------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `no-state-target` | Check the path template and recorded views; record missing reads. The route form may not be supported as a mutation target. |
|
||||
| `no-observation` | Re-record: read the entity back by id after the write; read it first for an update or delete. |
|
||||
| `unconfirmed` | Re-record: read the entity and its list after the write. |
|
||||
| `incomplete-entities` | Re-record: read the entity through every view that lists it. |
|
||||
| `unexplained-change` | Re-record once with a second, different call of the same write. |
|
||||
| `no-call` | Re-record once with a write that succeeds. |
|
||||
| `side-effect` | Stop: the application changes other entities. |
|
||||
| `contradicted` | Stop: a later read disagrees with the modelled effect. |
|
||||
| `body-unusable` | Re-record a UI write once with `request` steps (its body was not exposed); else stop. |
|
||||
|
||||
Use new scratch names on each attempt, and delete what an earlier attempt
|
||||
created before recording again (through the UI, or a `request` step with the
|
||||
id that capture shows): the environment starts from what the recording first
|
||||
reads, so a leftover object becomes seeded data that write tasks then find.
|
||||
New browser scenario captures include request times, so a fully timed capture
|
||||
can learn a write clock and serve updates that stamp modification times. Older
|
||||
captures or ones missing a request start keep record order and learn no clock.
|
||||
When coverage reports that limitation, record again with the current version
|
||||
before concluding that the timestamp change cannot be served.
|
||||
|
||||
## Export and hand off
|
||||
|
||||
`export_environment_bundle` with `source: {kind: "retained-evidence",
|
||||
evidence_id}` (or `{kind: "evidence-file", path}`), an absolute
|
||||
`output_directory` that does not exist yet and whose parent does, and a `name`
|
||||
(required when the application runs on `localhost` or an IP address). It returns
|
||||
the coverage again, `tool_count`, the written files and warnings; `dry_run:
|
||||
true` reports without writing. The bundle installs `rea-agents` of this REA's
|
||||
version from the registry; when the user runs an unreleased REA build, pass the
|
||||
`package_tarball` they give you (a packed `rea-agents` tarball) instead.
|
||||
|
||||
Tell the user how many tools answer from the state, which writes are served and
|
||||
which are withheld and why, and the run command (`agent-env run <folder>`). Say
|
||||
that the bundle ships the recorded responses and the capture's local paths
|
||||
(for a browser scenario, the browser executable's path), and
|
||||
list any `credential-named-members` warning pointers for review. Never publish
|
||||
or share the bundle yourself.
|
||||
|
||||
See
|
||||
[agent environments](https://github.com/morluto/rea/blob/main/docs/agent-environments.md)
|
||||
for what the state, replay and the bundle establish, and
|
||||
[evidence workflows](evidence-workflows.md) for the manifest and state views.
|
||||
|
||||
## Tasks for a desktop application environment
|
||||
|
||||
Use this when the user has a folder from `rea capture-desktop-application` and
|
||||
wants a task for the environment `rea export-desktop-application` makes from
|
||||
it: a prompt for a computer-use agent and checks that grade what the agent
|
||||
left in the app's files. You write the prompt and the checks; REA validates
|
||||
the task against the capture and exports it. These commands are CLI only. To
|
||||
build the environment and its task from a request instead, follow
|
||||
[desktop builds](desktop-build.md).
|
||||
|
||||
### Describe the change
|
||||
|
||||
Run `rea describe-desktop-application-task CAPTURE --format json`. Read:
|
||||
|
||||
- `owned_paths`: the only paths whose files the app serves, so the only files
|
||||
a check can read.
|
||||
- `files`: each file there whose state differs between the capture's first
|
||||
and last version, with its `role`, the `baseline` and `final` versions and
|
||||
the net `change`. Text changes list each added and removed line once, and
|
||||
`line_counts` gives lines found at both ends whose count changed.
|
||||
- `values` in each of those files: what the change added, changed and
|
||||
removed, `before` and `after`, at the pointer a check names it by, with
|
||||
`refers_to` naming the element a key such as `category="44"` stands for.
|
||||
Skip entries noted `by_position` or as noise. Only XML files, archives,
|
||||
JSON and key files have values: a text file's or database's change
|
||||
already lists its lines and rows.
|
||||
- `task`: a draft whose `checks` are suggestions from the net change of the
|
||||
documents the user worked on, or of the app's own state when no document
|
||||
changed.
|
||||
- `guards`: optional checks that the rest kept its seed values, such as a
|
||||
like sibling's field or a text file's neighbouring lines; add one or two
|
||||
to show the rest is untouched.
|
||||
- `notes`: why `files` is empty, or why a file's suggestions are thin, such
|
||||
as `by_position` when no attribute names the changed element.
|
||||
|
||||
### Write the prompt
|
||||
|
||||
Say what the user wants done, in their words and the app's terms, naming the
|
||||
app: "In Mousepad, add buy milk to my to-do list and save it". A solving
|
||||
agent's own shell cannot see the computer's files; the app's name sends it to
|
||||
the screen. Never say how the file stores it: no
|
||||
paths the user would not name, line formats, XML, keys or SQL, and never the
|
||||
checks. Replace the draft's placeholder; the export refuses it.
|
||||
|
||||
### Pick the checks
|
||||
|
||||
Checks must express only the observed change:
|
||||
|
||||
- Keep a suggestion only if it says what the user did. Drop those that follow
|
||||
from how the app saves: a format rewrite, renumbered lines, counters. A
|
||||
LibreCAD drawing gaining four holes was rewritten from DXF R12 to 2007, and
|
||||
the draft suggests counts of `SECTION`, `ENDSEC` and `CIRCLE`; only
|
||||
`CIRCLE` equals 9 is the user's change.
|
||||
- Never check unchanged content, whole files, or values the app stamps:
|
||||
times, ids it assigns, window sizes. REA refuses ISO 8601 and `asctime`
|
||||
date-times (`Thu Nov 5 09:20:31 2026`); the
|
||||
rest is your judgment.
|
||||
- Prefer a few robust checks: whole lines over positions, rows by meaningful
|
||||
columns over generated ids, `at_least` when the user may add more.
|
||||
|
||||
Kinds: `file_present` and `file_absent`; `lines_present` and `lines_absent`
|
||||
(`lines`); `line_count` (`exact` or `contains`, and `equals`, `at_least` or
|
||||
`at_most`); `value_equals` and `value_absent` (a JSON `pointer` into the view,
|
||||
such as `/groups/GROUP/KEY` for a key file); `text_equals` and
|
||||
`text_contains` (an XML element's whole text at a `pointer`, optional
|
||||
`normalize_whitespace`); `row_present` and `row_absent` (`table`, `where` by
|
||||
column) and `row_count`. Each names its `file` as a path under the home. A
|
||||
document saved as a zip archive, such as FreeCAD's `.FCStd`, reads as its
|
||||
entries: point into an entry's view, and name array members by selector
|
||||
rather than position, as
|
||||
`/entries/[name=Document.xml]/view/root/children/[name=Object][@name=Hole]`,
|
||||
so the check survives an app version that writes them in another order. A
|
||||
gzip-compressed document, such as Gnumeric's `.gnumeric`, reads as the
|
||||
document inside: point into it as into the same document uncompressed. Give
|
||||
`value_equals` a `tolerance` to compare a number the app writes as text, such
|
||||
as `"5.0000000000000000"`, with a number. Check what the user wrote in a
|
||||
document with `text_equals` on its paragraph element, not `value_equals` on a
|
||||
text node: apps such as AbiWord and Writer split a paragraph into runs as they
|
||||
save, so its first text node holds only part of it; use `text_contains` for a
|
||||
value within a sentence, such as a time. A binary document, such as GIMP's
|
||||
`.xcf`, has no view: give the task a `readers` entry, the app's own headless
|
||||
command printing `REA ` lines, and a check naming it in `reader`, as
|
||||
[desktop builds](desktop-build.md#read-a-binary-file-with-a-reader) shows. The
|
||||
[desktop application tasks](https://github.com/morluto/rea/blob/main/docs/desktop-application-tasks.md)
|
||||
guide has the exact rules.
|
||||
|
||||
### Export the task
|
||||
|
||||
Write the task as JSON with a `name`, the `prompt` and the `checks`, then run
|
||||
`rea export-desktop-application CAPTURE DIRECTORY --task TASK.json`. REA keeps
|
||||
the task only when its checks fail on the seed and all pass on the captured
|
||||
end state. A refusal names the check: one that fails on the end state does not
|
||||
match what the user left; "every check already passes on the seed" means no
|
||||
check captures the change. For several tasks from one capture, repeat
|
||||
`--task` and name each later task's end with `--task-end NAME=CHECKPOINT`.
|
||||
|
||||
When the export refuses an application that no apt repository installs, ask
|
||||
the user for the `.deb` file they installed it from and capture with
|
||||
`--package-file`, then ask where the computer may download that file and pass
|
||||
it as `--package-url`. Never fetch a vendor's download page yourself: such
|
||||
sites often refuse automated downloads, and the copy and its licence are the
|
||||
user's to choose.
|
||||
|
||||
Tell the user the task's name, prompt and checks, and how to measure a solve
|
||||
rate: run `agent-env run DIRECTORY --task NAME --agent claude-code` with
|
||||
`--model MODEL` three times and count the runs reported `passed`. The runs
|
||||
need a model endpoint: `LITELLM_BASE_URL` and `LITELLM_API_KEY`, or
|
||||
`base_url` and `api_key` under `[model]` in `.agentenv/config.toml`. Do not run
|
||||
agents unless asked. The bundle's seed is the user's real data: keep it local.
|
||||
@@ -0,0 +1,176 @@
|
||||
# Evidence, comparison, and verification workflows
|
||||
|
||||
Evidence-producing tools return the complete Evidence record directly in MCP
|
||||
`structuredContent` and CLI JSON. Read `normalized_result` for operation data,
|
||||
and cite `evidence_id` when another tool or your explanation needs a stable
|
||||
reference. Preserve authority, limitations, coverage, and residual unknowns. If a result
|
||||
is incomplete or paginated, continue only when the remaining data matters to
|
||||
the task; do not fetch a bundle or resource merely to read a result already
|
||||
returned inline. When complete `inspect_binary_layout` or
|
||||
`analyze_javascript_application` Evidence is already retained, call
|
||||
`inspect_analysis_view` for a summary, one section/symbol/module, or a stable
|
||||
page instead of repeating the producer.
|
||||
|
||||
For any logical Evidence source that advertises retained references, pass
|
||||
`{kind: "retained-evidence", evidence_id}` instead of copying the complete
|
||||
record back into a call. The same contract covers individual, optional, array
|
||||
and nested sources across native, process, JavaScript, managed, mobile and WASM
|
||||
workflows. Sources can independently mix inline records and exact references.
|
||||
Resolution preserves the source's identity, provenance, coverage, partial facts
|
||||
and unknowns; it neither reruns analysis nor makes incomplete facts complete.
|
||||
Keep domain role and identity requirements: a native dossier cannot substitute
|
||||
for a managed member observation, for example.
|
||||
|
||||
When starting from a summary or inspection page, use its
|
||||
`normalized_result.parent_evidence_id` to reference the complete source.
|
||||
The view's own `evidence_id` names
|
||||
only that view. `compare_artifacts` explicitly supports artifact summary inputs
|
||||
and resolves their parents; do not assume every consumer does. When a workflow
|
||||
follows source links, keep those linked records available too.
|
||||
|
||||
MCP references belong to the current connection's ledger. If the ID is known,
|
||||
pass it directly; no discovery call or provider setup is needed. If it is missing,
|
||||
import the exported bundle or supply complete inline Evidence. Do not retry an
|
||||
unchanged reference or rerun a producer merely to move an existing record.
|
||||
Export before closing the session when the source must survive it. For CLI JSON
|
||||
workflows that advertise `--evidence-bundle`, the same reference JSON resolves
|
||||
against one explicitly selected authenticated bundle:
|
||||
|
||||
```bash
|
||||
rea trace-application-feature request.json --evidence-bundle /absolute/path/evidence.json --json
|
||||
```
|
||||
|
||||
This includes JavaScript traces/comparisons and runtime reconciliation, managed
|
||||
reconstruction/native verification/graph projection, Android/Apple/Harmony graph
|
||||
projection, WASM interface comparison and retained analysis views. The managed
|
||||
member comparison CLI still takes two assembly paths; process comparison takes
|
||||
two capture Evidence JSON paths. Check command help for the installed version.
|
||||
An input bundle grants no implicit file lookup: `evidence-file` and historical
|
||||
graph file selectors are accepted only by contracts advertising them. See the
|
||||
[CLI reuse guide](https://github.com/morluto/rea/blob/main/docs/getting-started/cli.md#import-export-and-compare-evidence).
|
||||
|
||||
Completed `inspect_artifact` inventory also supports a summary and
|
||||
`view: {kind: "inventory", collection: "occurrences", logical_paths: ["package.json", "main.js"]}`.
|
||||
Omit `logical_paths` to page all available occurrences; `[]` selects none.
|
||||
Other inventory collections are `nodes`, `edges` and
|
||||
`integrity_contradictions`. Keep `source_complete` separate from page exhaustion:
|
||||
a missing match in partial source Evidence does not establish absence. Use the
|
||||
returned parent Evidence ID for subsequent views and export before closing the
|
||||
session when the source must survive it.
|
||||
When `tools/list` advertises `inspect_artifact.detail`, request `"summary"` to
|
||||
retain its complete source and receive that view immediately. Without that
|
||||
advertised choice, keep the existing complete call. CLI inspection returns
|
||||
portable complete Evidence; save it before projecting a selected inline view.
|
||||
|
||||
For native procedure/name/string inventories, select `detail: "summary"` when
|
||||
the connected tool advertises it and the task needs counts or selected rows.
|
||||
Use its parent Evidence ID with
|
||||
`view: {kind: "native-inventory", offset: 0, limit: 32, fields: ["value"]}`.
|
||||
Search tools retain the existing pattern/mode/case/document selection. Omit
|
||||
`fields` for complete records; `record.address` and `source_index` remain on
|
||||
selected rows. Selecting `value` keeps its string/decoding qualifications.
|
||||
Parent Evidence ID plus source index preserves same-address
|
||||
alternatives. Follow `coverage.next_offset` only as far as the question needs;
|
||||
exhausting retained rows does not establish complete program discovery.
|
||||
|
||||
`batch_decompile` returns every body unless you select `detail: "summary"` when
|
||||
the connected tool advertises it. Use its parent Evidence ID with
|
||||
`view: {kind: "batch-decompile", collection: "items"}` for body-free rows and
|
||||
exact `where.indices`, `addresses`, `procedure_addresses` or `statuses`. Add
|
||||
`include_pseudocode: true` for several chosen bodies, or use
|
||||
`collection: "pseudocode"` with one row's `index` to page a large body. Batch
|
||||
limitations aggregate every item, so do not attribute them to one successful row.
|
||||
|
||||
Use `record_unknown` to track unresolved questions in the user's investigation
|
||||
and name the authority or environment still required. Supply supporting and
|
||||
contradicting evidence IDs. It updates the session registry directly.
|
||||
Use `update_unknown` with the current revision; reread after a stale revision
|
||||
instead of retrying blindly. Only qualifying observed evidence can verify a
|
||||
resolution.
|
||||
|
||||
Use comparisons with complete, compatible page sets when claiming equivalence
|
||||
or absence:
|
||||
|
||||
- `compare_artifacts` compares inventory pages by occurrence path, content,
|
||||
metadata, and graph relations. Name each side as
|
||||
`{kind: "retained-evidence", evidence_id}` (an `inspect_artifact` result,
|
||||
its nested inventory or its summary) or
|
||||
`{kind: "evidence-file", path, evidence_id?}` instead of resending Evidence.
|
||||
- `compare_functions` compares explicit function Evidence, not fuzzy
|
||||
whole-binary matches. It rejects an `analyze_function` summary reply; pass
|
||||
the summary's `parent_evidence_id` as a `retained-evidence` reference or
|
||||
the complete dossier.
|
||||
- `compare_bundles` compares canonical bundle membership and unknown history.
|
||||
- `find_changed_behavior` combines existing comparisons; static differences
|
||||
remain candidates, not causal proof. Its `comparisons` accept exact references.
|
||||
- `build_call_path` needs explicit function dossiers from one artifact/provider;
|
||||
pass complete parent IDs in `functions`. An incomplete frontier makes absence
|
||||
unknown.
|
||||
- `correlate_static_and_runtime` uses explicit mappings; matching patterns are
|
||||
hypotheses, not causality. Both comparison arrays accept exact references.
|
||||
- `verify_reconstruction` evaluates a finite typed specification. A pass covers
|
||||
only declared comparable claims, not global equivalence.
|
||||
|
||||
Process captures are opt-in behavioral evidence, not a security sandbox. V3
|
||||
captures cannot be upgraded to V4; rerun the original scenario. Distinguish root
|
||||
exit from descendant settlement and require freshness when the task needs it.
|
||||
A timed-out target that must write a final report needs `finalization_ms`: REA
|
||||
sends SIGTERM to the captured root, keeps observing, and sends SIGKILL once
|
||||
only if the target has not exited by the end of the interval.
|
||||
`exit.finalization.signals` lists each attempt with its delivery result; the
|
||||
observed exit signal stays in `exit.signal`, `exit.code` is null for every
|
||||
deadline exit, and the code of a finalizer that exited on its own is in
|
||||
`exit.finalization.exit_code` (null on a signal exit or when no exit was
|
||||
observed).
|
||||
|
||||
Use `inspect_analysis_view` with `view: {kind: "api-surface"}` on retained
|
||||
`inspect_web_network_capture` HAR Evidence to group observed request lines by
|
||||
method, origin and path template. Format matches are inferences, not handler
|
||||
identity or schemas. Group pages cite parent record ordinals; consult record
|
||||
coverage and exclusions before claiming completeness. No requests are replayed.
|
||||
When the connected schema advertises `include_query_parameter_names`, select
|
||||
it in the view for distinct observed names with original record ordinals. Query
|
||||
values are omitted; the names establish neither required parameters nor a
|
||||
complete server schema. Keep the original parent Evidence for exact URLs.
|
||||
|
||||
Use `inspect_analysis_view` with `view: {kind: "environment-manifest"}` on the
|
||||
same retained HAR Evidence to project the primary origin's request lines into
|
||||
named tools with path templates, parameters, observed query names, value-free
|
||||
body shapes and record pointers for an agent environment. Opt into
|
||||
`template_rules` only when recorded identifiers need them; every template,
|
||||
parameter and merged sibling is an inference, no header, cookie or body value is
|
||||
copied, and the three stated unknowns stay unresolved.
|
||||
|
||||
Use `view: {kind: "environment-state"}` with the manifest's `template_rules` to
|
||||
extract the data those reads observed instead: entity types and identity
|
||||
fields, entities with recorded values, documents, and per-tool render plans
|
||||
checked against the recordings. The state comes only from reads before the
|
||||
first related write; types, identity and list membership are inferences. The
|
||||
view also gives each state-changing tool a write plan, served only when a later
|
||||
recorded read confirms its effect and none contradicts it.
|
||||
`rea environment-serve manifest.json --evidence capture.json` derives that
|
||||
state at startup, answers read tools from it, serves the write tools whose plan
|
||||
is served, each applying its effect to that state, and serves `data/reset`,
|
||||
`data/add` and `data/get` on `/agentenv`; other write tools are not served, and
|
||||
each plan states why in its `reason`. 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.
|
||||
Use `view: {kind: "environment-coverage"}` with the same rules to see what an
|
||||
environment built from a capture would serve: read tools answered from the
|
||||
state or replayed with their reason, and each write tool served or withheld
|
||||
with a hint about what to record next; it does not apply the serve-time
|
||||
catalog and state size checks. `rea environment-build <capture.har> <dir>`
|
||||
inspects, projects and exports in one step and prints the same coverage, or
|
||||
`null` when the bundle serves replay.
|
||||
|
||||
For a PE/ELF export question, `inspect_native_exports` accepts `detail: "summary"`
|
||||
and retains the complete table. Query `inspect_analysis_view` with
|
||||
`view: {kind: "native-exports", collection: "exports", names: ["selected_name"],
|
||||
fields: ["name"], offset: 0, limit: 32}` and the reported parent Evidence ID.
|
||||
All same-name versions and aliases survive; use `source_index` with the parent ID
|
||||
for stable identity. `collection: "issues"` pages interpretation failures. Page
|
||||
coverage describes selected retained rows; `summary.coverage` or `exports.coverage`
|
||||
still describes the source table, so an empty partial page does not prove absence.
|
||||
CLI `inspect-native-exports --detail summary --evidence_output PATH` saves the
|
||||
complete bundle for later `inspect-analysis-view --evidence-bundle PATH` requests.
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
# JavaScript and Electron application artifacts
|
||||
|
||||
For captured or bundled JavaScript that needs readable source recovery, use
|
||||
`recover_javascript_sources` with an absolute `path` and absent
|
||||
`output_directory`. Supply related runtime/shared/lazy files in
|
||||
`additional_paths` when advertised, then analyze the returned `analysis_input`
|
||||
directory together. Each input retains its own snapshot, digest and byte-range
|
||||
provenance; inputs and recovered code are never executed. Recovery requires a
|
||||
caller-supplied Wakaru on Linux x64; see [the recovery guide](https://github.com/morluto/rea/blob/main/docs/guides/javascript/javascript-recovery.md).
|
||||
|
||||
Use `analyze_javascript_application` directly on the operator-supplied ASAR or
|
||||
extracted tree. When the question concerns known source paths and the connected
|
||||
schema advertises `source_paths`, select exact inventoried paths such as
|
||||
`["package.json", "main.js", "preload.js"]`. Include supporting manifests or
|
||||
source maps explicitly; dependencies are not implicitly analyzed. REA retains
|
||||
the complete artifact inventory and identity but reads source text and analyzes
|
||||
only selected files. The result and summary record `source_selection`; files
|
||||
outside scope and their relationships remain unknown, so partial application
|
||||
coverage does not mean the selected source failed. Use repeated `--source-path`
|
||||
on either static application CLI route, or `--source-paths-json` with a JSON
|
||||
file for selections too long for one command line. Omit the selection when the
|
||||
question 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 defaults to 16 MiB / 16777216 bytes;
|
||||
an admission error names `asar.max_header_bytes` and its bounds (at most
|
||||
256 MiB). Call `update_analysis_settings` with that setting, `action: "set"`
|
||||
and enough bytes, then retry the same full-archive request. No inspection or
|
||||
REA restart is required. `REA_ASAR_MAX_HEADER_BYTES` seeds future REA processes.
|
||||
`source_paths`, `detail`, and `max_heap_mb` do not bypass or raise header admission.
|
||||
Runtime JavaScript timeout/heap defaults are also editable; explicit per-call
|
||||
`analysis_timeout_ms` and `max_heap_mb` take precedence.
|
||||
|
||||
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
|
||||
targets stay unresolved with that limitation. When size is unknown or large and the connected schema advertises
|
||||
`detail`, request `detail: "summary"`. This returns an `inspect_analysis_view`
|
||||
Evidence record with a distinct ID and a `normalized_result.parent_evidence_id`
|
||||
for the complete retained application analysis. Source-map contents are part of
|
||||
that static analysis. Read findings, coverage, limitations and unknowns, then
|
||||
follow a specific unanswered question. Older servers without `detail` return
|
||||
the complete application Evidence inline when it fits.
|
||||
|
||||
When the connected schema advertises `max_heap_mb` and `analysis_timeout_ms`,
|
||||
these select the isolated source analyzer's old-space heap and per-source
|
||||
deadline. Defaults are 1024 MiB and 300000 ms. They do not change the MCP
|
||||
process heap or the client's tool deadline. For a host timeout without REA
|
||||
output, use the [deadline recovery guide](connection-and-recovery.md#distinguish-client-and-server-deadlines)
|
||||
instead of raising the server budget. A Bun-hosted REA does not enforce the heap choice; on Windows it
|
||||
instead limits the analyzer's committed memory to that choice plus a 512 MiB
|
||||
runtime reserve.
|
||||
Resource-limited analyses preserve completed static facts and
|
||||
report partial semantic coverage with specific unknown scopes; this does not
|
||||
mean the source is malformed. Inspect those limits before retrying a source.
|
||||
When expanded relationships exceed the parent's available memory, inspect the
|
||||
file's modules item view for retained `static_analysis` and
|
||||
`semantic_module_analysis`. Their facts remain available even when graph links
|
||||
are unknown. Cumulative result exhaustion can stop analysis before every file
|
||||
is examined; the inventory and remaining unknown scopes distinguish that case.
|
||||
Timeout or cancellation after source analysis begins retains partial Evidence
|
||||
in the same session. A returned `error.details.partial_observation` reference
|
||||
can be supplied directly to `inspect_analysis_view`. If the SDK cancels locally, retrieve its recorded ID from
|
||||
the Evidence bundle before inspecting the partial analysis.
|
||||
|
||||
## Inventory route candidates without returning the application graph
|
||||
|
||||
When the advertised schema supports `view`, use `detail: "summary"` with
|
||||
`view: {kind: "javascript-routes", collection: "routes", fields: ["path", "confidence"], limit: 20}`.
|
||||
The same view works with `analyze_web_bundle` on already selected captured sources.
|
||||
The complete source Evidence is retained; use its `parent_evidence_id` with
|
||||
`inspect_analysis_view` for `summary`, `routes`, `occurrences`, `sources`, or
|
||||
`unknowns`. Filter and batch IDs before requesting more fields, and follow
|
||||
`coverage.next_offset`. CLI selections require `--evidence_output` to keep the
|
||||
complete record. Static patterns, inferred deployment bases, heuristic system
|
||||
classification, and unavailable sources never establish route reachability or
|
||||
the complete application route denominator. See the
|
||||
[route inventory guide](https://github.com/morluto/rea/blob/main/docs/javascript-route-inventory.md).
|
||||
|
||||
For captured endpoint observations and inference facts, `analyze_web_bundle`
|
||||
also accepts `view: {kind: "web-bundle", collection: "endpoints", limit: 32}`
|
||||
with `detail: "summary"`. Read later `endpoints`, `inferences`, or `summary`
|
||||
pages from the retained parent. Filter before requesting detail; retain
|
||||
`source_index` together with parent ID and collection, and request `location`
|
||||
or `basis` when tracing sources. Page exhaustion does not mean producer
|
||||
completeness: check `completeness`, structured `source_unknowns`, and limitations.
|
||||
Endpoint candidates remain inferences rather than confirmed network behavior.
|
||||
|
||||
## Read a module without repeating analysis
|
||||
|
||||
Use the actual returned parent ID, on the same connection, as `source.evidence_id`.
|
||||
The following IDs are placeholders to replace with returned values. When the
|
||||
module's node ID is not already known, page identities before selecting an item.
|
||||
Pages return only node IDs, paths and roles; choose a useful page size and follow
|
||||
`coverage.next_offset` when another page matters:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"kind": "retained-evidence",
|
||||
"evidence_id": "ev_ACTUAL_PARENT_ID"
|
||||
},
|
||||
"view": { "kind": "page", "collection": "modules", "offset": 0, "limit": 16 }
|
||||
}
|
||||
```
|
||||
|
||||
Select the relevant page entry by its exact `node_id` and recorded role:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"kind": "retained-evidence",
|
||||
"evidence_id": "ev_ACTUAL_PARENT_ID"
|
||||
},
|
||||
"view": {
|
||||
"kind": "item",
|
||||
"collection": "modules",
|
||||
"selector": { "node_id": "jag_node_ACTUAL_NODE_ID" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Module pages include asset, bundled and source module roles, so one path can
|
||||
identify several entries. Use `selector.path` only when uniqueness is established;
|
||||
the returned node ID avoids needing a complete inventory to prove uniqueness. On ambiguity,
|
||||
select the matching node ID from the page or the error's candidates. Follow
|
||||
`next_offset` when another page matters. An item exposes that module node's
|
||||
recorded observations, identity, hashes, exports and source ranges; it does not
|
||||
include every child syntax observation, related edge or original source file.
|
||||
An absent item fact is not evidence of absence from the whole application.
|
||||
|
||||
For canonical identities and retained source-range counts, use a typed reference
|
||||
page instead of reading every full item:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"kind": "retained-evidence",
|
||||
"evidence_id": "ev_ACTUAL_PARENT_ID"
|
||||
},
|
||||
"view": {
|
||||
"kind": "javascript",
|
||||
"collection": "modules",
|
||||
"projection": "references",
|
||||
"where": { "path": "main.js", "kind": "javascript-module" },
|
||||
"offset": 0,
|
||||
"limit": 16
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Filters match exact retained strings; omit a filter to include all values, use
|
||||
`path: null` for unavailable paths, and `path: ""` for a recorded empty path.
|
||||
Rows preserve canonical `identity` and distinct observation support states in
|
||||
`basis`. `retained_source_range_count` counts retained source-range observations,
|
||||
not runtime imports or unique reference sites. Use a row's `node_id` with the item
|
||||
view above for exact locations and full supporting observations. Follow
|
||||
`coverage.next_offset`; page exhaustion describes matching retained rows only.
|
||||
Check `source_coverage` for source selection, partial/unknown graph coverage and
|
||||
unknown counts before drawing a negative conclusion.
|
||||
|
||||
## Trace only the remaining question
|
||||
|
||||
Use `trace_application_feature` on the parent application Evidence for one
|
||||
literal node ID, route, string, API, IPC channel, module, or native export.
|
||||
Select `incoming` for relationships leading to the seed, `outgoing` for those
|
||||
leaving it, and `both` when the question needs both. Trace traversal includes
|
||||
containment relationships, so even a narrow seed can expand many nodes; a
|
||||
bidirectional trace can reach unrelated sibling modules. A module item or page
|
||||
is preferable when its observations already answer the question. Do not treat
|
||||
all reached nodes as participants in the feature. For a broad trace, pass
|
||||
`view: {"kind": "feature-trace", "collection": "paths"}` (or `summary`) to
|
||||
retain the complete trace and read terminal paths first; page `nodes` or `edges`
|
||||
with exact `where.node_ids` through `inspect_analysis_view` as needed.
|
||||
|
||||
Reuse retained parent Evidence when the server advertises it, or supply complete
|
||||
Evidence inline. Include Hopper or Ghidra Evidence only when its artifact digest
|
||||
matches exactly.
|
||||
|
||||
## Recover an oversized display
|
||||
|
||||
An oversized response reports `resource_constraint` and
|
||||
`details.resource: "transport"`. Reuse
|
||||
`details.reported_limits.evidence_reference` with `inspect_analysis_view` for a
|
||||
summary, one module, or a stable page of module identities.
|
||||
`export_evidence_bundle` writes the complete canonical session to a
|
||||
caller-selected file. These workflows keep the original Evidence and coverage;
|
||||
a broad follow-up can also exceed framing.
|
||||
|
||||
A client can truncate a successful result inside its text envelope without a
|
||||
REA `resource_constraint`. Treat a truncation notice or incomplete JSON as a
|
||||
display limitation; do not claim the full record was examined. Reuse the known
|
||||
parent ID for smaller views, or export complete Evidence to a selected file
|
||||
while the session remains open. If the parent ID was lost from the preview,
|
||||
use the prior analysis summary or explicit ledger entries to recover it; do
|
||||
not invent an ID or rerun analysis just to reproduce the same display.
|
||||
|
||||
BrowserWindow preferences, preload and contextBridge surfaces, IPC
|
||||
registrations, utility processes, and native binding requests are static syntax
|
||||
observations. Only a unique exact literal IPC channel match supports an inferred
|
||||
pairing. Dynamic or ambiguous channels remain unresolved. A requested `.node`
|
||||
member is not a verified native export. Never claim runtime reachability,
|
||||
registration, defaults, or policy enforcement from static analysis.
|
||||
|
||||
For version comparison, analyze each version once, then call
|
||||
`compare_application_versions`. Accept only its digest, source-map, structural
|
||||
fingerprint, or non-module semantic matches. Module ordinals and minified names
|
||||
are not persistent identity. Report added or removed only with complete
|
||||
opposite-side coverage; otherwise report unknown.
|
||||
|
||||
When the question asks how one exact exported callable's returned object shape
|
||||
changed, analyze each version once and then call
|
||||
`compare_javascript_export_shapes` with explicit module paths and export names.
|
||||
Use the returned IDs on the same connection, or complete inline Evidence
|
||||
records, from both analysis calls. Accept variant
|
||||
pairing only through the tool's unique exact literal discriminant. Read
|
||||
`property_inventories` and each change's `presence` before treating `unknown` as
|
||||
"the name was not observed": inventories list observed property names even when
|
||||
values stay unknown, with a `source_range` for each paired or unpaired variant.
|
||||
Array holes and mutation-invalidated slots are not observed properties.
|
||||
Complete parent coverage reports presence-only
|
||||
`added`/`removed` independently of unresolved values. Cite the
|
||||
comparison Evidence and report JSON Pointer changes; dynamic values, ambiguous
|
||||
variants, and incomplete parent-property coverage stay unknown. This is static
|
||||
inference, not runtime behavior. When runtime semantics are needed, run
|
||||
behavioral probes against the relevant application versions and capture them
|
||||
through the available browser, Electron, or process workflows.
|
||||
|
||||
## Reusing application Evidence
|
||||
|
||||
When advertised by the connected server, application trace and compare tools
|
||||
accept complete inline Evidence or
|
||||
`{"kind":"retained-evidence","evidence_id":"ev_<64 lowercase hex characters>"}`
|
||||
for their application input (`application`, or `left`/`right`). `inspect_analysis_view`
|
||||
uses the same retained-reference form in `source`, or portable inline Evidence,
|
||||
to project a summary, module page, or one module with its recorded observations.
|
||||
This notation is
|
||||
a template: replace it with the actual returned ID. Versions before 4.1.0 accept only full
|
||||
inline Evidence. Use the exact ID
|
||||
returned by the producer on the same MCP connection. Resolution does not run
|
||||
analysis or select a provider; findings remain inline. For summary or inspection
|
||||
replies, select the complete `normalized_result.parent_evidence_id`. Native
|
||||
observation arrays and runtime reconciliation's `static_layers[].analysis` and
|
||||
`runtime_observations[]` also accept exact references where advertised. Each
|
||||
source can independently be inline or retained, preserving identity, coverage
|
||||
and unknowns. CLI workflows advertising `--evidence-bundle` resolve these inputs
|
||||
from the explicitly selected bundle. `close_binary` releases the engine while
|
||||
retaining references and complete Unknown history on the same MCP connection.
|
||||
`reset_investigation` explicitly clears them; optional `save_path` checkpoints the
|
||||
complete bundle before clearing. Import that bundle in another connection to
|
||||
restore its original references. Retention is bounded, in-memory and never silently
|
||||
evicted; `binary_session.investigation` reports the budget. A missing reference
|
||||
includes its ID and recovery guidance.
|
||||
|
||||
For exact file/native metadata or processing gaps, use
|
||||
`view: {kind: "javascript-facts", where: {paths: ["package.json"]}, property_keys: ["name", "operation", "analysis_status"], limit: 32}`.
|
||||
Rows retain canonical node/observation identity and original Evidence. Paths
|
||||
match Evidence artifact-path/source-range locations; missing properties remain
|
||||
omitted and source coverage stays separate from page exhaustion. Batch paths and
|
||||
select only needed property keys; complete Evidence remains accessible by export.
|
||||
If names are unknown, opt into `include_available_property_keys: true`; it lists
|
||||
the original keys per returned observation without unselected values. Keep each
|
||||
row's node/observation identity paired when composing facts.
|
||||
These rows select application-graph observations; semantic relationships and
|
||||
semantic unknown records remain in the complete parent Evidence and trace tools.
|
||||
@@ -0,0 +1,943 @@
|
||||
# Native, managed, and packaged artifacts
|
||||
|
||||
For release comparisons on one MCP connection, retain `list_procedures` Evidence
|
||||
from each target and reuse its exact IDs after target switches or `close_binary`.
|
||||
For a handoff or new process, export the complete bundle and import it there,
|
||||
including its source closure. `reset_investigation` explicitly clears retained
|
||||
records; optional `save_path` checkpoints them before clearing.
|
||||
`match_native_functions` pairs unique exact names and, when supplied,
|
||||
complete observed body bytes. Reuse optional same-context `list_names`,
|
||||
`procedure_info`, `read_bytes` and existing `analyze_function` dossiers as
|
||||
`left_observations`/`right_observations`; an MCP `analyze_function` summary
|
||||
reply contributes its `parent_evidence_id` as a `retained-evidence` reference,
|
||||
not the summary itself. Avoid decompiling every function merely to match it. Its summary retains a parent for
|
||||
`inspect_analysis_view` `function-matches` collections `matches` and `functions`.
|
||||
Select columns, batch IDs and page individual facts; aliases remain unresolved.
|
||||
Unpaired observations do not prove additions/removals. Existing matched dossier
|
||||
pairs include inputs for `compare_functions`; otherwise analyze just chosen pairs.
|
||||
|
||||
Aggregate completed comparisons with `find_changed_behavior`, selecting each
|
||||
comparison's exact `retained-evidence` ID instead of resending full records.
|
||||
Inline comparison Evidence remains accepted. References belong to the current
|
||||
server: after handoff, import the original bundle including its source closure.
|
||||
Do not substitute dossier IDs or summary views. Static differences remain
|
||||
behavior candidates, with runtime behavior unknown unless separately observed.
|
||||
|
||||
For a matching representation refusal, inspect `details.limit` and raise
|
||||
`native.matching_representation_bytes` with `update_analysis_settings` before
|
||||
retrying the unchanged MCP request. CLI launch seed:
|
||||
`REA_NATIVE_MATCHING_REPRESENTATION_BYTES`. The default is 96 MiB; the policy
|
||||
range is 1 byte to 1 GiB and does not bound process RSS. Keep the complete
|
||||
inventories: splitting them changes global name/body uniqueness.
|
||||
|
||||
## Apple app resources
|
||||
|
||||
Use `open_bundle_resources` with the selected app path, then `inspect_plist`,
|
||||
`decode_interface_builder`, `inspect_asset_catalog`, or `inspect_keyed_archive`.
|
||||
The resource session reads the app without resolving `CFBundleExecutable` or
|
||||
starting a deep provider. Preserve `resource_root` provenance, per-resource
|
||||
hashes where reported, and null executable identity; a directory path is not
|
||||
an executable digest. Export retained Evidence before closing or switching
|
||||
roots. Binary analysis snapshots do not apply. Use `open_binary` to switch to
|
||||
executable analysis, and `close_binary` to release either session kind.
|
||||
|
||||
The four matching CLI commands accept the app path directly. For an archive
|
||||
inside the app, use `inspect-keyed-archive APP_PATH RELATIVE_ARCHIVE_PATH`.
|
||||
Host requirements for plist and compiled asset/Interface Builder tooling still
|
||||
apply; a resource-only session does not establish provider availability.
|
||||
|
||||
## Desktop installation directories
|
||||
|
||||
When an installation directory is supplied and its runtime is unknown, use
|
||||
`inspect_desktop_application` with its absolute path. Default MCP summary
|
||||
delivery retains complete Evidence. Read `files`, `omissions`, `candidates`, `components` or
|
||||
`next_probes` with `inspect_analysis_view` kind `desktop-application`, selecting
|
||||
exact paths, batched file/omission IDs or families and only needed fields and pages.
|
||||
Summary `probe_issues` retains counts and bounded previews. Select files with
|
||||
`has_issues: true` and fields `path`, `read_status`, `issues` to retrieve exact
|
||||
failures directly; preview text is display data, while `file_id` selects full facts. Preserve source
|
||||
coverage, read-range identity and unknowns; directory snapshot identity is not
|
||||
a digest of every file's contents. Component path markers do not establish
|
||||
runtime presence. For compact CLI output, use
|
||||
`inspect-desktop-application PATH --detail summary --evidence_output BUNDLE`.
|
||||
See [desktop installations](https://github.com/morluto/rea/blob/main/docs/desktop-applications.md).
|
||||
|
||||
## Release exposure
|
||||
|
||||
Use `audit_release_exposure` (`rea audit-release-exposure PATH`) when the question is what static analysis of a shipped `.app`, install directory, ASAR, or executable recovers. Each check has a stable id, a status, the observation behind it, and fixed remediation. Unknown and unassessed checks stay in the report. The report does not establish that the application is secure.
|
||||
|
||||
`text.credential_markers` reports a rule id and location only. Matched bytes, previews, lengths, and hashes of matched bytes are omitted.
|
||||
|
||||
`native.hardening`, `macho.hardened_runtime`, and `android.manifest` are not assessed here. Their next probes are `inspect_binary_hardening`, `inspect_signature`, and `inspect_android_package`.
|
||||
|
||||
See [release exposure](https://github.com/morluto/rea/blob/main/docs/release-exposure.md).
|
||||
|
||||
## Go build metadata
|
||||
|
||||
Use `inspect_go_binary` for an explicit local ELF, PE or Mach-O (universal
|
||||
files need `architecture`) when the
|
||||
question concerns the embedded compiler version, module/dependency versions,
|
||||
local replacements, build settings, or static Go string literals packed without
|
||||
NUL terminators. Pass `include_string_literals: true`
|
||||
(`--include-string-literals`, optional `max_string_literals` /
|
||||
`--max-string-literals`) to recover bounded inferred word-aligned `(ptr, len)`
|
||||
UTF-8 string slices from read-only data and page them through `go`
|
||||
`string_literals` views. No `open_binary`, Go installation or
|
||||
target execution is required. The CLI equivalent is `inspect-go-binary PATH`.
|
||||
Preserve artifact SHA-256, original file ranges, framed module bytes and every
|
||||
unparsed module-text line. A missing record is an unknown, not proof of a
|
||||
non-Go binary; observed metadata does not authenticate its claims, and static
|
||||
`(ptr, len)` string recovery excludes compiler-inlined stack/immediate strings
|
||||
without proving runtime reachability. Function,
|
||||
source and type recovery remain a separate native-analysis question.
|
||||
|
||||
## Model files
|
||||
|
||||
Use `inspect_model_artifact` (`inspect-model-artifact PATH`) for local GGUF v2/v3
|
||||
and safetensors declarations without a model runtime. Header-only mode does not
|
||||
read weights or establish full-file identity. `hash: "full"` explicitly streams
|
||||
all bytes. Retained `model-artifact` views page `metadata`, `tensors` and derived
|
||||
`types`, with exact batch filters and selected fields. Arrays retain typed counts
|
||||
and eight-element previews; omitted values, unknown types and runtime behavior
|
||||
stay explicit. See [model files](https://github.com/morluto/rea/blob/main/docs/model-artifacts.md).
|
||||
|
||||
## IL2CPP metadata
|
||||
|
||||
Use `inspect_il2cpp_metadata` for an explicit local Unity `global-metadata.dat`
|
||||
(versions 24, 27, 29, 31 and 39) when the question concerns assembly images,
|
||||
names, member owners, string literals, namespaces or index ranges. No `open_binary`, Unity installation or target
|
||||
execution is required. The CLI equivalent is `inspect-il2cpp-metadata PATH`.
|
||||
MCP defaults to counts with complete retained Evidence. Query `sections`,
|
||||
`images`, `types`, `methods`, `fields`, `properties`, `events`, `parameters` or
|
||||
`string_literals` through `inspect_analysis_view`; use exact names,
|
||||
batch indices and selected fields. Row indices are scoped by artifact SHA-256
|
||||
and collection; page offsets count filtered matches. Parameters support batch
|
||||
`method_indices` to read one method's parameters directly. Historical reports
|
||||
without member collections retain unknown counts rather than empty inventories. Preserve
|
||||
artifact SHA-256 and index widths. Unrecognized magic may mean encryption and
|
||||
is unsupported, not decrypted. Linking names to `GameAssembly` or
|
||||
`UnityFramework` code addresses remains a separate native-analysis question.
|
||||
See [IL2CPP metadata](https://github.com/morluto/rea/blob/main/docs/il2cpp-metadata.md).
|
||||
|
||||
## Rust dependency metadata
|
||||
|
||||
Use `inspect_rust_binary` for an explicit local ELF, PE, or Mach-O (universal
|
||||
files need `architecture`) when
|
||||
the question concerns the cargo-auditable crate list embedded in `.dep-v0`
|
||||
(Mach-O: `__DATA,.dep-v0`). No `open_binary`, Rust installation, or target
|
||||
execution is required. The CLI equivalent is `inspect-rust-binary PATH`.
|
||||
Preserve artifact SHA-256, package order, dependency indices, and the section
|
||||
file range. A missing section is null metadata, not proof the binary has no
|
||||
dependencies. An omitted package kind stays null. A rustc commit hash is
|
||||
inferred from a read-only `/rustc/<40-hex>/` path and does not by itself
|
||||
identify the compiler. See [Rust binaries](https://github.com/morluto/rea/blob/main/docs/rust-binaries.md).
|
||||
|
||||
## PE Authenticode certificate tables
|
||||
|
||||
Use `inspect_pe_certificates` for an explicit local PE32/PE32+ image when the
|
||||
question concerns the Authenticode certificate table, WIN_CERTIFICATE types, or
|
||||
embedded PKCS#7 signer and X.509 identity fields. No `open_binary`, Windows SDK,
|
||||
or target execution is required. The CLI equivalent is
|
||||
`inspect-pe-certificates PATH`. Preserve artifact SHA-256, table file ranges,
|
||||
payload hashes, original validity-time spellings, and
|
||||
`subject_key_identifier_hex` when the signer uses that form. A missing
|
||||
`IMAGE_DIRECTORY_ENTRY_SECURITY` directory is observed absence of that table,
|
||||
not proof the image is unsigned in every catalog or overlay sense. Signatures,
|
||||
chains, timestamps, and Authenticode digest coverage remain unobserved. See
|
||||
[PE Authenticode certificate tables](https://github.com/morluto/rea/blob/main/docs/pe-certificates.md).
|
||||
|
||||
## PE import and delay-load tables
|
||||
|
||||
Use `inspect_pe_imports` for an explicit local PE32/PE32+ image when the
|
||||
question concerns imported DLL and function names, ordinals, delay-load
|
||||
descriptors, or the pefile import hash. No `open_binary`, Windows SDK, or
|
||||
target execution is required. The CLI equivalent is `inspect-pe-imports PATH`.
|
||||
Preserve artifact SHA-256, directory file ranges, original DLL spellings, and
|
||||
ILT/IAT RVAs. A missing `IMAGE_DIRECTORY_ENTRY_IMPORT` directory is observed
|
||||
absence of that table, not proof the image never imported APIs through another
|
||||
table or overlay. Bound snapshots, loaded IAT contents, and export-forward
|
||||
resolution remain unobserved. See
|
||||
[PE import and delay-load tables](https://github.com/morluto/rea/blob/main/docs/pe-imports.md).
|
||||
|
||||
## Windows Shell Link shortcuts
|
||||
|
||||
Use `inspect_windows_shortcut` for an explicit local `.lnk` file when the
|
||||
question concerns the recorded target path, arguments, working directory, icon
|
||||
location, volume serial, network share names, ExtraData blocks, or Tracker
|
||||
droid identifiers. No `open_binary`, Windows SDK, COM, or target execution is
|
||||
required. The CLI equivalent is `inspect-windows-shortcut PATH`. Preserve
|
||||
artifact SHA-256, FILETIME raw decimals, IDList type bytes, and ExtraData
|
||||
signatures. Unknown IDList items and ExtraData signatures remain raw with
|
||||
SHA-256; they are not guessed. Version-1 UUID MAC and timestamp values are
|
||||
labelled derived. A missing optional section is observed absence of that
|
||||
structure. See
|
||||
[Windows Shell Link shortcuts](https://github.com/morluto/rea/blob/main/docs/guides/native/windows-shortcut.md).
|
||||
|
||||
## PE TLS callbacks and load configuration
|
||||
|
||||
Use `inspect_pe_load_config` for an explicit local PE32/PE32+ image when the
|
||||
question concerns code that runs before the entry point through TLS callbacks,
|
||||
or the security cookie, SafeSEH, CFG, EH-continuation and XFG declarations in
|
||||
the load configuration. No `open_binary`, Windows SDK, or target execution is
|
||||
required. The CLI equivalent is `inspect-pe-load-config PATH`. Preserve artifact
|
||||
SHA-256, directory and callback-array file ranges, and callback VAs as
|
||||
hexadecimal strings. Fields outside the declared `Size` are `null`. Guard-flag
|
||||
mitigations carry `evidence_kind: "inferred"`; enforcement remains unobserved.
|
||||
See
|
||||
[PE TLS callbacks and load configuration](https://github.com/morluto/rea/blob/main/docs/pe-load-config.md).
|
||||
|
||||
## Binary hardening
|
||||
|
||||
Use `inspect_binary_hardening` for an explicit local ELF, PE, or Mach-O file
|
||||
when the question concerns PIE or ASLR, NX, RELRO, stack-protector or FORTIFY
|
||||
signs, control-flow flags, or stripped state. No `open_binary`, pwntools, or
|
||||
target execution is required. The CLI equivalent is
|
||||
`inspect-binary-hardening PATH`. Universal Mach-O files return one image per
|
||||
slice. A missing import is `unknown`, not proof the protection was omitted.
|
||||
Authenticode and Mach-O code-signature rows report presence, not validity.
|
||||
`hardened_runtime` stays unknown and names `inspect_signature`. See
|
||||
[binary hardening](https://github.com/morluto/rea/blob/main/docs/binary-hardening.md).
|
||||
|
||||
## ELF note tables
|
||||
|
||||
Use `inspect_elf_notes` for an explicit local ELF32/ELF64 image when the
|
||||
question concerns PT_NOTE/SHT_NOTE owners, GNU build-id, or GNU ABI-tag
|
||||
fields. No `open_binary` or target execution is required. The CLI equivalent
|
||||
is `inspect-elf-notes PATH`. Preserve artifact SHA-256, table file ranges,
|
||||
descriptor hashes, and original owner spellings. A missing table is observed
|
||||
absence of those declarations, not proof the image never carried notes in
|
||||
another container. See
|
||||
[ELF note tables](https://github.com/morluto/rea/blob/main/docs/elf-notes.md).
|
||||
|
||||
## ELF and Mach-O initializer functions
|
||||
|
||||
Use `inspect_native_initializers` for an explicit local ELF or Mach-O image
|
||||
when the question is which functions run before `main` or at exit: ELF
|
||||
`DT_PREINIT_ARRAY`, `DT_INIT`, `DT_INIT_ARRAY`, `DT_FINI`, `DT_FINI_ARRAY` and
|
||||
legacy `.ctors`/`.dtors`, or Mach-O `__mod_init_func`, `__init_offsets` and
|
||||
`__mod_term_func`. Pass `architecture` for a universal Mach-O. The CLI
|
||||
equivalent is `inspect-native-initializers PATH`. PIE slots are resolved
|
||||
through RELATIVE, RELR and section relocations, and Mach-O slots through
|
||||
chained fixups. Keep each entry's `resolution`: `unresolved` means the value was
|
||||
not established, and `unresolved_import` names an external symbol. Page with
|
||||
`offset` and `limit`. See
|
||||
[ELF and Mach-O initializer functions](https://github.com/morluto/rea/blob/main/docs/guides/native/native-initializers.md).
|
||||
|
||||
## ELF unwind function ranges
|
||||
|
||||
Use `inspect_elf_unwind_ranges` for an explicit local ELF32/ELF64 image when
|
||||
the question concerns function starts and lengths that survive `strip`, which
|
||||
functions have an LSDA, or which ranges have no exact symbol. No
|
||||
`open_binary` or target execution is required. The CLI equivalent is
|
||||
`inspect-elf-unwind-ranges PATH`. Preserve artifact SHA-256, FDE start and
|
||||
end, containing section, exact symbol name, CIE index, LSDA, and personality.
|
||||
Page later ranges with `offset` and `limit`. A missing `.eh_frame` is
|
||||
observed absence of that declaration and of `PT_GNU_EH_FRAME`, not proof the
|
||||
image has no functions. Header disagreement is a limitation and does not drop
|
||||
decoded ranges. `.debug_frame` is reported present or absent and is not
|
||||
decoded. CFA instructions are counted and not evaluated. Indirect EH pointers
|
||||
are not dereferenced. See
|
||||
[ELF unwind function ranges](https://github.com/morluto/rea/blob/main/docs/guides/native/elf-unwind-ranges.md).
|
||||
|
||||
## Apple IPS crash reports
|
||||
|
||||
Use `inspect_apple_ips` for an explicit local Apple `.ips` file when the
|
||||
question concerns crash metadata, exception and termination facts, threads,
|
||||
usedImages, lossless registers, or documented crash classes. No `open_binary`,
|
||||
Xcode, atos, or target execution is required. The CLI equivalent is
|
||||
`inspect-apple-ips PATH`. Preserve artifact SHA-256, `bug_type` as a string,
|
||||
uppercase image UUIDs, and integer literals that exceed IEEE-754 range. Only
|
||||
`bug_type` `"309"` yields a crash body; other DiagnosticReports types return
|
||||
no crash result. Select `join_path` for one local Mach-O or dSYM to match
|
||||
report images to slices by UUID and architecture. Preserve the selected
|
||||
artifact identity, slice facts and unjoined reasons; a joined static address
|
||||
does not resolve function names or dSYM symbols. See
|
||||
[Apple IPS crash reports](https://github.com/morluto/rea/blob/main/docs/apple-ips.md).
|
||||
|
||||
## Linux kernel modules
|
||||
|
||||
Use `inspect_kernel_module` for an explicit local ELF32/ELF64 relocatable
|
||||
object when the question concerns `.modinfo` license, vermagic, alias,
|
||||
depends, or parm strings, the `__versions` symbol CRCs, or an appended module
|
||||
signature trailer. No `open_binary`, Linux host, or `modinfo` program is
|
||||
required. The CLI equivalent is `inspect-kernel-module PATH`. Preserve
|
||||
artifact SHA-256, key order, duplicate keys, CRC hex, and section file ranges.
|
||||
A missing section is observed absence when section names are known, not proof
|
||||
the module never carried that metadata. `.gnu.linkonce.this_module` is reported
|
||||
as present or absent; `struct module` stays unknown because its layout changes
|
||||
with the kernel version. `__ksymtab` records are not decoded. The PKCS#7 range
|
||||
and its SHA-256 are observed; certificate, signer, and digest coverage remain
|
||||
unvalidated. An absent trailer is not proof the module is unsigned in another
|
||||
container. gzip, xz, and zstd whole-file containers are unsupported and name
|
||||
`external_decompression` as the next probe: use an external codec utility to
|
||||
decompress into a separate file, then call `inspect_kernel_module` on that file. See
|
||||
[Linux kernel modules](https://github.com/morluto/rea/blob/main/docs/kernel-modules.md).
|
||||
|
||||
## Linux kernel build config
|
||||
|
||||
Use `inspect_kernel_build_config` for an explicit local kernel image (`vmlinux`
|
||||
ELF, raw arm64 `Image`, x86 `bzImage`/`zImage`, or `configs.ko`) when the
|
||||
question is which kernel version it is or how it was configured. No
|
||||
`open_binary`, Linux host, or `extract-ikconfig` is required. The CLI
|
||||
equivalent is `inspect-kernel-build-config PATH`; pass `name` for one exact
|
||||
`CONFIG_*` option and `offset`/`limit` to page the rest. Preserve the banner
|
||||
version, builder, and compiler, the config SHA-256 and option count, and each
|
||||
entry's value kind (`y`, `m`, `string`, `number`, `not_set`). A config is
|
||||
accepted only when `IKCFG_ST` is immediately followed by a valid gzip member
|
||||
and `IKCFG_ED`, so an ordinary `IKCFG_ST` string is not a config. Offsets with
|
||||
`space: "inflated_payload"` are positions in an inflated bzImage payload, not
|
||||
file offsets. An absent config describes only the searched bytes; the kernel
|
||||
may have been built without `CONFIG_IKCONFIG` or with it as a module. Truncated
|
||||
payloads are incomplete, not absent. A framed blob that does not decode, has a
|
||||
bad CRC, or holds non-config text is `malformed`, not absent. xz, lz4, lzma, zstd, bzip2, and lzo
|
||||
payloads are unsupported and name `external_decompression`: decompress with an
|
||||
external utility, then call `inspect_kernel_build_config` on the result. See
|
||||
[Linux kernel build config](https://github.com/morluto/rea/blob/main/docs/guides/native/kernel-build-config.md).
|
||||
|
||||
## CPython pyc files
|
||||
|
||||
Use `inspect_python_pyc` for an explicit local CPython 3.7–3.13 `.pyc` when the
|
||||
question concerns the header magic, PEP 552 source hash or timestamp, nested
|
||||
code-object names, or bytecode identity. No `open_binary`, Python installation,
|
||||
or target execution is required. The CLI equivalent is `inspect-python-pyc PATH`.
|
||||
Preserve artifact SHA-256, the 16-byte header fields, nested code names, and
|
||||
bytecode SHA-256. Bytecode is not decompiled. A decoded header does not prove
|
||||
the matching `.py` is present. See [CPython pyc inspection](https://github.com/morluto/rea/blob/main/docs/python-pyc.md).
|
||||
|
||||
## Erlang BEAM files
|
||||
|
||||
Use `inspect_erlang_beam` for an explicit local `FOR1`/`BEAM` file when the
|
||||
question concerns IFF chunks, atom names, exports, imports, lambdas, or the
|
||||
Code header. No `open_binary`, Erlang installation, or bytecode execution is
|
||||
required. The CLI equivalent is `inspect-erlang-beam PATH`. Preserve artifact
|
||||
SHA-256, chunk file ranges, 1-based atom indices, and original atom spellings.
|
||||
Missing optional tables stay null. For a few facts, use `detail: "summary"` with
|
||||
a `beam` view selecting a collection, exact names/indices and fields; read later
|
||||
pages from `parent_evidence_id` or the complete Evidence bundle. Same-name
|
||||
exports retain every arity and original atom index. CLI summary delivery requires
|
||||
`--evidence_output`. Null table counts remain distinct from decoded empty tables. See
|
||||
[Erlang BEAM files](https://github.com/morluto/rea/blob/main/docs/erlang-beam.md).
|
||||
|
||||
## SQLite snapshots
|
||||
|
||||
Use `inspect_sqlite_database` with an explicit local database snapshot for its
|
||||
schema and optional rows from one exact ordinary table. It requires Node.js
|
||||
24.x >=24.15 or 26+ with the native `DatabaseSync.limits` API. It also consumes the
|
||||
existing sibling `-wal`; retain both original digests when citing its result.
|
||||
Default output is a compact inventory; a selected table expands only its own
|
||||
schema and samples 20 rows. Select `columns` to avoid irrelevant or large cells,
|
||||
and request `schema_scope: "database"` only for complete schema details.
|
||||
Choose `row_limit` when a finite sample is useful and keep truncation and
|
||||
unspecified row order explicit. Virtual tables, shadow tables and views are
|
||||
schema facts, not row-read targets. REA inspects private copies and leaves
|
||||
the source files untouched; obtain a coherent quiescent database/WAL snapshot
|
||||
before inspection. See [SQLite snapshots](https://github.com/morluto/rea/blob/main/docs/guides/data/sqlite-databases.md).
|
||||
|
||||
## Recorded Linux crashes
|
||||
|
||||
Use `inspect_recorded_crash` with an explicit Linux x86-64 ELF core path to
|
||||
inspect historical thread registers, signals, raw notes and original file
|
||||
ranges. It is independent of the active disassembler target. Source-bound
|
||||
register values and note bytes are observations; missing notes, signal-thread
|
||||
association and current executable/library identity remain unknown. PIDs are
|
||||
historical metadata and never authorize live attach or control.
|
||||
|
||||
The optional `include_debugger_context` facet adds mapping candidates through
|
||||
caller-supplied GDB/pwndbg in an owned core-only session. Display names do not
|
||||
establish current file identity; zero reported flags leave permissions unknown.
|
||||
Requested unavailable context fails with setup guidance. See
|
||||
[recorded crashes](https://github.com/morluto/rea/blob/main/docs/guides/native/recorded-crashes.md)
|
||||
for exact upstream profiles, bounds and verification coverage.
|
||||
|
||||
## Offline ELF layout
|
||||
|
||||
Use `inspect_binary_layout` with an explicit local ELF path for file-backed
|
||||
sections, symbols, relocations, linkage names, and static mitigation inferences
|
||||
without opening a disassembler target. When that complete record is already
|
||||
retained, call `inspect_analysis_view` for a summary, mitigations or linkage
|
||||
facet, one section or symbol, or a stable page. Do not re-run the decoder to
|
||||
read a single object.
|
||||
|
||||
## Offline WASM
|
||||
|
||||
Use `inspect_wasm_artifact` with caller-supplied WABT for selected local bytes.
|
||||
For counts, validation and WAT identity, select `detail: "summary"` on the first
|
||||
MCP call. The complete original Evidence stays retained; use
|
||||
`normalized_result.parent_evidence_id` for exact exports or text pages. Omitted
|
||||
or complete detail keeps the existing complete result.
|
||||
For a completed result, use `inspect_analysis_view` with its reported retained
|
||||
reference for a summary or `view: {kind: "wasm", facet: "exports", offset: 0, limit: 32}`.
|
||||
Facets also include sections, imports, candidates, glue, WAT, headers, details
|
||||
and tool profile. Text offsets count UTF-16 code units; follow `next_offset`.
|
||||
The complete source remains retained after an oversized MCP reply. No target
|
||||
execution or network acquisition is implied, and WAT is decoded representation.
|
||||
|
||||
## Offline APK signatures
|
||||
|
||||
Use `inspect_apk_signature` for a selected local APK/ZIP/AAB. Default MCP summaries
|
||||
retain complete Evidence. Select `view.collection: signers/digests/lineage`,
|
||||
with scheme or ID batches, fields and paging; use `inspect_analysis_view` kind
|
||||
`apk-signature` for retained reads after deletion. IDs retain artifact/scheme
|
||||
scope and signer links; `fields: []` keeps identity links. Empty pages preserve
|
||||
partial decoding reasons and unknown authenticity. CLI compact delivery needs
|
||||
`--evidence_output` to preserve the complete parent.
|
||||
It reads the APK
|
||||
Signing Block (v2/v3/v3.1) and v1 `META-INF` signing without executing anything,
|
||||
and reports each signer's certificate facts (for v1, the certificate the PKCS#7
|
||||
block's SignerInfo names), the declared v3 rotation lineage,
|
||||
the declared source-stamp certificate and, for SHA-256/SHA-512 digests, whether
|
||||
the declared content digest matches the current bytes. That match is not a
|
||||
signature verification: anyone who changes the bytes can recompute the digest.
|
||||
`posture` summarises v1-only signing (which cannot tell a v1-only APK from one
|
||||
whose v2/v3 block was removed), observed signer agreement across schemes,
|
||||
whether the v1 signer equals the block-scheme signer (`false` is notable),
|
||||
whether every differing signer appears in a declared (unverified) rotation
|
||||
lineage, and the strongest scheme.
|
||||
It never claims authenticity: no signature or lineage is cryptographically
|
||||
verified.
|
||||
|
||||
## Native targets
|
||||
|
||||
After `open_binary`, use focused search, procedure, or function tools directly.
|
||||
Use `binary_overview` when target metadata or inventory context helps answer the
|
||||
question. Prefer literal search, names, decompilation, callers, callees, and
|
||||
cross-references. Addresses and recovered pseudocode are analysis observations,
|
||||
not original source. Provider unavailability and unsupported metadata remain
|
||||
unknown rather than false.
|
||||
|
||||
For large pseudocode, request `procedure_pseudo_code` with `detail: "summary"`
|
||||
on the first MCP call. It retains the complete observation and returns the
|
||||
original selection, text availability and length without the body. Use
|
||||
`normalized_result.parent_evidence_id` with `inspect_analysis_view` and
|
||||
`view: {kind: "native", facet: "pseudocode", offset: 0, limit: 20000}`;
|
||||
follow `coverage.next_offset` for later pages. Choose a smaller limit if one
|
||||
page exceeds the client or transport budget. Offsets and limits count UTF-16
|
||||
code units, not lines or tokens. Pages reuse the same observation without
|
||||
repeating decompilation. Null and empty text remain distinct. Omitted or
|
||||
`complete` detail preserves full inline delivery. Summary delivery requires a
|
||||
retaining session and does not reduce the work or memory of decompilation.
|
||||
|
||||
For a completed `analyze_function` dossier, use `inspect_analysis_view` with
|
||||
`view: {kind: "native", facet: "value_flow_operations", offset: 0, limit: 32}`
|
||||
and the exact retained Evidence ID to read selected facts without reanalysis.
|
||||
The default MCP reply is already a summary of that dossier: its
|
||||
`normalized_result.parent_evidence_id` is the retained ID to page, and its
|
||||
null counts mark facets the provider did not record or declared unavailable.
|
||||
Native facets also include procedure, pseudocode, assembly, basic blocks,
|
||||
comments, callers/callees, references, unresolved calls, referenced strings and
|
||||
names, the native API record, and value-flow summaries. Pseudocode offsets and limits count UTF-16
|
||||
code units; use the returned `next_offset` for continuation. Provider limitations
|
||||
and unavailable facts remain explicit; the complete parent Evidence is retained.
|
||||
|
||||
`inspect_macho` on a large framework returns megabytes of imports and exports.
|
||||
Select `detail: "summary"` for slice identity, UUID and per-collection counts,
|
||||
then page rows with `view: {kind: "macho", facet: "exports", offset: 0, limit: 64}`
|
||||
and `normalized_result.parent_evidence_id`. Facets are entrypoints,
|
||||
architectures, build_metadata, load_commands, dependencies, imports, exports,
|
||||
segments and provenance. `source_exhaustive: false` means unreturned symbols
|
||||
may exist.
|
||||
|
||||
To see which functions or Objective-C methods a Mach-O actually calls in one
|
||||
run, use `observe_native_calls` with explicit breakpoints and a bounded
|
||||
`duration_ms`/`max_events`. It launches a new process under LLDB, so the target
|
||||
runs and may change files or use the network. Hardened-runtime targets need the
|
||||
`get-task-allow` entitlement.
|
||||
Function breakpoints use exact LLDB runtime names: pass an `inspect_macho` export
|
||||
or import `runtime_name` (`main`), not its symbol-table `name` (`_main`). REA does
|
||||
not translate breakpoint names. Set `module` to the image
|
||||
file name when selecting that image only; otherwise loaded system images also
|
||||
match. Inspect retained locations and module paths before attributing a call.
|
||||
|
||||
Use `binary_session` with no arguments to check the open target, selected
|
||||
provider, and alignment. Its default summary `result.tool_availability` carries
|
||||
the complete tool inventory grouped by current status. Expand each group's
|
||||
`names` and inherit the inventory-level client requirements unless a group
|
||||
overrides them; availability, reasons, remediation, and modes remain inline.
|
||||
Provider candidates keep availability and target-support status, code, and
|
||||
reason. `omitted_fields` names what the summary leaves out; `{"detail":
|
||||
"complete"}` adds each unavailable candidate's `remediation`, provider
|
||||
diagnostics, candidate capability sets, and tool surface, `effects`, and
|
||||
`annotations`. Those arrays name true flags from fixed
|
||||
vocabularies, so an omitted known flag is false. `tools/list` remains the
|
||||
canonical source for full tool schemas when target or provider state changes.
|
||||
|
||||
Provider capability groups carry provider identity and ordered limitations.
|
||||
Prepend each set's `shared_limitations` to a group's `limitations` to recover the
|
||||
operation's full ordered list. Candidate capabilities, returned with complete
|
||||
detail, describe possible providers. Top-level session capabilities describe the current route, and
|
||||
`analysis_provider_binding` identifies the selected provider.
|
||||
|
||||
## Continue editable Ghidra analysis across processes
|
||||
|
||||
For a task spanning agent sessions, check `binary_session` after selecting
|
||||
Ghidra: the current provider's `capabilities[].shared_limitations` states whether
|
||||
Program checkpoints are enabled or the session is ephemeral. Successful native
|
||||
queries distinguish initial analysis from an actually restored packed Program;
|
||||
do not infer that restoration happened merely because checkpoint mode is enabled.
|
||||
|
||||
In ephemeral mode, choose a private absolute directory and set
|
||||
`REA_GHIDRA_CHECKPOINT_DIR` in the environment starting REA. Restart the MCP server
|
||||
after changing that launch configuration; no current tool call or runtime
|
||||
analysis-setting update enables it. Stock ELF/PE/Mach-O imports on Linux/macOS
|
||||
are supported; see the [checkpoint setup and limitations](https://github.com/morluto/rea/blob/main/docs/getting-started/installation.md#automatically-checkpoint-an-owned-ghidra-program).
|
||||
|
||||
With the setting enabled, normal opens restore compatible saved Programs
|
||||
automatically. Initial completed analysis is saved, and `close_binary` saves
|
||||
later metadata edits; no separate save/restore tool is needed. Repair a reported
|
||||
save failure and retry close. Cancellation or process failure can lose edits
|
||||
after the last successful save; unfinished initial analysis cannot resume.
|
||||
Keep the same checkpoint configuration for later processes. Evidence/Unknown
|
||||
history and immutable REA query snapshots have separate persistence workflows.
|
||||
|
||||
## Reuse caller-selected Ghidra analysis
|
||||
|
||||
When the caller supplies an expanded project, configure `REA_GHIDRA_PROJECT_PATH`
|
||||
(the `.gpr` marker) and optionally `REA_GHIDRA_PROGRAM_NAME` (one root program),
|
||||
then restart/reconnect before `open_binary`. CLI uses the same configuration.
|
||||
REA opens only a fingerprint-bound owned copy with `-process -noanalysis -readOnly`;
|
||||
original project files are not opened by the engine or saved. Database edits,
|
||||
import overrides and repair scripts are unavailable in this mode. Treat original
|
||||
analysis completeness/settings as unknown and prior edits as caller-project state.
|
||||
The program's recorded import digest must match the target; changed project content
|
||||
requires reopening for a fresh profile. See the
|
||||
[setup and preparation guide](https://github.com/morluto/rea/blob/main/docs/getting-started/installation.md#reuse-an-existing-ghidra-project).
|
||||
|
||||
## Ghidra startup deadline recovery
|
||||
|
||||
`provider_timeout` during the first Ghidra query can cover import, auto-analysis,
|
||||
bridge startup, and readiness. The default 330,000 ms is configurable through
|
||||
`REA_GHIDRA_STARTUP_TIMEOUT_MS`; a smaller query still needs the same cold import.
|
||||
|
||||
When the error names `ghidra.startup_timeout_ms`, call
|
||||
`update_analysis_settings` with `action: "set"` and a larger value within the
|
||||
reported bounds. Resolve retained cleanup before the next startup attempt.
|
||||
No REA restart is needed; an already accepted startup keeps its original
|
||||
budget. Follow the error's session-specific restart guidance, and preserve useful Evidence before closing
|
||||
and reopening the target when remediation requires that lifecycle step.
|
||||
|
||||
For a per-function timeout, update `ghidra.decompile_timeout_seconds` and retry
|
||||
the same function on the existing Program. Explicit `null` removes that
|
||||
per-function deadline. Inspection is optional when the error supplies the
|
||||
setting and bounds. Runtime updates disappear when REA exits; environment
|
||||
changes only seed future REA processes.
|
||||
|
||||
The client's tool-call deadline must allow startup plus the requested query;
|
||||
server settings and progress notifications cannot override it. CLI analysis
|
||||
avoids the MCP client deadline, but retains the provider deadline. For example:
|
||||
|
||||
```sh
|
||||
REA_GHIDRA_STARTUP_TIMEOUT_MS=1800000 rea analyze /absolute/path/to/app.exe --provider ghidra --json
|
||||
```
|
||||
|
||||
Thirty minutes is an example budget, not a completion guarantee. Keep host CPU
|
||||
and memory controls in place. Disable specific expensive analyzers only when
|
||||
their missing coverage is acceptable and retain the resulting limitations.
|
||||
Exported C and embedded resources remain useful independent evidence, but a
|
||||
timeout does not establish complete analysis or absence of code. See the
|
||||
[deadline and client guide](https://github.com/morluto/rea/blob/main/docs/reference/mcp-contracts.md#ghidra-first-query-deadlines-and-recovery).
|
||||
|
||||
## Bridge request ceiling
|
||||
|
||||
Hopper and Cutter share `REA_BRIDGE_MAX_REQUEST_BYTES`. Unset, both sides use
|
||||
16777216 bytes. The payload budget excludes the terminating LF. A decimal
|
||||
integer from 7464 to 536870887 raises or lowers that ceiling. The floor fits
|
||||
the largest bounded symbol-name command. A tight Cutter status still returns
|
||||
its session id and up to 64 completion receipts. Its path is included when it
|
||||
fits, and is unknown when it does not, so an older descriptor path is not
|
||||
paired with the new generation. The maximum is the encoded payload, one byte under Node's string ceiling so
|
||||
the framing LF still fits. Cutter measures, signs, and writes a fitting
|
||||
response in bounded chunks. The bridge searches only the newly read bytes
|
||||
for the framing LF. The client unescapes each socket chunk into one response
|
||||
string before parsing it, so this ceiling does not keep the paged wire frame
|
||||
and another concatenated copy. Invalid values are configuration errors and do not fall back to 16777216. `bridge.max_request_bytes` can be changed at runtime with `update_analysis_settings`. The launch seed is `REA_BRIDGE_MAX_REQUEST_BYTES`. Start Hopper or Cutter from that same environment so the bridge keeps the ceiling it started with until that bridge starts again. An out-of-band bridge
|
||||
without the setting stays at 16777216 bytes. The client reports that mismatch
|
||||
during discovery only after the hello proves a live authenticated bridge, and
|
||||
does not send a status request or the command. A stale descriptor is ignored.
|
||||
Discovery fails if any such live ceiling differs, even when another live
|
||||
session matches. A command response discarded for that ceiling stays an
|
||||
unknown execution with `output_truncated`. A hello
|
||||
that never sends its authenticated frame does not hold the accept loop.
|
||||
At most 8 connection threads run; a further accept is closed, and a failure
|
||||
to start a thread does not stop the listener. `completed_connection` is the
|
||||
longest prefix of connections that have terminated. Dense scalar replies are
|
||||
encoded in bounded batches.
|
||||
The 25000 ms Cutter request deadline and the 256-candidate discovery budget
|
||||
still have no runtime override.
|
||||
|
||||
## Selected native facts and call graphs
|
||||
|
||||
For a large `get_call_graph`, or repeated `procedure_address`,
|
||||
`procedure_callees`, `procedure_callers` and `resolve_containing_procedure`
|
||||
queries, select `detail: "summary"` when the first 64 recorded observations
|
||||
suffice. Read further `native-observation` pages from the returned parent Evidence
|
||||
ID. Graph message IDs index that page's exact-text dictionary; keep level,
|
||||
source index, failed nodes, and partial/unknown relationship coverage.
|
||||
Read referenced source context through `native-context` facets `overview`,
|
||||
`analysis-profile`, `limitations` and `result-limitations`. Reuse inspected
|
||||
context/profile values only for the same digest; until caveats are read,
|
||||
interpretation beyond the returned facts remains unknown. Complete Evidence
|
||||
remains retained and exportable. Small complete replies can cost fewer tokens
|
||||
than additional context/page calls; count the completed task and discovery.
|
||||
|
||||
## Static memory and original file bytes
|
||||
|
||||
For Ghidra, `read_bytes` reads initialized analysis memory, including loader
|
||||
fixups; it does not read a running process. Check `returned_bytes` and `complete`
|
||||
before decoding a table. An incomplete read is missing coverage, not a zero-filled
|
||||
tail. Use `list_segments` to inspect the selected block's initialization and address-space
|
||||
facts, and retain unavailable facts as unknown.
|
||||
|
||||
Use `address_to_file_offset` to anchor one observed address to original file
|
||||
bytes. A mapping for the first address does not establish a contiguous mapping
|
||||
for an entire table, and loader fixups can make analysis bytes differ from source
|
||||
bytes. Keep source ranges and analysis-memory observations separate.
|
||||
|
||||
A pointer table can refer to writable slots populated by a constructor rather
|
||||
than directly to immutable resources. An uninitialized block or an observed zero
|
||||
does not establish the slot's later runtime value. Follow `xrefs` and the relevant
|
||||
writer's assembly or pseudocode; distinguish recorded assignments from inferred
|
||||
execution order. Do not replace unreadable bytes with zeros or conclude that a
|
||||
resource is absent without the necessary initialization evidence.
|
||||
|
||||
## DOS MZ with Ghidra
|
||||
|
||||
For an admitted DOS MZ target, use `inspect_native_load_image` to check measured
|
||||
loaded bytes, file mappings, relocations and the entry against the immutable
|
||||
snapshot. Keep `mismatch` and `unsupported` explicit. Verified import covers the
|
||||
reported static image, not runtime DOS or PC-98 hardware behavior.
|
||||
|
||||
For a large load-image report, select `detail: "summary"` and query its
|
||||
`parent_evidence_id` with `inspect_analysis_view` kind `native-load-image`.
|
||||
Choose a collection such as `relocations` or `mappings`, select only needed
|
||||
fields, and page with offset/limit. Original indices preserve same-address
|
||||
alternatives. Null collections remain unrecorded or inapplicable; paging does
|
||||
not upgrade unsupported verification. CLI requires `--evidence_output` for
|
||||
summary delivery so complete source Evidence remains accessible.
|
||||
|
||||
For Ghidra decompilation, `procedure_pseudo_code` also accepts `procedure: "file-offset:0x..."`; CLI `rea decompile <path> --file-offset=0x... --provider ghidra` resolves the source byte offset internally. An unresolved 0x-prefixed numeric procedure selector also falls back to a unique file mapping. Existing symbols and analysis addresses win; multiple mappings fail as ambiguous. Preserve the returned file-offset and address locations and raw selection observations. ELF virtual addresses are distinct from file offsets; never assume an arbitrary offset plus image base is an analysis address.
|
||||
|
||||
Complete function body ranges use inclusive ends and can contain gaps. Do not
|
||||
treat the enclosing span as code.
|
||||
For packed targets, retain the original and separately derived artifact identities;
|
||||
decompiling an unpacking stub does not recover the unpacked program.
|
||||
|
||||
When reading Objective-C dispatch metadata, distinguish class implementation
|
||||
methods from protocol requirements: class methods report null requirement
|
||||
flags, while decoded protocol declarations retain required and optional facts.
|
||||
Property attributes remain raw name/value tokens; use the property's
|
||||
`atomicity` field for the decoded `N` marker or the default atomic behavior.
|
||||
Null class/meta flags, ivar counts, atomicity, or read-only values mean the
|
||||
selected provider did not establish that fact. Symbol names alone do not prove
|
||||
that a class is a root class or has no ivars.
|
||||
|
||||
## Managed PE/CLI
|
||||
|
||||
Start with `inspect_managed_artifact`. REA's canonical managed inspection is
|
||||
execution-free: do not claim it loaded, reflected, executed, or resolved the
|
||||
assembly. Keep managed/native boundaries and unavailable reconstruction facts
|
||||
explicit. A bring-your-own reconstruction oracle is separate from the canonical
|
||||
parser and must not become an implicit setup dependency.
|
||||
|
||||
For identity/classification questions, `inspect_managed_artifact` can explicitly
|
||||
select `detail: "summary"` on the first MCP call. It retains complete metadata
|
||||
and returns a linked overview with full classification/evidence, nullable
|
||||
module/MVID, frameworks, metadata coverage/issues/limitations and returned-row
|
||||
counts. Default complete requests remain unchanged. Read original rows with
|
||||
`inspect_analysis_view`, source `normalized_result.parent_evidence_id`, and
|
||||
`view: {kind: "managed", collection: "attributes", offset: 0, limit: 16}`.
|
||||
Collections are `references`, `resources` and `attributes`. Paging does not
|
||||
repeat parsing. Returned-row exhaustion
|
||||
does not prove complete metadata or absence under partial/unavailable coverage;
|
||||
preserve build-local tokens and their artifact/MVID scope.
|
||||
|
||||
`inspect_managed_members` always returns the assembly-wide `member_refs`, even
|
||||
for one selected type. For questions about a selected type, select
|
||||
`detail: "summary"` with `type_names`; it returns the selection (with unmatched
|
||||
names), coverage and per-collection counts. Page rows with
|
||||
`view: {kind: "managed-members", collection: "call_edges", offset: 0, limit: 64}`
|
||||
over `types`, `exported_types`, `fields`, `methods`, `member_refs`, `call_edges`,
|
||||
`field_accesses` or `user_strings`.
|
||||
Use exact `names` and `declaring_types` filters before paging supported
|
||||
collections. For a compact method lookup, request `fields: ["name",
|
||||
"declaring_type", "signature"]`; omit `body` to avoid anchors. Identity tokens,
|
||||
original `source_index`, module/MVID and source coverage remain. Check
|
||||
`unresolved_filter_rows` before interpreting an empty match as absence.
|
||||
|
||||
### .NET NativeAOT
|
||||
|
||||
NativeAOT binaries contain native machine code, so ordinary CIL decompilers
|
||||
cannot recover the original method bodies. When managed metadata/CIL is absent,
|
||||
classify that as a native-analysis route rather than claiming source recovery.
|
||||
Open the native image with the selected deep provider and inspect functions,
|
||||
strings, calls, and references; describe decompiler output as pseudocode and
|
||||
inference.
|
||||
|
||||
NativeAOT images can be PE/COFF, ELF, or Mach-O executables and shared
|
||||
libraries. Use file bytes and loader metadata rather than suffixes to identify
|
||||
them. For packaged apps, inventory/extract with REA's artifact tools and retain
|
||||
the exact contained image identity. PDB, ELF debug, or dSYM sidecars are
|
||||
additional evidence only when the provider accepts and matches them.
|
||||
|
||||
REA has a built-in read-only snapshot parser for x64 PE targets with .NET 8 RTR
|
||||
9.1 metadata. An optional headless Ghidra adapter adds database annotations and
|
||||
broader metadata recovery on Linux; it requires an explicitly configured
|
||||
NativeAOT JAR. These are separate routes. The built-in parser also runs on
|
||||
Windows Ghidra P0; read frozen literals from its report, because
|
||||
`search_strings` does not include them. See the
|
||||
[NativeAOT guide](https://github.com/morluto/rea/blob/main/docs/providers/ghidra-nativeaot.md)
|
||||
for setup, supported layouts, and host restrictions. Preserve binary identity
|
||||
and distinguish derived metadata from Ghidra database observations. Recovered
|
||||
types and native pseudocode are not original C# source. Windows Ghidra P0 has
|
||||
no database mutation authority.
|
||||
|
||||
## Packages and extraction
|
||||
|
||||
Use `inspect_artifact` for application bundles, archives, ZIP/APK/IPA/MSIX/AppX,
|
||||
ASAR, or DMG inputs when the artifact graph and findings help answer the
|
||||
question. It returns the complete artifact graph inline. Cite graph manifest
|
||||
IDs when using them.
|
||||
|
||||
For an IPA or a macOS `.app`, ZIP, or DMG, pass the inventory Evidence to
|
||||
`project_apple_application_graph`. It reports application roots and nested
|
||||
bundles by path convention: app extensions, XPC services, frameworks, login
|
||||
items, system and driver extensions, and plug-ins. It also lists privileged
|
||||
helpers, launchd plists, symlinks, and each bundle's `info_plist_path` and
|
||||
executable candidates. Roles are path conventions, not parsed plists; read the
|
||||
listed plists with `inspect_plist`.
|
||||
|
||||
After `open_binary` on a `.app` or Mach-O, use `trace_dylib_resolution` to see
|
||||
which file each `@rpath`, `@loader_path` and `@executable_path` load reaches for
|
||||
every executable in the bundle. It also lists missing or weak loads and earlier
|
||||
`@rpath` candidates that are absent. Narrow large bundles with `roots` or
|
||||
`architecture`. System paths stay undetermined because the dyld shared cache
|
||||
provides them.
|
||||
|
||||
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/reference/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
|
||||
destination. No separate permission grant is needed.
|
||||
|
||||
For classic iNES cartridges, `open_binary` recognizes the byte signature without
|
||||
an executable architecture. `inspect_artifact` retains header facts and each
|
||||
PRG/CHR file unit's offset, length and SHA-256; its nested inventory's
|
||||
`ines.reconstruction` verifies the actual ordered region bytes against the
|
||||
whole-file digest. Extraction includes the original header, optional trainer
|
||||
and uninterpreted trailing bytes. These file units are not mapper/CPU bank
|
||||
maps. NES 2.0, UNIF, dirty legacy headers and truncated payloads are explicitly
|
||||
refused. No emulator or 6502 analysis is performed. See the
|
||||
[iNES guide](https://github.com/morluto/rea/blob/main/docs/ines-containers.md).
|
||||
|
||||
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. 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
|
||||
analysis: the entry is `0x10100`, file offset zero, with imposed real-mode segment
|
||||
context. PSP/stack/device state remains unmodeled. See [DOS guide](https://github.com/morluto/rea/blob/main/docs/providers/ghidra-dos.md).
|
||||
|
||||
Use `inspect_byte_entropy` to triage high- and low-entropy ranges before extraction.
|
||||
|
||||
For other headerless images (embedded firmware without ELF/Mach-O/PE/MZ
|
||||
headers), open with `format: "raw-binary"`, `architecture` (`x86`, `x86_64`,
|
||||
`arm`, `arm64`, `6502`, or `m68k`), and `entry_point` (`0x` hex). File offset 0 is mapped at
|
||||
that address. Hopper and IDA refuse this interpretation; Ghidra uses
|
||||
`BinaryLoader` with a generic language: big-endian for `m68k`, little-endian
|
||||
otherwise. Big-endian ARM, Thumb-only, and Cortex-M variants are unsupported.
|
||||
`6502` selects NMOS 6502; the entry and complete file mapping must fit within
|
||||
`0x0000..0xffff`. 65C02, 65816, cartridge containers, bank switching, and mapper
|
||||
semantics are unsupported. `m68k` requires an even entry and decodes the 68040
|
||||
superset of the 68000 family; Amiga/Atari containers and vector-table entry
|
||||
discovery are unsupported. Windows Ghidra P0 admits raw images only for `6502`. See [raw binary guide](https://github.com/morluto/rea/blob/main/docs/providers/raw-binary.md).
|
||||
|
||||
Intel HEX, S-record, UF2 and DfuSe files are containers, not raw images:
|
||||
`inspect_artifact` lists address regions (UF2 per familyID, DfuSe per element
|
||||
with its alternate setting), and `extract_artifact` writes each region. Open an
|
||||
extracted region as `raw-binary` with its start address as `entry_point`. UF2
|
||||
numbering gaps leave coverage unknown; a DfuSe suffix CRC mismatch follows
|
||||
`integrity_policy`. See [UF2 and DfuSe](https://github.com/morluto/rea/blob/main/docs/uf2-dfuse.md).
|
||||
|
||||
### Function annotations in Ghidra
|
||||
|
||||
Fresh-import sessions admit annotations; existing-project reuse is read-only.
|
||||
Use `annotate_native_function` for one function name and/or entry comments, with at least one explicit change. Review its annotation readback and refreshed dossier inline. Changes are atomic; empty comments clear them, omitted fields preserve them. Later MCP calls observe edits. Normal close saves them when owned Program checkpoint mode is enabled; ephemeral mode discards them. CLI `annotate-native-function` follows the same setting when closing after its updated result. Select the [checkpoint workflow](#continue-editable-ghidra-analysis-across-processes) before edits that must survive a later process. Original executable bytes are unchanged; edits invalidate immutable snapshots. Windows P0 does not admit database mutations. For naming only, `set_address_name` / `set_addresses_names` also work with Ghidra: they name function entries or data addresses (primary labels) and return compact per-address success booleans instead of a dossier. Ghidra rejects batch addresses that request the same name or a name another selected address holds; `raw_result.failures` gives each failure's reason.
|
||||
|
||||
A provider switch or different target can retire the active Ghidra database and discard
|
||||
its edits, even if the new provider fails on a later call. Same-target,
|
||||
same-profile reopen keeps the active database. Retained annotation Evidence
|
||||
records what happened; it does not restore the edits.
|
||||
|
||||
For `compare_functions`, obtain `analyze_function` Evidence before and after the
|
||||
edit while the MCP session is open; annotation Evidence is not a comparison
|
||||
input. Export the needed Evidence before close if comparison will happen later.
|
||||
Authenticated same-artifact coordinates preserve renamed entries as
|
||||
`matched / same-entry`, with the canonical `entry_address` inline; name and
|
||||
exact-text changes remain separate dimensions. This requires compatible
|
||||
architecture, provider-owned mapping and selected-image commitments. Equal
|
||||
numeric addresses alone cannot establish correspondence; inspect retained
|
||||
source Evidence and coverage when the match remains ambiguous.
|
||||
|
||||
## Offline PE resource inventory
|
||||
|
||||
Use `inspect_pe_resources` with an absolute `path`, or
|
||||
`rea inspect-pe-resources ./selected.exe --json`, for portable PE32/PE32+
|
||||
resource inspection without opening a native target. Preserve returned Evidence:
|
||||
type/name/language IDs and UTF-16 names, original directory/data/payload ranges,
|
||||
code pages, payload hashes and static icon-group references. Same-language icon
|
||||
resolution is explicit; missing references and size mismatch remain visible.
|
||||
Other payloads are opaque, and this operation does not decode images or simulate
|
||||
Windows resource loading. Consult the budgets and supported tree profile in
|
||||
[offline binary diagnostics](https://github.com/morluto/rea/blob/main/docs/guides/native/binary-diagnostics.md).
|
||||
|
||||
## Offline PE and ELF export tables
|
||||
|
||||
Use `inspect_native_exports` with an absolute `path`, or
|
||||
`rea inspect-native-exports ./libexample.so --json`, to read a PE export
|
||||
directory or ELF dynamic symbol table on any host without opening a native
|
||||
target. Ordinal-only, forwarded and hidden-version exports stay distinct;
|
||||
partial or unsupported coverage means the inventory is incomplete, not that
|
||||
exports are absent. Use `inspect_macho` for Mach-O. See
|
||||
[offline binary diagnostics](https://github.com/morluto/rea/blob/main/docs/guides/native/binary-diagnostics.md).
|
||||
|
||||
For exact core-module import/export differences, use `compare_wasm_interfaces`
|
||||
with two complete inspection Evidence records (or current-session retained
|
||||
references) and explicit scope. Preserve unknown types/duplicate names; static
|
||||
interface equality is not runtime compatibility. CLI accepts complete inline
|
||||
Evidence in `rea compare-wasm-interfaces input.json --json`, or exact references
|
||||
with `--evidence-bundle /absolute/path/evidence.json`. Use the complete parent
|
||||
ID when the inspection returned a summary.
|
||||
|
||||
## Godot PCK
|
||||
|
||||
For a standalone PCK, `open_binary` then `inspect_artifact` with
|
||||
`detail: "summary"` retains the complete static inventory. Use the returned
|
||||
`parent_evidence_id` with `inspect_analysis_view` inventory occurrences filtered
|
||||
by exact `logical_paths` or `occurrence_ids`, and join `artifact_id` to nodes
|
||||
filtered by `artifact_ids`. Select only needed fields; identity links remain.
|
||||
Prefer `inspect-artifact --detail summary --evidence_output PATH` for CLI tasks;
|
||||
the same CLI discovers embedded packs via their EOF trailer without opening a
|
||||
native analysis provider. Normal native opening remains unchanged.
|
||||
|
||||
Distinguish declared MD5 from observed SHA-256 and graph/page completeness from
|
||||
`source_coverage`. Encrypted directories and sparse bundles have unknown entry
|
||||
coverage; encrypted members have unknown content identity. An empty filtered
|
||||
page cannot prove absence in unknown coverage. Retained views are historical,
|
||||
not fresh filesystem checks. No decryption, Godot resource decoding, GDScript
|
||||
decompilation or target execution is provided. See
|
||||
[Godot PCK](https://github.com/morluto/rea/blob/main/docs/godot-pck.md).
|
||||
|
||||
UnityFS AssetBundle containers (`.bundle`, `.ab`, YooAsset packages and other
|
||||
byte-identified files) list `CAB-*` SerializedFiles and `.resS` members with
|
||||
header and node facts; none/LZ4/LZ4HC member blocks stream on demand. Bundles
|
||||
declaring asset-bundle encryption keep header facts with unknown directory
|
||||
coverage; LZMA member bytes retain named occurrences with unavailable hashes.
|
||||
Virtual member offsets are not physical carrier locations. Format 6–8 readers
|
||||
cache one decoded block and support retained filtered/paged views. No
|
||||
decryption or SerializedFile object decoding is provided. See
|
||||
[UnityFS](https://github.com/morluto/rea/blob/main/docs/unityfs.md).
|
||||
|
||||
WeChat mini-program packages (`.wxapkg` files with `0xBE`/`0xED` marks) list
|
||||
members with declared names and absolute carrier offsets; member bytes are
|
||||
stored verbatim. `V1MMWX` PC-client packages report `encrypted` directory
|
||||
status with unknown coverage and are refused on extraction; no decryption is
|
||||
attempted. See
|
||||
[wxapkg](https://github.com/morluto/rea/blob/main/docs/wxapkg.md).
|
||||
|
||||
U-Boot legacy uImages use the same inspection/extraction workflows. Prefer a
|
||||
retained summary and selected inventory views for header facts or component
|
||||
IDs. Header addresses/CPU/OS are declarations; payloads remain as stored.
|
||||
Multi-file components retain their aligned physical ranges; the full payload
|
||||
is also materialized. Unknown name text retains its original 32 bytes. See
|
||||
[U-Boot uImage](https://github.com/morluto/rea/blob/main/docs/uimage.md).
|
||||
|
||||
## ESP images
|
||||
|
||||
For an ESP32-family app or bootloader image, `open_binary` then
|
||||
`inspect_artifact` with `detail: "summary"`. `root_format_metadata` holds the
|
||||
observed `header` and `descriptor` (its `kind` is the app or bootloader role)
|
||||
and the derived `chip`, `checksum`, `appended_sha256` and
|
||||
`undescribed_trailing` ranges. Segment rows (`segment-NN.bin`) carry
|
||||
`load_addr`, `classification` (`mapped`, `loaded`, `not-loaded` or `unknown`,
|
||||
per ESP-IDF `should_map`/`should_load`; RAM ranges are not checked) and
|
||||
`source_location`; select them with `inspect_analysis_view` and
|
||||
`logical_paths`. Signature blocks are `unverified`; `public_key_sha256`
|
||||
matches eFuse key digests.
|
||||
|
||||
Unknown `source_coverage` means truncation or undescribed trailing bytes, such
|
||||
as the flash segments of a `--ram-only-header` image; do not infer absence
|
||||
from it. Erased flash is described. Integrity mismatches are facts, not
|
||||
refusals. ESP8266 images are refused, and flash-encrypted images are not
|
||||
recognized. Segments are not disassembled, and RISC-V or Xtensa segments
|
||||
cannot be opened as raw-binary. See
|
||||
[ESP images](https://github.com/morluto/rea/blob/main/docs/esp-image.md).
|
||||
|
||||
## ESP flash images
|
||||
|
||||
A whole-flash dump opens as `esp-flash-image`. `root_format_metadata` holds
|
||||
`partition_table` (its `method`: `default`, `caller` or a derived
|
||||
`scan`), `bootloader` and `apps` ESP image facts, the `otadata` records,
|
||||
`partitions_outside_dump` and `boot_selection`. Every table has a
|
||||
`boot_selection`: its `basis` names the bootloader's branch (`no-otadata`
|
||||
without otadata, `none` when the bootloader rejects the table, `unknown`
|
||||
when a record is missing), and it lists its `assumptions`;
|
||||
`running_partition` is always `unknown`. Each image names its entry
|
||||
`path`. With `detail: "summary"` the root kind is `esp-flash-image-summary`
|
||||
and each image is a compact `summary` (chip, entry point, segment count,
|
||||
classified load ranges, signature block count, descriptor identity,
|
||||
integrity); complete detail keeps every segment. Partition rows
|
||||
(`partitions/<label>.bin`) carry the declared `type`, `subtype`, names,
|
||||
`flash_address`, `size` and flags; `encrypted` is a storage flag, not
|
||||
proof of ciphertext. `written_offset`/`written_end` bound the bytes that
|
||||
are not erased: an app slot whose facts say `erased` can still hold an older
|
||||
image, and a limitation says so. For a dump read from another flash address, call
|
||||
`open_binary` with `format: "esp-flash-image"` and `flash_offset`; an
|
||||
`esp-image` whose `flash_dump` is set names that offset in a next probe; a
|
||||
relocated table can be named with `partition_table_offset`. No table found
|
||||
means unknown, often flash encryption. Extraction writes `nvs_keys` as
|
||||
ordinary data. See
|
||||
[ESP flash images](https://github.com/morluto/rea/blob/main/docs/esp-flash-image.md).
|
||||
|
||||
## Bun standalone executables
|
||||
|
||||
A `bun build --compile` executable stores its module graph in Mach-O
|
||||
`__BUN,__bun`, a PE or ELF `.bun` section, or an appended trailer.
|
||||
`open_binary` then `inspect_artifact` reports root format `bun-standalone` with
|
||||
the carrier, structural layout, module count, entry point, raw flags and
|
||||
compile exec-argv; each module keeps its `/$bunfs/...` source name, loader,
|
||||
encoding, sizes and SHA-256, with sourcemap, bytecode and module-info regions as
|
||||
separate children. Use summary root metadata `entry_point_logical_path` as the
|
||||
exact inventory `logical_paths` selector, then read the selected content node by
|
||||
its artifact ID; the reader owns virtual-name normalization and indexed fallback. `extract-artifact` writes stored contents through the safe
|
||||
output tree; route extracted JavaScript to `analyze_javascript_application`.
|
||||
Layout labels describe record shapes, not a detected compiler version; unknown
|
||||
or ambiguous layouts are unsupported. Bytecode is retained, not decoded, and the
|
||||
executable is never run. See
|
||||
[Bun standalone executables](https://github.com/morluto/rea/blob/main/docs/bun-standalone.md).
|
||||
|
||||
## Deno compile executables
|
||||
|
||||
A `deno compile` executable stores its application in a Mach-O `__SUI,d3n0l4nd`
|
||||
section, an Intel Mach-O `<~sui-data~>` trailer, an ELF `SUI` note of type
|
||||
`0x53554901`, or a PE `RT_RCDATA` resource named `D3N0L4ND`.
|
||||
`open_binary` then `inspect_artifact` reports root format `deno-standalone`
|
||||
with the carrier, entry point, recorded options, and one occurrence per virtual
|
||||
file, including size and SHA-256. Transpiled output, CJS export analysis, and
|
||||
source maps are separate occurrences with the file's `index` and their own
|
||||
`role`. They normally use a `.deno-*` suffix on the file path and move to an
|
||||
indexed path on a collision, so use the reported `logical_path`. Symlink targets
|
||||
stay recorded path parts. A virtual filesystem that cannot be listed leaves
|
||||
coverage unknown.
|
||||
Environment-file values and CA certificate bytes are retained in local Evidence
|
||||
with their counts and byte lengths. The npm snapshot length is reported and not
|
||||
decoded. `extract-artifact` writes
|
||||
stored files through the safe output tree; route extracted JavaScript to
|
||||
`analyze_javascript_application`. Other layouts are unsupported, and the
|
||||
executable is never run. See
|
||||
[Deno compile executables](https://github.com/morluto/rea/blob/main/docs/deno-standalone.md).
|
||||
@@ -0,0 +1,140 @@
|
||||
# Runtime observation
|
||||
|
||||
## Native runtime questions
|
||||
|
||||
Start from the requested observation. State the selected target, input, expected
|
||||
result, failure signal and stopping condition before a run. Reuse static Evidence
|
||||
to choose a function or hypothesis; `trace_native_values` follows recovered
|
||||
static value dependencies and does not measure runtime values. Prefer static
|
||||
inspection or existing capture comparison when it already answers the question.
|
||||
|
||||
| Question | Existing workflow | Host and effects |
|
||||
| -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Which selected native entry is reached, with which integer argument registers? | `observe_native_calls` on the active Mach-O, with exact function/Objective-C breakpoints and a duration/event bound | macOS with LLDB and required debugger access. Launches a new owned process, stops at entries, records and continues; target execution may write files, show UI or use the network. It never attaches to an existing process. Inspect termination and partial coverage after the run. |
|
||||
| What does caller-authored instrumentation observe? | `list_frida_devices` / `list_frida_processes` when discovery is needed; `start_frida_session`, `load_frida_script`, then status/unload/close | Requires compatible installed Frida bindings and selected device access; the real REA verifier covers Linux. Attach selects an existing PID; spawn selects a program and starts it paused until `resume_frida_session`. Scripts execute in the target and can change memory, files, network activity and behavior. This is not passive inspection. |
|
||||
| Which debugger state or controlled execution explains the behavior? | `start_gdb_session` and `gdb_console`, or `start_rizin_debug_session` and `rizin_debug_command` | Persistent debugger workflows are Linux-only. GDB starts a debugger; console commands choose/load/attach/run targets. Rizin debug start launches the selected target and requires a durable `inferior_tty`. Both consoles are unrestricted and can change target memory/registers, run shell commands, write files and use the network. |
|
||||
| How do terminal output, process lifetime and selected files differ between runs? | `capture_process_scenario`, then `compare_process_captures` with compatible recorded inputs | New captures require Linux or macOS and a working native PTY backend; macOS also needs `xcrun`/Swift for ownership inspection. Capture launches an owned command with ordinary user permissions. Observation paths select snapshots, not a filesystem sandbox. Comparing retained captures does not execute targets and is also available on Windows. |
|
||||
| What does an existing desktop window show, or what changes after a declared UI action? | `observe_native_ui`; use `capture_native_ui_scenario` only for requested actions | macOS 14+ with required Screen Recording/Accessibility access. Select an existing PID/window. Observation does not launch or own the app; scenario actions can change its data or trigger network activity, and leave its state as-is. |
|
||||
|
||||
Close each persistent session with its matching tool. `close_frida_session`
|
||||
unloads scripts and detaches; it does not kill the target. A still-paused spawn
|
||||
is resumed only after instrumentation cleanup is confirmed. GDB and Rizin close
|
||||
can detach a live inferior and let it continue only after verifying its durable
|
||||
output terminal. When disposition or cleanup is unresolved, preserve the owned
|
||||
session and reported recovery; do not assume that closing the debugger terminated
|
||||
the target. Process capture and LLDB call observation instead own their launched
|
||||
processes and report their termination/cleanup outcome. Cancellation is not proof
|
||||
that cleanup completed.
|
||||
|
||||
Unrestricted GDB/Rizin commands and relevant start/close operations retire an
|
||||
active binary-analysis session in the same MCP server. Close an active Ghidra
|
||||
session explicitly first; after target effects settle, reopen the artifact before
|
||||
new static analysis. A Cutter bridge command is likewise unrestricted and may
|
||||
affect its GUI/target; it is not a passive native observation substitute.
|
||||
|
||||
To test a static hypothesis across two builds, retain compatible static
|
||||
comparison Evidence and `compare_process_captures` Evidence. Supply explicit
|
||||
finding/dimension mappings to `correlate_static_and_runtime`. It does not ingest
|
||||
arbitrary Frida, LLDB or debugger traces, auto-match names, or prove causality
|
||||
from cochange. Preserve those traces as their own Evidence and leave unobserved
|
||||
behavior unknown. Record truncation, unmatched breakpoints, changed target
|
||||
identity and cleanup uncertainty as limitations, rather than treating no retained
|
||||
event as proof that the behavior never occurs.
|
||||
|
||||
For same-session MCP comparisons, pass each capture inline or reuse it as
|
||||
`{"kind":"retained-evidence","evidence_id":"ev_..."}`. Default comparison
|
||||
keeps capture-local timing as provenance without treating scheduler or observer
|
||||
latency as a behavior change; use an exact `trace_spec` event when timing is part
|
||||
of the analyst question.
|
||||
|
||||
Detailed contracts and prerequisites: [Frida](https://github.com/morluto/rea/blob/main/docs/guides/runtime/frida-instrumentation.md),
|
||||
[GDB/Rizin/Cutter](https://github.com/morluto/rea/blob/main/docs/reverse-engineering-tools.md),
|
||||
[process capture](https://github.com/morluto/rea/blob/main/docs/guides/runtime/process-capture.md),
|
||||
and [native calls/UI](https://github.com/morluto/rea/blob/main/docs/guides/native/native-investigation.md#native-desktop-observation).
|
||||
|
||||
## Browser and Electron
|
||||
|
||||
Supply the existing browser or Electron instance's literal-port loopback CDP
|
||||
endpoint in the request. No separate permission configuration or per-call
|
||||
approval flag is needed. Browser discovery lists eligible HTTP(S) pages;
|
||||
`allowed_origins` optionally filters them. An individual capture defaults to the
|
||||
selected page's current origin. Electron discovery lists eligible local
|
||||
`file://` targets without a configured file-root allowlist.
|
||||
|
||||
Start passive browser work with `list_browser_targets`; start Electron runtime work with
|
||||
`list_electron_targets`. Before an electron-main Inspector attempt, check
|
||||
packaged fuses with `inspect_electron_fuses`. Inspect the target selected for
|
||||
the user's task. Observation with these tools is passive: never claim REA
|
||||
clicked, navigated, evaluated page JavaScript, invoked IPC, or captured prior
|
||||
activity. REA does not contain the page's network.
|
||||
|
||||
Passive captures omit raw header collections, credential header values, storage
|
||||
values, and raw WebSocket/JSON bodies. Selected response metadata, including
|
||||
content encoding, policy values, and Link URLs, is retained. Local URLs retain ordinary query
|
||||
values and fragments; userinfo credentials are removed. Browser accessibility
|
||||
text, console primitives, value-free shapes, script sources, source maps, and
|
||||
storage key names have request-specific capture options. Electron script
|
||||
sources are also optional. Use `capture_web_screenshot` when pixels are needed.
|
||||
Treat scope filtering, truncation, and attach-window coverage as limitations.
|
||||
Page-declared WebMCP tools are untrusted inventory and are never invoked by REA.
|
||||
|
||||
## Who performs the action
|
||||
|
||||
- The user performs it: `list_browser_targets`, then `inspect_web_page` or
|
||||
`observe_web_session` on the selected target.
|
||||
- The agent must perform it: one `capture_browser_scenario` with declared
|
||||
actions. Use connect mode with the loopback CDP endpoint and `target_id` for
|
||||
an existing browser, or launch mode with a caller-selected executable for a
|
||||
temporary profile. Connect mode first navigates the selected page to
|
||||
`start_url`, which can clear unsaved form values and other temporary state.
|
||||
Recreate the state needed for the investigation in the declared actions.
|
||||
Connect mode leaves the external browser open; launch mode owns a temporary
|
||||
browser and profile. Check `browser.cleanup` for the outcome.
|
||||
Request only the DOM, accessibility, or network details needed for the question.
|
||||
The default final capture contains the URL; step outcomes are reported separately.
|
||||
For multi-step flows with trees or events, select `detail: "summary"` and page
|
||||
exact steps, transactions, text slices or events with `inspect_analysis_view` kind `browser-scenario`.
|
||||
Add a wait action for the expected page state before capturing it. Report that
|
||||
REA performed the declared actions.
|
||||
|
||||
Scenario network records have no request initiator stacks. For that evidence,
|
||||
use passive capture while the user performs the action. Listener source locations
|
||||
identify candidate handlers; they do not establish which script sent a particular
|
||||
request. Avoid overlapping passive capture and scenario actions on the same target.
|
||||
|
||||
Focused follow-up tools:
|
||||
|
||||
- `observe_web_execution`: execution coverage during a window; it resets
|
||||
counters and temporarily disables optimization.
|
||||
- `inspect_web_event_listeners`: source locations for listeners registered
|
||||
directly on the first CSS match, without dispatching an event.
|
||||
- `compare_web_captures`: two normalized passive captures or recorded scenarios.
|
||||
- `discover_webmcp_tools`: inspect page-declared WebMCP inventory; never invoke
|
||||
the discovered tools.
|
||||
|
||||
Use `reconcile_javascript_runtime` only after static application Evidence and
|
||||
passive browser/Electron Evidence exist. Prefer captured-source digest identity;
|
||||
report path/digest disagreement as a mismatch and preserve ambiguity. Explicit
|
||||
path mappings are inference inputs and never broaden filesystem or CDP authority.
|
||||
A bundle observed at runtime does not prove every contained module executed.
|
||||
|
||||
## Fiddler Everywhere traffic debugging
|
||||
|
||||
For large saved captures, request `detail: "summary"`, then page retained Evidence
|
||||
with `inspect_analysis_view` and `view: {kind: "capture", detail: "preview", offset: 0, limit: 20}`.
|
||||
Select complete record pages only for needed headers, metadata or payloads; views
|
||||
read the historical parent without repeating capture decoding.
|
||||
|
||||
For selected protobuf/gRPC bodies, keep raw bytes as the source and use
|
||||
`inspect_analysis_view` kind `protobuf`, collection `bodies`, `frames` or
|
||||
`fields`. Batch exact record ordinals and field numbers/IDs, and select
|
||||
`schema_value` or `text` only when needed. Supply a local descriptor set and
|
||||
message type for schema interpretation; compressed payloads remain unknown.
|
||||
|
||||
Inspect native `.saz` snapshots with `inspect_web_network_capture` and
|
||||
`format: "saz"`; encrypted archives are unsupported. For live
|
||||
traffic analysis, connect Everywhere's separate MCP server and use its
|
||||
advertised session tools with an explicit `sessionsSource` (`LiveTraffic` or
|
||||
`AgentCalls`). Preserve existing sessions and filters when inspecting a
|
||||
recorded run. See the [capture and MCP guide](https://github.com/morluto/rea/blob/main/docs/guides/web/web-network-captures.md)
|
||||
for the workflow and Telerik's public setup and traffic-debugging skills.
|
||||
@@ -755,7 +755,9 @@ jobs:
|
||||
needs: [changes, static, build]
|
||||
if: needs.changes.outputs.apple == 'true'
|
||||
runs-on: macos-15
|
||||
timeout-minutes: 15
|
||||
# Passing runs take 10-15 minutes on macOS runners of varying speed, so a
|
||||
# 15-minute budget cancelled about a third of runs. Keep a hang bounded.
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
|
||||
@@ -14,7 +14,8 @@ permissions:
|
||||
|
||||
concurrency:
|
||||
group: codeql-production-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
# Let a main-branch baseline finish; supersede stale pull-request scans only.
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
@@ -52,7 +53,7 @@ jobs:
|
||||
threads: 2
|
||||
ram: 4096
|
||||
- name: Retain complete analysis evidence
|
||||
if: always()
|
||||
if: always() && !cancelled()
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: codeql-production-${{ matrix.language }}
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
node-version-file: .nvmrc
|
||||
- name: Validate the SDK pin against the provider's verified release
|
||||
run: node scripts/verify-ghidra-bridge-sources.mjs --check-sdk-pin >> "$GITHUB_ENV"
|
||||
# The bridge probe imports only source-owned ARM/Thumb bytes and never
|
||||
# The bridge probe imports only source-owned ARM, Thumb and MIPS bytes and never
|
||||
# executes target code. All SDK/project state stays in runner storage.
|
||||
- name: Acquire checksum-verified Ghidra SDK in isolated runner storage
|
||||
shell: bash
|
||||
@@ -46,7 +46,7 @@ jobs:
|
||||
java_home_variable="JAVA_HOME_${GHIDRA_JAVA_MAJOR}_X64"
|
||||
test -n "${!java_home_variable}"
|
||||
JAVA_HOME="${!java_home_variable}" npm run verify:ghidra:bridge-sources -- --verified-sdk
|
||||
- name: Inspect real ARM and Thumb instruction context through the bridge
|
||||
- name: Inspect real ARM, Thumb and MIPS instruction context through the bridge
|
||||
shell: bash
|
||||
run: |
|
||||
java_home_variable="JAVA_HOME_${GHIDRA_JAVA_MAJOR}_X64"
|
||||
@@ -58,10 +58,21 @@ jobs:
|
||||
-import "${probe_root}/arm-thumb.bin" -loader BinaryLoader -processor ARM:LE:32:v7 \
|
||||
-noanalysis -readOnly -deleteProject \
|
||||
-scriptPath "${GITHUB_WORKSPACE}/tests/conformance/ghidra;${GITHUB_WORKSPACE}/bridge/ghidra" \
|
||||
-postScript ReaArmContextProbe.java "${GITHUB_WORKSPACE}/bridge/ghidra" \
|
||||
-postScript ReaInstructionContextProbe.java "${GITHUB_WORKSPACE}/bridge/ghidra" \
|
||||
> "${probe_root}/output.log" 2>&1 || { cat "${probe_root}/output.log"; exit 1; }
|
||||
cat "${probe_root}/output.log"
|
||||
grep -F 'REA_ARM_CONTEXT_OK arm=0 thumb=1 unavailable=null (injected provider value)' "${probe_root}/output.log"
|
||||
mkdir -p "${probe_root}/mips-project"
|
||||
# MIPS32 addiu v0,a0,3; MIPS16 li v0,90. These bytes are never executed.
|
||||
printf '\003\000\202\044\132\152\000\000' > "${probe_root}/mips.bin"
|
||||
timeout 180s "${GHIDRA_INSTALL_DIR}/support/analyzeHeadless" "${probe_root}/mips-project" MipsContext \
|
||||
-import "${probe_root}/mips.bin" -loader BinaryLoader -processor MIPS:LE:32:default \
|
||||
-noanalysis -readOnly -deleteProject \
|
||||
-scriptPath "${GITHUB_WORKSPACE}/tests/conformance/ghidra;${GITHUB_WORKSPACE}/bridge/ghidra" \
|
||||
-postScript ReaInstructionContextProbe.java "${GITHUB_WORKSPACE}/bridge/ghidra" mips \
|
||||
> "${probe_root}/mips-output.log" 2>&1 || { cat "${probe_root}/mips-output.log"; exit 1; }
|
||||
cat "${probe_root}/mips-output.log"
|
||||
grep -F 'REA_MIPS_CONTEXT_OK standard=0 mips16=1' "${probe_root}/mips-output.log"
|
||||
# Each probe imports source-owned bytes at 0x1000, away from the Cortex-M
|
||||
# vector symbols that ARMCortex.pspec defines at 0, and decodes them from
|
||||
# the language's default context, so M-profile Thumb state must hold at
|
||||
|
||||
@@ -56,7 +56,8 @@ jobs:
|
||||
run: |
|
||||
capture_tool_root="${RUNNER_TEMP}/rea-mitmproxy-12.2.3"
|
||||
mkdir -p "${capture_tool_root}"
|
||||
curl --fail --location --retry 3 --max-time 180 \
|
||||
# This immutable GET may reset mid-body; retry it before checksum verification.
|
||||
curl --fail --location --retry 3 --retry-all-errors --max-time 180 \
|
||||
https://downloads.mitmproxy.org/12.2.3/mitmproxy-12.2.3-linux-x86_64.tar.gz \
|
||||
--output "${capture_tool_root}/mitmproxy.tar.gz"
|
||||
echo '2e95286b618fa6fd33e5e62a78c2e5112571d85f42ec2bac29b97ee242bdb5c5 mitmproxy.tar.gz' \
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
"package-lock.json",
|
||||
".claude-plugin/plugin.json",
|
||||
".codex-plugin/plugin.json",
|
||||
".cursor-plugin/plugin.json",
|
||||
"mcp.json",
|
||||
"_reference/**",
|
||||
"third_party/**",
|
||||
".codex-plugin/mcp.json"
|
||||
|
||||
+24
-1
@@ -63,6 +63,18 @@
|
||||
"rea/no-shared-module-mock": "error"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["src/domain/**/*.ts"],
|
||||
"rules": { "rea/no-locale-compare": "error" }
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"src/domain/**/*.test.ts",
|
||||
"src/domain/**/*.spec.ts",
|
||||
"src/domain/**/*.fixture.ts"
|
||||
],
|
||||
"rules": { "rea/no-locale-compare": "off" }
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"scripts/electron-active-hook*.cjs",
|
||||
@@ -76,12 +88,19 @@
|
||||
{
|
||||
"files": ["src/**/*.ts"],
|
||||
"rules": {
|
||||
"rea/no-babel-visitor-keys": "error",
|
||||
"typescript/no-misused-promises": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["tests/**/*.ts", "src/**/*.test.ts", "src/**/*.fixture.ts"],
|
||||
"files": [
|
||||
"tests/**/*.ts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.fixture.ts"
|
||||
],
|
||||
"rules": {
|
||||
"rea/no-babel-visitor-keys": "off",
|
||||
"max-lines": "off",
|
||||
"max-lines-per-function": [
|
||||
"error",
|
||||
@@ -94,6 +113,10 @@
|
||||
"typescript/no-misused-promises": "warn"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["src/domain/javascript/javascriptSemanticTraversal.ts"],
|
||||
"rules": { "rea/no-babel-visitor-keys": "off" }
|
||||
},
|
||||
{
|
||||
"files": ["src/application/**/*.test.ts"],
|
||||
"rules": {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
".": "6.8.0"
|
||||
".": "6.9.0"
|
||||
}
|
||||
+142
@@ -1,5 +1,147 @@
|
||||
# Changelog
|
||||
|
||||
## [6.9.0](https://github.com/morluto/rea/compare/rea-agents-6.8.0...rea-agents-6.9.0) (2026-11-11)
|
||||
|
||||
### Highlights
|
||||
|
||||
- Build and test desktop tasks from recorded application state, including downloaded Linux apps, reusable build computers and multiple tasks per capture.
|
||||
- Inspect more shipped artifacts offline: standalone application bundles, embedded firmware, NTFS acquisitions, API contracts and V8 code-cache containers.
|
||||
- Keep native and runtime investigations grounded in retained Evidence, with paged results, explicit coverage and recoverable resource limits.
|
||||
|
||||
### Changes
|
||||
|
||||
- Analyze targets and create private runtimes on fixed local ReFS volumes as well as NTFS, preserving persistent ACL, file identity, snapshot and cleanup checks. [#10086](https://github.com/morluto/rea/pull/10086). Thanks @QianNangong.
|
||||
- Capture, export and witness desktop tasks inside a build computer; keep an agentenv computer available through MCP and prepare a build host from one command. [#8954](https://github.com/morluto/rea/pull/8954), [#9041](https://github.com/morluto/rea/pull/9041), [#9045](https://github.com/morluto/rea/pull/9045), [#9049](https://github.com/morluto/rea/pull/9049), [#9199](https://github.com/morluto/rea/pull/9199). Thanks @earakely-scale.
|
||||
- Install desktop apps from SHA-256-pinned AppImages or upstream archives, retain selected package dependencies, and isolate explicitly declared build secrets. [#9215](https://github.com/morluto/rea/pull/9215), [#9112](https://github.com/morluto/rea/pull/9112), [#9225](https://github.com/morluto/rea/pull/9225). Thanks @earakely-scale.
|
||||
- Choose seed/end checkpoints, open seed documents at launch, build several tasks from one capture, and evaluate unreadable app state through headless checks or a screen judge. [#9037](https://github.com/morluto/rea/pull/9037), [#9054](https://github.com/morluto/rea/pull/9054), [#9216](https://github.com/morluto/rea/pull/9216), [#9217](https://github.com/morluto/rea/pull/9217), [issue morluto/rea#9676](https://github.com/morluto/rea/issues/9676). Thanks @earakely-scale.
|
||||
- Read gzip and XML desktop documents and draft assertions for nested fields, attribute text, child text and member counts. [#9050](https://github.com/morluto/rea/pull/9050), [#9111](https://github.com/morluto/rea/pull/9111), [#9114](https://github.com/morluto/rea/pull/9114), [#9132](https://github.com/morluto/rea/pull/9132), [#9185](https://github.com/morluto/rea/pull/9185). Thanks @earakely-scale.
|
||||
- Inventory and extract .NET single-file, Bun standalone and Deno compile executables, with caller-selected entries and output destinations. [#3787](https://github.com/morluto/rea/pull/3787), [#4031](https://github.com/morluto/rea/pull/4031), [#6998](https://github.com/morluto/rea/pull/6998), [#8527](https://github.com/morluto/rea/pull/8527), [issue morluto/rea#2352](https://github.com/morluto/rea/issues/2352), [issue morluto/rea#3490](https://github.com/morluto/rea/issues/3490). Thanks @gensokyo-dev, @jsk1004ha, @matbrgz, @mvanhorn, @Rinkia, @Zhong-fan.
|
||||
- Read UnityFS bundles, Godot 3 PCK archives, WeChat mini-program packages, Zstandard ZIP members and classic iNES regions. [#7699](https://github.com/morluto/rea/pull/7699), [#7781](https://github.com/morluto/rea/pull/7781), [#8148](https://github.com/morluto/rea/pull/8148), [#7780](https://github.com/morluto/rea/pull/7780), [#2816](https://github.com/morluto/rea/pull/2816). Thanks @blankym, @gensokyo-dev, @ShuaixinHuang, @XiaoBinGan, @Zhong-fan.
|
||||
- Inspect and extract Intel HEX, Motorola S-record, U-Boot uImage/FIT, ESP flash, UF2 and DfuSe firmware regions while retaining their container declarations. [#7136](https://github.com/morluto/rea/pull/7136), [#7234](https://github.com/morluto/rea/pull/7234), [#7771](https://github.com/morluto/rea/pull/7771), [#7498](https://github.com/morluto/rea/pull/7498), [#8228](https://github.com/morluto/rea/pull/8228), [#8230](https://github.com/morluto/rea/pull/8230). Thanks @555aaditya, @Entrpi, @gensokyo-dev, @iamcipherdev.
|
||||
- Inventory offline NTFS MFT records and paired USN journal acquisitions; retain source names, journal-version coverage and verified extension-attribute ownership. [#9911](https://github.com/morluto/rea/pull/9911), [#9914](https://github.com/morluto/rea/pull/9914), [#9957](https://github.com/morluto/rea/pull/9957), [#10006](https://github.com/morluto/rea/pull/10006), [issue morluto/rea#9867](https://github.com/morluto/rea/issues/9867). Thanks @2SinceJuly, @gensokyo-dev, @jayykernel, @N0zoM1z0.
|
||||
- Inspect V8 code-cache headers and retained byte patterns without executing the cache; report Electron cachedData boundaries and custom URL protocol registrations. [#8993](https://github.com/morluto/rea/pull/8993), [#9501](https://github.com/morluto/rea/pull/9501), [#2978](https://github.com/morluto/rea/pull/2978). Thanks @2SinceJuly, @gensokyo-dev, @UnknownHacker1, @XiaoBinGan.
|
||||
- Inventory local OpenAPI operations and GraphQL SDL fields/references; compare static JavaScript endpoints with HAR observations. [#9104](https://github.com/morluto/rea/pull/9104), [#9140](https://github.com/morluto/rea/pull/9140), [#9090](https://github.com/morluto/rea/pull/9090), [issue morluto/rea#3591](https://github.com/morluto/rea/issues/3591). Thanks @gensokyo-dev, @Y0UW1SH.
|
||||
- Import saved Playwright v10 trace Evidence, page scenario summaries, reuse saved response values across steps, and validate browser scenarios offline. [#9127](https://github.com/morluto/rea/pull/9127), [#7120](https://github.com/morluto/rea/pull/7120), [#7267](https://github.com/morluto/rea/pull/7267), [#7343](https://github.com/morluto/rea/pull/7343), [issue morluto/rea#5488](https://github.com/morluto/rea/issues/5488), [issue morluto/rea#6167](https://github.com/morluto/rea/issues/6167). Thanks @debavelaerel, @earakely-scale, @gensokyo-dev, @jayykernel, @kaoru0822-kitauji, @z2Ace0107.
|
||||
- Replay captured environment writes, including variable member sets, sorted creates, references, toggles and subsequent reads that explain the resulting state. [#7260](https://github.com/morluto/rea/pull/7260), [#7274](https://github.com/morluto/rea/pull/7274), [#7332](https://github.com/morluto/rea/pull/7332), [#7539](https://github.com/morluto/rea/pull/7539), [#7600](https://github.com/morluto/rea/pull/7600). Thanks @earakely-scale.
|
||||
- Apply selected R8 mappings, inspect Android manifest component declarations, link static JNI candidates and trace callers of external DEX methods. [#7456](https://github.com/morluto/rea/pull/7456), [#7379](https://github.com/morluto/rea/pull/7379), [#7472](https://github.com/morluto/rea/pull/7472), [#8154](https://github.com/morluto/rea/pull/8154), [issue morluto/rea#4448](https://github.com/morluto/rea/issues/4448), [issue morluto/rea#6329](https://github.com/morluto/rea/issues/6329), [issue morluto/rea#6403](https://github.com/morluto/rea/issues/6403), [issue morluto/rea#7811](https://github.com/morluto/rea/issues/7811). Thanks @555aaditya, @coygeek, @gensokyo-dev, @harshjohiya, @jayykernel, @Rinkia, @xu91102.
|
||||
- Expose managed field defaults, project retained member views, suggest Unity managed members and retain IL2CPP v108 header/string Evidence. [#8015](https://github.com/morluto/rea/pull/8015), [#7968](https://github.com/morluto/rea/pull/7968), [#5511](https://github.com/morluto/rea/pull/5511), [#9925](https://github.com/morluto/rea/pull/9925), [issue morluto/rea#7282](https://github.com/morluto/rea/issues/7282). Thanks @379061296, @8rulerstar, @dhruvac29, @Entrpi, @gensokyo-dev, @Henglie, @kaoru0822-kitauji, @ShuaixinHuang, @XiaoBinGan, @xu91102.
|
||||
- Report ELF/PE/Mach-O hardening, per-slice Mach-O encryption, initializer/finalizer functions and ELF function ranges recovered from unwind tables. [#8524](https://github.com/morluto/rea/pull/8524), [#5359](https://github.com/morluto/rea/pull/5359), [#9574](https://github.com/morluto/rea/pull/9574), [#9585](https://github.com/morluto/rea/pull/9585), [issue morluto/rea#4306](https://github.com/morluto/rea/issues/4306). Thanks @chordpli, @coygeek, @gensokyo-dev, @mvanhorn.
|
||||
- Read Linux core-dump process/mapping notes, kernel version/configuration data and Android ELF identity notes; join Apple IPS images to admitted Mach-O slices. [#8830](https://github.com/morluto/rea/pull/8830), [#9573](https://github.com/morluto/rea/pull/9573), [#9502](https://github.com/morluto/rea/pull/9502), [#9570](https://github.com/morluto/rea/pull/9570). Thanks @2SinceJuly, @mvanhorn, @rishikeshgowdakk, @saariuslystoned.
|
||||
- Open native extension/framework/XPC/plugin bundles, retain LLDB source coordinates and recover bounded Go string literals from pointer/length headers. [#8117](https://github.com/morluto/rea/pull/8117), [#2800](https://github.com/morluto/rea/pull/2800), [#9206](https://github.com/morluto/rea/pull/9206). Thanks @kaoru0822-kitauji, @matbrgz, @saariuslystoned.
|
||||
- Reuse Ghidra projects through verified copies and checkpoint owned Programs across sessions; add Windows P0 DOS MZ and RISC-V ilp32 admission. [#7236](https://github.com/morluto/rea/pull/7236), [#9236](https://github.com/morluto/rea/pull/9236), [#7144](https://github.com/morluto/rea/pull/7144), [#8229](https://github.com/morluto/rea/pull/8229), [issue morluto/rea#1048](https://github.com/morluto/rea/issues/1048). Thanks @akushonkamen, @corysutyak, @dark13b, @Entrpi, @gensokyo-dev.
|
||||
- Retry failed Kuna or directory decompiles independently and preserve stored pointer references and decompile-export source facts. [#8793](https://github.com/morluto/rea/pull/8793), [#8811](https://github.com/morluto/rea/pull/8811), [#8851](https://github.com/morluto/rea/pull/8851), [#8805](https://github.com/morluto/rea/pull/8805).
|
||||
- Read selected Evidence records and discover missing links without transferring whole bundles; aggregate retained comparison references and compare artifact inventories. [#8528](https://github.com/morluto/rea/pull/8528), [#8633](https://github.com/morluto/rea/pull/8633), [#8267](https://github.com/morluto/rea/pull/8267), [#7869](https://github.com/morluto/rea/pull/7869), [issue morluto/rea#7678](https://github.com/morluto/rea/issues/7678), [issue morluto/rea#8214](https://github.com/morluto/rea/issues/8214), [issue morluto/rea#8307](https://github.com/morluto/rea/issues/8307), [issue morluto/rea#8454](https://github.com/morluto/rea/issues/8454). Thanks @Entrpi, @gensokyo-dev, @kaoru0822-kitauji.
|
||||
- Page retained native observations, procedure/instruction references, feature traces and batch decompile summaries instead of repeating complete results. [#7134](https://github.com/morluto/rea/pull/7134), [#7146](https://github.com/morluto/rea/pull/7146), [#8585](https://github.com/morluto/rea/pull/8585), [#8588](https://github.com/morluto/rea/pull/8588), [#8591](https://github.com/morluto/rea/pull/8591), [#8594](https://github.com/morluto/rea/pull/8594), [#8629](https://github.com/morluto/rea/pull/8629), [#8631](https://github.com/morluto/rea/pull/8631), [issue morluto/rea#8498](https://github.com/morluto/rea/issues/8498), [issue morluto/rea#8510](https://github.com/morluto/rea/issues/8510). Thanks @gensokyo-dev, @kaoru0822-kitauji.
|
||||
- Expose guided workflows and installed guidance search through CLI/MCP, recover from common argument-name mistakes, and support CSV/TSV analysis views. [#6995](https://github.com/morluto/rea/pull/6995), [#6996](https://github.com/morluto/rea/pull/6996), [#8305](https://github.com/morluto/rea/pull/8305), [#8649](https://github.com/morluto/rea/pull/8649), [#7254](https://github.com/morluto/rea/pull/7254), [issue morluto/rea#2146](https://github.com/morluto/rea/issues/2146), [issue morluto/rea#5482](https://github.com/morluto/rea/issues/5482), [issue morluto/rea#6916](https://github.com/morluto/rea/issues/6916), [issue morluto/rea#6918](https://github.com/morluto/rea/issues/6918), [issue morluto/rea#8290](https://github.com/morluto/rea/issues/8290). Thanks @coygeek, @Deepak-Kambala, @gensokyo-dev, @HarsH-1877, @jayykernel, @kaoru0822-kitauji, @pablodiazjorge, @Tapraj-Pathak.
|
||||
- Select MCP tool families and compact output schemas; refresh provider candidates without switching and inspect provider-selection/release-verification diagnostics. [#7228](https://github.com/morluto/rea/pull/7228), [#7218](https://github.com/morluto/rea/pull/7218), [#8487](https://github.com/morluto/rea/pull/8487), [#8485](https://github.com/morluto/rea/pull/8485), [#9171](https://github.com/morluto/rea/pull/9171), [#9603](https://github.com/morluto/rea/pull/9603), [issue morluto/rea#2512](https://github.com/morluto/rea/issues/2512), [issue morluto/rea#3246](https://github.com/morluto/rea/issues/3246), [issue morluto/rea#8403](https://github.com/morluto/rea/issues/8403), [issue morluto/rea#9134](https://github.com/morluto/rea/issues/9134), [issue morluto/rea#9136](https://github.com/morluto/rea/issues/9136). Thanks @0xLLVEL, @2SinceJuly, @akshad-exe, @codebuff-team, @gensokyo-dev, @Henglie, @phucicb-hub, @wu546526.
|
||||
- Add non-executing process-scenario dry runs, opt-in command timings and caller-selected reference-source exclusions. [#8469](https://github.com/morluto/rea/pull/8469), [#7042](https://github.com/morluto/rea/pull/7042), [#2630](https://github.com/morluto/rea/pull/2630), [issue morluto/rea#2443](https://github.com/morluto/rea/issues/2443), [issue morluto/rea#5484](https://github.com/morluto/rea/issues/5484), [issue morluto/rea#8398](https://github.com/morluto/rea/issues/8398). Thanks @2SinceJuly, @dhruvac29, @gensokyo-dev, @jayykernel, @matbrgz, @trackoor, @YunzhouLi-hub.
|
||||
- Make resource-budget failures actionable across CLI/MCP and read per-call limits from the selected operation snapshot. [#9706](https://github.com/morluto/rea/pull/9706), [#9889](https://github.com/morluto/rea/pull/9889), [issue morluto/rea#9881](https://github.com/morluto/rea/issues/9881).
|
||||
- Ship self-contained Claude Code/Codex plugin installs and a Cursor Marketplace plugin; add CodeBuddy and LM Studio setup registration. [#7514](https://github.com/morluto/rea/pull/7514), [#9878](https://github.com/morluto/rea/pull/9878), [#2492](https://github.com/morluto/rea/pull/2492), [#8611](https://github.com/morluto/rea/pull/8611), [issue morluto/rea#2490](https://github.com/morluto/rea/issues/2490). Thanks @cainiao1992, @cpruijsen, @GamerDubz, @gensokyo-dev.
|
||||
- Inspect Windows Shell Link files and qualify recognized Python 3.14/3.15 pyc headers; choose Rizin decoder and map address for one-shot commands. [#7859](https://github.com/morluto/rea/pull/7859), [#8927](https://github.com/morluto/rea/pull/8927), [#8991](https://github.com/morluto/rea/pull/8991), [issue morluto/rea#8206](https://github.com/morluto/rea/issues/8206). Thanks @Entrpi, @mvanhorn, @XiaoBinGan, @xuanhieu.
|
||||
- Register REA with Cline through its native MCP client settings during setup. [#10128](https://github.com/morluto/rea/pull/10128), [issue morluto/rea#10127](https://github.com/morluto/rea/issues/10127). Thanks @bramrahmadi.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Keep UnityFS directory and payload reads within the declared bundle, reject undersized declarations, and prevent appended bytes from replacing the inventory or increasing its work budget. [58a0511660](https://github.com/morluto/rea/commit/58a051166047442b947c604c3f7ccde6707ee9df).
|
||||
- Validate runtime configuration before doctor reports readiness or registration writes files; preserve the source of malformed stored settings and proposed overrides. [#10102](https://github.com/morluto/rea/pull/10102).
|
||||
- Retry owned inspection descriptors before fresh process queries, preserve physical failures alongside cancellation, and retain cleanup authority until release succeeds. [#10113](https://github.com/morluto/rea/pull/10113), [#10141](https://github.com/morluto/rea/pull/10141), [#10109](https://github.com/morluto/rea/pull/10109).
|
||||
- Keep distinct linker-map occurrences when source-map declarations overlap, including path spellings that normalize to the same location. [aa017c61ff](https://github.com/morluto/rea/commit/aa017c61ff3803dea3b823664ae255c4059c19d4), [f668c86271](https://github.com/morluto/rea/commit/f668c862717fd1c63c649a04709191bbe86e4479).
|
||||
- Preserve remote OpenCode registrations and Hermes YAML anchor consumers instead of treating REA-like text as proof of local ownership. [#5152](https://github.com/morluto/rea/pull/5152), [issue morluto/rea#3325](https://github.com/morluto/rea/issues/3325). Thanks @coygeek, @gensokyo-dev, @xu91102.
|
||||
- Reject malformed UTF-8 CDP discovery replies, preserve partial Playwright-import Evidence, and retain initial child scope when replaying WebMCP scripts. [#4524](https://github.com/morluto/rea/pull/4524), [#9543](https://github.com/morluto/rea/pull/9543). Thanks @Afloat16, @Plastic-time.
|
||||
- Report unsupported filesystem paths and host-capacity failures at the responsible adb input boundary; retain local filesystem error provenance. [#6188](https://github.com/morluto/rea/pull/6188). Thanks @chordpli.
|
||||
- Preserve uncertainty when JavaScript alias walks exhaust their budget, keep unisolated program-var routes unknown, and analyze first-party code before dependencies. [#9387](https://github.com/morluto/rea/pull/9387), [#6778](https://github.com/morluto/rea/pull/6778), [#9341](https://github.com/morluto/rea/pull/9341), [issue morluto/rea#8201](https://github.com/morluto/rea/issues/8201), [issue morluto/rea#9321](https://github.com/morluto/rea/issues/9321). Thanks @gongfpp, @mvanhorn, @Rfxan, @xuanhieu, @yaneyba.
|
||||
- Resolve relative ESM backslash paths and exported/computed initializers; reject TLS versions and child-process literals Node itself refuses. [#4323](https://github.com/morluto/rea/pull/4323), [#5387](https://github.com/morluto/rea/pull/5387), [#9557](https://github.com/morluto/rea/pull/9557), [#9594](https://github.com/morluto/rea/pull/9594), [issue morluto/rea#4269](https://github.com/morluto/rea/issues/4269). Thanks @6eanut, @ahmed-husssain, @coygeek, @XiaoBinGan.
|
||||
- Validate PE certificate alignment, name structures and RDN grouping, and distinguish legacy Windows targets before PE header admission. [#9276](https://github.com/morluto/rea/pull/9276), [#9625](https://github.com/morluto/rea/pull/9625), [#10048](https://github.com/morluto/rea/pull/10048), [#10070](https://github.com/morluto/rea/pull/10070), [issue morluto/rea#10003](https://github.com/morluto/rea/issues/10003), [issue morluto/rea#9946](https://github.com/morluto/rea/issues/9946). Thanks @AixSxT, @coygeek, @gensokyo-dev, @N0zoM1z0, @ShuaixinHuang, @wunianze666-netizen.
|
||||
- Retain UTF-8 ZIP names in desktop exports, resolve nested desktop-entry IDs, and preserve reader inspection failures. [#9431](https://github.com/morluto/rea/pull/9431), [#9563](https://github.com/morluto/rea/pull/9563), [#9773](https://github.com/morluto/rea/pull/9773), [issue morluto/rea#9449](https://github.com/morluto/rea/issues/9449), [issue morluto/rea#9558](https://github.com/morluto/rea/issues/9558), [issue morluto/rea#9766](https://github.com/morluto/rea/issues/9766). Thanks @2SinceJuly, @ShuaixinHuang, @xu91102.
|
||||
- Report the actual link-time kernel banner, list ELF initializers in images with COPY relocations, and leave cross-code-page shortcut-icon comparisons unknown. [#9690](https://github.com/morluto/rea/pull/9690), [#10084](https://github.com/morluto/rea/pull/10084), [#9691](https://github.com/morluto/rea/pull/9691), [issue morluto/rea#9688](https://github.com/morluto/rea/issues/9688), [issue morluto/rea#9689](https://github.com/morluto/rea/issues/9689). Thanks @Plastic-time, @thunderq10.
|
||||
- Retain actionable debugger/provider failures: reconnect stale JEB MCP sessions, preserve GDB inferior-TTY checks, and report invalid IDA regex syntax. [#3754](https://github.com/morluto/rea/pull/3754), [#5539](https://github.com/morluto/rea/pull/5539), [#9544](https://github.com/morluto/rea/pull/9544), [issue morluto/rea#5099](https://github.com/morluto/rea/issues/5099). Thanks @akushonkamen, @coygeek, @flitzrrr, @Plastic-time.
|
||||
- Keep missing native call-input bindings and exhausted MCP discovery pages distinct from absence. [#10088](https://github.com/morluto/rea/pull/10088), [#10017](https://github.com/morluto/rea/pull/10017), [issue morluto/rea#8358](https://github.com/morluto/rea/issues/8358), [issue morluto/rea#9995](https://github.com/morluto/rea/issues/9995). Thanks @coygeek, @gensokyo-dev, @N0zoM1z0.
|
||||
- Preserve admitted EVM and pwntools replies and completed SQLite member facts through acquisition/finalization failures. [d77cf61](https://github.com/morluto/rea/commit/d77cf6186631743025a1bafb8c5a27262da6128e), [e813c4c](https://github.com/morluto/rea/commit/e813c4c344d2414d1b8dfe42a421792d91b01dcc), [669e617](https://github.com/morluto/rea/commit/669e617eec5422ebce1ab271af0fc7b51e90dc11).
|
||||
- Attribute keyed-archive errors to the archive argument, distinguish launcher failures from registry errors, and validate capture limiters before starting work. [#7731](https://github.com/morluto/rea/pull/7731), [#7843](https://github.com/morluto/rea/pull/7843), [#7947](https://github.com/morluto/rea/pull/7947), [issue morluto/rea#7292](https://github.com/morluto/rea/issues/7292), [issue morluto/rea#7597](https://github.com/morluto/rea/issues/7597), [issue morluto/rea#7630](https://github.com/morluto/rea/issues/7630), [issue morluto/rea#7638](https://github.com/morluto/rea/issues/7638). Thanks @coygeek, @gensokyo-dev.
|
||||
- Preserve unknown CDP coordinates and prior-hop response facts, deduplicate scenario guidance and recognize AppKit cell ownership. [#7842](https://github.com/morluto/rea/pull/7842), [#7807](https://github.com/morluto/rea/pull/7807), [#7933](https://github.com/morluto/rea/pull/7933), [#7916](https://github.com/morluto/rea/pull/7916), [issue morluto/rea#7342](https://github.com/morluto/rea/issues/7342), [issue morluto/rea#7426](https://github.com/morluto/rea/issues/7426), [issue morluto/rea#7434](https://github.com/morluto/rea/issues/7434), [issue morluto/rea#7681](https://github.com/morluto/rea/issues/7681). Thanks @coygeek, @gensokyo-dev.
|
||||
- Read legacy Erlang atom tables correctly, exclude Harmony symlinks from unavailable files, and preserve uncertain JavaScript with-scope member writes. [#7844](https://github.com/morluto/rea/pull/7844), [#7886](https://github.com/morluto/rea/pull/7886), [#7914](https://github.com/morluto/rea/pull/7914), [issue morluto/rea#7418](https://github.com/morluto/rea/issues/7418), [issue morluto/rea#7545](https://github.com/morluto/rea/issues/7545), [issue morluto/rea#7602](https://github.com/morluto/rea/issues/7602). Thanks @coygeek.
|
||||
- Preserve known artifact metadata without hashes, report missing Ghidra project programs as configuration errors, and retain unbacked file-offset diagnostics. [#7932](https://github.com/morluto/rea/pull/7932), [#8222](https://github.com/morluto/rea/pull/8222), [#8308](https://github.com/morluto/rea/pull/8308), [issue morluto/rea#7341](https://github.com/morluto/rea/issues/7341), [issue morluto/rea#8216](https://github.com/morluto/rea/issues/8216), [issue morluto/rea#8244](https://github.com/morluto/rea/issues/8244). Thanks @coygeek, @kaoru0822-kitauji, @macjayz.
|
||||
- Scope Hopper recovery to the caller lifetime and preserve Mach-O host-slice, Godot digest, browser-resource and selected-slice distinctions. [#9905](https://github.com/morluto/rea/pull/9905), [#10016](https://github.com/morluto/rea/pull/10016).
|
||||
- Retain partial OpenAPI Evidence, reject unrepresentable adb activity arguments, and preserve worker, Frida and owned-command failure/cancellation facts through cleanup. [#9908](https://github.com/morluto/rea/pull/9908), [#9918](https://github.com/morluto/rea/pull/9918), [#10055](https://github.com/morluto/rea/pull/10055), [#9963](https://github.com/morluto/rea/pull/9963), [#9964](https://github.com/morluto/rea/pull/9964).
|
||||
- Decode escaped HAR, qlog and Playwright JSON strings without retaining the fragmented strings that inflated decoder heap usage. [#10139](https://github.com/morluto/rea/pull/10139), [issue morluto/rea#10132](https://github.com/morluto/rea/issues/10132). Thanks @fcumaoglu, @mecrimino.
|
||||
- Preserve physical web-worker launch failures as the primary error when cancellation overlaps; retain cancellation separately from the exact launcher observation. [#10145](https://github.com/morluto/rea/pull/10145).
|
||||
- Classify adb wireless-debugging mDNS serials as TCP while preserving USB precedence and unknown device kind. [#10134](https://github.com/morluto/rea/pull/10134). Thanks @rudycelekli.
|
||||
- Normalize lipo’s i386 CPU spelling before Mach-O slice selection and recognize the `__chk_fail` FORTIFY handler import. [#10136](https://github.com/morluto/rea/pull/10136), [#10036](https://github.com/morluto/rea/pull/10036), [issue morluto/rea#10025](https://github.com/morluto/rea/issues/10025). Thanks @2SinceJuly, @coygeek, @rudycelekli.
|
||||
- Retain process CLI cleanup owners until delivery, preserve known local retry leases alongside unknown prior cleanup, and align lifecycle boundaries with tagged cancellation facts. [#10147](https://github.com/morluto/rea/pull/10147). Thanks @wunianze666-netizen.
|
||||
- Count only syntactically valid CSP nonce/hash sources when reporting browser policy. [#10135](https://github.com/morluto/rea/pull/10135). Thanks @rudycelekli.
|
||||
- Reject ELF tables inside the declared header and unmatched NT_FILE mapping pathnames; keep PE imports within their declared directory bounds. [#10133](https://github.com/morluto/rea/pull/10133), [#10138](https://github.com/morluto/rea/pull/10138), [#10044](https://github.com/morluto/rea/pull/10044). Thanks @rudycelekli, @ShuaixinHuang, @wunianze666-netizen.
|
||||
- Classify private nested Swift types by their own kind rather than their enclosing declaration. [#10085](https://github.com/morluto/rea/pull/10085), [issue morluto/rea#7501](https://github.com/morluto/rea/issues/7501). Thanks @BeqaKs, @Rinkia.
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
- Settings clients must replace `effect`, `rea_restart_required`, `restart_required` and `restartRequired` with `update_mode` (`runtime`, `restart`, `parameter`) and `pending_restart`. Parameter-supplied limits cannot be changed by the runtime setter; restart-mode values retain their startup value until restart. [#9885](https://github.com/morluto/rea/pull/9885), [be20bdfb26f7](https://github.com/morluto/rea/commit/be20bdfb26f75a573a9cad49d091f5a27f8fc745), [aee1178839dd](https://github.com/morluto/rea/commit/aee1178839dddcc54de42cce6d5d91b7a913034b). Thanks @gensokyo-dev, @N0zoM1z0.
|
||||
- Process and desktop callers must inspect `details.secondary_failures`/`secondaryFailures`: mixed batches keep physical/provider failures primary and retain typed cancellation with its original cause. Retained descriptors can produce `cleanup_incomplete`; follow the returned recovery instead of treating it as ordinary cancellation. Custom adapters must consume owner-issued inspection/sampling facts and retain their cleanup scopes until release succeeds. [#10141](https://github.com/morluto/rea/pull/10141), [#10113](https://github.com/morluto/rea/pull/10113), [#10109](https://github.com/morluto/rea/pull/10109).
|
||||
- `rea mcp add --command` now accepts a local stdio launcher only: HTTP(S) executable URLs are rejected before settings writes, and package acquisition is removed. Configure remote transports in each client’s native settings and install/select the local launcher before registration. [#10102](https://github.com/morluto/rea/pull/10102).
|
||||
- Runtime-instance graph identities now require `identity.capture_evidence_id` in addition to the capture digest and runtime key. Node IDs digest that identity, so regenerate reconciliation Evidence and rebuild node-keyed lookups even when the digest and runtime key are unchanged. [#10063](https://github.com/morluto/rea/pull/10063).
|
||||
- Retained process symlinks require their stored target bytes; recapture legacy observations that only described a link without retaining its target. [#10082](https://github.com/morluto/rea/pull/10082).
|
||||
- Function dossiers must record Swift literal inventory and its omissions together. Regenerate one-sided observations through a canonical provider; both-absent unsupported observations remain valid. [#10068](https://github.com/morluto/rea/pull/10068).
|
||||
- Conformance manifest schema v2 separates exact string markers from fragments and rejects the old ambiguous `strings` field. Regenerate unversioned fixtures with `npm run build:fixtures`. [#9977](https://github.com/morluto/rea/pull/9977).
|
||||
- Unavailable native/BEAM/Go/Rust view collections return `items.rows: null`, `coverage.status: "unavailable"`, `coverage.total: null` and `coverage.exhausted: false`; recorded empty collections still return `rows: []`. Refresh schemas, stop paging unavailable data and inspect `unknowns`; older saved views retain their recorded facts. [#9893](https://github.com/morluto/rea/pull/9893), [#8291](https://github.com/morluto/rea/pull/8291), [issue morluto/rea#8276](https://github.com/morluto/rea/issues/8276). Thanks @Xinglan233.
|
||||
- Desktop witnessing requires the current generated verifier: re-export old bundles using their original Evidence/task inputs. Pre-6.9 captures missing required `state.baseline_non_files` are rejected before state inspection, drafting or export; capture the application again to obtain contemporaneous SQLite member facts. [#9898](https://github.com/morluto/rea/pull/9898), [#9470](https://github.com/morluto/rea/pull/9470).
|
||||
- New browser captures record `save: []` for request actions that save nothing, changing scenario/Evidence digests. Keep historical digests with historical captures and use freshly recorded digests for new ones. [#9896](https://github.com/morluto/rea/pull/9896).
|
||||
- Selected SQLite rows require `row_offset` and `next_row_offset`; `rows.order` is `rowid`, `primary_key` or `unspecified`. A null next offset means either no continuation or no stated order: an unordered sample can still have `truncated: true`. Inspect both `order` and `truncated` before concluding the sample is complete. [#9331](https://github.com/morluto/rea/pull/9331), [issue morluto/rea#8234](https://github.com/morluto/rea/issues/8234). Thanks @2SinceJuly, @555aaditya.
|
||||
- Windows entropy Evidence now uses the admitted filesystem path spelling, so fresh analysis of a differently cased caller path can change `evidence_id`. Invalidate or re-key cached associations against the fresh Evidence, retaining old IDs only for their original observations. [#9393](https://github.com/morluto/rea/pull/9393). Thanks @HusnainMaroof.
|
||||
- `caller_input_paths` values may be ordered arrays of strings as well as strings. Update strict consumers to preserve repeated selections. [#9626](https://github.com/morluto/rea/pull/9626), [#9624](https://github.com/morluto/rea/pull/9624).
|
||||
- `observe_javascript_runtime` adds required `execution_context_id` fields to scripts and contexts. `context_key` is an opaque capture-local lifetime identity, not a reusable protocol ID, and Evidence identities change. Refresh schemas and recapture when new lifetime associations are needed. [#9471](https://github.com/morluto/rea/pull/9471), [issue morluto/rea#3382](https://github.com/morluto/rea/issues/3382). Thanks @coygeek.
|
||||
- Refresh cached `inspect_address_context` schemas: unavailable facets may carry typed input or resource-constraint errors while successful sibling facets remain available. [#8444](https://github.com/morluto/rea/pull/8444), [#8424](https://github.com/morluto/rea/pull/8424), [#8419](https://github.com/morluto/rea/pull/8419).
|
||||
- `analyze_function`/`trace_native_values` require `native_value_flow.limitations` on available and unavailable variants. Ghidra memory effects cover explicit high-p-code `LOAD`/`STORE` operations only; empty effects do not prove no memory access. The `value_flow_effect_scope` profile commitment invalidates older snapshots: retain embedded historical Evidence, reopen without the snapshot and save a fresh one. [#8651](https://github.com/morluto/rea/pull/8651).
|
||||
- Ghidra byte searches require `skipped_overlays`; loaded overlays no longer count as not loaded, and adjacent initialized blocks are searched with explicit coverage. Reopen targets and save fresh analysis snapshots after the profile/search-policy changes; historical Evidence stays importable. [#8608](https://github.com/morluto/rea/pull/8608), [#8376](https://github.com/morluto/rea/pull/8376), [#8840](https://github.com/morluto/rea/pull/8840), [issue morluto/rea#8374](https://github.com/morluto/rea/issues/8374), [issue morluto/rea#8563](https://github.com/morluto/rea/issues/8563), [issue morluto/rea#8607](https://github.com/morluto/rea/issues/8607).
|
||||
- `compare_functions` adds `function_match.method: "same-evidence"` when both inputs authenticate to one Evidence ID and entry comparison is unavailable. Accept the new matched variant, retain unknown dimensions and do not infer complete equivalence; one observation cannot have contradictory changed dimensions or hashes. [#8442](https://github.com/morluto/rea/pull/8442), [issue morluto/rea#8367](https://github.com/morluto/rea/issues/8367).
|
||||
- Kuna `analyze_function` can return `native_value_flow: {available: false, reason, limitations}` instead of null. Check `available` and preserve the provider reason; null means procedure-scoped unrecorded unknown, not confirmed absence. The workflow-profile digest changes: older trace Evidence remains history but must be rerun to satisfy current replay. [#8785](https://github.com/morluto/rea/pull/8785), [issue morluto/rea#8783](https://github.com/morluto/rea/issues/8783).
|
||||
- The opt-in hot/cold MCP catalog no longer preloads `inspect_analysis_view`. Discover it before use or batch it with its producer; the default full catalog remains available. [#9151](https://github.com/morluto/rea/pull/9151). Thanks @gensokyo-dev.
|
||||
- `batch_decompile` and retained batch views now use `items[].status: "unavailable"` with `reason: "no_pseudocode"` for null pseudocode, replacing the former `error`/`capability_unavailable` item. Empty or non-text values remain `status: "error"` with `unreadable_output`. Both count toward `failed`; preserve item limitations and accept historical error items. [#8737](https://github.com/morluto/rea/pull/8737), [issue morluto/rea#8736](https://github.com/morluto/rea/issues/8736).
|
||||
- `import_evidence_bundle`/CLI `evidence-import` now reject snapshot-shaped JSON with `invalid_request` instead of `evidence_integrity_mismatch`. Restore it with `open_binary.snapshot_path` or a compatible CLI `--snapshot`; bundle imports require a canonical bundle from `export_evidence_bundle`. [#8867](https://github.com/morluto/rea/pull/8867).
|
||||
- REA-launched Chromium keeps its sandbox. If launch fails on root/container hosts, first enable host sandbox support, such as a suitable non-root user or namespace/setuid facilities. The explicit `REA_BROWSER_NO_SANDBOX=true` fallback disables Chromium’s sandbox and does not establish an REA isolation boundary. [#8738](https://github.com/morluto/rea/pull/8738), [issue morluto/rea#8722](https://github.com/morluto/rea/issues/8722). Thanks @chordpli, @hkeysai.
|
||||
- Fresh objdump Evidence changes provider identity from `gnu.objdump`/`GNU objdump` to `{id: "objdump.command", name: "objdump command", version: null}`; launch errors use the same ID and architecture-list subjects may be null. Update provider-keyed caches/readers and retain the selected executable parameters without assuming GNU semantics; historical Evidence stays readable. [#8824](https://github.com/morluto/rea/pull/8824), [issue morluto/rea#8823](https://github.com/morluto/rea/issues/8823).
|
||||
- Kuna verification policy is separate from analysis identity. Earlier snapshots and resumable directory exports are incompatible even with the same executable. Preserve old files, reopen without the snapshot and save a fresh one or choose a new export directory; the [Kuna guide](https://github.com/morluto/rea/blob/main/docs/kuna-provider.md) explains extracting/importing embedded Evidence as history. [#8699](https://github.com/morluto/rea/pull/8699).
|
||||
- `inspect_analysis_view` rejects mismatched native parent predicates with `invalid_request` at `source.predicate_type`: function/inventory/observation views require `rea.analysis`, and matching views require `rea.native-function-matching`. Select the original correctly typed Evidence or rerun its producer; patching an existing predicate invalidates its identity. [#8451](https://github.com/morluto/rea/pull/8451).
|
||||
- `trace_feature` can succeed when xrefs exist but owner lookup is unavailable. Accept `references[].containing_procedure.status: "unavailable"` with provider/reason fields instead of requiring a `found` member, and inspect `residual_unknowns`; `truncated: false` does not establish resolved ownership. [#8368](https://github.com/morluto/rea/pull/8368).
|
||||
- `close_binary` retains investigation records; use `reset_investigation` to clear them. Cross-process recovery requires an explicitly acknowledged Evidence-bundle checkpoint. [#8361](https://github.com/morluto/rea/pull/8361), [issue morluto/rea#8347](https://github.com/morluto/rea/issues/8347). Thanks @gensokyo-dev.
|
||||
- `compare_functions` adds the matched `function_match.method: "same-entry"` variant with required `entry_address` when authenticated artifact, architecture, mapping, slice and entry commitments agree despite a rename. Refresh schemas and keep name/identity changes separate from entry correspondence. [#8263](https://github.com/morluto/rea/pull/8263), [issue morluto/rea#8213](https://github.com/morluto/rea/issues/8213). Thanks @gensokyo-dev.
|
||||
- `inspect_native_load_image` NativeAOT `metadata_recovery` uses a status-discriminated union: complete reports require `reason: null`; partial/not-applicable reports carry `{code, ...}` instead of prose reasons. Branch on codes and their fields while preserving historical/optional-extension strings. Invalid budgets now produce typed input/resource errors. [#8053](https://github.com/morluto/rea/pull/8053).
|
||||
- `trace_javascript_semantics` adds `influences` edges and moves direct literal-argument seeds from call-site to expression nodes. Relevant unknown dependencies can change `found` to `partial`: handle that status and inspect unknowns. Reanalyze retained application graphs to obtain the new edges; old graphs stay readable. [#7939](https://github.com/morluto/rea/pull/7939), [issue morluto/rea#7500](https://github.com/morluto/rea/issues/7500). Thanks @Rinkia.
|
||||
- `inspect_managed_members` changes `signature_resolution` from `type-names-v1` to `type-names-v2` and appends readable names to signature operands, such as `class:4 (Fixture.Program)`. Branch on the resolution version, accept annotated v2 strings and preserve historical v1/null displays. Signature digests are unchanged; `InternalCall` methods remain runtime-provided boundaries. [#5309](https://github.com/morluto/rea/pull/5309), [#9547](https://github.com/morluto/rea/pull/9547), [issue morluto/rea#5149](https://github.com/morluto/rea/issues/5149). Thanks @elricfd, @gensokyo-dev, @ln-bodicherla, @Plastic-time.
|
||||
- MCP calls default to 1,024 combined array elements/object members; excess input is rejected before dispatch with nonretryable `resource_constraint`, `resource: "transport"` and `reported_limits.max_input_elements`. For larger inline calls, set `REA_MCP_MAX_INPUT_ELEMENTS` to a digit-only positive decimal safe integer (1–9007199254740991) and restart, or select retained/file inputs. Fractional/exponent spellings are invalid; inputs are never truncated. [#7905](https://github.com/morluto/rea/pull/7905), [issue morluto/rea#7882](https://github.com/morluto/rea/issues/7882). Thanks @gensokyo-dev.
|
||||
- `inspect_macho` text names/paths can be null for non-UTF-8 bytes, with `name_bytes_hex`, `segment_bytes_hex` and `path_bytes_hex` alternatives; unsafe numeric sizes/offsets/alignments can be null with exact companion fields, and delayed-init `options` are numeric. Refresh schemas and preserve these facts; absent byte fields in older Evidence remain unrecorded. [#7952](https://github.com/morluto/rea/pull/7952), [issue morluto/rea#7391](https://github.com/morluto/rea/issues/7391). Thanks @coygeek.
|
||||
- Environment file-source errors move from the generic `evidence` issue path to `capture` for `environment-build` and `source.path` for environment bundle build/export. Missing/non-file/invalid UTF-8/JSON sources return `invalid_request` with `invalid_value`/`invalid_format` issues and `inspect_input_contract` recovery; repair the selected file. [#7900](https://github.com/morluto/rea/pull/7900), [issue morluto/rea#7523](https://github.com/morluto/rea/issues/7523). Thanks @coygeek.
|
||||
- Selected unpaired UTF-16 surrogates now make TOON, Markdown, CSV and TSV output fail with `invalid_request` and a nonzero exit even after a successful operation; Markdown also refuses NUL. Use `--format json` or `--format yaml` to preserve these values rather than accepting substituted text. [#7852](https://github.com/morluto/rea/pull/7852), [issue morluto/rea#7592](https://github.com/morluto/rea/issues/7592), [issue morluto/rea#7593](https://github.com/morluto/rea/issues/7593). Thanks @coygeek.
|
||||
- Reconstruction `evidence_bundle` inputs reject authenticated standalone records as `invalid_request` with field-level issues instead of accepting/misclassifying them as damaged bundles. Bundle-file import/export/comparison reports `invalid_request`/`invalid_input` with `details.reason: "wrong-kind"`. Supply a canonical bundle from `export_evidence_bundle`; tampered data remains an integrity failure. [#7895](https://github.com/morluto/rea/pull/7895), [issue morluto/rea#7562](https://github.com/morluto/rea/issues/7562). Thanks @coygeek.
|
||||
- Environment coverage can use `method-replay` for non-GET safe reads. Clock-generating write plans without a global clock anchor now return `served: false`, `reason: "unknown-clock"` instead of being served. Extend reason handling and recapture usable start times/completed durations before replaying those writes. [#7834](https://github.com/morluto/rea/pull/7834), [63220edcc3b4](https://github.com/morluto/rea/commit/63220edcc3b47d44e72a7d77518172d81961e67a), [issue morluto/rea#7387](https://github.com/morluto/rea/issues/7387). Thanks @coygeek.
|
||||
- Ghidra returns `not-in-listing` for in-memory addresses lacking listed instructions or defined data, replacing the former `undecodable` interpretation. Accept the new status and recreate snapshots after the raw-profile change; retain old embedded Evidence as history. [#7823](https://github.com/morluto/rea/pull/7823), [issue morluto/rea#7490](https://github.com/morluto/rea/issues/7490). Thanks @Entrpi.
|
||||
- `capture_process_scenario`/CLI process capture rejects `columns: 1` before target launch; update both initial terminal widths and every resize to at least 2. Sensitive interaction `data` is empty with `sensitive`/`input_bytes`, and raw echoes are redacted. Recapture both sides before comparing older private-input Evidence. [#7848](https://github.com/morluto/rea/pull/7848), [#7804](https://github.com/morluto/rea/pull/7804), [issue morluto/rea#7582](https://github.com/morluto/rea/issues/7582), [issue morluto/rea#7782](https://github.com/morluto/rea/issues/7782). Thanks @coygeek, @gensokyo-dev.
|
||||
- Managed setup registrations bind the selected absolute runtime and REA entry script, including package-runner cache paths. Keep that installation available; unknown registrations need confirmed manual repair. Setup no longer returns `prewarm` or emits its progress events. [c77735fa83a6](https://github.com/morluto/rea/commit/c77735fa83a66552ec45eef435ab3bb36026ecfe). Thanks @gensokyo-dev.
|
||||
- macOS Hopper launch paths/arguments reject double quotes, backslashes and line breaks before handoff. Select literal-safe prepared paths/loader arguments or a compatible provider. [#7732](https://github.com/morluto/rea/pull/7732), [issue morluto/rea#7727](https://github.com/morluto/rea/issues/7727). Thanks @gensokyo-dev.
|
||||
- New JavaScript application graphs omit the derived package `renderer` property. Use `renderer_declarations` for source fields and package-load edges for the selected candidate; historical Evidence remains readable. [5cf7133f823b](https://github.com/morluto/rea/commit/5cf7133f823bce2a3e42a6e1d0c8418e5ff9908d).
|
||||
- Replace Cutter `--json=true/false` with `--json-output=true/false`; bare `--json` still selects CLI result formatting. Replace `rea compare-bundles` with `rea compare`; MCP `compare_bundles` is unchanged. [567ea4b1e8bb](https://github.com/morluto/rea/commit/567ea4b1e8bb7dda67563d06f1b4977c2d92995a), [3515b262218f](https://github.com/morluto/rea/commit/3515b262218f2d4ba94ce6a7bda9766747b3d84d).
|
||||
- JEB engine refusals report `execution_failure` rather than `unsupported_target`; inspect retained upstream diagnostics for recovery. [c4cdb7658b0e](https://github.com/morluto/rea/commit/c4cdb7658b0eb5ef16b30bd8127479bce8c21233).
|
||||
- ASAR file occurrences may contain `unpacked: false`. Accept an optional boolean; absent historical fields remain unknown. [60834e391c3f](https://github.com/morluto/rea/commit/60834e391c3f81eb2343eba288b735c3bf3bde61).
|
||||
- Non-loopback MCP HTTP binds require `MCP_ALLOWED_HOSTS` or `rea mcp --http --allowed-hosts`. Bundle names must be unchanged HTTP hostnames within the 63-octet DNS-label limit. [#7172](https://github.com/morluto/rea/pull/7172). Thanks @DeryFerd, @gensokyo-dev.
|
||||
- `binary_session {}` is compact by default and omits provider availability diagnostics/remediation, target-support diagnostics/capabilities and tool-group surface/effects/annotations. Request `{"detail":"complete"}` for these facts and recovery guidance. [#7127](https://github.com/morluto/rea/pull/7127), [issue morluto/rea#7109](https://github.com/morluto/rea/issues/7109). Thanks @kaoru0822-kitauji.
|
||||
- Native input errors now include `details.operation` and field-level `details.issues`. Supply a nonempty `trace_native_values.procedure`; CLI `trace-native-values` rejects an empty procedure before opening the target as `VALIDATION_ERROR` with `fieldErrors`, while MCP reports `invalid_request` at `procedure`. [#7889](https://github.com/morluto/rea/pull/7889), [issue morluto/rea#7572](https://github.com/morluto/rea/issues/7572). Thanks @coygeek.
|
||||
- Readable JavaScript members that normalize to one logical path now stop `analyze_javascript_application` with `artifact_operation_failed`, `details.reason: "path"` and a partial inventory instead of selecting one occurrence. Inspect the inventory and analyze a copy without collisions; all-unavailable colliding sources remain unknown. [#7864](https://github.com/morluto/rea/pull/7864), [issue morluto/rea#7626](https://github.com/morluto/rea/issues/7626). Thanks @coygeek.
|
||||
- `trace_web_module_imports` with an empty/relative `REA_BROWSER_EXECUTABLE` now reports `capability_unavailable` with `invalid_browser_executable` instead of `missing_browser_executable`, retaining `details.diagnostics.executable`. Set an absolute Chromium path; an unset selection still means missing. [#7903](https://github.com/morluto/rea/pull/7903), [issue morluto/rea#7639](https://github.com/morluto/rea/issues/7639). Thanks @coygeek.
|
||||
- Unresolvable `import-reference-source` roots, capture scenario files and web-network capture/Protobuf descriptor paths (`ELOOP`/`ENAMETOOLONG`) now report `invalid_request`/`invalid_input` with responsible field/host-code issues rather than generic execution/unreadable-output failures. Repair the symlink chain or choose a shorter path. [#7847](https://github.com/morluto/rea/pull/7847), [#7814](https://github.com/morluto/rea/pull/7814), [issue morluto/rea#7607](https://github.com/morluto/rea/issues/7607), [issue morluto/rea#7636](https://github.com/morluto/rea/issues/7636). Thanks @Abelo9996, @coygeek.
|
||||
- `close_binary` with `snapshot_path` on a profileless/archive target now returns nonretryable `capability_unavailable` instead of `evidence_integrity_mismatch`, writes no snapshot and leaves the session open. Export needed Evidence, then close again without `snapshot_path`. [#7837](https://github.com/morluto/rea/pull/7837), [issue morluto/rea#7311](https://github.com/morluto/rea/issues/7311). Thanks @coygeek.
|
||||
- adb local-file refusals occur before device commands: missing/non-file/uninspectable `local_path`/`apk_path` and file-blocked `output_directory` return `invalid_request` with field issues/host codes; output-producing calls formerly used `unreadable_output`. Supply regular source files and a directory path whose parents are directories. [#7885](https://github.com/morluto/rea/pull/7885), [issue morluto/rea#7549](https://github.com/morluto/rea/issues/7549), [issue morluto/rea#7550](https://github.com/morluto/rea/issues/7550). Thanks @coygeek.
|
||||
- Evidence writes failing with `EFBIG`, `ENOSPC` or `EDQUOT` now report nonretryable `resource_constraint`, `details.reason: "storage-limit"`, path and optional `system_code` instead of `execution_failure`/`io`. Raise file-size allowance or free space/quota before retrying; a failed staged-file cleanup remains `cleanup_incomplete`. [#7887](https://github.com/morluto/rea/pull/7887), [issue morluto/rea#7573](https://github.com/morluto/rea/issues/7573). Thanks @coygeek.
|
||||
- PE signers add optional nullable `unsigned_attribute_oids`: fresh null means absent, an OID array means present, and omission in old Evidence is unrecorded. Unsigned attributes produce `coverage.status: "partial"` because nested signatures/timestamp contents remain undecoded; accept the new field and limitations. [#7920](https://github.com/morluto/rea/pull/7920), [issue morluto/rea#7767](https://github.com/morluto/rea/issues/7767). Thanks @Rinkia.
|
||||
- Valid ASN.1 exceeding certificate nesting/OID allowances now returns nonretryable `resource_constraint` rather than `invalid_request`/`invalid_input`, with `max_asn1_depth`/`max_oid_bytes`. These format/resource bounds have no runtime override; retain the diagnostics and use an independently suitable parser when necessary. [#9932](https://github.com/morluto/rea/pull/9932).
|
||||
- `trace_call_path`/`build_call_path` require discovery and observed-result fields in `search_scope`. An exhausted observed graph can still yield `goal_status: "unknown"` when provider discovery is incomplete. Refresh result schemas and workflow-profile expectations instead of equating graph exhaustion with complete discovery. [#8443](https://github.com/morluto/rea/pull/8443).
|
||||
- `inspect_native_instruction` adds `containing_instruction` for `not-instruction-boundary` and `containing_data` for `data`, with address/extent/identity/provenance. Accept these facts; omission in old Evidence is unrecorded. The Ghidra profile changes: reopen and save a fresh snapshot. [#8777](https://github.com/morluto/rea/pull/8777).
|
||||
- `trace_native_values` adds required `page_truncated` and tagged `traversal` coverage. `truncated` combines page omission with traversal truncation; exactly filling a budget alone no longer proves truncation. Inspect page coverage before fetching another page and traversal reason before raising budgets. [#8309](https://github.com/morluto/rea/pull/8309), [issue morluto/rea#8283](https://github.com/morluto/rea/issues/8283). Thanks @kaoru0822-kitauji.
|
||||
- `batch_decompile.addresses` has a separate hard ceiling of 20,000 entries. Split larger batches into calls of at most that size; increasing the configurable MCP transport allowance cannot remove this operation limit. [#5937](https://github.com/morluto/rea/pull/5937), [issue morluto/rea#5930](https://github.com/morluto/rea/issues/5930). Thanks @dakjdakd.
|
||||
- `close_binary` can retire the target while retaining cleanup owners: `cleanup_incomplete` may have `recovery.kind: "retry_cleanup"` despite `retryable: false`. Keep the same connection open and call `close_binary` again without `snapshot_path` to retry owned cleanup. [#8329](https://github.com/morluto/rea/pull/8329), [issue morluto/rea#8211](https://github.com/morluto/rea/issues/8211). Thanks @kaoru0822-kitauji.
|
||||
- Unconfirmed cleanup in `inspect_address_context`, `get_call_graph` or `trace_call_path` now produces tool-level `cleanup_incomplete` rather than a successful partial result or cancellation. Keep admitted partial Evidence and follow the returned same-session cleanup recovery. [#8417](https://github.com/morluto/rea/pull/8417), [#8516](https://github.com/morluto/rea/pull/8516), [issue morluto/rea#8369](https://github.com/morluto/rea/issues/8369), [issue morluto/rea#8416](https://github.com/morluto/rea/issues/8416). Thanks @kaoru0822-kitauji.
|
||||
- `inspect_ntfs_journal` omits detailed `mftMetadata.record_headers` by default and leaves continuation at the first omitted record. Select `mft_record_limit` from 1 to 32 when those details are needed; inventory counts and explicit coverage remain inline. [1a8a9b749a](https://github.com/morluto/rea/commit/1a8a9b749a86e4b065a6b3ee6b8bad3b2761bac6). Thanks @gensokyo-dev, @N0zoM1z0.
|
||||
- Desktop state directories now use `application.state_directories[].exists_at_start: null` plus `existence_error` when inspection fails (for example, access denial). Accept the tri-state field and preserve unknown instead of treating it as absence. [#9899](https://github.com/morluto/rea/pull/9899).
|
||||
|
||||
Full contribution record: [1848 commits and 1073 merged PRs](https://github.com/morluto/rea/blob/rea-agents-6.9.0/docs/releases/6.9.0.contributions.json).
|
||||
|
||||
## [6.8.0](https://github.com/morluto/rea/compare/rea-agents-6.7.0...rea-agents-6.8.0) (2026-10-25)
|
||||
|
||||
### Highlights
|
||||
|
||||
@@ -92,8 +92,9 @@ project. Installation and recovery details are in the setup guide below.
|
||||
|
||||
Setup supports Claude Code, Codex, Cursor, Gemini CLI, Grok Build and
|
||||
[other agents](docs/getting-started/installation.md#supported-agents). See
|
||||
[installation and setup](docs/getting-started/installation.md) for provider configuration and
|
||||
manual MCP registration and Claude Code/Codex plugin installation.
|
||||
[installation and setup](docs/getting-started/installation.md) for provider configuration,
|
||||
manual MCP registration, Claude Code/Codex plugins, and the Cursor Marketplace
|
||||
plugin.
|
||||
|
||||
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
|
||||
@@ -214,7 +215,7 @@ Additional tools and host support depend on the target:
|
||||
| EVM bytecode | Dispatch selectors, byte offsets, inferred arguments and mutability | Local raw/hex carrier on Linux x64; [offline EVM guide](docs/guides/evm/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/guides/native/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/guides/javascript/javascript-application-workflows.md) |
|
||||
| JavaScript / Electron | Modules, imports, source maps, routes, IPC, native add-ons, `rea audit-release-exposure` | Node.js and npm; Linux: procps-compatible `ps`; [application analysis](docs/guides/javascript/javascript-application-workflows.md) |
|
||||
| Websites | Page structure, scripts, network observations and requested screenshots | A Chrome-family browser; [browser analysis](docs/guides/web/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/guides/web/web-network-captures.md) |
|
||||
| .NET assemblies | Metadata, CIL instructions, declared native dependencies and build comparisons | None (static only); [managed-code guide](docs/guides/managed/managed-code-analysis.md) |
|
||||
|
||||
@@ -12,6 +12,7 @@ result, the solver's turns and cost from its trajectory when that is a local fil
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
import sys
|
||||
from importlib import metadata
|
||||
@@ -56,14 +57,23 @@ def _trajectory_end(context) -> tuple:
|
||||
return None, None
|
||||
|
||||
|
||||
def _checks(context, task: str) -> list:
|
||||
"""Each check's result as the task's verifier recorded it under the instance's verifications."""
|
||||
verifications = (_field(context, "metadata") or {}).get("verifications") or {}
|
||||
found = verifications.get(task) or next(iter(verifications.values()), {})
|
||||
def _solve_facts(run, task: str) -> tuple[str, list]:
|
||||
"""The selected verifier owns checks and score; run failures still take precedence."""
|
||||
verifications = (_field(run.context, "metadata") or {}).get("verifications") or {}
|
||||
found = verifications.get(task)
|
||||
results = found.get("results") if isinstance(found, dict) else None
|
||||
return [{"id": str(result.get("id")), "passed": result.get("result") is True,
|
||||
"description": str(result.get("description", ""))[:MAX_TEXT]}
|
||||
for result in results or [] if isinstance(result, dict)]
|
||||
checks = [{"id": str(result.get("id")), "passed": result.get("result") is True,
|
||||
"description": str(result.get("description", ""))[:MAX_TEXT]}
|
||||
for result in results or [] if isinstance(result, dict)]
|
||||
outcome = run.outcome.value
|
||||
if outcome not in ("failed", "cancelled"):
|
||||
score = found.get("score") if isinstance(found, dict) else None
|
||||
outcome = "unscored"
|
||||
# Match TaskRun's score >= 1 rule without borrowing another verifier's
|
||||
# score or claiming success when no selected checks were observed.
|
||||
if checks and type(score) in (int, float) and math.isfinite(score):
|
||||
outcome = "passed" if score >= 1 else "scored below 1"
|
||||
return outcome, checks
|
||||
|
||||
|
||||
def _version() -> str | None:
|
||||
@@ -108,9 +118,10 @@ def main(argv: list[str]) -> int:
|
||||
_say(protocol, {"error": "the bundle ran no task", "cleanup": _cleanup(result)})
|
||||
return 2
|
||||
turns, usd = _trajectory_end(run.context)
|
||||
outcome, checks = _solve_facts(run, task)
|
||||
error = getattr(run, "error", None)
|
||||
_say(protocol, {"outcome": run.outcome.value, "instance_id": run.instance_id,
|
||||
"seconds": round(float(run.duration), 1), "checks": _checks(run.context, task),
|
||||
_say(protocol, {"outcome": outcome, "instance_id": run.instance_id,
|
||||
"seconds": round(float(run.duration), 1), "checks": checks,
|
||||
"turns": turns, "usd": usd, "agentenv": _version(),
|
||||
"error": None if error is None else f"{type(error).__name__}: {error}"[:MAX_TEXT],
|
||||
"cleanup": _cleanup(result)})
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
"""Project selected verifier facts without importing or running agentenv."""
|
||||
|
||||
import unittest
|
||||
from types import SimpleNamespace
|
||||
|
||||
from bridge.agentenv.solve import _solve_facts
|
||||
|
||||
|
||||
def run_with(verifications, outcome="passed"):
|
||||
return SimpleNamespace(context={"metadata": {"verifications": verifications}},
|
||||
outcome=SimpleNamespace(value=outcome))
|
||||
|
||||
|
||||
class SolveFactsTest(unittest.TestCase):
|
||||
def test_matching_verifier_success_and_failure(self):
|
||||
for passed, score, outcome in ((True, 1.0, "passed"), (False, 0.0, "scored below 1")):
|
||||
with self.subTest(passed=passed):
|
||||
run = run_with({"wanted": {"results": [{"id": "selected", "result": passed}],
|
||||
"score": score}})
|
||||
self.assertEqual(_solve_facts(run, "wanted"),
|
||||
(outcome, [{"id": "selected", "passed": passed, "description": ""}]))
|
||||
|
||||
def test_missing_empty_and_unscored_selected_verifier_do_not_borrow_success(self):
|
||||
other = {"results": [{"id": "unrelated", "result": True}], "score": 1.0}
|
||||
for selected in (None, {}, {"results": [], "score": 1.0},
|
||||
{"results": [{"id": 0, "result": False}]}):
|
||||
for reversed_order in (False, True):
|
||||
with self.subTest(selected=selected, reversed_order=reversed_order):
|
||||
entries = [("other", other)]
|
||||
if selected is not None:
|
||||
entries.append(("wanted", selected))
|
||||
if reversed_order:
|
||||
entries.reverse()
|
||||
expected = ([{"id": "0", "passed": False, "description": ""}]
|
||||
if selected and selected.get("results") else [])
|
||||
self.assertEqual(_solve_facts(run_with(dict(entries)), "wanted"),
|
||||
("unscored", expected))
|
||||
|
||||
def test_selected_score_owns_outcome_and_checks_preserve_false_and_zero(self):
|
||||
# A weighted/any-pass verifier's recorded score can pass despite a failed
|
||||
# criterion; an unrelated failing score cannot override the selected one.
|
||||
rows = [{"id": 0, "result": False}, {"id": "zero", "result": 0},
|
||||
{"id": "yes", "result": True}]
|
||||
checks = [{"id": "0", "passed": False, "description": ""},
|
||||
{"id": "zero", "passed": False, "description": ""},
|
||||
{"id": "yes", "passed": True, "description": ""}]
|
||||
for score, expected in ((0, "scored below 1"), (0.5, "scored below 1"),
|
||||
(1, "passed"), (1.5, "passed")):
|
||||
with self.subTest(score=score):
|
||||
verifications = {"other": {"score": 0},
|
||||
"wanted": {"results": rows, "score": score}}
|
||||
self.assertEqual(_solve_facts(run_with(verifications, "scored below 1"), "wanted"),
|
||||
(expected, checks))
|
||||
|
||||
def test_failure_and_cancellation_preserve_partial_named_checks(self):
|
||||
for outcome in ("failed", "cancelled"):
|
||||
with self.subTest(outcome=outcome):
|
||||
run = run_with({"wanted": {"results": [{"id": "partial", "result": True}],
|
||||
"score": 1.0}}, outcome)
|
||||
self.assertEqual(_solve_facts(run, "wanted"),
|
||||
(outcome, [{"id": "partial", "passed": True, "description": ""}]))
|
||||
|
||||
def test_non_numeric_or_nonfinite_scores_remain_unscored(self):
|
||||
for score in (None, True, "1", float("nan"), float("inf")):
|
||||
with self.subTest(score=score):
|
||||
run = run_with({"wanted": {"results": [{"id": "yes", "result": True}],
|
||||
"score": score}})
|
||||
self.assertEqual(_solve_facts(run, "wanted")[0], "unscored")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -464,7 +464,9 @@ class ReaJadxBridge {
|
||||
if (element.getTagName().equals("uses-sdk")) {
|
||||
minSdk = element.getAttributeNS(android, "minSdkVersion");
|
||||
targetSdk = element.getAttributeNS(android, "targetSdkVersion");
|
||||
} else if (element.getTagName().equals("uses-permission")) {
|
||||
} else if (element.getTagName().equals("uses-permission")
|
||||
|| element.getTagName().equals("uses-permission-sdk-23")
|
||||
|| element.getTagName().equals("uses-permission-sdk-m")) {
|
||||
String permission = element.getAttributeNS(android, "name");
|
||||
if (!permission.isEmpty()) permissions.add(permission);
|
||||
}
|
||||
|
||||
@@ -958,15 +958,6 @@ class _BridgeServer(threading.Thread):
|
||||
proof.update(fragment.encode("utf-8"))
|
||||
return proof.hexdigest()
|
||||
|
||||
def _encode_authenticated_response(
|
||||
self, value: dict[str, Any], client_nonce: str, server_nonce: str
|
||||
) -> bytes | None:
|
||||
"""Return one exact frame. The socket path writes the same pieces."""
|
||||
proof = self._authenticated_proof(value, client_nonce, server_nonce)
|
||||
if proof is None:
|
||||
return None
|
||||
return b"".join(self._iter_authenticated_frame(value, proof))
|
||||
|
||||
def _iter_authenticated_frame(self, value: dict[str, Any], proof: str):
|
||||
yield _AUTHENTICATED_PREFIX
|
||||
for fragment in _response_fragments(value):
|
||||
|
||||
@@ -154,13 +154,6 @@ class HopperApiFacade:
|
||||
)
|
||||
|
||||
|
||||
def _configure_hopper_api(document_provider):
|
||||
"""Inject Hopper's document provider or a standalone test facade."""
|
||||
global _hopper_api, _rea_session_document
|
||||
_hopper_api = HopperApiFacade(document_provider)
|
||||
_rea_session_document = None
|
||||
|
||||
|
||||
def _api():
|
||||
"""Resolve Hopper globals lazily so importing this module needs no Hopper."""
|
||||
global _hopper_api
|
||||
|
||||
@@ -135,13 +135,27 @@ def inspect_elf(path, cache):
|
||||
from pwnlib.context import context
|
||||
with context.local(cache_dir=str(cache), log_level="warning"):
|
||||
from elftools.common.exceptions import ELFError
|
||||
from elftools.common.utils import struct_parse
|
||||
from elftools.elf.elffile import ELFFile
|
||||
from pwnlib.elf import ELF
|
||||
try:
|
||||
headers = ELFFile(io.BytesIO(content))
|
||||
section_count = headers.num_sections()
|
||||
if section_count:
|
||||
if headers.header.e_shentsize < headers.structs.Elf_Shdr.sizeof():
|
||||
raise LayoutFailure("format", "ELF section-header entry is shorter than the required structure.")
|
||||
location(headers.header.e_shoff, section_count * headers.header.e_shentsize, len(content))
|
||||
# Upstream symbol, relocation and dynamic access reads stored stream
|
||||
# bytes, while this profile reports logical names and file coordinates.
|
||||
# A string table is read only when it names sections or symbols.
|
||||
raw_headers = []
|
||||
for index in range(section_count):
|
||||
raw_header = struct_parse(headers.structs.Elf_Shdr, headers.stream,
|
||||
stream_pos=headers.header.e_shoff + index * headers.header.e_shentsize)
|
||||
raw_headers.append(raw_header)
|
||||
if raw_header.sh_flags & 0x800 and raw_header.sh_type in (
|
||||
"SHT_SYMTAB", "SHT_DYNSYM", "SHT_REL", "SHT_RELA", "SHT_RELR", "SHT_DYNAMIC"):
|
||||
raise LayoutFailure("unsupported-target", f"ELF section {index} ({raw_header.sh_type}) is SHF_COMPRESSED; logical metadata and its source coordinates are not decoded by this profile.")
|
||||
segment_count = headers.num_segments()
|
||||
if segment_count:
|
||||
location(headers.header.e_phoff, segment_count * headers.header.e_phentsize, len(content))
|
||||
@@ -153,12 +167,22 @@ def inspect_elf(path, cache):
|
||||
section_name_index = headers.get_shstrndx()
|
||||
if raw_name_index == 0xffff and section_name_index < 0xff00:
|
||||
raise LayoutFailure("format", f"ELF SHN_XINDEX resolves to ordinary index {section_name_index}; the escape requires an index at least SHN_LORESERVE (0xff00).")
|
||||
consumed_strings = set()
|
||||
if section_name_index != 0:
|
||||
if section_name_index >= section_count:
|
||||
raise LayoutFailure("format", f"ELF section-name table index {section_name_index} lies outside the declared section count {section_count}.")
|
||||
names_header = headers._get_section_header(section_name_index)
|
||||
if names_header.sh_type != "SHT_STRTAB":
|
||||
raise LayoutFailure("format", f"ELF section-name table {section_name_index} is not SHT_STRTAB.")
|
||||
consumed_strings.add(section_name_index)
|
||||
for header in raw_headers:
|
||||
if header.sh_type in ("SHT_SYMTAB", "SHT_DYNSYM"):
|
||||
consumed_strings.add(header.sh_link)
|
||||
for index, raw_header in enumerate(raw_headers):
|
||||
if (raw_header.sh_flags & 0x800 and raw_header.sh_type == "SHT_STRTAB"
|
||||
and index in consumed_strings):
|
||||
raise LayoutFailure("unsupported-target", f"ELF section {index} (SHT_STRTAB) is SHF_COMPRESSED; logical metadata and its source coordinates are not decoded by this profile.")
|
||||
if section_name_index != 0:
|
||||
location(names_header.sh_offset, names_header.sh_size, len(content))
|
||||
except (ELFError, ValueError, OverflowError, AssertionError, IndexError) as error:
|
||||
raise LayoutFailure("format", str(error)) from error
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
"""Producer admission regressions; no pwntools imports or target execution."""
|
||||
from contextlib import nullcontext
|
||||
import importlib.metadata
|
||||
from pathlib import Path
|
||||
import runpy
|
||||
import sys
|
||||
import tempfile
|
||||
import types
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
layout = runpy.run_path(str(Path(__file__).with_name("layout_impl.py")))
|
||||
|
||||
|
||||
class UpstreamReached(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
class LayoutStorageTests(unittest.TestCase):
|
||||
def inspect(self, section_type, flags, section_stride=64, sections=None, shstrndx=0):
|
||||
described = sections if sections is not None else [
|
||||
types.SimpleNamespace(sh_type="SHT_NULL", sh_flags=0, sh_link=0),
|
||||
types.SimpleNamespace(sh_type=section_type, sh_flags=flags, sh_link=0),
|
||||
]
|
||||
class Headers:
|
||||
header = types.SimpleNamespace(e_shoff=64, e_shentsize=section_stride, e_shstrndx=shstrndx)
|
||||
structs = types.SimpleNamespace(Elf_Shdr=types.SimpleNamespace(sizeof=lambda: 64))
|
||||
stream = object()
|
||||
|
||||
def num_sections(self): return len(described)
|
||||
def num_segments(self): return 0
|
||||
def get_shstrndx(self): return self.header.e_shstrndx
|
||||
def _get_section_header(self, index):
|
||||
return described[index]
|
||||
|
||||
class Elf:
|
||||
def __init__(self, *_args, **_kwargs):
|
||||
raise UpstreamReached("No artifact decoding or emulation is allowed in this test")
|
||||
|
||||
modules = {name: types.ModuleType(name) for name in (
|
||||
"pwnlib", "pwnlib.context", "pwnlib.elf", "elftools", "elftools.common",
|
||||
"elftools.common.exceptions", "elftools.common.utils", "elftools.elf", "elftools.elf.elffile")}
|
||||
modules["pwnlib.context"].context = types.SimpleNamespace(local=lambda **_kwargs: nullcontext())
|
||||
modules["pwnlib.elf"].ELF = Elf
|
||||
modules["elftools.common.exceptions"].ELFError = type("ELFError", (Exception,), {})
|
||||
modules["elftools.elf.elffile"].ELFFile = lambda _stream: Headers()
|
||||
modules["elftools.common.utils"].struct_parse = lambda _struct, _stream, stream_pos: described[(stream_pos - 64) // max(section_stride, 1)]
|
||||
count = len(described)
|
||||
content = bytearray(64 + count * max(section_stride, 64))
|
||||
content[:7] = b"\x7fELF\x02\x01\x01"
|
||||
content[16:18] = (1).to_bytes(2, "little") # ET_REL
|
||||
content[18:20] = (62).to_bytes(2, "little")
|
||||
content[40:48] = (64).to_bytes(8, "little")
|
||||
content[58:60] = section_stride.to_bytes(2, "little")
|
||||
content[60:62] = count.to_bytes(2, "little")
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
snapshot = Path(directory) / "object.snapshot"
|
||||
snapshot.write_bytes(content)
|
||||
with patch.dict(sys.modules, modules), patch.object(importlib.metadata, "version", side_effect=layout["PACKAGES"].__getitem__):
|
||||
return layout["inspect_elf"](snapshot, Path(directory) / "cache")
|
||||
|
||||
def test_compressed_interpreted_storage_refuses_before_upstream_decoding(self):
|
||||
for section_type in ("SHT_SYMTAB", "SHT_DYNSYM", "SHT_REL", "SHT_RELA", "SHT_RELR", "SHT_DYNAMIC"):
|
||||
with self.subTest(section_type=section_type):
|
||||
with self.assertRaises(layout["LayoutFailure"]) as raised:
|
||||
self.inspect(section_type, 0x800)
|
||||
self.assertEqual(raised.exception.reason, "unsupported-target")
|
||||
self.assertEqual(raised.exception.args[0], f"ELF section 1 ({section_type}) is SHF_COMPRESSED; logical metadata and its source coordinates are not decoded by this profile.")
|
||||
with self.assertRaises(UpstreamReached):
|
||||
self.inspect(section_type, 0)
|
||||
|
||||
def test_unreferenced_compressed_string_table_remains_admitted(self):
|
||||
with self.assertRaises(UpstreamReached):
|
||||
self.inspect("SHT_STRTAB", 0x800)
|
||||
|
||||
def test_consumed_compressed_string_tables_are_refused(self):
|
||||
name_table = [
|
||||
types.SimpleNamespace(sh_type="SHT_NULL", sh_flags=0, sh_link=0),
|
||||
types.SimpleNamespace(sh_type="SHT_STRTAB", sh_flags=0x800, sh_link=0),
|
||||
]
|
||||
linked = [
|
||||
types.SimpleNamespace(sh_type="SHT_NULL", sh_flags=0, sh_link=0),
|
||||
types.SimpleNamespace(sh_type="SHT_SYMTAB", sh_flags=0, sh_link=2),
|
||||
types.SimpleNamespace(sh_type="SHT_STRTAB", sh_flags=0x800, sh_link=0),
|
||||
]
|
||||
cases = (
|
||||
("section-name", name_table, 1, 1),
|
||||
("symbol-link", linked, 0, 2),
|
||||
)
|
||||
for label, sections, shstrndx, index in cases:
|
||||
with self.subTest(label=label):
|
||||
with self.assertRaises(layout["LayoutFailure"]) as raised:
|
||||
self.inspect("SHT_NULL", 0, sections=sections, shstrndx=shstrndx)
|
||||
self.assertEqual(raised.exception.reason, "unsupported-target")
|
||||
self.assertEqual(
|
||||
raised.exception.args[0],
|
||||
f"ELF section {index} (SHT_STRTAB) is SHF_COMPRESSED; logical metadata and its source coordinates are not decoded by this profile.",
|
||||
)
|
||||
|
||||
def test_uninterpreted_compressed_payload_does_not_change_admission(self):
|
||||
with self.assertRaises(UpstreamReached):
|
||||
self.inspect("SHT_PROGBITS", 0x800)
|
||||
|
||||
def test_short_section_header_stride_refuses_before_raw_header_scan(self):
|
||||
for stride in (0, 1, 63):
|
||||
with self.subTest(stride=stride):
|
||||
with self.assertRaises(layout["LayoutFailure"]) as raised:
|
||||
self.inspect("SHT_PROGBITS", 0, stride)
|
||||
self.assertEqual(raised.exception.reason, "format")
|
||||
self.assertIn("section-header entry", str(raised.exception))
|
||||
for stride in (64, 96):
|
||||
with self.subTest(stride=stride):
|
||||
with self.assertRaises(UpstreamReached):
|
||||
self.inspect("SHT_PROGBITS", 0, stride)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -68,6 +68,11 @@ export const documentationSections = [
|
||||
source: "guides/native/windows-shortcut.md",
|
||||
route: "/windows-shortcut",
|
||||
},
|
||||
{
|
||||
source: "guides/native/ntfs-metadata.md",
|
||||
route: "/ntfs-metadata",
|
||||
text: "Acquired NTFS metadata",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -358,6 +363,11 @@ export const documentationSections = [
|
||||
source: "design/limits-and-recovery.md",
|
||||
route: "/design/limits-and-recovery",
|
||||
},
|
||||
{
|
||||
text: "REA limit inventory",
|
||||
source: "design/rea-limit-inventory.md",
|
||||
route: "/design/rea-limit-inventory",
|
||||
},
|
||||
{
|
||||
text: "MCP tool design",
|
||||
source: "development/tool-design.md",
|
||||
@@ -650,6 +660,11 @@ export const documentationSections = [
|
||||
source: "reconstruction-coverage.md",
|
||||
route: "/reconstruction-coverage",
|
||||
},
|
||||
{
|
||||
text: "Release exposure",
|
||||
source: "release-exposure.md",
|
||||
route: "/release-exposure",
|
||||
},
|
||||
{
|
||||
text: "Reverse-engineering tool integrations",
|
||||
source: "reverse-engineering-tools.md",
|
||||
|
||||
+3
-4
@@ -21,6 +21,7 @@ product pages. The VitePress documentation source is this `docs/` tree.
|
||||
- [Linux kernel build config](guides/native/kernel-build-config.md)
|
||||
- [Recorded crash evidence](guides/native/recorded-crashes.md)
|
||||
- [Windows Shell Link shortcuts](guides/native/windows-shortcut.md)
|
||||
- [Acquired NTFS metadata and change journals](guides/native/ntfs-metadata.md)
|
||||
|
||||
## JavaScript and Electron
|
||||
|
||||
@@ -111,10 +112,7 @@ product pages. The VitePress documentation source is this `docs/` tree.
|
||||
## Development and verification
|
||||
|
||||
- [Settings and recovery](design/limits-and-recovery.md)
|
||||
- [Flutter budget calibration](verification/flutter-budget-calibration.md)
|
||||
- [Source-map budget calibration](verification/source-map-budget-calibration.md)
|
||||
- [Source-location delivery qualification](verification/source-location-delivery.md)
|
||||
- [JavaScript precision calibration](verification/javascript-precision-calibration.md)
|
||||
- [REA limit inventory](design/rea-limit-inventory.md)
|
||||
- [MCP tool design](development/tool-design.md)
|
||||
- [Testing REA](development/testing.md)
|
||||
- [Client and agent verification](development/client-verification.md)
|
||||
@@ -199,6 +197,7 @@ the exact commit messages and references from the release they describe.
|
||||
- [Python packaged applications](python-packaged-applications.md)
|
||||
- [CPython pyc inspection](python-pyc.md)
|
||||
- [Reconstruction coverage](reconstruction-coverage.md)
|
||||
- [Release exposure](release-exposure.md)
|
||||
- [Reverse-engineering tool integrations](reverse-engineering-tools.md)
|
||||
- [Rust binary dependency metadata](rust-binaries.md)
|
||||
- [U-Boot legacy uImage containers](uimage.md)
|
||||
|
||||
+29
-4
@@ -85,10 +85,35 @@ names are retained. Original bytes remain in the caller's artifact; complete
|
||||
inventory Evidence does not embed the entire source JSON. Duplicate JSON members
|
||||
use the shared parser's last-value-wins behavior, recorded in source coverage.
|
||||
|
||||
If decoding or later validation fails after a verified read, the typed error
|
||||
retains a compact `file-snapshot-hash` observation with the exact path, digest
|
||||
and byte length. Syntax diagnostics do not quote source JSON. Cancellation
|
||||
does not replace a parser failure that has already completed.
|
||||
If decoding or validation fails after a verified read and before any operation,
|
||||
reference, or diagnostic row is retained, the typed error keeps a compact
|
||||
`file-snapshot-hash` observation with the exact path, digest and byte length.
|
||||
Syntax diagnostics do not quote source JSON. Cancellation does not replace a
|
||||
parser failure that has already completed.
|
||||
|
||||
When cancellation or the retained-facts limit stops OpenAPI traversal after at
|
||||
least one operation, reference, or diagnostic row, that observation is
|
||||
authenticated Evidence for the partial inventory rather than the hash. The
|
||||
normalized result uses the same inventory shape, `source_coverage.status` is
|
||||
`partial`, and only the examined rows are present. Reuse those rows with
|
||||
`inspect_analysis_view`. A session that already retained the Evidence uses:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": { "kind": "retained-evidence", "evidence_id": "<evidence_id>" },
|
||||
"view": {
|
||||
"kind": "api-contract",
|
||||
"collection": "operations",
|
||||
"offset": 0,
|
||||
"limit": 64
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
An inline record uses the same view with
|
||||
`source: { "kind": "inline", "evidence": <complete Evidence> }`. Do not reread
|
||||
the file to reconstruct the rows. A later hash is not substituted once this
|
||||
Evidence is attached.
|
||||
|
||||
## Resource bounds and verification
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ graph TD
|
||||
HOPPER["src/hopper/<br/>Hopper launch & Unix-socket protocol<br/>BridgeLauncher, HopperClient, protocol"]
|
||||
GHIDRA["src/ghidra/<br/>Ghidra discovery, profile & function analysis<br/>snapshot, Unix/Windows transport, bounded lifecycle"]
|
||||
IDA["src/ida/<br/>Upstream MCP contract adaptation<br/>live GUI binding or owned headless database"]
|
||||
KUNA["src/kuna/<br/>BYO Kuna deep analysis candidate<br/>discovery reads metadata; version probe on target open"]
|
||||
IDA_MCP["External ida-pro-mcp<br/>GUI proxy or database supervisor<br/>upstream installation and engine lifecycle"]
|
||||
|
||||
KUNA["src/kuna/<br/>BYO Kuna decompiler, a deep analysis candidate<br/>discovery reads metadata only; version probe when a target opens"]
|
||||
@@ -66,7 +65,7 @@ graph TD
|
||||
subgraph "Provider Process Foundation"
|
||||
PROCESS["src/process/<br/>owned process groups, private roots<br/>deadlines, bounded file reads and diagnostics, cleanup"]
|
||||
WINDOWS["src/windows/<br/>Windows host boundary adapters<br/>package loader, opaque handles, owned jobs and private runtimes"]
|
||||
WINDOWS_NATIVE["native/windows/src/<br/>Node-API implementation<br/>NTFS admission, protected DACLs and atomic Job Object assignment"]
|
||||
WINDOWS_NATIVE["native/windows/src/<br/>Node-API implementation<br/>NTFS/ReFS admission, protected DACLs and atomic Job Object assignment"]
|
||||
FILESYSTEM["src/filesystem/<br/>owned file and directory handles<br/>stable reads, staged output, caller paths"]
|
||||
end
|
||||
|
||||
@@ -193,10 +192,7 @@ graph TD
|
||||
APP -->|EVM interface port| EVM
|
||||
EVM --> PROCESS
|
||||
EVM --> DOMAIN
|
||||
COMPOSITION --> KUNA
|
||||
KUNA --> PROCESS
|
||||
KUNA --> FILESYSTEM
|
||||
KUNA --> DOMAIN
|
||||
COMPOSITION --> ANDROID_TOOLS
|
||||
ANDROID_TOOLS --> PROCESS
|
||||
ANDROID_TOOLS --> DOMAIN
|
||||
|
||||
@@ -5,7 +5,9 @@ who owns each value, when an update takes effect, how providers enforce it, and
|
||||
how to extend the system. The public tool contract is in
|
||||
[MCP contracts](../reference/mcp-contracts.md#editable-analysis-settings); recorded runtime
|
||||
checks and their limitations are in the
|
||||
[verification report](../verification/runtime-analysis-settings.md).
|
||||
[verification report](../verification/runtime-analysis-settings.md). The
|
||||
[limit inventory](rea-limit-inventory.md) lists every numeric `REA_` limit, which
|
||||
of them are runtime settings, and which stay restart-only.
|
||||
|
||||
## Problem and design boundary
|
||||
|
||||
@@ -129,12 +131,14 @@ Windows ChangeTime admission waits out a fresh timestamp before recording a
|
||||
baseline. `REA_WINDOWS_CHANGE_TIME_DRIFT_MS` (default 2000 ms, floor 1 ms,
|
||||
maximum 60000 ms), `REA_WINDOWS_CHANGE_TIME_SETTLE_POLL_MS` (default 25 ms,
|
||||
floor 1 ms, maximum 1000 ms), and `REA_WINDOWS_CHANGE_TIME_SETTLE_MAX_POLLS`
|
||||
(default 40, floor 1, maximum 1000) are launch settings. Unset keeps those
|
||||
defaults. An invalid value is a configuration error: it names the setting, the
|
||||
rejected value, source `setting`, the default, the floor, and the maximum, and
|
||||
says to set a positive decimal integer in the environment that starts REA and
|
||||
then restart REA. There is no runtime override. Setup forwards an explicit
|
||||
selection. When the poll budget runs out, admission keeps the last observation
|
||||
(default 40, floor 1, maximum 1000) are runtime settings. Unset keeps those
|
||||
defaults. An invalid launch value is a configuration error: it names the
|
||||
setting, the rejected value, source `setting`, the default, the floor, the
|
||||
maximum, and `update_mode: "runtime"`. It omits `pending_restart` because
|
||||
the rejected value is not an accepted configuration. Change the
|
||||
active value with `update_analysis_settings`. The launch seed must be a
|
||||
positive decimal integer in that range. Setup forwards an explicit selection.
|
||||
When the poll budget runs out, admission keeps the last observation
|
||||
instead of failing the readable file. Raising a setting only changes how long
|
||||
that wait can last. It does not change Windows ChangeTime itself.
|
||||
|
||||
@@ -255,8 +259,8 @@ are runtime-wide, not scoped to a target or an individual connection.
|
||||
### Failure and retry
|
||||
|
||||
An ASAR admission error supplies `details.limit` with the exact setting,
|
||||
effective value, units, bounds, scope, application point, restart requirement
|
||||
and, when known, required bytes and value source. The agent can immediately call:
|
||||
effective value, units, bounds, scope, application point, `update_mode`,
|
||||
`pending_restart` and, when known, required bytes and value source. The agent can immediately call:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -273,13 +277,34 @@ that argument; raising a runtime default cannot override it.
|
||||
|
||||
The resource owner constructs `details.limit` from the registry plus the budget
|
||||
it actually enforced. Metadata includes `agent_editable: true`,
|
||||
`scope: "rea-runtime"`, and `rea_restart_required: false`. Optional
|
||||
`scope: "rea-runtime"`, `update_mode`, and `pending_restart`. `update_mode`
|
||||
is `runtime` when `update_analysis_settings` can change the active value,
|
||||
`restart` when this process keeps the value it started with, and `parameter`
|
||||
when the budget is adjustable through a per-call argument. Its `source` records
|
||||
whether the reported value came from a request or a default. An explicit `analysis_timeout_ms`,
|
||||
`max_heap_mb`, or `command_timeout_ms`, plus artifact reader limits and
|
||||
web-network capture budgets, use `parameter`. `pending_restart` is false when
|
||||
that reported value is the one this process is using. Optional
|
||||
`required_value`, `source`, and `parameter` fields are supplied only where known
|
||||
or applicable. Do not infer a source because a value happens to equal a default.
|
||||
Error copying, attribution, redaction, and delivery must preserve these facts.
|
||||
Human-readable remediation explains the same failure; clients should not need
|
||||
to parse that sentence to identify an editable setting.
|
||||
|
||||
This output is breaking. Results and errors no longer carry the previous
|
||||
restart boolean or a single effect field, and there is no compatibility alias.
|
||||
Read `update_mode` to see whether the setter can change the active value, and
|
||||
`pending_restart` to see whether a configured value is waiting. A configuration
|
||||
error for a Windows ChangeTime setting carries `update_mode` on
|
||||
`details.settings`. Its rejected value does not establish an accepted pending
|
||||
configuration, so `pending_restart` is omitted. The removed field names
|
||||
are listed in the changelog.
|
||||
|
||||
An inspected setting whose launch value is invalid and which has no runtime
|
||||
override likewise omits `pending_restart`: it has no accepted configured value
|
||||
to classify. Setting a valid runtime override reports `pending_restart: false`;
|
||||
resetting it restores the invalid launch state and the omission.
|
||||
|
||||
`scope` and `applies_at` describe a continuing caller, such as an MCP
|
||||
connection. A one-shot invocation, such as a CLI command, has released its
|
||||
provider session and exited its runtime before its caller reads the failure,
|
||||
@@ -288,8 +313,11 @@ so its adapter projects with an explicit `"invocation"` caller lifetime.
|
||||
`scope: "rea-invocation"`, `applies_at: "next_invocation"` and the launch
|
||||
`environment` seed when one exists. `agent_editable: true` still holds, because
|
||||
the caller chooses that environment value or per-call `parameter` for the new
|
||||
invocation; `rea_restart_required: false` means no running REA process needs a
|
||||
restart. A producer keeps guidance that holds only while its caller retains the
|
||||
invocation; `update_mode: "runtime"` and `pending_restart: false` mean the
|
||||
reported value is active in this process. `update_mode: "restart"` means
|
||||
`update_analysis_settings` does not change it. `update_mode: "parameter"` means
|
||||
the budget is adjustable through a per-call argument; `source` identifies where
|
||||
the reported value came from. A producer keeps guidance that holds only while its caller retains the
|
||||
session, such as "the Ghidra session remains usable" or a same-session runtime
|
||||
update, in `continuingCallerGuidance`; the shared presentation adds it only for
|
||||
a continuing caller. The producer's own message and remediation must stay true
|
||||
@@ -499,7 +527,10 @@ own `expanded_bytes` controls its independently enforced bundle expansion.
|
||||
|
||||
Failures preserve `details.reader_limit` with the exact parameter, effective
|
||||
value, units, supported range, required value when known, next-call scope and
|
||||
`can_increase`. When `can_increase` is true, raise that field and retry the same
|
||||
`can_increase`. `update_mode` is `parameter`: the caller selects the value on
|
||||
the next call, and `update_analysis_settings` does not accept it.
|
||||
`pending_restart` is false. Web-network capture budgets use the same mode.
|
||||
When `can_increase` is true, raise that field and retry the same
|
||||
complete artifact. At the supported maximum, or when the required representation
|
||||
exceeds it, the failure is not retryable by increasing that budget; inspect the
|
||||
declared dimensions and input validity, or explicitly choose a suitable reader.
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
# REA limit inventory
|
||||
|
||||
Audit for [#9881](https://github.com/morluto/rea/issues/9881). Counts below are
|
||||
from this revision. The inventory includes numeric `REA_` launch limits and
|
||||
the fixed reconnect control generated into the Hopper bridge.
|
||||
`scripts/verify/rea-numeric-limits.mjs` checks recognized TypeScript source
|
||||
reads (tests excluded) against the environment seeds of
|
||||
[`ANALYSIS_SETTINGS`](https://github.com/morluto/rea/blob/main/src/domain/analysisSettingDefinitions.ts) or an
|
||||
exception in [`numericLimitRegistry.ts`](https://github.com/morluto/rea/blob/main/src/domain/numericLimitRegistry.ts)
|
||||
with a reason. Static syntax recognition cannot prove arbitrary dynamic reads
|
||||
or how often a function executes.
|
||||
|
||||
The Hopper demo-dialog timeout is read by `scripts/hopper-demo-x11.py`, and
|
||||
the reconnect control is generated by `src/hopper/BridgeLauncher.ts` for
|
||||
`bridge/hopper_bridge.py`. Their registry entries identify behavioral witness
|
||||
tests. Node lint checks those paths exist but reports their behavior as
|
||||
unverified; it does not execute Python or prove either reader. Run
|
||||
`npm run test:focused -- tests/boundary/providers/hopper/linuxPrivateDisplay.test.ts tests/boundary/providers/hopper/hopperBridgeReconnect.test.ts`
|
||||
to exercise the witnesses. The reconnect witness exercises the bridge consumer
|
||||
with an injected timeout; `npm run test:local -- src/hopper/bridgeBootstrapLimit.test.ts`
|
||||
verifies the separate launcher output. Neither test is run by Node lint. A
|
||||
skipped Python test leaves its behavior unverified.
|
||||
|
||||
`update_mode` is `runtime` when `update_analysis_settings` can change the active
|
||||
value, `restart` when this process keeps the value it started with, and
|
||||
`parameter` when the budget is adjustable through a per-call argument; `source`
|
||||
separately identifies where the reported value came from.
|
||||
`pending_restart` is true only when an accepted configured value is not the one
|
||||
this process is using. A rejected Windows ChangeTime launch value does not
|
||||
establish an accepted configuration, so that failure omits `pending_restart`.
|
||||
The other values reported here are in force, so `pending_restart` is false. Prose that only says to
|
||||
restart REA is marked `prose`. `mcp_server_restart_required` is a
|
||||
server-identity alignment state in `src/serverIdentity.ts`, not a setting field.
|
||||
|
||||
Three numeric limits are absent from this tree and are being moved into the
|
||||
runtime system on their own PRs. This audit does not change them:
|
||||
|
||||
| Name | Tracking |
|
||||
| -------------------------------------------- | -------- |
|
||||
| `REA_NTFS_MFT_MAX_FILE_BYTES` | #9868 |
|
||||
| `REA_REGF_HIVE_MAX_FILE_BYTES` | #9865 |
|
||||
| `REA_WEB_BUNDLE_ENDPOINT_LITERAL_CANDIDATES` | #9836 |
|
||||
|
||||
When those names land in `src`, the static check requires them to be analysis
|
||||
settings. They are not on the restart-only list.
|
||||
|
||||
## Counts
|
||||
|
||||
| Category | Count |
|
||||
| --------------------------------------------------------------------- | ---------------------------------------------------------------------------: |
|
||||
| Runtime analysis settings | 28 (25 have an `REA_` seed; 3 are per-call parameters only) |
|
||||
| Per-call numeric `REA_` limits still read from the launch environment | 0 |
|
||||
| Restart-only numeric `REA_` limits | 15 |
|
||||
| Numeric `REA_` candidates recognized in TypeScript source | 38 |
|
||||
| Numeric `REA_` controls with external or generated-reader provenance | 2 |
|
||||
| Non-numeric `REA_` settings kept restart-only | 52 caller settings, plus process-protocol names that are not caller settings |
|
||||
| Hardcoded ceilings left for follow-up | grouped below; none converted in the inventory change |
|
||||
|
||||
## Runtime analysis settings
|
||||
|
||||
Already adjustable with `update_analysis_settings`. Each call reads the snapshot
|
||||
accepted for that operation. Launch source is `default` or `setting`; a runtime
|
||||
override is `source: "runtime"`. The structured field is `update_mode: "runtime"` and `pending_restart: false`.
|
||||
`applies_at` is the finer point
|
||||
(`next_operation`, `next_worker`, or `next_startup`).
|
||||
|
||||
| Setting | Environment seed | Owner | Default | Floor | Maximum | Read |
|
||||
| -------------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------- | ----------------------------------------- | ---------------: | -------------------------------------: | --------------------- |
|
||||
| `asar.max_header_bytes` | `REA_ASAR_MAX_HEADER_BYTES` | `src/domain/analysisResourceLimits.ts` | 16777216 | 1 | 268435456 | per operation |
|
||||
| `asar.max_listing_bytes` | `REA_ASAR_MAX_LISTING_BYTES` | `src/domain/analysisResourceLimits.ts` | 67108864 | 1 | `Number.MAX_SAFE_INTEGER` | per operation |
|
||||
| `ghidra.value_flow_max_operations` | `REA_GHIDRA_VALUE_FLOW_MAX_OPERATIONS` | `src/domain/analysisResourceLimits.ts` | 3000 | 1 | 2147483647 | per operation |
|
||||
| `ghidra.value_flow_max_inputs_per_operation` | `REA_GHIDRA_VALUE_FLOW_MAX_INPUTS_PER_OPERATION` | `src/domain/analysisResourceLimits.ts` | 64 | 1 | 2147483647 | per operation |
|
||||
| `ghidra.value_flow_max_edges` | `REA_GHIDRA_VALUE_FLOW_MAX_EDGES` | `src/domain/analysisResourceLimits.ts` | 12000 | 1 | 2147483647 | per operation |
|
||||
| `ghidra.decompile_max_payload_mib` | `REA_GHIDRA_DECOMPILE_MAX_PAYLOAD_MIB` | `src/domain/analysisResourceLimits.ts` | unset (`null`, unbounded payload policy) | 1 | 2047 | per operation |
|
||||
| `ghidra.startup_timeout_ms` | `REA_GHIDRA_STARTUP_TIMEOUT_MS` | `src/domain/analysisResourceLimits.ts` | 330000 | 1 | 2147483647 | next provider startup |
|
||||
| `hopper.startup_timeout_ms` | `REA_HOPPER_STARTUP_TIMEOUT_MS` | `src/domain/analysisResourceLimits.ts` | 120000 | 1 | 2147483647 | next provider startup |
|
||||
| `ghidra.decompile_timeout_seconds` | `REA_GHIDRA_DECOMPILE_TIMEOUT_SECONDS` | `src/domain/analysisResourceLimits.ts` | unset (`null`, decompile stays unbounded) | 1 | `MAX_GHIDRA_DECOMPILE_TIMEOUT_SECONDS` | per operation |
|
||||
| `jadx.operation_timeout_ms` | `REA_JADX_OPERATION_TIMEOUT_MS` | `src/domain/analysisResourceLimits.ts` | 120000 | 1 | 2147483647 | per operation |
|
||||
| `regex.matching_deadline_ms` | `REA_REGEX_MATCHING_DEADLINE_MS` | `src/domain/analysisResourceLimits.ts` | 5000 | 1 | 2147483647 | per operation |
|
||||
| `regex.worker_heap_request_mib` | `REA_REGEX_WORKER_HEAP_REQUEST_MIB` | `src/domain/analysisResourceLimits.ts` | 128 | 7 | 16384 | next worker |
|
||||
| `capture.decoder_old_generation_mib` | `REA_CAPTURE_DECODER_OLD_GENERATION_MIB` | `src/domain/analysisResourceLimits.ts` | 192 | semi-space floor | 16384 | next worker |
|
||||
| `javascript.analysis_timeout_ms` | none (`analysis_timeout_ms`) | `src/domain/javascript/javascriptAnalysisResourceControls.ts` | owner default | 1 | 2147483647 | per operation |
|
||||
| `javascript.max_heap_mb` | none (`max_heap_mb`) | `src/domain/javascript/javascriptAnalysisResourceControls.ts` | owner default | owner floor | owner maximum | next worker |
|
||||
| `wasm.command_timeout_ms` | none (`command_timeout_ms`) | `src/domain/wasm/wasmArtifact.ts` | owner default | 1 | owner maximum | per operation |
|
||||
| `native.matching_representation_bytes` | `REA_NATIVE_MATCHING_REPRESENTATION_BYTES` | `src/domain/analysisResourceLimits.ts` | 100663296 | 1 | 1073741824 | per operation |
|
||||
|
||||
An out-of-range `update_analysis_settings` value is rejected by the setting's
|
||||
schema. Invalid launch seeds that the global environment parser accepts as
|
||||
provider-local stay inspectable with `source: "invalid"`.
|
||||
|
||||
## Per-call limits in the runtime system
|
||||
|
||||
These are checked when the work runs. Each keeps its `REA_` seed, default,
|
||||
floor, and maximum. The accepted operation snapshot supplies the value.
|
||||
`update_mode` is `runtime` and `pending_restart` is false for the value in
|
||||
force. An update outside the range is rejected. A hit names the setting and
|
||||
reports the current value, source, and range. A rejected Windows ChangeTime launch value omits `pending_restart`.
|
||||
|
||||
| Environment | Owner | Default | Floor | Maximum | Applies | Fields |
|
||||
| ------------------------------------------ | ------------------------------------------- | ----------------------: | ----: | ---------: | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- |
|
||||
| `REA_BRIDGE_MAX_REQUEST_BYTES` | `src/config/bridgeMaxRequestBytes.ts` | 16777216 | 7464 | 536870887 | each bridge request, from the accepted operation snapshot | `update_mode: "runtime"`, `pending_restart: false` |
|
||||
| `REA_DEBUGGER_COMMAND_DEADLINE_MS` | `src/domain/analysisResourceLimits.ts` | 120000 | 1 | 2147483647 | each command, from the accepted operation snapshot | `update_mode: "runtime"`, `pending_restart: false` |
|
||||
| `REA_DEBUGGER_MAX_COMMAND_OUTPUT_BYTES` | `src/domain/analysisResourceLimits.ts` | 16777216 | 1 | 89303718 | each command, from the accepted operation snapshot | `update_mode: "runtime"`, `pending_restart: false` |
|
||||
| `REA_HOPPER_CALLER_SCAN_BUDGET_MS` | `src/domain/analysisResourceLimits.ts` | 2000 | 1 | 2147483647 | each caller scan, from the accepted operation snapshot | `update_mode: "runtime"`, `pending_restart: false` |
|
||||
| `REA_JEB_MCP_TIMEOUT_MS` | `src/jeb/JebMcpConnection.ts` | 60000 (MCP SDK default) | 1 | 2147483647 | discovery and each tools/call, from the accepted operation snapshot | `update_mode: "runtime"`, `pending_restart: false` |
|
||||
| `REA_KUNA_PROJECT_TIMEOUT_MS` | `src/kuna/KunaConfiguration.ts` | 1800000 | 1 | 2147483647 | each project export and whole-program scan, from the accepted operation snapshot | `update_mode: "runtime"`, `pending_restart: false` |
|
||||
| `REA_KUNA_TIMEOUT_MS` | `src/kuna/KunaConfiguration.ts` | 120000 | 1 | 2147483647 | each function decompile, from the accepted operation snapshot | `update_mode: "runtime"`, `pending_restart: false` |
|
||||
| `REA_PWNTOOLS_MAX_INPUT_BYTES` | `src/native/pwntools/PwntoolsInputLimit.ts` | 33554432 | 1 | 1073741824 | each pwntools decode, unless the call passes `producer_limits.input_bytes`; otherwise the operation snapshot | `update_mode: "runtime"`, `pending_restart: false` |
|
||||
| `REA_WINDOWS_CHANGE_TIME_DRIFT_MS` | `src/config/windowsChangeTimeSettle.ts` | 2000 | 1 | 60000 | each ChangeTime observation, from the accepted operation snapshot | `update_mode: "runtime"`; invalid launch omits `pending_restart` |
|
||||
| `REA_WINDOWS_CHANGE_TIME_SETTLE_POLL_MS` | `src/config/windowsChangeTimeSettle.ts` | 25 | 1 | 1000 | each ChangeTime observation, from the accepted operation snapshot | `update_mode: "runtime"`; invalid launch omits `pending_restart` |
|
||||
| `REA_WINDOWS_CHANGE_TIME_SETTLE_MAX_POLLS` | `src/config/windowsChangeTimeSettle.ts` | 40 | 1 | 1000 | each ChangeTime observation, from the accepted operation snapshot | `update_mode: "runtime"`; invalid launch omits `pending_restart` |
|
||||
|
||||
## Restart-only numeric limits
|
||||
|
||||
These stay out of `update_analysis_settings`.
|
||||
|
||||
| Environment | Owner | Default | Floor | Maximum | Read | Why restart-only |
|
||||
| ----------------------------------- | -------------------------------------- | ------------------: | -------: | ------------------------: | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| `REA_DEBUGGER_MAX_PENDING_COMMANDS` | `src/domain/analysisResourceLimits.ts` | 16 | 1 | 256 | debugger manager construction | Queue capacity of the manager created at startup. `update_mode: "restart"` and `pending_restart: false`. |
|
||||
| `REA_DEBUGGER_MAX_SESSIONS` | `src/domain/analysisResourceLimits.ts` | 8 | 1 | 64 | debugger manager construction | Session-pool size of the manager created at startup. `update_mode: "restart"` and `pending_restart: false`. |
|
||||
| `REA_HOPPER_DEMO_DIALOG_TIMEOUT_MS` | `src/domain/hopperStartupFailure.ts` | 10000 | 1 | 2147483647 | Linux private-display adapter start | The helper reads the process environment. Prose restart. |
|
||||
| `REA_JADX_ACTIVE_PROCESSOR_COUNT` | `src/android/JadxConfiguration.ts` | unset (JVM default) | 1 | 2147483647 | JADX JVM launch | `-XX:ActiveProcessorCount` is fixed for that JVM. Prose on invalid values. |
|
||||
| `REA_JADX_HEAP_MIB` | `src/android/JadxConfiguration.ts` | unset (JVM default) | 1 | `Number.MAX_SAFE_INTEGER` | JADX JVM launch | `-Xmx` is fixed for that JVM. Prose on invalid values. |
|
||||
| `REA_KUNA_CACHE_MAX_BYTES` | `src/kuna/KunaConfiguration.ts` | 4294967296 | 1048576 | `Number.MAX_SAFE_INTEGER` | Kuna cache construction | The cache is sized once for the provider. Prose restart. |
|
||||
| `REA_KUNA_JOBS` | `src/kuna/KunaConfiguration.ts` | 1 | 1 | 32 | Kuna run-slot construction | Worker-pool width for the provider. Prose restart. |
|
||||
| `REA_MCP_DOCTOR_DEADLINE_MS` | `src/config/mcpStartupBudgets.ts` | 30000 | 1 | 2147483647 | MCP server startup | Startup phase of the MCP server itself. Prose. |
|
||||
| `REA_MCP_FIRST_CATALOG_BUDGET_MS` | `src/config/mcpStartupBudgets.ts` | 20000 | 1 | 2147483647 | MCP server startup | Startup phase of the MCP server itself. Prose. |
|
||||
| `REA_MCP_INITIALIZE_BUDGET_MS` | `src/config/mcpStartupBudgets.ts` | 15000 | 1 | 2147483647 | MCP server startup | Startup phase of the MCP server itself. Prose. |
|
||||
| `REA_MCP_MAX_INPUT_ELEMENTS` | `src/config/mcpInputBudget.ts` | 1024 | 1 | `Number.MAX_SAFE_INTEGER` | MCP server creation | Argument admission for the server process. Prose restart. |
|
||||
| `REA_MCP_MAX_RESPONSE_BYTES` | `src/config/mcpResponseBudget.ts` | 10485760 when unset | 10485760 | `Number.MAX_SAFE_INTEGER` | MCP server creation | Stdio receive buffer and the paired client buffer. Prose restart. |
|
||||
| `REA_MCP_TOOLS_LIST_BUDGET_MS` | `src/config/mcpStartupBudgets.ts` | 5000 | 1 | 2147483647 | MCP server startup | Startup phase of the MCP server itself. Prose. |
|
||||
| `REA_RECONNECT_TIMEOUT_SECONDS` | `src/hopper/BridgeLauncher.ts` | 30 | 30 | 30 | written into the Hopper bridge helper | Not a caller setting. It is `HOPPER_SHUTDOWN_TIMEOUT_MS / 1000`. |
|
||||
| `REA_SWIFTC_COMPILE_TIMEOUT_MS` | `src/config/providerStartupTimeout.ts` | 120000 | 1 | 2147483647 | Darwin ownership-helper reader construction | Captured at process start for that helper compile. Prose restart. |
|
||||
|
||||
## Restart-only non-numeric settings
|
||||
|
||||
No floor or maximum. They are read from the launch environment at startup.
|
||||
Recovery text tells the caller to change the launch environment, which takes
|
||||
effect on the next process. They stay
|
||||
restart-only because they choose a command, a binary, a filesystem root, the
|
||||
browser sandbox, secret patterns, the provider, or the shape of the MCP server
|
||||
or logger.
|
||||
|
||||
| Name | Owner | Why |
|
||||
| ------------------------------------ | -------------------------------------------------- | ------------------------------------------- |
|
||||
| `REA_ADB_PATH` | `src/adb/AdbConfiguration.ts` | Caller-selected executable path. |
|
||||
| `REA_AGENT_ENV_COMMAND` | `src/application/DesktopBuildDoctor.ts` | Caller-selected command. |
|
||||
| `REA_ANALYSIS_PROVIDER` | `src/config/environment.ts` | Provider choice for the process. |
|
||||
| `REA_APKTOOL_COMMAND` | `src/apktool/ApktoolConfiguration.ts` | Caller-selected command. |
|
||||
| `REA_BINWALK_COMMAND` | `src/application/SetupRegistrationEnvironment.ts` | Caller-selected command. |
|
||||
| `REA_BROWSER_EXECUTABLE` | `src/application/CapabilityInventory.ts` | Caller-selected browser binary. |
|
||||
| `REA_BROWSER_NO_SANDBOX` | `src/application/SetupRegistrationEnvironment.ts` | Browser sandbox policy. |
|
||||
| `REA_CAPINFOS_COMMAND` | `src/pcap/PcapConfiguration.ts` | Caller-selected command. |
|
||||
| `REA_CUTTER_BRIDGE_DIR` | `src/application/SetupRegistrationEnvironment.ts` | Filesystem root for the Cutter bridge. |
|
||||
| `REA_DARWIN_MODULE_CACHE_PATH` | `src/application/SetupRegistrationEnvironment.ts` | Filesystem path for the Swift module cache. |
|
||||
| `REA_DARWIN_SWIFTC_PATH` | `src/application/SetupRegistrationEnvironment.ts` | Caller-selected compiler path. |
|
||||
| `REA_DCONF_COMMAND` | `src/desktop/DconfDatabaseReader.ts` | Caller-selected command. |
|
||||
| `REA_DOCKER_COMMAND` | `src/application/DesktopBuildDoctor.ts` | Caller-selected command. |
|
||||
| `REA_EVM_PRLIMIT_COMMAND` | `src/application/SetupRegistrationEnvironment.ts` | Caller-selected command. |
|
||||
| `REA_FIRMWARE_PRLIMIT_COMMAND` | `src/application/SetupRegistrationEnvironment.ts` | Caller-selected command. |
|
||||
| `REA_GDB_COMMAND` | `src/application/SetupRegistrationEnvironment.ts` | Caller-selected debugger binary. |
|
||||
| `REA_GHIDRA_CHECKPOINT_DIR` | `src/config/environment.ts` | Filesystem root. |
|
||||
| `REA_GHIDRA_COMPILER_SPEC_ID` | `src/config/environment.ts` | Provider analysis choice. |
|
||||
| `REA_GHIDRA_DISABLED_ANALYZERS` | `src/config/environment.ts` | Provider analysis choice. |
|
||||
| `REA_GHIDRA_LANGUAGE_ID` | `src/config/environment.ts` | Provider analysis choice. |
|
||||
| `REA_GHIDRA_NATIVEAOT_JAR` | `src/config/environment.ts` | Caller-selected binary path. |
|
||||
| `REA_GHIDRA_PROGRAM_NAME` | `src/config/environment.ts` | Provider project selection. |
|
||||
| `REA_GHIDRA_PROJECT_PATH` | `src/config/environment.ts` | Filesystem root. |
|
||||
| `REA_GHIDRA_SEED_FILE` | `src/config/environment.ts` | Filesystem path. |
|
||||
| `REA_IDA_MCP_CONFIG` | `src/config/environment.ts` | Filesystem path of the IDA MCP config. |
|
||||
| `REA_ILSPY_CMD_PATH` | `src/config/environment.ts` | Caller-selected executable path. |
|
||||
| `REA_JADX_MCP_JAR` | `src/android/JadxConfiguration.ts` | Caller-selected binary path. |
|
||||
| `REA_JAVASCRIPT_PRLIMIT_COMMAND` | `src/application/SetupRegistrationEnvironment.ts` | Caller-selected command. |
|
||||
| `REA_JEB_MCP_URL` | `src/config/environment.ts` | Provider endpoint. |
|
||||
| `REA_KUNA_CACHE_DIR` | `src/kuna/KunaConfiguration.ts` | Filesystem root. |
|
||||
| `REA_KUNA_COMMAND` | `src/kuna/KunaConfiguration.ts` | Caller-selected executable path. |
|
||||
| `REA_LOG_LEVEL` | `src/config/environment.ts` | Logger configuration for the process. |
|
||||
| `REA_MCP_INPUT_SCHEMA_PROFILE` | `src/config/environment.ts` | MCP server schema shape. |
|
||||
| `REA_MCP_OUTPUT_SCHEMA_PROFILE` | `src/config/environment.ts` | MCP server schema shape. |
|
||||
| `REA_MCP_TOOL_CATALOG_PROFILE` | `src/config/environment.ts` | MCP server catalog shape. |
|
||||
| `REA_MCP_TOOL_FAMILIES` | `src/config/environment.ts` | Which tools the MCP server registers. |
|
||||
| `REA_MITMDUMP_COMMAND` | `src/application/SetupRegistrationEnvironment.ts` | Caller-selected command. |
|
||||
| `REA_OBJDUMP_COMMAND` | `src/application/SetupRegistrationEnvironment.ts` | Caller-selected command. |
|
||||
| `REA_PWNDBG_GDB` | `src/native/pwndbg/PwndbgCoreContext.ts` | Caller-selected debugger binary. |
|
||||
| `REA_PWNDBG_GDBINIT` | `src/native/pwndbg/PwndbgCoreContext.ts` | Caller-selected file path. |
|
||||
| `REA_PWNDBG_VENV_PATH` | `src/native/pwndbg/PwndbgCoreContext.ts` | Filesystem root. |
|
||||
| `REA_PWNTOOLS_PYTHON` | `src/native/pwntools/PwntoolsDecoder.ts` | Caller-selected interpreter path. |
|
||||
| `REA_REFERENCE_SECRET_PATTERNS_JSON` | `src/config/environment.ts` | Secret-pattern policy. |
|
||||
| `REA_RIZIN_COMMAND` | `src/rizin/RizinDebugSessionManager.ts` | Caller-selected debugger binary. |
|
||||
| `REA_SIGROK_COMMAND` | `src/signals/SigrokRecordingProvider.ts` | Caller-selected command. |
|
||||
| `REA_SIGROK_PRLIMIT_COMMAND` | `src/signals/SigrokRecordingProvider.ts` | Caller-selected command. |
|
||||
| `REA_TSHARK_COMMAND` | `src/pcap/PcapConfiguration.ts` | Caller-selected command. |
|
||||
| `REA_TSHARK_PRLIMIT_COMMAND` | `src/pcap/PcapNativeBound.ts` | Caller-selected command. |
|
||||
| `REA_UNBLOB_COMMAND` | `src/application/SetupRegistrationEnvironment.ts` | Caller-selected command. |
|
||||
| `REA_WABT_BIN_DIRECTORY` | `src/wasm/WabtArtifactProvider.ts` | Filesystem root of the WABT tools. |
|
||||
| `REA_WAKARU_COMMAND` | `src/application/SetupRegistrationEnvironment.ts` | Caller-selected command. |
|
||||
| `REA_XPROP_COMMAND` | `src/application/desktop/DesktopCaptureFailure.ts` | Caller-selected command. |
|
||||
|
||||
`REA_MANAGED_LINUX_HOPPER_LAUNCHER` is a fixed path constant, and
|
||||
`REA_WORKFLOW_PROVIDER` is a provider identity object. Neither is an
|
||||
environment setting. Names that look like `REA_` but are process protocol, not
|
||||
caller settings:
|
||||
`REA_ELECTRON_CAPTURE_ARGV`, `REA_BUILD_COMMIT`, `REA_BUILD_COMPUTER_REA_ARCHIVE`, `REA_INSTALL_SCRIPT`,
|
||||
`REA_OWNS_PROCESS_LIFETIME`, `REA_PAYLOAD`, `REA_PROCESS_RUN_ID`, `REA_RUN_ID`,
|
||||
`REA_SOCKET`, `REA_STATE_FORMAT`, `REA_TARGET_PATH`, `REA_TOKEN`, bridge markers
|
||||
such as `REA_COMMAND_COMPLETE_`, and the `ERR_REA_WINDOWS_NATIVE` code.
|
||||
`GHIDRA_INSTALL_DIR`, `JAVA_HOME`, `HOPPER_LAUNCHER_PATH`, `HOPPER_TARGET_PATH`,
|
||||
`HOPPER_TARGET_KIND`, and `HOPPER_LOADER_ARGS_JSON` are launch configuration
|
||||
without the `REA_` prefix. Paths and the provider choice among them stay
|
||||
restart-only for the same reason as the table above.
|
||||
|
||||
## Hardcoded ceilings left for follow-up
|
||||
|
||||
These are checked per call and tell the caller this release has no runtime
|
||||
override. They are not `REA_` settings, so the numeric-limit check does not
|
||||
list them. Each family has its own owner. Turning one into a setting needs that
|
||||
owner's default, floor, maximum, and an error that carries the setting id,
|
||||
value, source, and range. Format and protocol ceilings that the
|
||||
[limits guide](limits-and-recovery.md) already calls fixed stay fixed. In
|
||||
particular, JSON nesting stops at `MAX_JSON_DEPTH` (1000) and the debugger
|
||||
control-reply budget stays separate from
|
||||
`REA_DEBUGGER_MAX_COMMAND_OUTPUT_BYTES`.
|
||||
|
||||
| Family | Examples | Follow-up |
|
||||
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- |
|
||||
| Native structural input ceilings | PE resources, imports, load config, certificates, exports, initializers, binary hardening, Windows shortcuts | One setting per ceiling, or a shared input budget only where the owners match. |
|
||||
| Native plist | `MAX_NATIVE_PLIST_BYTES`, decode bytes, nesting depth | Separate from JSON depth. |
|
||||
| SQLite inspection | concurrent inspections, input bytes, diagnostic bytes | Pool width stays restart-only if it sizes the worker set; byte budgets can become settings. |
|
||||
| Producer command allowances | fixed command deadline and retained output where the text says there is no runtime override | Distinct from per-call `producer_limits`. |
|
||||
| Hopper caller-scan retention and page allowances | `HOPPER_CALLER_SCAN_RETENTION_BYTES`, `HOPPER_CALLER_PAGE_ALLOWANCE_BYTES` | Explicitly not raised by the scan time budget. |
|
||||
| Rizin frame protocol | `MAX_FRAME_BYTES`, queued frames | Protocol bounds, not caller budgets. |
|
||||
| Debugger detach and control replies | `DETACH_TIMEOUT_MS`, `DEBUGGER_CONTROL_REPLY_BYTES` | Ownership deadlines, not the shared command deadline. |
|
||||
| Web network capture nesting | `max_nesting_depth` already has a per-call parameter | The fixed depth maximum is the follow-up, not the parameter. |
|
||||
|
||||
## Static check
|
||||
|
||||
`npm run lint` runs `scripts/verify/rea-numeric-limits.mjs` after
|
||||
dependencies are installed. `scripts/verify/architecture-guards.mjs` runs the
|
||||
same check when `typescript6` is already installed; the pre-install CI step
|
||||
cannot. The check scans `src` excluding tests,
|
||||
keeps names that are numeric limits, and requires each name to be an
|
||||
`environment` on an analysis setting or a registry entry with a reason.
|
||||
The registry accepts only `restart-only`. A limit checked on each call has to
|
||||
be an analysis setting. The check rejects a `per-call` registry entry.
|
||||
@@ -138,7 +138,8 @@ that could not be released.
|
||||
If the capture fails for any other reason before `capture.json` is written,
|
||||
the application is closed the same way and the content already retained is
|
||||
removed from the capture folder. The error names any process or file that
|
||||
could not be removed.
|
||||
could not be removed. An already-failed capture retains its original failure
|
||||
and reports cancellation during cleanup separately.
|
||||
|
||||
A person types these lines in the terminal. An agent can drive the
|
||||
application with a tool such as `xdotool` and write the lines to a FIFO that
|
||||
@@ -185,8 +186,9 @@ package that installed it. A Debian package records its name, version,
|
||||
architecture and the apt sources that list the installed version, with the
|
||||
origin (`o=`) apt reports for each source in `source_origins`, such as `Ubuntu`
|
||||
for the Ubuntu archive and its mirrors or `LP-PPA-<name>` for a PPA; an empty
|
||||
source list means the version came from a local `.deb` or the package lists
|
||||
are missing, which `package_lists_present` tells apart. apt's lists folder,
|
||||
source list means apt reports no source for the installed version.
|
||||
`package_lists_present` reports whether the lists are present. It is `null`
|
||||
when REA cannot read the lists directory. apt's lists folder,
|
||||
and the trusted keys below, are where `apt-config` resolves
|
||||
`Dir::State::Lists`, `Dir::Etc::TrustedParts` and `Dir::Etc::Trusted` under
|
||||
`Dir`, so an `APT_CONFIG` file that moves them is followed: on a computer
|
||||
@@ -214,9 +216,9 @@ does not bring it. A program link that dpkg does not own counts as owned when
|
||||
dpkg owns the file it resolves to, as an alternatives link does. An
|
||||
`--executable` launch, or an entry no package owns, such as
|
||||
one in `~/.local/share/applications`, records the executable's package. When
|
||||
`dpkg-query` does not finish or exits with an error for the executable or the
|
||||
entry, the package is `unknown` and the limitations say which path, since a
|
||||
failed lookup is not proof that no package owns it. The sources, vendor
|
||||
`dpkg-query` fails for the executable or entry, or the selected path contains
|
||||
characters `dpkg-query -S` would interpret as a pattern, package ownership is
|
||||
`unknown` and the limitations name the path. The sources, vendor
|
||||
repositories and `--package-file` match below are the recorded package's; the
|
||||
library walk still reads the executable.
|
||||
|
||||
@@ -243,7 +245,9 @@ writes it on Ubuntu 24.04, has that key as its only candidate, as apt trusts
|
||||
no other for it: REA reads the field's continuation lines as deb822 writes
|
||||
them, a `.` line standing for an empty one, from the key block's `BEGIN` line
|
||||
to its last `END` line, and records the key's path as the entry's sources
|
||||
file. A key counts when gpgv reports a valid signature by it and no bad,
|
||||
file. A fingerprint restriction in `Signed-By` leaves `signing_key` null.
|
||||
The reason names the restriction that REA could not verify. A key counts
|
||||
when gpgv reports a valid signature by it and no bad,
|
||||
expired, revoked or unverifiable signature by it, whatever gpgv's exit status:
|
||||
a release also signed by a key the host lacks makes gpgv fail. Each candidate
|
||||
is copied, an armored key decoded to a binary keyring, into a private
|
||||
@@ -272,8 +276,16 @@ looks each soname up as ld.so does: in the RPATH of the needing image and of
|
||||
each image up its chain of loaders to the executable when the needing image
|
||||
has no RUNPATH, then in its RUNPATH (with `$ORIGIN` expanded and paths
|
||||
normalized), and then in the `ldconfig -p` cache entries for the executable's
|
||||
machine. It asks `dpkg-query -S` for each library's package. Libraries in the
|
||||
executable's own folder belong to the application: they are walked but not
|
||||
machine. Each candidate's ELF machine, class and byte order must match the
|
||||
needing image before it is selected or its dependencies are walked. A foreign
|
||||
search-path candidate is skipped in favor of later directories or the cache; a
|
||||
cache architecture flag alone does not establish compatibility. If a candidate's
|
||||
identity cannot be read, that lookup stays unresolved, without selecting its
|
||||
package or guessing that a later candidate would load. A compatible identity
|
||||
remains available if a later header or dependency-table check fails; its package
|
||||
is retained with an incompleteness reason. REA asks `dpkg-query -S` for each
|
||||
selected library's package. Libraries in the executable's own folder belong to
|
||||
the application: they are walked but not
|
||||
listed, and neither is the application's own package. One batched
|
||||
`apt-cache policy` then keeps only the packages the Ubuntu 24.04 archive or a
|
||||
recorded vendor repository with a verified key offers, in any component its
|
||||
|
||||
@@ -57,7 +57,11 @@ bundle. A failed export, cancellation
|
||||
included, removes the bundle it had not yet published, so no partial copy of the
|
||||
user's data remains. If the bundle was published but its output handles could
|
||||
not be closed, the command reports a cleanup error that carries the export
|
||||
Evidence; the bundle itself is complete.
|
||||
Evidence; the bundle itself is complete. Cancellation during final output
|
||||
handle cleanup also preserves the complete bundle and returns its Evidence
|
||||
as a partial observation. If closing the handles fails too, the cleanup
|
||||
failure remains primary and cancellation is retained separately. The complete
|
||||
bundle remains usable.
|
||||
|
||||
## The bundle
|
||||
|
||||
@@ -336,6 +340,9 @@ A withheld file larger than 48 KiB is refused, since its base64 must fit one
|
||||
environment variable. `--withheld-copy <folder>` copies the withheld files,
|
||||
as captured, into a new or empty folder outside the bundle. The result lists
|
||||
them as `withheld_files`, each with its `setting`, `variable` and `handle`.
|
||||
REA resolves both destinations before writing either. A path that cannot be
|
||||
resolved, including a dangling link, is refused; the copy and bundle cannot
|
||||
contain one another, including through symbolic links.
|
||||
|
||||
`--consent <file>` ships the person's consents, a `consent.json` that
|
||||
`record_build_consent` records, as the bundle's own `consent.json`.
|
||||
|
||||
@@ -619,6 +619,10 @@ answer or missing marked output reports a reader error; it does not establish
|
||||
that the document lacks the expected value. Correct the command or its output and retry; increase
|
||||
`timeout_s` within its accepted range when the reader needs longer.
|
||||
|
||||
A source inspection failure, such as an inaccessible parent or a symlink loop,
|
||||
also reports a reader error and leaves affected checks undecided. Only a missing
|
||||
source or a source that is not a regular file is reported as absent.
|
||||
|
||||
Export runs readers on both retained ends, using the seed bytes as the bundle
|
||||
actually ships them. The witness and exported verifier run them in the
|
||||
computer after the app's files settle. Cleanup failures retain the reader's
|
||||
|
||||
@@ -262,6 +262,11 @@ in the bundle differs from what the export writes for it. A reset
|
||||
relaunches the app, and REA waits until the computer is ready again before
|
||||
answering, sending progress notifications while it waits.
|
||||
|
||||
Re-export bundles whose generated verifier uses an older evaluator before
|
||||
witnessing them with current REA. The verifier must match the current export
|
||||
exactly; re-exporting uses the existing capture Evidence and task inputs,
|
||||
which remain unchanged.
|
||||
|
||||
Only a check that fails on what the app's view shows counts as a failure. A
|
||||
check that fails because its file or table could not be read, such as an
|
||||
SQLite file locked past the reader's wait, or because what it looks for may
|
||||
@@ -303,7 +308,11 @@ however many entries it dropped. The result returns the same record. When writin
|
||||
folder something else wrote into, the witness keeps its stages: check the
|
||||
stage that ended it again, with the same task, and REA writes the record
|
||||
without checking again. Once it is saved, the same check returns the saved
|
||||
record again, so a record saved as its call was cancelled is not lost. A
|
||||
record again, so a record saved as its call was cancelled is not lost.
|
||||
Cancellation during the published record's final handle cleanup returns the
|
||||
record Evidence with the error. When cleanup also fails, the next matching
|
||||
check retries those handles and returns the existing record without recording
|
||||
or writing it again. A
|
||||
computer is witnessed once; witness again from a fresh computer. A bundle of
|
||||
several tasks is witnessed one task per fresh computer: the seed stage
|
||||
refuses a task whose steps and verifier differ from the bundle's for that
|
||||
|
||||
@@ -43,6 +43,37 @@ does not establish broader Pi compatibility. See the pinned upstream
|
||||
[`declarations.ts`](https://github.com/earendil-works/pi/blob/b45e0ebcc5ae2fc42a6f2f23104d10e656e6bedb/packages/codemode/src/declarations.ts)
|
||||
and [renderer usage notes](https://github.com/earendil-works/pi/blob/b45e0ebcc5ae2fc42a6f2f23104d10e656e6bedb/packages/codemode/README.md#declarations-for-the-model).
|
||||
|
||||
## Cline
|
||||
|
||||
The original contributor reported a run on 2026-11-11 on Linux (Fedora 45),
|
||||
using Cline CLI 3.0.74 and the integration based on REA `main` at `9924bf344`.
|
||||
That run checked client config listing and a direct registered-server MCP
|
||||
handshake (254 tools on that build). It predates the verifier lifecycle changes
|
||||
below and does not establish their real-client behavior.
|
||||
|
||||
`npm run verify:cline-client` creates its sandbox home before launching commands
|
||||
and removes inherited `CLINE_MCP_SETTINGS_PATH`, `CLINE_DATA_DIR` and `CLINE_DIR`.
|
||||
Setup therefore exercises the default
|
||||
`~/.cline/data/settings/cline_mcp_settings.json` path under the sandboxed home.
|
||||
Cline's CLI must list that registration using the sandbox's explicit
|
||||
`--data-dir`; this checks the file parser, not independent default-home discovery.
|
||||
The exact registered launcher then
|
||||
completes SDK initialization and tool discovery through REA's owned stdio
|
||||
transport. Stdin stays open until discovery finishes. Command and transport
|
||||
cleanup completes before the verifier records lineage or reports success.
|
||||
|
||||
The updated orchestration has recording-port coverage for delayed discovery,
|
||||
failed server identification and failed cleanup. These tests use the installed
|
||||
SDK and verifier lifecycle owner, but do not execute Cline or a real REA server.
|
||||
The updated real-client lane has not been rerun during this reconciliation.
|
||||
|
||||
Not covered by the lane: a model-driven tool call inside Cline. Cline's provider
|
||||
configuration (`providers.json`) is versioned and auth-shaped, and the CLI ignores
|
||||
`OPENAI_BASE_URL`, so the loopback model fixture cannot drive it without depending
|
||||
on that private schema. The IDE extension is not covered either: its MCP settings are
|
||||
UI-managed and live under editor-specific `globalStorage` roots, which `rea setup`
|
||||
does not write in this release.
|
||||
|
||||
<a id="llamacpp"></a>
|
||||
|
||||
## llama.cpp
|
||||
|
||||
@@ -4,6 +4,13 @@ Pushes to main automatically open or refresh a Release Please PR with the next
|
||||
version and changelog. Review its migration notes and wait for its current CI
|
||||
checks to pass. Merging that PR into main starts publication automatically.
|
||||
|
||||
The push caused by merging a same-repository Release Please PR skips proposal
|
||||
generation: the separate merged-release workflow owns tag creation and
|
||||
publication. This avoids looking for the new version's tag before that workflow
|
||||
has created it. The next ordinary main push resumes proposals. API lookup
|
||||
failures and missing release boundaries on ordinary pushes or manual preparation
|
||||
still fail closed.
|
||||
|
||||
The Release workflow validates the merged release metadata and ancestry before
|
||||
creating a tag. npm and MCP Registry publication use the exact reviewed merge
|
||||
SHA returned by Release Please. Before either registry is published, the release
|
||||
@@ -156,7 +163,13 @@ resume bot regeneration. The label does not freeze the base branch: new base
|
||||
commits require re-inventorying and re-reviewing the notes.
|
||||
|
||||
Update both the release branch's `CHANGELOG.md` and the PR body, preserving
|
||||
Release Please's surrounding metadata. Before creating a release, the workflow
|
||||
Release Please's surrounding metadata. Keep Author readiness declarations and
|
||||
other PR metadata outside the first and last standalone `---` notes delimiters.
|
||||
The version heading must start the notes within those delimiters (or use Release
|
||||
Please's generated component wrapper). The checker uses Release Please's parser
|
||||
to verify that publication will extract the reviewed notes.
|
||||
|
||||
Before creating a release, the workflow
|
||||
checks an inventory when present, requires its target to equal the reviewed
|
||||
merge's first parent, and compares the freshly fetched PR body to the changelog.
|
||||
It rejects changes outside the release metadata paths and stale credit records
|
||||
@@ -350,8 +363,10 @@ tag remains in main's ancestry. Keep the released tag unchanged.
|
||||
|
||||
The synchronization must include `.release-please-manifest.json`,
|
||||
`package.json`, both root versions in `package-lock.json`, `CHANGELOG.md`,
|
||||
`server.json`, both plugin manifests (`.claude-plugin/plugin.json` and
|
||||
`.codex-plugin/plugin.json`), the Codex server declaration (`.codex-plugin/mcp.json`), both
|
||||
`server.json`, the Claude Code and Codex plugin manifests
|
||||
(`.claude-plugin/plugin.json` and `.codex-plugin/plugin.json`), the Codex
|
||||
server declaration (`.codex-plugin/mcp.json`), the Cursor Marketplace manifest
|
||||
(`.cursor-plugin/plugin.json`) and server pin (`mcp.json`), both
|
||||
marketplaces (`.claude-plugin/marketplace.json` and
|
||||
`.agents/plugins/marketplace.json`), and the versioned documentation examples. Run
|
||||
`npm run docs:generate`, `npm run docs:check`, and the release configuration
|
||||
|
||||
+35
-27
@@ -238,7 +238,9 @@ broad changes or diagnosing CI, rather than after every edit. Package/install
|
||||
changes additionally need package verification; provider changes need actual
|
||||
provider evidence.
|
||||
|
||||
Vitest projects use up to two workers, bounded by host parallelism.
|
||||
Vitest projects use up to two workers, bounded by host parallelism. GitHub
|
||||
Actions jobs own their runner and use up to four; see
|
||||
[test deadlines](#developer-commands) for how deadlines scale there.
|
||||
`process-boundary` runs later with serial files because process-tree sampling
|
||||
shares host resources. Acceptance and process-global cases use isolated forks
|
||||
without serial scheduling. Pure domain/service, composition, conformance,
|
||||
@@ -283,7 +285,7 @@ coverage. Ordinary CI also exhausted the former 384 MiB budget after earlier
|
||||
files loaded the shared source/contract graph, while later command registration
|
||||
and schema/help rendering still needed transient allocation space. This is a
|
||||
measured capacity control, not a suite-wide speedup claim. The worker count
|
||||
remains bounded at two, and spawned REA processes retain their own heap settings.
|
||||
remains bounded, and spawned REA processes retain their own heap settings.
|
||||
Coverage enablement still controls instrumentation, test deadlines and coverage
|
||||
thresholds; explicitly disabling it or selecting only a provider does not enable
|
||||
instrumentation.
|
||||
@@ -299,6 +301,18 @@ work from fixture generation, schema compilation, subprocess startup and cleanup
|
||||
Choose elapsed, CPU and process-family memory limits before the run; a worker
|
||||
count or test timeout alone does not enforce those limits.
|
||||
|
||||
A test deadline turns a hang into a named failure; it is not a performance
|
||||
assertion. `vitest.config.ts` applies the deadlines in
|
||||
`tests/support/testDeadlines.ts` per project: 30 seconds for source projects
|
||||
and 120 seconds for built projects, with hooks sharing their project's
|
||||
deadline. Coverage doubles every deadline, and so does hosted CI, where
|
||||
CPU-bound cases share every core with other workers and their subprocesses.
|
||||
Do not pass a per-test timeout to fit a slow host. Tag a bounded workload that needs longer with
|
||||
`{ tags: ["long-running"] }`, or a whole file with
|
||||
`// @module-tag long-running`. Assert elapsed time explicitly when speed is the
|
||||
behavior under test. Derive an explicit deadline only when a test must outlive
|
||||
an operation deadline whose diagnostics it checks.
|
||||
|
||||
Keep capacity fixtures intact when diagnosing a test failure. For byte equality
|
||||
of large buffers, use `Buffer.equals` or `Buffer.compare`; a generic structural
|
||||
diff can allocate far more than the production operation.
|
||||
@@ -407,6 +421,10 @@ relying on the new scope. While the variable is unset, the existing default
|
||||
setup continues scanning. Adding the configuration file alone does not change
|
||||
default setup in this user-owned repository.
|
||||
|
||||
Pull-request scans are cancelled when superseded. Active scans on `main` finish
|
||||
so frequent pushes cannot prevent a complete baseline from being uploaded.
|
||||
Cancelled runs skip the SARIF artifact upload when no report was produced.
|
||||
|
||||
Each analysis uses two threads and a 4096 MiB CodeQL memory budget; language
|
||||
jobs run one at a time. Complete SARIF reports are retained for seven days.
|
||||
For a scope comparison, use the same source SHA, CodeQL bundle, default query
|
||||
@@ -738,6 +756,16 @@ materialized source. Exercise descriptor close failure and retry before output
|
||||
publication.
|
||||
Use explicit abort reasons and assert their identity at admission and after
|
||||
provider completion, alongside retained observations and cleanup state.
|
||||
Include a physical I/O failure reused as the abort reason and genuine
|
||||
cancellation whose reason is already a typed error; neither error names nor
|
||||
value equality establishes origin. Assert that cleanup capabilities carried by
|
||||
that opaque reason are neither adopted nor released. Verify an owning command's timeout or
|
||||
refusal policy when preparation records cancellation but its caller is still
|
||||
active. Parallel inspection failures must retain completed observations and
|
||||
mixed physical/cancelled request facts after all peers settle, including
|
||||
multiple failed closes and partial cleanup retry. For input copying, hold an
|
||||
admitted read or write in flight before cancelling; descriptor close and
|
||||
workspace retirement must await its settlement.
|
||||
|
||||
Electron fuse regressions cover actual descriptor close denial and retry through
|
||||
the built CLI, same-connection MCP recovery, mixed descriptor outcomes, and
|
||||
@@ -1063,32 +1091,12 @@ existing four-minute timing collection plus the bounded diagnostic stages.
|
||||
|
||||
Fast built shards target under ten minutes of uncontended shard-job execution.
|
||||
That figure is the `test-shard` job. The job waits for classification and the
|
||||
build, and the portable-test merge runs after the slowest shard. On 2026-10-20,
|
||||
run `39451548945` measured those surrounding jobs with runner queue excluded:
|
||||
classification 15 seconds, build 49 seconds, and the portable-test merge 29
|
||||
seconds. Shard 1/5 of that run spent 22 seconds before built Vitest and 3
|
||||
seconds after it, including `npm ci` at 9 seconds. `node_modules` is about 674
|
||||
MiB, so publishing it as a shared artifact would transfer more data than that
|
||||
install saves. The npm download cache stays the setup cache.
|
||||
|
||||
File timings from that run put the built suite at 7944 seconds of module time.
|
||||
The sequencer keeps each file's full duration on one worker. Extra workers
|
||||
overlap other files in the same sequence group, and `process-boundary` runs
|
||||
after that group. Scheduling the unsplit inventory onto five shards peaks at
|
||||
820 seconds of tests. That run's slowest built shard job lasted 925 seconds
|
||||
(shard 4/5), and shard 1/5 spent 874 seconds in built Vitest, so hosted job
|
||||
time sits above the file schedule. Six shards of the same inventory peak at
|
||||
684 seconds of tests. Eight shards, after the 578-second loader file is split
|
||||
by case count (54 cases stay in that file and 46 move into each of three
|
||||
files), peak at 513 seconds of tests. With the measured 25-second shard setup,
|
||||
that shard job is about 538 seconds. Adding the measured classification, build,
|
||||
and merge makes an uncontended portable critical path of about 631 seconds,
|
||||
still before the gap between this file schedule and hosted Vitest. Runner queue
|
||||
is separate and grows when more shard jobs compete for runners.
|
||||
build, and the portable-test merge runs after the slowest shard. Runner queue is
|
||||
separate and grows when more shard jobs compete for runners. The npm download
|
||||
cache stays the setup cache rather than a shared `node_modules` artifact.
|
||||
`process-boundary` stays serial because process-tree sampling shares the host.
|
||||
Raising the worker cap from two to four on this four-core host cut a six-file
|
||||
acceptance sample from 96–101 seconds to 71 seconds and did not remove the
|
||||
single-file floor, so the cap stays two. Full qualification keeps six covered
|
||||
Hosted CI jobs use four workers; other hosts stay at two
|
||||
because they are shared with other checks. Full qualification keeps six covered
|
||||
shards; its longer instrumentation is outside this fast budget.
|
||||
|
||||
The separate `CI timings` workflow batches recent completed CI and Release runs
|
||||
|
||||
@@ -93,6 +93,38 @@ include the smallest useful reproduction, impact and coverage limits. Do not
|
||||
claim autonomous-agent selection from a scripted trace. Check related reports
|
||||
before proposing another issue, and avoid treating lack of API parity as a bug.
|
||||
|
||||
### Write descriptions for selection and a valid first call
|
||||
|
||||
Start with the analyst task, selected source and useful result. Put material
|
||||
effects and the deciding boundary between neighboring tools early. Progressive
|
||||
discovery previews the first 240 characters, so those characters should identify
|
||||
the operation without requiring the rest of its reference documentation.
|
||||
|
||||
Keep exact call syntax where the advertised schema cannot convey it. The compact
|
||||
input profile strips most annotation prose and can reduce nested controls to
|
||||
`{type: "object"}`. Moving selectors into parameter descriptions alone does not
|
||||
make them available to those clients. For example, retained pseudocode needs
|
||||
both `source.kind: "retained-evidence"` and `view: {kind: "native", facet:
|
||||
"pseudocode"}`; a short exact example can be more useful than many paragraphs.
|
||||
Use the producer's handoff for other supported views rather than maintaining
|
||||
another supposedly exhaustive list in the shared consumer description.
|
||||
|
||||
Keep configuration tutorials and detailed matching algorithms with their owning
|
||||
parameter contracts, product guides and actionable failures. Retain applicability,
|
||||
source identity, uncertainty, authority and cleanup facts needed to choose or
|
||||
safely continue the operation. An unresolved symbol lookup is not a completed
|
||||
reference search; an exhausted page does not establish absence in unexamined
|
||||
source. Shorter copy must preserve these distinctions.
|
||||
|
||||
For wording changes, use a small set of representative agent tasks at the affected
|
||||
boundaries. Hold schemas, tool order, fixtures and host configuration fixed when
|
||||
comparing copy; add repetitions only for failures or ambiguous outcomes. Score
|
||||
actual arguments, corrective calls and supported final claims separately. A
|
||||
correct eventual answer can conceal malformed-call loops, while a valid call
|
||||
can still produce an overstated answer. Report whole-task usage, including
|
||||
retries and cached input, rather than treating fewer description bytes as proof
|
||||
of lower token cost.
|
||||
|
||||
## Design recovery around the failure
|
||||
|
||||
Distinguish a request that violates its input contract from a valid selection
|
||||
@@ -326,7 +358,9 @@ In multi-stage work, retain each completed, admitted observation before awaiting
|
||||
the next stage. Later reads, validation, cancellation, or finalization can fail
|
||||
without erasing those facts. Carry them through typed failure outcomes with
|
||||
explicit coverage of unperformed work; do not construct a successful result for
|
||||
stages that never ran.
|
||||
stages that never ran. For concurrent reads, the batch owner settles every
|
||||
admitted peer before reporting a failure. Retain completed observations together with each
|
||||
failed request's physical, cancellation and cleanup facts.
|
||||
|
||||
- Keep target admission, provider readiness, active work, observed process exit,
|
||||
and resource release separate. A valid process handle, successful launcher,
|
||||
@@ -366,12 +400,13 @@ stages that never ran.
|
||||
primary failure and let incomplete cleanup retain its own classification.
|
||||
Preserve the caller's abort reason as the typed cancellation error's cause,
|
||||
including when cancellation is observed only after provider completion.
|
||||
Shared command owners must retain the observed cancellation reason separately
|
||||
from physical failures and cleanup ownership. Carry that fact through failure
|
||||
wrapping so adapters can preserve the exact reason without interpreting it.
|
||||
ZIP member streams retain the exact signal reason; hdiutil wrappers consume
|
||||
the command owner's typed cancellation record and keep physical command
|
||||
failures separate, even if a host error is named `AbortError`.
|
||||
The producing boundary records cancellation separately from physical failures
|
||||
and cleanup ownership. A caller's abort reason is opaque: its value, error
|
||||
type, name or cause chain cannot establish failure origin or cleanup authority.
|
||||
Consumers use the owner's parsed facts. An established command timeout keeps
|
||||
its timeout or refusal policy when preparation records a cancellation.
|
||||
Failure wrapping and operation rebinding preserve these facts and already
|
||||
classified secondary failures.
|
||||
Client cancellation alone does not prove native work stopped.
|
||||
For atomic publication, document the cancellation cutoff and preserve any
|
||||
committed output's publication receipt.
|
||||
@@ -389,7 +424,9 @@ stages that never ran.
|
||||
original failure and completed observations. Later failure composition must
|
||||
report only resources whose cleanup remains unresolved. Carry cleanup
|
||||
capabilities explicitly in typed outcomes so consumers can bind returned errors
|
||||
to exact owners without reparsing diagnostic cause chains.
|
||||
to exact owners without reparsing diagnostic cause chains. A cleanup-status
|
||||
observer does not replace a callable close capability retained by the caller's
|
||||
scope.
|
||||
Bind every caller-visible retry error and aggregate, including an error already
|
||||
produced by the provider. An aggregate remains incomplete until all owners it
|
||||
reports are released; releasing one child cannot clear another child's status.
|
||||
|
||||
@@ -44,6 +44,9 @@ file memory regions and paths (`NT_FILE`), fault signal and code (`NT_SIGINFO`),
|
||||
auxiliary vectors (`NT_AUXV`) across 32-bit and 64-bit images. Other owners or unparsed
|
||||
notes keep `core` null.
|
||||
|
||||
An `NT_FILE` descriptor with nonzero bytes after its declared filenames
|
||||
retains its raw note evidence and leaves `core` null.
|
||||
|
||||
Linux `CORE` decoding requires System V/unspecified (0) or GNU/Linux (3)
|
||||
OSABI with ABI version zero. An unspecified OSABI alone does not establish
|
||||
Linux origin. An explicitly different OSABI or ABI version leaves `core` null
|
||||
|
||||
@@ -651,6 +651,13 @@ be verified. See [MCP contracts](../reference/mcp-contracts.md) for session life
|
||||
[Ghidra first-query deadlines](../reference/mcp-contracts.md#ghidra-first-query-deadlines-and-recovery)
|
||||
for import, client timeouts and recovery.
|
||||
|
||||
One-shot binary analysis validates the selected operation's input before creating
|
||||
a provider session, opening the target, or replaying a snapshot. Invalid selectors
|
||||
and option combinations report their input errors before target or provider
|
||||
availability errors. An already-cancelled request keeps its cancellation reason.
|
||||
Caller-selected paths and request parameters remain separate from parsed execution
|
||||
arguments in Evidence.
|
||||
|
||||
A one-shot command attempts provider-session and runtime cleanup before reporting
|
||||
a failure. If cleanup remains incomplete, inspect the reported resources and
|
||||
follow the error's remediation. [Same-session cleanup retry](../reference/mcp-contracts.md#retained-cleanup-retry),
|
||||
@@ -1282,6 +1289,50 @@ backing up client settings or starting registration. Its `--agent` and
|
||||
`--command`/`-c` options accept spaced and equals forms. Values must be nonempty; a following flag does not satisfy a spaced option's
|
||||
missing value.
|
||||
|
||||
Registration command text is a launcher format, not a shell program. ASCII spaces
|
||||
separate words; single and double quotes delimit adjacent fragments of a word.
|
||||
Backslashes, tabs, variables and shell punctuation are literal data. Quoted empty
|
||||
arguments are preserved, including an empty argument after the executable. An
|
||||
empty executable, unfinished quote or NUL character fails before registration. For example:
|
||||
|
||||
```sh
|
||||
rea mcp add --agent cursor --command '"/path with spaces/server" "" --mcp' --json
|
||||
```
|
||||
|
||||
The registered executable is `/path with spaces/server`, with arguments `""` and
|
||||
`--mcp`. Windows backslashes use the same literal rules after the invoking shell
|
||||
has passed the option value. With no `--command`, REA uses its exact current
|
||||
runtime and entrypoint arguments without converting them to text and parsing them
|
||||
again. No package acquisition or server execution occurs during registration.
|
||||
`--no-global` refuses any selection requiring global storage before writing files.
|
||||
|
||||
`rea mcp add --schema --json` returns the named input and output JSON Schemas.
|
||||
Successful and partial registration reports contain the exact `command`, `args`
|
||||
and a `clients` outcome list. `ok` is true only when every selected client is
|
||||
configured or unchanged. Failed clients retain actionable errors; cancellation
|
||||
marks remaining clients `not_started`. A failed client does not erase a successful
|
||||
sibling's receipt. Existing settings and environment overrides survive refresh;
|
||||
backups identify the original bytes, and identical repeats create no new backup.
|
||||
Client IDs are case-insensitive for the helper-compatible catalog; documented
|
||||
aliases include `droid`/`factory`, `gemini`, `grok`, `kilo`/`kilocode`, `kimi`,
|
||||
`kiro`, `mastra`, `pi-agent`, `hermes-agent`, `cline-vscode`, and
|
||||
`codeium`/`cascade`. `github-copilot` selects VS Code; use
|
||||
`github-copilot-cli` for Copilot CLI. Amp uses `--agent amp`.
|
||||
|
||||
Kilo project registration follows its native configuration layers and requires a
|
||||
verified Git worktree. Selected `KILO_CONFIG`, `KILO_CONFIG_DIR` and
|
||||
`KILO_CONFIG_CONTENT` overrides remain authoritative. A conflicting higher-priority
|
||||
source must be updated before registration can succeed; readonly layers are never
|
||||
copied into the selected file. An unknown project root fails before writing and
|
||||
does not fall back to global settings.
|
||||
|
||||
`rea mcp add --command` accepts stdio launcher text. An HTTP(S) URL in the
|
||||
executable position is refused before any settings change; configure remote MCP
|
||||
transport in the client's own settings. Earlier delegated registration could
|
||||
interpret a URL as remote transport for some clients while storing it as an
|
||||
executable for Amp. That inconsistent URL interpretation and package acquisition
|
||||
are removed. Launcher arguments that happen to contain URLs remain arguments.
|
||||
|
||||
`rea mcp doctor --json` checks production MCP startup and reports child logs in
|
||||
`diagnostics`. It drains stderr while retaining at most its first 64 KiB of raw
|
||||
bytes as text, omitting a final UTF-8 code point if it crosses that byte limit.
|
||||
@@ -1377,6 +1428,7 @@ the CLI result should use JSON; either argument order is accepted.
|
||||
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `0` | The operation completed. Its result may include partial evidence, warnings or unresolved questions. |
|
||||
| `1` | The operation could not complete. Structured output identifies invalid input, permissions, cancellation, timeouts or another failure when available. |
|
||||
| `3` | `audit-release-exposure` completed with `--fail_on` and an exposed check meets that severity. Unknown and unassessed checks do not change this status. |
|
||||
| `128 + N` | Signal-derived status. An unhandled signal may have ended the process, with the shell or runtime preserving the conventional status; a command may instead have handled the signal, waited for its operation and cleanup to settle, and assigned the same status (`130` for SIGINT, `143` for SIGTERM). In the handled case, it may also have printed a structured `cancelled` result. |
|
||||
|
||||
`rea mcp --http` is long-running and prints no structured result. It exits
|
||||
@@ -1413,6 +1465,28 @@ Evidence and missing source records, see
|
||||
Other outputs have their own receipt shapes; for example,
|
||||
[environment export](#export-an-environment-bundle) reports a published directory.
|
||||
|
||||
A failure that carries partial Evidence in `details.partial_observation`, such
|
||||
as `provider_timeout` or `resource_constraint`, publishes that partial Evidence
|
||||
to `--evidence_output` under the same new-file and atomic rules, then keeps its
|
||||
error code, message and remediation when cleanup is confirmed. With `--detail summary`,
|
||||
`details.partial_observation` holds the summary view of the partial Evidence
|
||||
instead of the complete record, and `details.diagnostics.evidence_bundle`
|
||||
reports the written path and byte count. Linked source records must all be
|
||||
available before publication; missing sources leave the destination unchanged
|
||||
and are reported in `details.source_closure`. A provider cleanup failure can
|
||||
still publish its captured Evidence without clearing the cleanup error or its
|
||||
resource ownership. If publication is refused before commit, for example because
|
||||
the file already exists, the complete partial Evidence stays inline and `details.diagnostics.evidence_bundle_error` gives the
|
||||
refusal's code, message and a limitation. A refusal after commit keeps the
|
||||
receipt in `details.diagnostics.evidence_bundle` and the delivered view: when
|
||||
staging cleanup stays incomplete, the code becomes `cleanup_incomplete`, the
|
||||
original failure is retained in `details.execution_failure`, and `details` also carries `published`,
|
||||
`published_path`, `bytes`, `cleanup: "incomplete"` and `resources`, as for a
|
||||
successful run, and a later cancellation reports `cancelled` in
|
||||
`evidence_bundle_error` with the signal's exit status. Without
|
||||
`--evidence_output`, and for cancellation before publication or raw provider
|
||||
observations, the failure output is unchanged.
|
||||
|
||||
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
|
||||
@@ -1488,6 +1562,18 @@ Bun standalone executables use the existing `inspect-artifact` and
|
||||
sourcemaps and bytecode without running the executable. See
|
||||
[Bun standalone executables](../bun-standalone.md) for layout coverage and limits.
|
||||
|
||||
### Release exposure
|
||||
|
||||
```sh
|
||||
rea audit-release-exposure /absolute/path/to/MyApp.app --json
|
||||
rea audit-release-exposure ./dist/MyApp.app --fail_on high --json
|
||||
```
|
||||
|
||||
Reports what static analysis of a shipped `.app`, install directory, ASAR, or
|
||||
executable recovers. `--fail_on high|medium|low` exits `3` when a completed
|
||||
audit has an exposed check at that severity. Unknown and unassessed checks stay
|
||||
in the report and do not change the exit status. See
|
||||
[Release exposure](../release-exposure.md).
|
||||
Deno compile executables use the same commands to inventory and materialize the
|
||||
embedded virtual filesystem, remote modules, and recorded options. Inventory retains
|
||||
embedded environment-file values and certificate bytes in local Evidence with their
|
||||
|
||||
@@ -39,6 +39,17 @@ path and supported version of the runtime you intend to use, then update only
|
||||
the runtime command, preserving the REA script arguments and other settings.
|
||||
Rerun setup to review the registration and restart the client.
|
||||
|
||||
Doctor JSON records each registration's `command_identity` as `owned`, `foreign`,
|
||||
or `unknown`, separately from its readiness `state`. An invalid timeout or client
|
||||
policy can leave ownership established. Setup uses that recorded observation for
|
||||
its default client selection, then inspects selected configuration again before
|
||||
planning writes; a missing or unreadable launcher remains unknown.
|
||||
|
||||
A retained command does not prove the client selects it. Doctor also checks
|
||||
that client's native transport selectors; a higher-priority remote selector can
|
||||
leave the command owned while alignment remains unknown. Metadata that is not a
|
||||
native connection selector is preserved rather than interpreted as a transport.
|
||||
|
||||
`rea mcp doctor --json` tests the production MCP adapter using the runtime
|
||||
executable and environment of the terminal running doctor. It does not launch
|
||||
the client's configured command or reproduce the client's environment. If doctor
|
||||
@@ -109,7 +120,25 @@ unfamiliar prefix. The unavailable fork reported in
|
||||
For a client that supports MCP catalog refresh, set
|
||||
`REA_MCP_TOOL_CATALOG_PROFILE=hot-cold` in REA's server environment and restart
|
||||
the connection. REA then advertises a small initial catalog and loads other
|
||||
named tools through `discover_tools`. Setup preserves this explicit setting.
|
||||
named tools through `discover_tools`. Setup can record the explicit choice:
|
||||
|
||||
```bash
|
||||
rea setup --client codex --tool-catalog-profile hot-cold --dry-run
|
||||
rea setup --client codex --tool-catalog-profile hot-cold
|
||||
```
|
||||
|
||||
The plan shows `REA_MCP_TOOL_CATALOG_PROFILE=hot-cold` before approval. This
|
||||
selects server catalog loading; enable and verify the client's catalog refresh
|
||||
separately. Setup preserves its existing feature flags and tool approval lists.
|
||||
To restore upfront advertisement, use `--tool-catalog-profile full`, then
|
||||
reconnect. Omitting the option preserves the saved profile and keeps `full` for
|
||||
a new registration. Existing explicit environment selections are also retained.
|
||||
|
||||
Setup does not infer refresh from a client name or enable experimental client
|
||||
features. The verified Codex trial below covers one version with an explicit
|
||||
flag; FastMCP was tested with explicit refresh calls. Neither establishes
|
||||
automatic refresh for every installed version or other client. Keep `full`
|
||||
until refresh is established for the selected client and configuration.
|
||||
See the [discovery contract](../reference/mcp-contracts.md#hotcold-catalog-discovery) for
|
||||
pagination, identity and family-scope semantics.
|
||||
|
||||
@@ -723,6 +752,51 @@ The global MCP path is a plain JSON file; setup preserves every other server
|
||||
and top-level key when it upserts `rea`. Loading this registration, the
|
||||
bundled skill, and real REA tool calls through CodeBuddy are verified.
|
||||
|
||||
## Cline
|
||||
|
||||
MCP registration already supports both clients: `rea mcp add --agent cline`
|
||||
(or `cline-vscode`) configures the VS Code extension, while
|
||||
`rea mcp add --agent cline-cli` configures the CLI. The setup lifecycle uses
|
||||
`rea setup --client cline` and `rea doctor --client cline` for the CLI.
|
||||
`rea uninstall` also removes its REA-owned Cline CLI entry.
|
||||
|
||||
For Cline's CLI, setup writes `mcpServers.rea` into
|
||||
`~/.cline/data/settings/cline_mcp_settings.json`; set `CLINE_MCP_SETTINGS_PATH`
|
||||
to select another file. Otherwise `CLINE_DATA_DIR` selects the data directory,
|
||||
then `CLINE_DIR` selects the root containing `data`; blank overrides are ignored.
|
||||
Setup and `mcp add --agent cline-cli` share this native path selection. Entries carry
|
||||
`command`, `args`, and `env`; stdio is the default transport. Setup preserves
|
||||
every other server and top-level key when it upserts `rea`, and refuses a
|
||||
`rea` entry it did not write rather than adopting or overwriting it.
|
||||
|
||||
Existing nested `transport` registrations retain their representation during
|
||||
setup. In that shape, launch `env` and `cwd` belong inside `transport`;
|
||||
setup preserves those values and other nested metadata separately from outer
|
||||
registration policy.
|
||||
|
||||
That refusal includes a hand-written `rea` entry: ownership is decided by
|
||||
comparing the entry's launcher with the running installation's entry point, so a
|
||||
registration that points at a different install path is reported as `foreign`
|
||||
and left unchanged. Rename or remove that entry, then rerun setup; doctor's
|
||||
remediation names the file and the entry to change.
|
||||
|
||||
Cline discovers skills in the shared `~/.agents/skills` directory. Setup
|
||||
installs the bundled skill there,
|
||||
and `--skill-client cline` resolves to that shared directory; setup does not
|
||||
write a second copy under `~/.cline/skills`.
|
||||
|
||||
The IDE extension keeps its own MCP settings, reached from the Cline panel's
|
||||
**Configure MCP Servers** action. Use `rea mcp add --agent cline` for that
|
||||
registration; `rea setup --client cline` configures the CLI only.
|
||||
|
||||
Restart Cline after setup so the client reloads `mcpServers`. Cline's default
|
||||
MCP tool-call timeout is 120 seconds; native provider work that spends longer
|
||||
starting Hopper, Ghidra, or IDA can exceed it, so raise the timeout in Cline's
|
||||
MCP settings for long native investigations.
|
||||
|
||||
Setup, doctor's alignment report, foreign-registration refusal, and uninstall
|
||||
removal are covered by `tests/acceptance/setup/clineClientSetup.test.ts`.
|
||||
|
||||
## WorkBuddy
|
||||
|
||||
For [WorkBuddy](https://www.workbuddy.cn/docs/workbuddy/From-Beginner-to-Expert-Guide/Function-Description/MCP-Guide), setup writes `mcpServers.rea` into the
|
||||
@@ -738,6 +812,13 @@ and top-level key when it upserts `rea`. WorkBuddy also reads a project-level
|
||||
user-level file only. Loading this registration and real REA tool calls
|
||||
through WorkBuddy are verified.
|
||||
|
||||
For CodeBuddy and WorkBuddy, REA's write checks cover their documented stdio
|
||||
entries. If an existing `rea` row contains fields whose native interpretation is
|
||||
unclassified, setup preserves it and reports unknown write applicability before
|
||||
changing the file. Doctor retains any established launcher ownership while
|
||||
reporting alignment as unknown. This does not prevent safe removal of a row
|
||||
whose REA ownership is established.
|
||||
|
||||
## ZCode
|
||||
|
||||
For [ZCode](https://zcode.z.ai/en/docs/mcp-services), setup registers `rea` in the nested `mcp.servers` table of the
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
Run REA, connect your selected agents, and check the tools needed for your task.
|
||||
Setup previews configuration changes and asks for approval before applying them.
|
||||
|
||||
| Task | Section |
|
||||
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| Connect an agent | [Start setup](#start-setup), then [review changes](#review-setup-changes) |
|
||||
| Install a Claude Code/Codex plugin | [Agent plugins and marketplaces](#agent-plugins-and-marketplaces) |
|
||||
| Run unreleased code | [Run REA from a checkout](#run-rea-from-a-checkout) |
|
||||
| Diagnose one task | [Scoped readiness checks](#check-readiness-for-your-task) |
|
||||
| Configure an analysis engine | [Hopper](#hopper), [Ghidra](#ghidra), the [IDA guide](../providers/ida-provider.md), or [Kuna](../kuna-provider.md) |
|
||||
| Update or remove REA | [Maintenance](#diagnose-update-and-remove) |
|
||||
| Resolve a client-specific problem | [Client configuration](client-configuration.md) |
|
||||
| Task | Section |
|
||||
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| Connect an agent | [Start setup](#start-setup), then [review changes](#review-setup-changes) |
|
||||
| Install a Claude Code/Codex plugin | [Agent plugins and marketplaces](#agent-plugins-and-marketplaces) |
|
||||
| Install the Cursor Marketplace plugin | [Cursor Marketplace](#cursor-marketplace) |
|
||||
| Run unreleased code | [Run REA from a checkout](#run-rea-from-a-checkout) |
|
||||
| Diagnose one task | [Scoped readiness checks](#check-readiness-for-your-task) |
|
||||
| Configure an analysis engine | [Hopper](#hopper), [Ghidra](#ghidra), the [IDA guide](../providers/ida-provider.md), or [Kuna](../kuna-provider.md) |
|
||||
| Update or remove REA | [Maintenance](#diagnose-update-and-remove) |
|
||||
| Resolve a client-specific problem | [Client configuration](client-configuration.md) |
|
||||
|
||||
## Start setup
|
||||
|
||||
@@ -481,6 +482,12 @@ updated stops the remaining removals. Uninstall reports each candidate
|
||||
their individual `actions` alongside its aggregate status and detail,
|
||||
including earlier removals when a later file fails. The paths name
|
||||
the discovered configuration candidates, not resolved physical file identities.
|
||||
If resource cleanup remains incomplete, uninstall reports a failed
|
||||
`uninstall_cleanup` item alongside the completed removals, with a structured
|
||||
`cleanup` observation naming the outstanding resources. An embedded host retains
|
||||
the exact cleanup owners: retrying that host's `close()` updates previously
|
||||
returned cleanup observations when release is confirmed. A new CLI invocation
|
||||
does not inherit those owners; inspect the reported resources before proceeding.
|
||||
For JSON clients, uninstall removes every repeated `rea` member in the effective
|
||||
server table only when each registration is REA-owned. An unowned earlier
|
||||
member, or an unowned OpenCode V1 entry that removing V2 would expose, stops
|
||||
@@ -676,6 +683,7 @@ hosted connector; see [its configuration](client-configuration.md#other-client-s
|
||||
| Codex | `codex` |
|
||||
| Cursor | `cursor` |
|
||||
| CodeBuddy | `codebuddy` |
|
||||
| Cline CLI | `cline` |
|
||||
| Gemini CLI | `gemini_cli` |
|
||||
| Windsurf | `windsurf` |
|
||||
| Devin | `devin` |
|
||||
@@ -1191,7 +1199,7 @@ require Hopper; Windows P0 remains read-only.
|
||||
Windows P0 admits native x86, x86-64, ARMNT (Thumb-2) and ARM64 PE applications and DLLs,
|
||||
[DOS MZ executables](../providers/ghidra-dos.md), plus explicitly
|
||||
selected [raw NMOS 6502 images](../providers/raw-binary.md#nmos-6502) with a caller-supplied
|
||||
entry at file offset 0, on fixed local NTFS volumes. Other raw CPU families remain
|
||||
entry at file offset 0, on fixed local NTFS/ReFS volumes. Other raw CPU families remain
|
||||
unsupported on Windows.
|
||||
The npm package bundles native Job Object ownership, protected private runtime
|
||||
DACLs, and handle-based path admission; no separate addon installation is needed.
|
||||
@@ -1240,17 +1248,35 @@ installation remains unavailable on Windows. Setup never installs Ghidra,
|
||||
Java, or Python. It preserves valid detected Ghidra/JDK settings in agent
|
||||
registrations. See [Windows Ghidra P0](../providers/windows-ghidra-p0.md) for provider diagnostics.
|
||||
|
||||
The separate `rea mcp add` builtin delegates most clients to Incur's package-runner
|
||||
child launcher. Run that acquisition from a trusted directory; prefer managed
|
||||
`rea setup` when supported. That child launcher can fail on Windows with `MCP_ADD_FAILED: spawn npx ENOENT`
|
||||
before registering a client. REA's setup path is unaffected. For a client supported
|
||||
by setup, review `rea setup --client opencode --skill=false --dry-run --json`
|
||||
(substitute its client ID), then use the same scoped command without `--dry-run`
|
||||
and approve the displayed plan. Non-interactive application additionally needs
|
||||
`--yes`. This configures setup's user-level client location; it does not replace
|
||||
`mcp add --no-global`, arbitrary `--command` registrations, or unsupported clients.
|
||||
The builtin launcher defect remains pending a dependency fix; a successful setup
|
||||
run does not verify that `mcp add` works on Windows.
|
||||
`rea mcp add` registers the selected server launcher directly in client settings.
|
||||
It does not acquire a package or start the server. Omit `--command` to register
|
||||
the runtime and REA entrypoint currently executing the CLI. Use `--agent` to
|
||||
select clients; repeat it for a mixed selection. With no selection, REA uses
|
||||
detected user-level clients and Amp; if none of the other supported clients are
|
||||
detected, it selects their full registration catalog and Amp.
|
||||
|
||||
REA preserves existing environment overrides, client policy, peer servers and
|
||||
unrelated settings. A changed existing file gets a private backup; an identical
|
||||
repeat keeps the file and creates no new backup. The result reports exact
|
||||
`command` and `args`, each selected client's effective scope, and configured,
|
||||
unchanged, failed or not-started outcomes. A partial failure returns a nonzero
|
||||
status while retaining successful client outcomes and recovery paths.
|
||||
|
||||
`--no-global` writes only project-level settings. A selection containing Amp or
|
||||
another client without project storage fails before any writes; select those
|
||||
clients in a separate global registration. Managed `rea setup` remains available
|
||||
for its supported clients and additional setup tasks. Registration preserves
|
||||
Windows launcher paths and arguments as data. Windows ACL privacy cannot be
|
||||
verified through POSIX mode bits; Fx results distinguish requested Windows modes
|
||||
from verified POSIX modes. Controlled source tests do not establish real Windows
|
||||
client behavior.
|
||||
|
||||
`rea mcp add --command` accepts stdio launcher text. An HTTP(S) URL in the
|
||||
executable position is refused before any settings change; configure remote MCP
|
||||
transport in the client's own settings. Earlier delegated registration could
|
||||
interpret a URL as remote transport for some clients while storing it as an
|
||||
executable for Amp. That inconsistent URL interpretation and package acquisition
|
||||
are removed. Launcher arguments that happen to contain URLs remain arguments.
|
||||
|
||||
When `GHIDRA_INSTALL_DIR` is unset, doctor and the Ghidra provider also search
|
||||
`PATH` for `ghidra` or `ghidraRun`, resolve the selected launcher through its
|
||||
@@ -1843,7 +1869,10 @@ The repository's single-plugin marketplaces are declared in
|
||||
`.claude-plugin/marketplace.json` and `.agents/plugins/marketplace.json`.
|
||||
Both select an exact `rea-agents` npm version instead of mutable source-checkout
|
||||
contents. Release Please updates their selectors alongside the plugin manifests.
|
||||
No plugin-only publication or generated skill files committed to Git are needed.
|
||||
Claude Code and Codex do not need plugin-only publication or generated skill
|
||||
files committed to Git. The Cursor Marketplace plugin is the exception in
|
||||
[Cursor Marketplace](#cursor-marketplace): its skill copy is committed because
|
||||
that install is a Git checkout.
|
||||
The qualified release archive contains a runtime-only manifest and
|
||||
`npm-shrinkwrap.json` plus bundled runtime dependencies, including PTY packages
|
||||
for each supported OS and CPU; development dependencies and development-only overrides
|
||||
@@ -1884,7 +1913,8 @@ only the registrations and skill locations that `rea setup` manages, so for a
|
||||
plugin-only install `rea doctor --client <id>` and `rea doctor --skill` report
|
||||
`missing` and recommend `rea setup`. Do not follow that remediation. Check the
|
||||
plugin with the client instead (`claude plugin list` and `/mcp` in Claude
|
||||
Code, `codex plugin list` in Codex).
|
||||
Code, `codex plugin list` in Codex, Cursor's plugin settings for a Marketplace
|
||||
install).
|
||||
|
||||
For analysis engines, ask the connected server: have the agent call
|
||||
`binary_session` and read `result.tool_availability`, which reports what the
|
||||
@@ -1897,7 +1927,7 @@ terminal, use the package runner at the version the plugin pins:
|
||||
<!-- x-release-please-start-version -->
|
||||
|
||||
```bash
|
||||
npx -y rea-agents@6.8.0 doctor --provider ghidra --json
|
||||
npx -y rea-agents@6.9.0 doctor --provider ghidra --json
|
||||
```
|
||||
|
||||
<!-- x-release-please-end -->
|
||||
@@ -1907,6 +1937,66 @@ That report describes the terminal's environment, not the plugin server's.
|
||||
The server inherits the client's environment, so a setting such as
|
||||
`GHIDRA_INSTALL_DIR` that exists only in your terminal does not reach it.
|
||||
|
||||
### Cursor Marketplace
|
||||
|
||||
Cursor's Marketplace installs this public repository as one plugin. The
|
||||
install includes both the `reverse-engineer-anything` skill and the `rea` MCP
|
||||
server. REA does not publish an MCP-only "Add to Cursor" install link, because
|
||||
that link would register the server without the skill.
|
||||
|
||||
The manifest is `.cursor-plugin/plugin.json`. Cursor discovers `mcp.json` at
|
||||
the repository root and the skill directory named by `skills`. The committed
|
||||
skill is `.cursor-plugin/skills/reverse-engineer-anything`, a copy of the
|
||||
authored skill at `.agents/skills/reverse-engineer-anything`.
|
||||
`node scripts/generate-cursor-plugin-skill.mjs --check` fails when that copy
|
||||
drifts, including in `npm run docs:check` and package prepack. Marketplace
|
||||
installs are a Git checkout and do not contain `dist/`. The server entry
|
||||
therefore runs the published package instead of a local build:
|
||||
|
||||
<!-- x-release-please-start-version -->
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"rea": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "rea-agents@6.9.0", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- x-release-please-end -->
|
||||
|
||||
Release Please updates that pin with `.cursor-plugin/plugin.json` and
|
||||
`package.json`. The skill text can describe capabilities newer than the pinned
|
||||
server until the next release; follow the connected server's tool list. The
|
||||
same pin is what `rea doctor --provider <id>` should use when you inspect an
|
||||
engine from a terminal, as shown above.
|
||||
|
||||
A Marketplace install gives you:
|
||||
|
||||
- the `reverse-engineer-anything` skill and its references
|
||||
- an `rea` MCP server launched with `npx -y rea-agents@<pinned version> mcp`
|
||||
(Cursor shows it as `plugin-rea-rea`)
|
||||
- the shared plugin logo at `assets/rea-plugin.png`
|
||||
|
||||
It does not install analysis engines, put `rea` on `PATH`, or write
|
||||
`~/.cursor/mcp.json`. `rea setup --client cursor` remains the direct
|
||||
registration path and still writes that file plus the setup-owned skill. Use
|
||||
the Marketplace plugin or that registration, not both, so Cursor does not
|
||||
start two `rea` servers.
|
||||
|
||||
Node.js and npm must be available to Cursor. The plugin does not install them.
|
||||
Restart Cursor after the plugin is listed. If tools stay missing, read the
|
||||
plugin server's launch error. `rea doctor --client cursor` does not see
|
||||
Marketplace state and can report `missing`; do not run setup to repair a
|
||||
plugin-only install.
|
||||
|
||||
Publishing the listing is a separate maintainer step at
|
||||
[cursor.com/marketplace/publish](https://cursor.com/marketplace/publish).
|
||||
This repository change does not submit the plugin.
|
||||
|
||||
## MCP Registry
|
||||
|
||||
REA is published in the official MCP Registry as `io.github.morluto/rea`. Registry
|
||||
|
||||
+4
-2
@@ -49,8 +49,10 @@ as the 4.3 and 4.4.1 exporters do, so the declared MD5 does not depend on the
|
||||
encryption IV. Encrypted members whose declared MD5s differ therefore also
|
||||
compare `unknown` in `metadata` and `availability`: the MD5s declare
|
||||
different scripts, but REA cannot verify them, and equal MD5s add nothing for
|
||||
the same reason. An encrypted member with an MD5 on only one side stays
|
||||
`unknown`.
|
||||
the same reason. An encrypted member with an MD5 on only one side, including
|
||||
an all-zero MD5 that records no claim, stays `unknown` in `metadata` and
|
||||
`availability`: the claim's presence differs, and one claim does not prove
|
||||
the script changed.
|
||||
|
||||
## CLI
|
||||
|
||||
|
||||
@@ -247,12 +247,9 @@ rea inspect-dart-aot app.apk --pool-policy '{"contains":"package:","uri_limit":2
|
||||
```
|
||||
|
||||
The equivalent MCP input is `pool_policy: {contains: "package:", uri_limit: 2048}`.
|
||||
This recovers all bounded package-URI observations in the measured Gallery and
|
||||
LocalSend APKs. Check the result's limits and coverage for other targets; long
|
||||
runs and unsupported snapshot layouts remain separate limitations. The
|
||||
[calibration report](../../verification/flutter-budget-calibration.md)
|
||||
keeps the default at 500 because increasing every complete overview also delivers
|
||||
more strings when they are unnecessary. Use `detail: "summary"` for the MCP
|
||||
Check the result's limits and coverage; long runs and unsupported snapshot
|
||||
layouts remain separate limitations. The default is 500; raising it can deliver
|
||||
more strings than a complete overview needs. Use `detail: "summary"` for the MCP
|
||||
identity/count task described above.
|
||||
|
||||
These controls do not raise APK, ELF, library or response budgets, deserialize
|
||||
|
||||
@@ -215,7 +215,10 @@ Resolution follows dyld:
|
||||
image that loaded it, up to the process root.
|
||||
- Dependencies load dependents-first in load-command order, and each image
|
||||
loads once per process. A later @rpath request whose install name matches an
|
||||
already loaded image reuses it.
|
||||
already loaded image reuses it. Loading an image and expanding its dependencies
|
||||
are separate: an already loaded sibling can first be expanded through another
|
||||
dependency, inheriting that traversal's rpath stack. Cycles do not expand an
|
||||
image twice, and lazy edges do not establish a launch-time traversal chain.
|
||||
- Symlinks such as `Versions/Current` are followed inside the analyzed root.
|
||||
An escape through `..` or an absolute link is `escapes-target`.
|
||||
- Dyld path components are POSIX names. On Windows hosts, link text uses `\`
|
||||
@@ -252,8 +255,12 @@ one of:
|
||||
|
||||
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
|
||||
request that reuses it by install name is `conditional` too. A definitely loaded
|
||||
image can also first expand through a conditional chain: its dependency edges
|
||||
then have `loader_conditional: true`, while later reuse of the image retains its
|
||||
definite first-load result.
|
||||
|
||||
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
|
||||
|
||||
@@ -317,6 +317,9 @@ MCP returns a `partial_observation` retained reference after recording succeeds;
|
||||
open it with `inspect_analysis_view` on the same connection. If the SDK stopped
|
||||
waiting before receiving the reply, follow [MCP cancellation recovery](../../reference/mcp-contracts.md#progress-and-cancellation)
|
||||
to find the record. CLI failure output contains the complete partial Evidence.
|
||||
With `--evidence_output`, the CLI also publishes it to that file and, with
|
||||
`--detail summary`, prints only its summary view; see
|
||||
[evidence publication](../../getting-started/cli.md#output-and-exit-status).
|
||||
Owned analyzer cleanup is verified before private files are released; uncertain
|
||||
cleanup retains ownership for retry and is reported separately.
|
||||
Typed cancellation or another primary interruption remains attached while
|
||||
@@ -453,9 +456,13 @@ RPC client syntax also contributes network endpoint candidates, in both
|
||||
- `graphql:query`, `graphql:mutation`, and `graphql:subscription` record a
|
||||
named operation found at the start of a string or cooked template literal —
|
||||
the name must be followed by variable definitions (`($`), a directive, or a
|
||||
selection set starting with a field name — or in a precompiled
|
||||
`OperationDefinition` document object. A standalone Source object's `body`
|
||||
remains an operation candidate even when it has `locationOffset` metadata.
|
||||
selection set starting with a field, named fragment spread, or inline fragment
|
||||
— or in a precompiled `OperationDefinition` document object. A precompiled
|
||||
operation name must be one complete GraphQL Name token (ASCII letters,
|
||||
digits, and underscores, with no leading digit). Recognition is limited to
|
||||
static operation headers; it does not validate a complete GraphQL document or
|
||||
prove that the application sends the operation. A standalone Source object's
|
||||
`body` remains an operation candidate even when it has `locationOffset` metadata.
|
||||
A graphql-tag `loc.source.body` copy is suppressed only when that source
|
||||
belongs to a recovered document with the same operation and its containing
|
||||
document, location and source have proven private metadata ownership. Writes,
|
||||
@@ -807,9 +814,8 @@ retained graph capacity, worker memory and deadlines. Both
|
||||
`primitive_bytes` charges six estimated JSON bytes per UTF-16 code unit plus
|
||||
quotes before creating concatenated strings. Ordinary ASCII can exhaust that
|
||||
conservative estimate before its actual JSON encoding reaches the selected
|
||||
byte count. The [calibration record](../../verification/javascript-precision-calibration.md)
|
||||
keeps existing defaults for its measured literal-value tasks; it does not
|
||||
establish optimal candidate, getter or alias budgets for larger applications.
|
||||
byte count. Candidate, getter and alias budgets can be adjusted for larger
|
||||
applications.
|
||||
|
||||
All fields accept positive safe integers; worker memory, execution and JSON
|
||||
representation bounds remain independently enforced. Omission keeps the defaults;
|
||||
|
||||
@@ -651,6 +651,9 @@ only when both identities are available and their format-specific comparison
|
||||
establishes a difference. ELF module names retain case, PE module names compare
|
||||
case-insensitively, and a case-only match for Mach-O or an unknown format stays
|
||||
unresolved because the available Evidence does not establish case behavior.
|
||||
The authenticated subject format establishes the native platform: thin and
|
||||
universal Mach-O use the same lookup rules; missing or unrecognized formats
|
||||
remain unknown. Retained source Evidence keeps its original subject format.
|
||||
For PE imports, `.dll`, `.exe`, a trailing period, and absolute paths suppress
|
||||
appending `.dll`; other names may also be tried with `.dll`. Unix loaders use
|
||||
the platform suffix (`.so` or `.dylib`) and `lib` prefix variations. A suffix
|
||||
|
||||
@@ -44,6 +44,11 @@ before dependency seeks. Structural inventory and the convenience-map engine
|
||||
still parse the snapshot separately; eliminating that remaining duplication
|
||||
requires preserving the upstream GOT/PLT and mitigation facts.
|
||||
|
||||
The layout profile returns `unsupported_target` for `SHF_COMPRESSED` string,
|
||||
symbol, relocation or dynamic metadata sections before upstream convenience-map
|
||||
decoding. Their logical names and entry coordinates cannot be read from the
|
||||
compressed file bytes. Other compressed payload sections remain opaque.
|
||||
|
||||
## Interpreting results
|
||||
|
||||
- Artifact path, SHA-256 and size identify original selected bytes. All parsing
|
||||
@@ -478,6 +483,13 @@ section directory with neither a dynamic symbol table nor a dynamic segment
|
||||
reports a complete empty inventory. Mach-O exports are reported by
|
||||
`inspect_macho`.
|
||||
|
||||
ELF export tables marked `SHF_COMPRESSED` are not decompressed. A compressed
|
||||
dynamic symbol table or its string table reports `unsupported` coverage rather
|
||||
than treating stored bytes as symbols or names. Compressed version tables or
|
||||
their string tables keep readable export rows with `partial` coverage and
|
||||
unresolved versions. When version definition storage is compressed, requirement
|
||||
names also remain unknown because unseen definitions may override them.
|
||||
|
||||
`max_file_bytes` defaults to 256 MiB (maximum 512 MiB; CLI `--max-file-bytes`).
|
||||
Export directories in PE headers are read like those in sections. An export or
|
||||
dynamic symbol table above 262144 entries, more than 262144 rows, or more than
|
||||
|
||||
@@ -74,6 +74,12 @@ A record whose length word is `0xffffffff` uses the 64-bit extended length
|
||||
that follows it. In `.eh_frame` the CIE ID and CIE pointer after that length
|
||||
stay 4 bytes wide.
|
||||
|
||||
LEB128 operands retain their signed or unsigned 64-bit value, including valid
|
||||
ten-byte sign padding. An overflowing or unterminated operand is not wrapped
|
||||
into a function address: its affected record is omitted, coverage is incomplete,
|
||||
and other decodable records remain available. A negative FDE range is likewise
|
||||
omitted rather than interpreted as a positive size.
|
||||
|
||||
`DW_EH_PE_datarel` fields in `.eh_frame_hdr` are relative to the header
|
||||
address. In `.eh_frame` they are relative to the GOT: `DT_PLTGOT` when the
|
||||
dynamic table names it, otherwise the `.got.plt` or `.got` section address.
|
||||
@@ -173,5 +179,12 @@ on one page share a fixed 16 MiB text allowance; a page that exceeds it fails
|
||||
with a resource error whose recovery is a smaller `limit`, because
|
||||
`max_ranges` and `max_file_bytes` do not raise it.
|
||||
|
||||
Compressed symbol or name tables and symbol-table links that do not name a
|
||||
file-backed `SHT_STRTAB` section leave symbol names unknown and coverage
|
||||
incomplete; decoded FDE ranges remain available.
|
||||
|
||||
A compressed dynamic section cannot supply `DT_PLTGOT`. Without another
|
||||
observed GOT base, affected data-relative unwind pointers remain unresolved.
|
||||
|
||||
Malformed ELF headers fail without partial success. This workflow does not
|
||||
execute the image, evaluate CFA programs, or follow indirect pointers.
|
||||
@@ -32,9 +32,14 @@ otherwise.
|
||||
followed by a version token beginning with a digit and ends at a NUL or
|
||||
newline within 512 bytes. `version` is that token. `builder` is the first
|
||||
parenthesized group (`user@host`). `compiler` is the second group up to the
|
||||
last `) #`, so nested parentheses in compiler strings are kept. The banner is
|
||||
`absent` when no such string was found in the searched bytes and `unknown`
|
||||
when the bytes were not searched.
|
||||
last `) #`, so nested parentheses in compiler strings are kept. Since Linux
|
||||
6.1, kbuild also leaves the weak banner of `init/version.o`. It is compiled
|
||||
before the build number and timestamp exist, so unless `KBUILD_BUILD_VERSION`
|
||||
and `KBUILD_BUILD_TIMESTAMP` are both set, it has a space right after `#` or at
|
||||
its end. When a later banner repeats that text up to `#` without that gap, the
|
||||
later banner is reported; otherwise the first one is. The banner is `absent`
|
||||
when no such string was found in the searched bytes and `unknown` when the
|
||||
bytes were not searched.
|
||||
|
||||
`config` is `present` only when all of the following hold:
|
||||
|
||||
|
||||
@@ -54,7 +54,11 @@ Each `entries[]` item reports:
|
||||
limitation says so.
|
||||
- `value_va`, `value_file_offset` and `section`: the resolved target address,
|
||||
its file offset and its containing section. These are null when the value
|
||||
was not established. A file offset is also null when load segments map the
|
||||
was not established. In a linked ELF, file offsets come only from `PT_LOAD`:
|
||||
an unmapped or zero-filled target keeps its observed address but has a null
|
||||
file offset, even if a section header declares bytes at that address. ET_REL
|
||||
targets retain their relocation symbol's section-relative coordinates.
|
||||
A file offset is also null when load segments map the
|
||||
address ambiguously (overlapping segments with different file offsets, or
|
||||
file and zero-fill memory), and the report is then `incomplete`.
|
||||
- `symbol`: a defined symbol whose value equals the target exactly, or the
|
||||
@@ -87,17 +91,37 @@ relocations are decoded for x86-64, i386, AArch64 and 32-bit ARM. A slot is
|
||||
also `unresolved` when a dynamic relocation writes only part of it, starts
|
||||
inside it, or writes it more than once with different values.
|
||||
|
||||
A `COPY` relocation writes as many bytes as the image's own dynamic symbol
|
||||
records, and a TLS descriptor relocation writes two words. A slot outside
|
||||
those bytes keeps its stored word, so a non-PIE executable that copies `stdout`
|
||||
or `environ` into `.bss` still lists its `init_array` targets as `raw`. When a
|
||||
`COPY` symbol's size cannot be read, or the `COPY` sizes add up to more than
|
||||
the file's byte count, relocation coverage is unknown and stored words are
|
||||
`unresolved`.
|
||||
|
||||
Section `REL` / `RELA` tables are applied to slots that no dynamic relocation
|
||||
covers. When such a table is skipped for an unexpected entry size, cannot be
|
||||
read, or lies past the record budget, every slot it could reach that has no
|
||||
relocation found is `unresolved`, and a `.ctors` slot is not dropped as a
|
||||
sentinel. A section record that writes only part of a slot, starts inside it,
|
||||
or repeats it also leaves the slot `unresolved`. In a relocatable object a
|
||||
or repeats it also leaves the slot `unresolved`. In a linked image, a section
|
||||
`COPY` record covers the size that its table's linked symbol records, as a
|
||||
dynamic one does. When that symbol was not read, or the section `COPY` sizes
|
||||
add up to more than the file's byte count, the table counts as not fully read.
|
||||
A record that writes memory with no file bytes, such as zero-fill `.bss`,
|
||||
changes only the slots it overlaps in memory, provided its extent is known: a
|
||||
kind with a fixed width, or a sized `COPY`. A record of any other kind there
|
||||
leaves its table not fully read. In a relocatable object a
|
||||
table reaches only the section named by its `sh_info`. In a linked image, a relocation section without `SHF_ALLOC`
|
||||
(such as one kept by `--emit-relocs`) was already applied by the static
|
||||
linker, so the slot's stored word is used rather than applying the record
|
||||
again.
|
||||
|
||||
Relocation ownership follows virtual addresses in linked images and section
|
||||
identity plus offset in relocatable objects. Distinct slots that share source
|
||||
file bytes keep independent values and overlap checks; a write to one does not
|
||||
relocate or invalidate the other.
|
||||
|
||||
An absolute relocation against an `STT_GNU_IFUNC` symbol is `unresolved`: the
|
||||
symbol value is the resolver, and the loader stores whatever the resolver
|
||||
returns.
|
||||
@@ -150,6 +174,11 @@ A symbol name that cannot be read, because its string table is missing or its
|
||||
offset lies outside the table, is reported as no name and makes the report
|
||||
`incomplete` with a counted limitation. Name offset 0 is the empty name.
|
||||
|
||||
ELF sections marked `SHF_COMPRESSED` are not decoded as initializer slots,
|
||||
symbols, names or relocation records. Affected facts remain unresolved and
|
||||
coverage is incomplete; other readable tables remain available. An explicit
|
||||
`DT_SYMTAB` must identify the decoded symbol table used for dynamic relocations.
|
||||
|
||||
The dynamic relocation tables are read in steps that yield to other work and
|
||||
observe cancellation, so a large `DT_RELR` table does not block the server.
|
||||
|
||||
|
||||
@@ -462,7 +462,9 @@ most 64 procedures and retains at most 4 MiB of encoded scan results. A composed
|
||||
workflow reuses its own index and clears it when the workflow finishes. The
|
||||
default cooperative scan budget is
|
||||
2,000 ms; set `REA_HOPPER_CALLER_SCAN_BUDGET_MS` to a positive integer number of
|
||||
milliseconds before starting REA to change it. The default limits additional
|
||||
milliseconds before starting REA to change the launch value, or use
|
||||
`update_analysis_settings` with `hopper.caller_scan_budget_ms` for newly accepted
|
||||
operations. The default limits additional
|
||||
work on the serial Hopper bridge; larger documents may need a higher setting.
|
||||
Results report the examined procedure count and any budget interruption.
|
||||
An individual page, native caller list, and target instruction list each have
|
||||
@@ -531,6 +533,24 @@ nodes and edges. Node payloads are bounded to 8 MiB and serialized results to
|
||||
32 MiB. Pagination returns edges whose source is on the node page and preserves
|
||||
stable IDs for endpoints outside that page.
|
||||
|
||||
After fully examining and retaining a callee's parameters, an unmatched
|
||||
recovered CALL operand is reported at the caller's call-site address in
|
||||
`unknowns[].call_inputs`. One group lists its `input_indices` (positive p-code
|
||||
input positions; input 0 is the destination), `call_node_id`, exact resolved
|
||||
`destination` selector and caller `evidence_id`. The operands themselves stay
|
||||
in the retained call node and source Evidence. For example, a three-argument
|
||||
call with only parameter ordinal 0 recovered retains the index-1 binding and
|
||||
reports indices `[2, 3]` together. This does not establish a variadic signature
|
||||
or invent formal parameters.
|
||||
|
||||
A depth, function, node or edge refusal, unavailable value flow, or truncated
|
||||
callee recovery does not establish such an examined gap. Those conditions
|
||||
keep their existing unknowns and traversal reasons. Call-input groups remain
|
||||
available when paging omits their call node; follow `call_node_id` in subsequent
|
||||
pages or the source Evidence. Older traces may omit `call_inputs`. Parameter
|
||||
and return bindings use canonical procedure addresses established by analyzed
|
||||
dossiers while preserving the provider's destination selector.
|
||||
|
||||
Procedure, node and edge `evidence_id` values identify the source function
|
||||
observations used by the trace. In an MCP session, retrieve them from the
|
||||
Evidence bundle for inspection or export. A replayed source keeps the original
|
||||
@@ -1031,6 +1051,11 @@ complete observation.
|
||||
arm64e formats;
|
||||
- legacy `LC_DYLD_INFO` rebase and bind opcodes.
|
||||
|
||||
Text relocation records retain their import identity without claiming a
|
||||
pointer value. Bind types are explicit: a non-lazy binding with no declared
|
||||
type is invalid. Reads that overlap only part of an encoded chained-fixup word remain
|
||||
unresolved rather than treating those stored bytes as an ordinary pointer.
|
||||
|
||||
[dyld symbol names are byte strings](https://github.com/apple-oss-distributions/dyld/blob/dyld-1330/mach_o/BindOpcodes.cpp#L203-L208),
|
||||
compared with [`strcmp`](https://github.com/apple-oss-distributions/dyld/blob/dyld-1330/mach_o/BindOpcodes.cpp#L42-L56).
|
||||
Dependent library install names likewise originate as
|
||||
@@ -1316,7 +1341,7 @@ the matching native decompiler. Experimental Windows x64 P0 admits native
|
||||
x86, x86-64, ARMNT (Thumb-2) and ARM64 PE applications and DLLs, [DOS MZ
|
||||
executables](../../providers/ghidra-dos.md), plus explicitly selected
|
||||
[raw NMOS 6502 images](../../providers/raw-binary.md#nmos-6502) with a caller-supplied load address,
|
||||
on fixed local NTFS volumes. Other raw CPU families remain unsupported on Windows.
|
||||
on fixed local NTFS/ReFS volumes. Other raw CPU families remain unsupported on Windows.
|
||||
The boundary uses bundled Job Object ownership, protected runtime DACLs, and
|
||||
handle-based path admission. See [Windows Ghidra P0](../../providers/windows-ghidra-p0.md) and
|
||||
[issue #527](https://github.com/morluto/rea/issues/527).
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
# Acquired NTFS metadata and change journals
|
||||
|
||||
Use offline acquisitions of the logical `$MFT` stream and `$UsnJrnl:$J`
|
||||
stream from the same volume. REA reads the selected files without mounting a
|
||||
volume, following data runs, querying Windows, or replaying journal operations.
|
||||
Pairing the acquisitions is the caller's responsibility.
|
||||
|
||||
```bash
|
||||
rea inspect-artifact ./MFT --json
|
||||
rea inspect-ntfs-journal ./MFT ./UsnJrnl-J --maxRows=50 --json
|
||||
```
|
||||
|
||||
MCP accepts absolute local paths:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "inspect_ntfs_journal",
|
||||
"arguments": {
|
||||
"mft_path": "/artifacts/MFT",
|
||||
"journal_path": "/artifacts/UsnJrnl-J",
|
||||
"max_rows": 50
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The paired workflow admits at most 64 MiB per acquisition. Its Evidence records
|
||||
both paths, lengths and SHA-256 digests. Keep the acquisitions and compare both
|
||||
digests between pages. Offsets refer to those original files, whose bytes remain
|
||||
unchanged; sector fixups are restored only in a scratch record before attribute
|
||||
interpretation.
|
||||
|
||||
`mftMetadata` reports aggregate inventory and fixup coverage, and at most 32
|
||||
record details when requested with `mft_record_limit` / `--mftRecordLimit`
|
||||
(default 0, inventory counts only). Names retain their individual parent references, namespaces,
|
||||
FILETIMEs, sizes and flags; several names are not collapsed into a path. Standard
|
||||
information timestamps stay separate from filename timestamps. All 64-bit times
|
||||
and sizes use decimal strings. Resident attributes retain value spans;
|
||||
nonresident attributes retain sizes, VCN ranges and validated packed mapping
|
||||
pairs, including sparse and fragmented runs. Attribute-list entries retain full
|
||||
references and IDs.
|
||||
|
||||
For a selected base record with attribute lists, `attributeListResolution`
|
||||
checks references inside the same acquired MFT. A link requires the exact
|
||||
record/sequence identity, verified fixups, matching base reference, and matching
|
||||
attribute type, name, ID and lowest VCN. `linkedAttributes` and
|
||||
`linkedFileNames` carry additional extension facts with original source offsets;
|
||||
local physical-record attributes stay separate. Global counts and
|
||||
`fileNameCoverage` describe physical-record walks, without double-counting
|
||||
linked facts.
|
||||
|
||||
Each detail page shares a budget of 32 additional decoded records (at most
|
||||
2 MiB of source record bytes), and each base record delivers at most 32 reference
|
||||
results. This bounds decoding and delivery, not total process memory.
|
||||
|
||||
- `references` identifies source list entries and reports resolved attribute
|
||||
offsets, ambiguity counts, or concrete unresolved reasons.
|
||||
- `knownEntryCount` counts entries discovered in available resident lists.
|
||||
`omittedKnownEntries` counts their undelivered results. Unreadable lists or
|
||||
omitted references may hide further entries; these are not whole-file totals.
|
||||
- `unreadListAttributeOffsets` marks list values unavailable from the acquired
|
||||
records. Zero known entries does not prove an empty list when this is nonempty.
|
||||
- `incompleteRecordIndices` preserves partial local walks. A valid referenced
|
||||
prefix can remain available while overall link coverage is incomplete.
|
||||
|
||||
List graphs are visited by source identity, including cycles. Reused sequences,
|
||||
contradictory headers, wrong base ownership and ambiguous attributes remain
|
||||
unresolved. If an additional-record budget is exhausted, reduce the detail page
|
||||
size or inspect the referenced slot directly with `mft_record_start`. Original
|
||||
list entries remain in attribute metadata when reference results are omitted.
|
||||
Nonresident list values and file contents require data outside the supplied MFT
|
||||
and remain unavailable here.
|
||||
|
||||
Journal rows follow acquisition order. V2 records use full 64-bit MFT references,
|
||||
including sequence numbers. Reused, inconsistent and unverifiable identities
|
||||
remain unresolved. V3 and V4 contain opaque 128-bit IDs, represented losslessly
|
||||
as unsigned little-endian decimal values with `referenceBytes: 16`; they are not
|
||||
joined to 64-bit MFT identities. V4 records carry no timestamp or name, so those
|
||||
fields are `null`. Their inline extent sample contains at most 16 entries, with
|
||||
source offsets, exact signed values, total and omitted counts, and
|
||||
`remainingExtents` for the recorded continuation state.
|
||||
|
||||
Follow `nextFileOffset` with MCP `start_file_offset` or CLI `--startFileOffset`.
|
||||
Decoding starts exactly there; preceding bytes are not examined. For another
|
||||
MFT detail page, select a limit from 1 to 32 and pass `mftMetadata.next_record_header_index` as MCP
|
||||
`mft_record_start` or CLI `--mftRecordStart`. MFT pages and journal pages are
|
||||
independent. Use the journal byte length as its starting offset when only MFT
|
||||
details are needed. A `null` continuation means that view has no further page.
|
||||
|
||||
Padding, unsupported versions, malformed records and truncation remain coverage
|
||||
rows. A bad record with a valid declared length can be skipped; a length that
|
||||
cannot locate the next record stops journal decoding. `historyCompleteness`
|
||||
remains `unknown`: supplied bytes alone cannot establish missing captures,
|
||||
wrap, absent rename partners or a complete activity history. Multiple reasons,
|
||||
rename rows and parent changes remain distinct source facts.
|
||||
|
||||
Verification covers synthesized paired acquisitions,
|
||||
[unmodified Windows 11 MFT records through the packaged Linux CLI](../../verification/ntfs-metadata-2026-11-11.md),
|
||||
and [paired V2 streams from a public NTFS volume fixture checked against an independent parser](../../verification/ntfs-metadata-2026-11-11.md#paired-volume-fixture-verification)
|
||||
through CLI/MCP on Linux. The fixture's original acquisition provenance, real
|
||||
V3/V4 captures and Windows-host execution remain unverified. Nonresident payload
|
||||
recovery is outside implemented scope. Real extension-record captures remain
|
||||
unverified.
|
||||
|
||||
Format references: [Microsoft USN V3](https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ns-winioctl-usn_record_v3),
|
||||
[USN V4](https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ns-winioctl-usn_record_v4),
|
||||
and [Linux NTFS on-disk definitions](https://github.com/torvalds/linux/blob/master/fs/ntfs3/ntfs.h).
|
||||
@@ -62,7 +62,10 @@ arguments are present, argument character length, target extension, whether
|
||||
`ShowCommand` is minimized, and whether the icon location differs from the
|
||||
recorded target path. That comparison is `null` unless the icon and a recorded
|
||||
target are both full paths: a stored filename, relative path, or `%VAR%` form
|
||||
cannot show that two locations differ. This workflow does not emit verdicts
|
||||
cannot show that two locations differ. Windows stores the `LinkInfo` path only
|
||||
as ANSI when the system code page can represent it. An ANSI path with non-ASCII
|
||||
bytes is therefore not compared with a Unicode icon location, or the reverse,
|
||||
because the code page is unobserved. This workflow does not emit verdicts
|
||||
about intent.
|
||||
|
||||
A missing optional section is observed absence of that structure. It is not
|
||||
|
||||
@@ -757,7 +757,8 @@ and cache settings.
|
||||
Symlink observations preserve their stored target bytes in `symlink_target_hex`
|
||||
(lowercase hexadecimal). `symlink_target` retains valid UTF-8 text and is `null`
|
||||
when the target bytes cannot be decoded as UTF-8. Filesystem effects compare
|
||||
these exact bytes without resolving the link. Older captures without the hex
|
||||
field still parse; a legacy target containing U+FFFD has ambiguous byte identity,
|
||||
so matching target text alone produces an `unknown` effect. Symlink descendants
|
||||
remain outside filesystem observation regardless of target encoding.
|
||||
these exact bytes without resolving the link. Every retained symlink requires
|
||||
the hex field; captures without it must be captured again before comparison.
|
||||
Saved Evidence remains unchanged, and target bytes are never inferred from
|
||||
display text. Unreadable targets remain explicit enumeration omissions. Symlink
|
||||
descendants remain outside filesystem observation regardless of target encoding.
|
||||
@@ -566,7 +566,7 @@ 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
|
||||
defaults to 30000 and, after response cleanup completes, is an item limitation, not that analysis timeout. Pending or failed response cleanup returns an error retaining its owner. These
|
||||
controls are also available as CLI flags with hyphenated names. Worker protocol
|
||||
and result byte budgets have no runtime override.
|
||||
|
||||
@@ -635,7 +635,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 uses `source_map_fetch_timeout_ms` (default 30000) and a default 64 MiB aggregate streamed-response budget across redirects. Select `source_map_limits.fetch_bytes` to change byte admission for the next call. 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 defaults to 64 MiB for raw resolved identities and 32 MiB for aggregate inline evidence; `source_map_limits.fetch_bytes` and `source_map_limits.output_bytes` own those independent admissions. 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 default 64 MiB aggregate streamed-response budget across redirects. Select `source_map_limits.fetch_bytes` to change byte admission for the next call. After response cleanup completes, a fetch overrun is an item limitation, not a thrown analysis timeout. Pending or failed response cleanup instead returns an error retaining its owner. A deadline or byte-limit failure remains explicitly unavailable and makes bundle completeness partial. Source-map decoding defaults to 64 MiB for raw resolved identities and 32 MiB for aggregate inline evidence; `source_map_limits.fetch_bytes` and `source_map_limits.output_bytes` own those independent admissions. 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`.
|
||||
|
||||
A fully read response that fails UTF-8, JSON, mapping, or structural validation
|
||||
retains `artifact: null`, empty original-source, module-edge, and mapping
|
||||
|
||||
@@ -531,7 +531,10 @@ id the application assigns:
|
||||
start origin as the browser spells it, so a path may name `My List` or
|
||||
`My%20List` (`{*}` matches one segment, and the query is ignored), and fails
|
||||
the step unless a 2xx JSON response arrives before its `timeout_ms`; one still
|
||||
being read when the step times out or is cancelled saves nothing. A pointer
|
||||
being read when the step times out or is cancelled saves nothing. Saved values
|
||||
are committed only while the step remains active, after response reading and
|
||||
any request-route cleanup succeed. Cancellation after that commit retains
|
||||
them; a physical request or cleanup failure keeps its original reason. A pointer
|
||||
that names no string or number fails the step, so later steps never send a
|
||||
missing value, as does a response over 4,000,000 characters: a request step
|
||||
stops reading and aborts its fetch there. A UI step reads a body only when
|
||||
@@ -592,22 +595,25 @@ id the application assigns:
|
||||
partial failures without retaining an image to scrub later. Other requested
|
||||
artifacts remain available; affected screenshot/aggregate completeness is
|
||||
partial and is not eligible for equality.
|
||||
- Saved URLs and expanded request JSON are admitted before building their expanded strings or
|
||||
serializing. Its allowance is the smaller of Node's string limit and
|
||||
one sixteenth of current V8 available heap bytes, allowing for the expanded
|
||||
tree, serialization, Playwright transport and browser-side copies. Size
|
||||
- Saved URLs, structured queries, and expanded request JSON are admitted before
|
||||
building their expanded strings or serializing. Their allowance is the smaller
|
||||
of Node's string limit and one sixteenth of current V8 available heap bytes,
|
||||
allowing for the expanded tree, serialization, Playwright transport and
|
||||
browser-side copies. Size
|
||||
accounting includes JSON escaping and repeated references; each distinct
|
||||
saved value's size is measured once per request. An oversized request fails
|
||||
before browser dispatch; the complete request envelope, including repeated
|
||||
header values, is checked as well. URL encoding uses a conservative
|
||||
nine-characters-per-UTF-16-unit allowance before encoding a saved value.
|
||||
header values, is checked as well. URI-component and form-query sizes are
|
||||
counted with their respective escaping rules before encoding; repeated equal
|
||||
components reuse their measured size.
|
||||
Reduce the payload/repetitions, or raise the parent
|
||||
Node heap and restart; this is a conservative allocation estimate, not a
|
||||
measurement or guarantee of browser/process-family memory.
|
||||
- Evidence records a request step's empty `save` list as absent, so a scenario
|
||||
that saves nothing records the same parameters and `scenario_sha256` as
|
||||
before saved values existed, and REA versions without saved values read its
|
||||
captures.
|
||||
- Evidence records the current parsed request action, including `save: []`
|
||||
when no values are saved. Its parameters and `scenario_sha256` use that
|
||||
representation; new observations can have different identities from older
|
||||
captures that omitted the empty list. Retained Evidence keeps its original
|
||||
parameters and identity.
|
||||
|
||||
## Network evidence
|
||||
|
||||
|
||||
@@ -115,9 +115,7 @@ are made.
|
||||
## Compact point delivery and retained source text
|
||||
|
||||
Summary delivery is useful for large point answers. Complete output can answer
|
||||
a small-map task with fewer calls. The
|
||||
[delivery qualification](../../verification/source-location-delivery.md)
|
||||
records measured task costs and first-use discovery tradeoffs.
|
||||
a small-map task with fewer calls.
|
||||
|
||||
Complete delivery remains the default and includes raw map text and embedded source
|
||||
content. Select `detail: "summary"` in MCP, or `--detail summary` with
|
||||
@@ -199,16 +197,12 @@ budgets.
|
||||
| `codec_heap_mib` | 192 | Local codec old-generation request; process-memory enforcement remains host dependent |
|
||||
| `fetch_bytes` | 67108864 | Aggregate response bytes and, independently, resolved-identity bytes |
|
||||
|
||||
The local 8 MiB admission covers the pinned 4,284,329-byte main map and 5,529,840-byte
|
||||
DateSelect map from Actual Budget without an admission retry. This is an artifact
|
||||
compatibility allowance, not a context or latency optimization: complete Evidence
|
||||
retains raw map text, and those two measured replies estimate 1.59 and 2.23 million
|
||||
tokens. A smaller admission refuses the map; it does not compact successful
|
||||
Evidence. MCP retains complete Evidence before encoding; an oversized response
|
||||
The local map admission defaults to 8 MiB. Complete Evidence retains raw map
|
||||
text, so a larger admitted map can produce a large response. MCP retains complete
|
||||
Evidence before encoding; an oversized response
|
||||
returns its retained reference for `export_evidence_bundle`, or callers can use
|
||||
complete CLI JSON. Select opt-in compact delivery above to keep complete Evidence accessible while returning only point metadata or an explicitly selected text page.
|
||||
Browser collection keeps its separate conservative defaults; see the
|
||||
[calibration record](../../verification/source-map-budget-calibration.md).
|
||||
Browser collection keeps its separate conservative defaults.
|
||||
|
||||
Local tracing accepts all listed fields except `fetch_bytes`. Bundle fetching
|
||||
accepts all except `map_bytes` and `codec_heap_mib`: it uses its existing
|
||||
|
||||
@@ -174,7 +174,9 @@ Official references: [mitmproxy protocol support](https://github.com/mitmproxy/m
|
||||
|
||||
## Verifier regressions
|
||||
|
||||
After building REA, run these inside the same isolated guest:
|
||||
The built process-boundary test suite runs the Node verifier regressions on
|
||||
POSIX hosts. To run them directly after building REA, and to run the Python
|
||||
laboratory regressions with its pinned dependencies, use the isolated guest:
|
||||
|
||||
```sh
|
||||
node --test scripts/lib/http3-verifier-lifecycle.test.mjs scripts/lib/http3-capture-assertions.test.mjs
|
||||
|
||||
@@ -213,8 +213,8 @@ rejects it. The file is read, never loaded or executed.
|
||||
|
||||
A position-independent `libil2cpp.so` stores zero in most pointer slots and
|
||||
keeps the value in `R_AARCH64_RELATIVE` or `R_X86_64_RELATIVE` relocations
|
||||
(`DT_RELA`). The reader writes those values into a private copy before
|
||||
searching it, so addresses are the link-time addresses and RVAs are relative to
|
||||
(`DT_RELA`). The reader indexes loader values by virtual address while keeping
|
||||
the source bytes unchanged, so addresses are the link-time addresses and RVAs are relative to
|
||||
the first loaded segment. Android packed
|
||||
relocations (`DT_ANDROID_RELA`) are refused. No target code is executed.
|
||||
|
||||
@@ -451,11 +451,11 @@ The builds checked are listed after the module search rules above.
|
||||
| `generic-method-registration-not-found` | input error | No CodeRegistration layout bounds every genericMethodTable row, or the generic tables are unreadable. |
|
||||
| `ambiguous-generic-method-registration` | input error | More than one CodeRegistration layout bounds every genericMethodTable row. |
|
||||
|
||||
Format and selection failures name `binary_path`; capacity refusals remain typed resource errors. Failed linking preserves the metadata source identity, validated counts, selected binary path/architecture and its SHA-256 when observed, plus prior producer observations. It never publishes an incomplete native table as complete. The binary input is bounded to 1 GiB.
|
||||
Format and selection failures name `binary_path`; capacity refusals remain typed resource errors. Failed linking preserves the metadata source identity, validated counts, selected binary path/architecture and its SHA-256 when observed, plus prior producer observations. It never publishes an incomplete native table as complete. The binary input is bounded to 1 GiB. The virtual-pointer index has the same 1 GiB estimated representation allowance, reserving 2 KiB per distinct virtual destination before insertion for retained Maps and finish-time lookup storage. Repeated declarations of one destination share that reservation. This conservative allocation accounting is separate from actual process RSS and the report allowance; exhaustion returns a typed `native-index-capacity` refusal before another destination is retained.
|
||||
|
||||
Scans yield cooperatively in bounded batches. Name-address retention and reverse-trie construction are each limited to 65,536 entries/nodes and fallback module-array candidates to 64 (`native-index-capacity`); exceeding capacity does not prove absence. Rendered type text has a 64 MiB UTF-8 cache-workspace guard, separate from the 64 MiB encoded-report admission, and 64 nested rendering frames (`native-type-text-capacity` / `type-nesting-capacity`). Genuine cycles are malformed; unsupported type kinds are explicit coverage failures. Native row/text admission runs before allocation or retention. Unused generic parameter names are read on demand from the same stable metadata snapshot. There is no cross-inspection file cache; validated immutable Evidence is reused for session views.
|
||||
|
||||
ELF RELATIVE writes into zero-fill are kept as a private virtual-pointer overlay. Unresolved supported-width symbol relocations, including RELA PLT entries, remain unknown only for the bytes their ELF ABI relocation type covers; an adjacent 32-bit relocation does not make a separate 64-bit method slot unknown. Stored zeros never establish no-body. COPY, TLS descriptor, REL, packed APS2 and other unsupported relocation encodings fail closed. Input bytes are unchanged.
|
||||
ELF RELATIVE writes use a virtual-pointer overlay for both file-backed and zero-fill locations. Distinct virtual addresses that share source file bytes retain independent values; an untouched alias keeps its stored bytes. Unresolved supported-width symbol relocations, including RELA PLT entries, remain unknown only for the bytes their ELF ABI relocation type covers; an adjacent 32-bit relocation does not make a separate 64-bit method slot unknown. Stored zeros never establish no-body. COPY, TLS descriptor, REL, packed APS2 and other unsupported relocation encodings fail closed. Input bytes are unchanged.
|
||||
|
||||
ELF relocation tables and file-backed destinations may span adjacent load ranges when every range agrees on the file translation. Any overlapping zero-fill declaration makes those bytes ambiguous; REA refuses the table or relocation destination instead of choosing the stored file bytes. Missing file bytes remain distinct from conflicting owners: supported unresolved relocations outside file-backed memory retain their unknown overlay, while ambiguous destinations refuse linking. Registration coverage uses the same file/zero-fill ownership checks as pointer reads.
|
||||
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ The [documentation directory](README.md) lists every guide by domain.
|
||||
| Inspect native functions, references, or types | [Native binaries](guides/native/native-investigation.md), [Go metadata](guides/native/go-binaries.md), [Rust dependencies](rust-binaries.md), [CPython pyc files](python-pyc.md), [PE certificates](pe-certificates.md), [PE imports](pe-imports.md), [PE TLS/load config](pe-load-config.md), [ELF notes](elf-notes.md), [initializer functions](guides/native/native-initializers.md), [ELF unwind ranges](guides/native/elf-unwind-ranges.md), [Linux kernel modules](kernel-modules.md), [Linux kernel build config](guides/native/kernel-build-config.md), [Apple IPS](apple-ips.md), [Erlang BEAM](erlang-beam.md), [offline ELF layout](guides/native/binary-diagnostics.md), [recorded crashes](guides/native/recorded-crashes.md) |
|
||||
| Select a native provider or import format | [Ghidra semantics](providers/ghidra-provider.md), [Windows](providers/windows-ghidra-p0.md), [DOS](providers/ghidra-dos.md), [raw bytes](providers/raw-binary.md), [GameCube DOL](ghidra-dol.md), [MIPS](providers/ghidra-mips.md), [RISC-V](providers/ghidra-riscv.md), [PowerPC](ghidra-ppc.md), [PSP](providers/ghidra-psp.md), [NativeAOT](providers/ghidra-nativeaot.md), [IDA](providers/ida-provider.md), [Kuna](kuna-provider.md), [JEB](providers/jeb-analysis.md) |
|
||||
| Analyze JavaScript or Electron artifacts | [Static analysis](guides/javascript/javascript-artifact-reconstruction.md), [tracing and comparisons](guides/javascript/javascript-application-workflows.md), [application graph](guides/javascript/javascript-application-graph.md), [source recovery](guides/javascript/javascript-recovery.md) |
|
||||
| Compare static JavaScript with runtime observations | [Runtime attribution](guides/javascript/javascript-runtime-observation.md), [reconciliation](guides/javascript/javascript-runtime-reconciliation.md), [Electron observation](guides/javascript/electron-observation.md), [Electron fuses](electron-fuses.md) |
|
||||
| Compare static JavaScript with runtime observations | [Runtime attribution](guides/javascript/javascript-runtime-observation.md), [reconciliation](guides/javascript/javascript-runtime-reconciliation.md), [Electron observation](guides/javascript/electron-observation.md), [Electron fuses](electron-fuses.md), [Release exposure](release-exposure.md) |
|
||||
| Inspect assemblies, packages, or firmware | [Godot PCK](godot-pck.md), [UnityFS](unityfs.md), [wxapkg](wxapkg.md), [U-Boot uImage](uimage.md), [.NET](guides/managed/managed-code-analysis.md), [Python packages](python-packaged-applications.md), [Android](guides/android/android-analysis.md), [APK signatures](apk-signature.md), [Apktool resources](guides/android/apktool-resource-analysis.md), [ADB acquisition](guides/android/adb-device-analysis.md), [Apple](guides/apple/apple-application-analysis.md), [Harmony](guides/harmony/harmony-analysis.md), [firmware](guides/firmware/firmware-analysis.md), [Device Tree](devicetree.md), [FIT images](fit-images.md), [UF2/DfuSe](uf2-dfuse.md), [Flutter](guides/android/flutter-analysis.md), [ESP images](esp-image.md), [ESP flash images](esp-flash-image.md), [WASM](guides/wasm/wasm-artifacts.md), [EVM](guides/evm/evm-bytecode.md) |
|
||||
| Observe or compare a browser scenario | [CDP observation](guides/web/browser-observation.md), [scenarios](guides/web/browser-scenario-contract.md), [runtime evidence](guides/web/web-runtime.md), [historical captures](guides/web/web-network-captures.md) |
|
||||
| Serve recorded behavior as an agent environment | [Agent environments](agent-environments.md) |
|
||||
|
||||
+41
-9
@@ -59,7 +59,7 @@ Pseudocode read from a parallel project export includes a prototype-context
|
||||
limitation in its Evidence, including in function dossiers and composed
|
||||
workflows. Early single-function results have their own source limitation.
|
||||
|
||||
A single-function decompile, inventory, string, graph or xref run that exceeds its deadline fails as `provider_timeout`, naming the setting that owns the deadline and that raising it takes a restart. A project export that exceeds `REA_KUNA_PROJECT_TIMEOUT_MS` is an export failure instead: requests that need the export report `capability_unavailable` with the export's own retry guidance.
|
||||
A single-function decompile, inventory, string, graph or xref run that exceeds its deadline fails as `provider_timeout`, naming the setting that owns the deadline. Change the reported budget for newly accepted operations with `update_analysis_settings` using `kuna.function_timeout_ms` or `kuna.project_timeout_ms`. A project export that exceeds `REA_KUNA_PROJECT_TIMEOUT_MS` is an export failure instead: requests that need the export report `capability_unavailable` with the export's own retry guidance.
|
||||
|
||||
Windows is not supported yet. Supported targets are ELF and thin Mach-O executables for x86-64, AArch64 and ARM; PE and universal Mach-O are rejected with a typed reason.
|
||||
|
||||
@@ -90,7 +90,7 @@ The first text or assembly request in a session looks for this target's export i
|
||||
- Meanwhile, pseudocode comes from one `kuna decompile --addr` run. Name and address lookups, and listings, use the inventory the export takes with `kuna functions --json` before it decompiles. The session runs `kuna functions` itself, under `REA_KUNA_TIMEOUT_MS`, only when no export is building (an inventory-only request does not start one) or the export ends without an inventory.
|
||||
- Requests for the same function share one run; it stops when its last waiting request is cancelled. Each run analyzes the whole image again in its own process, so one REA process runs at most as many at once as the host has cores beyond `REA_KUNA_JOBS` (at least one). Further requests wait in order, and a waiting request is answered from the export if it finishes first. A run whose stop REA cannot prove keeps its slot until `close_binary` proves it stopped.
|
||||
- The session keeps each completed single-function text, up to 16 MiB in all with the least recently used dropped first, and answers repeats from it until the export can. After a failed export that lasts for the session.
|
||||
- Assembly and data names wait for the export; progress notifications report the wait every ten seconds. A session does not rebuild a failed export: requests that need it fail with `retryable: false`, the export's failure, its captured Kuna output and what to change before reopening the target. REA does not expose per-function records from a failed project export, even if the retained Kuna diagnostic refers to them. Single-function fallback Evidence reports the failed state and this limitation. If cleanup remains incomplete, its error takes precedence and `close_binary` retries the retained resources. A setting such as `REA_KUNA_PROJECT_TIMEOUT_MS` or `REA_KUNA_JOBS` is read when REA starts, so changing it also needs a restart. Pseudocode keeps using single-function runs.
|
||||
- Assembly and data names wait for the export; progress notifications report the wait every ten seconds. A session does not rebuild a failed export: requests that need it fail with `retryable: false`, the export's failure, its captured Kuna output and what to change before reopening the target. REA does not expose per-function records from a failed project export, even if the retained Kuna diagnostic refers to them. Single-function fallback Evidence reports the failed state and this limitation. If cleanup remains incomplete, its error takes precedence and `close_binary` retries the retained resources. Change the deadline for a newly accepted project export with `update_analysis_settings` using `kuna.project_timeout_ms`; a failed session does not restart its export, so close and reopen the target to start another. `REA_KUNA_JOBS` is read when REA starts, so changing it requires a restart. Pseudocode keeps using single-function runs.
|
||||
- A single-function answer says so in its limitations. It lacks the export's whole-program prototypes, so a later request can return different text for the same function.
|
||||
|
||||
Pseudocode, assembly, `analyze_function` and data-name answers record where their text came from in `raw_result.source`: `single-function`, or `project-export` with the cache directory. `procedure_pseudo_code` and `procedure_assembly` answers from the export also name the file, byte span and the file's SHA-256. Combined `analyze_function` answers retain both facet records in `raw_result.source.files`, each with its file, digest and byte span. Both texts come from one export; losing that project retries the complete report. Listings and procedure lookups carry no `raw_result`; omitted [Mach-O data entries](#mach-o-data-entries) are reported in their limitations. Agents can open or search the export's `.c` and `.asm` there directly when that is cheaper than calling a tool per function. Text read that way is target-derived, like any decompiler output, but it bypasses the untrusted-content marker that REA's tool results carry.
|
||||
@@ -99,7 +99,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 matching deadline and a worker old-generation heap. Literal matching remains the default. Cancellation or a matching deadline leaves the session available. The deadline is `REA_REGEX_MATCHING_DEADLINE_MS`, a positive decimal integer from 1 to 2147483647 ms. Unset uses 5000 ms. A larger value is refused because Node schedules a delay past that signed 32-bit bound as 1 ms. Invalid values are configuration errors and do not fall back to the default. The setting is read from the environment that starts REA, so a change needs a restart. A deadline failure names the effective milliseconds, whether they came from the default or the setting, the default, and the maximum. The worker old-generation heap does not raise it. The worker heap request is `REA_REGEX_WORKER_HEAP_REQUEST_MIB`, a decimal integer from 7 to 16384 MiB. Unset uses 128 MiB. A request below 7 MiB aborts the worker during startup, and a larger value is refused. Invalid values are configuration errors and do not fall back to 128. The setting is read from the environment that starts REA, so a change needs a restart. A heap failure names the effective request, whether it came from the default or the setting, the default, the floor, and the maximum. 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 worker heap 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 worker heap 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 worker heap 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.
|
||||
Regex procedure and string search uses ECMAScript Unicode matching in a cancellable worker with a matching deadline and a worker old-generation heap. Literal matching remains the default. Cancellation or a matching deadline leaves the session available. The deadline is `REA_REGEX_MATCHING_DEADLINE_MS`, a positive decimal integer from 1 to 2147483647 ms. Unset uses 5000 ms. A larger value is refused because Node schedules a delay past that signed 32-bit bound as 1 ms. Invalid values are configuration errors and do not fall back to the default. Change the budget for newly accepted searches using `update_analysis_settings` and `regex.matching_deadline_ms`; changing the launch environment requires a restart. A deadline failure names the effective milliseconds, known source, default, and maximum. The worker old-generation heap does not raise it. The worker heap request is `REA_REGEX_WORKER_HEAP_REQUEST_MIB`, a decimal integer from 7 to 16384 MiB. Unset uses 128 MiB. A request below 7 MiB aborts the worker during startup, and a larger value is refused. Invalid values are configuration errors and do not fall back to 128. Change the request for workers of newly accepted searches using `update_analysis_settings` and `regex.worker_heap_request_mib`; changing the launch environment requires a restart. A heap failure names the effective request, known source, default, floor, and maximum. 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 worker heap 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 worker heap 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 worker heap 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 project-export spans remain in the local export and the error identifies the file and range. A single-function run does not by itself retain a complete project export. `analyze_function` with `detail: "complete"` (the CLI default) returns the complete dossier inline, which can still be large; later retained views do not remove that first transfer. The MCP default retains the dossier and returns its summary, so page the facets you need through `inspect_analysis_view`, or prefer the individual text tools for a focused question.
|
||||
|
||||
@@ -149,8 +149,12 @@ its typed primary failure and captured output. Its live resource list follows
|
||||
both process and workspace ownership: proving process exit does not prove that
|
||||
the private workspace was removed, and retry updates earlier caller errors.
|
||||
If workspace setup fails, an unsuccessful rollback retains the original target
|
||||
or read failure together with its cleanup owner. Replacement stays blocked until
|
||||
that rollback is resolved; a clean rollback permits another setup attempt.
|
||||
or read failure together with its cleanup owner. Cancellation during input
|
||||
copying keeps the caller's reason; a physical read or write failure keeps its
|
||||
own diagnosis if cancellation follows. Failed copy-file cleanup retains the
|
||||
private workspace, and `close_binary` retries its remaining file owners before
|
||||
removing it. Replacement stays blocked until that rollback is resolved; a clean
|
||||
rollback permits another setup attempt.
|
||||
|
||||
## Provenance and limitations
|
||||
|
||||
@@ -164,7 +168,7 @@ that rollback is resolved; a clean rollback permits another setup attempt.
|
||||
REA writes Kuna's exports only inside `REA_KUNA_CACHE_DIR`:
|
||||
|
||||
- `projects/<key>/` holds published, immutable exports with a manifest of file digests.
|
||||
- `staging/` holds builds whose processes may still be live.
|
||||
- `staging/` holds active builds and builds with pending process or file cleanup.
|
||||
- `trash/` holds retired builds and evicted exports awaiting removal.
|
||||
- `home/` is Kuna's HOME.
|
||||
|
||||
@@ -180,7 +184,33 @@ the manifest's file identity as well as the export files. These refusal and
|
||||
migration cases are verified with controlled Kuna-format exports; they do not
|
||||
establish behavior of an independently installed Kuna release.
|
||||
|
||||
Builds publish by one rename, so a reader sees a complete export or none. If later staging retirement fails, the typed cleanup error retains the completed export's key, directory and manifest in `published_export`. The session adopts that verified project; later queries reuse its immutable files while `project_export.cleanup_incomplete` reports the retained owner's live state. `close_binary` retries only the remaining cleanup, and a successful retry resolves prior cleanup errors. A failed export followed by failed staging cleanup retains both failures; it does not invent a publication receipt. A session keeps the export it uses from eviction only within its own REA process. If another REA process sharing the cache evicts it, the session rebuilds it; meanwhile pseudocode falls back to single-function runs. A damaged or edited export is removed and rebuilt. REA retains the file state verified with each digest, checks it before warm-cache reuse, and checks open descriptors before and after reading text. Assembly indexes are checked against the same state; a changed file makes the whole report retry rather than mixing facets from different exports. Staging moves to `trash/` for removal only after REA proves its Kuna process stopped. Staging of a process it cannot prove stopped is never swept; REA keeps it owned, retries the stop on `close_binary`, and reports it until the stop is proven; that MCP error names the same-connection retry as `recovery.kind=retry_cleanup` ([retained cleanup retry](reference/mcp-contracts.md#retained-cleanup-retry)). Failed file removal also stays bound to its export and is retried by `close_binary`; closing does not report success while that cleanup remains. `rea doctor --provider kuna` reports the cache directory without creating it.
|
||||
Builds publish by one rename, so a reader sees a complete export or none. If
|
||||
later staging retirement fails, the typed cleanup error retains the completed
|
||||
export's key, directory and manifest in `published_export`. The session adopts
|
||||
that verified project; later queries reuse its immutable files while
|
||||
`project_export.cleanup_incomplete` reports the retained owner's live state.
|
||||
`close_binary` retries only the remaining cleanup, and a successful retry
|
||||
resolves prior cleanup errors. A failed export followed by failed staging
|
||||
cleanup retains both failures; it does not invent a publication receipt.
|
||||
|
||||
A session keeps the export it uses from eviction only within its own REA
|
||||
process. If another REA process sharing the cache evicts it, the session
|
||||
rebuilds it; meanwhile pseudocode falls back to single-function runs. A
|
||||
damaged or edited export is removed and rebuilt. REA retains the file state
|
||||
verified with each digest, checks it before warm-cache reuse, and checks open
|
||||
descriptors before and after reading text. Assembly indexes are checked
|
||||
against the same state; a changed file makes the whole report retry rather
|
||||
than mixing facets from different exports.
|
||||
|
||||
Staging moves to `trash/` for removal only after REA proves its Kuna process
|
||||
stopped and releases its copy-file handles. Staging of a process it cannot
|
||||
prove stopped is never swept; REA keeps it owned, retries the stop on
|
||||
`close_binary`, and reports it until the stop is proven; that MCP error names
|
||||
the same-connection retry as `recovery.kind=retry_cleanup` ([retained cleanup
|
||||
retry](reference/mcp-contracts.md#retained-cleanup-retry)). Failed file
|
||||
removal also stays bound to its export and is retried by `close_binary`;
|
||||
closing does not report success while that cleanup remains. `rea doctor
|
||||
--provider kuna` reports the cache directory without creating it.
|
||||
|
||||
## Verify with a real Kuna
|
||||
|
||||
@@ -196,5 +226,7 @@ The lane compiles a small source-owned fixture with the host C compiler and veri
|
||||
Failed runs also report process-lineage evidence and exit unsuccessfully. If provider or transport cleanup is unconfirmed, the report says `cleanup: "incomplete"` and records `retained_workspace`; that directory is preserved for investigation and cleanup retries.
|
||||
|
||||
Doctor reports an invalid Kuna cache, job count, or timeout setting with that
|
||||
setting's correction. Correct or unset the named setting and restart REA; these
|
||||
configuration rejections do not require replacing the selected Kuna executable.
|
||||
setting's correction. Cache size and job count stay with the process that
|
||||
started them. The two timeouts can be changed at runtime with
|
||||
`update_analysis_settings`. These configuration rejections do not require
|
||||
replacing the selected Kuna executable.
|
||||
@@ -40,6 +40,19 @@ signer identifier facts. A signer identified by subject key identifier reports
|
||||
that value as `subject_key_identifier_hex`. Other certificate types keep
|
||||
`pkcs7` null.
|
||||
|
||||
Each name attribute reports `rdn_index`, the zero-based position of its relative
|
||||
distinguished name (RDN) in the encoded name. Attributes in the same RDN share
|
||||
an index. Older retained Evidence may omit the index.
|
||||
|
||||
A distinguished name's `text` joins those attributes in encoded order.
|
||||
Attributes in one RDN are joined with `+`
|
||||
(`commonName=A+organizationName=B`). Separate RDNs are joined with `, `
|
||||
(`commonName=A, organizationName=B`). The separators follow
|
||||
[RFC 4514](https://www.rfc-editor.org/rfc/rfc4514) multi-valued RDN notation.
|
||||
Encoded order is kept, and values are copied as decoded, without RFC 4514
|
||||
escaping or RDN reversal, so a name of only single-valued RDNs still places
|
||||
`, ` between attributes.
|
||||
|
||||
Each signer reports `unsigned_attribute_oids`: null means the field was absent,
|
||||
and an array lists the types when present. Older retained Evidence may omit the
|
||||
field. Unsigned attribute contents, including nested signatures and timestamp
|
||||
@@ -51,6 +64,12 @@ image is unsigned in every catalog or overlay sense.
|
||||
|
||||
## Limits and failures
|
||||
|
||||
Confirmed DOS-only MZ files and declared NE, LE, or LX signatures are outside
|
||||
this PE32/PE32+ workflow and return `unsupported_target` with target-selection
|
||||
recovery. A recognized non-PE signature does not need a PE COFF header to be
|
||||
classified. Unrecognized signatures and truncated PE headers remain malformed
|
||||
input. `inspect-pe-resources` uses the same header admission and classifications.
|
||||
|
||||
The selected file is limited to 64 MiB by default (512 MiB maximum). At most
|
||||
eight `WIN_CERTIFICATE` entries are examined by default. Malformed PE headers,
|
||||
truncated certificate entries, and PKCS#7 that is not structurally signedData
|
||||
|
||||
+6
-3
@@ -33,7 +33,9 @@ Evidence file-offset range.
|
||||
If the first descriptor cannot be examined, the directory declaration remains
|
||||
present with no consumed `locations`, and coverage is partial. Descriptors,
|
||||
thunks and NUL-terminated names stay within PE's 32-bit RVA space, including
|
||||
PE32+ images; earlier valid rows survive an overflowing descriptor walk.
|
||||
PE32+ images. Descriptor walks also stay inside each data directory's declared
|
||||
byte size; an unterminated or partially covered final slot is reported as a
|
||||
malformed entry, while earlier valid rows survive.
|
||||
|
||||
`machine` retains the original unsigned COFF value. `architecture` decodes
|
||||
known machines, including ReadyToRun OS overrides when a CLI directory is
|
||||
@@ -69,8 +71,9 @@ with no runtime override; `max_file_bytes`, `max_dlls` and `max_functions` do
|
||||
not raise it. Resource failures report the exhausted allowance as `limit`
|
||||
(`dlls`, `functions` or `retained_text`) with matching recovery.
|
||||
|
||||
Unreadable DLL names, hint/name entries, or thunks are reported as partial
|
||||
coverage with `issues`. A descriptor whose required table RVA is zero (a
|
||||
Unreadable DLL names, hint/name entries, thunks, or descriptor slots outside
|
||||
the declared directory size are reported as partial coverage with `issues`. A
|
||||
descriptor whose required table RVA is zero (a
|
||||
standard `FirstThunk`, or a delay-load import address or name table) is
|
||||
reported as `malformed_entry` with no functions, never as a complete empty
|
||||
inventory. Delay-load descriptors that store virtual addresses rather than RVAs
|
||||
|
||||
@@ -65,7 +65,8 @@ escaping, before allocating the serialized request or sending it. The framing
|
||||
newline is excluded. An oversized request returns `resource_constraint` with
|
||||
the effective setting, its source, and the exact payload byte count.
|
||||
|
||||
Set the value in the environment that starts REA, then restart REA to apply it.
|
||||
`bridge.max_request_bytes` can be changed at runtime with
|
||||
`update_analysis_settings`. The launch seed is `REA_BRIDGE_MAX_REQUEST_BYTES`.
|
||||
This setting is enforced by the REA client; the Java bridge has no corresponding
|
||||
request ceiling.
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ rea function 'D:\samples\program.exe' main --json
|
||||
|
||||
Headless REA and the configured supervisor must share the host filesystem and native path syntax. Run REA on Windows when the supervisor runs on Windows. The attached profile can span WSL and a Windows GUI because it binds recorded input hashes instead of asking the GUI to open a WSL path.
|
||||
|
||||
REA copies the admitted binary into a private temporary directory, checks its digest, and requests an owned worker with `force_headless`. POSIX workspaces are created atomically with owner-only permissions, respecting the process umask; Windows uses the matching package's native private-DACL boundary on a local NTFS temporary directory. It injects the returned database ID into analysis requests. It verifies the active owned worker and input path rather than adopting a user database. On close or failed startup, it releases its session with `save: false`, verifies that it is absent from upstream session discovery, and removes its private input and sidecars. An unverified release retains the workspace and reports incomplete cleanup.
|
||||
REA copies the admitted binary into a private temporary directory, checks its digest, and requests an owned worker with `force_headless`. POSIX workspaces are created atomically with owner-only permissions, respecting the process umask; Windows uses the matching package's native private-DACL boundary on a local NTFS/ReFS temporary directory. It injects the returned database ID into analysis requests. It verifies the active owned worker and input path rather than adopting a user database. On close or failed startup, it releases its session with `save: false`, verifies that it is absent from upstream session discovery, and removes its private input and sidecars. An unverified release retains the workspace and reports incomplete cleanup.
|
||||
|
||||
One REA session owns one database. Stdio registrations default `IDA_MCP_MAX_WORKERS` to `1`; the explicit upstream `--max-workers 1` also bounds a supervisor. Database size and engine memory depend on the target and upstream; REA does not impose an engine memory limit. The original binary is never executed or overwritten. Optional `workspaceRoot` selects an existing absolute temporary-directory parent on the REA host. The selected parent is resolved by the filesystem before deriving its canonical identity, including POSIX symlink/parent components. Ensure it has space for the input copy and IDA working files.
|
||||
|
||||
|
||||
@@ -35,8 +35,10 @@ 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
|
||||
2.3.1). Change the budget for subsequent operations with
|
||||
`update_analysis_settings` using `jeb.mcp_timeout_ms`. To change the launch
|
||||
value, update REA's environment and restart. 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,
|
||||
|
||||
@@ -13,7 +13,7 @@ additional permission flag or degraded mode is required.
|
||||
|
||||
## Supported boundary
|
||||
|
||||
- Windows 10+ x64 with fixed local NTFS target and temporary volumes;
|
||||
- Windows 10+ x64 with fixed local NTFS/ReFS target and temporary volumes;
|
||||
- Node.js 22.x (>=22.23.4), 24.x (>=24.22.1), or 26.12.1+;
|
||||
- an operator-installed Ghidra 12.x (>=12.1) distribution (verified with 12.1.4);
|
||||
- a 64-bit full JDK inside that installation's declared Java range (JDK 21 or newer, with no maximum, for current 12.1 releases);
|
||||
@@ -91,7 +91,7 @@ mean Windows x64 itself is unsupported. Provider diagnostics retain the failure
|
||||
stage under `windows_native_failure`; the availability's `remediation` carries
|
||||
the corresponding repair.
|
||||
Self-test failures preserve the native operation and OS error text. Check the
|
||||
process's writable local NTFS temporary directory and the reported filesystem,
|
||||
process's writable local NTFS/ReFS temporary directory and the reported filesystem,
|
||||
DACL, Job Object or cleanup constraint, then rerun doctor after resolving it.
|
||||
Ghidra or Java reinstallation cannot resolve a native self-test failure. The
|
||||
provider remains unavailable until all native controls are proven; a later query
|
||||
@@ -192,7 +192,7 @@ unchanged; these observations do not establish a speedup. Configured processor
|
||||
selection is covered by profile tests, not these real-provider runs.
|
||||
|
||||
Admission opens and checks every path component without following a reparse
|
||||
point. It retains handles, verifies local NTFS semantics, and observes volume
|
||||
point. It retains handles, verifies local NTFS/ReFS semantics, and observes volume
|
||||
serial, 128-bit file ID, final handle path, requested path, and size. Reparse
|
||||
paths, alternate streams, ambiguous coordinates, UNC paths, and other
|
||||
filesystems are rejected with the actual constraint.
|
||||
|
||||
@@ -60,6 +60,48 @@ Evidence. `build_call_path.functions` also accepts retained references to the
|
||||
complete dossiers. Request `detail: "complete"` only when the record must travel
|
||||
inline.
|
||||
|
||||
The `inspect_analysis_view` description gives common call shapes rather than an
|
||||
exhaustive second catalog of view families. Follow the producing tool's named
|
||||
view kind and selector handoff. A summary's `normalized_result.parent_evidence_id`
|
||||
names the complete parent, not the summary record itself. Preserve that ID and
|
||||
the source discriminator:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"kind": "retained-evidence",
|
||||
"evidence_id": "ev_<parent digest>"
|
||||
},
|
||||
"view": {
|
||||
"kind": "native",
|
||||
"facet": "pseudocode",
|
||||
"offset": 0,
|
||||
"limit": 128
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The same source form works for a compatible inventory occurrence page with
|
||||
`view: {"kind":"inventory","collection":"occurrences","offset":0,"limit":64}`,
|
||||
a saved network record page with
|
||||
`view: {"kind":"capture","detail":"preview","offset":0,"limit":20}`, or a
|
||||
managed method page with
|
||||
`view: {"kind":"managed-members","collection":"methods","offset":0,"limit":64}`.
|
||||
`view: {"kind":"summary"}` has no facet. These are examples, not all supported
|
||||
families; use the producer and its guide for collection-specific fields and
|
||||
selection. The full input schema exposes accepted variants, while the default
|
||||
compact profile can omit nested shapes and parameter descriptions. Refreshing
|
||||
the same compact catalog does not restore those missing shapes; do not invent
|
||||
selectors from an opaque object declaration.
|
||||
|
||||
Text pages use UTF-16 code units; row pages count the selected retained
|
||||
collection. Source coverage and retained-page coverage remain distinct. A
|
||||
source's null or unavailable collection stays unknown, while an exhausted
|
||||
partial inventory does not prove that unexamined branches contain no matches.
|
||||
Likewise, a returned text page does not establish the whole parent's length
|
||||
unless the result reports that extent or exhaustion. Paging reuses completed
|
||||
Evidence and does not establish current live state.
|
||||
|
||||
Saved records from the pre-6.6 identity projection that omitted
|
||||
`relationship_coverage: null` from its digest remain incompatible, even when
|
||||
the serialized field is present. REA recognizes that exact previous commitment
|
||||
@@ -180,7 +222,7 @@ cannot answer, such as an address without one exact file offset, omits this
|
||||
hint; follow its `remediation.action`. `recovery.kind=inspect_timeout_state` names
|
||||
the operation and the REA server/provider deadline. Inspect partial Evidence
|
||||
and reported cleanup state, then follow the returned remediation. Change a
|
||||
request field or REA_* setting only when the returned remediation explicitly
|
||||
request field or REA\_\* setting only when the returned remediation explicitly
|
||||
recommends that change. Restart REA when that text says the value is read at
|
||||
startup. A mention that a control does not raise the deadline is not a
|
||||
recommendation to change it. When it names no setting, reduce supported work;
|
||||
@@ -576,13 +618,23 @@ batch-workload limit tracked in issue #5930.
|
||||
|
||||
### Error recovery and deadline ownership
|
||||
|
||||
Initialization instructions and the static JavaScript tool description teach
|
||||
recovery before a host can discard a tool response. Invalid input calls should be corrected from the connected schema
|
||||
Initialization instructions retain the deadline distinction before a host can
|
||||
discard a tool response; detailed recovery stays with the failure that owns it.
|
||||
Invalid input calls should be corrected from the connected schema
|
||||
(refresh `tools/list` only if stale), not retried unchanged. REA's returned
|
||||
`provider_timeout` describes its server/provider deadline; provider-authored
|
||||
remediation names the applicable controls and preserves partial Evidence and
|
||||
cleanup uncertainty.
|
||||
|
||||
An unresolved symbol lookup is a valid result, not a malformed request. It does
|
||||
not establish that a reference search completed or that the binary lacks the
|
||||
feature. Preserve the exact selector and the provider inventory's coverage.
|
||||
When remediation names an editable setting and its bounds, call
|
||||
`update_analysis_settings` directly if advertised; inspecting those same bounds
|
||||
first is optional. Explicit per-call values override runtime defaults, so fix
|
||||
the selected argument when remediation identifies it. Runtime updates apply to
|
||||
new work and cannot release retained cleanup resources.
|
||||
|
||||
A host timeout without a REA result is different: execution and cleanup remain
|
||||
unknown. Increasing an advertised `analysis_timeout_ms` cannot fix a shorter
|
||||
client deadline. Configure the client's tool timeout with execution, cleanup
|
||||
@@ -1013,6 +1065,17 @@ from an older request does not override a newer outcome. Request deadlines and
|
||||
cancellations neither mark nor clear availability. A new provider client starts
|
||||
without these outcomes.
|
||||
|
||||
A `provider_missing` group may also list `alternatives`: advertised tools the
|
||||
current provider makes available for part of that operation's question. When
|
||||
the provider does not declare `next_address` or `prev_address`, they list
|
||||
whichever of `inspect_native_instruction`, `read_function_instructions` and
|
||||
`procedure_assembly` qualify. These answer instruction-level questions only:
|
||||
none navigates arbitrary analyzed objects such as data or addresses outside a
|
||||
procedure, and neither listing order nor address plus length proves executed
|
||||
control flow. Calling the missing operation returns `capability_unavailable`
|
||||
with the same tools in `details.alternatives` and a remediation stating each
|
||||
one's scope. Without a qualifying alternative, both keep their generic advice.
|
||||
|
||||
Standalone command operations (such as `inspect_with_objdump` and
|
||||
`execute_rizin_command`) similarly reflect observed executable launch failures:
|
||||
an unprobed executable is reported available; once a launch failure is observed,
|
||||
@@ -1186,6 +1249,11 @@ Binary-only operations and binary analysis snapshots do not apply in this
|
||||
session. `open_binary` can switch back to executable analysis, and
|
||||
`close_binary` retires either session kind.
|
||||
|
||||
Both open operations can retire the previous analysis provider. That cleanup
|
||||
can discard ephemeral Ghidra edits or save a configured checkpoint, so their
|
||||
advertised effects include filesystem writes and possible data loss. The
|
||||
resource readers remain read-only within the selected bundle.
|
||||
|
||||
`inspect_plist` requires an open binary or bundle-resource session. An explicit
|
||||
`path` selects a plist in that context and does not create a session;
|
||||
`binary_session` reports `target_required` while neither session is open.
|
||||
@@ -1854,13 +1922,10 @@ support for omitted historical values.
|
||||
known and differ. If only one value is known, storage comparison is unknown;
|
||||
when both are omitted, storage is not compared.
|
||||
|
||||
<!-- BEGIN:compare-artifacts:compared-format-metadata-kinds -->
|
||||
|
||||
`compare_artifacts` also compares the declarations in the `format_metadata`
|
||||
of UnityFS members (`unityfs-entry`), PyInstaller entries
|
||||
`compare_artifacts` also compares the declarations in the `format_metadata` of <!-- BEGIN:compare-artifacts:compared-format-metadata-kinds -->UnityFS members (`unityfs-entry`), PyInstaller entries
|
||||
(`pyinstaller-entry`), Node SEA members (`node-sea-entry`),
|
||||
ESP image segments (`esp-image-segment`), DfuSe elements (`dfuse-element`),
|
||||
ESP flash partitions (`esp-flash-partition`) and FIT images (`fit-image`);
|
||||
ESP flash partitions (`esp-flash-partition`) and FIT images (`fit-image`)<!-- END:compare-artifacts:compared-format-metadata-kinds -->;
|
||||
each format's guide names the compared fields. A changed declaration is a
|
||||
metadata change, including when content is unavailable. A declaration that
|
||||
only one side records, or that the other side records as another kind, is
|
||||
@@ -1871,11 +1936,11 @@ container or from caller options that identify the target, or repeat
|
||||
occurrence fields, except Godot PCK source paths, which
|
||||
[Godot PCK archives](../godot-pck.md) explains.
|
||||
|
||||
<!-- END:compare-artifacts:compared-format-metadata-kinds -->
|
||||
|
||||
Every occurrence records `entry_kind`, `executable` and `encrypted`. A
|
||||
different entry kind, `encrypted` value or occurrence limitation text is a
|
||||
`metadata` difference, and a different `executable` value is an `executable`
|
||||
different entry kind or `encrypted` value is a `metadata` difference, and a
|
||||
different `executable` value is an `executable` difference. Occurrence and node
|
||||
limitation text describes diagnostic caveats, which remain in the source
|
||||
inventories; changing those caveats alone does not create a `metadata`
|
||||
difference. A symlink's own permission bits never mark it `executable`,
|
||||
because running a symlink runs its target. When either side's content is
|
||||
unavailable, `compare_artifacts` lists the differences that it can still
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# Release exposure
|
||||
|
||||
`audit_release_exposure` / `audit-release-exposure` reads one shipped artifact and reports what static analysis of that artifact recovers. The input is a macOS `.app` bundle, an install directory, an ASAR, or a single executable. Each check has a stable id, a status, the observation behind that status, and fixed remediation text.
|
||||
|
||||
The report does not establish that an application is secure. A check that could not be completed is `unknown` or `not_assessed`, and those counts stay beside the findings. There is no pass verdict and no letter grade.
|
||||
|
||||
```bash
|
||||
rea audit-release-exposure /Applications/Example.app --json
|
||||
rea audit-release-exposure ./dist/MyApp.app --fail_on high --json
|
||||
```
|
||||
|
||||
Without `--fail_on`, the exit status reflects only whether the audit finished. With `--fail_on high`, `--fail_on medium`, or `--fail_on low`, a completed audit exits `3` when an `exposed` check meets that severity. `high` matches high. `medium` matches high and medium. `low` matches high, medium, and low. `unknown` and `not_assessed` do not change the exit status. A tool failure is still exit `1`.
|
||||
|
||||
The CLI resolves a relative path against the caller's working directory. MCP requires an absolute filesystem path and returns the same report. MCP has no exit status.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "audit_release_exposure",
|
||||
"arguments": { "path": "/Applications/Example.app" }
|
||||
}
|
||||
```
|
||||
|
||||
## What is read
|
||||
|
||||
The audit composes existing readers. It does not reread Electron fuse bytes itself, and it does not rewrite the artifact.
|
||||
|
||||
| Check | Exposed when | Severity |
|
||||
| ------------------------------- | ------------------------------------------------------------------------------ | -------- |
|
||||
| `javascript.source_map_sources` | A shipped source map has `sourcesContent` | high |
|
||||
| `javascript.source_maps` | A shipped source map has no embedded sources | medium |
|
||||
| `electron.run_as_node` | The fuse implication is honored | high |
|
||||
| `electron.asar_integrity` | Embedded ASAR integrity is not enforced | medium |
|
||||
| `electron.only_load_from_asar` | Loading is not restricted to `app.asar` | medium |
|
||||
| `electron.node_cli_inspect` | Node CLI inspect arguments are honored | medium |
|
||||
| `packaging.extractable_payload` | A Bun, Deno, Node SEA, PyInstaller, .NET bundle, or ASAR has a readable member | low |
|
||||
| `native.debug_companions` | A `.pdb`, `.dSYM`, `.debug`, or linker `.map` ships beside the release | medium |
|
||||
| `native.pdb_path` | A PE CodeView record names a PDB path | low |
|
||||
| `go.build_paths` | Go build info or its build flags contain file paths | low |
|
||||
| `rust.dependency_metadata` | cargo-auditable metadata is present | low |
|
||||
| `text.credential_markers` | A text member contains a provider-prefixed marker | high |
|
||||
| `native.hardening` | Not assessed in this audit | |
|
||||
| `macho.hardened_runtime` | Not assessed in this audit | |
|
||||
| `android.manifest` | Not assessed in this audit | |
|
||||
|
||||
`go.build_paths` reads a flag's arguments by the rules of the tool that takes them. A linker `-X` value is an application string, so a relative one is not a path. A rooted one cannot be told from a file path, so it is reported: `-X main.route=/api/v1` is sampled like `-X main.root=/srv/build`, because dropping both would miss the second.
|
||||
|
||||
`text.credential_markers` matches provider-prefixed forms such as a PEM private-key header and documented vendor token prefixes. The report contains the rule id and location only. Matched bytes, previews, lengths, and hashes of matched bytes are omitted.
|
||||
|
||||
`native.hardening`, `macho.hardened_runtime`, and `android.manifest` stay `not_assessed`. Their next probes are `inspect_binary_hardening`, `inspect_signature`, and `inspect_android_package`.
|
||||
|
||||
Source map text is counted and then dropped. A selected file is read through the stable artifact reader. Text and source-map members stay inside the allowances listed under `coverage.allowances`, and each kind has its own allowance, so binary members cannot use up the read that a later source map needs. Native images on disk are registered from inventory classification and are not limited to those allowances. Other files and package members are identified from a bounded header. The bytes a package member's text or map read returns decide before its name does, so a PE called `payload.js.map` is read as a PE. A header with no NUL byte, or one that starts with a UTF-16 byte order mark, is scanned as text, so names such as `.env.production`, `server.key`, and `credentials` do not depend on an extension list. UTF-16 without a byte order mark has NUL bytes and is not recognized this way. A member already known to be text, such as a script, is also scanned when it is UTF-8 holding a stray NUL. One whose header is at least an eighth NUL bytes is taken to be wide text. It is not decoded and is counted as skipped, as is UTF-32. A binary plist is decoded, so its strings, dictionary keys and data are scanned in whichever encoding each object uses. One that cannot be decoded still has its bytes scanned and is counted as skipped. A file whose header could not be read leaves `text.credential_markers` undecided. A packaged ELF, Mach-O, or PE image is read in full and written to a temporary copy, removed afterward, so it can be probed for an embedded package. All packaged images share one `max_file_bytes` allowance. An image that does not fit, or whose bytes cannot be read, is not probed and leaves member coverage `unknown`. A packaged PE is also read for its debug records. An SVG file is read for its scripts as an HTML file is. A script that an HTML file loads, or a Node SEA main script, is examined as a script whatever it is called, so a name such as `boot.map` does not make it a map, and an HTML file loaded this way is still examined as HTML. Its bytes still decide over that role: a `.map` or loaded script whose text parses as a source map, a JSON object with `version` and `mappings`, `sources`, or `sections`, is read as a source map, so `<script src="main.map">` pointing at a map with `sourcesContent` still reports `javascript.source_map_sources` exposed. One read before that HTML file, one that is not found, one at a location the audit cannot place, or one past the 1 MiB of resolved script paths the audit keeps (`MAX_RELEASE_EXPOSURE_SCRIPT_TARGET_BYTES`) leaves `javascript.source_map_sources` undecided. A `.map` read before the HTML file that loads it is not reported as a linker map. Skipped members are listed under `coverage.omitted`. When the selection is a file, the parent directory is listed up to a fixed entry allowance for sibling `.pdb`, `.dSYM`, `.debug`, and linker `.map` debug companions. A sibling source map that the selected file declares, such as `app.js.map`, or a sibling script that a selected HTML file loads, such as `app.js`, is not read as part of the artifact, so it leaves `javascript.source_map_sources` undecided.
|
||||
|
||||
Inventory stops at 65,536 entries or 2 GiB of hashed bytes, and member coverage then stays `unknown`. A packed ASAR member is read from the captured archive, whose digest must match inventory. An unpacked member is read from its `.unpacked` companion, so its full bytes must also match the digest inventory recorded for that member, and a companion replaced after inventory fails the audit as a changed artifact. That digest check stays inside the read allowance: a companion larger than the allowance is read only up to the allowance, is not hashed to its end, and is treated as over its allowance without a digest verification. A declared integrity value that disagrees with the bytes does not stop the audit, because signing an unpacked native module after packaging is routine. The contradiction is recorded in the limitations and the audit continues.
|
||||
|
||||
A member of a package that inventory did not expand is reported as the host file path followed by the member path, for example `/dist/app.dll/notes.txt`. Inventory-expanded members keep their path relative to the selection.
|
||||
|
||||
A package member skipped by a read allowance still counts as readable for `packaging.extractable_payload`, because the format stores it unencrypted. An encrypted member or one that failed to read counts as unreadable. A member that failed to read, such as a compressed `payload.json` whose stream does not inflate, also leaves member coverage `unknown` unless its package states what it is, because its name does not rule out a nested image or package.
|
||||
|
||||
A map read counts against the source-map allowance when it starts, so an oversized or unreadable `.map` uses a read as a parsed one does. A sibling `.map` beside a selected file spends the same allowance, after the selected artifact has been read, and past it only the bounded header is read. A sibling whose header can begin a JSON object is then counted as skipped. A sibling `.map` that a selected HTML file loads as a script, or whose header is an ELF, Mach-O, or PE image, is not a linker map. A `.map` too large to parse is a linker map when its header cannot begin a JSON object. A larger `.map` that begins as JSON, or that has a JavaScript name such as `app.js.map`, is counted as skipped. `native.debug_companions` identifies a companion from its name or from a `.map` body that is not a source map, so its `exposed` result has `inferred` confidence. A symlink with a companion name counts by that name, and its target is not read. A symlink named as a source map, script, HTML, SVG, or CSS file is counted as skipped, whatever it points at, because links are not followed and that name is all the audit knows of what it would load. The target can still be scanned as a member under its own name, where a name such as `payload` is not read for map directives.
|
||||
|
||||
## Status
|
||||
|
||||
`exposed` means the check's condition was observed. `not_observed` means that condition was absent in a completed scan. `not_applicable` means the check does not apply to this artifact, for example Electron fuses on an app bundle with no Electron Framework, or on a directory whose native images were all read and hold no fuse sentinel. `unknown` means the check could not be decided, including a directory with no ASAR layout where those reads are missing or incomplete (an `asar: false` Electron build has no ASAR to find), safe fuses from an incomplete inventory, an unopened packaged native image, or a dropped image when the sample did not read an executable named as the Electron host or every executable that could be it, a missing fuse sentinel on an Electron target, a universal binary with a slice that has no sentinel or an undecided fuse, a file that changed after inventory, Electron fuses on a selected ASAR (which does not include the executable that holds them), a PE inside a package that was too large to read, Go or Rust metadata on a native image stored inside a package, and Go or Rust metadata that was not present. Absence of that metadata is not proof the binary is something else. `not_assessed` means this audit did not run the check.
|
||||
|
||||
Cancellation during a Go, Rust, fuse, or desktop read returns a typed cancellation error. Its partial observation holds the report with completed facts, and checks whose readers did not run are `unknown`. Cancellation during the member scan returns the same typed cancellation error. Its partial observation holds the members examined before the cancellation, with member coverage `unknown` and a limitation saying the scan was cancelled. Cancellation before the scan can be assembled, such as during inventory, returns no partial report.
|
||||
|
||||
Severity is `null` unless the status is `exposed`.
|
||||
File diff suppressed because it is too large.
Load diff
@@ -96,6 +96,10 @@ Persistent command Evidence retains the caller-selected and resolved startup pat
|
||||
|
||||
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, whose output budget defaults to 16 MiB. Rizin debug startup waits 30000 ms with no runtime override. Each command frame defaults to 120000 ms; its deadline, command-output budget, session capacity and pending-command queue use the [shared debugger launch settings](#debugger-launch-settings). The 16777216-byte frame cap and 4096-frame command cap remain fixed. Evidence names the cap that stopped the command. The one-shot `command_timeout_ms` setting does not change a debug session.
|
||||
|
||||
### Stopped debugger sessions
|
||||
|
||||
A Rizin or GDB session stops accepting commands when REA stops it, for example after an output or frame limit, a command deadline, cancellation or a protocol failure, or when the debugger process exits. REA keeps the stopped session and the first reason it observed until `close_rizin_debug_session` or `close_gdb_session` releases it, including after a retried cleanup succeeds. `rizin_debug_session_status` and `gdb_session_status` then report `state: "closed"` with that reason in `closed_reason`. A later `rizin_debug_command` or `gdb_console` on the session fails with `capability_unavailable`; `details.reason` carries the same reason, and the remediation is to close the session and start a new one. A `session_id` that this server never returned, or that close already released, fails with `invalid_request` instead.
|
||||
|
||||
### Debugger launch settings
|
||||
|
||||
GDB and Rizin share these settings in the environment that launches REA:
|
||||
@@ -107,10 +111,13 @@ GDB and Rizin share these settings in the environment that launches REA:
|
||||
| `REA_DEBUGGER_MAX_SESSIONS` | 8 | 1 to 64 |
|
||||
| `REA_DEBUGGER_MAX_PENDING_COMMANDS` | 16 | 1 to 256 |
|
||||
|
||||
Unset settings keep the defaults. Invalid selections fail configuration instead
|
||||
of falling back. Restart REA after changing its launch environment; these are
|
||||
not `update_analysis_settings` options. For MCP, set the values in the client's
|
||||
REA registration and restart that server.
|
||||
Unset settings keep the defaults. Invalid values are refused when the setting
|
||||
is used instead of falling back. Change the command deadline and output budget
|
||||
for subsequent operations with `update_analysis_settings` using
|
||||
`debugger.command_deadline_ms` and `debugger.max_command_output_bytes`. Session
|
||||
and pending-command capacities require a restart. To change the launch values,
|
||||
update REA's environment and restart; for MCP, edit the client registration and
|
||||
restart that server.
|
||||
|
||||
These settings also apply to one-shot `rea debug-with-gdb` and
|
||||
`rea debug-with-rizin` commands. They do not change the fixed initial-prompt
|
||||
@@ -133,6 +140,8 @@ rea debug-with-rizin --inferior-tty /dev/pts/7 ./program dr
|
||||
rea execute-rizin-command ./program iI
|
||||
```
|
||||
|
||||
Rizin exits with status 0 even when its shell refuses a statement, so the exit code does not show whether the command ran. Rizin 0.6 through 0.9.1 log one of four stderr lines for such a refusal: `ERROR: Command '…' does not exist.`, ``ERROR: Wrong number of arguments passed to `…`…``, `ERROR: core: Error while executing command: …` (an invalid statement), or `ERROR: core: Error while parsing command: …`. Rizin then skips the refused statement and every later one in the command. When the completed process's stderr contains one of these lines, REA reports `completion_status: "rejected"` and adds a limitation naming the refusal. stdout then holds only the output of earlier statements, so empty stdout is not an empty result. Other `ERROR:` lines, such as `ERROR: Cannot find function at …`, come from commands that ran; REA keeps them in stderr and reports `complete`. A command that lowers `log.level` or redirects stderr hides refusals from REA.
|
||||
|
||||
Captured stdout and stderr use the same `max_output_bytes` (CLI: `--max-output-bytes`) admission and recovery described above, default 16 MiB. One-shot commands independently use `command_timeout_ms`. Raising output admission cannot recover an earlier capture; command effects and cleanup must be checked before another invocation.
|
||||
|
||||
### Decoder and map inputs
|
||||
|
||||
@@ -26,9 +26,12 @@ for new work, roadmap granularity and producer-owned contracts.
|
||||
- [Native call source coordinates](native/call-source-locations/spec.md) ([plan](native/call-source-locations/plan.md), [tasks](native/call-source-locations/tasks.md), [verification](native/call-source-locations/verification.md))
|
||||
- [Go static string-header literal recovery](native/go-string-literals/spec.md) ([plan](native/go-string-literals/plan.md), [tasks](native/go-string-literals/tasks.md))
|
||||
- [Windows Shell Link shortcut inspection](native/windows-shortcut/spec.md) ([plan](native/windows-shortcut/plan.md), [tasks](native/windows-shortcut/tasks.md))
|
||||
- [NTFS $MFT and USN Journal inspection](native/ntfs-mft/spec.md) ([plan](native/ntfs-mft/plan.md), [tasks](native/ntfs-mft/tasks.md))
|
||||
- [Solidity terminal metadata inspection](solidity/cbor-metadata/spec.md) ([plan](solidity/cbor-metadata/plan.md), [tasks](solidity/cbor-metadata/tasks.md), [verification](solidity/cbor-metadata/verification.md))
|
||||
- [Inspect a V8 code cache container](v8/code-cache-inspection/spec.md) ([plan](v8/code-cache-inspection/plan.md), [tasks](v8/code-cache-inspection/tasks.md))
|
||||
- [Deno compile executable inventory and extraction](artifacts/deno-standalone/spec.md) ([plan](artifacts/deno-standalone/plan.md), [tasks](artifacts/deno-standalone/tasks.md))
|
||||
- [ELF unwind function ranges](native/elf-unwind-ranges/spec.md) ([plan](native/elf-unwind-ranges/plan.md), [tasks](native/elf-unwind-ranges/tasks.md))
|
||||
- [Linux kernel build config](native/kernel-build-config/spec.md) ([plan](native/kernel-build-config/plan.md), [tasks](native/kernel-build-config/tasks.md))
|
||||
- [Native initializers](native/native-initializers/spec.md) ([plan](native/native-initializers/plan.md), [tasks](native/native-initializers/tasks.md))
|
||||
|
||||
- [Release exposure audit](artifacts/release-exposure/spec.md) ([plan](artifacts/release-exposure/plan.md), [tasks](artifacts/release-exposure/tasks.md))
|
||||
@@ -7,7 +7,8 @@
|
||||
3. Runtime: read the response body when a step saves, start waiting for a UI
|
||||
step's response before it acts, keep saved values with their JSON type,
|
||||
fill placeholders, build Basic credentials, and redact secret saves.
|
||||
4. Evidence: leave an empty `save` out of the recorded step.
|
||||
4. Evidence: record the current parsed step, including an empty `save` list;
|
||||
preserve the representation and identity of retained Evidence.
|
||||
5. Environment build: warn about credential-named saved values not marked
|
||||
secret.
|
||||
6. Skill and docs: write through the UI first and save ids instead of guessing
|
||||
|
||||
@@ -47,10 +47,9 @@ values.
|
||||
- A value saved with `secret: true` is redacted from the selected source response
|
||||
before retention and from subsequent records. The environment build warns about saved values named like credentials
|
||||
that are not marked secret (`credential-named-saved-values`).
|
||||
- A scenario that saves nothing records the same Evidence parameters and
|
||||
`scenario_sha256` as before: an empty `save` is left out of the recorded
|
||||
step.
|
||||
- Earlier REA versions read captures that use saved values.
|
||||
- New Evidence records the current parsed request step, including an empty
|
||||
`save` list, in its parameters and `scenario_sha256`. Retained Evidence keeps
|
||||
its original representation and identity.
|
||||
- The compact MCP catalog stays under its measured one-megabyte frame.
|
||||
- The skill records writes the way the application's UI does and falls back to
|
||||
request steps when the UI cannot reach an operation or coverage withholds the
|
||||
|
||||
@@ -58,15 +58,9 @@ that initially failed to reserve complete Evidence wrapper depth.
|
||||
|
||||
The subsequent review fixes passed all 50 tests across six compiled acceptance,
|
||||
CLI, MCP and emitted-Python boundary files. Typecheck and lint also passed after
|
||||
those fixes. Default calibration records its separate measurements and
|
||||
limitations in the [Flutter](../../../verification/flutter-budget-calibration.md)
|
||||
and [source-map](../../../verification/source-map-budget-calibration.md) reports;
|
||||
those measurements are not native-provider verification.
|
||||
The calibrated source-map default and explicit smaller-budget recovery passed
|
||||
those fixes. The source-map default and explicit smaller-budget recovery passed
|
||||
all six compiled source-location CLI tests. The final formatting, type/lint,
|
||||
generated-documentation and README consistency checks passed. The observer's
|
||||
completed, timeout, surviving-child and signal-refusal controls retained
|
||||
receipts and confirmed empty process groups.
|
||||
generated-documentation and README consistency checks passed.
|
||||
|
||||
The final follow-up adds per-call artifact admission, limited recognition,
|
||||
shipped-seed policy agreement, bounded SQLite views and retained source-location
|
||||
@@ -78,12 +72,7 @@ and compact schema profiles with same-session lower/raise/lower admission.
|
||||
The final SQLite worker/emitted-reader checks passed all four scenarios. These
|
||||
are separate executed runs, not an aggregate unique-test count.
|
||||
|
||||
The [source-location delivery qualification](../../../verification/source-location-delivery.md)
|
||||
retains 18 successful public MCP measurements with matching parent IDs, exact
|
||||
mapping/snippet oracles and process-tree samples. The
|
||||
[JavaScript precision calibration](../../../verification/javascript-precision-calibration.md)
|
||||
retains 12 real CLI runs supporting unchanged numeric defaults for that narrow
|
||||
corpus. Native capture qualification and the live same-Program Ghidra receipt
|
||||
Native capture qualification and the live same-Program Ghidra receipt
|
||||
are linked from the [runtime verification report](../../../verification/runtime-analysis-settings.md).
|
||||
The Python gate passed all 102 tests; architecture guards passed across 2,571
|
||||
source files. Formatting, type/lint, generated docs, README consistency and
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# Implementation plan
|
||||
|
||||
## Boundary and contract
|
||||
|
||||
`src/domain/releaseExposure.ts` owns the report schema, check ids, statuses,
|
||||
severities and read allowances. `src/domain/releaseExposureCredentialMarkers.ts`
|
||||
owns the provider-prefixed marker rules. `src/artifacts/ReleaseExposureReader.ts`
|
||||
owns the bounded scan of the selected artifact and its members.
|
||||
`src/application/releaseExposure/ReleaseExposureService.ts` composes the existing
|
||||
owners through `ReleaseExposurePort` and decides each check from their results.
|
||||
`src/contracts/releaseExposureToolContracts.ts`, `src/cli/releaseExposureCommands.ts`
|
||||
and `src/server/registerReleaseExposureTool.ts` are thin adapters over the same
|
||||
service.
|
||||
|
||||
## Changes to existing owners
|
||||
|
||||
- `inventoryArtifact` gains optional `acquisitionLimits`. Only this audit sets
|
||||
them. Exhausting one keeps a partial inventory with unknown coverage. Other
|
||||
callers are unchanged.
|
||||
- `src/domain/binaryTarget.ts` adds `inspectPeCodeViewFromBuffer`, which
|
||||
separates absent CodeView records from incomplete parsing.
|
||||
`parsePeCodeViewFromBuffer` keeps its behavior on top of it.
|
||||
- `src/artifacts/inventory/classify.ts` exports
|
||||
`classifyEmbeddedExecutablePackage`, so the audit recognizes a packaged
|
||||
executable with the same probes as inventory.
|
||||
- Declared integrity uses `record-and-continue` for this audit only.
|
||||
|
||||
## Change detection
|
||||
|
||||
Every file read is bound to its inventoried digest. A file or container whose
|
||||
bytes differ from inventory at read time adds a change diagnostic and leaves the
|
||||
affected checks `unknown`. An unpacked ASAR member is read from its companion
|
||||
on disk rather than the captured archive, so its bytes are compared with the
|
||||
member digest that inventory recorded, and findings cannot mix an inventoried
|
||||
release with bytes written later. Native images carry their
|
||||
inventory digest into the Go, Rust and fuse reads.
|
||||
|
||||
## Effects and compatibility
|
||||
|
||||
The tool is read-only, local and additive to the CLI and MCP catalogs. It adds no
|
||||
provider and no runtime dependency. `verify:release-exposure` installs
|
||||
`@electron/fuses` into a temporary prefix when it runs.
|
||||
@@ -0,0 +1,75 @@
|
||||
# Release exposure audit
|
||||
|
||||
Pull request: https://github.com/morluto/rea/pull/8525
|
||||
|
||||
## Problem and outcome
|
||||
|
||||
REA can show what static analysis recovers from a shipped application, but a
|
||||
developer who wants that answer for their own release has to run several tools
|
||||
and combine the results by hand. Add one read-only audit that reads a single
|
||||
shipped artifact through the existing readers and reports, per named check,
|
||||
what was observed, so a team can review or gate a release before it ships.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Accept one local `.app` bundle, install directory, ASAR or single executable
|
||||
through `audit_release_exposure` (MCP, absolute path) and
|
||||
`rea audit-release-exposure` (CLI, path resolved against the caller's working
|
||||
directory). Both adapters return the same report.
|
||||
- Report a fixed set of checks, each with a stable id, a status of `exposed`,
|
||||
`not_observed`, `not_applicable`, `unknown` or `not_assessed`, the observation
|
||||
behind it, its locations and fixed remediation text. Severity is `null` unless
|
||||
the status is `exposed`.
|
||||
- Report no pass verdict, score or grade. The report states that it does not
|
||||
establish that an application is secure, and `unknown` and `not_assessed`
|
||||
counts stay beside the findings.
|
||||
- Compose existing owners: artifact inventory, Electron fuses, Go build info,
|
||||
cargo-auditable metadata, PE CodeView, embedded package classification and
|
||||
source-map parsing. Do not reimplement their parsing.
|
||||
- Never execute, modify or rewrite the artifact, and make no network request.
|
||||
- Bound every read. Inventory stops at 65,536 entries or 2 GiB of hashed bytes.
|
||||
Text, source-map and packaged-image reads have separate allowances reported
|
||||
under `coverage.allowances`; skipped members are listed under
|
||||
`coverage.omitted`. An exhausted bound leaves the affected checks `unknown`.
|
||||
An unpacked ASAR companion is compared with its inventoried digest only when
|
||||
it ends within the read allowance; one past the allowance is not read further
|
||||
to finish the digest and stays over its allowance, unverified.
|
||||
- Fail toward `unknown`: a read that could not be completed, a file or member
|
||||
whose bytes no longer match the inventoried digest, an unresolved or oversized
|
||||
source map, or missing metadata never becomes `not_observed`.
|
||||
- For `text.credential_markers`, report the rule id and location only. Matched
|
||||
bytes, previews, lengths and hashes of matched bytes are omitted. Source-map
|
||||
text is counted and then dropped.
|
||||
- Without `--fail_on`, the CLI exit status reflects only whether the audit
|
||||
finished. With `--fail_on high|medium|low`, a completed audit exits `3` when an
|
||||
`exposed` check meets that severity. A tool failure exits `1`.
|
||||
- A declared integrity value that disagrees with the bytes is recorded as a
|
||||
limitation and the audit continues.
|
||||
- Cancellation during a composed owner returns the typed cancellation error with
|
||||
the partial report attached.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- Domain tests cover status aggregation, severity, `--fail_on` thresholds and the
|
||||
absence of a verdict.
|
||||
- Reader tests cover source maps with and without `sourcesContent`, inline
|
||||
`data:` maps, HTML and SVG script loading, debug companions, credential markers
|
||||
in text members and binary plists, UTF-16 and NUL handling, read allowances,
|
||||
same-name package members, packaged native images and changed bytes after
|
||||
inventory, including an unpacked ASAR companion replaced after inventory and
|
||||
an oversized companion that is not read past its allowance.
|
||||
- Service tests cover Electron fuse decisions, Go and Rust metadata, partial
|
||||
inventory and cancellation with a partial report.
|
||||
- CLI and MCP return the same report; `--max-file-bytes` accepts the documented
|
||||
decimal token form.
|
||||
- `npm run verify:release-exposure` audits real fixtures, recorded in
|
||||
[the verification record](../../../verification/release-exposure-2026-10-31.md).
|
||||
- The [release exposure guide](../../../release-exposure.md) documents current
|
||||
behavior and limitations.
|
||||
|
||||
## Non-goals
|
||||
|
||||
Obfuscation, stripping, signing, active protection, modifying the artifact,
|
||||
running the target, network calls and a security verdict. `native.hardening`,
|
||||
`macho.hardened_runtime` and `android.manifest` stay `not_assessed` and name
|
||||
their next probes instead.
|
||||
@@ -0,0 +1,10 @@
|
||||
# Tasks
|
||||
|
||||
- [x] Define the report contract, checks, statuses and read allowances (FR: report, bounds).
|
||||
- [x] Add the bounded reader and the service that composes existing owners (FR: compose, fail toward unknown).
|
||||
- [x] Add CLI and MCP adapters with `--fail_on` exit status 3 (FR: exit status).
|
||||
- [x] Add domain, reader and service tests listed under acceptance.
|
||||
- [x] Verify real fixtures with `npm run verify:release-exposure`.
|
||||
- [x] Document current behavior in the release exposure guide.
|
||||
- [x] Accept decimal `--max-file-bytes` tokens through `cliDecimalField`.
|
||||
- [x] Bind unpacked ASAR member reads to their inventoried digests.
|
||||
@@ -10,8 +10,8 @@
|
||||
4. Verifier: `appTaskPython.ts` renders `READER_RUNNER`, `READERS`,
|
||||
`_reader_views` and `evaluate_with_readers` only for a task with readers,
|
||||
so a task without renders as before.
|
||||
5. Application: `readTaskReaderViews` and `readerViewsOfBytes` in
|
||||
`DesktopTaskReaders.ts`; `runReaderHere` in `src/desktop/TaskReaderProcess.ts`;
|
||||
5. Application: `readerViewsOfBytes` in `DesktopTaskReaders.ts`;
|
||||
`runReaderHere` in `src/desktop/TaskReaderProcess.ts`;
|
||||
the witness runs readers through `AgentEnvComputer.exec`; the export runs
|
||||
them on `shippedSeedBytes` and the end's retained content.
|
||||
6. Docs: the tasks reference, the witness page, the build skill's recipes for
|
||||
|
||||
@@ -26,7 +26,10 @@ these files.
|
||||
read through the stable artifact read and never executed.
|
||||
2. The banner is the first printable `Linux version ` string followed by a
|
||||
version token that starts with a digit and ends at a NUL or newline within
|
||||
512 bytes. Version, builder and compiler are split from it. The scan is
|
||||
512 bytes. Version, builder and compiler are split from it. A banner with a
|
||||
space right after `#` or at its end is the kbuild placeholder from
|
||||
`init/version.o`, built without a build number or timestamp; a later banner
|
||||
that repeats its text up to `#` without that gap replaces it. The scan is
|
||||
linear in the searched bytes.
|
||||
3. A config is `present` only when `IKCFG_ST` is followed by a gzip member that
|
||||
ends exactly at the next `IKCFG_ED`, inflates within `max_config_bytes`,
|
||||
|
||||
@@ -32,7 +32,14 @@ slot's location, resolved target and how that target was obtained. The
|
||||
Thumb bit is cleared for target section and file-offset lookup only. A slot with no
|
||||
relocation found is `unresolved` when a dynamic table, or a section table
|
||||
that could reach it, was not fully read; such a `.ctors` slot is not dropped
|
||||
as a sentinel. A linked image's non-`SHF_ALLOC` relocation sections were
|
||||
as a sentinel. A `COPY` relocation covers the bytes of its symbol's size and
|
||||
a TLS descriptor two words. The size comes from the dynamic symbol table for
|
||||
a dynamic record and from the table's linked symbols for a section record of
|
||||
a linked image; an unread size leaves coverage unknown. A linked image's
|
||||
section record that writes memory with no file bytes covers only the slots
|
||||
it overlaps there when its extent is established, by a fixed width or a
|
||||
`COPY` size, and otherwise leaves its table not fully read. A
|
||||
linked image's non-`SHF_ALLOC` relocation sections were
|
||||
applied at link time and are not reapplied. A Mach-O stored pointer word is
|
||||
used only when no undecoded bind stream or external relocation could
|
||||
replace it.
|
||||
@@ -74,8 +81,10 @@ ELF32 REL in-place addends, `ET_REL` section relocations and sentinels,
|
||||
unsupported relocation machines, slot, symbol and relocation budgets,
|
||||
over-long names, tallied repeated observations, a near-maximal section table
|
||||
with a full slot budget, cancellation in the relocation walks, skipped section
|
||||
relocation tables, partly overwritten slots, retained link-time relocations,
|
||||
unreadable names, Mach-O chained fixups, `LC_DYLD_INFO` rebases, 32-bit images
|
||||
relocation tables, partly overwritten slots, `COPY` and TLS descriptor extents,
|
||||
section `COPY` records sized by their symbol, section records that write
|
||||
memory without file bytes, retained link-time
|
||||
relocations, unreadable names, Mach-O chained fixups, `LC_DYLD_INFO` rebases, 32-bit images
|
||||
with undecoded binds, `MH_OBJECT` section relocations, `__init_offsets`, the
|
||||
shared and repeated `LC_SYMTAB` budget, and universal slices. CLI acceptance, filesystem boundary
|
||||
and MCP boundary tests exercise the public workflows and Evidence output.
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# Implementation plan
|
||||
|
||||
## Boundary and contract
|
||||
|
||||
Follow the existing artifact readers. `src/domain/windows/ntfsMft.ts` owns FILE
|
||||
record bytes and coverage; `src/domain/artifactFormatMetadata.ts` owns the
|
||||
`ntfs-mft` result schema. `ntfsMftAttributes.ts` owns verified attribute
|
||||
values and descriptor contracts. Journal joins retain an ordered identity/header
|
||||
index and its reference lookup per validated acquisition pair. MFT detail pages
|
||||
select at most 32 records from this index and decode only their retained source
|
||||
bytes; page selection never triggers a new whole-MFT scan. `NtfsMftArtifactReader` reads the admitted file
|
||||
through `ArtifactFileSource` and exposes its facts through `formatMetadata()`.
|
||||
A record stream is its own content, so the root occurrence carries every fact
|
||||
and no members are enumerated.
|
||||
|
||||
Recognition lives in `hasMftFileRecordSignature` and is applied in
|
||||
`classifyArtifactBytes`, next to the other unambiguous magic probes.
|
||||
|
||||
## Incremental work and validation
|
||||
|
||||
1. Define the first-step contract, limits and observations; add parser fixtures.
|
||||
2. Implement the FILE record header and update-sequence fixup parse with
|
||||
explicit limitations.
|
||||
3. Add the reader, format descriptor and byte classification.
|
||||
4. Decode attribute records, then `$FILE_NAME` attributes so a record's parent
|
||||
reference, names and timestamps become explicit; keep hard links separate.
|
||||
5. Parse `$UsnJrnl:$J` records and correlate them to records by full file
|
||||
reference, including sequence numbers, reporting unresolved references.
|
||||
6. Document the workflow in a native Windows artifact guide.
|
||||
|
||||
## Effects and compatibility
|
||||
|
||||
The inventory reads one caller-selected MFT file; the journal workflow reads
|
||||
the explicitly paired MFT and journal files. It adds no target execution,
|
||||
injection, mutation, protection recovery, network access, volume mount or live
|
||||
filesystem access, so no maintainer scope decision is required.
|
||||
`inspect_artifact` routing for every existing format is unchanged, and the new
|
||||
format id appears only for bytes whose first record carries the `FILE`
|
||||
signature.
|
||||
|
||||
## References
|
||||
|
||||
- https://learn.microsoft.com/en-us/windows/win32/fileio/master-file-table
|
||||
- https://github.com/libyal/libfsntfs/blob/main/documentation/New%20Technologies%20File%20System%20(NTFS).asciidoc
|
||||
|
||||
Current analyst behavior and limitations live in the
|
||||
[NTFS guide](../../../guides/native/ntfs-metadata.md).
|
||||
|
||||
## Acquired extension metadata
|
||||
|
||||
The MFT owner resolves attribute-list graphs for selected base records, using
|
||||
its existing verified record decoder and a page-local cache. The scanner's
|
||||
bounded sample and the journal's independent detail projection share this rule.
|
||||
The acquisition cache continues retaining only headers and raw validated bytes.
|
||||
Typed reference outcomes and linked attribute/name schemas belong to
|
||||
`ntfsMftAttributes.ts` and are consumed by the common metadata contract. Global
|
||||
physical counts stay independent of bounded reference delivery.
|
||||
|
||||
A page decodes at most 32 additional records beyond its selected physical
|
||||
records. Each base emits at most 32 reference results, retaining source list
|
||||
entries and explicit discovered omissions. This adds no volume reads, path
|
||||
reconstruction, nonresident payload recovery or target execution. Real extension
|
||||
captures and Windows-host execution remain unverified; source-built fixtures
|
||||
exercise reference ownership, malformed prefixes, cycles and resource bounds.
|
||||
|
||||
Journal and extension joins share `hasVerifiedMftRecordIdentity` at the MFT
|
||||
owner. It consumes parsed sequence, slot verdict, extent and fixup facts; each
|
||||
consumer keeps its separate base-versus-extension ownership rule.
|
||||
@@ -0,0 +1,93 @@
|
||||
# NTFS $MFT and USN Journal inspection
|
||||
|
||||
This specification records an implementation increment and its original problem
|
||||
statement. For current behavior and limitations, see the
|
||||
[NTFS workflow guide](../../../guides/native/ntfs-metadata.md).
|
||||
|
||||
## Problem and outcome
|
||||
|
||||
REA has no reader for acquired NTFS metadata artifacts. An analyst holding a
|
||||
captured `$MFT` stream cannot ask which FILE records it contains, whether their
|
||||
update-sequence fixups survived acquisition, or which records are directories,
|
||||
extensions of another record, or no longer in use. Add offline, read-only
|
||||
inventory of a selected `$MFT` file, delivered in steps so each one merges on
|
||||
its own.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Recognize a `$MFT` stream by a plausible first `FILE` record header under
|
||||
any file name. CLI and MCP target admission route it to the artifact reader.
|
||||
- Validate each FILE record header: the `FILE` signature, sequence number, flags,
|
||||
used and total byte counts, base record reference, and the update-sequence
|
||||
array's offset, count and array bounds.
|
||||
- Verify the update-sequence fixups: every sector trailer the array covers must
|
||||
hold the array's sequence number. A mismatch keeps the record's header facts
|
||||
and is reported per record and in the metadata count.
|
||||
- Report a missing, misplaced or short update-sequence array as unverified
|
||||
rather than as a clean record, and a trailing partial record as a byte count.
|
||||
- Report the first invalid record signature and the number of invalid slots.
|
||||
Continue at the next slot when the stream declared a supported record size.
|
||||
With a fallback record size, stop at the first invalid signature.
|
||||
- Bound the whole file at a fixed 512 MiB ceiling and report the ceiling as a
|
||||
`limit` failure with its boundary.
|
||||
- Return the first 32 decoded record headers with their source offsets and the
|
||||
number of omitted headers. Aggregate counts cover the full parsed stream.
|
||||
- Restore verified sector trailers in a per-record scratch buffer before
|
||||
scanning attributes. The domain decoder retains resident `$FILE_NAME`
|
||||
names, namespaces, parent references and source offsets. Report incomplete
|
||||
coverage when the walk cannot finish or an attribute list may refer to
|
||||
extensions. The first 32 record samples expose individual names, parent
|
||||
references, namespaces, FILETIME values, sizes and attribute bits. Keep each
|
||||
name attribute separate, including multiple names for one record.
|
||||
|
||||
- Resolve a selected base record's resident attribute lists only within the
|
||||
supplied MFT. Require full sequence/slot identity, verified fixups, base
|
||||
ownership and exact attribute type/name/ID/VCN. Preserve physical and linked
|
||||
facts separately, including each source offset.
|
||||
- Share at most 32 additional record decodes per detail page, and deliver at
|
||||
most 32 reference results per base. Preserve discovered-entry omissions,
|
||||
unavailable list values, ambiguity and partial record facts. Visit list source
|
||||
identities once, including cyclic graphs. Nonresident volume payload recovery
|
||||
remains outside the acquired-metadata boundary.
|
||||
|
||||
## Acceptance
|
||||
|
||||
Synthesized fixtures cover a clean record, a failed fixup, a missing update
|
||||
sequence array, an array shorter than the record's sector count, extension and
|
||||
directory records, a record whose signature is wrong mid-stream, a trailing
|
||||
partial record, an undeclared record size, a 4 KiB record, a stream shorter than
|
||||
one header, bytes without the `FILE` signature, and the file-size ceiling.
|
||||
Inventory tests cover the root occurrence's metadata and the coverage status
|
||||
when a fixup fails, and classification tests cover several file names for the
|
||||
same bytes.
|
||||
|
||||
The paired acquisition workflow is available through
|
||||
`rea inspect-ntfs-journal ./mft ./journal --maxRows 50 --json` and MCP
|
||||
`inspect_ntfs_journal` with `mft_path` and `journal_path`. Select an acquired
|
||||
logical MFT stream and the journal data stream from the same volume. Each
|
||||
file has a 64 MiB working-set admission limit. Follow `nextFileOffset` as
|
||||
`start_file_offset` on MCP or `--startFileOffset` on CLI and compare the two
|
||||
input digests between pages.
|
||||
|
||||
USN V2, V3 and V4 records are supported. V3/V4 opaque IDs remain unresolved
|
||||
against MFT references; V4 delivers bounded extent samples with omission counts.
|
||||
Both the journal events and the MFT metadata have independent continuation
|
||||
positions. Padding, malformed records and truncation appear as coverage rows.
|
||||
Record order follows the acquisition, and history completeness remains unknown.
|
||||
|
||||
Automated CLI/MCP workflow tests use synthesized acquisitions. Real Windows 11 MFT
|
||||
records were inspected through the packaged Linux CLI; see the
|
||||
[verification record](../../../verification/ntfs-metadata-2026-11-11.md).
|
||||
Paired V2 streams from a public NTFS volume fixture also passed CLI/MCP
|
||||
verification against an independent parser. The fixture's original acquisition
|
||||
environment and Windows-host execution remain unverified.
|
||||
|
||||
## Page reuse lifetime
|
||||
|
||||
Use one MCP session for multi-page traversal. Its shared acquisition scope keeps
|
||||
one successful digest-bound pair and MFT/reference lookup, validates selected
|
||||
file state before each reuse, refuses changed/unverifiable sources, and clears
|
||||
retained data at scope shutdown or pair eviction. Failed acquisitions are not
|
||||
cached. Each fresh CLI process reacquires its inputs. See the
|
||||
[completed-task comparison](../../../verification/ntfs-journal-paging-2026-11-11.md)
|
||||
for measurements, lifecycle regressions and verification limits.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Tasks
|
||||
|
||||
- [x] Define the first-step scope, contract and limits.
|
||||
- [x] Parse FILE record headers and update-sequence fixups with synthesized
|
||||
fixtures and explicit limitations.
|
||||
- [x] Add the reader, format descriptor and byte classification.
|
||||
- [x] Decode attribute records, then `$FILE_NAME` attributes with parent
|
||||
references, names, hard links and timestamps.
|
||||
- [x] Parse `$UsnJrnl:$J` V2 records and correlate them by full file reference.
|
||||
- [x] Return a bounded source-order page through CLI and MCP, preserving both
|
||||
input digests and explicit coverage rows.
|
||||
- [x] Decode V3/V4 layouts, bound extent samples, and report unknown history coverage.
|
||||
- [x] Page MFT metadata independently of journal events.
|
||||
- [x] Decode resident standard information, attribute-list references and nonresident mapping metadata.
|
||||
- [x] Resolve resident attribute-list graphs into acquired extension metadata with full ownership checks, bounded decoding and explicit partial coverage.
|
||||
- [x] Verify Windows 11 MFT records through the packaged Linux CLI, with pinned provenance and digests.
|
||||
- [x] Verify paired logical MFT/journal streams from a public NTFS volume fixture on Linux against an independent parser.
|
||||
- [ ] Verify Windows-host execution.
|
||||
@@ -0,0 +1,234 @@
|
||||
# Windows ReFS Filesystem Authority Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Admit fixed local ReFS volumes through REA's existing Windows native authority while preserving NTFS behavior and every current security invariant.
|
||||
|
||||
**Architecture:** Extend the existing native admission owner instead of creating a ReFS backend. Record the observed filesystem on native `File`/`Runtime` owners and pass it through every identity projection, while the TypeScript contract accepts only the same two values. Prove the behavior with an independent Win32 volume observer and the existing full native and Ghidra verifiers on both filesystems.
|
||||
|
||||
**Tech Stack:** C++17 Win32/Node-API, TypeScript/Zod/Vitest, Node.js 24.22.1, WSL Ubuntu with MinGW-w64, real Windows NTFS/ReFS volumes and Ghidra 12.1.4.
|
||||
|
||||
**Spec:** [spec.md](spec.md)
|
||||
|
||||
## Global Constraints
|
||||
|
||||
- Accept only fixed local `NTFS` and `ReFS` volumes reporting `FILE_PERSISTENT_ACLS`; every other filesystem fails closed.
|
||||
- Preserve native ABI version `1` and the existing identity fields; only the filesystem value domain expands.
|
||||
- Do not weaken path, reparse, sharing, DACL, snapshot, cancellation, ownership or cleanup checks.
|
||||
- Use Node.js `24.22.1`; Windows and WSL have independent `node_modules` and work areas. Generated native artifacts remain uncommitted.
|
||||
- Do not claim a check that did not run. Do not mark the PR ready for the human owner and do not merge it.
|
||||
|
||||
## Review Focus
|
||||
|
||||
- Cross-volume snapshots: source and destination must retain different observed filesystem values rather than inheriting one global value; Task 2 asserts both.
|
||||
- Less visible identity producers: native inspection, `runtime_open` and Cutter bridge verification must use the same owner-recorded value; Task 2 asserts each.
|
||||
- Reparse and cleanup adversarial behavior on ReFS: Task 2 keeps the existing ancestor-conversion and cleanup-escape controls intact and runs them on both volumes.
|
||||
- Unsupported values and stale consumers: Task 1 rejects an unknown filesystem at the schema boundary, Task 2 keeps the native allowlist/ACL predicates, and Task 3 pins user-facing NTFS/ReFS wording.
|
||||
- Generated artifacts and package identity: Task 4 verifies the manifest, package contents, clean Git state and actual ReFS CLI scenario rather than relying on compilation alone.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Filesystem identity contract
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `src/windows/WindowsNativeLoader.ts`
|
||||
- Modify: `src/windows/WindowsNativeLoader.test.ts`
|
||||
|
||||
**Interfaces:**
|
||||
|
||||
- Consumes: the existing `WindowsNativeLoadHost` inspection fixture and `loadWindowsNativeAuthority`.
|
||||
- Produces: `windowsFileIdentitySchema.filesystem` accepting exactly `"NTFS" | "ReFS"`; unsupported values produce `failureStage: "inspection"`.
|
||||
|
||||
- [ ] **Step 1: Prepare isolated toolchains and establish a clean baseline**
|
||||
|
||||
Use `nvm install 24.22.1 && nvm use 24.22.1`, then `npm ci` and `npm run check:fast` in the Windows ReFS worktree and in a separate WSL clone. Do not share `node_modules` between them. Record any pre-existing failure instead of attributing it to this change.
|
||||
|
||||
- [ ] **Step 2: Write the failing ReFS contract tests**
|
||||
|
||||
Extend the test fixture's capability overrides with `filesystem?: string`, applied to its identity. Add:
|
||||
|
||||
```ts
|
||||
it.each(["NTFS", "ReFS"])("admits %s filesystem identities", (filesystem) => {
|
||||
const result = loadWindowsNativeAuthority(fixture({ filesystem }).host);
|
||||
expect(result).toMatchObject({
|
||||
available: true,
|
||||
authority: { inspection: { filesystem: { filesystem } } },
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects an unsupported filesystem identity", () => {
|
||||
expect(
|
||||
loadWindowsNativeAuthority(fixture({ filesystem: "exFAT" }).host),
|
||||
).toMatchObject({ available: false, failureStage: "inspection" });
|
||||
});
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Run the tests to verify the new ReFS case fails**
|
||||
|
||||
Run: `npm run test:focused -- src/windows/WindowsNativeLoader.test.ts`
|
||||
Expected: the ReFS case fails because `z.literal("NTFS")` rejects it; NTFS and exFAT controls retain their expected outcomes.
|
||||
|
||||
- [ ] **Step 4: Implement the minimal schema change**
|
||||
|
||||
Change the field to `z.enum(["NTFS", "ReFS"])` and update its identity comment to local NTFS/ReFS objects. Do not change the ABI constants or any other schema field.
|
||||
|
||||
- [ ] **Step 5: Verify and commit**
|
||||
|
||||
Run `npm run test:focused -- src/windows/WindowsNativeLoader.test.ts` and `npm run check:fast`; expect PASS. Commit:
|
||||
|
||||
```bash
|
||||
git add src/windows/WindowsNativeLoader.ts src/windows/WindowsNativeLoader.test.ts
|
||||
git commit -m "feat(native): admit ReFS filesystem identities"
|
||||
```
|
||||
|
||||
### Task 2: Native admission, owned identity and real-volume verification
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `native/windows/src/authority.hpp`
|
||||
- Modify: `native/windows/src/filesystem.cc`
|
||||
- Modify: `native/windows/src/process.cc`
|
||||
- Modify: `tests/fixtures/windows/processBoundary.cc`
|
||||
- Modify: `scripts/verify-windows-native.mjs`
|
||||
|
||||
**Interfaces:**
|
||||
|
||||
- Produces: `File.filesystem: std::wstring` and `Runtime.filesystem: std::wstring`, assigned at admission and inherited by handle-relative children.
|
||||
- Produces: `napi_value identity(napi_env env, HANDLE handle, const std::wstring& path, const std::wstring& filesystem)`.
|
||||
- Produces: `process-boundary.exe volume-semantics <volume-root>` returning `{"filesystem":"NTFS|ReFS|OTHER","persistentAcls":boolean}` through an independent `GetVolumeInformationByHandleW` observation.
|
||||
|
||||
- [ ] **Step 1: Add the independent observer and failing native assertions**
|
||||
|
||||
Add the `volume-semantics` command to `processBoundary.cc`. In `verify-windows-native.mjs`, require `persistentAcls === true` and compare its filesystem string with the `.filesystem` property of `sourceIdentity`, `native.inspection.filesystem`, `driveRootRuntime`, `snapshot.source`, `snapshot.snapshot`, `readback`, `snapshotOwner.observation` and the Cutter bridge identity. Record the independently observed filesystem and an `observedFilesystemIdentity` control in the report when the boundary fixture is supplied.
|
||||
|
||||
- [ ] **Step 2: Build the unmodified native artifact and verify the ReFS failure**
|
||||
|
||||
Use WSL Node 24.22.1 for `npm run build:windows-native`, and compile the fixture with:
|
||||
|
||||
```bash
|
||||
mkdir -p .cache/windows-process-boundary
|
||||
x86_64-w64-mingw32-g++ -municode -std=c++17 -O2 -static -Wall -Wextra \
|
||||
-o .cache/windows-process-boundary/process-boundary.exe \
|
||||
tests/fixtures/windows/processBoundary.cc -ladvapi32
|
||||
```
|
||||
|
||||
Run `node scripts/verify-windows-native.mjs . .cache/windows-process-boundary/process-boundary.exe` with `TEMP` and `TMP` set to an ignored directory on ReFS. Expected: FAIL before target analysis with the original `Backing volume must be NTFS with persistent ACLs` constraint, proving the old native admission still blocks ReFS.
|
||||
|
||||
- [ ] **Step 3: Implement native admission and identity propagation**
|
||||
|
||||
In `openFile`, split the two failures into `Backing volume filesystem is outside the verified NTFS/ReFS profile` and `Backing volume does not support persistent ACLs`, then store the observed name on `File`. Replace NTFS-only path wording with fixed-local wording while leaving all other checks unchanged.
|
||||
|
||||
Add `filesystem` to `File` and `Runtime`. Set `Runtime.filesystem = parent->filesystem` in `createRuntime`, propagate `root.filesystem` in `runtimeDirectory`, and update every `identity` caller in `filesystem.cc` and `process.cc` to pass the owning value: open, inspection, runtime creation/open, Cutter verification, snapshot source and snapshot destination. Update NTFS-specific comments to the verified NTFS/ReFS boundary without altering cleanup behavior.
|
||||
|
||||
- [ ] **Step 4: Rebuild and verify ReFS, then NTFS**
|
||||
|
||||
Rebuild the native artifact and boundary fixture in WSL. Run `npm run verify:windows-native:artifact` and the full native verifier on ReFS; expect all existing controls plus `observedFilesystemIdentity` to pass with `filesystem: "ReFS"`.
|
||||
|
||||
Create a detached NTFS worktree at `C:\Users\oi\AppData\Local\Temp\rea-windows-refs-ntfs` for the same revision, install its Windows dependencies, and copy the same generated native artifact and boundary fixture into it. Run the full verifier there with `TEMP`/`TMP` on NTFS; expect `filesystem: "NTFS"` and no regression.
|
||||
|
||||
- [ ] **Step 5: Commit native code and its regression coverage**
|
||||
|
||||
```bash
|
||||
git add native/windows/src/authority.hpp native/windows/src/filesystem.cc \
|
||||
native/windows/src/process.cc tests/fixtures/windows/processBoundary.cc \
|
||||
scripts/verify-windows-native.mjs
|
||||
git commit -m "feat(native): support ReFS filesystem authority"
|
||||
```
|
||||
|
||||
### Task 3: Capability declarations, diagnostics and documentation
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `src/windows/WindowsNativeLoader.ts`
|
||||
- Modify: `src/windows/WindowsNativeLoader.test.ts`
|
||||
- Modify: `src/ghidra/GhidraProviderCapabilities.ts`
|
||||
- Create: `src/ghidra/GhidraProviderCapabilities.test.ts`
|
||||
- Modify: `src/ghidra/GhidraDoctor.ts`
|
||||
- Modify: `src/ghidra/GhidraDoctor.test.ts`
|
||||
- Modify: `scripts/verify-real-ghidra-windows.mjs`
|
||||
- Modify: `scripts/verify-windows-native-inspection.mjs`
|
||||
- Modify: `native/windows/README.md`
|
||||
- Modify: `docs/providers/windows-ghidra-p0.md`
|
||||
- Modify: `docs/providers/ida-provider.md`
|
||||
- Modify: `docs/getting-started/installation.md`
|
||||
- Modify: `docs/guides/native/native-investigation.md`
|
||||
- Modify: `docs/testing-lanes.md`
|
||||
|
||||
**Interfaces:**
|
||||
|
||||
- Produces: user-facing capability and recovery text limited to fixed local NTFS/ReFS, with no remaining NTFS-only claim in the touched Windows native/Ghidra workflows.
|
||||
- Produces: the real Ghidra verifier limitation `windows-x64-local-ntfs-refs-only`.
|
||||
|
||||
- [ ] **Step 1: Add failing wording tests**
|
||||
|
||||
Assert that the loader self-test remediation contains `writable local NTFS/ReFS temporary directory`, `windowsP0Limitations` contains `local NTFS/ReFS targets and runtimes`, and a passing doctor's `native_authority` detail contains `local NTFS/ReFS only`. Keep all existing diagnostic behavior assertions unchanged.
|
||||
|
||||
- [ ] **Step 2: Run focused tests and confirm the old wording fails**
|
||||
|
||||
Run: `npm run test:focused -- src/windows/WindowsNativeLoader.test.ts src/ghidra/GhidraProviderCapabilities.test.ts src/ghidra/GhidraDoctor.test.ts`
|
||||
Expected: FAIL on the NTFS-only strings.
|
||||
|
||||
- [ ] **Step 3: Update declarations and every owning document**
|
||||
|
||||
Apply the exact NTFS/ReFS wording from Step 1, update the inspection script's host/error and retained-handle comments, and replace the Ghidra report limitation. Update the listed guides to describe the same fixed-local boundary and record the independent volume-semantics observer. Do not alter NTFS MFT/USN functionality or unrelated historical specifications.
|
||||
|
||||
- [ ] **Step 4: Verify wording, discovery and static checks**
|
||||
|
||||
Run the focused tests, `npm run verify:test-discovery`, `npm run check:fast`, and a scoped search for `local NTFS`, `NTFS only`, `NTFS-only`, `fixed local NTFS` and `local-ntfs`. Expect PASS with no stale claim except the approved historical statement in `docs/specs/native/windows-refs/spec.md` and unrelated formats.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add src/windows/WindowsNativeLoader.ts src/windows/WindowsNativeLoader.test.ts \
|
||||
src/ghidra/GhidraProviderCapabilities.ts src/ghidra/GhidraProviderCapabilities.test.ts \
|
||||
src/ghidra/GhidraDoctor.ts src/ghidra/GhidraDoctor.test.ts \
|
||||
scripts/verify-real-ghidra-windows.mjs scripts/verify-windows-native-inspection.mjs \
|
||||
native/windows/README.md docs/providers/windows-ghidra-p0.md \
|
||||
docs/providers/ida-provider.md docs/getting-started/installation.md \
|
||||
docs/guides/native/native-investigation.md docs/testing-lanes.md
|
||||
git commit -m "feat(native): advertise ReFS Windows support"
|
||||
```
|
||||
|
||||
### Task 4: Final verification and Draft PR
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `docs/specs/native/windows-refs/tasks.md`
|
||||
- Create locally, never commit: `.cache/windows-refs-pr.md` and verification reports under `.cache/`.
|
||||
|
||||
**Interfaces:**
|
||||
|
||||
- Produces: one reviewed feature branch, a linked Draft PR, and reproducible NTFS/ReFS verification evidence. No generated binaries enter Git.
|
||||
|
||||
- [ ] **Step 1: Run source, documentation and package checks on the final revision**
|
||||
|
||||
In the independent WSL clone run `npm run check`, `npm run docs:check`, and `npm run verify:package`. On Windows run `npm run verify:test-discovery`, `npm run verify:windows-native:artifact`, `npm run verify:package:windows`, and `npm pack --dry-run`. Record actual results; investigate failures rather than weakening checks.
|
||||
|
||||
- [ ] **Step 2: Repeat all real Windows lanes on both filesystems at the final commit**
|
||||
|
||||
Build `.cache/windows-native-inspection-fixture` through WSL, then run `node scripts/verify-windows-native-inspection.mjs` with `TEMP`/`TMP` on each filesystem. Repeat the full `verify:windows-native` matrix with the independent boundary fixture.
|
||||
|
||||
Run `npm run verify:ghidra:windows` in each worktree with `GHIDRA_INSTALL_DIR=D:\工具\ghidra_12.1.4_PUBLIC`, `JAVA_HOME=C:\Program Files\Zulu\zulu-25`, and `TEMP`/`TMP` on the corresponding filesystem. Expect complete operation coverage, cleanup completion and `windows-x64-local-ntfs-refs-only`.
|
||||
|
||||
- [ ] **Step 3: Exercise the original ReFS user scenario through the source CLI**
|
||||
|
||||
In the ReFS worktree run `node scripts/rea.mjs analyze D:\项目\逆向分析\魔塔\TSW.exe` with `REA_ANALYSIS_PROVIDER=ghidra`, the Ghidra/Java settings above, and ReFS `TEMP`/`TMP`. Expect the original target SHA-256 `41cb9844d9bdcf2641a34d4b152d6fbbb0455077abe0e9d7bfed77761a4d2779`, a completed overview, and no snapshot-admission failure. Close the session and confirm owned runtime paths are removed.
|
||||
|
||||
- [ ] **Step 4: Review the final diff and synchronize upstream**
|
||||
|
||||
Run `git diff --check`, `git status --short`, `git diff upstream/main...HEAD`, and a generated-file sweep. Fetch `upstream/main`; if it moved, rebase this branch and rerun every affected real-world check. Update `tasks.md` to mark only completed items and commit it as `docs(native): record ReFS verification tasks`.
|
||||
|
||||
- [ ] **Step 5: Push and create the Draft PR**
|
||||
|
||||
Push `feat/windows-refs-support` to `QianNangong/rea`. Create a Draft PR to `morluto/rea:main` titled `feat(native): support ReFS filesystem authority`, linking #289 and summarizing the baseline failure, design, exact checks and remaining gaps. Use `.cache/windows-refs-pr.md` for the body and leave every human **Author readiness** declaration unchecked for the owner.
|
||||
|
||||
- [ ] **Step 6: Hand off for human ownership**
|
||||
|
||||
Ask the human owner to review the final diff and verification evidence, complete the readiness declarations themselves, and decide whether to mark the PR ready. Do not merge or represent maintainer approval as obtained.
|
||||
|
||||
## References
|
||||
|
||||
- [Windows ReFS specification](spec.md)
|
||||
- [REA #289: handle-based reparse-safe filesystem authority](https://github.com/morluto/rea/issues/289)
|
||||
- [Windows native build and verification guide](https://github.com/morluto/rea/blob/main/native/windows/README.md)
|
||||
@@ -0,0 +1,86 @@
|
||||
# Windows ReFS filesystem authority
|
||||
|
||||
## Problem and outcome
|
||||
|
||||
The Windows native authority currently admits only fixed local NTFS volumes.
|
||||
Its `openFile` admission combines the filesystem-name check and the persistent
|
||||
ACL check in one failure, so a ReFS target is rejected with `Backing volume must
|
||||
be NTFS with persistent ACLs` even when ReFS reports `FILE_PERSISTENT_ACLS` and
|
||||
the target's DACL is readable. The rejection occurs while creating the protected
|
||||
target snapshot, before Ghidra starts.
|
||||
|
||||
Extend the existing shared Windows filesystem authority to fixed local ReFS
|
||||
volumes without weakening its handle, identity, DACL, snapshot or cleanup
|
||||
boundaries. NTFS behavior must remain unchanged, and every other filesystem must
|
||||
continue to fail closed. This increment belongs to the additional-filesystem
|
||||
acceptance direction in
|
||||
[#289](https://github.com/morluto/rea/issues/289).
|
||||
|
||||
## Requirements
|
||||
|
||||
- Admit a fixed local volume only when its filesystem is `NTFS` or `ReFS` and it
|
||||
reports `FILE_PERSISTENT_ACLS`. Keep the existing fixed-drive, path-component,
|
||||
reparse-point and sharing admission rules unchanged.
|
||||
- Report unsupported filesystems and missing persistent ACL support as distinct
|
||||
constraints. Do not imply that ReFS lacks ACL support.
|
||||
- Record the observed filesystem in the native `File` or `Runtime` owner at
|
||||
admission. Handle-relative private children inherit the runtime's filesystem;
|
||||
snapshot sources and destinations report their respective observed values.
|
||||
Remove the hardcoded `NTFS` identity projection.
|
||||
- Accept exactly `NTFS` and `ReFS` in `windowsFileIdentitySchema`; unknown values
|
||||
remain invalid. Preserve the existing native observation structure and ABI
|
||||
version. An older consumer that only understands NTFS must continue to fail
|
||||
closed when it encounters ReFS.
|
||||
- Reuse the existing handle-relative implementation rather than adding a second
|
||||
filesystem backend. Do not add an environment override or a fallback that
|
||||
bypasses source admission, private DACLs, stable file identity, reparse
|
||||
rejection, immutable snapshots or owned cleanup.
|
||||
- Extend the independent Windows verifier fixture to report volume semantics,
|
||||
and make the real native verifier check source, runtime and snapshot
|
||||
filesystem identities against that independent observation.
|
||||
- Run the complete native conformance lane on NTFS and ReFS at the same revision,
|
||||
including DACL readback, source replacement denial, unrelated sibling rename,
|
||||
ancestor reparse denial, snapshot digest/cancellation and cleanup containment.
|
||||
Run the complete real Windows Ghidra lane on ReFS and repeat it on NTFS.
|
||||
- Update the Windows native build guide, Windows Ghidra P0 limitations, recovery
|
||||
guidance and verifier reports to say fixed local NTFS/ReFS only. Preserve all
|
||||
unrelated NTFS documentation and claims.
|
||||
|
||||
## Acceptance
|
||||
|
||||
Focused TypeScript tests accept NTFS and ReFS identities and reject unsupported
|
||||
filesystem values. The native build produces the Windows x64 artifact through
|
||||
the existing Linux/MinGW lane with Node 24.22.1, and generated artifacts remain
|
||||
uncommitted.
|
||||
|
||||
The same revision passes the complete native verifier on both filesystems and
|
||||
the real Windows Ghidra verifier on both filesystems. Source and snapshot
|
||||
filesystem identities are observed independently rather than asserted only from
|
||||
REA's own output. Relevant source, boundary, documentation, artifact and package
|
||||
checks pass; any unrun or failed check is reported explicitly and prevents a
|
||||
complete-support claim.
|
||||
|
||||
## Evidence already obtained
|
||||
|
||||
A disposable independent Win32 probe, built with the WSL MinGW toolchain and run
|
||||
without elevation, completed 24 checks on each filesystem. Both NTFS and ReFS
|
||||
reported persistent ACLs; created and read back protected private DACLs;
|
||||
provided stable 128-bit file IDs and final handle paths; denied source writes,
|
||||
source replacement and ancestor replacement through sharing violations; allowed
|
||||
an unrelated sibling rename; rejected conversion of a pinned nonempty ancestor
|
||||
into a reparse point with `ERROR_DIR_NOT_EMPTY`; and removed junctions by handle
|
||||
without modifying an external sentinel. The probe source, executable and owned
|
||||
test directories were removed. These observations support feasibility but do
|
||||
not replace the complete REA verification required above.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- SMB, UNC, exFAT, FAT32 and other filesystems or namespace variants.
|
||||
- Admitting reparse components, SUBST aliases, mounted-folder aliases or a
|
||||
mutable-path/provider authority expansion.
|
||||
- A separate ReFS backend, changed process-execution authority, Ghidra database
|
||||
mutation, or a native ABI version/structure change.
|
||||
- Weakening a failing assertion or omitting a required verification lane to make
|
||||
ReFS appear supported.
|
||||
- Marking the upstream pull request ready on behalf of the human owner or
|
||||
merging it.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Tasks
|
||||
|
||||
- [x] Confirm the upstream NTFS-only boundary, record the approved feature
|
||||
specification and validate the disposable Win32 feasibility probe.
|
||||
- [x] Extend the filesystem identity contract with focused failing/passing tests.
|
||||
- [x] Implement shared native NTFS/ReFS admission and owner-bound identity;
|
||||
verify it with the independent volume observer and full native lanes.
|
||||
- [x] Update capability declarations, diagnostics and owning documentation.
|
||||
- [x] Complete final source, documentation, artifact, package, native, Ghidra and
|
||||
original ReFS CLI verification on the same revision.
|
||||
- [x] Review and synchronize the branch, then create a Draft PR linked to #289.
|
||||
- [ ] Obtain human-owner review and readiness declarations before requesting
|
||||
maintainer review; do not merge on the owner's behalf.
|
||||
@@ -23,9 +23,8 @@ cannot admit the same map. Related: #6176, #8434, #8978.
|
||||
|
||||
A valid local map fails at an explicitly lowered admission, names map_bytes,
|
||||
and succeeds for the same point through the public CLI after increasing that
|
||||
budget. The calibrated 8 MiB default admits a complete map above 4 MiB while
|
||||
preserving an explicit smaller selection; see the
|
||||
[calibration record](../../../verification/source-map-budget-calibration.md).
|
||||
budget. The 8 MiB default admits a complete map above 4 MiB while
|
||||
preserving an explicit smaller selection.
|
||||
A finite fetched map similarly recovers after increasing decoded_records.
|
||||
Malformed maps, cancellation and failed cleanup retain their existing semantics.
|
||||
|
||||
|
||||
+9
-23
@@ -75,7 +75,7 @@ adds in-place reparse, breakaway, environment, and token observations.
|
||||
The separate `scripts/verify-windows-native-inspection.mjs` lane uses the
|
||||
`.cache/windows-native-inspection-fixture` artifact built on Linux with
|
||||
`node scripts/build-windows-native.mjs --inspection-fixture`. Its controlled
|
||||
first deletion failure checks retained NTFS ownership across a same-volume
|
||||
first deletion failure checks retained NTFS/ReFS ownership across a same-volume
|
||||
rename, later-query handle-based recovery, successful-admission caching, and
|
||||
environment-teardown cleanup. It neither
|
||||
establishes the cause of the intermittent #1701 host failure nor replaces
|
||||
@@ -842,28 +842,14 @@ 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
|
||||
files in the same sequence group, and `process-boundary` runs after that
|
||||
group. History published before the competing-loader split still names only
|
||||
`javascriptLiteralPercentPaths.test.ts`. Until an artifact records
|
||||
`javascriptLiteralLoaderOwnership.test.ts`, the sequencer assigns that
|
||||
recorded duration by the pre-split case counts: 54/192 stays with the
|
||||
percent-path file and 138/192 goes to the consolidated loader file. History
|
||||
that names the retired Early, Middle, and Late shards sums those durations
|
||||
onto the consolidated file instead, and scales a partial set as three equal
|
||||
shares. That weight is the old dual-surface cost. The demoted file runs every
|
||||
loader once through the shared stdio MCP session, so the first schedule
|
||||
overestimates it. Every discovered file still belongs to exactly one shard;
|
||||
Each tier keeps its own history because stale weights from another tier, or
|
||||
from before a large test change, unbalance the shards.
|
||||
CI assigns discovered files by historical duration rather than dividing only
|
||||
by file count. A file with no recorded duration, such as a newly added or
|
||||
renamed test, is weighted at the median recorded duration until a published
|
||||
artifact records it. Each file keeps its full duration on one worker. Extra
|
||||
workers overlap other files in the same sequence group, and `process-boundary`
|
||||
runs after that group. Every discovered file still belongs to exactly one shard;
|
||||
worker limits and project ordering remain unchanged. Fast qualification keeps
|
||||
eight built shards without coverage. The merge job rejects successful reports
|
||||
with missing, unexpected, or duplicate portable files. Coverage instrumentation
|
||||
|
||||
Loaded 100 of 2884 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user