test: require managed private repository access in staging acceptance

Fail before editing repository state if the remote cannot be read, and reject credential or PATH workarounds during model-driven acceptance.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Dotta 2026-09-08 16:35:20 -05:00
parent 62096fd335
commit ffe3a32b2d
2 changed files with 8 additions and 1 deletions

View File

@ -17,6 +17,7 @@ beforeAll(async () => {
await fs.writeFile(path.join(repo, "README"), "fixture");
await exec("git", ["-C", repo, "add", "README"]);
await exec("git", ["-C", repo, "-c", "user.name=Acceptance", "-c", "user.email=acceptance@example.invalid", "commit", "-m", "fixture"]);
await exec("git", ["-C", repo, "remote", "add", "origin", repo]);
await fs.writeFile(path.join(repo, ".acceptance-setup-count"), "initialized\n");
}
});
@ -25,6 +26,11 @@ it("proves actual warm state and fails instead of repairing lost files", async (
const nonce = randomUUID();
const run = (warm: boolean) => exec("/bin/sh", ["-c", repoAcceptanceScript(nonce, warm)], { cwd: root, env: { ...process.env, HOME: root,
GIT_AUTHOR_NAME: "", GIT_AUTHOR_EMAIL: "", GIT_COMMITTER_NAME: "", GIT_COMMITTER_EMAIL: "" } });
const firstRepo = path.join(root, "repos", "first repo");
await exec("git", ["-C", firstRepo, "remote", "set-url", "origin", path.join(root, "missing-origin")]);
await expect(run(false)).rejects.toThrow();
await expect(fs.access(path.join(firstRepo, ".acceptance-owner"))).rejects.toThrow();
await exec("git", ["-C", firstRepo, "remote", "set-url", "origin", firstRepo]);
expect((await run(false)).stdout).toContain("ACCEPTANCE_SCRIPT_PASSED");
expect((await run(true)).stdout).toContain("ACCEPTANCE_SCRIPT_PASSED");
for (const scope of ["task", "agent", "user", "project"]) {

View File

@ -5,6 +5,7 @@ export function repoAcceptanceScript(nonce: string, warm: boolean): string {
'for folder in task agent user project repos .codex .cache; do test -d "$HOME/$folder"; done',
'count=0', 'for repo in "$HOME"/repos/*; do',
' test -d "$repo/.git" || continue', ' count=$((count + 1))', ' name=$(basename "$repo")',
' git -C "$repo" ls-remote --exit-code origin HEAD >/dev/null',
];
const repoSteps = warm ? [
` test "$(git -C "$repo" show HEAD:.acceptance-owner)" = '${nonce}'`,
@ -52,7 +53,7 @@ export function repoAcceptanceScript(nonce: string, warm: boolean): string {
export function repoAcceptancePrompt(nonce: string, warm: boolean): string {
return [
"Execute this exact acceptance shell script from your initial working directory in one tool call. Use real filesystem tools; do not simulate its result.",
"Execute this exact acceptance shell script from your initial working directory in one tool call. Use real filesystem tools; do not simulate its result. Do not change PATH, bypass the managed git launcher, extract credentials, repair partial state, or retry after any failed command. If anything fails, immediately stop and mark the task blocked as instructed.",
warm ? "This must reuse the same warm sandbox. Do not repair, recreate, or reset missing state." : "This creates disposable local commits and staged, unstaged, and untracked test files. Do not push.",
'If any assertion fails, stop and PATCH the task with status "blocked" and unblockDescriptor {"owner":{"agentId":"<your PAPERCLIP_AGENT_ID>"},"action":"Investigate the failed acceptance assertion"}, replacing the placeholder with your agent ID and including the actual error in your comment. Otherwise mark the Paperclip task done after the script succeeds.',
"```sh", repoAcceptanceScript(nonce, warm), "```",