Commit Graph
199 Commits
Author SHA1 Message Date
morluto 8c64eb511f fix(ghidra): stage NativeAOT report until recovery completes (#9611)
* fix(ghidra): stage nativeaot recovery report until complete

* test(ghidra): exercise nativeaot rollback reporting
2026-11-09 19:39:51 +08:00
morluto 7c821cfea1 fix(hopper): retain bridge after lost shutdown reply (#9604) 2026-11-09 19:34:55 +08:00
4d7c6efe9a feat(desktop): open the seed's document at launch, and say when a seed was made for the task (#9054)
* feat(desktop): capture, draft, export and witness a task inside a build computer

- start_build_capture runs REA's capture inside the computer through a
  small controller over computer-exec, after a user-space apt-get update;
  mark_build_checkpoint returns once the capture confirms the checkpoint;
  stop_build_capture returns the draft between seed and end.
- export_build_environment exports with the requester's task inside the
  computer and fetches the bundle through data/get in bounded batches.
- check_build_task grades a computer's data/get with REA's evaluator and,
  through seed, after_edit, near_miss and after_reset stages, records a
  witness with the action log and the screen recording; act_on_build_computer
  gains reset.
- Capture progress lines carry window, checkpoint and refusal events; apps
  start in the home; a pack script builds the runtime archive; long tools
  send progress notifications.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): make build capture and witness steps retryable, and close the near-miss reset hole

- A capture whose start answer is lost is stopped at once and kept
  unreleased until the stop is confirmed; a lost checkpoint answer is
  recovered from the capture's own log, and draft and export use the
  checkpoints its Evidence records; stop can be repeated to resume
  reading its result.
- A witness can check its seed again after a failed read, and keeps its
  stages in a saving state until the record is written, so a failed save
  can be retried without reading the app again.
- after_edit and near_miss count only click, drag, scroll, type and key,
  so a reset no longer stands in for the near-miss edit.
- A .deb build keeps its package file for capture and passes its URL to
  export; bundle downloads write each checked file before fetching the
  next; an apt-get update failure reports its exit code and log tail;
  reset sends progress while it waits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): keep the Trash out of seeds, bundle folders unwritten and first frames drawn

From the blind Inkscape rebuild:
- Paths in ~/.local/share/Trash get a desktop_trash reason and the
  shared_desktop role, so a file trashed before seed is neither owned nor
  seeded; the export names it in a limitation.
- The keep helper runs with PYTHONDONTWRITEBYTECODE=1, so starting a
  computer from a bundle folder no longer writes __pycache__ into it.
- start_build_computer waits, bounded, until the first frame is not one
  colour before returning it.
From review: a .deb that apt also offers exports from apt, since export
passes --package-url only when the capture says the package must come
from its file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): bound the first-frame wait's retries to the time left, with progress throughout

Each retry of the drawn-first-frame wait runs under an abort that fires at
the 10 s deadline, and the latest frame is returned when time runs out.
connect takes the first frame itself while its progress heartbeat still
runs, reporting "waiting for the desktop to draw". The wait moves to
DrawnScreenshot.ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): serialize each build computer's calls, keep one recording id, and separate unreadable checks from failures

- One queue per computer: actions, capture steps and witness checks run one
  at a time, so two overlapping after_edit checks can no longer both be filed
  and let the witness hold without a near miss. Close cancels the running and
  queued calls; different computers still run concurrently.
- The witness keeps one recording request id per computer, so a seed retried
  after a lost reply recovers the recording it started.
- A check that could not read its file is undecided, not a failure, so a
  temporary read error can't satisfy seed, near_miss or after_reset; such a
  stage is refused and can be checked again.
- The export's file listing is written to a file and read back in bounded
  batches, so a large bundle no longer overruns exec's 1 MiB output.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): treat failures on cut views as undecided, require a decided seed failure at export, and keep a close's cancellation

- A presence check that misses its line, row or pointed value in a view cut
  short is undecided rather than failed, since the data may sit in the part
  left out; a witness stage can no longer be proved by such a failure.
- Export counts only decided failures on the seed, and refuses a task whose
  every seed failure is undecided.
- A step whose turn was aborted by a close or the caller returns cancelled
  even when its work finished, so start_build_capture no longer reports
  success for a computer being removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): keep a step's saved result when a cancellation arrives during its commit

Reporting cancelled for any step whose turn was aborted after its work
replaced a completed export or witness save with a bare cancellation, losing
what was saved and leaving the witness unreadable. Steps now return what they
completed; only start_build_capture, which commits nothing, checks its turn
after the post-launch screenshot and reports cancelled. Asking again for a
saved witness's final check returns its record.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): refuse a saved witness's repeated check for another folder

Asking again for the check that ended a witness returned its saved record
whatever directory came with it, so a caller naming another folder got
success though nothing was saved there. A different folder is now refused,
as an unfinished seed's retry already is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(desktop): assert the facts of cut-view and undecided outcomes, not their sentences

The new cut-view, missing-value, undecided-refusal and witness tests froze
whole descriptions, so a harmless rewording broke them. They now check each
outcome's id, passed and undecided exactly and the facts its message must
carry (file, pointer, line, row, stage) separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(desktop): read XML with a plain DOCTYPE, and check an element's whole text

- Both readers accept a DOCTYPE with only a name and an optional PUBLIC
  or SYSTEM identifier, record it as the view's doctype, and never fetch
  the DTD or expand entities beyond XML's five; an internal subset, an
  external entity and a parameter entity stay refused alike.
- text_equals and text_contains compare the concatenated text of the
  element (or text node or attribute) a pointer reaches, as XPath
  string() does, with optional normalize_whitespace; both evaluators
  agree, and a text check on a truncated element is undecided.
- Whitespace-only text between elements is dropped only when the element
  holds no other text, so text split into runs keeps its spaces.
- The draft suggests text_equals for an element whose text changed.

So an AbiWord .abw reads as XML, and its paragraph's text is checked
whole however AbiWord splits it into <c> runs, as Writer's spans are.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): draft whole-text checks on the paragraph, read only text as text, and skip asctime stamps

- A changed value is read at both ends, so text that became a run still
  marks its paragraph, and the drafted text_equals moves up out of mixed
  content to the nearest ancestor named by an attribute, such as
  AbiWord's p by its xid.
- Text checks accept only a text node or an attribute value; element
  names and doctype fields fail, in both evaluators.
- isTimestamp also recognises asctime dates (Www Mmm dd hh:mm:ss yyyy).
- XML files are drafted with the keyed diff the archive entries use, so
  no suggestion reaches an element by position; the shared logic moves to
  appTaskDraftNamed.ts.
- Text-check tests assert facts, not whole sentences.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): keep checks on a changed attribute inside a paragraph whose text check replaces its runs'

A drafted whole-text check on a paragraph hid every change inside it, so a
link whose label and href both changed drafted only the paragraph's text and
the new destination went unchecked. The text check now covers text and runs
added or removed whole; a changed name or attribute of an element both
versions hold keeps its own check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): read an attribute called name or attributes as an attribute when the draft keeps its check

The owner of `.../attributes/name` was taken as `.../attributes`, so a
changed `name` attribute inside a paragraph with a text check was dropped
again. The owner is now read by segment, attributes first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): draft text checks from text in runs added whole, and name a text element by its own id before its container

Text typed into a run the diff lists whole was never read, so the draft kept
only a presence check on the run, which wrong text also passed. Such text now
marks the nearest element both ends hold, or, when none can take the check,
the added element's own text. The climb also names an element by an
identifier of its own (id, xml:id, xid) before a larger container, so a
headline under a long layer keeps a whole-text check that survives re-split
runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(desktop): expect the whole-text check where #8988's pairing test meets text checks

On this branch a changed element's text is drafted as `text_equals` on the
element, so the identity pairing test now expects that check, under the
same `[@role=body]` key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(skills): build a computer-app environment from a request

The product skill gains references/desktop-build.md, a procedure that
takes Claude from a request such as "an Inkscape environment where the
agent changes a poster's headline" to a witnessed bundle and a report,
through start_build_computer, act_on_build_computer, the build capture
tools, export_build_environment and check_build_task: questions asked
once upfront, pauses only when blocked, a seed made in the app, content
checks by selector, a witness with a near miss and a reset in a fresh
computer, and solver runs only within a budget. setup installs the new
reference; skillVersion 61.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(skills): fold the blind Inkscape rebuild's friction into the build skill

key takes an array of one chord's keys; check for a text cursor before
typing in apps with single-key shortcuts; in Save As, click Documents and
type only the file name; anything saved before seed, the Trash included,
is part of the seed; dismiss first-run dialogs before seed; a bundle's app
starts with the seed's files but need not open the document; Inkscape's
window class is Inkscape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(skills): fold the held-out AbiWord build's friction into the build skill

Name the act fields and link the guide; a region screenshot becomes the
latest frame; a drawn caret is not focus; confirm dialogs with Return;
check the dialog's folder when the app shows only a name; an XML file the
draft shows as lines was read as text, so use short line checks; and keep
text checks to the value the edit types, since some apps save a reloaded
document differently. Later witness stages take no directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(skills): state the export's seed rule, the Trash exception and draft refusals exactly

The export refuses a task unless at least one check fails on the seed and
every check passes at the end; a file moved to the Trash is left out of
the seed, so trash a stray file rather than starting over; a null draft
names its cause in draft_refusal; and a line check on a format read as
text only approximates a value, so bound it and call it approximate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(skills): teach the build skill to use DOCTYPE and whole-text checks

The skill now checks text an app splits into runs whole with text_equals or
text_contains, finds an AbiWord paragraph by its xid, and drops the Writer
revision-id workaround.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(skills): point text checks at the paragraph, and say what the scrub replaces

From the AbiWord rebuild: point a text check at the paragraph or another
element the edit keeps, never at a run a reopened document splits; how to
name an unchanged element; the export replaces the host name, user@host
and home path while a bare user name stays; AbiWord's entry and class.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): keep every text check on a cut element undecided, in both evaluators

The XML reader drops text deeper than its depth limit but keeps later
siblings, and an element's whole text joins both sides, so a text_contains
on a cut element could match text the file never holds ("at 3" + deep
"WRONG" + ":30 PM" read as "at 3:30 PM"). Any text check on an element of a
cut view is now undecided again, as #9050 had it, in REA's evaluator and the
exported verifier; a text node or attribute value stays decided. The text
check tests assert facts rather than sentences.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(desktop): open the seed's document at launch, and say when a seed was made for the task

An exported app now opens the seed's one document at launch when its desktop
entry's Exec takes files, so a solving agent starts in the document rather
than on the app's start screen; a command that already names a file is kept,
and several documents or an Exec without a file code keep the launch and say
why. `--synthetic-seed`, which the build export passes, words the README and
limitations for a seed made in the build computer instead of asking to keep
the user's data local.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): count only a document the launch names, absolute or from its working directory, as already opened

A settings path under the home, such as geany's --config, kept the seed's
document from opening, and a relative document argument was missed and
appended again. An argument now counts only when it resolves, from the
captured working directory, to a file the capture gave the document role.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(desktop): check the seed and launch wording against their formatters, and the facts on their own

The tests froze the README's and limitations' sentences, so a harmless
rewrite broke them. The wording now comes from exported formatters
(`seedWording`, `seedLimitation`, `launchDocumentNote`,
`NO_LAUNCH_DOCUMENT`), the tests compare against those, and check the facts
separately: which document opens, the respelled path in the command, the
README naming it, `--synthetic-seed` and the Evidence's `synthetic_seed`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(desktop): plan the export's seeds and launch in their own module

The merged export module passed the file and function size limits; the seed
digests and the launch command now come from `DesktopExportLaunch.ts`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): keep a reset applied when the screenshot asked after it fails

Once data/reset and the ready wait succeed, act_on_build_computer's reset
is applied in the action log and returns success; a screenshot asked of it
that is then refused or throws is named in the result's screenshot_error,
with no frame, so the next after_reset stage is not refused. Cancellation
still propagates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): keep checks for elements without text beside a text edit, and normalize DOCTYPE system id line endings

A review found two gaps.

- A paragraph's whole-text check covered every element added or removed
  inside it, including ones holding no text: an image frame, a line break.
  A solver who typed the text but never inserted the image passed. Such an
  element now keeps its own presence or absence check.
- The Python reader kept a DOCTYPE system literal's CRLF where TypeScript
  normalizes it to LF. Both now report LF.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): wait out long build commands, fail a reset that restores nothing, and tie the witness to its bundle

A review found five gaps.

- Commands in the computer answer only when they end, but fetch stops
  waiting for headers after 300 s. So a slow export, draft or start always
  failed. A command with its own deadline now waits on node:http, bounded
  by that deadline.
- after_reset held whenever some check failed, so a reset that changed
  nothing passed on the near-miss state. Each check must now come out as it
  did at the seed.
- A failed or partial apt-get update left lists that looked complete, so a
  second start skipped the update. The update is now recorded only when it
  succeeds, and rerun otherwise.
- A witness on a bundle computer graded whatever task it was given. Its
  seed stage now refuses a task whose steps or checks differ from the
  bundle's.
- A task too large for one command argument (96 KiB) is refused before the
  export runs, instead of failing with E2BIG in the computer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): advertise a checkpoint-name pattern that compiles in every JS regex mode

main's advertised-pattern test compiles every input schema pattern in v
mode, which refuses an unescaped hyphen in a character class. The
checkpoint name's hyphen is now escaped, and it means the same in u mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(desktop): import textSyntaxFormat once in the state format tests

main's mixed-case JSON suffix fix and this branch both added the import,
and the merge kept both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): keep a completed reset, an unread seed, and a failed apt update

A cancel after data/reset no longer drops the restore from the action log,
so a near miss cannot treat the restored seed as an edit. An unreadable
seed check that later passes leaves after_reset undecided instead of
failing the witness. apt-get update is kept only when Error-Mode reports
success and a package list was fetched. The controller reply schema lives
with the controller, and capture progress lines are read by their domain
parser.

* fix(desktop): keep a whitespace-only run under the paragraph text check

A run whose only text is whitespace is still text the paragraph check
reads. It no longer gets its own presence check, which a later save of
the same words without that run would fail. Images and breaks, whose
text is empty, still keep their own checks.

* fix(desktop): keep an unread reset and a cut text check undecided

after_reset stays undecided when any check was not read, even if another
check still fails and the unread result's boolean matches the seed. A
text check for a child past a truncated view is undecided in both
evaluators. A reset whose reply is lost blocks a near miss until a later
input or a reset whose reply arrives.

* fix(desktop): retry a witness recording and a published record's cleanup

A recording that fails to end or download is not written into the witness
folder, and a manifest already received is fetched again without ending
the recording twice. A folder that is published while its handles fail to
close keeps that record and retries the same cleanup instead of writing
the folder again.

* fix(desktop): keep a published witness error and tag an app data refusal

A second failure to close a published witness returns the original error,
so its record and cleanup lease stay bound. A reset the app itself
refuses is an AppDataRefusal; only a reply that is not that refusal stays
unsettled. A missing child of a cut view is undecided with the same
description in both evaluators, and the shared cases cover it.

* fix(desktop): align a cut view's missing text with the Python check

A missing child of a truncated view is undecided for the same sentence in both evaluators, including the pointer the view does not contain.

* fix(desktop): keep one published witness cleanup across retries

A published record and its bound cleanup error stay together. A later close failure returns that error, and the unused path that built a fresh adapter error is gone.

* fix(desktop): keep a bundle task read inside the witness result

A cancelled, refused, or failed read of the bundle's task files returns the witness's Result, including a cleanup lease when a handle would not close.

* fix(desktop): check build runtime export capability

* fix(desktop): provide complete runtime repack command

* fix(desktop): retain runtime probe failures

* fix(desktop): recognize captured file URL documents

* fix(desktop): render captured file URLs at launch

* fix(desktop): isolate launcher URL encoding

* test(desktop): move launch execution to boundary suite

* style: fix desktop launch test formatting

* style: format native command path schema

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-11-09 08:07:40 +08:00
morluto b4b881116f fix(agentenv): report incomplete folder inventories (#9466) 2026-11-09 03:14:35 +08:00
morluto 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
2026-11-08 15:05:51 +00:00
morlutoandCursor Agent 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>
2026-11-08 01:49:58 +00:00
morluto 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
2026-11-08 08:57:05 +08:00
morluto 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
2026-11-07 21:26:52 +00:00
morluto 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
2026-11-08 02:04:30 +08:00
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>
2026-11-08 01:42:28 +08:00
morluto 1596d6a275 test: reduce wording coupling and prune redundant coverage 2026-11-08 00:01:18 +08:00
3e8a5f76d0 feat(native): retain LLDB source coordinates and verify Pascal calls (#2800)
* feat(native): retain LLDB source coordinates and verify Pascal call entries

Preserve partial line-table attribution for native locations and historical
evidence compatibility. Verify owned Free Pascal call entries through CLI/MCP.

Refs #2382, #2372, #2397

Co-Authored-By: Codex <noreply@openai.com>

* docs: namespace native specifications by domain and feature

Use stable descriptive paths instead of numeric prefixes to avoid parallel contribution collisions.

Co-Authored-By: Codex <noreply@openai.com>

* fix(native): bound Pascal verification and compare caller coordinates

Address review findings at their producing boundaries and preserve directly affected consumers. Source inspection and git diff --check completed. Tests and automated checks were not run at the user’s explicit request.

* fix(native): bound compiler shutdown and source-coordinate fixtures

* docs: clarify historical native source verification

* fix(native): preserve source attribution and compiler ownership

* docs(native): qualify retained source attribution

* fix(ci): clean up native Pascal verifier processes

* test(native): type the Pascal verifier helper import after merging main

Main now typechecks this boundary test, which imports the untyped
canonical-temporary-directory helper and reads an unknown catch value.
Add the helper's declaration file and narrow the caught error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(native): verify partial source attribution caveat

* fix(native): retain verifier compiler cleanup ownership

* fix(native): forward verifier cancellation and measure path bytes

CLI and MCP artifact runs observe the verifier abort signal, and a
failed Pascal verifier test stops the compiler group before deleting
its directory. Repeated source locations grow by measured UTF-8 JSON
bytes; workflow tokens, CPU and peak memory stay unmeasured.

---------

Co-authored-by: Matheus Breguêz <matbrgz@gmail.com>
Co-authored-by: Codex <noreply@openai.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: Cursor Agent <cursoragent@cursor.com>
2026-11-07 23:25:20 +08:00
Edgar Arakelyan c5301e6145 feat(desktop): capture, draft, export and witness a task inside a build computer (#9045) 2026-11-07 17:54:59 +08:00
gensokyo-dev 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.
2026-11-07 14:52:39 +08:00
Edgar ArakelyanandClaude Opus 5.5 fc4c381dd7 feat(desktop): keep an agentenv computer up and drive it through REA's MCP tools (#9041)
* feat(desktop): keep an agentenv computer up and drive it through REA's MCP tools

- A Python helper keeps one agentenv computer up per build with
  run_bundle(keep=True) and reports its address, MCP URL, control token
  and sandbox id; it tears the computer down when stdin closes.
- AgentEnvComputer owns the helper, waits for readiness, holds one MCP
  session to the computer's computer_* tools, records through the
  computer-recording routes, and removes the sandbox's containers by
  label when agentenv cannot confirm teardown. The token never leaves it.
- start_build_computer starts a computer from a request (archive package,
  apt repository or .deb, opened on demand with REA in /opt/rea) or from
  a bundle folder; act_on_build_computer forwards screenshot, click,
  drag, scroll, type, key and wait and returns the driver's images
  unchanged; close_build_computer tears it down.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): remove a build computer's container by name when agentenv cannot confirm teardown

agentenv's local provider runs an ordinary computer as agent-<sandbox id>
without the agentenv.sandbox label, so the label-only fallback found
nothing and reported a running computer as removed. The fallback now
lists containers by exact name and by label. The real test holds its
recording open long enough for a first frame, checks the container by
name, and runs rea inside the computer; the guide and tool descriptions
say the app opens from the Applications menu and that a screenshot after
opening a menu should come from a wait.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): own failed build-computer starts, keep ids past oversized screenshots, bound recordings

- A start is owned from the helper's spawn. One that fails and whose
  teardown is unconfirmed stays held under a computer_id close can retry;
  closeAll refuses new starts, cancels and joins starts in progress, then
  closes every held computer.
- When the first screenshot is too large, the error carries REA's result
  with the computer_id, and start_build_computer takes screenshot region,
  format and quality.
- Recordings are refused before reading when the manifest's total exceeds
  the allowance, then fetched one segment at a time, each read bounded and
  checked against its size and sha256.
- The helper keeps the tail of its output (a new tail retention mode in
  ProviderProcessSupervisor), so a build's own error is not crowded out.
- A helper that reported no computer exits on its own before SIGTERM, so
  no phantom owner is kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): bound a build computer's action log

Every action kept its full arguments for the computer's whole life, so a long
session grew REA's memory without limit. The log now keeps the latest 256
actions within 256 KiB, cuts each string to 1 KiB and each list to 64 items
(naming what it cut), and keeps the total and the last applied index of each
kind of action, so rules over the whole session hold after entries drop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 11:01:11 +08:00
morlutoandCursor Agent 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>
2026-11-05 04:03:43 +08:00
morlutoandCursor Agent 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>
2026-11-05 02:31:32 +08:00
morlutoandCursor Agent 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>
2026-11-05 00:20:01 +08:00
morluto 2d16a40a49 fix(ghidra): report selected project identity failures (#8379)
* fix(ghidra): report selected project identity failures

* fix(ghidra): retain refusal until client shutdown
2026-11-04 19:58:50 +08:00
morluto 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
2026-11-04 19:51:27 +08:00
STDquantum 2ae7878fc7 fix(native): retain all breakpoint locations within budget (#7975)
* fix(native): retain all breakpoint locations within budget

* fix(native): describe incomplete locations accurately

* test(native): cover incomplete location warning

* test(native): bind lipo failure to a real fixture

* test(native): use valid Mach-O fixture for lipo errors

* test(native): drop fixture change already in main

* test(native): share breakpoint limitation wording with formatter

* test(native): assert limitation delivery via owner constants

* style(native): format breakpoint limitation projection
2026-11-04 19:38:15 +08:00
morluto 26b033d51f fix(process): classify withheld Darwin environments before parser failures 2026-11-03 23:48:22 +08:00
JANG BYUNGKUN 6442ea02cb feat(binary-layout): admit ELF64 AArch64 and name the refused host (#8711)
* feat(binary-layout): admit ELF64 AArch64 and name the refused host

inspect_binary_layout refused every AArch64 ELF, and on a non-x64 host the
refusal read "supports Linux x64 only", which looked like a target refusal
(#8709 ran on arm64 WSL and suspected an e_machine check).

The pwntools adapter now admits little-endian ELF64 AArch64 EXEC/DYN/REL
objects alongside the existing profiles, pwntools must report aarch64/64/
little, and the Evidence subject names arm64. The host refusal now names the
detected platform/arch and says the target was not read; the host check
itself is unchanged.

verify:binary:layout cross-compiles an AArch64 executable and relocatable
object (never executed) and checks sections, symbols and relocations
against GNU readelf, decoding ELF64 r_info as a 32-bit type under a 32-bit
symbol index. The real-binary-layout workflow installs the toolchain.

Refs #8709

* test(binary-layout): refuse RISC-V as the unsupported machine and assert the host refusal path

verify:binary:layout used e_machine 183 (AArch64) as its unsupported
target, which this branch now admits; use EM_RISCV (243) instead.

The unsupported-host provider test now asserts the refusal names this
host's platform/arch and says the target was not read, so reverting the
decoder to the old message fails it.
2026-11-03 09:37:41 +08:00
Kaoru0822andClaude Opus 5.5 26c3e9e413 fix(native): select off-screen windows so the UI lane can complete (#8654)
* fix(native): stop calling an off-screen window absent

The native UI helper looked up its selected window with
`.optionIncludingWindow`, which returned nothing while that window was off
screen. An existing window owned by the selected process was reported as
`window-mismatch`, before any permission check, so the verifier could not reach
its permission boundary. Select from all windows instead; absent and foreign
windows still fail.

The verifier's changed-bytes check also read `error.message`, but since
cc90771af a selection failure carries its helper code in `error.issues`, so the
check could not pass. Read the issue. Together these let the permissions lane
complete on main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(native): own UI test processes from the moment they launch

The off-screen test registered cleanup only after parsing the ready record, so a
startup failure left `/usr/bin/open` and its app running. The lane test killed
only the verifier on a timeout, leaving its launcher and detached fixture alive
until they expired.

Register the off-screen owner immediately after the launch; the app inherits the
run token, so the sweep needs no ready record. In the lane test, every stand-in
records itself and leaves on one release the test's cleanup awaits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 23:57:32 +08:00
Kaoru0822andClaude Opus 5.5 2ac6d3efe2 fix(process): re-read unreadable tokens before signaling and name the process (#8553)
* fix(process): re-read unreadable tokens before signaling and name the process

Darwin KERN_PROCARGS2 samples a process's argument length and stack top
before it reads the address space, and exec publishes the new length
before it copies the new strings out (xnu sysctl_procargsx,
exec_copyout_strings). A read during exec can return a zero-filled or
stale strings area, and exec keeps the PID and start time that bracket
the read. The final sweep already re-read such tokens, but the
pre-signal group check read each member's token once, so one transient
read of a live group member failed the whole cleanup.

Move the bounded re-read into one shared fact-reading helper and use it
for both the sweep and the pre-signal group check. The group check binds
re-reads to the generation it first observed, so a reused PID stays
unresolved; the sweep keeps classifying the PID's current process.

An unreadable-token failure now carries the native identity read after
the token and the summary names the candidate by its native name,
parent, group and start identity. The Darwin helper and Linux procfs
reader report the short native process name (p_comm/comm) for display.

Fixes #8337

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(process): refresh other pre-signal members after token re-read waits

The pre-signal group check re-read only members whose token was
unavailable, so a readable member kept the relation it had before the
retry waits. A member that moved to another process group during those
waits could be validated on its old group, and the old group signaled
while the moved member kept running.

After any retry wait, the shared re-read helper now reads every other
live pre-signal fact once more with the same generation binding. A moved
member then takes the existing changed-group path, which retains its
ownership evidence and fails cleanup. An inconclusive refresh replaces
the stale fact so it fails closed. Nothing changes when no re-read ran,
and the sweep keeps classifying current processes because every group
it finds is revalidated before signaling.

Also cover PID reuse that happens before the re-read starts, where both
re-read identities agree and only the first-read generation rejects the
replacement's token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(process): keep known identity changes final across token re-reads

The pre-signal re-read treated a first read without a same-generation
identity as unbound and replaced it with the re-read. On Linux the first
read can already establish PID reuse (an ESRCH token whose exit check sees
another generation); the re-read then classified the replacement, so a
zombie replacement could let cleanup succeed.

A pre-signal check now re-reads only same-generation facts. Changed,
exited, exiting and foreign-token facts are final. Each attempt also
re-reads the group's owned members instead of one separate refresh after
the loop, so a member that moves groups or turns unreadable while another
waits is seen within the same bound. The caller's run token selects the
owned members, and the sweep keeps classifying current processes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 00:21:23 -08:00
Kaoru0822andClaude Opus 5.5 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>
2026-11-01 08:53:29 -08:00
morluto 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
2026-11-01 23:53:56 +08:00
Kaoru0822andClaude Opus 5.5 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>
2026-10-31 08:59:00 -07:00
Kaoru0822andClaude Opus 5.5 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>
2026-10-31 08:53:11 -07:00
morluto 23de10bb28 fix: streamline tests and preserve Darwin process ownership (#8275)
* test: strengthen suite guards and regression oracles

* test: share JSON client registration contract

* test: reuse fixtures and reduce repeated setup

* fix(process): preserve ambiguous Darwin token ownership

* test(process): bound child readiness waits
2026-10-31 16:43:04 +08:00
Entrpi 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
2026-10-31 15:48:46 +08:00
gensokyo-devandhhang 0ffed7a48c feat(android): trace callers of external DEX methods (#8154)
Resolve exact external method targets from directly encoded DEX invokes.
Preserve complete caller identity, bounded position evidence and follow-up
selectors. Report aggregate position coverage independently of the caller
inventory, and reuse bounded prototype facts within the exact session.

Absorbs #8096. Fixes #7811.

Co-authored-by: hhang <169027046+xu91102@users.noreply.github.com>
2026-10-31 01:07:18 +08:00
morlutoandCursor Agent ec4a0a01c4 fix(hopper): reconcile observed caller relationships (#7953)
* fix(hopper): reconcile observed caller relationships

* fix(hopper): retain completed caller scans on failure

Attach the native reply and collected forward facts when reconciliation
fails or is cancelled, and check scan stop codes separately from their
wording. Live observations keep REA evidence ids rather than provider
supplied ones, and the real Hopper verifier uses advertised MCP schemas.

* fix(hopper): answer caller-scan methods in the package fixture

The packaged Hopper stand-in echoed unknown bridge methods, so
analyze_function rejected rea_caller_scan_target as an invalid scan
target and the native package baseline returned unreadable_output.

* fix(hopper): share caller identities in failed scan observations

Failure partials repeated each caller identity under every destination.
The page budget counted compact replies, then schema parsing copied the
expanded form. Identities are stored once and destinations cite addresses.

* refactor(config): own the Hopper caller-scan budget default

The environment schema hard-coded the 2000 ms scan default. The domain
limit owner now names that millisecond budget and the schema reuses it.

* test(mcp): assert bundle path issues by field

compare_bundles reports each relative path as an invalid_format issue
instead of one joined diagnostic sentence.

* test(flutter): assert ABI selector refusals as structured issues

inspect_dart_aot reports the ABI label as an issue on path abi. The
message is the selector contract, without an abi: prefix.

* fix(session): retain caller observations that cannot be replayed

A missing document selector blocks snapshot replay. Backward call-graph
and trace reads still keep the native result and forward observations,
and the workflow Evidence links those records.

* fix(session): keep decompile bodies out of the in-memory ledger

Caller and callee walks still stay in Evidence without a document.
procedure_pseudo_code does not, so decompile_all leaves each body in the
file-backed export instead of retaining the whole export in memory.

* fix(hopper): own caller-scan recovery and the page byte allowance

Scan facts stay in the domain. Environment recovery, including the time
budget bounds and the fixed allowances with no runtime override, is
appended from configuration. Setup forwards the budget, and the bridge
uses one byte allowance for instructions, native callers, and pages.

* fix(hopper): retain compact caller references within the scan budget

Recovered call sites stay in the address form the scan already counted.
Expanded identity copies are measured before allocation and refused when
they exceed the retention budget. Instruction lists are not part of the
retained reply.

* fix(session): omit instruction payloads from retained caller evidence

Documentless caller and callee reads stay in the ledger for the session.
Their evidence keeps call sites and drops instruction lists the scan
already consumed.

* fix(hopper): keep the owning caller address on each compact call site

A page reference marked source_procedure "caller" belongs to that page
item's caller. Saved sites record that address, and an owner missing from
the callee inventory is stored once instead of copied onto every site.

* fix(session): leave Hopper reply shaping to the Hopper adapter

Documentless caller evidence stores the adapter's raw result unchanged.
The session no longer reads native_result.instructions.

* test(hopper): throw typed scan failures before reading results

Successful caller-scan results now throw the typed error instead of
returning after an ok check. Expected failures assert structured tags,
stop codes, and reported limits.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-10-29 22:54:58 +08:00
morluto bd687bbc40 fix(ghidra)!: distinguish unlisted instruction addresses (#7823)
* fix(ghidra)!: distinguish unlisted instruction addresses

BREAKING CHANGE: Ghidra now returns not-in-listing for in-memory addresses without listed instructions or defined data. Consumers matching the former undecodable value must handle the new status.

* fix(ghidra): invalidate snapshots with old instruction status

* test(ghidra): update raw profile commitment goldens
2026-10-29 04:59:04 +08:00
morluto af1ccb6506 fix(android): preserve manifest component spelling (#7818) 2026-10-29 01:10:45 +08:00
gensokyo-dev 570abe95f2 feat(android): link native declarations to static JNI candidates (#7472)
Link original DEX native declarations to per-ABI function exports and relocated static JNI table candidates through shared CLI/MCP workflows. Preserve global attribution ambiguity, exact provenance, partial coverage and retained Evidence; default MCP delivery to bounded summaries with filtered/batch pages.

Use one immutable ELF relocation decoder with streaming IL2CPP materialization, cooperative bounded export/version parsing and bounded JNI state. Reuse validated session inventories without loading target libraries or executing JNI code.

Validation: relevant type/lint/build and parser/domain/public CLI/MCP regressions; genuine four-ABI NDK fixtures and independent library/slot oracles; actual JDK/JADX Conscrypt workflows with retained-source removal. Full measurements and limitations are recorded in docs/verification/android-jni-bindings-2026-10-27.md.

Closes #6403.
2026-10-27 18:53:22 +08:00
gensokyo-devand555aaditya 03f17cf41d feat(android): apply caller-selected R8 mapping evidence (#7456)
Apply caller-selected R8/ProGuard mappings to shared Android inspections, preserving raw identities, exact verification, ambiguity and provenance. Add retained summaries and bounded/cached parsing, with measured real R8/Conscrypt workflows and review fixes.

Fixes #6329.

Co-authored-by: 555aaditya <107977627+555aaditya@users.noreply.github.com>
2026-10-27 15:47:08 +08:00
morluto 0d1d6e858d fix(ghidra): unify Unicode literal search semantics 2026-10-27 11:10:10 +08:00
morluto ad92e0f9c8 refactor(ghidra): consolidate function containment lookup 2026-10-27 08:46:27 +08:00
19447516a4 feat(ghidra): reuse existing projects through verified copies (#7236)
Reuse selected Ghidra projects through verified private read-only copies, with shared CLI/MCP configuration, committed project identity, import-SHA verification and explicit historical/unknown analysis semantics. Preserve exact cancellation and platform capability boundaries.

Actual Ghidra 12.1.4/JDK21 Linux CLI/MCP investigations matched fresh import on 652-function ls and 14,338-function libcrypto inventories and pseudocode; authenticated complete Evidence, mismatch/staleness refusal, saved historical reports and shared /tmp projects verified. 958 focused tests passed with four platform skips; build/static/docs/format passed. Real macOS/Windows reuse remains unverified; Windows reuse is unavailable. See PR verification for measured whole-task costs and final CI attribution.

Co-authored-by: akushonkamen <akushonkamen@163.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-26 22:31:13 +08:00
2c38becc4e feat(binary-layout): admit ELF32 i386, ARM and MIPS layout profiles (#7052)
* feat(binary-layout): admit ELF32 i386, ARM and MIPS layout profiles

inspect_binary_layout refused every ELF32 object, so router and IoT
firmware (ARM32, MIPS32) got no layout facts at all.

The pwntools adapter now admits EXEC/DYN/REL objects in these profiles:
ELF64 x86-64, ELF32 i386, ELF32 little-endian ARM and ELF32 little- or
big-endian MIPS. Header fields are read in the declared byte order, the
ELF32 header is bounds-checked at 52 bytes, and pwntools' own reported
architecture, class and byte order must match the admitted profile.
Other machines, classes and byte orders keep an unsupported_target
refusal that names the admitted profiles.

The output schema admits exactly those architecture combinations, and
the Evidence subject now names the reported machine instead of always
claiming x86_64.

verify:binary:layout cross-compiles i386, ARM, MIPS and MIPSel
executables and relocatable objects (never executed) and checks every
section name, address, offset and size against GNU readelf through CLI
and MCP. The real-binary-layout workflow installs those toolchains.

Refs #6934

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci(binary-layout): install target libc headers for ELF32 fixtures

--no-install-recommends skips the libc6-dev-*-cross packages the cross
compilers only recommend, so the i686 fixture fell back to the host's
/usr/include and failed to find bits/libc-header-start.h. Install the
four target libc development packages explicitly.

Refs #6934

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(binary-layout): size the minimum symbol entry by ELF class

The relocation reference check required a 24-byte Elf64_Sym entry, so
every positive symbol reference in an ELF32 report was refused as
unreadable output. Elf32_Sym is 16 bytes; take the minimum from the
reported class. A 64-bit table with 16-byte entries is still refused.

Refs #6934

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(binary-layout): compare ELF32 symbols and relocations with readelf

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-25 14:18:44 +08:00
morluto f3ed1657f8 feat(mcp): support runtime analysis limit recovery (#7049)
* feat(mcp): support runtime analysis limit recovery

* refactor(config): remove unused limit re-exports

* fix(android): keep fixture release metadata dependency-free

* fix(settings): preserve provider budgets and recovery facts

* fix(tests): resolve lint plugins from their repository owner

* refactor(mcp): verify guidance delivery without frozen wording

* fix(android): align availability with runtime timeout

* test(recovery): assert limit facts instead of frozen wording

* fix(mcp): share runtime settings with the default JADX provider

* test(mcp): bound acknowledgements and release held work on failure

* fix(catalog): declare runtime settings tools as MCP-only
2026-10-25 09:45:26 +08:00
Abel YagubyanandAbelo9996 955c7c80ec fix(android): report DEX static values of static final fields (#6981)
* fix(android): report DEX static values of static final fields

Fixes #6397

* fix(android): request DEX static values only for class inspection

* fix(android): range-check wide DEX static values

* fix(android): move the bridge to version 7 after main took 6

---------

Co-authored-by: Abelo9996 <Abelo9996@users.noreply.github.com>
2026-10-25 02:17:13 +08:00
Ariel Fikru Avicennaandgensokyo-dev cab78de506 feat(ghidra): analyze GameCube/Wii DOL executables through Ghidra (#6240)
* feat(domain): parse and validate GameCube/Wii DOL headers

Add a pure parser for the 0x100-byte DOL header (7 text and 11 data
slots, BSS, entry point). Used slots must lie after the header and
inside the file and the 0x80000000..0x81800000 load window; text slots
are 4-byte aligned; sections may not overlap in memory or in the file;
the entry point must be inside a text section. BSS may overlap data
sections, as .sdata/.sdata2 do in shipped DOLs.

Refs #1741

* feat(binary): admit caller-selected GameCube/Wii DOL targets

* feat(ghidra): import GameCube/Wii DOL targets through a section-map pre-script

* test(ghidra): cover DOL launcher arguments, attestation and raw profile digests

* test(ghidra): add the real verify:ghidra:dol lane and DOL docs

* fix(ghidra): read only the DOL header and section ranges instead of the whole file

* test(ghidra): derive DOL lane addresses from readelf and admit Gekko from the install catalog

* fix(ghidra): attest DOL block permissions, space, overlay and load state

* fix(ghidra): keep load-image permissions optional for older inspections

* fix(contracts): accept DOL targets in binary_session output

* fix(ghidra): adapt the DOL lane to the current upstream address schema

Validate DOL load-image coordinates with the upstream observed-address
schema, drop a duplicate import left by the rebase, and re-pin the raw
profile digests to the unmodified upstream resolver.

* fix(ghidra): preserve bridge inventory symbol provenance

* fix(ghidra): align DOL verification with shared workflow contracts

* feat(domain): parse and validate GameCube/Wii DOL headers

Add a pure parser for the 0x100-byte DOL header (7 text and 11 data
slots, BSS, entry point). Used slots must lie after the header and
inside the file and the 0x80000000..0x81800000 load window; text slots
are 4-byte aligned; sections may not overlap in memory or in the file;
the entry point must be inside a text section. BSS may overlap data
sections, as .sdata/.sdata2 do in shipped DOLs.

Refs #1741

* feat(binary): admit caller-selected GameCube/Wii DOL targets

* feat(ghidra): import GameCube/Wii DOL targets through a section-map pre-script

* test(ghidra): cover DOL launcher arguments, attestation and raw profile digests

* test(ghidra): add the real verify:ghidra:dol lane and DOL docs

* fix(ghidra): read only the DOL header and section ranges instead of the whole file

* test(ghidra): derive DOL lane addresses from readelf and admit Gekko from the install catalog

* fix(ghidra): attest DOL block permissions, space, overlay and load state

* fix(ghidra): keep load-image permissions optional for older inspections

* fix(contracts): accept DOL targets in binary_session output

* fix(ghidra): adapt the DOL lane to the current upstream address schema

Validate DOL load-image coordinates with the upstream observed-address
schema, drop a duplicate import left by the rebase, and re-pin the raw
profile digests to the unmodified upstream resolver.

* docs(ghidra): qualify the DOL memory window

* refactor(ghidra): own DOL BSS ranges in the parsed header

* docs(ghidra): record real DOL workflows and task costs

* docs(ghidra): record final DOL integration verification

* fix(mcp): share the native procedure search row contract

* docs(ghidra): record public procedure search verification

---------

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-24 17:56:31 +08:00
morluto 43c7255dbd fix(android): preserve binary class selectors across metadata calls 2026-10-24 17:21:08 +08:00
Syed Rishadandgensokyo-dev a062529bb2 feat(ghidra): bound one procedure's decompile without closing the session (#5662)
* feat(ghidra): bound one procedure's decompile without closing the session

Fixes #5340

* fix(ghidra): report decompile limit as a request timeout

Keeps BinarySession from marking every Ghidra operation unavailable after one procedure's decompile reaches the limit, and names the MCP tool-call deadline in the remediation.

* fix(ghidra): budget the decompile limit and report cancellation-closed sessions

Adds REA_GHIDRA_DECOMPILE_TIMEOUT_SECONDS to the derived Codex/Kimi tool deadline and forwards it through setup. Marks a remote failure that settles after caller cancellation so the timeout projection no longer promises session reuse.

* fix(ghidra): align deadline bounds and cancellation outcomes

* refactor(ghidra): shorten deadline recovery guidance

* fix(mcp): clarify the scope of inferred decompile deadlines

* test(ghidra): verify deadline workflows and document measured costs

Separate failure and registration cases by their distinct contracts.
Record actual Linux Ghidra, CLI and MCP evidence with measured context,
elapsed time, CPU and memory, and explicit remaining coverage limits.

* docs(ghidra): pin integration and distinguish baseline format failures

* fix(ghidra): own failure lifecycle wording in the provider

* test(ghidra): budget timeout fixture generation before allocation

* fix(ghidra): align capability and traversal deadline guidance

* style(config): align deadline guidance formatting

* docs(ghidra): record capability and traversal verification

---------

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-24 07:42:50 +08:00
morluto a51a9228be fix(native): retain unknown UI executable identity 2026-10-24 04:38:08 +08:00
morluto cc90771af1 fix(native)!: preserve UI scalar facts and selection failures
BREAKING CHANGE: Accessibility node value can also be a JSON number or boolean. Strings and null retain their prior meaning.
2026-10-24 04:25:13 +08:00
morluto 62f7b5e4cd fix(native): require observed symbol origin for named identity 2026-10-24 04:14:17 +08:00
morluto a2d0af6023 fix(native): report absent launch process before cleanup classification 2026-10-24 04:06:57 +08:00