mirror of
https://github.com/morluto/rea.git
synced 2026-11-13 02:02:36 +00:00
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:
1 parent
55b6d2ca20
commit
cb4e5cfbff
515 files changed
+21066
-3637
No files matched your search
@@ -45,6 +45,7 @@ import type {
|
||||
ProviderProcessSupervisor,
|
||||
} from "./ProviderProcess.js";
|
||||
import { OwnedCommandFailure, ownedCommandResources } from "./OwnedCommand.js";
|
||||
import { MAX_NODE_TIMER_DELAY_MS } from "../domain/analysisResourceLimits.js";
|
||||
|
||||
export type ArtifactAnalysisRuntime = Pick<
|
||||
PrivateRuntimeRoot,
|
||||
@@ -57,6 +58,7 @@ interface SelectedArtifactRead {
|
||||
readonly allowanceName: string;
|
||||
readonly observedOutput: AnalysisCapturedOutput | undefined;
|
||||
readonly signal?: AbortSignal | undefined;
|
||||
readonly budgetParameter?: "producer_limits.input_bytes";
|
||||
}
|
||||
|
||||
export const artifactCommandOutput = (
|
||||
@@ -207,7 +209,12 @@ export class ArtifactAnalysisResources {
|
||||
{ input_bytes: maximumBytes },
|
||||
{
|
||||
cause,
|
||||
...fixedProducerInputAllowance(maximumBytes, allowanceName),
|
||||
...(input.budgetParameter === undefined
|
||||
? fixedProducerInputAllowance(maximumBytes, allowanceName)
|
||||
: {
|
||||
retryable: false,
|
||||
remediationAction: `Increase ${input.budgetParameter} above ${String(maximumBytes)} bytes on the next call to admit the same complete selected artifact; no REA restart is required. Do not truncate required input bytes. Output, parser, transport and inherited OS limits remain independent.`,
|
||||
}),
|
||||
},
|
||||
);
|
||||
if (cause instanceof ArtifactReaderFailure && cause.reason === "integrity")
|
||||
@@ -501,6 +508,7 @@ export class ArtifactAnalysisResources {
|
||||
},
|
||||
effectiveLimits: LinuxResourceLimits | undefined,
|
||||
operation = this.operation,
|
||||
budgetParameter?: "producer_limits",
|
||||
): AnalysisError {
|
||||
const capturedOutput =
|
||||
cause.snapshot === null
|
||||
@@ -519,8 +527,11 @@ export class ArtifactAnalysisResources {
|
||||
if (cause.reason === "timeout")
|
||||
return new AnalysisTimeoutError(operation, limits.command_timeout_ms, {
|
||||
...detail,
|
||||
userMessage: `The owned producer command reached its fixed ${String(limits.command_timeout_ms)} ms deadline. This is not a client-side timeout; extending only the MCP client's deadline does not change this budget.`,
|
||||
remediationAction: `REA's fixed producer command deadline is ${String(limits.command_timeout_ms)} ms and this release has no runtime override. Inspect any partial output and cleanup before retrying. Repeating the unchanged request reaches the same deadline.`,
|
||||
userMessage: `The owned producer command reached its ${String(limits.command_timeout_ms)} ms deadline. This is not a client-side timeout; extending only the MCP client's deadline does not change this budget.`,
|
||||
remediationAction:
|
||||
budgetParameter === undefined
|
||||
? `REA's fixed producer command deadline is ${String(limits.command_timeout_ms)} ms and this release has no runtime override. Inspect any partial output and cleanup before retrying. Repeating the unchanged request reaches the same deadline.`
|
||||
: `${limits.command_timeout_ms < MAX_NODE_TIMER_DELAY_MS ? `Increase ${budgetParameter}.command_timeout_ms above ${String(limits.command_timeout_ms)} milliseconds on the next call (range 1..${String(MAX_NODE_TIMER_DELAY_MS)}); no restart is required.` : `${budgetParameter}.command_timeout_ms is already at the runtime timer maximum ${String(MAX_NODE_TIMER_DELAY_MS)} milliseconds; no higher deadline is supported. Narrow the selected work if that preserves the required observation.`} Inspect retained observations and confirm cleanup before retrying. This does not raise CPU, memory, output, parser or external client limits.`,
|
||||
});
|
||||
if (cause.reason === "output-limit")
|
||||
return new AnalysisResourceConstraintError(
|
||||
@@ -530,10 +541,15 @@ export class ArtifactAnalysisResources {
|
||||
{ output_bytes: limits.output_bytes },
|
||||
{
|
||||
...detail,
|
||||
...fixedAllowanceOptions(
|
||||
`The retained command-output allowance of ${String(limits.output_bytes)} bytes (this release has no runtime override)`,
|
||||
"capture",
|
||||
),
|
||||
...(budgetParameter === undefined
|
||||
? fixedAllowanceOptions(
|
||||
`The retained command-output allowance of ${String(limits.output_bytes)} bytes (this release has no runtime override)`,
|
||||
"capture",
|
||||
)
|
||||
: {
|
||||
retryable: false,
|
||||
remediationAction: `Increase ${budgetParameter}.output_bytes above ${String(limits.output_bytes)} bytes on the next call; no restart is required. Inspect captured output and confirm cleanup before retrying. This controls collection, not parser, transport, host memory or inherited OS limits. Repeating the unchanged request cannot raise it.`,
|
||||
}),
|
||||
},
|
||||
);
|
||||
if (
|
||||
@@ -556,7 +572,7 @@ export class ArtifactAnalysisResources {
|
||||
{
|
||||
...detail,
|
||||
retryable: true,
|
||||
remediationAction: `${reported} REA retains the tighter inherited limit. This release has no runtime override for that ceiling. A smaller artifact may finish inside the retained limit. The signal does not prove that ceiling was exhausted, so an unchanged retry may succeed or may fail the same way.`,
|
||||
remediationAction: `${reported} REA retains the tighter inherited limit. ${budgetParameter === undefined ? "This release has no runtime override for that ceiling." : `Review ${budgetParameter}.${signal === "SIGXFSZ" ? "file_bytes" : "cpu_seconds"} for a new call; a higher requested policy cannot raise a tighter inherited soft or hard limit. No REA restart is needed for a per-call update.`} A smaller artifact may finish inside the retained limit. The signal does not prove that ceiling was exhausted, so an unchanged retry may succeed or may fail the same way.`,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { BOUNDED_PRODUCER_LIMITS } from "../domain/producerResourceLimits.js";
|
||||
import { expect, it, onTestFinished, vi } from "vitest";
|
||||
import { writeFile, type FileHandle } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
@@ -8,7 +9,6 @@ import { readStableArtifact } from "../artifacts/readStableArtifact.js";
|
||||
import { ok } from "../domain/result.js";
|
||||
import { ArtifactResourceScope } from "../artifacts/ArtifactResourceScope.js";
|
||||
import {
|
||||
BOUNDED_PRODUCER_LIMITS,
|
||||
clampLinuxResourceLimits,
|
||||
prlimitArgumentVector,
|
||||
prlimitCeilingArguments,
|
||||
|
||||
@@ -16,16 +16,6 @@ const rows = {
|
||||
cpu_seconds: "Max cpu time",
|
||||
} as const;
|
||||
|
||||
/** Bound the resident input copy and retained text before allocation/collection. */
|
||||
export const BOUNDED_PRODUCER_LIMITS = {
|
||||
input_bytes: 32 * 1024 * 1024,
|
||||
output_bytes: 4 * 1024 * 1024,
|
||||
command_timeout_ms: 30_000,
|
||||
address_space_bytes: 1024 * 1024 * 1024,
|
||||
file_bytes: 64 * 1024 * 1024,
|
||||
cpu_seconds: 30,
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Pin soft and hard ceilings together, ending at the prlimit option terminator.
|
||||
* Callers that append the producer command themselves use this prefix.
|
||||
|
||||
Reference in new issue
Block a user