mirror of
https://github.com/morluto/rea.git
synced 2026-11-11 17:28:08 +00:00
bf671f20a2e4dcec087b1b2a5ac0f77dd3e0be21
512
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
01a7e2c3b7 |
feat(ntfs): expose the journal timeline through CLI and MCP
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com> |
||
|
|
a18867e623 | fix(mcp): retain artifact comparisons after terminal cancellation (#9945) | ||
|
|
c1d0f2bb45 | fix(environment): retain response cleanup through shutdown | ||
|
|
b4c8799123 | test: verify deadline settlement and retire cleanup fixtures | ||
|
|
a4da4e7230 |
docs(mcp): clarify tool selection and recovery guidance (#9817)
* docs(mcp): clarify tool selection and recovery guidance * test(mcp): prune wording assertions and preserve scope checks |
||
|
|
d2f9b8b7de |
feat(desktop): build several tasks from one capture, and measure each task's pass rate within a budget (#9216)
* docs(desktop): clarify gzip scrub limits * fix(setup): own desktop build process cleanup * fix(doctor): compare desktop settings with resolved defaults * fix(desktop): refuse a build runtime whose export takes no task ends Several tasks pass --task-end to the build computer's export, so a runtime packed before it now fails at the start of the capture with the repack fix, as a runtime without synthetic seeds already did, rather than at export. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style(desktop): format the noisy-record draft files with the pinned oxfmt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(desktop): give the root-array draft test its own describe The records describe grew past the 150-line lint limit with it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(doctor): inspect client-recorded desktop runners * fix(doctor): reuse matching runner probes * fix(setup): propagate cancellation to desktop actions * fix(desktop): rewrite a download's launch keys written with spaces around = The desktop entry parser accepts `Exec = notes %F` and an indented `TryExec =notes`, so the install script now matches those keys the same way instead of leaving the original program in place. Adds the feature's tasks.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep why a measured run failed in its solve record A solve that returned an outcome dropped the runner's error, so a run that failed to deploy, solve or verify was retried with no reason recorded. The record, the measure result and difficulty.json now carry it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(setup): stop Hopper on cancel, never report a cancelled setup ready, and keep a failed action's client setting - The Hopper install gets setup's signal: Linux already honoured it, and the macOS installer now stops its downloads and stops before mounting or copying. - runSetup checks the signal after the final doctor and close, so a cancellation there raises instead of returning ready. - A failed pack or agentenv install no longer writes its archive or runner to client configs, so the setting the client already had stays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(setup): keep the completed setup result in a cancellation after cleanup A cancellation during the final doctor or host close carried only the applied actions, dropping each client's result and backup path and the doctor report. It now carries the whole result as setup_result, as doctor's cancellation carries its report. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(desktop): move launch execution to boundary suite * fix(desktop): redact build schema failure output * refactor(desktop): normalize schema failure once * fix(desktop): omit unsafe schema parser snippets * fix(desktop): preserve draft change and selected path evidence * test(desktop): group retained dconf note regressions * fix(desktop): respect archive entry format in draft checks * test(desktop): separate unowned-file draft note cases * fix(desktop): preserve explicitly selected journal documents * fix(xml): avoid scanning selected ancestors per tag * fix(desktop): exclude covered text runs from draft counts * fix: preserve text when drafting desktop checks * fix: restore nested desktop state aliases * refactor: share UUID recognition across draft checks * fix: retain multiline XML attribute context * fix: retain relationship identifiers in task drafts * docs: clarify desktop draft identifier handling * test(desktop): type formatting run cases as pairs * fix(desktop): carry document format into selector evaluation * test(desktop): separate markup boundary regression group * fix(desktop): propagate formats through draft selectors * fix(desktop): switch selector format within archive entries * test(desktop): remove duplicate seed filename case * fix(setup): retain diagnostics when cancellation overlaps failure * refactor(setup): keep command cancellation at its owner * test(setup): verify cancellation at the application boundary * test(desktop): pass JSON format in exported index parity * docs(desktop): clarify task checks before scratch export * fix(desktop): respell selected paths in file URLs * test(desktop): group captured document spelling cases * test(desktop): run installer scripts at boundary * style(desktop): remove trailing blank line * fix(desktop): bound draft preview serialization * fix(desktop): restore selected state aliases * fix(desktop): respect entry format in draft noise * test(desktop): match exported alias evidence at its JSON boundary * fix(desktop): retain app state logs in exported seeds * fix: align desktop numeric seed comparisons * test(desktop): keep one draft exclusion fixture import * test(desktop): retain log eligibility across draft test groups * fix(doctor): resolve empty registered desktop runner * style: fix desktop launch test formatting * style: format native command path schema * fix(desktop): map selected external launch paths * style(desktop): format seed document regressions * test(desktop): group launch URL regressions * fix(desktop): omit redundant nested state aliases * fix(desktop): compare added free text as a whole * fix(desktop): check recompressed seeds as shipped * docs(desktop): clarify recovered seed format * test(desktop): group shipped gzip seed checks * fix: retain quoted identifier text in task drafts * fix: recognize Unicode XML in desktop state readers * fix(desktop): bound nested draft checks * fix(desktop): explain missing arrays in truncated views * fix(desktop): find XML type references in archives * test(desktop): remove duplicated capture assertions * fix(desktop): retain nested omitted text boundaries * style(desktop): format draft value imports * test(desktop): group model and draft value checks * fix(desktop): map captured launch paths once * refactor: remove unused whole-text guard state * refactor: stop passing unused text children * test: align free-text checks with whole-note policy * fix: validate recompressed desktop archive seeds * style(desktop): format archive seed regression * fix(desktop): retain placed-item sibling guards * fix(desktop): preserve archive paths and bound doctor reads * fix(doctor): refuse non-files before descriptor admission * fix(setup): track remaining cleanup resources across retries * test(desktop): specify XML format in heap pairing fixture * fix(setup): skip Hopper launch after cancelled copy * fix: preserve task measurement limits and cleanup * fix(desktop): retain reported solve sandbox cleanup * test(desktop): check retained log seed admission * fix(doctor): query agentenv for model endpoint * fix(doctor): preserve uncertainty for empty endpoint override * fix(desktop): redact runtime schema errors * fix(desktop): normalize captured file URLs * fix(desktop): report seeded files by capture path * fix(desktop): retain startup readiness failure stage * fix(desktop): retain JSON date checks * fix(desktop): preserve archive formatting checks * fix(desktop): preserve explicitly selected journal files * fix(desktop): report build command transport limits * docs(desktop): clarify unreadable dconf versions * test(desktop): remove duplicate history regression * fix(desktop): align XML names with exported reader * fix(desktop): create selected state alias targets * fix(desktop): inspect supported runtime archives * fix(desktop): keep ordinary text checks exact * fix(desktop): verify registered build host paths * fix(desktop): retain record identity in draft checks * test(desktop): preserve text reference numbers * fix(desktop): bound download install input reads * fix(desktop): match placed notes by whole text * test(desktop): match multiple task export results * fix(desktop): retain failed measurement file closes * fix(setup): retain completed actions on cancellation * test(setup): retain cancelled installer result * fix(desktop): scrub XML independently of reader compatibility * fix(desktop): preserve file aliases and reader diagnostics * style(desktop): format review fixes * fix(desktop): inspect archives with registered runner * test(desktop): verify registered archive interpreter * style(desktop): format capture review fixes * style(desktop): format review changes * feat(desktop): target agentenv-framework 0.9.1464 Desktop bundles, setup's --install-agentenv and the doctor's exact-version check now target 0.9.1464, which keeps an exported app's data/get call, holds the computer fixture above boot dialogs, leaves an unresolved setting's build unverified rather than failed, and mounts lock packages instead of copying them into the image. The web environment lane stays on 0.9.1431. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): retain per-solve sandbox cleanup roots * test(desktop): expect the solve cleanup helper among the shipped agentenv helpers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(desktop): clean up a stopped solve's sandboxes through agentenv 0.9.1482 agentenv-framework 0.9.1482 lists the local sandboxes under a root (local_sandbox_ids) and rebuilds one killed while it wrote its port map for teardown. The solve cleanup helper now terminates each sandbox agentenv lists, keeping its Docker and host-process checks, and reports anything else left under the root. Desktop bundles, setup's --install-agentenv and the doctor's version check target 0.9.1482. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): verify a killed solve's cleanup once its sandbox root is empty A solve's sandboxes are all local under its private root, and agentenv now keeps a sandbox's folder until its teardown is confirmed. So when the helper ends without a report and REA's cleanup empties that root, the cleanup is verified: a cancelled solve ends as a cancellation and a solve past its deadline as a failed run, rather than as cleanup the measure cannot vouch for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(desktop): target agentenv-framework 0.9.1485 0.9.1485 keeps a local sandbox's folder until its teardown is confirmed, which the solve cleanup's verified result relies on. (0.9.1484 failed to publish.) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): record a solve stopped before it reports as failed, not as a refused request A helper killed from outside or stopped at its deadline left no report, so the measure refused with invalid input and told the caller to fix its model endpoint. A helper a signal ended now gives a failed solve of unknown cost, which the measure records and stops on; one that exits on its own without a report still ends the measure as a solve that could not run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): check verifier behavior after selector changes * test(windows): verify rejected writes during cleanup by effect * fix(desktop): preserve selected alias target kinds in exports * fix(cli): retain caller capture paths in environment builds * fix(ghidra): classify oversized endpoint records consistently * test: align model and Evidence expectations with current contracts * fix(desktop): reconcile upstream sandbox cleanup recovery * fix(docs): link cleanup qualification as repository evidence --------- Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
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 |
||
|
|
387bcb795d |
feat(desktop): isolate declared secrets during app builds (#9225)
* fix(desktop): preserve local file URL authority * fix(desktop): preserve local file URL authority * fix(desktop): preserve local file URL authority * fix(desktop): render captured file URLs at launch * fix(desktop): classify numeric timestamps using field context * fix(desktop): classify numeric timestamps using field context * fix(desktop): classify numeric timestamps using field context * fix(desktop): retain context for generated draft values * fix(desktop): retain context for generated draft values * fix(desktop): retain context for generated draft values * test(desktop): cover generated IDs in text guards * test(desktop): cover generated IDs in text guards * test(desktop): cover generated IDs in text guards * fix(desktop): isolate launcher URL encoding * fix(desktop): isolate launcher URL encoding * fix(desktop): isolate launcher URL encoding * fix(desktop): isolate launcher URL encoding * fix(desktop): bound private key redaction spans * fix(desktop): retain published bundle on copy failure * fix(desktop): retain secret file cleanup owners * fix(desktop): retain both published output cleanup owners * test(desktop): verify UTF-16 credential refusal * test(desktop): verify truncated secret redaction over MCP * fix(desktop): retain clean text in noisy record fields * fix(desktop): classify added line values in one pass * fix(desktop): scan private key runs in one pass * fix(desktop): apply XML quote rules to text drafts * fix(desktop): distinguish XML attributes from quoted text * fix(desktop): preserve parsed XML line context * Format appTaskChecks.ts with the pinned oxfmt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): retain partial XML syntax facts * fix(desktop): recognize markdown autolinks in drafts * fix(desktop): reuse export exclusions in task drafts * fix(desktop): report unchecked client build paths * docs(desktop): clarify gzip scrub limits * test(desktop): build the fixture JWT from its parts and reformat The literal token made every edit of this file trip secret scanners; the test checks the same string. Also applies the pinned oxfmt to the key-run test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): reuse export exclusions in task drafts * docs(desktop): clarify gzip scrub limits * fix(setup): own desktop build process cleanup * fix(desktop): find no private key in NSS's key4.db password check An Electron app's NSS key database holds a password-check value shaped like an encrypted private key, so every such export was refused. An encrypted key now counts only under a password-based encryption scheme, never PBKDF2 or PBMAC1, and with at least the 48 bytes of encrypted data the smallest key needs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(doctor): compare desktop settings with resolved defaults * style(desktop): format the noisy-record draft files with the pinned oxfmt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(desktop): give the root-array draft test its own describe The records describe grew past the 150-line lint limit with it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(doctor): inspect client-recorded desktop runners * fix(doctor): reuse matching runner probes * fix(setup): propagate cancellation to desktop actions * fix(setup): stop Hopper on cancel, never report a cancelled setup ready, and keep a failed action's client setting - The Hopper install gets setup's signal: Linux already honoured it, and the macOS installer now stops its downloads and stops before mounting or copying. - runSetup checks the signal after the final doctor and close, so a cancellation there raises instead of returning ready. - A failed pack or agentenv install no longer writes its archive or runner to client configs, so the setting the client already had stays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): close five withheld-state gaps a review found - A sign-in window whose walk hit its entry limit, could not read a path or left a change unconfirmed is refused, rather than trusted as complete. - The export refuses app dconf keys the sign-in window changed and the seed would ship with a different value, naming the keys, not their values. - A bundle holding a gzip file that expands past what REA scans is refused. - Withheld bytes are kept under a handle of their own, created exclusively and never replaced; a later build's different bytes take the next free handle, and a handle the computer's answer names is checked before any write. - Setting names a Python keyword or a leading digit would break get file_, and names that collide get _2, _3 in a stable order. - Adds the feature's tasks.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): redact a cut secret's start only at REA's own cuts The boundary match for a secret cut short hid the start of any ellipsis-ended text, so "Please…" became a redaction. It now applies only where text ends one of REA's value cuts, whose lengths the producers and the redactor share, and the host redacts the app's stderr and progress before it quotes their end. Redacting before anything cuts stays a follow-up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(setup): keep the completed setup result in a cancellation after cleanup A cancellation during the final doctor or host close carried only the applied actions, dropping each client's result and backup path and the doctor report. It now carries the whole result as setup_result, as doctor's cancellation carries its report. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): publish secret files atomically, decompress a gzip seed once, and scan JSON strings linearly - A secret file is written under a private temporary name and linked to its handle, so a concurrent export never reads a half-written file and reuses its handle for other bytes. - The export decompresses each gzip seed file once and shares the result with the secret scan, the credential scan and the size refusal. - The cut-secret stopgap finds JSON string literals in one forward pass instead of restarting at every quote. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(desktop): move launch execution to boundary suite * fix(desktop): redact build schema failure output * refactor(desktop): normalize schema failure once * fix(desktop): omit unsafe schema parser snippets * fix(desktop): preserve draft change and selected path evidence * test(desktop): group retained dconf note regressions * fix(desktop): respect archive entry format in draft checks * test(desktop): separate unowned-file draft note cases * fix(desktop): preserve explicitly selected journal documents * fix(xml): avoid scanning selected ancestors per tag * fix(desktop): exclude covered text runs from draft counts * fix: preserve text when drafting desktop checks * fix: restore nested desktop state aliases * refactor: share UUID recognition across draft checks * fix: retain multiline XML attribute context * fix: retain relationship identifiers in task drafts * docs: clarify desktop draft identifier handling * test(desktop): type formatting run cases as pairs * fix(desktop): carry document format into selector evaluation * test(desktop): separate markup boundary regression group * fix(desktop): propagate formats through draft selectors * fix(desktop): switch selector format within archive entries * test(desktop): remove duplicate seed filename case * fix(setup): retain diagnostics when cancellation overlaps failure * refactor(setup): keep command cancellation at its owner * test(setup): verify cancellation at the application boundary * test(desktop): pass JSON format in exported index parity * docs(desktop): clarify task checks before scratch export * fix(desktop): respell selected paths in file URLs * test(desktop): group captured document spelling cases * fix(desktop): retain temporary secret file cleanup * fix(desktop): preserve unmarked token-shaped values * fix(desktop): withhold drafts after secret use * fix(desktop): guard drafts against shared secret changes * test(desktop): compare preserved seed bytes without enumeration * fix(desktop): bound draft preview serialization * fix(desktop): restore selected state aliases * fix(desktop): respect entry format in draft noise * test(desktop): match exported alias evidence at its JSON boundary * fix(desktop): retain app state logs in exported seeds * fix: align desktop numeric seed comparisons * test(desktop): keep one draft exclusion fixture import * test(desktop): retain log eligibility across draft test groups * fix(doctor): resolve empty registered desktop runner * style: fix desktop launch test formatting * style: format native command path schema * fix(desktop): map selected external launch paths * style(desktop): format seed document regressions * test(desktop): group launch URL regressions * fix(desktop): omit redundant nested state aliases * fix(desktop): compare added free text as a whole * fix(desktop): check recompressed seeds as shipped * docs(desktop): clarify recovered seed format * test(desktop): group shipped gzip seed checks * fix: retain quoted identifier text in task drafts * fix: recognize Unicode XML in desktop state readers * fix(desktop): bound nested draft checks * fix(desktop): explain missing arrays in truncated views * fix(desktop): find XML type references in archives * test(desktop): remove duplicated capture assertions * fix(desktop): retain nested omitted text boundaries * style(desktop): format draft value imports * test(desktop): group model and draft value checks * fix(desktop): map captured launch paths once * refactor: remove unused whole-text guard state * refactor: stop passing unused text children * test: align free-text checks with whole-note policy * fix: validate recompressed desktop archive seeds * style(desktop): format archive seed regression * fix(desktop): retain placed-item sibling guards * fix(desktop): preserve archive paths and bound doctor reads * fix(doctor): refuse non-files before descriptor admission * fix(setup): track remaining cleanup resources across retries * test(desktop): specify XML format in heap pairing fixture * fix(doctor): query agentenv for model endpoint * fix(doctor): preserve uncertainty for empty endpoint override * fix(desktop): protect host controls and quote withheld paths * fix: redact declared form-encoded secrets * fix(desktop): redact runtime schema errors * fix(desktop): normalize captured file URLs * fix(desktop): report seeded files by capture path * fix(desktop): retain startup readiness failure stage * fix(desktop): retain JSON date checks * fix(desktop): preserve archive formatting checks * fix(desktop): preserve explicitly selected journal files * fix(desktop): report build command transport limits * docs(desktop): clarify unreadable dconf versions * test(desktop): remove duplicate history regression * fix(desktop): align XML names with exported reader * fix(desktop): create selected state alias targets * fix(desktop): inspect supported runtime archives * fix(desktop): retain record identity in draft checks * fix(desktop): refuse unchecked declared secrets * fix(desktop): retain partial withheld export receipts * fix(desktop): detect escaped secrets in JSON state * fix(desktop): scrub XML independently of reader compatibility * fix(desktop): preserve file aliases and reader diagnostics * fix(desktop): scan escaped secrets in UTF-16 JSON * style(desktop): format secret scan changes * style(desktop): format review fixes * style(desktop): format capture review fixes * style(desktop): format review changes --------- Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
8bc01b48b4 |
feat(native): list ELF and Mach-O initializer and finalizer functions (#9574)
* feat(native): list ELF and Mach-O initializer and finalizer functions inspect_native_initializers and inspect-native-initializers list the functions an ELF or Mach-O image runs before and after main: ELF DT_INIT, DT_FINI, preinit, init and fini arrays and .ctors/.dtors, and Mach-O __mod_init_func, __mod_term_func and __init_offsets, with slot addresses, resolved targets, symbols where available and relocation facts for relocatable objects. Nothing is executed. Slot, symbol, relocation and note budgets are shared across tables, sentinels are matched at the image width, and target-derived names are bounded and marked untrusted. * fix(native): keep ELF initializer slots unresolved when relocation coverage is partial A skipped, unreadable or over-budget section relocation table now keeps every slot it could reach unresolved instead of reading the stored word as raw or dropping a .ctors slot as a sentinel. Dynamic writes that only partly overlap a slot, or write it twice, leave it unresolved. Linked images no longer reapply retained non-SHF_ALLOC link-time records. The dynamic relocation walk now pauses at the shared reader's step boundaries and observes cancellation there, resolved targets need only their first byte mapped, and unreadable symbol names make the report incomplete. * fix(native): stop reporting unchecked Mach-O initializer words as resolved Object files now apply their own section relocations: an UNSIGNED entry against a defined symbol gives symbol_addend, one against an undefined symbol gives unresolved_import, and any other entry leaves the slot unresolved. Linked images without a fixup decoder, such as 32-bit ones, keep pointer slots unresolved when an LC_DYLD_INFO bind stream or LC_DYSYMTAB external relocations could replace the stored word. LC_DYLD_INFO rebases now report dyld_info_rebase instead of chained_fixup, and unreadable symbol names make the report incomplete. Section headers keep their declared reloff and nreloc for this. * docs(native): move initializer guide under docs/guides/native The documentation guide assigns analyst workflows to docs/guides/<domain>/. Move the guide there, place its navigation and directory entries in the Native binaries group, and update links from the docs index, CLI guide, spec and authored skill. The public /native-initializers route is unchanged. The guide and spec also describe per-slot relocation coverage, retained link-time records, Mach-O object relocations, undecoded bind streams, the dyld_info_rebase resolution and unreadable names. * fix(native): keep IFUNC and partly relocated ELF initializer slots unresolved An absolute relocation against an STT_GNU_IFUNC symbol no longer reports the resolver address as the target. Section relocation records now use their real write width, so a record that writes only part of a slot, starts inside it or repeats it leaves the slot unresolved instead of reading a raw zero or dropping a .ctors slot as a sentinel. On 32-bit ARM the Thumb bit is cleared when locating a target's section and file offset, while value_va keeps the stored callable value. * fix(native): locate Thumb Mach-O initializer targets and reject arm64_32 with a 64-bit header On CPU_TYPE_ARM the Thumb bit is cleared when locating and naming a target, since nlist values do not carry it. An arm64_32 image that declares a 64-bit header is rejected as malformed rather than read with 8-byte slots. The guide and spec describe IFUNC relocations, partly relocated section slots, Thumb targets and this rejection. * fix(native): index initializer address lookups and keep ambiguous mappings unknown ELF and Mach-O initializer lookups now build the shared file mapping index once per image, so each slot and target lookup is logarithmic in the number of load segments rather than a scan of every mapping. An address that load segments map ambiguously no longer falls back to a section header offset. Its file offset is reported as unknown and the report is incomplete; only genuinely unmapped spans use the section fallback. * fix(native): report Mach-O bind names over the name budget A bound import name longer than the 1024-byte name budget was dropped without a trace, although it is the only identity of an unresolved initializer target. It now counts toward the over-long name limitation and makes the report incomplete. * test(native): count mapping lookups instead of timing the load index regression The load-mapping regression asserted a wall-clock bound, which is sensitive to machine load. It now spies on the shared mapping module and requires the same number of mapping scans and index builds for 8 and 64 slots, so a per-slot scan of every load segment fails deterministically on a small fixture. * fix(native): yield while decoding legacy rebase runs * fix(native): preserve initializer mapping and coverage * fix(native): index legacy fixup spans * fix(native): preserve relocation uncertainty and bound bind lookup work * fix(native): validate ELF slot mappings and yield section relocation scans --------- Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> |
||
|
|
ec7d09176b | fix(mcp): retain partial Playwright trace Evidence on failed imports (#9543) | ||
|
|
43f06eb1e8 |
feat(native): recover ELF function ranges from unwind tables (#9585)
* feat(native): recover ELF function ranges from unwind tables inspect_elf_unwind_ranges and inspect-elf-unwind-ranges read .eh_frame and .eh_frame_hdr from one local ELF32 or ELF64 image and list the function ranges its FDEs name, with CIE facts, LSDA and personality, the containing section and an exact symbol where one starts at the address. Nothing is executed and no disassembler is needed. Pointer encodings follow the DW_EH_PE rules with raw zero as null, discarded FDEs are counted and skipped, the .eh_frame_hdr search table is compared with the decoded FDEs, and record, row and symbol budgets are bounded. verify:elf:unwind-ranges compares the reported starts with llvm-dwarfdump or readelf on a compiled C++ program. * fix(elf): keep unresolved unwind facts out of reported ranges Skip FDEs whose initial location is indirect and do not locate .eh_frame through an indirect eh_frame_ptr, since pointer slots are not functions. Stop an unbounded header-located scan at a CIE with an unrecognized augmentation, report ignored duplicate PT_GNU_EH_FRAME headers as incomplete coverage, and accept a null personality stored under an indirect encoding. Keep only symbols at decoded FDE starts, cache name observations per string-table offset, and decode names only for the returned page under a fixed 16 MiB text allowance, so repeated or long names no longer grow memory with the symbol count. * fix(scripts): run the ELF unwind verifier under owned process trees Launch probes, compiler drivers, the stripper, the frame dump and the inspection through createVerifierCommands, as verify-binary-hardening does, so a timeout or interrupt stops the whole tree. The temporary directory is removed only after the owned commands have closed. * docs(elf): move ELF unwind ranges guide under docs/guides/native The documentation guide assigns analyst workflows to docs/guides/<domain>/. Move the guide there, place its navigation and directory entries in the Native binaries group, and update links from the docs index, CLI guide, spec and authored skill. The public /elf-unwind-ranges route is unchanged. * fix(elf): give unwind text limits their own recovery and skip indirect tables Throw a dedicated failure when a page's symbol names exceed the 16 MiB text allowance, and map it to a resource error that tells the caller to request a smaller limit rather than raise max_ranges. Read a CIE augmentation with one bounded NUL search and keep it as a byte view, decoded only for returned CIEs, so a long augmentation is never built up character by character. Leave an .eh_frame_hdr search table with an indirect encoding unread: the header is incomplete, the comparison is unavailable, and the table no longer bounds a header-located .eh_frame scan. * fix(elf): resolve header count and table forms and name IFUNC resolvers Leave a non-zero .eh_frame_hdr FDE count under an indirect encoding unresolved, since it is the address of a slot that is not followed, and mark the header incomplete without reading the table. Treat a DW_EH_PE_omit table encoding as an omitted search table before testing the indirect bit, so a header that declares a count without a table stays present with complete coverage, and accept that form in output validation. Match STT_GNU_IFUNC symbols at exact FDE starts after function symbols, with a limitation that the name is the resolver, not the implementation it selects at run time. * fix(elf): require allocated unwind pointer bases * fix(elf): map unwind header relative base * fix(elf): validate unwind load mappings * test(elf): cover mapped nonallocated frame agreement --------- Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> |
||
|
|
f21fda0fc0 |
feat(elf): report a Linux kernel image's version banner and embedded build config (#9573)
* feat(elf): report a Linux kernel image's version banner and embedded build config inspect_kernel_build_config and inspect-kernel-build-config read one local vmlinux, raw arm64 Image, gzip bzImage or zImage, or configs.ko and report its Linux version banner and the IKCONFIG .config embedded between IKCFG_ST and IKCFG_ED, without executing it. A config is present only when a gzip member ends exactly at IKCFG_ED, passes its CRC-32 and ISIZE checks and parses as .config text; framing that fails is reported malformed, never absent. bzImage gzip payloads are inflated within a budget and other codecs are named as unsupported, using codec detection now shared with the kernel module parser. The config search, inflate sizes and option counts are bounded, scans honor cancellation, and target-derived text is marked untrusted. * fix(elf): reject a gzip member whose header checksum fails When FHCRC is set, compare the low 16 bits of the header CRC-32 before inflating, so a damaged header no longer yields a present config or an inflated bzImage payload. * fix(elf): detect the bzImage codec inside the declared payload Codec detection now reads the same payload_offset/payload_length slice that is inflated, so bytes past a short payload cannot name its codec. * fix(elf): report a framed config that does not decode as malformed A damaged or cut-off deflate stream between IKCFG_ST and IKCFG_ED was skipped and could end as an absent config with complete coverage. It is now malformed with config_gzip_invalid, and a later valid config still wins. * fix(elf): scan config lines in place and accept long string values Config text is read one line at a time instead of split into an array, and a quoted value is validated before it is decoded once. The 4096-character string cap is removed: Kconfig has no such limit and max_config_bytes already bounds every line, so a long CONFIG_EXTRA_FIRMWARE list is no longer reported as malformed. * fix(elf): let a live cancellation reach the kernel config parser The parser ran synchronously, so an abort raised during parsing could not change the signal before it returned. Inflation now runs on the zlib thread pool and each scan yields to the event loop once per MiB, so the existing cancellation checks observe a real abort. * refactor(elf): carry the refused kernel config budget as a typed fact Budget failures are now KernelBuildConfigBudgetFailure with a knob field, and the provider builds its recovery advice from that field instead of searching the diagnostic message for an option name. * docs(elf): move the kernel build config guide under docs/guides/native The documentation guide assigns analyst workflows to docs/guides/<domain>/. Move the guide there, place its navigation and directory entries in the Native binaries group, and update links from the docs index, CLI guide, spec and authored skill. The public /kernel-build-config route is unchanged. * fix(elf): yield while checking one long config line A config made of one long quoted value never reached the per-line yield, so the control-byte check, value validation and SHA-256 ran in one synchronous block. Each now works one MiB window per event-loop turn, and the line patterns match only a bounded name prefix instead of the whole value. * fix(elf): return paged config entries that do not pin the decoded text Entry names and values were V8 slices of the whole decoded config, so a one-entry page kept the full text alive. Entries in the returned page are now standalone copies, so retained memory follows the page size. * fix(elf): yield while kernel marker searches find nothing IKCFG_ST, IKCFG_ED and banner searches used one Buffer.indexOf over the rest of the image, so a large image with no marker never yielded. They now search overlapping one MiB windows and yield after each window without a match. * fix(elf): preserve long kernel config names * fix(elf): frame kernel configs by gzip member boundaries --------- Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> |
||
|
|
df2d018b30 |
feat(desktop): read gzip documents as the document inside (#9111)
* fix(desktop): release a capture when its start is cancelled after launch Cancelling start_build_capture during the opened app's screenshot left the capture running, so the next start was refused. The capture is now kept for the owner's cleanup, and the next start stops it first. * 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. * test(desktop): pass the settle timing when reading a witness bundle The witness takes the settle timing before the bundle path, so the bundle-read tests keep the path in its own argument. * fix(desktop): bound a guest file answer and split a long controller argument A data/get whose base64 answer would exceed a quarter of the V8 heap is refused before it is read. Controller JSON that exceeds Linux's single-argument limit travels as several arguments the controller joins. * fix(desktop): keep an underreported guest file from raising its read A data/get answer is admitted only when its base64 body fits in the heap quarter after the copies held during parse. Decoded bytes larger than the computer reported are dropped. * fix(desktop): grade shipped seeds and keep selected settings and sqlite logs Seed checks follow the files the bundle ships, so an omitted lock is absent. An incomplete checkpoint is not reported as no change. A selected link keeps its spelling, and a database's wal and journal stay supporting state. Closing the fake computer stops a detached capture. * fix(desktop): keep added-record checks off ids, dates, and joined timestamps A position-named record's fields keep their paths, so an identifier, a stamped date, and text past the limit are not suggested checks. A whole-text check does not climb into an ancestor whose text joins a timestamp. * fix(desktop): bound home fetches and keep unsettled edits readable Split home-folder reads by the guest answer budget, keep a capacity error from the capture output, and drop the superseded task-argument refusal. Grade kept text per line, leave unretained dconf unread, and reserve by-position notes for XML children. Map a linked database's sidecars through the selected spelling and stop a detached capture only when its start identity still owns the pid. * fix(desktop): describe unretained dconf as unread The key comparison treats a missing copy as unknown. The comment still said that copy counted as an empty key list. * test(desktop): keep a capture capacity error through endedCapture An output past the guest answer ceiling stays the resource constraint, with its heap recovery and non-retryable status, instead of a generic capture-exit message. * fix(desktop): keep nested save times and formatting runs out of checks A field check drops save-time leaves before it joins the field, so a nested timestamp is not part of the suggested text. A text check beside a save time uses the paragraph when the diff names a formatting run. * test(desktop): read paragraph pointers from checks that have them * test(desktop): expect a large task to export intact The 96 KiB refusal is gone. A prompt past that size reaches the computer and comes back unchanged, instead of failing before export. * fix(desktop): keep real edits that save-side heuristics were dropping Repeated unnamed fields stay content checks. A formula that still has text is not renumbered with its ExprID. One gained style attribute is the edit; a repeated fill-in stays upkeep. Phone numbers and plain clock times stay text, and a decimal is the element's whole text. An older verifier matches on the task it states, not its evaluator source. * fix(desktop): cover repeated records and keep timestamps out of checks An added record whose words are already in the seed still gets the list's text when that text fits. Readiness is a start reason, so a final check names seed locks without matching the message. Field text split by a timestamp stays separate, and a timestamp line is not offered as a guard. * fix(desktop): compare a cell's joined decimal within tolerance The whole-element check keeps numeric tolerance, so 437.80 and a long float still match 437.8, including when a run splits the digits. A different number or other text does not. Both evaluators read an element's text for that comparison. * fix(desktop): grade a number from a complete XML element only A tolerance check joins an element's text only in an XML file or an XML archive entry, and leaves that check undecided when the view is cut, so a dropped descendant cannot turn the kept runs into a passing number. A JSON object with the same shape stays the value itself. Equivalent decimals and a split run on a whole cell still match. * fix(desktop): accept an older grader only when its index helper agrees The witness still matches a bundle whose evaluator is this REA's, or the older index expression alone when no path segment is a leading-zero number. A truncated verifier, a changed grader, or that older helper beside a segment such as 01 no longer counts as the same task. * fix(desktop): require the added record and leave save times out of list checks A record a selector names is checked itself, so its words have to be in that record. When an unnamed record only repeats words the seed already has, a list that holds a save time is checked by the text around that time. A later save of the same records still passes, and a missing or rewritten record fails. * fix(desktop): judge the older index helper by pointer segments only A leading zero in a file name or a URL does not change how the older index helper reads a pointer. The witness still rejects that helper when a pointer segment is a number such as 01. * fix(desktop): do not suggest list text the seed already passes A repeated record is shown by text the seed does not hold. The seed's own text is not a check. A pointer inside a check value is not a pointer segment for the older index helper. * fix(desktop): keep a linked settings file in the folder the link points at A selected ~/.config alias no longer moves MuseScore settings to that alias. The seed keeps settings/MuseScore or Documents, which is the path the export opens the note from. * fix(desktop): split home fetches by answer size and keep a size refusal A batch of tiny files stops before each path's envelope exceeds the host answer budget. A capture output past that ceiling stays a resource error instead of becoming a generic exit. * fix(desktop): seed a selected link under the path the app uses The selected spelling wins, so ~/.config/MuseScore is not rewritten to the folder it points at and the note stays the one launched document. A database wal and journal follow that database. A launch argument is respelled the same way. Teardown signals a detached PID only when its start identity still matches. * fix(desktop): keep a witness's actions and an incomplete checkpoint A failed witness save retries the action log it first recorded. A deletion left unconfirmed between the seed and the end is not reported as no change. Windows packs npm through a shell, which can start npm.cmd. * fix(desktop): read verifier pointers from the parsed checks A brace inside a check value is not an object boundary. A leading-zero pointer after that value still rejects the older index helper. * fix(desktop): prefer the most specific home spelling and retarget launch files A selected parent directory no longer hides a settings folder walked through a link. A launch filename under that folder is replaced with the seeded file's absolute path. * fix(desktop): pack the build runtime through npm's JavaScript entry npm pack and npm ci no longer spawn npm.cmd through a shell, so a temporary directory whose path contains spaces stays one argument. * fix(desktop): spell launch settings and keep a database log exact A database log matches only that file, so a neighboring folder is not moved. A launch option and the working directory use the same home spelling as the seed. * fix(desktop): move a state database's logs with the database The write-ahead log and journal follow the spelling the database received, including a walked state link. A neighboring folder stays put. A separate --config argument uses that spelling too. * fix(desktop): keep a selected file ahead of a database-log guess A file selected as itself keeps that spelling even when its name ends in -journal. Relative launch arguments are resolved in the captured working directory before that directory moves. * fix(desktop): keep outside-home database logs and option values A selected database outside the home keeps its write-ahead log. Launch options are rewritten only when they name a captured file or settings path. * fix(desktop): follow a database mapping and own limitation text A selected database keeps its log when a parent folder moves or the file sits outside the home. Trash and seed-lock tests compare the owning notice with the paths, and launch options that are not captured paths stay as written. * fix(desktop): retarget a settings folder that holds captured files A nested profile directory is a captured path when a seeded file is inside it. An option value that only resolves under the home stays as written. * fix(desktop): keep a program word and a directory's neighbor The program after env stays the program even when a captured file sits in a folder of that name. A selected directory is not a database, so a neighboring file keeps the parent folder's spelling. * fix(desktop): record whether a selected path is a directory Capture stores the walked path's kind. A neighboring file of a selected directory keeps the parent folder's spelling even when that directory never changes and its children are not content roots. * fix(desktop): mark containing paths without a pairwise scan A recorded path marks its known ancestors as directories in one walk up the path, instead of comparing every recorded path with every other. * fix(desktop): keep a selected folder that is named like a database log A folder the caller selected stays a selected root when its name ends in -journal or -wal. A generated log beside a database file still does not. * fix(desktop): refuse a build command that exceeds the argument vector Splitting one argument still leaves the whole command under Linux's E2BIG limit. A request past that budget is refused before the process starts. * fix(desktop): remap a captured path in an env assignment The program word stays the program. A NAME=value assignment keeps its name and follows a captured path value when that path's spelling moves. * fix(desktop): keep oversized text out of draft guards A value or line longer than the draft's text bound is not copied into a guard, so one large frame cannot fill the task by itself. * fix(desktop): keep an empty env value empty An empty assignment is not a path. Resolving it named the working directory and rewrote the value when that directory's spelling moved. * fix(desktop): check build runtime export capability * fix(desktop): provide complete runtime repack command * fix(desktop): retain runtime probe failures * test(desktop): identify capture independently of schema preflight * fix(desktop): preserve document URLs and value formats * fix(desktop): bound added checks and omit noisy text guards * fix(desktop): preserve launch URLs and JSON draft values * fix(desktop): recognize captured file URL documents * fix(desktop): render captured file URLs for runtime home * fix(desktop): distinguish phone numbers from save metadata * fix(desktop): preserve launch URLs and user text * fix(desktop): preserve local file URL authority * fix(desktop): preserve local file URL authority * fix(desktop): render captured file URLs at launch * fix(desktop): classify numeric timestamps using field context * fix(desktop): classify numeric timestamps using field context * fix(desktop): retain context for generated draft values * fix(desktop): retain context for generated draft values * test(desktop): cover generated IDs in text guards * test(desktop): cover generated IDs in text guards * fix(desktop): isolate launcher URL encoding * fix(desktop): isolate launcher URL encoding * fix(desktop): isolate launcher URL encoding * fix(desktop): retain clean text in noisy record fields * style(desktop): format the noisy-record draft files with the pinned oxfmt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(desktop): move launch execution to boundary suite * fix(desktop): redact build schema failure output * refactor(desktop): normalize schema failure once * fix(desktop): omit unsafe schema parser snippets * fix(desktop): preserve draft change and selected path evidence * test(desktop): group retained dconf note regressions * fix(desktop): respect archive entry format in draft checks * test(desktop): separate unowned-file draft note cases * docs(desktop): clarify task checks before scratch export * fix(desktop): respell selected paths in file URLs * test(desktop): group captured document spelling cases * fix(desktop): bound draft preview serialization * fix(desktop): restore selected state aliases * fix(desktop): respect entry format in draft noise * test(desktop): match exported alias evidence at its JSON boundary * style: fix desktop launch test formatting * style: format native command path schema * fix(desktop): map selected external launch paths * style(desktop): format seed document regressions * test(desktop): group launch URL regressions * fix(desktop): omit redundant nested state aliases * fix(desktop): compare added free text as a whole * fix(desktop): check recompressed seeds as shipped * fix(desktop): map captured launch paths once * refactor: remove unused whole-text guard state * refactor: stop passing unused text children * test: align free-text checks with whole-note policy * fix: validate recompressed desktop archive seeds * style(desktop): format archive seed regression * fix(desktop): redact runtime schema errors * fix(desktop): normalize captured file URLs * fix(desktop): report seeded files by capture path * fix(desktop): retain startup readiness failure stage * fix(desktop): retain JSON date checks * fix(desktop): preserve archive formatting checks * fix(desktop): preserve explicitly selected journal files * fix(desktop): report build command transport limits * style(desktop): format capture review fixes --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.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> |
||
|
|
25885b05c0 |
feat(v8): inspect V8 code cache containers and retained byte patterns (#8993)
* feat(v8): inspect V8 code cache containers and their retained byte patterns Bytenode-compiled `.jsc` files — the V8 code cache container that `vm.Script`, `vm.compileFunction` and bytenode 2.x write, and that Node single-executable applications and Electron apps ship — had no format-native reader. `inspect_binary_layout` shows the surrounding ELF/PE and `inspect_artifact` inventories the file, but neither decodes the V8 structures, so an agent could not tell which V8 line produced the file, could not learn the container is metadata rather than source, and had nothing to point at a version-pinned decompiler. Issue #8543. `inspect_v8_code_cache` joins the format-native family with `inspect_python_pyc`, `inspect_erlang_beam` and `inspect_kernel_module`: one explicit local file, bounded parsing, no execution, no installation, no child process. **The container is version-dependent, so the reader reports roles with confidence instead of assuming an ABI.** All eight header words are reported with byte offset, observed value, the role this reader believes the word has, and whether that role is `confirmed`, `inferred`, or `unconfirmed`. Only three facts gate admission: the header size this reader pins, the V8 code cache magic high half `0xc0de` (the low half is `ExternalReferenceTable::kSize` and varies per build, so it is a build fingerprint rather than a constant), and a declared payload length that reaches exactly the end of the file. I derived the field semantics from the producer rather than assuming them, and two findings changed the design: - **The word V8 calls the source hash holds the source length on the measured producers.** A 54-code-unit source stored `54`, and sources with the same code-unit length but different content stored the same value, including a source whose UTF-8 length was 154. The reader reports it as `source_length` and the docs say that this name is what the measurement supports, not a claim about what another build stores there. - **`vm.compileFunction` sets a high bit in that word.** The reader masks it out and reports the producer family as `script` or `compile_function`, so the source length stays correct for both producers. Embedded strings are reported as **byte-pattern observations with absolute byte ranges**, labelled as such in the field name and in the limitations. A reported sequence is not proof V8 retained it as a string, and a missing literal is not proof it is absent. **Fail-closed boundaries, all covered by tests:** an unknown magic is a typed `unsupported_target` failure because the file is not a V8 code cache; a short header or a payload-length disagreement is a typed `invalid_request` failure. Neither yields a partial parse and neither records Evidence. Non-goals are explicit in the tool description and the docs: the payload is serialized V8 heap data, not source; recovering logic needs a version-pinned View8-style decompiler that this tool neither provides nor depends on. Fixtures are generated from the running V8 instead of committing a version-pinned binary, so the tests exercise the real producer and stay valid across Node upgrades. - Semantic owner and earliest changed stage: format-native V8 code cache container decoding. - CLI and MCP/tool-catalog contract: one new `artifact-provider` tool and one new `inspect-v8-code-cache` CLI command, registered in `TOOL_CONTRACTS`, the `artifact` language family, `TOOL_EFFECTS`, the capability declarations and services, and the capability inventory. `docs:check` passes, so the generated catalog agrees. - Provider, bridge, target-format, or platform compatibility: no provider runs and no external tool is required, so the tool is available on every supported Node host. - Evidence, artifact, provenance, or reconstruction contract: complete Evidence with the payload byte range as its location; no artifact format, reader, or reconstruction change. - Generated metadata, package, or installation impact: catalog and document facts regenerated by the existing checks; no new dependency. Expected effects: - [x] Target content is returned as bounded structured facts. - `src/v8/V8CodeCacheParser.test.ts` (13 cases): real-producer header facts, per-field role and confidence, source length for both producers, an observation's absolute offset verified against the file bytes, the limitation text, foreign magic, payload-length mismatch, short header, missing payload bytes, a different build constant still admitted, and the observation budget. - `tests/boundary/mcp/v8CodeCacheMcp.test.ts` (4 cases): advertisement and annotations, header facts over MCP, relative-path rejection, unsupported magic, malformed container. - `tests/acceptance/v8CodeCacheCli.test.ts` (4 cases): the public CLI, relative-path resolution, byte-range observations, and the typed failure. - `npx vitest run src/contracts src/v8 src/application/v8CodeCache src/domain/v8` — 242 passed - `npx vitest run tests/boundary/mcp/v8CodeCacheMcp.test.ts tests/acceptance/v8CodeCacheCli.test.ts tests/boundary/filesystem/productCatalog.test.ts tests/acceptance/tools/localToolContracts.test.ts` — 20 passed, 4 skipped - `npx tsc --noEmit -p .` — exit 0 - `npm run build` — exit 0 - `npm run lint` — 0 errors - `npm run knip` — exit 0 - `npm run docs:check` — exit 0 - `npx oxfmt --check src tests docs` — exit 0 Gap: the header table is measured on node v24.22.1 / V8 13.6.233.17-node.58 only. No other V8 build is available here, so a different build's field order is untested; that is exactly why only three facts gate admission and the remaining roles carry a confidence level rather than being asserted. Additive. No existing tool, schema, or behaviour changes. The reader never executes the selected file, never launches a process, and never accesses the network; its audited effects are `mutatesSession: true` only, matching the other static format readers. Human owner: @XiaoBinGan - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue: #8543. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. * chore: retrigger title and readiness checks after the title was corrected * fix(v8): bound the payload scan and use the repository path conventions Review feedback from @greptile-apps on four points. **Bound the synchronous payload scan.** The scan is one synchronous pass over the payload, so the 512 MiB ceiling allowed a single request to hold the process for several seconds. The ceiling is now 64 MiB, matching the pinned CPython pyc reader, and the default is 32 MiB. The scan stays synchronous, like the BEAM and ELF note readers in this family, but the budget that bounds it is no longer large enough to matter. The new `max_file_bytes` ceiling and default are documented. **Use the absolute-path schema.** `path` now uses `absoluteLocalPathStringSchema` instead of `localPathStringSchema`, matching `inspect_erlang_beam`. A relative name previously passed validation and was resolved against the server's working directory, so `module.jsc` could select a different file than the caller meant. The rejection is now at the schema boundary. **State the extraction step.** The handoff in `docs/v8-code-cache.md` now says a cache embedded in a single-executable application or an Electron app must be extracted first, because this reader requires the magic at byte zero and returns `unsupported_target` for the surrounding ELF/PE executable. **Load only the owning contract group in tests.** Both tests now import `V8_CODE_CACHE_TOOL_CONTRACTS` directly instead of resolving the tool through the full catalog, so a focused test no longer constructs every other tool's schema. 21 cases pass across the parser, MCP boundary and CLI acceptance files; `tsc` 0; `build` 0; `knip` 0; `docs:check` 0; `oxfmt --check` 0. * fix(v8): select the tool contract by name in the focused tests Reverts the catalog-position selection I added for a review suggestion. This repository has a lint rule (`rea(no-positional-tool-contract)`) that forbids selecting a tool contract by catalog order, and `toolContract("inspect_v8_code_cache")` is how every neighbouring focused test selects one. The positional form I tried introduced two lint errors, so the named form stays. The review concern was that resolving through the full catalog constructs every other tool's schema. That cost is real but it is the repository's chosen trade: catalog ordering must never select an operation or schema, and `toolContract` is the named accessor that enforces it. * test(v8): cover the new tool in the absolute-path boundary test Main added `tests/boundary/mcp/absoluteLocalPathTools.test.ts` after this branch was opened. It enumerates every tool whose MCP `tools/list` schema must reject a relative path, and `inspect_v8_code_cache` uses `absoluteLocalPathStringSchema`, so the tool belongs in that list. Adding it keeps the enumerated field set complete instead of leaving one absolute-path tool untested. `tests/boundary/mcp` + v8 + contracts: 256 passing. `tsc` 0; `build` 0; `knip` 0; `docs:check` 0; `npm run lint` 0 errors. * perf(v8): read the payload by index instead of allocating per byte `for (const [index, byte] of payload.entries())` allocates a two-element array for every byte of the cache payload. On a 1 MiB payload that allocation dominated the scan. Measured with a real cache built from this parser, alternated so the two forms run against the same input: | payload | entries() | indexed reads | | --- | --- | --- | | 1 MiB | 15.5ms | 4.4ms | That is 3.49x on the scan, and the gap widens on smaller payloads where the allocation cost is a larger share (7.3x at 64 KiB in a synthetic run of the same shape). The scan is the whole cost of `inspect_v8_code_cache` once the file is read, so this is the tool's own hot loop. Output is unchanged: the parser returns one retained string for the 64 KiB fixture, and `src/v8` plus the CLI and MCP boundary files stay at 21 passing. `tsc` 0; `build` 0; `npm run lint` 0 errors. * fix(v8): admit only decimal tokens on the numeric CLI options Main added `tests/boundary/cli/cliDecimalArguments.test.ts` after this branch was opened. It enumerates every numeric CLI option and requires `0x10` and `1e3` to be rejected, because plain `Number` coercion would read them as 16 and 1000. This command's three options forwarded the domain fields unchanged, so the test failed on them: inspect-v8-code-cache options.maxFileBytes: Parser.parse accepts 1e3 inspect-v8-code-cache options.maxStrings: Parser.parse accepts 0x10 inspect-v8-code-cache options.maxStrings: Parser.parse accepts 1e3 inspect-v8-code-cache options.minStringBytes: Parser.parse accepts 0x10 `cliDecimalField` publishes the input view that parses the decimal token first and then lets the domain field own bounds, defaults and help, which is what the other numeric commands use. `tests/boundary/cli/cliDecimalArguments.test.ts` now passes. `tsc` 0; `build` 0; `npm run lint` 0 errors; `knip` 0; `docs:check` 0. * fix(v8): recognize module caches, and advise from remaining headroom Two review findings, each measured on Node 24.22.1 before changing anything. **A module cache was reported as a script.** `vm.SourceTextModule.createCachedData()` sets bit 30 of the source-length word, which the source-length mask `0x1fffffff` leaves out, and the producer check only tested the function bit at bit 29: | producer | source word | | --- | --- | | `vm.Script` | `0x00000013` for a 19-unit source | | `vm.compileFunction` | `0x20000009` for a 9-unit source | | `vm.SourceTextModule` | `0x40000013` for a 19-unit source | So a real module cache was labelled `script`, and `vm.Script` rejects that container. The producer enum gains `module` and the module bit is tested first; the source length is unchanged because both flags sit outside the mask. **The budget advice recommended a retry that could not work.** Both limits have ceilings — `max_strings` at 65536 and `min_string_bytes` at 256 — so an admitted file with more than 65536 runs of 256 bytes reached the branch while every suggested retry was a rejected input. `observationBudgetRemediation` now reads the remaining headroom and only recommends a change that is still admissible, falling back to selecting a smaller artifact when neither can move. The parser message states the fact and leaves recovery to the provider, which is the only place that can see both budgets. `MAX_INSPECT_V8_CODE_CACHE_MIN_STRING_BYTES` names the `min_string_bytes` ceiling that the schema previously spelled inline, so the advice and the schema cannot drift. `docs/v8-code-cache.md` describes both flag bits. `src/v8` plus the CLI and MCP boundary files: 28 passing; 7 new cases fail on the base commit. `tsc` 0; `build` 0; `npm run lint` 0 errors; `knip` 0; `docs:check` 0. * refactor(v8): decide the budget recovery as data, and test the decision The remediation tests matched fragments of the advice sentence and banned old phrases. `docs/testing.md` asks for error codes, recorded limits and recovery behaviour instead of frozen prose, so a harmless reword could fail those tests while wrong advice passed them. `observationBudgetRecovery` now returns the decision — which retries remain within the schema's admitted range, and whether a smaller artifact is the only option — and `observationBudgetRemediation` renders one sentence from it. The tests assert the decision, so the wording is free to change and an incorrect choice cannot pass. This also fixes a bug in the previous shape: it took the `min_string_bytes` branch to mean "lower it", but that branch is reachable with the value already at the schema minimum, where lowering is not a legal retry. The decision now carries `canLowerMinStringBytes` and a `requiresSmallerArtifact` flag for that case. 5 cases, all failing on the base commit, covering both headroom states, either ceiling alone, and the run-length floor. `src/v8` plus the CLI and MCP boundary files: 28 passing. `tsc` 0; `build` 0; `npm run lint` 0 errors; `knip` 0; `docs:check` 0. * ci: rerun after the wakaru release download recovered The only failing job on this branch was `javascript_recovery / real-javascript-recovery`, which failed on `curl: (22) The requested URL returned error: 504` while downloading `wakaru-linux-x64.tar.gz`. The release is reachable again (HTTP 200), so this empty commit re-triggers the lane. * docs(v8): place the guide in the tree and record the feature The guide sat at `docs/v8-code-cache.md`, outside the `docs/guides/` tree every other guide uses, and neither index linked it, so it could not be reached from `docs/README.md` or the VitePress sidebar. Moved to `docs/guides/javascript/`, linked from both indexes, and recorded the feature under `docs/specs/v8-code-cache-inspection/` with `spec.md`, `plan.md` and `tasks.md`. The spec keeps only the premises that were measured on Node 24.22.1 — the three producer words and the retained-string layout — rather than restating the implementation. `npm run docs:check` 0; `npm run format:check` 0; `tsc` 0; `build` 0; `lint` 0 errors; `knip` 0. V8 reader, CLI and MCP files: 28 passing. * docs(v8): use the documented spec path and test the advice against its struct Two review findings. **The records were at `docs/specs/v8-code-cache-inspection/`.** `AGENTS.md:73` asks for `docs/specs/<domain>/<feature-slug>/`, so they move to `docs/specs/v8/code-cache-inspection/`. **The verification section claimed more than the tests do.** It said the producer cases were built from real `vm.Script`, `vm.compileFunction` and `vm.SourceTextModule` output, and that the budget advice was compared with its owning formatter. In fact only `vm.Script` and `vm.compileFunction` are real producers — the module case sets the measured bit on a `vm.Script` cache — and only `observationBudgetRecovery` was asserted. Corrected the claim, and closed the second gap rather than only describing it: `observationBudgetRemediation` now has four cases holding the sentence to the struct it renders from. The sentence must not advise a knob the struct closed, and must mention a smaller artifact exactly when the struct requires one. Verified by making the sentence advise `max_strings` after the ceiling was reached — the test fails. Wording stays free; wrong advice does not. `npm run docs:check` 0; `npm run format:check` 0; `tsc` 0; `build` 0; `lint` 0 errors; `knip` 0. V8 reader, CLI, MCP, absolute-path and decimal-argument files: 34 passing. * fix(v8): restore the absolute-path contract entry after the rebase The rebase onto `main` conflicted in `tests/boundary/mcp/absoluteLocalPathTools.test.ts`: `main` gained `inspect_api_contract`, `inspect_devicetree`, `inspect_playwright_trace` and `inspect_python_pyc` in both the contract list and the path-field map while this branch added `inspect_v8_code_cache`. Both sides are additive, so both are kept. Without the resolution the branch carried conflict markers, which made `mergeable_state` `dirty` and every check on it meaningless. Re-verified after the rebase: `tsc` 0, `build` 0, `format:check` 0, `lint` 0 errors, `knip` 0, `docs:check` 0, and the V8 reader plus its CLI, MCP, absolute-path and decimal-argument boundary files at 34 passing. * test(v8): pin the producer from the runtime's own header word An independent reviewer ran these files on Node 22.23.4, 24.22.1 and 26.12.1. Only 22.23.4 failed, on `separates the compileFunction producer bit from the source length`, expecting `compile_function` and reading `script`. The cause is the fixture, not the parser: `vm.compileFunction(...).cachedData` carries `0x20000009` in the source-length word on Node 24.22.1, with bit 29 set, while Node 22.23.4 does not set that bit at all. Whether a given V8 build marks the word is a build detail, so asserting one build's spelling made the check version-dependent. The case now reads the word the runtime produced and asserts the parser maps it correctly, and keeps the part that must hold everywhere: the source length is the low bits, so it equals both `word & 0x1fffffff` and the source's length. The flag meanings themselves stay pinned by the synthetic `withHeaderWord` cases above, which do not depend on any build. Reverting the parser's `compile_function` arm fails this case and `keeps the function and module flags distinct`. `src/v8` plus the CLI, MCP and absolute-path boundary files: 24 and 34 passing. `tsc` 0; `build` 0; `npm run format:check` 0; `npm run lint` 0 errors; `knip` 0. * fix(v8): report an unflagged producer word as unknown, not as a script `vm.compileFunction` marks bit 29 of the source-length word on Node 24.22.1 (`0x20000004` for a 4-unit source) and does not mark it on Node 22.23.4 (`0x00000004` for the same call). Whether a V8 build marks a function cache is therefore a build detail, and an unflagged word is either a `vm.Script` cache or an unmarked function cache. The container carries nothing that separates the two. The reader reported `script` for that case, which is a confident claim the bytes do not support. My previous commit made the test accept whichever value the runtime produced, which recorded the ambiguity instead of resolving it in the contract. `unknown` is now a producer value, the unflagged word maps to it, and the observed word stays in `header.fields` for a caller that trusts a specific build fingerprint. A limitation line says the same in the report itself. `header.producer` widens to `["script", "compile_function", "module", "unknown"]`; `script` is no longer produced, because no unflagged word can be shown to be one. The spec's producer rule and its verification notes are updated to match. Reverting the mapping to `script` fails 2 of the 24 `src/v8` cases. `src/v8` with the CLI, MCP and absolute-path boundary files: 33 passing. `tsc` 0; `build` 0; `docs:check` 0; `npm run format:check` 0; `npm run lint` 0 errors. `knip` reports one unused export (`builtinDataEffectMethod`) on `main` as well, so it is not from this change. * fix(artifacts): retain completed identity across native parser failures * docs(v8): preserve unknown unflagged cache provenance --------- Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> |
||
|
|
891371e738 |
fix(objdump): reflect observed launch failure in discovery availability (#9051)
* fix(objdump): reflect observed launch failure in discovery availability Distinguish a statically registered standalone command from an executable whose launch has failed in the active server session. Discovery leaves unprobed commands optimistically available, reports an observed launch failure as provider_unavailable with the command remediation, keeps the tool callable for retries, and clears the failure after a subsequent successful launch. Fixes #8826. * test(reverse): verify overlapping command launch dispatch ordering * test(reverse): unblock gated test workers before awaiting service closure * test(reverse): bound lifecycle acknowledgement and join launched workers * fix(reverse): distinguish host capacity exhaustion from command launch failures * fix(reverse): preserve host capacity across Linux process ownership preparation * fix(reverse): exclude process ownership admission failures from command launch state * fix(reverse): preserve Darwin process ownership preparation error across command launch * fix(reverse): disambiguate cleanup declaration in provider observation * fix(reverse): preserve command deadline timeout during Darwin ownership preparation * fix(reverse): isolate Darwin baseline ps errors and provide platform-aware admission guidance * fix(reverse): rely on typed baseline admission failures and use owning repair formatter in tests * test(reverse): use owning formatters for process ownership remediation assertions * fix(reverse): restrict Linux ownership prerequisite remediation to missing ps and preserve system error codes * fix(reverse): retain typed process ownership prerequisite with preserved error codes * fix(reverse): remove unvalidated error label fallbacks and keep admission tags out of system_code * fix(reverse): keep Windows native runner failures out of command-launch state * fix(process): preserve current_process_unreported refusal in Linux provider readiness * fix(process): distinguish no-code ps failure from missing ps and cover rizin launch failure * fix(windows): classify process_spawn host-control rejections as RuntimeControlUnavailableError |
||
|
|
6b3372e259 | perf(tests): reduce repeated schema compilation and CLI startup | ||
|
|
3602b64c45 |
fix(providers): retain cleanup ownership across probes and queued work (#9468)
* fix(providers): retain cleanup ownership across probes and queued work * fix(jeb): retain primary discovery failures during cleanup * test(providers): bound cleanup and readiness barriers * test(jeb): scope availability cleanup fault injection * test(jeb): retain caller error through cleanup recovery |
||
|
|
88cf498036 |
fix!: preserve results when source publication fails (#8444)
* fix: retain address context cleanup failures * fix!: preserve address context input errors BREAKING CHANGE: Strict clients that cached the previous full inspect_address_context output schema must refresh tools/list and accept the typed error field on unavailable facets. * test: use session contract for address context * fix!: preserve address context resource recovery BREAKING CHANGE: Clients validating unavailable context facets against a cached strict full output schema must refresh tools/list to accept resource_constraint errors. * fix: expose authenticated records refused by the evidence ledger (#8426) * fix: preserve completed evidence on retention refusal * fix: preserve context when unretained evidence exceeds delivery limits * fix(mcp): recover oversized context from session evidence * fix(evidence): preserve completed atomic write results * fix: retain completed results when source publication fails * test: cover bounded recovery with unknown retention * fix(evidence): preserve recovery identity and finalization facts * fix(evidence): clarify retention of omitted observations * test(evidence): compare omission guidance with its owner * fix(evidence): preserve completed composed workflows * fix(evidence): clarify unretained recovery export * test(evidence): cover mixed recovery guidance * fix(evidence): preserve caller scope in secondary failures * refactor(evidence): remove superseded cleanup projection * test(evidence): align recovery checks with owners * fix: preserve cleanup on partial recovery limits * test: use owners for diagnostic wording * fix: admit completed analysis before evidence construction * fix: preserve selected paths when reusing evidence * fix(cli): preserve caller path in unretained evidence * fix(evidence): preserve recovery metadata and admission bounds * refactor: consolidate evidence closure imports * style(test): format CLI help default annotations (#9280) * test(mcp): keep recovery checks focused on contract facts * fix(evidence): preserve feature trace replay revision * test: align evidence recovery checks with ownership * test: align partial recovery and cleanup diagnostics * fix(evidence): preserve nested partials during cleanup * fix(evidence): respect outer recovery ownership * fix(capture): discard rejected nested observations * test(frida): assert inline evidence recovery --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
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 |
||
|
|
0b028cc75a |
feat(mcp): refresh provider candidates without switching (#8487)
* fix(mcp): report provider candidate observation scope * feat(mcp): refresh provider candidates without switching * docs: clarify candidate inspection ownership * fix(mcp): clarify provider reselection on reopen * test(mcp): bound candidate refresh lifecycle gates * test(mcp): keep temporary fixture cleanup with its owner |
||
|
|
b40b0b8665 |
feat: page recorded Evidence arrays (#8863)
* feat(kuna): verify release 1.990 * feat(kuna): preserve stored pointer references * fix(kuna): group image-wide reference coverage gaps * fix(evidence): retain producer-required xref observations * fix(mcp): clarify xref address page scope * fix(kuna): preserve reference target aliases * feat: page recorded evidence arrays * fix(mcp): guide large evidence views to files * fix: preserve source context in recorded views * fix: keep recorded rows accessible with large context * fix: disclose alias scope in recorded references * test(kuna): identify pointer fixture version * fix(view): keep deep recorded-array pages inside Evidence depth Parent parameters are valid on the Evidence root and one level too deep under a page result. Omit those parameters, and refuse a row that still cannot be nested, instead of throwing from Evidence parsing. * test(view): narrow recorded-array depth pages before reading parameters * fix(view): validate recorded page rows once --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
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 |
||
|
|
31278c7b5a |
fix!: qualify call paths by provider discovery (#8443)
* fix!: qualify call paths by provider discovery * fix: preserve compact call coverage schema guidance * fix: preserve call discovery reasons in path evidence * fix(evidence): retain discovery limits in call verification * test: declare discovery in reconstruction controls * fix: preserve call discovery across facet limits --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
872890bef3 | test: clarify environment and desktop contract checks | ||
|
|
106ba1730f |
fix!: preserve address context resource recovery (#8424)
* fix: retain address context cleanup failures * fix!: preserve address context input errors BREAKING CHANGE: Strict clients that cached the previous full inspect_address_context output schema must refresh tools/list and accept the typed error field on unavailable facets. * test: use session contract for address context * fix!: preserve address context resource recovery BREAKING CHANGE: Clients validating unavailable context facets against a cached strict full output schema must refresh tools/list to accept resource_constraint errors. * fix: expose authenticated records refused by the evidence ledger (#8426) * fix: preserve completed evidence on retention refusal * fix: preserve context when unretained evidence exceeds delivery limits * fix(mcp): recover oversized context from session evidence * fix(evidence): preserve completed atomic write results * fix(cli): preserve caller path in unretained evidence * style(test): format CLI help default annotations (#9280) --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
c5301e6145 | feat(desktop): capture, draft, export and witness a task inside a build computer (#9045) | ||
|
|
6c08320654 |
feat(process): add a non-executing dry run to capture_process_scenario (#8469)
* feat(process): add a non-executing dry run to capture_process_scenario Preparation prompts asked an agent to prepare a scenario without running it but could only suggest the tool that launches the target. Add dry_run: true so the CLI and MCP resolve the executable, working directory, observation paths and admission checks, then return planned Evidence under the rea.process-scenario-plan predicate. Planned Evidence is not capture Evidence and comparison tools refuse it as a capture. The preparation prompt now suggests the dry-run call, and the scenario identity commitments exclude the operation-only field. Fixes #8398 * fix(process): redact planned sensitive input and share admission Address review findings on the dry-run contract: - Redact sensitive input events in planned Evidence and preserve only their byte length. - Recheck cancellation after the last awaited admission step. - Run the sensitive-matcher and filesystem-root admission checks that a capture performs before launch. - Assert the prompt advertises the dry_run field without freezing explanatory wording. * test(process): hold the final admission step for cancellation Add a preparation host seam so the regression can cancel while the last filesystem admission call is pending, then assert the returned AnalysisCancelledError retains the caller's reason. * refactor(process): remove the unused plan alias Keep the plan schema as the single exported contract and satisfy the unused-export check. * fix(process): report admission-time aborts as planning cancellation `prepareProcessScenarioPlan` returned the admission error verbatim, so an abort that landed while `admitFilesystemObservationRoots` awaited its `lstat` surfaced as a cancelled `ProcessCaptureError` with `operation: process_capture` even though no process ran. Convert that result through the same `cancelled()` projection the neighbouring checks use, and pin it with a test. * fix(contracts): keep the process result invariants on the dry-run union The output schema for `capture_process_scenario` became a union of the capture and plan shapes, and the union no longer carried the description that advertised the cross-field invariants to MCP clients — the boundary test reads `normalized_result.description`. Attach a description to the union that names both variants and keeps the capture invariants verbatim. * test(process): exercise the post-admission cancellation check The previous regression aborted immediately after starting preparation and released the held admission afterwards. Preparation awaits runtime path resolution first, so that abort was always observed by the pre-admission check; deleting the post-admission "if (aborted()) return cancelled();" still left the test green. Signal from the admitRoots seam when admission is actually entered, abort only after that point, then let admission resolve ok. Preparation now has to reach the check between a successful admission and the ok result, and the assertion pins both the AnalysisCancelledError tag and the caller's reason as its cause. Verified red-green: removing only the post-admission check fails this test (expected true to be false at prepared.ok) while the other two pass, and restoring it passes all three. * test(process): gate the admission seam on acknowledgement Race the admission acknowledgement against planning's own settlement and a bounded deadline, and release and join planning in `finally`, so a planning result that arrives before admission fails the test instead of stalling it until the suite timeout. * fix(contracts): hold plans to the scenario refinements and redact inputs `processScenarioPlanSchema` described the resolved dry-run response but dropped every cross-field check the input contract applies, so a plan could advertise out-of-order events, an event past `timeout_ms`, or a terminal beyond the renderer cell budget while claiming it had been validated. Extract those checks into `scenarioRefinements` and refine the plan's scenario with them. The plan's input event also carried `sensitive` and an optional `input_bytes`, which accepted a sensitive event that still shipped its data. Model the public and sensitive forms as separate exact variants: public input forbids `input_bytes`, sensitive input requires an empty `data` plus its byte length. --------- Co-authored-by: 2SinceJuly <202121119+2SinceJuly@users.noreply.github.com> |
||
|
|
7e9cf83fca |
feat(mcp): guide agents from argument-name mistakes in procedure and search tools (#2146) (#8649)
* feat(domain): guide agents from neighboring-tool argument mistakes (#2146) * feat(mcp): guide agents from argument-name mistakes in MCP tools (#2146) * fix(domain): suppress argument replacement when expected field is present (#2146) Suppress argument replacement guidance when the expected field is already present in the call input, preventing invalid suggestions such as advising procedure when procedure was already provided. Defrost explanatory prose assertions in tests and bind test cases to production toolContract schemas. * test(domain): use named contract families and decouple guidance prose in tests (#2146) Import named contract families (OFFICIAL_TOOL_CONTRACTS, APPLICATION_TOOL_CONTRACTS, ENHANCED_TOOL_CONTRACTS) instead of the full tool catalog per docs/testing.md. Replace hardcoded explanatory message and remediation strings with dynamic references to the owning guidance constants. * test(domain): restore independent replacement field assertions (#2146) Keep exact checks for expected replacement field names ('procedure', 'pattern', 'address', 'query') independent of the owning guidance helper per docs/testing.md, while retaining dynamic validation for message and remediation prose. |
||
|
|
5303199163 |
feat(api-contract): inspect local GraphQL SDL and field references (#9140)
* feat(api-contract): inspect local GraphQL SDL and field references * fix(api-contract): retain caller metadata and bound selection work |
||
|
|
985b9eae96 |
feat(browser): import saved Playwright v10 trace evidence (#9127)
* feat(browser): import saved Playwright v10 trace evidence * fix(browser): preserve original Playwright ZIP member names |
||
|
|
91d73a113e |
feat(contracts): inventory offline OpenAPI operation declarations (#9104)
* feat(contracts): inventory offline OpenAPI operation declarations * docs(contracts): link fixture provenance outside the docs site * fix(contracts): describe the shared API document byte allowance * fix(api-contract): preserve safe diagnostics and completed source facts |
||
|
|
1c0a02d4a4 |
fix(evidence): bound malformed file field diagnostics (#8557)
* fix(evidence): bound malformed file field diagnostics `readEvidenceFileSource` projected every validator issue, and the generic error delivery applied the MCP response budget afterwards. A file with many invalid fields therefore produced a transport `resource_constraint` that replaced the typed file error, so the caller lost the selected path entirely. Issue #8453 reports exactly that: 20,000 invalid values still returned a direct `invalid_request` with the path and every field issue, while 125,000 returned `resource_constraint` with neither. `projectInputIssuesWithinBudget` already existed for this but had no production caller. The reader now projects within a 64 KiB allowance and, when the whole list does not fit, keeps the largest leading group that does and appends one explicit omission issue naming how many of how many were dropped. The typed file error and its `path` therefore survive the response boundary, and the diagnostics stay actionable and explicitly incomplete instead of hiding the real failure. Two regressions cover the bound and the fits-in-budget case. With the unbounded projection restored, the bound test and its supporting fixtures fail. * chore: retrigger title and readiness checks after the title was corrected * fix(evidence): bound file diagnostics in one pass and cover the MCP boundary Review findings on the first version. **The prefix was not maximal.** `boundedContentIssues` halved the list and returned the first attempt that fit, so a file just over the allowance lost roughly half its diagnostics. Prefix selection now lives in the shared projector (`projectInputIssuesBounded`), which walks the issues once and stops exactly at the allowance, keeping the largest fitting prefix. **A compound issue could still lose its location.** One `unrecognized_keys` issue naming hundreds of keys expands into hundreds of field diagnostics and can exceed the allowance on its own. The projector now retains a diagnostic at that issue's path instead of returning only the omission notice. **The regression never crossed the MCP boundary.** The issue is about the delivered MCP error, so `evidenceFileSourceMcp.test.ts` sends the 125,000-value fixture through the production `inspect_analysis_view` tool and asserts the delivered error stays `invalid_request`, keeps `details.path`, keeps bounded `content_issues`, and fits the response budget. Both regressions fail without the bound. * test(evidence): move the MCP delivery regression to the adapters project Review finding. `scripts/lib/test-projects.mjs` assigns `src/application/**` to the `services` project, so the delivery regression sat in the wrong project even though it exercises the production MCP tool registration. Moving it to `src/server/` puts it in `adapters`, which runs the other MCP boundary tests and plans the same way. |
||
|
|
3708538e85 |
feat(javascript): compare static endpoints with HAR captures (#9090)
* feat(javascript): compare static endpoints with HAR captures * test(javascript): preserve original HAR fixture bytes during formatting * test(javascript): load the byte-preserved HAR fixture |
||
|
|
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> |
||
|
|
0beedcd712 |
perf(mcp): add opt-in hot/cold tool discovery (#9046)
Add per-connection discovery that loads canonical named tools on demand while preserving the default full catalog. Bound discovery replies before changing visibility, preserve family exclusions and Evidence workflows, and reset visibility on HTTP reconnect. Verified with focused protocol tests and real Codex CLI artifact investigations; token costs remain task-dependent, so the profile is opt-in. |
||
|
|
ad518cff65 |
feat(artifacts): select extraction entries and output destination (#4031)
* feat(artifacts): select extraction entries and output destination Refs morluto/rea#3490 * fix(artifacts): omit absent selection from execution parameters * fix(artifacts): protect source directories and verify public selection * fix(artifacts): keep optional selection inputs JSON-safe * fix(artifacts): separate reader ownership from selected destinations Validate complete reader inventory independently from collisions among selected output entries. Use occurrence-parent ownership instead of filename prefixes so independently owned PyInstaller entries remain selectable while nested-reader members remain refused. Validate advertised MCP schemas through the shared acceptance helper and add real PyInstaller/ASAR and excluded-entry regressions. * fix(artifacts): advertise absolute extraction destinations Reuse the shared host-absolute local path schema instead of an opaque refinement so SDK-converted JSON Schema preserves the runtime constraint. Extend the advertised-path and MCP-handler regression matrix for extract_artifact.output_root. * fix(contracts): advertise unique extraction occurrence IDs --------- Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com> |
||
|
+27 |
fb453f2930 |
fix(mcp): support retained pseudocode summaries and paging (#5046)
* refactor(mcp): share official tool evidence registration Route official tools through registerEvidenceTools and remove the duplicate execution, progress, and Evidence delivery pipeline. Preserve relationship coverage in the shared path and reuse the existing source Evidence recording helper. Validation: typecheck and 29 focused MCP tests passed. Real native providers were not exercised. * fix(mcp): support retained pseudocode summaries and paging Allow procedure_pseudo_code to return an opt-in summary linked to its retained complete Evidence. Extend inspect_analysis_view to page the original pseudocode without repeating provider analysis. Preserve default complete output and exclude delivery detail from provider parameters and source Evidence identity. Add regression coverage for large results, Unicode, null and empty output, missing retention, transport-overflow recovery, and CLI paging. Validation: 178 focused tests, build, check, docs:check, and test discovery passed. Real stdio simulation reconstructed 98,000 code units exactly. Real Ghidra, iTunes, and Claude Code verification remains unavailable. Fixes #5032 * test(mcp): scope pseudocode contract lookup to official tools * feat(desktop): capture and export apps installed from a downloaded .deb (#8954) * feat(desktop): capture a Linux desktop application in use Add `capture-desktop-application`, a CLI-only, Linux and X11 capture that launches an installed desktop application, watches it while it is used and writes capture Evidence plus SHA-256 addressed content: - inventory: desktop entry, launch command, executable, package and its apt sources (or snap, flatpak, AppImage), Electron markers and candidate state directories; - session: the launched process tree, client windows from xprop with the first application window time and a window match, and files held open; - state: a stat walk of the home directory before launch, at checkpoints read from stdin, at stop and after exit, with created, modified, deleted and retyped paths and the content of changed files and state directories. It refuses non-Linux hosts, missing DISPLAY or xprop, a non-empty output folder and an application whose window is already open, and signals only processes it started. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): own launched processes, confirm walk coverage and keep cancelled captures - Launch through the owned provider path with a run token; release with SIGTERM, then the token-verified group cleanup, after every session. Processes without the token are never signalled; each records whether it carries it, and the session records whether cleanup was verified. - Report creations and deletions only where a walk listed the nearest existing directory; count the rest as unconfirmed. - Retain a file only when it is still the walked version, through owned no-follow reads; charge the budget only for new content; create files exclusively in a private output folder owned by the caller. - Walk content roots outside the home directory, compare paths in their physical spelling, and run executables from the caller's directory. - Refuse when the window list cannot be read, re-evaluate window ownership each sample, handle one queued request per sample with a bounded stdin queue, and write the capture with end reason `cancelled` on interruption. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep owned cleanup failures and fresh digests - Allow a capture cancelled before any requested checkpoint to hold only the baseline. - Retry an incomplete stop once; if cleanup is still unverified, write the capture and fail with the run token and process group as cleanup resources. - Classify path changes after a walk (ENOTDIR and other selected-file errors) as changed_since_walk instead of failing the capture. - Treat a non-directory ancestor as proof that nothing existed beneath it. - Report a before digest only for the file version it was read from. - Derive stderr_truncated from stderr's own byte counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * wip(desktop): state view over a capture folder Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep failed file-handle closes owned for retry Content reads pass retainFailedClose, so a handle whose close fails stays owned by the content store; the capture retries those closes after it is written and fails with the output folder as the cleanup resource if one still cannot be closed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(desktop): read a captured application's state Add inspect-desktop-application-state, a CLI command that reads a capture folder into the application's state: every retained or changed file with its role and reasons, a typed JSON view of each version (SQLite through the shared worker, dconf through a private dconf dump, JSON, XML, key files, text) and the kinds of change between versions (lines, values, keys, rows). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): report process and handle cleanup failures together When both the launched processes and a retained file's handle remain unresolved after the capture is written, one cleanup error now lists both reasons and both resource sets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(desktop): export a captured application as an agentenv computer app Add export-desktop-application, which writes an agentenv bundle with one computer_app environment from a capture folder and its state view: the apt package, a boot launch matched on the captured window class with a window ready check, owned paths from the state roles, a seed of the baseline files, data hooks that call agentenv's add/get/reset helpers with a typed JSON view on get, a skill, a README and a deploy smoke task. The desktop CLI commands now load their services lazily. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep state views faithful to the capture - Read key files, XML attributes, dconf groups and SQLite tables into dictionaries without inherited properties, so captured keys such as __proto__ stay data. - Version databases with their write-ahead log as of each checkpoint, and stage only digest-verified bytes for the SQLite and dconf readers. - Detect the format per version, report format changes, keep JSON null and empty containers as values, keep XML text and preserved whitespace, and mark truncated views (including XML depth) and comparisons of them. - Number versions and changes by checkpoint index, decide baseline presence from the captured type, and keep tagged SQLite integers, text bytes and blobs distinct. - Carry the capture's limitations and omitted content forward, match state directories by their home path, index changes once per capture, keep failed handle closes owned, and finish the CLI through the shared owner. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep coverage, logs and handles honest in the state view - Read coverage flags only from formats whose readers write them, so JSON fields named truncated stay data. - Fail a SQLite version whose write-ahead log existed but was not retained or does not match its digest, instead of reading the database alone. - Close retained content on every exit, including cancellation, and report a close that still fails together with the primary failure. - Finish the CLI with the canonical operation name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): export only what the computer can install and seed - Refuse packages not from the Ubuntu 24.04 archive, since the computer installs by name from that archive. - Start the launch command in the captured working directory. - Respell the home path only in files the state view read as text. - Report files that were not retained instead of dropping them silently. - Load captured dconf keys for apps that own no files. - Keep home-level files as owned paths; rename reserved Python class names. - Mark truncated SQLite and text views in the class's get view, and read file types the way the state view does. - Release the output tree through a resource scope, and read seeds through an owner closed on every exit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep staged folders owned, symlinked state roots and XML values - Stage database bytes in a private runtime root released through a resource scope, so a failed removal keeps its owner and is reported with the read's outcome. - Report cleanup facts and owners from desktop failures instead of wrapping them as a plain adapter error. - Record the state directories as walked, in their physical spelling, and match roles against both spellings, so files in a symlinked state directory are not mistaken for selected documents. - Keep whitespace-only XML leaf values; drop only formatting between elements. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): read XML in the exported app the way the state view does Keep whitespace-only leaf values and xml:space="preserve" text in the generated get view; drop only formatting between elements. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): release retained handles with their owners, read older captures - Release retained-content handles whose close failed through a resource scope on every exit; a release that fails again reports the exact handle owners. A read that finished keeps its bytes when only its close failed. - Accept captures written before state directories were recorded, and say in the state view's limitations that symlinked state directories may be misclassed for them. - Compute each XML element's whitespace context once instead of scanning siblings for every text run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): boot without the working folder, bound XML, accept mirrors - Try the captured working directory only when an argument is relative, and start the app even when that folder is missing. - Cut the generated XML view at REA's node and depth limits, and keep one unreadable file from failing data/get. - Accept Ubuntu 24.04 mirrors, not only the canonical hosts; PPAs and other repositories are still refused. - Read seeds through the retained-content owner's new signature. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): state view review round - Stage a retained -journal beside its database so the SQLite worker accepts an inactive journal and refuses a hot one; a -wal or -journal that existed but was not retained (including one omitted at the baseline) makes the version unreadable. - Keep tables that read when another fails, and let cancellation and unfinished cleanup propagate instead of becoming view errors. - Read text as a key file only when every line parses as one. - Rank a file named in a window title or selected by the caller as a document even when the application holds it open; match titles on file-name boundaries; leave the display name out of dconf matching. - Bound JSON and key file views (4 MiB, 500 levels, exact numbers) and report too-large, missing and altered retained content separately. - Add no version or change while a database stays absent. - Read staged databases in place instead of copying them again. - Give Evidence the same limitations as the result. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): export review round - Load captured dconf keys without D-Bus: install dconf-cli, compile the existing and captured key files into the user database, and warn on failure instead of stopping the server. - Start relative-argument launches in the captured working directory, the home included, since the framework launches from the app folder; respell the home itself and option values under it. - Read views in a thread, skip files over 64 MiB, align the generated readers with the state view's, and close SQLite connections. - Never own the home or a shared base folder; map a symlinked state directory's files back to their home spelling. - Report omitted files and unretained opened folders. - Name the module so it cannot shadow another, and keep the class off the module's own names; derive names the bundle check accepts. - Write seeds as they are read, and remove an unpublished bundle on failure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): capture review round - Ask the launch process group and token carriers to exit before killing them, on errors too; report incomplete cleanup with its facts. - Count descendants of the launch as started by the capture even when their environment cannot be read; treat a reused pid as a new process. - Follow symlinked desktop entries; name a flatpak's state after its application id; match flatpak windows by name only. - Stop on end of input; refuse empty, duplicate and reserved checkpoint names; require whitespace after the checkpoint keyword. - Stay on each walk root's device, and never walk or retain `/` or a directory containing the home; say so in the limitations. - Refuse a window manager that does not publish _NET_CLIENT_LIST. - Remove retained content when a capture fails before it is written. - Skip reading a file larger than the remaining content budget. - Record apt's archive origin for each package source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): read an unset client list as no windows when supported xfwm4 leaves _NET_CLIENT_LIST unset while it manages no windows, so the capture refused an ordinary desktop with nothing open. Read _NET_SUPPORTED with the list: an unset list means no windows when the window manager supports it, and the capture is refused only when it does not. `xprop`'s "no such atom" output now reads as unset too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): accept packages by apt's archive origin Accept a package source when apt reports its origin as Ubuntu for a noble suite, so mirrors count and PPAs or other repositories that merely have "ubuntu" in their URL do not. Captures made before origins were recorded fall back to Canonical's own archive hosts. Seed reads report why retained content could not be used. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(desktop): capture and export apps from vendor apt repositories A closed-source app installed from its vendor's apt repository, such as Typora, can now be captured and exported as a computer app. - The capture records each non-Ubuntu repository listing the installed version (uri, suite, components from apt's sources files, one-line or deb822) and the key that signs it: the signed-by key, or the trusted key that gpgv shows verifies the repository's signed index. The key is retained with the capture. - The capture records the packages owning the libraries the executable loads (DT_NEEDED with RUNPATH and the linker cache, through REA's ELF readers), since a vendor package may not depend on them. - The export declares a verified vendor repository as an AptSource with its key, installs a vendor package's library packages, and adds --no-sandbox to an Electron app's launch, since a container denies Chromium's sandbox. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): report a locked database at once in data/get A database the running app holds locked made each data/get wait sqlite's five-second busy timeout before reporting it. Record the Typora run in an agentenv computer in the verification. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf(desktop): detect key files without splitting the whole text Read lines one at a time and stop at the first that a key file view would drop, instead of splitting a file of up to 64 MiB into arrays before its format is known. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep symlinked homes and state folders under the home in exports - Respell a path under its state folder's logical spelling only when that spelling is under the captured home, so a symlinked HOME keeps its files; pair walked and logical state folders only when the capture lists the same number, and match the innermost folder first. - When two files map to one home path, keep the one present before the capture and name the other in the limitations. - Read key files in the generated data/get with the state view's rule, checked against it by running the helper under python3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): end captures on zombies and keep cleanup owners - A zombie or dead process no longer keeps the session open. - Remove only the partial capture file this run created. - Keep the exact owners of handles and processes whose cleanup failed on the returned error, so a retry can release them; test the published capture's cleanup-failure branch with mixed outcomes and retries. - Release the application once even when the exit checkpoint fails. - A cancellation before the capture is written removes what it retained. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): vendor package review round - Match apt sources through `apt-get indextargets`, which covers flat `./` and `/` suites and gives each release file and sources entry. - Accept a key whose signature verifies even when the release carries another signature without a key here; keep only the verifying key from a keyring holding several (OpenPGP packet splitter). - Install the package from its repository's release (`name/<release>`), declare one source per URI and suite, support only the capture host's architecture, and refuse Ubuntu Pro repositories. - List only library packages the computer can install; walk libraries only for vendor installs, with RPATH inherited as ld.so does, normalized paths, and DT_NEEDED bounded while reading. - Put --no-sandbox after the program an env wrapper launches; keep the gpgv folder's owner when its removal fails; respect --max-file-bytes for keys; wait 0.25 s on a busy SQLite database in data/get. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(desktop): keep the vendor spec's gpgv command on one line A code span broken across lines left `<binary keyring>` for VitePress to read as an unclosed HTML tag, so the docs build failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(desktop): add a validated task to exported desktop applications Each capture can now yield one agentenv task in its exported bundle. An agent writes the task (a prompt plus declarative checks over the app's data/get views); REA validates it and stays model-free. - `describe-desktop-application-task` summarises a capture's net change per file (role, format, views before and after) and drafts checks. - Checks: file presence, lines present/absent/counted, JSON-pointer values, SQLite rows and counts. REA keeps a task only if a check fails on the seed and every check passes on the captured end state; a file that was not retained at the baseline counts as absent, as the computer starts. - `export-desktop-application --task` writes tasks/NAME.json (deploy, agent, skills, recording, prompt, verifier), a compiled verify.py that reads data/get, and an eval. A boundary test runs the verifier under python3 and checks it agrees with REA's evaluator on every check kind. - Docs, spec and skill guidance, with the solve-rate recipe. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(desktop): keep the seed test in its own block Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(desktop): record the task verifier driven in an agentenv computer Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(desktop): record the Typora task run in an agentenv computer Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep task checks bounded, complete and attributable - line_count counts lines holding a substring (contains) instead of matching a regular expression, which could stall the verifier on agent-written text and read differently in Python. - value_equals of a whole object or array is undecided on a truncated view. - The draft keeps a database whose rows changed under an unchanged hash, and a file whose truncated views match while it changed. - A task file that cannot be read keeps the reader's detail, and a failed cleanup keeps the read failure as its primary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): leave a file with one version out of the task draft Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(desktop): update the task verification's test counts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(desktop): record the task solve rate with Claude Code and Sonnet 5.5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(desktop): capture and export apps installed from a downloaded .deb capture-desktop-application --package-file reads the file's control fields with dpkg-deb and records its SHA-256, size and dependencies when it holds the installed package; the file itself is never kept. The library walk now also runs for local installs. export-desktop-application --package-url declares agentenv's Download(url, sha256) for that file, its dependencies and library packages as apt packages, and a run script that installs it with dpkg. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): seed app-named dotfiles and respell UTF-16 seeds The capture now treats dotfiles in the home named after the application (.varicad-cfg.ini, .notesrc) as state roots, so a file the app only reads during the capture is still seeded. The exported seeding respells the captured home in UTF-16 text files with a byte-order mark, keeping the mark. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): hold readiness until the app's own window shows An exported app is ready only once a window of its class that the taskbar lists is shown, so a splash screen of the class, which skips the taskbar, no longer counts as the app being up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(desktop): record VariCAD captured, exported and run in an agentenv computer Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep exported views strict JSON for infinite and inexact numbers The exported data/get spells infinite and negative-zero SQLite reals as REA's SQLite reader does ("Infinity", "-Infinity", "-0"), and refuses a JSON file holding a number that reading would change (1e999, integers past 2^53, -0, rounded fractions) with the state view's own error, instead of a view with an infinity in it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep package-file facts tied to one file and URLs unechoed - A --package-url refusal never repeats the URL, and credentials are checked before the scheme. - The package file's identity must hold between dpkg-deb's read and the hash. - A failed close keeps its cleanup owner even when the capture is cancelled. - Readiness also ignores windows typed as splash screens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): record database logs and keep state changes distinct - A selected path that is not a directory brings its -wal and -journal as content roots, so the capture records whether they exist and retains them. - The state view treats a file as absent only under recorded content roots and refuses a database whose log presence is unknown. - JSON changes list containers too, so an array that becomes an object with the same members is a change. - Key file entries escape the key as a JSON pointer segment, so [a/b] c and [a] b/c stay apart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep watching through unread samples and late workers - An unreadable window list is unknown, not zero windows, and is named in the limitations. - Before ending the session, live run-token carriers no parent link reached are tracked; an unreadable process table leaves the exit unknown. - An env prefix's assignments find the program and name its XDG folders. - flatpak run options that take a value are skipped with it, -- is honoured and a /arch/branch suffix is dropped from the id. - State directories include the entry's full id. - Path options refuse empty values; roots count toward the entry limit. - A capture file whose close failed stays owned and is retried on discard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): bound apt sources, keep older captures and cleanup owners - Sources files parse into one stanza per line or deb822 paragraph with its URIs and suites kept as lists, so no URI x suite product is built. - Repository architectures and release are optional, so captures written before they were recorded parse; the export treats them as unrestricted and unknown. - Library sources are matched against every index of a declared repository's URI, suite and components. - Two failures side by side keep both causes and both cleanup owners, and a host file whose close fails reports a lease on its handle. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): match escaped key file entries and suggest containers through members - The draft's key file lookup uses the state view's escaped `group/key`, so a key holding `/` or `~` still gets its suggestion. - JSON and XML changes now list containers too; the draft suggests an added or removed container through its listed members, and a container only when none of its members is listed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): read relative PATH entries from the launch folder A program, or an empty or relative PATH entry, is resolved from the folder the program starts in, as the launch does, so `env PATH=. app` with the entry's Path still finds the app. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf(desktop): compare JSON views on one shared path JSON and XML changes are found by walking both trees with one shared pointer path, building a pointer only for a listed value, so memory follows depth rather than every container's full path. A pointer over 4096 characters is counted but not listed. A 256-level document with 4000-character keys went from about 251 MiB of heap to under 1 MiB. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep JSON Lines as text in the exported reader The exported reader parses the whole text before an inexact number makes it JSON with an error, so JSON Lines with an integer above 2^53 stay text as in REA. Over-long integer spellings are unsafe without converting them. The guide no longer claims large integers keep their value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep the state-path help free of dash-led words The CLI alias check reads `-wal` and `-journal` in help text as short flags, so the help names the write-ahead log and rollback journal instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): never record or export apt source credentials - Source URIs lose any user name and password as they are parsed, the way apt splits them, and so do index-target URIs and descriptions and the sources apt-cache policy lists, so matching works whether or not apt prints them. - A repository whose entry held credentials is marked `uri_credentials_removed`, and the export refuses it, or an older capture whose URI still holds them, with a reason that names no URL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): look programs up without normalizing their paths Program paths and PATH entries are joined rather than resolved, so `..` after a symbolic link means what it means to the launch. The lookup moves to its own module. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): note inexact JSON numbers with a flag, not a list The exported reader only needs to know whether any number was inexact, so it keeps a boolean instead of every rejected spelling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): refuse older captures that still hold apt credentials A capture written before credentials were removed counted the credentialed repository's libraries as installable, so the export refuses it whole and asks for a new capture rather than declaring packages no source offers. Recorded policy sources are redacted in export messages too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(desktop): keep the credential fixture on an example host A login on a real host reads as a secret to the commit scanner, so the older capture's fixture uses apt.example.com like the other credential tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): tidy looked-up paths and search relative entries only for env Empty and `.` segments are dropped from a looked-up program path, which keeps `/snap/bin/` entries recognisable as snaps, while `..` is still left for the kernel. Relative and empty PATH entries are searched only in the PATH an `env` prefix sets, which travels with the exported launch; the host's own PATH does not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): keep excluded and unwalked database logs unknown The capture records the paths every walk left out, and the state view treats a log as absent only under content roots the baseline walked completely and outside those exclusions, so an excluded or unvisited log leaves the database unread rather than read without it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): judge JSON numbers after duplicate keys settle The exported reader marks an inexact number instead of flagging it during the parse, then looks for marks in the parsed value, so a number a later duplicate key overwrote no longer refuses the file, as in REA. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): redact a repository's policy source when it names it An older capture whose policy source matched no sources entry kept that text whole, and the export named the repository by it; the export now names it without any user name or password. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): never signal the launch group on unknown membership When the current read cannot observe a carrier's process group, the carrier is signalled on its own instead of letting an older process-table row grant a group-wide SIGTERM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): look programs up in the launch's order and refuse host-relative finds The lookup searches PATH as the launch does, an empty entry meaning the launch folder, so inspection and launch name the same program. A program found only through a relative or empty entry of the host's own PATH is refused, since the exported computer would not have it; an env prefix's PATH travels with the command. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): count unchecked paths and keep logs behind them unknown Each walk counts the paths it could not stat and the directories on another device it did not enter, and the checkpoint records it as `unchecked_paths`. The state view treats a log as absent only when the baseline left nothing unchecked, so a log whose stat failed stays unknown. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf(desktop): scan parsed JSON with one iterator per level The check for marked numbers walks the parsed value with an iterator per nesting level instead of copying each container's children; a million-entry array went from about 15.7 MiB to 8.1 MiB of peak traced memory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): start a relative program from its captured folder An exported launch whose program path is relative, such as `./app` from an entry's Path, now changes to the captured working directory first, as it already did for relative arguments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * fix(electron): reject non-directory scenario roots before launch (#8967) * fix(contracts): align managed example MethodDef scope (#8966) * docs(debugger): document configurable session limits (#8963) * docs(debugger): document configurable session limits * docs(debugger): clarify GDB control command deadlines * docs(debugger): qualify configurable GDB output budget * docs(debugger): clarify one-shot CLI settings scope * docs(debugger): preserve repository line endings * docs(testing): explain npm launcher selection in PowerShell (#8962) * docs(mcp): explain PowerShell launch environment scope (#8961) * docs(mcp): explain PowerShell launch environment scope * docs(mcp): qualify saved setup selections and OpenCode environment * fix(native): declare temporary filesystem writes for inspect_macho (#8959) * fix(environment): retain ID ordering with missing clocks (#8957) * fix(environment): retain ID ordering with missing clocks * fix(environment): compare known creation clocks across gaps --------- Co-authored-by: hhang <169027046+xu91102@users.noreply.github.com> * fix(gpu): distinguish ELF string scan limits from corruption (#8955) Co-authored-by: hhang <169027046+xu91102@users.noreply.github.com> * fix(setup): replace the fixed Hopper download deadline with a stall timeout (#7150) * fix(setup): replace the fixed Hopper download deadline with a stall timeout Hopper package downloads aborted after a fixed 120 s, which was also the largest deadline the download owner accepted. The current 32 MB Linux package needs about 132 s at the reporter's sustained 245 KB/s, so setup could never finish on that connection, and the timeout surfaced only as Node's generic abort message. Abort a download when no response bytes arrive for 30 s, or when it outlives a 15-minute overall bound, with a tagged HopperDownloadTimeoutError that names the URL, the limit reached and the bytes received. Linux and macOS setup already relay a thrown download error's message; the Linux publisher now keeps it for release metadata and public key fetches instead of a generic verification failure. Metadata and key fetches keep their 10 s bound. Refs #7077 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(setup): keep the macOS release feed on the metadata limit The stall-timeout change left the macOS release feed fetch on the package download bounds. That fetch could then wait up to 15 minutes instead of the 120 s it had, while the installation guide says release metadata keeps a 10 s limit. Only the Linux publisher owned that limit. Move the 10 s metadata limit into HopperDownload.ts beside the package bounds. The Linux feed and key fetches use it, and the macOS installer now passes it for its feed fetch through the installer host. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): parse environment-serve --port and --host like rea mcp --http (#7092) * fix(cli): parse environment-serve --port and --host like rea mcp --http environment-serve declared --port as a number, so incur coerced the flag text with Number(): an empty --port= bound an ephemeral port instead of failing, and 0x1F90 or 1e3 were reinterpreted. --host accepted whitespace. docs/cli.md says these flags resolve like rea mcp --http, which accepts only decimal port text and a non-empty trimmed host. The flags now use the same rules and are refused before binding. * refactor(cli): reuse the shared MCP listener port and host schemas * fix(adb): separate unresolvable paths and host capacity in adb spawn failures (#6188) * fix(adb): name unexecutable adb paths in readiness refusals When REA_ADB_PATH or the PATH-resolved adb is a directory or a file the host refuses to execute, the version probe fails at spawn with EACCES or EPERM. That fell through to the generic "did not report a usable version" refusal, which named neither the path nor the cause. Classify those spawn errors as binary_not_executable (provider rejection executable_missing), name the selected path and errno, and give remediation for the environment, PATH and host-policy cases. The generic fallback now names the selected path too. Fixes #5689 * fix(process): admit synchronous spawn errors as captured failures Node throws spawn errors other than EACCES, EAGAIN, EMFILE, ENFILE and ENOENT synchronously from execFile. execFileBytes called execFile inside its Promise executor, so ENOTDIR or EPERM became a rejection without capture fields and execFileOutputFailure returned undefined. Consumers that classify by failure code, such as the adb version probe, could not see the code, which left the adb EPERM branch unreachable. Catch synchronous spawn errno errors at the capture boundary and attach the same empty capture an asynchronous spawn failure carries. Argument validation errors stay unadmitted. The adb version probe now reports an ENOTDIR selected path, such as a REA_ADB_PATH whose parent is a regular file, as a missing binary with the filesystem error code instead of the generic version refusal. * fix(process): expose spawn failures from the capture owner execFileBytes knows when a command never started, but ExecFileOutputFailure did not say so, so consumers reread raw syscall and code fields and disagreed. Mark both the synchronous throw and an asynchronous `spawn <path>` error with `spawnFailed: true`, and set `path` on the synchronous error to match the asynchronous shape. Argument validation errors stay unadmitted. Consumers now use the owner field: - inspectAdbClient never reports a spawn errno as `exit_code`. ENOENT, ENOTDIR, ELOOP and ENAMETOOLONG are `binary_missing`; EACCES and EPERM stay `binary_not_executable`; any other spawn errno, such as EINVAL, is `binary_not_executable` with a path-naming "could not be started" message. Each records `filesystem_error` and `path_source`. EACCES remediation also names parent directory search permission, and EPERM remediation no longer names host policy as the only cause. - DarwinProcessRunTokenReader tags every not-started compiler as `spawn_failed`, not only ENOENT. EACCES, EPERM and ENOTDIR were previously `failed`. - NativeDmgArtifactReader uses one not-started rule for both `processNotStarted` (previously `spawn ` only, so synchronous errors were missed) and the ENOENT unavailable/io split (previously any `spawn` prefix). Its fake hosts now reject with real execFileOutput spawn failures. * fix(process): classify spawn failures consistently across consumers Admit synchronous and asynchronous spawn errnos through one helper that requires an errno and a `spawn` or `spawn <path>` syscall. The synchronous shape now also gains `spawnargs`, so both shapes match. Use the owner's `spawnFailed` fact in the remaining consumers: - inspectAdbClient reports exhausted host capacity (EAGAIN, EMFILE, ENFILE, ENOMEM) as a host failure to retry and no longer tells the caller to change REA_ADB_PATH. Path-resolution errnos come from a predicate the filesystem owner exports. - runAdbCapture says adb could not be started instead of claiming an exit code for a process that never ran. - The Darwin compiler probe words every spawn_failed outcome as a start failure, not a compilation failure. - Asset catalog inspection treats any assetutil that never started as unavailable, not only ENOENT. * fix(process): report host spawn capacity as a retryable constraint Spawn errnos that report exhausted host capacity (EAGAIN, EMFILE, ENFILE, ENOMEM) were classified by adb readiness alone. assetutil reported them as an unavailable tool, which marked inspect_asset_catalog unavailable in the session, and adb commands reported them as protocol failures. Classify them once in the process capture owner and report a retryable capacity constraint with recovery advice from assetutil and adb commands. * docs(adb): describe host capacity failures from device operations * fix(adb): report exhausted host spawn capacity as runtime unavailability A host that cannot start adb for lack of process, memory or descriptor capacity is not a configuration problem. Give it its own failure code and map it to the runtime_unavailable provider rejection instead of not_configured. * fix(adb): report probe-time host capacity as a retryable constraint A device operation whose adb version probe could not start for lack of host capacity was refused as capability_unavailable without retryable. It now reports the same retryable capacity constraint as a later adb command. * fix(adb): keep the selected adb path in probe-time capacity errors The retryable capacity constraint raised at the version probe dropped the selected_binary and path_source diagnostics the refusal used to carry. * refactor(adb): keep the spawn-failure fact to adb consumers Restore the DMG reader, Darwin compiler probe and assetutil to main. The capture owner still marks a never-started command, including the spawn errors Node throws synchronously, and only the adb readiness probe and adb commands read that fact. * test(adb): assert spawn-failure facts instead of refusal wording The new adb tests compared complete refusal sentences and banned an old phrase. They now check the errno, selected path, path source and the owner's spawn-failure marker, so wording edits do not break them. * fix(adb): own one host-capacity remediation and cover the spawn route The host-capacity constraint and the configuration failure each carried their own remediation sentence. AdbConfiguration now owns the text and both use it, so the constraint's remediation.action equals diagnostics.remediation. The synchronous spawn-throw test now runs on Node's execFile route and on the owned spawn route adb uses (stopSignal). The provider test covers inspect_adb_client under EMFILE next to list_adb_devices, and the docs say which operations report the retryable capacity constraint and which report runtime_unavailable. * fix(process): report EMFILE and ENFILE spawn failures without stdio After an EMFILE or ENFILE spawn failure Node creates no stdio, so the owned stop-signal route threw a TypeError while reading the streams and the later spawn error went unhandled. Attach the error listener first and capture absent streams as empty, so adb reports retryable host capacity. * fix(adb): keep a completed push when host capacity stops its digest check A capacity failure starting sha256sum came back as a retryable error even though adb push had already written the file. Repeating the request with overwrite=false is then refused because the destination exists. Return the receipt with an unavailable device digest and name the capacity failure in its limitations, so the caller is told the transfer is unverified rather than advised to retry. * docs(adb): list host capacity as an unverified push case --------- Co-authored-by: t <t@t> * test(gdb): expect configurable stream truncation diagnostics (#8965) * test(gdb): expect configurable stream truncation diagnostics * build(gdb): include prerequisite duplicate-import repair from #8884 * fix(javascript): resolve module-level Electron options in functions (#8960) * fix(javascript): resolve module-level Electron options in functions * fix(javascript): limit module option ancestry walk * fix(javascript): preserve uncertain captured argument ordering * fix(javascript): retain hoisted activation uncertainty * fix(javascript): retain function ownership through loops * fix(javascript): account for classic global activations * fix(javascript): bind first activations to lexical identities * fix(javascript): retain uncertain global activation timing * fix(javascript): isolate receiver facts and share computed reads * fix(javascript): retain projected and opaque global activations * fix(javascript): refresh activation bounds as opaque effects grow * fix(ci): format website watch directories without changing configuration * fix(javascript): share source reads across opaque-effect updates * fix(javascript): retain constructed-code global activation bounds * fix(javascript): share runtime activation and receiver facts * fix(javascript): reuse pattern reads and function positions * fix(javascript): isolate copied paths and preserve runtime reads * style(javascript): format migrated reference imports * fix(javascript): normalize constructor activation and receiver effects * fix(javascript): retain aliased receiver timing and lexical global this * fix(javascript): preserve effect-free receiver identity across activations * fix(javascript): retain outer activation and prototype effects * fix(javascript): index implicit reads without deep path rescans * fix(javascript): retain aliased prototype and parameter read uncertainty * fix(javascript): index reflected reads through intrinsic invocation facts * fix(javascript): retain unresolved global activation reads * chore: refresh PR branch after review fix publication * fix(javascript): retain projected receiver reads and cache method facts * fix(javascript): retain inherited and implicit activation reads * fix(javascript): retain caller-owned this uncertainty * fix(javascript): retain reflected reads with unresolved spread arguments * fix(javascript): preserve enclosing activation for decorators * fix(javascript): track intrinsic literal prototype effects * fix(javascript): retain catch activation from implicit reads * perf(javascript): reuse effective keys for projected reads * fix(javascript): retain possible caller-owned ambient effects * fix(uninstall): preserve caller-selected Kuna caches during purge (#7921) * fix(uninstall): keep a managed cache namespace whole when it holds a caller-selected Kuna cache purge --purge-data reported a REA_KUNA_CACHE_DIR selection below the default Kuna cache as retained, then removed it together with its parent namespace. A namespace that contains the selection is now retained and reported, so the retained report is true. Fixes #7344 * fix(uninstall): also keep a namespace equal to, or reached by symlink traversal from, the selected Kuna cache Compare the namespace and the selection with the same normalization, treat an equal path as contained, and resolve existing paths before planning so a symbolic link followed by .. is judged by where it leads. * fix(uninstall): judge a selection with parent traversal where the filesystem resolves it Collapsing .. lexically contradicts the existing rule that parent traversal after a symbolic link leads elsewhere, and broke the retained-through-symlink-traversal test. Compare spellings without .. directly and resolve existing paths for the rest, so the symlink-parent case still purges the default cache while a selection that resolves into a managed namespace is retained. * fix(uninstall): keep a namespace whole when the selection's location is unknown A realpath failure other than ENOENT/ENOTDIR (for example EACCES under an inaccessible parent) no longer counts as "absent". Each namespace that may contain the caller-selected Kuna cache is retained instead of purged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * fix(changed-behavior): withhold equality for unknowns and contradictions (#7624) find_changed_behavior derived behavior_status from each process comparison's aggregate status alone. An unchanged comparison whose first_divergence was unknown (residual unknowns prevent proving no divergence) and a consistent contradiction comparison both fell through to observed_unchanged, with no unresolved finding and no changed-behavior registry unknown. An unchanged comparison with unknown divergence now counts as unknown and adds one comparison-level unresolved first_divergence finding carrying its reason, as artifact comparisons already do for coverage. A contradiction status makes the aggregate unknown, and contradiction dimensions are classified and counted as contradictions instead of unresolved branches. Complete unchanged comparisons stay observed_unchanged and changed comparisons with unknown localization stay observed_changed. Fixes #7384 Fixes #7383 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * fix(process): reject contradictory filesystem capture facts (#7631) * fix(process): reject captures whose top-level filesystem facts contradict their checkpoints A process capture records its filesystem state twice: files_before, files_after and filesystem_effects at the top level, and the initial and final filesystem_checkpoints. Validation never reconciled the two, and comparison reads only the checkpoints. A caller-authored capture recording a created file at the top level while its final checkpoint was empty was therefore accepted and compared as unchanged. Semantic validation now requires the initial checkpoint to match files_before with no effects, and the final checkpoint to match files_after and filesystem_effects. The native producer builds both representations from the same snapshots, so produced captures are unaffected; consistent created-file captures still compare as changed. Fixes #7371 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(process): cover file-list checkpoint mismatches independently of effects Every rejected case in the checkpoint-consistency test also disagreed on effects, so removing both file-list comparisons left it passing. Add initial and final checkpoint cases whose file lists alone disagree while effects and coverage accounting stay valid. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * fix(process): report deadlines expiring during final cleanup (#7635) * fix(process): report a deadline that elapses during final cleanup as a timeout runOwnedCommand checked its absolute command deadline before awaiting process cleanup, but on the ordinary successful path it consulted only the caller's cancellation signal afterwards. A command whose deadline expired while successful cleanup was still awaited therefore resolved as success. After cleanup, an elapsed deadline now throws OwnedCommandFailure with reason "timeout" and the completed snapshot, as docs/tool-design.md requires a final signal check after the last awaited finalization step. Existing primary failures, caller cancellation and incomplete-cleanup classification keep their precedence. Fixes #7369 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(process): drive the cleanup-deadline regression with controlled time The regression test gave output collection 100 ms of real time before the deadline. On a busy worker the deadline could expire during collection instead, taking a different failure path and failing the test even with the fix. Use fake timers, wait until cleanup has started, then advance past the deadline and release cleanup, so the ordering no longer depends on worker speed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * fix(enhanced): bound batch decompile input size (#5937) * fix(artifacts): handle early ASAR extraction cancellation (#5672) * fix(artifacts): own source errors during output setup * fix(artifacts): join silent source destruction before returning * fix(artifacts): retain source cleanup failures with primary errors * fix(artifacts): join source finalization and classify secondary failures * fix(firmware): separate source cleanup from output rollback * fix(artifacts): retain live source cleanup dependencies * fix(artifacts): preserve source failure completion and semantics * fix(artifacts): retain scope cleanup owners and typed failures * fix(artifacts): keep cleanup classification and admission recovery When the operation completed and only scope cleanup failed, keep the cleanup failure's own reason instead of reporting io, matching main (fixes artifactProvider.cleanupRetry). When a typed primary is rebuilt with pending scope cleanup, carry its userMessage and ASAR header admission so callers keep the configured ceiling and setting. * fix(artifacts): translate plain file-close failures through the reader path The outer file-cleanup branch rebuilt every ArtifactFileCleanupFailure as a ProviderAdapterError, so dyld reads lost their io, unavailable, format and cancelled reasons and their exact file-cleanup cause. Compose separately only when the failed primary owns its own translation (a domain error, source failure or scope cleanup failure); raw and reader primaries are already projected by the file failure with its exact lease. * fix(artifacts): bound source destruction by cancellation and keep wrapper admission After cancellation, SafeOutputTree.write could wait indefinitely for a source whose destruction did not settle, both in the destroy join and in the iterator's wait for close. Both waits now end at cancellation plus a fixed 1 s grace, modeled on the process-output closure grace. A destruction that outlives it is reported as incomplete source cleanup under an exact lease that releases only once closure is observed without a late error. ArtifactResourceCleanupFailure and SafeOutputSourceFailure now keep the primary's admission, matching withCleanup. * fix(artifacts): keep one settled wait while observing a stuck source observeClosure raced the same pending close promise against a new timer every 10 ms, so a source whose destruction never settled accumulated one reaction per poll for as long as it stayed open. Each poll now waits on its own promise that the close listener or the unref'd timer settles, leaving one pending wait and one close listener. The lifecycle test also asserts that a late close releases the retained owner without an explicit retry. * fix(artifacts): settle pending reads before cancellation * test(artifacts): observe the consumed ZIP iterator on cancellation * test(artifacts): validate projected cleanup resources before sorting * test(mcp): reserve parent capacity for timeout recovery * fix(artifacts): contain ASAR cancellation before output consumption * test(artifacts): hash ASAR cancellation fixture bytes * fix(decompile): retain inventory limitations and selection (#8466) * fix(decompile): retain inventory limitations with the latest selection The manifest and decompile index dropped procedure-inventory limitations, so a directory separated from its Evidence response could not explain why functions were selected or omitted. Keep those limitations on the manifest and in a latest_run index record that also names the filter and counts that produced them. Older runs remain represented only by their retained function records. Fixes #8355 * test(decompile): surface export errors and check function caveats Address review findings on the inventory-limitation regression: - Throw the typed export error instead of returning from a failed Result. - Assert historical function records keep their own pseudocode caveats and do not receive the latest inventory warnings. * fix(pyinstaller): leave PE carrier binary members unmarked (#6730) The Windows bootloader sets no execute bit on extracted ARCHIVE_ITEM_BINARY members (the S_IXUSR fchmod in pyi_archive.c is #ifndef WIN32). Mark type b members executable only when the carrier dialect is posix. * fix(jeb): reconnect after stale MCP sessions (#3754) * fix(jeb): reconnect after stale MCP sessions * fix(jeb): preserve failures for overlapping MCP requests * fix(jeb): make cleanup operations explicit and stabilize timeout fixtures * fix(setup): flag unresolved migrated Claude Desktop storage (#8971) * fix(setup): flag unresolved migrated Claude Desktop storage * fix(setup): preserve Claude MSIX process view when config is unresolved * fix(enhanced): restore batch input record limit * docs(tool-design): audit agent workflow guidance (#8439) * docs(tool-design): audit agent workflow guidance * docs(tool-design): check deployed guidance versions * fix(cli): align ADB directory and package query schemas (#8974) * fix(cli): align ADB directory and package query schemas * fix(cli): preserve ADB selector correction details * fix(devicetree): reject duplicate node paths in Evidence (#8970) * fix(pe): classify valid DOS targets as unsupported (#7530) fix(pe): classify confirmed DOS targets as unsupported Signed-off-by: Rudy Celekli <rudy@gradiahq.com> * fix(native): reject nonzero reserved ELF dynamic symbols (#7528) fix(native): validate the reserved ELF dynamic symbol Signed-off-by: Rudy Celekli <rudy@gradiahq.com> * fix(evidence): traverse large source link sets safely (#8457) * fix(verification): use inspected Ghidra JDK (#8440) * fix(mcp): clarify retained dossier handoff in crash prompt (#8437) * fix(evidence): clarify unsupported view recovery (#8412) * fix(evidence): clarify unsupported view recovery * fix(evidence): explain sensitive capture view refusal * test(ghidra): check regex recovery at its owning boundary (#8578) * test(ghidra): check structured snapshot profile mismatch (#8536) * test(ghidra): check retained historical snapshot evidence (#8381) * test(ghidra): check retained historical snapshot evidence * test(ghidra): select historical observations by address * test(cli): cover Frida argument admission and spawn ordering (#3356) * fix(cli): reject spawn arguments in Frida attach mode * test(cli): remove redundant Frida recorder assignments --------- Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com> * 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. * fix(cli): normalize exit status on worker cleanup failure (#8049) (#8050) * fix(cli): normalize exit status on worker cleanup failure (#8049) * test(cli): verify SDK output status and finalization rejection on exit * ci: retrigger checks --------- Co-authored-by: Sarthak Pandey <sarthak@email.com> * fix(gdb): keep inferior-tty verification for read-only queries (#5539) * fix(gdb): keep TTY verification across read-only inferior-tty inspection The console command path cleared `inferiorTtyVerified` before dispatching any command whose text merely mentioned `inferior-tty`, so the read-only `show inferior-tty` query permanently revoked a persistent session's verified output sink; no in-session path ever restored the flag, and a later close of a live session failed detach verification with capability_unavailable. Exempt the exact read-only query forms (`show inferior-tty` and the MI `-inferior-tty-show`) from the output-mutation predicate; every other command mentioning the TTY setting keeps revoking, so mutating commands still fail closed and detach keeps re-reading the live TTY before detaching. Cover the query forms, composite commands, and the inspect-then-close detach path with regression tests. Fixes #5099 * test(gdb): classify show inferior-tty in the one-shot table and rename the TTY classification table - Add a 'show inferior-tty' row to the 'classifies one-shot GDB commands' table: the read-only query no longer invalidates the detach proof, a user-visible one-shot behavior change. - Rename the 'classifies read-only inferior TTY queries as non-mutating' table to 'classifies inferior TTY commands' since two of its rows are mutation cases. - Assert via the existing recorded-commands array that the inspected 'show inferior-tty' text is actually dispatched, and add an execute-path assertion that the MI '-inferior-tty-show' form leaves the verified-sink flag intact (defensive exemption: REA's own MI calls do not route through this gate). --------- Co-authored-by: akushonkamen <akushonkamen@users.noreply.github.com> * fix(browser): report an out-of-range generated position as a selection fault (#7133) trace_web_source_location reported a well-formed generated_position past the end of the selected script as invalid_format on generated_position, with no bounds, so callers were told their input was malformed and not which coordinate to change. Report out_of_range on the line or column that is past the end, with its valid bounds, as export_web_scripts and inspect_web_network_capture now do for their selections. The position scan now returns the bound it ran past, so the offset and the reported limit come from one pass and cannot disagree on line terminators. Fixes #7132 * fix(captures): classify unresolvable capture paths as capture_path input (#7814) * fix(captures): classify unresolvable capture paths as capture_path input Fixes #7636 * test(captures): cover unresolvable descriptor paths --------- Co-authored-by: Abelo9996 <Abelo9996@users.noreply.github.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> * fix(apple): preserve exact integer precision with post-table plist objects (#8910) * fix(javascript): resolve electron findings through aliases of interop results (#8914) * fix(javascript): resolve electron findings through aliases of interop results * fix(javascript): resolve interop aliases iteratively and check target mutations * fix(javascript): retain possible writes through uncertain aliases and guard positive reads * perf(javascript): cache alias change status across semantic interop lookups * fix(javascript): transient Windows private-runtime source-transfer (#8769) * fix(javascript): transient Windows private-runtime source-transfer Parent source-transfer into the Windows private runtime root failed with EPERM on path-based exclusive create. Write through a native transient private-runtime path that closes the handle after flush so per-job rm still works, and yield around the sync write so abort deadlines can fire. * fix(javascript): yield timer phase before Windows source-transfer write * fix(il2cpp): reject module image references outside retained inventory (#8956) * fix(ida): admit Docker host-gateway names as local MCP hosts (#8932) Containerized REA reaches an IDA MCP server on the container host through host.docker.internal (Docker, Podman compatibility) or host.containers.internal (Podman). The HTTP registration refinement only admitted localhost, 127.0.0.1 and [::1], so doctor reported the valid gateway registration as invalid_configuration. Admit both gateway names in the registration's local-host set. The refinement still requires http or https, no URL credentials, and refuses every other host. Fixes #8925 * fix(mcp): report target after failed open (#8613) * fix(mcp): report target after failed open * test(session): cover failed open receipt ownership * test(session): verify restored target receipt * test(mcp): retain target on snapshot mismatch * test(mcp): retain oversized open failure receipts * test(cli): avoid continuing session receipt in one-shot errors * fix(mcp): report provider after failed switch * test(ghidra): verify failed open preserves annotations * test(mcp): join queued receipt request before cleanup * test(session): assert open failure receipts in lifecycle suites * test(session): keep open-failure receipt checks within function limits Move the provider-collision case and snapshot fixture setup out of the functions that grew when both failure receipts were asserted. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> * fix(prompts): include existing static artifact investigation routes (#8972) * fix(prompts): include existing static artifact investigation routes * fix(prompts): preserve workflows in existing family scopes * fix(prompts): require readers for Apple resource routes * fix(rizin): keep debug targets off the debugger command stream (#8647) * fix(rizin): keep debug targets off the debugger command stream A Rizin debug target inherited Rizin's stdin, which is REA's command stream. Once resumed, a target that reads stdin consumed REA's commands, so close returned cleanup_incomplete and the one-shot CLI hung. Route the target's stdin to the caller-selected TTY alongside stdout and stderr. Before detaching, refuse a target whose stdin is still the command stream, so a Rizin or backend that ignores the key gets a specific, retained failure instead of a resumed target and a timeout. Fixes #8642 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(rizin): keep the stdin test launcher's descriptors under dash The launcher gated its target with `cat "$2" >/dev/null`. dash applies a simple command's redirection to the shell itself until the command returns, so on Ubuntu the waiting shell's fd 1 was /dev/null, and that shell is the target REA reads in /proc. All 8 Linux-gated tests then failed the existing output-descriptor check. macOS /bin/sh is bash, which redirects only in the forked child, so this did not show locally. Gate without any redirection. Production code is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(rizin): reject unmodeled commands and own cleanup at acquisition Address review of the stdin regression tests. The launcher accepted any unknown line, so the marker that followed could complete it, and assertions only checked that commands were present. An added `dc` or a repeated `olj` still passed. It now records an unknown line and exits, and the tests pin the exact command sequence. Cleanup hung off module state assigned after setup finished, so a failed setup left its directory and terminal child behind. Each resource now registers its own finish hook when acquired, using createTestTempDirectory. Success checks throw the typed error instead of asserting `.ok`, and the refusal probe no longer sits inside a loop and conditional. Production code is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * fix(ci): align tests with current evidence contracts * feat(native): report binary hardening for ELF, PE and Mach-O (#8524) * feat(native): report binary hardening for ELF, PE and Mach-O Documents inspect_binary_hardening and its CLI equivalent, including per-property states, supporting evidence, read budgets, and one report per Mach-O slice. Explains that missing protection imports remain unknown, signature presence does not establish validity, and hardened runtime requires inspect_signature. Adds hardening links throughout the documentation. The supplied diff also removes the advanced CodeQL workflow and configuration, along with snapshot-binding mismatch guidance. * fix(native): validate declared payloads and dynamic tables before hardening rows Run the shared range checks for ELF, read imports from the dynamic tables rather than section metadata, and keep an unresolved symbol count apart from an absent table. Check every Mach-O command before building rows and retain only the offsets the rows need. Make the verifier's readelf output wide, check the emitted format before parsing Mach-O, and place the sources before the libraries in the link. * fix(native): share Mach-O segment admission with hardening reads A segment with a section count its cmdsize cannot hold passed the hardening reader and could enable restrict_segment. Move the size, section count and file range checks to a shared admission that readMachoImage and the hardening reader both use, and pin the ELF load-size case with a regression test. * fix(hardening): reject Mach-O section payloads past the slice and empty ELF interpreters Segment admission never checked each section's payload range, so a file-backed section past the slice still produced rows. Decode sections with the section header owner and mark the slice malformed when a payload leaves it; zero-fill and empty sections own no file bytes and are exempt. admitInterp accepted a NUL first byte in a longer extent, which counted an empty interpreter as PIE evidence. It now requires a nonempty path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KuWHGvzJkrhCqjtEHUwqyH * fix(native): read CFG instrumentation from decoded GuardFlags Use the IMAGE_GUARD_CF_INSTRUMENTED flag that guardFlagRecord already decodes instead of masking the raw GuardFlags word a second time. * fix(native): reject ELF table spans a second PT_LOAD remaps The hardening reader mapped DT_STRTAB, DT_SYMTAB and hash tables through the one PT_LOAD containing the table's first address. A second PT_LOAD starting inside the table could map the rest of it from other file bytes and the reader still reported parsed import evidence. Cap each mapping at the next PT_LOAD that starts inside it, reject a requested range that crosses that boundary, and stop hash reads at the same limit, matching the conflicting-mapping refusal in readElfSymbols. * fix(native): dedupe ELF note tables only on shared boundaries The hardening reader dropped any note table whose bytes another table already covered. A covering SHT_NOTE can hold a non-GNU note whose descriptor is itself a complete GNU property note, while PT_NOTE names that inner note directly. Walking only the outer stream missed the GNU marker and reported CET disabled. Drop an alias only when it starts and ends on boundaries of admitted tables, which are note boundaries of the walked streams. Any other covered alias leaves the feature rows unknown, as a partial overlap already does. * fix(native): admit every Mach-O symbol record after a canary match The Mach-O stack protector scan returned as soon as it found an undefined ___stack_chk_fail, so a later undefined symbol whose n_strx lay outside the string table was never checked. The same damaged table parsed or failed as malformed depending only on record order. Keep the match and finish the bounded record walk. Records after the match are only checked against the string table bounds, so their names are not read or charged to the scan budget. The ELF reader already admits its whole symbol table before matching names. * fix(native): accept ELF load aliases with the same file translation The hardening reader treated every PT_LOAD that starts inside a table, or that also contains the table's address, as a conflicting mapping. A load with the same address-to-file translation names the same file bytes, so tables it overlaps still have one interpretation, and the canonical ElfLoadMap already merges such spans. Treat equivalent loads as one interpretation. A load with a different translation, or the zero-filled tail of an equivalent load, still ends the usable range, so a remapped table is still rejected. * fix(native): keep same-span ELF note tables with different alignments unknown A section and a program header that share endpoints were treated as one note stream even when their effective note alignments differed. Walking the same bytes at 4 and 8 can frame different notes, so dropping the second table could hide a GNU property word and report CET or BTI as disabled. Require matching effective alignment at both endpoints, and no alignment change inside the covered span, before treating a table as an alias. Otherwise mark the feature rows unknown. The fixture's .note.gnu.property section now declares the class's note alignment, as toolchains emit it. * refactor(native): read LC_SYMTAB through the shared fixed-word decoder Move the Mach-O fixed uint32 command layouts out of MachoCommandNames into domain/apple/machoLoadCommands so there is one owner of those offsets. MachoCommandNames and the hardening reader now both decode through it; the hardening reader keeps its own bounds and import policy. * fix(native): skip Mach-O common definitions in canary imports A common definition sets N_UNDF|N_EXT like an import but stores its allocation size in n_value. An object holding only `int __stack_chk_fail;` therefore reported stack_protector: enabled. Require a zero n_value before an undefined external counts as an import, for both nlist widths. * refactor(native): read linkedit data commands through the shared fixed-word decoder readMachoLinkeditDataCommand reproduced the dataoff/datasize offsets that FIXED_WORD_FIELDS already owns. Take the command and decode through decodeMachoFixedWordFields, as readMachoSymtabCommand does, keeping the truncation and endianness behavior. * fix(native): skip empty SHT_NOTE sections in ELF hardening A zero-sized SHT_NOTE owns no bytes, so the section directory marks it not file-backed and the hardening reader rejected the whole image as malformed, while readElfImage accepted the same bytes. Skip empty note sections before the file-backing check; they have nothing to walk. * fix(scripts): run hardening verifier commands through the shared owner The binary hardening verifier started its probes and compiler drivers with raw spawnSync, which bypassed the src/process/ supervision that AGENTS.md requires. Every launch now goes through createVerifierCommands, and the temporary root is removed only after the owner closes cleanly. * fix(scripts): clean up hardening verifier commands on Ctrl-C SIGINT or SIGTERM ended Node before withVerifierCleanup ran, so detached compiler trees and the temporary root could outlive the verifier. The verifier now turns those signals into an abort that every owned command receives, so cleanup closes the owner and removes the root before exit. * fix(scripts): fail the hardening verifier when a signal lands outside a command Only the owned commands read the interruption signal, so a SIGINT or SIGTERM during the final cleanup or between commands was recorded and then dropped, and the verifier exited 0. After cleanup settles, the verifier now throws the interruption reason. A failure the operation or its cleanup already raised still leaves first and is not replaced. * fix(native): fail Mach-O slices with a malformed encryption command The hardening reader turned every malformed status from the shared encryption reader into an unknown `encrypted` row, so a short LC_ENCRYPTION_INFO_64 or an encrypted range past the slice still left the slice parsed with a full report. Only two conflicting encryption commands stay an unknown row now. Any other encryption defect fails the slice like other structural command failures. * fix(native): ignore STB_LOCAL undefined ELF symbols as imports A local undefined __stack_chk_fail or __memcpy_chk is never resolved against another object, so it does not establish an external import. Skip STB_LOCAL bindings when reading protector signs, and give the fixture's positive symbols STB_GLOBAL binding. --------- Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> --------- Signed-off-by: Rudy Celekli <rudy@gradiahq.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: Edgar Arakelyan <edgar.arakelyan@scale.com> Co-authored-by: ShuaixinHuang <1836656514@qq.com> Co-authored-by: highmachs <samarjeeth06@gmail.com> Co-authored-by: hhang <17309584214@163.com> Co-authored-by: hhang <169027046+xu91102@users.noreply.github.com> Co-authored-by: Paritosh Lahre <155938586+SandstromPL@users.noreply.github.com> Co-authored-by: Adolanium <94890352+Adolanium@users.noreply.github.com> Co-authored-by: 김준호 <101695482+chordpli@users.noreply.github.com> Co-authored-by: t <t@t> Co-authored-by: Hasan Zayni <36798269+dark13b@users.noreply.github.com> Co-authored-by: Salman Almutairi <141588124+salmanalmutairi1@users.noreply.github.com> Co-authored-by: Lucien <164857476+dakjdakd@users.noreply.github.com> Co-authored-by: RRFZ <247457381+Plastic-time@users.noreply.github.com> Co-authored-by: 2SinceJuly <hongjxiao@gmail.com> Co-authored-by: Wade <160517347+Sriram-PR@users.noreply.github.com> Co-authored-by: Martin Klein <36695017+flitzrrr@users.noreply.github.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> Co-authored-by: Rudy Mizrahi Celekli <47457359+rudycelekli@users.noreply.github.com> Co-authored-by: xin zhuang <65798732+1052326311@users.noreply.github.com> Co-authored-by: Beqa <91750923+BeqaKs@users.noreply.github.com> Co-authored-by: NoThing <sarthakpandey5667@gmail.com> Co-authored-by: Sarthak Pandey <sarthak@email.com> Co-authored-by: akushonkamen <74654766+akushonkamen@users.noreply.github.com> Co-authored-by: akushonkamen <akushonkamen@users.noreply.github.com> Co-authored-by: amyanger <57688398+amyanger@users.noreply.github.com> Co-authored-by: Abel Yagubyan <abelyagubyan@berkeley.edu> Co-authored-by: Abelo9996 <Abelo9996@users.noreply.github.com> Co-authored-by: Jiabin Yin <54463072+Nolkee@users.noreply.github.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Mohamed Ayoub Eleuch <58662566+AyoubElleuch@users.noreply.github.com> Co-authored-by: Kaoru0822 <kanadekitauji@proton.me> Co-authored-by: Matt Van Horn <mvanhorn@users.noreply.github.com> Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com> |
||
|
|
560674e2de |
feat(native): report binary hardening for ELF, PE and Mach-O (#8524)
* feat(native): report binary hardening for ELF, PE and Mach-O Documents inspect_binary_hardening and its CLI equivalent, including per-property states, supporting evidence, read budgets, and one report per Mach-O slice. Explains that missing protection imports remain unknown, signature presence does not establish validity, and hardened runtime requires inspect_signature. Adds hardening links throughout the documentation. The supplied diff also removes the advanced CodeQL workflow and configuration, along with snapshot-binding mismatch guidance. * fix(native): validate declared payloads and dynamic tables before hardening rows Run the shared range checks for ELF, read imports from the dynamic tables rather than section metadata, and keep an unresolved symbol count apart from an absent table. Check every Mach-O command before building rows and retain only the offsets the rows need. Make the verifier's readelf output wide, check the emitted format before parsing Mach-O, and place the sources before the libraries in the link. * fix(native): share Mach-O segment admission with hardening reads A segment with a section count its cmdsize cannot hold passed the hardening reader and could enable restrict_segment. Move the size, section count and file range checks to a shared admission that readMachoImage and the hardening reader both use, and pin the ELF load-size case with a regression test. * fix(hardening): reject Mach-O section payloads past the slice and empty ELF interpreters Segment admission never checked each section's payload range, so a file-backed section past the slice still produced rows. Decode sections with the section header owner and mark the slice malformed when a payload leaves it; zero-fill and empty sections own no file bytes and are exempt. admitInterp accepted a NUL first byte in a longer extent, which counted an empty interpreter as PIE evidence. It now requires a nonempty path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KuWHGvzJkrhCqjtEHUwqyH * fix(native): read CFG instrumentation from decoded GuardFlags Use the IMAGE_GUARD_CF_INSTRUMENTED flag that guardFlagRecord already decodes instead of masking the raw GuardFlags word a second time. * fix(native): reject ELF table spans a second PT_LOAD remaps The hardening reader mapped DT_STRTAB, DT_SYMTAB and hash tables through the one PT_LOAD containing the table's first address. A second PT_LOAD starting inside the table could map the rest of it from other file bytes and the reader still reported parsed import evidence. Cap each mapping at the next PT_LOAD that starts inside it, reject a requested range that crosses that boundary, and stop hash reads at the same limit, matching the conflicting-mapping refusal in readElfSymbols. * fix(native): dedupe ELF note tables only on shared boundaries The hardening reader dropped any note table whose bytes another table already covered. A covering SHT_NOTE can hold a non-GNU note whose descriptor is itself a complete GNU property note, while PT_NOTE names that inner note directly. Walking only the outer stream missed the GNU marker and reported CET disabled. Drop an alias only when it starts and ends on boundaries of admitted tables, which are note boundaries of the walked streams. Any other covered alias leaves the feature rows unknown, as a partial overlap already does. * fix(native): admit every Mach-O symbol record after a canary match The Mach-O stack protector scan returned as soon as it found an undefined ___stack_chk_fail, so a later undefined symbol whose n_strx lay outside the string table was never checked. The same damaged table parsed or failed as malformed depending only on record order. Keep the match and finish the bounded record walk. Records after the match are only checked against the string table bounds, so their names are not read or charged to the scan budget. The ELF reader already admits its whole symbol table before matching names. * fix(native): accept ELF load aliases with the same file translation The hardening reader treated every PT_LOAD that starts inside a table, or that also contains the table's address, as a conflicting mapping. A load with the same address-to-file translation names the same file bytes, so tables it overlaps still have one interpretation, and the canonical ElfLoadMap already merges such spans. Treat equivalent loads as one interpretation. A load with a different translation, or the zero-filled tail of an equivalent load, still ends the usable range, so a remapped table is still rejected. * fix(native): keep same-span ELF note tables with different alignments unknown A section and a program header that share endpoints were treated as one note stream even when their effective note alignments differed. Walking the same bytes at 4 and 8 can frame different notes, so dropping the second table could hide a GNU property word and report CET or BTI as disabled. Require matching effective alignment at both endpoints, and no alignment change inside the covered span, before treating a table as an alias. Otherwise mark the feature rows unknown. The fixture's .note.gnu.property section now declares the class's note alignment, as toolchains emit it. * refactor(native): read LC_SYMTAB through the shared fixed-word decoder Move the Mach-O fixed uint32 command layouts out of MachoCommandNames into domain/apple/machoLoadCommands so there is one owner of those offsets. MachoCommandNames and the hardening reader now both decode through it; the hardening reader keeps its own bounds and import policy. * fix(native): skip Mach-O common definitions in canary imports A common definition sets N_UNDF|N_EXT like an import but stores its allocation size in n_value. An object holding only `int __stack_chk_fail;` therefore reported stack_protector: enabled. Require a zero n_value before an undefined external counts as an import, for both nlist widths. * refactor(native): read linkedit data commands through the shared fixed-word decoder readMachoLinkeditDataCommand reproduced the dataoff/datasize offsets that FIXED_WORD_FIELDS already owns. Take the command and decode through decodeMachoFixedWordFields, as readMachoSymtabCommand does, keeping the truncation and endianness behavior. * fix(native): skip empty SHT_NOTE sections in ELF hardening A zero-sized SHT_NOTE owns no bytes, so the section directory marks it not file-backed and the hardening reader rejected the whole image as malformed, while readElfImage accepted the same bytes. Skip empty note sections before the file-backing check; they have nothing to walk. * fix(scripts): run hardening verifier commands through the shared owner The binary hardening verifier started its probes and compiler drivers with raw spawnSync, which bypassed the src/process/ supervision that AGENTS.md requires. Every launch now goes through createVerifierCommands, and the temporary root is removed only after the owner closes cleanly. * fix(scripts): clean up hardening verifier commands on Ctrl-C SIGINT or SIGTERM ended Node before withVerifierCleanup ran, so detached compiler trees and the temporary root could outlive the verifier. The verifier now turns those signals into an abort that every owned command receives, so cleanup closes the owner and removes the root before exit. * fix(scripts): fail the hardening verifier when a signal lands outside a command Only the owned commands read the interruption signal, so a SIGINT or SIGTERM during the final cleanup or between commands was recorded and then dropped, and the verifier exited 0. After cleanup settles, the verifier now throws the interruption reason. A failure the operation or its cleanup already raised still leaves first and is not replaced. * fix(native): fail Mach-O slices with a malformed encryption command The hardening reader turned every malformed status from the shared encryption reader into an unknown `encrypted` row, so a short LC_ENCRYPTION_INFO_64 or an encrypted range past the slice still left the slice parsed with a full report. Only two conflicting encryption commands stay an unknown row now. Any other encryption defect fails the slice like other structural command failures. * fix(native): ignore STB_LOCAL undefined ELF symbols as imports A local undefined __stack_chk_fail or __memcpy_chk is never resolved against another object, so it does not establish an external import. Skip STB_LOCAL bindings when reading protector signs, and give the fixture's positive symbols STB_GLOBAL binding. --------- Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
845eb54d2b |
fix(prompts): include existing static artifact investigation routes (#8972)
* fix(prompts): include existing static artifact investigation routes * fix(prompts): preserve workflows in existing family scopes * fix(prompts): require readers for Apple resource routes |
||
|
|
56be61191e |
fix(mcp): report target after failed open (#8613)
* fix(mcp): report target after failed open * test(session): cover failed open receipt ownership * test(session): verify restored target receipt * test(mcp): retain target on snapshot mismatch * test(mcp): retain oversized open failure receipts * test(cli): avoid continuing session receipt in one-shot errors * fix(mcp): report provider after failed switch * test(ghidra): verify failed open preserves annotations * test(mcp): join queued receipt request before cleanup * test(session): assert open failure receipts in lifecycle suites * test(session): keep open-failure receipt checks within function limits Move the provider-collision case and snapshot fixture setup out of the functions that grew when both failure receipts were asserted. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
71f680d7c1 |
feat(mcp): page retained instruction references (#8594)
* feat(mcp): page retained instruction references * test(mcp): verify oversized instruction reference recovery * test(mcp): follow instruction reference continuations * test(mcp): validate continuation source kind --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
4afb6b79ae |
fix(mcp): guide retained evidence input recovery (#8761)
* fix(mcp): guide retained evidence input recovery * style(mcp): format catalog and server types * test(mcp): verify HTTP capacity recovery guidance * test(mcp): model catalog recorder imports in cleanup fixtures record-mcp-catalog.mjs loads tool contracts and the Evidence-input contract before it registers cleanup owners. The cleanup fixture still sentineled only the previous imports, so those loads failed before any owner wrote cleanup.jsonl. Track the script's read() calls and replace the new modules with the empty contract list this fault injection uses. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
93295c3df3 |
fix(mcp): report selection after failed target opens (#8726)
* fix(mcp): report selection after failed target opens * fix(mcp): retain resource root selection in open failures * test(session): assert selection during cleanup failures * test(mcp): delay failed open response across target switch * test(session): distinguish no selection from pending cleanup * test(session): assert selections during cleanup and cancellation * test(mcp): join the failed-open gate before restoring its spy The snapshot-switch gate waited only on its acknowledgement, so a request that settled early hung until the runner timeout, and a later assertion failure restored the spy while that request was still in flight. Race the acknowledgement and join the launched open in finally before mockRestore. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
f1622fc8b4 |
feat(native): page retained feature traces (#8585)
* feat(native): page retained feature traces * fix(snapshot): retain linked source evidence for replay * test(snapshot): verify linked foreign evidence stays scoped * docs(mcp): clarify imported residual questions * docs(mcp): guide trace reference classification * fix(cli): report result sources when Evidence publication fails A trace keeps linked sources on the result. Use those records for the undelivered source closure as well as the bundle, so a refused output does not report them as not captured. * ci: rerun pull request checks The merge of origin/main did not start the CI workflow for this head. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
6df2ac1d7e |
fix(evidence): report partial workflow question publication (#8848)
* fix(evidence): report partial workflow question publication * fix: project nested recovery for caller lifetime |
||
|
|
6259ac41a4 |
fix(mcp): guide target recovery for scoped tools (#8659)
* fix(mcp): guide target recovery for scoped tools * test(mcp): cover unscoped target recovery * fix(mcp): warn before scoped session restart * refactor(mcp): own scoped target recovery guidance * fix(mcp): include unknown history in restart guidance |
||
|
|
144843ccc2 |
fix(debugger): let REA exit when a debugger could not be stopped (#8652)
* fix(debugger): let REA exit when a debugger could not be stopped `rea debug-with-gdb` and `rea debug-with-rizin` printed cleanup_incomplete and set exit status 1, but the retained child and its pipes kept the event loop alive, so the process never exited. A stdio MCP server whose client disconnected hung the same way. closeOwnedDebuggerSessions is the owner both managers finish through. It now unreferences retained sessions, as supervised providers already do after incomplete cleanup, restores the references on retry, and names the retained process IDs. The one-shot commands report those IDs, since no later command can retry. Debugger ownership, signals and detach behavior are unchanged. GDB cleanup requests also no longer hold the host until their 120 s command deadline, because cleanup already bounds its own wait. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(debugger): name retained debuggers when an MCP server shuts down An MCP server that exits with a retained debugger logged only "REA provider cleanup failed" and "could not close cleanly", so nothing named the process left for the caller to check. The PIDs were on OwnedDebuggerCleanupError, but each shutdown reporter read only the outer aggregate's message, and the debug failure_cause description dropped the field too. The failure type now lives in its own dependency-free module with one reader that walks composed failures. The shutdown report, the server's onclose log, the debug description and the one-shot CLI all use it, and the shutdown report writes the same remediation the CLI returns. The fake debuggers now model each request exactly, with real reply shapes, and a request they do not model fails the test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(debugger): compare retained-debugger guidance with its formatter The new checks froze the wording "Check process ... and its target". docs/testing.md asks guidance checks to compare with the owning formatter, alongside independent checks of the facts. They now do, and each still proves the process ID is named, because a formatter comparison alone would pass if the formatter dropped it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
710fad8acf |
feat(evidence): discover missing Evidence links without transferring records (#8633)
* feat(evidence): discover missing Evidence links without transferring records An agent could only learn that a retained record's source was absent by reading complete records or by having a downstream analysis refuse. The summary said nothing about links, and complete-record retention was easy to mistake for source closure. - Add detail: links to get_evidence_bundle and CLI inspect-evidence-bundle: paged link rows with retained or missing status and no record payloads, for selected records against the whole session or file. - Add retained-closure traversal, the walk composed workflows require, reporting complete or incomplete. Direct reads make no closure claim. - Count direct and missing direct links in the summary. Fixes #8454 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(evidence): count a repeated Evidence link once in every delivery The Evidence schema does not deduplicate evidence_links, so the summary counted a repeated link twice while link rows and counts reported it once. Both now read one helper for a record's distinct direct links. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(evidence): validate link delivery against the advertised schemas The test never called tools/list, so neither the shared validator nor the MCP client checked its replies against what each profile advertises. A schema that rejected the links result could have passed. Fetch the advertised definition and validate every request and reply against it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
93b8b82db7 |
feat(native): deliver batch decompile as a retained summary (#8631)
* feat(native): select retained batch decompile results through analysis views A completed batch_decompile could only be read whole. When it did not fit the MCP response budget, or an agent wanted one function, inspect_analysis_view refused the parent as unsupported and the only recovery was exporting the session. - Own the batch result schema in the domain, replacing the contract's copy and the workflow's hand-written item types. - Add summary and batch-decompile views: body-free rows keyed by original index with exact filters and opt-in bodies, and UTF-16 pages of one body. - Report the decompiling provider from the upstream analysis profile, since the Evidence provider is the composing workflow. - Keep batch limitations visibly aggregated rather than attributing them to one successful item. Fixes #8498 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(native): deliver batch decompile as a retained summary A batch that fits still floods the caller's context with every body, and one that does not fit only named an export. Selecting a body that cannot fit named an export too, even though its text pages can. - Accept detail: summary on batch_decompile: retain the complete batch first and return its counts, identities and sizes. The default stays complete, and the selection never reaches the Evidence parameters. - Offer a ready-to-call body-free first page when a complete batch overflows. - When a selected batch page overflows, continue from the same retained parent with fewer rows, then with one body's text pages. Refs #8498 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(native): count every unavailable entry label in a batch summary label_unavailable only counted failed lookups, so a batch whose provider answered null for every label reported zero. The identity contract defines a null name as an unavailable label in both cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(native): continue an oversized batch view from the caller's own source A batch view read from an Evidence file or inline record advertised a retained-evidence continuation for a parent the session never retained, so following it failed. A view's continuation now repeats the caller's source and only narrows the selection. An inline record offers none, because it cannot be repeated within the reply it overflowed. Non-batch views skip the selection parse, since delivery asks about every view it returns. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(native): require advertised batch schemas through the shared validator A local validator map dropped any tool without an output schema, so removing an advertised schema would have left these contract tests green. Require both named schemas and validate through createMcpSchemaValidation, as docs/testing.md asks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(native): offer file view continuations on servers that retain nothing A fixed-target server reads an Evidence file through inspect_analysis_view but records nothing, so its overflow skipped the continuation and returned generic CLI guidance. A view's continuation names the caller's source and needs no session, so it no longer depends on recording. Retained references still do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |