* fix(application): accept alternative document selection in binary_overview (#2460)
Update binary_overview capability negotiation so that either current_document or list_documents satisfies the document identity requirement, matching resolveAnalysisDocument runtime semantics. When a provider declares neither document capability, resolveAnalysisDocument reports AnalysisCapabilityUnavailableError for current_document rather than leaking the internal list_documents fallback. Preserve list_segments as an independently mandatory requirement.
* fix(application): retain document fallback provider errors
Return the fallback producer error unchanged, retaining operation identity, retry advice, diagnostics and cleanup instead of fabricating missing capabilities.
Source inspection and git diff --check; tests/builds/typechecks/CI reruns skipped at explicit user request.
* test(application): retain document fallback error expectations
Composition and MCP controls now expect the original list_documents producer error and reason.
Source inspection and git diff --check only. Tests, builds and typechecks skipped by explicit user request. GitHub review writes paused globally.
* fix(ida): assert attached-mode routing failure
---------
Co-authored-by: yashas1624 <yashas1624@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
When every registered deep provider rejected a target, select() returned
an intentionally unbound success for any concrete environment selector,
including one that names no registered provider. A misconfigured
REA_ANALYSIS_PROVIDER therefore opened the target unbound, and the later
deep-operation diagnostic blamed target support instead of the unknown
configuration. The same identifier requested explicitly already failed
with unknown_provider.
Take the unbound shortcut only for a registered environment preference.
An unknown configured identifier now reaches concrete selection and fails
with unknown_provider, matching the explicit request. Registered
preferences and auto still leave artifact-only targets unbound.
Fixes#2592
* feat(managed): decode ldstr user strings in member inspection
inspect_managed_members reported every ldstr operand as a bare 0x70 token,
so an analyst could see that a method loads a literal but not which one.
Answering "where is this path or key used" required a second tool.
Read the optional #US stream and add a top-level user_strings inventory:
each distinct token loaded by an inspected method body, once, in token
order, with its #US file offset and decoded UTF-16 value. Instruction
anchors and normalized CIL digests keep their build-local tokens. A missing
#US stream or malformed item is reported against its token as partial
coverage. Evidence recorded before this field reads user_strings as null.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): collect user strings only from ldstr
A malformed ldtoken can carry a 0x70 token, which the operand decoder
classifies as a string operand. Only ldstr loads a literal, so collect
user strings by opcode.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): admit user-string tokens and failures before collecting them
Charge each distinct ldstr token to the decode budget before adding it to
the collection set, and admit each #US failure before retaining it. A
missing #US stream is now one stream-level issue rather than one per
token.
Document why the #US terminal flag is not validated: Mono and Roslyn
assemblies disagree with ECMA-335 II.24.2.4 and the runtime ignores it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(managed): describe missing #US reporting and the unvalidated flag byte
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(managed): cover #US items that run past the stream end
An odd length whose payload crosses the end of #US, and a two-byte
length prefix that starts on the last #US byte, are both rejected as
"User string leaves #US" beside a readable literal. The test fails if
that bounds check is removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): report reserved #US length prefixes as string failures
The compressed-length reader shared by #Blob and #US hard-coded
invalid-blob and "Metadata blob" for a reserved prefix, so a malformed
user string was published as a blob failure. The caller now names the
item it reads: #Blob keeps its code and message, and #US reports
invalid-string.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): append member inspection issues without argument spreading
inspectManagedMembersBytes gathered every producer's issues with
issues.push(...list), passing one argument per issue. A large malformed
input, such as hundreds of thousands of distinct bad ldstr operands or
MemberRef rows, overflows the stack with an untyped RangeError instead of
returning partial coverage. All six sites now use
appendManagedParseIssues, which appends one issue at a time.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): classify truncated #US and #Blob length prefixes by item
A two- or four-byte compressed-length prefix cut off by the end of the
artifact went through the generic range check and was reported as
invalid-row. The prefix reader now uses the item's own code for both
reserved and truncated prefixes: invalid-string for #US, invalid-blob for
#Blob. The unused generic range helper is removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): retain user-string terminal flag conformance issues
* test(managed): write ECMA-335 #US terminal flags and cover flag issues
d5b7b0704 reports a #US terminal flag that differs from ECMA-335
II.24.2.4. The fixture heap always wrote 0, so its non-Latin-1 literals
now read as nonconforming. The fixture writes the spec flag, and a new
test flips one flag each way ("ok" set to 1, "it's" set to 0) and checks
that both literals remain beside one issue each.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): classify ldstr operands before collapsing a missing #US
With no #US stream, every collected ldstr operand was counted as a #US
reference and reported only as missing-stream, while the same non-0x70
operand got invalid-heap-index when the stream existed. parseUserStrings
now owns which operands are user-string tokens: any other operand is
invalid-heap-index either way, and only 0x70 tokens count toward the
missing-stream issue. The heap reader drops its duplicate kind check.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): state user-string limits in member comparisons
compare_managed_members ignored user_strings, so a method whose ldstr
literal changed at the same token, or legacy Evidence that never examined
literals, could read as unchanged with no caveat. The comparison now adds
an unknown limitation when either side predates user strings and a
not-compared limitation when literals were observed. ExportedType and
user-string inventories share one uncomparedInventory rule.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(managed): advertise ldstr literals in member inspection help
The MCP tool description, the type_names input, and the CLI command and
--type help now say that inspect_managed_members returns the #US string
literals that ldstr loads, and that a type selection limits them to the
literals the selected types' method bodies load.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): read the empty #US entry at offset 0
ECMA-335 II.24.2.4 makes the first #US entry the empty blob: a zero
length with no terminal flag byte. ldstr 0x70000000 loads it, but the
odd-length check rejected it as invalid-string, dropping the literal and
making coverage partial. Offset 0 with length 0 now reads as "".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): reserve #US offset 0 and admit literals before scanning
Offset 0 is the reserved empty #US entry, so a nonempty item there is now
invalid-string instead of a published literal. The literal's projection
is reserved before the terminal-flag scan, so an inadmissible item fails
at the budget without reading every code unit. The scan's loop index no
longer shadows the token's heap index.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): report #US length prefixes wider than ECMA-335 assigns
compressedLength accepted an overlong encoding, such as 0x80 0x05 for a
5-byte item, without comment. It now reports whether the width is the
one ECMA-335 II.23.2 assigns, and the #US reader reports a non-minimal
prefix as an invalid-string conformance issue beside the readable
literal, like the terminal flag. readMetadataUserString returns every
issue it observes. #Blob behavior is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): check the #US length width before the empty entry
The offset-0 empty entry returned "" before the length-width check, so an
overlong empty entry such as 0x80 0x00 read as complete. The width issue
is now collected first and returned with the empty literal.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): admit #US width issues only for returned literals
The overlong-prefix issue was reserved before the fatal shape checks, so
an item that then failed, such as 0x80 0x00 away from offset 0, leaked
512 bytes of budget per token. The width issue is now built and admitted
only on paths that return the literal.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): keep #US issues out of member metadata status
User-string issues, including terminal-flag and length-prefix
conformance differences, marked metadata.status partial, so
compare_managed_members turned one-sided methods and fields into unknown
even though every member row was examined. #US issues now make coverage
partial while metadata.status describes the member inventory.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): give user strings their own coverage
#US issues entered the member coverage, so every consumer that reads it
as member coverage (application graph member facts, comparison status)
reported examined members as partial over a literal conformance
difference. user_strings is now { state, literals, issues }: #US issues
live there and never change the member coverage or metadata.status.
parseUserStrings returns that inventory directly.
compare_managed_members inspects with user strings skipped, since it
never reads literals, so a large literal cannot exhaust the decode budget
of a comparison. Its limitations state once that literals are not
compared, and the ExportedType limitations return to their main form.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): mark user strings partial when a body is not fully decoded
With user strings owning their coverage, an inspected method body that
was partial, malformed, or truncated no longer reached their state, so a
literal after the decode stopped was missing from a "complete" inventory.
parseUserStrings now marks the inventory partial unless every inspected
body was fully decoded, keeping the literals it did observe.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): mark user strings partial when a method row is omitted
A MethodDef row that failed before its body was read was recorded as an
issue and omitted, so its ldstr instructions were never scanned, yet the
user-string inventory could still read as complete. parseUserStrings now
takes the parseMethods result and stays partial whenever a method row
failed, as well as when an inspected body was not fully decoded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): count only method rows that may hide a selected body
Any parseMethods issue marked user strings partial, including an
unreadable name on a method outside the type selection, so a fully
scanned selection read as incomplete. parseMethods now reads each row's
owner first and reports unscannedRows: rows that produced no method while
their owner is selected or unknown. parseUserStrings uses that count.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): treat unreadably named types as possibly selected
Under a type_names selection, a type whose name could not be read may be
a requested type, but its methods were skipped without counting toward
unscannedRows, so an unexamined body left user strings complete. A
method whose owner's name is unreadable now counts as possibly selected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): judge user-string scans by CIL decoding, not body status
body.status is malformed for an invalid exception section even when
every instruction decoded, so user strings read as partial although every
ldstr was examined. The body reader now reports whether its CIL was fully
scanned, independent of exception-region validity, and parseMethods folds
unscanned bodies and unproduced rows into one unscannedMethods count that
parseUserStrings uses instead of reinterpreting body.status.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): stop deduplicating user-string issues
The inventory passed its issues through uniqueManagedParseIssues, which
serializes every issue into an unbudgeted map: about 42 MB of heap and
113 ms for 125,000 issues on Node 24. The issues are unique by
construction (one failure or per-offset conformance issues per distinct
token, one missing-stream issue), so the inventory now returns them, and
its literals, without copies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(managed): preserve selected string coverage unknowns
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* fix(ghidra): report unapplied PE CodeView PDB limitation (#2259)
When Ghidra analyzes a PE target that references companion debug symbols
in its CodeView (IMAGE_DEBUG_TYPE_CODEVIEW / RSDS or NB10) debug directory,
Ghidra's headless analyzer cannot automatically locate or apply the companion
PDB from isolated runtime directories without companion admission. Procedure
names remain analysis-generated (FUN_<address>).
Parse CodeView debug metadata (RSDS GUID/age and NB10 age) during PE target
resolution, and report an Evidence limitation informing callers and agents
that referenced debug symbols were not applied and procedure names are
analysis-generated.
Fixes#2259
* test(pe): group CodeView header coverage separately
* fix(ghidra): avoid contradictory PDB limitations
* fix(android): make DEX descriptor pattern portable
* fix(ci): isolate Linux Hopper process fixture inventory
* 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>
* style: format identity comparison and IDA runner
---------
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
Co-authored-by: Lucien <164857476+dakjdakd@users.noreply.github.com>
* fix(frida): drain admitted operations and honor queued cancellation
* fix(frida): settle cancelled loads before queued resume
* test(frida): share lifecycle fixtures without duplicating assertions
* fix(frida): preserve operation admission before session close
* test(apple): bound cold archive fixture compilation
* fix(frida): retain cancelled script creation evidence
* test(release): scope preflight schema to selected jobs
* fix(process): report no remaining time after a provider deadline fires
Node timers can fire while performance.now() is still a fraction of a
millisecond short of the monotonic deadline. ProviderStartupDeadline then
reported interruption "timeout" and an aborted signal while remainingMs()
returned ceil(0.x) = 1, so polling loops guarded by remainingMs() > 0
(Hopper and Ghidra startup) could run past an elapsed deadline, and the
real-timer test "aborts a bounded wait when its real monotonic deadline
expires" failed intermittently in CI (expected 1 to be 0).
Once the deadline's own timer has classified a timeout, report zero
remaining time. A deterministic regression test fires the timer with the
monotonic clock 0.4 ms short of the deadline.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* 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 8cac51e121)
* fix(android): make DEX descriptor pattern portable
(cherry picked from commit 1335bcddc5)
* 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: morluto <morluto@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+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>
Co-authored-by: OpenAI Codex <codex@openai.com>
* feat(native): read embedded cargo-auditable Rust dependency lists
* fix(native): trim PE section padding and compute dependency cycles iteratively
* fix(native): ignore SHT_NOBITS sections and validate dependency edges linearly
* fix(native): bound compiler path scanning and retained hashes
* fix(rust): pass package arrays as named parameterized test cases
* fix(rust): admit graph expansion and preserve resource units
* fix(rust): reject malformed packages, false cycles, and hidden compiler paths
Fail the first malformed cargo-auditable package before Zod collects an
issue per field. Require cyclic dependency indices to match the cycles in
package dependencies. Keep read-only ELF ranges when a section name does
not fit the bounded name window, so a rustc path in that range is still
reported.
* fix(ci): repair integrated checks and Hopper test baseline
* fix(go): verify Mach-O sections against segments
---------
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
* feat(browser): attach passive tools to browsers without HTTP discovery
Accept a literal loopback browser WebSocket,
ws://127.0.0.1:PORT/devtools/browser/ID, as the cdp_endpoint of the six
passive browser tools. Discovery then reads Browser.getVersion and
Target.getTargets over that socket, and the target session adopts the
same socket, so a browser that asks for consent per connection prompts
once per call.
The socket identifier gates access, so Evidence records the endpoint as
ws://127.0.0.1:PORT/devtools/browser/[REDACTED], and runtime
reconciliation accepts that recorded form. HTTP endpoints and their
Evidence are unchanged. Electron, web runtime, scenario and Inspector
endpoints stay HTTP-only.
Refs #2288
* test(browser): match browser-socket captures against HTTP discovery
Check in the real Chrome lane that DevToolsActivePort names the same
browser socket as /json/version, and that inspecting the selected page
through that socket leaves DOM structure and scripts unchanged compared
with an inspection through HTTP discovery.
Refs #2288
* fix(browser): bound browser-socket handshake and report discovery timeouts
Run the browser-socket WebSocket handshake and both discovery commands
under one discovery deadline, so a port that accepts the connection but
never completes the upgrade times out instead of waiting forever.
Report a reached deadline as a timeout without carrying the internal
abort as its cause, so CLI and MCP project provider_timeout rather than
cancelled. Caller cancellation is still reported as cancelled.
Refs #2288
* 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>
ECMA-426 DecodeSourceMapSources reads a content slot only while its index
is within sourcesContent, so a shorter array leaves trailing sources
without content and a longer array adds no sources. Local application
analysis and browser collection rejected any length mismatch and dropped
every original from the map.
The content helper now checks only entry types. Browser collection drops
its separate check because the leaf schema already validates every
supplied entry, and the raw records are still budgeted before parsing.
Fixes#2821
* fix(setup): treat empty DSH_HOME as unset (#2666)
The released `@deepseek-ai/dsh-home-paths` package explicitly treats an
empty or whitespace-only `DSH_HOME` as unset and selects the default
Harness home patch. `dshHomeDirectory` previously used nullish coalescing
(`env.DSH_HOME ?? join(home, ".dsh")`), so an empty override flowed
straight through `join(..., "cordis.patch.yml")` and produced a
cwd-relative `cordis.patch.yml` outside the client-selected home.
Treat empty and whitespace-only overrides as unset, matching the sibling
OpenCode override resolver and the released DSH resolver. The patch now
lands at `$DSH_HOME/cordis.patch.yml` for explicit overrides, the default
`~/.dsh/cordis.patch.yml` for empty/unset, and trimmed whitespace for
padded overrides.
Adds `src/application/SupportedClients.test.ts` covering the empty,
whitespace-only, unset, padded, and explicit cases via the public
`supportedClients(...)` entrypoint. Fixes#2666.
* test(setup): remove superseded DSH path unit coverage
---------
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* feat(native): search analyzed memory for masked byte patterns
The diff adds search_bytes to the CLI, the shared MCP contract, Ghidra
inventory, and the headless bridge, and advertises the same operation on
Hopper as unavailable until that provider is verified. Patterns are
hexadecimal byte pairs with optional ?? wildcards and an optional
equal-length bit mask; the TypeScript boundary and the bridge both
require a nonempty pattern, equal lengths, and at least one constrained
bit. Ghidra walks initialized blocks in address order within inclusive
bounds, keeps overlapping matches inside a single block, and returns
each hit with its segment, unique source file offset, and containing
procedure, continuing through a cursor bound to the target, profile,
pattern, mask, and bounds. Each page reports the inclusive ranges
examined and the skipped uninitialized blocks; cancellation returns a
typed error and discards the active Ghidra database.
address_to_file_offset now uses the same unique-offset helper, which
rejects a mapping that is missing, ambiguous, or larger than a safe
integer.
* fix(native): limit unbounded byte search to loaded memory
Without start or end, search_bytes walked every Ghidra block, including
non-loaded file parts such as .symtab and overlay blocks, which the docs
call out of scope. Unbounded searches now skip those blocks and list them
in searched.skipped_not_loaded; explicit bounds in their address space
still search them. Document that a match must end at or before end.
* fix(native): preserve implicit address spaces in range consumers
* fix(native): reject present malformed byte search state
---------
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* fix(targets): compare the Info.plist bplist prefix without ASCII folding
The six-byte prefix check used an encoding that maps high-bit bytes onto bplist, so a non-binary property list could be sent to the binary decoder.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(targets): satisfy the strict index check in the plist prefix test
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* feat(setup): add Kimi Code client support
Registers rea in ~/.kimi-code/mcp.json (or $KIMI_CODE_HOME/mcp.json), preserving unrelated settings with a .rea.backup; registration is command-based stdio with no type field, startupTimeoutMs 30000 and toolTimeoutMs 120000 from MCP_STARTUP_POLICY.
Strict JSON parsing: empty or whitespace-only files initialize; malformed JSON is rejected untouched with no backup; explicit transport other than stdio reports invalid.
Bundled skill uses the shared ~/.agents/skills destination that Kimi Code discovers, installed and verified through the shared-skill flow.
Validated by 19 Kimi-specific tests, 260 adjacent-client regressions passing, check:fast and docs:check, and real-client verification on Kimi Code 0.40.1 (173 tools discovered, real mcp__rea__analyze_javascript_application call succeeded).
* fix(setup): preserve Kimi tool filters and strict JSON coverage
---------
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* fix(host): separate REA host support from Hopper installer targets
LinuxDistribution.supported carried two meanings at once: that the host runs
REA, and that the automated Hopper installer is tested on it. The doctor read
the first meaning from the second, so Debian-derived hosts such as Kali
reported unsupported_host while their providers worked normally.
Rename the field to hopperSetupSupported, which only the Hopper installer and
setup planning consume, and derive host support from the package family
through supportsReaHost(). Any distribution with a recognized apt, dnf, or
pacman family is now a REA host. The tested Hopper installer list is
unchanged, so Debian and Kali keep falling back to configuring an existing
provider instead of downloading an untested package.
Verified on Kali 2026.3 (Debian testing, x86_64): rea doctor reports a healthy
environment with Ghidra 12.1.4, and analyze_function decompiles an x86_64 ELF
through the MCP server. npm run check, npm run docs:check, and the application
and Ghidra suites pass. No Hopper or IDA host workflow was exercised.
* fix(setup): stop skill checks after first drift
---------
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* fix(cli): label each uninstall skill root by its client
rea uninstall reported every managed skill destination under the
shared "skill" label (with only Claude Code special-cased), so a
retained or failed directory could not be told apart from the others.
Use the destination's client identifier so the aggregated detail names
each root: "shared: retained (...)", "claude_code: removed (...)",
"antigravity: retained (...)". Retained and failed entries now point to
the specific directory that needs attention.
Fixes#2111
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test(cli): align skill summary assertions with client and path labels
---------
Co-authored-by: wjl8636 <wjl8636@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* fix(setup): resolve the configuration MSIX Claude Desktop reads
On Windows, setup, doctor and uninstall always used
%APPDATA%\Claude\claude_desktop_config.json. The MSIX build of Claude
Desktop (package family Claude_pzs8sxrjxfjjc) virtualizes AppData writes
and reads its package-private copy under
%LOCALAPPDATA%\Packages\<family>\LocalCache\Roaming\Claude once it exists.
Setup from an ordinary process therefore wrote a file the app never reads,
and doctor reported that file healthy.
Resolve the Claude Desktop location once, in supportedClients(): the
private copy when it exists, else the AppData file the package still
reads, else a new private copy. An unrecognized Claude_* publisher or
unreadable package storage is reported instead of falling back to AppData.
Compare one of the package's private files with its AppData path through
realpath.native to learn whether the running package started this
process. From that redirected view, or when no file can be compared,
setup and uninstall refuse to change Claude Desktop's configuration,
because the running app rewrites it from memory. From a redirected view
they also refuse writes under %APPDATA% and %LOCALAPPDATA% for other
clients and skills, which would land in the package's private storage.
Setup refuses to register a launcher stored in any MSIX package's
private storage, discloses which file the package reads, and tells the
user to quit Claude Desktop fully on every platform. Configuration fails
with target_changed if the package switched to its private copy after
the plan was shown. Uninstall removes REA from both files.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(setup): record the verified MSIX Claude Desktop registration
On the Windows 11 host with the MSIX build 2.31226.1.0, setup from an
ordinary terminal with the app quit wrote the package-private copy. After
the app restarted, the entry persisted, doctor reported it aligned, and
Claude Desktop's MCP log showed REA starting and answering tools/list.
Uninstall against the real app remains unverified.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* style(setup): format MSIX review corrections
* fix(setup): carry the admitted legacy path through uninstall removal
clientRegistrationRemoval returned a removeLegacy boolean, and removeClient
recomputed the legacy path separately, so TypeScript could not prove the
path existed when removeLegacy was true and `tsc --noEmit` failed in
Uninstall.ts. The decision now returns the admitted legacy path itself;
preflight and removal consume that one value.
The alias regression matched new-destination children with a "/"
separator while building paths with path.join, so it failed on Windows.
It now uses path.sep.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(setup): split MSIX Claude Desktop lifecycle cases under the function length limit
The uninstall cases pushed the registration lifecycle describe past the 150-line lint limit. Group them separately, with the AppData registration case kept among the registration cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* fix(apktool): resolve Windows PATH launchers before invocation
Resolve the default launcher through the selected PATH/PATHEXT before choosing native process creation or the existing conservative cmd.exe wrapper. Reuse the resulting selection and one canonical environment for the version probe and decode.
Follow-up to the release #1693 review of #1777. Source inspected and formatted; tests, builds, check reruns and real Windows Apktool execution were skipped at maintainer request.
* fix(apktool): bound lookup and retain only selected environment
Source inspection and targeted formatting only. Tests, builds, lint, typechecks and provider workloads were not run at the user's explicit request.
* fix(apktool): use supported timeout diagnostics
Retain lookup phase through AnalysisErrorOptions diagnostics while preserving the operation and timeout identity. Source inspection and targeted formatting only; tests, checks, builds and provider workloads were skipped at the user request.
---------
Co-authored-by: morluto <morluto@users.noreply.github.com>
* perf(evidence): reuse sealed bundle reads in compare and export
`rea compare`, the compare_bundles MCP tool and `rea evidence-export`
read bundles through the mutable reader, so each consumer
re-authenticated every record again: compareBundles parsed both bundles
a second time and bundleDigest's serializeEvidenceBundle a third time;
export's writer parsed the source once more before serializing.
These consumers only read the bundle, so read it through the existing
sealed reader (readImmutableEvidenceBundle). Later parses hit the
immutable bundle cache. Ordinary mutable reads, kept deliberately by
#1721, are unchanged. Output is byte-identical.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(process): report no remaining time after a provider deadline fires
Node timers can fire while performance.now() is still a fraction of a
millisecond short of the monotonic deadline. ProviderStartupDeadline then
reported interruption "timeout" and an aborted signal while remainingMs()
returned ceil(0.x) = 1, so polling loops guarded by remainingMs() > 0
(Hopper and Ghidra startup) could run past an elapsed deadline, and the
real-timer test "aborts a bounded wait when its real monotonic deadline
expires" failed intermittently in CI (expected 1 to be 0).
Once the deadline's own timer has classified a timeout, report zero
remaining time. A deterministic regression test fires the timer with the
monotonic clock 0.4 ms short of the deadline.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* fix(native): refuse inspect_signature on non-Mach-O targets
This provider's signature inspection covers Mach-O code signatures only.
On a xar pkg, codesign's "code object is not signed" verdict cannot see
the archive-level signature layer, so a signed or invalidly-signed package
was reported as signed:false with "Artifact is not signed." Match the
existing inspect_macho/list_architectures gate and report
capability_unavailable instead of an unsigned claim for a layer that was
never evaluated.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test(native): scope the signature-gate comment to this provider
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(native): align signature capability discovery with Mach-O support
Bind inspect_signature availability to Mach-O targets in capability discovery and align the public tool description.
Source inspection and git diff --check; tests/builds/typechecks/CI reruns skipped at explicit user request.
---------
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* feat(ghidra): admit raw NMOS 6502 analysis
* test(ghidra): require verified POSIX verifier cleanup
* test(ghidra): verify 6502 low-memory raw imports
* docs(skill): document raw NMOS 6502 support
* fix(ghidra): preserve requested Windows raw source paths
* docs(ghidra): include raw 6502 in Windows installation scope
* test(ghidra): verify Windows raw junction rejection through CLI and MCP
* fix(validation): make fixtures portable and preserve explicit Codex home
* fix(ghidra): attest raw mapping state and address space
* fix(ghidra): align diagnostics and regression groups
* fix(ghidra): bind raw attestation to language address space
* chore(ghidra): avoid verifier insertion conflict
* docs(ghidra): align linked raw admission guides
* fix(ghidra): retain 6502 verifier workspace on failure
* test(ghidra): isolate Windows authority doctor fixture
* fix(binary): re-admit Windows raw paths on session reopen
* test(binary): require fresh provider execution after path change
* Constrain 6502 to raw lifecycle and snapshot targets
* Bypass saved reads for unadmitted Windows paths
* Guard direct CLI snapshot replay on Windows paths
* fix(snapshot): gate Windows Ghidra replay on native admission
* fix(snapshot): constrain nested 6502 subjects to raw images
* test: make dyld slice fixtures portable
* test(mcp): expect trace_feature to report references the provider truncated
A provider that reports a capped xrefs read makes the trace truncated with a residual unknown for that target. An explicit complete report and a provider that reports nothing leave the trace as before.
* fix(mcp): report references a provider truncated in trace_feature
Executions gain an optional flag for a capped xrefs read, set by the IDA adapter from the upstream cap. trace_feature marks the trace truncated with a residual unknown for that target only when the provider reports a truncation; a provider that reports nothing keeps its previous result. The trace_feature workflow profile is revised so earlier results are not replayed.
* refactor(ida): report reference truncation whenever the runner observed an xrefs cap
* test(mcp): cover session forwarding, per-target state, native reports and failures of the trace coverage
* test(mcp): format the session forwarding test
* test(ida): expect headless IDA to resolve containing procedures from lookups and segment facts
Cover positive and negative containment, segment boundaries including addresses above 2^53, failures of the lookup and of the segment survey, cancellation, input validation and the admitted program as the only document.
* test(ida): expect feature tracing and address context to work on headless IDA
Run trace_feature, including a capped reference read, and inspect_address_context with and without an explicit document through the IDA session client.
* test(mcp): expect trace_feature availability to follow the search operations it calls
* fix(mcp): derive trace_feature availability from the search operations it calls
* feat(ida): resolve containing procedures and report the admitted program as the document
The modern headless profile resolves an address through the function lookup and, when no function contains it, tells a mapped address from an unmapped one using the database-scoped minimal survey. A survey that is missing, truncated or inconsistent fails the read. list_documents reports the single admitted program. The attached profiles do not declare either operation.
* docs(ida): describe containing procedures, the admitted document and truncated feature traces
* test(ida): verify containing procedures, the admitted document and feature tracing on real IDA
* docs(testing): list the headless IDA workflows the real lane verifies
* test(ida): make each survey failure case isolate a single defect
* test(ida): pin large addresses, segment order, document identity, attached refusals and each trace_feature prerequisite
* test(mcp): expect a repeated reference source to be resolved once in trace_feature
* fix(mcp): resolve the containing procedure of a repeated reference source once
* test(ida): trace the fixture procedure and derive probe addresses from its facts in the real lane
* test(process): format processCaptureLifecycle.test.ts after the merge
* test(ida): declare the alignment each synthetic universal slice offset satisfies
* refactor(ida): move the real lane's feature trace assertions into a helper
* test(ida): expect the real lane's feature trace check to accept references to every matched address
* fix(ida): check each trace reference against its own matched address in the real lane
* test(ida): pin that the new operations reject a document other than the admitted program
* refactor(ida): move the real lane's mapped non-function probe into a helper
* test(ida): expect the real lane's mapped data probe to skip strings inside functions
* fix(ida): try the target's strings in order for the mapped non-function probe
* test(ida): declare the real lane helper types for the verifier tests
* test(ida): expect the real lane to reject a listed string that resolves as unmapped
* fix(ida): fail the real lane when a listed string resolves as unmapped
Setup and uninstall re-printed every number in an existing Hermes
config.yaml from a JavaScript number. Hermes reads the file as YAML 1.1
with exact integers, so a Discord channel ID lost its low digits, an
octal mode such as 0600 became 600, and 0.0000001 became 1e-7, which
YAML 1.1 does not define as a float. Two IDs that round to the same
double were also rejected as duplicate keys, so setup could not
register at all.
Hermes YAML parsing and editing move to HermesConfigurationYaml. A parsed
number is written with its source spelling while that spelling still
reads as the node's value, the rule yaml's own boolean tag follows, and
two keys are duplicates only when both their value and their spelling
match. Parsed values stay JavaScript numbers.
Keep directory requests from becoming unresolved or pointing at sibling files
when constructing reference-source dependency graphs. Canonicalize index
candidates and preserve directory intent while retaining ordinary lookup rules.
Constraint: Preserve current TypeScript candidate objects and exact-before-Unicode lookup
Rejected: Reorder all file probes before index probes | Changes ordinary CommonJS candidate priority
Confidence: high
Scope-risk: narrow
Tested: Public CLI regression fails on base; focused reference and resolver suites pass; npm run check
Not-tested: Full suite on refreshed base; earlier full run had 12 baseline-reproduced failures
Declare the synthetic 4 KiB Mach-O slice alignment accurately while preserving the IDA thinning scenario. Share web cleanup aggregation and process-trace fixture facts instead of duplicating them across consumers and tests; keep the 3% duplication threshold unchanged.
Validation: npm run check:ci, test discovery, and 42 focused IDA, process-trace, web workflow and cleanup boundary tests. Duplication falls from 3.01% to 2.99%.
Keep failed stable-read handles and WABT runtime roots under retryable resource scopes. Preserve cancellation causes and primary errors, close the same service instances bound to MCP tools, and consolidate CLI operation/cleanup projection.
Validation: fast typecheck and lint, cached runtime build, docs checks, SDK schema validation, focused service and real-file cleanup tests, CLI cleanup regressions, and MCP lifecycle/shutdown workflows. Provider process fixtures simulate engine output; real WABT and Linux EVM execution are not established by this pass.
Compare import and require outcomes for static TypeScript references when compiler options are unknown. Preserve branch facts through worker IR and both graph projections; retain declaration fallbacks as candidates without changing explicitly selected paths.
Validation: 210 focused resolver and semantic tests; 21 production-boundary and source-extension tests. A bounded 2,000-reference probe adds about 16–17 ms wall time for dual resolution; full task token costs and real compiled application behavior remain unmeasured.
Once a Frida session reached its 16 MiB capture budget, every new message
evicted the oldest one with Array#shift, re-serialized it to recover its
byte charge, and searched and spliced its per-script array. Each of
those is linear in the retained messages, so with about 188k small
messages retained the cost per message rose from 0.14 µs to 32 µs and
capped the main thread at roughly 31k messages per second, which a
hooked hot function can exceed.
Keep both queues as head-offset FIFOs that compact once half their slots
are evicted, and record each message's charge when it is admitted.
Arrival order already makes the globally oldest message the oldest one
of its script, so per-script eviction becomes a head check. Eviction is
now amortized O(1) at about 0.14 µs per message; retained messages,
their order and the truncation flag are unchanged.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>