* feat(evidence): discover retained records without full payloads
* fix(evidence): guide oversized results to retained discovery
* style(tests): format retained discovery recovery assertion
Add optional finalization_ms to keep observing a captured root after SIGTERM, record the actual finalizer exit and each signal attempt, and escalate once when needed. Bind the initial root identity to captured ownership and preserve observations through cleanup uncertainty.
Fixes#1253.
Co-authored-by: Mykola Dementiev <[email protected]>
Co-authored-by: N0zoM1z0 <[email protected]>
* fix(electron): resolve pages served from inside app.asar
Packaged Electron applications load their renderer pages from file URLs
inside app.asar. The host filesystem cannot stat those paths, so
list_electron_targets excluded every such page as unsupported_url and
inspect_electron_page could not select it.
Resolve these URLs the way Electron's file protocol does: the first .asar
path component that is a regular file is the archive, and the remainder
must name a regular file in its header. Directories, links, and missing
members stay rejected. Parsed headers are cached by archive identity.
* fix(artifacts): extract and explain rewritten ASAR unpacked companions
Packaging tools commonly sign or strip .asar.unpacked native binaries after
writing the archive header, so their declared hashes no longer match.
analyze_javascript_application already accepts integrity_policy, but
extract_artifact did not, and inspect_artifact and extract_artifact still
told callers to "get a fresh copy", which cannot help for a shipped app.
- Accept integrity_policy on extract_artifact (MCP and CLI). The default
still fails closed; record-and-continue writes the observed bytes and
returns the extracted files' integrity_contradictions records.
- Name the unpacked entry and the post-packaging cause in integrity
failures, and point every operation that accepts integrity_policy at
record-and-continue.
- Report an active unpacked entry whose companion file is absent as
unavailable with its logical path instead of a format failure.
- Share one integrity_policy schema across the inventory, extraction, and
JavaScript application inputs.
* fix(electron): bound ASAR headers before allocation
---------
Co-authored-by: morluto <[email protected]>
inspect_binary_layout accepts the same optional detail input as
analyze_javascript_application. The default complete delivery is
unchanged; detail "summary" retains the complete layout Evidence in the
session and returns its inspect_analysis_view summary, whose
parent_evidence_id selects sections, symbols, mitigations or linkage
later. Both tools share one detail schema and output projection.
Co-authored-by: Claude Opus 5.5 <[email protected]>
analyze_javascript_application returns the complete application graph
inline, which repeats tens of kilobytes even for a few source lines and
exceeds the default 10 MiB MCP frame for a 300-function source file.
The new optional detail input keeps complete delivery by default. With
detail "summary" the server records the complete analysis Evidence in
the session and returns its inspect_analysis_view summary, whose
parent_evidence_id lets callers page modules, select items, or pass the
retained reference to application workflows. A server without Evidence
retention refuses summary detail with capability_unavailable rather
than returning a summary whose analysis cannot be reached.
Co-authored-by: Claude Opus 5.5 <[email protected]>
Hosts forward every tool's input schema to the model on each request.
Seventeen tools advertised a canonical example that embedded a complete
producer Evidence record, up to 22 KB each, accounting for 116 KB of the
450 KB of advertised input schemas.
Advertised examples now show an embedded Evidence record as its exact
retained-evidence reference when the canonical input accepts one, and
omit an example that can only carry inline Evidence. Canonical contract
examples, their executable tests, and validation are unchanged.
Co-authored-by: Claude Opus 5.5 <[email protected]>
Long captures emitted only a final result, so a quiet child looked idle.
Pass the shared rate-limited progress reporter through the capture lifecycle
and report the observed phase, elapsed time, and collected-unit counts.
CLI writes those lines to stderr; MCP forwards them only when the client
supplied a progress token. Final Evidence on stdout keeps its shape.
* feat(mcp): add compact input schema profile for size-capped providers
Moonshot's function-calling API rejects a request while any single tool
parameters schema exceeds its literal serialized size cap, so clients
such as kimi-cli fail every request while the default catalog is
attached (#1484).
Add an opt-in REA_MCP_INPUT_SCHEMA_PROFILE=compact server presentation.
Each advertised input schema is rendered within a 13,312-byte budget,
measured to sit below the observed provider cap: annotation prose
(nested descriptions, examples, defaults, titles) is dropped, repeated
annotation-free subschemas are shared through schema-local $defs/$ref
references the provider validates without expansion, and the three
structurally oversized schemas are advertised in a documented reduced
form. The canonical catalog, tool set, output schemas, and server-side
canonical validation are unchanged; the default full profile is
byte-identical to today's advertisement.
Boundary tests pin every compact schema to the budget, keep them valid
JSON Schema that still accepts every canonical example, hold reduced
presentations at three or fewer, and verify canonical rejection still
guards a permissive advertisement. Verified against the real Moonshot
API through kimi-cli: prompts succeed with the compact catalog attached
where the default catalog fails every request with 400.
* fix(mcp): preserve compact schemas through Kimi conversion
---------
Co-authored-by: morluto <[email protected]>
inspect_analysis_view is the recovery path when an analyze_function
dossier exceeds the MCP response budget, but its native facets covered
only procedure, pseudocode, assembly, callers/callees, references, and
value flow. Basic blocks, comments, unresolved calls, referenced strings
and names, and the native API record could not be read from retained
Evidence at all; basic blocks grow with the function just like assembly.
These are now facets: collections page by rows, and native_api is a
singleton. A dossier without an unresolved_calls record reports "not
recorded" rather than the value-flow failure reason.
Refs #1247 and #1065.
Co-authored-by: Claude Opus 5.5 <[email protected]>
Advertise content- and dialect-bound identities for self-contained output schemas so the SDK can reuse unchanged Ajv validators after complete tools/list refreshes. Preserve explicit IDs and relative reference bases.
Verify changed schemas, availability transitions, reconnects, numeric and selector constraints, explicit IDs, relative references, and advertised dialects through the pinned SDK boundaries.
Refs #1065, #723
createAnalysisExecution defaulted an omitted rawResult to a second
complete copy of the result. Every caller that had no distinct provider
representation therefore doubled its Evidence: decode_interface_builder,
inspect_keyed_archive, inspect_asset_catalog, trace_dylib_resolution,
inspect_native_dispatch_metadata, observe_native_calls,
observe_native_ui/capture_native_ui_scenario (including screenshots), and
small Ghidra/IDA lifecycle records. Sibling operations of the same
providers already recorded null.
An omitted rawResult now records null. Normalized results are unchanged.
MCP responses repeat Evidence in text and structured content, so each
response and its share of the 10 MiB transport budget shrink by the same
half; e.g. trace_dylib_resolution on a real app bundle drops from
3,217,119 to 1,612,524 bytes per representation.
Co-authored-by: Claude Opus 5.5 <[email protected]>
* fix(mcp): advertise object roots for union input schemas
Anthropic tool input schemas reject anyOf, oneOf, and allOf at the root.
Since 63bf9140 removed root flattening, compare_web_captures,
inspect_web_page, inspect_electron_page, and
project_managed_application_graph advertised root unions: Claude Desktop
disabled compare_web_captures and Claude Code exposed the tools without
parameters.
Present a root union of plain-reference object branches as one strict
object with the union of properties, shared required fields, a
minProperties bound, and a description of the accepted input groups. The
canonical Zod union still validates every call, so mixed input groups are
rejected before the handler runs. Branches whose reference siblings cannot
be merged keep their root alternatives.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* test(browser): keep comparison input boundary within lint limits
Express advertised and runtime expectations as one case table so the
boundary test stays under the 150-line function limit.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(mcp): preserve input group dependencies in object schemas
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
Since #1277 an error result reaches the client without structuredContent,
but toErrorToolResult and the transport recovery still budgeted it as
structured JSON plus escaped text. An error whose text fit between about
half and all of the response budget was replaced by resource_constraint,
and without Evidence retention the original diagnostic was lost.
Count only the escaped text for errors. The boundary, process-global and
real Ghidra large-result probes now use diagnostics that exceed the
text-only budget.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(mcp): deliver tool errors within advertised schema contracts
Retain complete typed JSON error content while omitting non-conforming
structured errors at the public transport boundary. Recover oversized
diagnostics into Evidence before removing their private structured carrier.
Update schema-validated client readers and cover actual stdio delivery.
Closes#1261
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
* test(mcp): read typed errors in canonical Evidence regressions
* test(mcp): validate public error diagnostics in acceptance workflows
Deliver complete Evidence directly through MCP with required nullable analysis profiles and immutable per-server delivery settings. Bind selected environments at construction and require typed cleanup outcomes with retained retry ownership.
Remove test-only routing, duplicate session and snapshot metadata, producer-field repairs, and ambiguous provider arguments. Separate artifact byte identity from occurrence classification and retain typed source-map and partial native facts across CLI, MCP, and verifier consumers.
BREAKING CHANGE: obsolete Evidence envelopes, session aliases, incomplete snapshots, and missing normalized producer facts are no longer accepted.
Add explicit summary, facet, item and paged views of retained analysis Evidence without repeating analysis. Preserve captured observations, graph validation, artifact identity, coverage and complete default results.
Fixes#1050
Verified with focused source, CLI, pinned-SDK schema and MCP tests, serial static checks, and one complete native Windows Notion ASAR workflow. Real Hopper/Ghidra verification was not performed for this provider-independent projection change.
Co-authored-by: Matt Van Horn <[email protected]>
* fix: Handle relayed SIGINT gracefully in withProcessCancellation
Changes `process.once` to `process.on` for SIGINT in `DirectAnalysis.ts`.
When REA is launched via npx, a single process-group SIGINT triggers two
SIGINT events (one direct, one relayed). Previously, the first event would
consume the handler and the second would abruptly terminate the Node process,
abandoning Ghidra resource cleanup.
This change ensures subsequent SIGINTs idempotently request cancellation
without crashing the process, matching the behaviour of `withCommandCancellation`.
* fix(cli): keep termination guards through provider cleanup
* test(cli): exercise repeated analysis signals on macOS
---------
Co-authored-by: N0zoM1z0 <[email protected]>
* feat(ghidra): make the startup deadline configurable
Large binaries (an 8 MB PE with about 20,000 functions) need more than the
fixed 330 s for import and full auto-analysis, so every first request timed
out. REA_GHIDRA_STARTUP_TIMEOUT_MS overrides the deadline in milliseconds;
absent, empty or invalid values keep the 330 s default.
* docs(ghidra): document REA_GHIDRA_STARTUP_TIMEOUT_MS
* fix(ghidra): parse startup deadlines through runtime configuration
---------
Co-authored-by: morluto <[email protected]>
Retain complete authenticated application Evidence when the repeated MCP representation exceeds the default receive frame or Node string limit. Return a typed transport constraint, keep useful followup queries available, and stream full canonical bundles to atomic destinations.
Verify complete Notion and Obsidian workflows on Linux and native Windows, full CLI/Evidence parity, and real large Chrome screenshot recovery. Preserve complete success contracts and caller-selected evidence paths.
Refs #1065, #1053.
* fix(mcp): advertise JSON values without recursive schemas
`z.json()` projects a self-referential `$defs/__schema0` entry. Twenty
tool input schemas and 123 output schemas carried it, and clients or
model APIs that reject recursive JSON Schemas refuse the whole tool
list. Every JSON value satisfies `{}`, so the shared JSON value schema
now advertises that. Runtime parsing still admits only JSON values.
Refs #919
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(mcp): keep advertised input schemas within model function-calling limits
Some model providers reject the whole tool list when any input schema
contains a recursive $ref or nests deeper than 10 levels (fixes#919).
Sanitize the advertised wire projection: break cyclic $refs, bound nesting
depth, and drop unreachable $defs. Canonical Zod contracts are untouched.
---------
Co-authored-by: Kaoru0822 <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: sx4im <[email protected]>
Co-authored-by: N0zoM1z0 <[email protected]>
## Changes
Related to #545 and the permission-system removal in #555.
- Upgrade the shipped skill to v24 and remove obsolete filesystem grants, per-call approval flags, Electron file-root configuration, and DMG approval flags. Calls follow the user-requested investigation directly. Keep setup plan confirmation, actual OS requirements, and process/archive lifecycle boundaries.
- Correct the passive browser guide: endpoint/scope come from requests; ordinary local URL queries are retained, while credentials remain redacted.
- Audit canonical tool effects: declare possible DMG process/temp-directory effects, mark fresh extraction non-idempotent, and mark comparisons of supplied captures/PNGs as closed-world. Align artifact-provider capability effects with temporary mount-directory writes.
- Retain non-read-only hints for calls that add Evidence to the session; document that annotations are hints and that clients control their confirmation UI. Do not mislabel session mutations as read-only to suppress prompts.
- Regenerate package, skill, MCP, and product metadata from source.
## Verification
- `npm run test:focused -- <11 affected test files>`: **40 tests passed**, including skill transaction/backup/idempotence, SDK tools/list annotations, actual local capture/PNG comparisons, artifact extraction/containment/cancellation, DMG launcher/cleanup seam, setup confirmation, browser MCP and scenario MCP, CLI catalog parity.
- `npm run check`: typecheck, lint, format, knip, package metadata.
- `npm run docs:check`: generated catalogs, skill metadata, documentation facts, completion ledger, error schema.
No local real Hopper/Ghidra run: their adapters and analysis operations are unchanged. Native macOS DMG behavior is covered locally through the launcher seam; no local macOS/hdiutil claim is made.
Real browser verification passed using existing Headless Chrome143.0.7499.4: actual CLI/stdio MCP,9,331,407-byte PNG, passive capture/source maps, and owned/external scenario cleanup. An initial full Chrome143 run failed the existing screenshot-height assertion (1397 versus1536); the dedicated headless-shell run passed the complete verifier without code changes. The verifier run-lineage field remained unavailable; no lineage-coverage claim is made. Browser download into `.codex` was blocked by CDN403, so the successful run used an existing browser without changing host configuration.
Return complete canonical Evidence records inline, including normalized_result, and preserve direct comparison and retained bundle identity.
Verified full deterministic gate, real Linux Ghidra CLI/MCP and independently installed artifact, generic package acceptance, private local samples, and targeted updates after syncing main.
Closes#551
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
* fix(hopper): report unavailable procedure body coverage
* refactor!: simplify runtime tools and remove replay engines
Keep direct inspection, capture, and comparison tools. Bind handlers to named contracts and let agents compose experiments with commands and local fixture servers.
BREAKING CHANGE: Remove controlled replay, Node characterization, finite replay-machine, managed runtime planning, and redundant string-tracing tools. Retire process replay, shims, reactive scenarios, custom checkpoints, and active browser replay and origin-scope inputs.