mirror of
https://github.com/morluto/rea.git
synced 2026-11-15 19:23:24 +00:00
babfc87ec0895ebd75cf32d5cb85bb09d1d1a44e
1184
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
57f75bb723 |
refactor(native): build debugger and native cancellations with a required reason (#10599)
* refactor(errors): require a reason for every analysis cancellation Add cancelledBy, the one constructor for AnalysisCancelledError. Its reason argument is required: an aborted signal, an earlier cancellation, a reason carried from an inner failure, or an OwnerCancellation when REA closed the work's owner itself. Closed adb, apktool, firmware, sqlite, gdb, web-bundle analyzer and binary-session record owners now report OwnerCancellation.ownerClosed instead of an absent reason. Firmware's predecessor wait returns its cancellation as a Result, removing an unreachable reason-less fallback. An architecture guard rejects new direct constructions, with a counted per-file baseline that can only shrink. * refactor(errors): share one aborted-signal predicate with cancelledBy * refactor(process): return a departing caller's reason from a shared startup wait * refactor(providers): build decompiler-provider cancellations with a required reason (#10587) Migrate every AnalysisCancelledError construction under src/ghidra, src/ida, src/cutter, src/jeb and src/kuna to cancelledBy and lower the guard baseline from 671 to 572. Closed Kuna target commands report OwnerCancellation.ownerClosed instead of an absent reason, and Kuna and JEB close abort their lifetimes with that typed reason. * fix(errors): read the reason of any signal-shaped cancellation source * refactor(native): build debugger and native cancellations with a required reason Migrate every AnalysisCancelledError construction under src/native, src/gdb and src/rizin to cancelledBy and delete Rizin's local rizinCancellation constructor; its reason choice becomes a CancellationReason. GDB close aborts active startups with OwnerCancellation.ownerClosed. * test(ci): cover the counted-baseline comparison behind the architecture guard * refactor(native): drop an unused cancellation import from native UI observation |
||
|
|
f6752bbe2c |
refactor(process): let debugger session cleanup errors read a confirmed stop (#10805)
* refactor(errors): read cleanup completion from dependencies instead of pushing it to dependents AnalysisError.cleanupIncomplete becomes a getter over the error's own unresolved state and its bound dependencies. The WeakRef dependents graph and resolveCleanup's push propagation are removed, and subclasses mark their initial state through markCleanupIncomplete instead of overriding a public mutable field. * fix(errors): settle bound dependencies before binding more A composite whose dependencies had released but whose status was never read stayed incomplete when a later dependency was bound. * refactor(errors): let errors read a lease group's release instead of resolving them (#10759) AnalysisCleanupLeaseGroup no longer calls resolveCleanup() on its error. The error holds the group as a release claim and reads cleanupReleased when asked, so completion follows the lease owner without a push. * chore(verify): count resolveCleanup and bindCleanupDependencies calls so they only shrink (#10763) * refactor(errors): let errors read a lease group's release instead of resolving them AnalysisCleanupLeaseGroup no longer calls resolveCleanup() on its error. The error holds the group as a release claim and reads cleanupReleased when asked, so completion follows the lease owner without a push. * chore(verify): count resolveCleanup and bindCleanupDependencies calls so they only shrink * refactor(process): let worker cleanup errors read their root epoch's release OwnedWorkerRuntime's root epoch is now an AnalysisCleanupReleaseClaim. Errors bound to it read its release when asked instead of the epoch pushing resolveCleanup() through weak references, and a runtime without a retained root binds an already-released owner. Removes the OwnedWorkerCleanupFailure structural type and four resolveCleanup() pushes; the counted baseline shrinks accordingly. * refactor(pcap): let pcap cleanup errors read command and snapshot release (#10792) Retained pcap commands, retained snapshot failures and snapshot completion descriptors now own their release and errors read it: commands and snapshot failures implement AnalysisCleanupReleaseClaim, and a failed completion-descriptor close is retried through an AnalysisCleanupLease bound to its error. Removes four resolveCleanup() pushes; the counted baseline shrinks accordingly. * refactor(process): let Darwin helper cleanup errors read their owner's release Darwin helper cache and run-token reader root cleanup now record an AnalysisCleanupRelease that every failure reports; a successful retry confirms it. Replaces the first-failure anchor that later failures depended on and the resolveCleanup() push. Removes two resolveCleanup() and two bindCleanupDependencies() calls; both counted baselines shrink. * refactor(ghidra): let Ghidra cleanup errors read the client's and checkpoint's release GhidraClient and GhidraCheckpoint bind each cleanup failure to an AnalysisCleanupRelease and confirm it when a later close or retry releases everything, instead of keeping a set of failures and pushing resolveCleanup() to each. Removes two resolveCleanup() calls; the counted baseline shrinks. * refactor(process): let debugger session cleanup errors read a confirmed stop OwnedDebuggerSessionRegistry binds each retained gdb or rizin cleanup failure to the session's AnalysisCleanupRelease and confirms it when a stop is confirmed, keeping the latest failure for retry reporting, instead of pushing resolveCleanup() to a set of failures. Removes one resolveCleanup() call; the counted baseline shrinks. * refactor(process): drop the debugger registry's unused closeOperation option Returning the latest retained failure removed the last reader of closeOperation; remove the option and the values gdb and rizin supplied. * refactor(server): let environment shutdown errors read a successful close (#10807) serveEnvironment binds each shutdown failure to an AnalysisCleanupRelease that a later successful close confirms, instead of pushing resolveCleanup() to a set of failures. The state-file retry test now also requires the earlier report to read the release. Removes one resolveCleanup() call; the counted baseline shrinks. |
||
|
|
add15d65b3 |
refactor(verify): give verifier fixture roots one lease on src/process (#10988)
* refactor(verify): give verifier fixture roots one lease on src/process * fix(verify): keep fixture registration closed, carry the lease on the caught failure, share cleanups once |
||
|
|
b3cdbb92ee |
refactor(browser): build browser cancellations with a required reason (#10581)
* refactor(errors): require a reason for every analysis cancellation Add cancelledBy, the one constructor for AnalysisCancelledError. Its reason argument is required: an aborted signal, an earlier cancellation, a reason carried from an inner failure, or an OwnerCancellation when REA closed the work's owner itself. Closed adb, apktool, firmware, sqlite, gdb, web-bundle analyzer and binary-session record owners now report OwnerCancellation.ownerClosed instead of an absent reason. Firmware's predecessor wait returns its cancellation as a Result, removing an unreachable reason-less fallback. An architecture guard rejects new direct constructions, with a counted per-file baseline that can only shrink. * refactor(errors): share one aborted-signal predicate with cancelledBy * refactor(process): return a departing caller's reason from a shared startup wait * refactor(browser): build browser cancellations with a required reason Migrate every AnalysisCancelledError construction under src/browser, src/javascript, src/electron, src/inspector and src/captures to cancelledBy and lower the guard baseline from 671 to 572. Service-worker setup aborts with OwnerCancellation.ownerClosed on close. * refactor(providers): build decompiler-provider cancellations with a required reason (#10587) Migrate every AnalysisCancelledError construction under src/ghidra, src/ida, src/cutter, src/jeb and src/kuna to cancelledBy and lower the guard baseline from 671 to 572. Closed Kuna target commands report OwnerCancellation.ownerClosed instead of an absent reason, and Kuna and JEB close abort their lifetimes with that typed reason. * fix(errors): read the reason of any signal-shaped cancellation source * test(ci): cover the counted-baseline comparison behind the architecture guard * refactor(electron): drop an unused error import from the fuse failure mapper |
||
|
|
26520bd290 |
refactor(providers): finalize apktool and shared artifact resources through runOwned (#10653)
* refactor(providers): finalize apktool and shared artifact resources through runOwned runOwned moves to the provider layer so provider sites can use it without depending on application workflows. It gains a completed-value projection (partial) for values that are not themselves partial observations, an optional signal, and cleanupLeases that bind a close failure to the exact leases whose confirmed release resolves it. ArtifactAnalysisResources.finish is removed; TShark and sigrok finalize through runOwned with the shared release as close. Apktool's hand-written release, cancellation and lease-group composition is replaced by runOwned. A failed primary now keeps a cancellation observed during final cleanup as a secondary failure, as the documented precedence requires. A counted architecture guard refuses new hand-written completed-result abort reclassification outside runOwned. * refactor(adb): finalize runtime-root work through runOwned (#10660) * refactor(adb): finalize runtime-root work through runOwned The ADB runtime-root finalizer re-derived the precedence by hand and kept its own cancellation-with-cleanup combiner. It now runs through runOwned: the work body maps snapshot failures, close releases the root lease and binds its own cleanup error, and partial projects the completed execution. A cancellation whose cleanup fails is now the shared cleanup composite with the cancellation as its primary, as runOwned produces for every other owner. * refactor(providers): keep completed values as diagnostics in runOwned and migrate four finalizers (#10691) * refactor(providers): keep completed values as diagnostics in runOwned and migrate signature, Ghidra, bundle and LLDB finalization * test(providers): run the lifecycle scenarios over every runOwned adopter shape (#10707) One table of testing.md lifecycle rows runs over partial, diagnostics, publishing and lease adopters, replacing the hand-written precedence cases it covers. * chore(lint): move runOwned's classifier baseline entry with the file |
||
|
|
b87b318ae7 |
refactor(wasm): leave WABT cancellation to the shared owners (#10796)
* fix(pcap): report a refused tool launch as an unavailable tool When a capture read's tool launch was refused with EPERM, pcap reported it as unreadable tool output (AnalysisProtocolError) instead of an unavailable tool. Pcap also never told "not executable" apart from "missing". Add classifyLaunchFailure in src/process as the one owner of which spawn errnos mean missing (ENOENT, ENOTDIR) and which mean present but not executable (EACCES, EPERM, ENOEXEC, EISDIR). Pcap, apktool and gdb used three different errno lists; all three now use it. * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * refactor(process): classify Java and adb launch refusals with the shared owner (#10598) The Ghidra and JADX Java probes and adb's version probe now take missing-versus-not-executable from classifyLaunchFailure instead of their own errno checks. ELOOP and ENAMETOOLONG join the owner's missing set, so adb keeps its existing classification and both Java probes now treat a non-directory path component as a missing runtime. * fix(pcap): preserve command launch attribution * test(pcap): expect an unknown failing stage when a limited capture tool exits unsuccessfully * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * test(lint): cover baselined files in the provider-failure classifier rule * fix(apktool): report the decoder JVM's heap exhaustion as memory, not a target refusal The supervisor now watches for a managed runtime's out-of-memory report while output streams (JVM java.lang.OutOfMemoryError, V8 'JavaScript heap out of memory'), so a retention budget cannot hide it. ProviderOutcome gains a runtime-exhausted kind and classifyProviderOutcome maps it once. Apktool decode opts in and moves to the shared classifier; Ghidra's single-purpose output token becomes the JVM runtime option and its area matching reuses the shared table. * fix(process): keep the runtime's out-of-memory report on the memory error it supports * fix(pcap): attribute a limited capture's exit through the prlimit wrapper * fix(process): keep a shortened out-of-memory line marked as shortened * fix(process): identify the refused executable for every launcher shape Name the executable on errnos Node throws synchronously from spawn (ENOEXEC, ENOTDIR, ...) and read the Windows native launcher's executable-launch constraint, so pcap attributes those refusals to the selected tool or limiter instead of an unknown stage. * test(pcap): prove synchronous launch naming with ENOTDIR on every POSIX host * fix(apktool): advise the JVM limit that governs the reported memory area * fix(ghidra): read the supervisor's parsed OOM area instead of reparsing lines * fix(sqlite,capture): read V8 heap exhaustion from streamed output, not retained stderr (#10724) The SQLite worker and the Node capture decoders now declare runtime: "v8", so the supervisor observes V8's heap report as output streams. Both classifiers read the runtime-exhausted outcome instead of matching retained stderr, so a report beyond the retention budget, or one whose process then overflowed its output budget, is still reported as memory exhaustion. * refactor(evm): classify EVMole worker outcomes through the shared provider classifier (#10716) * refactor(evm): classify EVMole worker outcomes through the shared provider classifier The EVMole worker's cancellation, deadline, output budget and CPU/file-size signals now go through classifyProviderOutcome; only the prlimit launch refusal and the reserved EFBIG exit remain in its dialect. The worker is opted into V8 exhaustion scanning so a heap report names its fixed 256 MiB heap. providerOutcomeOf now reads a launch refusal only from a spawn errno, so a private-storage or carrier read errno is no longer reported as a limiter launch failure. * fix(evm): keep a stream failure's exit status and update Linux worker expectations * refactor(process): read launch refusals through the launcher identity owner * refactor(wasm): classify WABT command outcomes through the shared provider classifier (#10727) * refactor(wasm): classify WABT command outcomes through the shared provider classifier WABT's cancellation, command deadline, output budget, and inherited-limit signals now go through classifyProviderOutcome; its dialect keeps only the configuration-probe and launch-refusal unavailability and the unclassified-exit output error. A tool ended by SIGXCPU/SIGXFSZ or the memory limit is now a resource constraint instead of an output error, and a refused launch in the producer phase is reported as unavailable. The shared timeout context gains the analysis setting that selected the deadline, and the output-limit context may name its exceeded budget. * fix(wasm): keep setup guidance when a WABT version probe's output cannot be collected * refactor(providers): classify raw provider failures through one owner * refactor(process): build classified cancellations with cancelledBy and the carried caller reason * chore(lint): count runOwned's close-failure mapper from main in the classifier baseline * fix(process): carry the runtime's exhaustion report on every memory error that claims it SQLite and historical-capture memory errors recognised a streamed V8 heap report but dropped it, so a report outside retained output reached callers without its source line or omission flags. One projection, runtimeExhaustionReport, now owns that shape for the shared classifier and both consumers. Also lowers the EVMole and WABT cancellation-constructor baselines. * fix(process): keep the provider's recovery for a native-thread exhaustion report The shared classifier replaced the provider-supplied recovery with generic capacity advice whenever the JVM reported it could not create a native thread, dropping Apktool's launcher guidance and flipping retryable to true. The provider's recovery now wins; the capacity advice remains the fallback for providers that supply none. * refactor(pwntools): classify pwntools failures through the shared provider classifier (#10782) * refactor(pwntools): classify pwntools failures through the shared provider classifier pwntools' per-site classifier is replaced by pwntoolsFailureDialect for classifyProviderFailure. Command outcomes go through classifyProviderOutcome, launch refusals through launcherRefusalOf instead of a 'spawn ' syscall prefix check, the input limit through the file dialect's fileSize, and the cleanup report through commandCleanup. The shared read cancellation now carries the reader's partial observation, and resource-signal reports accept provider detail. * fix(pwntools): report a failed command's output once and expect resource_constraint for overflow The shared outcome owner already attaches the command's output as capturedOutput, so the pwntools adapter fallback no longer copies the same text into diagnostics.stdout, diagnostics.stderr and diagnostics.captured_output; diagnostics keep the exit facts. Update the overflow expectations the dialect migration missed (layout provider cleanup and over-budget rows, pwntools cleanup) to resource_constraint. * refactor(wasm): leave WABT cancellation to the shared owners WabtFailures matched any Error named AbortError as a cancellation. No WABT path produces one: reads, path checks and owned commands report cancellation as ArtifactReaderFailure or OwnedCommandFailure, which classifyProviderFailure and classifyProviderOutcome already classify with the caller's reason. The provider's two signal checks now build the cancellation with cancelledBy. Lowers the AnalysisCancelledError constructor baseline for both WABT files to zero. * fix(wasm): report a cancelled snapshot write as the caller's cancellation The private snapshot write passed the caller's signal to Node's writeFile, whose abort envelope reached the dialect's unclassified output failure once the name-based AbortError guess was removed. The write now turns the envelope carrying its own signal's reason into cancelledBy at the producer. * refactor(firmware): classify firmware failures through the shared provider classifier (#10810) Firmware producers now report their own deadline expiry: the start check, the output inventory and launcher admission throw the phase timeout where they observe the abort, and a read the phase signal cancelled reports it through the dialect's interruption. The classifier no longer rereads a cancellation's reason as a timeout. A new readCleanup hook keeps firmware's cleanup report shape. |
||
|
|
2caedcfb57 |
refactor(platform): give the host platform one owner and ratchet ambient process.platform reads (#10911)
* refactor(platform): give the host platform one owner and ratchet ambient process.platform reads * refactor(process): pass the host platform to process sampling instead of reading it ambiently #10755 added two process.platform reads (ps selection in process sampling and the desktop build doctor's ps fact) after the host-platform ratchet was measured. The desktop fact already receives the host platform from doctor; process sampling now receives it from the capture harness, removing all five ambient reads there. |
||
|
|
b655645608 |
refactor(errors): give caller aborts a typed reason at the adapters (#10633)
* refactor(errors): give caller aborts a typed reason at the adapters Squashes 908813551f, 87858de4dc (fix(mcp): preserve cancellation reasons in handlers) and fa151dc3f6 (test(server): race handler-entry gates against the triggering tool call) onto main without #10566's pre-squash commits. * refactor(errors): give owner-initiated aborts a typed reason outside the browser adapters (#10692) * refactor(errors): give owner-initiated aborts a typed reason outside the browser adapters * refactor(verify): keep the abort-reason scan receiver-independent Playwright's route.abort takes a network error code; the one call site now names its default code instead of the guard exempting a variable name. * refactor(browser): give owner-initiated CDP aborts typed reasons (#10706) * refactor(browser): give owner-initiated CDP aborts typed reasons * fix(browser): give the page-side request fetch page-native abort reasons The request callback runs in the page through page.evaluate and cannot reach REA's modules. Define its deadline and cleanup reasons as DOMExceptions inside the callback, and make the test fake evaluate the callback from its source so module imports are unavailable, as in a page. * test(process): expect the reader close's typed owner reason Closing the Darwin run-token reader aborts its compilation with OwnerCancellation.ownerClosed since the owner-abort change in this PR; the boundary test still expected the default DOMException. * fix(server): report HTTP session replacement and shutdown to pending tools as an owner close |
||
|
|
df0bdd9f58 |
refactor(process): let Darwin helper cleanup errors read their owner's release (#10801)
* refactor(errors): read cleanup completion from dependencies instead of pushing it to dependents AnalysisError.cleanupIncomplete becomes a getter over the error's own unresolved state and its bound dependencies. The WeakRef dependents graph and resolveCleanup's push propagation are removed, and subclasses mark their initial state through markCleanupIncomplete instead of overriding a public mutable field. * fix(errors): settle bound dependencies before binding more A composite whose dependencies had released but whose status was never read stayed incomplete when a later dependency was bound. * refactor(errors): let errors read a lease group's release instead of resolving them (#10759) AnalysisCleanupLeaseGroup no longer calls resolveCleanup() on its error. The error holds the group as a release claim and reads cleanupReleased when asked, so completion follows the lease owner without a push. * chore(verify): count resolveCleanup and bindCleanupDependencies calls so they only shrink (#10763) * refactor(errors): let errors read a lease group's release instead of resolving them AnalysisCleanupLeaseGroup no longer calls resolveCleanup() on its error. The error holds the group as a release claim and reads cleanupReleased when asked, so completion follows the lease owner without a push. * chore(verify): count resolveCleanup and bindCleanupDependencies calls so they only shrink * refactor(process): let worker cleanup errors read their root epoch's release OwnedWorkerRuntime's root epoch is now an AnalysisCleanupReleaseClaim. Errors bound to it read its release when asked instead of the epoch pushing resolveCleanup() through weak references, and a runtime without a retained root binds an already-released owner. Removes the OwnedWorkerCleanupFailure structural type and four resolveCleanup() pushes; the counted baseline shrinks accordingly. * refactor(pcap): let pcap cleanup errors read command and snapshot release (#10792) Retained pcap commands, retained snapshot failures and snapshot completion descriptors now own their release and errors read it: commands and snapshot failures implement AnalysisCleanupReleaseClaim, and a failed completion-descriptor close is retried through an AnalysisCleanupLease bound to its error. Removes four resolveCleanup() pushes; the counted baseline shrinks accordingly. * refactor(process): let Darwin helper cleanup errors read their owner's release Darwin helper cache and run-token reader root cleanup now record an AnalysisCleanupRelease that every failure reports; a successful retry confirms it. Replaces the first-failure anchor that later failures depended on and the resolveCleanup() push. Removes two resolveCleanup() and two bindCleanupDependencies() calls; both counted baselines shrink. * refactor(ghidra): let Ghidra cleanup errors read the client's and checkpoint's release (#10802) GhidraClient and GhidraCheckpoint bind each cleanup failure to an AnalysisCleanupRelease and confirm it when a later close or retry releases everything, instead of keeping a set of failures and pushing resolveCleanup() to each. Removes two resolveCleanup() calls; the counted baseline shrinks. |
||
|
|
85df21992f |
refactor(native): read retained inventory views through the operation fact contracts (#10883)
* refactor(native): read retained inventory views through the operation fact contracts * refactor(native): read matching inventories through the operation fact contracts (#10887) * refactor(native): read dispatch symbol fallbacks as lenient name facts at the port (#10889) * refactor(native): read dispatch symbol fallbacks as lenient name facts at the port * test(native): accept undeclared name-row fields in both dispatch consumers * refactor(native): read literal searches and overview counts as operation facts (#10894) * refactor(native): read literal searches and overview counts as operation facts * refactor(native): read addressed inventory rows as operation facts in every reader (#10899) * refactor(native): read addressed inventory rows as operation facts in every reader * test(native): cover xrefs name resolution through the name fact contract * test(server): pin procedure completion to the procedure inventory contract |
||
|
|
d0fee4e58e |
fix(mcp): re-emit advertised patterns in a portable regex grammar (#10582)
* test(mcp): check advertised schemas against a portable dialect in every profile * fix(mcp): re-emit advertised patterns in a portable regex grammar * fix(mcp): validate advertised dialect by selected profile * fix(mcp): preserve schema widening through references * fix(mcp): refuse zero-padded repeat bounds and record host-specific path patterns * fix(mcp): keep references valid when presentation widens their targets * fix(mcp): relax references into negations and conditionals presentation may remove * fix(mcp): keep astral literals and dynamic references widening in every mode * fix(mcp): omit astral literals and relax untracked references when presentation widens * fix(mcp): read reference pointers by schema position, not segment spelling * fix(mcp): protect references into collapsing boolean unions and keep referencing branches out of the collapse * fix(mcp): omit patterns whose classes name astral characters * fix(mcp): decide union collapse and pointer protection from canonical branches * docs(mcp): document non-u astral matching and pin BMP agreement across V8 modes * test(mcp): expect the advertised base64 schema to omit the unbounded pad-bit probe * fix(mcp): protect references into unevaluated keywords lost evaluation removes * fix(mcp): emit stack-safe classes with non-ASCII members and protect draft-07 reference siblings * fix(mcp): protect references into literal siblings of relaxed draft-07 references |
||
|
|
5bf66f7500 |
refactor(domain): one owner for the non-array record predicate (#10588)
* refactor(domain): one owner for the non-array record predicate Thirty-four source files each declared isRecord as a non-null object that is not an array, and six more spelled the same predicate as isObject, isSchemaRecord or isStorageRecord. They now import isRecord from src/domain/isRecord.ts, whose overloads keep JsonValue narrowing for the desktop and environment readers. DshCordisPatch's predicate also excludes Cordis expressions, so it is renamed isPatchRecord. architecture-guards refuses a new local copy under any name. The seven files that still hold one are listed and must leave the list when their copy goes. * fix(guards): count record predicate copies precisely * test(hopper): retry after confirmed application exit * fix: reject stale record predicate exceptions |
||
|
|
d5e0747025 |
refactor(process): build infrastructure cancellations with a required reason (#10595)
* refactor(errors): require a reason for every analysis cancellation Add cancelledBy, the one constructor for AnalysisCancelledError. Its reason argument is required: an aborted signal, an earlier cancellation, a reason carried from an inner failure, or an OwnerCancellation when REA closed the work's owner itself. Closed adb, apktool, firmware, sqlite, gdb, web-bundle analyzer and binary-session record owners now report OwnerCancellation.ownerClosed instead of an absent reason. Firmware's predecessor wait returns its cancellation as a Result, removing an unreachable reason-less fallback. An architecture guard rejects new direct constructions, with a counted per-file baseline that can only shrink. * refactor(errors): share one aborted-signal predicate with cancelledBy * refactor(process): return a departing caller's reason from a shared startup wait * refactor(providers): build decompiler-provider cancellations with a required reason (#10587) Migrate every AnalysisCancelledError construction under src/ghidra, src/ida, src/cutter, src/jeb and src/kuna to cancelledBy and lower the guard baseline from 671 to 572. Closed Kuna target commands report OwnerCancellation.ownerClosed instead of an absent reason, and Kuna and JEB close abort their lifetimes with that typed reason. * refactor(process): build infrastructure cancellations with a required reason Migrate every AnalysisCancelledError construction in shared process, provider, artifact, domain, server and CLI code and in the smaller providers to cancelledBy, lowering the guard baseline from 671 to 566. Option bags that carried a cause are split so the cancellation branch cannot receive one. * fix(errors): read the reason of any signal-shaped cancellation source * test(ci): cover the counted-baseline comparison behind the architecture guard |
||
|
|
5d5ab53536 |
refactor(native): select ELF sections through the keyed owner (#10780)
* refactor(native): select ELF sections through the keyed owner * test(native): pin returned exports and versions for repeated version sections * refactor(nativeaot): read neither of repeated frozen object regions (#10790) * refactor(nativeaot): read neither of repeated frozen object regions through the keyed owner * refactor(parsers): retire every first-match section lookup (#10793) * fix(nativeaot): report an ambiguous frozen object region as partial (#10812) * refactor(native): select program headers and load commands through the keyed owner (#10827) * refactor(native): select the GOT base and dependency segments through the keyed owner (#10847) * refactor(native): select the GOT base and dependency segments through the keyed owner resolveGotBase selects the SHT_DYNAMIC section and the allocated .got.plt/.got sections with uniqueKeyed, so a repeat leaves the GOT base unknown instead of taking the first match; elfDependencies reads PT_LOAD segments through the same keyed program table as PT_DYNAMIC. A new keyed-first-match guard recognizes a find/findLast or filter-then-[0] whose predicate compares a key field, whatever the table is called; existing matches are baselined. The unwind fixture can declare PT_DYNAMIC headers and repeated .dynamic/.got.plt sections. * test(native): pin the PT_DYNAMIC path and destructured keyed lookups The keyed-first-match guard moves to scripts/verify/keyed-first-match.mjs with focused tests, and now recognizes a destructured key in any position and a destructured filter predicate. The single PT_DYNAMIC unwind test declares .dynamic as SHT_PROGBITS so only the program header supplies DT_PLTGOT, and asserts the resolved ranges. * fix(macho): refuse repeated chained-fixup and dyld-info tables (#10850) parseMachoLayout kept the last LC_DYLD_CHAINED_FIXUPS range and merged the rebase/bind streams of every LC_DYLD_INFO(_ONLY) command. A repeat now refuses the slice as malformed. NativeMachoInspection's chained import-name reader already declined repeated LC_DYLD_CHAINED_FIXUPS; that rule is now covered by a test. * fix(verify): count a filter index only on the filter's own result |
||
|
|
45881575a6 |
ci(windows): validate advertised MCP schemas in the Windows lane (#10785)
* ci(windows): validate host-absolute path schemas in the Windows lane Windows hosts advertise their own absolute-path pattern (#7151). The lane compiled it through advertisedDialect.test.ts but never validated a Windows path against it. Run absoluteLocalPathSchema.test.ts there, select the lane when the pattern's owner changes, and guard both schema checks in the lane. Refs #10517 * ci(windows): run live MCP schema validity in the Windows lane toolSchemaValidity.test.ts compared the live advertisement with the POSIX-generated .cache/mcp-tool-catalog.json, so it could not run where the Windows lane skips artifact generation. Move the generated-catalog cases into generatedToolCatalog.test.ts, share the reference walkers through the advertised-schema fixture, and add the live-server file to the curated Windows lane and its scope. |
||
|
|
2af3be132c |
refactor(process): let worker cleanup errors read their root epoch's release (#10789)
* refactor(errors): read cleanup completion from dependencies instead of pushing it to dependents AnalysisError.cleanupIncomplete becomes a getter over the error's own unresolved state and its bound dependencies. The WeakRef dependents graph and resolveCleanup's push propagation are removed, and subclasses mark their initial state through markCleanupIncomplete instead of overriding a public mutable field. * fix(errors): settle bound dependencies before binding more A composite whose dependencies had released but whose status was never read stayed incomplete when a later dependency was bound. * refactor(errors): let errors read a lease group's release instead of resolving them (#10759) AnalysisCleanupLeaseGroup no longer calls resolveCleanup() on its error. The error holds the group as a release claim and reads cleanupReleased when asked, so completion follows the lease owner without a push. * chore(verify): count resolveCleanup and bindCleanupDependencies calls so they only shrink (#10763) * refactor(errors): let errors read a lease group's release instead of resolving them AnalysisCleanupLeaseGroup no longer calls resolveCleanup() on its error. The error holds the group as a release claim and reads cleanupReleased when asked, so completion follows the lease owner without a push. * chore(verify): count resolveCleanup and bindCleanupDependencies calls so they only shrink * refactor(process): let worker cleanup errors read their root epoch's release OwnedWorkerRuntime's root epoch is now an AnalysisCleanupReleaseClaim. Errors bound to it read its release when asked instead of the epoch pushing resolveCleanup() through weak references, and a runtime without a retained root binds an already-released owner. Removes the OwnedWorkerCleanupFailure structural type and four resolveCleanup() pushes; the counted baseline shrinks accordingly. * refactor(pcap): let pcap cleanup errors read command and snapshot release (#10792) Retained pcap commands, retained snapshot failures and snapshot completion descriptors now own their release and errors read it: commands and snapshot failures implement AnalysisCleanupReleaseClaim, and a failed completion-descriptor close is retried through an AnalysisCleanupLease bound to its error. Removes four resolveCleanup() pushes; the counted baseline shrinks accordingly. |
||
|
|
43934682ab |
refactor(gdb): parse MI result records with one typed record parser (#10799)
* refactor(gdb): parse MI result records with one typed record parser GdbSessionManager recognized ^done with a prefix regex at seven sites, kept a hand-written span scanner and a second character scanner for -list-thread-groups, and decoded C-string fields with a dynamic RegExp. src/gdb/GdbMiRecord.ts now parses a result record into its token, class and typed results (C-string bytes, tuples, value lists and result lists), and returns a typed malformed-mi-record failure with a reason and offset. The done checks, the thread-group PID inventory and the C-string field reader use it; the stream dispatcher reads only the record header through the same module. An architecture guard keeps MI result-record regexes in the owner. * perf(gdb): encode each unescaped C-string run once The MI C-string decoder allocated a Buffer per unescaped character, pushed every byte into a number array, and copied the rest of the line for each hex or octal escape. It now validates unescaped runs in place, encodes each run once, reads escapes with sticky patterns, and joins the chunks once. On a 12.1 MiB groups reply: 887/832 ms elapsed and 818/775 ms CPU before, 76/76 ms elapsed and 131/128 ms CPU after; peak RSS 152-170 MiB both. * test(gdb): refuse a malformed ^done for a startup setting through a real session A fake GDB answers -gdb-set auto-load off with ^done,msg="unterminated. The session must not start: the typed MI record parser refuses the record, where main's ^done prefix match accepted it (the case fails against main's GdbSessionManager). * feat(gdb): record the GDB version from -gdb-version in session Evidence (#10865) * feat(gdb): record the GDB version from -gdb-version in session Evidence Startup now asks -gdb-version before the auto-load setting and reads its first console stream record through a new MI stream-record parser (parseGdbMiStreamRecord). Each session's Evidence names that version; an unrecognised banner, malformed record or refused query leaves it null (unknown), as before. Fake GDB fixtures answer -gdb-version from one owner in gdbTestHelpers: a stdin preamble for scripted fakes and answerFakeGdbStartup for in-process fakes, so scenarios model only their own commands. * fix(gdb): leave a lossily decoded version unknown and frame fake startup replies by line * test(gdb): reject unmodeled commands in the lossy version banner fixture * test(gdb): refuse commands the scripted fake GDBs do not model (#10947) * test(gdb): refuse commands the scripted fake GDBs do not model * test(gdb): match the migrated fakes' special commands exactly |
||
|
|
4e84af7531 |
fix(test): run the Hopper launch-failure CLI case in fresh processes on macOS CI (#10825)
The case checks that a one-shot CLI exits after a retained-cleanup failure and that the operating system then releases the Hopper target lease to a retry. Since #10412, `cli.run` serves plain commands on the file's shared CLI process. That process keeps the lease, as the cleanup-ownership rules require while cleanup is incomplete, and never exits between commands, so the retry was refused as "already open" and the final lease check failed on macOS. Run both attempts with `freshProcess: true`, which the fixture provides for process-exit facts. The case is macOS-only because target leases are taken only on the macOS launcher route, and no CI lane ran it, so add it to the Apple lane and its change scope. |
||
|
|
479abaf3b2 |
refactor(python): read pyc and PYZ marshal values through one shared reader (#10806)
* refactor(python): read pyc and PYZ marshal values through one shared reader * refactor(python): read pyc 64-bit values and header fields through shared readers (#10834) |
||
|
|
8443930bd3 |
refactor(limits): declare the Node timer bound and duration schema once (#10640)
* refactor(limits): declare the Node timer bound and duration schema once Fifteen modules re-declared 2_147_483_647 as their own timer maximum and eleven built the same 1..2^31-1 millisecond schema. They now use MAX_NODE_TIMER_DELAY_MS and timerDurationMsSchema from src/domain/analysisResourceLimits.ts, and an architecture guard rejects the literal outside that owner and five non-timer int32 bounds. The generated MCP tool catalog is byte-identical. * refactor(limits): keep the JVM processor-count bound separate from the timer bound REA_JADX_ACTIVE_PROCESSOR_COUNT is a Java int count, not a timer delay, so it keeps its own named bound and a documented exception in the signed 32-bit guard. Remove the timer-bound and zod imports the duration-schema migration left unused. * refactor(limits): keep the TShark packet-count bound separate from the timer bound packet_limit is passed to TShark's -c as a C int packet count, not a timer delay, so it keeps its own named bound and a documented exception in the signed 32-bit guard. |
||
|
|
6a4caa065b |
refactor(providers): classify raw provider failures through one owner (#10757)
* fix(pcap): report a refused tool launch as an unavailable tool When a capture read's tool launch was refused with EPERM, pcap reported it as unreadable tool output (AnalysisProtocolError) instead of an unavailable tool. Pcap also never told "not executable" apart from "missing". Add classifyLaunchFailure in src/process as the one owner of which spawn errnos mean missing (ENOENT, ENOTDIR) and which mean present but not executable (EACCES, EPERM, ENOEXEC, EISDIR). Pcap, apktool and gdb used three different errno lists; all three now use it. * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * refactor(process): classify Java and adb launch refusals with the shared owner (#10598) The Ghidra and JADX Java probes and adb's version probe now take missing-versus-not-executable from classifyLaunchFailure instead of their own errno checks. ELOOP and ENAMETOOLONG join the owner's missing set, so adb keeps its existing classification and both Java probes now treat a non-directory path component as a missing runtime. * fix(pcap): preserve command launch attribution * test(pcap): expect an unknown failing stage when a limited capture tool exits unsuccessfully * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * test(lint): cover baselined files in the provider-failure classifier rule * fix(apktool): report the decoder JVM's heap exhaustion as memory, not a target refusal The supervisor now watches for a managed runtime's out-of-memory report while output streams (JVM java.lang.OutOfMemoryError, V8 'JavaScript heap out of memory'), so a retention budget cannot hide it. ProviderOutcome gains a runtime-exhausted kind and classifyProviderOutcome maps it once. Apktool decode opts in and moves to the shared classifier; Ghidra's single-purpose output token becomes the JVM runtime option and its area matching reuses the shared table. * fix(process): keep the runtime's out-of-memory report on the memory error it supports * fix(pcap): attribute a limited capture's exit through the prlimit wrapper * fix(process): keep a shortened out-of-memory line marked as shortened * fix(process): identify the refused executable for every launcher shape Name the executable on errnos Node throws synchronously from spawn (ENOEXEC, ENOTDIR, ...) and read the Windows native launcher's executable-launch constraint, so pcap attributes those refusals to the selected tool or limiter instead of an unknown stage. * test(pcap): prove synchronous launch naming with ENOTDIR on every POSIX host * fix(apktool): advise the JVM limit that governs the reported memory area * fix(ghidra): read the supervisor's parsed OOM area instead of reparsing lines * fix(sqlite,capture): read V8 heap exhaustion from streamed output, not retained stderr (#10724) The SQLite worker and the Node capture decoders now declare runtime: "v8", so the supervisor observes V8's heap report as output streams. Both classifiers read the runtime-exhausted outcome instead of matching retained stderr, so a report beyond the retention budget, or one whose process then overflowed its output budget, is still reported as memory exhaustion. * refactor(evm): classify EVMole worker outcomes through the shared provider classifier (#10716) * refactor(evm): classify EVMole worker outcomes through the shared provider classifier The EVMole worker's cancellation, deadline, output budget and CPU/file-size signals now go through classifyProviderOutcome; only the prlimit launch refusal and the reserved EFBIG exit remain in its dialect. The worker is opted into V8 exhaustion scanning so a heap report names its fixed 256 MiB heap. providerOutcomeOf now reads a launch refusal only from a spawn errno, so a private-storage or carrier read errno is no longer reported as a limiter launch failure. * fix(evm): keep a stream failure's exit status and update Linux worker expectations * refactor(process): read launch refusals through the launcher identity owner * refactor(wasm): classify WABT command outcomes through the shared provider classifier (#10727) * refactor(wasm): classify WABT command outcomes through the shared provider classifier WABT's cancellation, command deadline, output budget, and inherited-limit signals now go through classifyProviderOutcome; its dialect keeps only the configuration-probe and launch-refusal unavailability and the unclassified-exit output error. A tool ended by SIGXCPU/SIGXFSZ or the memory limit is now a resource constraint instead of an output error, and a refused launch in the producer phase is reported as unavailable. The shared timeout context gains the analysis setting that selected the deadline, and the output-limit context may name its exceeded budget. * fix(wasm): keep setup guidance when a WABT version probe's output cannot be collected * refactor(providers): classify raw provider failures through one owner * refactor(process): build classified cancellations with cancelledBy and the carried caller reason * chore(lint): count runOwned's close-failure mapper from main in the classifier baseline * fix(process): carry the runtime's exhaustion report on every memory error that claims it SQLite and historical-capture memory errors recognised a streamed V8 heap report but dropped it, so a report outside retained output reached callers without its source line or omission flags. One projection, runtimeExhaustionReport, now owns that shape for the shared classifier and both consumers. Also lowers the EVMole and WABT cancellation-constructor baselines. * fix(process): keep the provider's recovery for a native-thread exhaustion report The shared classifier replaced the provider-supplied recovery with generic capacity advice whenever the JVM reported it could not create a native thread, dropping Apktool's launcher guidance and flipping retryable to true. The provider's recovery now wins; the capacity advice remains the fallback for providers that supply none. * refactor(pwntools): classify pwntools failures through the shared provider classifier (#10782) * refactor(pwntools): classify pwntools failures through the shared provider classifier pwntools' per-site classifier is replaced by pwntoolsFailureDialect for classifyProviderFailure. Command outcomes go through classifyProviderOutcome, launch refusals through launcherRefusalOf instead of a 'spawn ' syscall prefix check, the input limit through the file dialect's fileSize, and the cleanup report through commandCleanup. The shared read cancellation now carries the reader's partial observation, and resource-signal reports accept provider detail. * fix(pwntools): report a failed command's output once and expect resource_constraint for overflow The shared outcome owner already attaches the command's output as capturedOutput, so the pwntools adapter fallback no longer copies the same text into diagnostics.stdout, diagnostics.stderr and diagnostics.captured_output; diagnostics keep the exit facts. Update the overflow expectations the dialect migration missed (layout provider cleanup and over-budget rows, pwntools cleanup) to resource_constraint. |
||
|
|
c06a0b9ee8 |
feat(pcap): read tshark JSON packets through one envelope owner with an adjustable expansion bound (#10788)
* refactor(pcap): read tshark JSON packets through one envelope owner PcapOutput and the packet-capture reader each decoded tshark -T json and checked the packet envelope. The capture reader let SyntaxError escape and accepted any shape until its field schema ran. src/pcap/TsharkJsonPackets.ts now owns the envelope (malformed JSON, the packet array, each packet's _source.layers) as typed failures, and the pcap byte and expansion budget. Both consumers map those failures to their existing error kinds. An architecture guard keeps _source.layers reads in the owner. * fix(captures): keep producer output on a refused packet reply parsePacketOutput threw AnalysisOutputError itself, so the provider's failure mapping returned it without the captured stdout and stderr, both for envelope refusals and for unordered or out-of-limit frames. It now returns a Result with the reason and cause, and the provider builds the AnalysisOutputError with capturedOutput. * feat(captures): bound packet-capture JSON expansion by an adjustable setting The capture path parsed TShark's selected-field JSON without the expansion estimate the pcap reader charges. It now reads through readTsharkJsonPackets under capture.packet_json_expansion_bytes (REA_CAPTURE_PACKET_JSON_EXPANSION_BYTES). The estimate charges at most 130 bytes per code unit and the output is one Node string, so no admissible output reaches 69,793,215,440 bytes; the default and maximum are 128 GiB, so the budget refuses only when lowered. A refusal is an adjustable_budget resource constraint naming the setting and keeps the producer output; a malformed launch seed is refused before the capture is read. |
||
|
|
04cb416726 | chore(architecture): lower the stale McpRegistrationGit cleanup-composition baseline | ||
|
|
dd7597a108 |
refactor(errors): read cleanup completion from dependencies instead of pushing it to dependents (#10744)
* refactor(errors): read cleanup completion from dependencies instead of pushing it to dependents AnalysisError.cleanupIncomplete becomes a getter over the error's own unresolved state and its bound dependencies. The WeakRef dependents graph and resolveCleanup's push propagation are removed, and subclasses mark their initial state through markCleanupIncomplete instead of overriding a public mutable field. * fix(errors): settle bound dependencies before binding more A composite whose dependencies had released but whose status was never read stayed incomplete when a later dependency was bound. * refactor(errors): let errors read a lease group's release instead of resolving them (#10759) AnalysisCleanupLeaseGroup no longer calls resolveCleanup() on its error. The error holds the group as a release claim and reads cleanupReleased when asked, so completion follows the lease owner without a push. * chore(verify): count resolveCleanup and bindCleanupDependencies calls so they only shrink (#10763) * refactor(errors): let errors read a lease group's release instead of resolving them AnalysisCleanupLeaseGroup no longer calls resolveCleanup() on its error. The error holds the group as a release claim and reads cleanupReleased when asked, so completion follows the lease owner without a push. * chore(verify): count resolveCleanup and bindCleanupDependencies calls so they only shrink |
||
|
|
c296c91770 |
fix(apktool): report the decoder JVM's heap exhaustion as memory, not a target refusal (#10634)
* fix(pcap): report a refused tool launch as an unavailable tool When a capture read's tool launch was refused with EPERM, pcap reported it as unreadable tool output (AnalysisProtocolError) instead of an unavailable tool. Pcap also never told "not executable" apart from "missing". Add classifyLaunchFailure in src/process as the one owner of which spawn errnos mean missing (ENOENT, ENOTDIR) and which mean present but not executable (EACCES, EPERM, ENOEXEC, EISDIR). Pcap, apktool and gdb used three different errno lists; all three now use it. * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * refactor(process): classify Java and adb launch refusals with the shared owner (#10598) The Ghidra and JADX Java probes and adb's version probe now take missing-versus-not-executable from classifyLaunchFailure instead of their own errno checks. ELOOP and ENAMETOOLONG join the owner's missing set, so adb keeps its existing classification and both Java probes now treat a non-directory path component as a missing runtime. * fix(pcap): preserve command launch attribution * test(pcap): expect an unknown failing stage when a limited capture tool exits unsuccessfully * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * test(lint): cover baselined files in the provider-failure classifier rule * fix(apktool): report the decoder JVM's heap exhaustion as memory, not a target refusal The supervisor now watches for a managed runtime's out-of-memory report while output streams (JVM java.lang.OutOfMemoryError, V8 'JavaScript heap out of memory'), so a retention budget cannot hide it. ProviderOutcome gains a runtime-exhausted kind and classifyProviderOutcome maps it once. Apktool decode opts in and moves to the shared classifier; Ghidra's single-purpose output token becomes the JVM runtime option and its area matching reuses the shared table. * fix(process): keep the runtime's out-of-memory report on the memory error it supports * fix(pcap): attribute a limited capture's exit through the prlimit wrapper * fix(process): keep a shortened out-of-memory line marked as shortened * fix(process): identify the refused executable for every launcher shape Name the executable on errnos Node throws synchronously from spawn (ENOEXEC, ENOTDIR, ...) and read the Windows native launcher's executable-launch constraint, so pcap attributes those refusals to the selected tool or limiter instead of an unknown stage. * test(pcap): prove synchronous launch naming with ENOTDIR on every POSIX host * fix(apktool): advise the JVM limit that governs the reported memory area * fix(ghidra): read the supervisor's parsed OOM area instead of reparsing lines * fix(sqlite,capture): read V8 heap exhaustion from streamed output, not retained stderr (#10724) The SQLite worker and the Node capture decoders now declare runtime: "v8", so the supervisor observes V8's heap report as output streams. Both classifiers read the runtime-exhausted outcome instead of matching retained stderr, so a report beyond the retention budget, or one whose process then overflowed its output budget, is still reported as memory exhaustion. * refactor(evm): classify EVMole worker outcomes through the shared provider classifier (#10716) * refactor(evm): classify EVMole worker outcomes through the shared provider classifier The EVMole worker's cancellation, deadline, output budget and CPU/file-size signals now go through classifyProviderOutcome; only the prlimit launch refusal and the reserved EFBIG exit remain in its dialect. The worker is opted into V8 exhaustion scanning so a heap report names its fixed 256 MiB heap. providerOutcomeOf now reads a launch refusal only from a spawn errno, so a private-storage or carrier read errno is no longer reported as a limiter launch failure. * fix(evm): keep a stream failure's exit status and update Linux worker expectations * refactor(process): read launch refusals through the launcher identity owner * refactor(wasm): classify WABT command outcomes through the shared provider classifier (#10727) * refactor(wasm): classify WABT command outcomes through the shared provider classifier WABT's cancellation, command deadline, output budget, and inherited-limit signals now go through classifyProviderOutcome; its dialect keeps only the configuration-probe and launch-refusal unavailability and the unclassified-exit output error. A tool ended by SIGXCPU/SIGXFSZ or the memory limit is now a resource constraint instead of an output error, and a refused launch in the producer phase is reported as unavailable. The shared timeout context gains the analysis setting that selected the deadline, and the output-limit context may name its exceeded budget. * fix(wasm): keep setup guidance when a WABT version probe's output cannot be collected * refactor(process): build classified cancellations with cancelledBy and the carried caller reason * chore(lint): count runOwned's close-failure mapper from main in the classifier baseline * fix(process): carry the runtime's exhaustion report on every memory error that claims it SQLite and historical-capture memory errors recognised a streamed V8 heap report but dropped it, so a report outside retained output reached callers without its source line or omission flags. One projection, runtimeExhaustionReport, now owns that shape for the shared classifier and both consumers. Also lowers the EVMole and WABT cancellation-constructor baselines. * fix(process): keep the provider's recovery for a native-thread exhaustion report The shared classifier replaced the provider-supplied recovery with generic capacity advice whenever the JVM reported it could not create a native thread, dropping Apktool's launcher guidance and flipping retryable to true. The provider's recovery now wins; the capacity advice remains the fallback for providers that supply none. |
||
|
|
254bb21857 |
refactor(browser): send only CDP commands with registered result schemas (#10666)
* refactor(browser): send only CDP commands with registered result schemas * refactor(browser): open Playwright CDP sessions only through the registered-command owner * fix(browser): keep the restore obligation for an applied override with a malformed reply A schema-rejected success reply means the browser applied the Emulation override, so the attached environment owner records the reset obligation before reporting the protocol error. Only a rejected or unanswered command leaves no obligation. * refactor(browser): open verifier-script CDP sessions through the registered-command owner (#10710) * fix(browser): register the CDP commands JavaScript verifiers send The verifier scripts send Browser.close, Page.createIsolatedWorld, Page.navigate, Page.reload, Target.activateTarget, Target.closeTarget and Target.createTarget through CdpConnection, which now admits every reply through its command's result schema. Register those schemas, refuse an unregistered run-time name as a typed malformed reply instead of a TypeError, and check script send literals against the registry. * fix(browser): keep Target.closeTarget's success member for the verifiers |
||
|
|
1f7884b5b9 |
refactor(process): classify owned command outcomes through one owner (#10628)
* fix(pcap): report a refused tool launch as an unavailable tool When a capture read's tool launch was refused with EPERM, pcap reported it as unreadable tool output (AnalysisProtocolError) instead of an unavailable tool. Pcap also never told "not executable" apart from "missing". Add classifyLaunchFailure in src/process as the one owner of which spawn errnos mean missing (ENOENT, ENOTDIR) and which mean present but not executable (EACCES, EPERM, ENOEXEC, EISDIR). Pcap, apktool and gdb used three different errno lists; all three now use it. * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * refactor(process): classify Java and adb launch refusals with the shared owner (#10598) The Ghidra and JADX Java probes and adb's version probe now take missing-versus-not-executable from classifyLaunchFailure instead of their own errno checks. ELOOP and ENAMETOOLONG join the owner's missing set, so adb keeps its existing classification and both Java probes now treat a non-directory path component as a missing runtime. * fix(pcap): preserve command launch attribution * test(pcap): expect an unknown failing stage when a limited capture tool exits unsuccessfully * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * test(lint): cover baselined files in the provider-failure classifier rule * fix(pcap): attribute a limited capture's exit through the prlimit wrapper * fix(process): identify the refused executable for every launcher shape Name the executable on errnos Node throws synchronously from spawn (ENOEXEC, ENOTDIR, ...) and read the Windows native launcher's executable-launch constraint, so pcap attributes those refusals to the selected tool or limiter instead of an unknown stage. * test(pcap): prove synchronous launch naming with ENOTDIR on every POSIX host * refactor(process): build classified cancellations with cancelledBy and the carried caller reason * chore(lint): count runOwned's close-failure mapper from main in the classifier baseline |
||
|
|
b33e5c4867 | refactor(python): report pyc format failures through ParseFailure (#10664) | ||
|
|
a67dbe07a4 |
refactor(process): own deadlines as one monotonic type with a finalize budget (#10723)
* refactor(process): own deadlines as one monotonic type with a finalize budget Deadline (src/domain/deadline) holds a monotonic work budget and a separate finalize budget that starts when finalization begins. ProviderStartupDeadline is built on it and exposes finalize(), so a failed Ghidra startup drains launcher output under its own budget and the caller's signal instead of the expired startup signal. The six wall-clock deadline sums in src move onto Deadline; a counted guard keeps the one page-clock conversion and rejects new copies. * refactor(process): share one finalize window across repeated beginFinalize calls |
||
|
|
d1e2a261f8 |
fix(server): report unconfirmed HTTP response cleanup as a cleanup error (#10719)
NodeHttpRequestOwner.drain() reported a failed response-source finalizer as a transport resource constraint, which reads as a budget the caller could raise. It is retained cleanup, so drain now throws a ProviderCleanupError with cleanupIncomplete and the retained resource, and the file leaves the typed-resource-refusal baseline. |
||
|
|
2e1e6593f2 |
refactor(application): own the finalization precedence in runOwned (#10645)
* refactor(application): own the finalization precedence in runOwned runOwned runs owned work, closes its owner and applies the documented precedence once: a recorded failure stays primary, cancellation before commit keeps the completed value as a partial observation, cancellation after commit keeps the value, and unconfirmed cleanup reports cleanup_incomplete while keeping the completed value. finishAnalysisCommand now projects its Finalized outcome; its 31 callers are unchanged. * fix(application): preserve finalization outcomes * fix(application): classify finalization by the primary error and keep cancellation through recovered publication A producer composite whose primary is a cancellation finalized as failed because the kind read only the top-level error class; it now follows primaryAnalysisError. A cancellation that arrived while a recovered value's publication failed was dropped because the signal was read before that last await; it is now attached to the publication failure as a secondary. * fix(cli): keep the initial failure snapshot whenever close itself succeeded |
||
|
|
61fd6336bf |
refactor(hopper): build Hopper cancellations with a required reason (#10601)
* refactor(errors): require a reason for every analysis cancellation Add cancelledBy, the one constructor for AnalysisCancelledError. Its reason argument is required: an aborted signal, an earlier cancellation, a reason carried from an inner failure, or an OwnerCancellation when REA closed the work's owner itself. Closed adb, apktool, firmware, sqlite, gdb, web-bundle analyzer and binary-session record owners now report OwnerCancellation.ownerClosed instead of an absent reason. Firmware's predecessor wait returns its cancellation as a Result, removing an unreachable reason-less fallback. An architecture guard rejects new direct constructions, with a counted per-file baseline that can only shrink. * refactor(errors): share one aborted-signal predicate with cancelledBy * refactor(process): return a departing caller's reason from a shared startup wait * refactor(providers): build decompiler-provider cancellations with a required reason (#10587) Migrate every AnalysisCancelledError construction under src/ghidra, src/ida, src/cutter, src/jeb and src/kuna to cancelledBy and lower the guard baseline from 671 to 572. Closed Kuna target commands report OwnerCancellation.ownerClosed instead of an absent reason, and Kuna and JEB close abort their lifetimes with that typed reason. * fix(errors): read the reason of any signal-shaped cancellation source * test(ci): cover the counted-baseline comparison behind the architecture guard * refactor(hopper): build Hopper cancellations with a required reason Migrate the remaining AnalysisCancelledError constructions under src/hopper to cancelledBy. Regex-search close aborts its workers with OwnerCancellation.ownerClosed. HopperCleanup and HopperClient are not touched. * test(hopper): cover cancellation during search shutdown |
||
|
|
d9daf09ea5 | refactor(capture): report decoder failures through ParseFailure with named limits (#10708) | ||
|
|
3a29b6b8ea | refactor(il2cpp): report format failures through ParseFailure (#10701) | ||
|
|
cd5ea9a9fb |
fix(hopper): name the failing fields when a bridge reply misses its contract (#10713)
* fix(hopper): name the failing fields when a bridge reply misses its contract * fix(ci): run the package baseline when the fake Hopper bridge changes * fix(hopper): name nested union failures and cover every native schema in the package scope |
||
|
|
89640a446a |
fix(parsers): stop reading every RangeError as a format failure (#10602)
* refactor(parsers): report format failures through one ParseFailure algebra Add ParseFailure (malformed, truncated, unsupported, limit, with format, offset and field) and its one carrier, ParseFailureError, in the domain. BinaryReader now names truncation and the field it read, and its native format and resource failures are ParseFailureError subclasses. Providers projected a format failure with their own instanceof ladder, and some dropped the selected path from the invalid_format message. parseFailureAnalysisError now owns that projection for the native, Go, devicetree, V8, Windows Shortcut and Electron fuse providers. The V8 code cache, Windows Shortcut and Electron fuse format classes are removed in favour of the algebra. The architecture guard counts raw Buffer and DataView reads, plain Error throws in parser folders and plain JSON.parse of parser input against baselines that can only shrink. * fix(parsers): stop reading every RangeError as a format failure Mach-O, Swift and Objective-C metadata parsers threw RangeError for a truncated or malformed record, so their catch sites treated any RangeError as a partial decode: a call stack overflow or a host string limit became an "unresolved" metadata reason, and the IL2CPP Mach-O path reported it as a malformed container. Those parsers and the CIL method body reader now throw ParseFailureError. hostRangeErrorKind is the one interpreter of a host RangeError (stack overflow, host capacity, raw out-of-bounds read), and parseFailureFromCause admits only a parse failure or a raw out-of-bounds read as evidence about the input. Fixup stream catch-alls rethrow host limits. The architecture guard counts the remaining direct instanceof RangeError checks. * fix(parsers): preserve Apple metadata failure ownership * test(architecture): shrink parser failure baseline * fix: preserve uncertainty for host range errors |
||
|
|
e652f4409e |
fix(verify): rewrite counted baselines only when a count was lowered (#10669)
* fix(verify): rewrite counted baselines only when a count was lowered * test(verify): own the baseline write decision in a tested helper |
||
|
|
133e7762b6 |
refactor(source-maps): report decoder failures through ParseFailure (#10690)
SourceMapFormatFailure and its format/unsupported/limit/section-overlap reasons are replaced by ParseFailureError with format source-map. Limits carry the selected allowance name and maximum; a section-boundary overlap is a malformed failure on the section-boundary field. The codec reply protocol and every public error are unchanged. |
||
|
|
d482bb9369 | refactor(apple-ips): report crash-report format failures through ParseFailure (#10665) | ||
|
|
8c052bdec5 |
test(architecture): ratchet top-level layer direction and mutual imports (#10584)
* test(architecture): ratchet top-level layer direction and mutual imports Declare a layer for every top-level src/ directory and root source file (domain, contracts, foundation, providers, application, composition, adapters) in scripts/lib/module-layers.mjs. verify:module-boundaries now also builds the production import graph between those units and compares it with a counted baseline: 45 unit pairs import a higher layer (248 imports) and 23 unit pairs import each other. A new upward pair, more imports on a recorded pair, a new mutual import, or an undeclared unit fails; shrinkage is reported so the baseline can be lowered. * fix(architecture): enforce layers for isolated units |
||
|
|
fd555be8b4 |
refactor(errors): type 14 baselined resource refusals as fixed ceilings or measured exhaustion (#10639)
* refactor(errors): type 14 baselined resource refusals as fixed ceilings or measured exhaustion Fixed ceilings (NTFS journal file, web-bundle worker transfer, Playwright trace parser, lipo field retention, exactly representable file sizes) now name their allowance; observed heap or result-capacity exhaustion and occupied admission declare measuredExhaustion. The typed-resource-refusal baseline drops from 24 sites in 19 files to 10 in 10. * fix(browser): name the trace parser allowance the record actually exhausted * test(ntfs): compare the oversized-acquisition recovery with its owning formatter |
||
|
|
a22fb6e60b |
fix(model): report malformed GGUF and Safetensors headers as invalid_format through ParseFailure (#10667)
* refactor(model): report GGUF and Safetensors format failures through ParseFailure * fix(model): report malformed model headers as invalid_format through the shared mapping Malformed and truncated GGUF and Safetensors headers now take the shared ParseFailure mapping (invalid_request, invalid_format on path) instead of the model provider's own BinaryTargetError file_format_rejected. Unsupported forms stay unsupported_target and model allowances keep their resource-constraint recovery. |
||
|
|
ef15353c69 |
refactor(android): build mobile-provider cancellations with a required reason (#10590)
* refactor(errors): require a reason for every analysis cancellation Add cancelledBy, the one constructor for AnalysisCancelledError. Its reason argument is required: an aborted signal, an earlier cancellation, a reason carried from an inner failure, or an OwnerCancellation when REA closed the work's owner itself. Closed adb, apktool, firmware, sqlite, gdb, web-bundle analyzer and binary-session record owners now report OwnerCancellation.ownerClosed instead of an absent reason. Firmware's predecessor wait returns its cancellation as a Result, removing an unreachable reason-less fallback. An architecture guard rejects new direct constructions, with a counted per-file baseline that can only shrink. * refactor(errors): share one aborted-signal predicate with cancelledBy * refactor(process): return a departing caller's reason from a shared startup wait * refactor(android): build mobile-provider cancellations with a required reason Migrate every remaining AnalysisCancelledError construction under src/adb, src/android, src/apktool, src/apkSignature, src/flutter, src/il2cpp, src/dotnet and src/frida to cancelledBy and lower the guard baseline from 671 to 608. A closed adb provider reports OwnerCancellation.ownerClosed for later probes, and JADX and apktool shutdown abort with that typed reason. * refactor(providers): build decompiler-provider cancellations with a required reason (#10587) Migrate every AnalysisCancelledError construction under src/ghidra, src/ida, src/cutter, src/jeb and src/kuna to cancelledBy and lower the guard baseline from 671 to 572. Closed Kuna target commands report OwnerCancellation.ownerClosed instead of an absent reason, and Kuna and JEB close abort their lifetimes with that typed reason. * fix(errors): read the reason of any signal-shaped cancellation source * test(ci): cover the counted-baseline comparison behind the architecture guard |
||
|
|
959af004df |
docs: refuse literal tool counts in living prose (#10585)
* docs: refuse literal tool counts in living prose docs:check now refuses a count of ten or more tools in README, AGENTS, CONTRIBUTING, docs/ (except dated releases, specs, verification and ADR records), the authored skill and the public website. The catalog owns that number and every hand-written copy goes stale when a tool is added. The three current statements (240, 172 and 254 tools, all measured on earlier builds) now refer to the catalog of the measured build instead. * fix(docs): exclude generated pages from prose checks * fix(docs): rerun the tool-count check when any scanned prose changes The docs:check:built cache inputs and the CI docs lane did not cover AGENTS.md, CONTRIBUTING.md, every .agents/skills tree or website/public, so an edit there could reuse a cached pass or skip the docs job. The scanner now owns one isLivingProsePath predicate; the CI plan selects the docs lane with it, and a test binds the turbo inputs to the scanned roots. |
||
|
|
b342254f9a |
refactor(macho): read universal Mach-O slices only where admission selected them (#10642)
Hopper and native dispatch metadata re-ranked FAT slices from the target's architecture name instead of reading the admitted universalSlice. Both now consume the admitted range and refuse when it is missing or undeclared. Mach-O load-command codes move to one table with an architecture guard. |
||
|
|
29fb608559 |
refactor(rust): report cargo-auditable section failures through ParseFailure (#10652)
* refactor(rust): report cargo-auditable section failures through ParseFailure RustAuditableFormatFailure restated the malformed/unsupported algebra and the provider translated it by hand; container BinaryFormatFailures were re-wrapped and lost their kind. The reader now throws ParseFailureError (format rust-auditable), container failures propagate unchanged, and the provider maps both through parseFailureAnalysisError. A counted guard keeps new per-format failure classes from returning. * test(rust): pin the container's truncated failure facts through the Rust reader |
||
|
|
3e0dc29041 |
fix(browser): type CDP command replies and parse frame trees once (#10604)
* fix(browser): type CDP command replies and parse frame trees once CdpConnection.send is typed by method name. A command registered in src/browser/protocol/CdpCommands.ts has its parameters typed from the protocol table Playwright ships and its reply parsed once by its own result schema; a mismatch rejects that command with CdpMalformedReply (protocol_error, command, JSON pointer) without poisoning the connection. Playwright storage sessions admit replies through the same table. Page.getFrameTree and Page.getResourceTree are the first registered commands. Their one parser keeps per-frame facts tolerant (malformed child entries remain explicit omissions) and replaces the per-site readers: observeMainFrameUrl, mainFrameUrl, walkFrameTrees, frameTreeResources, runtimeFrameTreeSchema and the scenario storage frame schema. A reply without a frame tree used to be retried for two seconds and reported as target_not_allowed; it is now one protocol_error. A guard test counts literal CDP command names without a result schema per source file; the baseline can only shrink. * fix(browser): consume parsed CDP facts across boundaries |
||
|
|
ef1b92bf1e |
test(mcp): check advertised schemas against a portable dialect in every profile (#10567)
* test(mcp): check advertised schemas against a portable dialect in every profile * fix(mcp): validate advertised dialect by selected profile * fix(mcp): refuse zero-padded repeat bounds and record host-specific path patterns |
||
|
|
85da0bd4ee |
refactor(errors): require a reason for every analysis cancellation (#10566)
* refactor(errors): require a reason for every analysis cancellation Add cancelledBy, the one constructor for AnalysisCancelledError. Its reason argument is required: an aborted signal, an earlier cancellation, a reason carried from an inner failure, or an OwnerCancellation when REA closed the work's owner itself. Closed adb, apktool, firmware, sqlite, gdb, web-bundle analyzer and binary-session record owners now report OwnerCancellation.ownerClosed instead of an absent reason. Firmware's predecessor wait returns its cancellation as a Result, removing an unreachable reason-less fallback. An architecture guard rejects new direct constructions, with a counted per-file baseline that can only shrink. * refactor(errors): share one aborted-signal predicate with cancelledBy * refactor(process): return a departing caller's reason from a shared startup wait * refactor(providers): build decompiler-provider cancellations with a required reason (#10587) Migrate every AnalysisCancelledError construction under src/ghidra, src/ida, src/cutter, src/jeb and src/kuna to cancelledBy and lower the guard baseline from 671 to 572. Closed Kuna target commands report OwnerCancellation.ownerClosed instead of an absent reason, and Kuna and JEB close abort their lifetimes with that typed reason. * fix(errors): read the reason of any signal-shaped cancellation source * test(ci): cover the counted-baseline comparison behind the architecture guard |
||
|
|
e53212655b |
refactor(contracts): derive the public tool catalog from one contract-group list (#10564)
* refactor(contracts): derive the public tool catalog from one contract-group list toolContracts.ts and toolFamilies.ts each imported and listed the same contract groups. toolContracts.ts now owns one ordered group object; TOOL_CONTRACTS is its flattened values in the same catalog order, and toolFamilies.ts reads TOOL_CONTRACT_GROUPS from it instead of re-importing every group. The static catalog-source lint rule learns the Object.values(groups).flat() composition so positional-contract enforcement still discovers every group without executing modules. * fix(lint): reject computed tool catalog groups |