import { expect } from "@playwright/test"; import { execFile } from "node:child_process"; import { promisify } from "node:util"; import { realpath, readFile, writeFile } from "node:fs/promises"; import path from "node:path"; import { checks, sameTask, type Entity } from "./internal-support.js"; import { savedTaskWorkspace } from "./runtime-workspaces.js"; import { runtimeDefinition, runtimeObservation, observeRuntime, type RuntimeAgent } from "./runtime-support.js"; const exec = promisify(execFile); async function ownedGit(cwd: string, args: string[]) { const root = process.env.PAPERCLIP_RUNNER_E2E_TEMP_ROOT; if (!root || !(await realpath(cwd)).startsWith(`${await realpath(root)}${path.sep}`)) throw new Error("Git fixture escaped the isolated task workspace"); return (await exec("git", args, { cwd, timeout: 15_000, maxBuffer: 262_144 })).stdout; } export function gradeInspectGit(value: unknown) { const c = checks(); const o = runtimeObservation(value); c.add("real-authorized-repository-evidence", !!o, "Actual task binding, owned repository baseline and independent before/after bytes are required."); if (!o) return c.result(); const before = o.state.workspaceBefore as { workspace: { id: string; cwd: string } }; const after = o.state.workspaceAfter as typeof before; c.add("exact-task-repository-scope", !!before && !!after && before.workspace.id === after.workspace.id && before.workspace.cwd === after.workspace.cwd && o.state.nativeInspectionCwd === after.workspace.cwd && sameTask(o.state.task as Entity, o.tasks.find(row => row.id === (o.state.task as Entity).id)) && o.tasks.length === 1 && o.state.noRemote === true, "The actual chat native workspace is the exact authorized bound task checkout, without an unrelated checkout or configured remote."); c.add("real-uncommitted-header-and-unrelated-change", typeof o.state.diffBefore === "string" && /diff --git a\/header.html b\/header.html/.test(o.state.diffBefore) && /Launch later/.test(o.state.diffBefore) && /Launch sooner/.test(o.state.diffBefore) && /diff --git a\/existing-notes.txt b\/existing-notes.txt/.test(o.state.diffBefore) && o.state.diffAfter === o.state.diffBefore && o.state.statusAfter === o.state.statusBefore && o.state.headAfter === o.state.headBefore && o.state.headerAfter === o.state.headerBefore && o.state.notesAfter === o.state.notesBefore, "Both real synthetic edits and the committed baseline remain byte-for-byte unchanged by this inspection."); c.add("actual-diff-summary-with-file-references", /header\.html/.test(o.reply) && /Launch later/i.test(o.reply) && /Launch sooner/i.test(o.reply) && /existing-notes\.txt/.test(o.reply) && /uncommitted|working (?:tree|copy)|not (?:yet )?committed/i.test(o.reply) && !/(?:I(?:'ve| have)? |successfully )(?:pushed|committed|published|deployed)|remote.*(?:has been|was) updated/i.test(o.reply), "The answer describes the observed header and unrelated diff, distinguishes uncommitted work and makes no remote-update claim."); c.add("real-native-inspection-only", o.runs.length === 2 && o.runs.every(run => run.status === "succeeded") && o.runs.filter(run => run.agentId === o.leadId).length === 1, "The real prior workspace setup and one native inspection are the only provider executions."); return c.result(); } export const runtimeGitCases = [runtimeDefinition("workspaces.inspect-git", async ctx => { if (ctx.input.execution.environment.id !== "local") throw new Error("Owned repository fixture requires the actual local runtime"); const state = await savedTaskWorkspace(ctx); const cwd = state.workspaceBefore.workspace.cwd; await ownedGit(cwd, ["init", "--initial-branch=eval-fixture"]); if ((await ownedGit(cwd, ["remote"])).trim()) throw new Error("Disposable synthetic task repository unexpectedly has a remote"); const header = path.join(cwd, "header.html"), notes = path.join(cwd, "existing-notes.txt"); await writeFile(header, `