Seal sensitive terminal chunks before deferred rendering, apply one bounded
capture-local literal matcher, and retain exact redacted byte accounting.
Keep private input facts in explicit fields and separate comparison policies.
Retain distinct terminal failures once and verify structured refusal facts.
Fixes#7782
BREAKING CHANGE: sensitive interaction data is empty with sensitive and input_bytes fields instead of a byte-count placeholder. Sensitive raw_data is also redacted. Read input_bytes and recapture both comparison sides when migrating older private-input Evidence.
Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
Assisted-by: Yukari (gensokyo-skills:yukari-boundary-analysis)
CSP3 parsing keeps the first directive of each name in a policy and ignores
later repeats; Chrome reports "Ignoring duplicate Content-Security-Policy
directive". parseCsp flattened every policy's directives into one stream, so
a header such as `script-src 'self'; script-src 'unsafe-inline'` reported the
ignored `'unsafe-inline'` directive as declared and counted nonces and hashes
from it. Track directive names per policy so only the effective directive is
retained, while the same name in separate comma-separated or repeated-field
policies is still listed once per policy.
* fix(javascript): keep both-direction feature traces from crossing shared containers
trace_application_feature with direction "both" walked the application
graph as if it were undirected. From a seed, one outgoing or incoming step
into a shared container (an asset or the artifact root) followed by steps
in the other direction reached every sibling of that container, so a trace
seeded on one storage key returned the whole connected graph.
"both" now returns the union of the outgoing and incoming closures. Each
walk keeps its own predecessor chains, so a terminal path never changes
direction midway. "outgoing" and "incoming" are unchanged.
* test(javascript): check both-direction trace paths end to end
The existing tests checked predecessor maps but no returned path. Add a
trace whose seed reaches one storage terminal outgoing and another
incoming, and assert each path's complete node_ids and edge_ids. A
pathTo that reads only the first walk's map returns a one-node path for
the incoming terminal and fails this test.
* fix(javascript): confine only ascended containers in both-direction traces
Making "both" the union of separate outgoing and incoming walks dropped
modules that a feature reaches by crossing directions. In the Notes
known-answer evaluation, the notes:export channel is pointed at by both
the preload asset (invokes) and the handler (handles); its preload,
renderer and csv modules are reached only through relationships that
change direction, so the trace kept main.js alone and the feature_modules
claim failed in tests/boundary/mcp/agentKnownAnswerMcp.test.ts.
Walk both directions in one traversal again, and confine only the
containment case the change was meant to stop: a node reached by stepping
up a contains edge from one of its children follows only further contains
steps up. A shared asset or artifact root then no longer leads into its
other children, while relationships across the feature are kept. The
Notes trace returns csv.js, main.js, preload.js and renderer.js again
(30 nodes; the previous main returned the whole 32-node graph).
outgoing and incoming traces are unchanged, and paths come from one
predecessor map again, as before this branch.
* fix(javascript): stop double-expanding application projection estimates
estimateJavaScriptStaticApplicationProjection multiplied the per-record
metadata allowance (2 KB plus the path) by the 8x expansion that it also
applies to checkpoint bytes. A projected record serializes to about 0.46 KB,
so the allowance alone already covers retention; expanded again, the
charge was about 25x the serialized application relationships.
The charge accumulates in the parent's shared result budget. On a
synthetic 2.8 MB Vite-style build (88 files, one 456 KB chunk), the first
10 files used 2.0 GB of a 2.08 GB budget while the parent heap held about
300 MiB. The other 78 files lost their application relationships and were
offered a 0-byte semantic budget. On a 201-file build the charges exceeded
the budget at file 93 and the analysis failed with resource_constraint,
leaving the remaining sources without static facts.
Keep the 8x expansion for checkpoint and repeated bytes and count the
per-record allowance once. The same builds now refuse 14 and 102
projections instead of 78 and a failed run; peak RSS stays at 1.2 GB and
2.0 GB under a 4.2 GB parent heap limit.
workerFailureComposition simulated 64 KiB of parent result budget, which
the corrected charge for its one-finding checkpoint fits. Lower that
headroom to 32 KiB so the case still exercises a refused projection.
* test(javascript): cover application projections near the shared parent budget
The estimate test compares one file's charge with its serialized graph,
but no test put several sources against one parent result budget. Replay
one recorded static checkpoint for five sources against an exact budget:
sources 1-3 fit, source 4 misses by half a source and keeps its static
facts with the reported required and budget bytes, and the last source
fits again once no checkpoint reserve is held back. A worker that charges
the projection twice, or not at all, passes the existing tests and fails
this one.
* test(javascript): cover a malformed source before a valid one under the shared budget
The testing guide asks representation-expansion and capacity changes for
a large malformed input followed by a valid input, and for escaped or
expanded representations.
Under an exact parent budget, a 3 MiB checkpoint cut off inside a string
comes first and is rejected as unreadable output with no static facts.
The valid source after it keeps its application relationships; it fits
only if the rejected bytes took no charge. A worker that charges the
static checkpoint on receipt, before parsing, passes the existing tests
and fails this one.
The estimate ratio test also runs with a nested source path and storage
keys holding quotes, backslashes, a tab and multibyte text, which expand
in serialized JSON; the charge stays within 3x to 8x of the serialized
application graph (5.3x).
* fix(javascript): resolve Vite build-output preload dependencies
With an absolute base, Vite writes __vite__mapDeps entries relative to the
build output directory (for example assets/chunk.js), and its preload helper
prefixes the configured base at runtime. REA emitted these entries as
dynamic-import module specifiers, so a scheme-less path without a leading
dot resolved as a bare package and every entry was reported as an
unresolved "external" module, even when the build output directory was
selected.
The static analyzer now marks such entries with a vite-output: specifier,
as Webpack chunk loads are marked with chunk:. Entries starting with ./,
../ or /, and scheme-qualified entries, keep their previous handling. The
graph resolves a marked entry as a URL path under each ancestor directory
of the importing file; exactly one ancestor holding the file establishes
the build output directory. Otherwise the entry is not-found (or
unavailable when several ancestors match) with a limitation that names
the build output directory.
On a synthetic 7-file Vite build, the 12 preload entries that were
"external" now resolve when the build output directory is selected, and
are not-found with that guidance when only assets/ is selected.
* fix(javascript): keep unanalyzed Vite output candidates
resolveViteOutputDependency considered only resolved ancestors. A file
that exists under an ancestor but was not analyzed (for example
dist/assets/lazy.css for the entry assets/lazy.css) resolves there as
unavailable, and that result was replaced by the root's not-found with a
limitation saying that no ancestor holds the file.
Keep resolved and unavailable ancestor candidates together. One candidate
is returned with its own path and limitations; several are reported as
unavailable with every candidate path and limitation. Only when no
ancestor can hold the file does the root's not-found result stand.
Apktool 2.9.0 replaced SnakeYAML with the YamlWriter that 3.x still uses:
apktool.yml starts with an untagged `version: 2.x.y` line and strings are
written unquoted with Java-style escapes. Only a `version: 3.x.y` header
selected the producer dialect, so 2.9.0-2.12.x output went through YAML
core parsing: a versionName of `1.0 #beta` became `1.0`, escaped quotes kept
their backslashes, an empty name became null, and `1.0: beta` made the whole
decode fail as invalid metadata.
Select the line-oriented reader for 2.9.0 and later as well. Older tagged
SnakeYAML documents keep YAML scalar semantics.
Every source string literal without an established Next root was tested
against /(?:^|\/)app\/(?:[\s\S]*\/)?page(?:\.[cm]?[jt]sx?|-[^/?#]+\.js|)(?:[?#].*)?$/u.
The unanchored search restarted at every app/ segment and rescanned to the
end of the literal, and each page? or page# candidate scanned to the next
line terminator before $ failed. A long literal therefore took quadratic
time on the analysis thread: about 6 s for a 256 KB literal of repeated
app/ segments, and 3.5 s for 224 KB of x/page? followed by a newline.
The first app/ segment admits every later page segment, and . cannot cross
a line terminator, so a query or fragment after the page filename starts on
the last line. Test the tail after the first app/ segment one page segment
at a time instead; results are unchanged.
Use one command owner for setup, client writers, Gemini policy and CLI defaults.
Migrate recognized runner registrations with backups and remove runner prewarm.
Retain unknown identities and exercise real offline npm, CLI and MCP workflows.
Fixes#7757
BREAKING CHANGE: managed MCP registrations use the selected absolute runtime
and REA entry script, including package-runner cache paths. Keep that installation
available or restore it before setup; unknown registrations require confirmed
manual repair. Setup no longer returns prewarm or emits its progress events.
Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
Assisted-by: Yukari (gensokyo-skills:yukari-boundary-analysis)
* feat(artifacts): add U-Boot legacy uImage reader (part of #7129)
Recognize legacy uImages by their 0x27051956 magic and inventory them as containers: 64-byte header facts (arch/os/type/compression raw and named, load/entry addresses, name, timestamp) with header and data CRC32 verified, stored payload extractable as payload.bin, and multi-file images split from the stored size table into image-<n>.bin. Compressed payloads stay as stored; nothing is executed or decompressed. Wires the format through classification, the artifact reader dispatch, extraction, and the evidence/snapshot format vocabularies. Related to #7129 (uImage part only); HEX/SREC and FIT are out of scope.
* fix(uimage): preserve aligned component ranges and exact header facts
* fix(uimage): retain buffered members through consumption and cancellation
* fix(uimage): preserve active read and validation failure precedence
---------
Co-authored-by: gensokyo-dev <[email protected]>
Admit the final macOS Hopper launcher arguments before application handoff.
Keep prepared-image source identity, return precise typed refusal locations,
and preserve bootstrap/lease cleanup. Update native CLI/MCP recovery
coverage and the installation guide.
Fixes#7727
BREAKING CHANGE: macOS Hopper launches refuse double quotes, backslashes
and line breaks in final helper paths or arguments before application
handoff. Select literal-safe launcher/runtime/database paths and loader
arguments, or a compatible provider. Original executable names can remain
unchanged when their prepared image path is literal-safe.
Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
Assisted-by: Yukari (gensokyo-skills:yukari-boundary-analysis)
* feat(artifacts): read UnityFS AssetBundle containers
inspect-artifact and extract-artifact now recognize the UnityFS signature
and treat format versions 6 through 9 as containers. Header facts (format
version, player/engine strings, declared size, dataflags, blocks-info
bounds and the declared 16-byte data hash) are retained alongside a
directory of CAB-* and .resS members. Member bytes stream on demand:
only the blocks covering the requested member are read and decompressed
with bounded expansion and cancellation.
Bundles declaring asset-bundle encryption keep header facts and report
unknown directory coverage. LZMA blocks-info reports unknown coverage;
LZMA member reads fail as unavailable while the directory stays
readable. Malformed counts, out-of-stream members and declared sizes
beyond the file fail as format errors. UnityFS classifies by bytes in
root detection, inventory graph construction and desktop inspection,
which emits a unityfs-header fact.
Validation: tsc --noEmit, oxlint (no new findings on touched files),
17 reader tests covering LZ4HC/uncompressed tables, blocks-info at end,
format 6 without padding alignment, multi-block members, malformed
input, unsupported compression, cancellation and abandoned streams;
full artifacts/domain/conformance suites pass. Verified against one
real YooAsset bundle (Unity 2021.3.32f1, format 8, LZ4HC): the
streamed SerializedFile contained its managed assembly byte-identical
to a UnityPy extraction. Other producer variants unverified.
* fix(unityfs): own bounded member reads and preserve partial evidence
* refactor(unityfs): clarify producer revision flag decisions
* fix(artifacts): preserve coverage authority and bound UnityFS block work
---------
Co-authored-by: gensokyo-dev <[email protected]>
Resolve Windows ADB, Apktool and update commands against the selected
PATH/PATHEXT before launch. Keep explicit paths and relative PATH choices,
report lookup failures, and reuse absolute batch invocation and ownership.
Add native launch/argv regressions, real npm metadata probes and focused
CI ownership so these boundaries retain Windows verification on the fast tier.
Fixes#7724
Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
Assisted-by: Yukari (gensokyo-skills:yukari-boundary-analysis)
Reuse shared padded-base64 facts and derive encoded admission from the existing decoded-byte budget. Refuse overflow before decoded allocation and retain padded syntax. Cover capacity, compact HTTP replies and live MCP state readback.
Fixes#7719
Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
* feat(artifacts): inventory and extract Intel HEX and Motorola S-record regions
open_binary refused Intel HEX and S-record programming files as an
unsupported format, so inspect_artifact and extract_artifact could not
answer which bytes load at which addresses.
Recognize both encodings by a fully valid first record and decode them
statically into address-contiguous regions, each an inventory entry named
0x<start>-0x<end>.bin and extractable as raw bytes. Root format_metadata
records the encoding and variant, record counts, unique and duplicate
bytes, address bounds, termination, declared start address, S0 header and
validated S5/S6 count. Gaps are never filled; start addresses are declared
facts, not proven entry points.
Checksum, record-type, byte-count, line-length, overlap-conflict, address
wrap and post-termination errors fail closed with the line number; a
missing termination record leaves coverage unknown. Decoding is bounded by
a 128 MiB file ceiling (decoded bytes are at most half the file and are
reserved after the size check) and 65,536 address-discontiguous runs.
Refs #7129
* fix(artifacts): refuse Intel HEX extended address records with a non-zero address
* fix(artifacts): bound HEX region copies and retain stream cancellation
---------
Co-authored-by: gensokyo-dev <[email protected]>
Refresh compatible security fixes and verified dependency notices. Keep
historical HTTP/3 guest verification separate from the refreshed trust store.
Fixes#7700
Assisted-by: Aya (gensokyo-skills:aya-source-investigation)
* feat(environment): serve the writes callers make without recorded form fields
- A create member a recording sent empty ("", null, false, [] or {}) is no
longer required; a call that leaves it out is applied as sending that value
(body.blank).
- List views render envelope members that list the listed entities' ids
(Paperless's `all`), so creates in such collections are confirmed.
- Updates move their entity in collections kept sorted by a field they write,
and a failed whole-collection read after an update can teach that order.
- A later create that stores an unruled field otherwise is withheld at the
create, and an item read may fill values a create's answer had not loaded.
- An unsent field respelled between null, [] and {} is unchanged.
- The skill asks for one create with every field and one with only what a
person must give.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(skill): show how to read signed-in pages before recording
Agents guessed capture keys (artifacts, dom, final) to see pages behind
sign-in, which inspect_web_page cannot reach.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): accept every empty spelling recorded creates sent
A create that fills only what a person must give sends `null` where the
full create sent a string, and `null` or `false` for the same flag. The
merged plan now accepts each recorded empty value, and a call that leaves
the member out is applied as the earliest call sent it.
Also adds the spec folder for this change.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(skill): keep the vary-fields step neutral on UI or API writes
Agents read "the form" as a cue to write through the UI, where some
applications' request bodies are not exposed; a body-unusable UI write
now re-records once with request steps.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record verification for blank members and sorted writes
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): address review of blank members and sorted writes
- Bulk updates move their entities in turn against the others' earlier
values and install the final order once, as replay does.
- A member's recorded empty values stay accepted once a later call teaches
its default; a left-out member with a default keeps the default.
- Write answers spell empty lists and maps as their recorded answers did.
- A rename can teach a sort when the creates chose one by a field the
update did not write, such as ids that ascend with titles.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(environment): serve the writes that later reads explain
- An item read whose object is marked deleted (deleted, isDeleted or
is_deleted true) agrees with an absent entity, as EspoCRM answers a
deleted record; such an object never seeds or adopts an entity.
- maxSize, max_results and maxResults are page sizes, for whole-collection
list lines and the list query's limit role.
- An item view also shows the fields only reads after its type's first write
show, when no initial entity holds them (Vikunja's task subscription),
without requiring them; write answers leave such a field out for entities
without it, and it no longer withholds the write as incomplete-entities.
- The skill asks updates to change the fields a person would change, and
expects a deleted object to read back as 404 or marked deleted.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): answer sent empty members as sent, and keep a placed create's order
- A write answer spells an empty list or map the call did not send as its
recorded answer did; one the call sent is answered as sent, so a create
sending `[]` is not answered `null` because the first recorded create was.
- A read listing the whole collection that placed a create leaves the create
only the sorted inserts whose order that read follows, so a later rename
cannot teach a sort an earlier read ruled out.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): answer bulk updates without fields only later reads show
A bulk update's answer renders each entity with the same allowance a single
update's answer has: a field only reads after the type's first write showed,
which no initial entity holds, is left out for an entity without it, so a
bulk update of a seeded task is no longer refused for lacking it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): correct how the EspoCRM contact update task passes
The agent trajectories show gpt-oss passes it by creating a replacement contact
and deleting the original, since the served update refuses emailAddress; the
update itself is refused in both builds.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): answer a read of a served-deleted entity marked deleted
An application that soft-deletes still answers a deleted record by id, marked
deleted. Serving now keeps an entity a served delete removed from a type whose
recorded item reads show that, until a reset or load and within the size
data/add loads, and answers a read of it with its last fields and the flag
true, instead of refusing the read.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep unloaded create answers, check bulk answers with sent members, narrow inserts only on collection-order reads
- A create whose item read loaded values its answer had not records them
(`observation.read.unloaded`), and a served create's answer keeps them as
the recorded answer showed them, a zero-time owner included, while the state
holds the read's.
- Replay checks a bulk update's recorded answers with each target's sent
members, as serving answers them, so echoed `null` and `[]` no longer make
the plan body-unusable.
- A whole-collection read whose query sorts it shows the query's order, so it
no longer narrows a create's sorted insert candidates.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the census with main's unknown-clock rule merged
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(environment): serve query numbers, counted values and made objects
- A query parameter accepts a number or boolean, which serving sends as its
JSON text, as agents send page sizes and flags.
- A sequence may start at the value its first create took above every value
its type held (Vikunja's per-project task index), and a later create's
composed, template or started-sequence rule is adopted when it also spells
the first create's value.
- A made-object rule explains an object the application makes with each
created entity: members the request stamped, members holding the entity's
own id, and counts one past the held objects' values.
- A create's answer names the id of the one object a one-element array member
holds, so bulk creates link to their type.
- The skill reads each listed object by id before writing.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(environment): let a linked create take path values it stores
A create linked to its type's own collection, whose path has no parameters,
accepts any path values when its plan stores each one in a field, as a Vikunja
task stores its project; replay and serving apply it alike.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): learn a sort from a rename only when moving its entities reaches it
Serving moves only the entities a write changes in a collection kept sorted,
so replay now tries a sort after a rename only when the entities no write the
read exercised changed already follow it. Seeded folders listed out of title
order no longer teach a title sort that serving would answer with another
order.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep unloaded create answers a sent value did not echo, and learn no sort from query-sorted reads
- A served create keeps a value its recorded answer had not loaded unless the
call sent that member and the plan stores it as sent, so a create sending
`active: false` is answered `false` as recorded while the state holds the
read's `true`.
- A rename no longer teaches a sort from a whole-collection read its query
sorts, whose ties need not follow the collection's own order.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): verify query values, counted values and made objects
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): learn the soft-delete flag in the state view and serve by it
Extraction now records the member later item reads set true on a record the
application soft-deleted, and the item view carries it as `deleted_flag`.
Serving reads that fact instead of scanning recorded bodies itself, so one
owner decides what a soft delete looks like.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the call-values checks at #727493821024
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): learn the soft-delete flag from item reads with a query too
A client may read a deleted record back only with a query, such as a
cache-busting parameter. Every successful read of the item tool now shows the
flag; only plain later reads still add fields.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the call-values checks at #727445832406
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): learn sorts only from orders a list read confirmed
- A sort retry after a failed whole-collection read requires the entities no
write changed since a list last showed them to follow it already, rather than
excusing every entity the update's tool ever wrote: an earlier rename a list
confirmed in place stays where it was.
- An update takes its creates' sort only from a create a list read showed
placed; replay still tries a sort a create guessed from the initial order.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): drop entities read back as deleted and answer soft deletes as deleted
- A held entity a later read shows marked deleted is dropped, not adopted with
the marked object's fields.
- Bulk-update replay renders answers with the optional and later-only fields
serving uses, so a bulk update of created and seeded entities replays.
- A served delete of a soft-deleting type answers with the entity marked
deleted, single and bulk.
- A deleted flag only query reads showed is a field of the item view, so a
served tombstone keeps it where live records omit it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): check made objects as recorded and keep their ids and clocks honest
- A made object's clock counts as a write clock, so a capture with no clock
anchor withholds the create instead of stamping 1970.
- Members holding the entity's identity follow the id written, generated or
sent, through the type's id field.
- A later create's made object is checked as recorded, before its own members
are rewritten, so one naming another entity withholds the plan.
- A later create's template is adopted only when it spells that create's value
too, not just when the first create's text holds its source value.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): move updated entities only by placed sorts and keep query-sorted reads from confirming order
Replay moved an updated entity by a sort a create only guessed, while the
update plan exported only placed sorts, so a read could confirm an update
by a move serving would not make. Both now use the placed sort. A passing
list read clears its entities from the moved set only when the state
decides the order of every entity it lists, so a read whose query sorts
it no longer hides an earlier move from a later sort check.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): count six withheld plans that explain more, not seven
The bulk task create counted among them is served on this branch.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): try a learned sort by moving each pending write in turn, as serving does
#retrySort sorted the whole collection, which a list could match while
serving, moving each renamed entity in turn against the others' values
before their own writes, gave another order. The state now records the
values each write replaced, and the retry replays the writes since a
list in collection order last showed their entities.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): answer a served delete with the deleted flag its recorded answer showed
An application may answer a delete with the record as it was and mark it
deleted only on later reads. Delete answers, single and bulk, now take
the flag's value from the recorded answer; reads of a served-deleted
entity still show it marked deleted.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* chore(environment): set aside two hunks next to lines main's saved-values change rewrites
Main's #7267 changes the lines beside the blank-member docs and the
empty-spelling check in explainUpdate. Setting them aside lets that merge
apply cleanly; the commit after it puts them back on top of main's text.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* chore(environment): restore the set-aside hunks on main and bump the skill to 51
Puts the blank-member docs and the empty-spelling check back beside main's
slug and composed text and heldSlugRule. Main is at skill 50 with
different text, so this branch's skill changes take 51.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* chore(environment): bump the skill to 52 above #7260's 51
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* chore(environment): put back the call-values hunks main's merge took its side for, and bump the skill to 53
The merge of main kept main's side where it overlapped this branch, so it
could commit without a conflict. This restores this branch's side next to
main's: made-object agreement beside the & slug spellings, sequence starts
in the earlier evidence (now built by earlierOf), the combined value
imports, and recording step 2 beside main's UI-first step 3. Main is at
skill 50 and #7274 at 52, so this branch takes 53.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep sorts a list showed in place ruled out, and created answers' nested members as recorded
A whole list in collection order that showed a renamed entity where a
sort by the renamed field would have moved it now rules that sort out, so
a later rename of the same entity cannot teach it. A create's answer
leaves out members its item read added inside an object the answer
showed, as the recorded answer did; the state still stores them.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep a later create's made object only with clocks its request stamped
followsMadeObjects only checked that a made object's clocks parsed, so a
later create whose object showed an older clock still passed, while serving
stamps the write's clock. Its clocks must now be in the rule's format and
within the stamp window of that create's request.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): compare soft-deleted read fields
* fix(environment): reject contradictory learned sequences
* fix(environment): preserve initially deleted item observations
* fix(environment): index stored deleted entities separately
* fix(environment): replay lists that include deleted records
* fix(environment): make no count of a made-object member earlier creates held alike
A count only a later create shows starts at the exemplar's value, which is
right only while the exemplar is the one create accepted: creates accepted
after it showed the member unchanged, which a count would have moved. The
merge now refuses such a count, as the top-level sequence check does.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
A saved response's decoded size is bounded by its received size, or the
declared length of one served from cache, times 1032 for each gzip or deflate
coding, the most DEFLATE expands. Grafana answers folder creates gzipped, so a
UI step saving a new folder's uid was refused. Other codings and unknown or
zero sizes stay refused before the body is read.
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
* feat(environment): serve the writes callers make without recorded form fields
- A create member a recording sent empty ("", null, false, [] or {}) is no
longer required; a call that leaves it out is applied as sending that value
(body.blank).
- List views render envelope members that list the listed entities' ids
(Paperless's `all`), so creates in such collections are confirmed.
- Updates move their entity in collections kept sorted by a field they write,
and a failed whole-collection read after an update can teach that order.
- A later create that stores an unruled field otherwise is withheld at the
create, and an item read may fill values a create's answer had not loaded.
- An unsent field respelled between null, [] and {} is unchanged.
- The skill asks for one create with every field and one with only what a
person must give.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(skill): show how to read signed-in pages before recording
Agents guessed capture keys (artifacts, dom, final) to see pages behind
sign-in, which inspect_web_page cannot reach.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): accept every empty spelling recorded creates sent
A create that fills only what a person must give sends `null` where the
full create sent a string, and `null` or `false` for the same flag. The
merged plan now accepts each recorded empty value, and a call that leaves
the member out is applied as the earliest call sent it.
Also adds the spec folder for this change.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(skill): keep the vary-fields step neutral on UI or API writes
Agents read "the form" as a cue to write through the UI, where some
applications' request bodies are not exposed; a body-unusable UI write
now re-records once with request steps.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record verification for blank members and sorted writes
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): address review of blank members and sorted writes
- Bulk updates move their entities in turn against the others' earlier
values and install the final order once, as replay does.
- A member's recorded empty values stay accepted once a later call teaches
its default; a left-out member with a default keeps the default.
- Write answers spell empty lists and maps as their recorded answers did.
- A rename can teach a sort when the creates chose one by a field the
update did not write, such as ids that ascend with titles.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): answer sent empty members as sent, and keep a placed create's order
- A write answer spells an empty list or map the call did not send as its
recorded answer did; one the call sent is answered as sent, so a create
sending `[]` is not answered `null` because the first recorded create was.
- A read listing the whole collection that placed a create leaves the create
only the sorted inserts whose order that read follows, so a later rename
cannot teach a sort an earlier read ruled out.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep unloaded create answers, check bulk answers with sent members, narrow inserts only on collection-order reads
- A create whose item read loaded values its answer had not records them
(`observation.read.unloaded`), and a served create's answer keeps them as
the recorded answer showed them, a zero-time owner included, while the state
holds the read's.
- Replay checks a bulk update's recorded answers with each target's sent
members, as serving answers them, so echoed `null` and `[]` no longer make
the plan body-unusable.
- A whole-collection read whose query sorts it shows the query's order, so it
no longer narrows a create's sorted insert candidates.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): learn a sort from a rename only when moving its entities reaches it
Serving moves only the entities a write changes in a collection kept sorted,
so replay now tries a sort after a rename only when the entities no write the
read exercised changed already follow it. Seeded folders listed out of title
order no longer teach a title sort that serving would answer with another
order.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep unloaded create answers a sent value did not echo, and learn no sort from query-sorted reads
- A served create keeps a value its recorded answer had not loaded unless the
call sent that member and the plan stores it as sent, so a create sending
`active: false` is answered `false` as recorded while the state holds the
read's `true`.
- A rename no longer teaches a sort from a whole-collection read its query
sorts, whose ties need not follow the collection's own order.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): learn sorts only from orders a list read confirmed
- A sort retry after a failed whole-collection read requires the entities no
write changed since a list last showed them to follow it already, rather than
excusing every entity the update's tool ever wrote: an earlier rename a list
confirmed in place stays where it was.
- An update takes its creates' sort only from a create a list read showed
placed; replay still tries a sort a create guessed from the initial order.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): move updated entities only by placed sorts and keep query-sorted reads from confirming order
Replay moved an updated entity by a sort a create only guessed, while the
update plan exported only placed sorts, so a read could confirm an update
by a move serving would not make. Both now use the placed sort. A passing
list read clears its entities from the moved set only when the state
decides the order of every entity it lists, so a read whose query sorts
it no longer hides an earlier move from a later sort check.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): try a learned sort by moving each pending write in turn, as serving does
#retrySort sorted the whole collection, which a list could match while
serving, moving each renamed entity in turn against the others' values
before their own writes, gave another order. The state now records the
values each write replaced, and the retry replays the writes since a
list in collection order last showed their entities.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* chore(environment): set aside two hunks next to lines main's saved-values change rewrites
Main's #7267 changes the lines beside the blank-member docs and the
empty-spelling check in explainUpdate. Setting them aside lets that merge
apply cleanly; the commit after it puts them back on top of main's text.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* chore(environment): restore the set-aside hunks on main and bump the skill to 51
Puts the blank-member docs and the empty-spelling check back beside main's
slug and composed text and heldSlugRule. Main is at skill 50 with
different text, so this branch's skill changes take 51.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep sorts a list showed in place ruled out, and created answers' nested members as recorded
A whole list in collection order that showed a renamed entity where a
sort by the renamed field would have moved it now rules that sort out, so
a later rename of the same entity cannot teach it. A create's answer
leaves out members its item read added inside an object the answer
showed, as the recorded answer did; the state still stores them.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
* feat(environment): serve the writes callers make without recorded form fields
- A create member a recording sent empty ("", null, false, [] or {}) is no
longer required; a call that leaves it out is applied as sending that value
(body.blank).
- List views render envelope members that list the listed entities' ids
(Paperless's `all`), so creates in such collections are confirmed.
- Updates move their entity in collections kept sorted by a field they write,
and a failed whole-collection read after an update can teach that order.
- A later create that stores an unruled field otherwise is withheld at the
create, and an item read may fill values a create's answer had not loaded.
- An unsent field respelled between null, [] and {} is unchanged.
- The skill asks for one create with every field and one with only what a
person must give.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(skill): show how to read signed-in pages before recording
Agents guessed capture keys (artifacts, dom, final) to see pages behind
sign-in, which inspect_web_page cannot reach.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): accept every empty spelling recorded creates sent
A create that fills only what a person must give sends `null` where the
full create sent a string, and `null` or `false` for the same flag. The
merged plan now accepts each recorded empty value, and a call that leaves
the member out is applied as the earliest call sent it.
Also adds the spec folder for this change.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(skill): keep the vary-fields step neutral on UI or API writes
Agents read "the form" as a cue to write through the UI, where some
applications' request bodies are not exposed; a body-unusable UI write
now re-records once with request steps.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record verification for blank members and sorted writes
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): address review of blank members and sorted writes
- Bulk updates move their entities in turn against the others' earlier
values and install the final order once, as replay does.
- A member's recorded empty values stay accepted once a later call teaches
its default; a left-out member with a default keeps the default.
- Write answers spell empty lists and maps as their recorded answers did.
- A rename can teach a sort when the creates chose one by a field the
update did not write, such as ids that ascend with titles.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(environment): serve the writes that later reads explain
- An item read whose object is marked deleted (deleted, isDeleted or
is_deleted true) agrees with an absent entity, as EspoCRM answers a
deleted record; such an object never seeds or adopts an entity.
- maxSize, max_results and maxResults are page sizes, for whole-collection
list lines and the list query's limit role.
- An item view also shows the fields only reads after its type's first write
show, when no initial entity holds them (Vikunja's task subscription),
without requiring them; write answers leave such a field out for entities
without it, and it no longer withholds the write as incomplete-entities.
- The skill asks updates to change the fields a person would change, and
expects a deleted object to read back as 404 or marked deleted.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): answer sent empty members as sent, and keep a placed create's order
- A write answer spells an empty list or map the call did not send as its
recorded answer did; one the call sent is answered as sent, so a create
sending `[]` is not answered `null` because the first recorded create was.
- A read listing the whole collection that placed a create leaves the create
only the sorted inserts whose order that read follows, so a later rename
cannot teach a sort an earlier read ruled out.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): answer bulk updates without fields only later reads show
A bulk update's answer renders each entity with the same allowance a single
update's answer has: a field only reads after the type's first write showed,
which no initial entity holds, is left out for an entity without it, so a
bulk update of a seeded task is no longer refused for lacking it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): correct how the EspoCRM contact update task passes
The agent trajectories show gpt-oss passes it by creating a replacement contact
and deleting the original, since the served update refuses emailAddress; the
update itself is refused in both builds.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): answer a read of a served-deleted entity marked deleted
An application that soft-deletes still answers a deleted record by id, marked
deleted. Serving now keeps an entity a served delete removed from a type whose
recorded item reads show that, until a reset or load and within the size
data/add loads, and answers a read of it with its last fields and the flag
true, instead of refusing the read.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep unloaded create answers, check bulk answers with sent members, narrow inserts only on collection-order reads
- A create whose item read loaded values its answer had not records them
(`observation.read.unloaded`), and a served create's answer keeps them as
the recorded answer showed them, a zero-time owner included, while the state
holds the read's.
- Replay checks a bulk update's recorded answers with each target's sent
members, as serving answers them, so echoed `null` and `[]` no longer make
the plan body-unusable.
- A whole-collection read whose query sorts it shows the query's order, so it
no longer narrows a create's sorted insert candidates.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the census with main's unknown-clock rule merged
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): learn a sort from a rename only when moving its entities reaches it
Serving moves only the entities a write changes in a collection kept sorted,
so replay now tries a sort after a rename only when the entities no write the
read exercised changed already follow it. Seeded folders listed out of title
order no longer teach a title sort that serving would answer with another
order.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep unloaded create answers a sent value did not echo, and learn no sort from query-sorted reads
- A served create keeps a value its recorded answer had not loaded unless the
call sent that member and the plan stores it as sent, so a create sending
`active: false` is answered `false` as recorded while the state holds the
read's `true`.
- A rename no longer teaches a sort from a whole-collection read its query
sorts, whose ties need not follow the collection's own order.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): learn the soft-delete flag in the state view and serve by it
Extraction now records the member later item reads set true on a record the
application soft-deleted, and the item view carries it as `deleted_flag`.
Serving reads that fact instead of scanning recorded bodies itself, so one
owner decides what a soft delete looks like.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): learn the soft-delete flag from item reads with a query too
A client may read a deleted record back only with a query, such as a
cache-busting parameter. Every successful read of the item tool now shows the
flag; only plain later reads still add fields.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): learn sorts only from orders a list read confirmed
- A sort retry after a failed whole-collection read requires the entities no
write changed since a list last showed them to follow it already, rather than
excusing every entity the update's tool ever wrote: an earlier rename a list
confirmed in place stays where it was.
- An update takes its creates' sort only from a create a list read showed
placed; replay still tries a sort a create guessed from the initial order.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): drop entities read back as deleted and answer soft deletes as deleted
- A held entity a later read shows marked deleted is dropped, not adopted with
the marked object's fields.
- Bulk-update replay renders answers with the optional and later-only fields
serving uses, so a bulk update of created and seeded entities replays.
- A served delete of a soft-deleting type answers with the entity marked
deleted, single and bulk.
- A deleted flag only query reads showed is a field of the item view, so a
served tombstone keeps it where live records omit it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): move updated entities only by placed sorts and keep query-sorted reads from confirming order
Replay moved an updated entity by a sort a create only guessed, while the
update plan exported only placed sorts, so a read could confirm an update
by a move serving would not make. Both now use the placed sort. A passing
list read clears its entities from the moved set only when the state
decides the order of every entity it lists, so a read whose query sorts
it no longer hides an earlier move from a later sort check.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): try a learned sort by moving each pending write in turn, as serving does
#retrySort sorted the whole collection, which a list could match while
serving, moving each renamed entity in turn against the others' values
before their own writes, gave another order. The state now records the
values each write replaced, and the retry replays the writes since a
list in collection order last showed their entities.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): answer a served delete with the deleted flag its recorded answer showed
An application may answer a delete with the record as it was and mark it
deleted only on later reads. Delete answers, single and bulk, now take
the flag's value from the recorded answer; reads of a served-deleted
entity still show it marked deleted.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* chore(environment): set aside two hunks next to lines main's saved-values change rewrites
Main's #7267 changes the lines beside the blank-member docs and the
empty-spelling check in explainUpdate. Setting them aside lets that merge
apply cleanly; the commit after it puts them back on top of main's text.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* chore(environment): restore the set-aside hunks on main and bump the skill to 51
Puts the blank-member docs and the empty-spelling check back beside main's
slug and composed text and heldSlugRule. Main is at skill 50 with
different text, so this branch's skill changes take 51.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* chore(environment): bump the skill to 52 above #7260's 51
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep sorts a list showed in place ruled out, and created answers' nested members as recorded
A whole list in collection order that showed a renamed entity where a
sort by the renamed field would have moved it now rules that sort out, so
a later rename of the same entity cannot teach it. A create's answer
leaves out members its item read added inside an object the answer
showed, as the recorded answer did; the state still stores them.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): compare soft-deleted read fields
* fix(environment): preserve initially deleted item observations
* fix(environment): index stored deleted entities separately
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
Check destination kind before overwrite policy and cover directory recovery,
regular-file controls, symlink modes and preservation.
Fixes#7444.
Independent review: APPROVE for patch SHA-256
3d65eb23d01da9b6df786ad0db337dcff79d85923f23678a5168babb88c16080,
relayed by the coordinating thread (reviewer identity not supplied in the
delegated packet). Triggers: file I/O, error handling, three shipping files.
Validation: baseline/candidate runtime builds and actual synthetic CLI probes;
initial focused run 70 passed, 2 Windows EPERM fixture failures, 3 skipped.
Final changed filesystem file 42 passed, 5 skipped; symlink semantics and
full aggregate checks remain unverified. Targeted format/lint/discovery passed.
Ship Claude Code and Codex from one release-pinned npm artifact with bundled runtime dependencies, extraction-only MCP qualification, plugin-aware recovery, and synchronized release metadata.
Integrates #2815 and the original proposal #1977. The original commits remain available on the PR branch; retain their author and assistant credit in this squash.
Validation: required CI passed, real Codex/Claude loading verified, and reviewed packaging/recovery findings addressed.
Co-authored-by: GamerDubz <[email protected]>
Co-authored-by: morluto <[email protected]>
Co-authored-by: OpenAI Codex <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Retire redundant historical JSON copies from the active documentation tree after verifying identical published release snapshots and an immutable route-report archive. Preserve current release data, original evidence, release publication logic and historical access.
Validation: 48 release tests; documentation conformance and rendered archive link/digest; Git blob/SHA-256 checks; selected current-head CI passed. Greptile: 5/5 with no actionable findings. Codex GitHub review unavailable due quota.
Closes#7517.
Migrate MCP session tests to the named lifecycle output schema and preserve raw reply envelopes. Move R8 type/alias checks to the production field resolver and recovery guidance checks to their scoped factory; remove superseded test-only exports and an unused import.
Validation: 99 focused tests, an exact-old-schema negative control, full selected CI including all 8 shards and source tests, and Greptile source review passed. Fresh-head real stdio MCP analyzed [email protected] and retained a complete authenticated Evidence bundle after close; compact/full catalogs are unchanged. Full local typed lint hit the 3 GiB memory guard; scoped typed lint passed. Codex review quota exhausted.
Fixes#7513.
Use one typed-checker worker by default without changing semantic scope or caller overrides. Reuse the bounded CLI worker for pure argument validation while retaining fresh-process coverage and all upstream cases.
Keep registration tests independent of real package-runner downloads while asserting the actual prewarm command and startup context. Pass the advertised binary_session definition by name to package verification, retaining default SDK validation and complete catalog/contract checks while avoiding compilation of unrelated tool outputs. Preserve all four installed-tarball scenarios and existing deadlines.
Strengthen Hermes preview operation/backup assertions and clarify physical-path routing documentation.
Assisted-by: Suika (gensokyo-skills:suika-scatter-gather-planning)
Android overload selection declared a plain number, so the CLI argument
parser coerced the raw token with Number before the schema ran. An empty
token therefore arrived as 0, and hexadecimal, exponent, signed, and
float spellings arrived as their numeric value, leaving both commands to
proceed to artifact admission on a selector the caller never wrote as a
decimal integer.
Reuse the existing decimal token parser that the other integer CLI
options already use. Omitted and explicit decimal zero keep their current
meanings, and the published schema for overloadIndex is unchanged.
Validation: npm run compile, the cli-boundary vitest project for
tests/boundary/cli/cliIntegerArguments.test.ts (56 passed), npm run
typecheck, npm run lint, npm run lint:typed, npm run format:check, npm
run metadata:check, npm run verify:architecture-guards, and npm run
knip:production. The new cases fail against the base source and pass with
the change.
Fixes#7430.
Co-authored-by: S1Mon <[email protected]>
The phone header gave each link an equal minmax(0, 1fr) column and
allowed overflow-wrap: anywhere, so single-word labels such as
"Showcases", "Anleitungen", "Руководства" and "Посібники" broke between
letters at 320-430px. Links now share the row as flex items that never
shrink below their longest word. Labels wrap only at spaces, and a word
wider than the whole row can still break, preserving the enlarged-text
fit from #3598.
Refs #3597
Cache direct return/yield source expressions by immutable AST identity for all existing static and semantic consumers. Weak keys bound retention to AST lifetime; mutable analysis facts and Evidence remain unchanged. Refs #6311; full CastleIO analysis still times out.
Validation: 225 focused tests; baseline cache-regression controls; build, serial check:fast and test discovery passed. CastleIO direct-syntax facts equal with 78,272 warm lookups reduced from 2.72-2.81s to 13.0-13.4ms. Complete sourcemap-codec CLI analyses retained byte-identical Evidence; no end-to-end speedup or token reduction claimed.
CI: source 20,888 passed / 15 skipped; seven built-dependent shards, static, docs, package builds, Linux native baseline and real JS recovery CLI/MCP passed. Shard 6 Hermes path-preview failures both reproduce on exact main b9d1a61dd; Portable tests fails downstream. Greptile 5/5, no findings; Codex quota exhausted. Authorized admin bypass for unrelated baseline CI and unchecked human readiness; no human review attestation made.
Clarify the Objective-C analyzer message, coverage limitation, structured failure diagnostics, and existing opt-out/startup resource controls.
Verification: exact documentation change applied on main 79d2fc054; docs:check passed. Installed Ghidra 12.2 analyzer/scheduler and REA error/launch owners inspected. No real macOS target reproduction; original failure remains unknown. PR CI and Greptile passed; Codex review unavailable.
rea doctor reported a skill copy with an unreadable or unresolved path as identity state unknown but classified its skill:identity check as config_drift, which claims the copy has drifted. docs/installation.md keeps an unreadable skill identity unknown, and the sibling registration checks already classify unknown state as unknown. The skill check and the DoctorScope fallback now do the same.
* fix(hermes): preserve consumers of anchored registrations
Keep original alias values and comments before setup or uninstall replaces an anchored REA node. Preserve original nested bindings and retained sharing through the common YAML writer.
Fixes#3325
* test(hermes): assert retained alias object identity
* fix(hermes): preserve removed keys and surviving alias owners
* test(cli): restore retained-view cancellation phase coverage
* fix(setup): retain copied Hermes anchor comments
* chore(hermes): reverse incidental merge hook changes
Reverse the merge relative to its included-main parent to restore exact upstream bytes. Reapply only the independently reviewed shared-owner and regression patch in a normal follow-up commit. Keep all ordinary history and normal hooks; no remote push of the rejected hook drift.
Refs #3325
* fix(hermes): retain reviewed shared-owner integration
* chore(hermes): reverse incidental merge hook changes
Reverse the merge relative to its included-main parent to restore exact upstream bytes. Reapply only the independently reviewed shared-owner and regression patch in a normal follow-up commit. Keep all ordinary history and normal hooks; no remote push of the rejected hook drift.
Refs #3325
* fix(hermes): retain exact reviewed shared-owner regression
* test(native): align plist command fixtures with main
Adopt the two maintained-main fixture files as of
dd198d037f. Distinguish exact XML lint
validation from conversion commands and retain truthful provenance,
source-value, format, limitations and unknown-scalar assertions.
The original seven provenance failures reproduce before this repair.
The affected three-file group passes all 86 checks afterward. Product
code and installed-package bytes remain unchanged.
Co-authored-by: morluto <[email protected]>
* fix(native): retain bound-target dispatch failure contracts
Adopt morluto's canonical Apple dispatch metadata owner and bounded MCP
and cleanup controls from 41e10b240c.
Keep fresh admission separate from already-bound target changes and
retain access-denied classification, exact physical causes and cleanup
ownership. Update the two stale unit expectations exposed by Source CI.
The original unit pair reproduces before the correction. Current focused
regressions, package verification and installed feature controls pass.
Only the canonical Apple owner and related controls are ported; this does
not integrate unrelated later-main changes or create another contribution.
Co-authored-by: morluto <[email protected]>
* test: align plist provenance and package listing fixtures
Keep the exact XML lint invocation in CLI provenance and include the
required CLI environment owner in the synthetic package member list.
Preserve binary provenance and all LF, CRLF, literal-CR and bytecode checks.
* revert(hermes): restore canonical main before reviewed replay
This reverts commit 575a10d194, reversing
changes made to bb17e90f27.
* test(cli): retain full cancellation oracle with prepared projection
---------
Co-authored-by: hhang <[email protected]>
Co-authored-by: gensokyo-dev <[email protected]>
Co-authored-by: morluto <[email protected]>
* fix(native): classify confirmed dSYM dyld refusals
* style(native): format target refusal handling
* fix(native): confirm precise Mach-O layout refusals before export fallback
* test(cli): observe cancellation at stable source resolution boundary
* fix(native): reject contradictory dyld layout refusals
* fix(native): preserve mixed dyld diagnostic failures
* fix(native): retain the evidence behind contradictory layout refusals
When the imports and exports refusals disagree, or a refusal disagrees with
the parsed Mach-O header, inspect_macho returned a generic output error that
kept only one dyld_info capture. It dropped the header file type and the other
refusal, so the failure could not show why the admitted diagnostic was
rejected.
The contradiction now has its own error. Its diagnostics keep the parsed file
type and every admitted refusal (mode, admitted layout, exit code and output),
and the captured output is still the conflicting command. The test checks the
reason and the retained diagnostics for each contradiction case.
* test(native): allow time for real Mach-O CLI and MCP controls
Link original DEX native declarations to per-ABI function exports and relocated static JNI table candidates through shared CLI/MCP workflows. Preserve global attribution ambiguity, exact provenance, partial coverage and retained Evidence; default MCP delivery to bounded summaries with filtered/batch pages.
Use one immutable ELF relocation decoder with streaming IL2CPP materialization, cooperative bounded export/version parsing and bounded JNI state. Reuse validated session inventories without loading target libraries or executing JNI code.
Validation: relevant type/lint/build and parser/domain/public CLI/MCP regressions; genuine four-ABI NDK fixtures and independent library/slot oracles; actual JDK/JADX Conscrypt workflows with retained-source removal. Full measurements and limitations are recorded in docs/verification/android-jni-bindings-2026-10-27.md.
Closes#6403.
Restore independent PE fixtures and dependency-complete standalone artifact verifier tests. Execute existing real Windows native behavior and inspection recovery proofs before unrelated curated tests.
Validation: 101 focused tests; full typecheck; scoped lint, module/discovery/format/docs checks; valid/corrupt real-image verifier controls; real Windows artifact, behavior, and inspection recovery proof steps passed. Greptile found no actionable issues. Codex review quota exhausted.
CI remains red from exact-base failures: Source 9, Windows 7 (base 15; loader 8 repaired), and built shard 4's 7 matching failures; 7 other shards cancelled by fail-fast. Later Windows package/Node 22/24 checks skipped. User explicitly authorized bypass of established main failures. No claim of complete CI or unavailable coverage.
Fixes#7474.
Declare copied complete browser observations as abbreviated object operands, keeping canonical validation and normalization controls unchanged. Preserve all other tool declarations and Evidence identities.
Refs #4973 and #4081.
Apply caller-selected R8/ProGuard mappings to shared Android inspections, preserving raw identities, exact verification, ambiguity and provenance. Add retained summaries and bounded/cached parsing, with measured real R8/Conscrypt workflows and review fixes.
Fixes#6329.
Co-authored-by: 555aaditya <[email protected]>
Move the retained allocation report and unchanged receipt JSON into verification documentation. Keep one report producer, repair current and archived links, document test-support ownership, and remove retired lint inputs.
Fixes#7458.
Validated focused/Python checks, report consistency, docs rendering, and real Bash CLI/MCP facts against an independent oracle. Greptile reviewed all seven files without comments. CI source/Windows/shard-8 failures match clean-main or existing-main controls; the requester authorized merging with those established failures. Codex review quota was unavailable.
768b58c6d (fix(setup): honor Droid home override) made factoryDirectory
resolve from FACTORY_HOME_OVERRIDE, so setup now writes the registration
and the personal skill copy under that home instead of ~/.factory. The
Factory Droid section still described only ~/.factory, and the page names
every other client's home override (KIMI_CODE_HOME, QODER_CONFIG_DIR,
QWEN_HOME, HERMES_HOME, CODEX_HOME, GEMINI_CLI_HOME, PI_CONFIG_DIR, DSH_HOME),
so Droid was the only one missing.
Match v1 APK certificate and signer serials by signed integer value. Normalize each comparison identity once and preserve raw certificate bytes and Evidence.
37 source/integration tests, 23 real Android SDK verifier cases, SDK-valid padded APK CLI/MCP oracle and serial static checks passed. Hosted real-apk-signature passed. CI27pass7fail2skip7cancel; exact-main controls reproduce17source and14targeted existing-main assertions. NativeWindows/Mac/Node22 baseline gaps and canceled shards are documented. Greptile sole finding is unchanged upstream browser privacy code, scoped and resolved without a fix claim. Requester authorized readiness and unrelated-main failure bypass; no human review is attested.
Co-authored-by: gensokyo-dev <[email protected]>
Extend static manifest declarations and retain precise source locations and historical unknowns. Share bounded selected component views across CLI and MCP with complete parent Evidence.
Verified real ApiDemos, an AAPT2-built fixture, legacy Evidence, default-package metadata and relevant CLI/MCP contracts. Recorded whole-task token estimates, timing/resource limits and independent main-failure controls in the PR.
Co-authored-by: Harsh <[email protected]>
Normalize transport-specific discovery facts at their shared owner; preserve upstream duplicate-ID rejection and correct discovery-time attachment uncertainty in all consumers.
53 focused regressions, serial static checks and real Chrome CLI/MCP fault injection/inspection pass. Greptile final head 5/5. Exact-main controls reproduce all 17 source and 21 shard-8 failures; seven shards cancelled and remain unverified. Requester authorized readiness and unrelated-main CI bypass. Human review is not attested.
Co-authored-by: gensokyo-dev <[email protected]>
Keep cookies with opaque partitions distinct from unpartitioned identities while retaining value hashes and incomplete comparison coverage. Preserve known partition hashes and use the existing shared CLI/MCP fingerprint owner.
Validated with 63 source and 57 storage boundary tests, builds/static checks, and real Chrome156 CLI/MCP controls. Live opaque-cookie emission was not reproduced; its protocol regression is explicit. Hosted CI's unrelated failures were reproduced against exact main a905a71e3; seven fail-fast-cancelled shards remain unverified; Greptile's sole existing-main finding was scoped and documented. Human readiness remains unasserted; bypass authorized by the requester.
Co-authored-by: gensokyo-dev <[email protected]>
Remove the derived package renderer property from new application graphs. Use renderer_declarations for source fields and package loads edges for the selected candidate; previously retained Evidence remains readable.
Add validate-browser-scenario for offline schema and semantic checks of inline JSON, local files and stdin. Return compact validity/action/secret counts without reading secret values or discovering, launching, attaching to or navigating a browser.
Execution and validation share CLI input admission and the canonical domain schema. Preserve existing capture lifecycle, diagnostics, cancellation and caller-relative executable paths.
Integrates #7149 with attribution. Fixes#5488. Validation includes 24 focused tests, static/build/docs checks, and the preserved real PocketBase scenario with its backend stopped and secret variables unset. Verification and resource/token measurements are recorded in docs/verification/browser-scenario-validation-2026-10-27.md.
Co-authored-by: Ace <[email protected]>
Save typed response fields and reuse generated IDs or authentication values across browser scenario requests, UI observations and navigation through the shared CLI/MCP workflow.
Preserve exact numbers, retained Evidence, explicit source/coverage limits and prospective page-value semantics. Bound response decoding, retained spellings and request serialization before allocation, and protect marked response values across source records, follow-up text and planned screenshots.
Integrates Edgar Arakelyan's #7162, including follow-ups through 9f5191ab0. Final local validation: 560 feature-branch tests and 561 current-main integration tests, static/build/docs checks and real PocketBase CLI/MCP privacy workflows. Whole-task comparison and verification limits are recorded in docs/verification/browser-saved-values-2026-10-26.md.
Co-authored-by: Edgar Arakelyan <[email protected]>
Replace overlapping traversals with one bounded relationship owner. Preserve superview direction, treat conflicting or unsupported registry placement as unknown, and retain source facts and coverage.
Keep historical inventory summary variants with their projection owner and share embedded PCK trailer observations while preserving each reader’s admission policy.
Share exact live target variants across open and session responses, preserving historical Evidence and snapshot admission. Consolidate equivalent ELF metadata aliases at their owner.
Pass parsed MIPS program declarations to shared-load analysis and validate IDA string address selectors before enumeration, including empty inventories.
Move shared function, dossier, inventory, reference and output semantics from the legacy Hopper module to native domain owners. Migrate provider, adapter, test and verifier consumers directly.
Reuse the read-side capture validation before publication so exported bundles can be imported. Preserve historical and foreign record identity and existing destination files on failure.
Resolve IDA compatibility facts in one place and migrate capability, session, and verifier consumers. Move native search fields to the domain and reuse residual unknown fields for filters.
Migrate schema, installer, ASN.1, and tooling consumers to their owning definitions. Remove the redundant CI task entry and the deprecated Cutter command-local JSON flag.
BREAKING CHANGE: Replace Cutter --json=true or --json=false with --json-output=true or --json-output=false. Bare --json still controls CLI result formatting.
Use canonical owners for literal matches, tool families, MCP schema presentation and IDA protocol selection; remove unused web-bundle reexports. Remove the duplicate CLI command name and keep the canonical compare workflow.
BREAKING CHANGE: rea compare-bundles has been removed. Use rea compare instead. The MCP compare_bundles tool is unchanged.
Parse JEB failure envelopes at the provider boundary and retain the original response, recovery facts, and selected inputs. Do not infer an unsupported target from undocumented error codes; preserve completed primary observations when metadata requests fail.
BREAKING CHANGE: JEB engine refusals now report execution_failure rather than unsupported_target. Consumers should inspect the retained upstream diagnostics for the engine's reason and recovery facts.
Authenticate exact retained parents against current and documented historical summary projections, including caller-selected display paths. Keep source facts, Evidence commitments and unsupported-projection rejection intact.
Attach to external browsers without implicit default-context overrides, and own temporary focus only on the selected page. Preserve unrelated page media and exact page inventory through CLI/MCP. Remove bootstrap-page retries; retain late/failed cleanup ownership and verified SDK notices.
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
Co-authored-by: gensokyo-dev <[email protected]>
Compare each retained member's exact runtime key and role without treating archive order as semantic identity. Keep one-sided legacy declaration gaps unknown, preserve proven changes with unavailable content, and retain original Evidence.
Record packed and unpacked ASAR file declarations at the reader boundary and compare known storage changes without treating historical omissions as packed. Preserve known differences when bytes are unavailable and retain existing integrity precedence.
BREAKING CHANGE: ASAR file occurrences may now contain unpacked: false. Consumers that validate only true must accept an optional boolean; absent historical fields remain unknown.
Normalize function address and name without requiring an unused upstream size. Preserve complete upstream observations and the explicit unknown body coverage across IDA protocol profiles.
Reuse completed embedded-format observations only after validating the admitted file identity and state, and centralize reader construction across inventory and extraction. Preserve early refusal, selected-path checks, ZIP ownership, and each operation's traversal policy. A source changed between preflight and inventory now fails integrity validation.
Preserve status independently of malformed content and use one declaration reader for route grouping, state extraction and manifest eligibility. Verify the partial facts through CLI and MCP views.
Derive each facet's row schema from the Mach-O producer and validate it against the requested page. Preserve the existing wire shape and historical defaults.
Distinguish omitted slice fields from declarations that cannot be interpreted, and preserve their source in native results and artifact limitations. Keep structural fallback and capacity failures explicit.
Use one owner for exact recorded timestamps and documented native-Date fallback in state and probe replay. Retain the source and disclose native precision and host-timezone dependence in state limitations.
Validated historical chronology, timezone and unknown-duration regressions against prior behavior.
Keep missing or ambiguous scenario request durations unknown, retain learned clock rules, and withhold plans that cannot generate an observed clock. Refuse such writes in older imported states before changing state or generators.
BREAKING CHANGE: The write-plan reason can now be unknown-clock; strict clients must accept the new output value.
Validated state, CLI and advertised MCP workflows, documentation, and focused clock and cleanup regressions.
Retain valid request starts independently of duration and require observed completion for interval-based state and write inferences. Bound indexed interference checks across captured writes while preserving ordinal fallback and unmodified Evidence.
Validated state, comparison, CLI and MCP workflows with known, unknown, overlapping and redacted timing controls; check:fast passed.
Preserve producer-supported recovery guidance after an existing-image DMG attachment refusal, without borrowing or detaching existing mounts. Keep diagnostics, root provenance and unknown coverage; centralize guidance ownership and run the real mounted-image regression in macOS CI.
Co-authored-by: gensokyo-dev <[email protected]>
The collection-paging paragraph says complete Evidence stays accessible through
`get_evidence`, but no tool by that name exists. The session family registers
`get_evidence_bundle`, which is the only name the catalog, the contracts and the
CLI equivalents use.
Every other page already uses the full name, so this was the only place a reader
or agent would look for a tool that cannot be called.
Admit same-major Ghidra releases at or above the verified minor through the existing compatible/unverified policy. Preserve the observed version, verified12.1.4 pin, installation-declared Java floor and separate NativeAOT verification gate.
367 targeted tests/static/docs, all10 real Java bridge-source compilation, and actual Linux12.2/JDK25 CLI/MCP queries and cleanup pass. JDK21 remains refused for12.2. Exact-main controls reproduce all3 unrelated CI assertions; canceled shards and an apt-blocked binary-layout lane remain unverified.
Co-authored-by: gensokyo-dev <[email protected]>
Distinguish invalid supported timestamp spellings from unrecognized legacy formats at the recorded-date owner. Probe replay retains ordinal order for invalid dates without changing the existing legacy fallback.
Validated date parsing, state ordering and comparison workflows; the prior implementation reorders the invalid-date regression.
Retain a limitation when ASAR block integrity fields are present. Whole-file hash verification does not establish block verification or Electron runtime acceptance.
Validated inventory and extraction workflows, including partial and malformed block declarations.
Use the shared recorded timestamp interpretation for replay ordering, including exact fractions and UTC interpretation of supported zone-less forms. Preserve native-Date fallback for unsupported historical spellings.
Validated environment comparison, state ordering and CLI tests; five new cases reproduce prior drift.
Carry reported algorithms and hashes into listing limitations when the declaration cannot be compared, retaining the existing verification and extraction policies. Bound escaped text before allocation.
Validated ASAR inventory, extraction, cleanup and MCP workflows; prior code omits the declaration details.
Read bounded plist format probes and Linux resource-limit reports through positive short reads before classifying their contents. Preserve explicit EOF, report capacity, physical failures and descriptor cleanup ownership.
Validated 66 focused tests and check:fast; nine new fault-injected cases fail against the previous implementation. Linux procfs was not verified on a real Linux host.
Share provider availability, admission, logging and Evidence delivery across browser, Electron and runtime tools. Reuse retained summary delivery for Python and BEAM selected views while preserving preflight and complete parent Evidence.
Validated 47 focused MCP and retained-view acceptance tests and check:fast.
Reuse the positional range owner for target metadata, Hopper Mach-O selection and Kuna spans. Preserve physical failures, completed span evidence and cleanup ownership across cancellation and short reads.
Validated 147 focused file and lifecycle tests; ten new cases reproduced failures against the prior implementation.
Resolve ordered descriptor values at the shared JavaScript fact owner and preserve uncertain intrinsic writes instead of stale exports. Normalize ordinary method values and reuse canonical primitive, prototype, ambient identity and ordering facts across consumers.
384 selected tests, format/static/docs checks, all final CI jobs and reviews pass. Actual Node controls cover 35 bundles; one possibly repeated factory explicitly stays unknown. Shipped Obsidian selected-source complete Evidence matches base/fixed CLI and MCP, with coverage and resource measurements in the PR.
Co-authored-by: gensokyo-dev <[email protected]>
Continue reading Mach-O and Electron ranges after positive short descriptor reads, while preserving explicit EOF, cancellation, file identity and cleanup semantics. Advance fuse scanning and hashing by the bytes actually read.
Validated focused filesystem, Mach-O, dyld, Electron and MCP workflows: 117 tests passed, two Windows-only tests skipped; check:fast passed.
Use the common analysis-view reader for Rust and native inventory validation, preserving historical defaults and original Evidence while retaining schema-specific validation.
Validated 123 focused view and service tests and check:fast.
Centralize completed file observations and cleanup error projection across stable-file providers while preserving each provider’s failure classification and exact cleanup leases. Cover BEAM finalization cancellation and devicetree cleanup retries.
Validated 223 focused lifecycle and MCP tests and check:fast.
Parse shared request and response fields at the CDP boundary while preserving capture, session and runtime admission policies. Treat empty request IDs as unknown so unrelated events cannot be joined, and retain redirect occurrences and partial response evidence.
Validate 221 focused tests, fast checks, and real Chrome network and runtime verifiers.
Derive member roles at the table-of-contents boundary and share declaration and Python-module interpretations across validation, projection, metadata, header reconstruction and nested PYZ traversal. Retain source type codes and generic-file behavior for other printable types.
Validation: 217 focused archive, CLI and MCP tests passed, including mixed-role byte and metadata checks. Typecheck and lint passed.
Share Field scalar facts and use one coded-index tag registry for widths and decoding. Preserve reserved constructor tags, generic-instantiation restrictions, heap failure order and selected-field signature admission.
Derive native import member kind from the validated MemberForwarded coordinate independently of name lookup, retaining known field or method identity when its display name is unreadable.
Validation: 368 focused source, CLI and MCP tests passed; five lost-kind regressions reproduced on the previous commit. Heap-width, coded-width, reserved-tag and selection boundaries are covered. Typecheck and lint passed.
Have the MethodDef row owner derive code type, managed kind and the P/Invoke flag for both body decoding and native-boundary inventory. Remove duplicate masks and unreachable fallbacks while preserving raw flags, zero-RVA precedence and ImplMap-specific declaration policy.
Validation: 280 focused source, CLI and MCP tests passed, including cross-workflow flag combinations and declaration/body policy boundaries. Typecheck and lint passed.
Centralize CDP script/context declarations and frame-claim interpretation across web capture, Electron, V8, active runtime and storage seeding. Preserve each workflow's admission, provenance and retention policies while removing superseded helpers and schemas.
Malformed or conflicting frame claims now leave passive scripts unattributed. Reused context IDs replace future frame authority without rebinding earlier scripts, and source readers reject empty script IDs.
Validation: 153 focused tests and check:fast passed; 13 regression failures reproduced on the prior commit. Real Chrome script export and runtime CLI/MCP verifiers passed, including correctly reported uncertain cleanup after intentional target closure. Electron regression coverage used simulated CDP.
Pass validated blob location and decoded metadata with their admitted descriptor from classification to the reader. Keep root cleanup ownership, freshness checks, format validation order and direct-reader decoding intact, then release borrowed facts after preparation.
Validation: 147 focused source, CLI and MCP tests passed, including real Node blob production; check:fast passed. Optional injected-ELF Docker verification was unavailable because the Docker daemon is not running.
Derive dependency and generic-error facts once per owning task, chunk or multifile stage. Reuse those facts for failure classification and dependency aggregation, preserving unnamed identities, severity precedence and raw diagnostics.
Validation: 70 focused tests passed; 41 platform-guarded tests skipped on macOS. Typecheck and lint passed. Real Unblob/Linux provider behavior was not run.
Share CPython magic framing, version and header facts while keeping standalone marshal coverage and PyInstaller reconstruction eligibility distinct. Preserve legacy headers, opaque unknowns and source bytes.
Validated 272 focused tests across source, CLI and MCP workflows, a 38-test reader recheck, and check:fast.
Parse each frame event using its declared protocol fields and retain loader and ancestry only across same-document updates. This removes alias-based attribution, invalidates malformed committed frame facts, and prevents stale WebMCP tools surviving a same-URL document replacement.
Migrate Electron, screenshot, capture, timeline, and execution consumers to the shared facts owner and retire the old helper exports. Validated 428 focused tests, test discovery, typecheck/lint, and real Chrome CLI/MCP network capture; Electron and WebMCP regressions use simulated CDP.
Page retained web-bundle endpoint observations and inferences through shared CLI/MCP projections, preserving source identities, scoped unknowns, coverage and complete Evidence access.
Based on HarsH’s original implementation in #7213 (6b1d5d42). Real Chromium/CLI/SDK verification and whole-task cost limits are recorded in docs/verification/web-bundle-paging-2026-10-26.md.
Explicit user authorization permits leaving human-readiness declarations unchecked and bypassing reproduced main failures (ADB listing fixture, package catalog expectation, untouched APK verifier formatting). No human-review attestation is made.
Co-authored-by: HarsH <[email protected]>
Retain file identity after Rust, web artifact, shared selected-input and historical capture reads complete before close or cancellation fails. Preserve descriptor-set snapshots in diagnostics alongside sanitized capture observations.
Classify canonical physical capture failures before cleanup composition; source permission errors and bare syscall failures keep their meaning through late cancellation and retry. Keep explicit sensitive-value redaction on retained facts.
Validation: 247 focused cases passed, two Linux-only cases skipped; build, typecheck, lint and formatting passed. Real descriptors with controlled finalization faults establish reader ownership and facts. Worker reply and multi-file database completion semantics remain separate audit work.
Normalize completed stable-file path, digest and length in one shared observation owner. Migrate thirteen identical provider projections while preserving their selected paths, schema checks and cleanup composition.
Keep specialized metadata and worker reply observations at their existing owners. Validation: shared real-descriptor coverage and provider lifecycle tests passed; build, typecheck, lint and formatting passed.
Retain exact completed file path, digest and length in Python pyc and Erlang BEAM failure observations. Translate Python close failures at the provider boundary and bind them to the retained descriptor cleanup leases so later successful retries resolve prior errors.
Exercise actual services and file handles with completed reads, cancellation during finalization and physical read failure followed by cancellation. Assert no fabricated snapshot on early failure and resolution of every prior cleanup report.
Validation: six focused descriptor regressions plus existing filesystem, parser and MCP coverage passed; build and static checks passed. Authored format fixtures establish portable reader behavior, not CPython/Erlang runtime execution.
Count retained UTF-8 text rather than UTF-16 code units, including exact-byte base64 spellings. Bound the decoded version-name map independently from output expansion, releasing replaced entries from its live storage charge.
Add real service/provider boundary controls for accepted and over-budget symbol names, version names and unused version metadata. Existing per-string bounds remain the allocation owner.
Validation: native parser, filesystem and CLI/MCP views passed; build, typecheck, lint and formatting passed. No serialized-report size cap, OOM reproduction or performance improvement is claimed.
Charge PE alias names when storing them, before target interpretation can suppress output rows. Validate unused-slot names as bytes without retaining or decoding strings. Keep row and forwarder accounting separate so names are charged once.
Preserve alias ordering, malformed unused-name issues and ordinal-only suppression. Add production service/provider retention regressions using compact shared-pointer fixtures.
Validation: 43 focused parser, filesystem, CLI and stdio MCP tests; fresh build, typecheck, lint and formatting passed. Three bounded Node 24.22.1 measurement pairs showed median process RSS high-water 154000 to 93168 KiB; timing and sampled family memory have cache/startup/sampling limits. No Windows loader acceptance or OOM reproduction claim.
Capture one environment snapshot per admitted WABT, JADX, firmware and Wakaru operation. Use it for tool selection, session identity and child launches while preserving configuration updates between operations.
Regressions reproduce changed JVM options under an old session key, mixed engine/limiter selection and environment drift between subprocesses. Keep selected-wrapper and cleanup coverage in a shared fixture with separate scenarios.
Validation: 115 distinct focused tests passed across the final five-file selection, including seven selected-command cases after refactoring. Fresh build, typecheck, lint and formatting passed. Tests use real subprocess fixtures; no real JADX/WABT/Binwalk/Wakaru engine or native Windows verification is claimed.
Retain authenticated provider source records independently of snapshot replay eligibility and return them explicitly to plain application callers, including late cancellation. CLI/MCP commit source records before delivering links; function dossiers share the canonical Evidence constructor. Keep directory replies compact and preserve successful retry verification.
Real Ghidra CLI/MCP investigations verify 652-function ls, historical report provenance, cross-session resume, unchanged source/project content and complete offline Evidence. Final full 14,338-function libcrypto comparison matches all metadata/pseudocode facts and independent fresh-import observations: 14,194 written, 143 external, one recorded deadline; 494.03 s, 445.63 CPU s, 1.584 GiB sampled family peak under 2-CPU/8-GiB guards, with no OOM or cleanup failure.
144 focused tests and static/docs/site checks pass; latest-main integration passes 289 cases plus typecheck/lint and actual CLI snapshot source retrieval. Final CI source/static/build/docs/quality/package checks pass. Four ADB shard failures also occur in main CI 40349559391; cancelled coverage remains unverified and author declarations stay unchecked under the user's explicit bypass authorization. No human-review attestation is made.
Parse literal import framing and retain ambiguous boundaries. Consult undefined symbol-table names only when needed to distinguish producer spacing, with import and export captures owned separately.
Validation: 59 native tests passed and real Apple tools on inert arm64 fixtures reproduced the old loss and verified the fix. Fresh build, typecheck and lint passed. Small warm-task median elapsed was unchanged; cold costs and agent tokens were not measured.
Consume Toybox’s single NAME separator without stripping source whitespace. Keep MCP subprocess fixtures independent of ambient PATH and validate calls through the existing named-schema helper.
Validation: focused ADB provider/parser and MCP tests passed; no real Android device was used.
Distinguish local provider readiness failures from target-support refusals in shared CLI/MCP diagnostics, preserving original codes and evidence. Avoid claiming configured providers are unconfigured.
120 focused tests, static/docs checks and real ELF CLI/MCP verification pass. Hosted CI has the same four ADB failures as exact main d9908fd7a; three canceled shards remain unverified. Merge uses the user's explicit authorization to bypass proven main failures. Fresh Codex and Greptile reviews are clear.
Fixes#7214
Co-authored-by: gensokyo-dev <[email protected]>
Respect Node asynchronous exec/execFile method-default stdio instead of interpreting an ignored option. Remove the superseded callback-shape query while preserving caller input, Evidence, uncertainty, argv and fork controls. Independently validated on current main through actual Node pipe capture, matching real-app CLI/MCP facts, 81 targeted tests and static checking. Closes#7217.
Require operator-declared hostnames before serving MCP HTTP outside loopback, preserving Host/Origin gates. Parse hostname identities once, share typed startup recovery across CLI/MCP, and announce an admitted client URL. Generated AgentEnv bundles declare their client/service names and validate DNS/HTTP name identity before export.
Validated through real packaged HTTP requests, direct SDK connection, compiled export refusals, 184 focused tests, static and documentation checks on the refreshed main integration. Final CI and review evidence is recorded in the PR body.
BREAKING CHANGE: non-loopback deployments require MCP_ALLOWED_HOSTS or rea mcp --http --allowed-hosts; bundle names must be unchanged HTTP hostnames within the 63-octet DNS label bound.
Co-authored-by: gensokyo-dev <[email protected]>
Route six artifact verifiers through the canonical complete MCP output and error parsers. Remove duplicated JSON/schema interpretation while retaining Evidence authentication, provider provenance, independent CLI parsing and CLI/MCP parity checks. Validate malformed success/error envelopes at the shared boundary.
Validation: 11 boundary tests, Go compiler verifier (30 cases), and synthetic IL2CPP/Flutter verifier workflows passed; typecheck/lint passed. PCAP readiness passed with stub tools, but capture inspection is unsupported on macOS. Linux-only binary-layout and EVM verifier toolchains were unavailable.
Share release JSON decoding, vendor fields and package integrity checks across macOS setup and Linux publishing/cache reads. Reject malformed UTF-8 instead of repairing macOS metadata, retain established initial BOM tolerance, and preserve complete vendor rows through admission and cache retention. Keep platform channel, signature, installation and cleanup policies unchanged.
Validation: 134 focused tests passed with 21 platform skips; typecheck and lint passed. Linux-only signed-cache cases were updated but skipped on the macOS host. No live Hopper installation performed.
Reuse selected Ghidra projects through verified private read-only copies, with shared CLI/MCP configuration, committed project identity, import-SHA verification and explicit historical/unknown analysis semantics. Preserve exact cancellation and platform capability boundaries.
Actual Ghidra 12.1.4/JDK21 Linux CLI/MCP investigations matched fresh import on 652-function ls and 14,338-function libcrypto inventories and pseudocode; authenticated complete Evidence, mismatch/staleness refusal, saved historical reports and shared /tmp projects verified. 958 focused tests passed with four platform skips; build/static/docs/format passed. Real macOS/Windows reuse remains unverified; Windows reuse is unavailable. See PR verification for measured whole-task costs and final CI attribution.
Co-authored-by: akushonkamen <[email protected]>
Co-authored-by: morluto <[email protected]>
Give the object-structured provider envelope one owner that retains original dictionary members. Remove duplicate schemas, text extraction and JSON-or-text decoding plus the downstream casts that repaired lossy record clones. Keep provider-specific error, truncation, wrapper and payload-selection policies in each adapter.
Validation: IDA/JEB compatibility tests, pinned SDK transport tests and provider regressions passed; check:fast passed. Real IDA/JEB applications were not exercised.
Preserve XML, OpenStep and binary dictionary keys at their format owners. Share validated binary reference facts with materialization while retaining scalar precision, UID identity and bounded expansion. Migrate archive, Interface Builder, native and app-bundle consumers, then remove obsolete key-omission accounting and schema copies.
Validated source regressions and compiled CLI/MCP workflows, including native plist fidelity and archive identity. Typecheck, lint, docs and test discovery pass. No performance benchmarks were required.
Use portable hex escapes for Windows absolute-path separators in the shared local path schema. Preserve host path semantics and caller spelling; validate Annex B/u/v compilation and Node win32 agreement. Closes#7151.
Publish portable browser request-path and HTTP-token patterns at their canonical owner, preserving input spelling and existing policy. Independently reproduced and verified through actual full-profile stdio MCP catalog and domain/MCP regressions on latest main. Closes#7168.
Preserve observed failed-response HTTP status through Linux Hopper setup diagnostics without changing download rejection, retry, or installation policy. Independently validated on latest main through red/green regressions, actual TLS sockets, focused checks and CI. Closes#7182.
Keep binary_session available when Linux owned-child probes lack procps ps. Preserve typed ownership-prerequisite failures in direct execution and report per-provider readiness in status. Independently validated on latest main through real stdio MCP plus focused regression, static and documentation checks. Closes#7164.
Upgrade Zod to 4.6.6 and refresh locked license inventories. Preserve REA's established timestamp spellings through one shared UTC/offset grammar, including completion-verifier consumers. Size the stdin resource regression from the child's actual heap capacity.
Fixes#7173
Includes the dependency and inventory changes proposed in #7184.
Co-authored-by: tijo95 <[email protected]>
Scope MCP discovery, setup, doctor, status and recovery guidance by selected tool families using one contract inventory and shared catalog identity. Preserve default discovery, canonical validation and complete Evidence.
Fixes#3246. Builds on #3026. Real libcrypto workflow verifies all 5,367 exports and identical complete Evidence. Static/source/build/docs/Windows/package/Greptile checks pass; ten assertions reproduced identically on clean main and feature across Node 24/22, with cancelled coverage explicitly unverified. Merge uses the user-authorized bypass for baseline failures and unchecked human-readiness declarations, without attesting human review.
Co-authored-by: 0xLLVEL <[email protected]>
Co-authored-by: Codebuff <[email protected]>
Co-authored-by: Claude Opus 4.6 <[email protected]>
Add opt-in bounded output-schema advertisements while preserving the full default, canonical server validation and complete structured content. Verify real stdio discovery under a 1 MiB receive cap, all 5,367 libcrypto export coordinates, complete Evidence parity, whole-task serialization estimates and resource bounds.
Fixes#2512. Integrates #7054 by Akshad Jogi with original authorship retained.
Co-authored-by: Akshad Jogi <[email protected]>
Move shared request parsing into its application owner, migrate all consumers, and remove six duplicated admission blocks while preserving cancellation and validation policy.
Keep operator-selected JavaScript paths in verifier parent Evidence while retaining canonical comparison guards. Validated with 204 passing tests, 3 Linux-x64-only skips, typecheck, lint, and test discovery.
Share ordered schema positions between Gemini literal checks, DeepSeek regex
checks, and catalog array-shape checks. Reuse the canonical keyword and local
reference owners; keep unreferenced instance literals opaque and unresolved
external or dynamic targets unknown.
Gemini and catalog checks now catch constraints in schemas reached through
references into examples. Preserve source paths, resource scopes, cycles and
regex occurrence counts. Align fixture first-error selection with the native
Gemini check and use consistent bracketed array locations in diagnostics.
Validation: 55 focused tests passed, including full/compact MCP catalogs;
typecheck, lint, discovery, and Node source-loader checks passed. The old
Gemini scanner reproduced the local-reference false negative. Installed
Gemini and DeepSeek clients were not run.
This reverts commit 7336a566ac (#7119).
After #7120 and the other merges of 2026-10-25 grew inspect_analysis_view's
complete input schema (71,762 bytes plus 3,003 bytes of examples), the 64 KiB
fitting from #7119 could no longer keep instance level 3 and fell back to
level 2. That summarized the inline Evidence source and the view selector
collections, so main CI failed in toolInputReferences, toolSchemaValidity,
analysisViewMcp, absoluteLocalPathSchema, javascriptFactsViewMcp and
godotPckMcp. #7119's own CI ran against bc143125e, before that growth.
Reverting restores the complete full-profile advertisement while the size
limit is redesigned against these contracts (#4081 stays open).
Co-authored-by: Claude Opus 5.5 <[email protected]>
Migrate twelve application service files to the existing provider input owner,
preserving schema causes, cancellation precedence, caller selection, and
retained Evidence. Keep flows with distinct error policies separate.
Replace the DeepSeek verifier's recursive object scan with schema-position
traversal using the canonical keyword and local-reference owners. Literal
pattern fields no longer cause false regex failures; patternProperties keys
are checked alongside actual pattern constraints in native regex modes.
Validation: 271 focused workflow/service tests and six verifier regressions
passed; static checks, discovery, and actual Node source-loader smoke passed.
The baseline scanner reproduced the new regressions. Installed DeepSeek client
execution was not run.
Retain validated DOS relocation records in their domain owner and consume
those facts in Ghidra load-image preparation. Preserve ordered duplicate
aliases, overlapping writes, and original/final byte evidence.
Share FAT header facts across generic, native, and Hopper readers without
merging their distinct admission policies. Replace managed method bodies'
two identical mapping lookups with one owned offset-and-extent result.
Validation: 660 focused tests passed across 19 suites; typecheck, lint, and
test discovery passed. Hopper/Ghidra checks used fixtures and simulated
provider observations; no real external provider execution was performed.
Share ELF note headers across note inspection, Flutter build IDs, Node SEA,
and recorded-crash source binding. Decode REL/RELA records once for MIPS
shared-load analysis and IL2CPP linking, removing superseded scalar helpers.
Share the CLR header prefix between desktop detection and managed PE parsing
while preserving their distinct read bounds and admission policies. Cover
those differences and ignored R_NONE fields with production-boundary tests.
Validation: 493 focused tests passed, two existing skips; static checks and
test discovery passed. Public managed/desktop CLI and ELF notes CLI/MCP
workflows exercised; no real external analysis providers were run.
Reuse the existing provider input admission helper across twelve services,
preserving cancellation, schema errors, path policies, and Evidence handling.
Share ELF dynamic records across Dart, MIPS, and IL2CPP readers, and reuse
Mach-O segment and section records for Node SEA location.
Require canonical DOS ownership before GPU PE section discovery so relocation
bytes cannot masquerade as a PE pointer. Cover valid short DOS headers and
the malformed case through both inventory and the public CLI.
Centralize ELF section and Godot trailer declarations while preserving caller admission policies. Route six PE entrypoints through canonical DOS ownership so relocation data cannot establish a PE header, and update NativeAOT interpretation identity and verifier dependency coverage.
Share exact ELF program-header facts across nine consumers while preserving their admission and precision policies. Centralize conformance path and digest binding, retain verifier-specific checks, and route fixture-owner changes to CI qualification.
Allow native matching representation budgets to be selected at runtime or launch while retaining the 96 MiB default and main shared-provenance accounting. Preserve actionable configuration recovery through the setting owner and verify complete CLI/MCP matches for 20k/50k synthetic inventories and real stripped LLVM 14/15 inventories.
Fixes#6406.
Based on #7112 by Kaoru0822; original authorship and co-author credit retained.
Co-authored-by: Kaoru0822 <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
This reverts commit 7336a566ac (#7119).
After #7120 and the other merges of 2026-10-25 grew inspect_analysis_view's
complete input schema (71,762 bytes plus 3,003 bytes of examples), the 64 KiB
fitting from #7119 could no longer keep instance level 3 and fell back to
level 2. That summarized the inline Evidence source and the view selector
collections, so main CI failed in toolInputReferences, toolSchemaValidity,
analysisViewMcp, absoluteLocalPathSchema, javascriptFactsViewMcp and
godotPckMcp. #7119's own CI ran against bc143125e, before that growth.
Reverting restores the complete full-profile advertisement while the size
limit is redesigned against these contracts (#4081 stays open).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Refs: #7135
Scope expected Ghidra input failures to the active request after the authenticated startup handshake. Preserve operation output, identity and log coordinates while retaining cumulative output with its session owner; lifecycle and unexpected failures keep full diagnostics.
Share remote input-code classification with domain error projection. Verify startup rejection, healthy continuation, cleanup, unknown errors, OOM diagnostics and real CLI/MCP workflows. The measured unknown-symbol reply falls from 13,170 to 2,209 bytes with unchanged successful facts and Evidence IDs.
Add optional native load-image summary delivery and retained selected-row pages through shared CLI/MCP analysis views. Preserve source verification, provenance, unavailable collections, exact row identity and opt-in byte/check payloads.
Preserve direct caller paths during shared CLI summary publication and cover raw/DOL projection contracts through the actual SDK. Real Ghidra ELF CLI/MCP captures, retained and file-backed pages, focused regressions and static checks passed; the PR records existing main schema failures and the JavaScript resource-recovery CI uncertainty.
A write below a slot that stores a value read from the same slot, such
as `s.c = s.c.p; s.c.i = 1` on a parameter, revisits the binding with
one more segment after the stored key on every turn. The cycle closure
only recognized segments added at the front of the path (`node =
node[key]`), so the work-list never terminated and exhausted the owned
worker heap (CodeMirror 5 `mode/stylus/stylus.js`).
Recognize a contiguous segment inserted after a stable base, check that
repeating it after that base can never be pruned, and escape through it
once, as the self-alias rule already does. Front insertions keep their
existing order and result.
Fixes#7130
Co-authored-by: Claude Opus 5.5 <[email protected]>
Reference-store identity queries resolved the written target as a value,
so once a step consumed the written key the walk continued into the value
read from that slot and recorded it, and everything reachable from it, as
an object the store mutates. Every value stored into one local object at
unknown keys then received an entry for every such store, and each new
store re-queued every earlier one. Ambient-write indexing grew cubically
in the number of such stores.
Receiver queries now drop items whose projection no longer ends at the
written key. Stored-value selection has one owner, which the resolver and
the store fixpoint share. The fixpoint re-queues a dependent only when a
changed entry can reach it with a selection that its receiver query keeps.
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fix(mcp)!: return a compact binary_session status by default
binary_session {} with no target open returned about 66 KB, most of it
provider rejection diagnostics and candidate capability sets that the
skill's recovery flow re-reads on every retry. 6.8.0 grew it by 21%
because the shared regex capability limitation began repeating setting
bounds and step-by-step recovery for every search operation of every
provider (#6099, #6267, #6301, #7049) and IDA gained that limitation for
its two search operations (#4862).
The regex limitation now states the effective deadline and heap, their
sources and where to change them; the deadline and heap errors keep the
full recovery. binary_session gains detail: summary (default) or
complete. The summary keeps open state, target identity, the binding,
route capabilities, run, activity and health status, each candidate's
availability and target-support status, code and reason, and every
tool's availability, reason, remediation and modes, and lists the
fields it leaves out in omitted_fields. Complete detail returns the
previous shape. The CLI capabilities and providers commands keep
complete provider facts through the same application projection.
BREAKING CHANGE: binary_session {} no longer returns
analysis_provider_candidates[].availability.diagnostics,
target_support.diagnostics or capabilities, or tool_availability group
surface, effects and annotations. Pass {"detail": "complete"} to get
them.
Fixes#7109
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(mcp): key binary_session output fields by detail
The output schema accepted detail: "complete" with summary candidates or
tool groups, and a summary without omitted_fields, so detail did not
tell callers which fields existed. Each session kind is now crossed
with a detail-specific shape: a summary requires omitted_fields and
summary-only candidates and tool groups; complete requires diagnostics,
candidate capabilities and static tool flags and forbids omitted_fields.
Both the canonical schema and the SDK-validated advertised schema reject
mismatched shapes.
The verifier helper accepts summary candidates only for a validated MCP
summary; CLI provider output still requires candidate capabilities.
Regex limitation tests check values, sources and setting names instead
of whole sentences.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fix(cli): report JSON Lines selection refusals as caller errors
A --format jsonl refusal because the selected value is not a record
collection is the caller's output selection, not unreadable analysis
output. Report it as invalid_request/invalid_input that names the
selection and its observed shape, keep the --format json /
--filter-output remediation, and drop the rea doctor advice.
AnalysisInputError gains an optional producer remediation, mirroring
the other refusal classes. The JSON Lines owner examines its documented
boundaries once for both admission and refusal facts.
docs/cli.md now states that columnar results such as
inspect-sqlite-database --table rows are not record collections.
Fixes#7110
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(cli): carry JSON Lines refusal facts as structured observations
JSON Lines refusals now put the location and shape of each refused value
in details.issues[].observed, and the message is built from those facts.
Tests assert the classification, issue path, observed facts, and the
shared remediation constant instead of fixed sentences.
The filtered analysis-view export check now uses a non-empty request
and compares the emitted rows with the unfiltered export.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Logical branch selection evaluated the left operand to decide which
branches stay reachable, and value evaluation then evaluated the selected
left branch again. In a left-nested `a || b || c ...` chain every level
repeated that, so semantic analysis doubled per operand and a 24-operand
chain exhausted the per-source deadline.
The selection now carries the left operand's value with the branch, and
value evaluation reuses it. Provenance still walks the branch nodes.
Results are unchanged.
Fixes#7115
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fix(mcp): fit every advertised input schema within the 64 KiB client limit
Claude Desktop drops a local connector tool whose compact-JSON input
schema exceeds 64 KiB. The full input profile advertised
compare_web_captures at 171,867 bytes and inspect_analysis_view at
71,632 bytes, because the self-contained projection inlines the
complete producer capture schemas once per side.
The full advertisement now fits the limit at its producing boundary.
A property whose schema repeats an earlier sibling's points at it, and
schemas below the deepest instance level that fits are summarized as
their types, size constraints and descriptions. Every rewrite widens the
advertisement through the existing relaxation rules for oneOf, not,
if/then/else, contains and unevaluated keywords, so canonical inputs
stay accepted and the canonical contract still validates every call.
Schemas within the limit are unchanged, and the compact profile is
still presented from the complete projection.
Numeric const and enum literals are also relaxed in the advertisement,
like boolean literals, since Gemini accepts only string enum members.
Fixes#4081
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(mcp): keep fitted input summaries widening and at the deepest fitting level
Array summaries took item types only from `items`, so a tuple such as
`{prefixItems: [{type: string}], items: {type: number}}` was advertised
as a number array that rejected `["a", 1]`. Item types now include tuple
positions from `prefixItems`, a draft-07 `items` array, and
`additionalItems`, and stay unconstrained when later elements are open.
A summary can also be longer than the schema it replaces (a nullable
array becomes an anyOf), so candidate size is not monotone in the
retained depth and stopping at the first overflow could skip a deeper
candidate that fits. A schema is now kept whole when its summary is not
smaller, and fitting searches from the deepest level down.
Property tests check that every summary accepts what its schema accepts
over every catalog input subschema and synthetic tuples, and that the
fitted schema is the deepest fitting candidate. The browser comparison
boundary test now expects a malformed `after` capture to be rejected
canonically, since `after` is advertised as the same schema as `before`;
the same malformation on `before` stays advertised-invalid.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fix(javascript): bind defaulted and destructured Webpack factory roles
A Webpack factory whose module parameter was defaulted (`e = {}`) or
destructured (`{exports: x}`) reported an exact empty export list with
complete coverage, because roles were taken only from plain identifiers.
Bind factory roles once, by position, in javascriptBundlerFactoryRoles.
Defaulted module/exports parameters keep their role (the convention always
supplies the argument), `{exports: alias}` binds the alias to
module.exports, and a repeated sloppy parameter name binds its last
argument. Other role patterns (rest, array, nested or computed keys, a
non-identifier loader) receive no role and count as an unknown finding,
so the file's analysis is partial instead of claiming no exports. The
export collector, the factory require name and the standalone bootstrap
externals all use these parsed roles.
Fixes#7113
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(javascript): keep factory receivers through unordered reads
A defaulted role parameter kept the unused default in the binding facts
passed to write ordering, so a receiver read inside a loop, nested block
or closure was unresolved and its export silently dropped while the
module stayed complete.
The role owner now removes defaults the calling convention never runs
before ordering. Separately, an export-shaped write through a role
binding whose read stays unordered now counts as an unknown finding
instead of being dropped, so an incomplete list is never reported as
complete.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(javascript): treat never-run factory parameter defaults as dead code
Removing unused defaults from binding facts let writes inside a default
expression reach the export collector: `(e = {}, t = (() => {
e.exports.ghost = 1; })())` reported `ghost` although Webpack supplies
both arguments. Loader calls in such defaults also produced require
references and async chunk keys.
The role owner now records the default of every role parameter, any
binding pattern included, as never run. The export collector, the
async-chunk walk and the static source traversal skip those subtrees,
so they yield no exports, references or chunk keys. Defaults of later,
non-role parameters still run and are still reported.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
When cancellation or the deadline interrupted LLDB after it had published
its bridge result, the tracer never read that result, so an explicit
`target_process_created: false` (or `target_process_exit_observed: true`)
was lost. The run kept a `native-target:unknown` marker that no cleanup
retry could release, wedging the tracer for every later trace.
Read the published result once LLDB's process group is stopped, even for
an interrupted run, and apply the same target-gone proof in cleanup retry.
Cancellation or timeout stays the primary outcome; a created target, a
truncated result, or a missing PID alone stays unresolved.
Fixes#5385
Co-authored-by: Claude Opus 5.5 <[email protected]>
* perf(native): charge matching for what it copies, not borrowed retained inventories
Native function matching deep-walked every retained list_procedures record
at about 2.8 KB per Ghidra-shaped row, although the session ledger lends
those immutable records without a copy, and charged each inventory's one
Evidence ID once per function. The report and Evidence copies of every
emitted member were not charged at all.
Charge each inventory row before parsing for the member it becomes,
including its report and Evidence copies, charge the shared inventory ID
once, and skip the walk only for borrowed immutable inventories and closure
records that matching never parses. Inline Evidence, bundle records and
selected observations keep their existing charges. Retained references now
fit about 22,000 rows per side instead of 10,000, and an oversized side is
refused before its rows are parsed.
Refs #6406
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(native): charge the envelope of borrowed matching inputs
Borrowed inventories skipped admission entirely, but matching copies their
limitations into the report and Evidence and digests their profile, so a
retained inventory with few rows and large limitations escaped the
allowance. Charge every envelope field and leave only the result payloads,
which row charging covers or matching never parses, uncharged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Reduced compact input schemas gave every array property an any-value item
schema, a six-member type list beside nested `items`. Gemini function
declarations accept `items` only beside the single `array` type, so every
request through a Gemini-backed client failed with
`properties[functions].items.items: field predicate failed: $type == Type.ARRAY`.
Reduced array properties now advertise the element types their canonical item
schemas accept. Unknown, tuple, and mixed array elements use the empty item
schema, and properties that may be arrays or another type list typed anyOf
branches. An inline `not: {}` keeps the empty schema. The compact catalog test
now rejects `items` beside a non-array type as well as untyped item unions.
Fixes#5201
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fix(artifacts): admit raw UDRW disk images
Raw (UDRW, UDTO) disk images have no UDIF koly trailer, so target
admission and root inventory both refused them as unsupported binaries.
Recognize disk images in one domain owner (koly trailer, GPT, Apple
partition map, MBR, or an unpartitioned HFS+/HFSX volume header) that
both boundaries consume.
hdiutil reports "has no checksum" for these images; the native reader
now treats that status line as an explicit absent checksum, records the
nonzero verify command, attaches read-only, and reports that integrity
was not verified. Checksum mismatches and unrecognized images are still
refused.
Positional range reads used by these probes now fill until end of file
so short host reads cannot hide a signature.
Fixes#5687
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(artifacts): read disk image signature windows at the recognizer
Target admission passed its first unfilled 4 KiB read to the raw-image
checks, so a short host read could hide a GPT, APM, MBR or HFS+
signature that inventory (which fills its prefix) still observed. The
recognizer now reads its own leading window through the caller's
filling positional read, and target admission fills its format-probe
prefix as well. The controlled short-read regression now covers target
admission alongside inventory.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
inspect_macho reported only the symbol-table spelling (`_main`), while
LLDB, dlsym and observe_native_calls use the runtime spelling (`main`).
Passing a static name as a breakpoint silently selected a different
function, so results from the two tools could not be joined by name.
Keep `name` as the exact symbol-table fact and add a derived
`runtime_name` to every export and import row, produced by one shared
Mach-O symbol-name owner. Managed P/Invoke verification now uses the
same owner instead of its own underscore stripping.
Fixes#5298
Co-authored-by: Claude Opus 5.5 <[email protected]>
Retain complete browser scenario Evidence while delivering compact summaries and selected step, event, transaction and text views through shared CLI/MCP workflows. Preserve initial CLI failures across cleanup retries and validate with real Chromium/TodoMVC.
Co-authored-by: Kaoru0822 <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* feat(environment): take created entities' read-backs and re-derived update members
- A create's observation takes the fields the first read of its entity
shows that the answer lacks, and an item read's clock spellings, when the
read agrees with the answer otherwise. The plan records the read
(observation.read with its shape); an item read then observes rather than
checks, a list read only adds fields and still checks. Serving merges the
same recorded objects.
- An update member sent back as the clock the entity held and stored as a
fresh clock near the call is a clock rule; one stored as the slug of
another member stored as sent is a slug rule. Both are accepted with any
value, as whole-object writes send what they read.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the write-views verification
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): reconcile write views without hiding contradictions
* fix(environment): reject incompatible slug-only saves
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
* fix(javascript): report fork's silent stdio as piped
Node's child_process.fork pipes stdin, stdout and stderr when options.silent is truthy and options.stdio is neither a string nor an array, and inherits them otherwise. REA never read silent, so fork("worker.js", { silent: true }) was reported with stdio_mode default (inherited). The unset-stdio case of fork now reads silent: truthy gives pipe, falsy or missing gives default, and an unresolved value gives dynamic.
* fix(javascript): apply fork's silent rule to other known stdio values
* fix(ghidra): report a DOL language override conflict as a configuration error
A REA_GHIDRA_LANGUAGE_ID outside PowerPC:BE:32:* made an otherwise admitted GameCube DOL an unsupported target. docs/ghidra-provider.md and the other fixed-import lanes treat such an override as a configuration error naming the conflicting setting. The DOL lane now uses the same languageOverrideConflict owner and names only REA_GHIDRA_LANGUAGE_ID, since DOL accepts a compiler-spec override.
* test(ghidra): keep a valid compiler spec out of the DOL language conflict
* feat(binary-layout): admit ELF32 i386, ARM and MIPS layout profiles
inspect_binary_layout refused every ELF32 object, so router and IoT
firmware (ARM32, MIPS32) got no layout facts at all.
The pwntools adapter now admits EXEC/DYN/REL objects in these profiles:
ELF64 x86-64, ELF32 i386, ELF32 little-endian ARM and ELF32 little- or
big-endian MIPS. Header fields are read in the declared byte order, the
ELF32 header is bounds-checked at 52 bytes, and pwntools' own reported
architecture, class and byte order must match the admitted profile.
Other machines, classes and byte orders keep an unsupported_target
refusal that names the admitted profiles.
The output schema admits exactly those architecture combinations, and
the Evidence subject now names the reported machine instead of always
claiming x86_64.
verify:binary:layout cross-compiles i386, ARM, MIPS and MIPSel
executables and relocatable objects (never executed) and checks every
section name, address, offset and size against GNU readelf through CLI
and MCP. The real-binary-layout workflow installs those toolchains.
Refs #6934
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* ci(binary-layout): install target libc headers for ELF32 fixtures
--no-install-recommends skips the libc6-dev-*-cross packages the cross
compilers only recommend, so the i686 fixture fell back to the host's
/usr/include and failed to find bits/libc-header-start.h. Install the
four target libc development packages explicitly.
Refs #6934
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(binary-layout): size the minimum symbol entry by ELF class
The relocation reference check required a 24-byte Elf64_Sym entry, so
every positive symbol reference in an ELF32 report was refused as
unreadable output. Elf32_Sym is 16 bytes; take the minimum from the
reported class. A 64-bit table with 16-byte entries is still refused.
Refs #6934
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(binary-layout): compare ELF32 symbols and relocations with readelf
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
Apple's crash report JSON documents termination.byPid, byProc and flags, the body's parentPid, and
the metadata line's build_version and platform. The parser shapes did not list them, so they were
reported only by name in unlisted_keys / unlisted_body_keys and their values were dropped: a
watchdog kill no longer said which process ended it, and process kept parentProc without its pid.
#4297 asks for termination members beyond namespace/code/indicator to be retained as recorded, and
docs/apple-ips.md says documented fields are reproduced.
They are now kept: termination.by_proc, termination.by_pid and termination.flags, process.parent_pid
and metadata.build_version / metadata.platform. The integers are recorded integers, so they count
toward max_integer_text_bytes and a type mismatch is recorded like the other fields.
* fix(cli): preserve literal Markdown table facts
* test(cli): retain capacity diagnostics through Markdown escaping
* fix(cli): keep intraword underscores readable in Markdown tables
Underscore runs between letters or digits cannot open or close CommonMark emphasis, so escaping them only adds noise to identifiers such as source_index and invalid_request in raw Markdown. Escape underscore runs only at word boundaries and restore the original diagnostic assertions.
inspect_web_network_capture reported a record_ordinals entry past the capture's records as an invalid_format issue on record_ordinals, with no bounds. It is now an out_of_range issue on that entry (record_ordinals[i]) with minimum 0 and maximum total_records - 1, or invalid_value when the capture has no records.
RFC 9110 section 5.5 excludes leading and trailing whitespace from a field value. The gRPC-web trailer parser stripped only leading SP/HTAB, so 'grpc-status: 0 ' was reported as '0 '. Trailing SP/HTAB is now excluded too; internal whitespace and the examined byte count are unchanged.
REA_GHIDRA_LANGUAGE_ID only allowed LE or BE as the endian field and no '/' in the processor, so it rejected four language IDs that ship with Ghidra: ARM:LEBE:32:v7LEInstruction and v8LEInstruction (ARM BE8) and M16C/60:LE:16:default and M16C/80:LE:16:default. The syntax check now allows LEBE and a slash between processor name parts; the installed .ldefs catalog check is unchanged.
Preserve GitHub User metadata for Copilot while excluding it from generated human thanks and accepted prose credits. Extend the real inventory/render/check regression and document the known agent identity.
* feat: add FreeBuff agent support for REA setup
Register FreeBuff as a supported setup client using the shared user
agents directory (~/.agents/mcp.json with mcpServers, skills in
~/.agents/skills), which matches what FreeBuff Desktop loads. Adds the
client definition, boundary tests, supported-agent docs, and the skill
reference client list.
* fix(freebuff): detect FreeBuff from its profile directory, not shared .agents
The ~/.agents marker made FreeBuff appear installed for any home where
REA had installed shared skills (the default skill destination, also
Gemini CLI's), producing false doctor failures. Detect FreeBuff from
its own fixed profile directory ~/.config/freebuff-desktop instead,
and add a regression test covering a home with only the shared agents
skill directory.
* fix(setup): require product evidence for FreeBuff discovery
Address review findings at their producing boundaries and preserve directly affected consumers. Source inspection and git diff --check completed. Tests and automated checks were not run at the user’s explicit request.
* fix(uninstall): retain unverified shared client configuration
* fix(clients): preserve scoped removal evidence
* fix(doctor): omit undefined selectedClientIds under exactOptionalPropertyTypes
Passing selectedClientIds explicitly as undefined fails typecheck on this
branch (TS2379), which blocks the focused test workflow before any test
can run. Spread the option only when defined.
* fix(update): separate ownership evidence from product applicability
rea update's maintenance scope inspected only product applicability
evidence, so when a FreeBuff profile was absent but REA already owned a
version-pinned row in the shared ~/.agents/mcp.json, the plan omitted
freebuff and left the integration stale. FreeBuff now declares its
registration storage as shared, which proves ownership of an owned row
but never product applicability, and maintenance requests ownership
evidence through that declaration instead of reinterpreting the shared
paths. Doctor and setup keep readiness evidence, foreign rows stay out
of maintenance, and the Doctor exactOptionalPropertyTypes fix makes the
focused test workflow runnable.
* test(dotnet): split oversized operand extent diagnostics describe
The describe callback reached 162 lines (max 150), failing
max-lines-per-function and blocking the pre-push check for this branch.
Move the single-case extent scenarios into their own describe; no test
content or order changes.
* fix(update): preserve ZCode's disabled shared registration during maintenance
The shared user agents file doubles as ZCode's fallback, where
`enable: false` disables the registration. Ownership-based maintenance
read that row as a FreeBuff registration, whose format does not
recognize the flag, so the row was selected and the emitted setup
command rewrote it, dropping the flag and silently re-enabling a
registration the user had disabled.
registrationActivation now honors `enable: false` for any client whose
registration storage is shared, because the activation fact binds every
reader of that storage. Maintenance leaves such rows out; doctor
reports them as stale, matching ZCode's own treatment.
* fix(doctor): let explicit client selection authorize the config read
When an ACL or an inaccessible shared parent made every access probe
fail, a client selected by name was omitted before the configuration
read could return its unreadable-config detail, so doctor reported it
as not detected with installation remediation: an unresolved selected
path collapsed to absence.
An explicit selection now authorizes the read outright and the probes
serve automatic discovery only. A selected client with an unreadable
config reports invalid with the read failure; one with no config
reports missing; automatic discovery still probes before inspecting.
* fix(uninstall): share shared-storage checks between ZCode and FreeBuff
clients() queued ~/.agents/mcp.json twice: once as zcode_fallback and once
as freebuff. ZCode has no discoveryPaths, so its strict read still blocked
uninstall on malformed shared text, despite FreeBuff's new retain-and-continue
behavior. For a valid owned entry, ZCode removed it first, so FreeBuff reported
skipped rather than removed.
Make the shared file's checks and removal one shared decision:
- Add zcodeDiscoveryPaths to ZCode so it has its own applicability evidence.
- Gate zcode_fallback push on applicable, not just zcodeFallbackPath presence.
- Report shared storage ownership as one decision for both clients:
FreeBuff and ZCode now use clientOwnershipEvidencePaths together, so a
recognizable REA-owned row proves ownership once for the shared storage, and
both clients report the same result consistently.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix(uninstall): merge duplicated host and prove shared ownership from owned rows
Uninstall.ts declared systemUninstallHost twice, preventing module load,
with the exported copy returning only clients and the second copy missing
clientWriteBlocker. Merge into one exported host carrying both blockers.
hasOwnershipEvidence used access() existence, so an unrelated malformed
~/.agents/mcp.json established ownership and blocked every removal.
Ownership now requires a readable, recognizable REA-owned row via the
injected filesystem, so unrelated shared data stays retained.
Also cover ZCode discoveryPaths in its path test.
* fix(uninstall): keep denied product-local configurations fail-closed
Unproven product applicability marked every configuration path of that client unverified, so a denied ZCode profile turned an unreadable product-local config into a retained item: uninstall continued and could report complete with REA still registered. The retain-and-continue exception now applies only to storage REA does not own, classified once by clientSharedRegistrationPaths (shared configuration plus another product's same-scope fallback).
Covers the Greptile P1 on Uninstall.ts. Validation: the new test fails on the pre-fix Uninstall and passes after it; freebuff/zcode/updateMaintenance/bom/dsh suites green; clientLifecycle, clientRegistrationStatus and claudeDesktop keep the same 8 host failures as the pre-merge baseline (symlink EPERM, stale-vs-aligned on Windows).
* fix(update): retain FreeBuff when ZCode reads the shared fallback
Maintenance deduplicated clients on the path each inspection read, so ZCode's fallback view of ~/.agents/mcp.json marked that file "covered" and dropped FreeBuff from the scope. ZCode setup writes ~/.zcode/cli/config.json and deliberately leaves the fallback untouched (docs/client-configuration.md), so the emitted command refreshed only ZCode while the shared row both products load stayed pinned to the old package version. Each setup action rewrites only its own configuration path and no other action rewrites the shared row, so every selected client keeps its own maintenance action; the read-path covered/deduped filter is removed.
Covers the Codex P2 on UpdateMaintenance.ts:104. Validation: the new regression fails on e2fdec384 with {clients:["zcode"]} and passes with {clients:["freebuff","zcode"]}; updateMaintenance 31/31, setupClientConfigCleanupOwnership, cliUpdateAlias, updateOutput, cliStartupImports green; tsc --noEmit, oxlint (0 errors) and oxfmt --check clean; clientRegistrationStatus keeps the same 4 symlink/stale-vs-aligned failures this Windows host has on base e2fdec384 (verified by stashing the change).
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <[email protected]>
* fix(uninstall): preserve completed reads as shared ownership evidence
hasOwnershipEvidence caught every read failure and kept scanning, so a handle-close failure after a successful read — a RegularFileCleanupFailure whose completed outcome still contains the exact shared-file text — was discarded as "no proof". FreeBuff's applicability-unverified storage therefore never got its ownership fact, and once the retained handle blocked later reads, readClientConfiguration downgraded them to retained: inspection passed, removals soft-failed, and runUninstall(true) could purge REA data while the active shared registration remained. The catch now parses the completed outcome for the ownership text while missing or unreadable storage and malformed data keep their proves-nothing semantics, so ownership holds and every later read failure stays blocking.
Covers the Codex P2 on Uninstall.ts:252. Validation: the new regression fails on 4dbfdf1a9 (freebuff reports no blocking failure while the poisoned-scope error lands on claude_code) and passes after; setupClientConfigCleanupOwnership 25/25; the other 21 Uninstall-consumer suites are byte-identical to base 4dbfdf1a9 (61 pre-existing Windows-host failures: symlink EPERM, stale-vs-aligned); tsc --noEmit, oxlint (0 errors, same 6 warnings) and oxfmt --check clean.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <[email protected]>
* fix(uninstall): keep owned-row proof through removal refusals
hasOwnershipEvidence treated any clientRegistrationRemoval refusal as no ownership: an effective REA-owned rea member shadowed by an earlier foreign duplicate (shadowed_unowned_member), or an owned native row beside a foreign V1 fallback (foreign_legacy_fallback), discarded the already-parsed positive row fact. With FreeBuff unverified and close failures recurring on the preflight/removal rereads, those failures were then downgraded to retained, so runUninstall(true) removed the skill and purged REA data while the active owned row remained. The refusal now carries the owned rows that motivated it — the refusal only refuses the edit — and hasOwnershipEvidence evaluates that fact on both paths; preflight and removal keep refusing the unsafe edit exactly as before.
Covers the Codex P2 on Uninstall.ts:269. Validation: the new regression fails on 225cb214a (freebuff reports no blocking failure while the poisoned-scope error lands on claude_code) and passes after; setupClientConfigCleanupOwnership 26/26; the 21 Uninstall-consumer suites are byte-identical to the recorded 225cb214a baseline (61 pre-existing Windows-host failures: symlink EPERM, stale-vs-aligned); tsc --noEmit, oxlint (0 errors, same 6 warnings) and oxfmt --check clean.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <[email protected]>
* fix(uninstall): keep unresolved discovery probes from softening shared failures
The discovery probe swallowed every stat failure, so a FreeBuff profile denied with EACCES/EIO was indistinguishable from an absent profile: shared storage was marked applicability-unverified and, when ~/.agents/mcp.json also remained unreadable, the ownership and removal reads softened to retained. runUninstall(true) then removed the skill and purged REA data while an installed FreeBuff could still hold an active registration — the regression even reports complete. Absence (ENOENT) is now the only state that leaves shared paths unverified; any other probe failure leaves applicability unresolved, and shared-config failures stay blocking.
Covers the Codex P2 on Uninstall.ts:318. Validation: the new regression fails on 7572a7082 with status complete and purged data and passes after; freebuffClientConfiguration 13/13; the Uninstall-consumer batches are byte-identical to the recorded baselines (61 pre-existing Windows-host failures: symlink EPERM, stale-vs-aligned); tsc --noEmit, oxlint (0 errors, same warning rules) and oxfmt --check clean.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <[email protected]>
* fix(uninstall): retain completed configuration reads as removal evidence
A close failure after a completed read discarded the text that read
produced, so an owned registration row the text proves softened to
retained. The completed text now drives removal, keeping shared-config
failures blocking when ownership evidence exists.
Co-Authored-By: Anthropic <[email protected]>
* fix(uninstall): stop removal when a cleanup retry leaves a handle unreleased
A completed reread whose handle the cleanup retry cannot release now fails
blockingly instead of serving the text: with no owned row, the soft path
let removeAll purge managed data before close() reported the incomplete
cleanup. The completed text is served only after the retry releases the
handle; an unreleased handle is REA's own failure, never applicability
uncertainty, so it bypasses the retained softening.
Co-Authored-By: Anthropic <[email protected]>
* fix(uninstall): keep the ZCode fallback when its profile probe is unresolved
A denied or failed profile probe leaves ZCode's applicability unresolved,
never absent, but the fallback branch dropped the shared row on
applicability alone: with the native config and FreeBuff's profile both
absent, an installed ZCode kept its uninspected registration while
uninstall purged skill and data. Unresolved probes now keep the fallback
in scope with the same fail-closed treatment as other unresolved shared
paths; definitive absence still keeps ZCode out of another product's
primary storage.
Co-Authored-By: Anthropic <[email protected]>
* fix(setup): preserve a shared row's enable:false during FreeBuff repair
The shared agents file doubles as ZCode's fallback, so its `enable: false`
binds every reader: doctor now reports the disabled row as stale for
FreeBuff, but following that remediation rebuilt the generic JSON entry
without the flag and silently re-enabled a registration ZCode disabled.
Repairs of shared storage now carry the activation fact forward, while a
client's own native storage keeps its established single-reader repair
contract; the denied-profile uninstall regression also pins the
fallback's new fail-closed inspection beside the denied read.
Co-Authored-By: Anthropic <[email protected]>
* test(uninstall): retarget the completed-reread regression to a released retry
The concurrent-writer regression held the reread handle open forever,
which the fail-closed path now serves: it duplicated the unreleased-handle
regression while documenting the opposite contract. The fixture's close
spy gains a failure limit so the cleanup retry releases the handle, and
the test again proves the completed text drives removal of the
concurrently added owned row, with purge verified against the cache
layout purge actually removes.
Co-Authored-By: Anthropic <[email protected]>
* fix(doctor): report a preserved shared disable as a manual conflict
Preserving a shared row's enable:false left doctor recommending a setup
run that registrationCurrent correctly treats as already current, so the
scoped doctor returned needs_human forever. The shared-enable
interpretation now has one owner, sharedEnableFlagBinds, used by both
the activation rule and the remediation: a row disabled through the
shared flag reports the manual conflict and states that rea setup will
not change it, instead of an endlessly ineffective repair.
Co-Authored-By: Anthropic <[email protected]>
* fix(doctor): keep a native ZCode disable on the setup repair path
The manual-conflict remediation matched a native zcode row through
sharedEnableFlagBinds, but setup drops enable:false on single-reader
storage, so a native disabled registration was told setup would not
change it. The remediation now reads setup's own writer rule,
exported as setupPreservesDisabledActivation: shared storage and the
zcode fallback view keep the manual-conflict message, while a native
row keeps the working rea setup instruction. Regressions pin both
remediations.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <[email protected]>
* revert: drop the unrelated managed-CIL describe split
The split does not belong to FreeBuff client support and only widens this
PR's diff.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <[email protected]>
* fix(uninstall): remove the shared agent registration once for both clients
ZCode's ~/.agents/mcp.json fallback and FreeBuff's own configuration queued the
same physical file twice, so ZCode removed the row and FreeBuff then reported
it absent, losing the outcome for the client that owns the file.
Resolve every configuration path to one owner -- the client whose
configuration it is -- and project that single inspection and removal to each
client that loads it. A fallback reader still contributes its discovery probe,
so an installed or unresolved reader keeps the shared file fail-closed.
Discovery also accepted a dangling ~/.config/freebuff-desktop link, which setup
and doctor reject because they follow the target, so an unrelated malformed
shared file blocked every other removal. Resolve the link before treating the
profile as installation evidence, keeping lstat for removal safety.
Also date the FreeBuff release wording against the published 6.7.0 package.
* fix(uninstall): keep a row per client when two clients own one file
OPENCODE_CONFIG can point OpenCode at FreeBuff's configuration file, where
OpenCode writes `mcp.rea` and FreeBuff writes `mcpServers.rea`. Grouping by
filename gave that path a single owner, so uninstall removed only OpenCode's
row, reported that removal for FreeBuff, and could purge managed data with
FreeBuff's registration still active.
Share the decision only through a fallback view of another client's row: every
client that declares the path as its own configuration keeps its own
inspection and removal, and the fallback reader reports each of them.
* fix(clients): preserve discovery and fallback registration identity
Follow product discovery link targets without losing configuration entry
presence or explicitly selected inspections. Associate fallback readers with
the format owner's registration table and project outcomes by owner and path,
so OpenCode removal cannot be reported as a ZCode fallback removal.
All three new boundary regressions fail against the previous source and pass
with the fixes. Validation: check:fast; 217 focused tests passed; the two
changed test files were rerun with 50 passing tests. No installed FreeBuff
client was launched.
---------
Co-authored-by: morluto <[email protected]>
Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Kaoru0822 <[email protected]>
Co-authored-by: Codebuff <[email protected]>
* fix(apple): keep the recorded image name and frame symbol offset of IPS reports
Apple's IPS format documents usedImages[].name and frames[].symbolLocation, and docs/apple-ips.md says documented body fields are reproduced, but the parser shapes did not list either member. They were syntax-checked and discarded without an unlisted_keys entry, so a symbolicated frame lost its +offset and every image its binary name. Both are now kept: images[].name and frames[].symbol_location as a recorded integer, with type mismatches recorded like other fields.
* fix(apple): count frame symbol offsets in the integer text check
When formatting arrays of objects that have no own enumerable keys as
Markdown, formatObjectTable derives empty headers and outputs a malformed
table with an invalid delimiter row. Require at least one item with keys in
isObjectArray and fall back to JSON serialization when headers are empty.
Fixes#7057
Content-identical assets share a node whose observations are ordered by identity. Accept either retained display path when selecting that node, while retaining exact per-path reference and observation assertions.
* fix(browser): report an out-of-range script_index as a selection fault
A valid export_web_scripts manifest without the selected script_index was reported as an invalid_format input issue, as if the manifest file were malformed. It is now an out_of_range issue on script_index with the valid bounds, or invalid_value when the manifest has no scripts.
* test(browser): keep the out-of-range index case in its own block
---------
Co-authored-by: morluto <[email protected]>
Separate syntax, semantic uncertainty, examination limits and observed Electron applicability at the static producer, then preserve them through worker, graph and retained/inline summary views. Derive the established parse_status from the same facts and leave historical measurements unknown. Give semantic resource-limit classifications one schema owner.
Replace repeated block-prefix searches and copies with collector-scoped syntax indexes. Keep invocation environments separate, charge indexing/replay to the existing work budget and yield during prefix work. Remove the superseded synchronous collector entrypoint.
Validated producer, worker, CLI/MCP, historical and partial-coverage regressions, plus actual cancellation during indexing. Bounded authored 128/256-call controls preserved all prior facts while replacing repeated search/copy work with one index pass; this is not a throughput or agent-token benchmark.
Convert native directory separators only at Git patch argument production. Exercise fresh, applied and invalid dependency patches in private copies, preserving protectNTFS, and select the regression for Windows CI.
Replace the spelling-based mock inventory with one binding-aware Oxlint rule. Canonical test projects own isolation for both Vitest and lint; external temporary CLI probes avoid concurrent test discovery.
Validated actual local Git and Oxlint execution, resolved-policy parity, CI selection and report tests. Native Windows verification remains with CI. Refs: #7050
Use the domain-owned activity extra count in CLI parsing and advertisement. Preserve nested Rosetta registers at the selecting parser and qualified register projection, sharing the existing aggregate budget.
Port the Rosetta work from Adolanium commits 1889ac153 and c9e93bd88 in #6976, including morluto follow-up 07fa932ee. Add malformed-container and mixed-thread budget controls. CLI/MCP coverage uses a recorded ReportCrash excerpt in an authored report, without generating a native crash or contacting an Android device.
Refs: #6291, #6976, #6977
Co-authored-by: Adolanium <[email protected]>
Preserve primary copy failures, exact descriptor retry ownership and complete-session cleanup state. Make the authored JEB HTTP fixture join admitted callbacks after transport closure.
Validated with controlled real-file faults, cancellation/finalization and retry cases, plus local HTTP and existing CLI/MCP lifecycle regressions. No real IDA or JEB engine was exercised.
Remove the redundant async declaration from the Ghidra session assertion helper so its existing callers receive assertion failures within their synchronous error boundary. Keep call order unchanged.
Validation: a public-helper Node subprocess accepts authored valid handshake facts and rejects incomplete analysis and a target-digest mismatch. The regression failed for the original async declaration with Missing expected exception, then passed with the fix. No installed Ghidra execution was performed.
Clarify structural parsing, admitted facts and freshness, useful facade and compatibility responsibilities, immutable JSON proof, and partial Evidence retention. Document fixture cleanup ownership, semantic fault injection and the limits of static checks; extend the existing PR owner hint. Correct the session-record architecture label.
Validation: docs:check (including nine README consistency tests), rendered docs:build with link validation, touched Markdown formatting and git diff --check passed. Source and installed Vitest cleanup behavior were reviewed. No runtime behavior changed.
Turn recurring parser and projection failures into a selectable regression
guide covering format assumptions, raw identity, missing values, partial work,
independent limits, representation expansion, snapshots, and public delivery.
Link it from the agent instructions and PR template without adding checkboxes.
Clarify completed-observation ownership, digest representations, and exclusive
success/failure budget accounting. Preserve capacity fixtures and use byte
comparisons for large buffers to avoid diagnostic allocation blowups.
Passive page capture retained console entries and websocket frames with no
aggregate ceiling. Every sibling retention surface already enforces
WEB_RUNTIME_LIMITS.retainedEventBytes (8 MiB): the observation session's
pre-arm buffer and document-request identities, the browser runtime sources,
requests, and metadata, the V8 inspector's retained metadata, and this same
capture's script metadata, which has its own count-and-bytes budget. A page
that logs a few hundred megabytes of console text, or sends text frames whose
JSON shapes carry hundreds of thousands of keys, grew the capture without
limit until the process ran out of memory; the MCP response budget runs after
the handler, so the growth happened before any typed refusal could exist.
Admit each console entry and websocket frame against the same shared budget
before retaining it. A refused entry is counted through the completeness
tracker's dropped-events vocabulary, which already carries console_events and
websocket_frames kinds and was so far used only for late scripts, so the
inspection reports a truncated inventory with the dropped count instead of
silently overflowing. Console entry bytes measure the retained representation:
the entry's type, url, argument-type strings, and the text capture's retained
bytes, which the handler already computed per entry. A websocket frame retains
its shape summary rather than the payload, and the shape grows with the
payload's own keys, so the frame is charged the serialized size of the shape
it retains. beginAuthorizedFrame resets the counter together with the rest of
the per-frame state.
Out of scope: response metadata and agent hints, whose rows are fixed-shape
facts already bounded per response, and any new setting. The shared 8 MiB
constant is reused as-is.
Validation: RED then green in src/browser/CdpCaptureEvents.eventBudget.test.ts,
where the console case previously retained every oversized entry and the
websocket case retained the over-budget frame; 26 tests across the neighboring
console, websocket, coverage, and completeness suites pass. On this Windows
host the wider browser project has 26 pre-existing failures in three
Electron/WebBundle worker-spawn files, reproduced identically with this change
stashed (26 failed, 644 passed on the pristine base; 26 failed, 647 passed
with it on the same file set). tsc --noEmit over the changed set exits 0,
oxlint reports 0 errors, oxfmt --check is clean, and verify:module-boundaries
passes. No real browser session was driven on this host; the browser CI lane
owns that coverage.
Each retained entry now carries a conservative fixed overhead, and each captured console text value a wrapper cost, so a stream of minimal entries cannot admit millions of objects into the budget when shapes are disabled; a mixed-kind test locks that console entries and websocket frames spend one shared allowance.
overflow into the remediation and ended the reason with the session
continuation sentence, but the real-Ghidra boundary check still required
the old reason text, so every lane that runs verifyGhidraBoundaries failed
on real Ghidra.
* feat(environment): explain values an application derives from other fields
Prompt-built environments withheld creates whose responses carry values the
application derives deterministically, which the write model kept as
constants or could not match across calls:
- A composed string is literal text plus parts read from the fields other
rules write: a field's value, its slug, or a clock's calendar digits. A
create composes a string only when another entity of the type spells it
the same way and none spells it otherwise, and never from two sources
serving could tell apart; an update composes an unsent change from members
stored as sent and unchanged fields that also spell its value before the
call. A composed field no longer pins the members it reads.
- A trimmed clock format drops trailing fraction zeros, as Go spells
nanoseconds. It is learned from the type's values, a later create or a
later update, and spreads to the plan's other clocks unless a value shows
a fixed width.
- A large integer no entity of the type holds, among distinct ones of the
same length and kind, is a generated unique value, served as a seeded
integer.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the derived-values verification
Gates, tests, write plans over 69 recorded captures and served write tasks on the baseline and on this branch.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(environment): learn a create plan from every call
A later create the plan does not take is explained on its own and merged when both calls show the same fields, every field both rule they rule alike, and a field neither rules holds one value: members either call sent are accepted, only those every call sent are required, and an echoed member a call left out takes the value that call stored, kept in the body's defaults.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(environment): sorted arrays, referenced entities and nested view keys
- An echo is `sorted` when the application stored the sent strings in
code-point order; serving stores them sorted, and a plain echo and a
sorted one agree in update and create plans.
- A `reference` is an object field holding fields of the entity a sent
member names, as the state holds it. The member is accepted with any
value; replay and serving look the entity up, and serving refuses a call
naming one the environment does not hold.
- A view names in `nested_fields` the keys it always shows of objects it
shows with fewer keys than an entity stores; a stored object it never
recorded renders with them. The view spelling learner moves to its own
module.
- Every later create, not only one the plan refuses, is merged into its
plan when it agrees, keeping the plan's rule order.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep clock spellings, linked ids and word boundaries honest
- A later update's clocks take the plan's spelling, sibling-trimmed
clocks included, wherever the call's values fit it, so an update whose
later call trims only one of two clocks is served.
- A held value that ends its fraction in a zero keeps a create's clock
at a fixed width, whatever order the held spellings come in.
- A large integer that another field of the created entity also holds
is linked, as a repeated token is: it is never unique, and the create
is withheld as unexplained-change.
- Composed parts are delimited by whole characters through the shared
joinsBefore/joinsAfter, so an astral letter joins a match to its word.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(environment): keep a same-width fixed clock out of trimming
A held .123456780 beside a held .12345678 keeps the create's clock at
nine digits in either order; the cases fail on 8ce1127b5.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the create-calls verification
Gates, tests, write plans over 69 recorded captures and served write tasks on the derived-values baseline and on this branch.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): note the create-calls census on current main
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): check composed parts and clock fits before they shape a plan
- A composed string whose part has nothing to spell refuses the create
or update through the apply Result instead of keeping a stale value.
- A composition learned on a later call is rebuilt from each earlier
call's fields, so an earlier call that left the value otherwise
contradicts it.
- An update adopts its fitted clock spellings only after the
unknown-entity and contradiction checks, so a call on an entity an
unmodelled write left unknown no longer trims a served plan's clock.
- Sibling trimming on a later create also checks that call's fields,
so a sibling clock it shows with a trailing zero stays fixed-width.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(environment): split the derived-values view tests by rule
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep fixed-width, zone and generated-integer evidence through a plan
- A plan keeps the first value that showed each clock at a fixed width,
from held entities and every accepted create or update. No later fit
or sibling trim widens that field, and a later call that shows it
shorter is withheld.
- Two stamped clocks are one composed source only when they share a
zone offset. A held entity that holds the target field as anything
the parts do not spell, a non-string included, vetoes the
composition. The token index is built once, and only when a string is
left to compose.
- A generated integer that another field repeats as a number at any
depth is linked. Compare treats two integers of one JSON kind and
length under a unique rule as generated values.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep optional references across create calls and in answers
- A reference a later create added stays while further creates leave its
member out, and agrees with a later call that shows it again.
- A create's answer shows optional reference and echo fields only when the
call wrote them, whichever recorded call the answer came from.
- An update that re-sends the id of the entity a field already repeats keeps
the plan's reference instead of pinning the member.
- An id naming entities of one type in several collections teaches no
reference, and serving or replay refuses a call that names one.
- An echo is not promoted to sorted once a call stored its strings out of
code-point order as sent.
- Nested view keys compare as sets and keep the first recording's order.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(setup): share registration prewarm host preparation
* fix(environment): retain write evidence and match trimmed response clocks
* fix(environment): withhold creates whose generated integer another string repeats
A unique integer whose digits show in another top-level string that no
template or composed rule rebuilds from it (an echoed serialText, or a
token like folder-<id>) withholds the create as unexplained-change,
since serving would seed the integer and keep the string. A templated
copy is still served.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): respect earlier clock widths and left-out members in later creates
- The create merge widens a clock to trimmed only against the value that
showed its width: a held entity or accepted call at a fixed width keeps it
untrimmed.
- A later create that left out a member the plan fills, with a default or a
reference's absence, while its observation shows that field otherwise is
unexplained-change, so the plan cannot serve the stale value.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): hold later creates and compare to the composed and integer forms
- A later create whose response spells a composed field otherwise than
the plan rebuilds it is withheld as unexplained-change.
- A unique field learned from a generated integer accepts only an
integer of the same length and kind from a later create, as serving
seeds one.
- Compare counts a composed field as equal when each side's response
spells it from its own fields, which compare under their own rules.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): preserve composed parts and unique generator families
* fix(environment): reject contradictory create references
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
Remove duplicate root lists and teardown deletion for directories already owned by createTestTempDirectory. Retain independent IDA workspaces, runtime closure, environment resets, permission recovery and explicit deletion assertions.
Validation: all nine affected suites passed (126 tests); installed Vitest cleanup ordering reviewed. Provider protocols use authored fixtures, not installed IDA or Ghidra.
Decode optional-header declarations once and pass detached directory words, locations and SizeOfHeaders to native consumers. Preserve executable machine admission, raw GPU/resource machine reporting, RVA mapping and certificate file-offset semantics.
Validation: fresh build/catalog, full static checks, 466 core/provider fixture tests, 122 workflow tests and 14 selected file-backed PE admission tests passed. Public CLI and actual stdio MCP used authored artifacts; installed external providers were not qualified. Added 17 structural cases and two GPU machine-policy controls. Eager directory decoding costs remain unmeasured.
Carry the command identity already parsed during registration inspection into maintenance selection. Keep activation, validity and public status output separate.
Validation: fresh build/catalog and full static checks; registration status, update maintenance and setup cleanup ownership suites passed (90 tests).
Return typed fetch outcomes with completed map coverage when acquisition is
cancelled or a response resource fails. Compose those facts with the captured
inspection as partial bundle Evidence, preserving exclusions, exact abort causes,
and cleanup priority without claiming unperformed script analysis.
Keep complete response-body SHA-256 and byte counts when map interpretation
fails, while preserving compact failure rows and capacity for later valid maps.
Reuse the read owner digest for successful text artifacts and preflight their
JSON representation before parsing. Historical failed rows remain importable.
Exercise controlled HTTP/stream boundaries, CLI SIGINT, and SDK cancellation
with later MCP Evidence retrieval. Share the public cancellation fixture and
use one Result API across consumers. Real Chromium and Windows CLI cancellation
were not verified.
* feat(environment): explain values an application derives from other fields
Prompt-built environments withheld creates whose responses carry values the
application derives deterministically, which the write model kept as
constants or could not match across calls:
- A composed string is literal text plus parts read from the fields other
rules write: a field's value, its slug, or a clock's calendar digits. A
create composes a string only when another entity of the type spells it
the same way and none spells it otherwise, and never from two sources
serving could tell apart; an update composes an unsent change from members
stored as sent and unchanged fields that also spell its value before the
call. A composed field no longer pins the members it reads.
- A trimmed clock format drops trailing fraction zeros, as Go spells
nanoseconds. It is learned from the type's values, a later create or a
later update, and spreads to the plan's other clocks unless a value shows
a fixed width.
- A large integer no entity of the type holds, among distinct ones of the
same length and kind, is a generated unique value, served as a seeded
integer.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the derived-values verification
Gates, tests, write plans over 69 recorded captures and served write tasks on the baseline and on this branch.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep clock spellings, linked ids and word boundaries honest
- A later update's clocks take the plan's spelling, sibling-trimmed
clocks included, wherever the call's values fit it, so an update whose
later call trims only one of two clocks is served.
- A held value that ends its fraction in a zero keeps a create's clock
at a fixed width, whatever order the held spellings come in.
- A large integer that another field of the created entity also holds
is linked, as a repeated token is: it is never unique, and the create
is withheld as unexplained-change.
- Composed parts are delimited by whole characters through the shared
joinsBefore/joinsAfter, so an astral letter joins a match to its word.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(environment): keep a same-width fixed clock out of trimming
A held .123456780 beside a held .12345678 keeps the create's clock at
nine digits in either order; the cases fail on 8ce1127b5.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): check composed parts and clock fits before they shape a plan
- A composed string whose part has nothing to spell refuses the create
or update through the apply Result instead of keeping a stale value.
- A composition learned on a later call is rebuilt from each earlier
call's fields, so an earlier call that left the value otherwise
contradicts it.
- An update adopts its fitted clock spellings only after the
unknown-entity and contradiction checks, so a call on an entity an
unmodelled write left unknown no longer trims a served plan's clock.
- Sibling trimming on a later create also checks that call's fields,
so a sibling clock it shows with a trailing zero stays fixed-width.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(environment): split the derived-values view tests by rule
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep fixed-width, zone and generated-integer evidence through a plan
- A plan keeps the first value that showed each clock at a fixed width,
from held entities and every accepted create or update. No later fit
or sibling trim widens that field, and a later call that shows it
shorter is withheld.
- Two stamped clocks are one composed source only when they share a
zone offset. A held entity that holds the target field as anything
the parts do not spell, a non-string included, vetoes the
composition. The token index is built once, and only when a string is
left to compose.
- A generated integer that another field repeats as a number at any
depth is linked. Compare treats two integers of one JSON kind and
length under a unique rule as generated values.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(setup): share registration prewarm host preparation
* fix(environment): retain write evidence and match trimmed response clocks
* fix(environment): withhold creates whose generated integer another string repeats
A unique integer whose digits show in another top-level string that no
template or composed rule rebuilds from it (an echoed serialText, or a
token like folder-<id>) withholds the create as unexplained-change,
since serving would seed the integer and keep the string. A templated
copy is still served.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): hold later creates and compare to the composed and integer forms
- A later create whose response spells a composed field otherwise than
the plan rebuilds it is withheld as unexplained-change.
- A unique field learned from a generated integer accepts only an
integer of the same length and kind from a later create, as serving
seeds one.
- Compare counts a composed field as equal when each side's response
spells it from its own fields, which compare under their own rules.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): preserve composed parts and unique generator families
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
Give ordinary Evidence creation an explicit unknown-payload input contract
while retaining the strong JSON contract for producer helpers and cooperative
immutable creation. Keep schema admission, input snapshotting and identity
hashing with the Evidence owner.
Remove 32 generic JSON preparses that only fed ordinary Evidence construction.
Preserve semantic format validation, selected-source bindings, standalone
JSON boundaries, typed executions and scenario digest contracts. Invalid JSON
now reports its Evidence parameters/normalized_result/raw_result prefix.
Validation: fresh runtime/catalog build, 560 focused and README tests passed,
4 platform-specific cases skipped, full static/docs checks, test discovery,
duplication and diff checks. New regressions cover omitted semantic optionals,
raw-result defaults and nested undefined refusal without input mutation.
Installed providers, real browsers/Frida/JADX and Linux-only recovery remain
unverified; boundary providers are authored fixtures.
Carry the final artifact inspection's exact nested source Evidence through
AnalysisExecution. Derive links in the shared Evidence builder instead of
reparsing the result in CLI and MCP adapters. Retain validation for unknown
and historical Evidence inputs.
Move the shared source recorder into application ownership and migrate its
consumers. Record sources before parents; keep source recording failures
from publishing summaries. Decline snapshot entries whose source closure the
current entry format cannot represent, while retaining investigation Evidence.
Validation: actual ASAR regression failed before the change with missing
links and passes afterward; exact nested identity, source recorder refusal,
final-close cancellation and cleanup failure, historical authentication,
snapshot controls and public CLI/MCP workflows. Fresh runtime/catalog build,
full static/docs, discovery and duplication checks pass. Installed native
providers and platform-specific skipped cases remain unverified.
Return native admission issues and an explicit Hopper timeout result from
the configuration owner. Doctor consumes those parsed facts instead of raw
timeout text plus a separate issue list. Reuse a successful aggregate parse;
validate the individual timeout independently when other settings reject it.
Preserve aggregate error precedence, JEB isolation, omission, constraints,
causes and provider scope. Keep partial diagnostics when unrelated NUL,
loader arguments, language selection or timeout settings are invalid.
Validation: configuration and Doctor workflow regressions, mixed-invalid
settings, full static/docs checks. No installed provider was exercised.
Keep completed module and candidate identities, glue observations, and the
admitted tool profile when WABT validation or later inspection fails. Recover
stable reads from their existing owner when descriptor finalization fails;
mark unparsed glue explicitly and preserve validation uncertainty. Forward
partial Evidence through output/cleanup errors and preserve pre-abort reasons.
Exercise producer failures, partial acquisition, decoding, finalization and
cleanup retry with simulated owned WABT commands. Public CLI and stdio MCP
coverage follows the retained Evidence reference through get_evidence_bundle.
Real WABT 1.0.42 and the Windows shell-fixture lane were not verified.
* fix(il2cpp): accept arm64 module arrays loaded through adrp/add pairs
A Unity 2022.3 macOS Master (LTO) arm64 build keeps no static CodeRegistration, so the module-array fallback that only decoded x86-64 RIP-relative references reported code-registration-not-found.
The registration owner now also decodes aligned adrp + add pairs in executable ranges and keeps the same exact-module-set and single-reference rules.
A minimal Mach-O fixture failed on the previous reader (47 passed / 1 failed) and passes here with four fail-closed variants (48/48 binary tests).
* fix(il2cpp): name the matched instruction form in inferred module-array limits
The inferred-array limitation always described RIP-relative LEA/MOV, which is wrong for arm64 results.
The provider now names the adrp/add pair on arm64, and the tool contract and docs cover both forms and state that a located array alone does not finish linking a Master build.
The new arm64 provider case failed before the wording change (1 passed / 1 failed) and both cases pass now.
* fix(il2cpp): accept type tables loaded without a static MetadataRegistration
A Unity 2022.3.62f3 macOS Master build inlines MetadataRegistration as well as CodeRegistration, so linking stopped at metadata-registration-not-found after the module array was found. Registration now infers the only field linking reads, the Il2CppType table, from the one run of type-shaped pointers that covers every referenced type index and whose start is loaded by the existing RIP-relative or adrp/add forms; types_field is null and the Evidence is inferred. The new arm64 and x86-64 fixtures failed on the previous reader (52 passed / 2 failed). Four run-selection variants (interior reference, run extended before the loaded address, two loaded runs, run shorter than the referenced indices) keep metadata-registration-not-found; instruction decoding and record-shape checks are not covered by these fixtures.
* test(il2cpp): pin adrp page deltas, register pairing and type-record shape
Every adrp fixture targeted its own 4 KiB page, so dropping the page delta or its sign extension, the add register check, the type-kind bound or the type-definition bound left all binary tests passing. Fixtures now reach a later and an earlier page, pair an add with a different destination or source register, break the type run with an out-of-range kind or type-definition index, and bound type-table candidates when the metadata references few type indices. Each of those five source mutations now fails 1 to 3 of 85 binary and provider tests.
* refactor(il2cpp): share Il2CppType kind decoding and document type-table bounds
The type-table fallback decoded the Il2CppType kind and class/value-type kinds separately from the type namer; both now use the Types owner. Zero and unaligned words are rejected before mapping lookup (Master sample metadata-registration search 92 to 68 ms). Docs and the limitation state that types_count is an upper bound, that a run spanning mappings or a small referenced type range can fail, and credit Cpp2IL StrippedCodeRegSupport and the data-side MetadataRegistration searches of Il2CppDumper and Cpp2IL. Master sample output is unchanged (11,031 code addresses, 37,025 type rows).
* fix(il2cpp): refuse generic instances when the type table was inferred
An inferred type table has no static MetadataRegistration, so the
genericMethodTable it would anchor cannot be located. Report
generic-methods-unsupported instead of reading from a null field.
* fix(il2cpp): fail closed when an inferred type table is not unique
Adversarial review found that the type-table fallback could pick another
type-shaped pointer table when the real one was unloaded or excluded, could
replace a static MetadataRegistration whose counts matched, and accepted a
run cut short by a mapping end. Require exactly one long-enough run in the
image, ending inside its mapping and loaded by code; skip the fallback when a
record's two counts matched; accept only assigned Il2CppTypeEnum kinds; and
look records up through the indexed file mapping so many mappings cannot
multiply the scan. Docs and limitations now describe the run length as at
least every referenced type index rather than an upper bound.
* fix(il2cpp): keep the type-table fallback cheap and its refusals exact
Review follow-ups: check that an address can lie in a mapping before the
throwing indexed lookup, so words pointing into gaps or zero-fill no longer
build an exception each (64 MiB: 74 s to under 2 s); treat a run starting at
its mapping start like one reaching its end; stop at the second long-enough
run instead of a 64-candidate capacity error; ignore ADRP/ADD pairs on
register 31; and say whether a counted MetadataRegistration was unusable or
no code-loaded run was found. Docs no longer generalize from one build or
state tool history they do not source.
* fix(il2cpp): judge type-table slots by their loaded value
The run scan read stored words, so a dyld-bound slot's placeholder could
decide whether a run qualified. Confirm each slot through readSlot and give
a run bounded by a bound or unresolved slot an unknown extent, so the
placeholder no longer changes the choice.
* docs(il2cpp): keep the failure-reason table layout
Shorten the two changed meanings so the table keeps its column widths and the
diff shows only those rows.
* docs(il2cpp): keep the reason table at its formatted width
* fix(il2cpp): read type-table record fields through the loader too
The previous change confirmed table slots through readSlot but still read
each record's kind and definition index from stored bytes. Read them with
readUInt32 and readSlot, and treat a record field the loader binds or leaves
unresolved like an unresolved slot: the run it bounds has an unknown extent.
* perf(il2cpp): share image mappings across loader-aware reads
---------
Co-authored-by: morluto <[email protected]>
Separate typed manifest/capture composition from unknown-input loading.
Builds retain the admitted replay facts locally for credential warnings and
record counts instead of parsing the same capture again. Keep full captures
out of the compact replay source and preserve manifest-first authentication,
parent identity checks, failure precedence and cancellation points.
Validation: environment source/build/report/scenario/input-snapshot/state
workflows and public build CLI; fresh runtime/catalog build, full static/docs,
test discovery and duplication checks. No external clients or targets ran.
Use the existing named-contract retained-summary handler for pcap capture
inspection. Remove its duplicate validation, detail selection, preflight and
Evidence projection policy while preserving client inspection separately.
Validation: named pcap MCP schema/delivery, parent issue attribution and
workspace admission tests; fresh runtime/catalog build and full static/docs
checks. Native packet dissection and Linux-only retained-view tests were not
verified on this macOS host.
Return the validated descriptor and its original metadata from regular-file
admission. Propagate that contract through owned reads, hashes, snapshots,
artifact inventory and provider file workflows instead of replacing initial
facts with another stat. Keep arbitrary output-handle operations separate.
Preserve final descriptor/path identity proofs, borrowed-source verification,
BigInt precision, cancellation provenance and failed-close ownership. Remove
the obsolete source and owned-ZIP baseline stages and update their consumers
and regressions. Tie read completion faults to actual reads instead of the
retired duplicate stat; instrument real handles without fake handle wrappers.
Validation: fresh runtime/catalog build; focused source, lifecycle, filesystem,
CLI/MCP and authored provider-fixture tests; full static checks; docs checks;
test discovery; duplication check. Platform-specific cases remain skipped on
macOS. No installed provider or device behavior was verified.
The IPS JSON reader decodes \uXXXX escapes with String.fromCharCode and
returns raw slices verbatim, so an escaped unpaired surrogate reaches
Evidence as-is: malformed text reported under complete coverage, with no
refusal and no uncertainty. A crash report's procName or exception message
comes from the crashed process, so the escape is reachable input.
Refuse the string the way the parser already refuses other malformed
content. The check runs on the decoded value, so it covers escaped and
unescaped text alike, and a high surrogate followed by its low surrogate
escape stays valid text.
Validation: RED then green in src/native/apple/losslessJson.test.ts, where
the new case previously accepted the escaped surrogate; 311 tests across
the apple parser suites pass; tsc --noEmit over the changed set exits 0;
oxlint reports 0 errors; oxfmt --check is clean; verify:module-boundaries
passes.
Co-authored-by: morluto <[email protected]>
Flatten the prewarm cases so suite grouping does not exceed the function-size gate. Let createTestTempDirectory own cleanup instead of deleting the same roots from a second afterEach owner. Preserve all registration and warning assertions.
Validation: all four focused filesystem cases passed using temporary client configurations and injected prewarm results; no package runner or provider was launched.
Use the shared source owner for Mach-O and PyInstaller admission, descriptor and selected-path identity, hashing and cleanup. Retain lipo joining and reader-owned PyInstaller admission, caller cancellation and private PYZ leases. Centralize admission failure projection and remove the superseded PyInstaller wrapper.
Preserve physical identity verification before late hash-completion cancellation. Close an owned source before returning failed initial metadata acquisition and retain the exact handle when close fails. A focused regression failed twice before that fix and now passes.
Validation: fresh runtime build, 259 focused fixture tests, nine documentation checks and all local static/discovery/duplication gates passed. An earlier check also ran four system-lipo suite cases (three read-only native inspections) before the final source fix; those were excluded from subsequent fixture qualification.
* fix(hopper): keep installed apt dependencies at their versions during Linux setup
apt-get install upgrades every listed package that is already installed, so Linux setup could upgrade the system python3 and X11 libraries while installing Hopper. Runtime dependencies are now installed with --no-upgrade in a separate transaction before the Hopper archive, which may still upgrade. The setup approval plan lists both commands.
* fix(hopper): narrow the apt upgrade claim and cover split transaction failures
* fix(evidence): preserve JSON ownership through metadata updates
---------
Co-authored-by: morluto <[email protected]>
* fix(setup): materialize the pinned package-runner cache before the first client start
Package runners key their package cache by the requested spec, so the
entry installed for the @latest invocation that ran setup cannot serve
the pinned rea-agents@<version> registration. The first client start
installed that entry inside the client's MCP startup deadline and timed
out (three consecutive 30 s timeouts observed in one client log; a
controlled cold install with every tarball already cached took 22 s).
Setup now materializes the pinned entry once after applying
registrations: best-effort, bounded by a timeout, launched from a
neutral working directory, and non-fatal on failure. The setup result
carries the prewarm summary, interactive output prints a warning when
the step fails, and direct launcher registrations keep skipping it.
Fixes#7027
* fix(setup): gate prewarm to applied registrations and supervise the runner tree
Address review findings on the prewarm step:
- Gate the prewarm on at least one applied client registration
(configured_<client>), so an empty plan or a skill-only run never
installs into the package-runner cache; the step now only follows
registrations the user approved in this transaction.
- Replace execFileOutput with a supervised spawn: on timeout the whole
runner tree stops through cleanupWindowsProcessTree on Windows and a
process-group kill on POSIX, because killing only the direct child
leaves npm holding the inherited output pipes past the deadline.
- Emit started and completed progress events around the prewarm so an
interactive cold install no longer looks like a frozen setup.
* fix(setup): forward terminal interrupts to the detached prewarm runner
A detached POSIX package-runner group no longer receives the terminal's
Ctrl-C, so setup could exit while the runner kept installing in the
background. The supervised launch now registers SIGINT and SIGTERM
forwarding for the duration of the prewarm: the runner tree is stopped
through the same family cleanup as the timeout, and the default
termination is restored afterwards. An interrupted launch reports a
failure reason instead of a hang.
Transfer the inventoried ZIP descriptor after inventory reader cleanup, then
borrow it for materialization instead of reopening the pathname. Release the
exact owner before publishing output; preserve failed owners for cleanup retry
and completed inventory facts through cancellation or later tagged failures.
This uses the existing admitted-descriptor reader API without a third carrier
hash pass. Remove the superseded materialization wrapper.
Cover identical-member carrier replacement, directory/missing replacements,
late cancellation at both handoff and final close, mixed cleanup outcomes and
retry. Root-owner test seams preserve real output-handle cleanup. Compiled
CLI/MCP ZIP, archive and report regressions also run; no benchmark is claimed.
Keep observed empty JSON strings separate from missing fields in IPS process,
image, frame, register and OS-version facts. Preserve empty unlisted keys,
retain malformed UUID source text, and keep unknown architecture interpretation
separate from raw spelling. Classification excludes empty supporting fields.
Validate producer cases plus compiled CLI and stdio MCP delivery against the
same output contract. This is saved-report inspection, without target execution.
Publish Godot res:// declarations and PyInstaller CArchive/PYZ keys through
shared occurrence source_path while preserving safe logical extraction paths.
Consolidate PyInstaller file, directory and namespace projection through one
owner, and account for the additional retained source spelling before allocation.
Cover producer inventory, Windows separator conversion, PYZ module/data keys,
CLI extraction bytes and retained MCP inventory views. Format fixtures are
synthetic; real Godot/PyInstaller producer lanes were not run.
Compose one source owner for Godot PCK and Node SEA admission, descriptor identity, carrier hash binding and retained handle cleanup. Preserve format-specific parsing and member streams, drain their reader operations before source close, and leave borrowed descriptor release with its caller.
Validation: runtime build and 136 focused tests passed, including 17 real-descriptor integration cases for delayed admission, cached hash mismatch, close failure and retry, borrowed handles, admission cleanup cancellation and mixed peer outcomes. Tests use local authored carriers and controlled failure seams.
Separate raw SEA names from safe logical extraction paths. Accept empty asset
keys, retain absolute main paths and conflicting source spellings, and assign
deterministic paths through the shared artifact path registry. Keep duplicate
raw keys malformed and include sourcePath in owned entry equality.
Validate 102 focused regressions including compiled CLI and stdio MCP inventory
and extraction, the canonical SDK schema case, 9 documentation consistency
cases, cached build, typecheck/lint and formatting. A pinned Node-generated
preparation blob is verified in a synthetic ELF carrier; real injected native
executables and the optional Docker lane were not run.
Parse the original unframed module bytes for every build-info result. Remove the duplicate text facade and string-source branch while retaining observed text, framed bytes, malformed lines, quoting and replacement semantics.
Validation: 163 Go parser, image, provider and public CLI/MCP tests passed using local binary fixtures; build, static and documentation checks passed.
Require the immutable Evidence read APIs already implemented by production owners. Remove the detached-only compatibility fallbacks and forwarding helpers, and bind consumers directly to their owner. Preserve editable detached exports and existing snapshot semantics.
Use the shared canonical CLI error classifier for process commands instead of reinterpreting their projection. Validation: 172 focused application and process tests, build, static checks and documentation checks passed using local fixtures.
Specialize the buffer-backed directory driver for its actual ELF consumers and remove the unused PE branch. Share PE subject architecture interpretation at the existing machine owner, preserving unknowns for conflicting formats and unproven managed overrides.
Validation: runtime build and 108 focused service, native parser, GPU, and CLI/MCP tests passed using local fixtures. Live descriptor-backed PE readers remain supported.
Construct the canonical ToolResultDelivery through the native continuation policy factory. Move type and lifecycle spy consumers to the core owner while preserving explicit response budgets and the deferred runtime composition.
Validation: runtime build and 335 focused tests passed; 41 Linux-only firmware cases were skipped on macOS. Tests use authored local fixtures, not real external providers.
Preserve the verbatim direct CLI selection in caller_input_path, separate from canonical subject identity and provider/query parameters. Fresh publication uses the existing immutable metadata import path so provider auto-recording cannot discard request provenance. Replay returns the current selection without rewriting stored Evidence or partitioning the cache by alias. Historical records without the optional field still authenticate.
Use the domain semantic projection for ledger agreement, remove the duplicate projection and subject-only replacement names, and preserve request metadata at same-invocation summary delivery. Later retained-view questions do not inherit that context. Existing one-shot parameters.input_path remains for compatibility.
Validation: 149 focused tests, 28 public CLI/MCP cases, all canonical advertised schemas through the pinned SDK, and nine documentation tests passed across the affected checks. Build, typecheck/lint, and formatting passed. Two Windows-only replay cases were skipped on macOS. Native macOS and managed fixtures were exercised; no Hopper/Ghidra/IDA runtime was started.
* fix(android): report DEX static values of static final fields
Fixes#6397
* fix(android): request DEX static values only for class inspection
* fix(android): range-check wide DEX static values
* fix(android): move the bridge to version 7 after main took 6
---------
Co-authored-by: Abelo9996 <[email protected]>
* feat(artifacts): inventory and extract Node.js single executable application blobs
Adds a node-sea artifact reader that locates the NODE_SEA_BLOB payload in
Mach-O sections, ELF notes and PE RCDATA resources, decodes the blob
header, main script, optional snapshot and code cache, and named assets,
and extracts their stored bytes through the existing safe output tree.
The executable is never run. Resource-tree errors in a PE without a
NODE_SEA_BLOB name stay with native classification; truncated, unknown
or over-limit SEA declarations fail closed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe
* fix(artifacts): reuse PE resource facts and bound SEA asset tables
Move the bounded NODE_SEA_BLOB name probe into the shared PE resource
layout module so SEA admission uses the same header and section mapping
as the full parser; the layout reader now accepts a header prefix with
the file size. Bound SEA asset count and decoded name bytes before
records are created and report resource bounds as limit failures. Offer
the JavaScript next probe only for main scripts with a source suffix.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe
* fix(artifacts): make SEA metadata construction cancellable
---------
Co-authored-by: Matt Van Horn <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
* fix(targets): keep original DOS padding out of e_lfanew
A complete DOS header with a nonempty relocation table that ended before
e_lfanew treated the padding dword at 0x3c as a Windows declaration. Without
a recognized Windows signature, fall back to the validated DOS structure so
original DOS images are not refused as malformed Windows targets. Preserve
unresolved-candidate handling when no relocation table delimits the padding.
* test(ghidra): cover DOS padding and unresolved header candidates
* fix(targets): read Windows signatures before dismissing DOS padding
* docs(targets): reconcile DOS padding admission contract
Document that relocation-table padding inside a complete DOS header is DOS data, while an unread Windows signature beyond the current probe is requested before that rule applies.
Aligns docs/installation.md with docs/ghidra-dos.md after the MZ admission fix.
---------
Co-authored-by: dhruvac29 <[email protected]>
Retain the exact selected CLI path in one-shot provider Evidence while preserving canonical subject identity and provider inputs. The shared request-provenance boundary replaces the artifact-only special case across native, managed, and bundle-resource routes. Remove the redundant parameter fallback and make the private managed helper receive explicit Evidence parameters.
Validation: real macOS codesign fixtures through the compiled CLI retained app aliases for signature, plist, and absent asset inspections, with direct-target controls. Archive selection, managed direct analysis, and snapshot replay regressions passed; Windows-specific replay cases were skipped on macOS. Build, static, format, and docs checks passed. Snapshot-backed direct request provenance still follows its existing authenticated query contract.
Refs: #5479
Hash the observed database version with object-store definitions at the CDP boundary. Missing, invalid, or imprecise versions preserve store evidence with incomplete coverage and an explanation. Mark the revised projection so historical store-only hashes cannot create false changes or prove unchanged versions. Preserve comparable metadata and independent storage changes.
Remove the redundant storage comparability wrapper and use each fingerprint's parsed scope instead of interpreting its identity string.
Validation: producer-to-comparison regressions and a compiled CLI to stdio MCP comparison passed, including version-only changes, invalid versions, legacy projections, and complete database additions/removals. Static and docs checks passed. CDP responses were simulated; no real browser runtime was exercised.
Explain unreadable ELF note section names without discarding complete note coverage. Keep export and PE import rows when only version or DLL-name metadata is unresolved, and stop claiming those retained rows were unreported.
Use native byte equality for the 4 MiB ELF extended-numbering source-preservation checks; generic deep equality enumerated every buffer byte and exhausted the test worker heap. The full fixture and byte coverage remain.
Validation: focused ELF note, native export, and PE import regressions plus complete CLI/MCP adapter files passed under the existing 512 MiB heap limit. Build, typecheck/lint, formatting, and documentation checks passed.
* fix(ghidra): admit recordless MIPS-I legacy targets
MIPS-I headers carry a zero-value ISA field (EF_MIPS_ARCH_1) and predate the ABI flags record. The recordless legacy admission only accepted EF_MIPS_ARCH_32 and EF_MIPS_ARCH_32R2, so every MIPS-I target was refused before provider selection even when its ELF32/ET_EXEC shape matched the existing inferred-o32 lane.
Admit MIPS-I through the same recordless legacy path, pin the endian-matched 32-bit MIPS language, and use a distinct support-lane identity so profile-bound snapshots invalidate. Declared-ABI MIPS-I headers remain refused because that lane is verified for MIPS32r2 only. The session reports that the generic 32-bit language also decodes later MIPS32 instructions and that MIPS-I subset conformance is not established from the header.
Fixes#6933.
* fix(ghidra): bind MIPS profiles to their target
Refuse a committed MIPS lane or ELF metadata that was resolved for a different target, including the same-endian MIPS-I and MIPS32 legacy lanes that share a language pin. Report the committed caller-selected MIPS-I language in the session limitation instead of claiming the provider pin.
---------
Co-authored-by: dhruvac29 <[email protected]>
* feat(environment): report what an environment serves with an environment-coverage view
A new inspect_analysis_view kind over capture Evidence. It projects the
state an environment derives with the given template rules and reports
each tool as answered from state, replayed with its view reason, a served
write, or a withheld write with its reason, the records behind it and a
hint about what to record next. The hints cover every write reason, so a
new reason without one fails to compile.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(environment): build an environment bundle in one command
rea environment-build <capture> [directory] inspects a HAR (or reads
capture Evidence), projects the environment manifest from the in-memory
Evidence, authenticates the pair, prepares the state and writes the bundle
environment-export writes. Every bundle file is byte-identical to the
three-step path for the same capture and options.
The report adds the capture and manifest identities, the coverage summary,
warnings (a loopback capture named after its file, credential-named body
members by pointer) and the next command. --dry-run writes nothing. The
default template rules are the four the published environments use.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(environment): cover environment-build and the coverage view
Domain tests check the hint table against the state view's reasons, the
summary, and the view against the environment-state view it summarizes.
Service tests build the fixture capture and compare every file with the
three-step path, a dry run, loopback naming and the refusals. A CLI test
compares a HAR built in one step with the three CLI steps byte for byte,
and an MCP test projects the view from every source kind.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(environment): build the real-agentenv lane's bundle with environment-build
The lane now runs the command users run: it builds the Grafana-shaped HAR
with environment-build and the packed checkout, checks the report, then
runs the bundle with agent-env as before.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): document environment-build and the coverage view
The agent environments guide opens with the one-step build: the report,
the hint for each withheld write reason, and what a bundle ships. The CLI
guide, the capture guide and the skill reference name the command and the
environment-coverage view.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): harden environment-build after review
- The credential scan walks with its own stack, so a deeply nested body
cannot crash the build, and it also reports credential-named header
names, query names, form body members and string arrays.
- The build checks SIGINT between stages: cancelled before the bundle
stage it writes nothing, during the write it names the written bundle.
- A dry run opens the package tarball, so it refuses what a build refuses.
- Repeated template rules are refused, a HAR saved as .json gets a hint,
file-derived names follow the bundle name rules, `localhost.` counts as
a loopback origin, and the next command is shell-quoted.
- --capture-timeout-ms passes through to the HAR inspection, and a
missing directory is refused before inspection.
- The no-observation hint covers updates and deletes of entities the state
never held; the coverage view states that it does not apply the
serve-time admission checks; the inspect_analysis_view description
names the view.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): state the build's conditions and record its verification
The guides now state when the one-step bundle equals the three-step one,
which headers inspection excludes, what the credential warning scans, how
cancellation behaves, and that the coverage view does not apply the
serve-time admission checks. The spec folder records the census, the end
to end runs, the gates and the review.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): dispatch a pending interrupt before each build stage check
The manifest, state and coverage stages run synchronously, so a SIGINT
that arrived during them was only dispatched once the bundle write had
begun. Each check now yields first, so an interrupt before the bundle
stage cancels the build with nothing written.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): scan scenario credentials, own the dry-run tarball and serialize Evidence once
A browser scenario's retained header values and the query parameters of its recorded URLs are scanned for credential
names as a HAR's are, through a review projection of its records. A dry run admits and releases the package tarball
through the export's regular-file scope, so a close it cannot confirm keeps its owner, and checks for cancellation
after that last await. Evidence is written into one exactly sized buffer instead of chunks joined by a copy.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* style(environment): format the build spec
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): scan every form occurrence and MIME-less scenario bodies
The build's credential scan collapsed form bodies with Object.fromEntries, so a
repeated field kept only its last occurrence: `api_key=secret&api_key=` warned
about nothing although the Evidence ships the value, and repeated values were
undercounted. Form fields are now scanned as ordered name/value pairs, as
headers and query strings already are.
The review projection of a capture_browser_scenario dropped a request body
recorded without a media type, so the scan never saw it. Review keeps such a
body's text with an empty media type; the manifest projection still reads only
bodies it can classify.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): scan structured HAR form params and the request side of unattributed scenario transactions
A HAR request recorded with postData.params and no text is scanned by those parameters, each occurrence counting, and
the review projection keeps the request side of a scenario transaction whose response cannot be attributed, so the
credential warning covers what evidence.json ships in both cases.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): validate build paths and read dry-run tarballs
* fix(environment): report bodies too large for the credential scan
Text bodies over the scan's 4 MiB limit, including a response decoded only as a prefix, are reported as a
credential-scan-incomplete warning by record and side, never by content, so an absent credential-named-members
warning no longer reads as a complete check. The spec and agent-environments guide also state the path validation and
dry-run tarball read that e52ae1cd added.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(verification): release cold source transform services
* fix(javascript): retain capture context along covered mutation paths
* fix(environment): admit serialized exports and scan HAR form fallbacks
* fix(environment): admit in-memory build inputs against heap headroom and scan SaveHar null-text forms
The inspected HAR's Evidence and the projected manifest are checked against live heap headroom before they are
serialized, with the same check the file route uses, so a capture too large to parse and seal is refused as
resource_constraint before anything is written. A request whose postData text is SaveHar's null is scanned by its
structured params.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): measure the credential scan limit in UTF-8 bytes
A body counts against the 4 MiB limit by its UTF-8 length, not its UTF-16 code units, so multibyte text over the
limit is reported as unscanned instead of parsed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(javascript): erase inline type imports before binding values
* fix(environment): parse credential form bodies by their media type
* fix(environment): review untyped retained form fields
* fix(environment): bound request comparisons and preserve write proofs
* fix(environment): keep write proofs and bundle review complete
* fix(environment): finalize entity overrides with simulated views
* test(environment): restore 0895c89b's untyped form tests and hint
Integrating main took main's credential scan and coverage view, which
dropped 0895c89b's tests and its body-unusable hint. Main's scan passes
the tests, now reading the scenario by event. The hint names the
response too, since extraction and serving also withhold a write as
body-unusable when its recorded response cannot be read.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(environment): scan a scenario content event recorded twice
Main's event scan reads both content events of a transaction whose
content the capture recorded twice; the test fails on 0895c89b, whose
review projection dropped that transaction's response. The spec names
event pointers among the first 20.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): retain contradictions and trim retired state
* fix(environment): distinguish mixed array order from changed values
* fix(environment): keep dependent create state pinned
* fix(environment): keep checking retired view observations
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Kaoru0822 <[email protected]>
Co-authored-by: morluto <[email protected]>
Co-authored-by: gensokyo-dev <[email protected]>
Forward the file owner's completed stable-read hash and byte count through descriptor-close failure or cancellation in PE resources, certificates and imports, ELF notes and kernel modules, native exports, Apple IPS, and APK signature inspection. Preserve the primary failure, exact cancellation reason, and failed-close cleanup lease.
Validation: 32 acquisition-finalization regressions across eight providers and 30 existing APK provider, lifecycle, and identity tests passed. Existing native filesystem regressions and typecheck/lint also passed. No external analysis engines or Android device were used.
Keep malformed canonical devicetree phandles unresolved instead of falling back to legacy identities. Report the PE dynamic relocation offset and section at their exact source widths with Size-gated absence and zero preservation. Clarify classic kernel-module version coverage and byte-preserving string encoding.
Validation: 158 focused parser, service, filesystem, and finalization regressions; 14 CLI/MCP tests; build, typecheck/lint, formatting, and docs checks passed. Fixtures establish parser behavior; no external analysis engines were exercised.
The shared source-loading suite covers the former generic command and pre-exit lineage regression, plus package ownership, error-class identity, native module behavior, and preservation of a caller-owned compiler context. Remove the overlapping older fixture after validating those controls.
Reuse the shared immutable-result reader for Interface Builder while checking its current parent binding on every read. Accept truthful optional schema outputs and validate normalized JSON before freezing or caching it, preserving explicit undefined facts without caching them.
Move accumulator construction and inline admission policy into the domain. One prepared projection retains the same budget across admission and projection while preserving standalone defaults, custom budgets, and authentication order.
Keep ASAR header details and the Godot header parser module-local. Use the canonical lease types in Hopper consumers, including release-cache publication, while preserving acquisition and cleanup behavior.
* feat(browser): record when scenario requests were observed and how long they took
Request events carry observed_at, the wall-clock time the provider observed
the request start, and finished or failed events carry the browser's
elapsed_ms when it reports one. Both are optional, so earlier captures still
parse, and scenario comparisons leave them out as a committed built-in rule.
The real-Chrome network lane checks every request and finished response is
timed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(environment): time browser scenario records so their state learns a write clock
Scenario records take startedDateTime from when each request was observed and
time from the browser's duration, as HAR entries are timed. A timed scenario
of the book session learns the same clock and serves the same writes as its
HAR; an untimed one keeps record order and learns no clock, as before.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): document scenario request times and timed scenario records
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): start scenario records at the browser's own request start
The provider observes a request up to tens of milliseconds after the browser
starts it while it reads other responses, so a record starting then and
ending after the browser's duration mixed two clocks. Finished and failed
events now carry the browser's started_at, records prefer it and fall back to
observed_at, and comparisons drop it too. Tests cover the fallback for a
request that never ended or ended twice, a partly untimed capture keeping
record order, comparing an untimed capture with a timed one, and the
real-Chrome lane checks every finished request carries the browser's start
and duration.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): document the browser start time, its fallback lag and older readers
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the scenario timing verification
Gates, the real-Chrome lane, prompt-recorded and re-recorded published
scenario captures built with and without their times, the stale published
environments left unrepublished, and the review.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(browser): compare timed completion events in the request-time comparison test
The comparison test's captures had no finished or failed events, so dropping
started_at and elapsed_ms from them went untested. The captures now end one
request and fail the other, the test asserts both carry times, compares them
shifted by seven seconds and against an untimed capture, and a control shows
a changed failure on a timed completion is still reported.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
* feat(firmware): inspect flattened devicetree blobs
Adds inspect-devicetree and inspect_devicetree for FDT v16/v17 blobs
without target execution or external dependencies. Results include
validated headers, reservations, a node/property tree with bounded raw
previews, and derived standard values and selected phandle references.
Parsing enforces file, tree, and decoded representation budgets and
rejects malformed input without partial success. Summary delivery
supports retained Evidence pagination, with tests covering parsing,
service validation, CLI delivery, and MCP access after the input is
removed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe
* fix(firmware): reject conflicting devicetree phandles and bound page summaries
A node whose phandle and linux,phandle disagree no longer resolves under
either value; the conflict is reported as a limitation. Finalization
failures after a completed read retain the file-snapshot-hash partial
observation, matching the Go provider. Devicetree view pages carry
fixed-size context and counts instead of repeating summary strings, so a
large bootargs no longer pushes every page over the MCP response budget.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe
---------
Co-authored-by: Matt Van Horn <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
* feat(elf): inspect Linux kernel module metadata
Adds inspect-kernel-module and inspect_kernel_module for ELF32/ELF64
ET_REL Linux kernel modules, read statically without executing them.
Reports ordered .modinfo entries with duplicates preserved, __versions
symbol CRCs, the presence of .gnu.linkonce.this_module and __ksymtab,
.init.text and .exit.text sizes, and an appended module signature
trailer with its PKCS#7 byte range and SHA-256. gzip, xz and zstd
containers are reported unsupported with external decompression as the
next probe. Malformed headers and exhausted entry budgets return no
partial success.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe
* fix(elf): bound kernel module ksymtab listing and tighten contracts
Charge listed __ksymtab* sections against max_entries, omit section names
longer than 256 bytes with ksymtab_name_exceeds_limit, and aggregate the
non-file-backed limitation so repeated huge names cannot inflate Evidence.
Use fixedTupleSchema for the signature pad bytes with projection parity
tests, and assert the late-cancellation reason and retained observation.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe
* fix: resolve merge integration errors
---------
Co-authored-by: Matt Van Horn <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
Keep each admitted HTTP handler owned through Evidence writes and error rendering, including after its client disconnects. Close joins graceful transport shutdown and handler work before publishing completion, and propagates exact late failures while preserving ordinary request diagnostics.
Share lifecycle ownership across OpenAI, Anthropic, and Gemini fixtures while retaining protocol-specific parsing and responses. Exercise real disconnects, graceful concurrent and repeated close, ordinary 400s, and opaque late failures.
Use JSON.parse directly in package verification and retain one parsed Cursor recovery snapshot. Route native command source loading through the shared transform-service owner so completed command cleanup leaves no transform child.
Preserve JSONC validation and caller inputs. Cover the actual public source-loading lifecycle with an authored command and verified process lineage.
* fix(importer): reach package-main selection for trailing-slash directory references
posix.normalize preserves a trailing slash in the specifier, so normalized was sub/ while dirname(match) was sub; the resolvedThroughIndex comparison failed and selectPackageMain never ran for require("./sub/"). Compare against the slash-stripped directory so trailing-slash directory references take the same package-main path as the plain spelling. Boundary rows pair each trailing-slash request with the existing manifest fixtures and are validated against Node's own resolver in the same table.
Fixes#4189
* fix(importer): derive trailing-slash directory identity with path semantics
The lookbehind strip kept a trailing slash when the final component ended in a line terminator (require("./pkg\n/")), so dirname(match) still never matched and the trailing-slash path skipped package-main selection for those directories. Join the normalized path with "." instead: path semantics collapse any trailing slash run regardless of the preceding character, and behave identically to the strip on every other spelling. Boundary fixture gains a newline directory with a package.json, an index and a declared main so the index path (not the no-match branch) exercises the comparison.
Addresses Codex P1 on #4219
* fix(importer): normalize package-main targets with path semantics
---------
Co-authored-by: Hemang Varshney <[email protected]>
Co-authored-by: Kaoru0822 <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* feat(pe): inspect TLS callbacks and load configuration
Adds inspect-pe-load-config and inspect_pe_load_config for PE32 and
PE32+ images, with artifact hashes and file ranges in the returned
evidence. Reports callback addresses and mappings, plus size-covered
security-cookie, SafeSEH, CFG, EH-continuation and XFG fields;
flag-derived mitigation claims are explicitly labeled inferred. Missing
directories remain null, and malformed storage or exhausted read budgets
return errors without partial success. Adds documentation and tests for
service validation, CLI/MCP access, malformed inputs and stable-file
handling.
x86 images that declare the legacy 64-byte load-config directory are
read to the structure's own Size when those bytes are file-backed, as
the Windows loader does.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe
* fix(pe): retain snapshot facts and bound load-config section lookup
Keep the completed stable-read path, SHA-256 and byte count as a
file-snapshot-hash partial observation when descriptor close fails or is
cancelled. Report the checked Size span as structure_location and add it
to Evidence locations beside the declared directory range. Resolve
callback sections through a sorted segment index built once per image,
keeping the ambiguity failure. Pin every load-config field to offsets
transcribed from the PE/COFF spec and llvm COFF.h at its exact Size
boundary for PE32 and PE32+.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe
---------
Co-authored-by: Matt Van Horn <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* feat(environment): report what an environment serves with an environment-coverage view
A new inspect_analysis_view kind over capture Evidence. It projects the
state an environment derives with the given template rules and reports
each tool as answered from state, replayed with its view reason, a served
write, or a withheld write with its reason, the records behind it and a
hint about what to record next. The hints cover every write reason, so a
new reason without one fails to compile.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(environment): build an environment bundle in one command
rea environment-build <capture> [directory] inspects a HAR (or reads
capture Evidence), projects the environment manifest from the in-memory
Evidence, authenticates the pair, prepares the state and writes the bundle
environment-export writes. Every bundle file is byte-identical to the
three-step path for the same capture and options.
The report adds the capture and manifest identities, the coverage summary,
warnings (a loopback capture named after its file, credential-named body
members by pointer) and the next command. --dry-run writes nothing. The
default template rules are the four the published environments use.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(environment): cover environment-build and the coverage view
Domain tests check the hint table against the state view's reasons, the
summary, and the view against the environment-state view it summarizes.
Service tests build the fixture capture and compare every file with the
three-step path, a dry run, loopback naming and the refusals. A CLI test
compares a HAR built in one step with the three CLI steps byte for byte,
and an MCP test projects the view from every source kind.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(environment): build the real-agentenv lane's bundle with environment-build
The lane now runs the command users run: it builds the Grafana-shaped HAR
with environment-build and the packed checkout, checks the report, then
runs the bundle with agent-env as before.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): document environment-build and the coverage view
The agent environments guide opens with the one-step build: the report,
the hint for each withheld write reason, and what a bundle ships. The CLI
guide, the capture guide and the skill reference name the command and the
environment-coverage view.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): harden environment-build after review
- The credential scan walks with its own stack, so a deeply nested body
cannot crash the build, and it also reports credential-named header
names, query names, form body members and string arrays.
- The build checks SIGINT between stages: cancelled before the bundle
stage it writes nothing, during the write it names the written bundle.
- A dry run opens the package tarball, so it refuses what a build refuses.
- Repeated template rules are refused, a HAR saved as .json gets a hint,
file-derived names follow the bundle name rules, `localhost.` counts as
a loopback origin, and the next command is shell-quoted.
- --capture-timeout-ms passes through to the HAR inspection, and a
missing directory is refused before inspection.
- The no-observation hint covers updates and deletes of entities the state
never held; the coverage view states that it does not apply the
serve-time admission checks; the inspect_analysis_view description
names the view.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): state the build's conditions and record its verification
The guides now state when the one-step bundle equals the three-step one,
which headers inspection excludes, what the credential warning scans, how
cancellation behaves, and that the coverage view does not apply the
serve-time admission checks. The spec folder records the census, the end
to end runs, the gates and the review.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): dispatch a pending interrupt before each build stage check
The manifest, state and coverage stages run synchronously, so a SIGINT
that arrived during them was only dispatched once the bundle write had
begun. Each check now yields first, so an interrupt before the bundle
stage cancels the build with nothing written.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(browser): send declared requests from a scenario page with a request step
A capture_browser_scenario step `request` sends one declared HTTP request
through the page's own fetch, with its cookies and session, the way the
application's frontend would, and reads the whole response so the capture
records the transaction like any other. The path must resolve to the start
URL's origin, and the page must be on that origin when the step runs.
Query values and header values may be literals or declared secrets, and a
header may read its value from a cookie or a local storage entry, which is
then redacted from later records like a declared secret. `expected_status`
fails the step on any other status. Scenarios without a request step are
unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(browser): verify request steps in a real browser through to a built environment
verify:browser:request records a write session against a fixture item API
that refuses writes without its CSRF cookie header and stored bearer
token. It checks that every request lands in its own step, that the page
values authenticated each write and appear in no record, header or body,
that an unexpected status fails the step and cancels the rest, and that
environment-build serves the recorded create, update and delete.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(environment): export environment bundles over MCP
export_environment_bundle writes the bundle environment-build writes, from
capture Evidence retained in the session or one capture Evidence file,
into an absolute output directory that must not exist and whose parent
must exist, as extract_firmware and export_web_scripts require; it never
creates the parent or reuses a directory. It returns the same report,
whose schema now lives in the domain so the CLI and the tool share it, and
dry_run reports without writing. A loopback capture without a file needs a
name. The build's refusal messages no longer name CLI flags.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): scan scenario credentials, own the dry-run tarball and serialize Evidence once
A browser scenario's retained header values and the query parameters of its recorded URLs are scanned for credential
names as a HAR's are, through a review projection of its records. A dry run admits and releases the package tarball
through the export's regular-file scope, so a close it cannot confirm keeps its owner, and checks for cancellation
after that last await. Evidence is written into one exactly sized buffer instead of chunks joined by a copy.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(skill): build agent environments from a prompt with request steps and the bundle tool
Add the environments reference to the skill and install it with setup: record
against a disposable instance, sign in through the UI, write with request
steps and read each write back, check coverage, re-record by withheld reason
and export the bundle. Route it from SKILL.md, name agent environments in the
skill description, and document the request step, the export tool and
recording writes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* refactor(browser): split the request lane and header resolution into smaller functions
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* style(environment): format the build spec
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): say when an untimed capture learns no write clock
Coverage of a capture whose records are not all timed, which includes every
browser scenario capture, now states that the state learns no clock, so an
update stamped with a server-set modification time stays unexplained-change
however often it is recorded.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(skill): give agents a whole scenario shape with step timeouts
Agents guessed the scenario schema field by field and two hung on steps
without timeout_ms. The reference now starts from a complete scenario with a
timeout on every step, and says a scenario capture cannot serve updates the
application stamps with a modification time.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(browser): keep request steps on their origin and their page values redacted
- Follow no redirects: a redirect fails the step and nothing reaches the
location it names (checked in real Chrome), and check the page's origin
again in the page as the request is sent.
- Send nothing once the step's time has run out or it was cancelled while
header values were read; the in-page deadline is what remains of the step's.
- Keep every page value redacted under a repeated or colliding label, keep a
value's first marker when it is read again, and leave values shorter than
8 characters unredacted rather than rewriting ids, ports and hosts.
- Refuse a header name given twice, User-Agent (Chrome drops it) and line
breaks in literal values and prefixes; fail before sending when a secret or
page value holds them.
- Append query entries after the path's literal query without re-encoding it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): document request step limits and word bundle refusals for both surfaces
Document redirects, timeouts, page value redaction, HttpOnly cookie sources
and header refusals for request steps. Refusals shared by environment-build
and export_environment_bundle no longer name CLI flags, and the retained
loopback refusal no longer prints an empty file name. The skill reference
asks for read-backs after each write, shows the coverage view's source, names
package_tarball for unreleased builds and the browser path a scenario ships.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): scan every form occurrence and MIME-less scenario bodies
The build's credential scan collapsed form bodies with Object.fromEntries, so a
repeated field kept only its last occurrence: `api_key=secret&api_key=` warned
about nothing although the Evidence ships the value, and repeated values were
undercounted. Form fields are now scanned as ordered name/value pairs, as
headers and query strings already are.
The review projection of a capture_browser_scenario dropped a request body
recorded without a media type, so the scan never saw it. Review keeps such a
body's text with an empty media type; the manifest projection still reads only
bodies it can classify.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(browser): close request step edge cases from the second review
- Append query entries correctly after a path ending in "?", "&" or "#".
- Refuse 3xx expected statuses, which an unfollowed redirect can never
report, and say a redirected write may already have been applied.
- Redact a page value also as fetch sends it, without surrounding spaces
and tabs.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): document page value body costs, redirects and MCP dry runs
Document that reading a page value shrinks the bodies a capture keeps under
the default allocation limit, that redirected writes may have landed, that
the MCP dry_run still checks its output directory and which refusals name
the tool, and keep the .har hint in the HAR-as-JSON refusal for both
surfaces.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the prompt-to-environment verification
Gates, the real-browser lanes, five environments built from prompts by an
agent on disposable VMs and evaluated with two models, and the two reviews.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(skill): count rollback failures from the managed skill files
The environments reference made the skill eight files, so the recovery tests now derive the counts they expect from
MANAGED_SKILL_FILES instead of fixing them at six and seven.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(adb): restore the portable Java float pattern a merge rewrote
A lint autofix during a merge unescaped the hyphens in javaFloatValuePattern, which is invalid in a v-mode character
class, so the advertised start_adb_activity schema failed to compile in every JS regex mode. The file now matches main.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(browser): show the request step inside a whole scenario
Every JSON example in the browser scenario guide is a capture_browser_scenario input the catalog test parses, so the
request step example now sits in a launch scenario instead of standing alone.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): scan structured HAR form params and the request side of unattributed scenario transactions
A HAR request recorded with postData.params and no text is scanned by those parameters, each occurrence counting, and
the review projection keeps the request side of a scenario transaction whose response cannot be attributed, so the
credential warning covers what evidence.json ships in both cases.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): validate build paths and read dry-run tarballs
* fix(environment): report bodies too large for the credential scan
Text bodies over the scan's 4 MiB limit, including a response decoded only as a prefix, are reported as a
credential-scan-incomplete warning by record and side, never by content, so an absent credential-named-members
warning no longer reads as a complete check. The spec and agent-environments guide also state the path validation and
dry-run tarball read that e52ae1cd added.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(verification): release cold source transform services
* fix(javascript): retain capture context along covered mutation paths
* fix(environment): guard request dispatch and report export limits
* fix(environment): admit serialized exports and scan HAR form fallbacks
* fix(environment): admit in-memory build inputs against heap headroom and scan SaveHar null-text forms
The inspected HAR's Evidence and the projected manifest are checked against live heap headroom before they are
serialized, with the same check the file route uses, so a capture too large to parse and seal is refused as
resource_constraint before anything is written. A request whose postData text is SaveHar's null is scanned by its
structured params.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): measure the credential scan limit in UTF-8 bytes
A body counts against the 4 MiB limit by its UTF-8 length, not its UTF-16 code units, so multibyte text over the
limit is reported as unscanned instead of parsed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(browser): send request steps only before their deadline and keep page reads on the start origin
The page receives the step's absolute deadline and a one-second start window, so a busy page that runs the request
late, or after the step is cancelled, sends nothing; local storage is read only on the start origin; the response is
drained without keeping its body; an unparseable path is a field issue; retained Evidence is refused for heap headroom
before it is serialized; and the skill says how to reach server-assigned ids.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* style: format integrated export admission
* fix(javascript): erase inline type imports before binding values
* fix(browser): run the request lane under the shared verifier command owner
The browser request lane runs each CLI call through createPackageVerifierCommands on a private runtime root, so a
timeout, output overflow or failure stops the CLI and the browser it launched before the root is removed, and a failed
stop is reported with the root retained. The verification record states the lane's current counts.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): scan scenario content by event and read bodies by their media type
A browser scenario's credential scan reads every retained network-content event, including a response attached
mid-flight and a transaction no record represents, with event pointers, and each transaction URL's query once; the
review record projection it replaces is removed. A body is parsed as a form or as JSON by its recorded media type,
falling back to its shape, so valid forms such as `password=x&` are scanned and sentences are not read as forms.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Kaoru0822 <[email protected]>
Co-authored-by: morluto <[email protected]>
* fix(environment): keep read-only POSTs out of the write list
A POST that repeats the latest read of its path, tunnels only read
operations, names a lookup in its path's last meaningful word, or renews
a session no longer counts as a state write: it is replayed, does not cut
initial windows, and does not end observation searches. A tool stays a
write when a related read line changes across one of its calls.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): take an entity an unplanned write made when a read first shows it
A successful item read of an entity the gate's copy never held, after a
write no built plan models, puts the entity into the copy instead of
failing the read, so later writes to it are checked as usual. An entity a
modelled write touched is never taken back.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): plan a create into the type its returned id is read under
A POST whose path names no state type becomes a create into the type
whose item read first names an id its response returned, when the id is
new to the state; serving creates in that read's collection. A successful
POST that returned an id a type's reads only show after it also ends that
type's initial window, so entities a capture created stay out of the
initial state.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): end a type's initial reads at the write its reads disagree across
When a type's reads disagree across a write under another root, the
type's initial window now ends at the earliest write within that change
and the state is extracted again, instead of leaving every view of the
type replayed. The cut composes with the creation cut; the earlier wins.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): replay request lines that show entities in another form
A read line that shows the same entities in another form, by an extra
query parameter that adds or drops members, or conflicts with a base
line on a shared entity, is a variant: it leaves the view's checks and
the entity observations, the view names it with the query keys that pick
it out, and a call matching those keys replays its recording. A filter
role whose name matches no field needs two agreeing values.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): specify and record the state-target changes
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep a read-only POST a write when its evidence is incomplete
Body-level container operations are skipped like query ones, a lookup is named only
by the path's last literal segment and never alongside a write word, a tool with a
redirected or unanswered call is not reclassified, and the mutation veto is resolved
over all candidates at once so another read-only call cannot explain a read change.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): answer a field selection only when the state shows it exactly
Serving tests a field selection before any variant key: a projection value a replayed
read gave, or one no checked line gave other than `*`, replays. A list sets aside a
line asking for some fields only before the identity proof, and a dropped variant's
membership change no longer rewrites the type.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): hold adopted entities and linked creates to what the recording shows
An adopted entity is charged against the view's budget like a created one. A linked
create holds only for its exemplar's path arguments: serving refuses others and the
gate counts such a call as unmodelled. A response's identity-named id links at any
length, but a short one only to a type read before the call.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the review fixes' measurements
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): release a discarded planning pass before planning again
A rewrite cut clears the first pass, so the budget rewinds to a checkpoint taken after
the write cutoffs and created ids before the state is extracted again. Rewrite spans are
charged and appended without spreading them into an argument list.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): link no create whose id an earlier read showed, and read only whole batches
A linked create is rejected when an earlier list of its type or read of its collection
showed the returned id. Body ids are walked without spreading children into an argument
list. An RPC call reads only when every operations entry names an operation of its own.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): let the gate skip exactly the reads serving replays
Serving's replay decision moves to the domain as replayReason, and the write gate uses it:
a read serving replays can neither approve nor veto a write, and a read of every field
beside a replayed selection is checked. A selection read missing a required field is
still skipped, since part of an entity can neither confirm nor check it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the second review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): read writes, links and creation cuts only from evidence that rules out other causes
- A read-only POST repeats only a read that finished before it began; the veto compares
the latest read finished before a call with the first begun after it, and counts a
recorded absence on one side as a change. `modify` and `replace` are write words.
- A redirected or unanswered write lets a later item read adopt the entity it may have made.
- A creation cut counts a read still running when the POST began as after it, and a list
read shows its listed entities' own ids, not those they nest.
- A linked create's item read must come before any other tool's write.
- Line shapes are charged to the budget as they are built.
- A `fields=*` list line is whole, not a field selection.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the third review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): tie linked creates to their returned ids and order state by the lines left
- A linked create is observed only in a read of an id its response returned,
envelopes included, and serving takes its recorded path values in either spelling.
- A list read shows a suffix-named identity (`projectId`) distinct across its entities.
- A read-only POST compares the read that finished last before it began.
- An entity's first sighting comes from the lines left after variant lines are dropped.
- The pairwise variant pass stops at a work limit, leaving every line checked.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the fourth review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep foreign keys, stale reads and double decoding out of write evidence
- A list read counts a suffix-named field as its entities' ids only when no
id-named field identifies them, so an `ownerId` beside `id` cuts no window.
- A read-only POST is compared with the read that finished last among those no
other write follows, so a consuming call stays a write.
- A linked create's source path values compare as spelled on both sides, so no
spelling is decoded twice.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the fifth review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): compare linked sources by position, decode path fields once and bound read and variant scans
- A linked create's source values compare segment by segment, so a template
naming two parameters alike cannot accept a changed first one.
- Serving fills a linked create's path fields with its arguments decoded once,
as the gate learned them.
- The read-only check reads each related line's records once per call, between
the nearest other writes.
- Member signatures are JSON arrays, so a name holding the separator still
conflicts; the variant work limit counts line pairs as well as entities.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the sixth review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): replay late and variant-only items, fill linked path fields from the exemplar and charge membership spans
- An item line first recorded after the initial window that names a new shaping
parameter and shows other members is a replayed variant, like an initial one.
- An item only a replayed line showed, which the state never started with,
answers with its own recording; one the state held and lost stays missing.
- A linked create fills its path fields from its exemplar's path decoded once,
whichever accepted spelling the call sends.
- Each membership change span is charged against the budget before it is kept.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the seventh review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): blame a failed read on the writes whose fields it disagrees on
A failed item read with no interfering unmodelled write contradicts its creates and
deletes, and an update only when a field the update wrote or its response showed
differs. A create is contradicted when a later read embeds it elsewhere and the state
does not. A create member is fixed to its recorded value when a constant it would
have to change derives from it: its text inside a constant, a referenced entity's name,
or an instant beside a sent date, matched by related field names.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): explain unsent update changes and nested clocks by what the recording shows
An update's unsent change can be a modified-by stamp beside a created-by counterpart, a
value derived from the one sent member stored nowhere (accepted only while the target
holds the recorded before-value), or a sent clock the call left in its own second.
Objects whose clocks all moved with the request are nested clocks, opaque tokens of a
type's own length are generated, and an enveloped body is learned as its one object.
A write takes only its recorded query, an echoed reference to a nested object and a
state word paired with other fields stay at their recorded values, and a slug is tried
before a token.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): order collections by whole lines and sort only arrays a read-back proves sorted
A collection's initial order comes from the first list line that shows every entity its
type's sightings do and applies no order. A view renders a string-array field sorted
only after a counted read-back shows the written values in an order that neither the
written order nor existing-values-first explains, and never once a read showed it
unsorted. Sort and direction parameters share one vocabulary and are never learned as
inert, and a create placed by disagreeing sorts or a random id falls back to last.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(environment): serve bulk writes at a collection and target item actions
A DELETE, PUT or PATCH at a collection, or a POST at its delete path, whose body names
held entities by id is applied to each named entity, and serving refuses it unless every
id is held. A POST to an entity's action path that answers nothing or the entity is an
update of it; it is served only when a recorded call found each scalar it sets already
at that value. Served bulk bodies advertise their items, and compare probes pass them.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): decide late item lines against the lines left, charge replay keys and bisect rewrite cuts
- Item lines first recorded after the initial reads are decided once variants
are dropped, against the lines left: a new shaping parameter showing other
members, or a selection of some fields leaving members out, replays.
- Each replay key is charged against the budget before it is kept.
- A rewrite span's earliest write is found by bisection over the writes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the eighth review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): set aside response members a path mints anew on every read
A top-level UUID or clock that differs on every repeat of one path's successful reads,
with no write between, is left out of that path's item, list and document comparisons
and named in the view's per_response_members. Serving keeps the recorded value.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): count only reads finished before a linked create began as showing its id held
A list still running when the call began may show what the call made, as the
creation cut already decides, so it no longer refuses the link.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): count a list total nested in a paging object
An item total in a top-level object beside the list, such as pageInfo.totalRows, is a
counter on the same evidence as a top-level one: it must equal the number listed, and
one that differs marks the line partial. Serving and the gate render it from the state
through its JSON pointer and leave the object's other members as recorded.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): take a created entity's nested clocks from its read-back
After a create's generated values pass, its stored nested clocks take the instants the
first later read of the entity shows, as an update's already do, so a create whose
response and read spell the clock differently is confirmed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): import the compare tool definition as a type
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): describe the new write rules and trim repeated parsing
The environment and capture docs describe sorted arrays, per-response members, nested
counters, item actions, bulk writes, the new write rules and refusals, and their known
limits. `_order` is a direction only. Sorted-array retries and the per-response scan
parse only the reads they need, and identifier words come from one helper.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): confirm no update whose clocks or fields the evidence cannot show it writing
An unsent clock an update left in the second it ran keeps the update unconfirmed until
another call shows the clock stamped. A field the state lacks that the read and the
update's response both show is the update's change, so without a rule for it the read
confirms nothing. A modified-by name stamp brings its id sibling along, and created
entities are indexed by id when a failed read is checked for embeds.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): show pinned query and body values in the served catalog and apply bulk writes atomically
A pinned query parameter is required with its recorded value as the only choice, and a
call that leaves it out takes that value. A fixed body member shows its recorded value,
and an enveloped body its wrapping, in the schema, the description and the refusal.
Bulk writes go through the same query pin and update or remove their entities at once.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): specify and record the write-rule changes
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep served creates' items missing, check same-type earlier reads, and bound late lines and read-only stretches
- An item only a replayed line showed replays only while no served create has
added to its type, so a created and deleted item stays missing.
- A linked create's earlier item-read veto checks only reads of the candidate's
type or collection that show the item, so another type's id does not hide it.
- An item read answered with JSON null shows no id to a creation cut.
- Late lines' member names are charged before they are kept.
- The read-only check precomputes nearest writes and passes once over each
write-free stretch per path, skipping lines whose reads all agree.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the ninth review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): link creates past empty item reads, sweep repeated reads once and keep only returned ids for creation cuts
- A linked create passes over a later item read naming its id whose body shows
no item, such as JSON null, and links the next one.
- Read-only repeated reads are found in one sweep: each path's reads wait by
end time until a call's start passes them, and a write clears them.
- A creation cut keeps, and charges, only the shown ids some creation returned.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the tenth review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): take bulk ids literally, check each recorded call's query once, and keep learned sorts open to contrary reads
Bulk writes take body ids as written, refuse a call naming one entity twice, size updates from the replacements
installed, generate each entity's values from that entity, and delete only with the members their exemplar sent
besides the ids. Comparison translates bulk body ids with the target collection's mapping.
Update rules echo a creation clock sent back unchanged, require every held clock, and refuse a nested clock once any
recorded call kept its object. A recorded call sent with another query than its exemplar's, including item actions,
documents and deletes, neither confirms nor teaches its plan, and only successful calls with that query relax a
create's guards.
A counted read listing a learned array unsorted drops the sort from its view, sort evidence comes only from the
entities the read covers, and a top-level counter whose name starts with a slash is named by its escaped pointer.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the review fixes' checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* perf(environment): compare variant lines through shared entities and parse each compared body once
The variant pass indexes a tool's lines by the entities they show and compares only lines that share one, charging
the index to the budget while it is held; the pairwise work limit still decides when a tool keeps every line checked.
Read-only decisions keep each response body's canonical digest, taken once while its parse is charged, across calls
and veto passes. The creation cut no longer parses reads at or after the write that ends the initial reads, and reads
the ids a body shows inside its lease. Adoption looks up a read's target only after an unplanned write before it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the eleventh review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* perf(environment): list a type's collections only when the path's own holds no id, and parse variant base lines once
The write gate's item target lists the type's held collections, and the removed targets', only when the path's own
collection holds none of its ids, so a served item view's reads no longer walk every entity of the type. The variant
pass parses the base lines' queries once for all the variants they key, and not at all when it found none.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the twelfth review round's checks and the sweep's cost
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the 50-capture sweep's wall, CPU and peak memory
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): remove duplicate schema after main integration
* fix(environment): honor recorded bulk identity kinds
* fix(environment): retain scoped evidence and honor write defaults
* test(environment): keep SDK regressions independently scoped
* docs(environment): record scoped write verification and measured costs
* fix(environment): serve bulk writes whose response lists each entity they wrote
A bulk call answering an array with one element per entity its body names, in the body's order, is classified by
its elements, so the existing renderer serves it from the entities each call writes. Responses listing entities out
of order, with differing members or id spellings, wrapped elements or an envelope still refuse.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): measure the 50 captures at the scoped-envelope head
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): classify bulk responses and release verifier transforms
* fix(environment): classify and verify complete bulk responses
* fix(javascript): retain capture context along covered mutation paths
* test(environment): verify bulk responses through the real MCP SDK
* test(environment): separate bulk response proof regressions
* fix(environment): preserve request absence and generated value relationships
* fix(environment): verify complete nested clocks on creates
* fix(javascript): erase inline type imports before binding values
* fix(environment): share complete generated value verification
* fix(verifiers): load the Windows source graph only when needed
* fix(environment): validate write responses before stored clock restamps
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Kaoru0822 <[email protected]>
Co-authored-by: gensokyo-dev <[email protected]>
Co-authored-by: morluto <[email protected]>
The staging refusal told callers to increase max_output_files or max_output_bytes within its schema maximum. At the schema ceiling that recovery does not exist, so the refusal was unactionable exactly where the least room remains.
firmwareStagingBudgetRemediation now branches on the selected value against the schema maximum: below the ceiling it names the room and the control, at the ceiling it states that a further raise is unsupported and points at a smaller firmware byte range. The schema maxima move into named constants so the advice and the accepted range cannot drift apart.
Verified with a module test for both budgets at the ceiling and one below it (red on the previous single-form remediation), plus the existing firmware suites.
Migrate the remaining native verifier commands to shared ownership with explicit stdin contracts, command-before-fixture cleanup, and failure receipts. Preserve observed catalog counts and unknowns, retained artifacts, native assertions, and selected launch inputs.
Remove the obsolete raw exec export and share output persistence across native verifiers. Exercise actual entrypoints with authored failed preflights and acknowledged descendants, plus filesystem failures and opaque error preservation.
Move command and retained resource lifetimes into a shared verifier owner, keeping package workspace release as a separate dependency. Migrate Pi and Hermes verification to that owner while preserving open pipes, explicit EOF, diagnostics, and retained labs.
Require positive writable finalization before accepting EOF delivery. Cover premature close, opaque failures, late ownership delivery, mixed cleanup outcomes, exact retry, and real descendant cleanup with authored process boundaries.
Remove duplicate MCP defaults, the fixed CDP deadline message, and the canned Windows authority reason after verifying their only consumers were tests.
Pin independent expected budget facts, exercise active default and selected CDP deadlines, and verify exact authored native diagnostic propagation. Preserve malformed-input, cancellation, omission, and authority assertions. Verified 222 focused cases, 9 README cases, build, static checks, docs, discovery, and duplication at 3.58%.
Record erasure during definition indexing and reuse it across runtime references, captures, effects, module links, routes, Electron and Vite. Preserve source type links and emitted decorator and computed-key effects; keep actual runtime reads and escapes conservative.
Validation: 1,647 focused tests and 9 documentation tests passed, with build, static and documentation gates. The inherited reference-lifetimes stress file exhausts a 512 MiB worker on both unmodified 18451e479 and this change; that file remains unverified. TypeScript 7.0.2 emit was inspected for ES2022 and ES2018 without executing emitted code.
* feat(domain): parse and validate GameCube/Wii DOL headers
Add a pure parser for the 0x100-byte DOL header (7 text and 11 data
slots, BSS, entry point). Used slots must lie after the header and
inside the file and the 0x80000000..0x81800000 load window; text slots
are 4-byte aligned; sections may not overlap in memory or in the file;
the entry point must be inside a text section. BSS may overlap data
sections, as .sdata/.sdata2 do in shipped DOLs.
Refs #1741
* feat(binary): admit caller-selected GameCube/Wii DOL targets
* feat(ghidra): import GameCube/Wii DOL targets through a section-map pre-script
* test(ghidra): cover DOL launcher arguments, attestation and raw profile digests
* test(ghidra): add the real verify:ghidra:dol lane and DOL docs
* fix(ghidra): read only the DOL header and section ranges instead of the whole file
* test(ghidra): derive DOL lane addresses from readelf and admit Gekko from the install catalog
* fix(ghidra): attest DOL block permissions, space, overlay and load state
* fix(ghidra): keep load-image permissions optional for older inspections
* fix(contracts): accept DOL targets in binary_session output
* fix(ghidra): adapt the DOL lane to the current upstream address schema
Validate DOL load-image coordinates with the upstream observed-address
schema, drop a duplicate import left by the rebase, and re-pin the raw
profile digests to the unmodified upstream resolver.
* fix(ghidra): preserve bridge inventory symbol provenance
* fix(ghidra): align DOL verification with shared workflow contracts
* feat(domain): parse and validate GameCube/Wii DOL headers
Add a pure parser for the 0x100-byte DOL header (7 text and 11 data
slots, BSS, entry point). Used slots must lie after the header and
inside the file and the 0x80000000..0x81800000 load window; text slots
are 4-byte aligned; sections may not overlap in memory or in the file;
the entry point must be inside a text section. BSS may overlap data
sections, as .sdata/.sdata2 do in shipped DOLs.
Refs #1741
* feat(binary): admit caller-selected GameCube/Wii DOL targets
* feat(ghidra): import GameCube/Wii DOL targets through a section-map pre-script
* test(ghidra): cover DOL launcher arguments, attestation and raw profile digests
* test(ghidra): add the real verify:ghidra:dol lane and DOL docs
* fix(ghidra): read only the DOL header and section ranges instead of the whole file
* test(ghidra): derive DOL lane addresses from readelf and admit Gekko from the install catalog
* fix(ghidra): attest DOL block permissions, space, overlay and load state
* fix(ghidra): keep load-image permissions optional for older inspections
* fix(contracts): accept DOL targets in binary_session output
* fix(ghidra): adapt the DOL lane to the current upstream address schema
Validate DOL load-image coordinates with the upstream observed-address
schema, drop a duplicate import left by the rebase, and re-pin the raw
profile digests to the unmodified upstream resolver.
* docs(ghidra): qualify the DOL memory window
* refactor(ghidra): own DOL BSS ranges in the parsed header
* docs(ghidra): record real DOL workflows and task costs
* docs(ghidra): record final DOL integration verification
* fix(mcp): share the native procedure search row contract
* docs(ghidra): record public procedure search verification
---------
Co-authored-by: gensokyo-dev <[email protected]>
Join identity-verified PTY family cleanup and native exit before workspace removal, retaining failed cleanup capabilities for retry. Replace duplicate kill-and-reject loops with shared process ownership and deadlines.
Capture configuration before setup using owned file handles and compare raw bytes. Preserve interactive cancellation, terminal restoration, redirected output, and selected inputs; remove the test-only forwarding export. Verified 122 focused cases, 9 README cases, build, static checks, docs, discovery, and duplication at 3.58%.
Add lambdas names-filter selector cases to checkSelectors:
- names: ['start'] returns the matching lambda with resolved fields
- names: ['missing'] returns an empty page
Add a chunks no-match case:
- names: ['Xyzz'] returns an empty page for an absent chunk tag
Also clarify in docs/erlang-beam.md what names selects for each
collection: the four-character IFF tag for chunks, the resolved
function name (never null) for lambdas, and the decoded atom name
string for atoms.
Co-authored-by: Saiyam Jain <[email protected]>
* fix(ghidra): enforce the bridge request ceiling before writing
Hopper and Cutter both measure an oversized payload and refuse it before the
request reaches its bridge, using the shared REA_BRIDGE_MAX_REQUEST_BYTES
ceiling. Ghidra had no ceiling on either end: GhidraWire.request wrote the
stringified request straight to the socket, and the Java bridge reads request
lines with an unbounded readLine() after its bounded 64 KiB handshake.
Serialize once, measure the encoded payload, and refuse before the operation
is registered as pending and before any socket write, so an oversized request
never reaches the bridge. Carry the typed constraint as the cause and
re-attribute it in projectPrimarySessionError, so callers see the same
resource constraint Hopper and Cutter already report.
The Ghidra bridge reads no ceiling of its own, so its recovery text names that
only the REA client applies the setting instead of asking for a bridge restart.
Validation: src/ghidra/GhidraClientWire.test.ts (3 cases, red then green),
src/config/bridgeMaxRequestBytes.test.ts (16), src/ghidra/GhidraRequestQueue.test.ts
(25); tsc --noEmit over the changed set exits 0; oxlint reports 0 errors;
oxfmt --check clean; verify:module-boundaries passes. The two failures in the
wider src/config+src/ghidra+src/hopper+src/cutter sweep
(captureDecoderHeap, GhidraAnalysisSeeds symlink EPERM) reproduce identically
on pristine bded9c628 with this change stashed. The Ghidra fixture suite
cannot run on this Windows host: fakeGhidra.mjs renames bridge-endpoint.json
and hits EBUSY on 3 of 3 runs, so the fixture-level test was not added.
* fix(ghidra): preflight request bytes before encoding
---------
Co-authored-by: gensokyo-dev <[email protected]>
Tag close outcomes with Result so rejected undefined remains a failure. Preserve all hook attempts, retained resource owners, aggregate causes, and cleanup retry.
* feat(il2cpp): read generic containers on demand and render method spec names
Generic container indices and records are demand readers on the same metadata snapshot, so links that do not ask for generic instances allocate nothing. Type rendering keeps one graph walk with its workspace, depth and cycle guards; the C#-like names and the Il2CppDumper GetMethodSpecName names are two styles over it.
* feat(il2cpp): link generic method instances with admitted rows and kept issues
generic_instances links every genericMethodTable row through methodSpecs, genericInsts and genericMethodPointers, choosing the one CodeRegistration layout whose counts bound every row. The table is reserved against the report budget before any row is resolved; rows and issues are admitted before retention, and a contradicting row stays unknown with an address-backed issue instead of failing the link. Views page the rows by definition, state, address and name, unrequested and historical collections stay unknown, and Ghidra seeds fold instances after the definitions.
* feat(il2cpp): accept --generic-instances on the CLI and describe it in tool contracts
* docs(il2cpp): describe generic method instances and their limits
* fix(il2cpp): keep issued generic rows unknown and name their row
A method spec that contradicted the metadata still reported its pointer slot as code, while the schema and provider limitation promised unknown. Such rows now keep no address, every issue carries its genericMethodTable row, the domain validator requires unknown exactly on issued rows, and shared specs name one other row instead of all of them. The row-size lower bound moves to the metadata admission owner, the hex helper is shared, and budget wording says checked rather than reserved.
* test(il2cpp): reject ambiguous generic layouts and pin budget, yield and limit paths
* fix(il2cpp): keep unmapped generic slots per row and reject undeclared arguments
Layout selection no longer requires every genericMethodPointers slot to be
mapped; each row reads its own slot, so one unmapped slot leaves only that
row unknown with an issue. Method specs whose class or method argument count
differs from the owner's declared generic container are issued and unnamed.
Fixtures now declare the containers their generic rows fill.
* fix(il2cpp): page generic method issues instead of retaining them in summaries
Summaries keep generic_methods without its issues and count them in
counts.generic_method_issues; the generic_method_issues collection pages
them by rows, indices and fields, as code_gen_modules already does. Docs
also name the method_indices filter the request schema accepts.
* fix(il2cpp): read split generic arguments per slot and method containers on demand
Generic argument arrays may span adjacent loader ranges: admit them with
hasPointerArrayCoverage and read each slot through readPointer, instead of
requiring the whole array in one mapping.
Method generic container indices are read on demand from the method record,
like type containers, so no link path allocates a per-method column. An owner
whose container index is out of range now leaves the method spec unnamed with
an issue instead of naming it unchecked.
* fix(il2cpp): report generic entries past the address space at their row
A damaged methodSpecs or genericMethodPointers pointer could make a spec or
slot address exceed 64 bits. The issue kept that address, which the address
schema rejects, so inspection failed instead of leaving the row unknown.
Check the entry range first and attach the issue to the genericMethodTable
row (or its slot field).
* chore(il2cpp): remove unrelated formatting changes
* fix: restore adb float pattern and mobile fixture from main
The merge commit's lint-staged run rewrote these two main files: oxlint --fix
dropped the escape in [+\-], which is invalid under the RegExp v flag.
* fix(il2cpp): preserve unreadable generic method identities
* docs(il2cpp): record generic-instance workflow verification
* docs(il2cpp): qualify final integration checks
---------
Co-authored-by: gensokyo-dev <[email protected]>
FilesystemTreeView mapped root-relative dyld paths to host paths with path.join. On Windows a component such as ..\outside\x.dylib was normalized out of the analyzed root, so a file outside it was opened, parsed and hashed. Components containing a backslash or colon are now absent on Windows, Windows link text is split on backslashes, and every host path is checked to stay inside the root before it is opened.
* fix(process): preserve the caller abort reason in regex worker cancellations
Both cancellation outcomes of matchRegexValues, the pre-admission refusal
and the abort observed while the worker runs, now carry the caller's
signal.reason as the error cause. Hopper's regex search returns that result
unchanged, so cancelled regex search_procedures and search_strings results
regain the exact reason the caller supplied.
* test(process): assert the caller abort reason for cancelled regex matches
Cover the pre-cancelled refusal and an abort raised while the worker is
running, asserting the cause is the identical reason object.
* feat(apple): inspect IPS crash reports
Add inspect_apple_ips for caller-selected Apple .ips files. Parse the
first-line metadata object and, when bug_type is the string 309, the
crash body: process identity, exception and termination facts, threads,
usedImages, lossless integer registers, and documented classification
rules. Other bug types including 288 stackshots return no crash result.
Opened Mach-O and dSYM UUID joins remain unobserved.
Related to #4297
* fix(apple): keep IPS register literals exact
Use the arm64e fixture integer that matches 0x8527000193ed4944 instead
of an IEEE-754-rounded decimal, and count the lossless JSON example
length from the source text.
* fix(apple): budget IPS parsing and keep typed presence
Parse the IPS metadata and crash body through a projection of the
documented members. Members the report does not interpret are
syntax-checked without being materialized, and thread, frame, image and
the new max_registers budgets run before each row is parsed, so a large
selected file fails with a typed resource error instead of first
expanding every row. Fixed allowances bound JSON nesting, unlisted key
names and termination reasons.
Present values whose JSON type differs from the documented one are no
longer read as absence: they are listed in coverage.type_mismatches and
coverage becomes partial, including wrong-type or missing threads and
usedImages collections. osVersion keeps the producer dictionary or the
string form. Frame roles follow physical frame depth, so the top frame
of a non-faulting thread is current_instruction and inlined rows share
the following frame's role. SIGKILL classes compare the canonical hex
once, so 0xdeadd0cc no longer matches dead10cc. Invalid UTF-8 is refused
instead of being replaced, and JSON strings are decoded by copying
unescaped spans.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Ra7LM2NyQ7DumdssxbUq5g
* fix(apple): bound integer text expansion and reconcile coverage
* refactor(apple): retain image metadata at its owning row
* refactor(apple): validate row capacity through reconciled coverage
* test(apple): verify resource recovery at the public error boundary
* docs(apple): record complete IPS task and corpus measurements
* docs(apple): record integrated checks and stdio corpus evidence
* docs(apple): record PE integration and baseline cleanup controls
* fix(native): bound IPS string decoding and preserve invalid identities
* refactor(native): use exact optional IPS source evidence
* docs(native): verify IPS escape capacity and complete-task costs
* test(native): verify IPS through production stdio MCP
* style(tests): format IPS advertised schema bindings
* fix(native): preserve unresolved IPS references and recorded frame semantics
* docs(native): record IPS reference review evidence
* fix(apple-ips): enforce JSON and report consistency
* docs(apple-ips): record final consistency verification
---------
Co-authored-by: Matt Van Horn <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: gensokyo-dev <[email protected]>
* fix(environment): keep read-only POSTs out of the write list
A POST that repeats the latest read of its path, tunnels only read
operations, names a lookup in its path's last meaningful word, or renews
a session no longer counts as a state write: it is replayed, does not cut
initial windows, and does not end observation searches. A tool stays a
write when a related read line changes across one of its calls.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): take an entity an unplanned write made when a read first shows it
A successful item read of an entity the gate's copy never held, after a
write no built plan models, puts the entity into the copy instead of
failing the read, so later writes to it are checked as usual. An entity a
modelled write touched is never taken back.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): plan a create into the type its returned id is read under
A POST whose path names no state type becomes a create into the type
whose item read first names an id its response returned, when the id is
new to the state; serving creates in that read's collection. A successful
POST that returned an id a type's reads only show after it also ends that
type's initial window, so entities a capture created stay out of the
initial state.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): end a type's initial reads at the write its reads disagree across
When a type's reads disagree across a write under another root, the
type's initial window now ends at the earliest write within that change
and the state is extracted again, instead of leaving every view of the
type replayed. The cut composes with the creation cut; the earlier wins.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): replay request lines that show entities in another form
A read line that shows the same entities in another form, by an extra
query parameter that adds or drops members, or conflicts with a base
line on a shared entity, is a variant: it leaves the view's checks and
the entity observations, the view names it with the query keys that pick
it out, and a call matching those keys replays its recording. A filter
role whose name matches no field needs two agreeing values.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): specify and record the state-target changes
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep a read-only POST a write when its evidence is incomplete
Body-level container operations are skipped like query ones, a lookup is named only
by the path's last literal segment and never alongside a write word, a tool with a
redirected or unanswered call is not reclassified, and the mutation veto is resolved
over all candidates at once so another read-only call cannot explain a read change.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): answer a field selection only when the state shows it exactly
Serving tests a field selection before any variant key: a projection value a replayed
read gave, or one no checked line gave other than `*`, replays. A list sets aside a
line asking for some fields only before the identity proof, and a dropped variant's
membership change no longer rewrites the type.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): hold adopted entities and linked creates to what the recording shows
An adopted entity is charged against the view's budget like a created one. A linked
create holds only for its exemplar's path arguments: serving refuses others and the
gate counts such a call as unmodelled. A response's identity-named id links at any
length, but a short one only to a type read before the call.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the review fixes' measurements
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): release a discarded planning pass before planning again
A rewrite cut clears the first pass, so the budget rewinds to a checkpoint taken after
the write cutoffs and created ids before the state is extracted again. Rewrite spans are
charged and appended without spreading them into an argument list.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): link no create whose id an earlier read showed, and read only whole batches
A linked create is rejected when an earlier list of its type or read of its collection
showed the returned id. Body ids are walked without spreading children into an argument
list. An RPC call reads only when every operations entry names an operation of its own.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): let the gate skip exactly the reads serving replays
Serving's replay decision moves to the domain as replayReason, and the write gate uses it:
a read serving replays can neither approve nor veto a write, and a read of every field
beside a replayed selection is checked. A selection read missing a required field is
still skipped, since part of an entity can neither confirm nor check it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the second review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): read writes, links and creation cuts only from evidence that rules out other causes
- A read-only POST repeats only a read that finished before it began; the veto compares
the latest read finished before a call with the first begun after it, and counts a
recorded absence on one side as a change. `modify` and `replace` are write words.
- A redirected or unanswered write lets a later item read adopt the entity it may have made.
- A creation cut counts a read still running when the POST began as after it, and a list
read shows its listed entities' own ids, not those they nest.
- A linked create's item read must come before any other tool's write.
- Line shapes are charged to the budget as they are built.
- A `fields=*` list line is whole, not a field selection.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the third review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): tie linked creates to their returned ids and order state by the lines left
- A linked create is observed only in a read of an id its response returned,
envelopes included, and serving takes its recorded path values in either spelling.
- A list read shows a suffix-named identity (`projectId`) distinct across its entities.
- A read-only POST compares the read that finished last before it began.
- An entity's first sighting comes from the lines left after variant lines are dropped.
- The pairwise variant pass stops at a work limit, leaving every line checked.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the fourth review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep foreign keys, stale reads and double decoding out of write evidence
- A list read counts a suffix-named field as its entities' ids only when no
id-named field identifies them, so an `ownerId` beside `id` cuts no window.
- A read-only POST is compared with the read that finished last among those no
other write follows, so a consuming call stays a write.
- A linked create's source path values compare as spelled on both sides, so no
spelling is decoded twice.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the fifth review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): compare linked sources by position, decode path fields once and bound read and variant scans
- A linked create's source values compare segment by segment, so a template
naming two parameters alike cannot accept a changed first one.
- Serving fills a linked create's path fields with its arguments decoded once,
as the gate learned them.
- The read-only check reads each related line's records once per call, between
the nearest other writes.
- Member signatures are JSON arrays, so a name holding the separator still
conflicts; the variant work limit counts line pairs as well as entities.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the sixth review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): replay late and variant-only items, fill linked path fields from the exemplar and charge membership spans
- An item line first recorded after the initial window that names a new shaping
parameter and shows other members is a replayed variant, like an initial one.
- An item only a replayed line showed, which the state never started with,
answers with its own recording; one the state held and lost stays missing.
- A linked create fills its path fields from its exemplar's path decoded once,
whichever accepted spelling the call sends.
- Each membership change span is charged against the budget before it is kept.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the seventh review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): decide late item lines against the lines left, charge replay keys and bisect rewrite cuts
- Item lines first recorded after the initial reads are decided once variants
are dropped, against the lines left: a new shaping parameter showing other
members, or a selection of some fields leaving members out, replays.
- Each replay key is charged against the budget before it is kept.
- A rewrite span's earliest write is found by bisection over the writes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the eighth review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): count only reads finished before a linked create began as showing its id held
A list still running when the call began may show what the call made, as the
creation cut already decides, so it no longer refuses the link.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): keep served creates' items missing, check same-type earlier reads, and bound late lines and read-only stretches
- An item only a replayed line showed replays only while no served create has
added to its type, so a created and deleted item stays missing.
- A linked create's earlier item-read veto checks only reads of the candidate's
type or collection that show the item, so another type's id does not hide it.
- An item read answered with JSON null shows no id to a creation cut.
- Late lines' member names are charged before they are kept.
- The read-only check precomputes nearest writes and passes once over each
write-free stretch per path, skipping lines whose reads all agree.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the ninth review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(environment): link creates past empty item reads, sweep repeated reads once and keep only returned ids for creation cuts
- A linked create passes over a later item read naming its id whose body shows
no item, such as JSON null, and links the next one.
- Read-only repeated reads are found in one sweep: each path's reads wait by
end time until a call's start passes them, and a write clears them.
- A creation cut keeps, and charges, only the shown ids some creation returned.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the tenth review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* perf(environment): compare variant lines through shared entities and parse each compared body once
The variant pass indexes a tool's lines by the entities they show and compares only lines that share one, charging
the index to the budget while it is held; the pairwise work limit still decides when a tool keeps every line checked.
Read-only decisions keep each response body's canonical digest, taken once while its parse is charged, across calls
and veto passes. The creation cut no longer parses reads at or after the write that ends the initial reads, and reads
the ids a body shows inside its lease. Adoption looks up a read's target only after an unplanned write before it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the eleventh review round's checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* perf(environment): list a type's collections only when the path's own holds no id, and parse variant base lines once
The write gate's item target lists the type's held collections, and the removed targets', only when the path's own
collection holds none of its ids, so a served item view's reads no longer walk every entity of the type. The variant
pass parses the base lines' queries once for all the variants they key, and not at all when it found none.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs(environment): record the twelfth review round's checks and the sweep's cost
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Kaoru0822 <[email protected]>
* perf(artifacts): read stable files into one bounded buffer
* perf(artifacts): fill stable snapshots through direct descriptor reads
* docs(perf): qualify stable snapshot memory with real ELF and BEAM tasks
* test(artifacts): count descriptor close retries from admission
* test(artifacts): capture the retained descriptor after asynchronous admission
* docs(perf): record integrated qualification and cleanup fixture correction
CDP joins repeated response header field lines with LF. Only the Link projection split them, so a repeated Content-Security-Policy lost the first directive of each later policy, and a repeated Referrer-Policy reported no policy. Header normalization now keeps each field line, CSP parses every line and comma-separated policy, single-valued fields combine lines with a comma, and Link uses the shared lines.
fix(functions): name the rejected side and supplied kind in Evidence errors
Function comparison previously reported only that analyze_function/rea.analysis Evidence was required, leaving callers to discover which side was wrong and what was supplied. Include the side, its operation and predicate, and the expected pair in the input issue.
Co-authored-by: dhruvac29 <[email protected]>
Own operation results and exact rejections in withVerifierCleanup, including
undefined, null and independent cleanup failures. Remove the optional-primary
cleanup contract and migrate every caller, preserving returns, annotations,
signal restoration and dependent cleanup order.
Make Frida/JEB reporters fail on reasonless rejections and retain JEB fixture
files while provider cleanup is incomplete. Own the nested packaged WASM
verifier and expose its composite process/root cleanup capability for retry.
Update runnable docs and isolated fixture dependencies.
Validation: 547 focused cases in 20 files, eight isolated boundary unit checks,
static/build/docs/discovery gates and duplication check (3.58%). Node process,
SDK and descriptor cleanup are exercised; provider and packaging results in
orchestration tests are simulated. Pack/install subprocess ownership remains
with the existing shared package runner outside the nested-command change.
* fix(setup): report host-owned cleanup resources alongside the primary's
SetupHost.close documents that it reports the resources a setup host still
owns, but its contract returned only a string. runSetup therefore built the
ProviderCleanupError from the primary failure's cleanupResources alone, so a
resource the host failed to release reached the projection only inside a
free-text reason while the error asks the caller to review the reported local
resources.
Return a SetupCloseReport instead. closeSetupResources absorbs the structured
resources of any cause that reports them, through
ArtifactReaderFailure.cleanupObservation, and leaves opaque failures
message-only so no resource name is invented. runSetup then unions the host's
resources with the primary's before building the typed cleanup error.
Two boundary tests read the close result directly: the skill-cleanup case now
asserts the retained backup path in the report reason rather than in a bare
string, and the shared ownership helper takes an opaque close result because it
only ever awaits undefined from either host it is given.
Validation: RED then green in src/application/Setup.recovery.test.ts, where
the new case previously received only the primary resource; 116 tests across
the seven Setup and cleanup-ownership suites pass; tsc --noEmit over the
changed set, its setup callers, and both boundary tests exits 0; oxlint
reports 0 errors; oxfmt --check is clean; verify:module-boundaries passes.
The two failures in src/setupEnvironment.test.ts reproduce identically on
pristine bded9c628 with this change stashed.
* fix(setup): preserve cleanup ownership through host reports
* fix(setup): bind finalization reports to cleanup owners
* fix(setup): retain live resources in returned cleanup views
* fix(setup): preserve completed cleanup and exact installer resources
* fix(setup): retain delegated cleanup across authority changes
* fix(setup): compose callback and source cleanup authorities
* fix(setup): retain producer cleanup failure reasons
* fix(cli): render structured setup cleanup resources
* fix(setup): separate failure evidence from cleanup ownership
* fix(setup): normalize close failures and unify lease binding
* fix(setup): preserve direct lease resource attribution
---------
Co-authored-by: gensokyo-dev <[email protected]>
Remove the reconstruction-only request schema and consume the canonical parsed
JavaScript application input. Production already owns parsing at the service
boundary; direct test seams now use that same schema instead of a weaker path
contract. Preserve format, filesystem, source selection and lifecycle validation.
Add a NUL-path regression for canonical admission and typed input-error
projection. Verified 63 focused cases plus static, build, docs, discovery and
duplication checks; no target execution or real-provider claims.
Route application and provider-environment harnesses through the shared MCP
connection owner. Join accepted handshakes during shutdown, retain each failed
close for retry, preserve primary and independent cleanup failures, and release
provider files only after their session closes.
Surface BinarySession close Result errors in production and artifact fixture
teardown. Add real SDK and descriptor-boundary regressions for startup races,
concurrent cleanup, mixed failures and recovery. Use a provider-free plist for
descriptor ownership so installed deep engines cannot change the test outcome.
* perf(entropy): separate physical reads from report blocks
* test(entropy): type the injected positional short-read boundary
* test(entropy): retain full catalog transport capacity in task probe
* docs(perf): record real entropy task costs and limits
* docs(perf): record latest-main entropy qualification
* test(native): expect artifact_changed when a bound metadata target is lost
41e10b240 made a bound metadata target that fails the source boundary
(`path`) or disappears (`ENOENT`) report AnalysisArtifactChangedError, as
its comment and docs/testing.md state, but left the module test expecting
AnalysisInputError. The test now asserts the shipped contract, so main's
Test shard and Portable tests lanes pass again.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(package): ship the CLI process environment owner in launcher fixtures
c2caae88f moved launcher environment preparation into
scripts/lib/cli-process-environment.mjs, made scripts/rea.mjs import it and
made verifyPackagePack require it in the packed listing, and updated the
dispatcher fixtures, but two other fixtures still omit it:
- packageTarListing's fake tar listing, so every case stops at "package
omitted the CLI process environment owner" before its own assertion;
- deferredRuntime's copied compiled package, so the copied launcher fails
to resolve its import instead of reporting the corrupted catalog.
Both fixtures now include the module, as the package ships it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(native): expect XML plist validation in typed-value provenance
9f5dd56e2 records a successful `plutil -lint` of an XML plist source in
provenance, as docs/native-investigation.md states, but the macOS typed-value
CLI test still expected only the `file` step for both formats. XML sources now
expect the lint step; binary sources are unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
* feat(cli): accept JavaScript source selections from a JSON array or file
Add --source-paths-json to analyze and analyze-javascript-application.
It takes an inline JSON array or a JSON file path of exact inventoried
paths and appends them after any --source-path values, so a long
selection no longer has to fit on one command line (cmd.exe through npx
on Windows stops at 8,191 characters). Entries stay artifact-relative and
go through the existing source_paths validation; the native lane rejects
the option like --source-path.
Refs #4987
* fix(cli): cancel --source-paths-json file reads with the command
Pass the command's abort signal through parseCliJsonInput to
readJsonInputFile, so SIGINT/SIGTERM stop a selection-file read instead
of waiting for it to finish. A cancelled read now propagates its abort
rather than being reported as a file read failure.
* test(cli): preserve ASAR identity for JSON file selections
* docs(cli): record source-selection task costs and identity verification
---------
Co-authored-by: KJLavender <[email protected]>
Co-authored-by: Kaoru0822 <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: gensokyo-dev <[email protected]>
Give the launcher and shared command worker one lightweight owner for package-version binding, Windows empty-home handling and Android browser-cache defaults. Preserve per-command preparation and environment restoration, package the owner explicitly, and retain its package and JavaScript recovery CI scopes.
Validation: dispatcher/version/shared-session, home fallback, evaluator/MCP/process cleanup and CI scope tests passed. Functional archive/install/repack, installed static CLI analysis and MCP checks passed; no real Codex/model trial or Windows/Termux runtime qualification was performed.
Keep the maintained manual evaluator, fixture rubrics and semantic tests together under tests/evaluation/model-evals instead of shipping them in dist. Load the same typed owners from the manual runner and update the architecture and client guide. Grading/report contracts and executable logic are unchanged.
* feat(pe): inspect import and delay-load tables
Add inspect_pe_imports / inspect-pe-imports to read PE32/PE32+ import
and delay-load directories without executing the image. The report keeps
DLL names, named and ordinal functions, ILT/IAT RVAs, and a pefile
import hash of the standard import table. A missing directory is
observed absence, not proof the image never imported APIs.
* fix(pe): default PE import fixture options
Allow peImportImage() without an argument so CLI and filesystem tests
can use the KERNEL32 sample without repeating an empty options object.
* test(pe): keep import path cases on the dedicated MCP contract
inspect_pe_imports already rejects relative MCP paths in its own
boundary test. Leave the shared absolute-path matrix to tools whose
handler issue projection matches that suite's expected shape.
* fix(native): index virtual-to-file mapping lookups
mappedFileOffset scans every mapping twice per span, so a parser that
translates one span per table entry costs sections x entries. Add
fileMappingLookup, which builds an O(n log n) interval index once and
answers each span in O(log n) with the same accept, reject and
translation results. A differential test checks it against
mappedFileOffset over randomized overlapping mappings and zero fills.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Ra7LM2NyQ7DumdssxbUq5g
* fix(pe): report partial import evidence and exact pefile hashes
- Withhold imphash with an explicit reason whenever the standard import
table is partial (unreadable names or thunks, missing tables), or when
pefile 2024.8.26 would hash a different row sequence: invalid or
truncated names, ordinal 0, descriptors without functions, tables its
bounds or repeat/spread heuristics discard, and its 8192-thunk import
symbol cap. Delay-load issues do not withhold it.
- Hash ordinal imports with pefile's complete ordlookup tables and its
ord<decimal> fallback instead of declining unmapped ordinals.
- Report a nonterminal descriptor whose FirstThunk is zero, and a
delay-load descriptor whose IAT or INT RVA is zero, as malformed_entry
partial coverage instead of a complete empty inventory.
- Directory evidence lists the file spans actually consumed for the
descriptor array and terminator; discontiguous mappings produce
separate spans and separate Evidence ranges.
- Carry exhausted limits as PeImportLimitFailure.limit and derive
recovery from it; the fixed 16 MiB retained-text ceiling reports a
fixed allowance instead of max_file_bytes advice.
- Translate RVAs through the indexed mapping lookup and yield with a
cancellation check every 1024 table entries.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Ra7LM2NyQ7DumdssxbUq5g
* fix(pe): read only own ordinal tables for DLL names
DLL names such as constructor and __proto__ pass pefile's name rule but
resolved inherited object members, throwing before the ord<n> fallback.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Ra7LM2NyQ7DumdssxbUq5g
* fix(native): preserve PE import facts and prove hash compatibility
* test(native): verify PE import workflows and measured costs
* refactor(native): narrow PE facts across the container union
* docs(native): record integrated PE import validation
* fix(native): bound every PE import RVA span
* docs(native): measure RVA guard completed workflows
* fix(pe): reconcile import coverage with retained rows
* fix(pe): retain partial imports at descriptor mapping gaps
---------
Co-authored-by: Matt Van Horn <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: gensokyo-dev <[email protected]>
When Smart App Control or an App Control policy refuses
rea-windows-x64.node, the loader reported the failure as the artifact
stage. Doctor and provider diagnostics then told the user to restore or
rebuild the native files, although their version and SHA-256 had
already matched the package manifest.
The loader now tags a failure of the module load itself, after the
manifest and digest checks pass, as the load stage. The reason keeps the
Windows error text and says that restoring the file cannot help, that
Ghidra and JADX need the native controls, that rea setup can still
register clients, and that REA must run where policy allows the file or
the maintainers can be asked about a signed build. Readiness keeps the
documented runtime_missing code for unloadable artifacts.
Setup does not depend on the native controls: with the addon
unavailable, the published 6.7.0 CLI still planned and applied the
claude_code registration, so no setup gate is changed.
Fixes#5723
Use exact recorded start facts for state extraction independently of derived clock formatting limits. Preserve millisecond interval policy, missing-time fallback, redacted-write cutoffs, and bounded timestamp retention; remove the superseded clock comparator.
Two source and two compiled CLI regressions reproduced post-write values being selected as initial state. State/clock/date, CLI/MCP view, and static checks passed after the fix.
Move the synthetic evaluator and its unchanged semantic tests out of the shipped runtime. Retain actual CLI and MCP Evidence separately from the synthetic nine-stage baseline in a versioned verifier artifact, execute its reported conformance checks, and assign the verifier to its CI lane.
Validation: evaluator/state/classifier source suites, compiled CLI/MCP views, verify:readiness, static checks, build and docs passed. Readiness observed coverage is static analysis; fixture runtime behavior and reconstruction closure were not executed.
Resolve the filesystem-selected manifest parent once before deriving script paths and reuse the shared containment rule. Preserve selected manifest spelling and capture metadata while retaining source integrity, symlink refusal and cleanup. Cover differing and identical lexical siblings through both artifact consumers and public CLI/MCP parity.
Move body-retention coverage accounting to the manifest request-line owner. Preserve source retention facts by ordinal and remove the competing eligibility rule from scenario projection.
Remove the redundant spelling gate after the shared intrinsic owner proves native constructor and source-base identity. Retain local-constructor and replaced-export uncertainty through public application analysis.
Consume the signature producer status before inferring operand-resolution limits. Preserve exact byte-match provenance while malformed paired signatures remain unknown through current and historical Evidence, CLI and MCP.
Retire the unused graph serialization facade and use one typed query implementation after canonical request admission. Migrate tests to the owning schemas while preserving graph commitments, Unicode transport, provenance, uncertainty, traversal and reconstruction controls.
* feat(javascript): link assignment right-hand sides to their writes
A declaration carries its value forward, but a later assignment to a
variable, a property or through a compound operator stopped the forward
trace at the right-hand-side read. The semantic IR now records one
syntactic assignment flow per simple assignment target (ranges, operator,
owning callable), and the graph projection connects each retained read
of the right-hand side to the write occurrence through a defines
relation. Compound assignments also consume the previous value of the
target; the written value itself stays unknown, keeping the boundary of
#4342 intact.
Fixes#6193
* fix(javascript): preserve computed key assignment ownership
* test(javascript): retain nested callback assignment ownership
* docs(javascript): record assignment influence verification
* test(mcp): isolate mocks and acknowledge cancellation boundaries
* test(javascript): retain CLI diagnostics and current-main verification
---------
Co-authored-by: gensokyo-dev <[email protected]>
Use the authoritative scenario schema directly in all 25 test consumers. Preserve unknown-input annotations and every lifecycle, permission, normalization, identity and cleanup assertion; retain the separate branded capture validation boundary.
Retire test-only coverage and verifier constructors while preserving the live authenticated reader and evaluation path. Derive fixture inputs from the canonical contract schema and author commitments with an independent canonical JSON hash. Remove redundant success assertions while retaining typed failures and semantic controls.
Remove the unused estimator export. Check storage and escaping through typed authentication refusals with fixed allowances, preserving bounded traversal and acceptance controls.
Remove test-only completion and historical manifest parsers, use authoritative completion schemas, and keep graph hashing with the validated manifest producer. Verify commitments with independent canonical JSON and SHA-256 checks through domain and public CLI workflows.
Remove the isolated package, replay and trust-gate modules with their synthetic-only tests. No application, CLI/MCP, verifier or package export consumes them. Keep active provider completion, managed conformance, fixture verification, readiness and reconstruction coverage paths.
Retain the selected catalog path with captured assetutil failures and malformed metadata. Map two explicit selected-path invalid-catalog diagnostics to the existing format error while preserving other failure classifications. Verify the observed diagnostic through the real CLI and stdio MCP using a truncated temporary catalog and an unchanged valid control.
Reject normalization omission counts that exceed unknown-size rendered frames at the shared capture parser. Preserve historical captures without the optional stage counter and expose the same constraint through CLI and MCP diagnostics.
Use the active in-scope materializer directly from the existing inventory fixture, with the same explicit resource-scope admission and cleanup owner. Keep staged snapshot mutation and extraction lifecycle regressions intact.
Remove the unintegrated memory-map and peripheral-attribution modules with their dedicated tests. No application, CLI/MCP contract, verifier or package export consumes them; the shipped firmware analysis and publication workflows remain unchanged.
Remove the undocumented name alias from list_names fallback and validate the canonical value rows with the existing strict policy. Keep record defaults in the public input contract and require explicit decoder budgets. Preserve provenance, partial coverage, source coordinates and typed failures in active application and MCP tests.
Pass the caller-selected input field to the shared managed parse-failure
owner. Derive filename and field from one comparison selection, reporting
leftPath or rightPath while ordinary inspection continues to report path.
Preserve typed input classification and completed-left partial Evidence.
Replace weaker direct malformed-input cases with a compiled CLI workflow
covering both sides, the healthy comparison, and sibling inspection.
Document the input-attribution contract.
Validation: the public regression reproduced the generic path issue;
focused CLI, comparison and shared-reader controls passed after repair.
No managed assembly or external analysis provider was executed.
Use one containing-procedure parser beside its declared schema for
navigation, address facets, and feature trace references. Keep the trace
cache and reference type bound to parsed facts, returning typed malformed
output before SDK projection instead of passing unchecked JSON onward.
Retain same-address search alternatives such as Kuna's distinct string
encodings. References identify target addresses, so observe and emit each
target once while retaining duplicate rows from the provider observation.
Remove address-only match collapse and redundant residual deduplication.
Document these semantics.
Validation: regression-first runs reproduced four malformed-resolution
failures and three alternative/reference-replay failures. Focused MCP and
consumer controls passed after repair. Real native engines were not run.
Retain relevant program facts in the shared native directory and consume them for mappings and relocations. Remove redundant table coordinates and presence flags. This preserves extended program counts so PT_DYNAMIC beyond the raw sentinel remains visible, while load and relocation admission keep their distinct policies.
Parse module metadata at the image reader that validates its framing. Consume those facts in the provider while preserving raw bytes, text uncertainty, source locations, parser semantics and the public report contract.
Remove the test-only selection/projection facade and its unused synthesized binding scan. Keep lexical and identity controls at their active owners, with combined behavior covered through EnhancedTools.
Successful worker transport can carry an explicit failed parser status
with no semantic projection. Preserve that producer fact through the
shared source-availability interpretation used by full and incremental
graph construction, rather than dropping the source's semantic scope.
Retain the module when capacity permits, per-family incomplete-module
unknowns, and unknown omitted extents. Preserve existing operational
failure reasons and limits without classifying syntax as resource loss.
Document this coverage behavior.
Validation: regression-first run had 3 expected failures; all 22 selected
projection and public CLI source-selection/HTML cases passed after repair.
No JavaScript target execution or live external provider was involved.
Pair a preceding low surrogate only with its adjacent high surrogate.
Unpaired code units must not make an earlier letter become the token's
neighbor. Keep UTF-16 offsets and source strings unchanged at the shared
delimiter owner used by rule discovery, copy checks, and replacement.
Cover valid astral letters, digits, emoji, and lone-surrogate controls,
plus create/read behavior through a CLI-started environment MCP server.
Validation: regression-first run had 4 expected failures; after the fix,
437 selected domain, application, and server-boundary tests passed.
Use the existing builtin argument split for the invalid-log-level doctor exemption, removing independent flag scanners from the launcher and reusable CLI test worker. Empty output values and doctor-looking command data now preserve configuration refusal precedence; shell completion stays transport data.
Check fresh and shared frontends with production argument parsing, retain both doctor readiness paths, and verify non-doctor requests stop before the real launcher imports command handlers.
Validate engine output in the worker and transport output at reply admission. Have the typed function projector consume admitted producer facts in the provider, removing the fused parse/project facade and discarded worker projection.
Preserve duplicate order, missing inferences and raw metadata. Keep malformed producer checks at the schema and cover the provider handoff with source identity, diagnostics and cleanup assertions.
Read screenshot identity from the selected frame-tree root instead of a
filtered inventory that could substitute a child. Reuse the frame record
parser for initial and event identities, rejecting malformed roots before
capture while preserving known origin refusals.
Share explicit origin-scope diagnostics across CDP workflows without
changing policy or conflating startup uncertainty, document replacement,
worker protection, and Inspector restrictions. Document the recovery and
make screenshot navigation fixture ordering explicit.
Validation: 577 focused checks passed across 13 files; one platform-specific
invalid-byte-filename case skipped. Build, typecheck, lint, formatting,
generated documentation checks, README conformance, and discovery passed.
No full suite or live browser/provider execution.
Carry exact target keys and canonical processor facts from Clang bundle and ELF metadata producers into inventory agreement checks. Remove the string-only handoff and downstream reparsing while keeping public spelling, selection, uncertainty and admission behavior.
Cover unrecognized targets, conflicting notes and identity retained before malformed notes through the provider boundary. Preserve distinct unselected-payload behavior for standalone ELF and known bundle targets.
Use one lossless Mach-O name projection for symbols and dependency paths, retaining undecodable bytes and partial binding facts. Keep referenced NIB string failures unknown and preserve their source nodes through the shared lazy projection. Valid Unicode, readable sibling metadata and weak-bind scope remain usable.
Exercise the producer and CLI/MCP consumers, and align date-overlap and object-capacity fixtures with their owning archive contracts without relaxing admission or omission assertions.
Remove the test-only Objective-C property facade that discarded completeness. Verify its remaining semantics through portable Mach-O metadata decoding, including retained partial properties and located issues.
Decode the single IDA text result directly while preserving native JSON and structured-content precedence. Update the stale SDK deadline assertion to check the busy tool through its diagnostic owner.
* feat(ghidra): bound one procedure's decompile without closing the session
Fixes#5340
* fix(ghidra): report decompile limit as a request timeout
Keeps BinarySession from marking every Ghidra operation unavailable after one procedure's decompile reaches the limit, and names the MCP tool-call deadline in the remediation.
* fix(ghidra): budget the decompile limit and report cancellation-closed sessions
Adds REA_GHIDRA_DECOMPILE_TIMEOUT_SECONDS to the derived Codex/Kimi tool deadline and forwards it through setup. Marks a remote failure that settles after caller cancellation so the timeout projection no longer promises session reuse.
* feat(ghidra)!: default analyze_function to a retained summary
analyze_function was the one analysis tool never wired into REA's
detail: summary|complete convention, so it always returned the complete
native dossier inline (0.2-10 MB, dominated by value-flow and
references). Agents on tool-result-capped harnesses never reached the
pseudocode.
Add `detail` to analyze_function, defaulting to summary: return a
compact dossier (procedure identity, pseudocode size, facet counts,
value-flow availability) and retain the complete dossier Evidence in
the session. Page pseudocode, references, assembly and value-flow
through normalized_result.parent_evidence_id with inspect_analysis_view,
which already projects every native facet. detail: complete returns the
full dossier inline as before. Delivery detail never reaches the
provider or Evidence identity.
BREAKING CHANGE: analyze_function now defaults to the compact summary
view instead of the complete dossier inline. Pass detail: "complete"
for the previous behavior.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* feat(cli): expose analyze_function detail on the function command
Wire `rea function` into the shared CLI detail-delivery convention
(--detail, --evidence_output) so the CLI and MCP adapters offer the same
summary | complete choice for analyze_function. Summary delivery writes
the complete dossier Evidence to a bundle and returns the compact
summary view; it fails before analysis when --evidence_output is
missing, so no provider work is wasted. The CLI default stays complete
because a one-shot command has no in-process Evidence retention.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* refactor(ghidra): harden analyze_function summary after independent review
FlatlineRoundtable cross-model review (6 lanes) converged on the summary
projection's availability semantics being underspecified. Document that
facet_availability is authoritative over raw pseudocode length, that
code_units are UTF-16 (the unit inspect_analysis_view pages by), and that
value_flow.truncated is meaningful only when value-flow is available.
Parenthesize the nullish-coalescing/comparison for clarity. No behavior
change; declined claims (value-flow "truncated collapse", unresolved_calls
dead code) were schema-impossible or already correct.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* test(ghidra): cover analyze_function detail wiring on both adapters
Close the roundtable's top convergent finding: the summary path had only
domain-projection coverage, not the server/CLI wiring where the breaking
behavior lives.
MCP server (registerEnhancedTools): the default delivers a retained
summary whose complete parent is recorded for paging; delivery detail is
stripped before the provider request; detail: complete returns the full
dossier inline; a registration without retention rejects a summary
request before any provider work.
CLI (rea function): the default returns the complete dossier; --detail
summary without --evidence_output fails before analysis; with the bundle
sink it returns the compact summary and writes the complete Evidence
bundle.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(ghidra): keep analyze_function delivery detail out of provider inputs
Address the five automated review findings on #5660.
P1: `detail` lived in the shared enhancedInputSchemas.analyze_function, so
inspect_native_api composed `{procedure, detail: "summary"}` and the strict
Ghidra analyze_function schema rejected it. Delivery detail is now owned by
the analyze_function MCP tool contract; the handler separates it before any
provider call, and executeFunctionAnalysisEvidence parses the provider input
only. The MCP regression test validates provider input exactly as the
production Ghidra client does and exercises inspect_native_api.
P2: the analyze_function summary Evidence now carries the parent's
relationship_coverage like native facet views, so partial or unknown
caller/callee discovery is not reported as complete.
P2: the summary reports the dossier's declared facet_availability, nulls the
counts of facets the provider declared unavailable, and lists each reason in
unknowns, so Kuna's empty references, comments and basic blocks are not
mistaken for observed absence.
P2: inspect-analysis-view evidence-file sources accept the Evidence bundle
that --evidence_output writes, selecting a record with source.evidence_id
when the bundle holds several; the CLI test reads the saved bundle back
through that route.
Tests that assert the complete dossier over public analyze_function now pass
detail complete, and the oversized-dossier test asserts the summary view it
previously expected to be unsupported.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(ghidra): keep omitted function facets unknown in the summary
The analyze_function summary coerced an omitted unresolved_calls record to
a count of 0 while the native facet view reports the same dossier as "not
recorded", and it carried no counts at all for the pageable
swift_string_literals facets. Count optional records as null when the
dossier omits them, name them in unknowns, and add nullable counts for both
Swift literal facets. The summary Evidence envelope also dropped the
function address: createAnalysisViewEvidence now derives one function-view
predicate for both the address location and relationship coverage.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(scripts): request complete analyze_function dossiers in real-provider checks
The real-provider check scripts call analyze_function over MCP and then
consume the complete dossier: requireFunctionDossier, functionDossierSchema,
.procedure/.pseudocode reads, operation assertions, compare_functions inputs
and the oversized-dossier rejection path. The summary default broke them.
Every such call site now passes detail: "complete". Provider-direct callers
are unchanged because detail is an MCP contract field; the admission-error
sites stay unchanged because provider failures return before the summary
branch.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(ghidra): keep unavailable value-flow counts unknown in the summary
summarizeDossier coerced the five value_flow_* counts to zero when
native_value_flow was null (IDA, Kuna) or declared unavailable (Ghidra),
so the summary reported empty collections while value_flow.available said
otherwise. The counts are now null unless value flow is available, with the
reason already named in unknowns.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(evidence): budget authentication headroom by file shape and serialized size
The evidence-file headroom reserved two parsed copies, calibrated for one
record, and charged strings at two bytes per character. Bundle
authentication additionally holds the schema-parsed bundle, the re-parsed
records and two JSON.stringify results, which expand control characters and
lone surrogates sixfold: a bundle whose raw_result is a million NUL
characters estimated at 2 MB parsed but needed 12 MB of serialized text.
The budget now has a parsed term and a serialized term per file shape, owned
by EvidenceAuthenticationHeadroom and shared by the analysis-view reader and
the bundle importer, which had no guard. Two transient peaks the budget did
not name are removed at their producers: the canonical digest hashes a large
leaf directly instead of concatenating it into its buffer, and the JSON
validator walks containers by cursor so a wide array no longer queues one
entry per member.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(mcp): route analyze_function summary replies to dossier consumers in docs and prompts
The MCP guide, the version-comparison and crash-triage prompt contracts,
the authored skill and the Kuna, IDA and function-matching docs still told
agents to pass analyze_function replies straight to compare_functions or
build_call_path. Under the summary default those consumers reject the reply.
They now name the retained-evidence reference for compare_functions, the
observations fields of match_native_functions, and detail: "complete" for
build_call_path, which accepts only inline dossiers.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* test(evidence): pin validator member order and keep interrupted validation yielding
Independent review of the cursor validator found the interrupted-validation
fixture relied on the old last-first walk: its over-deep head was reached
before the first cooperative yield. The padding now precedes the deep
element so the walk yields first, which is the invariant the test guards.
A new case pins first-defect-in-member-order reporting, skipped
non-enumerable keys no longer count toward the yield cadence, and the
import-headroom test loads the reader through a fresh module graph so it
holds under the services project's shared workers.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(ghidra): align deadline bounds and cancellation outcomes
* refactor(ghidra): shorten deadline recovery guidance
* fix(mcp): clarify the scope of inferred decompile deadlines
* test(ghidra): verify deadline workflows and document measured costs
Separate failure and registration cases by their distinct contracts.
Record actual Linux Ghidra, CLI and MCP evidence with measured context,
elapsed time, CPU and memory, and explicit remaining coverage limits.
* docs(ghidra): pin integration and distinguish baseline format failures
* fix(ghidra): own failure lifecycle wording in the provider
* test(ghidra): budget timeout fixture generation before allocation
* fix(analysis): preserve summary provenance and bound bundle guidance
* fix(ghidra): align capability and traversal deadline guidance
* style(config): align deadline guidance formatting
* docs(ghidra): record capability and traversal verification
* docs(analysis): use absolute paths for Evidence files
* docs(analysis): record completed function summary measurements
* docs(analysis): update main integration validation
---------
Co-authored-by: Syed Rishad <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: gensokyo-dev <[email protected]>
Keep the JSON parse attempt and exact numeric source literals together through optional XML classification. Replace the probing parse and raw-string parser with readPlistJson, preserving duplicate-key behavior, signed zero, ambiguous number types, prototype omissions and failure precedence.
Project fresh results from private facts and preserve native command controls, captures and provenance. Verify parser reuse and real provider-boundary conversion choices, plus compiled CLI and MCP behavior with real plutil.
Reuse filesystem-aware path selection for resource-only plist sessions so directory symlinks and trailing separators retain their meaning. Parse dyld bind names once as lossless text or exact bytes, preserving partial binding facts and independent valid metadata without invented class identities. Keep coverage issues separate from known opcode applicability and exercise both producer and generated Mach-O consumers.
Restrict Windows A/W suffix and stdcall candidates to their applicable native format. Preserve original metadata and per-observation Evidence ownership. Exercise identity contradictions and wrong-role controls through the shared CLI and stdio MCP workflows.
Fixes#6926
Decode base64 JSON body bytes at the shape owner without replacement characters. Keep incomplete request correspondence unknown and use explicitly complete authored inventories for positive comparison controls. Repair semantic truncation and storage fixtures to satisfy their owning contracts without weakening assertions.
Keep Mach-O UUID interpretation at reconciliation, environment values at the details owner, and inventory scope admission at the public operation. Remove the obsolete UUID scalar, duplicate DSH dispatch, two intermediate inventory exports, and unused body-cutoff predicate.
Keep test resource scopes explicit and cover oversized bodies through the real comparison workflow. Correct stale DSH invalid-result assertions and model DMG cancellation with the command owner, retaining an opaque AbortError control and mount cleanup checks.
Verify fresh provider budget resolution without coupling inspection to probe counts, while preserving caller-selected positive timeouts and file bytes. Compare effective peer registrations before and after updates instead of rebuilding legacy OpenCode entries in a different representation.
Project the supervisor's compact stop flag to an explicit boolean only when an owned snapshot is available. Require confirmed false before treating SIGKILL as external or attaching cgroup kill evidence, so missing diagnostics remain unknown.
Cover known false, true and missing facts while preserving operation-scoped OOME precedence and real owner cleanup behavior.
Bind multi-owner shutdown errors to their live typed cleanup dependencies so retained aggregates narrow and clear as each resource is released. Keep unknown or already-resolved rejections conservatively incomplete.
Cover both release orders, retained MCP Evidence, late cancellation and retry through the SDK session shutdown boundary.
Carry descriptor outcomes, cancellation, retention and physical origin as named facts so wrappers cannot drop ownership context. Replace raw primary failure unwrapping with provenance facts across artifact consumers, and use Result for Kuna span reads including undefined rejections.
Exercise actual descriptors, rollback, cancellation and cleanup retry; update brittle snapshot and completion fixtures to use their producing boundaries.
* feat(ghidra): bound one procedure's decompile without closing the session
Fixes#5340
* fix(ghidra): report decompile limit as a request timeout
Keeps BinarySession from marking every Ghidra operation unavailable after one procedure's decompile reaches the limit, and names the MCP tool-call deadline in the remediation.
* fix(ghidra): budget the decompile limit and report cancellation-closed sessions
Adds REA_GHIDRA_DECOMPILE_TIMEOUT_SECONDS to the derived Codex/Kimi tool deadline and forwards it through setup. Marks a remote failure that settles after caller cancellation so the timeout projection no longer promises session reuse.
* fix(ghidra): align deadline bounds and cancellation outcomes
* refactor(ghidra): shorten deadline recovery guidance
* fix(mcp): clarify the scope of inferred decompile deadlines
* test(ghidra): verify deadline workflows and document measured costs
Separate failure and registration cases by their distinct contracts.
Record actual Linux Ghidra, CLI and MCP evidence with measured context,
elapsed time, CPU and memory, and explicit remaining coverage limits.
* docs(ghidra): pin integration and distinguish baseline format failures
* fix(ghidra): own failure lifecycle wording in the provider
* test(ghidra): budget timeout fixture generation before allocation
* fix(ghidra): align capability and traversal deadline guidance
* style(config): align deadline guidance formatting
* docs(ghidra): record capability and traversal verification
---------
Co-authored-by: gensokyo-dev <[email protected]>
Recognize baseline-dependent #JTD metadata at the shared layout owner before table sizing and decoding. Report unsupported partial metadata across all inspection workflows, preserve admitted PE/CLI and metadata header facts, and keep member identities and inventories unknown without the baseline.
A generated PE carrier reproduced complete coverage and a wrong standalone MethodDef token before the fix. Producer and actual CLI/MCP checks now cover all three inspections, normal metadata, retained comparison after source deletion, exact caller selection, source digests, unchanged bytes, and known header facts. Released .NET writer/reader sources establish framing applicability; natural PE occurrence and real CLR/Edit-and-Continue execution were not verified.
Reuse the existing direct-call returned-reference owner for immediate synchronous function results and feed proven loader facts into historical imports. Simple returned require retains its identity; mixed, opaque, and canonical shim alternatives retain explicit uncertainty rather than disappearing.
Focused semantic, Electron, and public CLI regressions passed, including CommonJS, ESM, async/generator, mutable argument, direct-loader, and source-provenance controls. No runtime target or Proxy evaluator was introduced.
Fixes#3535
Reuse the nonempty NUL-free local path contract before normalization in artifact commands, auxiliary inputs, and output destinations. Empty selections now fail at parsing instead of selecting the working directory; explicit relative paths preserve their target.
Public CLI checks cover primary and auxiliary empty paths, exact relative-file digest, explicit current-directory selection, symlink parent semantics, and environment export inputs. Correct the desktop fixture to assert the existing CLI validation envelope.
Classify lipo parse failures once for native and artifact consumers, retain valid read-only ELF ranges independently of optional section names, and map IL2CPP reader architecture through the existing CPU identity owner before Mach-O parsing.
Regression-first checks reproduced malformed lipo output, lost unnamed-section compiler paths, and the amd64/x86_64 adapter mismatch. Focused parser, artifact, Rust CLI/MCP, Go, and IL2CPP controls passed; authored fixtures do not establish real-provider behavior.
Fixes#5982Fixes#3397
Resolve application and managed workflow contracts through the canonical name-based resolver, removing catalog-position overloads and the obsolete local facade.
Use the existing retained-summary policy for eight offline registrations. Pass only validated delivery detail to that owner while preserving exact typed service inputs and validation, admission, logging, and Evidence recording order.
Align export-shape MCP parity coverage with the existing absolute-path contract using an absolute dot alias. Preserve exact caller-path parameters, canonical artifact parity, distinct Evidence identity, and the export comparison assertions.
Resolve declaring TypeDef tokens within their own source and reuse the retained nominal identities for pairing, absence, and aggregate coverage. Remove display-name membership interpretation while preserving partial known pairs and whole-inventory matching.
A generated managed fixture reproduced false additions and removals for distinct nested owners sharing a display name before this change. All 305 focused producer and public CLI-to-stdio-MCP checks passed, including comparisons after source removal, missing identities, and genuine whole-inventory changes. Clarify selected-scope semantics in the docs; no live managed runtime was used.
Select registration without skill installation in the synthetic-client recovery matrix. Preserve all four specific remediation assertions and verify the plan, failure reason, and absence of unrelated installation work.
Route MCP snapshot reads through the session's existing file-resource owner so cleanup remains visible, blocks replacement, and can be retried by close_binary. Keep reads inside the serialized open callback and remove superseded adapter resource plumbing.
Validate typed errors, exact descriptor recovery, unchanged source bytes, replay provenance, and same-connection lifecycle ordering. Focused snapshot, target cleanup, and MCP lifecycle checks passed with simulated providers; no live provider was exercised.
Fixes#6216
Classify selected-input read failures at the shared artifact boundary and remove duplicate phase-based translations from TShark and sigrok. Keep other read stages raw for their existing owners and retain cleanup resources until retry succeeds.
Extend the descriptor outcome matrix with post-run private-copy integrity failures, late cancellation, retained command output, failed cleanup, and successful retry.
Project admitted output facts beside the command owner and remove adapter-local copies. Preserve byte-count omission, explicit signal and exit facts, and caller-specific truncation and failure policies.
Update ADB timeout regressions to assert the existing prerequisite frame and original process cause, including captured output on both frames.
Derive aggregate selected-scope agreement from retained nominal type identities instead of requested spellings. Keep incomplete or historical selected scope unknown while preserving caller selections, whole-inventory distinction, paging and member absence behavior.
Cover equivalent requests, same-label nested owners, missing and partial identity facts, and complete empty selections. Exercise CLI inspection Evidence through stdio MCP comparison after removing its selected source file.
Keep the selected running JVM visible when its version is unsupported, while retaining missing-runtime fallback controls. Assert the native snapshot binding and composed workflow Evidence profiles separately, preserving their exact commitments through a rejected snapshot switch.
Preserve source code-point prefix endpoints in the shared marshal UTF-8 decoder, including separately encoded surrogate values. Keep native TextDecoder spans, full validation, byte identity and the existing 80-unit budget. Update the PyInstaller consumer without changing its text contract.
Validation: 207 relevant source tests;24 affected compiled CLI/MCP/filesystem CI tests; independent CPython3.11.2 compiler/marshal oracle and real argparse;18 equivalent performance tasks; build/check passed. Codex reviewed7c0f7abc6b without major findings.
CI bypass authorized for demonstrated baseline-only failures:101 source and179 built cases reproduced on actual tested main ba9c5bc68. Cancelled shard remainder is unverified. See PR body and discussion for scope and evidence.
Fixes#6476
Parse declarations before selecting values, admit safe integers once, and retain bounded raw numeric issues. Preserve display and package selection policies while distinguishing absent and malformed values.
Keep completed display facts in typed physical-size failures, share the existing diagnostic sample limit, and verify real CLI/MCP contracts with a strict fake ADB.
Parse MIME parameters once with strict quoted-value and duplicate handling,
and compare equivalent default binary profiles. Keep excluded HAR MIME
unknown, explicit framing independent, and nominal gRPC sanitization intact
across malformed or repeated declarations.
Add public CLI/MCP and native-header regressions with source identity and
partial-coverage assertions. Preserve upstream wire and schema admission.
Fixes#6836
Stop interactions and sampling before final observation, and stop the owned
target before failure-path rendering. Cache finalized terminal facts through
disposal and cleanup retry while preserving the original failure.
Version deferred terminal observation order for every normalization profile,
including disabled PID and port normalization. Add public CLI/MCP descendant,
partial-evidence and compatibility controls without replacing upstream owners.
Fixes#6443
Share parser-owned package and runtime facts across dependency consumers.
Preserve uncertain loader requests and explicit wrapper bindings without
inventing unbound require authority in known modules. Cover selected source
grammar through the public MCP boundary and retain ambient/type dependencies.
Open each selected directory before loading its scoped policy, retaining
partial directory failures and cleanup ownership. Preserve explicit caller
negation precedence and source diagnostics across inventory projections.
Clarify how version comparison retains container provenance without claiming
semantic drift. Use independent unknown source inputs to keep candidate-limit
fixtures meaningful as conditional branch evaluation becomes more precise.
Fixes#6891Fixes#6882Fixes#6883Fixes#6859
Validate the selected workspace lookup through stat before canonicalization,
preserving typed configuration causes and physical traversal semantics. Cover
readiness without writes and tie startup cleanup regressions to explicit
cancellation or timeout producer outcomes.
Fixes#6828
Omit absent inventory facts without erasing explicit unknowns. Compare canonical file occurrences by source path and digest while preserving complete container provenance in observations and Evidence.
Consolidate candidate-capacity fixtures around unresolved alternatives and update inventory coverage and source-occurrence oracles. Preserve resource, identity, relationship uncertainty, cancellation, and transfer regressions.
* fix(pe): accept WIN_CERTIFICATE padding counted in dwLength
* perf(pe): reuse decoded PKCS#7 ASN.1 tree
* style: format files inherited from main for CI
---------
Co-authored-by: morluto <[email protected]>
* fix(ghidra): report kernel OOM kills as a memory constraint
A kernel or container OOM killer ends Ghidra with SIGKILL and prints no
java.lang.OutOfMemoryError, so the failure fell through to the generic
execution_failure that points at `rea doctor`.
On Linux with cgroup v2, read the process's own memory.events oom_kill
count before launch and again after a SIGKILL. When it rose, project
resource_constraint (memory) with the group's memory.max, and advise on
the whole process tree (native decompiler processes included) instead of
a larger Java heap. Otherwise name the signal as a possible OOM kill.
Fixes#5859
* fix(ghidra): scope OOM-kill attribution to what the cgroup proves
Review follow-up for the SIGKILL projection:
- The process supervisor records stop_requested before it sends any
signal, and Ghidra diagnostics carry it, so a SIGKILL from REA's own
stop is never reported as an outside kill. Only process and protocol
failures qualify; launcher (start) failures can include REA's rollback.
- Word the memory constraint as an OOM kill in REA's cgroup or a child
group; the count is per cgroup, not per process tree.
- Keep the open_binary reopen guidance for an established session.
- Resolve the cgroup directory through the cgroup2 mount in
/proc/self/mountinfo, so subtree mounts are joined from their root,
and read kernel files to EOF within a budget.
- Report memory_max as "max" for an unlimited group and null only when
the limit could not be read.
The showcase illustration was a single light PNG, so it stayed a white
slab on GitHub's dark themes. Redraw it as a light and a dark SVG, and
swap the linked image in README.md and all 21 translations for a
<picture> with a prefers-color-scheme: dark source. Alt text and link
targets are unchanged. The PNG is deleted because nothing else uses it.
website/figures.md notes the pair.
🤖 Generated with Claude Code (Sonnet 5.5) 🦊
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
This reverts commit 56eca648d. The equivalent completed two-client measurement increased elapsed and CPU time, so compiler sharing has not established a benefit.
Separate malformed locators and fixed records from unsupported disk layouts or numeric representation limits at the ZIP tail owner. Preserve the classic 65535-entry fallback and existing downstream parsed facts.
Add public CLI and stdio MCP valid, damaged, restored and unsupported controls; document the bounded validation scope.
Fixes#6471
Keep typed search denial and acquired snapshot facts through cleanup and finalization. Record unfollowed symlink coverage at the snapshot owner, preserve physically enumerated parents, and retain uncertainty beneath omitted links without losing proven sibling deletions.
Update parsed omission contracts, public CLI/MCP regressions and documentation without introducing a new lifecycle or coverage framework.
Fixes#6446Fixes#6444
Coalesce equal parsed file definitions and reject conflicting same-name definitions before registry import resolution. Preserve field presence, known and opaque facts through one budgeted SDK parse while retaining original descriptor bytes and digest.
Keep unique files in their original order, reuse the existing admission traversal, and cover public CLI/MCP import, ordering, presence and source-provenance controls. Document REA ambiguity policy separately from protoc precedence.
Validate recorded-core program-header projections against the selected pyelftools architecture table after binding e_machine to the snapshot. Preserve numeric unknowns and reject names borrowed from another machine or inconsistent header bytes.
Add source-binding malformed controls and authored auxiliary-header carriers to the existing real CLI/MCP verification lane. Document pinned parser semantics separately from payload interpretation and real crash coverage.
Fixes#6538
Parse optional CDP worker relationships once for browser and Electron collectors. Keep absent ownership unavailable, malformed relationships invalid, and proven foreign targets outside the selected scope; retain existing origin and file authorization.
Add public CLI protocol fixtures and documentation for coverage and withheld details.
Fixes#6475
Select active constituent-dimension unknowns for an overall comparison claim while preserving comparison identity and exact scope for individual claims. Use the same selected facts for classification, citations, limitations and recommended probes; remove redundant aliases.
Cover stdio MCP registration, aggregate and independent claims, resolved latest revisions, source provenance and foreign comparison scopes.
Fixes#6879
* docs: add 21 missing src/ dirs to architecture.mermaid (#6901)
* docs: restore KUNA and AUX node declarations lost in merge
* docs: remove final conflict marker
The favicon tile (#20252b) is almost invisible on a dark browser tab
strip, and the social card opened on its own is light only. Add one
prefers-color-scheme: dark block to each SVG. Each edit is a pure
insertion, and the light render is 0 pixels different in magick and in
CairoSVG. CairoSVG ignores the block, so the PNG that link previews
fetch stays light. website/figures.md says so.
🤖 Generated with Claude Code (Sonnet 5.5) 🦊
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
Require a real clock-field context for numeric time normalization and actual rendered write rules for generated strings. Preserve literal read, replay and missing-response values, and retain generated aliases and distinctness within each response.
Keep clock context separate from entity identity while traversing arrays. Add domain and public CLI controls for measurements, business strings, confirmed writes, missing responses and generated-value relationships, with documented inference limits.
Fixes#6878Fixes#6837
Validate message-local field numbers and fully qualified registry identities during existing descriptor admission before constructing the schema registry. Preserve repeated wire occurrences, enum aliases and independent scopes, with bounded name allocation and retained capture provenance through CLI/MCP refusals.
Fixes#6834
Keep staged recording names as relative file operands, including a literal dash. Recognize exact selected input-option refusal captions even when sigrok exits successfully or a caller key contains a newline; retain producer diagnostics and typed request failures across CLI/MCP.
Fixes#6875Fixes#6839
Resolve pointer and scalar facts through their shared loader-aware owners before registration search or type rendering. Preserve unresolved names and attributes, read count fields at their declared width, and admit declared zero-fill registration tails without accepting unmapped bytes.
Cover relocation overlap and adjacency, loader-bound fields, ABI padding, nullable names, and CLI/MCP behavior; document format and verification limits.
Fixes#6881Fixes#6873Fixes#6871
* fix(environment): match served items whose route repeats a separator
callSegments split the tool path template itself and dropped empty literal
segments, while the held collection is split by segmentsOf, which keeps an
internal empty segment. A captured item route such as /api//books/{id} was
stored under collection /api//books but searched with ["api","books"], so
collectionMatch rejected it and a served item read reported the extracted
entity as missing.
Split the call template through segmentsOf, the same owner used for the held
collection path, so a repeated separator is preserved on both sides and the
item answers from its extracted collection. Single-separator routes stay
distinct and param positions are unchanged.
Fixes#6847
* fix(environment): keep repeated-separator collections writable
Preserving empty literal segments in callSegments made createdCollection's
missing-argument guard reject a create whose route repeats a separator, such
as POST /api//books: the empty literal segment tripped the
segments.some(text.length === 0) check and answerCreate refused the valid
route. Restrict the guard to empty supplied parameter segments, so a missing
path argument is still refused while a repeated-separator collection stays
writable as well as readable.
---------
Co-authored-by: gensokyo-dev <[email protected]>
* feat(decompile): write function pseudocode to a directory and return a manifest
Add decompile_all and `rea decompile-all` so a caller can write one
provider pseudocode file per function, or a filtered set, and receive
only a small manifest. The result stays bounded when the program is
larger than a local model's tool-result cap.
Resume continues an export for the same target digest, provider,
analysis profile, and layout. Matching files are skipped, conflicting
files stay unchanged, and one function's failure does not stop the
rest. Cancellation leaves files already written. Requesting dwarf
layout reports that compilation-unit paths are unavailable.
Simulated-provider tests cover the manifest, resume, filters, limits,
cancellation, and the failure cap. MCP registration, CLI coverage,
schema validity, the product catalog, check:fast, and docs:check
passed. Real Ghidra was not exercised.
Refs #6090
* fix(decompile): keep unknown export identity unresumable and recover torn journals
Resume treated two missing target or profile digests as a match, so an
export of one binary could continue into another. Resume now requires both
digests, and a decompiler observation without the export's profile, or with
a different target, is recorded as profile_changed.
A crash during a journal append left a torn final line that made the export
unresumable. Text after the last newline is now treated as uncommitted and
truncated before the next append, and stale temporary files are removed.
An inventory row with an empty address aborted the whole export because its
failure record failed the journal schema. Such rows are now excluded and
counted in the limitations.
A limited resume retried the same recorded failures first and never reached
new functions. Functions not yet attempted now run before retries. File path
reservations come from every journal line, so an output_io record no longer
releases a path. The index is rebuilt from the journal in numeric address
order, and journal close and cleanup failures return a Result.
The cancellation test now cancels after a file is committed and checks that
file survives and is skipped on resume. Redundant snapshot-replay checks are
removed, the CLI limit uses the contract constant, and --snapshot no longer
claims decompile-all updates it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): refuse resume of a missing export and repair journals by byte offset
A second review round found that resume against a directory that does not
exist silently started a full new export and reported it as resumed. Resume
now requires an existing export directory.
The torn-line repair measured the committed journal from decoded text, so
damaged UTF-8 could move the truncation point past the end of the file. The
journal is now read as bytes and cut at the last newline byte, and an intact
journal is not truncated, so a concurrent append is kept.
A per-function observation for a different target is now recorded as
target_changed instead of profile_changed. A failure to remove a partly
created output directory is reported instead of hidden. The journal handle is
closed on every path again, including an unexpected throw. The path allocator
no longer gives up after 1,000 collisions and reuses a taken name.
Tests now use createTestTempDirectory, assert journal lines against the
journal schema, and cover resume of a missing directory, resume with an
unknown analysis profile, and a target-mismatched observation.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): keep a function's first file name across failed retries
Reserving every journal path stopped other addresses from taking a path, but
an address looked up only its latest record. After its file went missing and
a retry failed without a path, the next resume moved the function to a
hash-suffixed name and orphaned the original. Each address now keeps the
first path the journal gave it.
A matched commit still ran the decompiler but did not count toward limit.
The limit now counts every function taken on after skipping verified files.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): never follow a journal symlink and check procedure_info identity
Torn-line repair truncates the journal, and the journal was opened through
any symlink in the export directory, so repair could truncate a file outside
it. The journal must now be a regular file and is opened without following
symlinks where the platform supports it.
Body ranges from procedure_info were written without checking that the
observation belonged to this export or described the requested function. An
observation with a different provider, profile or target, or another entry
point, now leaves the body unavailable with that reason.
File, journal and index writes now use FileHandle.writeFile, which writes the
whole buffer instead of trusting one write call. The stale temporary sweep is
removed: a matching file name does not prove this export created the file.
The inverted-range test now uses one address space so it reaches the
inversion check.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): bound returned caveats and keep verified checksums
Ghidra names each terminal call's address in its per-function caveats,
so decompile_all copied one new caveat per function into the returned
Evidence and the answer grew with the program. The returned Evidence
now keeps the eight most often observed distinct per-function caveats,
grouped by provider and text as they are rendered, plus a count of the
rest. Inventory caveats are unchanged, and other workflows are not
bounded. Each function keeps the caveats of the observations it used:
a written file in its header, now including procedure_info caveats,
and a failed attempt in its journal and index record. A procedure_info
observation for another target or profile is foreign and contributes
none.
A failure record for a function that was already written replaced the
record holding its checksum, so after a transient read error a resume
decompiled that function again. The journal now keeps the last
successful write separately from the latest attempt. Resume verifies
against that write and records it again once the file verifies.
A caller abort that arrives while the export finishes now returns
cancellation with the caller's reason instead of a success manifest,
as #6143 does for other late finalization. A publish, index or close
failure stays the primary error.
Also make the missing-journal resume error say what to do, and add
boundary tests: one runs decompile-all through the real CLI against a
fake Kuna to check flag mapping, the relative output directory,
filters and limit; one runs decompile_all through production MCP
registration to check that the caveat bound is applied.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): keep each function's complete caveats in the index
The returned Evidence keeps eight distinct per-function caveats and
counts the rest, pointing readers at the export. A written function's
file header truncates its caveats after 4,000 characters, and its
journal record kept none, so a large function with many terminal calls
could lose caveats from both the answer and the export.
Every journal record, written or failed, now keeps the complete caveats
of the observations its attempt used, and decompile-index.json carries
them. The header stays a readable summary and, when truncated, says
that the index keeps the complete list.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): report external functions instead of failing them
Ghidra classifies imports as external functions with an empty body and
returns null pseudocode for them, as its limitations state. decompile_all
recorded each one as an invalid_pseudocode failure ("not text"), so a
dynamically linked program reported every import as a decompiler failure:
34 of 116 functions in /usr/bin/xxd.
procedure_info owns the external classification. When it classifies a
function as external, the export now records status "external", counts it
in counts.external, writes no file and requests no pseudocode. The record
keeps the body fact as observed. The journal header pins the target,
provider and profile, so a resume skips a recorded external function
without asking the provider again; a limit below the external count still
leaves nothing remaining. A null pseudocode result for a function whose
classification is not external is reported as no_pseudocode.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): report finalization failures after a cancelled export
When the caller's abort stopped the publish loop, decompile_all returned
that cancellation before checking the index write and the journal close,
which had already run. A failure to finalize the export was hidden, so
the caller could not tell the saved index or journal was incomplete.
Publish failures stay primary, then index and close failures. A
cancellation counts as the caller's only when the caller's signal is
aborted, and is then reported after a successful finalization with the
caller's own reason. A provider's own cancellation, without a caller
abort, stays a publish failure like any other. Tests cover an index
failure and a close failure after the caller stops the loop, a stopped
loop with a successful finalization keeping the caller's reason, and a
provider cancellation staying primary over an index failure.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): remove a created output directory that cannot be secured
createPrivateDirectory ran mkdir and chmod as one step. When mkdir
succeeded and chmod failed, it returned an error before #create reached
its cleanup, leaving an empty directory behind. A fresh export then
refused the existing directory, and a resume refused it for having no
journal, so the caller had to remove it by hand.
mkdir and chmod are now separate. A mkdir failure created nothing, so
nothing is removed. A chmod failure after this call created the
directory removes it with a non-recursive rmdir: it is still empty, so a
path another process filled or replaced meanwhile is refused rather than
deleted, and that refusal is reported.
A filesystem boundary test fails chmod for the new root and checks the
directory is gone and a retry succeeds. A module test confirms that a
function written earlier and now classified as external still reports a
changed file at its path as output_exists.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* refactor(process): share the socket lease with owners other than Hopper
The socket lease that keeps two REA processes from opening the same Hopper
document lived only in HopperLease, with Hopper error messages built in.
A decompile export needs the same guarantee for its output directory.
OwnedLease now holds the lease mechanism unchanged: a listening local
socket that the operating system ends with its process, owner identity
answered by the live holder, and recovery of a stale socket serialized
through a recovery directory. Callers map a tagged LeaseFailure to their
own error. HopperLease keeps its exports and maps each failure to the
same HopperStartError message as before. On Windows the lease is a named
pipe, which needs no stale recovery.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): hold the output directory per run and stop on repeated write failures
Two runs could resume the same output directory at once. Each read the
journal once, and the index each wrote reflected only its own view, so
the last writer could drop the other run's records. A run's torn-line
repair could also truncate the other run's append.
DecompileExport now holds a lease on the output directory, named by its
device and inode, from before the journal is read (or, for a new export,
from just after the directory is created and before its journal exists)
until the journal is closed. A second run is refused as a retryable
capacity constraint that reports the holder's process ID. The lease ends
with its process, so a crashed run leaves no lock to clear. The lease is
released on every open failure, and a failed release is reported.
An export also kept decompiling every remaining function when its files
had stopped being writable mid-run, for example on a full disk, failing
each one with output_io. After five consecutive functions whose files
could not be written or read, the export now stops with an output error
that carries the counts and the last failures. A verified file or any
other outcome ends a run of failures. Committed files and records stay,
the index is still written, and a later resume continues.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* docs(native): record directory export verification
Record matched real Ghidra outputs, bounded caveat and cleanup regressions,
actual catalog-inclusive context estimates, runtime measurements and coverage
limits for the pinned integration.
* fix(native): bound export summaries and reserve portable paths
Use one case-folded reservation owner for allocation and resumed journals.
Budget inline failures and provider caveats by encoded JSON bytes while
retaining complete records in the output index. Align the tool contract
with the collector order and verify SDK result-window behavior.
* docs(native): refresh final export measurements
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: gensokyo-dev <[email protected]>
Describe the diagram as selected layer owners and dependency paths. Link the canonical composition factories and direct Frida/Cutter entry wiring, and add the omitted Kuna deep-provider node and its verified dependencies.
Documentation checks cover source links and generated facts; no exhaustive directory inventory or new provider capability is claimed.
Fixes#6901
Count each verified required obligation once across retained closure observations and validate their finite status/count rules against the supplied final ledger. Compare every retained semantic outcome variant across CLI/MCP instead of selecting the first pair, preserving all observations and Evidence.
Validation: evaluator regressions reject duplicate closure, contradictory intermediate status, and later outcome drift while retaining valid controls. The readiness verifier passes with the source-owned C fixture and actual CLI/stdio-MCP static JavaScript/Electron workflows. Variant sets do not establish equal repeat counts or run pairing; final-ledger consistency does not authenticate historical ledgers or proof freshness.
Fixes#6893Fixes#6894
Retain module-name displays observed before optional metadata failure so strict objdump framing can use those facts. Preserve uncertainty across name sections and report unknown completeness when unattributed producer warnings concern skipped custom metadata; keep exact warnings, core validation, WAT and artifact provenance.
Validation: focused source/process regressions and 61 real WABT1.0.42 CLI/MCP verifier cases pass. The unmodified official macOS arm64 archive matches its published SHA-256. Coverage includes outer/inner malformed name metadata, valid empty-map controls, stable core/interface facts and cleanup. No inspected WASM target was executed.
Fixes#6885
Resolve Go pointer descriptors and strings across complete, consistent file-backed spans, including PE headers and adjacent ELF load ranges. Reuse the canonical image-mapping selection for native exports. Preserve existing gaps, alias, zero-fill and capacity refusals.
Forward parsed zero-fill ownership through IL2CPP relocation tables, destinations and mapped-span checks. Distinguish missing spans from ambiguous ownership in the shared mapping failure: unresolved relocation targets may remain unknown, while ambiguous raw registration bytes cannot be reused as a resolved count.
Validation: parser, provider, service, native-export, IL2CPP and public CLI/MCP regressions cover PE32/PE32+ headers, split ELF descriptors/contents, relocation count conflicts, ordinary unresolved targets and unchanged inputs. Authored carriers establish static parsing, not Windows loading or actual legacy Go linker emission.
Fixes#6831Fixes#6830
Move the unchanged resolution contract into its domain owner and use it when
building navigation context. Preserve provider failures instead of guessing
absence from error text or malformed result shapes. Return null only for an
explicit valid negative resolution.
Remove the obsolete error-message matcher and partial name parser. Cover four
malformed result shapes, original error identity, valid positive/negative facts
and the typed MCP unreadable-output response. Original source failed six cases.
Validation: navigation source/MCP and advertised schema checks passed. Compact
and full generated catalogs are byte-identical to the parent. Static, docs,
discovery and duplication checks passed.
Reuse sameRegularFileState for artifact, native plist and entropy readback.
Remove private copies of identity/size/timestamp checks and consistently include
mode in the existing stable-state contract.
Keep initial identity-only artifact admission, byte-count checks, capacity and
error precedence, symlink choices, cancellation and descriptor cleanup intact.
Validation: stable-file, plist, artifact outcome, entropy and public CLI/MCP
lifecycle regressions passed; static and documentation checks passed.
Use the existing bounded thin-header decoder for loaded and embedded FAT
identities, thin-image resolution, and both prepared-copy readback paths.
Preserve raw unsigned CPU/subtype facts and endian handling.
Keep the initial eight-byte dispatch, FAT framing, selection and ranking,
source digests, error ordering, cancellation and cleanup authority local.
Validation: Mach-O container, Hopper image/copy lifecycle and file-offset close
boundary suites passed. No attached Hopper GUI or real-provider run performed.
Decode metadata coded indexes once into null, valid or invalid facts. Migrate
all existing consumers and remove parallel token and failure-reason decoders.
Keep required-null policy with each column, preserving tokens, reason text,
offsets, issue ordering and readable partial metadata.
Retain known table/row coordinates even when invalid; TypeRef regressions
preserve row-zero and out-of-range enclosing facts without granting validity.
Attribute naming consumes the same validated constructor coordinate.
Validation: metadata/member/native-boundary/signature source suites and public
CLI/MCP recovery workflows passed; static, docs and duplication checks passed.
Give accepted target IDs one owner for processor identity and canonical case,
while preserving exact target spelling for selection and Evidence. Use that
fact for payload/bundle comparison instead of splitting on a colon.
Keep feature differences unknown unless exact target keys agree. Cover legacy
plus-feature declarations in both directions and mixed processor case with
individually named physical-byte regressions. The original code failed twelve
of the twenty-one comparison cases; the updated matrix passes all cases.
Validation: GPU source, physical boundary, compiled CLI and lifecycle suites
passed. Static, docs, schema and duplication checks passed. No GPU execution.
Closes#6792.
ELF images with `PT_DYNAMIC` but no `SHT_DYNSYM` section incorrectly reported a complete, empty export inventory. The shared ELF directory reader now owns the dynamic-segment observation; CLI/MCP report `unsupported` with a reason. Existing symbol-table results remain intact. Read-only format correction; no new execution authority or public schema.
Validation on the current main integration:
- `npm run check`, test discovery, and 166 selected Linux tests pass, including actual CLI/stdio MCP cases and PE/IL2CPP/GPU/Rust reader consumers. Original author validation: 113 tests on macOS, including regressions that failed before the fix; test discovery passed.
- Real Debian libc (1,926,232 bytes) and libLLVM 14 (109,967,296 bytes), with only section-header-count/name-index bytes changed, reproduce the old false absence in both public adapters. The reviewed implementation returns unsupported in both adapters. Independent Python maps unchanged `PT_DYNAMIC` declarations and selected symbol bytes; original `readelf` agrees. The reduced files are not loaded or executed; `readelf -D` itself cannot enumerate these reduced layouts, and that failed oracle attempt is retained.
- Unmodified libc still returns all 3,025 exports, byte-identical complete Evidence and the same Evidence ID as the baseline. Resource-guarded public probes completed without stops or payload leftovers. No speed, memory or model-token improvement is claimed for this coverage fix.
Codex review completed with no findings. CI failed: all 61 observed failures (including 47 omitted from the aggregate report by canceled shards) reproduce with identical complete failure diagnostics on the exact CI base and merge trees. Baseline-only bypass is explicitly authorized for this maintenance session; canceled/skipped coverage remains unverified. See the final CI attribution comment. The original author's readiness declaration below is preserved.
## Author readiness
Human owner: @leeguooooo
- [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
- [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
- [x] I declare this PR ready for initial maintainer review.
Reuse the shared offset-instant owner for calendar validation and exact probe ordering. Preserve first-century years, arbitrary recorded fraction digits in the supported offset profile, ordinal ties and legacy native-Date fallback. Keep original clock spelling when conversion leaves the supported four-digit year range, and refuse unrepresentable generated clocks before committing state.
Validation: focused clock/comparison and public CLI regressions cover leap years, offset equivalence, precise DELETE/GET order, spelling classification and refusal atomicity. Replay/state compatibility checks pass. Numeric state intervals and generated-clock progression retain their documented millisecond limits.
Fixes#6835Fixes#6643
Retain each resource directory's type/name path and incoming entry ranges before metadata accounting. Empty branches keep their identity, and shared directory bytes retain each distinct incoming path. Validate the expanded facts in the shared service and advertise them through the canonical contract.
Validation: parser, service, filesystem and public CLI/MCP regressions cover numeric/named empty branches, shared directories and unchanged artifact/payload hashes. Controls use authored PE32/PE32+ files; Windows loader behavior remains unverified.
Fixes#6872
Correct the pinned HAR schema's missing object types and duration constraints at the shared decoder boundary. Preserve optional omission and the -1 sentinel without repairing producer measurements, and identify the owned corrections in decoder provenance.
Keep unsupported or redacted response encodings unavailable to replay and state extraction. Empty-response classification now uses the same body owner, preserving known empty content separately from unavailable content. Regenerate contract examples from decoded fixture bytes and the shared view service.
Validation: focused decoder, replay/state, CLI and MCP regressions, including unselected malformed records and confirmed write responses. Contract examples reproduce through MCP. Authored capture controls do not establish real-browser producer coverage.
Fixes#6890Fixes#6889
Set the repository jscpd ceiling to the requested 4%. Preserve the scan
inventory, token/line minima, ignore rules and report failure propagation.
Validation: npm run jscpd passed at 3.59% duplication; scoped format check passed.
Use a valid canonical embedded map in the decoder row-budget regression.
The old empty map fails version admission before it can reach the row limit.
Retain that malformed-map case separately and assert typed constraint metadata
for format, external-section and capacity failures from the real codec process.
Validation: source-map source suites and all sixteen physical decoder boundary
tests passed. Static, documentation and test-discovery checks passed.
Give raw and header-selected imports one owner for their twelve identical
semantic revision declarations. Preserve property order, parameter values,
omissions and all provider/language/processor override precedence.
Validation: Ghidra behavior and MIPS/RISC-V/PowerPC profile suites passed.
Seventy direct before/after cases retained identical Results, serialization,
parameter order and digests. No real Ghidra process verification was performed.
Pass hierarchy or connection identity from the producing call rather than
searching graph IDs containing caller-selected paths and authored IDs. Keep
connection omissions from making a retained hierarchy appear partial.
Replace mirrored ID-substring test oracles with exact endpoint relationships.
Cover marker-bearing paths and authored identities through domain, CLI/MCP,
summary and byte-retention boundaries.
Validation: affected source and compiled/public tests passed, including native
Foundation/ibtool fixture lanes; one Linux-only invalid-byte filename case
skipped on macOS. Static, docs and discovery checks passed.
Share incremental replacement UTF-8 decoding across web and JavaScript workers, bound content before complete-line allocation and handle split CRLF consistently. Keep named schemas, request versus checkpoint failures, worker reuse and stream cleanup authority in their servers. Cover real server recovery and deterministic byte boundaries.
Preserve load and resolve operations through semantic facts, worker transfer and graph Evidence. Only loads propagate executable ownership. Project ambient member writes and escapes through the shared path- and site-aware mutation owner; retain source literals, bases and uncertainty. Cover ownership and mutation boundaries through CLI and MCP.
Artifact comparison owns the inventory Evidence identities whose integrity mismatched. Residual unknowns consume those identities and static/runtime correlation keeps contradictory or unresolved findings separate from observed changes.
Adds a real-ASAR MCP comparison and correlation regression with ordinary-content controls. Validation is pending the centrally coordinated lane; single-file formatting and lint completed.
Have the function observation owner select aggregate dimensions before residual-unknown lookup. Retain independent dimension scope, unknown citations and recommended probes through the public MCP verifier.
Validation is pending the centrally coordinated lane; single-file formatting and lint completed.
Compare all CLI/MCP repeats within their operation, call kind and expected-success group. Reconcile closure decreases with unique required obligations in the supplied ledger, retaining malformed observations in findings and snapshots.
Validation is pending the centrally coordinated lane; single-file formatting and lint completed.
Include required-claim surfaces and reachable dependencies in ownership, verifier commitments, contradiction, package proof and summary checks. Preserve all applicable package outcomes instead of accepting any passing proof.
Adds authenticated synthetic scope cases and a shared public CLI/MCP regression workflow. Validation is pending the centrally coordinated lane; single-file formatting and lint completed.
Use completed codec input to establish legacy CCOB extents, preserving declaration/integrity failures independently. Reuse bounded input windows, charge actual reads and decoding attempts, and qualify recovery after incomplete decoding. Publish only established or qualified terminal extents so interruption retains completed declarations. Recognize bitcode representation in HIP bundles while leaving inner facts unsupported.
Fixes#6887Fixes#6880
Select legacy Atom when AtU8 is empty and skip zero-byte optional FunT. Preserve explicitly empty counted arrays, malformed nonempty failures, last-occurrence selection and original chunk provenance. Share structural fixtures across producer and public workflow regressions.
Fixes#6816Fixes#6874
Refuse compressed note sections with typed unsupported-target semantics before framing or decoding, preserving stored-range checks and physical descriptor-offset provenance. Flutter retains independent build IDs with partial coverage when compressed notes are skipped. Verify the existing shared alignment fix with prefixed notes across classes and table kinds.
Fixes#6869Closes#6563
Charge the whole-catalog admission guard by escaped decoded names, preserving raw-byte lookup identity and final worker reply limits. Keep UTF-16 inventory and detailed-schema results whose returned facts fit the documented allowance.
Fixes#6888
* feat(cli): add JSON Lines output for row-oriented results (#5487)
- Support opt-in JSON Lines format (--format jsonl) for row-oriented results and collection views with clear record boundaries
- Preserve stable source identities and stream records deterministically line-by-line
- Emit final coverage and limitation metadata as a distinct line with https://rea.dev/schemas/jsonl-coverage-v1.json to prevent confusion with data rows
- Distinguish error outputs with https://rea.dev/schemas/jsonl-error-v1.json
- Reject non-row-oriented results that lack record boundaries with an unreadable_output error
- Document JSON Lines streaming conventions in docs/cli.md
- Add boundary tests covering empty results, multiline strings, partial coverage, large fields, and non-row rejection
* fix(cli): preserve diagnostics, provenance, and nested collections in JSONL
* fix(cli): frame classified failures and reject unrepresented JSONL facets
---------
Co-authored-by: gensokyo-dev <[email protected]>
Share endpoint identity and repeated-name ambiguity across call and reference dimensions. Compare same-artifact procedure entries by canonical coordinates while retaining raw reference sites and source Evidence. Keep observed comparison status separate from reconstruction proof.
Fixes#6853
Separate common row constraints from established storage sizes. Preserve Q8_1 and K-layout uncertainty, plus numeric IDs and ambiguous textual identities for historically shifted IDs16–25. Keep zero-byte facts and identity limitations independently, and propagate producer facts through totals, cancellation and retained views. Pin released source evidence and document the compatibility cost.
Fixes#6848
Use original object-table UIDs for inventory, hierarchy and connector references. Retain authored identity fields as data, refuse forged reference aliases and select UIKit top-level collections without substituting unrelated roots.
BREAKING CHANGE: Keyed archives that previously used authored objectID or object-id graph identities now use decimal table UIDs. Authored values remain attributes; ibtool and native NIBArchive identities retain their existing source semantics.
Fixes#6849Fixes#6850
Retain producer traversal uncertainty through inventory, extraction, Interface Builder decoding and executable-root discovery. Keep known copied files and decoded facts with honest coverage; share omission normalization and bound omitted archive paths with their source reasons.
Fixes#6852Fixes#6825Fixes#6582
Reuse the shared one-shot finalizer for discovery and instrumentation, preserve finalization cancellation with completed observations, and bind Frida cleanup errors to exact owners so confirmed retry recovers the primary error.
BREAKING CHANGE: instrument-with-frida JSON now returns the canonical Evidence record directly. Read normalized_result.cleanup_error instead of the earlier top-level cleanup_error wrapper field.
Parse a named proof contract once and qualify exact obligation, owner, revision, fixture/case, and verifier/claim tuples. Preserve unavailable proof separately from applicable failed outcomes.
BREAKING CHANGE: ID-array reconstruction proof records no longer qualify for verified or ready ledgers. Producers must supply implementation and revision bindings with individual claim outcomes; ledger diagnostics now distinguish inapplicable, unavailable, and failed proof.
Replace ambiguous display-label sorting with exact relation assertions keyed by metadata tokens. Distinguish same-name methods and verify directed ownership, edge counts, properties and Evidence without depending on graph order.
Decode named comparison payloads and validate nested citations at one domain boundary. Preserve workflow-specific authentication, source closure policy and validation order; cover malformed payloads and citation boundaries.
Use one bound JSON selection set for inventory metadata, keeping raw-name byte
comparison and filtering inside SQLite while preserving caller projection order
and repetition. Large requests reach native result-column capacity attribution.
Separate unavailable row sources from generated-expression failures. Preserve
SQLite's reason and selected table/path, offer schema-only recovery, and avoid
claiming corruption or recommending unreadable columns.
Validated UTF-8/UTF-16 identity, native inspection/worker tests and CLI/MCP failure
and recovery workflows. The large CLI selection uses the existing framed CLI
fixture to avoid host argv limits. Source bytes and identity remain unchanged.
Fixes#6855Fixes#6604
Share AMDGPU triple grammar between bundle and note owners so modern target
spellings participate in processor/feature conflict detection. Propagate CUBIN
register conflicts into object, target and report coverage.
Normalize adjacent PTX dot keywords in the lexer, removing the downstream pointer
splitter. Parse post-type alignment while distinguishing parameter and pointee
layout, preserving names and byte provenance when layout remains unknown.
Validated production-boundary matrices and public CLI/MCP coverage workflows with
inert fixtures. Correct the HIP-v3 control's ELF processor declaration. Real GPU,
assembler and compiler-produced modern-note behavior remains unverified.
Fixes#6844Fixes#6823Fixes#6858Fixes#6868Fixes#6861
Read Apktool 3's producer string dialect before YAML can discard hashes or
reinterpret values. Preserve older YAML behavior and decode producer escapes once.
Select the exact root AndroidManifest.xml resource in REA's JADX bridge and
derive summaries once with namespace-aware XML parsing. Preserve decoded text,
summarize before its display cap, invalidate cached facts with the loaded session,
and remove superseded upstream manifest handlers. Keep the engine pinned to 0.7.1.
Validated Apktool parser/provider and public adapter controls; compiled the bridge
against the verified pinned JAR and ran its real Java regressions plus public CLI
and stdio MCP manifest parity checks. Real Apktool execution remains unverified;
the new manifest fixtures use plain XML. No Android application was executed.
Fixes#6804Fixes#6866Fixes#6863Fixes#6819
Use one marshal surrogatepass decoder for PYZ directories and Python bytecode.
Validate ordinary UTF-8 spans with the native fatal decoder, preserving BOMs,
lone surrogates, raw bytes and marshal reference slots.
Distinguish legacy full-pyc CArchive modules from modern marshal-only modules
before reconstructing headers. Share typed source/codec failures between stream
output and completion while retaining native-read drain and cleanup ownership.
Validated focused producer, reader, lifecycle, CLI and MCP regressions, plus
public inventory/extraction of CPython 3.14-generated marshal tables and code.
No packaged application was executed. Document original versus derived bytes.
Fixes#6800Fixes#6789
Keep validated PE padding in the selected Evidence range while consumed zlib bytes own compressed and inflate-ratio limits. Preserve typed resource failures and bounded allocation. Validated accepted padding, over-ratio and compressed-size controls through source, real CLI and stdio MCP workflows.
Use Float.valueOf grammar at shared admission and retain selected spelling through am --ef. Validated scientific notation, malformed controls and exact MCP forwarding with a source-owned ADB fixture; no device execution.
Fixes#6796
Separate AMDGPU processors from feature-qualified note identities. Read Apple hidden ARM64 table rows once and preserve visibility through artifact, dylib and fuse consumers. Keep Objective-C++ template commas within type attributes and incomplete metadata unknown.
Validated provider/parser and production property regressions, Electron CLI/MCP consumers, and native Apple lipo -hideARM64 output through the production slice reader and public artifact inspection. LLVM execution remains unverified.
Fixes#6806Fixes#6799Fixes#6801
Match table metadata by stored name bytes and fold only ASCII code units for relationships, reusing parsed facts without per-trigger queries. Preserve caller paths on structured worker limits and V8 heap failures.
Validated invalid UTF-8 collisions, distinct UTF-16 names and real worker transport refusal through CLI and stdio MCP. Controlled stderr covers OOM classification; actual memory exhaustion was not induced.
Fixes#6795Fixes#6607
Share embedded-map version admission and derive indexed overlap from represented mappings. Carry createRequire filename bases through worker facts and graph identity. Select factory export bindings at each bundler owner.
Validated accepted and malformed source maps through real CLI and stdio MCP codec workflows; verified loader and esbuild graph output against Node runtime controls. Rebased consumer checks passed.
Fixes#6803Fixes#6614Fixes#6798Fixes#6797
Reuse preflight-parsed container references for bounded decoder-copy normalization. Preserve original artifact bytes, scalar provenance and reference order. Verify three-byte offset and reference encodings through CLI and stdio MCP.
Fixes#6805
Retain warnings from validator, objdump and decoder through one diagnostic owner. Keep uninterpretable name bytes and explicit name-metadata coverage in complete results and summaries.
Fixes#6812
Reject duplicate decoded JSON names before object conversion. Use one checksummed zlib stream parse and retained PE FileAlignment to distinguish exact zero padding from trailing payload bytes. Exercise public CLI and stdio MCP.
Fixes#6814Fixes#6793
Share selected-file errno ownership with model inspection and codec result accounting with Rust. Verify actual descriptor exhaustion and unchanged-input recovery in an isolated child.
Fixes#6666
Resolve attribute display names from validated nesting and parsed member facts, admit composed names before allocation, and preserve unknown malformed chains. Keep ReadyToRun classification ahead of metadata hints while retaining each observed hint.
Fixes#6815Fixes#6810
Use one retained-path owner for module references and items. Preserve selected paths and genuine ambiguity across module kinds; remove the superseded singular helper.
Fixes#6790
Reuse the reader correction from PR #6705, and share the byte projection budget with output validation. Verify actual APK parsing through compiled CLI and stdio MCP at 0, 1, 2, 3, 64 and 65 descriptor bytes.
Co-authored-by: Ezra <[email protected]>
Fixes#6697
Read link targets as bytes before strict UTF-8 admission. Retain malformed targets as unreadable with source hex; preserve literal replacement characters and valid BOM-prefixed targets.
Fixes#6765
Validate supervised text once before version or capture interpretation. Exercise POSIX client probes through compiled CLI and stdio MCP; capture-summary native bounds remain host-specific.
Fixes#6775
* feat(cli): report version and runtime with an explicit output format
`rea --version --json` and `--version --format <format>` ignored the format
and printed only the bare version, so support reports gathered the runtime
and platform by hand.
A root --version request that selects a format now renders a documented
report: package name and version, JavaScript runtime and version, platform,
architecture, and whether the runtime satisfies the supported range. It
contains no paths, environment values, user or host names, and starts no
provider. Plain --version is unchanged, --help keeps precedence, and other
output controls keep Incur's plain version.
The runtime verdict uses a new shared supportsJavaScriptRuntime rule that
rea doctor now uses too, so both judge Bun by its Node.js compatibility
version. mcp doctor's private JSON/format renderer moves to cliOutput as
renderCliDocument and is shared with the version report.
Closes#5483
* refactor(errors): centralize input failure construction
Carry caller messages through the existing schema issue owner instead of constructing and discarding an intermediate input error. Remove forwarding schema helpers and migrate equivalent constructors across investigation, firmware, dylib, process, and screenshot workflows while preserving diagnostic paths and causes.
* docs(readme): add Roman Urdu edition (#6499)
* docs(readme): add Roman Urdu edition
Register ur-Latn with a pending website catalog and preserve English command examples.
Script-tag handling follows morluto's shared helper proposed in PR #2043 (c46f606c89).
* test(website): cover completed script-tag page metadata
* fix(process): parse native teardown relation sentinels
* fix(cli): make version report privacy checks environment-independent
The CLI test rejected any report containing the OS account name, so an
account named node, linux or rea failed a correct report. Check unique
caller-controlled HOME, cwd and environment markers instead; the strict
schema still rejects any additional field.
The CLI guide said --version with other output controls prints the plain
version, but invalid combinations such as --json with --token-limit report
their existing output-flag error first. Describe both outcomes and test them.
* refactor(nativeaot): share report facts across budget stages
Centralize parse-wide identity and coverage facts while keeping conservative admission values separate from measured rows and counters. Reuse the derived truncation reason and retain the final serialization bound.
Tighten the report-budget regression so unexpected parser finalization errors cannot be swallowed by its budget search.
* fix(adb): preserve empty properties and verbatim version names
* fix(artifacts): recognize empty Zip64 containers
Fixes#6540
* fix(erlang): accept uninterpreted BEAM alignment bytes
Fixes#6517
* fix(gpu): accept PTX entries without parameter lists
Fixes#6493
* fix(python): preserve signed code-object line numbers
Fixes#6490
* refactor(ghidra): centralize load image check recording
Share expected and observed check construction across MZ, COM, and raw-binary attestations. Preserve format-specific rules and source coordinates, and derive mapping callback types from the recording owner.
* fix(inspector): preserve script identity and parse-failure facts
Fixes#6535Fixes#6546
* fix(artifacts): recover malformed PYZ sizes without losing siblings
Fixes#6120
* fix(erlang): accept extended BEAM atom lengths
Fixes#6503
* refactor(erlang): reject overflowing BEAM atom lengths
* fix(gpu): preserve PTX and AMD target facts
Fixes#6469Fixes#6483
* refactor(targets): preserve ambiguous MZ header evidence
* fix(adb): retain refused activity launch reports
Parse complete nonzero Activity Manager reports while preserving other command failures and their captured output. Admit dollar signs only in the activity component name for nested Android classes.
Fixes#6528Fixes#6527
* fix(mcp): retain partial evidence through shared delivery
* fix(python): honor version-specific code equality
Fixes#6547
* fix(pyinstaller): preserve namespace declarations
Project PYZ namespace packages as metadata so their query paths do not claim output directories. This lets independent CArchive files retain the same logical path and remain inspectable and extractable.
Fixes#6539
* docs: clarify evidence ownership and verification guidance
* docs(adb): clarify emulator observation field
* docs(artifacts): clarify active-reader extraction scope
* fix(erlang): select the last repeated BEAM chunk
Fixes#6518
* fix(il2cpp): distinguish rank-one array types
Fixes#6534
* fix(python): align pyc and PYZ marshal decoding
Fixes#6560Fixes#6559
* fix(browser): preserve frame identity across captures (#4040)
* fix(browser): preserve capture evidence fidelity
* fix(browser): align frame identity comparisons
* fix(browser): retain historical frame evidence
* fix(electron): retain same-document script owners
* fix(electron): bind frame proof to tree reads
* fix(browser): retain malformed frame scope
* fix(browser): retain WebMCP event scope
* fix(browser): retain malformed timeline identity
* fix(browser): unify frame identity and scope
* fix(electron): prove enclosing frame ancestry
* fix(electron): separate ancestry from file policy
* fix(browser): preserve transient fragment semantics
* fix(browser): retry uncertain initial frame scope
* fix(browser): preserve runtime frame identity
* refactor(browser): separate independent capture fixes
* fix(electron): detect tree-first document replacement
* fix(electron): retain same-document tree authority
---------
Co-authored-by: eco-null <[email protected]>
Co-authored-by: morluto <[email protected]>
* fix(elf): resolve symbol versions from requirements
Fixes#6533
* fix(elf): follow loader version index precedence
VERDEF entries replace VERNEED names for shared indices, matching glibc lookup behavior.
* test(firmware): bind owned producers and exercise real limits
* fix(adb): preserve push target semantics
Fixes#6566Fixes#6567
* fix(cli): merge sibling output filter slices
Fixes#6542
* fix(browser): preserve Link context semantics
Fixes#6504Fixes#6505Fixes#6506
* fix(python): classify historical headers and signed flags
Fixes#6568, #6487
* fix(python): normalize legacy code flags for equality
Preserve CPython 3.7–3.10 constructor flag semantics in code keys.
* fix(environment): compare captured bodies by representation
Keep JSON, text, and retained bytes distinct through fidelity comparison. Compare binary bodies by bytes, including valid UTF-8 bytes against equivalent text, and keep empty-body compatibility explicit.
Fixes#6564
* docs: clarify derived values and comparison controls
* fix(environment): scope fidelity ID normalization
Reserve equal global ID pairs and stop normalizing contested pairings. Keep numeric measurements literal, scope keyed collection identities through learning and comparison, and normalize string references only where learning established the same field as an ID.
Fixes#6565Fixes#6550Fixes#6557
* test(process): print the progress frames when the sparse-child bound fails (#6427)
The sparse-child capture test asserted the frame bound with a bare boolean,
so a failure only printed "expected false to be true". The assertion now
carries the running progress details (elapsed time, frames, samples,
interactions) as its failure message. This only adds diagnostics to a
failure; it does not change what passes and does not fix the flake.
Refs #5889.
🤖 Generated with Claude Code (Sonnet 5.5) 🦊
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
* fix(il2cpp): name the metadata file when linking finds malformed metadata (#6425)
* fix(flutter): honor ELF note alignment when reading build IDs (#6423)
* fix(flutter): honor ELF note alignment when reading build IDs
* test(flutter): key shared note ranges by effective alignment
Cover a program and section declaration that share one note range: differing effective alignments (8 and 4) must both be read, while declarations that both normalize to four bytes (1 and 4) still share one read. 24-byte build IDs pad identically at both alignments, so only the range key decides the read count.
* refactor(firmware): centralize audited tool requirements
* fix(javascript): associate requested bindings only with resolved native addons (#6402)
* fix(javascript): associate requested bindings only with resolved native addons
* test(javascript): cover the exact native addon association
---------
Co-authored-by: morluto <[email protected]>
* fix(python): reject code keys and set members with unhashable consts (#6424)
* fix(python): reject code keys and set members with unhashable consts
* fix(python): refuse to hash a tuple that is still being read
* fix(python): hash a code object's co_consts tuple, not its item list
---------
Co-authored-by: morluto <[email protected]>
* fix(model): recognize named chat templates in summaries
Count retained template content rather than only the default key; keep names-only inventories distinct.
Fixes#6569
* fix(model): retain resolved GGUF alignment under cancellation
Publish alignment from the parser when explicit metadata validates it, or when metadata completion establishes the default. Preserve that fact through later parsing and hashing failures.
Fixes#6579
* fix(environment): reject out-of-range clock offsets
Reject invalid ISO offsets while preserving valid boundary values. Validate stored clock-format offsets through the same parser so malformed imported formats cannot reach rendering.
Fixes#6524
* fix(environment): preserve submillisecond insert ordering
Compare retained submillisecond components after milliseconds, so ordered collections recognize and place distinct timestamps correctly.
Fixes#6525
* fix(environment): restrict epoch normalization to clock fields
Require a time-field token boundary before treating numeric values as epoch clocks, so identifiers such as media format codes remain literal. Clarify recognized field forms and clock offset and precision semantics in the fidelity guide.
Fixes#6551
* fix(process): preserve sibling path identities
Keep aliases on selected paths at clear text delimiters so a longer sibling filename is not rewritten as the executable. Version the normalization contract and cover source and actual PTY behavior.
Fixes#6586
* fix(sigrok): retain recording suffix for autodetection
Copy recordings under a private filename that retains the caller-selected final suffix, and pass that filename to sigrok. This restores filename-based autodetection without exposing the source directory.
Fixes#6580
* test(go): assert unresolved MZ candidate boundary
* fix(pe): ignore unused export ordinal slots
Fixes#6577
* fix(macho): recognize arm64_32 binaries
Fixes#6581
* fix(go): honor amd64p32 pointer width
Fixes#6590
* fix(pe): accept BER indefinite CMS values
Fixes#6574
* fix(browser): reject overlapping indexed source maps
Fixes#6562
* fix(browser): resolve prefixed XHTML form actions
Fixes#6561
* fix(browser): preserve well-known path case
Fixes#6571
* docs(browser): clarify parser evidence contracts
* fix(gpu): accept percent-prefixed PTX entry names
Fixes#6592
* fix(gpu): accept PTX compute target aliases
Preserve the source spelling of NVIDIA's documented compute_xx target synonym.
Fixes#6494
* fix(gpu): parse legacy PTX body parameters
PTX 1.0 through 1.3 declares kernel parameters inside the entry body. Keep later-version parameter-list parsing unchanged.
Fixes#6594
* fix(gpu): keep unknown targets out of exact filters
Fixes#6599
* fix(gpu): resolve extended CUBIN symbol sections
Fixes#6600
* docs(firmware): document the Windows Unblob submodule checkout (#6464)
On Windows, the pinned Unblob commit cannot be checked out because 11
upstream fixture paths under tests/integration/ are invalid on NTFS.
Document the verified sparse-checkout workaround and point Windows
contributors to it from CONTRIBUTING.
Claude-Session: https://claude.ai/code/session_01LjhoPGpqAwHwcCgectzRsp
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fix(recovery): retain file outcomes and cleanup ownership
Use shared owned-file and directory primitives throughout Wakaru discovery,
snapshots, report parsing and publication. Preserve primary read failures and
completed fingerprints when final close fails or receives cancellation.
Retain exact cleanup capabilities before retiring workspaces, block new work
while cleanup is unresolved, and bind error status to the aggregate owner so
partial cleanup and later retry keep resource attribution current.
* fix(pe): preserve biased export ordinals
Accept the format-derived ordinal range for PE export slots.
* docs: clarify parser authority and compatibility evidence
* fix(python): preserve code-name identity
Fixes#6593
* fix(managed): validate metadata operands and locals declarations
Classify MemberRef operands from parsed signatures, validate signature table references and LocalVarSig blobs, and compare observed locals declaration presence. Keep partial CIL facts and transient-budget ownership at the method reader.
Fixes#6578Fixes#6572Fixes#6558Fixes#6513
* fix(python): preserve historical signed code fields
Keep signed co_stacksize and co_flags for historical magic entries whose constructors accepted them. Preserve magic 3410 with a constructor-revision limitation; reject negative values from 3411 onward.
Fixes#6487
* fix(python): compare code objects without inline caches
Fixes#6597
* fix(tests): stabilize process fixtures and malformed input coverage (#6570)
Preserve renamed-executable identity, complete-line readiness and bounded child lifetimes. Use genuinely malformed Inspector input and explicit ADB file-probe/push/hash facts while preserving cancellation, cleanup, Evidence and completeness assertions. Adopt current main Go fixtures and retain malformed COFF coverage.
Fixes#6556
Refs #6480
* test(apktool): own lifecycle fixtures and process observations
* refactor(mcp): reuse parsed Evidence tool parameters
* fix(runtime): align remaining Node security pins and setup guidance (#6316)
Derive exported Docker image versions from .nvmrc through generated package metadata. Align active setup translations with patched Node release floors and verify actual CLI exports, real Docker/agentenv, package and website workflows.
Eight built-test shards pass; three unrelated managed source failures reproduce on clean main and remain tracked in #6650.
Refs #6480
Co-authored-by: gensokyo-dev <[email protected]>
* fix(model): retain exact safetensors shape dimensions
Keep unsigned integer declarations exact until their owning field is interpreted. Bound actual offsets at conversion and validate shape products in declaration order, preserving large empty tensor shapes without hiding an earlier overflow.
Fixes#6627
* fix(python): read legacy TYPE_INT64 marshal values
Fixes#6609
* fix(apk): read constructed BER signer signatures
Share the bounded BER tree reader between PE certificates and APK v1 CMS, then accept constructed OCTET STRING signature values while retaining the declared signer and certificate facts. Embedded X.509 certificate decoding keeps its DER requirement.
Fixes#6603
* fix(adb): count Unicode requested permissions
Count requested-permission rows containing Unicode names, and keep counting subsequent rows in the same dumpsys section.
Fixes#6584
* fix(signals): reject missing sigrok channels
Recognize the exact selected-channel diagnostic even when sigrok-cli exits successfully, while preserving partial producer output in the invalid-input details. Cover both public JSON adapters and add the missing-channel case to the Linux real-tool verifier.
Fixes#6631
* fix(elf): reuse recognized machine architecture facts
Preserve the shared EM_HEXAGON classification in Go and Rust image reports.
Fixes#6629
* fix(asn1): decode four-byte BER lengths unsigned
Accumulate length octets arithmetically so a four-octet length with bit 31 set remains a positive unsigned value and is rejected by the containing-range check rather than becoming a negative length.
* fix(gpu): preserve parameter and target declarations
Decode observed V2 CUDA parameters, retain qualified PTX parameter names and entry resource counts, and preserve family and feature target declarations through selection and consistency checks.
Fixes#6624Fixes#6625Fixes#6626Fixes#6618Fixes#6613Fixes#6606
* fix(captures): preserve canonical TShark alias fields
TShark resolves selected field aliases before writing packet JSON. Keep the requested selector in Evidence while accepting the canonical field key produced for it.
Fixes#6595
* fix(qlog): mark records with unknown STREAM FIN incomplete
Keep known STREAM ranges and the unknown FIN value, while listing the source event among incomplete fact records so summary and retained views agree.
Fixes#6598
* fix(pcap): retain absolute HTTP request targets
Reuse parsed URI facts and preserve uncertainty when mixed request records cannot all be resolved from the producer output.
Fixes#6537
* fix(rust): preserve historical cargo-auditable feature facts
Accept observed feature arrays, preserve omitted values as unknown across producer revisions, and keep older retained reports compatible. Reuse bounded JSON sizing before graph expansion.
Fixes#6622
* fix(ptx): normalize parameter declarators once
Fixes#6606
* fix(managed): compare observed call targets
Compare aligned managed call edges by their reported declaring type and method name, keeping missing target facts unknown without comparing build-local tokens. Document the static comparison limits.
Fixes#6630
* fix(artifacts): compare PyInstaller declaration facts
Compare stable producer-tagged declarations independently of materialized payloads. Preserve missing facts as unknown without applying PyInstaller rules to foreign metadata or nested container entries.
Fixes#6484Fixes#6485
* test(managed): retain derived facts in cloned method fixtures
Clone caller-scoped call and field facts with the fixture methods. Keep known CIL changes alongside unavailable target metadata in the missing-row controls.
* refactor(apk): consume shared BER node facts
Remove the APK reader's pass-through children and content projections so format consumers read the shared BER owner's nodes directly. Keep only the encoded-span helper needed for exact issuer and certificate bytes, and describe CMS BER as this parser's structural owner.
* fix(adb): delimit permission section by indentation
* test(managed): preserve field-access owner identities
* fix(managed): share reference instruction semantics
Use the same parsed method/field operand predicate when producing member edges and comparing call and field shapes. Exclude ldtoken and operands without a value from both interpretations.
* test(managed): align source goldens with metadata validation
Fixes#6650
* fix(native): consolidate observed address validation
* fix(gdb): separate queued work from MI synchronization
Queued console followers have not dispatched MI records. Use active protocol requests when deciding whether the admitted close can verify and detach its inferior.
Fixes#6661
* fix(gdb): wait for the outer console command to finish
After a running result, queue a tokenized read-only MI query to establish that GDB has returned to its command loop. Keep collecting through intermediate inferior stops and retain the query reply as protocol Evidence.
Fixes#6660
* fix(erlang): retain admission cancellation reason
Preserve the caller's AbortSignal reason when BEAM inspection is cancelled before provider admission. Keep the production filesystem boundary and late-completion contracts covered.
Fixes#6658
* fix(desktop): probe GameMaker data filenames
Select conventional Linux and macOS game data files for the existing bounded FORM/GEN8 probe. Add service-boundary regressions and document the selected names.
Fixes#6659
* fix(harmony): exclude raw resources from manifests
Classify known resource paths once and keep a raw resource named module.json from changing the package model or appearing as a manifest. Add a filesystem-boundary regression and clarify the documented hint.
Fixes#6638
* fix(gpu): bound embedded section reads
Fixes#6657
* fix(gpu): retain resources across entry pragmas
Fixes#6651
* fix(reference-source): preserve raw POSIX filename identity
Mark directories with non-UTF-8 names unsupported without following replacement-character paths, while retaining readable sibling observations.
Fixes#6653
* fix(reference-imports): retain exact dynamic import targets
Use the shared exact-literal reader for dynamic imports, preserving expression-free templates and transparent TypeScript wrappers while leaving computed targets unknown.
Fixes#6654
* fix(reference-imports): retain exported import-equals dependencies
Route exported external import-equals declarations through the same relationship owner as plain declarations so their required target is not dropped.
Fixes#6655
* fix(managed): respect native module case semantics
Preserve the observed native format when comparing module identities so ELF case-only differences remain mismatches while unknown platform behavior stays unresolved.
Fixes#6652
* fix(il2cpp): reject duplicate method tokens per image
Reject duplicate MethodDef row identities within one owning image before publishing native addresses or Ghidra seeds, while retaining cross-image reuse and folded code addresses.
Fixes#6610
* refactor(reference-imports): share exact literal parsing
Route legacy nested import-expression handling through the same exact-literal owner as dynamic imports, removing a duplicate string-only check.
Fixes#6654
* fix(model): preserve optional metadata and tensor alignment
Fixes#6656Fixes#6637Fixes#6636
* fix(macho): infer legacy Intel simulator platforms
Fixes#6649
* fix(macho)!: preserve ambiguous chained import names
Keep the exact producer expression and report unknown symbol identity when chained-import text cannot distinguish a binding addend from a literal name suffix.
Fixes#6648
BREAKING CHANGE: inspect_macho import names can be null when identity is ambiguous. Use raw_name for the observed expression and name_status to distinguish it from an exact symbol name.
* fix(elf): retain raw export name bytes
Fixes#6647
* refactor(macho): separate dyld import and export parsing
Keep mode-specific inputs and parsed row types at their respective parser boundaries.
* fix(macho): preserve import identity in retained views
Use distinct row contracts for imports and exports, retaining ambiguous names and historical import defaults without adding import-only fields to export pages. Verify the SDK-advertised schemas and both facets through MCP.
* style(desktop): format GameMaker probe coverage
* chore(deps): update Vite security patch and dependency inventory (#6416)
Update Vite/PostCSS and refresh the lock-derived inventory while retaining TSRS platform selection and runtime dependency versions.
Source/static checks, installed-platform signatures, full/production audits, real CLI/MCP workflows and all four package platforms pass. Portable CI retains the independently reproduced main PTX fixture failure tracked in #6675; use the owner-authorized existing PR-only baseline exception. Refs #6480.
* fix(release): isolate npm publication from dependency execution (#6681)
Keep dependency execution in read-only release jobs and validate the original qualified archive with Node built-ins before publication. Refresh registry state on every publisher attempt; retain exact bytes/channel verification, v1 read-only recovery, and installed CLI/MCP checks before MCP publication.
Static/docs checks, artifact/registry/recovery tests and real package/rehearsal verification pass. All four hosted package platforms pass. Portable CI retains the independently reproduced main PTX failure in #6675 and fail-fast missing coverage; use the owner-authorized existing PR-only exception, with limitations documented in the PR. Refs #6480.
* refactor(json): consolidate representation size accounting
Share bounded UTF-8 and UTF-16 JSON measurements across state serving, write retention and source-map admission. Remove duplicate counters and distinguish retained state estimates from encoded bytes while preserving limits and exact refusal diagnostics.
* refactor(android): own search summaries at the producer boundary
Reuse validated class pages for inline pagination audits while retaining complete provider replies. Move retention into the shared Android workflow and remove the MCP-only service wrapper and application text reparser. Preserve unknown JSON metadata, late cancellation and retention failures.
* test: align boundary fixtures with producer contracts
Model GDB console completion, use real directory reads and cleanup for late-enumeration failures, and distinguish supported PTX pointer qualifiers from unknown declarations. Preserve original assertion and cleanup failures through scoped test finalizers.
* fix(rust): retain parsed defaults in cached Evidence views
Borrow sealed reports only when they match the parsed facts; otherwise cache the owned normalized snapshot. Keep historical feature omissions unknown through saved bundles and repeated retained pages without changing the source Evidence.
Fixes#6689
* fix(model): retain parsed headers when hashing is interrupted
Share partial observation ownership across GGUF and Safetensors. Preserve completed header facts through cancellation and MCP error delivery without claiming finalized digests or file identity.
Fixes#6684
* fix(gpu): preserve PTX parameter and target facts
Fixes#6664Fixes#6675Fixes#6680Fixes#6695
* fix(go): read inline build strings from ELF mappings
Fixes#6716
* fix(rust): scan read-only ELF load data
Fixes#6663
* fix(il2cpp): deduplicate consistent ELF registration aliases
Fixes#6715
* fix(il2cpp): track unresolved ELF relocation widths
Fixes#6701
* fix(artifacts): preserve raw directory name identity
Fixes#6665
* fix(desktop): retain unsupported filename coverage
Fixes#6665
* fix: preserve unknown historical module resolution
Fixes#6679Fixes#6678Fixes#6612
* fix: retain proven createRequire URL bases
Fixes#6612Fixes#6678
* fix(apple): preserve keyed archive table identity
Fixes#6662
* fix(plist): reject XML dictionary keys without values
Fixes#6682
* fix(apple): preserve NIBArchive special real values
Fixes#6583
* fix(signals): reject missing targets and invalid UTF-8
Fixes#6671Fixes#6693
* fix(beam): accept bytes after declared form
Fixes#6717
* fix(artifacts): compare source map target identity
Fixes#6706
* fix(pyinstaller): retain executable member metadata
Fixes#6702
* fix(pyinstaller): decode interned unicode names
Fixes#6676
* fix(pyinstaller): retain colliding archive observations
Keep source-distinct CArchive rows and decoded PYZ children in inventory. Refuse only when extraction reaches a destination conflict.
Fixes#6674
* fix(dotnet): preserve managed metadata comparison facts
Decode VARARG sentinels and allow omitted empty blob heaps while retaining failures for referenced missing data. Compare field and catch targets using owning parsed facts instead of build-local tokens.
Fixes#6720Fixes#6686Fixes#6713Fixes#6712
* fix(dotnet): keep TypeRef catch identity unknown
Fixes#6712
* test(apple): assert projected interface builder facts
* fix(dotnet): correct metadata comparison regressions
* fix(il2cpp): deduplicate aliased registration fields
Fixes#6715
* test(pyinstaller): match interned name producer encoding
Use Python 3.13 PYZ magic with the matching archive version and exercise FLAG_REF with TYPE_INTERNED.
Fixes#6676
* test(dotnet): split managed comparison blocks
* test(apple): isolate NIBArchive real projection group
* fix(parsers): correct Rust import and PTX alignment control
* fix: recognize aliased createRequire bindings
Fixes#6612Fixes#6678
* test(apple): retain NIBArchive limitation path
* fix(il2cpp): deduplicate aliased metadata registration
Fixes#6715
* test(managed): retain observed target changes across member remaps
* fix: track require.resolve references
Fixes#6678
* test(pyinstaller): encode PYZ list length correctly
Write the marshal list length as its raw little-endian count and surface inventory limitations when completeness regresses.
Fixes#6676
* fix(managed): retain unknown catch identity beside observed name changes
* fix: retain require.resolve source facts
Fixes#6678
* refactor(javascript): name retained require call facts explicitly
* fix: resolve selected require call members
Fixes#6678
* fix(javascript): keep unresolved created-loader bases unknown
* refactor(artifacts): centralize completed file outcomes
Project completed values and cancellation from the descriptor owner once across artifact consumers. Preserve completed void outcomes and format-specific validation and cleanup policies.
Keep later aborts from replacing captured APK and SQLite close failures, and retain the exact APK cancellation reason. Exercise real descriptors, public workflows and cleanup retries.
* fix(javascript): isolate package facts from host prototypes
Build frozen package field snapshots with a null prototype and restrict reference-source main lookup to own properties. Preserve declared null and empty values, index fallback, source identity and unavailable manifest evidence.
Compare inherited main and exports lookup with the native Node resolver, retain package observation coverage and verify CLI/MCP package workflows.
* fix(captures): advertise offline capture inspection without a browser provider (#6725)
* fix(parsers): preserve format boundaries and query occurrence identity
Normalize parsed facts at their owning boundaries across PE exports and certificates, ELF section names, GPU bundles, IL2CPP generic types, dyld slice selection, source maps, environment replay, and JavaScript mapped arguments. Preserve partial facts and explicit unsupported cases; clarify the corresponding documentation.
Validation: 831 affected tests passed with one existing skip across 23 files; build, typecheck/lint, documentation, formatting, and 2133-file test discovery passed. Format controls are synthetic; real Unity, GPU, and ARM-device execution is unverified.
Fixes#6709Fixes#6688Fixes#6719Fixes#6718Fixes#6704Fixes#6703Fixes#6692Fixes#6723Fixes#6687Fixes#6726Fixes#6696Fixes#6691Fixes#6727
* fix(process): require observed environment ownership tokens
Centralize run-token extraction at the environment observation boundary and require an own field. Build decoded OS environment records without host prototypes while retaining source names, empty values and last-assignment precedence.
Reject inherited matching tokens before cleanup signaling, preserve normal owned-group behavior, and verify live Linux process environments alongside native CLI/MCP capture workflows.
* fix(parsers): retain independent facts and boundary identity
Share bounded ELF section-name decoding across native and note readers; retain read-only ranges and coverage reasons when names are unknown. Preserve ELF symbol-version bytes, dyld-bound method uncertainty, partial gRPC-Web trailers, and per-parent model identity checks. Compare GPU signatures as bytes and require a PTX module header. Share selected-path errno classification across EVM and BEAM.
Validation: 397 shared-parser tests passed (one existing skip), 5 MCP schema tests passed, 14 EVM error-mapping tests passed, and 23 protobuf CLI/MCP matrix cases passed across focused runs. Build, typecheck/lint, docs, formatting, and 2134-file discovery passed. Full EVM provider workflow remains locally unverified on Darwin arm64; format controls are synthetic.
Fixes#6738Fixes#6737Fixes#6745Fixes#6740Fixes#6749Fixes#6747Fixes#6739
* fix(setup): preserve source keys across configuration boundaries
* fix(setup): keep the CLI-only skill choice offered under a client ID (#6401)
* fix(setup): keep the CLI-only skill choice offered under a client ID
* test(setup): cover the accept-all CLI-only skill selection
* fix(apple): report a read-denied selected archive as host access denial (#6479)
* fix(apple): report a read-denied selected archive as host access denial
inspect-keyed-archive reported a host read refusal on the caller-selected bundle entry as artifact_operation_failed/execution_failure with reason io, leaving EACCES or EPERM only inside message text. The caller selected that entry, so the refusal is a selection outcome with its own typed classification, system code and read-access recovery.
DirectoryArtifactReader now marks a refused entry open with DirectoryArtifactEntryAccessDenied, which retains the host system code and the selected entry path. KeyedArchiveReader, which owns the caller's selection, maps it to the shared AnalysisAccessDeniedError, and artifact failure translation keeps that typed error instead of replacing it with a generic io failure. Other readers and other reader failures are unchanged; every existing reason keeps its current projection.
Adds the access_denied projection coverage plus a real host refusal through the production reader and a non-permission control.
* fix(apple): carry cleanup ownership and cover raw refusals for a denied selection
Addresses the two review findings on the denied-selection classification:
- The typed host access denial now carries the reader's cleanup observation, so a denied open that left a resource owned does not project as fully cleaned.
- Adds coverage that starts from raw host EACCES/EPERM/EIO refusals with the real DirectoryArtifactReader open path, so the marker itself is exercised rather than constructed by the test. EIO stays an artifact failure.
* fix(native): report plist symlink loops and overlong paths as selection failures (#6371)
Co-authored-by: Abelo9996 <[email protected]>
* docs(cli): document opt-in Bash completion setup (#6250)
* fix(doctor): check only the current platform's Hopper launcher candidates (#6253)
* fix(doctor): check only the current platform's Hopper launcher candidates
Doctor built one launcher list for every platform, so on macOS it could
report a Linux-only path as a healthy Hopper ahead of a renamed bundle,
and setup then registered that path. Give per-platform automatic
candidates one owner that runtime configuration and doctor both read,
scan renamed macOS bundles and probe the Homebrew cask only on macOS,
and share runtime's renamed-bundle scan with the doctor host.
Fixes#6228
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(doctor): keep the renamed Hopper bundle scan asynchronous
Sharing runtime's synchronous scan made the doctor host read
~/Applications with readdirSync, which blocks the event loop on a slow
or network-mounted home. Give MacHopperPaths an asynchronous scan for
doctor beside runtime's lazy synchronous one, sharing the directory
filter and candidate builder, and check that both return the same
candidates.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(doctor): model renamed launchers with runtime's POSIX joins
Since #5235, runtime builds macOS launcher paths with posix.join, so on
Windows the discovery table's native-join renamed launcher no longer
matched runtime's candidate. Model launchers with posix.join and keep
filesystem setup native, as MacHopperPaths.test.ts does.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fix(entropy): name offset when the byte window starts past EOF (#6495)
Fixes#6482
Co-authored-by: Abelo9996 <[email protected]>
* fix(sqlite): report result-column capacity refusals as capacity (#6327)
A projection wider than SQLite's native result-column limit failed with the
generic "too many columns in result set" SQL error. The inspector could not
attribute that error to a generated column, so the worker reported "format"
and the parent blamed the caller's path as invalid_format even though the
selected database was readable.
Classify the refusal from SQLite's own column limit for the private
connection, carry the selected and engine counts through the worker reply,
and project it as a capacity resource constraint. The database stays
readable, no partial rows are returned, and the recovery names the column
counts and splitting the projection across calls.
* fix(web): refuse an existing script-export destination as invalid input (#6313)
* fix(web): refuse an existing script-export destination as invalid input
export_web_scripts refused an existing output directory or link correctly,
but reported it as artifact_operation_failed / execution_failure with no
field issue or recovery. SafeOutputTree.create raises that refusal as a
path failure before any output tree exists, and the export mapper wrapped
it as an artifact failure.
Attribute pre-admission path refusals to output_directory as an
AnalysisInputError, as environment export already does for its directory.
Both now share one helper owned beside SafeOutputTree; failures after the
tree is admitted keep their artifact semantics.
Fixes#6029
* fix(artifacts): type SafeOutputTree destination refusals
Admission conversion treated any cleanup-free path failure raised before
admission as a refusal of the selected directory, so an acquired-tree setup
failure, such as being unable to restrict a created root to 0700, blamed
valid output_directory or directory input.
SafeOutputTree.create now raises SafeOutputTreeDestinationRefusal for the
refusals of the selection itself: a relative or reserved root, an existing
root, and an accepted existing root that is not an empty directory. The shared
conversion accepts only that type, directly or wrapped by
SafeOutputTreeCreationFailure, so script and environment export no longer
track admission separately.
* fix(evm): reject repeated container keys in Solidity metadata (#6230)
* fix(evm): reject repeated container keys in Solidity metadata
* test(evm): check the repeat-key diagnostic for deeply nested keys
* docs(ci): add a repeatable static analysis example (#6496)
* docs(ci): add a repeatable static analysis example
* fix(ci): isolate example reports and repair the guide link
---------
Co-authored-by: gongfpp <[email protected]>
* fix(setup): retain unresolved environment facts when deriving budgets
* fix(parsers): preserve format evidence and caller input identity
Retain bounded FAT and offset-tagged PE observations through archive hashing,
classification, and content nodes. Preserve PyInstaller member paths according
to the observed carrier dialect and share APK v1 signing-name semantics.
Read SQLite's implicit sqlite_schema table without inventing a stored schema
declaration. Distinguish unsupported ELF numbering and decoded-name admission
from malformed data and fixed scan allowances. Preserve Sigrok basenames and
classify matching explicit input-format refusals at their owning boundary.
Validation: 554 distinct tests passed, 3 skipped across serial focused runs;
build, typecheck/lint, docs, formatting, and discovery (2141 files) passed.
Sigrok command-boundary simulators do not establish real-tool decoding.
Small repeated public PyInstaller CLI runs had equivalent inventory facts;
warm median elapsed 0.5431s before / 0.5426s after, with no speed claim.
Fixes#6733Fixes#6741Fixes#6722Fixes#6732Fixes#6736Fixes#6734Fixes#6764Fixes#6766
Refs #6739
* fix(parsers): respect container facts and real decoding boundaries
Use zip.js's parsed symlink fact for inventory and open refusal. Treat an
unmatched Godot trailer as an unconfirmed candidate while preserving failures
for confirmed malformed packs. Report entropy path-resolution failures at the
selected-input boundary.
Separate Go header discovery from inline string extents in ELF and Mach-O,
and apply the aggregate content allowance after validating real source ranges.
Normalize binary plist UID widths through the existing scalar-copy owner,
budget exact clone growth, preserve source identity, and refuse inexact UIDs.
Validation: 389 distinct tests passed, one Linux /proc test skipped on Darwin;
build, typecheck/lint, docs, single-thread formatting, and discovery (2142 files)
passed. CLI/MCP Go fixtures and public ZIP/Godot/keyed-archive workflows ran.
Real producer prevalence and external provider execution were not established.
Repeated ordinary keyed-archive CLI inventory facts and estimated reply tokens
were equal before/after. Warm median elapsed was 0.5166s / 0.5177s; no speed claim.
Fixes#6751Fixes#6763Fixes#6754Fixes#6767Fixes#6762Fixes#6779
* refactor(mcp): consolidate Evidence recording and operation progress
* fix(setup): reuse URL component admission for Hopper releases
* perf(cli): avoid loading analysis commands for version reports
---------
Co-authored-by: morluto <[email protected]>
Co-authored-by: Hifza Zafar <[email protected]>
Co-authored-by: Can <[email protected]>
Co-authored-by: eco-null <[email protected]>
Co-authored-by: Cassie_Fox <[email protected]>
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
Co-authored-by: Wade <[email protected]>
Co-authored-by: RRFZ <[email protected]>
Co-authored-by: pablodiazjorge <[email protected]>
Co-authored-by: Ezra Brilliant <[email protected]>
Co-authored-by: gensokyo-dev <[email protected]>
Co-authored-by: GamerDubz <[email protected]>
Co-authored-by: raidnouredden-ux <[email protected]>
Co-authored-by: 吴佳浩Alben <[email protected]>
Co-authored-by: Abel Yagubyan <[email protected]>
Co-authored-by: Abelo9996 <[email protected]>
Co-authored-by: ShuaixinHuang <[email protected]>
Co-authored-by: Paritosh Lahre <[email protected]>
Co-authored-by: Dery Ferdika <[email protected]>
Co-authored-by: gongfpp <[email protected]>
Co-authored-by: gongfpp <[email protected]>
Preserve boundary facts and uncertainty through their consumers. Add focused production-boundary regressions and update affected documentation.
Fixes#6760
Preserve boundary facts and uncertainty through their consumers. Add focused production-boundary regressions and update affected documentation.
Fixes#6758
Preserve boundary facts and uncertainty through their consumers. Add focused production-boundary regressions and update affected documentation.
Fixes#6756Fixes#6752Fixes#6755
Preserve boundary facts and uncertainty through their consumers. Add focused production-boundary regressions and update affected documentation.
Fixes#6780
Preserve format and Evidence semantics at their owning boundaries, with focused regression coverage and documentation where applicable.
Fixes#6773Fixes#6786
Preserve format and Evidence semantics at their owning boundaries, with focused regression coverage and documentation where applicable.
Fixes#6785Fixes#6714Fixes#6735Fixes#6750
Preserve format and Evidence semantics at their owning boundaries, with focused regression coverage and documentation where applicable.
Fixes#6772Fixes#6787
Use zip.js's parsed symlink fact for inventory and open refusal. Treat an
unmatched Godot trailer as an unconfirmed candidate while preserving failures
for confirmed malformed packs. Report entropy path-resolution failures at the
selected-input boundary.
Separate Go header discovery from inline string extents in ELF and Mach-O,
and apply the aggregate content allowance after validating real source ranges.
Normalize binary plist UID widths through the existing scalar-copy owner,
budget exact clone growth, preserve source identity, and refuse inexact UIDs.
Validation: 389 distinct tests passed, one Linux /proc test skipped on Darwin;
build, typecheck/lint, docs, single-thread formatting, and discovery (2142 files)
passed. CLI/MCP Go fixtures and public ZIP/Godot/keyed-archive workflows ran.
Real producer prevalence and external provider execution were not established.
Repeated ordinary keyed-archive CLI inventory facts and estimated reply tokens
were equal before/after. Warm median elapsed was 0.5166s / 0.5177s; no speed claim.
Fixes#6751Fixes#6763Fixes#6754Fixes#6767Fixes#6762Fixes#6779
Retain bounded FAT and offset-tagged PE observations through archive hashing,
classification, and content nodes. Preserve PyInstaller member paths according
to the observed carrier dialect and share APK v1 signing-name semantics.
Read SQLite's implicit sqlite_schema table without inventing a stored schema
declaration. Distinguish unsupported ELF numbering and decoded-name admission
from malformed data and fixed scan allowances. Preserve Sigrok basenames and
classify matching explicit input-format refusals at their owning boundary.
Validation: 554 distinct tests passed, 3 skipped across serial focused runs;
build, typecheck/lint, docs, formatting, and discovery (2141 files) passed.
Sigrok command-boundary simulators do not establish real-tool decoding.
Small repeated public PyInstaller CLI runs had equivalent inventory facts;
warm median elapsed 0.5431s before / 0.5426s after, with no speed claim.
Fixes#6733Fixes#6741Fixes#6722Fixes#6732Fixes#6736Fixes#6734Fixes#6764Fixes#6766
Refs #6739
* docs(ci): add a repeatable static analysis example
* fix(ci): isolate example reports and repair the guide link
---------
Co-authored-by: gongfpp <[email protected]>
* fix(web): refuse an existing script-export destination as invalid input
export_web_scripts refused an existing output directory or link correctly,
but reported it as artifact_operation_failed / execution_failure with no
field issue or recovery. SafeOutputTree.create raises that refusal as a
path failure before any output tree exists, and the export mapper wrapped
it as an artifact failure.
Attribute pre-admission path refusals to output_directory as an
AnalysisInputError, as environment export already does for its directory.
Both now share one helper owned beside SafeOutputTree; failures after the
tree is admitted keep their artifact semantics.
Fixes#6029
* fix(artifacts): type SafeOutputTree destination refusals
Admission conversion treated any cleanup-free path failure raised before
admission as a refusal of the selected directory, so an acquired-tree setup
failure, such as being unable to restrict a created root to 0700, blamed
valid output_directory or directory input.
SafeOutputTree.create now raises SafeOutputTreeDestinationRefusal for the
refusals of the selection itself: a relative or reserved root, an existing
root, and an accepted existing root that is not an empty directory. The shared
conversion accepts only that type, directly or wrapped by
SafeOutputTreeCreationFailure, so script and environment export no longer
track admission separately.
A projection wider than SQLite's native result-column limit failed with the
generic "too many columns in result set" SQL error. The inspector could not
attribute that error to a generated column, so the worker reported "format"
and the parent blamed the caller's path as invalid_format even though the
selected database was readable.
Classify the refusal from SQLite's own column limit for the private
connection, carry the selected and engine counts through the worker reply,
and project it as a capacity resource constraint. The database stays
readable, no partial rows are returned, and the recovery names the column
counts and splitting the projection across calls.
* fix(doctor): check only the current platform's Hopper launcher candidates
Doctor built one launcher list for every platform, so on macOS it could
report a Linux-only path as a healthy Hopper ahead of a renamed bundle,
and setup then registered that path. Give per-platform automatic
candidates one owner that runtime configuration and doctor both read,
scan renamed macOS bundles and probe the Homebrew cask only on macOS,
and share runtime's renamed-bundle scan with the doctor host.
Fixes#6228
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(doctor): keep the renamed Hopper bundle scan asynchronous
Sharing runtime's synchronous scan made the doctor host read
~/Applications with readdirSync, which blocks the event loop on a slow
or network-mounted home. Give MacHopperPaths an asynchronous scan for
doctor beside runtime's lazy synchronous one, sharing the directory
filter and candidate builder, and check that both return the same
candidates.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(doctor): model renamed launchers with runtime's POSIX joins
Since #5235, runtime builds macOS launcher paths with posix.join, so on
Windows the discovery table's native-join renamed launcher no longer
matched runtime's candidate. Model launchers with posix.join and keep
filesystem setup native, as MacHopperPaths.test.ts does.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fix(apple): report a read-denied selected archive as host access denial
inspect-keyed-archive reported a host read refusal on the caller-selected bundle entry as artifact_operation_failed/execution_failure with reason io, leaving EACCES or EPERM only inside message text. The caller selected that entry, so the refusal is a selection outcome with its own typed classification, system code and read-access recovery.
DirectoryArtifactReader now marks a refused entry open with DirectoryArtifactEntryAccessDenied, which retains the host system code and the selected entry path. KeyedArchiveReader, which owns the caller's selection, maps it to the shared AnalysisAccessDeniedError, and artifact failure translation keeps that typed error instead of replacing it with a generic io failure. Other readers and other reader failures are unchanged; every existing reason keeps its current projection.
Adds the access_denied projection coverage plus a real host refusal through the production reader and a non-permission control.
* fix(apple): carry cleanup ownership and cover raw refusals for a denied selection
Addresses the two review findings on the denied-selection classification:
- The typed host access denial now carries the reader's cleanup observation, so a denied open that left a resource owned does not project as fully cleaned.
- Adds coverage that starts from raw host EACCES/EPERM/EIO refusals with the real DirectoryArtifactReader open path, so the marker itself is exercised rather than constructed by the test. EIO stays an artifact failure.
Centralize run-token extraction at the environment observation boundary and require an own field. Build decoded OS environment records without host prototypes while retaining source names, empty values and last-assignment precedence.
Reject inherited matching tokens before cleanup signaling, preserve normal owned-group behavior, and verify live Linux process environments alongside native CLI/MCP capture workflows.
Normalize parsed facts at their owning boundaries across PE exports and certificates, ELF section names, GPU bundles, IL2CPP generic types, dyld slice selection, source maps, environment replay, and JavaScript mapped arguments. Preserve partial facts and explicit unsupported cases; clarify the corresponding documentation.
Validation: 831 affected tests passed with one existing skip across 23 files; build, typecheck/lint, documentation, formatting, and 2133-file test discovery passed. Format controls are synthetic; real Unity, GPU, and ARM-device execution is unverified.
Fixes#6709Fixes#6688Fixes#6719Fixes#6718Fixes#6704Fixes#6703Fixes#6692Fixes#6723Fixes#6687Fixes#6726Fixes#6696Fixes#6691Fixes#6727
Build frozen package field snapshots with a null prototype and restrict reference-source main lookup to own properties. Preserve declared null and empty values, index fallback, source identity and unavailable manifest evidence.
Compare inherited main and exports lookup with the native Node resolver, retain package observation coverage and verify CLI/MCP package workflows.
Project completed values and cancellation from the descriptor owner once across artifact consumers. Preserve completed void outcomes and format-specific validation and cleanup policies.
Keep later aborts from replacing captured APK and SQLite close failures, and retain the exact APK cancellation reason. Exercise real descriptors, public workflows and cleanup retries.
Decode VARARG sentinels and allow omitted empty blob heaps while retaining failures for referenced missing data. Compare field and catch targets using owning parsed facts instead of build-local tokens.
Fixes#6720Fixes#6686Fixes#6713Fixes#6712
Share partial observation ownership across GGUF and Safetensors. Preserve completed header facts through cancellation and MCP error delivery without claiming finalized digests or file identity.
Fixes#6684
Borrow sealed reports only when they match the parsed facts; otherwise cache the owned normalized snapshot. Keep historical feature omissions unknown through saved bundles and repeated retained pages without changing the source Evidence.
Fixes#6689
Model GDB console completion, use real directory reads and cleanup for late-enumeration failures, and distinguish supported PTX pointer qualifiers from unknown declarations. Preserve original assertion and cleanup failures through scoped test finalizers.
Reuse validated class pages for inline pagination audits while retaining complete provider replies. Move retention into the shared Android workflow and remove the MCP-only service wrapper and application text reparser. Preserve unknown JSON metadata, late cancellation and retention failures.
Share bounded UTF-8 and UTF-16 JSON measurements across state serving, write retention and source-map admission. Remove duplicate counters and distinguish retained state estimates from encoded bytes while preserving limits and exact refusal diagnostics.
Keep dependency execution in read-only release jobs and validate the original qualified archive with Node built-ins before publication. Refresh registry state on every publisher attempt; retain exact bytes/channel verification, v1 read-only recovery, and installed CLI/MCP checks before MCP publication.
Static/docs checks, artifact/registry/recovery tests and real package/rehearsal verification pass. All four hosted package platforms pass. Portable CI retains the independently reproduced main PTX failure in #6675 and fail-fast missing coverage; use the owner-authorized existing PR-only exception, with limitations documented in the PR. Refs #6480.
Update Vite/PostCSS and refresh the lock-derived inventory while retaining TSRS platform selection and runtime dependency versions.
Source/static checks, installed-platform signatures, full/production audits, real CLI/MCP workflows and all four package platforms pass. Portable CI retains the independently reproduced main PTX fixture failure tracked in #6675; use the owner-authorized existing PR-only baseline exception. Refs #6480.
Use distinct row contracts for imports and exports, retaining ambiguous names and historical import defaults without adding import-only fields to export pages. Verify the SDK-advertised schemas and both facets through MCP.
Keep the exact producer expression and report unknown symbol identity when chained-import text cannot distinguish a binding addend from a literal name suffix.
Fixes#6648
BREAKING CHANGE: inspect_macho import names can be null when identity is ambiguous. Use raw_name for the observed expression and name_status to distinguish it from an exact symbol name.
Route legacy nested import-expression handling through the same exact-literal owner as dynamic imports, removing a duplicate string-only check.
Fixes#6654
Reject duplicate MethodDef row identities within one owning image before publishing native addresses or Ghidra seeds, while retaining cross-image reuse and folded code addresses.
Fixes#6610
Preserve the observed native format when comparing module identities so ELF case-only differences remain mismatches while unknown platform behavior stays unresolved.
Fixes#6652
Route exported external import-equals declarations through the same relationship owner as plain declarations so their required target is not dropped.
Fixes#6655
Use the shared exact-literal reader for dynamic imports, preserving expression-free templates and transparent TypeScript wrappers while leaving computed targets unknown.
Fixes#6654
Mark directories with non-UTF-8 names unsupported without following replacement-character paths, while retaining readable sibling observations.
Fixes#6653
Classify known resource paths once and keep a raw resource named module.json from changing the package model or appearing as a manifest. Add a filesystem-boundary regression and clarify the documented hint.
Fixes#6638
Select conventional Linux and macOS game data files for the existing bounded FORM/GEN8 probe. Add service-boundary regressions and document the selected names.
Fixes#6659
Preserve the caller's AbortSignal reason when BEAM inspection is cancelled before provider admission. Keep the production filesystem boundary and late-completion contracts covered.
Fixes#6658
After a running result, queue a tokenized read-only MI query to establish that GDB has returned to its command loop. Keep collecting through intermediate inferior stops and retain the query reply as protocol Evidence.
Fixes#6660
Queued console followers have not dispatched MI records. Use active protocol requests when deciding whether the admitted close can verify and detach its inferior.
Fixes#6661
Use the same parsed method/field operand predicate when producing member edges and comparing call and field shapes. Exclude ldtoken and operands without a value from both interpretations.
Remove the APK reader's pass-through children and content projections so format consumers read the shared BER owner's nodes directly. Keep only the encoded-span helper needed for exact issuer and certificate bytes, and describe CMS BER as this parser's structural owner.
Clone caller-scoped call and field facts with the fixture methods. Keep known CIL changes alongside unavailable target metadata in the missing-row controls.
Compare stable producer-tagged declarations independently of materialized payloads. Preserve missing facts as unknown without applying PyInstaller rules to foreign metadata or nested container entries.
Fixes#6484Fixes#6485
Compare aligned managed call edges by their reported declaring type and method name, keeping missing target facts unknown without comparing build-local tokens. Document the static comparison limits.
Fixes#6630
Keep known STREAM ranges and the unknown FIN value, while listing the source event among incomplete fact records so summary and retained views agree.
Fixes#6598
TShark resolves selected field aliases before writing packet JSON. Keep the requested selector in Evidence while accepting the canonical field key produced for it.
Fixes#6595
Decode observed V2 CUDA parameters, retain qualified PTX parameter names and entry resource counts, and preserve family and feature target declarations through selection and consistency checks.
Fixes#6624Fixes#6625Fixes#6626Fixes#6618Fixes#6613Fixes#6606
Accumulate length octets arithmetically so a four-octet length with bit 31 set remains a positive unsigned value and is rejected by the containing-range check rather than becoming a negative length.
Recognize the exact selected-channel diagnostic even when sigrok-cli exits successfully, while preserving partial producer output in the invalid-input details. Cover both public JSON adapters and add the missing-channel case to the Linux real-tool verifier.
Fixes#6631
Share the bounded BER tree reader between PE certificates and APK v1 CMS, then accept constructed OCTET STRING signature values while retaining the declared signer and certificate facts. Embedded X.509 certificate decoding keeps its DER requirement.
Fixes#6603
Keep unsigned integer declarations exact until their owning field is interpreted. Bound actual offsets at conversion and validate shape products in declaration order, preserving large empty tensor shapes without hiding an earlier overflow.
Fixes#6627
Derive exported Docker image versions from .nvmrc through generated package metadata. Align active setup translations with patched Node release floors and verify actual CLI exports, real Docker/agentenv, package and website workflows.
Eight built-test shards pass; three unrelated managed source failures reproduce on clean main and remain tracked in #6650.
Refs #6480
Co-authored-by: gensokyo-dev <[email protected]>
Preserve renamed-executable identity, complete-line readiness and bounded child lifetimes. Use genuinely malformed Inspector input and explicit ADB file-probe/push/hash facts while preserving cancellation, cleanup, Evidence and completeness assertions. Adopt current main Go fixtures and retain malformed COFF coverage.
Fixes#6556
Refs #6480
Keep signed co_stacksize and co_flags for historical magic entries whose constructors accepted them. Preserve magic 3410 with a constructor-revision limitation; reject negative values from 3411 onward.
Fixes#6487
Use shared owned-file and directory primitives throughout Wakaru discovery,
snapshots, report parsing and publication. Preserve primary read failures and
completed fingerprints when final close fails or receives cancellation.
Retain exact cleanup capabilities before retiring workspaces, block new work
while cleanup is unresolved, and bind error status to the aggregate owner so
partial cleanup and later retry keep resource attribution current.
On Windows, the pinned Unblob commit cannot be checked out because 11
upstream fixture paths under tests/integration/ are invalid on NTFS.
Document the verified sparse-checkout workaround and point Windows
contributors to it from CONTRIBUTING.
Claude-Session: https://claude.ai/code/session_01LjhoPGpqAwHwcCgectzRsp
Co-authored-by: Claude Opus 5.5 <[email protected]>
Copy recordings under a private filename that retains the caller-selected final suffix, and pass that filename to sigrok. This restores filename-based autodetection without exposing the source directory.
Fixes#6580
Keep aliases on selected paths at clear text delimiters so a longer sibling filename is not rewritten as the executable. Version the normalization contract and cover source and actual PTY behavior.
Fixes#6586
Require a time-field token boundary before treating numeric values as epoch clocks, so identifiers such as media format codes remain literal. Clarify recognized field forms and clock offset and precision semantics in the fidelity guide.
Fixes#6551
Reject invalid ISO offsets while preserving valid boundary values. Validate stored clock-format offsets through the same parser so malformed imported formats cannot reach rendering.
Fixes#6524
Publish alignment from the parser when explicit metadata validates it, or when metadata completion establishes the default. Preserve that fact through later parsing and hashing failures.
Fixes#6579
* fix(python): reject code keys and set members with unhashable consts
* fix(python): refuse to hash a tuple that is still being read
* fix(python): hash a code object's co_consts tuple, not its item list
---------
Co-authored-by: morluto <[email protected]>
* fix(flutter): honor ELF note alignment when reading build IDs
* test(flutter): key shared note ranges by effective alignment
Cover a program and section declaration that share one note range: differing effective alignments (8 and 4) must both be read, while declarations that both normalize to four bytes (1 and 4) still share one read. 24-byte build IDs pad identically at both alignments, so only the range key decides the read count.
The sparse-child capture test asserted the frame bound with a bare boolean,
so a failure only printed "expected false to be true". The assertion now
carries the running progress details (elapsed time, frames, samples,
interactions) as its failure message. This only adds diagnostics to a
failure; it does not change what passes and does not fix the flake.
Refs #5889.
🤖 Generated with Claude Code (Sonnet 5.5) 🦊
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
Reserve equal global ID pairs and stop normalizing contested pairings. Keep numeric measurements literal, scope keyed collection identities through learning and comparison, and normalize string references only where learning established the same field as an ID.
Fixes#6565Fixes#6550Fixes#6557
Keep JSON, text, and retained bytes distinct through fidelity comparison. Compare binary bodies by bytes, including valid UTF-8 bytes against equivalent text, and keep empty-body compatibility explicit.
Fixes#6564
Project PYZ namespace packages as metadata so their query paths do not claim output directories. This lets independent CArchive files retain the same logical path and remain inspectable and extractable.
Fixes#6539
Parse complete nonzero Activity Manager reports while preserving other command failures and their captured output. Admit dollar signs only in the activity component name for nested Android classes.
Fixes#6528Fixes#6527
Share expected and observed check construction across MZ, COM, and raw-binary attestations. Preserve format-specific rules and source coordinates, and derive mapping callback types from the recording owner.
Centralize parse-wide identity and coverage facts while keeping conservative admission values separate from measured rows and counters. Reuse the derived truncation reason and retain the final serialization bound.
Tighten the report-budget regression so unexpected parser finalization errors cannot be swallowed by its budget search.
Carry caller messages through the existing schema issue owner instead of constructing and discarding an intermediate input error. Remove forwarding schema helpers and migrate equivalent constructors across investigation, firmware, dylib, process, and screenshot workflows while preserving diagnostic paths and causes.
Validate canonical dimension ownership, summary counts, and exact changed or unknown projections before investigation consumers publish derived Evidence. Reuse the shared dimension contract in selectors and keep historical source fixtures internally consistent.
Verify authentic malformed comparisons across all three MCP consumers while preserving valid reordered and unknown results and retained source Evidence.
* fix(javascript): report recovery inputs that collide on a case-insensitive filesystem
* test(javascript): cover a recovery input selected twice on any filesystem
* test(javascript): cover snapshot collision causes and unrelated write failures
Require Node.js ^22.23.4 || ^24.22.1 || >=26.12.1 across package engines, setup/doctor and the standalone installer. Validate patch boundaries and maintain runtime-independent listener identity, heap-option and HTTP schema-binding tests.
Closes#6283
Refs #6480
BREAKING CHANGE: Node versions below 22.23.4, 24.22.1 and 26.12.1 are no longer supported. Upgrade Node before installing or updating REA; the installer does not upgrade Node.
Co-authored-by: gensokyo-dev <[email protected]>
* fix(lifecycle): reject session work once close has started
Process shutdown closed the shared binary session without sealing it, so a
stdio tool call could open a provider after that close and leave the child
running. GDB ran a queued console command or a second close after the session
had started closing because the queued turn did not repeat admission checks.
Shutdown now refuses later target acquisition, and a queued GDB command or
duplicate close fails as unavailable once its turn finds the session closing
or gone.
Co-authored-by: morluto <[email protected]>
* fix(gdb): block console admission after cleanup starts
---------
Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: morluto <[email protected]>
The EVM interface failure translator grouped the stable reader's input
limit with path and format refusals, so a carrier over the fixed 4 MiB
input allowance surfaced as a non-retryable invalid_request whose only
record of the allowance was issue text pointing at the input schema.
The same refusal now returns a non-retryable resource_constraint with
resource file-size and reported_limits.maximum_input_bytes, following
the WABT input translator, while path and format reader refusals stay
input errors. The reply-size write failure keeps its own branch.
Fixes#6053
capture-process recorded exit.code 0 for a target a scenario event killed
with SIGKILL or SIGTERM, beside the nonzero exit.signal. The result builder
and the retained observation each kept any nonnegative PTY exit code for an
exited capture without consulting the signal; only finalization checked it.
Project the exit once in captureExitObservation, whose normal exit code is
null when a nonzero signal ended the target, and use the same rule for
finalization. Normal exits keep their codes, including 0 and 3, and deadline
exits remain null.
Fixes#6445
`mcp doctor --format` and `--format=` reported VALIDATION_ERROR
"Invalid output format: missing", although docs/cli.md documents
MISSING_OUTPUT_VALUE for valued output flags without a value and
`capabilities` already returns it. Classify absent and empty values as
missing, share the existing missing-value message, and keep
VALIDATION_ERROR for a present but unsupported format.
Fixes#6455
Claude-Session: https://claude.ai/code/session_01LjhoPGpqAwHwcCgectzRsp
Co-authored-by: Claude Opus 5.5 <[email protected]>
Check the ARM/Thumb success marker with the runner-provided grep -F. The real Ghidra probe succeeded, but the previous rg dependency made the lane exit 127.
Validated with the actual workflow shell, producer-failure and missing/incorrect marker controls, 17 focused tests, and hosted Ghidra 12.1.4 / JDK 21 compilation and ARM/Thumb context checks.
Inject interrupts through imported projection and Evidence resolution boundaries so lexical service calls cannot bypass the test. Preserve exact normalized partial results, authenticated Evidence provenance and signal exit codes.
Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
Require parsed seed facts in the pure trace projection and leave raw request defaults at the shared workflow boundary. Remove the redundant seed parse, unused raw-seed alias and duplicate seed-match binding.
Move omitted-versus-explicit defaults and full Evidence identity checks to compiled CLI/MCP acceptance. Reuse the owned MCP fixture and request files in the tests. Matching, native handoff, empty-literal, coverage and immutability checks remain covered; public schemas and successful outputs are unchanged.
Return expected source and semantic failures from the runtime input owner as tagged Results. Bind source schema validation to concrete schemas, preserve nested active-capture paths, and let unexpected interpretation and derivation failures reach the adapter boundary.
Remove broad protocol-error wrappers, duplicate active identity validation, and redundant JSON result parsing. Migrate parsed-fact consumers and retain CLI/MCP contracts. Relevant source and public-boundary tests pass; six injected implementation-fault controls fail on the prior revision. Live Electron behavior was not exercised.
Route CLI and MCP coverage requests through the shared strict workflow boundary before authenticating source Evidence. Preserve canonical advertised schemas, use integrity errors for malformed source bundles, and use the workflow operation for input diagnostics.
Remove the unused throwing domain facade and keep semantic fixture assertions on the parsed Result APIs. Validate compiled CLI and stdio MCP parity, strict request rejection, domain authority/time semantics, generated schemas, and unexpected failure propagation. No external providers execute in these checks.
Separate source corruption and selected-role errors from unexpected derivation failures. Normalize coordinates before body membership and conflict checks, reuse parsed requests, and account for outer observation arrays before validation copies.
Authenticate inventory requests once before family projection, remove obsolete schema aliases and raw facades, and preserve unresolved occurrence references from partial pages without fabricating content identities.
* fix(reconstruction): dedupe residual unknown ids with uniqueSorted
Current main calls uniqueBy, which is not defined, so typecheck fails.
Residual unknown ids are strings, and the adjacent lists already use
uniqueSorted.
Co-authored-by: morluto <[email protected]>
* feat(config): make the bridge request ceiling configurable
REA_BRIDGE_MAX_REQUEST_BYTES replaces the hard-coded 16 MiB Hopper and
Cutter request payload ceiling. The default stays 16777216 bytes. Values
outside 7464 to 268435456 bytes are configuration_invalid.
Part of #6176.
Co-authored-by: morluto <[email protected]>
* fix(cutter): keep cleanup ownership when a sent command's reply is oversized
An authenticated command may already have changed the Cutter document
when its reply exceeds the frame ceiling. Return the existing unknown
execution, with the ceiling diagnostic in the message, so receipt
cleanup still waits. A frame that overflows before the command is sent
remains a resource constraint.
Co-authored-by: morluto <[email protected]>
* style: format the bridge request ceiling sources
oxfmt --check failed on the five files that set and test
REA_BRIDGE_MAX_REQUEST_BYTES. Formatting only; an oversized Cutter
reply still stays an unknown execution.
Co-authored-by: morluto <[email protected]>
* fix(cutter): exclude the LF from the response frame budget
REA_BRIDGE_MAX_REQUEST_BYTES counts payload bytes. The Cutter response
reader and authenticated encoder were reserving one byte for the
terminating LF, so an exact-limit response was rejected. A reply that
exceeds the ceiling after the command was sent still stays an unknown
execution.
Co-authored-by: morluto <[email protected]>
* fix(bridge): measure escaped JSON before allocating the request
A command of U+0001 characters can expand sixfold. JSON.stringify of
that expansion can throw past Node's string ceiling before the payload
check. Count the escaped size within REA_BRIDGE_MAX_REQUEST_BYTES
first and refuse it as a resource constraint.
Co-authored-by: morluto <[email protected]>
* fix(config): derive the bridge request maximum from JSON expansion
A 256 MiB ceiling still lets a shorter U+0001 command expand past Node's
536870888-character string limit. The maximum is now
floor((536870888 - 296) / 7) = 76695798, the longest such command whose
authenticated frame fits in one string. Requests are still measured
before JSON.stringify.
Co-authored-by: morluto <[email protected]>
* fix(bridge): size the Cutter frame deadline and send the measured Hopper payload
The authenticated Cutter command is encoded after the challenge, so a
one-second read rejected an in-budget frame. That read now allows one
second per mebibyte of the ceiling and never waits longer than 25
seconds. Hello stays at one second. Hopper writes the payload it already
measured instead of serializing the same request again.
Co-authored-by: morluto <[email protected]>
* fix(config): bound the bridge request maximum by the serialized string
The ceiling already measures escaped JSON, so dividing Node's string limit by the seven-byte expansion rejected encoded payloads that still fit. The maximum is 536870887, one byte under that string ceiling, leaving room for the framing LF.
Co-authored-by: morluto <[email protected]>
* fix(hopper): serialize a bridge request when it reaches the wire
The queue kept each encoded frame, plus the caller's params, until Hopper finished the active request. A raised ceiling made a few waiting calls enough to exhaust the heap. The FIFO now keeps the params, and the frame is encoded only for the request being written.
Co-authored-by: morluto <[email protected]>
* fix(cutter): hash the bridge proof prefix and payload separately
An exact-limit Cutter frame plus the HMAC prefix exceeds Node's single-string ceiling, so the client threw before sending an admitted command. The prefix and payload are now separate HMAC updates, including the response proof.
Co-authored-by: morluto <[email protected]>
* fix(cutter): keep recovery fields when a status path exceeds the frame
A long current_file made the status reply miss the ceiling, and the fallback then dropped session_id and the completion receipts. The status now omits the path and version and still returns the session, connection proof, and up to 64 receipts. That required recovery frame is smaller than the 7464 floor.
Co-authored-by: morluto <[email protected]>
* fix(cutter): report an unknown path when status identity does not fit
A bounded status kept the new document generation and omitted the path, so the client filled in the descriptor's older path. The observed path is sent when it fits. When it does not, current_file is null and is not replaced with that stale path.
Co-authored-by: morluto <[email protected]>
* fix(cutter): count structured replies by their encoded JSON size
The response guard charged 16 bytes per primitive and two bytes per list slot, so a dense array under the configured ceiling was replaced with output_truncated. Numbers, booleans, null, and container punctuation now use their JSON lengths.
Co-authored-by: morluto <[email protected]>
* fix(cutter): stream authenticated responses in bounded chunks
A fitting reply was signed from retained raw bytes, escaped bytes, and a
joined frame, so a ceiling near 512 MiB could exhaust Cutter before send.
Measure and sign JSON pieces, then write the same frame in 64 KiB chunks.
Co-authored-by: morluto <[email protected]>
* fix(bridge): keep Cutter admission from stalling or hiding sessions
Read an unauthenticated frame off the accept loop. A command reply that
does not fit keeps completion and generation and reports an oversized path
as null. Discovery reports a ceiling mismatch instead of an absent session.
The maximum HMAC proof is opt-in, and both bridges reject non-ASCII digits.
Co-authored-by: morluto <[email protected]>
* fix(cutter): bound frame scans and client response copies
Search only newly read bytes for the framing LF. Unescape each socket
chunk into one response string, check the proof, and then parse it.
Co-authored-by: morluto <[email protected]>
* fix(cutter): keep completion, admission, and dense replies bounded
Report completed_connection only through connections that have
terminated. Cap connection threads and keep the listener up if one
fails to start. Batch scalar JSON and fail discovery when any ceiling
mismatches.
Co-authored-by: morluto <[email protected]>
* fix(cutter): hash requests in parts and scan escapes once
Update the client-proof prefix and request separately. Stop the response
decoder at the first quote or backslash instead of rescanning the tail.
Co-authored-by: morluto <[email protected]>
* fix(cutter): confirm live ceiling mismatches and omitted output
A stale descriptor from a previous ceiling is not a discovery mismatch
until its hello proves a live authenticated bridge. A response discarded
for the frame ceiling after dispatch reports output_truncated.
Co-authored-by: morluto <[email protected]>
* test(cutter): close the unauthenticated ceiling-mismatch fixture
The listener that fails the hello proof is destroyed after its challenge
so discovery cleanup does not wait on that socket.
Co-authored-by: morluto <[email protected]>
---------
Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: morluto <[email protected]>
The registry fixture sent response headers before reading the upstream body,
then always wrote a 500 on error. A body failure hit ERR_HTTP_HEADERS_SENT,
which hid the real error and crashed the verifier with its helper still running.
The fixture now reads the body first, destroys a response that already started,
and the verifier rethrows the first fixture error.
Refs #6038.
🤖 Generated with Claude Code (Sonnet 5.5) 🦊
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
fix(managed): retain types after member limits
Admit type identity and a bounded recovery envelope before member decoding so callers can discover smaller selections after capacity exhaustion.
Fixes#5146
Co-authored-by: eco-null <[email protected]>
Co-authored-by: morluto <[email protected]>
* fix(native): preserve whitespace in otool load-command strings
otool prints dylib install names and rpaths as `<key> %s (offset %u)`
with exactly one separator space around the recorded string. The parser
trimmed the value and stripped the offset suffix with `\s+`, so a valid
install name such as " leading.dylib " became "leading.dylib" in both
the dependency inventory and the raw load-command fields.
Parse these offset-suffixed string fields by their exact format and
strip only the single-space offset suffix.
Fixes#3384
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(native): verify exact Mach-O install names through CLI and MCP
---------
Co-authored-by: Bhaaraadwaj <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
`start_xvfb` treated `--display-number 0` as omitted because it used the
option's truthiness, so an explicit `:0` was replaced by a random display
and its collision check ran against that random display instead.
Select the random display only when the option is absent, and add a
fixture-backed regression test covering explicit zero, an occupied
explicit zero, explicit one, and omission.
Fixes#5189
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fix(scripts): remove the ADB verifier's pushed probe file from the device
The verifier pushed `/data/local/tmp/rea-verify-<timestamp>.txt` for its
transfer roundtrip but never deleted it, so every successful run left a
probe behind while reporting that all checks passed.
After a successful no-overwrite push, the verifier now removes that exact
destination with the provider-reported adb client and confirms its absence
through `list_adb_directory`. Removal runs even when the pull fails, and a
removal failure is reported as a failed check instead of a pass.
`pull_adb_file` still retains device originals.
Fixes#5190
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(scripts): cover ADB probe cleanup after pull failure and leftover probes
Add verifier cases where the pull returns an error or throws after a
successful push, and where `adb shell rm` exits 0 but the listing still
shows the probe. Pull failures must still remove the probe, and a leftover
probe must fail the run.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fix(setup): keep client and skill setup when the Hopper install fails
A failed Hopper package install returned from runSetup before any client
registration or skill install ran, so one optional provider's package
conflict (zlib-ng-compat on Arch and CachyOS) cost every other approved
change. Record the failure instead, apply the remaining plan without a
Hopper launcher, and report needs_human with the install's code and
remediation.
Fixes#5113
* fix(setup): keep the Hopper failure when a client write or the skill install fails too
* fix(setup): keep client and skill setup when the Hopper install fails
A failed Hopper package install returned from runSetup before any client
registration or skill install ran, so one optional provider's package
conflict (zlib-ng-compat on Arch and CachyOS) cost every other approved
change. Record the failure instead, apply the remaining plan without a
Hopper launcher, and report needs_human with the install's code and
remediation.
Fixes#5113
* fix(setup): keep the Hopper failure when a client write or the skill install fails too
---------
Co-authored-by: morluto <[email protected]>
* fix(apple): classify keyed-archive objects by declared superclasses
Interface Builder keyed archives record each object's superclass chain
in `$classes`, but the decoder classified objects by class-name
substrings alone. UINavigationController, UITabBarController and
UISearchController contain "control" but not "viewcontroller", so they
were reported as controls.
Classify keyed-archive objects by UIKit/AppKit view-controller, control
and view bases in their declared chain first, falling back to the name
heuristic only when the chain names none. The decoder now reads
`$classes` through one helper shared with NSArray detection.
Fixes#5218
* test(apple): cover each declared keyed-archive base with neutral class names
Neutral names classify only through the archived superclass chain, so each
UIKit and AppKit base entry and the control-before-view ordering now has a
case that fails without it.
* perf(apple): parse each keyed-archive class chain once
Objects sharing one class descriptor reparsed and scanned its whole
`$classes` array per object, so 20,000 objects sharing a 20,000-name chain
took about 16 seconds to decode. Cache each descriptor's chain as a set by
archive UID; the same archive decodes in about 3.5 seconds, matching main.
---------
Co-authored-by: Kaoru0822 <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Pin admitted script identities and metadata before selected source reads. After the final CDP read, count unique additional retained IDs as dropped script inventory so incomplete captures stay unknown without extending source reads or inventing budget failures. Cover producer and comparison behavior through registered MCP tools.
Co-authored-by: gongfpp <[email protected]>
* feat(firmware): attribute hardware MMIO peripheral memory regions in native disassembly
- introduce hardwareMemoryMap domain model supporting standard ARM Cortex-M, RISC-V, MIPS, x86, and ARM64 physical memory region classifications (Code, SRAM, Peripheral MMIO, System Control Space, External Device)
- distinguish RAM/ROM and address-space segments from MMIO (isolate ARM External RAM / Device and MIPS kseg0/kseg1 uncached mirrors and boot ROM as non-MMIO)
- add hardwarePeripheralAttribution to map analyzed instruction references to hardware peripheral blocks and summarize peripheral register interaction profiles with numerical offset ordering
- expand ReaGhidraBridge.java decoder_context to capture ARM TMode execution register alongside MIPS ISA_MODE for native instruction inspection
- add focused unit and boundary tests across hardwareMemoryMap.test.ts, hardwarePeripheralAttribution.test.ts, GhidraFunctionValues.test.ts, and ghidraCompactReferencesMcp.test.ts verifying region bounds, MMIO isolation, numerical sorting, 32-bit/64-bit overflow rejection, ARM TMode MCP preservation, and bridge contract bindings
- make fake Ghidra installation host platform-aware on Windows in GhidraLanguageOverride.test.ts
* test(ghidra): inspect ARM and Thumb context in the Java bridge
---------
Co-authored-by: morluto <[email protected]>
* fix(hopper): keep macOS and Linux launcher paths POSIX
* fix(hopper): keep Linux and macOS bundle paths POSIX
Linux package archives and macOS app-bundle launcher paths describe the target host, not the host running the test. Build them with path.posix so exercising these installers from Windows produces the same paths as the target platform.
* fix(electron): follow Windows symlink targets with native separators
readlink returns backslash-separated targets on Windows. Splitting only on '/' kept a whole relative target as one component, so nested links were not followed and a relative target could pass the framework-root check without being walked. Split on both separators on Windows and add a regression for an escaping target.
* test(windows): align host-specific path and lifecycle expectations
Compare generated skill and provider-command paths with native joins, bind ADB device-path validation to an explicit platform, and prepare simulated POSIX Ghidra install roots on Windows. Skip POSIX-only Hopper lease, permission-bit, and symlink-parent cases, assert Windows' unsupported Hopper state instead, and cover the Windows Ghidra native-source admission step before snapshot replay. Launch Node child seams with SystemRoot available and expect Windows close-failure resource retention.
* test(windows): close review coverage gaps
---------
Co-authored-by: Kaoru0822 <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
* fix(native): admit universal Mach-O files without a host slice
FAT Mach-O admission selected only the host's slice and rejected a valid
container whose slices are all foreign, so list-architectures returned
target_unavailable instead of the container's inventory. A thin foreign
image was already admitted.
Prefer the host's slice and otherwise select the first declared supported
slice. Remove the Ghidra installation probe's re-parse under other host
architectures, which existed only to work around the rejection.
Fixes#5404
* fix(native): select the first valid foreign FAT slice
Without a host slice, FAT selection took the first declared slice even when
it was too short for its Mach-O header, rejecting a container whose later
foreign slice is valid. The Ghidra decompiler probe then reported such a
foreign-only decompiler as unknown rather than incompatible. Select the first
foreign slice that can hold its header; a malformed host slice still fails.
* fix(native): select foreign FAT slices from every declaration
Foreign-slice fallback chose among architecture families after keeping only
each family's first declaration, so an undersized first arm64 subtype hid a
valid later arm64 subtype. Select from all declarations, and report the
deduplicated families separately. The host-slice rule is unchanged. Move the
FAT selection tests into their own block.
* fix(native): admit only unambiguous foreign FAT families
With no host slice, a family declared more than once, such as arm64 and
arm64e, has no provider-neutral choice: IDA analyzes the recorded slice while
Hopper prefers its own subtype. Select only families declared exactly once and
keep ambiguous foreign-only containers rejected, as on main.
* fix(ghidra): decide FAT decompiler compatibility from validated families
Slice selection now refuses a foreign-only FAT table that declares one family
more than once, such as arm64 and arm64e, and the decompiler probe reported that
refusal as unknown, so an x64 host accepted an arm64-only decompiler. When
selection fails, read the table's validated CPU families and report the
decompiler incompatible when they exclude the host. Selection and host
exclusion now have separate owners in binaryTarget.ts.
Authenticate source bundles through their shared owner and retain workspace lookup facts for evaluation. Preserve source integrity failures and precise caller constraints while allowing unexpected generated-output failures to propagate. Carry the typed closure result through the service and CLI without redundant JSON validation.
Validation: 242 focused tests, source checks, docs conformance, test discovery and duplication gate passed. Six public SDK regressions fail on the baseline. No analysis provider execution is claimed for the coverage workflow.
* fix(native): admit thin arm64_32 Mach-O targets for static inspection
Target admission mapped Mach-O CPU types only to x86, x86_64, arm and
arm64, so a thin arm64_32 object was rejected as "unsupported Mach-O
architecture" before list-architectures, inspect-macho or
inspect-signature could run, although the same slice inside a FAT file
was inventoried.
Recognize CPU_TYPE_ARM64_32 as its own Mach-O-only architecture with a
dedicated thin target variant, so ELF, PE and raw-binary paths cannot
carry it. Add its slice policy so 32-bit dispatch metadata refuses it
like other 32-bit Mach-O images instead of reporting a CPU mismatch.
Ghidra, Hopper and IDA have no verified arm64_32 lane and decline it
explicitly; Hopper's declined families now share one predicate.
Fixes#5713
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* ci(apple): run the thin arm64_32 CLI regression on macOS
The regression compiles an arm64_32 object with Apple clang, so it skips
on the Ubuntu jobs. List it in the macOS Apple artifact job and its
change scope so the job runs it and changes to it select that job.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fix(mcp): report Linux-only integrations as unsupported_host off their hosts
Session discovery folded the host check into each optional integration's
enabled flag, so on macOS or Windows the Linux-only packet, signal,
firmware, pwntools, EVM and Wakaru tools reported provider_missing.
Their execution guards refuse those hosts whatever is configured, so
installing a provider there could never make them available.
The server now records, per integration, when the host is outside its
verified host and no service is injected. Discovery checks that before
configuration and reports unsupported_host with the existing
remediation. Injected services and supported hosts behave as before.
Fixes#5730
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* refactor(mcp): share provider host checks with session discovery
Discovery restated each Linux-only integration's host rule in
createServer while its provider kept a separate execution check, so the
two could drift apart again. Each provider now exports its host
predicate, uses it in its execution guard, and composition hands the
same predicate to createServer for both the host restriction and the
enabled flag.
Observed host restrictions now also apply when an embedder supplies its
own availability policy, as provider load failures already do, because
no policy lets the default providers pass their host checks.
The MCP regression moves to tests/process-global and emulates darwin
arm64, linux arm64 and linux x64 through the real createServer, so CI on
Linux x64 exercises the unsupported-host branch. It also covers a
configured policy and the matching execution refusals.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(mcp): keep caller host restrictions beside observed ones
The observed host restriction replaced a configured policy's whole
hostUnsupported map. For an injected service the observed value is
false, so a caller's own restriction was lost and the tool was reported
available. Combine both per integration: either the caller or the
observed host can mark it unsupported.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(pcap): expect unsupported_host for packet tools off Linux
The host-independent PATH case asserted provider_missing on every host.
Off Linux the packet tools are unavailable because of the host, so
discovery now reports unsupported_host there; Linux still reports
provider_missing for an unusable PATH.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fix(reconstruction): dedupe residual unknown ids with uniqueSorted
Merged obligation candidates called uniqueBy, which is not defined, so
the project did not typecheck. String ids already use uniqueSorted.
Co-authored-by: morluto <[email protected]>
* docs(limits): describe how to design admission recovery
Add a short contributor guide for named defaults, settings, recovery
text, and the agent recovery ladder, and mirror that ladder into the
authored skill.
Co-authored-by: morluto <[email protected]>
* fix(hopper): pass distribution readers into install-host tests
systemLinuxHopperInstallHost now requires the caller's distribution
reader. The Linux install tests still passed only the environment, so
typecheck failed.
Co-authored-by: morluto <[email protected]>
* docs(limits): name the parser doctor shares with startup
Co-authored-by: morluto <[email protected]>
* test: align pcap, storage, and regex fixtures with current contracts
Source and portable CI failed on fixtures that still described the
previous pcap client identity, legacy storage fingerprints, and the
old regex deadline sentence.
Co-authored-by: morluto <[email protected]>
* docs: link repository experiments outside the built site
---------
Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: morluto <[email protected]>
Prevent polling readers from observing truncated readiness JSON in compiler fixtures. Retain deterministic cancellation controls and strengthen the real Swift compiler case to run native identity inspection, verify parent/group facts, and check stable identity across reads.
Validated all 32 Darwin tests with the real host toolchain. A delayed write reproduces the old JSON race; delayed atomic publication passes. No CI timeout or retry changes.
* test: prefer structured assertions over recovery prose
Lock regex, IDA, Hopper/Kuna, MCP budget, capture-heap, and pcap
failures on error codes and reported limits instead of full recovery
sentences.
Co-authored-by: morluto <[email protected]>
* test: keep decoder heap negatives off the Windows reserve
"512 MiB" also appears in the Bun Windows reserve sentence. The
negative check stays on "512 MiB (source setting)", which is the other
adapter's heap.
Co-authored-by: morluto <[email protected]>
* test: keep the one-retry cap and deadline recovery tokens
The lost-connection guidance must say once only, so an unlimited
"whenever it is safe" rewrite fails. Deadline recovery still has to
name set, restart, the floor, and the maximum constant.
Co-authored-by: morluto <[email protected]>
* test: keep heap, MCP, pcap, and preload recovery tokens
Codex still wanted the set/restart/floor/maximum heap guidance, MCP
default/floor/maximum bounds, Wireshark install guidance, and the
dropped-preload attribution limit as separate tokens.
Co-authored-by: morluto <[email protected]>
* test: keep shared-context and transport recovery tokens
Shared-context capture must still exclude requests without a known root
or descendant frame. Shutdown must end the REA process before starting
again, and a failed HTTP listen must offer another port or stopping the
process that holds it.
Co-authored-by: morluto <[email protected]>
* test: keep handoff, input-check, and budget format tokens
Skill and server guidance must still tell the user to restart the MCP
client. Process failures must still say to check the input files. Invalid
MCP phase budgets must still say positive decimal integer and ms.
Co-authored-by: morluto <[email protected]>
* test: bind budget floors and active deadline sources
The phase-budget minimum is the start of "from N to M ms", so a digit
inside the maximum no longer satisfies it. Capability text must contain
the active "N ms (source ...)" pair, not the default number and a heap
source mentioned apart.
Co-authored-by: morluto <[email protected]>
* test: bind heap MiB sources and pcap host tokens
A configured 256 MiB request must appear as "256 MiB (source setting)",
so a byte-sized 256 no longer passes. Unsupported pcap hosts must still
name Linux, util-linux, Windows, and owned Job Objects as separate tokens.
Co-authored-by: morluto <[email protected]>
* test: bind the selected decoder heap to MiB and source
The two-adapter limitation must contain "256 MiB (source setting)".
The exhaustion message binds that capacity as "256 MiB V8 old-generation
heap (source setting)", so a byte-sized 256 no longer passes.
Co-authored-by: morluto <[email protected]>
* test: bind doctor client seconds and prlimit absolute guidance
Doctor recovery must name startup_timeout_sec of the policy's seconds,
so a hardcoded 60 no longer passes while the policy stays 30. A relative
prlimit must say the value must be absolute and tell the user to check
REA_TSHARK_PRLIMIT_COMMAND.
Co-authored-by: morluto <[email protected]>
* test: assert integrity codes for rehashed evidence and coverage
Independently rehashed process Evidence and a tampered digest project
evidence_integrity_mismatch. An unsupported comparison operation stays
invalid_request. Unsupported inventory coverage status is an integrity
failure whose reason carries the coverage.status schema issue.
Co-authored-by: morluto <[email protected]>
---------
Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: morluto <[email protected]>
Resolve raw input at the application boundary and reuse its facts in both MCP admission paths. Keep cleanup, mutation retirement and execution ordering while retaining structured correction details for rejected commands.
Validation: 186 focused tests, source checks, docs conformance and duplication gate passed. The new compiled CLI regression fails on the main baseline. Provider process controls use deterministic fixtures; no real Rizin verification is claimed.
* fix(android): retain snapshot descriptors when close fails
Preserve the stable-file diagnosis or completed copy facts when an APK
or engine snapshot close rejects, and retry that exact owner before
workspace retirement.
Co-authored-by: morluto <[email protected]>
* fix(kuna): retain span descriptors when close fails
Preserve completed span text or the short-read diagnostic when close
rejects, and keep session close incomplete until that handle is released.
Co-authored-by: morluto <[email protected]>
* fix(android): attribute snapshot cleanup to the descriptor that failed
A finished copy can be nested under another descriptor's rejected close.
Walk that chain, keep the snapshot hash on the partial observation, and
name every descriptor that is still open.
Co-authored-by: morluto <[email protected]>
* fix(kuna): gate span admission until a retained close releases
Overlapping requests can pass the entry cleanup check before any lease
exists. Hold each span open through its close so the next open retries
that descriptor instead of admitting another one.
Co-authored-by: morluto <[email protected]>
* fix(android): preserve nested snapshot facts when both closes fail
Walk nested close failures so a finished copy and a changed-APK diagnosis
survive when the source descriptor also rejects close. Attribute cleanup to
each descriptor that failed, and classify a nested close cancellation.
Co-authored-by: morluto <[email protected]>
* fix(kuna): release recovered span leases before the next open
Serialize span admission and close without holding the queue across the byte
read. Recheck the caller signal after that wait, and drop a recovered lease
from the resource scope as well as the span map.
Co-authored-by: morluto <[email protected]>
* fix(android): retain a source descriptor when admission close fails
openRegularFile can reject after the descriptor opens. If that close also
fails, keep the owner on the snapshot cleanup map instead of dropping it
when adoption never runs.
Co-authored-by: morluto <[email protected]>
* fix(kuna): keep cancellation when a completed span close fails
Pass the caller signal into span finalization. If the read already finished
and close then rejects, report cancellation as the primary error and keep
the span text with the retained descriptor.
Co-authored-by: morluto <[email protected]>
* style: format Android and Kuna close-ownership changes
CI format:check rejected the four files touched by the close-ownership fixes.
Co-authored-by: morluto <[email protected]>
* fix(android): keep the snapshot hash inside a nested cancellation
A destination close that succeeds after abort throws RegularFileCancelled
with the finished copy. When the source close then rejects, recover that
copy so cancellation keeps the digest and file-snapshot-hash observation.
Co-authored-by: morluto <[email protected]>
* fix(android): keep the snapshot hash on a direct close cancellation
A finished copy whose descriptor closes successfully after abort is a
top-level RegularFileCancelled. Attach its digest and file-snapshot-hash
observation to that cancellation.
Co-authored-by: morluto <[email protected]>
* fix(kuna): preserve the caller abort reason after a successful span close
A completed read whose close then succeeds throws a cancellation wrapper.
Return AnalysisCancelledError with the caller's abort reason instead of
that wrapper.
Co-authored-by: morluto <[email protected]>
---------
Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: morluto <[email protected]>
Parse caller selections and authenticated Evidence at their owners, reuse the parsed function and comparison facts, and preserve unexpected implementation failures. Remove downstream error guessing and redundant validation wrappers.
Verify with 526 affected tests, source checks, docs conformance, test discovery and duplication checks. Seven public SDK regressions fail on the main baseline. No real-provider execution was performed.
fix: repair main after bulk merge
Restore typecheck after #3826 called uniqueBy, and align the red fixtures
with the merged pcap, browser, IDA, and Hopper contracts.
Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: morluto <[email protected]>
* fix(setup): offer Hopper installation only where setup can install it
On a host where automated Hopper installation is ineligible (Windows,
macOS below 12 or with an unknown version, or an unsupported or
unidentified Linux distribution), an unhealthy setup without a Hopper
launcher ended by advising "Rerun with --yes --install-hopper", and the
same run then refused that request. The eligibility rule existed twice
(the discovery proposal and the explicit-install gate, with separate macOS
parsers that disagreed on malformed versions), and the final advice
consulted neither.
Make setup discovery the single owner of Hopper install eligibility. The
explicit gate refuses with the unchanged copy through hopperInstallRefusal,
and the final advice offers --install-hopper only where the host is
eligible; ineligible hosts fall back to doctor remediation. hostRemediation
now checks only the Node.js runtime. An empty or unparseable macOS version
is now refused by the explicit gate instead of installing.
Fixes#3944
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* chore: drop merge-only formatter changes
* test: align inherited fixtures with current analysis contracts
* test(ida): assert search recovery instead of diagnostic prose
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
2026-10-23 03:17:34 +08:00
4551 changed files with 571003 additions and 287600 deletions
description:Reverse engineer native, managed, Electron/JavaScript, packaged, firmware, and browser targets with REA. Use shipped-artifact or requested runtime evidence to explain features, compare versions, decompile code, or guide a reconstruction. Skip REA for ordinary source-repository architecture analysis.
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. 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:"45"
version:"53"
---
# REA
Use REA when a claim depends on a shipped binary or package, decompilation,
passive application runtime evidence, or comparison with
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.
@@ -17,6 +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.
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
@@ -37,42 +40,23 @@ 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. Run `rea doctor` when REA could not start
or tools stay missing after that restart. Read the recovery guide before a
second repair attempt.
returns the same unchanged result. For plugin installs, follow
| No REA tools in the active session | Inspect registration with `rea doctor --client codex --json`. A skill installation alone does not register MCP. |
| 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. |
| 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,
@@ -81,6 +85,63 @@ 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`: 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.
-`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:
- 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.
- 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.
- 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:
@@ -93,9 +154,12 @@ rea setup --client codex --dry-run --json
Use the current supported client's ID: `claude_code`, `claude_desktop`, `codex`,
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
@@ -250,36 +323,61 @@ 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 `result.tool_availability` carries a
complete inventory grouped by shared facts. Expand each group's`names` and
inherit the inventory-level client requirements unless a group overrides them;
availability, reasons, remediation, modes, and flags remain inline. The
`effects` and `annotations` 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, 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 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 describe possible
providers. Top-level session capabilities describe the current route, and
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.
## 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/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.
Preserve useful Evidence before closing the session or restarting REA. Check
`close_binary` and resolve reported cleanup failures. Set a larger startup budget
in the environment that launches REA, then restart REA and reconnect the MCP
client before reopening the same target. Closing and reopening a binary in the
existing server keeps its original configuration and starts import again.
Environment changes in an agent's shell do not update an already running MCP
server. If its launch configuration cannot be changed, report that constraint
and the exact retry setting instead of claiming a fixed technical limit.
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. A new attempt repeats import. 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
@@ -296,6 +394,50 @@ Exported C and embedded resources remain useful independent evidence, but a
timeout does not establish complete analysis or absence of code. See the
[deadline and client guide](https://github.com/morluto/rea/blob/main/docs/mcp-contracts.md#ghidra-first-query-deadlines-and-recovery).
## 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. 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
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
@@ -323,6 +465,14 @@ 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
@@ -453,6 +603,7 @@ discovery are unsupported. Windows Ghidra P0 admits raw images only for `6502`.
### 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 and session-scoped; empty comments clear them, omitted fields preserve them. Later MCP calls observe edits until close. CLI `annotate-native-function` returns the updated analysis before discarding the session. 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.
## Offline PE resource inventory
@@ -501,3 +652,20 @@ 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
| 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.
Detailed contracts and prerequisites: [Frida](https://github.com/morluto/rea/blob/main/docs/frida-instrumentation.md),
@@ -22,6 +22,8 @@ Keep proof of ownership separate from validity, editability, and readiness. Malf
For lifecycle changes, follow [ownership and completion invariants](docs/tool-design.md#own-the-lifecycle) and select the applicable [lifecycle regressions](docs/testing.md#lifecycle-regressions). Include late handshakes, cancellation during final cleanup, mixed child outcomes, and cleanup retry where those stages exist; active-execution cancellation alone does not cover finalization.
Before adding complexity for a speculative or vanishingly unlikely race or security edge case, explain the concrete failure mode, likelihood, and complexity cost to the user and get their buy-in. Do not silently expand scope for theoretical robustness.
Assess brittleness in touched code during implementation, debugging, review, and maintenance. Fix the producing representation or ownership rule before adding downstream repairs. Normalize once at the owning boundary using format-aware parsers. Remove superseded representations, aliases, wrappers, and redundant tests after verifying affected consumers. Introduce abstractions only when they remove observed complexity.
When fixing a bug, inspect the producing boundary and affected consumers for duplicated interpretation or unclear ownership. Complete any directly related refactor in the same change and remove superseded code. Passing regression tests alone does not establish that the brittleness is resolved. If related cleanup remains, explain what remains and why.
@@ -51,9 +53,12 @@ Optimize in this order:
3. CPU and memory. Avoid unnecessary work and copies; bound concurrency,
retained state and serialization growth.
For changes affecting these costs, measure representative completed tasks and
compare equivalent workflows before and after where available. Report token
usage, elapsed time, CPU time and peak process-family memory. Separate cold
Reserve performance measurements for changes that target performance or have a
to helper calls, imports, or representations alone do not require synthetic
benchmarks. When measurement is warranted, measure representative completed
tasks and compare equivalent workflows before and after where available. Report
token usage, elapsed time, CPU time and peak process-family memory. Separate cold
and warm runs, label estimates, and state unmeasured costs. Fewer bytes alone
do not establish fewer tokens or faster analysis.
@@ -70,13 +75,15 @@ Use [.nvmrc](.nvmrc) and `package.json#packageManager` for the pinned toolchain.
Use relevant checks for the change. The complete local gate, `npm run check:pr`, is optional for broad changes or CI diagnosis. See [CONTRIBUTING.md](CONTRIBUTING.md) for development, generated-file ownership, and release conventions.
Coordinate expensive checks across agents. If a test unexpectedly consumes heavy CPU, stop its owned process family and profile a bounded representative case before retrying. Inspect production work, fixture generation, subprocesses, and repeated setup; preserve regression coverage when optimizing. Follow the [test resource guidance](docs/testing.md#developer-commands).
`docs/public/product-catalog.json`, `docs/verification/managed-conformance-*.json`, and `skills/` are ignored outputs. Edit source contracts and `.agents/skills/reverse-engineer-anything/`, then regenerate as needed. `.cache/mcp-tool-catalog.json` is test metadata; runtime builds and source checking do not consume it. Never commit binaries, provider project documents, credentials, `dist/`, `node_modules/`, or local planning artifacts.
## Tool and Test Changes
For tool design, follow [docs/tool-design.md](docs/tool-design.md): start from the analyst question, reuse existing contracts, preserve caller choices, and return useful evidence inline. Limits must follow real format, protocol, authority, or resource constraints. Account for representation expansion before allocation; derive completeness from examined coverage.
For test changes or provider claims, use [docs/testing.md](docs/testing.md). Prefer real public CLI/MCP workflows, then production-boundary integration, then producer goldens. Keep module tests for distinct semantics stronger workflows cannot reliably reproduce. Preserve malformed-input, cancellation, cleanup, permission, capacity, and target-identity coverage when pruning. Report unverified coverage explicitly; simulated providers do not establish real-provider behavior.
For test changes or provider claims, use [docs/testing.md](docs/testing.md). Select applicable [boundary regressions](docs/testing.md#boundary-regressions) for parser, inventory, snapshot, and projection fixes. Prefer real public CLI/MCP workflows, then production-boundary integration, then producer goldens. Keep module tests for distinct semantics stronger workflows cannot reliably reproduce. Preserve malformed-input, cancellation, cleanup, permission, capacity, and target-identity coverage when pruning. Report unverified coverage explicitly; simulated providers do not establish real-provider behavior.
Use Conventional Commit subjects and PR titles. Mark breaking changes with `!` or a `BREAKING CHANGE:` footer. Describe behavior changes, relevant validation, and real-provider verification scope.
- Build local agent environments from network captures, browser scenarios, or a prompt, then serve derived reads and evidence-gated writes and compare them with fresh application captures.
- Inspect more shipped formats, including GPU code objects, BEAM, Python bytecode, Unity IL2CPP metadata, Godot PCK, PyInstaller, Node.js SEA, devicetree, and additional PE/ELF tables.
- Keep large investigations focused with retained summaries, selected fact queries, configurable recovery limits, and row-oriented CLI exports. Complete Evidence remains available.
### ⚠ BREAKING CHANGES
- **Function analysis:**`analyze_function` now defaults to a retained summary. Set `detail: "complete"` for the previous inline dossier; the CLI retains its complete default and requires `--evidence_output` when selecting a summary. [#5660](https://github.com/morluto/rea/pull/5660). Thanks @CryptoJones, @gensokyo-dev, @RishTheFish21.
- **Accessibility:** Accept JSON numbers and booleans in node `value`, alongside strings and null. Update consumers that previously assumed text-only values. [cc90771](https://github.com/morluto/rea/commit/cc90771af14f045538651615147d8bf86b576549), [#6759](https://github.com/morluto/rea/pull/6759), [#6467](https://github.com/morluto/rea/issues/6467). Thanks @coygeek, @gensokyo-dev, @mvanhorn.
- **JSON Lines:**`--format jsonl` now emits object-collection rows followed by a `$rea: "jsonl/v1"`, `type: "metadata"` record; scalar selections and unsupported reports are refused. Parse control records separately, select a single supported collection when necessary, and use `--format json` for the previous whole-document output. See [JSON Lines framing](https://github.com/morluto/rea/blob/rea-agents-6.8.0/docs/cli.md#json-lines-record-output). [#5629](https://github.com/morluto/rea/pull/5629), [#5487](https://github.com/morluto/rea/issues/5487). Thanks @gensokyo-dev, @jayykernel, @vijaykiran06.
- **Interface Builder:** Keyed-archive graph identities use decimal table UIDs instead of authored `objectID`/`object-id`. Treat authored IDs as attributes and update persisted graph lookups; ibtool and native NIBArchive identities keep their source semantics. [6fbe67d](https://github.com/morluto/rea/commit/6fbe67d66e3d716db69929503a3a232a7ada0860).
- **Frida:**`instrument-with-frida` JSON returns the canonical Evidence directly. Read `normalized_result.cleanup_error` instead of the former top-level wrapper field. [48f700e](https://github.com/morluto/rea/commit/48f700ee35e0988ed973e5486dc9db33f2a5d944).
- **Reconstruction proof:** ID-array proof records no longer establish verified or ready ledgers. Supply implementation/revision bindings and individual claim outcomes; handle inapplicable, unavailable, and failed proof diagnostics. [f8b65e7](https://github.com/morluto/rea/commit/f8b65e78723b1e2169f94dd1226198ea3139707e).
- **Mach-O imports:** Handle a null import `name` when identity is ambiguous; use `raw_name` and `name_status` to distinguish observed expressions from exact symbols. [5d0d243](https://github.com/morluto/rea/commit/5d0d243a45c9132e1aff75d454ab53d86a74cc31), [169512a](https://github.com/morluto/rea/commit/169512a35bb015ff209168fb8bc1c9b31a2c678b).
- **Node.js:** Use a runtime satisfying `^22.23.4 || ^24.22.1 || >=26.12.1`; Node 23 and 25 are unsupported. Upgrade Node before installing or updating REA; the installer does not upgrade it. [#6315](https://github.com/morluto/rea/pull/6315), [#6283](https://github.com/morluto/rea/issues/6283). Thanks @GamerDubz, @gensokyo-dev, @ShikamaruNaaraa.
- **Browser storage:** Historical hashed storage remains readable, but comparisons stay unknown until both captures are recaptured in the new representation. [#6341](https://github.com/morluto/rea/pull/6341), [#6289](https://github.com/morluto/rea/issues/6289). Thanks @coygeek, @gongfpp.
- **Environment serving:**`environment-serve` serves derived state by default, including write tools whose effects are confirmed by recorded evidence. Use `--replay-only` for stateless replay of manifest tools. Read stop-summary `state` instead of `state_evidence_id`. [#5351](https://github.com/morluto/rea/pull/5351), [#6158](https://github.com/morluto/rea/pull/6158). Thanks @earakely-scale, @gensokyo-dev, @kaoru0822-kitauji.
- **MCP schemas:** Input advertisements default to compact. Set `REA_MCP_INPUT_SCHEMA_PROFILE=full` for complete advertised guidance and nested constraints. [#5975](https://github.com/morluto/rea/pull/5975). Thanks @gensokyo-dev.
- **Browser console arguments:** Accept null `argument_types` and `text_capture.status: "unavailable"` when the protocol argument inventory is omitted or malformed; preserve that uncertainty. [#6016](https://github.com/morluto/rea/pull/6016), [#5934](https://github.com/morluto/rea/issues/5934). Thanks @coygeek, @kaoru0822-kitauji.
- **Reconstruction summaries:**`summary.by_evidence_authority` is keyed by Evidence authority; read the former source-state counts from required `summary.by_source_state`. Regenerate ledgers whose closure digests depended on the old projection. [#5875](https://github.com/morluto/rea/pull/5875), [#5838](https://github.com/morluto/rea/issues/5838). Thanks @coygeek, @kaoru0822-kitauji.
- **Swift bindings:** Conformance `type_name` and `protocol_name` may be null; consume typed `type_binding`/`protocol_binding` evidence. Replace the former Objective-C-specific import-binding type/schema with `MachoImportBinding`. [d0067ba](https://github.com/morluto/rea/commit/d0067ba34a39ea47dd7e11bb2e6169bc0938cc3f).
- **WebSocket frames:** Accept null opcodes and preserve unknown frame facts; numeric opcodes are restricted to the four-bit protocol range. [0bc2b42](https://github.com/morluto/rea/commit/0bc2b42001f684beffcf47b70e507443b1a5d320).
- **Resource-only inspection:** Evidence subjects and executable digests may be null. Use `resource_root` and each resource's reported provenance instead of requiring an executable target. [6a6adf7](https://github.com/morluto/rea/commit/6a6adf703fa44100643947d20fbc670f86260b1b).
- **Browser timestamps:** Console and session-timeline timestamps may be null when the protocol supplies no finite/comparable time. Keep unknown time explicit in sorting and comparisons. [690fc51](https://github.com/morluto/rea/commit/690fc518540bae982038a74f47ef7781201785aa), [2a0410f](https://github.com/morluto/rea/commit/2a0410f1717b3126e8a95063d77dea66a597010a).
- **Reference sources:** Read failed root enumeration from `rootFailure` rather than a synthetic failed child at `"."`; preserve the top-level source-graph limitation. [6296fdf](https://github.com/morluto/rea/commit/6296fdf560f1ac4aa55985558edaa98300aacdbc).
- **Filesystem capture:** Accept `entry_unavailable` and `identity_changed` enumeration omission reasons in addition to the previous reason literals. [c85b44e](https://github.com/morluto/rea/commit/c85b44e1b14851c54e65327a4807f79ad5cd5a61). Thanks @rudrakshagarwal4200-ai.
- **APK locales:** Replace numeric legacy selectors such as `es-r419` with `es-419` or `b+es+419`. Two-letter regions remain supported. [29910d1](https://github.com/morluto/rea/commit/29910d16b98fe4b607a7aa15928789a73614b0b9). Thanks @mertkayacs.
- **XML plist scalars:** Recognize `$plist_type: "unknown"` and read `element`, `literal`, and `reason`; unresolved XML scalars use this wrapper instead of the former real/null unknown marker or malformed scalar prefixes. Supported extended UTC years preserve their timestamp. [3537e58](https://github.com/morluto/rea/commit/3537e58c1ab29309f06eabf50bc52adba9817a0c).
### Changes
- **Binary layouts:** Inspect ELF32 i386, little-endian ARM, and little- or big-endian MIPS `EXEC`/`DYN`/`REL` layouts on Linux x64 using a caller-supplied pwntools environment. [#7052](https://github.com/morluto/rea/pull/7052), [#6934](https://github.com/morluto/rea/issues/6934). Thanks @roblennon, @salmanalmutairi1.
- **Agent environments:** Project network captures and Evidence files into manifests, preserve template path pairs and positions, export AgentEnv bundles, and serve manifests as replay environments. [#4954](https://github.com/morluto/rea/pull/4954), [#5293](https://github.com/morluto/rea/pull/5293), [#5664](https://github.com/morluto/rea/pull/5664), [#4999](https://github.com/morluto/rea/pull/4999), [#4975](https://github.com/morluto/rea/pull/4975). Thanks @earakely-scale, @gensokyo-dev, @kaoru0822-kitauji.
- **Capture to environment:** Build environments from browser scenarios or a prompt, extract the initial observed state, and compare the environment with application probe captures. [#5182](https://github.com/morluto/rea/pull/5182), [#6946](https://github.com/morluto/rea/pull/6946), [#5319](https://github.com/morluto/rea/pull/5319), [#5699](https://github.com/morluto/rea/pull/5699). Thanks @earakely-scale, @gensokyo-dev, @kaoru0822-kitauji.
- **State-backed tools:** Render read filters, search, sorting and paging from state; apply confirmed write effects with broader state targets and recording-based write admission. [#5352](https://github.com/morluto/rea/pull/5352), [293832b](https://github.com/morluto/rea/commit/293832bafc9a054914ec514fe906dd4936c7a372), [#5800](https://github.com/morluto/rea/pull/5800), [#5787](https://github.com/morluto/rea/pull/5787), [#5600](https://github.com/morluto/rea/pull/5600), [5375ff0](https://github.com/morluto/rea/commit/5375ff0f9aadb4fd0d46333815aa0431e3df1010), [#6169](https://github.com/morluto/rea/pull/6169), [#6385](https://github.com/morluto/rea/pull/6385), [#6897](https://github.com/morluto/rea/pull/6897). Thanks @earakely-scale, @gensokyo-dev, @kaoru0822-kitauji.
- **State learning:** Model application-assigned values, preserve view-specific clock spellings, learn write clocks from scenario timing, derive fields, and learn creates across sorted arrays and referenced entities. [7ec9b6e](https://github.com/morluto/rea/commit/7ec9b6e56e1b3762285dca881db6d900a389ab9c), [#6136](https://github.com/morluto/rea/pull/6136), [957bcfa](https://github.com/morluto/rea/commit/957bcfa149c1a0593bb0aa2466cc56d1d4f62e7d), [#6138](https://github.com/morluto/rea/pull/6138), [#6967](https://github.com/morluto/rea/pull/6967), [#7025](https://github.com/morluto/rea/pull/7025), [#7034](https://github.com/morluto/rea/pull/7034). Thanks @earakely-scale.
- **Recorded writes:** Serve creates whose compatible read-backs add omitted fields or express timestamps at a different precision, and whole-object updates that regenerate observed slugs or modification times. Conflicting observations still withhold writes. State views and bundles carrying the new read-back data need REA 6.8.0 or later to serve. [#7080](https://github.com/morluto/rea/pull/7080). Thanks @earakely-scale.
- **Native investigations:** Page native inventory summaries, match functions across builds, export pseudocode to resumable directories, and select objdump disassembly by symbol. [#5378](https://github.com/morluto/rea/pull/5378), [#5390](https://github.com/morluto/rea/pull/5390), [#6170](https://github.com/morluto/rea/pull/6170), [#5171](https://github.com/morluto/rea/pull/5171), [#4249](https://github.com/morluto/rea/issues/4249), [#5343](https://github.com/morluto/rea/issues/5343), [#5159](https://github.com/morluto/rea/issues/5159). Thanks @coygeek, @CryptoJones, @gensokyo-dev, @kaoru0822-kitauji.
- **Engine workflows:** Bound a single Ghidra decompilation without closing its session, analyze GameCube/Wii DOL executables, and inspect static CUDA/HIP code objects. [#5662](https://github.com/morluto/rea/pull/5662), [#6240](https://github.com/morluto/rea/pull/6240), [#5813](https://github.com/morluto/rea/pull/5813), [#5340](https://github.com/morluto/rea/issues/5340), [#5345](https://github.com/morluto/rea/issues/5345). Thanks @arielfikru, @coygeek, @gensokyo-dev, @RishTheFish21.
- **PE/ELF:** Inspect export tables without an engine, PE imports/delay-loads, Authenticode certificates, TLS callbacks/load configuration, ELF notes, Linux kernel module metadata, and Zstandard section-name tables. [#6278](https://github.com/morluto/rea/pull/6278), [#6509](https://github.com/morluto/rea/pull/6509), [#4830](https://github.com/morluto/rea/pull/4830), [#7008](https://github.com/morluto/rea/pull/7008), [#4837](https://github.com/morluto/rea/pull/4837), [#7010](https://github.com/morluto/rea/pull/7010), [#6987](https://github.com/morluto/rea/pull/6987), [#4057](https://github.com/morluto/rea/issues/4057). Thanks @gensokyo-dev, @kaoru0822-kitauji, @mvanhorn, @Rinkia, @ShuaixinHuang.
- **APK output:** Set `string_tables_only` or CLI `--string-tables-only` to omit duplicate primary strings and avoid their output-capacity charge. [7c458f0](https://github.com/morluto/rea/commit/7c458f04b9155707c8ba406f8b455b10016f1b99), [#4990](https://github.com/morluto/rea/pull/4990), [#4982](https://github.com/morluto/rea/issues/4982). Thanks @gensokyo-dev, @kaoru0822-kitauji, @N0zoM1z0.
- **Retained analysis:** Reuse successful validation of authenticated immutable native/imported-JavaScript parents and captures. Query retained Go build identity, Rust dependencies, JavaScript source-to-bundle mappings, and native export facts without repeating full output. [8f7d12e](https://github.com/morluto/rea/commit/8f7d12e30d63f3d3b4cfe2a90336362841438f56), [#4962](https://github.com/morluto/rea/pull/4962), [#5349](https://github.com/morluto/rea/pull/5349), [#5524](https://github.com/morluto/rea/pull/5524), [#5815](https://github.com/morluto/rea/pull/5815), [#6128](https://github.com/morluto/rea/pull/6128), [#6907](https://github.com/morluto/rea/pull/6907), [#4810](https://github.com/morluto/rea/issues/4810), [#5499](https://github.com/morluto/rea/issues/5499), [#5802](https://github.com/morluto/rea/issues/5802), [#6112](https://github.com/morluto/rea/issues/6112), [#6900](https://github.com/morluto/rea/issues/6900). Thanks @gensokyo-dev, @kaoru0822-kitauji, @N0zoM1z0.
- **Compact results:** Use retained Frida/GDB/objdump summaries, omit redundant Ghidra raw results, and defer the analysis runtime during MCP catalog discovery. [#5661](https://github.com/morluto/rea/pull/5661), [#5614](https://github.com/morluto/rea/pull/5614), [#5355](https://github.com/morluto/rea/pull/5355), [#4424](https://github.com/morluto/rea/pull/4424), [#5640](https://github.com/morluto/rea/issues/5640), [#5584](https://github.com/morluto/rea/issues/5584), [#5337](https://github.com/morluto/rea/issues/5337). Thanks @coygeek, @gensokyo-dev, @kaoru0822-kitauji, @leeguooooo.
- **Analysis work:** Reuse Hopper literal-string records, JavaScript workers and captured prefix selections, Interface Builder validation and plist scalar schemas; bound stable reads to one snapshot buffer and avoid decoding omitted GGUF strings. [#5017](https://github.com/morluto/rea/pull/5017), [#5819](https://github.com/morluto/rea/pull/5819), [31de177](https://github.com/morluto/rea/commit/31de177404461d122761d8243abe4fd24564f4da), [#5885](https://github.com/morluto/rea/pull/5885), [85e38ac](https://github.com/morluto/rea/commit/85e38ac199dff15e8c43343d9170db7e0e46d284), [#6966](https://github.com/morluto/rea/pull/6966), [#5781](https://github.com/morluto/rea/pull/5781), [#5010](https://github.com/morluto/rea/issues/5010), [#5855](https://github.com/morluto/rea/issues/5855), [#6954](https://github.com/morluto/rea/issues/6954), [#5774](https://github.com/morluto/rea/issues/5774). Thanks @gensokyo-dev, @kaoru0822-kitauji.
- **Native scheduling:** Batch modern IDA callee lookups, schedule decompilation reads on demand, index NativeAOT type closure, and retain call-path ancestry once per visited node. [0c6fed9](https://github.com/morluto/rea/commit/0c6fed90b74c75a9fd23d1ec1b510a7274f85887), [06fe7ee](https://github.com/morluto/rea/commit/06fe7eecbc8c387414b4c1aa0d88ad6314f54f0c), [ce61680](https://github.com/morluto/rea/commit/ce61680c04c95a9cdfad5335632a99542af26d37), [5e4ec0f](https://github.com/morluto/rea/commit/5e4ec0fa1b678aa3bf20704ec9110224ba8c1676).
- **Selected processing:** Prepare CLI positional schemas only for the selected command, separate entropy reads from report resolution, prune typed-array reference escapes, index state-write cutoffs, decode only selected replay query values, and skip payload text during WAT framing. [315b234](https://github.com/morluto/rea/commit/315b23403f0819967878cee418c3f9cb4b1a69d9), [#6950](https://github.com/morluto/rea/pull/6950), [#5139](https://github.com/morluto/rea/pull/5139), [#5350](https://github.com/morluto/rea/pull/5350), [96ea32b](https://github.com/morluto/rea/commit/96ea32b7e4e28d3c9cd79a1de4b8e1ba3b4244e9), [70835d3](https://github.com/morluto/rea/commit/70835d3d5f030deadf606e1c79c70a60883e50c9), [#5766](https://github.com/morluto/rea/pull/5766), [#6947](https://github.com/morluto/rea/issues/6947), [#5760](https://github.com/morluto/rea/issues/5760). Thanks @galleonli, @gensokyo-dev, @kaoru0822-kitauji.
### Fixes
- **IPS report fields:** Preserve the recorded terminating process and PID, termination flags, parent PID, and build/platform metadata. [#7079](https://github.com/morluto/rea/pull/7079), [#7078](https://github.com/morluto/rea/issues/7078). Thanks @rodricksz4h5.
- **Ghidra language selection:** Accept stock language IDs containing `LEBE` or slash-separated processor names, and report conflicting DOL language overrides as configuration errors naming `REA_GHIDRA_LANGUAGE_ID`. [#7070](https://github.com/morluto/rea/pull/7070), [#7072](https://github.com/morluto/rea/issues/7072), [#7081](https://github.com/morluto/rea/pull/7081), [#7082](https://github.com/morluto/rea/issues/7082). Thanks @Adolanium.
- **Setup and Hopper:** Preserve the Linux embedding runtime, supported x86_64 host restriction, readiness-based provider choices, orderly demo-helper shutdown, and installed apt dependency versions. Keep cleanup and skill publication ownership through retries. [#5041](https://github.com/morluto/rea/pull/5041), [#3422](https://github.com/morluto/rea/pull/3422), [f5d1012](https://github.com/morluto/rea/commit/f5d1012fabfe99af82523c3078ce9d93eb3780c1), [#4966](https://github.com/morluto/rea/pull/4966), [#6974](https://github.com/morluto/rea/pull/6974), [211e353](https://github.com/morluto/rea/commit/211e3533b34f81ae0910ad4f53f2a3d3c8587d3e), [#6920](https://github.com/morluto/rea/pull/6920), [#5015](https://github.com/morluto/rea/issues/5015), [#3419](https://github.com/morluto/rea/issues/3419), [#4921](https://github.com/morluto/rea/issues/4921), [#6975](https://github.com/morluto/rea/issues/6975). Thanks @Abel-I-Akhigbe, @Adolanium, @DavidFB-creator, @DeryFerd, @gensokyo-dev, @kaoru0822-kitauji, @sx4im.
- **Client setup:** Treat empty APPDATA as unset, distinguish MSIX Claude Desktop process views, preserve aliased Hermes server tables, reuse client dialect/alias bindings, and materialize the pinned package-runner cache before the first start. [#5126](https://github.com/morluto/rea/pull/5126), [#4903](https://github.com/morluto/rea/pull/4903), [#3785](https://github.com/morluto/rea/pull/3785), [b7eeded](https://github.com/morluto/rea/commit/b7eededf5af5061a834f93f57f2c888acf870344), [#7032](https://github.com/morluto/rea/pull/7032), [#5104](https://github.com/morluto/rea/issues/5104), [#4278](https://github.com/morluto/rea/issues/4278), [#3320](https://github.com/morluto/rea/issues/3320), [#7027](https://github.com/morluto/rea/issues/7027). Thanks @CmsChase, @coygeek, @myso-kr, @pablodiazjorge, @vaidehi-snk, @wxj006007.
- **Target admission:** Preserve thin arm64_32 Mach-O support, distinguish JVM identity before FAT admission, validate FAT format/CPU identity, preserve original DOS header padding, and reject NULs in local objdump/rizin paths. [#5788](https://github.com/morluto/rea/pull/5788), [6843dbe](https://github.com/morluto/rea/commit/6843dbea9bce4709ee2e8bf46c38f0bbf640716b), [497037e](https://github.com/morluto/rea/commit/497037e6e3975cbb37cfd89ea0ad300faa2a4769), [#7013](https://github.com/morluto/rea/pull/7013), [#3600](https://github.com/morluto/rea/pull/3600), [#5713](https://github.com/morluto/rea/issues/5713), [#6510](https://github.com/morluto/rea/issues/6510). Thanks @coygeek, @dhruvac29, @kaoru0822-kitauji, @Lew1sWong, @qorvr.
- **Mach-O and dylibs:** Preserve container framing, facts when dyld rejects a missing UUID, verified-signature snapshot identity, unsigned diagnostics, absolute paths inside the selected root, legacy platform rules, lazy-load payloads, and reasons for rejecting present dylibs. [cf3288d](https://github.com/morluto/rea/commit/cf3288d8cf7a09685acf89103b36c32359be56fa), [2b263a7](https://github.com/morluto/rea/commit/2b263a7fe9e9d4c185c7d6af6b4e67b21a73af30), [eb7acc7](https://github.com/morluto/rea/commit/eb7acc70bf06f119e8639e30a78081d5ba82b0bf), [1502cfb](https://github.com/morluto/rea/commit/1502cfbc8ca0d1d1d86eebf334018dfb418bbac0), [90062c0](https://github.com/morluto/rea/commit/90062c092228dea9d33fadc0d7e1b968105b8b2c), [#5650](https://github.com/morluto/rea/pull/5650), [3b67b36](https://github.com/morluto/rea/commit/3b67b362aa2cd79eac5af57d0965e81a7d0b8c2b), [#5551](https://github.com/morluto/rea/issues/5551). Thanks @coygeek.
- **Native facts:** Admit direct dispatch-metadata providers; preserve record-local Objective-C omissions, snapshot profiles, class-import binding identity, stripped class labels, version-like names, and qualified Swift protocol identities. [50b6975](https://github.com/morluto/rea/commit/50b6975d861069e2c6cfa202780621449f863802), [9eec57b](https://github.com/morluto/rea/commit/9eec57b469087fe9bff3d29dcc02f47074159e91), [0ba4d6f](https://github.com/morluto/rea/commit/0ba4d6f43ad610dacc861a1548be1a5c4712cd61), [4d7de00](https://github.com/morluto/rea/commit/4d7de00d4cc9a95ec2b7a3123b04e01db2daafa0), [22c84ce](https://github.com/morluto/rea/commit/22c84ce64aa6c7601aa81af86d4117b5a4c2feac), [4852c83](https://github.com/morluto/rea/commit/4852c830af1e3b9df437235b7a8fa8970a6d1c59), [aa9043f](https://github.com/morluto/rea/commit/aa9043f6b61c453e4735795cfe6a559bf6b6cc16).
- **Archives and files:** Complete positional ZIP reads, preserve bounded ASAR signatures, report stable symlink loops as resolution failures, retain target applicability, and report unknown traversal coverage. Retain reported integrity contradictions for members present in only one compared artifact. [#4414](https://github.com/morluto/rea/pull/4414), [e8da7e1](https://github.com/morluto/rea/commit/e8da7e1edd075feec0e6beedec93d5645fed8125), [#5571](https://github.com/morluto/rea/pull/5571), [#5763](https://github.com/morluto/rea/pull/5763), [#5867](https://github.com/morluto/rea/pull/5867), [#5521](https://github.com/morluto/rea/issues/5521), [#5731](https://github.com/morluto/rea/issues/5731), [#5837](https://github.com/morluto/rea/issues/5837), [#7076](https://github.com/morluto/rea/pull/7076). Thanks @Afloat16, @coygeek, @jdotc1, @kaoru0822-kitauji, @WenyuChiou.
- **Extraction and file ownership:** Restrict destination-case recovery to owned collisions, retain physical-read failures through late cancellation/cleanup, preserve cleanup capabilities for retry, and retain independent firmware extraction failures. [932fbb7](https://github.com/morluto/rea/commit/932fbb7d84a9a995b9aee3c1be7da05a8c4d7bbb), [9499667](https://github.com/morluto/rea/commit/949966712e68d8857a50a165ecddf04c2d7e6d3b), [56679dd](https://github.com/morluto/rea/commit/56679dd2ae31dda58e181f8bf99775014f7bb82b), [b3c912a](https://github.com/morluto/rea/commit/b3c912ab79ad147a37b6cfbe1552a1a5eecec629), [7298bd0](https://github.com/morluto/rea/commit/7298bd08d134860b84b4073f6703021916a5a4c5).
- **Processes and cancellation:** Retain partial samples and shutdown gaps, unresolved descendants and caller abort reasons; bind cleanup errors to their owners, propagate comparison contradictions, and report no normal exit code for signalled targets. [ba866a2](https://github.com/morluto/rea/commit/ba866a26ecbe179a717e746cbc0d1605ae616ad5), [#5270](https://github.com/morluto/rea/pull/5270), [#6144](https://github.com/morluto/rea/pull/6144), [a721c42](https://github.com/morluto/rea/commit/a721c42c07dc674c32ab939627355b8a1bee97a5), [#6298](https://github.com/morluto/rea/pull/6298), [#6486](https://github.com/morluto/rea/pull/6486), [#5935](https://github.com/morluto/rea/issues/5935), [#5944](https://github.com/morluto/rea/issues/5944), [#6100](https://github.com/morluto/rea/issues/6100), [#6101](https://github.com/morluto/rea/issues/6101), [#6110](https://github.com/morluto/rea/issues/6110), [#6113](https://github.com/morluto/rea/issues/6113), [#6121](https://github.com/morluto/rea/issues/6121), [#6131](https://github.com/morluto/rea/issues/6131), [#6132](https://github.com/morluto/rea/issues/6132), [#6218](https://github.com/morluto/rea/issues/6218), [#6445](https://github.com/morluto/rea/issues/6445). Thanks @agorevski, @coygeek, @gongfpp, @kwakhyun, @mhamzasakhi.
- **Provider cleanup:** Preserve Windows native handles until close is confirmed, native/Inspector/Electron cleanup ownership, Kuna probe identity and cleanup, IDA registration configuration, and Hopper preparation ownership. [#5772](https://github.com/morluto/rea/pull/5772), [87ab054](https://github.com/morluto/rea/commit/87ab054ea384b3fcbae2998b1f94685edcd5f624), [ff78165](https://github.com/morluto/rea/commit/ff78165978de9dbcf9fa16c2acf74bf85a69dc44), [04ae07a](https://github.com/morluto/rea/commit/04ae07ab8c9ae1a6697b6ad15489bbde515da8b5), [dd0015a](https://github.com/morluto/rea/commit/dd0015aaf156c5701ef9598bcc6c885e6b8da803), [b231c28](https://github.com/morluto/rea/commit/b231c28cf64c2f799ada99343f8f21e0e6acb15e), [#4505](https://github.com/morluto/rea/issues/4505), [#5616](https://github.com/morluto/rea/issues/5616).
- **Provider diagnostics:** Give Ghidra restart recovery, stable Homebrew aliases, unsupported-host results for Linux-only integrations, correct IDA regex/readiness handling, and clear diagnostics when Windows refuses a verified native addon. [#5356](https://github.com/morluto/rea/pull/5356), [7c6142e](https://github.com/morluto/rea/commit/7c6142efdc19a42c148d0e8c96b69d18e63c7f87), [#5793](https://github.com/morluto/rea/pull/5793), [#4862](https://github.com/morluto/rea/pull/4862), [99ccfb6](https://github.com/morluto/rea/commit/99ccfb6e709ac4bc0afe176315280abde9ebcb9f), [#6832](https://github.com/morluto/rea/pull/6832), [#5730](https://github.com/morluto/rea/issues/5730), [#4860](https://github.com/morluto/rea/issues/4860), [#5723](https://github.com/morluto/rea/issues/5723). Thanks @coygeek, @dark13b, @gensokyo-dev, @jgt87, @jpmorris41488, @Lew1sWong.
- **MCP results:** Preserve protocol envelopes on oversized errors, enforce and advertise absolute Evidence paths, retain typed output-filter errors and selected JSON paths, and give client/provider timeout recovery. Compact advertisements now normalize reported enum and union shapes for strict gateway translation. [562dab0](https://github.com/morluto/rea/commit/562dab00c5cbf76a9b2695bad93792eccdc9a49d), [3cf6206](https://github.com/morluto/rea/commit/3cf6206614e65b5ebb6284a5709090dfb8f9aaee), [0e83d92](https://github.com/morluto/rea/commit/0e83d92c583ae36afe00b2c23dd2a0f1d025cbca), [4714c7e](https://github.com/morluto/rea/commit/4714c7eaa3d1d8b6a5df0aff586e844b9d9ab06d), [1bfa60a](https://github.com/morluto/rea/commit/1bfa60ac20e1a344bcf3132c08d15b6860b05c61), [#5608](https://github.com/morluto/rea/pull/5608), [#3806](https://github.com/morluto/rea/pull/3806), [#5598](https://github.com/morluto/rea/issues/5598), [#3800](https://github.com/morluto/rea/issues/3800). Thanks @gensokyo-dev, @Hahaa909, @wang1xiang.
- **Browser lifecycles:** Retain historical outcomes through cleanup, stop late navigation before session release, stop expired work, observe aborted fetch settlement, and mark later scenario actions skipped after failure or cancellation. [2e5171e](https://github.com/morluto/rea/commit/2e5171e391b83f8a467d0861fd452c1f78621fd8), [599fdac](https://github.com/morluto/rea/commit/599fdac029912f96c511f859660483405d2de26f), [b2fad36](https://github.com/morluto/rea/commit/b2fad362f2b37f81dc9a6f784f4521e4ca24d41e), [13a8640](https://github.com/morluto/rea/commit/13a864020414577006dce58d7fdaa877ddd0cb52), [#6023](https://github.com/morluto/rea/pull/6023), [#5943](https://github.com/morluto/rea/issues/5943). Thanks @coygeek, @kaoru0822-kitauji.
- **Electron observations:** Preserve listener callback ownership and count registrations by source callsite; block trash calls in the active hook, retain window handles through cancelled selection, and preserve cancellation during finalization. [dfe8378](https://github.com/morluto/rea/commit/dfe8378cf5a727e3d93d47a5986233175c6ef898), [5064007](https://github.com/morluto/rea/commit/506400748eb1d6c674f0cf51330073929c45f939), [816a9dc](https://github.com/morluto/rea/commit/816a9dc98886e6d824cd8ae88b68731b161d5dda), [1707d17](https://github.com/morluto/rea/commit/1707d171d750955bf6387e028e378183b360ffe3), [4e2a566](https://github.com/morluto/rea/commit/4e2a566d6c7e053ecbbee1b684311ed31ea163bf).
- **JavaScript source maps:** Keep unmapped and missing mappings unknown, preserve partial indexed-map facts and section paths, propagate preparation capability errors, and retain observed worker failures through cancellation. [a4dbb36](https://github.com/morluto/rea/commit/a4dbb36d8ea83e9f94dd289ac1a2d220d2c72c9b), [2b2e362](https://github.com/morluto/rea/commit/2b2e362a00fc5ba2f93fa6c62e2d8780072d1b4b), [498a667](https://github.com/morluto/rea/commit/498a667234b0140c1cfa43c819b35454ab11d14e), [#6149](https://github.com/morluto/rea/pull/6149), [#6214](https://github.com/morluto/rea/pull/6214), [f01dcca](https://github.com/morluto/rea/commit/f01dccab77f712fb4ac936d0a6e92a70d12f0789), [#6082](https://github.com/morluto/rea/issues/6082), [#6061](https://github.com/morluto/rea/issues/6061). Thanks @coygeek, @diyasharma05, @kaoru0822-kitauji.
- **JavaScript semantics:** Preserve overflowing timer uncertainty, unavailable-scope comparisons, directory-form URL/ESM path intent, and artifact confinement. Replaced globals lose built-in effects; erased imports no longer become runtime bindings. Treat a known truthy `fork()``silent` option as piped stdio unless a string/array `stdio` override takes precedence; unresolved options stay dynamic. [#3456](https://github.com/morluto/rea/pull/3456), [8d198d6](https://github.com/morluto/rea/commit/8d198d6ec707402d75276f516e0090d71767b7e4), [#4646](https://github.com/morluto/rea/pull/4646), [#2700](https://github.com/morluto/rea/pull/2700), [#4565](https://github.com/morluto/rea/pull/4565), [#6994](https://github.com/morluto/rea/pull/6994), [#3400](https://github.com/morluto/rea/issues/3400), [#3882](https://github.com/morluto/rea/issues/3882), [#3367](https://github.com/morluto/rea/issues/3367), [#7083](https://github.com/morluto/rea/pull/7083), [#7084](https://github.com/morluto/rea/issues/7084). Thanks @Adolanium, @amyanger, @coygeek, @gensokyo-dev, @HawkForge, @rohitg00, @viniciusdsandrade.
- **JavaScript routes and imports:** Treat path data as route candidates, preserve route flag and lexical RPC identities, package-main trailing-slash selection, catch aliases, and factory parameter ownership. [#6360](https://github.com/morluto/rea/pull/6360), [38ecc02](https://github.com/morluto/rea/commit/38ecc0248e1993d25a2f7dd350024484cce797bb), [#4219](https://github.com/morluto/rea/pull/4219), [21097b1](https://github.com/morluto/rea/commit/21097b192b1ab94647e3446b1a2a4dd00e924d5e), [f774dc4](https://github.com/morluto/rea/commit/f774dc420b3befe2b8e68971b4116da2d62fc800), [#6349](https://github.com/morluto/rea/issues/6349), [#4189](https://github.com/morluto/rea/issues/4189). Thanks @coygeek, @hemv-857, @kaoru0822-kitauji, @Nikhi00718.
- **Managed/IL2CPP:** Preserve extension-only scope uncertainty and type discovery after member limits, nested names, ReadyToRun/declaration facts, selected type scope, valid shared-suffix strings, and truncated IL2CPP metadata prefixes. [#5674](https://github.com/morluto/rea/pull/5674), [#5312](https://github.com/morluto/rea/pull/5312), [87fa1b6](https://github.com/morluto/rea/commit/87fa1b613d2b6bda1722855a00f1390f27731b64), [bc2d494](https://github.com/morluto/rea/commit/bc2d494030efd1ccabaeaa0bd49226aa87c378a2), [1f0eb22](https://github.com/morluto/rea/commit/1f0eb228e50908ee2a2aaa72d329178ae1a2cdbd), [4c5fae5](https://github.com/morluto/rea/commit/4c5fae5179dd54c4a0d427cd2a115b9c887e3841), [b3aadaf](https://github.com/morluto/rea/commit/b3aadaf474e59b33e5ff465236008a67eccefb87), [#5467](https://github.com/morluto/rea/issues/5467), [#5146](https://github.com/morluto/rea/issues/5146). Thanks @coygeek, @eco-null, @elricfd, @umi008.
- **Format boundaries:** Preserve independent facts across malformed inputs in model, GPU, WASM, Rust, Android, and SQLite inspection; report optional metadata warnings without discarding core results. [eb41f35](https://github.com/morluto/rea/commit/eb41f358cf83d5626f09de68332f9718f9aa6482), [#5789](https://github.com/morluto/rea/pull/5789), [00a9e95](https://github.com/morluto/rea/commit/00a9e95de91a4bd4d2a41f8aee704a53fa575750), [fc63fe8](https://github.com/morluto/rea/commit/fc63fe8682654086261540dcf3c59afc36c7d58f), [39a91d4](https://github.com/morluto/rea/commit/39a91d4db96ca13224c25936330ea84fe78970e5), [6c6e2ad](https://github.com/morluto/rea/commit/6c6e2ad62b20f810b54f5a567e66fc55241514b2), [929a0a7](https://github.com/morluto/rea/commit/929a0a76c870d9991e015dde58308fd9df0280b8), [d137a4c](https://github.com/morluto/rea/commit/d137a4cdde0049de967f1d5cd429ed9e1f7d0a10), [ef475fc](https://github.com/morluto/rea/commit/ef475fcf8b0601c61052b7091568ba574546417d), [#5749](https://github.com/morluto/rea/issues/5749). Thanks @coygeek, @gensokyo-dev.
- **Capture decoding:** Preserve malformed protobuf trailer facts and wire/schema identity, HTTP/2 URI and UTF-8 failure facts, WebMCP property coverage, and offline capture availability without a browser provider. Report invalid record ordinals as selection errors with actual bounds where available, and trim surrounding SP/HTAB from gRPC-web trailer values while preserving internal whitespace. [9cf7a7c](https://github.com/morluto/rea/commit/9cf7a7cb0d3c72a1121fde280cb11bf911af8055), [b3c3b21](https://github.com/morluto/rea/commit/b3c3b21e43cab4e71b460d08829d8c6e4e9b9c21), [4cb1f1d](https://github.com/morluto/rea/commit/4cb1f1d820df4498ee464bcf72a5f47d40cf8dab), [51e5938](https://github.com/morluto/rea/commit/51e593877642ab42fb5bf25812f4a4110ee7ac26), [d23be5c](https://github.com/morluto/rea/commit/d23be5c0898c39c9f0c54e2e0b43ee746d92d316), [#6725](https://github.com/morluto/rea/pull/6725), [#3947](https://github.com/morluto/rea/issues/3947), [#7067](https://github.com/morluto/rea/pull/7067), [#7068](https://github.com/morluto/rea/issues/7068), [#7069](https://github.com/morluto/rea/pull/7069), [#7071](https://github.com/morluto/rea/issues/7071). Thanks @Adolanium, @coygeek, @Sriram-PR.
- **Evidence and errors:** Authenticate ledger Evidence before committing; preserve parent-schema diagnostics, canonical correction details and owned cleanup outcomes; identify the rejected function-Evidence side/kind. Fixed allowances now name their actual limits. [0407bbf](https://github.com/morluto/rea/commit/0407bbfbe65e8fa475e8bb0c78c30170e2c2f55e), [#6361](https://github.com/morluto/rea/pull/6361), [1629266](https://github.com/morluto/rea/commit/1629266e3c08c90fed6bba5383528af7986a12b7), [#6969](https://github.com/morluto/rea/pull/6969), [#5860](https://github.com/morluto/rea/pull/5860), [#6034](https://github.com/morluto/rea/issues/6034), [#5932](https://github.com/morluto/rea/issues/5932), [#5847](https://github.com/morluto/rea/issues/5847). Thanks @AyoubElleuch, @coygeek, @dhruvac29, @kaoru0822-kitauji.
- **ADB and firmware recovery:** Report an unparsed push checksum as unverified, normalize absent installer-package sentinels, describe extraction-relative Unblob links, and avoid recommending a budget increase at its fixed ceiling. [#6010](https://github.com/morluto/rea/pull/6010), [#4073](https://github.com/morluto/rea/pull/4073), [#4573](https://github.com/morluto/rea/pull/4573), [#6971](https://github.com/morluto/rea/pull/6971), [#5924](https://github.com/morluto/rea/issues/5924), [#4175](https://github.com/morluto/rea/issues/4175). Thanks @coygeek, @Ganesh2325, @kaoru0822-kitauji, @Rinkia, @XiaoBinGan, @yankikucuk.
- **CLI formatting:** Share Markdown report formatting, exclude inherited row values, and preserve arrays of empty objects as JSON. Render Markdown table headers and cells literally while keeping intraword underscores readable. [b784912](https://github.com/morluto/rea/commit/b784912811fd10ac9dc425696dc0e9af632afa34), [#6984](https://github.com/morluto/rea/pull/6984), [#7058](https://github.com/morluto/rea/pull/7058), [#7057](https://github.com/morluto/rea/issues/7057), [#7073](https://github.com/morluto/rea/pull/7073). Thanks @Plastic-time, @ShuaixinHuang, @viniciusdsandrade.
- **WASM and APK metadata:** Preserve ambiguous WASM identity and partial facts, glue URL query/fragment text across line terminators, APK signer identity, and raw issuer identity when comparison rules are unknown. [af8f0ba](https://github.com/morluto/rea/commit/af8f0badf64fd3546392b6aa4625777904b2f051), [#6802](https://github.com/morluto/rea/pull/6802), [f783f0f](https://github.com/morluto/rea/commit/f783f0f1e82472cdddd4de2156d974f729e332a6), [115a78f](https://github.com/morluto/rea/commit/115a78fe241276c34917b496621954c5f29bfc15), [#6639](https://github.com/morluto/rea/issues/6639). Thanks @coygeek, @gensokyo-dev, @gongfpp.
- **Source identity:** Preserve Next route spelling, module grammar and loader request identity, directory package-main behavior, accessor effects, exact source targets, and resolver-discovery versus module-loading distinctions. [ddd7ac7](https://github.com/morluto/rea/commit/ddd7ac7b846b48191ead1f7dcd0e3bd735468fa8), [9974512](https://github.com/morluto/rea/commit/99745126009b15060d71c38809418858a07d5afa), [f2e5fd1](https://github.com/morluto/rea/commit/f2e5fd148a85fa737302dd194a33172c4561093e), [baf1678](https://github.com/morluto/rea/commit/baf16784af3592534687052431c145daef55cfd1), [6e324b2](https://github.com/morluto/rea/commit/6e324b224405f2befd953234f6dc210cf72ad50a), [75daf0c](https://github.com/morluto/rea/commit/75daf0c7df108f04ab41f34aec1a31d4a7ceb322), [f91b7f8](https://github.com/morluto/rea/commit/f91b7f8009c9af27a5e0148e3b07d20bfe3b7a2a).
- **Graphs and selected facts:** Preserve JavaScript graph omissions/version facts, Electron native-loader facts, web JSON identity/coverage, module-path selection, feature-trace qualifications, selected native paths, endpoint context, and mixed Swift demangler outcomes. [30db499](https://github.com/morluto/rea/commit/30db499db310f073d9bf3d3acfd77985e1cb7e2e), [5a7bddb](https://github.com/morluto/rea/commit/5a7bddb3aeb0345854e76b79d529aed1c40e2054), [79805f2](https://github.com/morluto/rea/commit/79805f244a1ec0850f3109929168a9c8ebb1b908), [f719dc4](https://github.com/morluto/rea/commit/f719dc46c51a55b3926eec9659d06e7dfb95132b), [7784fdb](https://github.com/morluto/rea/commit/7784fdbad78f8b384d513f0e7dae8e983cd48ef8), [76500f1](https://github.com/morluto/rea/commit/76500f12b54e07b1ea700a403b2593890d63b42a), [676d29f](https://github.com/morluto/rea/commit/676d29f9eef794cea668f5f09f0ff510c848a513), [edf7b3d](https://github.com/morluto/rea/commit/edf7b3d32c3248f221e27f7ce5a3d34e8590285b), [93de7bc](https://github.com/morluto/rea/commit/93de7bc7e324a761162a31625b838ba0d4e3824d).
- **Managed boundaries:** Honor native platform symbol lookup, consume resolved IL2CPP ELF declarations, and attribute malformed comparison inputs to the supplied argument. [64fa1db](https://github.com/morluto/rea/commit/64fa1db1309218283df19f3ee4dba61f5fbd2a67), [87745af](https://github.com/morluto/rea/commit/87745af52ab0ccd3a172c2534c516d41b0095035), [96ad94f](https://github.com/morluto/rea/commit/96ad94f69eda5d68c7335ff775b6927b1376fd2b).
- **Provider and worker recovery:** Preserve output loss after successful command exit, physical refusal diagnostics, bounded worker control framing, JavaScript worker-phase/budget attribution, admitted ambiguity choices, and selected EVM limiter availability. Scope objdump debug-link limitations to DWARF requests and keep process-capture preparation nonexecuting. [e639edf](https://github.com/morluto/rea/commit/e639edf6204c05285d96840478926592daf95876), [171b33b](https://github.com/morluto/rea/commit/171b33b2c4defc6cbea49545bedf4272b72d1ea2), [34563fc](https://github.com/morluto/rea/commit/34563fcc9bd92af30668820dcac5635e27181094), [3f9357b](https://github.com/morluto/rea/commit/3f9357b5990d166a38440f56f439452266650093), [cec8f1e](https://github.com/morluto/rea/commit/cec8f1e8f305d6332272457a6ee419d3c5fb6359), [a74d859](https://github.com/morluto/rea/commit/a74d859a19122fb8f1282b3632d320997b1caae0), [c284168](https://github.com/morluto/rea/commit/c284168c4b1cd214ce7f504d43da28528d82d603), [4fb936f](https://github.com/morluto/rea/commit/4fb936fe86bb7a07f94f819ae8510301f2ef69c9).
- **Setup and limits:** Retain unknown environment-budget facts, selected-skill/maintenance uncertainty, Hopper URL admission and bookmark verification, and listener failure recovery that matches the system cause. [a718037](https://github.com/morluto/rea/commit/a7180370332350bc0f998fbd643888221759570e), [d1fbebb](https://github.com/morluto/rea/commit/d1fbebb578538dc94fd5e376e6e1959218efa835), [60accad](https://github.com/morluto/rea/commit/60accad2de8f2862fe91901502fe26cc5390fb36), [fd7da77](https://github.com/morluto/rea/commit/fd7da77fc02dcfaf7d1bc9f2fb240d71cdd27c59), [0c440bf](https://github.com/morluto/rea/commit/0c440bfc07f3cb343e2e836d27cccaed539cfe9c).
- **State and Evidence:** Retain export tarball ownership and SQLite primary outcomes through cleanup retry, count emitted SQLite schema names across encodings, scope display refresh to matching snapshot bindings, and report retained-result validation failures consistently. Reconstruction uses one effective completion scope and kind-based labels when names are blank. [ab58edc](https://github.com/morluto/rea/commit/ab58edcdf50b4bd687900ee2dc362ecc5c3dce15), [1006714](https://github.com/morluto/rea/commit/100671427105791a5c5913a918b63a394f6bc83e), [a47788a](https://github.com/morluto/rea/commit/a47788a6a4abb067273f954275a9d0a269adf1e7), [8aa40e9](https://github.com/morluto/rea/commit/8aa40e9a61155cff8b6f3c138c601bf805b20653), [b8c1b45](https://github.com/morluto/rea/commit/b8c1b45316882beeab4a9de49381d94e131fab0f), [a35b933](https://github.com/morluto/rea/commit/a35b9335a0124674ee5e3abe8c075f1fff6b4fa6), [#6137](https://github.com/morluto/rea/pull/6137), [#6126](https://github.com/morluto/rea/issues/6126). Thanks @carlogiovannineri-rgb, @mohithhhh.
- **Capture coverage:** Name browser bundle budgets and deadline recovery, separate domain readiness from worker attribution, attribute rendered-frame omissions to their producing stage, share offline-capture host admission with discovery, preserve selected signal-file semantics, and retain short Flutter GNU build IDs. [#6036](https://github.com/morluto/rea/pull/6036), [ba78133](https://github.com/morluto/rea/commit/ba781330d6d28b22d15498e63c144fb40e086156), [5934387](https://github.com/morluto/rea/commit/5934387f4185129efe9dc8b7338d8bc3fa5b25bd), [ad629b2](https://github.com/morluto/rea/commit/ad629b2e31c3a9495b27179360b508fa021fe86a), [928ba76](https://github.com/morluto/rea/commit/928ba76882bfd216dde8ed79118789b2c3aad4f9), [678c4cf](https://github.com/morluto/rea/commit/678c4cfa68e2fee12f620075e12dc87d9b1195b0).
- **Additional boundary facts:** Retain parser format/query occurrence identity and independent malformed-input facts, unresolved nested Swift identifiers, and completed signing-capture coverage; describe crash documents without assuming a provider. [5f702dd](https://github.com/morluto/rea/commit/5f702dd6ccd9e8e505e224854b91678439c3b41f), [99d2d7a](https://github.com/morluto/rea/commit/99d2d7ad22bcbd780919760008aba6a88e7d1077), [90e433d](https://github.com/morluto/rea/commit/90e433df06b3f83417176b8db1b0a905f9df1d3a), [#5548](https://github.com/morluto/rea/pull/5548), [ee12d51](https://github.com/morluto/rea/commit/ee12d517a25d34853d40e31fc039c7d1576c60e1), [#5538](https://github.com/morluto/rea/issues/5538). Thanks @coygeek, @ShuaixinHuang.
- **Documentation:** Add the Romanian README. [#7026](https://github.com/morluto/rea/pull/7026). Thanks @An3treiu.
Full contribution record: [1740 commits and 497 merged PRs](https://github.com/morluto/rea/blob/rea-agents-6.8.0/docs/releases/6.8.0.contributions.json).
@@ -78,7 +180,7 @@ Full contribution record: [4 commits and 1 merged PR](https://github.com/morluto
### ⚠ BREAKING CHANGES
- **Saved Evidence:** Evidence and analysis snapshots now require explicit nullable `relationship_coverage` in their identity commitments. Artifact inventories require scoped coverage and explicit `integrity_contradictions`; obsolete `coverage_status` and prose-based coverage inference are removed. Regenerate old Evidence/snapshots and inventory observations with this release: saved files are not migrated and omitted facts are not filled with guessed defaults. ([db8128d](https://github.com/morluto/rea/commit/db8128dc0d1c4f731f3d19877fa00d25cf17f657), [0405c9d](https://github.com/morluto/rea/commit/0405c9d361de6d904dfa16cc0b6d8350407f2c9b), [a9588be](https://github.com/morluto/rea/commit/a9588be4ebdd20eeda975cb63ffcdb1cd868b340)).
- **Saved Evidence:** Evidence and analysis snapshots now require explicit nullable `relationship_coverage` in their identity commitments. Earlier records whose digest omitted null coverage are incompatible even when the serialized field is explicitly null. Artifact inventories require scoped coverage and explicit `integrity_contradictions`; obsolete `coverage_status` and prose-based coverage inference are removed. Regenerate old Evidence/snapshots and inventory observations with this release: saved files are not migrated and omitted facts are not filled with guessed defaults. ([db8128d](https://github.com/morluto/rea/commit/db8128dc0d1c4f731f3d19877fa00d25cf17f657), [0405c9d](https://github.com/morluto/rea/commit/0405c9d361de6d904dfa16cc0b6d8350407f2c9b), [a9588be](https://github.com/morluto/rea/commit/a9588be4ebdd20eeda975cb63ffcdb1cd868b340)).
- **Browser capture results:** Consumers must retain resolved capture limits, event families and omission facts. Set desired budgets through the supported capture options; omitted caller inputs still select defaults, but stored observations must report the resolved values. Admitted content reads queue behind bounded concurrency. ([57a23f0](https://github.com/morluto/rea/commit/57a23f0a2da0fdc3835e203718ded8acea5a34e6)).
- **Android version codes:**`inspect_adb_package.version_code` is a decimal string rather than a JSON number. Read it as a string, or use `BigInt` for numeric comparison. ([#3485](https://github.com/morluto/rea/pull/3485), [morluto/rea#3368](https://github.com/morluto/rea/issues/3368), [7666a48](https://github.com/morluto/rea/commit/7666a482b69dc7cabdbac3bbaf89a43e32300192)). Thanks @coygeek, @kaoru0822-kitauji.
- **Native UI failures:** Failed or cancelled native UI scenarios now return typed errors with the collected report in `partial_observation`. Handle the error path and read that report instead of expecting a successful result containing failed steps. ([d909919](https://github.com/morluto/rea/commit/d9099190ab3a819bd3a9fd62a8714cef398016d5)).
@@ -2581,7 +2683,7 @@ Read the [6.1 to 6.2 migration guide](docs/migration-6.2.md) before upgrading. R
| WASM artifact | Validation, sections, exact import/export WAT forms and decoded WAT | Caller-supplied WABT 1.0.42; `inspect_wasm_artifact` |
| EVM bytecode | Dispatch selectors, byte offsets, inferred arguments and mutability | Local raw/hex carrier on Linux x64; [offline EVM guide](docs/evm-bytecode.md) |
@@ -241,7 +253,12 @@ for features added since the latest npm release.
## Showcases
[](https://rea.tools/showcase/)
Record a web app session, turn its API into tools, and export an environment an AI agent can use. Run it with AgentEnv, then add tasks and reward checks for RL training or evaluation.
[Read the guide](https://rea.tools/guides/rl-environments/) ·
[Watch the video](https://x.com/reatools/status/2112574822584918075?s=20)
If you've used REA on something interesting, we'd love to see it. Share your
case in an [issue](https://github.com/morluto/rea/issues) or a
[pull request](https://github.com/morluto/rea/pulls), including the target,
your question, how REA helped, and what you found.
## Build RL environments
Give an AI agent a local environment to practice tasks such as finding an issue or creating a folder, without running the original app. Use it for reinforcement learning (RL) or to test how well an agent completes tasks.
REA turns recorded API requests and responses into tools the agent can call. The environment uses the recorded data and supports changes only when the recording confirms their effects.
With REA set up in your agent, replace the example URL and folder tasks below with your own:
```text
Use REA to build an RL environment from my test web app at
http://127.0.0.1:3000.
Cover listing, creating, renaming, and deleting folders. You may create and
remove test folders. Leave existing data unchanged.
Save it in a folder named my-env. Check which operations work and tell me
how to run it.
```
<details>
<summary>Use the command line instead</summary>
Use these commands if you already have a file containing the app’s recorded browser requests and responses. Running the result also requires AgentEnv and Docker.
```sh
rea environment-build ./session.har ./my-env --name my-env --json
agent-env run ./my-env
```
</details>
REA exports a runnable environment with a basic test to check that it starts and responds. Use it with your RL framework to define task goals, add reward checks, and run training.
[Build an environment](https://rea.tools/guides/rl-environments/) ·
@@ -10,7 +10,7 @@ Do not disclose vulnerabilities, proof-of-concept exploits, credentials,
private binaries, Hopper documents, or private Ghidra projects in a public
issue.
Use **Report a vulnerability** in the repository's **Security** tab to submit the report privately. Do not open a public issue to request a private contact channel.
Use **Report a vulnerability** in the repository's **Security** tab as the preferred way to submit the report privately. If GitHub private reporting is unavailable to you, email [[email protected]](mailto:[email protected]). Do not open a public issue to request a private contact channel.
Include the affected REA version, operating system/distribution, selected
provider and version, impact, reproduction conditions, and any suggested
| npm dependencies | [Complete inventory](licenses/npm-dependencies.txt) of every entry in `package-lock.json`, including transitive, optional platform, development, and website dependencies. [Runtime notices](licenses/npm-runtime-notices.txt) preserve the copyright, license, and NOTICE documents from integrity-verified release archives, plus the MIT notice for Rolldown's generated runtime helpers. Development dependencies are inventoried but are not all distributed in REA's npm package. |
| pefile ordinal tables | Import-hash ordinal names are derived from [pefile 2024.8.26](https://github.com/erocarrera/pefile/tree/4b3b1e2e568a88d4f1897d694d684f23d9e270c4), copyright 2004–2024 Ero Carrera. Preserve the [MIT license](licenses/pefile-2024.8.26-LICENSE.txt). The Python package is not a runtime dependency. |
| NativeAOT parser | REA's derived parser uses the MIT-licensed [ghidra-nativeaot](https://github.com/Washi1337/ghidra-nativeaot/tree/effeb734fc570c32650f88b159608979dc7b423e) work of Washi and the NativeAOT layout definitions in [dotnet/runtime](https://github.com/dotnet/runtime/tree/a3b2d40328be0be3f8dd43f0e5cc925b8827b044). Preserve [Washi's MIT notice](licenses/nativeaot-parser-MIT.txt) and the [.NET Foundation MIT notice](licenses/dotnet-runtime-MIT.txt). |
| EVM analysis | `[email protected]`, MIT, copyright 2023 Maxim Andreev. The published npm archive omits its license document; REA retains the [original upstream license](third_party/evmole/LICENSE) and [provenance](third_party/evmole/README.md). It is also included in the runtime notices. |
| Windows native addon | The release addon is compiled with MinGW-w64 and statically links GCC runtime libraries. Preserve the [MinGW-w64 runtime notices](licenses/MinGW-w64-runtime.txt), [GPLv3 text](licenses/GPL-3.0.txt), and [GCC Runtime Library Exception 3.1](licenses/GCC-Runtime-Library-Exception-3.1.txt). The exception governs eligible compiled combinations; it does not relicense the runtime itself under MIT. The Node-API build headers are from Node 22.19.0; its [original license and component notices](licenses/Node-22.19.0-LICENSE.txt) are retained. Node itself is supplied by the user. Snapshot provenance and release-toolchain review requirements are in [licenses/README.md](licenses/README.md). |
@@ -52,27 +53,27 @@ REA's adapters do not grant, replace, or waive these licenses. The upstream
executables and their dependency graphs are supplied separately. Git submodules
pin inspection sources; they are not included in the npm package.
| Project | License and source | REA relationship |
| Ghidra | [Apache-2.0](https://github.com/NationalSecurityAgency/ghidra/blob/Ghidra_12.1.4_build/LICENSE), with the government-work and component qualifications in its [NOTICE](https://github.com/NationalSecurityAgency/ghidra/blob/Ghidra_12.1.4_build/NOTICE) | Bring your own Ghidra 12.1.4. Copies of its [LICENSE](licenses/ghidra-12.1.4-LICENSE.txt), [NOTICE](licenses/ghidra-12.1.4-NOTICE.txt), and [DISCLAIMER](licenses/ghidra-12.1.4-DISCLAIMER.txt) are retained for reference. |
| JADX | [Apache-2.0](https://github.com/skylot/jadx/blob/v1.5.6/LICENSE) | The audited jadx-headless-mcp source uses JADX 1.5.6 for Android decompilation; the engine JAR is separately supplied. |
| Kuna | [Apache-2.0](https://github.com/Noelo-Lab/kuna/blob/v1.833/LICENSE), with its [NOTICE](https://github.com/Noelo-Lab/kuna/blob/v1.833/NOTICE) | Bring your own `kuna`; REA verified 1.833 and never downloads, installs or bundles it. REA invokes it as a separate process. |
| pyelftools | [Public-domain dedication and component notices](https://github.com/eliben/pyelftools/blob/v0.33/LICENSE) | 0.33; includes separately licensed bundled material, including Construct. |
| Unicorn | [GPL-2.0 and component notices](https://github.com/unicorn-engine/unicorn/blob/2.1.2/COPYING) | 2.1.2; used by the caller-supplied ELF analysis profile for instruction emulation. |
| GNU GDB | [GPL-3.0-or-later](https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/COPYING) | Caller-supplied debugger for the optional pwndbg core-file workflow. |
| LLDB / LLVM | [Apache-2.0 with LLVM exceptions](https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT) | Caller-supplied debugger; the installed distribution's component and historical notices also apply. |
| Ghidra | [Apache-2.0](https://github.com/NationalSecurityAgency/ghidra/blob/Ghidra_12.1.4_build/LICENSE), with the government-work and component qualifications in its [NOTICE](https://github.com/NationalSecurityAgency/ghidra/blob/Ghidra_12.1.4_build/NOTICE) | Bring your own Ghidra; see [supported versions](docs/installation.md#ghidra). Copies of the 12.1.4 [LICENSE](licenses/ghidra-12.1.4-LICENSE.txt), [NOTICE](licenses/ghidra-12.1.4-NOTICE.txt), and [DISCLAIMER](licenses/ghidra-12.1.4-DISCLAIMER.txt) are retained for reference. |
| JADX | [Apache-2.0](https://github.com/skylot/jadx/blob/v1.5.6/LICENSE) | The audited jadx-headless-mcp source uses JADX 1.5.6 for Android decompilation; the engine JAR is separately supplied. |
| Kuna | [Apache-2.0](https://github.com/Noelo-Lab/kuna/blob/v1.833/LICENSE), with its [NOTICE](https://github.com/Noelo-Lab/kuna/blob/v1.833/NOTICE) | Bring your own `kuna`; REA verified 1.833 and never downloads, installs or bundles it. REA invokes it as a separate process. |
| pyelftools | [Public-domain dedication and component notices](https://github.com/eliben/pyelftools/blob/v0.33/LICENSE) | 0.33; includes separately licensed bundled material, including Construct. |
| Unicorn | [GPL-2.0 and component notices](https://github.com/unicorn-engine/unicorn/blob/2.1.2/COPYING) | 2.1.2; used by the caller-supplied ELF analysis profile for instruction emulation. |
| GNU GDB | [GPL-3.0-or-later](https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/COPYING) | Caller-supplied debugger for the optional pwndbg core-file workflow. |
| LLDB / LLVM | [Apache-2.0 with LLVM exceptions](https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT) | Caller-supplied debugger; the installed distribution's component and historical notices also apply. |
case"list_classes"->"Pages of case-sensitive matching top-level class names; offset and next_offset are inventory positions, limit bounds matching rows. Omitted or empty query inventories all names.";
case"get_class_summary"->"Parsed member metadata for one exact class name; no source generation.";
case"get_class_summary"->"Parsed member metadata for one exact class name; no source generation. Set dex_static_values to include encoded static final field values.";
case"get_method_body"->"Source for an exact class and stable same-name overload index; static initializers use smali to preserve folded field initialization.";
default->"Complete static using-node inventory for an exact class or selected method overload; one node may contain multiple invoke instructions, and source lines are unresolved.";
tryfail("pid-not-application","LaunchServices does not expose an application for the selected PID; this does not establish that the process is absent")
}
guardletcanonicalPointer=realpath(url.path,nil)else{tryfail("target-mismatch","Running executable path cannot be resolved")}
guardleturl=app.executableURLelse{
tryfail("application-executable-unavailable","The selected application does not expose an executable URL; select a PID with an identifiable application executable")
}
guardletcanonicalPointer=realpath(url.path,nil)else{tryfail("executable-path-unavailable","Running executable path cannot be resolved")}
raiseLayoutFailure("format",f"ELF symbol table {index} links to invalid string table {h.sh_link}.")
strings=all_sections[h.sh_link]
@@ -294,6 +319,7 @@ def inspect_elf(path, cache):
"Relocatable relocation targets with SHN_UNDEF or inactive SHT_NULL headers retain their reported section index/offset as unknown; they do not establish an associated target section.",
"GOT/PLT are derived upstream convenience maps; PLT inference can emulate selected instructions in Unicorn. They do not establish target runtime behavior; aliases may collapse and warnings may indicate incomplete coverage. Their completeness is unknown.",
"Mitigations are upstream static heuristics, not runtime protection. ET_DYN does not prove an executable; absent canary symbols do not prove every function unprotected.",
"Kernel configuration/version discovery is not performed; these memory-content scans do not supply the reported structural, linkage or mitigation facts.",
"This profile inspects ELF EXEC/DYN/REL layout only. It does not analyze recorded cores, resolve loaded libraries, launch the target as a host process or start a debugger.",
"Symbol/relocation inventories reflect original section tables. A sectionless image can still report dynamic dependency names; missing tables do not prove absence of dynamic symbols or relocations.",
*(["Absent section-name table: section-dependent RELRO/canary heuristics may be incomplete; protection coverage is unknown."]ifall_sectionsandsection_name_index==0else[]),
| `pull_adb_package` | read | Complete split APK set from `pm path`, each file digested |
| `pull_adb_file` | read | One absolute device path pulled and digested |
@@ -103,6 +103,11 @@ existing analysis families directly, for example
| `start_adb_activity` | **mutates device** | Starts an intent (`am start -a` with optional URI, component, and up to 16 typed extras); preserves the activity manager's verdict |
| `stop_adb_app` | **mutates device** | Force-stops every process of a package, ending a dynamic-analysis run |
When `push_adb_file` receives an existing directory, adb places the local file
inside it under the local basename; Evidence reports that effective file path
while retaining the caller's directory path in the input parameters. The
private read-only staging copy preserves the source file's executable bits.
For `inspect_adb_window`, `focus_contexts` retains each display header, its exact
display ID when recognized, and every focus declaration with its original line.
Declarations without a display header are explicitly `unscoped`. A missing
| `no-state-target` | The write's path names no collection or item the capture reads. Read the collection or item it changes. |
| `no-call` | No recorded call of this tool was modelled, for example because every call failed. Record a successful call. |
| `body-unusable` | The retained request or response cannot be modelled. Record a successful call with a complete supported request and reproducible response. |
| `no-observation` | Nothing showed the entity or document this write changed. Read a created entity back by id right after the write; for an update or delete the state must already hold the entity, so read it before the write or record the create that made it. |
| `unexplained-change` | The write changed fields it did not send, in a way no rule explains. A second, different call of the same tool can show the pattern. |
| `contradicted` | A later read disagreed with the modelled effect. Check the read at contradicted_by. |
| `side-effect` | The write changed something besides its own entity, which the environment does not model. |
| `unconfirmed` | No later read showed the effect. Read the entity and its list after the write. |
| `incomplete-entities` | The write is confirmed, but the views that show its entity cannot render it in full. Read the written entity through every view that lists it. |
| `unknown-clock` | The learned rules generate timestamps, but the capture establishes no global served clock start. Record usable start times and completed durations for every request. |
The bundle ships `evidence.json`, the whole capture Evidence, response bodies
included. Inspection excludes the values of the standard authentication headers
(`Authorization`, `Cookie` and `Set-Cookie` among them) and URL userinfo; a
custom key header such as `X-Api-Key`, a token in the query string and tokens
an application returns in bodies remain. The environment views refuse captures
inspected with `--sensitive-value`, so scrub a capture before building it. The
report's `credential-named-members` warning counts recorded header names, query
parameter names and JSON or form body members whose names look like
credentials (whole name segments such as `token`, `secret`, `password`,
`api_key`, `authorization` or `session`) and hold a value, and lists the first
20 by record and pointer, never by value. A body is read as a form or as JSON by
its recorded media type, or by its shape when it has none or one naming
neither. A browser scenario is
scanned by event (`event 4 response /token` names
`normalized_result.events.items[4]`): every retained request and response
content event, including a response whose request began before the browser was
attached and a transaction no record represents, and each transaction URL's
query once. Bodies larger than 4 MiB of UTF-8 text are not
scanned; `credential-scan-incomplete` counts them and lists up to 20 record or
event pointers, including base64 bodies whose decoded scan was cut. An empty name
warning does not establish that these bodies were checked. A browser scenario's
saved values (`save` and `save_response`) named like credentials but not marked
`secret: true` are recorded unredacted; `credential-named-saved-values` lists up
to 20 of them by parameter pointer. Names do not establish sensitivity,
so the build never refuses on them. Capture
Evidence also records the capture file's absolute path (`subject.local_path`,
`parameters.capture_path`, `locations`, `artifact.path`), and the bundle
carries it: build from a neutral folder when that path should not ship.
Over MCP, `export_environment_bundle` builds the same bundle and returns the
same report. Its `source` is capture Evidence the session retained
(`{"kind": "retained-evidence", "evidence_id"}`), such as a
`capture_browser_scenario` or `inspect_web_network_capture` result, or a
capture Evidence file (`{"kind": "evidence-file", "path"}`); inspect a HAR with
`inspect_web_network_capture` first. Retained Evidence is written into the
bundle as `--format json` writes it, so the bundle is the one
`environment-build` writes from that file. `output_directory` must be an
absolute path that does not exist yet, whose parent does; the tool creates it
and refuses an existing directory, empty or not. `name`, `template_rules`,
`package_tarball` and `dry_run` work as `--name`, `--template-rule`,
`--package-tarball` and `--dry-run` do, and retained Evidence has no file to
name the environment after, so a loopback or IP origin needs `name`. Unlike
`--dry-run`, `dry_run` still checks `output_directory`. Destination refusals
name `export_environment_bundle`; the others name their stage as
`environment-build`'s do.
## From a browser scenario
@@ -125,6 +320,51 @@ the replayed body is the bytes the browser exposes for each response, with any
declared secret replaced by its redaction marker (a body that redaction had to
empty replays no body).
To record writes, sign in through the UI and then send the application's API
calls with [request steps](browser-scenario-contract.md#request-steps): each
sends one request to the start origin through the page's own `fetch`, with the
session's cookies, and a header can carry the CSRF cookie or stored token the
application's own requests send. A write is served only when the capture shows
its effect, so read each collection before writing, read every written entity
back by id and in its list right after the write, and leave more than a second
between a create and its first edit. A request step's path is fixed when the
scenario is written and cannot use a value an earlier response returned, so an
id must be known before the run: one the caller chooses, such as a `uid` in the
create body, or one an earlier scenario created. When the server assigns ids,
read the list after each create (the create's response or the list shows the
new entity), and record updates and deletes in a second scenario that reads
the first one's objects by id before editing them, or make them through the
UI. The environment coverage view names each
write it withholds and what to record next. A scenario with write requests
changes the application's data: record against an instance whose data may
| `item` | The entity the path arguments name, rendered into the recorded envelope of `envelope_ordinal`. Arguments match as replay matches them: each collection segment equals the held collection's segment as written or after percent-decoding, and the identity is the last argument percent-decoded, then as written; values are never re-split on `/`. Any entity the state holds answers, including one `data/add` loaded; query arguments only decide `replay.exact_match`. An entity the state does not hold answers the tool's latest recorded 400, 404 or 410 response with `state.view``missing`, or is a tool error when none was recorded; one lacking a field every recording carried is a tool error, unless a read showed the application leaves that field out; a body is never invented. |
| `list` | When the arguments name one of the lines the view checked exactly (its latest recordings before the first related write; every path and query value equal to the recording's, and every recorded query parameter supplied), that recorded envelope with its array rendered from the state: every entity of the collection in state order for `membership: "all"` or a line `all_record_ordinals` names, or the recorded members still held. A call with no query argument answers from such a line of the collection its path arguments name that only pages its list, with `replay.exact_match` false. On a line the view's `query` answers, and for a call whose every query argument has a role there (an argument-less call aside), the answer is the query evaluated over the state: filtered, searched, sorted and paged, with counters at the number listed and `query.totals` at the number matched, and `state.membership: "query"`; such a call answers on a query or whole line of its collection with `replay.exact_match` false. A value an `inert` parameter never recorded, or a parameter without a role, replays its recording. A member lacking a field every recording carried makes the call a tool error rather than a partial list. |
| `document` | When the arguments name the document's checked line exactly, the state's value for it; a tool error when the state holds none. |
| `recorded` | The recording, as replay answers it. |
| `item` | The entity the path arguments name, rendered into the recorded envelope of `envelope_ordinal`, whose `per_response_members` (such as a request id), like a list's or a document's, keep their recorded values. Arguments match as replay matches them: each collection segment equals the held collection's segment as written or after percent-decoding, and the identity is the last argument percent-decoded, then as written; values are never re-split on `/`. Any entity the state holds answers, including one `data/add` loaded; query arguments only decide `replay.exact_match`, except that a call matching one of the view's `projected_query_keys`, or on a view with `projected_record_ordinals` asking for some fields only with a value other than `*` no checked line gave or one a replayed read gave, replays its recording. An entity the state does not hold answers the tool's latest recorded 400, 404 or 410 response with `state.view``missing`, or is a tool error when none was recorded; one lacking a field every recording carried is a tool error, unless a read showed the application leaves that field out; a body is never invented. |
| `list` | When the arguments name one of the lines the view checked exactly (its latest recordings before the first related write; every path and query value equal to the recording's, and every recorded query parameter supplied), that recorded envelope with its array rendered from the state: every entity of the collection in state order for `membership: "all"` or a line `all_record_ordinals` names, or the recorded members still held. A call with no query argument answers from such a line of the collection its path arguments name that only pages its list, with `replay.exact_match` false. On a line the view's `query` answers, and for a call whose every query argument has a role there (an argument-less call aside), the answer is the query evaluated over the state: filtered, searched, sorted and paged, with counters at the number listed and `query.totals` at the number matched, and `state.membership: "query"`; such a call answers on a query or whole line of its collection with `replay.exact_match` false. A value an `inert` parameter never recorded, a parameter without a role, a call matching one of the view's `projected_query_keys`, or a field selection the checked lines do not show (as for `item`), replays its recording. A member lacking a field every recording carried makes the call a tool error rather than a partial list. |
| `document` | When the arguments name the document's checked line exactly, the state's value for it; a tool error when the state holds none. |
| `recorded` | The recording, as replay answers it. |
A read with repeated query values uses replay, because the state query model
does not infer repeated-parameter semantics. A repeated-query write is refused
before it can change state for the same reason.
List counters retain their recorded number or digit-string representation.
Changing a digit-string counter preserves its observed zero-padding width;
query-total inference remains limited to canonical decimal counts. Path matching
uses the same segment parser as extraction, preserving empty internal segments.
An item or list view that always spells a clock field otherwise than the
entity's stored value names that spelling in `clock_formats`, and a value it
never recorded, such as a created entity's clock, is rendered in it: a list that
writes `+00:00` where item reads write `Z` lists a new entity the same way.
A view that names a field in `sorted_arrays` lists that string array sorted, as
a read-back showed the application does, while the state keeps it in the order
it was written, so a write's own answer echoes it. If a later counted read
contradicts that ordering, the view stays recorded and its earlier reads no
longer confirm served writes. A view that names a field in `nested_fields`
always showed that field's objects with the same keys, in any order, and fewer
than an entity stores, such
as a list showing a parent without the parent's own nested type; a stored
object it never recorded, such as a created entity's parent, is rendered with
those keys. Members a view names in
`per_response_members`, such as a request id each response mints, keep the
value its recording carried. A list's `counters` and `query.totals` are
top-level members or members one level down in a paging object
(`/pageInfo/totalRows`); either is set to the number listed or matched, and
members beside it such as `isLastPage` stay as recorded.
A list or document call that names no checked line, including a line recorded
after a write or with other query values, answers from the recording. Every
answer has the replay shape plus `state`: `{"source": "state", "view": …}`
naming the entity, collection or document path, or `{"source": "recording",
"reason": …}` with the view's reason, `no-view`, `unrecorded-request`, `page-exceeded` (a call naming a page of a whole list that the collection has outgrown) or `projection` (a call to an item tool whose recordings asked for some fields only, naming such a parameter for an entity the state holds; the answer is a recording, so it does not show served writes). A
"reason": …}` with the view's reason, `no-view`, `unrecorded-request`, `page-exceeded` (a call naming a page of a whole list that the collection has outgrown), `projection` (a call to an item or list tool with replayed reads asking for a selection of fields the checked lines do not show, or leaving out a projection parameter every checked line names) or `variant` (a call matching another `projected_query_keys` key: a parameter, or a value of one, only lines showing the entities in another representation named, or leaving out a parameter every other line named). A `projection` or `variant` answer is a recording, so it does not show served writes. A
state answer carries the base record's status, content type and `replay`
provenance with `truncated: false`; one whose JSON would exceed 256 KiB is
refused as a `resource_constraint` tool error rather than cut. Extraction does
not state-back a document whose rendered JSON exceeds 256 KiB; that read stays
recorded (`rendered-oversize`) and replays the captured body. Query `POST`s
stay served and answer from their recordings with the reason `query-body`.
recorded (`rendered-oversize`) and replays the captured body. Query `POST`s,
and `POST` tools the capture shows only reading (a lookup answering as a `GET`
did, an RPC tunnel naming read operations, a session renewal), stay served and
answer from their recordings with the reason `query-body`; they are not write
tools.
A line establishes whole-collection membership only from the beginning:
`offset`, `start`, `_start` and `page` must be zero when present. Positive or
@@ -459,29 +737,56 @@ tools are not served, so no call claims a change it does not make; each one's
plan states why in its `reason`. A served write changes the live state, which
| `create` | Adds an entity to the collection the path names, built from the observed entity with each ruled field taken from the call or generated, at the plan's `insert` position. A plan tied to its exemplar's collection writes only there. |
| `update` | Sets the sent members on the entity the path names, constants for members accepted only with their recorded value, and the clock, increment, slug, unique and renewed changes the plan models. |
| `delete` | Removes the entity the path names. |
| `document` | Merges the body into the plan's document object, or replaces it for `PUT`. |
| `create` | Adds an entity to the collection the path names, built from the observed entity with each ruled field taken from the call or generated, at the plan's `insert` position. A plan tied to its exemplar's collection writes only there. |
| `update` | Sets the sent members on the entity the path names, constants for members accepted only with their recorded value, and the clock, nested clock, increment, slug, stamp, derived, composed, reference, unique and renewed changes the plan models. |
| `update`(action) | A `POST`, `PUT` or `PATCH` to an item path plus an action segment (`/{type}/{id}/archive`) sets, on the entity before the segment, each scalar the recorded calls showed the action set (`set`), with any sent members; it is served only when a recorded call found those fields already set, so a toggle never is. |
| `delete` | Removes the entity the path names. |
| bulk `update` or `delete` | A `DELETE`, `PUT` or `PATCH` at a collection, or a `POST` to it plus `delete`, `remove` or `destroy`, applies its effect to every entity the body names, as recorded: an array of ids or of objects carrying the id field, at the root or as the body's one array member (`{"IDs": […], "Read": true}`). |
| `document` | Merges the body into the plan's document object, or replaces it for `PUT`. |
An update's unsent changes follow the plan's rules. A `held-clock` is a clock
the client sends back as it read it and the application stamps anew (Ghost's
`updated_at`): the call must send the entity's value and the field takes the
write's clock. A `nested-clock` sets the clocks inside an object the entity
holds, in that object's recorded format. A `stamp` writes the acting user
the entity already names under its `created…by` counterpart into a
`modified…by` or `updated…by` field. A `derived` field takes a value showing
the one sent member's text that the entity stores nowhere (a field Ghost
derives from `html`), only with that member's recorded value. An action's
`set` rule sets a scalar to the value the recorded calls left it at.
Its answer has the status and content type of the plan's recorded response,
with the written entity or its identity rendered in, no body, or the recorded
body. A call whose body is not an object, sends a member the capture did not
show stored, sends a fixed member with another value or a member of another
JSON type, or lacks a required member is a tool error naming the accepted
members; so is a rendered answer missing a field the recorded response
carried, and an update or delete of an entity the state does not hold answers
members; so is a call sending query parameters other than the exemplar's (they
may change what the body does), a body not wrapped in the exemplar's envelope
(Ghost's `{"posts": [{…}]}`), a bulk call naming an id the state does not hold,
a `held-clock` member sent with another value than the entity holds, a call
sending a `derived` rule's member to an entity that does not hold the value the
recorded call found, a nested clock on an entity holding no such object, and a
rendered answer missing a field the recorded response carried, and an update or delete of an entity the state does not hold answers
the recorded 400, 404 or 410 of the tool or of an item view of the type, if
any. A refused call leaves the state unchanged. Values a write generates are
any. A served delete of a type whose item view has a `deleted_flag` (the
member, `deleted`, `isDeleted` or `is_deleted`, its reads set `true` on a
record the application soft-deleted, as EspoCRM does) keeps the entity until
`data/reset` or `data/add`, within the size `data/add` loads, so a read of it by
id answers its last fields with that flag `true`. A refused call leaves the
state unchanged. Values a write generates are
deterministic: the clock starts at `write_clock` and advances one second per
served write, sequences take one past both the largest held value and the
largest they generated, and UUIDs and tokens derive from the state Evidence
id, tool, field and write count, skipping held values. `data/reset` and
id, tool, field and write count, skipping held values. If `write_clock` is null,
plans needing `clock`, `held-clock`, or `nested-clock` retain their learned rules
but are withheld with `unknown-clock`; other confirmed plans can still be served.
`data/reset` and
`data/add` restart the clock, counter and sequences, so the same calls after a
reset give the same state. Answers carry `state: {"source": "state", "view":
"create" | "update" | "delete", …}` or `"document-write"`.
"create" | "update" | "delete", …}` or `"document-write"`; a bulk answer adds
`ids`, every entity it wrote in body order, with `id` naming the first.
The data plane serves three JSON-RPC methods:
@@ -573,13 +878,17 @@ id are unique; `view_fields` is optional and names item or list views of its
type. Views render their values over the entity's fields, so a view's values
must not set the type's identity field to a value whose text differs from the
entity's `id`. Spell a collection as requests spell it, as `data/get` reports it: list
calls find entities under the checked line's recorded path. Each document
calls find entities under the checked line's recorded path. State collection
envs/grafana-example/manifest.json byte-exact copy of manifest.json
envs/grafana-example/evidence.json byte-exact copy of capture.json
@@ -669,7 +997,8 @@ serves replay. The complete tool catalog the bundle serves must also fit the
server's advertised catalog budget before any files are written. Privately parsed JSON is sealed once so authentication
and replay share immutable response trees rather than copying the capture repeatedly.
`--name` replaces the manifest's portable kebab-case name as the env folder and env id
(Windows device names such as `con` and `lpt1` are refused);
(at most 63 characters for its DNS service label; Windows device names and
labels interpreted as IP addresses are refused);
`--package-tarball <path>` copies a packed `rea-agents` tarball into the env
folder and makes the Dockerfile install it instead of the registry package and
remove it in the same layer, which is how a checkout rather than a release is
@@ -687,7 +1016,12 @@ Windows inherits ACLs and REA does not establish owner-only access there. Choose
an already private Windows destination when captured content needs it.
The Dockerfile sets `MCP_HOST=0.0.0.0` and `MCP_PORT=18765`, the port the
framework maps for an MCP server env; the framework's own deploy supplies
framework maps for an MCP server env, and `MCP_ALLOWED_HOSTS` naming the loopback
addresses and the environment name, because the container binds outside loopback
and the server refuses to serve on such a bind without an operator-declared
allowlist: the framework's published port is reached over loopback and its
gateway proxies to the env container by the compose service name (the
environment name). The framework's own deploy supplies
`MCP_HOST`, `MCP_PORT` and `ENVIRONMENT_NAME`, so the served card carries the
env's name. It installs Debian's `python3` because the framework's local
sandbox probes a container's readiness with `python3` inside it, which the slim
@@ -755,8 +1089,59 @@ recording replayed in its place and never from a recording whose body the probe
two collections can reuse a live id, and an equal pair stays in that collection. A live id in a later request's path, query or body is translated before the
environment answers, a path parameter by the collection the live path names (a nested collection keeps its parent values, each decoded once, and a literal route segment stays), except a query value that pages a list, such as `limit`
or `page`. Each call is checked against the served tool's input schema first, as the MCP server checks it. After mapping, two clock values compare by format only (ISO-8601 strings, and epoch numbers under
time-named fields), and two different values each side generated on its own compare equal: both UUIDs, or one length of
eight or more with the same character classes and a digit. The report counts each kind of normalised value.
`at`, `time`, `date`, `timestamp`, `created`, `updated` or `modified` field names, including snake-case and camel-case forms).
Numeric arrays retain that containing field's clock context through nested
arrays; an object's own fields establish their own context. Numeric values at
the body root, in root arrays, or under measurement fields remain literal.
Generated values normalize only where this confirmed, served write's entity
response rules identify generation. A UUID identity rule must still compare two
UUIDs, and a `unique` rule two UUIDs or two generated integers (10 to 20
digits) of one JSON kind and length; a `renewed` rule applies only at its
recorded pointers,
with `*` matching actual array items. Token/sequence strings retain the existing
format check: equal length of at least eight, the same character classes, and
a digit. Numeric sequences continue to compare literally unless an ID mapping
applies. String shape and names such as `token` or `sku` alone do not establish
generation. Read and replay responses without these facts stay literal except
for supported clocks and learned IDs. A missing write target replays an absence
response and does not inherit the successful entity response's generation rules.
Admitted generated values must also preserve aliases and distinct identities
within that response. UUID identity uses the generator's case-insensitive
matching; token and sequence strings retain their literal identity. This
correspondence ends with the answer and is not inferred across calls.
A `composed` response field must spell the value its parts build from that
response's own fields. Its parts then compare by their rendered text or their
source fields' clock and ID rules. A coherent archive URL can therefore differ
only in normalized clock digits without reporting a value difference; an
incoherent URL still differs even when both sides repeat the same stale text.
Normalized compositions count under `generated`; source fields are counted once.
The report counts each kind of normalised
value; the generation rules remain model-derived facts, rather than new
observations of the application.
ISO clock offsets are accepted only within RFC 3339's `00`–`23` hour and `00`–`59` minute ranges.
Probe ordering retains every recorded fractional-second digit in ISO timestamps
with a four-digit year, `T`, and a `Z` or `±HH:MM` suffix. Equal instants use ordinal order. Other native-Date
spellings keep their existing millisecond interpretation; an absent or unreadable
start time makes the whole probe use record order. Original capture timestamps
remain unchanged. Clock-format comparison and respelling recognize four-digit
ISO years `0000`–`0099` as well as later years, with normal calendar validation.
Respelling preserves the original value when the target zone would require a year
outside `0000`–`9999`; generated writes refuse a clock outside that format.
Capture-state start ordering uses the same exact recorded timestamp facts,
including minute-only times and fractions longer than nine digits. Recorded
spellings may use `T` or a space, `Z` or an extended/compact offset, or no zone
(interpreted as UTC). Equal starts use ordinal order; a missing or unreadable
start makes the capture use record order. Request interval and overlap checks
still use millisecond coordinates, and generated-clock progression compares
milliseconds. Derived ISO clock formats still require seconds and at most nine
fractional digits.
Comparison keeps response representations distinct: JSON values compare structurally, text compares as text, and a
retained base64 body compares by bytes (including with UTF-8 text carrying those same bytes), never by its base64
spelling. ID mappings apply at identifier fields, `ids`/`uuids`/`guids` lists, an entity's own identity within its
collection, and a string field learning confirmed as a state-held ID. ID mappings leave other numeric and string values unchanged. A
global conflict involving an equal pair is not used to normalize either pair; the report counts it as an ID conflict.
A step agrees when the statuses and the normalised bodies are equal. The report gives agreement overall, per probe and
per tool, `agreement_ignoring_order` for steps that differ only in item order, and each step's differences, at most 20,
@@ -777,16 +1162,16 @@ with a JSON pointer and both values cut short:
| `unmapped-id` | The application answered with success and the environment did not, for a path id the comparison never mapped |
What a probe did not observe is not counted as the application's behaviour. A record without a usable request line,
such as a redacted URL or a transaction the capture cannot attribute, is not replayed, nor is a request to another
origin than the application's (`other-origin`: the probe's origin with the most JSON-like records, as the manifest
such as a redacted URL or a transaction the capture cannot attribute, is not replayed, nor is a request to an origin different
from the application's (`other-origin`: the probe's origin with the most JSON-like records, as the manifest
chooses its own), and a request with no recorded
answer is made, since it may have changed the application, but not compared: each probe lists them under `unobserved` with the reason, and the summary counts them. A live
body the probe did not record compares by status only and is counted as `unobserved_bodies`, unless the answer never
carries one (204, 205, 304, `HEAD`). A browser probe captured without `capture.network.response_body` is refused, as
is one that makes POST, PUT or PATCH calls without `capture.network.request_body`.
Agreement covers only the calls the probes make, after the mapping the answers allow. Values compared by form, clocks
and generated values, can still differ in content, and an equal answer after a write shows the state matched for that
Agreement covers only the calls the probes make, after the mapping the answers allow. Clocks compared by format
and fields normalized under explicit generation rules can still differ in content, and an equal answer after a write shows the state matched for that
and [string escape owner](https://github.com/iBotPeaches/Apktool/blob/18b5e99cb56ff9451e8aa55b065dcf5bbd616975/brut.j.yaml/src/main/java/brut/yaml/YamlStringEscapeUtils.java#L55-L116).
- **The manifest is the decoded text**, bounded at 512 KiB and reported as
truncated when larger.
- **Strings are projected verbatim.** Escaped entities stay escaped, and
@@ -167,6 +180,11 @@ Multi-locale and table-only projection were also verified through real CLI and
stdio MCP workflows on Linux with Apktool 3.0.3/JDK 21 against NewPipe 0.29.1,
ApiDemos 6.0.18 and Appium Settings 8.2.1. Independent XML projection checks,
exact facts/Evidence parity and bounded task costs are recorded in the
[shared-decode and table-only checkpoint](../experiments/analysis-efficiency/apktool-string-tables.md).
[shared-decode and table-only checkpoint](https://github.com/morluto/rea/blob/42e1a17d6e6c0487f17be0bae248553c4caba7f7/experiments/analysis-efficiency/apktool-string-tables.md).
This qualifies selected resource facts, not application execution or independent
binary resource-decoder completeness.
If the selected APK changes while its private snapshot is copied, acquisition
returns `artifact_changed`; request-schema correction cannot recover a stable
snapshot. Launcher spawn permission denial is distinct from a missing launcher,
and configuration diagnostics retain the selected command and system error.
@@ -235,7 +249,7 @@ A `conditional` image is still traced, because it is an in-root candidate
that may load. Every edge below it has `loader_conditional: true`, and a
request that reuses it by install name is `conditional` too. An in-root dylib
with no platform load command remains unknown unless the root is an executable
with observed macOS platform and the candidate’s CPU type is x86_64, i386, or arm64. In that macOS context,
with observed macOS platform and the candidate's CPU type is x86_64, i386, or arm64. In that macOS context,
[Apple's dyld](https://github.com/apple-oss-distributions/dyld/blob/fd8d0c4d52320ebf64db34f3cb280310d905c5ae/mach_o/UnsafeHeader.cpp#L1137-L1145) supplies an implicit macOS platform to legacy dylibs on those CPU
types. The candidate records `platform_basis: "macos-dyld-implicit"`; the
reported slice fields `platform: null` and `platforms: []` remain the parsed
MAIN["src/main.ts + src/main/<br/>MCP server adapter: stdio default, streamable HTTP opt-in<br/>config, session, process lifetime"]
@@ -19,14 +21,14 @@ graph TD
subgraph "Application Layer"
APP["src/application/<br/>Shared CLI/MCP workflows<br/>enhanced analysis and investigations"]
SESSION["SessionProviderRouter + BinarySession<br/>one immutable deep binding per target<br/>disjoint auxiliary routing"]
REGISTRY["AnalysisProviderRegistry<br/>sorted deep candidates<br/>deterministic selection, no fallback"]
REGISTRY["AnalysisProviderRegistry<br/>sorted deep candidates<br/>deterministic selection, no fallback<br/>ProviderInspectionScope: prerequisite observation lifetime"]
RECORDS["src/application/investigation/<br/>composed InvestigationRecords + narrow ports<br/>EvidenceLedger and Unknown ownership"]
SNAPSHOT["BinarySessionRecords + AnalysisSnapshotCache<br/>binary target/profile snapshots<br/>compatibility facade and post-commit notifications"]
SNAPSHOT["BinarySessionRecords + AnalysisSnapshotCache<br/>binary target/profile snapshots and session file ownership<br/>record coordination and post-commit notifications"]
ANDROID_TOOLS["src/adb/ + src/apktool/ + src/jeb/<br/>BYO device, resource-decoding and JEB adapters<br/>owned adb and Apktool processes; JEB engine client over MCP"]
CAPTURE_TOOLS["src/captures/ + src/pcap/ + src/signals/ + src/sqlite/<br/>BYO tshark, pcap, sigrok and SQLite child inspection<br/>selected captures, recordings and databases; owned processes"]
<descid="desc">Three illustrations. A brick-breaker screen with a speaker on each side stands for the DX-Ball sound-pan showcase. A browser window joined by a wire to a clipboard stands for the Notion clipboard-bridge showcase. A ring of 24 dots with one orange dot around a dark centre stands for the TH04 bullet-ring showcase.</desc>
<descid="desc">Three illustrations. A brick-breaker screen with a speaker on each side stands for the DX-Ball sound-pan showcase. A browser window joined by a wire to a clipboard stands for the Notion clipboard-bridge showcase. A ring of 24 dots with one orange dot around a dark centre stands for the TH04 bullet-ring showcase.</desc>
@@ -12,13 +12,20 @@ For request/response bodies and traffic debugging, see
[Fiddler Everywhere captures and MCP](web-network-captures.md#reading-fiddler-captures-saz).
Inspect native SAZ or HAR 1.2 offline with REA, or connect Everywhere's separate MCP server.
HTTP discovery and browser WebSocket inputs require an explicit port. An
explicit default `:80` remains valid and is retained in the canonical endpoint;
omitting the port remains invalid. HTTP `/json/list` discovery preserves usable
siblings when optional metadata is malformed: attachment becomes unknown and
row/field diagnostics appear in `limitations`. Target identity and socket
authority are validated independently before selection and connection.
## Shipped surfaces
- `list_browser_targets` / `rea list-browser-targets` discovers all eligible page targets at the endpoint by default, with an optional exact-origin filter.
- `inspect_web_page` / `rea inspect-web-page` captures DOM structure, accessibility nodes, scripts, resources, safe response/DOM metadata, attach-window network and console metadata, WebSocket frame sizes, workers, quota, and optionally selected storage key names, redacted storage-content fingerprints, or script sources.
- `analyze_web_bundle` / `rea analyze-web-bundle` parses selected script artifacts without execution and derives chunk edges, route and endpoint candidates, vendor fingerprints, static WebMCP declarations, and optionally source-map/original-source evidence.
- `observe_web_session` / `rea observe-web-session` arms an observation window of the requested duration for an external user action and records ordered reload, SPA navigation, redirect, failure, lifecycle, and target-termination metadata.
- `discover_webmcp_tools` / `rea discover-webmcp-tools` uses the experimental CDP WebMCP domain to return every in-scope registration and its complete observed `input_schema` declaration and canonical `input_schema_sha256` digest inline. Declarations are untrusted JSON data, including declared types, required fields, enums, examples and reference URLs. REA does not resolve schema references. These fields replace `input_schema_shape`. Registrations with the same name and URL in distinct observed frames retain separate identities. `tool_key` includes the observed frame ID; it is not a stable identity across navigation or browser sessions. Same-frame registration updates replace that owner only, and removal leaves other owners intact. Declared `readOnly`, `untrustedContent`, `consequential`, and `autosubmit` annotation hints are reported per registration: `true`/`false` are declared values, `null` means the declaration did not provide the hint in that capture, and a missing `consequential` key means the hint was not recorded, either in a historical capture or because the observed annotation was invalid. Consult discovery completeness and exclusions to distinguish these cases. Malformed annotation values or registration stacks retain the registration with incomplete coverage and an `invalid_protocol_value` exclusion. Other malformed protocol payloads can fail discovery explicitly. REA never exposes `WebMCP.invokeTool`.
- `discover_webmcp_tools` / `rea discover-webmcp-tools` uses the experimental CDP WebMCP domain to return observed in-scope registrations and their complete observed `input_schema` declaration and canonical `input_schema_sha256` digest inline. Declarations are untrusted JSON data, including declared types, required fields, enums, examples and reference URLs. REA does not resolve schema references. An omitted optional `inputSchema` is a valid parameterless registration, represented by null schema and digest. These fields replace `input_schema_shape`. Registrations with the same name and URL in distinct observed frames retain separate identities. `tool_key` includes the observed frame ID; it is not a stable identity across navigation or browser sessions. Same-frame registration updates replace that owner only, and removal leaves other owners intact. Declared `readOnly`, `untrustedContent`, `consequential`, and `autosubmit` annotation hints are reported per registration: `true`/`false` are declared values, `null` means the declaration did not provide the hint in that capture, and a missing `consequential` key means the hint was not recorded, either in a historical capture or because the observed annotation was invalid. Consult discovery completeness and exclusions to distinguish these cases. Malformed annotation values or registration stacks retain the registration with incomplete coverage and an `invalid_protocol_value` exclusion. Other malformed protocol payloads can fail discovery explicitly. REA never exposes `WebMCP.invokeTool`.
- `compare_web_captures` / `rea compare-web-captures` compares passive captures or exact-step-aligned browser scenarios. Scenario results commit reproducible literal normalization and expose alignment failures plus artifact-level action, screenshot, DOM, accessibility, URL, history, storage, and event differences. Missing or truncated evidence is never treated as equivalence.
@@ -54,6 +61,57 @@ from a protocol omission. Rejected DOM facts also mark derived URL and agent-hin
metadata incomplete, while valid facts from other nodes and documents remain
available in the capture.
Page network and console coverage starts independently at the first observed
event from that domain or its successful enable acknowledgment. The capture's
lifecycle start is earlier and does not establish domain readiness. Events
received before the enable reply remain part of the observation.
Worker output is a final target-inventory snapshot. `attached` describes any
debugging client, not an REA-owned observing session. The selected page-session
collector does not collect worker-session requests, console events, or scripts,
and workers that disappeared before the snapshot may be missing; worker
coverage is therefore attach-limited. Missing ownership metadata is reported as
`unattributed_target` with unavailable worker attribution, separately
from a proven foreign owner excluded as `out_of_target_scope`. A shared origin
| Renamed WebMCP tool keys/frame IDs with one matching name, owner origin, and frame URL | Compare the registration content; local IDs do not prove change |
| Duplicate WebMCP owners with the same name, origin, and frame URL | Unknown correspondence; complete group count differences still prove change |
| Matching script inventory keys with retained source digests | Compare the retained SHA-256 values even without a producer hash |
| One corresponding script source is unavailable, or neither source nor producer hash is available | Source equality remains unknown; inventory changes and other proven differences survive |
| A partial HTTP response group is a subset of the complete peer | Unknown; omitted repeated responses can explain the difference |
| An observed HTTP response fingerprint is absent from the complete peer group | Changed; omissions cannot explain that retained response |
| A WebSocket connection or frame inventory is incomplete | Do not align retained payloads by position |
Storage fingerprints decode supported CDP primitive/JSON values before hashing.
Debugger descriptions, previews, and remote references do not represent storage
content. Actual JSON properties with those names remain content. Reference-only
objects, unsupported values, and opaque cookie partition identities remain
incomplete. Previously exported fingerprints are not recomputed; recapture both
sides when comparing captures produced across this decoder change.
IndexedDB schema fingerprints with `projection_version: 2` include the observed
database version and object-store definitions. A missing, malformed, or imprecise
version leaves the schema fingerprint incomplete while retaining observed store
facts. Historical fingerprints without this marker covered object stores only:
matching historical hashes cannot establish unchanged database versions, and a
historical hash is not compared with a version-bearing hash. Recapture both
sides for a complete IndexedDB version comparison; other proven storage changes
remain reportable.
Script comparison groups observations by reported URL and compares unordered
content samples. Producer inventory keys include optional metadata, so a changed
key cannot by itself prove script removal or addition. Missing module, length,
language or source-hash facts remain unknown; shared known values and complete
retained source digests can still prove a group change. Partial inventories use
the same omission rule as repeated HTTP samples. WebMCP dropped-tool counts also
prevent equality, and two incomplete owner inventories cannot prove tool
correspondence merely from their different retained registrations.
- `capture_web_screenshot` / `rea capture-web-screenshot` returns a content-addressed visible-viewport PNG.
- `compare_web_screenshots` / `rea compare-web-screenshots` performs bounded local PNG pixel comparison without OCR or external services.
- The CLI comparison commands accept each capture, screenshot artifact or normalization policy as inline JSON or a JSON file path. Use files for screenshot artifacts and scenario captures, whose embedded PNG bytes can exceed the host's command-line length limit.
@@ -97,6 +155,11 @@ preserve these authority and lifecycle differences. They share one exclusion
vocabulary (`BrowserExclusionReason`): every denial reason maps onto it, even
where a wire schema keeps a narrower historical bucket.
Passive page and Inspector capture enable the `Debugger` domain. A target's
`debugger` statement can then pause execution; these observation paths do not
suppress pauses with `Debugger.setSkipAllPauses` or resume the target. Their
lack of explicit pause commands does not guarantee uninterrupted execution.
CDP attachment is not a guarantee that the browser preserves all state.
Chromium can clear another client's `navigator.platform` emulation when REA's
page session disconnects, even if that session sent no emulation commands.
@@ -267,7 +330,11 @@ read as registration state only after domain availability is confirmed.
Discovery is attach-only: the command needs a reachable loopback CDP endpoint
and a target ID from `list_browser_targets`, and it never navigates, reloads,
or evaluates the page. Observe the page in the state you want to measure;
registered tools reflect the document as loaded.
registered tools reflect what the protocol delivered. If an in-scope subframe
already exists when discovery attaches, `webmcp_tools` remains attach-limited:
Chromium replay may omit its older registrations. Later live registrations
retain their frame ownership but do not establish recovery of those missing
descriptors. REA does not reload, evaluate, or invoke tools to fill that gap.
Accessibility names/descriptions, console primitive text, JSON body shapes, WebSocket shapes, script content, and storage key names are selected independently:
@@ -309,6 +376,20 @@ are reported in the result.
Call `list_browser_targets` first because target IDs are browser-instance-specific. REA rechecks the selected target's current type and origin immediately before attaching. Without an origin filter, discovery lists all eligible pages; an individual capture defaults to the selected page's current origin.
REA establishes a main-frame origin boundary before enabling Runtime, Debugger, or Network observation, rechecks it before document capture, and validates it again afterward. If the main frame navigates during final capture, REA discards the mixed result and returns `target_changed`.
An observed navigation also takes precedence over failures from stale
document reads, such as a script ID invalidated by reload; cancellation remains
cancellation. Retry after navigation settles, or refresh target discovery if
the selected page was replaced. Origin-scope refusals from page inspection,
runtime observation, screenshots, and WebMCP discovery explain the permitted
HTTP(S) origin scope and direct the caller to select a permitted document or
explicitly revise `allowed_origins`. Page capture also preserves an observed
main-frame scope violation when a later document read fails. An unresolved
initial main frame does not establish an origin violation; its bounded startup
retries retain a distinct refusal.
Screenshot capture requires a valid main-frame identity. Malformed identity
produces a protocol failure; a readable child frame cannot substitute for the
main frame.
The web-session timeline uses CDP monotonic seconds where the event producer
provides a comparable timestamp; absent or invalid timestamps are `null` rather
@@ -322,31 +403,63 @@ events retain their paired prior-hop response context when the timestamped
next-request event falls inside the window. The pre-arm timeline buffer is bounded
by original CDP message bytes. If clock sampling completes after that budget is
exhausted, the operation returns `payload_limit` instead of a partial window.
Cancellation and clock-request failures retain their own outcomes.
Cancellation and clock-request failures retain their own outcomes. Session
`load_failed` rows require a previously observed main-frame `Document` request;
subresources, child-frame requests and failures without admitted request ownership
are excluded. Redirects reuse their request identity, and completed/failed requests
release it. Active request identity metadata uses the existing 8 MiB retained-event
allowance; exhaustion fails the observation explicitly instead of guessing scope.
## Data minimization
The Link projection parses repeated CDP header field lines independently and
retains their declarations in order, including derived untrusted agent hints.
Commas inside URI targets or quoted parameters remain part of those values.
Response metadata parses repeated CDP header field lines independently. The
Link projection retains their declarations in order. `csp.directives` lists the
directives of every CSP policy in order, across field lines and comma-separated
policies, without recording policy boundaries, so a directive name can repeat
across policies. As in CSP3, a repeated name within one policy is ignored.
Single-valued policy fields combine their lines as one comma-separated value,
as RFC 9110 specifies. Each link keeps its target in `href` and
its relationship context in `context_url` with a separate `context_scope`;
absent `anchor` uses the response URL, while a relative `anchor` resolves
against that URL. Anchored links remain in the projection, but a `link_rel`
agent hint is emitted only when the resolved context matches the response URL
before userinfo credentials are removed. Following [RFC 8288](https://www.rfc-editor.org/rfc/rfc8288.html),
the `rel`, `anchor`, and `type` parameters use their first occurrence, and
quoted-pair escapes are decoded as specified by [RFC 9110 §5.6.4](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.6.4).
The context fields are optional when reading older saved captures. Commas
inside URI targets or quoted parameters remain part of those values.
Well-known-resource hints require an exact supported pathname; path case is
preserved because a case variant may identify a different HTTP resource.
COOP and COEP projections retain the exact declared token after validating the
complete Structured Field Item, including parameters such as `report-to`.
These are declarations, not an assessment of the document's effective policy;
absent, malformed or non-token items project as `null`.
Console entries, WebSocket frame summaries, and selected request/response JSON
shape outputs share one 8 MiB retained-observation allowance per capture. Shape
inference admits expanded path bytes before allocating those paths, including
escaped and Unicode property names. Replacing or removing a request's shapes
refunds their retained charges. A refused body shape preserves network metadata
and any captured peer shape with `resource_budget_exhausted` coverage; a refused
WebSocket frame is counted as dropped rather than reclassified as non-JSON text.
The allowance has no runtime override. Protocol messages and JSON input parsing
remain subject to their separate transport admission; this output allowance does
not bound the whole process heap.
REA retains local observation data and removes only URL userinfo credentials, explicitly declared scenario secrets, and values from structured credential/storage fields:
- URL observations preserve the complete local URL, including query values, fragments, duplicate parameters, and their order. Only username/password userinfo is removed; malformed original URL strings remain available with `origin: null`.
- DOM snapshots retain node types, node names, value lengths, and attribute names, but not text or attribute values.
- Accessibility structure and roles are retained by default, while names and descriptions require `include_accessibility_text: true`.
- Supported DOM URL attributes are projected separately as resolved destinations. Empty `action` on HTML or XHTML forms and empty `formaction` on HTML or XHTML submit controls resolve to the document URL; other relative URL attributes resolve against the captured document base.
- Accessibility structure and reported roles are retained by default, while names and descriptions require `include_accessibility_text: true`. The browser protocol may omit an individual role; that role remains unknown for comparison. Other observed accessibility differences can still establish a change.
- Network observations retain method, status, MIME type, size, type, initiator stack location, and complete URLs with userinfo credentials removed. Redirects reported by CDP are attached as ordered `redirects` on the one request ID, with the prior request URL, CDP response URL, method/type, response status/MIME/encoded length, request timestamp, and the next `requestWillBeSent` event timestamp. CDP delivers `redirectResponse` with that next request event, so the latter is an event boundary rather than an exact response timestamp. Redirect response headers and bodies are discarded; hops outside the selected origins are discarded with the request chain. Headers are discarded after an allowlisted projection of length/encoding, structured CSP/Link/policy fields, and untrusted agent hints. Cookies and authorization headers are never retained.
- Request/response bodies are not requested or parsed by default. When selected, only allowed-origin JSON media types are read, converted immediately to complete value-free typed paths, types and observation counts, and discarded. Each path segment is either `{ "kind": "property", "name": "raw property name" }` or `{ "kind": "array-element" }`; array-element types include primitives and nested arrays. Literal `*` properties remain distinct from array elements. `Network.getResponseBody` is never sent unless JSON body shape capture is selected. A JSON-typed request body that CDP reports through `hasPostData` but omits from `postData`, or that cannot be parsed as JSON, makes `json_body_shapes` unavailable. That request's `body_shapes.status` is `partial`, not `included`, when only its response shape was captured. Comparison uses body shapes only when both captures selected them, and compares request/response shapes only where both observations provide those facts. Unavailable or truncated selected coverage makes equivalence unknown; observed differences still report changed.
- Request/response bodies are not requested or parsed by default. When selected, only allowed-origin JSON media types are read, converted immediately to complete value-free typed paths, types and observation counts, and discarded. Each path segment is either `{ "kind": "property", "name": "raw property name" }` or `{ "kind": "array-element" }`; array-element types include primitives and nested arrays. Literal `*` properties remain distinct from array elements. `Network.getResponseBody` is never sent unless JSON body shape capture is selected. A JSON-typed request body that CDP reports through `hasPostData` but omits from `postData`, or that cannot be parsed as JSON, makes `json_body_shapes` unavailable. That request's `body_shapes.status` is `partial`, not `included`, when only its response shape was captured. Base64 response bytes must be valid UTF-8 before JSON interpretation; invalid bytes leave the response shape unavailable and preserve any observed request shape and network metadata. Producer-decoded strings and genuine U+FFFD characters retain their reported meaning. Comparison uses body shapes only when both captures selected them, and compares request/response shapes only where both observations provide those facts. Unavailable or truncated selected coverage makes equivalence unknown; observed differences still report changed.
For normalized passive inputs with complete request inventories on both sides,
request additions and removals remain observable even when selected body shapes,
response metadata, or WebSocket coverage are unavailable. HTTP request and
WebSocket inventory coverage are evaluated separately; complete HTTP coverage
cannot prove a missing WebSocket connection. Limited request inventory still
prevents request-absence claims. This comparison rule does not make live CDP's
cannot prove a missing WebSocket connection. A missing request in a limited inventory cannot prove absence; a retained
requestabsent from a complete peer can prove a change. This comparison rule does not make live CDP's
attach-limited inventory complete or establish body-shape equality.
An unavailable HTTP resource type also leaves request identity incomplete:
observations with the same method and URL remain possible matches across types,
@@ -361,11 +474,15 @@ REA retains local observation data and removes only URL userinfo credentials, ex
uses `websocket_connections` and `websocket_frames`. Drops in other event kinds
and the aggregate total do not by themselves limit HTTP inventory. Proven
Repeated identical HTTP content samples establish multiplicity changes only
with complete request inventories; limited inventories retain known content
comparisons without interpreting duplicate sample counts as changes.
Repeated HTTP samples retain multiplicity. A partial group that is contained
in a complete peer cannot prove modification, even when the omitted response
had different content. A retained sample absent from the complete peer can
prove modification. Two partial groups cannot establish response
correspondence from their different retained samples alone.
WebSocket stream inventories and connection counts likewise require complete
WebSocket coverage. Redirect resource types use only shared known metadata:
WebSocket coverage. Retained frame positions are compared only with complete
connection/frame inventories; matching direction/opcode sequences alone do
not prove alignment after drops. Redirect resource types use only shared known metadata:
an omitted type leaves equality unknown rather than proving a modification.
- Console observations with a stack source retain call type, argument types, the CDP `Runtime.Timestamp` in milliseconds since Unix epoch, and source location. An absent or invalid timestamp is `null` and makes `console_events` incomplete; an observed zero remains zero. Argument types are listed by CDP argument position. An absent or non-array argument inventory is `null`, and a malformed argument keeps its position as `unknown`; either makes `console_events` incomplete, while an observed empty inventory remains `[]`. A malformed stack or top stack frame is not replaced by its caller: the console event is excluded, and a request initiator location or WebMCP `registration_source` is `null`; each is reported as `invalid_protocol_value`. This epoch-millisecond clock is separate from the monotonic-second timestamps in `observe-web-session`. When console text capture is selected, already-delivered primitive values are retained verbatim with their original `argument_index`; objects, getters, and remote properties are never expanded. Text capture is `unavailable` when the argument inventory is unknown.
- WebSocket observations retain direction, opcode, and payload byte length. A missing or malformed CDP opcode is returned as `null`, with opcode-dependent payload byte length and shape also `null`, and marks `websocket_frames` incomplete. Missing or wrong-typed payload data is not treated as empty; its byte length is `null`, and a text payload shape is unknown. Numeric opcode `0` and an observed empty payload remain distinct from missing data. Opcode is nullable in the public inspection schema, so clients must handle unknown protocol values. When shape capture is selected, text messages are classified as text or complete value-free JSON shape; binary bytes, hashes, prefixes, and raw payloads are never retained.
@@ -377,6 +494,11 @@ Frames, resources, scripts, events, and workers outside the selected origin scop
Retained workers include validated opener-target and parent-frame IDs when CDP
provides them; these relationships do not expand the exact-origin boundary or
prove static module ownership.
Workers without either relationship are withheld with an `unattributed_target`
exclusion and `workers` in `unavailable_sections`: a same-origin URL does not
establish which page owns a worker. A supplied relationship to another target or
frame remains `out_of_target_scope`. Missing ownership also remains unknown when
the worker URL is empty; withheld target details are not returned.
## Completeness and limits
@@ -391,6 +513,14 @@ validation and resource bounds. Omitted script metadata makes its affected
section explicitly truncated.
Disallowed-origin entries are filtered before retention.
Script metadata and selected source reads use one fixed admitted-script snapshot.
New in-scope script IDs still retained when the final CDP read completes are
counted in `scripts.total` and `completeness.dropped_events.scripts`, with
`scripts` marked truncated; they do not extend the source-read pass. Repeated
late events for the same ID count once. The original snapshot is not replaced
or reduced by later updates to an existing ID. These omissions do not imply
that a source byte or time budget was exhausted.
Selected script-source collection shares a 32 MiB aggregate UTF-8 retention
budget and the `command_timeout_ms` deadline (default 20000 ms) across the
capture. The byte budget has no runtime override. An oversized source is
@@ -445,6 +575,12 @@ An explicitly empty MIME type is valid. The optional content size may be absent;
an invalid supplied size remains unknown with incomplete resource coverage while
the resource's other facts are retained. Zero and nonnegative fractional sizes
are preserved.
`resource_key` remains the exact observation identity used by script
reconciliation. Capture comparison groups resources by URL, origin, type and
MIME type, then compares known sizes within a group. If a matched group contains
an unknown size, comparison reports unknown rather than treating the observation
as a resource addition or removal; complete inventory coverage still establishes
when an entire group is absent.
CDP discovery has a 10-second response deadline. HTTP discovery documents
use an 8 MiB budget. Browser-socket discovery (`Browser.getVersion`,
@@ -474,20 +610,61 @@ Network and console coverage starts only after REA attaches and enables the rele
Source maps are not fetched by inspection. Bundle analysis fetches them only when `fetch_source_maps` is selected, with exact-origin redirect checks and no credentials, cookies, or referrer. Each fetch operation uses `source_map_fetch_timeout_ms` (default 30000) and a 64 MiB aggregate streamed-response budget across redirects. The byte budget has no runtime override. A fetch overrun is an item limitation, not a thrown analysis timeout. A deadline or byte-limit failure remains explicitly unavailable and makes bundle completeness partial. Source-map decoding also bounds raw resolved identities to 64 MiB and aggregate inline evidence to 32 MiB. Failed maps preserve their failure context when it fits; if another context cannot fit, collection stops with the full requested count, the returned processed count, and an explicit unknown-results limitation. Retained mappings and original sources are returned inline. See [source-location limits](web-source-location.md) for the structural decoder bounds. Original source artifacts with `.ts`, `.tsx`, `.mts`, or `.cts` suffixes carry `text/typescript`; other source names retain `text/javascript`.
source-map items retain the script's `declared_url` separately from the observed
`effective_url`. successful maps use the latter as their source-resolution base.
failed fetches retain the last response URL observed within the approved origins;
`effective_url` is `null` when no response was observed. query parameters are
A fully read response that fails UTF-8, JSON, mapping, or structural validation
retains `artifact: null`, empty original-source, module-edge, and mapping
arrays, and an explicit failure limitation. Invalid content is `invalid`;
decoder or structural capacity refusal is `fetch_failed`. Its optional
`response_identity` records the complete body's SHA-256 digest, byte count,
and `fetch-response-body-bytes` representation without retaining malformed
text or charging that text to the 32 MiB output budget. These are bytes
delivered by Fetch after HTTP content decoding and before UTF-8 decoding, not
HTTP wire bytes. The identity is absent when the body was not fully read, and
older observations may omit it. A response whose text cannot fit the existing
output budget is likewise `fetch_failed` with text omitted and completed-body
identity; JSON parsing and source-map decoding are not attempted. Successful and partial maps keep their
full text artifacts. Their original text, including an initial BOM or XSSI
line, remains distinct from the parsing view that removes that framing.
Collection reads the body once and does not raise its response or output limits.
When fetching is selected, source-map `excluded` facts preserve the capture
ledger's reasons and counts for declarations rejected before download. No
disallowed URL details are retained or fetched. `requested` and `processed`
count the admitted fetch requests; exclusions are counted separately. Excluded
declarations make the collection unavailable, or partial when maps were retained.
An empty collection with no declarations remains `not_requested`.
If the caller cancels while later source maps are being fetched, the failure's
partial Evidence retains the captured page and every completed map item. Its
`normalized_result.kind` is `web-bundle-acquisition` and
`analysis_status` is `not_performed`: no script-analysis result is claimed.
`source_maps.requested` remains the admitted request count,
`source_maps.processed` counts completed items, and any unprocessed requests
have an explicit unknown-results limitation. Capture exclusions remain in the
same collection. The cancellation error keeps the caller's exact reason;
an already observed response resource or cleanup failure keeps its own error
category and cleanup owner.
Source-map items retain the script's `declared_url` separately from the observed
`effective_url`. Successful maps use the latter as their source-resolution base.
Failed fetches retain the last response URL observed within the approved origins;
`effective_url` is `null` when no response was observed. Query parameters are
preserved, and both URLs count toward the inline evidence budget.
Current fetches emit a string or null; historical observations may omit
`effective_url` without changing their stored content or Evidence identity.
An observed URL must fit before its response body is read. If it cannot fit,
remaining map results are explicitly unknown; failed cancellation retains its
cleanup context and resource constraint.
Indexed maps whose decoded mappings cross the next section's starting position
are invalid under [ECMA-426](https://tc39.es/ecma426/2024/), rather than complete
maps with clipped mapping rows. Fetch collection and source tracing share this
validation.
## Non-goals and threat model
The browser provider deliberately does not expose generic CDP commands, `Runtime.evaluate`, WebMCP invocation, navigation, input, downloads, page closure, or browser closure. Screenshot capture is the sole pixel surface and returns an image only when requested. REA disables the domains it enabled, detaches the target session, and closes only its own WebSocket.
Discovery and attachment errors remain primary if closing REA's socket also
fails. The cleanup failure is reported alongside the original command failure;
it cannot replace the operation diagnostic.
This feature is not a browser sandbox or network containment mechanism. The attached page and browser continue running with their existing privileges and may make external requests independently of REA. CDP gives deep access to the selected browser profile, so use a dedicated profile, include only origins you intend to inspect, and treat other same-user processes as outside this boundary.
@@ -10,27 +10,39 @@ liveness deadlines. `INPUT_JSON` may be inline JSON or a JSON file path.
The minimal request contains only browser launch/connect selection, `start_url`,
and at least one `actions` entry. Launch `headless` defaults to `true` and can
be set to `false` where the host supports a visible browser. Navigations follow
the destinations named by the scenario and the page's ordinary browser requests;
there is no separate origin allowlist or request-interception layer. Environment
the destinations named by the scenario and the page's ordinary browser requests,
and [request steps](#request-steps) send only to the start URL's origin;
there is no separate origin allowlist. Request steps use a temporary dispatch
gate for cancellation; ordinary page requests retain their browser behavior. Environment
settings (including service workers blocked by default), empty storage, and a
final sanitized URL capture are supplied by default. Set
`environment.service_workers` to `allow` when the application requires them.
The connected service-worker policy owner retains its exact CDP transport
through discovery, attachment and restoration. Failed admission preserves its
primary diagnostic when socket cleanup also fails; later policy cleanup retries
that retained transport and clears cleanup uncertainty only after close succeeds.
For attached browsers, `block` rejects captures when the selected page or its
frames are controlled by a service worker or already have a registration,
including after navigation. Existing caller registrations are never removed.
including after navigation. Policy checks bracket each artifact capture, including
the final step. If an external worker takes control while artifacts are being
captured, REA rejects the capture and retains the completed artifacts in
`details.diagnostics.collected_artifacts`; they do not establish policy-compliant
completion. Existing caller registrations are never removed.
Navigation can run destination code before a newly discovered worker is rejected;
that rejection does not roll back browser effects. REA removes its owned
future-document scripts, restores live frame methods, then disconnects.
Add secret declarations, storage seeds, and additional artifact or event
capture only when needed. Action, secret, and storage counts are not capped.
capture only when needed. Missing environment-backed secrets fail as input errors before browser acquisition, naming the declaration and required variable. An explicitly set empty string is a resolved value. Action, secret, and storage counts are not capped.
Duration, action, and navigation timeouts remain separate from CDP command
deadlines. `command_timeout_ms` (default 20000; omit it to keep that default
and leave it out of Evidence) bounds launch startup, the connect-over-CDP
handshake, target lookup, environment commands, and storage CDP commands,
including replies from attached child targets. Set it in the scenario JSON.
including replies from attached child targets. It also bounds the initial
`start_url` navigation through the load event; a redirect or replacement
navigation cannot leave startup waiting indefinitely. Set it in the scenario JSON.
`capture-browser-scenario` has no `--command-timeout-ms` option.
It does not change action `timeout_ms`, `wait_for_timeout.duration_ms`, or
navigation. Service-worker restoration keeps a fixed 5000 ms grace and does
action navigation. Service-worker restoration keeps a fixed 5000 ms grace and does
not inherit a raised `command_timeout_ms`. CDP discovery stays on its own
fixed deadline. When service workers are blocked, the registration check
before discovery has its own fixed 10000 ms deadline; `command_timeout_ms`
@@ -39,6 +51,30 @@ covers endpoint discovery only. The following WebSocket handshake and
`Target.attachToTarget` each use `command_timeout_ms`. `capture.limits` controls retained event and network-content
budgets; it does not change those liveness deadlines.
## Validate a scenario before running it
`validate-browser-scenario INPUT_JSON` checks one scenario against the same
`browserScenarioSchema` refinement that `capture_browser_scenario` admits, and
stops there. `INPUT_JSON` may be inline JSON, a JSON file path, or `-` for
standard input.
```bash
rea validate-browser-scenario ./browser-scenario.json --json
```
A valid scenario reports `{"valid":true,"actions":<count>,"secrets":<count>}`
and exits 0. An invalid one exits 1 and reports the same field paths capture
would report, so a correction made here is the correction capture needs:
duplicate or reserved step IDs, duplicate secret identities and
- A `request` step saves with `save: [{name, json_pointer, secret}]`, from its
own response. A `click` or `press` step saves with `save_response: {method,
path, save}`, from a newly observed matching response while the step waits.
The recorder watches before the action and excludes requests already running,
such as an earlier autosave. Method/path matching does not prove that the UI
caused the request: use a path that distinguishes the intended operation from
background polling. Multiple observed matches before binding fail as ambiguous;
requests starting after this observation window cannot be ruled out. It matches the method and a path on the
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
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
its decoded size is bounded at 12,000,000 bytes or less: its received size,
or the declared Content-Length of one served from cache, times 1032 for each
gzip or deflate coding, the most DEFLATE expands. Other codings and unknown
or zero sizes are refused before materializing the body; decoded text over
the character limit also fails. The UI action may already have applied.
- `{saved:name}` sends a saved value in a request step's `path`, including its
query, and in a `goto` destination's `url`, percent-encoded; a destination's
structured `query` values are sent as declared. A saved value that makes a
path segment `.` or `..`, alone or with the text beside it (including `%2e`),
fails the step, since the URL would drop it. In a request step's `json` body,
a string that is only `{saved:name}` becomes the saved value with the JSON
type it was saved with, so a saved number id is sent as a number, and
`{saved:name}` inside a longer string is filled as text. A header value or
Basic credentials part sends one as `{"source": "saved", "name"}`. Other
braces, such as `{id}`, are sent as written, and so is a percent-encoded
`%7Bsaved:name%7D` anywhere but a `goto` URL, whose parsed form spells the
braces that way.
- Validation refuses a saved value that no earlier step saves. A later save of
the same name replaces the value. An integer past 2^53, which JSON parsing
would round to another number, and a number that is not finite, such as
`1e400`, negative zero, or a value that underflows to zero, such as `1e-400`, fail the step
that saves it.
- A scenario keeps at most 4,000,000 characters of saved values at once,
counting distinct retained redaction spellings, including trimmed variants,
of values saved as secret. Replacing a binding releases its live value
charge, while secret spellings remain protected for the scenario lifetime.
A save past the budget fails before changing the binding.
- A value saved with `secret: true` is redacted however short, as a declared
secret is, as `[REDACTED:page:<step_id>.<name>]`. The selected source
response is protected before retaining its body or header values, including
when only headers were requested. If that body cannot be read safely, its
body and header values remain unavailable. Before publishing the capture,
the selected source transaction's earlier URL, request headers and request
body are also protected using the admitted values. Unresolved source values
withhold that transaction's affected metadata/content with an explicit
limitation. Before publication, retained events are rechecked
with the final marked-response values, including immediate follow-up requests
and their response bodies, console/page errors, WebSocket text and event URL/name fields. Learned redaction facts are independent of source-identity readiness. Unknown source values withhold only the selected
source transaction. Other saved values, such as ids, stay visible, since
environments model them. The environment build warns about saved values
named like credentials that are not marked secret
(`credential-named-saved-values`).
- Page-derived cookie/local-storage values and constructed Basic credentials
remain redacted only from observations made after they were read/built.
They do not retroactively rewrite earlier facts. The final event projection
borrows only declared and response-marked patterns; promotion of an already
held page value to an explicit response secret preserves its first marker.
Projection state is session-local, references admitted pattern/byte owners,
and is invalidated on admission or response classification changes.
- Screenshots are withheld as `missing` from the start when the scenario plans
any response save marked `secret: true`, page-derived or Basic authentication
header values, or whenever nonempty sensitive values
are already known. Raw pixels cannot be safely text-redacted, so the provider
does not request pixels in those cases. This also protects earlier steps and
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
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.
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
@@ -136,14 +220,25 @@ and Claude Code reports that autocompact is thrashing. To avoid this:
`mcpServers.rea` entry in `~/.claude.json` (`$CLAUDE_CONFIG_DIR/.claude.json`
when that variable is set), then restart Claude Code. Setup keeps this
override.
- To remove entire tool families from the upfront catalog, run
`rea setup --client claude_code --tool-families <ids>` with the families the
workflow needs (see [the advertising scope contract](mcp-contracts.md#tool-family-advertising-scope)).
Out-of-scope tools are not advertised and their calls fail with the SDK's
disabled-tool error, so widen the selection when a task needs another
family. Setup writes the scope into the entry's `env` as
`REA_MCP_TOOL_FAMILIES`; rerun setup with a different selection to refresh
it, then restart Claude Code.
The sizes above come from REA's own `tools/list`. A live Claude Code session
against DeepSeek's API is unverified.
For a client whose stdio reader rejects the complete catalog frame, add
`"REA_MCP_OUTPUT_SCHEMA_PROFILE": "off"` to REA's `env` object and restart the
client. This omits only advertised output schemas; REA still validates complete
structured results against its canonical contracts. See [MCP output schema
For a client whose stdio reader rejects the complete catalog frame, set
`"REA_MCP_OUTPUT_SCHEMA_PROFILE": "compact"` to bound every advertised output
schema, or `"off"` to omit them, in REA's `env` object, then restart the client.
Both keep canonical result validation and complete structured results; `compact`
keeps a widened root shape and `off` advertises nothing. On catalogs large
enough that full input schemas alone approach the frame limit, also keep the
input profile at its `compact` default. See [MCP output schema
profiles](mcp-contracts.md#output-schemas).
## Kimi Code
@@ -159,8 +254,16 @@ startup; an explicit Ghidra startup timeout of 2700000 ms produces a 2820000 ms
tool timeout. The startup allowance follows an explicitly selected Ghidra or
Hopper provider, and otherwise uses the larger known Ghidra/Hopper deadline.
An explicit `REA_JEB_MCP_TIMEOUT_MS` deadline, shared by catalog discovery and
each tools/call, also contributes to that maximum. For `ida` or `auto` selection, a valid IDA registration's parsed
each tools/call, also contributes to that maximum. An explicit `REA_GHIDRA_DECOMPILE_TIMEOUT_SECONDS` is added to the Ghidra startup allowance, because a single-decompile call can import the target and then decompile up to that limit; setup forwards it into the registration. For `ida` or `auto` selection, a valid IDA registration's parsed
`timeoutMs` also contributes to that maximum; its default is 300000 ms.
The derived value is a single-decompile estimate, not a deadline for an
unbounded batch. For example, startup 330 seconds plus two 600-second
decompiles and 120 seconds of headroom needs an estimated 1650 seconds,
before any additional listing or output work. Select the client tool deadline
for the intended workload, split `batch_decompile`, use `decompile_all`
limit/resume, or reduce `trace_native_values``max_functions`. The trace can
decompile several functions serially; its depth and graph budgets do not
make the single-decompile allowance a whole-traversal deadline. Existing positive caller deadlines are preserved.
Setup forwards these explicitly selected REA deadlines and the input schema
profile into the registration; unrelated process values are omitted. An
explicit `REA_JADX_OPERATION_TIMEOUT_MS` is forwarded with the JADX
@@ -168,6 +271,20 @@ registration but does not contribute to the derived tool timeout; raise
`toolTimeoutMs` to cover a longer selected JADX deadline.
This headroom is a practical default, not a guarantee for every analysis
duration. Setup preserves positive timeout values already in the `rea` entry.
Setup also forwards explicitly selected input/output schema profiles,
`REA_MCP_MAX_RESPONSE_BYTES`, provider paths and supported Ghidra, JADX and Kuna
settings. It also forwards explicit executable and resource selections for ADB,
apktool, packet capture, GDB/Rizin/objdump, Cutter, WABT, Wakaru, firmware and
signal tools, browser inspection, and pwntools/pwndbg. This includes their
supported prlimit overrides, Darwin Swift compiler/SDK/module-cache selections,
and compile timeout, logging level and explicitly configured reference-secret
patterns. A provider being unavailable does not discard its selected paths;
doctor reports its readiness separately. Explicit selections override discovered
defaults, including when setup runs again with a changed selection. Unrelated
environment variables, process ownership tokens and one-shot target paths are not
| [Domain definitions](https://github.com/morluto/rea/blob/main/src/domain/analysisSettingDefinitions.ts) and [types](https://github.com/morluto/rea/blob/main/src/domain/analysisSettings.ts) | Exact setting IDs, value types, shared bounds/defaults, units, provider/operation associations, application points, and structured limit metadata. Numeric constants stay with their domain owner. |
| [Launch parser](https://github.com/morluto/rea/blob/main/src/config/analysisSettings.ts) | Parse selected launch values once, preserving an invalid value as a typed configuration failure rather than substituting a default. |
| [AnalysisSettings](https://github.com/morluto/rea/blob/main/src/application/AnalysisSettings.ts) | Own one runtime's launch baseline, immutable override revisions, atomic updates, inspection, and accepted-operation snapshots. It does not own provider lifecycle or cleanup. |
| [Composition](https://github.com/morluto/rea/blob/main/src/main/eagerRuntime.ts) and [typed configuration views](https://github.com/morluto/rea/blob/main/src/config/runtimeAnalysisSettings.ts) | Inject the same settings reader into providers and workflows; translate overrides into the configuration each consumer understands. |
| Provider or resource owner | Resolve the effective budget, enforce it at the applicable boundary, and attach the actual value and known source to failures. |
| [MCP registration boundary](https://github.com/morluto/rea/blob/main/src/server/EvidenceMcpServerCore.ts) | Enter the operation's settings scope before invoking its handler. |
| [Settings contracts](https://github.com/morluto/rea/blob/main/src/contracts/analysisSettingsContracts.ts) and [tool registration](https://github.com/morluto/rea/blob/main/src/server/registerAnalysisSettingsTools.ts) | Validate named requests and deliver inspection/update results without requiring an open target or healthy analysis provider. |
The normal path is: composition creates the store, an MCP handler captures its
current revision, and providers read that snapshot when resolving budgets.
If an owner rejects work, it reports the effective limit through the shared
error projection. A subsequent settings update publishes a new revision for
later handlers. It does not reach into the failed operation or retry it.
### Accepted-operation snapshots
`AnalysisSettings.run()` installs the current immutable snapshot in
`AsyncLocalStorage`. Its `read` function returns that snapshot inside the
operation and the latest revision outside it. Providers depend on the reader
contract rather than on the mutable store or an ambient environment lookup.
Acceptance here is entry into the registered handler's settings scope, not
arrival of bytes at the MCP transport. Work queued or awaited within that scope
keeps its snapshot. Deferred server initialization must still dispatch through
@@ -53,7 +53,7 @@ Every collection supports `fields`, `offset` and `limit`; its stable row ID is
always included. Selection changes delivery, not source inspection. Pages keep
source coverage and parent Evidence links. Page exhaustion does not establish
absence in a partial source. Complete Evidence remains accessible through
`get_evidence` and Evidence bundle export.
`get_evidence_bundle` and Evidence bundle export.
The summary's `probe_issues` counts files with reported issues and their retained
issue entries. It previews at most two such files, including stable `file_id`,
@@ -97,17 +97,18 @@ same bundle. Export writes only the caller-selected output file.
| Unity Mono | A managed assembly below `*_Data/Managed` or `Contents/Resources/Data/Managed` has an exact UnityEngine assembly reference. |
| Unity IL2CPP | A recognized IL2CPP metadata magic (with the raw version when complete) coexists with a conventionally named native `GameAssembly.dll`, `GameAssembly.so`, `GameAssembly.dylib` or `libil2cpp.so` image. Build correspondence remains unknown. |
| Godot | A `GDPC` header at file start or a validated executable trailer offset. |
| GameMaker | A bounded `FORM` container starts with a `GEN8` chunk. |
| GameMaker | A bounded `FORM` container starts with a `GEN8` chunk. The scan probes conventional `data.win`, `game.unx`, and `game.ios` data files for that header. |
| Unreal | `Content/Paks` path conventions or an IoStore TOC signature; arbitrary `.pak` filenames are insufficient. |
| Electron | A `resources/app.asar` or `resources/default_app.asar` path convention; archive validity is unverified. |
When the four-byte metadata magic is present but version bytes are incomplete,
the fact retains `raw_version: null`; it does not offer an IL2CPP metadata
inspection probe. A complete magic/version prefix with supported raw version 29,
31 or 39 offers an
`inspect_il2cpp_metadata` follow-up at its admitted file path, including when no
native library was found. This probe does not establish full metadata validity
or correspondence to a native binary. See [IL2CPP metadata](il2cpp-metadata.md).
inspection probe. A complete magic/version prefix with supported raw version
24, 27, 29, 31 or 39 offers an`inspect_il2cpp_metadata` follow-up at its
admitted file path, including when no native library was found. This probe does
not establish full metadata validity or correspondence to a native binary;
version 24 inspection still applies only to supported header layouts. See
[IL2CPP metadata](il2cpp-metadata.md).
Candidates are derived or inferred from these facts and do not prove loading or
execution. BepInEx, MelonLoader, Easy Anti-Cheat and BattlEye labels identify
Inspection does not retain DOM values, execute renderer code, navigate, click,
invoke Electron IPC, close a target, or terminate the application.
@@ -100,6 +140,8 @@ window-targeted renderer reload/crash actions, and synthetic `open-url` or
WebContents identities, process metrics, and IPC channel and value-shape metadata.
Payload values are not retained.
`window_index` selects from Playwright's current Page list at the start of each action. REA resolves that Page to its corresponding BrowserWindow once; the action's `target` uses the BrowserWindow's capture-scoped `window_id`, matching the window inventory. Reordering either enumeration after selection does not retarget the action. Handle cleanup failures retain the completed action records and remain owned for provider cleanup retry.
Run the real fixture verifier with an operator-provided Electron runtime:
```bash
@@ -124,8 +166,10 @@ native-addon, process, and IPC timeline events. IPC channels and argument-shape
metadata retain their observed lengths; payload values are never retained.
Renderer crash/restart and deep-link actions are synthetic
scenario controls; their attempted and observed outcomes remain in the
timeline. The active hook blocks and records external shell/navigation,
permission, download, popup, updater, and OS-integration effects. The timeline
timeline. The active hook blocks and records the shell methods listed below
and selected navigation, permission, download, popup, updater, and
OS-integration APIs. These method patches do not contain direct filesystem,
network, native-addon, or other unpatched target effects. The timeline
is explicitly partial when attachment starts after application activity. The
startup, including the initial state snapshot, has a 60-second deadline.
Actions wait until completion or request cancellation; a click whose target
@@ -134,11 +178,14 @@ window, remains pending until cancelled. After cancellation, the final state
read has 5 seconds before REA keeps the initial snapshot instead; the
cancellation keeps the caller's reason and records that expiry in its
diagnostics.
Blocked synchronous shell APIs keep their return contracts:
The shell policy is owned by `blockedShellResults` in
`scripts/electron-active-hook-boundaries.cjs`. Its synchronous blocks are:
`showItemInFolder` returns `undefined` and `writeShortcutLink` returns `false`.
Their `shell-attempt` events record the blocked phase and argument shapes;
neither result means the requested host operation occurred. The existing
`openExternal` and`openPath` blocks continue to reject their promises.
`openExternal`,`openPath`, and `trashItem` blocks reject their promises.
The `trashItem` block prevents that call from reaching the OS trash operation;
it does not intercept other ways the application can remove files.
CLI SIGINT/SIGTERM requests cancellation and awaits owned-process cleanup.
Window IDs, URLs, and cached titles come from one main-process Electron snapshot,
so a crashed renderer does not require a successful renderer-side title query.
@@ -152,6 +199,15 @@ If cleanup cannot be verified, the error retains collected observations in
`details.partial_observation` and marks their application cleanup `unverified`.
Cleanup uncertainty does not authorize signaling unrelated processes.
On Linux, Chromium-based processes can overwrite the initial environment memory
exposed through `/proc/<pid>/environ`. The environment may be readable while
`REA_PROCESS_RUN_ID` is absent, even if the application still sees it through
`process.env`. REA reports the missing marker and leaves lineage ownership and
cleanup unverified; the PID, executable, or parent relationship cannot replace
that ownership proof. This limitation can affect owned Electron captures on
native Linux as well as WSL. It does not establish that all Electron versions or
Linux environments behave the same way.
Main-process IPC recording keeps original-function removal for `on` and `once`
registrations and records a fired `once` callback once. Native Node.js owns
`once` registration, firing and callable dispatch as well as removal order and
@@ -218,7 +274,9 @@ initialization, the hook leaves listener callbacks unwrapped and records a
callback and receiver; callback execution remains unobserved. This comparison
assumes Node's EventEmitter prototype has not itself been globally decorated
before hook initialization. The provider loads the hook before the application
and excludes `NODE_OPTIONS` from the child environment.
and excludes `NODE_OPTIONS` from the child environment. It preserves selected
`DISPLAY`, `XAUTHORITY` and `WAYLAND_DISPLAY` values, including the caller-selected
X11 authorization-file path.
An opaque later listener or unsupported emitter state can prevent proof of
removal order. The hook then delegates removal
@@ -247,8 +305,13 @@ capture provides them.
ASAR observation reads the header through one open file handle and validates its
declared lengths against the archive size. Header/index admission is the same
budget used by static ASAR reads: 16 MiB / 16777216 bytes by default, or
`REA_ASAR_MAX_HEADER_BYTES` (at most 256 MiB) when set. An oversized header is
budget used by static ASAR reads: 16 MiB / 16777216 bytes by default, seeded by
`REA_ASAR_MAX_HEADER_BYTES` (at most 256 MiB). In MCP,
`update_analysis_settings` can override `asar.max_header_bytes` for new
operations without restarting REA. Cached headers are checked against each
operation's admission, including after a decrease. See the
rea inspect-analysis-view '{"source":{"kind":"evidence-file","path":"/reports/app-beam.evidence.json"},"view":{"kind":"beam","collection":"imports","modules":["erlang"]}}' --json
```
The bundle retains the complete report. Subsequent MCP queries may use
`source: {kind: "retained-evidence", evidence_id: parent_evidence_id}` or an
Evidence file. Retained and offline views still work after the original BEAM
file is deleted. Supplying `view` requires `detail: "summary"`; omitting it
returns only the structural summary. Selection changes delivery, not parsing or
coverage, and executes no bytecode.
## Limits and failures
The selected file is limited to 64 MiB by default (512 MiB maximum). At most
@@ -6,6 +6,8 @@ For remote devices, pass a host with an optional port (`host[:port]`; bracket IP
MCP exposes `list_frida_devices`, `list_frida_processes`, `start_frida_session`, `load_frida_script`, `resume_frida_session`, `unload_frida_script`, `frida_session_status`, and `close_frida_session`. A spawned process starts paused so scripts can load first. Closing unloads session scripts and detaches. If a spawn remains paused, REA resumes it only after script cleanup or session detach confirms the instrumentation is released; if both cleanup paths fail, the target stays paused and the cleanup error is retained. REA never kills the target. MCP sessions end with the server process. The one-shot CLI command `instrument-with-frida` accepts one inline script or script file, observes messages for a bounded duration, and returns Evidence with the source hash and captured messages.
`instrument-with-frida --json` returns the Evidence record directly, matching MCP. Consumers of the earlier `{evidence, cleanup_error}` CLI wrapper should read the record at the JSON root and the session cleanup observation at `normalized_result.cleanup_error`. If final provider cleanup fails or cancellation arrives during it, the typed error retains completed Evidence in `details.partial_observation`. Discovery commands retain their device or process report in the same field.
For state and capture-coverage checks, pass `{"session_id":"SESSION_ID","detail":"summary"}` to `frida_session_status`. Each call reads the observed session state and retains the complete observation. The reply is an `inspect_analysis_view` Evidence summary with the session identity, state, scripts, `messages_retained`, and `messages_truncated`; message payloads remain in its `parent_evidence_id`. The count covers retained queued messages, not every target event. Omitted `detail` or `detail=complete` preserves the existing complete reply.
A summary's selected fields look like this (excerpt):
@@ -15,7 +15,31 @@ snapshot parser and a separate optional annotation extension. Check the
[release boundary](installation.md#released-package-and-main) when using npm.
See [import language and analysis seeds](installation.md#ghidra-import-language-and-analysis-seeds)
to override the header-detected language or seed analysis.
to override the header-detected language or seed analysis. An override that conflicts with a fixed raw, DOS, PSP, MIPS, RISC-V or GameCube DOL import
is a configuration error naming the conflicting settings. It does not make an
otherwise admitted target unsupported; REA preserves the requested settings.
An inaccessible language
catalog remains a read failure; it does not prove that a configured language is
undefined. Installation `application.properties` has a fixed 1 MiB read allowance
with no runtime override. The failure retains that allowance and directs recovery
at the selected installation metadata.
Retained process diagnostics can report termination by `SIGKILL`; the signal alone
cannot establish an OOM kill. REA gives neutral recovery guidance and preserves the
signal. Confirm resource causes from process output or host/container records;
operation-scoped JVM `OutOfMemoryError` observations retain their separate resource
classification. Automatic kernel or cgroup OOM attribution is not implemented.
After the authenticated startup handshake, rejected inputs (`invalid_request`,
`not_found`, `ambiguous`, or an invalid function name) use
`diagnostics.diagnostic_scope: "request"` when their active output checkpoint is
available. They preserve the active request's
`failure_output`, target/profile identity and runtime/log coordinates, while
omitting cumulative launcher stdout/stderr and launch-support output. Startup,
process, protocol and other remote failures retain full session diagnostics.
The Ghidra client still owns its bounded cumulative output; this projection does
not clear it or alter session readiness. Log paths refer to the owned ephemeral
runtime and are removed by normal cleanup.
Provider selection and profile identity follow
[MCP contracts](mcp-contracts.md#identity-and-discovery). One deep
@@ -23,6 +47,18 @@ provider stays bound to the target; runtime failure never selects another
provider automatically. The contracts below describe Ghidra observations,
not equivalence with another engine's pseudocode or analysis database.
## Request payload ceiling
Ghidra requests use `REA_BRIDGE_MAX_REQUEST_BYTES`: default 16 MiB, with a
configurable range of 7,464–536,870,887 bytes. REA measures UTF-8 JSON, including
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.
This setting is enforced by the REA client; the Java bridge has no corresponding
request ceiling.
## Admitted inventory semantics
| Concern | Ghidra contract |
@@ -135,6 +171,43 @@ have no file backing. ELF mappings are observed
without independent format-specific load-image verification, as the result's
status and limitations state.
For large relocation inventories, select MCP `inspect_native_load_image` with
`detail: "summary"`. It returns verification state, observed identity and counts,
while retaining complete Evidence. Use `normalized_result.parent_evidence_id`
with `inspect_analysis_view` and a view such as:
```json
{
"kind": "native-load-image",
"collection": "relocations",
"offset": 0,
"limit": 32,
"fields": ["address", "status", "type"]
}
```
Collections are `source_files`, `mappings`, `relocations`, `entry_points`,
`entry_context`, `checks` and DOL `sections`. Optional
`indices` select original row indices before paging; empty indices select none.
Fields are collection-specific. Relocation defaults omit byte payloads; check defaults omit potentially large `expected`/`observed` inventories. Request those fields explicitly when needed. Other collections default to all fields. Metadata recovery remains counted and retained in complete parent Evidence.
Parent Evidence, collection and `source_index` identify a row, including same-address
relocation alternatives. Null counts or rows mean unrecorded or inapplicable;
they never establish an empty observation. Exhausting a page does not upgrade
unsupported verification or runtime coverage. Pages query immutable retained
facts without reopening the target or repeating Ghidra work.
Each page carries the source's structured `verification_status` independently
of its page coverage.
CLI summary delivery requires a complete Evidence bundle:
```sh
rea inspect-native-load-image <path> --provider ghidra --detail summary --evidence_output /new/load-image.json --json
```
Read selected pages later through `inspect-analysis-view` using the returned
parent ID and an `evidence-file` source pointing to that bundle. Complete
delivery remains the default in both adapters.
An unsuccessful numeric procedure lookup reports the current Ghidra image base
and gives the CLI commands above alongside the corresponding MCP operations.
Repeat any target-format, architecture, and entry-point options used to open the
@@ -162,7 +235,7 @@ profile stages before retrying their retained descriptors.
| Decompiler lifetime | One persistent `DecompInterface` is opened for the imported Program and disposed during bridge shutdown. Native decompilation has no fixed per-function deadline. External functions or functions without bodies return `null`; cancellation and native failure remain distinct. |
| Decompiler lifetime | One persistent `DecompInterface` is opened for the imported Program and disposed during bridge shutdown. Native decompilation has no fixed per-function deadline unless the launch setting `REA_GHIDRA_DECOMPILE_TIMEOUT_SECONDS` or runtime override `ghidra.decompile_timeout_seconds` sets one; a decompile that reaches it fails only that request with `remote_code``decompile_timed_out`, the Program and session stay open, and the next decompile uses a fresh decompiler process. External functions or functions without bodies return `null`; cancellation and native failure remain distinct. |
| Serialization | A FIFO sends one Program request at a time. Caller cancellation removes queued work promptly and is passed to active socket waits. This is an adapter safety commitment, not a claim that every Ghidra API is thread-safe. |
| Function identity | Every function result carries the entry address and Ghidra FunctionManager classification for external, thunk, and resolved thunk target. These are observations, not proof that unresolved targetless calls have been recovered. |
| Assembly and pseudocode | Assembly is complete Ghidra Listing text; pseudocode is Ghidra decompiler output. Neither is original source, and cross-provider comparison never treats Hopper and Ghidra text as equal or unequal semantic facts. |
@@ -172,6 +245,13 @@ profile stages before retrying their retained descriptors.
| P-code value flow | Function dossiers include up to 3,000 high-p-code operations, at most 64 inputs per operation, and 12,000 def-use edges. Results identify memory reads/writes, branches, and calls by p-code opcode, and mark decompiler-dead operations. Large results report truncation, an omitted-operation lower bound, and known omitted-input/edge counts. The dossier is an intra-function graph; `trace_native_values` composes derived parameter/argument and return/output dependencies across resolved calls. It does not resolve memory aliasing, call side effects, runtime behavior, persistent state, or business meaning. |
| Result extent | Function instruction scans and native API boundary observations remain complete. P-code flow is the explicit bounded exception; its count fields distinguish exact retained counts from lower-bound or known-omitted counts. Caller cancellation and provider failures remain distinct. |
Runtime updates apply to newly accepted operations on the existing Program.
They preserve accepted budgets and do not clear cleanup blockers or change the
client deadline. Transient decompile timeout failures remain uncached so the
same function can be retried after raising the limit. See the
[settings design](design/limits-and-recovery.md) for snapshots, precedence,
and provider integration.
Function extents and instruction completeness refer to Ghidra's analyzed body.
An inferred no-return call can terminate that body before subsequent bytes.
Pseudocode, assembly, procedure info, instruction windows, incoming and outgoing
@@ -257,3 +337,9 @@ next match. Coverage can overlap between pages; do not sum it as unique memory.
page. These blocks are never searched. Cancellation returns a typed error,
discards the active Ghidra database, and does not return a successful partial page.
Hopper byte search remains unavailable until its implementation is verified.
`--evidence_output` is required for CLI summary delivery and never overwrites an
existing file. The default CLI/MCP reply remains complete.
[Measured workflows](../experiments/analysis-efficiency/go-build-views.md) include
[Measured workflows](https://github.com/morluto/rea/blob/42e1a17d6e6c0487f17be0bae248553c4caba7f7/experiments/analysis-efficiency/go-build-views.md) include
catalog repetition and extra calls. Identity/count questions benefit from a
single summary. In the tested Codex full-catalog configuration, a compound
question about identity and one dependency uses fewer tokens in captured request JSON with
@@ -112,8 +118,28 @@ module record and no dependency records has an observed empty dependency list.
The built-in TypeScript reader supports ELF, PE and thin Mach-O images, and one
selected slice of a universal Mach-O, with Go's inline or historical pointer
build-info encoding. Source ranges refer to the original stable file snapshot,
including pointer-backed strings. It does not scan arbitrary byte strings as
compiler metadata.
including pointer-backed strings. The shared native container owns address
mapping, including file-backed PE headers. A descriptor or string can cross
adjacent mappings when their virtual addresses map to physically contiguous
file bytes with the same translation. Gaps, conflicting aliases, zero-fill
aliases and noncontiguous string source bytes cannot establish a single source
range and are refused. Native export C strings use the same mapping checks but
can join multiple source chunks because their result has no single-span source
contract. Legacy pointer-backed fields are decoded at
the width declared by Go's build-info record, independently of the image's ELF
class. It does not scan arbitrary byte strings as compiler metadata.
Legacy string descriptors and contents may use the declared file-backed PE
headers. A descriptor or string may also cross adjacent loader mappings when
their virtual ranges cover every requested byte and identify one contiguous
| Gaps between regions | Separate regions; never zero-filled |
| Out-of-order records | Sorted into regions |
| An address written twice with the same value | Accepted and counted in `duplicate_bytes` |
| An address written twice with different values | Fails, naming the address and the line spans of both writes |
| Checksum mismatch, odd hex length, non-hex character, byte count disagreeing with the line | Fails with the line, declared and computed values, and record type |
| Line longer than 521 (Intel) or 514 (S-record) characters, excluding the line ending | Fails before the line is decoded |
| Intel type `06` or higher, `S4`, wrong fixed length for Intel `01`–`05` or `S5`–`S9` | Fails |
| Missing Intel `01` or `S7`–`S9` | Regions are returned; coverage is unknown and the file may be truncated |
| A non-blank record after termination, or a second `S0` | Fails; blank lines are allowed anywhere |
| `S5`/`S6` count different from the data records before it | Fails |
| Termination type not matching the data address width | Reported as a limitation; the declared fact is kept |
| Conflicting repeated `03`/`05` start records | Fails; identical repeats are allowed |
| An Intel data record whose 16-bit offset wraps past `0xFFFF` | Fails: producers disagree on whether the address wraps or continues linearly |
| I16HEX data above `0xFFFFF`, or data crossing the S1/S2/S3 address width | Fails |
Lowercase hex, LF and CRLF line endings, and trailing spaces or tabs are
accepted. A CR not followed by LF is an invalid character. Failures apply to
the whole file and return no partial regions.
## Limits
The file must be at most 128 MiB. Every data byte needs two hex digits, so the
decoder reserves at most half the file size for decoded bytes before reading,
and stores only written addresses. The decoder retains at most 65,536
address-discontiguous record runs before merging them into regions. A run is a
sequence of consecutive records whose addresses continue each other. Both are
fixed resource bounds, not format limits, and fail as limits (`file-size` and
`capacity`) with no runtime override. Configurable ceilings are tracked in
[#6176](https://github.com/morluto/rea/issues/6176). The line-length limits are
the one-byte record count: Intel HEX allows 255 data bytes, while S-record
counts include address and checksum bytes.
Decoded regions are cached only for the reader's lifetime. Each open checks
its admitted carrier identity again. Region streams copy at most 64 KiB per
chunk, so consumers cannot mutate cached bytes and opening a large region does
not copy it in full. Caller cancellation keeps its exact reason, and closing
the reader waits for active region streams to close.
## Analyzing a region
Inventory does not establish the CPU, byte order or memory map, or that a
declared start address is executable. To disassemble a region, extract it and
open the region file with `open_binary` using format `raw-binary`, an
architecture you choose, and `entry_point` set to the region start address;
raw-binary maps file offset 0 at `entry_point`. Each region is opened
separately, so references between regions are not resolved. A caller-selected
Ghidra language and base address for raw-binary imports is tracked in
@@ -80,6 +80,71 @@ Native MCP 1.1.2 can navigate in the previously focused pseudocode tab when swit
Native tool observations retain actual tool names and complete JSON text. Upstream `structuredContent` can be a shortened preview even while text contains the full result. REA reads the full native representation and rejects missing/malformed text instead of treating previews as complete observations.
### Migrate a legacy attached registration
Both attached profiles remain supported. Migrating replaces the upstream server;
adding `"protocol": "native"` to a legacy Python proxy registration is insufficient.
The native plugin is separate from mrexodia/ida-pro-mcp, and upgrading mrexodia to
its modern tool catalog does not select this profile.
1. Back up the working registration file. Install and start the native plugin
using its [upstream instructions](https://github.com/0xshlomil/ida-free-mcp).
IDA and the plugin are bring-your-own; REA does not install or build them.
Use a build with the navigation correction described above, and restrict its
listener to loopback or apply the documented host firewall restriction.
Stop the legacy endpoint first if both servers would use the same port.
2. Open the same original input binary in IDA and wait for analysis. Keep that
file readable by REA. The native metadata resource must report its recorded
input SHA-256; the resource's `path` identifies the database, not an input
file to substitute. Universal Mach-O inputs still require a thin extraction.
3. Replace the registration, using the native plugin's actual local endpoint.
For example, this legacy registration:
```json
{
"mode": "attached",
"command": "python",
"args": [
"/absolute/path/to/ida_pro_mcp/server.py",
"--ida-rpc",
"http://127.0.0.1:13337"
]
}
```
becomes:
```json
{
"mode": "attached",
"protocol": "native",
"url": "http://127.0.0.1:13337/mcp"
}
```
Keep `REA_IDA_MCP_CONFIG` pointing at the replacement file and close/reopen
the REA binary session to connect with it. If changing the environment's
configuration path, restart the MCP server as described above. Do not reuse
the legacy RPC URL as an MCP HTTP endpoint.
4. Check `binary_session` availability before resuming workflows. Direct
`procedure_callers` becomes unavailable and dossier callers remain unknown;
incoming address xrefs do not establish direct call edges. Native strings
use C-string rendering. Assembly and instruction reads no longer navigate
the GUI; native pseudocode still changes focus and closes existing
pseudocode tabs. IDA Free decompilation may require cloud access and consent.
5. Run the [real-provider verification](#verification) with two distinct
functions and the required second-function marker. Supply independently
known string and xref oracles for those checks. Existing Windows evidence
covers IDA Pro 9.3 with the documented source build and listener change;
it does not establish stock-plugin, Windows Free, or native macOS behavior.
A valid registration or successful doctor check alone does not verify the
connection, target identity, or function switching.
REA continues to verify identity and image base around requests and closes only
its connection, preserving the attached database. Restore the backed-up legacy
registration and its upstream endpoint to return to the legacy profile.
The legacy producer moves the active GUI as a side effect: assembly and raw function instructions jump to the function, and successful pseudocode opens or reuses a pseudocode view. A function dossier does both. Native GUI decompilation also changes the active view. `binary_session` reports these operations with `effects.may_show_ui: true`; headless operations and the other attached operations report `false`.
## Give REA a target for headless analysis
@@ -108,7 +173,14 @@ Headless REA and the configured supervisor must share the host filesystem and na
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.
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. Ensure it has space for the input copy and IDA working files.
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.
Readiness and allocation check the selected spelling with native
alone can collapse `file/..`. Diagnostics retain the selected spelling; private
input paths use the canonical parent for upstream identity checks.
When a completed `idb_open` response reports success or is otherwise ambiguous, but no active owned private worker can be verified, REA retains the private workspace even if `idb_list` appears empty. A later close can retry verification if the original owned worker becomes discoverable. A completed explicit `idb_open` rejection retains the existing no-worker cleanup path. This is a local admission/ownership safeguard and **does not** provide a process-termination receipt or change the legacy reaped-worker protocol.
@@ -133,7 +205,7 @@ Add the registration path to the **REA** MCP entry's environment, keeping the up
}
```
Use a package version that actually includes this adapter; repository main can be ahead of the npm release. After reconnecting, call:
Use a package version that actually includes this adapter; repository main can be ahead of the npm release. After reconnecting, call the sequence below; the default `analyze_function` reply is a summary that retains the dossier, so add `"detail":"complete"` when the dossier itself must come back inline:
@@ -168,4 +240,38 @@ The verifier requires the resolved procedure in both inventory and procedure sea
The initial real workflows use stdio registrations for the legacy Windows GUI profile and a Windows x64 headless supervisor with IDA 9.3. The headless workflow has also passed on macOS arm64 with IDA Professional 9.1 (build 9.1.250226) against the same upstream commit `c133c3853faa111a9b00ee615c013b720d0c4acd`, using a source-built arm64 Mach-O fixture; Mach-O C symbols carry a leading underscore, so the procedure name is `_rea_fixture_add`. Streamable HTTP is tested against a loopback MCP fixture with the pinned client SDK; a real IDA HTTP-supervisor workflow remains unverified. Linux headless engine operation, other IDA releases, architectures, and modern attached GUI tools require their corresponding real workflows before support is claimed.
Native Windows verification uses IDA Pro 9.3 with the public two-function fixture and Windows `whoami.exe`, using upstream `c9d15d98e8a143fc74f6e14037c48f63889b6d6c` with a loopback-listener change. It covers production CLI/MCP parity, distinct-function switching, identity and connection cleanup. See the [correctness and performance measurements](https://github.com/morluto/rea/blob/main/experiments/analysis-efficiency/ida-native-windows.md). This follow-up did not run Windows IDA Free or native macOS.
Native Windows verification uses IDA Pro 9.3 with the public two-function fixture and Windows `whoami.exe`, using upstream `c9d15d98e8a143fc74f6e14037c48f63889b6d6c` with a loopback-listener change. It covers production CLI/MCP parity, distinct-function switching, identity and connection cleanup. See the [correctness and performance measurements](https://github.com/morluto/rea/blob/a2e2c29b59e8775b0e6aedb09a9eb16adf32646b/experiments/analysis-efficiency/ida-native-windows.md). This follow-up did not run Windows IDA Free or native macOS.
Headless readiness distinguishes an explicit `auto_analysis_ready: false` from
unknown readiness (`null`). The former returns a retryable capability refusal
with wait-and-retry guidance; the latter asks for upstream readiness inspection
without claiming that analysis is running. Neither is malformed protocol output.
An unusable `workspaceRoot` reports its directory constraint as a configuration
error before opening an IDA worker. Native JSON metadata resources accept omitted
media types and normal case/parameter variants of `application/json`; their
resource URI, JSON structure and recorded target identity remain checked.
The public profile's registration digest excludes HTTP authentication header
values (`Authorization`, `Proxy-Authorization`, and `Cookie`). Mark any other
credential fields explicitly with `"sensitive": { "headers": ["X-Api-Key"],
"env": ["PRIVATE_VALUE"] }` in the registration. Header names match without
case; environment names match exactly. These values are also redacted from IDA
diagnostics. Ordinary fields such as `IDADIR` and noncredential headers remain
part of analysis identity. Credential rotation does not change that public
identity; each newly resolved client factory still captures its own complete
transport registration and creates a fresh connection.
Caller cancellation is classified at the MCP request boundary using the installed
SDK's exact abort outcome. A later abort during error unwinding does not replace
an established provider failure. Cancellation retains the caller's original reason
and collected diagnostics; metadata timeouts name the requested analysis operation
while retaining the resource-read failure as their cause. This request cancellation
does not authorize saving or closing an attached GUI database.
Registration refusals retain schema-authored constraints, including the
native/attached lifecycle requirement, local credential-free endpoint requirement
and absolute workspace root. Configuration diagnostics omit registration values.
Target and private-worker identity refusals retain the failed check, its reason
and recovery guidance in the public error before any analysis replies exist.
These diagnostics do not relax identity admission or authorize closing an attached
exactly one slice of a universal Mach-O and `--generic-instances` adds generic
method instances. The report retains the native reader's
`amd64` spelling for x86-64; loader CPU checks use the corresponding `x86_64`
identity. Multiple slices with the same architecture label are refused as
`ambiguous-slice-selection`, including
distinct ARM subtypes that both map to `arm64`. On macOS, use `lipo -info`
to enumerate exact subtypes, then extract the intended subtype into a separate
file, for example `lipo universal -thin arm64e -output thin-arm64e`. Inspect
that thin file without `--architecture`. An exact `arm64e` slice is not
selected by `lipo -thin arm64`. Thinning resolves only selection ambiguity;
the metadata must still match and unsupported pointer encodings remain unsupported.
## Observations
@@ -204,12 +223,25 @@ assembly image. Each module record starts with its module name, its method
pointer count and its method pointer array. The reader finds, for every metadata
image, the single record whose name pointer reaches that image's name string and
whose count equals the image's method count. It then requires exactly one
`codeGenModulesCount`/`codeGenModules` pair that lists exactly those records. No
symbols are needed, so stripped builds work. A method's token row id selects its
slot in the module's method pointer array.
`codeGenModulesCount`/`codeGenModules` pair that lists exactly those records.
`codeGenModulesCount` and module method counts own four bytes, followed by
alignment padding before their eight-byte pointers. Unresolved loader writes
overlapping those four bytes prevent the registration from being established;
padding outside the field is neither required nor interpreted as part of its
count. No symbols are needed, so stripped builds work. A method's token row id
selects its slot in the module's method pointer array. Within one image, each method must
claim a distinct MethodDef token row; duplicate rows are refused before any
linked method table or seed output is published. Row ids may repeat across
different images, and distinct rows may still resolve to the same address when
the binary uses identical-code folding.
For ELF, a repeated load mapping that resolves a complete module record to the
same virtual address and file bytes contributes one record. Distinct virtual
record addresses remain distinct candidates, and conflicting file mappings
remain malformed.
Module records establish names through their declared NUL-terminated string pointers. NUL/0xFF padding, spaces, Unicode and suffix-shared storage are supported. A pointer to a longer string does not match just its suffix; a pointer directly into a shared suffix may name it. Exact reversed UTF-8 matching avoids rescanning the file for every name and retains duplicate-name owners until module records resolve them. A contributor investigated a Linux
`GameAssembly.so` from Unity 2023.2.13f1 whose static registration was not located. When no static pair is resolved on x86-64, the reader searches executable ranges for bytes consistent with RIP-relative LEA/MOV references to module-array candidates. Exactly one referenced array candidate must remain. `code_gen_modules_field` is then `null`, and Evidence is **inferred**: instruction boundaries, the absence of a static registration elsewhere, and runtime use were not verified. The module records and slots themselves remain file observations. Static-table associations are **derived**. Otherwise the result is `code-registration-not-found`.
`GameAssembly.so` from Unity 2023.2.13f1 whose static registration was not located. When no static pair is resolved on x86-64 or arm64, the reader searches executable ranges for bytes consistent with a reference to a module-array candidate: RIP-relative LEA/MOV on x86-64, an adjacent `adrp`/`add` pair on arm64. Exactly one referenced array candidate must remain. `code_gen_modules_field` is then `null`, and Evidence is **inferred**: instruction boundaries, the absence of a static registration elsewhere, and runtime use were not verified. The module records and slots themselves remain file observations. Static-table associations are **derived**. Otherwise the result is `code-registration-not-found`. Cpp2IL's StrippedCodeRegSupport plugin also recovers the module list of an inlined CodeRegistration from the module names; this fallback additionally requires the exact located module set and a single code reference. A Unity 2022.3.62f3 macOS Master build checked by a contributor keeps neither registration symbol; its type table is then inferred as described below.
The binary/metadata pair is caller-selected. Name/count/token agreement is structural evidence, not a cryptographic same-build proof. File-offset locations refer to the primary metadata artifact; linked virtual addresses refer to `binary.artifact`. Both SHA-256 identities remain available in compact native pages as `artifact` and `binary_source`.
@@ -239,7 +271,9 @@ The result adds:
`rva` (address minus `image_base`), both hexadecimal strings. `state` is
`code` when the module slot holds an unambiguously mapped executable address, `no-body` when an observed slot is zero,
as for abstract, extern and most generic methods, and `unknown` when no type
range in any image holds the method or a symbol relocation leaves its slot unresolved.
range in any image holds the method, a symbol relocation leaves its slot
unresolved, or dyld will bind a Mach-O slot. The raw word in a dyld-bound
slot is not treated as the resolved address.
`address` and `rva` are `null` unless `state` is `code`. The summary counts
each state in `counts.method_address_states`. Ghidra seeds are written only
for `code` rows.
@@ -248,19 +282,148 @@ The result adds:
field and parameter index with `type`, the index into the binary's
`Il2CppType` table, and `name`, rendered from that table: C# keywords for
primitives (`int`, `string`, `object`), `Namespace.Outer+Inner` for type
definitions, `T[]`, `T[,]`and `T*`, generic instances as
definitions, `T[]` for vectors, `T[*]`for rank-one multidimensional arrays,
`T[,]` for rank-two arrays and `T*`, generic instances as
`System.Collections.Generic.List<string>` and generic parameters by their
metadata name (`TKey`). A trailing `&` marks a by-reference type. `name` is
`null` only for type index `-1`.
metadata name (`TKey`). Nested generic arguments stay with the component
that declares them, for example `Game.Outer<int>+Inner<string>` or
`Game.Outer<int>+Leaf` when the nested type adds no parameters. A trailing
`&` marks a by-reference type. `name` is `null` for type index `-1`, metadata
version 27 as described below, or an unresolved type-table slot. A dyld bind
or unresolved ELF relocation retains the type index without interpreting its
stored word as a resolved pointer. If an unresolved loader value occurs
inside a type graph, linking is refused with `unsupported-pointer-encoding`;
a concrete name is not synthesized from that placeholder.
`binary` also records `types_field` and `types_count`: the address of
`Il2CppMetadataRegistration.typesCount` and its value. That record is found as
the single place whose `fieldOffsetsCount` and `typeDefinitionsSizesCount` both
equal the metadata type-definition count and whose type table is file mapped.
Linking reads only that table. When no record on x86-64 or arm64 has both of
those counts, the reader collects maximal runs of pointers to Il2CppType-shaped
records (an assigned Il2CppTypeEnum kind from 0x01 to 0x1e; class and
value-type data below the type-definition count) that are long enough for every
type index the metadata references. Exactly one such run may exist in the
image, it must start and end inside its mapping (a run touching either end may
continue in a neighbouring mapping), and its start must be loaded by the same
instruction forms as the module-array fallback. `types_field` is then `null`,
`types_count` is that run's length rather than an observed `typesCount`, and
Evidence is **inferred**. The run length is at least every referenced type
index but can differ from `typesCount`: a type-shaped pointer after the table
would lengthen it, and an unreadable slot (such as an unresolved relocation)
would end it early. Only the type indices the metadata references are read. A
second long-enough run anywhere, a run that a type-shaped neighbour extends
before the loaded address, a run touching a mapping end or a slot the loader
binds or leaves unresolved (its stored word is only a placeholder), and a covered
128-byte record whose two counts match but whose other fields are unusable all
leave `metadata-registration-not-found` rather than a guess; the search stops
at the second run. The length requirement only separates the type table from
other pointer runs when the metadata references most of it: on the one Master
build checked, the highest referenced index is 6,031 of 6,576 entries. A
metadata referencing few type indices usually
leaves several short runs and fails closed.
Counts use their declared 32-bit width independently of alignment padding.
The complete 128-byte registration must have unambiguous loader coverage. Its
used fields through byte 112 must be file-backed; a trailing declared zero-fill
range can cover the final unused fields. An unmapped or conflicting tail is
refused. These layouts follow the versioned [Unity 2022.3.8f1 producer header](https://github.com/MlgmXyysd/libil2cpp/blob/master/libil2cpp/Unity_2022.3/2022.3.8f1/il2cpp-class-internals.h#L596-L637)
(redistributed source) and the [AArch64 aggregate alignment rules](https://github.com/ARM-software/abi-aa/blob/2025Q1/aapcs64/aapcs64.rst#aggregates).
Dyld pointer ownership comes from the parsed bind stream, as in Apple's
[dyld analyzer](https://github.com/apple-oss-distributions/dyld/blob/dyld-1165.3/common/MachOAnalyzer.cpp#L1508-L1511), rather than the slot's placeholder word.
The padding, zero-fill-tail and unresolved-type cases have authored regression
fixtures; they do not add real Unity-build verification to the checks above.
Without `binary_path`, `binary` is `null` and the four binary collections are
empty in the complete producer report to indicate unrequested observations. Their summary counts, including state counts, are `null`, and native page requests report unavailable observations. This does not establish an empty native inventory. Missing native fields in historical Evidence remain unknown too.
### Generic method instances
`generic_instances: true` (CLI `--generic-instances`, needs `binary_path`) also
links the instances in `Il2CppMetadataRegistration.genericMethodTable`, as
Il2CppDumper does: each row's `genericMethodIndex` selects an `Il2CppMethodSpec`
(generic method definition plus class and method `Il2CppGenericInst`), and its
`methodIndex` selects a `genericMethodPointers` slot. Without the option both
fields below are `null` (not linked, so unknown), as are the summary counts
`generic_method_instances` and `generic_method_instance_states` and the seed
counts. The result adds:
- `binary.generic_methods`: `generic_method_pointers_field` (the address of
`genericMethodPointersCount`), the pointer, table, method spec and generic
instance counts, `generic_method_table_stride` and `issues` (each with the
`row` it leaves unknown, the `address` of the contradicting row, method spec
or pointer slot record, and a `message`);
- `generic_method_instances`: one row per table entry (row position is the
table index) with `method_spec`, `method` (the recorded definition index,
including invalid values, or `null` when the index cannot be read),
`name`, and `state`, `address` and `rva` as in `method_addresses`: `code`,
`no-body` for a zero pointer slot, or `unknown` exactly when an issue names
the row.
Names follow Il2CppDumper's `GetMethodSpecName`, for example
`System.Collections.Generic.Dictionary<int, string>$$TryGetValue` or
`System.HashCode$$Add<int>`: namespaces only on the declaring type, nested types
joined with `.`, the backtick arity cut, `IntPtr`/`UIntPtr`/`TypedReference`
and no byref mark. These names do not depend on the byref bit, so version 27 is
covered.
Header versions do not separate the CodeRegistration layouts (27.0, 27.1 to
29 and 29.1/31 differ in the fields before `codeGenModulesCount`). Every layout for the header version is tried, and
exactly one must have a `genericMethodPointers` count and an invoker count that
bound every table row; the layout also fixes the row size (12 bytes, or 16 with
an adjustor thunk index). No layout agreeing fails as
`generic-method-registration-not-found`, more than one as
`ambiguous-generic-method-registration`. An empty table selects no layout:
the result has no rows, and `generic_method_pointers_field`,
`generic_method_pointers_count` and `generic_method_table_stride` are `null`.
A table of a few rows can still leave two layouts agreeing, which fails as
ambiguous rather than picking one. Metadata versions 24 and 39 and builds
without a static CodeRegistration (`code_gen_modules_field``null`) or
MetadataRegistration (`types_field``null`) fail as
`generic-methods-unsupported`: for version 24 the type-definition generic
container offset and the generic class layout have not been checked against a
real build, so it is refused rather than guessed.
After the layout is fixed, rows that contradict another table do not fail the
whole link: a method spec naming a method or generic instance out of range,
class or method arguments whose count differs from the generic container the
owner declares (none for a non-generic type or method), an owner whose generic
container index is out of range, a name that cannot be rendered, or a pointer slot that is unmapped, has an
unresolved relocation or points outside unambiguous executable file data adds
an `issues` entry, and that row is `unknown` with no address. A method spec
issue also leaves `name``null`, even when the pointer slot is valid: the slot
would otherwise be reported under a definition nothing confirms. Capacity
refusals are never turned into issues. Rows that share one method spec
(Il2CppDumper refuses such a table) each get an issue at their row address that
names one other sharing row, and all of them lose `name` and become `unknown`.
A zero pointer slot is a `no-body` row and has no issue. Before any row is
resolved, the smallest row for every table entry is checked against the
remaining report budget; each row and issue is then admitted as it is retained.
Compact summaries omit `binary.generic_methods.issues` and keep its count in
| `unsupported-container`| unsupported | Not a 64-bit little-endian Mach-O, PE or ELF image (ELF: AArch64 or x86-64 with dynamic section). |
| `slice-selection-required`| unsupported | A universal Mach-O was given without `binary_architecture`. |
| `ambiguous-slice-selection` | unsupported | More than one universal slice matches the selected architecture label; select an exact subtype externally. |
| `slice-not-found` | unsupported | The requested slice is absent, or a thin binary was given an architecture. |
| `unsupported-pointer-encoding` | unsupported | Mach-O chained fixups or Android packed (APS2) ELF relocations; pointers not decoded. |
| `malformed-container` | input error | The container headers are damaged. |
| `code-gen-modules-not-found`| input error | An image has no module record; often a binary from a different build. |
| `ambiguous-code-gen-module` | input error | More than one module record matches an image. |
| `code-registration-not-found` | input error | No unique module table or executable-byte array candidate was resolved. |
| `invalid-method-token` | input error | A token is outside its module's method-pointer rows, or a MethodDef row is reused within one image. |
| `invalid-method-pointer` | input error | A slot is unavailable or its nonzero address lacks unambiguous executable file coverage. |
| `metadata-registration-not-found` | input error | No single MetadataRegistration or code-loaded type-table candidate was resolved. |
| `invalid-type` | input error | A type index or `Il2CppType` record is out of range, unmapped or malformed. |
| `unsupported-type-kind` | unsupported | A valid type kind has no implemented rendering. |
| `generic-methods-unsupported` | unsupported | Generic instances were requested for metadata version 24 or 39, or a build lacks either static registration. |
| `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 to1GiB.
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.
Scans yield cooperatively in bounded batches. Name-address retention and reverse-trie construction are each limited to65,536 entries/nodes and fallback module-array candidates to64 (`native-index-capacity`); exceeding capacity does not prove absence. Rendered type text has a64MiB UTF-8 cache-workspace guard, separate from the64MiB encoded-report admission, and64 nested rendering frames (`native-type-text-capacity` / `type-nesting-capacity`). Genuine cycles are malformed; unsupported type kinds are explicit coverage failures. Native row/text admission runs before allocation or retention. Unused generic parameter names are read on demand from the same stable metadata snapshot. There is no cross-inspection file cache; validated immutable Evidence is reused for session views.
Scans yield cooperatively in bounded batches. Name-address retention and reverse-trie construction are each limited to65,536 entries/nodes and fallback module-array candidates to64 (`native-index-capacity`); exceeding capacity does not prove absence. Rendered type text has a64MiB UTF-8 cache-workspace guard, separate from the64MiB encoded-report admission, and64 nested rendering frames (`native-type-text-capacity` / `type-nesting-capacity`). Genuine cycles are malformed; unsupported type kinds are explicit coverage failures. Native row/text admission runs before allocation or retention. Unused generic parameter names are read on demand from the same stable metadata snapshot. There is no cross-inspection file cache; validated immutable Evidence is reused for session views.
ELF RELATIVE writes into zero-fill are kept as a private virtual-pointer overlay. Unresolved supported-width symbol relocations, including RELA PLT entries, remain unknown; stored zeros never establish no-body. COPY, TLS descriptor, REL, packed APS2 and other unsupported relocation encodings fail closed. Input bytes are unchanged.
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.
Native address queries batch exact64-bit hexadecimal `addresses` and `states` (`code`, `no-body`, `unknown`), intersecting indices and pagination. Numerically equal address spellings match; original row indices and every shared-body alternative survive:
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.
Native address queries batch exact 64-bit hexadecimal `addresses` and `states` (`code`, `no-body`, `unknown`), intersecting indices and pagination; `generic_method_instances` accepts the same filters plus `method_indices` (generic definition indices). Numerically equal address spellings match; original row indices and every shared-body alternative survive:
```json
{
@@ -329,8 +498,11 @@ loaders place the binary: `0x100000` for an ELF linked at 0, and the link base
for Mach-O and PE; `--seed-base 0x...` overrides it for a different import. When
identical code folding gives several methods one address, the first method names
the function and a `# folded <address> <kept> also <names>` comment line after
the seeds lists the others, so the kept name is visibly one of several. Ghidra still names a seeded function that is a thunk after its
target. The file is atomically published with exclusive creation; an existing destination is never replaced. Failed staging retains its cleanup owner for retry. Source digest and link/seed-base comments make the mapping inspectable. Unknown slots are skipped separately from observed no-body slots. `--seed-base` requires `--ghidra-seeds`; overflowing rebased addresses and names/outputs beyond the existing Ghidra protocol limits (2,000 name characters,32MiB file,1,000,000 entries) are refused before publication. The CLI and reusable service use one formatter and owned output workflow; ordinary MCP inspection remains read-only.
the seeds lists the others, so the kept name is visibly one of several. With
`--generic-instances`, linked generic instances are seeded after the method
definitions under their Il2CppDumper-style names; an instance sharing an
address with a definition or another instance is folded the same way. Ghidra still names a seeded function that is a thunk after its
target. The file is atomically published with exclusive creation; an existing destination is never replaced. Failed staging retains its cleanup owner for retry. Source digest and link/seed-base comments make the mapping inspectable. Unknown slots are skipped separately from observed no-body slots. `--seed-base` requires `--ghidra-seeds`; overflowing rebased addresses and names/outputs beyond the existing Ghidra protocol limits (2,000 name characters, 32 MiB file, 1,000,000 entries) are refused before publication. The CLI and reusable service use one formatter and owned output workflow; ordinary MCP inspection remains read-only.
## Failures
@@ -354,16 +526,15 @@ message names one reason:
| `nested-type-conflict` | A type is listed as nested in two types, in itself, or in a cycle of declaring types. |
| `declaring-type-mismatch` | A method inside a type's method range names a different type, or a method lies outside its type's range. |
| `image-range-overlap` | Two images claim the same type definitions. |
| `invalid-string` | A name index does not start a string, or the name is unterminated or not valid UTF-8. |
| `invalid-string` | A name index is outside the strings section, its string is unterminated, or it is not valid UTF-8. |
A version field that disagrees with the file's layout, for example a version
39 file relabeled as 29, usually surfaces as `unexpected-header-size` or
`record-size-mismatch`.
Two checks are stricter than the IL2CPP runtime: a name index must start a
string, and an empty range's start must lie between -1 and the collection size.
Every Unity-written file checked so far satisfies both; metadata rewritten by
other tools may be rejected.
An empty range's start must lie between -1 and the collection size, which is
stricter than some runtime paths. String indices are byte offsets; a valid
offset may select a suffix of another NUL-terminated name.
An incomplete inventory is never reported as complete. Failures after a verified
snapshot retain partial source Evidence with its SHA-256, byte length and any
@@ -383,10 +554,11 @@ report limit can still require the summary and paging path.
- Decrypting or deobfuscating protected metadata.
- Linking Mach-O binaries that use chained fixups, ELF images with Android
packed (APS2) relocations, and 32-bit images; generic method instances,
adjustor thunks and invokers.
packed (APS2) relocations, and 32-bit images; adjustor thunks and invokers;
generic method instances for metadata versions 24 and 39 or builds without a static
CodeRegistration.
- Full method signatures beyond the rendered field, parameter and return type
names, generic method instances, and type names for metadata version 27.
names, and type names for metadata version 27.
- Running Ghidra or another disassembler. `--ghidra-seeds` only writes a seed
file for [`REA_GHIDRA_SEED_FILE`](installation.md); use the
[native workflow](native-investigation.md) for native code.
rea setup --yes --all-detected --install-hopper --json
```
Client configuration writes detect changes to the file read by setup, including
when a matching recovery backup already exists. A detected conflict reports
`reason: "conflict"` and preserves the newer file; review it and rerun setup.
Rollback likewise requires the file identity and content installed by that
transaction. Requests for the same resolved path are serialized within one REA
process. These checks do not provide an operating-system compare-and-swap or
coordinate arbitrary external writers, so avoid editing client configuration
while setup is applying it.
### Skill destinations
The bundled skill is installed in each selected client's personal skill directory.
@@ -145,7 +170,9 @@ Setup leaves existing skill copies in other locations untouched.
Setup refuses symbolic links at the selected skill directory or its managed
`references` directory, matching uninstall and update's ownership rules. Use a
regular skill directory, or select `--skill=false` to configure the client
registration without installing the bundled skill.
registration without installing the bundled skill. A non-directory ancestor is
reported as `ENOTDIR`; preserve the blocking file and correct the directory path
before rerunning setup.
The final selected directories are checked before approval and again before
setup changes any client or Hopper installation. Unselected client destinations
do not block other setup choices. Doctor reports linked or non-directory skill
@@ -153,6 +180,26 @@ paths as `unmanaged`, names the affected paths, and provides those alternatives;
an unreadable skill identity remains `unknown`. Uninstall retains and reports
files it cannot safely remove, including their ownership manifest.
The skill installer preserves byte-exact backups of changed existing files,
including invalid UTF-8, BOMs, and permission modes, and verifies each published
file through its owned descriptor. Before publication it checks the selected
file identity; first installation uses an exclusive hard link and refuses a
concurrently created destination. Filesystems without hard-link support cannot
publish a first-install skill file.
Rollback restores an existing file only while its published identity, state,
and bytes still match that installation attempt. A recovery backup preserves
the original bytes; it does not authorize overwriting a later user edit or
replacement. Conflicts report the affected paths and recovery backups. If a
newly created skill file cannot be verified, setup retains it and reports manual
recovery rather than deleting by pathname. Staging cleanup failures remain
owned and retryable, and setup does not report installation success while
cleanup is unresolved.
These checks do not lock out another writer modifying the same inode or exclude
pathname changes between the last check and publication. Avoid editing managed
skill files or running another installer while setup applies them.
`rea setup --skill-client claude_code --yes --json` refreshes and verifies the
selected skill destination independently of MCP registration selection. The
final `doctor.scope.skill_clients` records which skill destinations were
@@ -167,7 +214,8 @@ identity remains available at `identity.catalog`.
Setup pins package-runner MCP registrations to the exact installed REA version,
installs the matching skill and on-demand references in the same plan, and adds
`startup_timeout_sec = 30` for Codex and Grok Build. Codex also receives a
`startup_timeout_sec = 30` for Codex and Grok Build when no positive timeout
is already configured. Codex also receives a
`tool_timeout_sec` derived from known provider startup plus operation headroom.
## Limit REA to one project or agent profile
@@ -227,7 +275,7 @@ After reviewing an update plan, rerun that same prefixed setup command without
`--dry-run` and approve its exact changes. Profile removal likewise needs the
prefix on `claude mcp remove --scope user rea` and any `rea uninstall` command;
keep the broader client scope of uninstall in mind. Restart the selected
profile after changing its pinned registration.
profile after changing its registration.
`claude mcp remove` removes only the registration. To remove REA from this
profile without running the broader uninstall flow, first back up the profile's
@@ -277,34 +325,30 @@ commands. Record an existing selection first if you intend to restore it after
finishing. The configuration path below is the default profile's
`~/.claude.json`; a different active profile uses its own config root instead.
Register with the variable unset:
<!-- x-release-please-start-version -->
Register with the variable unset, substituting the absolute runtime and entry
script from your existing installation or setup dry-run:
```bash
claude mcp add --scope local rea -- npx -y rea-agents@6.7.0 mcp
claude mcp add --scope local rea -- "/absolute/path/to/node" "/absolute/path/to/rea/scripts/rea.mjs" mcp
```
On native Windows, use the same project directory and wrap the package-runner
shim so the stdio client can launch it:
On native Windows, use the same project directory and absolute paths:
```powershell
claude mcp add --scope local rea -- cmd.exe /d /c npx -y rea-agents@6.7.0 mcp
claude mcp add --scope local rea -- "C:\Program Files\nodejs\node.exe" "C:\tools\rea\scripts\rea.mjs" mcp
```
<!-- x-release-please-end -->
Local scope stores the entry under that directory's path in `~/.claude.json`,
so other projects don't load it. This route doesn't install the bundled skill.
Avoid `--scope project`, which writes `.mcp.json` into the repository where it
can be committed or copied. `rea doctor` and `rea uninstall` read only the
user-level entry, so they don't report or remove a local-scope registration;
remove it with `claude mcp remove --scope local rea` from the same directory.
`rea update` doesn't refresh it either, so it stays on the version it names.
`rea update` doesn't refresh it either, so it continues using the selected installation.
To move it to a newer release, first back up the project entry in
`~/.claude.json` and record its environment and other metadata. In particular,
preserve caller-selected overrides such as `REA_MCP_INPUT_SCHEMA_PROFILE` and
`REA_MCP_MAX_RESPONSE_BYTES`. Run `claude mcp remove --scope local rea` from the
`REA_MCP_MAX_RESPONSE_BYTES`, and `REA_MCP_TOOL_FAMILIES`. Run `claude mcp remove --scope local rea` from the
same directory, then recreate it with the platform-appropriate command above
and the new version. Reapply every recorded environment value with Claude
Code's `mcp add --env NAME=value` options and restore any other retained entry
@@ -375,6 +419,13 @@ The public error code varies by caller: `capability_unavailable`,
only a generic startup error. Check this prerequisite before following
provider-specific recovery advice.
`binary_session` still returns status on such a host. Providers whose
readiness check reaches the owned-child launch, such as Ghidra's Java probe,
JADX and Apktool, report themselves unavailable with a reason naming the
missing `ps`. A provider that fails an earlier configuration check, such as
JADX without `REA_JADX_MCP_JAR`, keeps that reason. The other providers keep
their own status. `open_binary` keeps the refusal described above.
## Diagnose, update, and remove
`rea doctor --json` is strictly read-only. `rea update` updates only the npm or Bun global installation that owns the running CLI. Source checkouts and package-runner copies must be updated through the mechanism that owns them; a fresh package-runner invocation can use `npx rea-agents@latest` or `bunx rea-agents@latest`. `rea uninstall` removes only REA-owned agent registrations and skill files; `--purge-data` additionally removes REA cache and state paths.
Run current setup to migrate recognized older `npx`/`bunx` registrations, with
backups, then restart the client. Unrelated or unidentified registrations remain
untouched. Setup does not prewarm a separate package-runner command.
Persistent registrations should use one exact package version. `rea setup`
writes the same package-runner shape, or `bunx rea-agents@<version> mcp` when
setup runs through `bunx`, and pins it to the exact version that performed
setup. Run current setup to refresh an older registration, then restart the
client.
If setup itself runs from a package-runner cache, the registration depends on
that cache entry and the selected runtime remaining installed. Removing either
makes startup fail; it does not download or resolve another package. Restore the
same installation and rerun setup. Changing package requests, cache roots, or
runtimes can create a different installation identity. If the old entry cannot be
identified, restore it first or manually remove the confirmed REA registration
before running setup again. A global installation provides a more durable path.
## Package runners and global installation
A package-runner invocation can use a REA version installed in the current project. To
request the latest release explicitly, use:
Packagerunners can select project-local packages and read project configuration,
even for explicit version requests. Acquire REA from a trusted working directory,
outside the target project, and pass absolute target paths to analysis commands.
REA cannot validate package acquisition that happens before its entrypoint starts.
To request the latest release explicitly, use:
```bash
npx rea-agents@latest setup
@@ -1300,18 +1707,16 @@ For an intentional rollback, make the package request explicit:
npm exec --yes --package=rea-agents@2.4.0 -- rea setup
```
Setup continues to pin persistent MCP registrations to the exact version that
performed setup. Running current setup later migrates unversioned or older
managed registrations through the normal reviewed setup transaction.
Setup binds persistent MCP registrations to the installation that performed setup.
Running current setup later migrates recognized legacy package-runner registrations
through the normal reviewed setup transaction.
With Bun, `bunx rea-agents setup` (or `bunx rea-agents@latest setup`) is the
equivalent entry point. Setup run through `npx` registers
`npx -y rea-agents@<version> mcp`; setup run through `bunx` or `bun x` registers
`bunx rea-agents@<version> mcp`. On Windows, setup wraps either command in
`cmd.exe /d /c` so clients can start the runner's command shim. Neither
registration points into the runner's temporary package cache.
equivalent acquisition entry point. Managed registrations use the selected Bun
executable and REA entry script directly. Windows registrations likewise use
absolute runtime and script paths, without a package-runner command shim.
REA supports Node.js 22.x (>=22.19), 24.x (>=24.11), and 26+. Node.js 23, 25, and prereleases are unsupported. It uses the npm already paired with that runtime and never upgrades Node.js, npm, or Homebrew.
REA supports Node.js 22.x (>=22.23.4), 24.x (>=24.22.1), and 26.12.1+. Node.js 23, 25, earlier 26.x releases, and prereleases are unsupported. It uses the npm already paired with that runtime and never upgrades Node.js, npm, or Homebrew.
When REA runs on Bun, the `rea doctor``node` check reports the Bun version and
the Node.js compatibility version Bun declares, and passes when that
@@ -1343,8 +1748,29 @@ Review the plan, approve the selected client changes, then restart those clients
This registers the installed entrypoint directly; installing the global package
alone does not replace existing `npx` registrations. Each client still has its own
REA process and analysis state. Direct registrations follow the installed CLI;
use `rea update` to update it. Running setup through `npx` again selects the pinned
package-runner command. Do not register paths inside npm's temporary package cache.
use `rea update` to update it. Running setup through `npx` again selects the
installation that executes setup, potentially in npm's temporary package cache;
retain that cache entry for as long as the registration uses it.
### npm workspace errors before REA starts
An `npx` launch can inspect the caller's npm project before executing REA. For
example, a direct dependency whose override conflicts with its declared spec
can cause npm's `EOVERRIDE`, even when the requested REA package is already
cached. This is a package-runner failure: REA has not started and cannot return
an MCP error. [#3690](https://github.com/morluto/rea/issues/3690) reproduced it
outside OpenCode as well as through that client's workspace-default launch.
Use the direct global-installation setup flow above to replace the affected
package-runner registration, then restart the client. If REA is already installed
globally, run that installed `rea setup --client <client-id> --dry-run`, review
the direct launcher in the plan, and apply the approved scope. Installing a
global copy alone does not change an existing registration. Keep the client's
working directory: changing it to bypass npm inspection can change the meaning
of relative target paths. A direct REA entrypoint preserves that directory
without asking npm to resolve the workspace's dependency graph.
### Global installation wrapper
The optional curl wrapper installs only the global npm package:
After reviewing it, install the same package version:
```bash
bash rea-install.sh --version "$rea_version"
```
The tag pins the selected script revision; `--version` selects the npm package
version. Neither command verifies a signature on the downloaded script.
Supported options are `--version <semver>`, `--dry-run`, `--no-setup`, `--no-prompt`, and `--verbose`. Neither `--no-prompt` nor a non-interactive shell grants permission to install external dependencies.
Hopper setup distinguishes a confirmed occupied destination from a failed
destination inspection. It also reports local archive staging and installed
launcher inspection failures separately from download failure or launcher
absence. Follow the reported operation, path, and available filesystem code; an
unresolved inspection does not establish that a destination exists or a launcher
failed parsing and unexamined source. `semantics` records the number of observed
unknown findings and typed uncertainty, including returned-reference widening
and unavailable type-only compiler options. `examination` reports static semantic
resource limits and Electron wrapper expansion limits independently. A completed
pass does not establish complete runtime semantics. Route examination and result
capacity remain in the separate route inventory.
Electron applicability is `observed` when a static Electron module reference is
retained, and otherwise `unknown`: a source without such a reference does not
prove that the application is inapplicable. Sources excluded by `source_paths`
retain `not-examined` with a reason and null semantic counts. Historical Evidence
without this facet remains unmeasured. The existing `parse_status` remains its
conservative overall summary; finer facts do not relabel earlier partial results.
Summary delivery counts these facts under `summary.coverage.static_sources`.
Read exact per-file measurements with `inspect_analysis_view`, selecting
`kind: "javascript-facts"` and `property_keys: ["analysis_coverage"]`, or inspect
the module item. Both views use retained Evidence and preserve source provenance.
## ASAR integrity
ASAR inventory checks Electron integrity metadata for embedded archive entries
@@ -177,8 +251,25 @@ An unpacked entry whose companion bytes were not supplied remains
`unavailable`. REA continues analyzing embedded JavaScript and records the
missing native/resource bytes as unknown. The occurrence keeps
`hash_status: unavailable`; no content-addressed child artifact is created for
those missing bytes. See [MCP integrity handling](mcp-contracts.md#integrity-record-and-continue)
for the tool-result contract.
those missing bytes. New ASAR file occurrences record `unpacked: true` for
companion files and `unpacked: false` for packed entries, including when the
file bytes are unavailable. An omitted flag in an older inventory remains
unknown; it does not establish either storage mode. See
[MCP integrity handling](mcp-contracts.md#integrity-record-and-continue) for the
tool-result contract.
JavaScript whose syntax cannot be parsed retains unavailable semantic coverage
with `incomplete-module` unknowns for each semantic family and unknown omitted
node and relation extents. The source module is retained when node capacity
permits. A parser failure alone does not imply resource truncation or a named
resource limit. Decoding failures and deliberately
unselected sources retain the same explicit semantic coverage gap.
HTML whose bytes are not valid UTF-8 retains its file observation and an unknown
`parse-html-script-references` scope with artifact-byte authority. Reference
discovery was unavailable; zero retained script links does not establish that
the unreadable HTML declared none. Readable HTML with no references has no such
gap, and readable external references retain their load edges.
## Large results
@@ -219,6 +310,16 @@ waiting before receiving the reply, follow [MCP cancellation recovery](mcp-contr
to find the record. CLI failure output contains the complete partial Evidence.
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
cleanup is incomplete. Confirmed release restores that primary classification,
including the caller's exact cancellation reason, while retaining partial
application Evidence and historical cleanup diagnostics.
Private worker storage failures retain the source identity, worker phase and
reported I/O message as execution failures; they are distinct from malformed
worker output. A per-source temporary-file cleanup failure preserves static and
module facts together with any parent application-projection limit. Cleanup
failure does not authorize expanding relationships that parent admission declined.
## What is reconstructed
@@ -249,15 +350,27 @@ utility-process runtime paths retain the runtime filename selected by the caller
Selected bounded text is then parsed as inert data to recover:
- `package.json` metadata and declared main or renderer entrypoints;
- Electron preload paths and renderer files visible in static syntax;
- Electron preload paths owned by proven BrowserWindow options and renderer
files loaded through proven BrowserWindow instances;
- local HTML script entrypoints;
- Webpack and Rspack chunk registrations and module factories represented as
AST literals;
AST literals, plus esbuild `__commonJS` module tables; recovered esbuild
CommonJS exports use its factory's `exports`-then-`module` parameter order.
Export receivers and loader helpers retain those calling-convention roles only
while the binding at the read still holds its original parameter value;
replacing a parameter does not give the replacement object that role;
- static imports, dynamic imports, CommonJS `require` calls, workers, and
service workers (only `new Worker(new URL(path, import.meta.url))` resolves
relative to the calling module; string worker and service-worker paths use
the document base URL or Node's working directory, which static analysis
does not establish, so they keep their expression and stay unresolved);
- Vite preload dependency tables (`__vite__mapDeps`): `./` entries resolve
relative to the importing chunk; base-relative entries such as
`assets/chunk.js` carry a `vite-output:` specifier and resolve under the one
ancestor directory of the importer that holds them, the build output
directory. A file found there but not analyzed, such as a stylesheet, stays
`unavailable` with its path. Selecting only the assets directory leaves them
`not-found`;
- route, network endpoint, storage, and vendor-marker observations;
- local source-map declarations and original
source names and content digests;
@@ -296,9 +409,11 @@ RPC client syntax also contributes network endpoint candidates, in both
initializer and no binding assignments; shadowed locals do not inherit client
identity. `subscribe` additionally requires a tRPC observer
argument (`onData`, `onError`, `onStarted`, `onStopped`, `onComplete`, or
`onConnectionStateChange`). `this` roots, browser globals, and any path
containing an RTK Query `endpoints` segment are never procedures; cache-key
helpers such as `queryKey` issue no request and are excluded.
`onConnectionStateChange`). `this` roots and unshadowed browser globals are
excluded. A lexical client can be named `history`, and its router segments can
use browser-global spellings. RTK Query `endpoints` chains are excluded only
when the root has no recognized tRPC client binding. Cache-key helpers such as
`queryKey` issue no request and are excluded.
- `trpc:link:<link>` records the literal `url` option of `httpLink`,
`httpBatchLink`, `httpBatchStreamLink`, and `httpSubscriptionLink` when the
link's callee name survives bundling, including `(0, module.httpBatchLink)`
@@ -329,6 +444,36 @@ recorded path keeps those leading carrier segments; the procedure path is its
suffix. Utility calls such as `useUtils().invoice.list.fetch()`, `useQueries`,
and links whose callee was renamed by a minifier are not recognized.
Bundler adapters own callback roles: Webpack supplies module, exports, then
loader; esbuild CommonJS supplies exports, then module. Export extraction uses
those binding identities for assignments and declarations, so renaming either
parameter does not change the recovered names. The convention always supplies
every role argument, so a role parameter's default never runs: a defaulted
module or exports parameter keeps its role, and the default expression yields
no exports, references or chunk keys. `{exports: alias}` in the module position
binds `alias` to `module.exports`.
Other role patterns, such as rest, array, nested or computed-key patterns or a
non-identifier loader, receive no role and count as unknown findings, so the
file's analysis is partial rather than an exact empty export list. An
export-shaped write through a role binding whose value at that read cannot be
ordered against a replacement is also an unknown finding. Global
property-definition intrinsics require lexical and visible-write proof. Factory export declarations
also require the loader's `d` member to have no prior or unordered visible
replacement, including writes through lexical aliases. Unrelated loader members
do not invalidate declarations. Ordering describes declarations within one factory
activation; helper integrity on entry, effects of earlier invocations, and
arbitrary call side effects remain unproven.
Computed writes through a standalone loader's exposed module/cache table use
the shared value owner; an unknown key invalidates the original-slot proof
rather than implying a fresh chunk installation. A function stored on a
standalone loader member does not write the table merely by being defined:
the bootstrap owner excludes its deferred writes only when that member is
unread and the loader namespace stays confined. Calls, member aliases, dynamic
member reads, namespace escapes, or
receiver-based access retain uncertainty about those writes. Export names
describe recognized declarations, not a proof
of final runtime property lifetime or arbitrary helper behavior.
Each recovered bundle module retains the exact factory-source digest. A complete
bounded AST also receives a `babel-ast-v3` structural fingerprint. It ignores
ordinary identifier spellings while retaining literal and directive values,
@@ -355,6 +500,22 @@ prefix is never presented as a complete stable fingerprint.
## Authority and unknowns
API identity is a derivation: a familiar method or property name does not
establish a browser or Electron API. The shared lexical, ambient-write, and
member-mutation owners must establish the receiver before static API facts become
roles or storage observations. Path `join`, `resolve`, and `fileURLToPath` use
proven Node imports; source-relative URL conversion additionally requires an
unmodified global or proven Node `url.URL` constructor and `import.meta.url`.
Native constructor aliases retain that identity; their local spelling does not
determine URL semantics, and replaced exports or local constructors remain unknown.
Relative results of native path operations retain filesystem-expression context;
their spelling does not turn them into module specifiers. Other calls preserve
their expressions. A property named `preload` outside a proven BrowserWindow
configuration does not establish a script entrypoint. Renderer recovery currently
covers direct BrowserWindow instances, stable local aliases, and their
`webContents`; other receiver-producing APIs remain unmodeled. Complete AST
traversal does not imply complete API-model coverage.
Artifact bytes and AST syntax are observations. Entrypoint resolution, imports,
loads, calls, and persistence relationships are static inferences and explicitly
say that syntax does not prove runtime execution. A malformed or unavailable
@@ -488,6 +649,14 @@ candidate. Dynamic channels are never paired, and multiple compatible handlers
are reported as ambiguous without adding a caller-to-handler edge. A matching
channel still does not prove registration order, reachability, or runtime use.
Native-addon call bindings consume the same loader identity and normalized
arguments as dependency analysis, including optional calls. Local methods or
parameters named `require` establish no native binding; `require.resolve` records
lookup rather than a native namespace. CommonJS re-export bindings require a
selected export value and an applicable shared export receiver. Arithmetic and
logical compound stores keep their dependency observations without asserting that
the addon is the selected exported value.
For `.node` bindings, member names mean “requested by JavaScript syntax.” A
resolved add-on path does not convert them into verified native exports. Native
symbol verification remains a separate deep-analysis claim.
@@ -513,6 +682,11 @@ inventory digest before parsing, and malformed ASAR operations return typed
format diagnostics that retain the local container path. Native add-ons are
represented by metadata only.
POSIX directory names are read as raw bytes and admitted as logical paths only
when they round-trip through UTF-8. Invalid names are left untouched, retained
siblings remain inventoried, and traversal coverage is marked unknown with the
first rejected basename bytes identified in hexadecimal.
## Bounds and coverage
The reconstruction keeps internal resource safeguards for artifact entries,
@@ -600,6 +774,10 @@ deadline per source, including startup and fact transfer. Select
`max_heap_mb` and `analysis_timeout_ms` through MCP, or `--max-heap-mb` and
`--analysis-timeout-ms` on the dedicated CLI command. These choices control the
analyzer; the caller's `NODE_OPTIONS` still controls the CLI/MCP process heap.
For defaults across new MCP operations, use `update_analysis_settings` with
`javascript.max_heap_mb` or `javascript.analysis_timeout_ms`. Explicit per-call
arguments take precedence, and accepted work keeps its original settings. See
the [settings design](design/limits-and-recovery.md#precedence-and-lifetime).
V8 old-space limits do not impose a process RSS limit. When REA runs on Bun,
the analyzer ignores the V8 heap flags; resource failures then report
`worker_heap_limit_bytes` as null instead of a requested or V8-reported limit.
@@ -636,6 +814,13 @@ execution and memory limits continue to determine examined coverage. Raising onl
a node capacity does not raise the unknown capacity. Graphs without unknown
omissions omit this optional coverage field, preserving their existing identities.
These node and unknown capacities bound retained graph projection. Parsing,
static analysis and semantic fact construction precede that projection for an
admitted source. Lowering the capacities can reduce projection and retention
work, but does not bound upstream semantic-analysis time or memory. Select fewer
`source_paths` to reduce the sources analyzed; heap and deadline controls set
separate resource failure boundaries with the runtime-specific limits above.
While sources remain, the sequential worker reserves one next compact static
checkpoint at its 8 MiB bound with the same 6x retention expansion used at
admission. Earlier checkpoints are already charged to retained bytes; the
@@ -756,6 +941,24 @@ URL targets before selecting a later package-local file; an unsupported bare
package or recursive alias keeps its unresolved outcome rather than selecting
a later fallback.
For a proven `createRequire(new URL(relativeFile, import.meta.url))` call,
relative `require()` edges use the selected filename's directory and retain the
source-relative `resolution_base_path` on the graph edge. This follows Node's
`createRequire(filename)` contract; the path is a loader-resolution fact and
does not change the source file or call-site Evidence identity. If the filename
cannot be proven, REA keeps the require target unresolved rather than silently
resolving it from the caller's directory.
Module-reference graph edges, including native-addon `loads` edges, retain
`properties.operation`: `load` identifies
an import or loader invocation that may execute the target; `resolve` identifies
a proven `require.resolve()` lookup that discovers a target without executing it.
Both retain the exact specifier, resolution mode, selected resolution base, and
call-site Evidence. Resolve-only edges do not propagate application ownership or
create executable-import gaps when their targets are missing. A modified
`.resolve` member remains an uncertain `load`, because its replacement may execute
code. These static facts do not establish that a call runs at runtime.
ESM relative module paths, legacy package subpaths without exports, and selected
package exports targets use URL suffix handling and one percent-decoding pass.
Bare specifiers retain their complete query/fragment text for exports key matching.
@@ -798,3 +1001,17 @@ truncated under the `html_inline_script_locations_per_file` limit, and the
scope's evidence counts the omitted locations. The graph names the
file and up to 10 starting lines in its limitations, and coverage is partial. Import maps, speculation rules, data blocks, and blank
bodies are not JavaScript and are not reported.
For static source relationships, an explicitly requested declaration filename
(`.d.ts`, `.d.mts`, or `.d.cts`) retains its inventoried identity through both
`import` and `require`. A declaration found only as an emitted-extension fallback
remains unavailable as a runtime implementation. Package URL targets decode
filename escapes once, including dots within filenames; forbidden whole segments
and encoded separators remain rejected. ESM local-path classification uses the
authored request before URL whitespace preprocessing, so leading whitespace
cannot turn a bare request into a relative file dependency.
For example, a leading tab or newline before `./dep.mjs` remains a bare
package request; Node's later package-URL normalization can resolve it under
`node_modules`, independently of a same-named file beside the importer. Resolver
qualification checks the exact path and file existence: [`import.meta.resolve()`](https://github.com/nodejs/node/blob/v24.22.1/doc/api/esm.md#importmetaresolvespecifier)
alone can return a URL for a missing file.
Loaded 100 of 4551 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.