From ca8462931a226cc88c4856d868e51a1a4a57eb9e Mon Sep 17 00:00:00 2001 From: sawyer Date: Tue, 14 Jul 2026 19:26:28 -0400 Subject: [PATCH] fix: normalize cold-start source commit --- scripts/cold-start-contract.mjs | 20 +++++++++++++++++--- scripts/run-cold-start-smoke.mjs | 4 ++-- scripts/test-cold-start-contract.mjs | 25 +++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/scripts/cold-start-contract.mjs b/scripts/cold-start-contract.mjs index 16c9e7c..23df7ef 100644 --- a/scripts/cold-start-contract.mjs +++ b/scripts/cold-start-contract.mjs @@ -57,12 +57,26 @@ function requireExactArrayValues(actual, expected, label) { } } +function requireEvidenceFiles(actual) { + const paths = Array.isArray(actual) + ? actual.map((value) => String(value).replaceAll("\\", "/")) + : []; + const complete = REQUIRED_EVIDENCE_FILES.every((relativePath) => + paths.some((value) => value === relativePath || value.endsWith(`/${relativePath}`)) + ); + if (!complete) throw new Error("cold-start response is missing required evidence files"); +} + +function leadingGitCommit(value) { + return String(value || "").match(/^([0-9a-f]{40})(?:\s|$)/)?.[1] || null; +} + export function verifyColdStartResponse( response, { expectedSourceCommit = CANDIDATE_SOURCE_BASE_COMMIT } = {} ) { requireRecord(response); - if (response.source_commit !== expectedSourceCommit) { + if (leadingGitCommit(response.source_commit) !== expectedSourceCommit) { throw new Error("cold-start response reported the wrong source commit"); } if (response.frozen_baseline_commit !== FROZEN_BASELINE_COMMIT) { @@ -77,10 +91,10 @@ export function verifyColdStartResponse( } requireExactArrayValues(response.proof_commands, REQUIRED_PROOF_COMMANDS, "proof commands"); const boundary = String(response.branch_boundary || "").toLowerCase(); - if (!/(branch|worktree)/.test(boundary) || !boundary.includes("main") || !/(do not|don't|avoid|not edit)/.test(boundary)) { + if (!/(branch|worktree)/.test(boundary) || !boundary.includes("main") || !/(do not|don't|avoid|not edit|prohibit)/.test(boundary)) { throw new Error("cold-start response did not preserve the protected branch boundary"); } - requireExactArrayValues(response.evidence_files, REQUIRED_EVIDENCE_FILES, "evidence files"); + requireEvidenceFiles(response.evidence_files); return { source_commit_matches: true, diff --git a/scripts/run-cold-start-smoke.mjs b/scripts/run-cold-start-smoke.mjs index b72d152..054aba3 100644 --- a/scripts/run-cold-start-smoke.mjs +++ b/scripts/run-cold-start-smoke.mjs @@ -88,7 +88,7 @@ const errors = []; let response = null; let contractAssertions = null; let traceAssertions = null; -if (execution.status !== 0) { +if (execution.status !== 0 || execution.error) { const detail = execution.error?.code === "ETIMEDOUT" ? `timed out after ${timeout}ms` : (execution.stderr || execution.stdout || `exit ${execution.status}`).trim(); @@ -108,7 +108,7 @@ try { const statusAfter = run("git", ["status", "--porcelain"], 15000); const assertions = { - codex_exit_zero: execution.status === 0, + codex_exit_zero: execution.status === 0 && !execution.error, codex_not_timed_out: execution.error?.code !== "ETIMEDOUT", repository_unchanged: statusBefore.status === 0 && statusAfter.status === 0 diff --git a/scripts/test-cold-start-contract.mjs b/scripts/test-cold-start-contract.mjs index 98886e3..a7de0bc 100644 --- a/scripts/test-cold-start-contract.mjs +++ b/scripts/test-cold-start-contract.mjs @@ -62,11 +62,36 @@ assert.equal( }).next_task_matches, true ); +assert.equal( + verifyColdStartResponse({ + ...valid, + source_commit: `${CANDIDATE_SOURCE_BASE_COMMIT} (Merge pull request #8)` + }).source_commit_matches, + true +); +assert.equal( + verifyColdStartResponse({ + ...valid, + evidence_files: valid.evidence_files.map((relativePath) => `/tmp/loopspine/${relativePath}`) + }).source_evidence_complete, + true +); +assert.equal( + verifyColdStartResponse({ + ...valid, + branch_boundary: "Meaningful edits remain prohibited on main; use this worktree." + }).protected_branch_boundary, + true +); assert.throws( () => verifyColdStartResponse({ ...valid, source_commit: FROZEN_BASELINE_COMMIT }), /source commit/ ); +assert.throws( + () => verifyColdStartResponse({ ...valid, source_commit: `HEAD ${CANDIDATE_SOURCE_BASE_COMMIT}` }), + /source commit/ +); assert.throws( () => verifyColdStartResponse({ ...valid, promotion_status: "approved" }), /promotion status/