mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 01:41:21 +00:00
fix(ci): align verification with current lifecycle contracts
This commit is contained in:
1 parent
aa017c61ff
commit
7f920465c5
36 files changed
+300
-167
No files matched your search
@@ -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 ({
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user