Files
openclaw/scripts/github/real-behavior-proof-check.mjs
Hannes Rudolph 4a0f497f16 improve: simplify PR context and evidence (#94676)
* improve: simplify PR context and evidence

* improve: decouple PR context from proof labels

* fix: satisfy PR context lint
2026-06-19 14:00:38 -06:00

68 lines
2.1 KiB
JavaScript

#!/usr/bin/env node
// Checks external PR body context and evidence.
import { readFileSync } from "node:fs";
import { pathToFileURL } from "node:url";
import {
evaluatePullRequestContext,
isMaintainerTeamMember,
} from "./real-behavior-proof-policy.mjs";
function escapeCommandValue(value) {
return String(value)
.replace(/%/g, "%25")
.replace(/\r/g, "%0D")
.replace(/\n/g, "%0A")
.replace(/:/g, "%3A");
}
function isMainModule() {
return Boolean(process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href);
}
async function main(env = process.env) {
const eventPath = env.GITHUB_EVENT_PATH;
if (!eventPath) {
console.error("::error title=PR context check failed::GITHUB_EVENT_PATH is not set.");
process.exit(1);
}
const event = JSON.parse(readFileSync(eventPath, "utf8"));
const pullRequest = event.pull_request;
if (!pullRequest) {
console.log("No pull_request payload found; skipping PR context check.");
process.exit(0);
}
const appToken = env.GH_APP_TOKEN;
const org = event.repository?.owner?.login;
const authorLogin = pullRequest.user?.login;
if (appToken && org && authorLogin) {
try {
if (await isMaintainerTeamMember({ token: appToken, org, login: authorLogin })) {
console.log(
`PR author @${authorLogin} is an active member of the ${org}/maintainer team; skipping PR context check.`,
);
process.exit(0);
}
} catch (error) {
console.warn(
`::warning title=Maintainer membership check failed::${escapeCommandValue(error?.message ?? String(error))}`,
);
}
}
const evaluation = evaluatePullRequestContext({ pullRequest });
if (evaluation.passed) {
console.log(evaluation.reason);
process.exit(0);
}
const message = `${evaluation.reason} Add a concise problem statement and the most useful validation evidence to the PR body. Focused tests, CI results, screenshots, recordings, terminal output, live observations, redacted logs, and artifact links all count.`;
console.error(`::error title=PR context required::${escapeCommandValue(message)}`);
process.exit(1);
}
if (isMainModule()) {
await main();
}