fix(ci): align verification with current lifecycle contracts

This commit is contained in:
morluto committed 2026-11-11 15:10:51 -05:00
1 parent aa017c61ff
commit 7f920465c5
36 files changed
+300 -167

No files matched your search

+5 -14
View File
@@ -12,7 +12,6 @@ import {
import { dirname, isAbsolute, join } from "node:path";
import { parse as parseToml } from "smol-toml";
import { clientRegistrationCommandText } from "../dist/cli/clientRegistrationCommandText.js";
import { TOOL_CONTRACTS } from "../dist/contracts/toolContracts.js";
import { PRODUCT_IDENTITY } from "../dist/identity.js";
import { pathExists } from "./lib/verify-package-core.mjs";
@@ -53,28 +52,20 @@ const isDirectRegistration = async (command, cli) =>
(await realpath(command[1])) === (await realpath(cli));
const verifyMcpAdd = async ({ commands, cli, environment, npxLog, home }) => {
await commands.run(cli, ["mcp", "add"], environment);
await commands.run(cli, ["mcp", "add", "--agent", "amp"], environment);
const settings = JSON.parse(
await readFile(join(home, ".config", "amp", "settings.json"), "utf8"),
);
const registration = settings?.["amp.mcpServers"]?.rea;
if (!Array.isArray(registration?.args))
throw new Error("Incur mcp add did not write the native Amp registration");
throw new Error("REA mcp add did not write the native Amp registration");
const command = [registration.command, ...registration.args];
if (!(await isDirectRegistration(command, cli)))
throw new Error(
"Incur mcp add did not register the selected absolute runtime and REA script",
"REA mcp add did not register the selected absolute runtime and REA script",
);
// Amp consumes the same command through Incur's parser. Check the delegated
// helper receives that command as one argument, without flattening its argv.
deepStrictEqual(JSON.parse(await readFile(npxLog, "utf8")), [
"add-mcp",
clientRegistrationCommandText(command),
"--name",
"rea",
"-y",
"-g",
]);
if (await pathExists(npxLog))
throw new Error("Native MCP registration invoked an external installer");
};
const verifySetupPlan = async ({
-1
View File
@@ -51,7 +51,6 @@ export const ADB_DEVICE_STATES = [
"detached",
] as const;
export const adbDeviceStateSchema = z.enum(ADB_DEVICE_STATES);
export type AdbDeviceState = (typeof ADB_DEVICE_STATES)[number];
const keyStringSchema = z.string().min(1).max(256);
const keyPattern = /^[A-Za-z0-9._\x2d]+$/u;
@@ -445,6 +445,7 @@ it("pages every retained dossier collection and the native API record", () => {
page("swift_string_literals", {
...original,
swift_string_literals: [literal],
swift_string_literal_omissions: [],
}),
).toMatchObject({ item: [literal], coverage: { total: 1 } });
expect(page("swift_string_literals")).toMatchObject({
-3
View File
@@ -314,9 +314,6 @@ export const auditReleaseExposureInputSchema = z.strictObject({
export type ReleaseExposureReport = z.infer<typeof releaseExposureReportSchema>;
export type ReleaseExposureCheck = z.infer<typeof releaseExposureCheckSchema>;
export type AuditReleaseExposureInput = z.infer<
typeof auditReleaseExposureInputSchema
>;
export interface ReleaseExposureTargetFact {
readonly selected_path: string;
@@ -544,7 +544,7 @@ it("preserves cancellation before and after the signal-zero probe", async () =>
const reason = new Error("cancelled");
controller.abort(reason);
filesystem.readFile.mockRejectedValueOnce(
Object.assign(new Error("aborted"), { name: "AbortError" }),
Object.assign(new Error("aborted"), { name: "AbortError", cause: reason }),
);
await expect(
host.processIdentities?.([entry], controller.signal),
@@ -1652,15 +1652,15 @@ describe("application workflow CLI export Evidence", () => {
operation: "compare_javascript_export_shapes",
predicate_type: "rea.javascript-export-shape-comparison",
normalized_result: {
summary: { added: 1, removed: 0, changed: 0, unknown: 0 },
changes: [
{
summary: { added: 1, removed: 0, changed: 0, unknown: 3 },
changes: expect.arrayContaining([
expect.objectContaining({
status: "added",
path: "/depth",
presence: { left: "absent", right: "present" },
right: { availability: "literal", value: 1 },
},
],
}),
]),
},
});
}, 20_000);
@@ -541,8 +541,15 @@ describe("CommonJS export identity and scope regressions", () => {
expect(comparison).toMatchObject({
left: { status: "selected" },
right: { status: "selected" },
summary: { added: 0, removed: 0, changed: 0 },
changes: [],
summary: { added: 0, removed: 0, changed: 0, unknown: 1 },
changes: [
{
status: "unknown",
path: "/count",
left: { availability: "unknown" },
right: { availability: "unknown" },
},
],
});
});
});
@@ -1,5 +1,6 @@
import {
captureDecoderHeapRecovery,
captureDecoderHeapContinuingRecovery,
CAPTURE_DECODER_OLD_GENERATION_SETTING,
DEFAULT_CAPTURE_DECODER_HEAP,
} from "../../../src/config/captureDecoderHeap.js";
@@ -112,7 +113,9 @@ it.skipIf(process.versions.bun !== undefined && jobLimit === null)(
expect(JSON.stringify(response)).not.toContain("caller-marked");
expect(JSON.stringify(response)).not.toContain("rea doctor");
const remediation = String(exhausted.error.remediation?.action ?? "");
expect(remediation).toContain(captureDecoderHeapRecovery(testHeap));
expect(remediation).toContain(
captureDecoderHeapContinuingRecovery(testHeap),
);
const failed: unknown = await execute(
process.execPath,
[
@@ -318,11 +318,16 @@ it.each(
method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: `${origin}/app` },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: `${origin}/app`,
},
childFrames: [
{
frame: {
id: "child",
loaderId: "loader-child",
parentId: "frame-main",
url: `${origin}/child`,
},
@@ -416,7 +421,11 @@ it.each(
method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: `${origin}/app` },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: `${origin}/app`,
},
childFrames: [
{
frame: {
@@ -1213,7 +1222,11 @@ it.each([undefined, 7, ""])(
method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: `${origin}/app` },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: `${origin}/app`,
},
childFrames: [
{
frame: {
@@ -44,13 +44,18 @@ it.each(["late", "initial", "destroyed", "final-malformed", "out-of-scope"])(
method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: mainUrl },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: mainUrl,
},
childFrames:
reads > 1 || kind === "initial"
? [
{
frame: {
id: "child",
loaderId: "loader-child",
parentId: "frame-main",
url:
kind === "out-of-scope"
@@ -66,6 +71,7 @@ it.each(["late", "initial", "destroyed", "final-malformed", "out-of-scope"])(
{
frame: {
id: "child",
loaderId: "loader-child",
parentId: "frame-main",
url: childUrl,
},
@@ -168,17 +174,27 @@ it.each(["reordered", "parent-changed", "path-changed"])(
const first = {
frame: {
id: "first",
loaderId: "loader-first",
parentId:
reads > 2 && kind === "parent-changed" ? "second" : "frame-main",
url: reads > 2 && kind === "path-changed" ? app : child,
},
};
const second = {
frame: { id: "second", parentId: "frame-main", url: app },
frame: {
id: "second",
loaderId: "loader-second",
parentId: "frame-main",
url: app,
},
};
return {
frameTree: {
frame: { id: "frame-main", url: main },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: main,
},
childFrames: reads > 2 ? [second, first] : [first, second],
},
};
@@ -223,11 +239,16 @@ it.each([
method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: main },
frame: { id: "frame-main", loaderId: "main", url: main },
childFrames:
reads === 1 || kind === "same-document"
? ["first", "second"].map((id) => ({
frame: { id, parentId: "frame-main", url: child },
frame: {
id,
loaderId: `loader-${id}`,
parentId: "frame-main",
url: child,
},
}))
: [],
},
@@ -292,6 +313,7 @@ it.each([
: {
frame: {
id: "first",
loaderId: "loader-first",
parentId: "frame-main",
url: "https://foreign.test/",
},
@@ -365,11 +387,16 @@ it("excludes srcdoc scripts before source reads while retaining declared labels
method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: mainUrl },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: mainUrl,
},
childFrames: [
{
frame: {
id: "srcdoc",
loaderId: "loader-srcdoc",
parentId: "frame-main",
url: "about:srcdoc",
},
@@ -730,7 +757,11 @@ describe("CdpElectronProvider frame capture", () => {
command.method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: main },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: main,
},
childFrames: [
{
frame: {
@@ -951,7 +982,10 @@ describe("CdpElectronProvider malformed inventory replies", () => {
"resources",
"Page.getResourceTree",
(fileUrl: string) => ({
frameTree: { frame: { id: "main", url: fileUrl }, resources: null },
frameTree: {
frame: { id: "main", loaderId: "loader-main", url: fileUrl },
resources: null,
},
}),
],
["workers", "Target.getTargets", () => ({ targetInfos: null })],
@@ -1119,7 +1153,11 @@ it.each(
method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: main },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: main,
},
childFrames:
phase === "refreshed" && reads === 1
? []
@@ -1127,6 +1165,7 @@ it.each(
{
frame: {
id: "child",
loaderId: "loader-child",
url: child,
...(parent === "missing"
? {}
@@ -1136,6 +1175,7 @@ it.each(
{
frame: {
id: "grandchild",
loaderId: "loader-grandchild",
parentId: "child",
url: child,
},
@@ -1240,7 +1280,11 @@ it.each(
method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: main },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: main,
},
childFrames:
phase === "refreshed" && reads === 1
? []
@@ -1248,6 +1292,7 @@ it.each(
{
frame: {
id: "parent",
loaderId: "loader-parent",
parentId: "frame-main",
url: parentUrl,
},
@@ -1255,6 +1300,7 @@ it.each(
{
frame: {
id: "local",
loaderId: "loader-local",
parentId: "parent",
url: child,
},
@@ -1356,10 +1402,19 @@ it.each(["about:blank", "https://foreign.invalid/root"])(
method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: rootUrl },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: rootUrl,
},
childFrames: [
{
frame: { id: "local", parentId: "frame-main", url: local },
frame: {
id: "local",
loaderId: "loader-local",
parentId: "frame-main",
url: local,
},
},
],
},
@@ -1414,7 +1469,7 @@ const replayFrameTree = (
reads: number,
) => ({
frameTree: {
frame: { id: "frame-main", url: main },
frame: { id: "frame-main", loaderId: "loader-frame-main", url: main },
childFrames:
reads === 1 || (kind === "during-tree" && reads === 2)
? [
@@ -53,7 +53,11 @@ it.each(
method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: origin + "/app" },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: origin + "/app",
},
childFrames: [{ frame: frame(origin) }],
},
}
@@ -149,11 +153,16 @@ it.each([
method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: origin + "/app" },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: origin + "/app",
},
childFrames: [
{
frame: {
id: "child",
loaderId: "loader-child",
parentId: "frame-main",
url:
rawUrl === "allowed"
@@ -279,11 +288,16 @@ it.each([
method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: origin + "/app" },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: origin + "/app",
},
childFrames: [
{
frame: {
id: "child",
loaderId: "loader-child",
parentId: "frame-main",
url: origin + "/child",
},
@@ -349,7 +363,11 @@ it("retains the committed loader through same-document updates before a replacem
method === "Page.getFrameTree"
? {
frameTree: {
frame: { id: "frame-main", url: origin + "/app" },
frame: {
id: "frame-main",
loaderId: "loader-frame-main",
url: origin + "/app",
},
childFrames: [
{
frame: {
@@ -1048,11 +1048,16 @@ describe("source-map operation deadline observations", () => {
];
const result = await fetchWebSourceMapsOk(requests, input(), undefined, {
timeoutMs: 100,
fetch: () => {
fetch: (_url, options) => {
calls += 1;
return calls === 1
? Promise.resolve(validMapResponse())
: new Promise<Response>(() => undefined);
: new Promise<Response>((_resolve, reject) => {
const signal = options?.signal;
signal?.addEventListener("abort", () => reject(signal.reason), {
once: true,
});
});
},
});
@@ -248,18 +248,22 @@ it.each([
);
if (cancellationFails) {
const result = await pending;
expect(result).toMatchObject({
ok: false,
error: {
_tag: "AnalysisResourceConstraintError",
message: expect.stringContaining("Expanded source-map evidence"),
cleanupIncomplete: true,
cleanupResources: ["source-map-response"],
cause: expect.objectContaining({
errors: expect.arrayContaining([reason]),
}),
},
});
expect(result.ok).toBe(false);
if (result.ok) throw new Error("Expected output admission failure");
expect(result.error._tag).toBe("AnalysisResourceConstraintError");
expect(result.error.message).toContain("Expanded source-map evidence");
expect(result.error.cleanupIncomplete).toBe(true);
expect(result.error.cleanupResources.length).toBe(1);
expect(result.error.cleanupResources[0] === fetchedUrl).toBe(true);
await expect
.poll(() =>
result.error.secondaryFailures.some((failure) =>
failure.secondaryFailures.some(
(secondary) => secondary.cause === reason,
),
),
)
.toBe(true);
} else {
await expect(pending).resolves.toMatchObject({
ok: true,
+4 -2
View File
@@ -184,8 +184,10 @@ describe("Cutter CLI commands", () => {
{ REA_CUTTER_BRIDGE_DIR: directory },
);
expect(result.exitCode).toBe(0);
expect(result.stdout).toContain("invalid_request");
expect(result.exitCode).toBe(1);
expect(JSON.parse(result.stdout)).toMatchObject({
code: "invalid_request",
});
});
});
@@ -36,7 +36,8 @@ cliTest.skipIf(!["darwin", "linux"].includes(process.platform))(
arguments: ["providers", "--json"],
environment,
});
expect(providers.exitCode).toBe(expectedExit);
// Listing providers does not start native analysis or consume its timeout.
expect(providers.exitCode).toBe(0);
const doctor = await cli.run({
arguments: ["doctor", "--provider", "hopper", "--json"],
environment,
@@ -111,7 +111,7 @@ it.each([
},
);
it("retains an OpenCode remote registration with a REA-like command", async () => {
it("removes the owned OpenCode launcher despite invalid transport", async () => {
const home = await createTestTempDirectory("rea-registration-remote-owner-");
const configPath = join(home, ".config/opencode/opencode.json");
const environment = { XDG_CONFIG_HOME: join(home, ".config") };
@@ -145,10 +145,17 @@ it("retains an OpenCode remote registration with a REA-like command", async () =
if (client === undefined) throw new Error("Expected the configured client");
expect(await host.removeClient(client)).toMatchObject({
name: "opencode",
status: "retained",
status: "removed",
});
expect(await readFile(configPath, "utf8")).toBe(source);
expect(await readdir(dirname(configPath))).toEqual(["opencode.json"]);
expect(JSON.parse(await readFile(configPath, "utf8"))).toEqual({
caller_root: "keep",
mcp: { servers: { peer: { type: "local", command: ["peer"] } } },
});
expect(await readFile(`${configPath}.rea.backup`, "utf8")).toBe(source);
expect(await readdir(dirname(configPath))).toEqual([
"opencode.json",
"opencode.json.rea.backup",
]);
} finally {
expect(await host.close?.()).toBeUndefined();
}
@@ -32,7 +32,7 @@ const droidPath = (
describe("Factory Droid configuration paths", () => {
it("resolves the user MCP config file and marker directory", () => {
expect(droidPath("/home/a")).toEqual({
expect(droidPath("/home/a")).toMatchObject({
name: "droid",
displayName: "Factory Droid",
configPath: join("/home/a", ".factory", "mcp.json"),
@@ -92,7 +92,7 @@ describe("DeepSeek Harness configuration paths", () => {
);
it("resolves the home Cordis patch under the Harness home", () => {
expect(dshClient({})).toEqual({
expect(dshClient({})).toMatchObject({
name: "dsh",
displayName: "DeepSeek Harness",
configPath: resolve("/home/a", ".dsh", "cordis.patch.yml"),
@@ -52,7 +52,7 @@ const freebuffPath = (
describe("FreeBuff configuration paths", () => {
it("resolves the shared user agents file and the profile marker directory", () => {
expect(freebuffPath("/home/a")).toEqual({
expect(freebuffPath("/home/a")).toMatchObject({
name: "freebuff",
displayName: "FreeBuff",
configPath: join("/home/a", ".agents", "mcp.json"),
@@ -83,7 +83,7 @@ describe("Hermes configuration paths", () => {
);
it("resolves config.yaml under the platform Hermes home", () => {
expect(hermesPath({})).toEqual({
expect(hermesPath({})).toMatchObject({
name: "hermes",
displayName: "Hermes",
configPath: join("/home/a", ".hermes", "config.yaml"),
@@ -59,7 +59,7 @@ describe("Kimi Code configuration paths and skills", () => {
"linux",
override === undefined ? {} : { KIMI_CODE_HOME: override },
);
expect(client).toEqual({
expect(client).toMatchObject({
name: "kimi",
displayName: "Kimi Code",
configPath: join(directory, "mcp.json"),
@@ -61,7 +61,7 @@ describe("LM Studio home resolution", () => {
"resolves mcp.json in the %s home",
async (layout) => {
const { directory, client } = await installedHome(layout);
expect(client).toEqual({
expect(client).toMatchObject({
name: "lm_studio",
displayName: "LM Studio",
configPath: join(directory, "mcp.json"),
@@ -22,7 +22,7 @@ const ompPath = (env: Parameters<typeof supportedClients>[2]) =>
describe("OMP configuration paths", () => {
it("uses the default agent directory and OMP's environment overrides", () => {
expect(ompPath({})).toEqual({
expect(ompPath({})).toMatchObject({
name: "omp",
displayName: "OMP",
configPath: "/home/a/.omp/agent/mcp.json",
@@ -19,7 +19,7 @@ const qoderPath = (
describe("Qoder configuration paths", () => {
it("resolves the user settings file and marker directory", () => {
expect(qoderPath("/home/a")).toEqual({
expect(qoderPath("/home/a")).toMatchObject({
name: "qoder",
displayName: "Qoder",
configPath: join("/home/a", ".qoder", "settings.json"),
@@ -31,7 +31,7 @@ const qwenPath = (
describe("Qwen Code configuration paths", () => {
it("resolves the user settings file and marker directory", () => {
expect(qwenPath("/home/a", "linux")).toEqual({
expect(qwenPath("/home/a", "linux")).toMatchObject({
name: "qwen_code",
displayName: "Qwen Code",
configPath: join("/home/a", ".qwen", "settings.json"),
@@ -40,7 +40,7 @@ const zcodePath = (
describe("ZCode configuration paths", () => {
it("resolves the user config file and marker directory", () => {
expect(zcodePath("/home/a")).toEqual({
expect(zcodePath("/home/a")).toMatchObject({
name: "zcode",
displayName: "ZCode",
configPath: join("/home/a", ".zcode", "cli", "config.json"),
@@ -17,9 +17,9 @@ import { createToolResultDelivery } from "../../../src/server/toolResult.js";
import { SafeOutputTree } from "../../../src/artifacts/SafeOutputTree.js";
import { SafeOutputTreeCreationFailure } from "../../../src/artifacts/SafeOutputTreeCreationFailure.js";
// Assert recovery behavior through the public reference table, while keeping
// row identity expectations independent of the instruction's digest.
const gapsWithContinuations = (
// Extraction-stage assertions use producer-reported gaps. Unclassified byte
// coverage has its own oracle in the selected-interval workflow below.
const stageGapsWithContinuations = (
result: ReturnType<typeof firmwareResultSchemas.extract_firmware.parse>,
) => {
const instructions = new Map(
@@ -28,12 +28,14 @@ const gapsWithContinuations = (
instruction,
]),
);
return result.extraction_gaps.map(({ continuation_id, ...gap }) => {
const instruction = instructions.get(continuation_id);
if (instruction === undefined)
throw new Error("Missing recovery instruction");
return { ...gap, continuation: instruction };
});
return result.extraction_gaps
.filter(({ kind }) => kind !== "unclassified-range")
.map(({ continuation_id, ...gap }) => {
const instruction = instructions.get(continuation_id);
if (instruction === undefined)
throw new Error("Missing recovery instruction");
return { ...gap, continuation: instruction };
});
};
const directoryCloseFailure = vi.hoisted(() => ({
@@ -159,6 +161,22 @@ it("extracts a selected interval with verified file identity and parent-byte lin
executable_path: fixture.commands.unblob,
});
expect(normalized.selection).toMatchObject({ offset: 2, length: 4 });
const unclassified = normalized.extraction_gaps.filter(
({ kind }) => kind === "unclassified-range",
);
expect(unclassified).toEqual([
expect.objectContaining({
input_path: "$output/rootfs/config",
range: { offset: 0, length: 14 },
root_file_range: null,
}),
]);
expect(
normalized.extraction_continuations.find(
({ id }) => id === unclassified[0]?.continuation_id,
)?.instruction,
).toContain("published child");
expect(normalized.files[0]).toMatchObject({
relative_path: "rootfs/config",
size: 14,
@@ -324,19 +342,17 @@ it("shares recovery prose across distinct unknown chunk identities", async () =>
const normalized = firmwareResultSchemas.extract_firmware.parse(
result.value.normalized_result,
);
expect(normalized.extraction_gaps).toHaveLength(1000);
expect(
new Set(normalized.extraction_gaps.map(({ provider_id }) => provider_id))
.size,
).toBe(1000);
expect(normalized.extraction_continuations).toHaveLength(1);
const [instruction] = normalized.extraction_continuations;
const gaps = normalized.extraction_gaps.filter(
({ kind }) => kind === "unknown-chunk-handler",
);
expect(gaps).toHaveLength(1000);
expect(new Set(gaps.map(({ provider_id }) => provider_id)).size).toBe(1000);
const ids = new Set(gaps.map(({ continuation_id }) => continuation_id));
expect(ids.size).toBe(1);
const instruction = normalized.extraction_continuations.find(({ id }) =>
ids.has(id),
);
expect(instruction?.instruction).toContain("inspect_firmware_regions");
expect(
normalized.extraction_gaps.every(
(gap) => gap.continuation_id === instruction?.id,
),
).toBe(true);
});
it("retains a task dependency failure when the producer names no executable", async () => {
@@ -349,7 +365,7 @@ it("retains a task dependency failure when the producer names no executable", as
const normalized = firmwareResultSchemas.extract_firmware.parse(
result.value.normalized_result,
);
expect(gapsWithContinuations(normalized)).toEqual([
expect(stageGapsWithContinuations(normalized)).toEqual([
{
kind: "missing-extractor-dependency",
input_path: "$input",
@@ -374,7 +390,7 @@ it("preserves an unnamed dependency failure on its owning chunk", async () => {
const normalized = firmwareResultSchemas.extract_firmware.parse(
result.value.normalized_result,
);
expect(gapsWithContinuations(normalized)).toEqual([
expect(stageGapsWithContinuations(normalized)).toEqual([
{
kind: "missing-extractor-dependency",
input_path: "$input",
@@ -399,7 +415,7 @@ it("routes a nested unknown chunk through its published child", async () => {
const normalized = firmwareResultSchemas.extract_firmware.parse(
result.value.normalized_result,
);
expect(gapsWithContinuations(normalized)).toEqual(
expect(stageGapsWithContinuations(normalized)).toEqual(
expect.arrayContaining([
expect.objectContaining({
kind: "unknown-chunk-handler",
@@ -413,10 +429,10 @@ it("routes a nested unknown chunk through its published child", async () => {
}),
]),
);
expect(gapsWithContinuations(normalized)[0]?.continuation).toContain(
expect(stageGapsWithContinuations(normalized)[0]?.continuation).toContain(
"only if Binwalk is configured with REA_BINWALK_COMMAND",
);
expect(gapsWithContinuations(normalized)[0]?.continuation).toContain(
expect(stageGapsWithContinuations(normalized)[0]?.continuation).toContain(
"unavailable without configured Binwalk",
);
});
@@ -432,7 +448,7 @@ it("retains every eligible child in a maximum-depth continuation", async () => {
const normalized = firmwareResultSchemas.extract_firmware.parse(
result.value.normalized_result,
);
const gap = gapsWithContinuations(normalized).find(
const gap = stageGapsWithContinuations(normalized).find(
({ kind, input_path }) =>
kind === "depth-limited" && input_path === "$output/rootfs/config",
);
@@ -454,7 +470,7 @@ it("withholds the nested rerun advice when the published child exceeds the input
const normalized = firmwareResultSchemas.extract_firmware.parse(
result.value.normalized_result,
);
expect(gapsWithContinuations(normalized)).toEqual([
expect(stageGapsWithContinuations(normalized)).toEqual([
{
kind: "unknown-chunk-handler",
input_path: "$output/rootfs/config",
@@ -489,7 +505,7 @@ it.each([
);
expect(normalized.depth_limited_paths.length).toBeGreaterThan(0);
expect(
gapsWithContinuations(normalized).filter(
stageGapsWithContinuations(normalized).filter(
(gap) => gap.kind === "depth-limited",
),
).toEqual(
@@ -513,7 +529,7 @@ it("reports a failed multi-file stage as an extractor-failure gap", async () =>
const normalized = firmwareResultSchemas.extract_firmware.parse(
result.value.normalized_result,
);
expect(gapsWithContinuations(normalized)).toEqual(
expect(stageGapsWithContinuations(normalized)).toEqual(
expect.arrayContaining([
expect.objectContaining({
kind: "extractor-failure",
@@ -539,7 +555,7 @@ it.each(["task-error", "task-warning"])(
const normalized = firmwareResultSchemas.extract_firmware.parse(
result.value.normalized_result,
);
const failures = gapsWithContinuations(normalized).filter(
const failures = stageGapsWithContinuations(normalized).filter(
(gap) => gap.kind === "extractor-failure",
);
expect(normalized.diagnostics).toContainEqual(
@@ -580,7 +596,7 @@ it("retains independent failures beside dependencies at each extraction owner",
const normalized = firmwareResultSchemas.extract_firmware.parse(
result.value.normalized_result,
);
const gaps = gapsWithContinuations(normalized);
const gaps = stageGapsWithContinuations(normalized);
expect(gaps).toHaveLength(4);
for (const provider_id of ["gzip-id", "mixed-id"]) {
const owned = gaps.filter((gap) => gap.provider_id === provider_id);
@@ -609,7 +625,7 @@ it("carries the owning multi-file stage on a task-level dependency gap", async (
const normalized = firmwareResultSchemas.extract_firmware.parse(
result.value.normalized_result,
);
expect(gapsWithContinuations(normalized)).toEqual([
expect(stageGapsWithContinuations(normalized)).toEqual([
{
kind: "missing-extractor-dependency",
input_path: "$input",
@@ -666,7 +682,7 @@ it.each(["depth", "dependency", "link"])(
if (mode === "depth")
expect(normalized.depth_limited_paths).toEqual(["$output/rootfs/config"]);
if (mode === "depth")
expect(gapsWithContinuations(normalized)).toEqual([
expect(stageGapsWithContinuations(normalized)).toEqual([
{
kind: "depth-limited",
input_path: "$output/rootfs/config",
@@ -695,7 +711,7 @@ it.each(["depth", "dependency", "link"])(
},
]);
if (mode === "dependency")
expect(gapsWithContinuations(normalized)).toEqual([
expect(stageGapsWithContinuations(normalized)).toEqual([
{
kind: "missing-extractor-dependency",
input_path: "$input",
@@ -723,7 +739,7 @@ it.each(["depth", "dependency", "link"])(
link_target_hex: Buffer.from("/etc/passwd", "utf8").toString("hex"),
},
]);
expect(gapsWithContinuations(normalized)).toEqual([
expect(stageGapsWithContinuations(normalized)).toEqual([
{
kind: "unpublished-entry",
input_path: "$output/escape",
@@ -35,9 +35,6 @@ vi.mock("node:fs/promises", async (importOriginal) => {
if (typeof args[0] === "string" && fileClose.selected(args[0])) {
const close = handle.close.bind(handle);
fileClose.handles.push(handle);
onTestFinished(async () => {
if (handle.fd >= 0) await close();
});
handle.close = async () => {
fileClose.cancel?.abort();
if (fileClose.denied)
@@ -175,7 +172,11 @@ linuxX64.each([
denied ? ProviderCleanupError : AnalysisCancelledError,
);
if (denied) {
const failure = result.error.cause;
const primary = result.error.cleanupPrimary;
expect(primary?.secondaryFailures).toContainEqual(
expect.objectContaining({ cause: controller.signal.reason }),
);
const failure = primary?.cause;
expect(failure).toBeInstanceOf(ArtifactFileCleanupFailure);
if (!(failure instanceof ArtifactFileCleanupFailure))
throw new Error("Expected exact file cleanup owner");
@@ -17,29 +17,29 @@ import { awaitAcknowledgement } from "../../fixtures/lifecycleAcknowledgement.js
const expectRecoveredBatch = (response: CallToolResult, owned: string) => {
expect(parseMcpToolError(response).error).toMatchObject({
code: "resource_constraint",
code: "cleanup_incomplete",
details: {
completed_observation: {
resources: [owned],
partial_observation: {
evidence: {
normalized_result: {
items: [
{ status: "ok" },
{
status: "error",
error: {
code: "cleanup_incomplete",
details: { resources: [owned] },
},
},
],
},
normalized_result: { items: [{ status: "ok" }], total: 1 },
},
},
secondary_failures: expect.arrayContaining([
{
code: "resource_constraint",
category: "resource_constraint",
message: expect.any(String),
retryable: true,
remediation: expect.any(Object),
details: expect.objectContaining({ operation: "record_evidence" }),
},
]),
},
});
};
it("keeps a mixed batch cleanup owner after source retention fails and retries it", async () => {
it("keeps a batch cleanup owner and its completed prefix after source retention fails", async () => {
const root = await createTestTempDirectory("rea-batch-owned-cleanup-");
const target = join(root, "fixture.com"),
owned = join(root, "owned");
@@ -240,7 +240,7 @@ it("cancels a capture's start when the computer closes while it waits for the op
expect(parseMcpToolError(await started).error.code).toBe("cancelled");
}, 60_000);
it("returns the bundle an export saved when the computer closes while it commits", async () => {
it("reports cancellation and the published bundle when the computer closes during commit", async () => {
const { client } = await fakes();
const id = await startBuildComputer(client, BUILD_REQUEST);
await captureSeedAndEnd(client, id);
@@ -255,10 +255,13 @@ it("returns the bundle an export saved when the computer closes while it commits
tasks: [{ task: BUILD_TASK }],
directory,
});
expect(exported.isError, JSON.stringify(exported)).not.toBe(true);
expect(exported.structuredContent).toMatchObject({
computer_id: id,
directory,
expect(parseMcpToolError(exported).error).toMatchObject({
code: "cancelled",
details: {
diagnostics: {
published_bundle: { directory, files: expect.any(Number) },
},
},
});
expect((await readdir(directory)).length).toBeGreaterThan(0);
await closed;
+11 -5
View File
@@ -729,7 +729,7 @@ it("saves a witness record again after a failed save, without checking again", a
).toContain("ended");
});
it("returns the record a witness saved when the computer closes while the save commits", async () => {
it("reports cancellation and the saved witness when the computer closes during commit", async () => {
const witness = await witnessed();
const { client, id, check, directory } = witness;
await throughNearMiss(witness);
@@ -741,11 +741,17 @@ it("returns the record a witness saved when the computer closes while the save c
arguments: { computer_id: id },
});
});
const saved = parsed(await check({ stage: "after_reset" }));
expect(saved.witness?.record).toMatchObject({
path: join(directory, "witness.json"),
verdict: "held",
const failure = parseMcpToolError(
await check({ stage: "after_reset" }),
).error;
expect(failure).toMatchObject({
code: "cancelled",
details: { partial_observation: expect.any(Object) },
});
const saved = JSON.parse(
await readFile(join(directory, "witness.json"), "utf8"),
);
expect(saved.normalized_result).toMatchObject({ verdict: "held" });
await closed;
});
@@ -96,14 +96,14 @@ describe("local application workflow verifier", () => {
);
const result = JSON.parse(stdout);
expect(result.export_shape_comparison).toMatchObject({
summary: { added: 1, removed: 0, changed: 0, unknown: 0 },
changes: [
{
summary: { added: 1, removed: 0, changed: 0, unknown: 3 },
changes: expect.arrayContaining([
expect.objectContaining({
status: "added",
path: "/depth",
right: { availability: "literal", value: 1 },
},
],
}),
]),
});
}, 20_000);
});
+5 -2
View File
@@ -6,7 +6,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
import { expect, it } from "vitest";
import { regexMatchingDeadlineRecovery } from "../../../src/config/regexMatchingDeadline.js";
import { regexMatchingDeadlineContinuingRecovery } from "../../../src/config/regexMatchingDeadline.js";
import {
DEFAULT_REGEX_MATCHING_DEADLINE_MS,
MINIMUM_REGEX_WORKER_HEAP_REQUEST_MIB,
@@ -476,7 +476,10 @@ it("stops a slow match at the configured deadline and names the setting", async
pending_restart: false,
});
expect(projected.remediation.action).toContain(
regexMatchingDeadlineRecovery({ deadlineMs: 100, source: "setting" }),
regexMatchingDeadlineContinuingRecovery({
deadlineMs: 100,
source: "setting",
}),
);
expect(matched.error).toMatchObject({
_tag: "AnalysisResourceConstraintError",
@@ -13,7 +13,11 @@ import { expect, it as test } from "vitest";
import { runWithAnalysisOperationSnapshot } from "../../../../src/domain/analysisOperationSnapshot.js";
import { kunaInstallationCancellation } from "../../../../src/kuna/KunaInstallation.js";
import { readKunaConfiguration } from "../../../../src/kuna/KunaConfiguration.js";
import {
readKunaConfiguration,
kunaFunctionDeadline,
kunaProjectDeadline,
} from "../../../../src/kuna/KunaConfiguration.js";
import { inspectKunaInstallationOwned as inspectKunaInstallation } from "./kunaResourceScope.js";
import { createTestTempDirectory } from "../../../fixtures/temporaryDirectory.js";
import { fakeKunaCalls, writeFakeKuna } from "./fakeKuna.js";
@@ -256,24 +260,25 @@ it("parses cache, timeout and job settings at the configuration boundary", () =>
"kuna.function_timeout_ms": 250,
},
},
() =>
readKunaConfiguration(
() => {
const parsed = readKunaConfiguration(
{
...environment,
REA_KUNA_PROJECT_TIMEOUT_MS: "0",
REA_KUNA_TIMEOUT_MS: "-1",
},
"linux",
),
);
if (!parsed.ok) throw new Error(parsed.error.reason);
return {
project: kunaProjectDeadline(parsed.value),
function: kunaFunctionDeadline(parsed.value),
};
},
);
expect(overridden).toMatchObject({
ok: true,
value: {
projectTimeoutMs: 4000,
projectTimeoutSource: "runtime",
functionTimeoutMs: 250,
functionTimeoutSource: "runtime",
},
project: { ms: 4000, source: "runtime" },
function: { ms: 250, source: "runtime" },
});
expect(
runWithAnalysisOperationSnapshot(
@@ -400,12 +400,12 @@ const parserClaims = (
{
id: "comparison_coverage",
expectedValue: {
status: "complete-within-inputs",
status: "partial",
paired_variants: 3,
added: 1,
removed: 0,
changed: 0,
unknown: 0,
unknown: 3,
},
source: { ...source, select: comparisonCoverage },
},
@@ -334,10 +334,6 @@ it("retries a late Playwright open after cancellation before accepting another c
await closeStarted;
finishFirstClose();
const failedRetry = await provider.captureScenario(scenario);
expect(failedRetry.ok).toBe(false);
if (!failedRetry.ok) expect(failedRetry.error.cleanupIncomplete).toBe(true);
const retried = await provider.captureScenario(scenario);
expect(retried.ok).toBe(true);
if (retried.ok) expect(retried.value.steps).toHaveLength(2);