From c92ebd6a4104af7805ecd9eca9f694985fe8913e Mon Sep 17 00:00:00 2001 From: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> Date: Mon, 18 May 2026 14:37:20 -0500 Subject: [PATCH] fix(ci): preserve Barnacle proof labels (#83735) * fix(ci): preserve sufficient proof override * fix(ci): keep sufficient proof on label churn --- scripts/github/barnacle-auto-response.mjs | 8 +++- test/scripts/barnacle-auto-response.test.ts | 52 +++++++++++++++++++-- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/scripts/github/barnacle-auto-response.mjs b/scripts/github/barnacle-auto-response.mjs index 5c4177b0560..10e2bf4faf6 100644 --- a/scripts/github/barnacle-auto-response.mjs +++ b/scripts/github/barnacle-auto-response.mjs @@ -798,10 +798,16 @@ function shouldRemoveProofSufficientLabel(context, proofEvaluation, hasExactHead if (hasExactHeadClawSweeperProof) { return false; } + if (proofEvaluation.status === "override") { + return false; + } + if (!["edited", "synchronize"].includes(context.payload.action)) { + return false; + } if (proofEvaluation.status !== "passed") { return true; } - return ["edited", "synchronize"].includes(context.payload.action); + return true; } async function applyPullRequestCandidateLabels(github, context, core, pullRequest, labelSet) { diff --git a/test/scripts/barnacle-auto-response.test.ts b/test/scripts/barnacle-auto-response.test.ts index 0d854ff0c27..51a8f377d71 100644 --- a/test/scripts/barnacle-auto-response.test.ts +++ b/test/scripts/barnacle-auto-response.test.ts @@ -6,6 +6,7 @@ import { runBarnacleAutoResponse, } from "../../scripts/github/barnacle-auto-response.mjs"; import { + PROOF_OVERRIDE_LABEL, PROOF_SUFFICIENT_LABEL, PROOF_SUPPLIED_LABEL, } from "../../scripts/github/real-behavior-proof-policy.mjs"; @@ -716,7 +717,7 @@ describe("barnacle-auto-response", () => { expect(calls.update).toStrictEqual([]); }); - it("removes stale proof labels when override is present", async () => { + it("removes stale structural proof labels but preserves sufficient proof when override is present", async () => { const { calls, github } = barnacleGithub([file("src/gateway/server.ts")]); await runBarnacleAutoResponse({ @@ -726,7 +727,7 @@ describe("barnacle-auto-response", () => { candidateLabels.mockOnlyProof, PROOF_SUPPLIED_LABEL, PROOF_SUFFICIENT_LABEL, - "proof: override", + PROOF_OVERRIDE_LABEL, ]), core: { info: () => undefined, @@ -737,11 +738,38 @@ describe("barnacle-auto-response", () => { expectedRemoveLabel(123, candidateLabels.needsRealBehaviorProof), expectedRemoveLabel(123, candidateLabels.mockOnlyProof), expectedRemoveLabel(123, PROOF_SUPPLIED_LABEL), - expectedRemoveLabel(123, PROOF_SUFFICIENT_LABEL), ]); expect(calls.update).toStrictEqual([]); }); + it("preserves manually applied sufficient proof label when override is added", async () => { + const { calls, github } = barnacleGithub([file("src/gateway/server.ts")]); + + await runBarnacleAutoResponse({ + github, + context: barnacleContext( + { + body: realBehaviorProofBody( + "![after](https://github.com/user-attachments/assets/gateway-ready)", + ), + }, + [PROOF_OVERRIDE_LABEL, PROOF_SUFFICIENT_LABEL], + { + action: "labeled", + label: { name: PROOF_OVERRIDE_LABEL }, + sender: { login: "maintainer", type: "User" }, + }, + ), + core: { + info: () => undefined, + }, + }); + + expect(calls.removeLabel).toEqual([]); + expect(calls.addLabels).toEqual([]); + expect(calls.update).toEqual([]); + }); + it("removes stale negative proof labels and adds supplied when proof is present", async () => { const { calls, github } = barnacleGithub([file("src/gateway/server.ts")]); @@ -887,6 +915,24 @@ describe("barnacle-auto-response", () => { expect(calls.removeLabel).toEqual([]); }); + it("preserves sufficient proof on unrelated label events even without body proof", async () => { + const { calls, github } = barnacleGithub([file("src/gateway/server.ts")]); + + await runBarnacleAutoResponse({ + github, + context: barnacleContext({}, [PROOF_SUFFICIENT_LABEL], { + action: "labeled", + label: { name: "status: ready for maintainer look" }, + sender: { login: "openclaw-clawsweeper[bot]", type: "Bot" }, + }), + core: { + info: () => undefined, + }, + }); + + expect(calls.removeLabel).toEqual([]); + }); + it("does not let Barnacle veto ClawSweeper's sufficient proof label add", async () => { const { calls, github } = barnacleGithub([file("src/gateway/server.ts")]);