


























@@ -1,5 +1,13 @@
11// Barnacle owns deterministic GitHub triage and auto-response behavior.
223+import {
4+MOCK_ONLY_PROOF_LABEL,
5+NEEDS_REAL_BEHAVIOR_PROOF_LABEL,
6+PROOF_OVERRIDE_LABEL,
7+evaluateRealBehaviorProof,
8+labelsForRealBehaviorProof,
9+} from "./real-behavior-proof-policy.mjs";
10+311const activePrLimit = 20;
412513const thirdPartyExtensionMessage =
@@ -134,6 +142,18 @@ export const managedLabelSpecs = {
134142color: "C5DEF5",
135143description: "Candidate: PR template appears mostly untouched.",
136144},
145+[NEEDS_REAL_BEHAVIOR_PROOF_LABEL]: {
146+color: "C5DEF5",
147+description: "Candidate: external PR needs after-fix proof from a real setup.",
148+},
149+[MOCK_ONLY_PROOF_LABEL]: {
150+color: "C5DEF5",
151+description: "Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI.",
152+},
153+[PROOF_OVERRIDE_LABEL]: {
154+color: "C2E0C6",
155+description: "Maintainer override for the external PR real behavior proof gate.",
156+},
137157"triage: dirty-candidate": {
138158color: "C5DEF5",
139159description: "Candidate: broad unrelated surfaces; may need splitting or cleanup.",
@@ -154,6 +174,8 @@ export const candidateLabels = {
154174docsDiscoverability: "triage: docs-discoverability",
155175testOnlyNoBug: "triage: test-only-no-bug",
156176refactorOnly: "triage: refactor-only",
177+needsRealBehaviorProof: NEEDS_REAL_BEHAVIOR_PROOF_LABEL,
178+mockOnlyProof: MOCK_ONLY_PROOF_LABEL,
157179dirtyCandidate: "triage: dirty-candidate",
158180riskyInfra: "triage: risky-infra",
159181externalPluginCandidate: "triage: external-plugin-candidate",
@@ -196,10 +218,23 @@ const maintainerAuthorLabel = "maintainer";
196218const privilegedAuthorAssociations = new Set(["OWNER", "MEMBER", "COLLABORATOR"]);
197219const privilegedRepositoryRoles = new Set(["admin", "maintain", "write"]);
198220const candidateLabelValues = Object.values(candidateLabels);
221+const proofCandidateLabelValues = [NEEDS_REAL_BEHAVIOR_PROOF_LABEL, MOCK_ONLY_PROOF_LABEL];
199222const noisyPrMessage =
200223"Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch.";
201224202225const candidateActionRules = [
226+{
227+label: candidateLabels.needsRealBehaviorProof,
228+close: true,
229+message:
230+"Closing this PR because it does not include real behavior proof. Please reopen or resubmit with after-fix evidence from a real OpenClaw setup; terminal screenshots, console output, redacted logs, recordings, linked artifacts, and copied live output count. Unit tests, mocks, snapshots, lint, typechecks, and CI are supplemental only.",
231+},
232+{
233+label: candidateLabels.mockOnlyProof,
234+close: true,
235+message:
236+"Closing this PR because the proof only shows tests, mocks, snapshots, lint, typechecks, or CI. Please reopen or resubmit with after-fix evidence from a real OpenClaw setup; terminal screenshots, console output, redacted logs, recordings, linked artifacts, and copied live output count.",
237+},
203238{
204239label: candidateLabels.dirtyCandidate,
205240close: true,
@@ -438,6 +473,14 @@ export function classifyPullRequestCandidateLabels(pullRequest, files) {
438473labelsToAdd.push(candidateLabels.blankTemplate);
439474}
440475476+labelsToAdd.push(
477+ ...labelsForRealBehaviorProof(
478+evaluateRealBehaviorProof({
479+ pullRequest,
480+}),
481+),
482+);
483+441484const docsOnly = filenames.every(isMarkdownOrDocsFile);
442485const docsSignal =
443486/\b(add|adds|update|updates|fix|fixes|improve|cleanup|clean up|typo|readme|docs?|documentation|translation|translate)\b/i.test(
@@ -718,14 +761,18 @@ async function addMissingLabels(github, context, core, issueNumber, labels, labe
718761719762async function applyPullRequestCandidateLabels(github, context, core, pullRequest, labelSet) {
720763const files = await listPullRequestFiles(github, context, pullRequest);
721-await addMissingLabels(
722-github,
723-context,
724-core,
725-pullRequest.number,
726-classifyPullRequestCandidateLabels(pullRequest, files),
727-labelSet,
764+const classifiedLabels = classifyPullRequestCandidateLabels(
765+{
766+ ...pullRequest,
767+labels: [...labelSet].map((name) => ({ name })),
768+},
769+files,
728770);
771+const staleProofLabels = proofCandidateLabelValues.filter(
772+(label) => labelSet.has(label) && !classifiedLabels.includes(label),
773+);
774+await removeLabels(github, context, pullRequest.number, staleProofLabels, labelSet);
775+await addMissingLabels(github, context, core, pullRequest.number, classifiedLabels, labelSet);
729776}
730777731778function isAutomationUser(user, fallbackLogin = "") {
@@ -931,7 +978,9 @@ export async function runBarnacleAutoResponse({ github, context, core = console
931978const isLabelEvent = context.payload.action === "labeled";
932979const isPrCandidateEvent =
933980pullRequest &&
934-["opened", "edited", "synchronize", "reopened", "labeled"].includes(context.payload.action);
981+["opened", "edited", "synchronize", "reopened", "labeled", "unlabeled"].includes(
982+context.payload.action,
983+);
935984if (!hasTriggerLabel && !isLabelEvent && !isPrCandidateEvent) {
936985return;
937986}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。