Use one named input-schema projection for clients and catalog identity, preserve dialect declarations, and bound compact schema depth. Keep canonical SDK output validation when output advertisements are disabled. Release request-owned state on cancellation and carry upstream limitations through composed workflows. Preserve doctor full-output envelopes and validate navigation facts at their owner.
Reviewed fixes: #2088, #2108, #2513, #2684, #2693, #2695, #2836, #2864, #2868, #2877, #2933, #2998, #3002, #3015.
Validation: focused schema, SDK output-validation, context, and workflow tests passed; no schema dialect or canonical output validation was relaxed.
Declare observed Ghidra and Hopper facets, preserve unavailable pseudocode, and attach dossier call-set coverage. Version the analysis profiles to invalidate older snapshots and remove the retired include_assembly fixture branch.
Add MCP comparison and snapshot-replay regressions plus real-provider checks for empty and unavailable facets. Fixes#2980.
* fix(process): expose Darwin swiftc compile deadline via env
Busy hosts can exceed the hard-coded 60s ownership-helper compile
timeout. Honor REA_SWIFTC_COMPILE_TIMEOUT_MS like the other provider
startup deadlines, keeping 60000 as the default.
Fixes#2184
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(process): keep the Swift compile deadline with its runtime owner
* fix(comparison): recheck historical calls-only changes (#2223)
* fix(comparison): preserve incomplete function call evidence
Keep missing, unknown, partial and unresolved call relationships unknown in function comparisons and reconstruction claims. Aggregate IDA caller and callee coverage without overwriting uncertainty.
Validate with 144 focused tests, typecheck/lint, docs checks and test discovery. Real providers were not verified; the full headless IDA session suite requires unavailable Windows native controls.
* fix(comparison): recheck historical calls-only changes
---------
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
(cherry picked from commit 688defca0f)
* fix(ci): isolate Linux Hopper process fixture inventory
(cherry picked from commit 8cac51e12184d56a9ba80a4427b3e6082ddac1ec)
* fix(android): make DEX descriptor pattern portable
(cherry picked from commit 1335bcddc569a1cfb34b6efedcb6f2e3aaaa3357)
* fix: repair the static-check failures on the default branch (#2895)
* fix: repair the static-check failures on the default branch
The default branch fails its own required `Static checks` job three ways, so
every pull request reports that job as failed regardless of its own change.
- `npm run format:check` reports `src/domain/functionComparison.test.ts` and
`src/ida/IdaOperationRunner.ts`.
- `npm run lint` reports a duplicate `import { join } from "node:path"` in
`tests/boundary/mcp/ghidraInventoryMcp.test.ts` (lines 4 and 17).
- `npm run typecheck` reports `format: "devin"` missing from the client format
union in `src/application/SupportedClients.ts`, and an unchecked index in
`tests/boundary/cli/clientProfileLifecycle.test.ts`, whose pair array is
inferred as `string[][]`.
Apply the pinned formatter, drop the duplicate import, list the `"devin"` format
that its own definition already uses, and mark the pair array `as const`.
Validation: `npm run check:fast` and `npm run format:check` pass.
* fix(setup): keep Devin on the JSON configuration dialect
---------
Co-authored-by: 吴佳浩 <wujiahao@supremind.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
(cherry picked from commit df3d96da80)
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
Co-authored-by: morluto <17176810+morluto@users.noreply.github.com>
Co-authored-by: Lucien <164857476+dakjdakd@users.noreply.github.com>
Co-authored-by: 吴佳浩Alben <35291372+XiaoBinGan@users.noreply.github.com>
Co-authored-by: 吴佳浩 <wujiahao@supremind.com>
Error results reach the wire as text plus `isError: true`, but the
text-only envelope omitted the flag. An error up to 15 bytes above the
result budget passed both the delivery and transport checks and was sent
as the original diagnostic instead of taking the oversized-error recovery
path.
Rename the error representation to "error-text" and size its envelope
with the flag, so ToolResultDelivery and the error transport share the
complete delivered shape. Successful structured results are unchanged.
Fixes#2557
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* perf(native): add opt-in Mach-O summary delivery and retained pages
inspect_macho returns every import and export inline. For VS Code's
Electron Framework one MCP call carries 2.5 MB of text (about 828k o200k
tokens), and the same again as structuredContent; the MCP response
budget admits it. Agents asking for slice identity, UUID or dependency
counts paid that cost on every first call.
Add the established opt-in detail selection: omitted or complete keeps
the existing complete result and Evidence identity, while summary
retains the complete Evidence and returns slice identity with
per-collection returned/total/exhaustive counts (956 tokens).
inspect_analysis_view kind macho pages the original rows of any
collection or the command provenance, repeating the producer's own
total and exhaustive flag so page exhaustion is never read as absence.
Delivery detail never reaches the native tools or the source Evidence
ID: registerEvidenceTools gains a parametersForEvidence hook, so the
summary's parent is the same Evidence as a complete call.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(mcp): refuse unretainable summary delivery before analysis
A server without Evidence retention (a fixed analysis source) ran the
complete inspect_macho or inspect_artifact analysis for detail summary
and only then refused it in summarizeRetainedAnalysis, paying the very
cost summary delivery exists to avoid. registerEvidenceTools gains a
preflight hook; both registrations check retention there, as the WASM,
EVM, managed, pcap and capture handlers already do before dispatch.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(native): keep whole rows in Mach-O architecture and segment pages
The page item union listed plain-object row arrays, and zod returns the
first union member that parses while dropping unknown keys. Entrypoint
rows declare only file_offset, so every architecture and segment row
(which also carry a numeric file_offset) matched it and lost its name,
CPU fields, permissions and sections. Rows now use exact key sets, and
imports/exports share one member. The MCP test pages every facet of a
real /bin/ls and compares it with the unparsed complete rows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Close persisted Evidence, bundle, profile and unknown record shapes so parsing cannot silently remove caller metadata before checking semantic identity. Keep constructor provider projection explicit and JSON payload fields open.
Exercise actual MCP export/import with independent record and manifest mutations, unchanged state after rejection, and a valid round trip. Prune duplicate source assertions. Validation: focused domain/CLI/MCP/filesystem checks, converted JSON Schemas, docs and typecheck/lint.
Keep complete default delivery and exact filters. Select stable ID pages at the ledger owner before cloning, return filtered totals and continuation offsets, and preserve detached records through the shared session port.
Validate public MCP paging, safe-integer edges, snapshot replay and converted JSON Schemas. Document the bounded Flameox workflow comparison and its token/CPU/latency measurement limits; no real model performance claim.
* feat(server): frame analysis-target content as untrusted data
Strings, decompiled code, page text, scripts, captures and logs returned
by REA originate from the analysed target, which can embed text aimed at
the agent. Nothing marked that content, so a prompt injection inside a
binary or page could steer the agent toward tools that run code.
- Server instructions now state that target-derived tool output is data,
never instructions, and that any request in it to run, install,
download or send something is a prompt-injection attempt to report.
- Tool contracts declare returnsTargetContent. It is on by default; only
seven tools whose results hold REA session state or caller-supplied
values (binary_session, close_binary, export_evidence_bundle,
record_unknown, update_unknown, inspect_adb_client,
inspect_apktool_client) are audited exceptions, so new tools start
marked.
- Successful results of marked tools carry
_meta.provenance = { untrusted_content: true, source: "analysis_target" }.
content and structuredContent are unchanged, and the response budget
accounts for the fixed marker bytes.
Tests cover the encoding and budget accounting, the audited exception
list against the contract catalog, and an in-memory MCP client that sees
the instructions and the marker on a marked tool but not on
binary_session.
* fix(server): mark failed target-content results as untrusted too
The untrusted provenance marker was attached only on the success branch
of ToolResultDelivery, but failures can carry target-derived text as
well: error messages, captured output, and partial observations such as
the terminal frames a failed capture_process_scenario retains in
partial_observation. A host gating later process or device actions on the
marker would have treated an adversarial error payload as trusted.
Every error path in src/server now carries the failing tool's provenance:
- toErrorToolResult and toRecordedPartialErrorToolResult take the tool's
target-content flag explicitly, so each caller is audited by the type
checker; toCallToolResult, toEvidenceToolResult (recording failure), the
response-budget error that replaces an oversized success, and the
Electron partial-evidence path pass contract.returnsTargetContent.
- Admission failures in runAdmittedToolOperation resolve the flag from the
tool name through the new toolReturnsTargetContent, the same predicate
the contract metadata uses; unknown names stay marked.
- The transport's oversized-error replacement keeps the original's marker
and counts it in its budget check, matching the projected error.
- Errors the MCP SDK builds itself (input validation, thrown handlers) are
marked in the transport for target-content tools only.
Error encoding accounts for the marker bytes exactly as success encoding
does. docs/mcp-contracts.md now states that error results carry the
marker. Tests cover marked and unmarked error results, the
capture_process_scenario partial-observation errors in-process and over
the SDK transport, the recorded partial-evidence path, the budget
replacement, the oversized-error replacement, and SDK validation errors
for a marked and a content-free tool.
* fix(contracts): mark session status, close and client probes as target content
The content-free exception set was audited against successful results
only. Now that failures carry the marker too, every exception was
re-audited against its error paths with one question: can the result
include text produced by an external process, provider or device, or
stored content REA did not author?
Removed from TARGET_CONTENT_FREE_TOOLS:
- close_binary: a failed provider cleanup (GhidraClient cleanup error via
createGhidraDiagnostics) projects the launcher's captured stdout and
stderr, which can contain target-derived log text.
- binary_session: capability status reports runtime unavailability as the
provider error message (ProviderAdapterError and similar), and the
provider candidate and Android availability diagnostics include probe
output such as the apktool stderr excerpt.
- inspect_adb_client: the success result carries the version and
installed path parsed from `adb version` stdout, and a failed probe
keeps a stderr_excerpt.
- inspect_apktool_client: the success result carries the first line of
the launcher's `--version` output, and a failed probe keeps a
stderr_excerpt.
- update_unknown: the new revision carries forward the stored question
and domain, which an imported evidence bundle can supply; list_unknowns
and get_evidence_bundle already return that data marked.
The set now holds only export_evidence_bundle (path, byte and record
counts; failures are filesystem, cancellation, or a fixed integrity
message) and record_unknown (the caller's input plus REA-computed ids
and digests; registry errors project only a reason code).
The conformance test pins the reduced set and asserts each removed tool
is marked. Tests that used binary_session as the unmarked example now use
record_unknown. docs/mcp-contracts.md lists the remaining exceptions and
why the removed tools stay marked.
* fix(contracts): include target-content policy in the catalog identity
createToolCatalog() and CATALOG_IDENTITY.tools projected every
client-visible contract field except returnsTargetContent. Because the
untrusted-content framing left schemas, effects, prompts, CLI names and
the package version unchanged, a same-version MCP process started before
the update digested equal to the new server and binary_session reported
it aligned although it never emits _meta.provenance.
Project the flag as returns_target_content in both the digested tool
catalog and CATALOG_IDENTITY.tools, and export createCatalogDigests so a
boundary test proves that toggling the flag on one tool changes the
tools and combined digests.
Put setup, developer commands, MCP replies, and investigation recipes before
client details and implementation references. Preserve existing guide anchors,
examples, provenance, partial-result recovery, and provider restrictions.
Correct verified documentation drift, synchronize the Ghidra capability
wording, and regenerate metadata for skill version 40. Keep uncertain platform
and lifecycle findings unchanged. Refs #2156.
Validation: 56 focused tests, check:fast, docs:check, VitePress production build,
format and link/example checks. Real isolated CLI/MCP probes cover Ghidra,
NativeAOT, HAR, cancellation, Chrome, large ELF delivery, native type limits,
and the new JS/managed/process/setup recipes. Heavy work uses two CPUs;
a resource-heavy DOM probe was stopped and replaced by a smaller real CDP
payload-limit control. Windows, macOS GUI, ADB, and the full CI matrix were
not executed.
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Add opt-in retained inventory and WASM Evidence views with exact nested output contracts and a small static WASM descriptor. Preserve old complete CLI/MCP workflows, producer choices, original authenticated Evidence and cleanup ownership.
Validated with real public applications, genuine old Evidence migration, 123 focused assertions, 11 synchronized description checks and 42 installed-package WABT cases. Detailed generated experiment JSON stays outside the final tree; concise findings and reproduction inputs remain. Main-existing completion/package CI failures are separately attributed and left unchanged.
Refs #2016
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Distinguish an unresolved goal from an exhausted call graph and preserve provider failures through cancellation. Retain completed IDA replies and post-operation identity observations as partial Evidence without claiming a verified final binding. Remove source-wide bundler cache-name heuristics and stale expectations.
* feat(mcp): derive an API surface view from retained web network captures
* fix(mcp): fail closed on sensitive parents and budget api-surface path expansion
* fix(mcp): keep recorded api-surface paths and budget only templated segments
* fix(mcp): read api-surface paths only from canonical URLs and charge new values once
* fix(mcp): reject authority-less api-surface URLs and key groups by rule positions
* fix(mcp): label api-surface confidence from all groups and cap transient path memory
* fix(mcp): budget api-surface dedup sets and narrow detail outputs
Charge retained deduplication sets before allocation, advertise only
each analysis operation's summary from its detail output, and document
that any templated group makes every API-surface page inferred.
* fix(mcp): bound api-surface path text and record limitations
Charge retained literal path copies before allocation, publish only
valid media-type essences, and deduplicate examined record limitations
onto the view.
* fix(mcp): keep api-surface refusals and path splits inside the reply budget
Sensitive-parent refusals now use the token sensitive_values_unretained so declared literals are not echoed. A later path split is charged against bytes already retained, and the published example includes the HAR record limitation with its matching digest.
* fix(mcp): budget api-surface method text before group keys
Charge method and origin text against the reply budget before the group key is serialized. Document that samples merge only when method, origin, and exact segment rules match.
* fix(mcp): bound api-surface copies and control-character authorities
Reject authorities containing a tab or newline so WHATWG cannot move userinfo into the recorded path. Charge four path copies, two method and origin copies, and each distinct content type against bytes already retained.
* fix(mcp): preflight combined api-surface group charges
Total path, method, origin, and segment charges before retaining a new group. Track content types in a set so distinct MIME essences are not compared quadratically.
* fix(mcp): charge api-surface content-type sets on first use
Create the per-group content-type set when the first essence is retained, and charge it before allocation. Groups with no content type no longer keep an empty set.
* refactor(analysis): centralize API-surface ownership and admission
Own grouping, deduplication, and combined retained/temporary resource admission in one accumulator. Charge fixed group storage before allocation and materialize only the requested page.
Share recorded URL parsing between capture redaction and projection, preserving source paths and excluding ambiguous credential fields. Cover resource admission invariants and the compiled HAR-to-view workflow.
* fix(analysis): admit capture schema clone before parsing
* fix(javascript): share Electron mutation proof with wrapped calls
* test(mcp): align graph and catalog checks with current contracts
* fix(analysis): admit and validate portable capture views
---------
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
Return deduplicated execution caveats once and preserve provider-owned relationship diagnostics and completeness on graph nodes. Keep complete relationship reads exhaustive despite contextual caveats, including portable call-path reconstruction.
Preserve omitted diagnostic fields in historical Evidence and bind reported diagnostics into semantic identity. Revise graph workflow and Ghidra adapter profiles so old cached representations cannot replay under the new contracts.
Remove stale duplicate-lookup test claims and redundant fixture validation. Prune million-entry duplicate cases while retaining argument-stack and deep-chain regressions; bounded Flameox captures identified validation and canonical hashing costs.
Validation: static and architecture checks, generated docs, 364 focused tests before pruning, 21 call-path tests after pruning, public MCP schema validation and targeted profile tests. Real engine behavior was not locally exercised.
BREAKING CHANGE: get_call_graph normalized_result now contains { graph, limitations }; traversal-depth groups are under graph.
Group repeated session tool availability and provider capability facts, preserve complete named contracts and ordered limitations, and remove duplicate catalog descriptors. Update consumers and migration guidance.
Validated by all 31 CI jobs, focused source checks, and actual Claude Code/Linux Hopper/native Windows Ghidra small-target workflows on the current integration tree.
Refs #723.
BREAKING CHANGE: binary_session no longer includes server_identity.catalog.tools; tool_availability and provider capabilities use grouped facts documented in docs/mcp-contracts.md.
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Give atomic Evidence and snapshot writes an explicit resource owner, preserve primary failures and completed publication receipts, and retry retained staging cleanup at the owning lifecycle. Verify inode identity before publishing or deleting; unknown path disappearance remains a cleanup failure. Keep snapshot admission reusable when a session closes and reopens.
Consolidate JavaScript source-scope classification so cancellation cannot fabricate failures for unselected files. Classify configuration failures as invalid input. Remove stale assertions and reuse shared test cleanup ownership.
Validation: 266 focused tests before final ownership tightening, 108 affected tests afterward, static and documentation checks, actual invalid-configuration CLI behavior, and isolated test temporary-directory hygiene.
Refs #1968
Supply schema-validated inspect_analysis_view arguments after completed native function Evidence is recorded and exceeds MCP delivery capacity. Preserve the full canonical result and its provenance. Verify exact source paging, export and following-call usability through real Ghidra stdio MCP.
Fixes#1849
Co-authored-by: Minghang Chamling <133689405+cold-atom@users.noreply.github.com>
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
* test(ida): expect callee edges from the call graph on non-x86 targets
* fix(ida): read callee edges from the call graph on non-x86 targets
* test(ida): pin address order of call graph additions
* docs(ida): describe the call graph source for non-x86 callees
* test(ida): pin the x86 baseline, the call graph reader and its failure modes
* fix(ida): check the call graph root, scope truncation to the root and degrade without callgraph
* test(ida): expect managed PE off the x86 path, possible-truncation wording and a complete ARM64 traversal
* fix(ida): keep managed PE and x86 reads off the call graph path and qualify truncation
* test(ida): answer only expected leaf roots and assert the requested call graph roots
* test(ida): expect a call graph the producer cannot give consistently to fail the callee read
* fix(ida): fail the callee read when the call graph cannot be obtained consistently
* fix(ida): preserve call edge authority and workflow uncertainty
* fix(ida): preserve explicit root call graph caps
---------
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
MCP annotations derived destructiveHint only from mayDiscardData, so tools
that run the analysis target or a caller-selected executable
(capture_process_scenario, observe_native_calls) and tools that change an
attached Android device (install/uninstall/push/start/stop) advertised
destructiveHint: false.
Add explicit executesForeignCode and mutatesDevice effect flags, audit them
across all 170 tool effect records, and derive
destructiveHint = mayDiscardData || executesForeignCode || mutatesDevice.
readOnlyHint semantics are unchanged.
Hopper/Ghidra metadata writers (set_address_name, set_addresses_names,
set_bookmark, set_comment, set_inline_comment, annotate_native_function)
can replace or clear existing analyst names and comments, so they now
declare mayDiscardData as well.
A contract test pins the destructive set and requires every tool whose
description mentions running, launching, executing, starting, installing or
uninstalling to declare one of the new flags or carry a reasoned exception,
so wording and effects cannot silently drift. The binary_session effects
output schema carries the new flags.
Forward Ghidra startup waiting observations through the existing progress reporter. Count emitted MCP status notifications and omit the unknown total to keep progress strictly increasing.
Verified with focused tests, type/lint/docs checks, packaging and actual installed Windows timeout/recovery workflows. Native first-query speed and large-target memory remain open under #1065.
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Preserve the primary Hopper startup failure and launcher diagnostics while retaining resources when cleanup cannot be confirmed. Reauthenticate matching external application sessions before document cleanup, keep the Python bridge available for bounded reconnects, and expose the provider-owned Hopper startup deadline.
Real headless Linux Hopper semantic analysis and 65 focused configuration, handshake, cleanup, and bridge tests passed. macOS authorization/crash causes and saved-HOP behavior require their own real-provider verification.
Refs #1808
Co-authored-by: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
* 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 <16836724+nikolay-dementiev@users.noreply.github.com>
Co-authored-by: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com>
* 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 <76467478+morluto@users.noreply.github.com>
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
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 <76467478+morluto@users.noreply.github.com>
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
* 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 <noreply@anthropic.com>
* 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 <noreply@anthropic.com>
* fix(mcp): preserve input group dependencies in object schemas
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
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 <noreply@anthropic.com>
* 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 <455140+mvanhorn@users.noreply.github.com>
* 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 <1705004398@qq.com>
* 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 <76467478+morluto@users.noreply.github.com>