mirror of
https://github.com/morluto/rea.git
synced 2026-11-15 11:13:21 +00:00
cb4e5cfbff25c2dda8683ef8598c17cec8a73473
363
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
cb4e5cfbff |
feat(analysis): make resource budgets recoverable across CLI and MCP (#9706)
* refactor(analysis): centralize resource budgets and recovery facts * feat(analysis): expose ASAR and Ghidra runtime admission controls * feat(artifacts): expose reader admission and preserve limited recognition * feat(javascript): expose recoverable semantic precision budgets * feat(web): add recoverable source-map budgets and compact retained views * feat(web): make historical capture decoding budgets recoverable * fix(desktop): enforce selected view policies across capture and export * feat(runtime): make Frida and LLDB retention budgets selectable * feat(native): expose diagnostic budgets and preserve exhaustion causes * feat(managed): expose recoverable snapshot and representation budgets * feat(metadata): make Go and Rust inspection budgets recoverable * feat(wasm): expose representation and producer admissions * feat(evm): expose per-call worker resource budgets * feat(android): make resource and string-pool omissions recoverable * feat(producers): expose command and recorded-capture budgets * docs(analysis): record recovery contracts and integrated validation * fix(docs): link calibration oracle from published verification pages * fix(docs): restore desktop task anchors and receipt links * test(analysis): align fixtures with selectable budget contracts * fix(analysis): remove source-location projector dependency cycle * test(analysis): refresh budget recovery and verifier regressions * test(analysis): preserve format and publication recovery expectations * test(windows): align conformance with owned runtime admission * fix(desktop): preserve selected alias kinds in exported state * test(analysis): align provider fixtures with recoverable budgets * test(desktop): validate emitted alias metadata structurally * fix(ghidra): classify bounded Windows endpoint refusals * test(cli): assert selectable artifact admission recovery * fix(cli): preserve capture provenance in environment builds |
||
|
|
95ebd38d3f |
fix(ci): restore main workflows and captured-state replay (#9763)
* fix(cli): record the caller HAR path in environment-build evidence environment-build inspected a HAR without the caller path that inspect-web-network-capture records, so the published evidence.json omitted caller_input_path and failed the byte-for-byte portable check. Also update three stale portable expectations that already fail on main: the no-reader verifier digest matches the #9185 selector parent, uncapped IDA callee pages report complete discovery, and a CLI refusal of a malformed artifact inspection includes the undelivered source closure. * fix: restore portable docs, alias, offset, and Windows cleanup checks The witness page linked task anchors that were never written, so any docs-touching PR failed the route check. A selected state directory was restored as a dangling symlink by a duplicated helper. An empty safetensors file reports the extent as outside the file before offset conversion. Windows cleanup refusal uses the runtime's in-progress message. * fix(cli): keep the caller's HAR spelling in environment-build evidence inspect-web-network-capture records the path the caller typed. The one-shot build had already absolutized that path, so a relative capture disagreed with the three-step bundle. The byte-for-byte check now runs from the capture directory and requires caller_input_path grafana.har. * fix(desktop): create alias targets only for directory selections A missing settings file was created as a directory because the helper treated any absent path as a directory. The capture's selected path kind now travels with the alias, and only a directory alias creates its target. An absent file alias stays a file the app can create. * fix(desktop): keep legacy alias kind unknown Captures written before selected_paths.kind leave the alias unknown. Defaulting those to a directory makes an omitted settings file a directory, so a later write through the alias fails with EISDIR. * fix(desktop): keep alias kind a file, directory, or unknown The export plan was widening a missing selected path kind to string. Record file or directory only when the capture says so, and unknown otherwise. * fix(desktop): narrow a missing alias kind to unknown The selected path kind was widened to string, so the export plan could not keep the file, directory, or unknown distinction. * test(desktop): expect alias kind in the rendered app module The export now records whether a selected alias is a directory. The rendered STATE_ALIASES tuples include that kind. * fix(ghidra): reject an oversized Windows TCP endpoint as invalid The POSIX read maps a record past the compact endpoint bound to "Ghidra TCP endpoint is invalid". The Windows lease reported that same bound as a generic observation failure, so an expanded endpoint failed the Windows lane with a different message. * fix(desktop): create a legacy alias when a child proves it is a directory A capture written before selected path kind can still nest one alias inside another. That parent is a directory. A legacy leaf stays unknown so a missing settings file is not created as a directory. * fix(desktop): restore selected aliases when the app owns no files An empty state directory does not become an owned path, so the class was ownless and never called _ensure_state_aliases. The ownless class now restores aliases whenever the export recorded some. * fix(desktop): create the parent of a missing file alias A file alias must stay a file. When its parent directory was not seeded, the symlink was dangling and a write through it failed with ENOENT. * ci: retrigger checks after an unrelated Windows timeout The Windows lane timed out in webModuleCli, which this diff does not touch, and the rerun API is unavailable. * test(evidence): preserve complete CLI refusal diagnostics --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com> |
||
|
|
1f9bf8af0e |
fix(providers): mark callee coverage partial at computed call sites (#8340)
* fix(call-path): keep computed-call targets out of complete callee coverage Ghidra reported complete callee coverage when a computed call had one ReferenceManager target, so trace_call_path, build_call_path and the function comparisons turned the static candidate into a definite negative. The bridge now keeps those targets as observed callees and marks callee coverage partial, naming the computed call sites. IDA callee reads cannot classify their call sites, so their callee coverage is partial too. The Ghidra call-coverage profile revision refuses older snapshots. A source-owned x86-64 bridge probe in the ghidra-bridge-sources job checks the slot, register and direct-call controls against real Ghidra. Fixes #8277 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ci): match the observed call coverage probe marker --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> |
||
|
|
645735fc0f |
feat(windows): inspect Shell Link (.lnk) shortcut files (#7859)
* feat(windows): inspect Shell Link (.lnk) shortcut files Add inspect_windows_shortcut / inspect-windows-shortcut to read one local Shell Link without resolving or executing the target. The report keeps header flags and FILETIMEs, IDList items, LinkInfo volume and network names, StringData, ExtraData including Tracker droid facts labelled derived, and derived observations such as argument length and a minimized ShowCommand. * fix(windows): tighten Shell Link string reads and coverage - Decode counted StringData over its full CountCharacters payload. - Locate LinkInfo string terminators before charging max_string_bytes and before decoding; an unterminated string is a coverage issue. - Mark an IDList without a TerminalID and an out-of-range LinkInfoHeaderSize as partial coverage. - Report arguments_present and argument_length as null when HasArguments is set but the field could not be read. - Derive target_extension from the joined base path and suffix. - Keep ISO dates for FILETIME and UUIDv1 timestamps before 1970. - Retain the completed file snapshot on parse failures. - Reject an empty CLI path before normalization. - Select the shortcut contract from its family in focused tests. - Fixture StringData no longer writes a NUL into the counted payload. * style: format docs index and Shell Link boundary type Apply oxfmt to the two files format:check reports so Static checks passes. * fix(windows): reject network share paths for Shell Link reads inspect_windows_shortcut is advertised as offline, but the Windows path schema admits UNC paths, and lstat on one can contact an SMB server and offer the caller's credentials. Reject UNC, extended UNC, and other host-prefixed device paths in the provider before any filesystem call. Extended drive paths such as \\?\C:\x stay allowed. A mapped network drive cannot be told from a local drive by its path, and the docs say so. * fix(windows): decode Unicode Shell Link file-entry names File-entry items with bit 0x04 of the type byte, such as 0x36, store a UTF-16LE name, but the parser always read it as Latin-1. The read stopped at the first zero byte, so report.exe became r and an IDList-only shortcut reported the wrong target_extension. Read those names as UTF-16LE. * fix(windows): read volume labels by exact Shell Link discriminator VolumeLabelOffset 0x14 selects VolumeLabelOffsetUnicode and is not itself a label offset, and that Unicode field exists for no other value. The parser treated any offset of 0x14 or more as having both, so a Unicode-only label such as "OS" also produced a false ANSI label "O", and an ANSI label stored past 0x14 had its own bytes read as a Unicode offset. Branch on the exact value in parseVolume, the one place that interprets it, and report a VolumeID too short to hold the selected field. The fixture wrote both encodings for a Unicode volume, which hid the false label, so it now writes one. * fix(windows): limit network share rejection to Windows hosts POSIX hosts read repeated leading slashes as one local root, so an accepted selection such as ///tmp/shortcut.lnk is a local file there. Apply the host-prefixed path check only on Windows, and take the platform through the provider constructor so the Windows path forms stay covered on every test host. * fix(windows): compare shortcut icons only against full paths A stored IDList filename or relative path cannot show that an icon at a full path is elsewhere, so the comparison reported a false difference. Report null unless the icon and a recorded target are both full paths, and assert the missing TerminalID issue by code and offset instead of its message. * fix(windows): keep unread ExtraData blocks unknown A walk that stopped before or inside ExtraData still reported the blocks that HasExpString and HasExpIcon expect as absent, though they were never checked for. Report a block as absent only after the TerminalBlock shows the section was read in full. Without one the block stays unknown and coverage stays partial. * fix(native): ignore LNK network provider type unless ValidNetType is set CommonNetworkRelativeLink NetworkProviderType is only meaningful when the ValidNetType flag (0x2) is set. Return null otherwise. * fix(native): accept any ExtraData TerminalSize below 4 as the terminal MS-SHLLINK requires TerminalSize to be less than 4, not exactly 0. Treat 1, 2 and 3 as the terminal block instead of a malformed block. * fix(native): derive shortcut target facts from the stored environment target Include the EnvironmentVariableDataBlock literal target among the target candidates for target_extension and the icon comparison. Variables are not expanded and the target is not opened. * fix(windows-shortcut): keep unexpanded variable paths unresolved in icon comparison A stored environment target such as C:\Users\%USERNAME%\app.exe could be compared as different from C:\Users\Alice\app.exe. Variable-bearing paths are never expanded, so the icon comparison now returns null unless a fixed target matches the icon exactly. * test: drop redundant ok assertion before typed error guard The testing guide asks for the typed error to be thrown before asserting a successful Result value, and says a preceding .ok assertion adds no coverage. * fix(windows): point out-of-range LinkInfo offsets at their field A LinkInfo, VolumeID or CommonNetworkRelativeLink offset that points past its structure was reported at base + offset. With an offset such as 0xffffffff that position exceeds uint32, so the report failed its schema and the service discarded the whole partial result. Report such issues at the offending offset field instead, which keeps every issue offset and coverage.failing_offset inside the file. Cover each LinkInfo offset field in the parser tests and the LocalBasePathOffset case through the stable filesystem service. * fix(windows): require RFC 4122 variant before deriving Tracker UUID facts A version nibble of 1 alone does not identify a version-1 UUID. Also require the clock_seq_hi_and_reserved top bits to be 10, so other GUID layouts keep their raw value and derive no MAC or timestamp. * fix(windows): ignore DeviceNameOffset fields unless ValidDevice is set MS-SHLLINK 2.3.2 says DeviceNameOffset and DeviceNameOffsetUnicode are ignored when the ValidDevice flag is clear. parseNetwork read both regardless, so garbage in those fields became device-name facts or malformed_structure issues. Read the flags once and only read the device name fields when ValidDevice is set. * fix(windows): keep unsupported Tracker headers as raw data Check TrackerDataBlock Length (0x58) and Version (0) before decoding. A block with any other header is retained as raw bytes with a malformed_structure issue, so it no longer yields MAC and timestamp facts under complete coverage. * fix(windows): compare shortcut icon paths by normalized location Collapse "." and ".." segments and repeated separators in the icon comparison as text only, never opening a path. ".." stops at the drive or UNC share root, and \\?\ and \\.\ paths stay verbatim. Join LocalBasePath with CommonPathSuffix as the target and use the bare base only when the suffix is empty, as the network share branch does. Read the selected shortcut with lstat and open only, so a rejected symlink's destination is never resolved. * fix(windows): keep the UNC share in the root after repeated separators normalizePath took the host and the next split part as the UNC root, so \\server\\share\..\app.exe kept an empty share and let .. remove the real share. Drop empty parts before picking the root so paths on different shares stay different. * fix(cli): parse windows shortcut limits as decimals The four inspect-windows-shortcut limit options now go through cliDecimalField like the other inspection commands, so values such as 0x10 are rejected and cliDecimalArguments.test.ts passes. * fix(native): reject linked parents of windows shortcuts A parent directory symlink or junction pointing at a UNC share was followed by the first lstat, since the network check reads only the path text and the symlink rejection covers only the final component. On Windows, lstat each ancestor from the drive root down and reject the path at the first link, before anything follows it. * docs(native): move Windows shortcut guide and add its feature spec Move the Shell Link guide to docs/guides/native/windows-shortcut.md and list it under Native binaries in the site navigation, keeping the /windows-shortcut public route. Update README, translated README, CLI page and authored skill links to the new physical path. Add docs/specs/native/windows-shortcut/ with spec.md, plan.md and tasks.md, as required by docs/development/documentation.md. * fix(native): admit the windows shortcut parent walk On Windows the ancestor link walk ran before the provider's resource admission, so close() could finish while the walk kept calling lstat. Run the walk inside the same admission as the read, and check the caller's signal before each ancestor lstat. * fix(native): walk the effective parents of windows shortcuts The ancestor link walk checked every prefix of the path as written, so C:\alias\..\real\a.lnk was refused when C:\alias is a directory link, although Windows removes alias\.. before opening the file. Walk the ancestors left after removing . and .. components, keeping the caller's spelling, never climbing above an absolute root, and leaving \\?\ paths as written since Windows does not normalize them. * test(native): assert the linked parent as a structured fact The parent link regression matched the phrase "junction, which" in the refusal message, so a wording edit would fail it. Report the linked ancestor as observed.linked_ancestor on the input issue and assert that fact instead of the explanatory text. * test(native): bound the shortcut close gate and release it in finally Race the parent walk lstat acknowledgement against inspection settling with awaitAcknowledgement, then release the gate and join the inspect and close work in finally so a failure reports its cause instead of waiting for the Vitest timeout. * fix(native): walk Windows shortcut parents lazily windowsAncestors built and kept every parent prefix before the first lstat, so a path with thousands of components allocated memory quadratic in its length. It now keeps only the normalized components and yields each parent from a running prefix as the walk reaches it. --------- Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> |
||
|
|
62a2814756 |
fix(windows): bound endpoint reads and retain failed file cleanup (#9620)
fix(windows): bound Ghidra endpoint reads |
||
|
|
7baed55130 |
fix(doctor): probe providers with the selected client's registration environment (#9108)
* fix(doctor): probe providers with the selected client's registration environment rea doctor read provider settings only from the terminal running it. A client registration that carries GHIDRA_INSTALL_DIR or REA_JADX_MCP_CONFIG under its own env block therefore looked unconfigured: doctor answered not_configured while the server that client starts inherited the settings and worked. This is the recovery command the docs point agents at, so the false negative sent them back to re-apply fixes that were already in place. When the caller names exactly one client, read that registration's effective environment and hand it to the provider checks. Terminal variables that providers resolve outside server config (PATH, SYSTEMROOT) stay inherited, and running doctor without --client still reports this terminal. A registration the loader cannot read keeps its own registration check as the answer instead of being re-reported as four missing providers. Fixes #9102 * fix(doctor): keep setup's terminal settings and a failed close on the host Greptile found two regressions in the selected-client environment read. Provider probes now start from the terminal and overlay the selected registration, instead of replacing the terminal with the registration alone. `rea setup --client` passes its own client selection through the same doctor call, so on a first run with GHIDRA_INSTALL_DIR exported and no registration yet, the replacements made setup report providerConfigured: false and offer Hopper over the selected BYO provider. The registration still wins for every value it records. The registration read now runs inside the caller's resource scope and, when the close of the configuration file fails, retains the returned owner there so host.close() retries it. Dropping that owner left an unretired handle with no way to report the unfinished cleanup. * fix(doctor): leave a registration's expression settings unknown Greptile found the previous fallback filling a name the selected client records as a Cordis expression with the terminal's value. `dsh` keeps such a value as `!!js ...`, which is not a literal; the parser reports the name in `unresolvedSettings`, and merging the terminal into it then made probes certify a setting the client owns and this process cannot read. Unresolved names are now removed after the overlay, and an unreadable, malformed, or unresolvable registration returns no environment at all, so the caller keeps the terminal instead of a partly-known one. Provider checks report those settings as unconfigured, which is the honest answer for a chain that resolves outside REA. dsh's missing registration still inherits the terminal, which is the case `rea setup` depends on. * fix(doctor): fold registration settings by platform identity `selectedProviderSettings` overlaid a selected client's registration on the terminal with an object spread. On Windows a registration can record `ghidra_install_dir` while the terminal exports `GHIDRA_INSTALL_DIR`; the spread kept both spellings, and since provider checks read the canonical uppercase names, doctor either certified the terminal's install or reported the setting as unconfigured. An expression the registration marks unresolved was skipped under one spelling while its terminal value survived under the other. Merge the two layers through `mergeEnvironmentOverrides` and fold the result with `snapshotEnvironment`, so the registration's value wins regardless of how it spells the name and the provider sees the names it reads. Fold the unresolved names the same way before deleting them, and export the helper so the two platform identities can be covered directly. * style(doctor): wrap the long import in the runtime test oxfmt wants the three imported names on their own lines; the previous commit left the single-line form, which fails `npm run format:check`. * test(codebuddy): construct the registration command like its sibling clients `npxRegistrationCommand` was removed in |
||
|
|
8c64eb511f |
fix(ghidra): stage NativeAOT report until recovery completes (#9611)
* fix(ghidra): stage nativeaot recovery report until complete * test(ghidra): exercise nativeaot rollback reporting |
||
|
|
44d232fccb |
fix(providers): retry live waiters after abandoned startup drains (#9467)
* fix(providers): retry live waiters after abandoned startup drains * test(providers): bound startup lifecycle acknowledgements |
||
|
|
4b4abcc2ee | refactor(core): reuse owned validation and Evidence reference rules (#9473) | ||
|
|
5044e20171 |
test: focus diagnostics and evidence checks on behavior (#9303)
* test: focus configuration diagnostics on their owners Preserve shape errors, selected paths, recovery guidance, and unchanged-file behavior across parser, setup, and uninstall boundaries. * test: focus artifact and evidence checks on behavior Retain format, identity, malformed-input, and cleanup coverage while removing fixed prose and closing the admitted test source. * refactor(debugger): use configured session admission limits * test: focus evidence and diagnostics on behavior * fix(test): restore verifier export and formatting * test(config): verify debugger limit ranges * test(rizin): keep fixture executable authoritative * test(rizin): isolate debugger fixture environment |
||
|
|
c5ed046d6e |
fix(ghidra)!: qualify memory effect coverage (#8651)
* fix(ghidra): qualify memory effect coverage * fix(native): retain value trace source limitations * fix(native): distinguish value trace policy commitments * fix(ghidra): bind value-flow scope to snapshot profile * test(ghidra): verify legacy value-flow snapshot recovery |
||
|
|
887b99888e |
fix(ghidra)!: distinguish skipped overlays in byte search (#8608)
* fix(ghidra)!: distinguish skipped overlays in byte search BREAKING CHANGE: Byte search results require skipped_overlays; loaded overlays no longer appear in skipped_not_loaded. The Ghidra profile changes so prior snapshots are not replayed. * fix(cli): explain overlay byte search scope * test(ghidra): exercise overlay search cursor handoff * test(ghidra): avoid freezing byte search help wording * test(ghidra): classify search start as an address bound * docs(ghidra): match the raw lane's overlay coverage The raw Ghidra lane checks a manually created overlay block through MCP. Say that, and do not claim an overlapping-load ELF, CLI search, or snapshot cursor handoff. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
1a0e2c77f2 |
fix(ghidra): qualify selected project call coverage (#8391)
* fix(ghidra): qualify selected project call coverage * test(ghidra): retain verifier MCP cleanup ownership * test(ghidra): document trusted verifier compiler selection * test(ghidra): document owned verifier exit marker * test(ghidra): remove ineffective scan directives * fix(ghidra): supervise project coverage verification * fix(ghidra): supervise verifier compiler process |
||
|
|
015a02d57b |
feat(ghidra)!: identify containing code and data (#8777)
* feat(ghidra)!: identify containing listed instructions * fix(ghidra): validate instruction containment status * fix(ghidra): validate containment coordinates * feat(ghidra): identify containing defined data * test(ghidra): correct snapshot and containment controls * docs(native): distinguish object and dynamic type sizes * docs(cli): retain incoming reference guidance * fix(mcp): clarify data object address guidance * test(ghidra): preserve defined data in reference fixtures |
||
|
|
688dca3e90 |
fix(mcp): report native value flow support in session status (#8786)
* fix(native)!: preserve value-flow absence semantics * fix(mcp): report native value flow support in session status * test(mcp): share schema validation and assert status facts * chore: preserve unrelated main imports |
||
|
|
9109e6f6a7 |
fix(ghidra): guide ambiguous selector recovery (#8768)
* fix(ghidra): guide ambiguous procedure selection * test(ghidra): distinguish malformed selectors * fix(ghidra): distinguish ambiguous file mappings * fix(ghidra): name mapping inspection workflows * docs(mcp): expose strict Ghidra address selection * docs(cli): explain Ghidra qualified address selection * test(ghidra): cover published ambiguous selector codes MCP and projection tests use procedure_ambiguous and file_offset_ambiguous, and match the recovery main already publishes for those codes. * fix(ghidra): name the space-qualified address that avoids offset fallback file_offset_ambiguous now tells the caller to use a form such as ram:0x1000. A bare 0x selector repeats the file-offset lookup. The MCP test requires that route and inspect_native_load_image. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
f912a68417 |
fix(ghidra): respect Java Unix socket path limits (#8382)
Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
c06b53644b |
fix(ghidra)!: preserve facts in inventory searches (#8376)
* fix(ghidra)!: preserve facts in inventory searches BREAKING CHANGE: Ghidra snapshots made before the search projection profile revision no longer match. Run fresh analysis and save a new snapshot. * test(ghidra): update raw profile digest goldens |
||
|
|
352a846127 |
test: reduce brittle assertions and test-only runtime paths (#9289)
* test: focus assertions on behavioral evidence Prune redundant and wording-coupled checks while retaining diagnostic, parser, recovery, and cleanup coverage. * refactor: remove test-only wrappers and duplicate checks Exercise production operations through test fixtures, remove unused adapters, and keep managed-member uncertainty guidance under its existing owner. * test: focus process validation on diagnostic facts * refactor: remove test-only runtime helpers Move semantic evidence fixture setup out of runtime and remove unused Windows settle recovery helpers while checking configured defaults independently. * test: focus artifact diagnostics on format facts * test: verify retained cleanup guidance delivery |
||
|
|
a67525cdf1 |
docs: organize canonical documentation layout and verify new pages (#2791)
* docs: organize canonical documentation layout (URGENTE) Group all existing authored guides by domain and ownership, expose complete navigation, and preserve their public routes. Update physical path consumers and release configuration while retaining historical records. Document domain-based specs and ADR slugs without global numbering. Co-Authored-By: Codex <noreply@openai.com> * fix(docs): honor home layout in all-page route verification * style: format reviewed source changes * fix(docs): preserve routes and navigation cache inputs * 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> * fix(docs): update links after guide relocation * docs: correct verified documentation route counts * fix(docs): update browser capture guide link after move (#2820) Refresh gettext protected-link comments alongside the authored href. Co-authored-by: Codex <noreply@openai.com> * fix(docs): include http3 lab in stable routes * fix(docs): preserve historical release evidence and links * fix(ghidra): restore Windows verifier identity import * docs(wakaru): preserve pinned upstream policy link * docs(index): retain recently added guide links * docs(mcp): preserve parent retention clarification * fix(cli): preserve standalone import guidance * fix(test): preserve translated guide link drift coverage --------- Co-authored-by: Matheus Breguêz <matbrgz@gmail.com> Co-authored-by: Codex <noreply@openai.com> Co-authored-by: morluto <17176810+morluto@users.noreply.github.com> Co-authored-by: 吴佳浩Alben <35291372+XiaoBinGan@users.noreply.github.com> Co-authored-by: 吴佳浩 <wujiahao@supremind.com> |
||
|
|
cbd4bd4a66 |
fix(ghidra): explain literal search candidate evidence (#8816)
* fix(ghidra): explain literal search candidate evidence
* style(test): format CLI help default annotations (#9280)
(cherry picked from commit
|
||
|
|
ad597388a4 | test: simplify Ghidra coverage propagation fixture | ||
|
|
1596d6a275 | test: reduce wording coupling and prune redundant coverage | ||
|
|
8eff651270 |
fix(ghidra): make checkpoint workflows discoverable (#9246)
Expose the existing opt-in Ghidra checkpoint lifecycle in tool descriptions and summary capabilities. Distinguish confirmed initial analysis from restored Programs, preserving the checkpoint path and digest through shared CLI/MCP results. Remove prose-driven checks and their scaffolding; retain canonical effects and lifecycle/source-fact coverage. Validated with 445 focused tests, 13 real Ghidra CLI/MCP scenarios and three isolated local Codex CLI tasks covering disabled setup, saving edits and fresh-agent restoration. |
||
|
|
c07ab4b994 |
feat(ghidra): checkpoint owned Programs across sessions
Add opt-in REA_GHIDRA_CHECKPOINT_DIR for owned Ghidra Program persistence through the shared CLI/MCP provider. Save completed initial analysis and metadata changes on normal close; verify and restore the last successful packed Program without auto-analysis. Preserve generation identity, exclusive ownership, typed cancellation and cleanup retry. Refresh checkpoint-dependent profiles after retirement, including failed-switch restoration, while retaining caller selection provenance. Keep source executables and caller projects unchanged. Validated with 720 focused tests (3 platform skips), 13 real Ghidra CLI/MCP scenarios, static/docs checks and CI. Review findings addressed. No version bump or release publication. Refs #8165. |
||
|
|
1cc979c104 |
feat(ghidra): admit DOS MZ targets on Windows P0 (#7144)
* feat(ghidra): admit DOS MZ targets on Windows P0 Windows Ghidra P0 refused dos-mz although the MzLoader import, 16-bit real-mode language attestation and load-image evidence are host-neutral. Admit dos-mz in inspectWindowsP0TargetSupport and run verify:ghidra:dos on Windows: inherit the system environment there, expect annotation and naming edits to be refused (P0 has no mutation authority), and skip verifier lineage like the 6502 lane. Explicit COM stays refused on Windows; its verifier is built around annotation edits. Refs #7121 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(ghidra): check naming refusal in the read-only DOS lane With mutable: false the address-boundary helper skipped every naming request, so the Windows report overstated its coverage. Assert that set_address_name and set_addresses_names are refused with capability_unavailable and leave the entry name unchanged, and declare the optional mutable argument in the .d.mts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(ghidra): unwrap failed profile Result before asserting Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * fix(ghidra): expect an unchanged DOS entry on Windows P0 verification Windows P0 refuses edits, so verifyGhidraAddressBoundaries skips the rename-and-restore and the entry keeps its imported symbol source. The post-check still expected user_defined, which only follows a rename. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
08a923f722 |
fix(ghidra): report restricted-host temp write denial on Windows (#8889)
* fix(ghidra): report restricted-host temp write denial on Windows Add a Windows doctor check that creates and deletes a file under os.tmpdir(), and classify a denied java_home.save in Ghidra startup output with its path, Win32 error 5, and TMP/TEMP remediation. The probe covers REA's own process only; a host that restricts only child processes is reported from the child's output at startup. Fixes #7075 * fix(ghidra): probe the session root and retain failed probe cleanup The Windows doctor temp_directory probe now writes under ghidraSessionRoot(), the same root Ghidra session runtimes use, instead of os.tmpdir(), which can differ when the inherited temp path has a dot-prefixed element. A probe file whose removal fails is retained on the doctor resource owner so doctor shutdown retries the removal; the result still reports its path. |
||
|
|
9ef70696dd |
fix(ghidra): expose bit-field base type identity (#8602)
* fix(ghidra): expose bit-field base type identity * test(ghidra): verify bit-field type handoff * test(ghidra): verify big-endian bit-field handoff * fix(ghidra): bind bit-field facts to snapshot profile --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
982e750a70 |
fix(ghidra): bind existing MIPS projects to target metadata (#8605)
Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
dd4b83c220 |
fix(ghidra)!: search adjacent initialized memory blocks (#8840)
* fix(ghidra)!: search adjacent initialized memory blocks BREAKING CHANGE: Ghidra analysis snapshots from earlier byte-search policies are refused; reopen the target and create a new snapshot. Historical Evidence remains importable. * test(ghidra): supervise cross-block fixture process * docs(ghidra): clarify contiguous search range * test(ghidra): verify search metadata and cleanup --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
63b66fa498 |
fix(search): clarify regex diagnostics and recovery (#8776)
* fix(ghidra): identify invalid regex patterns * docs(native): clarify regex dialects in search contracts * fix(ghidra): guide regex syntax recovery * fix(search): guide regex worker recovery * fix(search): preserve regex parser diagnostics * test(search): update regex boundary expectations * refactor(search): remove unused regex error hook --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
2d16a40a49 |
fix(ghidra): report selected project identity failures (#8379)
* fix(ghidra): report selected project identity failures * fix(ghidra): retain refusal until client shutdown |
||
|
|
103684bce1 |
fix(ghidra): guide recovery from unresolved procedure selectors (#8470)
* fix(ghidra): guide recovery from missing procedures * fix(ghidra): preserve mapped offset lookup recovery * fix(ghidra): distinguish unmapped procedure offsets * fix(ghidra): guide ambiguous selector recovery * fix(ghidra): clarify fresh import excludes project edits |
||
|
|
39172ca2e1 |
fix(ghidra): keep a changed existing project's refusal typed through launch (#8273)
* fix(ghidra): keep a changed existing project's refusal typed through launch When the selected REA_GHIDRA_PROJECT_PATH project changes after open_binary commits its profile, the launcher's verified copy refuses it with AnalysisArtifactChangedError. GhidraHeadlessLauncher wraps that in GhidraLaunchError, and the session error's cause became the wrapper, so the projection missed the existing artifact_changed branch and returned generic execution_failure with rea doctor advice. Read the launcher's primary failure when it is an AnalysisArtifactChangedError, so the refusal reaches callers as artifact_changed with the changed path and the existing reopen guidance. The refusal stays fail-closed: no automatic reopen or fresh-import fallback. Other launch failures keep their current projection. Fixes #8217 * fix(ghidra): describe a project profile mismatch without a timing claim When the owned copy of a selected Ghidra project no longer matches the fingerprint committed by open_binary, copyExistingGhidraProject threw RegularFileChangedError, so the artifact_changed reason said the input "changed while being read". A digest mismatch only shows that the project differs from its committed profile; the change may have happened before the copy started. Throw AnalysisArtifactChangedError directly with a reason that states the mismatch and leaves the time of the change unestablished. Changes observed while files are being read keep their existing reason. |
||
|
|
810cebcba0 |
fix(ghidra): explain read-only project edit refusals (#8413)
* fix(ghidra): explain read-only project edit refusals * test: follow provider guidance ownership |
||
|
|
1998e65705 |
fix(ghidra): discover installed versioned Homebrew JDKs (#8853)
* fix(ghidra): discover installed versioned Homebrew JDKs * test(ghidra): protect Homebrew Java candidate precedence * fix(ghidra): continue automatic JDK discovery after a failed keg |
||
|
|
d7df9df339 |
fix(ghidra): mark empty xrefs results as unresolved, not unreferenced (#8831)
* fix(ghidra): mark empty xrefs results as unresolved, not unreferenced
Ghidra 12.2 resolves no references to data addresses on some Mach-O
imports, and xrefs returned a bare empty list with nothing separating
'no references exist' from 'this provider resolved no references', so
callers concluded addresses were unreferenced.
projectExecution now attaches ghidraEmptyXrefsLimitation to an empty
xrefs result: the list reflects what this analysis resolved, not proof
the address is unreferenced. Non-empty results carry no caveat.
Covered by behavior tests for both branches; validated against
FM9-Edit-arm64 (expect: limitation) once the daemon session reopens.
* fix(ghidra): drop circular trace_feature cross-check from empty xrefs caveat
trace_feature calls xrefs internally, so recommending it as an independent
cross-check repeats the same lookup the caveat qualifies. Keep disassembly
as the single independent check.
* fix(ghidra): report actionable-reference absence and invalidate stale snapshots
Review follow-up on the empty xrefs caveat:
- The bridge filters synthetic entry-point references before observation, so
"resolved no references" could be false; the caveat now reports that no
actionable references were returned and names the omission.
- Drop the trace_feature cross-check: traceReferences observes xrefs per
matched string, repeating the same lookup instead of independent evidence.
- Bump instruction_references semantics to v3 so analysis snapshots captured
before the caveat replay no bare empty results; the profile commitment in
the snapshot binding no longer matches.
* feat(ghidra): mark empty function-reference facets as unresolved too
Extends the empty-xrefs caveat to the sibling ReferenceManager consumers
review follow-up identified: procedure_references and analyze_function
reference facets built on the same observation path could still present
empty arrays as collected facts.
- ghidraEmptyFunctionReferencesLimitation attaches when
procedure_references returns no references for the requested direction
and when a dossier observes no references in either direction;
callers/callees (function-manager derived, observed working on the
reported target) stay caveat-free.
- One emptyReferenceCaveat owner replaces the inline xrefs branch.
- function_references semantics bump to v3 so snapshots captured before
the caveat do not replay bare empty facets; raw profile digests
recomputed.
* fix(ghidra): cover annotation and instruction reference facets in the caveat
Review follow-up: annotate_native_function returns a dossier built by the
same analyzeFunction collection and inspect_native_instruction builds
incoming_references with visitObservedReferencesTo; both could present
empty arrays as collected facts under the reported ReferenceManager
failure.
- annotate_native_function attaches the caveat when its dossier observes
no references in either direction.
- inspect_native_instruction attaches it when incoming_references is an
explicit empty array (null or omission stays unavailable, matching the
field contract).
- Split the diagnostics describe to keep each block under the lint bound.
- Behavior tests cover attach and non-attach for both operations.
* fix(ghidra): name the honest cross-check limits in the reference caveats
Review follow-up: the motivating failure was a string address, so
'cross-check the disassembly at this address' pointed at nothing — data
and string addresses have no instruction to disassemble — and
inspect_native_instruction's incoming_references is built through the
same visitObservedReferencesTo path, so it was not independent either.
- xrefs caveat now states that no independent in-product cross-check
exists for the empty result, that surrounding disassembly only helps
at a code address, and that data or string addresses need an external
disassembly scan (otool -tV adrp/add pairing).
- Function-facet caveat separates outgoing references (own disassembly
is independent) from incoming references (no in-product check; scan
other code externally).
* fix(ghidra): use the address-scoped caveat for inspect_native_instruction
Greptile review follow-up: inspect_native_instruction checks incoming
references to one exact address, so the function-scoped caveat misdescribed
the scope; an instruction can be unreferenced while its function has
references elsewhere, and the address may have no containing function.
Attach the address-scoped xrefs caveat instead.
* fix(ghidra): qualify each empty reference direction independently
Analyze-function and annotate-native-function results attached the
unresolved-references caveat only when BOTH reference directions were
empty, so a dossier with one populated direction presented its empty
direction as a collected fact.
Split the combined function-references caveat into direction-scoped
limitations and attach one per empty direction (analyze_function,
annotate_native_function dossier readback, procedure_references by its
requested direction).
* fix(ghidra): qualify empty outgoing instruction references
inspect_native_instruction results carry two independent
ReferenceManager facets: the incoming list and the outgoing references
built from instruction.getReferencesFrom(). Only the incoming list was
checked, so an instruction with a populated incoming list and no
outgoing references presented the empty outgoing facet as a collected
fact, and any populated incoming list suppressed the caveat entirely.
Each facet is now qualified independently: the empty incoming list
keeps the address-scoped caveat; the empty outgoing list attaches the
new instruction-scoped outgoing limitation (this stream is not
entry-point filtered, so it claims no entry-point omission). Truth
table covered in describe("Ghidra empty instruction reference facets").
* fix(ghidra): gate the instruction outgoing caveat on decoded status
Non-decoded inspect_native_instruction results (data, not-in-listing,
not-instruction-boundary, outside-memory) return before the bridge ever
queries instruction.getReferencesFrom(), so their empty references list
is an unobserved facet, not an empty ReferenceManager observation. The
unconditional outgoing caveat claimed the ReferenceManager returned no
references from an instruction that does not exist at that address.
The outgoing limitation now attaches only when status is decoded; the
address-scoped incoming caveat still applies per the empty incoming
list, matching the original motivating data-address case.
* fix(ghidra): dossier incoming omission and external outgoing recovery
Two unqualified cases remained in the function-reference caveats:
- The analyze_function/annotation dossier excludes incoming references
whose source is inside the function's own body (a self-recursive call
is enough), so the projected empty list can mean 'no outside source
observed' or 'only in-body sources observed'. The dossier now uses a
dedicated incoming limitation naming the exclusion, pointing at the
outgoing edges/disassembly where in-body edges remain visible, and at
procedure_references(incoming) - the same ReferenceManager stream
without the in-body exclusion - as the in-product discriminator.
procedure_references keeps the generic incoming caveat: its incoming
stream is not in-body filtered.
- An external function has no local body, so the outgoing caveat's
'function's own disassembly' recommendation was impossible. Records
classified external now get an external-specific outgoing limitation
naming the defining artifact and this program's call sites instead
(procedure_references outgoing, analyze_function, annotation readback).
* fix(ghidra): qualify dossier incoming caveat observation
The dossier-specific incoming caveat claimed the ReferenceManager
observed no incoming references from outside the body, but
visitObservedReference (ReaGhidraBridge.java:3973-3974) drops
entry-point references before the body filter (1619-1621), so the
manager may have returned references the dossier never reports.
Reframe as 'returned no actionable' and name both omissions; correct
the recovery claim: procedure_references(incoming) lacks the in-body
filter but omits synthetic entry-point references as well.
|
||
|
|
aba56df689 |
fix(ghidra): reject uncommitted handshake reports before the first query (#8630)
The handshake check ran only inside startSession, which a query reached only when the profile committed a startup input, for PE or for an existing project. Any other session started lazily inside callTool, so analysis seeds, disabled analyzers, extension results, MIPS soft-float storage or a RISC-V calling convention that the profile did not commit were never checked and the query returned its result. Every query now runs the checked start first. The client shares one startup attempt, so there is still one launch, and a provider restarted within the session is checked again. That leaves startSession as the only start in the provider client, so the PE data-type path reuses its session info. Recovery guidance is unchanged: the former eager-start condition now selects only whether a completed handshake counts as a running provider. Fixes #8612 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
7bcefead69 |
test: strengthen and prune audited test coverage (#8573)
* test: strengthen and prune audited test coverage * test: require delivered DeepSeek skill instructions * test: keep schema fixture types private * test: verify Gemini receives skill instructions * test: bind Qwen skill evidence to its tool result * test: report NativeAOT verifier checks precisely * fix: verify Ghidra cleanup paths reliably * fix: verify Command Code skill activation * test: tighten cleanup and fixture checks * test: verify packet capture evidence is recorded * fix: report HTTP3 capture provenance accurately * test: preserve resource coverage through MCP * test: prune repeated assertions and retain cancellation identity * fix: validate client verifier fixture paths * test: skip Copilot verifier cases on Windows * test: keep verifier setup target relative |
||
|
|
85013da0ce |
fix(cli): describe one-shot timeouts for an invocation whose session has ended (#8535)
* fix(cli): describe one-shot timeouts for an invocation whose session has ended A one-shot CLI analysis that reached a provider deadline told its caller that the Ghidra session remained usable and reported a runtime-editable limit applying to the next operation, although the command had already released its provider session and runtime. The shared error projection now takes an explicit caller lifetime. Providers keep guidance that holds only for a continuing caller (session reuse, same-session runtime updates) apart from the request outcome, and the presentation adds it only for a continuing caller. One-shot owners (runDirectAnalysis, runProviderAnalysis, finishAnalysisCommand and the JavaScript application command) project for the invocation: details.limit reports scope rea-invocation, applies_at next_invocation and the launch environment seed, and the remediation leads with that setting for a new invocation. MCP output keeps its runtime-update and same-session guidance. Covers the Ghidra decompile timeout, decompiler failure, regex stack exhaustion and startup timeout, the shared regex deadline, the Kuna decompile timeout and the Hopper startup timeout. Fixes #8311 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): project composed child failures for the caller lifetime Cleanup composition embedded its primary and cleanup failures as continuing-caller projections, and baked the primary's message and the cleanup's remediation into the composed error. A one-shot command whose Ghidra startup timed out while shutdown also failed therefore still reported a rea-runtime limit and update_analysis_settings in details.diagnostics.primary_error. childFailureDiagnostics now snapshots each embedded child at composition for both lifetimes when its projection depends on the caller, so cleanup history keeps its composition-time state and the final projection selects the caller's form. composedCallerGuidance re-attributes message and remediation with their continuing-only parts kept separate. Error copies and redaction keep the invocation diagnostics. The Hopper startup timeout now carries its continuing guidance on the error like the other producers. Invocation limits keep agent_editable and rea_restart_required, with values that hold for a new invocation, so only scope and applies_at change and environment is added. In existing-project mode a decompile timeout or a cancelled session now says the next session copies and opens REA_GHIDRA_PROJECT_PATH again rather than repeating import and analysis. Tests compare delivered guidance with the owning formatters and constants instead of freezing prose. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
cbc69537cd |
fix(discovery): carry provider repair instructions into capability discovery (#8532)
* fix(discovery): carry provider repair instructions into capability discovery Provider readiness reported only a failure description, so capability discovery copied that description into tool_availability remediation and dropped repairs the owners already had: the JEB discovery-deadline setting, the ADB/Apktool execute-permission repair kept in diagnostics, and the IDA and Kuna configuration recovery. Unavailable ProviderAvailability now requires the owner's remediation next to its reason, and readiness-derived unavailable capability descriptors carry it too. Every producer supplies it (ADB, Apktool, JADX, JEB, Ghidra, Hopper, IDA, Kuna, pcap, owned-process prerequisites, profile rejection); the inventory uses it verbatim, falling back to the reason only for static capability facts that declare no repair. ADB/Apktool configuration failures own remediation as a field instead of diagnostics, and execution refusals project it as remediation.action. JADX doctor reads the availability's remediation instead of re-deriving it. binary_session complete candidate availability and unavailable capability groups expose remediation (CLI capabilities/providers too); summary omits it and lists it in omitted_fields. The superseded IDA configuration_remediation and windows_native_failure.remediation diagnostics are removed. Fixes #8506 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(discovery): keep owner repairs through provider selection and capability maps Address review findings on the readiness-remediation contract: - Provider selection rejections carry the availability owner's remediation, CLI/MCP error details project it, and an explicit selection refused by readiness uses it as remediation.action. IDA's unreadable registration and Ghidra's Windows readiness repair no longer degrade to generic selection advice now that the diagnostics copies are gone. - Ghidra's Windows readiness and existing-project capability maps carry the same repair as the availability. - pcap readiness keeps the limiter owner's repair (now a typed remediationAction) and falls back to Wireshark guidance only when the failure has none. - ADB/Apktool repairs are owner constants that are complete sentences. The execution refusal keeps its previous message-plus-repair recovery, which the compiled CLI contract asserts. - Regression tests compare with the owning formatter or constant and add public MCP and CLI coverage for an explicit IDA selection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
44b6384009 |
fix(native): find procedures by the secondary names exact lookup accepts (#8520)
* fix(native): find procedures by the secondary names exact lookup accepts search_procedures matched only each procedure's primary name, while exact lookup also accepts Kuna inventory aliases (versioned-symbol and generated sub_ names) and Ghidra symbols at an exact function entry. A search for a name procedure_address resolves returned nothing, and trace_feature silently missed the procedure. Both providers now match the same names their exact lookup accepts. A procedure still appears once under its primary name; the optional matched_aliases field lists the secondary names that matched, so aliases never become procedures of their own and list_procedures is unchanged. The shared domain helper owns that row rule for Kuna and for the Ghidra host-side Unicode folding pass. The Ghidra analysis profile records the new search semantics so older snapshots cannot replay alias-blind results. Fixes #8330 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ghidra): match leaf spellings of procedure names in search procedure_address accepts each entry symbol's leaf or namespace-qualified spelling, but procedure search tested only qualified names, so a regex such as ^audit_alias$ missed a secondary symbol ns::audit_alias (and ^same$ missed a primary alpha::same) that exact lookup selects. Lookup and search now share one bridge definition of the names that select a procedure, so they cannot drift. Matching secondary symbols are still reported by their qualified names; because a leaf ends its qualified spelling, the host's Unicode literal pass stays exact over those names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
df25bc8068 |
fix(ghidra): retain relocation symbol observations (#8531)
* fix(ghidra): retain relocation symbol observations * test(ghidra): verify named relocation symbols through CLI * fix(ghidra): clarify verification and supervise test commands * test(ghidra): share load verification guidance |
||
|
|
e18594b247 |
refactor(composition): unify capability bindings and cleanup ownership (#8441)
Bind typed service creation, observed availability and retryable cleanup in one composition owner. Reuse selected CLI/MCP factories and canonical contract groups without copying provider operation inventories. Closes #8429. Refs #740. Validated paired real application workflows, actual local Codex CLI Terra/high use, complete Evidence and Unknown checkpoint parity, compiler-backed import boundaries, SDK schemas and final real mixed routing. Automated review findings were fixed at their producing owners. Existing exact-base CodeQL alerts are documented on the PR under the owner-authorized unrelated-check exception; no global alerts or security rules were changed. Assisted-by: Suika (gensokyo-skills:suika-scatter-gather-planning) |
||
|
|
60149282fc |
test: strengthen integration oracles and verification (#8295)
* test: strengthen integration oracles and verification * test: bound lifecycle gates and strengthen workflow checks * test: verify complete paged and extracted results * test: preserve bytecode and cancellation evidence * test: strengthen retained evidence and fixture cleanup * test: require cross-projection bridge identities * test: retain fixture owners through cleanup failures * test: verify graph examples and project selectors * test: tighten provider and lifecycle regressions * test: consolidate hex coverage and bound cutter cleanup * test: bound subprocess output waits and strengthen graph checks * test: check mcp recovery and preserve cleanup owners * test: verify structured mcp argument failures * test: preserve artifact cleanup and gdb limit evidence * test: preserve evidence identities and bound provider gates * test: retain browser and comparison cleanup owners * test: bound startup and strengthen fixture oracles * test: bound lifecycle gates and verify recovered evidence * test: verify public outcomes and lifecycle ownership * test: assert precise evidence and release lifecycle gates * test: verify selected facts and bound cleanup waits * test: check retained evidence and decoded records * test: verify final reports and retain cleanup ownership * test: bound reviewed startup gates and retain cleanup * test: verify PE errors and preserve MCP cleanup * test: preserve MCP fixture cleanup ownership * test: release provider gates before late startup |
||
|
|
c287a73276 |
fix(ghidra): report unbacked file-offset addresses without schema repair (#8308)
* fix(ghidra): report unbacked file-offset addresses without schema repair address_to_file_offset projected a well-formed address in uninitialized or unmapped Ghidra memory as generic invalid input: the headline said the arguments were invalid and recovery pointed at the input schema, while the real reason survived only in a nested issue. The bridge now gives each outcome its own code (address_unmapped, address_uninitialized, file_mapping_absent, file_mapping_ambiguous, file_offset_unrepresentable) instead of folding them into invalid_request. The Ghidra projection keeps the bridge reason as the headline, points to inspect_native_load_image, records the caller's exact address and the file_mapping outcome, and scopes diagnostics to the request. AnalysisInputError gains conformsToInputContract so a conforming request omits recovery.kind=inspect_input_contract. Malformed addresses and other bridge refusals keep their existing projection. Fixes #8244 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(ghidra): match fixture block ends to bridge conventions The fake bridge treated .text's exclusive list_segments end (0x1100) as an inclusive bound, so address_to_file_offset mapped an address outside the block. Give the fixture's blocks one owner (start and size) and derive each reply from the production bridge convention: exclusive list_segments ends, inclusive byte-search coverage, half-open containment for file offsets. Add an MCP boundary test that reads the block edges from list_segments and search_bytes, maps the last file-backed byte and refuses the first address past each block with its outcome code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
7c9ed94259 |
fix(ghidra): decide batch names independently of request order (#8306)
* fix(ghidra): decide batch names independently of request order The Ghidra bridge applied set_addresses_names in JSON member order, each address in its own transaction, so a reordered but equivalent map could give a shared name, or a name released by another selected address, to a different address. The bridge now resolves every destination (namespace and leaf name) against the names held before the batch. Addresses that request the same destination, or a name that another selected address holds, are rejected without applying; the remaining edits are independent and apply as before. Both naming operations report each failure's canonical address, reason and related addresses. The adapter projects the bridge reply to the unchanged boolean results and keeps the reply as raw_result only when an address failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ghidra): report each contested batch name once A batch conflict listed every other requester on each failure, so k addresses competing for one name produced k(k-1) related addresses, and the adapter retained the whole reply, booleans included, as raw_result. The bridge now reports each contested destination once in a conflicts table with its namespace, name, requesting and holding addresses, and each conflict failure refers to it by index. Conflicts are ordered by their first requester, so indexes do not depend on member order. Single and batch naming share one planner and reply layout. The adapter validates the table in linear time and keeps only failures and conflicts in raw_result. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
e669365c3b |
feat(ghidra): admit RISC-V ilp32 ELF with a derived calling convention (#8229)
* feat(ghidra): record the RISC-V float-ABI calling-convention decision Decision D3 (#7477), provisional: admit ELF32 soft-float (ilp32) RISC-V images through a lane that keeps the pinned RISCV:LE:32:default language and corrects the calling convention in the bridge. This commit is the contract only; admission is unchanged. - The domain owns the e_flags float-ABI vocabulary and parses .riscv.attributes and Tag_RISCV_arch into a declared, absent or unavailable ISA declaration. - The Ghidra profile owns the lane table (class and float ABI), lane ids built from fields, the ilp32-prototype-v1 policy and its __rea_ilp32 prototype, and the extensions Ghidra 12.1.4 decodes with p-code. - The session handshake accepts the bridge's calling-convention report. - docs/ghidra-riscv.md keeps the decision record and per-ABI policies for ilp32 and ilp32f; a test keeps it in step with the tables. - tests/conformance/c/riscv-float-abi.c is the source the policies were measured on. * feat(ghidra): admit RISC-V ilp32 ELF with a derived calling convention ESP32-C2, C3, C5, C6, C61, H2 and H21 builds are ELF32 soft-float (ilp32) images, which the RISC-V lane refused at its double-float check. Ghidra 12.1.4's generic RV32 compiler specification models ilp32d, so its stock prototype would read float and double arguments from fa0-fa7. - Target resolution reads the one SHT_RISCV_ATTRIBUTES section through the same bounded ELF declaration reader as range validation, and records Tag_RISCV_arch as declared, absent or unavailable. - Admission selects a lane from the class and float-ABI table. The soft-float lane also requires an RV32I Tag_RISCV_arch that declares only extensions Ghidra decodes with p-code; the refusal names any others (Zcb, Zcmp, Zcmt, Zb*, xesp*). - Soft-float profiles commit float_abi, arch, riscv_calling_convention ilp32-prototype-v1 and the lane elf32-exec-le-soft-float-generic-v1. Double-float profiles are unchanged. - ReaGhidraRiscvCallingConvention.java runs after analysis. It derives __rea_ilp32 from the default prototype without floating-point entries and rules, with fs0-fs11 killed by calls, self-checks its storage and assigns it to every non-thunk function, external function and function definition. Its report is written last. - The provider client requires that report exactly when the profile commits the policy, before any operation, and keeps it as session limitations and caller-project history. ELF32 single-float (ilp32f), quad-float and ELF64 soft- or single-float images stay refused, now with a reason built from the lane table. * test(ghidra): verify RISC-V ilp32 against real Ghidra verify:ghidra:riscv now also builds tests/conformance/c/riscv-float-abi.c with ESP32-C3's -march=rv32imc_zicsr_zifencei -mabi=ilp32, typed with DWARF and linked again with --strip-all. Every allocated section of the stripped image must keep its address and bytes. - riscv-checks.mjs holds the ilp32 storage of each fixture function together with the words the compiler's call site writes there. An LLVM objdump reading of the caller must find every word at its stated location: an unaligned named double, the a7/stack split, two floats in an integer pair, a large structure by reference, aligned variadic pairs and an indirect call. - Through CLI and stdio MCP, the soft-float builds must report the soft-float lane and ilp32-prototype-v1, __rea_ilp32 with exactly that storage (one integer word per location when stripped), caller pseudocode that passes the source constants and names no floating-point register, the prototype outcome in retained Evidence, and decoded fence.i and csrr. - The RV32 double-float image relabelled as soft-float, refused before, is admitted through the new lane. RV64 soft-float, single-float and unsupported bits are refused with their reasons. - riscv-checks.test.ts runs the checks offline against recorded LLVM and Ghidra output, including Ghidra's stock ilp32d prototypes as a negative control. * fix(ghidra): pass RISC-V ilp32 values over 8 bytes by reference The psABI passes any value wider than 2 x XLEN by reference, scalars included. __rea_ilp32 converted only structures and unions over 8 bytes to pointers, so a long double (16 bytes) was joined into a1-a4. Measured on Ghidra 12.1.4, rea_riscv_abi_quad(long double value, int sel) read value from a4:4,a3:4,a2:4,a1:4 and sel from a5, where clang passes a pointer in a1 and sel in a2. - ReaGhidraRiscvCallingConvention.java now has one derivation driven by a per-policy row (floating-point entry size, preserved floating-point registers). Every policy inserts a rule before the input list's final join that converts any value of 9 bytes or more to a pointer; a return that size already becomes a caller buffer. The self-check requires a 16-byte value to pass by reference. - The fixture gains rea_riscv_abi_quad. The call-site oracle now checks the words the by-reference pointers point at, for the large structure and the long double, and the recorded data comes from an LLVM 19 build. - docs/ghidra-riscv.md: the decision record and the ilp32 policy row. ilp32-prototype-v1 keeps its id: no release carries it yet. * test(ghidra): check RISC-V lane limitations by their facts The limitation tests froze a full explanatory sentence, the note count and array positions, so a harmless rewording failed them: the pattern Greptile flagged on #7486. Assert the facts the notes must carry instead: the pinned language, the static-linkage boundary, one note naming the declared ABI, the ABI the pinned language models and the prototype REA applies, and the declared ISA. * test(ghidra): check return storage in stripped RISC-V ilp32 builds The stripped branch of assertRiscvIlp32Storage compared parameter storage only, so an inferred return that lost the high word of a register pair, such as rea_riscv_abi_wide at a0:4 instead of a1:4,a0:4, still passed. Stripped returns must now use the typed build's storage, or none when the result goes through caller memory. Recovered type names are still not compared: a test accepts other type names and refuses the dropped high word. * docs(ghidra): record decision D3 as decided in #7477 |
||
|
|
1dc97d8cec |
fix(ghidra): report a missing existing-project program as a configuration error (#8222)
* fix(ghidra): report a missing existing-project program as a configuration error When REA_GHIDRA_PROJECT_PATH selects a project that has no root program with the selected name, Ghidra's headless analyzer aborts with "Requested project program file(s) not found: <name>". REA reported this as a generic execution_failure with rea doctor advice, and the reason was visible only in the captured diagnostics. Recognize that refusal in the operation-scoped launcher output, matching only the exact name REA passed to -process, and return a ConfigurationError for REA_GHIDRA_PROGRAM_NAME. The message says whether the name was configured or defaulted from the target file name, and the remediation explains how to select the exact root program. The selected project is unchanged and there is no fallback to a fresh import. Other launch failures keep their existing projection. Fixes #8216 * test(ghidra): assert missing-program guidance through its formatter Compare the projected setting constraint and remediation with ghidraMissingProgramGuidance instead of freezing explanatory phrases, following docs/testing.md. The program name and configured-or-defaulted origin are still checked independently. |
||
|
|
ca7d1c3750 |
fix(ghidra): match startup-timeout guidance to the project mode (#8114)
In fresh-import mode, the startup-timeout remediation now points to REA_GHIDRA_PROJECT_PATH for reusing a completed analysis, next to the existing REA_GHIDRA_STARTUP_TIMEOUT_MS and REA_GHIDRA_DISABLED_ANALYZERS advice. In existing-project mode, the message no longer says Ghidra was importing and analyzing the target, and the remediation no longer suggests REA_GHIDRA_DISABLED_ANALYZERS, which configuration validation rejects together with REA_GHIDRA_PROJECT_PATH. Refs #3751 |