





















@@ -6,6 +6,7 @@ export const MOCK_ONLY_PROOF_LABEL = "triage: mock-only-proof";
66export const MAINTAINER_TEAM_SLUG = "maintainer";
7788export const CLAWSWEEPER_PROOF_VERDICT_STATUS = "clawsweeper_exact_head_pass";
9+const CLAWSWEEPER_BOT_LOGINS = new Set(["clawsweeper[bot]", "openclaw-clawsweeper[bot]"]);
9101011const privilegedAuthorAssociations = new Set(["OWNER", "MEMBER", "COLLABORATOR"]);
1112@@ -142,11 +143,10 @@ export async function isMaintainerTeamMember({
142143return body?.state === "active";
143144}
144145145-export function extractRealBehaviorProofSection(body = "") {
146+function extractMarkdownSection(headingRegex, body = "") {
146147// Normalize CRLF → LF so regexes and section slicing see GitHub web-editor PR
147148// bodies the same way as locally-authored Markdown.
148149const normalizedBody = normalizeLineEndings(body);
149-const headingRegex = /^#{2,6}\s+real behavior proof\b[^\n]*$/gim;
150150const match = headingRegex.exec(normalizedBody);
151151if (!match) {
152152return "";
@@ -157,6 +157,14 @@ export function extractRealBehaviorProofSection(body = "") {
157157return (nextHeading ? rest.slice(0, nextHeading.index) : rest).trim();
158158}
159159160+export function extractRealBehaviorProofSection(body = "") {
161+return extractMarkdownSection(/^#{2,6}\s+real behavior proof\b[^\n]*$/im, body);
162+}
163+164+function extractOutOfScopeFollowUpsSection(body = "") {
165+return extractMarkdownSection(/^#{2,6}\s+out-of-scope follow-ups\b[^\n]*$/im, body);
166+}
167+160168function fieldLineRegex(name) {
161169return new RegExp(
162170`^\\s*(?:[-*]\\s*)?(?:\\*\\*)?${escapeRegex(name)}(?:\\s*\\([^)]*\\))?(?:\\*\\*)?\\s*:\\s*(.*)$`,
@@ -246,7 +254,14 @@ function isTrustedClawSweeperComment(comment) {
246254const appSlug = String(
247255comment?.performed_via_github_app?.slug ?? comment?.performedViaGithubApp?.slug ?? "",
248256).toLowerCase();
249-return appSlug === "clawsweeper";
257+if (appSlug === "clawsweeper") {
258+return true;
259+}
260+// GitHub can omit performed_via_github_app on issue comments while still
261+// returning a reserved ClawSweeper App bot identity.
262+const login = String(comment?.user?.login ?? "").toLowerCase();
263+const userType = String(comment?.user?.type ?? "");
264+return CLAWSWEEPER_BOT_LOGINS.has(login) && userType === "Bot";
250265}
251266252267export function hasClawSweeperExactHeadProof({ pullRequest, comments = [] } = {}) {
@@ -292,7 +307,8 @@ export function evaluateRealBehaviorProof({ pullRequest, labels } = {}) {
292307return result("skipped", "Maintainer, collaborator, or bot PRs do not require this gate.");
293308}
294309295-const section = extractRealBehaviorProofSection(pullRequest?.body ?? "");
310+const body = pullRequest?.body ?? "";
311+const section = extractRealBehaviorProofSection(body);
296312if (!section) {
297313return result(
298314"missing",
@@ -303,6 +319,9 @@ export function evaluateRealBehaviorProof({ pullRequest, labels } = {}) {
303319const fields = Object.fromEntries(
304320requiredProofFields.map((field) => [field.key, extractFieldValue(section, field)]),
305321);
322+if (!fields.notTested) {
323+fields.notTested = extractOutOfScopeFollowUpsSection(body);
324+}
306325const missingFields = requiredProofFields
307326.filter((field) => isMissingValue(fields[field.key] ?? "", field))
308327.map((field) => field.key);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。