feat(analysis): make resource budgets recoverable across CLI and MCP (#9706)

* refactor(analysis): centralize resource budgets and recovery facts

* feat(analysis): expose ASAR and Ghidra runtime admission controls

* feat(artifacts): expose reader admission and preserve limited recognition

* feat(javascript): expose recoverable semantic precision budgets

* feat(web): add recoverable source-map budgets and compact retained views

* feat(web): make historical capture decoding budgets recoverable

* fix(desktop): enforce selected view policies across capture and export

* feat(runtime): make Frida and LLDB retention budgets selectable

* feat(native): expose diagnostic budgets and preserve exhaustion causes

* feat(managed): expose recoverable snapshot and representation budgets

* feat(metadata): make Go and Rust inspection budgets recoverable

* feat(wasm): expose representation and producer admissions

* feat(evm): expose per-call worker resource budgets

* feat(android): make resource and string-pool omissions recoverable

* feat(producers): expose command and recorded-capture budgets

* docs(analysis): record recovery contracts and integrated validation

* fix(docs): link calibration oracle from published verification pages

* fix(docs): restore desktop task anchors and receipt links

* test(analysis): align fixtures with selectable budget contracts

* fix(analysis): remove source-location projector dependency cycle

* test(analysis): refresh budget recovery and verifier regressions

* test(analysis): preserve format and publication recovery expectations

* test(windows): align conformance with owned runtime admission

* fix(desktop): preserve selected alias kinds in exported state

* test(analysis): align provider fixtures with recoverable budgets

* test(desktop): validate emitted alias metadata structurally

* fix(ghidra): classify bounded Windows endpoint refusals

* test(cli): assert selectable artifact admission recovery

* fix(cli): preserve capture provenance in environment builds
This commit is contained in:
morluto authored and GitHub committed 2026-11-10 05:11:20 -05:00
1 parent 55b6d2ca20
commit cb4e5cfbff
515 files changed
+21066 -3637

No files matched your search

+20 -6
View File
@@ -1,3 +1,4 @@
import { nativeCallCaptureLimits } from "../domain/native/nativeCallCaptureLimits.js";
import {
AnalysisCapabilityUnavailableError,
AnalysisCancelledError,
@@ -43,8 +44,8 @@ export const NATIVE_CALL_OBSERVATION_LIMITATIONS = [
export const NATIVE_CALL_BREAKPOINT_LOCATION_LIST_INCOMPLETE_LIMITATION =
"The breakpoint location list is incomplete; location_count gives the full matching count.";
export const NATIVE_CALL_BREAKPOINT_LOCATION_BUDGET_LIMITATION =
"Resolved breakpoint locations exceeded the aggregate 8388608-byte (8 MiB) metadata budget; omitted locations are counted in location_count. This metadata limit does not change the process outcome. This release has no runtime override.";
const breakpointLocationBudgetLimitation = (bytes: number): string =>
`Resolved breakpoint locations exceeded capture_limits.breakpoint_location_bytes (${String(bytes)} bytes); omitted locations are counted in location_count. This metadata limit does not change the process outcome. Select a larger budget before a new authorized observation; earlier omitted facts cannot be recovered.`;
/** Launch the active Mach-O under LLDB, record requested call entries, then stop it. */
export const observeNativeCalls = async (
@@ -122,6 +123,7 @@ const nativeCallFacts = (
trace: NativeCallReadback,
) => {
const { run } = trace;
const limits = nativeCallCaptureLimits(input.capture_limits);
const terminated = run.terminated && trace.terminated;
const terminationSummary = terminated
? "the process was killed"
@@ -131,6 +133,14 @@ const nativeCallFacts = (
.map(({ index }) => index);
const eventLimit = run.outcome === "event-limit";
const resourceLimit = run.outcome === "resource-limit";
const traceByteBudget = `capture_limits.trace_bytes (${String(limits.trace_bytes)} bytes)`;
const traceFrameBudget = `capture_limits.trace_frames (${String(limits.trace_frames)} frames)`;
const exhaustedTraceBudget =
run.resource_limit === "trace_bytes"
? traceByteBudget
: run.resource_limit === "trace_frames"
? traceFrameBudget
: `${traceByteBudget} or ${traceFrameBudget}`;
const breakpointLocationLimit = run.breakpoint_locations_truncated === true;
const partial =
eventLimit ||
@@ -140,6 +150,7 @@ const nativeCallFacts = (
run.outcome === "stop-limit" ||
unresolved.length > 0;
return {
capture_limits: limits,
target: {
path: target.path,
sha256: target.sha256,
@@ -183,6 +194,9 @@ const nativeCallFacts = (
status: partial ? "partial" : "complete",
event_limit_reached: eventLimit,
resource_limit_reached: resourceLimit,
...(run.resource_limit == null
? {}
: { capture_limit: run.resource_limit }),
...(breakpointLocationLimit
? { breakpoint_locations_truncated: true }
: {}),
@@ -198,7 +212,7 @@ const nativeCallFacts = (
: []),
...(resourceLimit
? [
`Observation stopped before retaining the next complete event because the estimated 8388608-byte (8 MiB) trace-payload or 65536-frame aggregate budget was reached; ${terminationSummary}. This release has no runtime override for those budgets.`,
`Observation stopped before retaining the next complete event because ${exhaustedTraceBudget} was reached; ${terminationSummary}. Select a larger corresponding budget before a new authorized observation; earlier omitted calls cannot be recovered.`,
]
: []),
...(run.outcome === "duration-elapsed"
@@ -213,7 +227,7 @@ const nativeCallFacts = (
]),
...(run.outcome === "stop-limit"
? [
`Observation stopped after repeated signal or exception stops; ${terminationSummary}.`,
`Observation stopped at capture_limits.other_stops (${String(limits.other_stops)} signal or exception stops); ${terminationSummary}. Select a larger budget before a new authorized observation; earlier omitted stops cannot be recovered.`,
]
: []),
...(unresolved.length === 0
@@ -228,14 +242,14 @@ const nativeCallFacts = (
? [NATIVE_CALL_BREAKPOINT_LOCATION_LIST_INCOMPLETE_LIMITATION]
: []),
...(breakpointLocationLimit
? [NATIVE_CALL_BREAKPOINT_LOCATION_BUDGET_LIMITATION]
? [breakpointLocationBudgetLimitation(limits.breakpoint_location_bytes)]
: []),
...(trace.stdout === null || trace.stderr === null
? ["One or more target output captures were unavailable."]
: []),
...(trace.stdout?.truncated === true || trace.stderr?.truncated === true
? [
"Target output beyond 1048576 bytes (1 MiB) per stream is counted but not kept. This release has no runtime override.",
`Target output beyond capture_limits.output_bytes (${String(limits.output_bytes)} bytes per stream) is counted but not kept. Select a larger budget before a new authorized observation; earlier omitted output cannot be recovered.`,
]
: []),
...(trace.stdout?.complete === false || trace.stderr?.complete === false