Retain unresolved process identity and launch evidence through retryable cleanup. Share capture path normalization and preserve failed filesystem observations. Bound child output and drain Windows pipes without one-chunk throttling.
Reviewed fixes include #1628, #2632, #2644, #2784, #2928, #2931, #2965, #2992, and #3011.
Validation: 92 focused source tests passed; four platform-specific skips. Real Windows and Hopper lifecycle coverage was not rerun.
* fix(electron): reject non-executable paths and contain launch rejections
An executable_path that runs but never prints the inspector line made
Playwright's electron.launch() leave three waits unawaited. They rejected
unhandled and Node ended the CLI or the MCP server (#2269).
Check the resolved executable_path is a regular file, and on non-Windows
hosts that it passes X_OK, before any launch. Wrap only the launch call
in a scoped unhandledRejection listener that absorbs rejections whose
stack is in playwright-core/lib and re-throws anything else.
Tested on Linux with Node 22.23.1, 24.18.0 and 26.11.1.
Refs #2269🤖 Generated with Claude Code (Sonnet 5.5, verified by Opus 5.5) 🦊
* fix(electron): absorb only this launch's orphaned rejections
The listener around the launch dropped every rejection with a
playwright-core stack, so an unrelated Playwright failure during the
launch window would vanish. Hold those rejections instead. When the
launch settles, drop only the ones whose message is part of the launch's
own error (the orphans of a failed launch). Raise every other one again
through the unhandledRejection path, so the process still fails. A launch
that succeeds raises all of them. Rejections without a Playwright stack
still fail at once.
One setImmediate turn before the decision lets rejections queued by the
settling tick arrive first. It is a single turn, not a timer. A shared
set of absorbed errors stops overlapping launches from raising each
other's orphans. The listener is removed on every path.
Add child-process tests that drive the built provider through its launch
seam, since Vitest's worker has its own unhandledRejection listener.
🤖 Generated with Claude Code (Sonnet 5.5, verified by Opus 5.5) 🦊
* test(electron): distinguish launch success from capture ownership
* test(electron): assert cleanup ownership failures around overlapping launches
* fix(comparison): recheck historical calls-only changes (#2223)
* fix(comparison): preserve incomplete function call evidence
Keep missing, unknown, partial and unresolved call relationships unknown in function comparisons and reconstruction claims. Aggregate IDA caller and callee coverage without overwriting uncertainty.
Validate with 144 focused tests, typecheck/lint, docs checks and test discovery. Real providers were not verified; the full headless IDA session suite requires unavailable Windows native controls.
* fix(comparison): recheck historical calls-only changes
---------
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* fix(android): make DEX descriptor pattern portable
* fix(ci): isolate Linux Hopper process fixture inventory
* fix(browser): avoid replaying observed launch rejections
* style: format comparison and IDA sources
* test(electron): allow cold macOS ownership setup
* test(electron): allow cold macOS setup in the early-exit path test
The test that runs an executable which exits at once builds the Swift
ownership helper twice on macOS: in the CLI process, and again in the
MCP server process on its first tool call that prepares. A cold Swift
cache can spend up to 120 seconds on a build. The test had only the
30 second default.
Give the test 180 seconds, as e1579ec31 did for
electronLaunchRejections.test.ts and 65a809a0d did for
webSourceLocationCli.test.ts. cli.run has no deadline of its own, so
it needs no timeoutMs.
🤖 Generated with Claude Code (Sonnet 5.5, verified by Opus 5.5) 🦊
* test(ci): isolate report fixtures and declare PowerPC Java bounds
---------
Co-authored-by: Claude Opus 5.5 <opus@fox.invalid>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
Co-authored-by: Lucien <164857476+dakjdakd@users.noreply.github.com>
* test(mcp): expect trace_feature to report references the provider truncated
A provider that reports a capped xrefs read makes the trace truncated with a residual unknown for that target. An explicit complete report and a provider that reports nothing leave the trace as before.
* fix(mcp): report references a provider truncated in trace_feature
Executions gain an optional flag for a capped xrefs read, set by the IDA adapter from the upstream cap. trace_feature marks the trace truncated with a residual unknown for that target only when the provider reports a truncation; a provider that reports nothing keeps its previous result. The trace_feature workflow profile is revised so earlier results are not replayed.
* refactor(ida): report reference truncation whenever the runner observed an xrefs cap
* test(mcp): cover session forwarding, per-target state, native reports and failures of the trace coverage
* test(mcp): format the session forwarding test
* test(ida): expect headless IDA to resolve containing procedures from lookups and segment facts
Cover positive and negative containment, segment boundaries including addresses above 2^53, failures of the lookup and of the segment survey, cancellation, input validation and the admitted program as the only document.
* test(ida): expect feature tracing and address context to work on headless IDA
Run trace_feature, including a capped reference read, and inspect_address_context with and without an explicit document through the IDA session client.
* test(mcp): expect trace_feature availability to follow the search operations it calls
* fix(mcp): derive trace_feature availability from the search operations it calls
* feat(ida): resolve containing procedures and report the admitted program as the document
The modern headless profile resolves an address through the function lookup and, when no function contains it, tells a mapped address from an unmapped one using the database-scoped minimal survey. A survey that is missing, truncated or inconsistent fails the read. list_documents reports the single admitted program. The attached profiles do not declare either operation.
* docs(ida): describe containing procedures, the admitted document and truncated feature traces
* test(ida): verify containing procedures, the admitted document and feature tracing on real IDA
* docs(testing): list the headless IDA workflows the real lane verifies
* test(ida): make each survey failure case isolate a single defect
* test(ida): pin large addresses, segment order, document identity, attached refusals and each trace_feature prerequisite
* test(mcp): expect a repeated reference source to be resolved once in trace_feature
* fix(mcp): resolve the containing procedure of a repeated reference source once
* test(ida): trace the fixture procedure and derive probe addresses from its facts in the real lane
* test(process): format processCaptureLifecycle.test.ts after the merge
* test(ida): declare the alignment each synthetic universal slice offset satisfies
* refactor(ida): move the real lane's feature trace assertions into a helper
* test(ida): expect the real lane's feature trace check to accept references to every matched address
* fix(ida): check each trace reference against its own matched address in the real lane
* test(ida): pin that the new operations reject a document other than the admitted program
* refactor(ida): move the real lane's mapped non-function probe into a helper
* test(ida): expect the real lane's mapped data probe to skip strings inside functions
* fix(ida): try the target's strings in order for the mapped non-function probe
* test(ida): declare the real lane helper types for the verifier tests
* test(ida): expect the real lane to reject a listed string that resolves as unmapped
* fix(ida): fail the real lane when a listed string resolves as unmapped
Summarize saved Wireshark4.x captures with enforced native resource limits, serialized admission, stable snapshot verification and retained fact/text pages. Preserve complete inventories within resource budgets and source uncertainty; report cleanup failure with partial Evidence and retained ownership.
Verified six recorded corpora /13026 packets with independent Scapy/Python oracles, real CLI/MCP/schema parity,60 SNI names,132 DNS addresses and1000 URIs. Real TShark CI now exercises summary/paging. Actual Windows/Bun Wireshark remains unverified; macOS capture requires a separate enforceable-bound decision.
Co-authored-by: 3QL <85309073+3QL@users.noreply.github.com>
Co-authored-by: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com>
* fix(artifacts): name CPU_SUBTYPE_ARM64E_X1 Mach-O slices arm64e
macOS 27 system binaries such as /bin/ls carry a third FAT slice with
cpusubtype 0x8000000c. The SDK defines subtype 12 as
CPU_SUBTYPE_ARM64E_X1, and CPU_SUBTYPE_HAS_ARM64E puts it in the arm64e
family. architectureName knew only subtype 2, so it named the slice
arm64, lipoNameMatches rejected lipo's arm64e.x1 name, and
inspect-artifact /bin/ls failed with integrity_mismatch.
The arm64e.x1 test fixture now uses the real subtype. It fails without
this change.
Refs #1168, #1765
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(artifacts): classify en-GB hdiutil verify refusals as format failures
hdiutil follows AppleLanguages. With en-GB it writes "image not
recognised", and verifyFailureReason matched only the US spelling, so a
file that is not a disk image got the reason unavailable. Both spellings
now give format. Other languages still give unavailable.
Refs #1765
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(process): read the full process table in the lifecycle cleanup check
The check ran ps -axo command= with the Node default maxBuffer of 1 MiB.
On a host with 1905 processes, the output is 1.52 MB, and the test failed
with "stdout maxBuffer length exceeded".
Refs #1765
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(process): bound cleanup observations to sampled descendants
* fix(apple): retain CPU subtype identity during dylib resolution
* test(process): retain OS PIDs for descendant observations
---------
Co-authored-by: David Lee <davidlee@Dav3Book-Pro-M4-Max.local>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
Resolve each caller-selected Electron path once at the application boundary, collect field-specific failures with original causes, and pass canonical paths directly to the provider. Update direct provider consumers and route the real verifier through the shared application workflow.
Validation: public CLI/MCP invalid-path acceptance, canonicalization boundary, provider tests, and cancellation/cleanup checks. Live Electron launch was not verified. This does not address the separate Playwright launch-rejection crash in #2269.
Fixes#2272
* fix(process): add an opt-in Swift module cache
Signed-off-by: Charan Rathore <180254320+charan-rathore@users.noreply.github.com>
* fix(process): preserve caller-owned Swift module caches
Fold the complementary implementation from #2260 into the earlier #2252 proposal, retaining the original contribution history.
Co-authored-by: NIU-123370 <191000457+NIU-123370@users.noreply.github.com>
* fix(process): bypass xcrun lookup for explicit Swift toolchains
---------
Signed-off-by: Charan Rathore <180254320+charan-rathore@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
Co-authored-by: NIU-123370 <191000457+NIU-123370@users.noreply.github.com>
observeSettlement classified a group as alive_at_deadline when the settlement
budget expired after one empty observation, though no live member was ever
seen. Track observed liveness and return unverifiable when the deadline ends
observation with only empty rounds. The two-consecutive-empty rule for
quiesced is unchanged, and the cleanup_outcome projection for non-quiesced
settlements stays cleaned.
Fixes#2170.
startMcpTransport loads optional observation providers once per process
and passes them to every server instance the SDK constructs. Each
instance's closeProviders also closed the shared browser scenario
provider, so when the SDK discarded a server/discover probe instance for a
legacy initialize, every later capture_browser_scenario call failed with
"Browser scenario provider is closing." Server instances no longer close
the caller-supplied provider; the transport returns
closeOptionalProviders and process shutdown closes it once.
Fixes#2195
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Use POSIX mkdtemp owner-only allocation directly instead of adding a fallible permission rewrite and rollback before returning the cleanup owner. Respect restrictive umasks, assert privacy and real scratch access, and align provider documentation.
Use Android 8-compatible batched find/stat with NUL-framed names and raw symlink targets. Preserve malformed or invalid UTF-8 records as partial evidence with exact source bytes. List hidden direct children without synthetic navigation entries.
Share process byte capture with UTF-8 callers and screenshots, removing duplicate timeout and cancellation supervision. Verified 35 focused process, ADB, CLI and MCP tests; compatibility checked against AOSP Oreo sources. Live Android device/emulator verification was not run.
Distinguish absent CLI directories from unreadable directory counts and truncated slots while preserving known PE headers and readable CLI data.
Retain environment-entry coverage in the Darwin parser and classify restricted empty, unavailable and ambiguous environments at the native boundary. Keep cleanup fail-closed; code-signing flags do not establish ownership.
Validation: 116 managed source tests, 13 ownership tests, native Swift parser probe and two live Darwin run-token tests; build, static checks and docs checks pass. Restricted-flag cases use parser fixtures; no real restricted capture is claimed. Related to #2035.
Return deduplicated execution caveats once and preserve provider-owned relationship diagnostics and completeness on graph nodes. Keep complete relationship reads exhaustive despite contextual caveats, including portable call-path reconstruction.
Preserve omitted diagnostic fields in historical Evidence and bind reported diagnostics into semantic identity. Revise graph workflow and Ghidra adapter profiles so old cached representations cannot replay under the new contracts.
Remove stale duplicate-lookup test claims and redundant fixture validation. Prune million-entry duplicate cases while retaining argument-stack and deep-chain regressions; bounded Flameox captures identified validation and canonical hashing costs.
Validation: static and architecture checks, generated docs, 364 focused tests before pruning, 21 call-path tests after pruning, public MCP schema validation and targeted profile tests. Real engine behavior was not locally exercised.
BREAKING CHANGE: get_call_graph normalized_result now contains { graph, limitations }; traversal-depth groups are under graph.
Bundle ordinary CLI and output entries to reduce Windows module filesystem resolution while preserving source URLs, lazy loading and worker resources. Keep release identity in its shared owning module.
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Assert that search_android_classes preserves duplicate class-name rows and reports duplicate_names when querying with an empty string on an APK reporting duplicated class inventories.
Parse otool field occurrences once and reject valueless required fields while retaining empty dylib options. Preserve compiler exit outcomes and stderr through capture errors and nested Ghidra causes, with explicit UTF-8 truncation after redaction.
Strengthen provider failure assertions and document the manual Ghidra 12.1.4 macOS x64 decompiler build using upstream instructions.
Validation: focused producer tests, nine fake-compiler preparation and cancellation tests, temporary-directory hygiene, static and documentation checks. No real Swift or Ghidra compilation was run locally.
Parse Apktool YAML and XML at the producer boundary, preserving scalar spelling, XML text and partial string coverage. Retain repeated JADX inventory rows with explicit duplicate-name counts and lookup ambiguity. Make the Apktool verifier report cleanup failures.
Validation: parser, provider and JADX fixture boundary tests; typecheck, lint and documentation checks. Real Apktool and JADX engines were not exercised.
Refs #1978
Give snapshot capture, header admission, packed members, and container streams one file-handle owner. Serialize adoption with reader shutdown, retain failed closes for retry, and remove snapshots only after descriptor cleanup succeeds.
Cover unread members, pending opens, zero-byte members, and paired format/cleanup failures. Keep intentionally unrecoverable test fixtures hygienic and strengthen managed identity and process cleanup-authority expectations.
Validation: full npm run check; 99 targeted tests and temporary-directory hygiene; exact discovery of 877 test files. No real vendor-provider verification was performed.
Replace duplicate path-helper checks with real ZIP inventory coverage and replace global memory sampling with bounded-chunk assertions while retaining 64 MiB digest coverage. Await artifact client cleanup, preserve Hopper lease ownership during teardown, and expose typed application failures.
Move artifact inventory, application projection, runtime reconciliation, and TODO scanner suites into their real boundary lanes. Extract Hopper process/socket cleanup cases while keeping injected session cleanup cases in composition.
Validation: all 56 focused tests passed; discovery finds all 876 test files exactly once. Test assertions and provider verification scope are unchanged.
Focused and zero-match search_android_classes responses embedded every
examined class name: JadxSession records each raw list_classes page into
observed calls, those calls ride into Evidence raw_result on the
registration path, and the complete inline Evidence is serialized into
every tool response (issue #1850: 382,435 bytes for one match).
When the server session retains Evidence, record the complete raw-call
record first, then deliver a summary Evidence that keeps the pagination
audit (totals, offsets, page sizes, elided item counts), the unchanged
normalized matches and truthful coverage metadata, and links the
retained complete inventory by Evidence ID. Sessions without retention
keep the complete inline delivery, so complete CLI JSON output is
unchanged and no provenance is discarded.
🤖 Generated with AI assistance (disclosure voluntary per repo policy)
Preserve per-member verification failures and sweep uncertainty across
supervisor stop and owned-command failures. Report the observed token
mismatch with its PID coordinates instead of implying PID reuse.
Keep unresolved ownership unsignaled and retain the supervisor for a later
verified stop. Exercise cancellation, timeout and cleanup revalidation with
source-owned process fixtures and cooperative settlement.
Closes#1856
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
* fix(bun): report the real runtime and enforce worker memory budgets on Windows
Under Bun, REA recorded Node/V8 identity it did not observe and its JavaScript helper processes ran without a memory bound, because Bun ignores the V8 heap flags REA passes. Source-map trace Evidence claimed runtime node-v8 with Bun's synthetic V8 heap limit (the decoder then rejected that limit, so trace_web_source_location always failed), analysis resource failures reported heap limits Bun does not enforce, the HAR decoder claimed a fixed 192 MiB heap, and doctor reported Bun's Node.js compatibility version as the Node version.
Identify the runtime once from process.versions. Source-map reports record id bun with the Bun and Node.js compatibility versions and a null v8_heap_limit_bytes; the decoder checks the heap budget only for V8 reports and rejects a report from a runtime other than the launching one. The analysis worker reports a null heap limit under Bun, HAR limitations and failures omit heap sizes under Bun, and the doctor node check reports Bun and passes when its Node.js compatibility version is supported.
On Windows under Bun, each helper's owned Job Object now carries a commit limit of its heap budget plus a measured 512 MiB Bun runtime reserve (704 MiB for the codec and HAR decoder, 1536 MiB for the default analyzer). The native addon accepts an optional page-aligned job memory limit on process_spawn, verifies it by readback, associates a private completion port before the child is created, and reports a sticky memoryLimitReached and peak job commit on each poll; inspect reports jobMemoryLimit. A requested limit with an artifact lacking the control refuses the launch, and non-Windows launchers refuse a limit.
Reaching the limit is classified by the job notification rather than Bun's exit status: the analyzer fails the current source with a memory resource failure reporting worker_process_memory_limit_bytes, the codec returns a memory resource failure, and the HAR decoder returns its memory failure with process_memory_limit_bytes. Bun source-map Evidence records process_memory_limit_bytes, verified against the launcher. Node.js launches and outputs are unchanged.
* fix(windows): drain memory notifications after observing exit
---------
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* fix(build): emit no runtime imports for type-only bindings
Under verbatimModuleSyntax, an import whose specifiers all carry inline
`type` modifiers compiles to `import {} from "..."`, a side-effect import
that still resolves and evaluates the module. 78 compiled modules carried
one, including `import {} from "playwright-core"` in the browser scenario
session, which loaded Playwright's module graph at MCP startup.
Use top-level `import type` for these bindings and enable oxlint's
typescript/no-import-type-side-effects rule so the pattern cannot return.
Refs #1685
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* perf(mcp): load Playwright when a scenario launches, not at startup
The browser scenario and Electron active providers are constructed before
the stdio server serves, and both bound Playwright's launchers at module
load. Resolve `chromium` and `_electron` from playwright-core when a
capture opens instead, as the web module resolver already does.
MCP startup now resolves 1,312 modules (4,902 resolutions) instead of
1,598 (6,076) before reading the first request, and no longer loads
playwright-core. Provider construction, the tool catalog, and capability
inventory are unchanged.
A boundary test spawns the stdio server, initializes, lists tools, and
asserts playwright-core and isomorphic-git were not resolved; the CLI
probe now exercises the real launch path to prove detection.
Closes#1685
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Add optional finalization_ms to keep observing a captured root after SIGTERM, record the actual finalizer exit and each signal attempt, and escalate once when needed. Bind the initial root identity to captured ownership and preserve observations through cleanup uncertainty.
Fixes#1253.
Co-authored-by: Mykola Dementiev <16836724+nikolay-dementiev@users.noreply.github.com>
Co-authored-by: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com>
Keep failed reader, root descriptor, and output-tree cleanup with the caller. Drain admitted work before close, retry the same retained owners, and block new resource work while cleanup is incomplete. Preserve primary failures and complete inventory observations.
Thread ownership through JavaScript reconstruction, the CLI's one-shot scope, MCP server shutdown, verifier scripts, and test fixtures. Remove redundant ownership flags and the unused validated test wrapper.
Validate with 850 passing focused tests across 90 suites (two skipped), targeted classification and cleanup retries, static and unused-code checks, and real macOS CLI/MCP directory, ZIP, and DMG workflows. Native Windows and deep-analysis providers were not verified.
BREAKING CHANGE: Direct artifact inventory/extraction and JavaScript analysis APIs require an explicit caller-owned ArtifactResourceScope. CLI and MCP input contracts are unchanged.
Validate columns × (rows + scrollback) against a 1,000,000-cell xterm working-buffer budget, including every resize with the selected scrollback. Document the budget in the advertised MCP input and process-capture guide; never clamp caller dimensions.
Validation: default/exact-boundary schema cases, prelaunch MCP rejection, compiled CLI capture, terminal rendering, normalization, cancellation, and lifecycle checks pass on macOS. This is resource admission, not a measured serializer throughput improvement; Linux-only and real deep-analysis providers were not exercised.
BREAKING CHANGE: process scenarios whose initial or resized terminal exceeds 1,000,000 combined visible-plus-scrollback cells are now rejected before launch.
Give Ghidra and Hopper an 8 MiB aggregate retained-output budget while continuing to drain their process pipes. Expose total observed bytes at the supervisor boundary and retained bytes plus explicit truncation in provider diagnostics.
Redact known transport tokens even when the retained prefix ends inside one, preserving adjacent caller path/query evidence. Existing partial-launch and cleanup ownership remain intact.
Validation: 285 tests across 34 focused suites passed; the final cutoff-fixture refinement passed all 31 Ghidra/Hopper diagnostic tests. check:fast and architecture guards passed. Provider fixtures use real child processes; real Ghidra/Hopper applications were not verified.
Resolve current paths and JVM options and rehash source identities for each request. Probe Java modules and engine capabilities only when creating a new session; remove the superseded full configuration resolver.
Focused configuration, session retirement, cancellation, cleanup and Android MCP boundaries passed. The 34-operation retained session now performs one prerequisite probe. Protocol fixtures do not establish real JADX or JDK performance.
Detach cancelled CDP sessions within the cleanup budget and retain event-finalization failures across retries. Honor Git filesystem encodings and exclude the promise-API probe from source-read failures.
Align existing integration regressions with retained process resources, filesystem-order-independent truncation, owned skill files, explicit native access facts and streamed JSON errors.
Validation: 132 acceptance tests passed (2 skipped), 83 affected boundary tests passed, Git/JSON/CLI boundary regressions passed, check:ci, docs:check and test discovery passed. Local verification used Node 24.18.0 on macOS; cross-platform CI remains pending.