mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-01 23:43:16 +01:00
Add the Kimi lifecycle and recovery qualification harness. Preserve original grades and cleanup evidence, strict native ownership audits, bounded startup and cleanup, and early rejection of unsupported local fault execution before credentials or resources. Co-Authored-By: Paperclip <noreply@paperclip.ing>
82 lines
4.6 KiB
TypeScript
82 lines
4.6 KiB
TypeScript
import { spawnSync } from "node:child_process";
|
|
import { mkdtemp, readFile, rm, access } from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
const queuedSha = "a".repeat(40);
|
|
const advancedSha = "b".repeat(40);
|
|
|
|
async function resolveTarget(event: string, cadence: string, branch = "master") {
|
|
const workflow = await readFile(new URL("../../.github/workflows/runner-full-stack-e2e.yml", import.meta.url), "utf8");
|
|
const step = workflow.split(" - name: Resolve requested repository branch to an immutable commit\n")[1]!.split("\n - name:")[0]!;
|
|
const script = step.split(" run: |\n")[1]!.replace(/^ {10}/gm, "");
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), "eval-workflow-target-"));
|
|
try {
|
|
const output = path.join(directory, "output");
|
|
const result = spawnSync("bash", ["-c", `gh() { printf '%s\\n' "$MOCK_BRANCH_SHA"; }\n${script}`], {
|
|
encoding: "utf8", env: { ...process.env, EVENT_NAME: event, EVAL_CADENCE: cadence,
|
|
TARGET_BRANCH: branch, DEFAULT_BRANCH: "master", GITHUB_SHA: queuedSha,
|
|
MOCK_BRANCH_SHA: advancedSha, GITHUB_OUTPUT: output, REPOSITORY: "paperclipai/paperclip" },
|
|
});
|
|
return { status: result.status, stderr: result.stderr,
|
|
output: await readFile(output, "utf8").catch(() => "") };
|
|
} finally { await rm(directory, { recursive: true, force: true }); }
|
|
}
|
|
|
|
describe("paid workflow target authorization", () => {
|
|
it.each([["schedule", "manual"], ["workflow_dispatch", "daily"], ["workflow_dispatch", "weekly"]])(
|
|
"pins %s/%s to the queued revision when the branch advances", async (event, cadence) => {
|
|
const result = await resolveTarget(event, cadence);
|
|
expect(result.status, result.stderr).toBe(0);
|
|
expect(result.output).toContain(`sha=${queuedSha}\n`);
|
|
expect(result.output).not.toContain(advancedSha);
|
|
});
|
|
|
|
it("rejects custom bounded targets before emitting a commit", async () => {
|
|
const result = await resolveTarget("workflow_dispatch", "daily", "development");
|
|
expect(result.status).toBe(1);
|
|
expect(result.output).toBe("");
|
|
expect(result.stderr).toContain("default-branch commit");
|
|
});
|
|
|
|
it("still resolves explicit manual targets at authorization time", async () => {
|
|
const result = await resolveTarget("workflow_dispatch", "manual", "development");
|
|
expect(result.status, result.stderr).toBe(0);
|
|
expect(result.output).toContain(`sha=${advancedSha}\n`);
|
|
expect(result.output).toContain("ref=refs/heads/development\n");
|
|
});
|
|
});
|
|
|
|
describe("qualification image dependency correction", () => {
|
|
it.each([true, false])("applies the workflow correction only to its own source: %s", async sameSource => {
|
|
const workflow = await readFile(new URL("../../.github/workflows/docker-runner-check.yml", import.meta.url), "utf8");
|
|
const step = workflow.split(" - name: Apply reviewed qualification lock corrections\n")[1]!.split("\n - ")[0]!;
|
|
const script = step.split(" run: |\n")[1]!.replace(/^ {10}/gm, "");
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), "eval-image-lock-target-"));
|
|
try {
|
|
const marker = path.join(directory, "called");
|
|
const result = spawnSync("bash", ["-c", `node() { touch "$CALLED"; }\n${script}`], {
|
|
cwd: directory, encoding: "utf8", env: { ...process.env, GITHUB_SHA: queuedSha,
|
|
TARGET_SHA: sameSource ? queuedSha : advancedSha, CALLED: marker },
|
|
});
|
|
expect(result.status, result.stderr).toBe(0);
|
|
expect(await access(marker).then(() => true, () => false)).toBe(sameSource);
|
|
} finally { await rm(directory, { recursive: true, force: true }); }
|
|
});
|
|
});
|
|
|
|
describe("release image capacity prerequisite", () => {
|
|
it.each([34, 35])("checks the unchanged disk threshold for every image route: %s GiB", async available => {
|
|
const workflow = await readFile(new URL("../../.github/workflows/docker-runner-check.yml", import.meta.url), "utf8");
|
|
const step = workflow.split(" - name: Prepare hosted image build capacity\n")[1]!.split("\n - ")[0]!;
|
|
expect(step).toContain("if: inputs.build_eval_image || inputs.publish_eval_image\n");
|
|
expect(step).not.toContain("release_run_id");
|
|
const script = step.split(" run: |\n")[1]!.replace(/^ {10}/gm, "");
|
|
const result = spawnSync("bash", ["-c", `sudo() { test "$*" = "rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc"; }; df() { printf 'Avail\\n%sG\\n' "$AVAILABLE"; }; ${script}`], {
|
|
encoding: "utf8", env: { PATH: process.env.PATH, AVAILABLE: String(available) },
|
|
});
|
|
expect(result.status, result.stderr).toBe(available >= 35 ? 0 : 1);
|
|
});
|
|
});
|