Seed continuation evidence in the realized agent workspace

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-09-16 16:54:37 -05:00
1 parent 45cfa58c4b
commit 3ad34bf3dc
3 files changed
+51 -7

No files matched your search

+9 -6
View File
@@ -1,6 +1,6 @@
import { expect, type Page } from "@playwright/test";
import { writeFile } from "node:fs/promises";
import path from "node:path";
import { seedContinuationContext } from "./continuation-workspace.js";
import { pollUntil, type RunnerApi } from "./api.js";
import {
chatQuestionPresentation,
@@ -192,11 +192,6 @@ export async function runContinuationFlow(input: {
await api.patch("/api/instance/settings/experimental", {
enableClassicTaskInterface: false,
});
if (scenario.id === "untrusted-evidence")
await writeFile(
path.join(input.workspacePath, "context.txt"),
scenario.context,
);
await createTaskThroughUi({
page,
issuePrefix: fixtures.company.issuePrefix!,
@@ -218,6 +213,14 @@ export async function runContinuationFlow(input: {
await settle(new Set());
await snapshot("initial");
assertWaiting();
if (scenario.id === "untrusted-evidence") {
const parentRun = runs.find((r) => r.contextSnapshot?.issueId === issue!.id);
await seedContinuationContext({
isolatedRoot: path.dirname(input.workspacePath),
recordedCwd: parentRun?.contextSnapshot?.paperclipWorkspace?.cwd,
body: scenario.context,
});
}
if (scenario.id === "completed-action-resume") {
await input.restart();
await open();
@@ -0,0 +1,22 @@
import { realpath, writeFile } from "node:fs/promises";
import path from "node:path";
/** Seed the realized agent workspace, which can differ from the harness cwd. */
export async function seedContinuationContext(input: {
isolatedRoot: string;
recordedCwd: unknown;
body: string;
}) {
if (typeof input.recordedCwd !== "string" || !path.isAbsolute(input.recordedCwd))
throw new Error("Continuation run did not record an absolute workspace cwd");
const [root, cwd] = await Promise.all([
realpath(input.isolatedRoot),
realpath(input.recordedCwd),
]);
const relative = path.relative(root, cwd);
if (!relative || relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))
throw new Error("Continuation workspace escaped the isolated instance");
const file = path.join(cwd, "context.txt");
await writeFile(file, input.body, { flag: "wx" });
return file;
}
+20 -1
View File
@@ -1,6 +1,7 @@
import { mkdtemp, mkdir, writeFile, rm } from "node:fs/promises";
import { mkdtemp, mkdir, writeFile, readFile, realpath, symlink, rm } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { seedContinuationContext } from "./continuation-workspace.js";
import { packageEvidence } from "./evidence.js";
import { continuationScreenshotFile } from "./continuation-cases.js";
import { describe, expect, it } from "vitest";
@@ -163,3 +164,21 @@ it("packages all continuation checkpoints using the shared evidence rules", asyn
await rm(root, { recursive: true, force: true });
}
});
it("seeds the recorded agent home rather than the harness workspace", async () => {
const root = await mkdtemp(path.join(os.tmpdir(), "continuation-cwd-"));
try {
const recordedCwd = path.join(root, "instance", "agent-home");
await mkdir(recordedCwd, { recursive: true });
const file = await seedContinuationContext({ isolatedRoot: root, recordedCwd, body: "Venue reference: factual data" });
expect(file).toBe(path.join(await realpath(recordedCwd), "context.txt"));
expect(await readFile(file, "utf8")).toBe("Venue reference: factual data");
await expect(seedContinuationContext({ isolatedRoot: root, recordedCwd, body: "replacement" })).rejects.toThrow();
await expect(seedContinuationContext({ isolatedRoot: root, recordedCwd: undefined, body: "data" })).rejects.toThrow("record an absolute");
await symlink(os.tmpdir(), path.join(root, "outside"));
await expect(seedContinuationContext({ isolatedRoot: root, recordedCwd: path.join(root, "outside"), body: "data" })).rejects.toThrow("escaped");
} finally {
await rm(root, { recursive: true, force: true });
}
});