Commit Graph
111 Commits
Author SHA1 Message Date
gensokyo-devandEntrpi 37827af591 feat(artifacts): compare inventories from Evidence sources (#7869)
* feat(artifacts): compare artifacts by Evidence reference and from the CLI

compare_artifacts made agents send back the complete inventory Evidence
that REA already retains, and the CLI had no artifact comparison.

Each side of compare_artifacts now takes exactly one of: complete inline
Evidence (unchanged), {kind: "retained-evidence", evidence_id}, or
{kind: "evidence-file", path, evidence_id?}. The two references are the
sources inspect_analysis_view accepts; both tools now compose one
definition in evidenceReference.ts. A summary still resolves to its exact
retained parent, and every source form gives the same comparison Evidence.
An unresolvable retained reference is refused with a typed missing
reference error.

The application layer owns source resolution and the comparison Evidence,
so MCP and the new `rea compare-artifacts` command share one workflow.
readEvidenceFileSource reports bundle-selection refusals at the caller's
own field path.

* refactor(artifacts): resolve compare_artifacts sides like compare_functions

compare_functions, compare_wasm_interfaces and the JavaScript application
comparisons name each side with evidenceInputSchema and resolve it with
resolvePairedEvidenceRequest. compare_artifacts reached the same result
for inline and retained sides through its own dispatch.

evidenceSourceInputSchema now extends evidenceInputSchema with the
Evidence-file reference, and resolvePairedEvidenceSources sends inline and
retained sides to the same resolveEvidenceInput and file sides to the
shared Evidence file reader. compare_artifacts uses both, so the forms it
shares with compare_functions are parsed and resolved by one owner. The
advertised input schema is unchanged.

* docs(cli): point rea compare to compare-artifacts for inventory contents

rea compare (compare_bundles) compares records by Evidence identity and
explicit pairs and never reads artifact contents, so two build
inventories stay unresolved there. Its help and the CLI guide now name
compare-artifacts for that comparison.

* fix(artifacts): resolve summary parents within Evidence source bundles

* perf(evidence): reuse file-owned immutable authentication proofs

* test(evidence): inject failures at both authentication boundaries

---------

Co-authored-by: Entrpi <[email protected]>
2026-10-29 03:12:03 +08:00
morluto 60ab4da329 fix(cli): correct completion options and setup guidance (#7851)
* fix(cli): align MCP doctor completion with its options

* fix(cli): explain zsh completion initialization

* fix(cli): include launcher timing in doctor completion

* style(cli): format doctor completion schema
2026-10-29 01:28:04 +08:00
Entrpiandgensokyo-dev 64196b08ca feat(artifacts): inventory and extract ESP32 firmware images (#7498)
* feat(artifacts): inventory and extract ESP32 firmware images

ESP32-family app and bootloader images (magic 0xE9) had no reader, so
open_binary refused OTA downloads, app partitions and bootloaders.

Add the esp-image container format behind inspect_artifact and
extract_artifact. A pure decoder reads each byte once and keeps only
fixed-size fields. Derived facts cover the chip, from a table cited to
ESP-IDF v6.1; segment classification as ESP-IDF's should_map and
should_load; checksum and appended SHA-256 results; app and bootloader
descriptors; Secure Boot v2 signature blocks, observed and unverified;
and undescribed trailing byte ranges. Truncation and undescribed bytes
make coverage unknown. ESP8266 images are refused with a specific
reason, and ciphertext stays unrecognized.

Add the format to every target, Evidence, snapshot, live-summary and
artifact vocabulary, document it, and add an optional verify:esp-images
lane that compares esptool-built images with esptool image-info and
espsecure signature-info-v2.

Refs #3615

* test(artifacts): run the ESP image lane on esptool v5.6.0

The lane compared descriptor fields only when esptool image-info printed
one, so a descriptor that REA reports and esptool does not print passed
without comparison. Compare the descriptor kind in both directions.

Record that the lane passed for all 13 images with esptool and espsecure
v5.6.0, the version the layout facts cite, as well as with 4.12.0.

* refactor(artifacts): define ESP image layout sizes once

The decoder and the derived facts each defined the segment-header,
appended-digest and flash-sector sizes, the erased-byte scan and the
offset formatter. Define them once with the other fixed-layout structures
and import them in both places. The signature slot count is the one
constant that drives the slot scan.

Correct the observedEnd comment: it is the end of the last chunk read.

* fix(artifacts): report ESP-IDF's segment length limit by chip

ESP-IDF's verify_segment_header rejects a segment of 16 MiB or more
unless the chip maps flash through 32-bit cache addresses
(SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP: ESP32-S3, P4, C5, C61, H4 and
S31 in v6.1). Record that capability in the chip table and add a
limitation for such segments; unknown chips get none.

`loaded` repeats should_load. It does not mean the bootloader accepts the
segment: verify_load_addresses still rejects one outside the chip's RAM,
which REA does not model. Say so in the docs, the skill reference and the
inventory limitation.

* test(artifacts): check ESP lane tools first and verify extraction

The lane started work before checking its tools, so a missing RISC-V
target, ld.lld, esptool or espsecure surfaced as a raw spawn or command
error. Check each one before building and name the variable to set. Warn
when esptool is not v5.6.0, the release the layout facts cite.

Assert each segment's class for the ESP32-C3 app, its variants and the
bootloader, as the Xtensa image already did. Extract the app and the
signed image through the CLI and compare every file with the bytes at
esptool's segment offsets or in the appended signature sector; the
source's SHA-256 must be unchanged and equal the reported root_sha256.

* docs(artifacts): state what the ESP image lane does not establish

The Verification section listed the lane's checks but not its gaps: only
ESP32-C3 and ESP32 images come from a real producer, no real project
build, OTA download or flash dump is inspected, no signature is verified,
and the lane does not run in CI.

Record the timing of the final lane run on esptool v5.6.0.

* fix(artifacts): compare ESP segment declarations

Segment entries hash only their data, so compare_artifacts reported a
segment that moved to another load address with the same bytes as
unchanged; only the image itself changed. Compare each segment's
load_addr and data_len as its declaration, as Node SEA and PyInstaller
members are compared, and count a changed declaration as a metadata
change, also when content is unavailable.

Header offsets are layout and the classification is derived, so neither
is compared.

* test(artifacts): run ESP lane commands as owned process trees

The lane ran its tools through execFile. A timeout killed only the direct
child, so a linker or assembler that Clang or GCC had started could keep
running while the lane removed its workspace. Run every command through
createVerifierCommands, check the tools inside withVerifierCleanup, and
remove the workspace only after commands.close() has stopped every tree;
a failed close keeps the workspace.

Only a nonzero exit now counts as a refusal or an expected esptool
failure; timeouts and spawn failures propagate. Supervising each command
roughly doubles the lane's run time.

* test(artifacts): cancel ESP decoding after its first decoded chunk

The cancellation test requested cancel or close on setImmediate, which
can land while the file is still being opened and checked, so it never
showed that decoding had started. It also passed against a reader that
ignored both requests while decoding. Acknowledge the decoder's first
chunk, then cancel or close, join the operation, and assert that no
later chunk reaches the decoder and that the reader ends closed.

* docs(artifacts): record which ESP metadata comparison ignores

Segments are compared by their declaration. The image's and the
signature blocks' format_metadata are not: every field comes from their
own bytes, which content comparison already covers, and a block's
image_digest_matches follows the image's content.

* docs(artifacts): state that ESP mmu_page_size is a base-2 logarithm

The app descriptor's mmu_page_size keeps ESP-IDF's name and value, the
MMU page size in log base 2 as esp_app_desc_t declares it, so 16 means
64 KiB. Say so in docs/esp-image.md and the schema comment; a reader
could otherwise take 16 as 16 KiB.

* fix(esp-image): retain member consumption and share lifecycle regressions

* test(artifacts): scope MCP catalogs and budget full-schema validation

* test(artifacts): verify compact output profiles and document bounded catalogs

* test(artifacts): close readers when cleanup-test admission fails

* test(artifacts): compare ESP image limitations with their owners

The decoder and reader tests froze complete limitation sentences, so a
harmless rewording failed them. The wording now has two owners:
ESP_IMAGE_LIMITATIONS in espImageFacts.ts, which the decoder, the inventory
and the reader use, and ESP_DESCRIPTOR_LIMITATIONS beside the descriptor
decoder. Tests compare delivered limitations with the owner, called with the
facts each case establishes (segment index, declared and available bytes,
offsets, chip, page range), next to the structured assertions they already
make. Delivered text is unchanged.

* test(esp-image): assert structured facts and owned guidance

* fix(esp-image): keep spi_flash_mode and descriptor fields before a truncated tail

ESP-IDF v6.1's esp_app_desc_t declares spi_flash_mode at byte 181, after
mmu_page_size, as the committed reference layout shows; the descriptor now
keeps it as stored. The decoder also required all 256 descriptor bytes,
though it reads none past byte 181, so a file ending in the reserved tail
lost the version, project, digest and revision facts it does hold. The app
descriptor now needs only its fields; the segment's truncation is reported
as before.

* test(esp-image): pin the P-192 public key digest to espsecure's layout

espsecure packs ECDSA signature blocks as "<BBBx32sB64s64s1031x" and
zero-pads a 48-byte P-192 point to 64 bytes, so the signature starts at
byte 101 for every SHA-256 curve. signature_info_v2 hashes sig_block[36:101]
and _digest_sbv2_public_key the curve ID with the padded point. No test built
a P-192 block; this one checks public_key_sha256 against that definition.

* fix(esp-image): keep each app descriptor field the file holds in full

A file can end anywhere inside the 256-byte esp_app_desc_t. The decoder
needed every field byte, so a cut at byte 176 dropped the version, project
and app_elf_sha256 it does hold. Once the 4-byte magic identifies an app
descriptor, each field is now kept when the file holds all of its bytes and
is null otherwise; observed_length records where the descriptor ends, so a
cut field is told apart from text that is not UTF-8. The fields after the
magic become nullable in the metadata schema.

* fix(esp-image): report a signature block whose image digest does not match

A CRC-valid Secure Boot v2 block can carry another image's digest. The
block recorded image_digest_matches false, but no limitation said so, unlike
a checksum or appended-SHA mismatch, so CLI and MCP summaries showed only
the generic unverified note. The mismatch is now a limitation; coverage
stays complete and signature_status stays unverified. The three other
signature-sector limitations move into ESP_IMAGE_LIMITATIONS with their
text unchanged, so all ESP image wording has one owner.

* refactor(esp-image): remove redundant descriptor byte guards

---------

Co-authored-by: gensokyo-dev <[email protected]>
2026-10-28 23:18:22 +08:00
Cipherandgensokyo-dev 18a8e71c9f feat(artifacts): add U-Boot legacy uImage reader (part of #7129) (#7234)
* 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]>
2026-10-28 19:11:41 +08:00
blankymandgensokyo-dev e78ac1a55b feat(artifacts): read UnityFS AssetBundle containers (#7699)
* 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]>
2026-10-28 16:47:39 +08:00
Aadityaandgensokyo-dev c36971953c feat(artifacts): inventory and extract Intel HEX and Motorola S-record regions (#7136)
* 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]>
2026-10-28 12:35:55 +08:00
d3b31a0e29 feat(cli): report opt-in command timings (#7042)
* feat(cli): report opt-in command timings

* fix(cli): time standalone MCP doctor

* fix(cli): retain timing on doctor errors

* fix(cli): preserve formatted version output with command timings

---------

Co-authored-by: dhruvac29 <[email protected]>
Co-authored-by: gensokyo-dev <[email protected]>
2026-10-28 11:53:29 +08:00
aa6f6436c9 feat(cli): add CSV and TSV analysis views (#7254)
* feat(cli): add CSV and TSV analysis views

Co-authored-by: Copilot <[email protected]>

* Update tests/boundary/cli/filteredArrayOutput.test.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Update src/cli.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix(cli): address delimited export review feedback

* fix(cli): format delimited output block in cliResultOutput

* fix(cli): retain delimited view uncertainty and align completions

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: gensokyo-dev <[email protected]>
2026-10-28 11:27:40 +08:00
morluto 2ad599dace fix(snapshot): export only target-bound observations 2026-10-27 07:55:16 +08:00
morluto 567ea4b1e8 refactor(ownership)!: consolidate legacy aliases
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.
2026-10-27 06:31:23 +08:00
morluto 3515b26221 refactor(ownership)!: remove redundant aliases
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.
2026-10-27 06:27:10 +08:00
YingNingandgensokyo-dev 4da7e46e9c fix(provider-selection): name whether a rejection came from availability or target support (#7220)
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]>
2026-10-26 23:49:11 +08:00
Dery Ferdikaandgensokyo-dev aa6c1d49fd fix(mcp)!: require allowed hosts for non-loopback HTTP binds (#7172)
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]>
2026-10-26 22:55:10 +08:00
Kaoru0822andClaude Opus 5.5 e06be06530 fix(cli): report JSON Lines selection refusals as caller errors (#7124)
* 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]>
2026-10-25 05:26:13 -07:00
RRFZ cc146042d1 fix(cli): preserve literal Markdown table facts (#7073)
* 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.
2026-10-25 13:55:18 +08:00
morluto 9b3a633298 fix(evidence): retain caller paths across snapshot replay
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.
2026-10-25 02:20:13 +08:00
ed79bf9361 feat(artifacts): inventory and extract Node.js single executable application blobs (#7000)
* 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]>
2026-10-25 02:10:41 +08:00
b4ba96a9a5 feat(firmware): inspect flattened devicetree blobs (#7009)
* 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]>
2026-10-24 22:45:22 +08:00
dba8a31978 feat(elf): inspect Linux kernel module metadata (#7010)
* 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]>
2026-10-24 22:35:20 +08:00
3d84215bb2 feat(pe): inspect TLS callbacks and load configuration (#7008)
* 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]>
2026-10-24 22:06:41 +08:00
02e049744f feat(environment): build agent environments from a prompt (#6946)
* 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]>
2026-10-24 21:51:41 +08:00
Ariel Fikru Avicennaandgensokyo-dev cab78de506 feat(ghidra): analyze GameCube/Wii DOL executables through Ghidra (#6240)
* 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]>
2026-10-24 17:56:31 +08:00
JANG BYUNGKUNandgensokyo-dev 3ce311757d feat(il2cpp): link generic method instances behind --generic-instances (#5785)
* 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]>
2026-10-24 16:19:05 +08:00
781760a195 feat(apple): inspect IPS crash reports (#6511)
* 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]>
2026-10-24 16:02:59 +08:00
4ef916da03 feat(pe): inspect import and delay-load tables (#6509)
* 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]>
2026-10-24 11:44:12 +08:00
morluto 5940600a22 fix(reference): preserve historical backslash import bases 2026-10-24 08:22:14 +08:00
1a48a82020 feat(analysis)!: default function MCP output to retained summaries (#5660)
* 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]>
2026-10-24 08:18:53 +08:00
morluto 9d7779d365 fix(cli): validate selected local paths before resolution
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.
2026-10-24 07:28:09 +08:00
morluto 13fcf58276 fix(session): own selected snapshot read cleanup
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
2026-10-24 07:07:06 +08:00
morluto 60bb202ca3 test(providers): assert runtime and snapshot ownership contracts
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.
2026-10-24 06:48:16 +08:00
morluto d5df7fd944 fix(reference): preserve source scope and loader authority
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 #6891
Fixes #6882
Fixes #6883
Fixes #6859
2026-10-24 06:24:55 +08:00
morluto a31b4a393a fix(cli): unify builtin and global completion scope 2026-10-24 04:26:54 +08:00
morluto 77ebfb5f8a fix(environment): retain primary facts through server cleanup failure 2026-10-24 04:14:17 +08:00
morluto 6f8dc9c139 fix(session): preserve binding commitments during restoration 2026-10-24 04:14:17 +08:00
morluto 59f0eb4244 fix(cli): validate output windows and finish pending writes 2026-10-24 04:05:23 +08:00
morluto fc404f008d fix(cli): count emitted documents and normalize token windows 2026-10-24 03:16:30 +08:00
morluto 3f5d879414 fix(cli): retain nested facts in Markdown tables 2026-10-24 03:16:29 +08:00
morluto cae03361cf fix(reference): separate local filesystem diagnostics from graph commitments 2026-10-24 03:11:07 +08:00
morluto 7479f0a464 fix(environment): distinguish destination refusal and write access failures 2026-10-24 03:11:07 +08:00
morluto 4a24b7e154 fix(evidence): preserve valid output paths near filesystem pathname limits 2026-10-24 03:00:09 +08:00
morluto ca8b6727c3 fix(cli): reject surplus positional arguments before execution 2026-10-24 03:00:08 +08:00
morluto b885f44bef fix(cli): preserve explicit Evidence record pairing in bundle comparison 2026-10-24 02:50:51 +08:00
morluto 0c4bf68ce8 merge: reconcile concurrent main fixes with issue remediation 2026-10-24 02:45:14 +08:00
morluto c3e4c116d5 fix(reference): retain unknown package scope for JavaScript loaders 2026-10-24 02:41:05 +08:00
morluto 80bc0f5ede docs: correct setup capture and recovery boundary guidance 2026-10-24 02:40:21 +08:00
morluto f2e5fd148a fix(reference): preserve module syntax and loader request identity 2026-10-24 02:35:36 +08:00
morluto ddb3987bb4 fix(reference): project import failures through the canonical error contract 2026-10-24 02:35:22 +08:00
morluto 1998640669 fix(reference): scope ignore rules and honor local Git case policy 2026-10-24 02:29:44 +08:00
kiranandgensokyo-dev 5d2c8c2b78 feat(cli)!: export row-oriented results as JSON Lines (#5629)
* 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]>
2026-10-24 02:13:28 +08:00
morluto 8aa40e9a61 fix(cache): scope Evidence display refresh to matching snapshot bindings 2026-10-24 01:47:30 +08:00