From b02a07655de03ed907cc0f8fdf8ace07abc4238b Mon Sep 17 00:00:00 2001 From: Shakker Date: Tue, 3 Mar 2026 21:13:41 +0000 Subject: [PATCH] fix: harden pr review artifact validation --- scripts/pr | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/scripts/pr b/scripts/pr index ebab4a85b56..d9725af11b7 100755 --- a/scripts/pr +++ b/scripts/pr @@ -500,6 +500,17 @@ EOF_MD { "recommendation": "READY FOR /prepare-pr", "findings": [], + "nitSweep": { + "performed": true, + "status": "none", + "summary": "No optional nits identified." + }, + "issueValidation": { + "performed": true, + "source": "pr_body", + "status": "valid", + "summary": "PR description clearly states a valid problem." + }, "tests": { "ran": [], "gaps": [], @@ -559,6 +570,85 @@ review_validate_artifacts() { exit 1 fi + local nit_findings_count + nit_findings_count=$(jq '[.findings[]? | select((.severity // "") == "NIT")] | length' .local/review.json) + + local nit_sweep_performed + nit_sweep_performed=$(jq -r '.nitSweep.performed // empty' .local/review.json) + if [ "$nit_sweep_performed" != "true" ]; then + echo "Invalid nit sweep in .local/review.json: nitSweep.performed must be true" + exit 1 + fi + + local nit_sweep_status + nit_sweep_status=$(jq -r '.nitSweep.status // ""' .local/review.json) + case "$nit_sweep_status" in + "none") + if [ "$nit_findings_count" -gt 0 ]; then + echo "Invalid nit sweep in .local/review.json: nitSweep.status is none but NIT findings exist" + exit 1 + fi + ;; + "has_nits") + if [ "$nit_findings_count" -lt 1 ]; then + echo "Invalid nit sweep in .local/review.json: nitSweep.status is has_nits but no NIT findings exist" + exit 1 + fi + ;; + *) + echo "Invalid nit sweep status in .local/review.json: $nit_sweep_status" + exit 1 + ;; + esac + + local invalid_nit_summary_count + invalid_nit_summary_count=$(jq '[.nitSweep.summary | select((type != "string") or (gsub("^\\s+|\\s+$";"") | length == 0))] | length' .local/review.json) + if [ "$invalid_nit_summary_count" -gt 0 ]; then + echo "Invalid nit sweep summary in .local/review.json: nitSweep.summary must be a non-empty string" + exit 1 + fi + + local issue_validation_performed + issue_validation_performed=$(jq -r '.issueValidation.performed // empty' .local/review.json) + if [ "$issue_validation_performed" != "true" ]; then + echo "Invalid issue validation in .local/review.json: issueValidation.performed must be true" + exit 1 + fi + + local issue_validation_source + issue_validation_source=$(jq -r '.issueValidation.source // ""' .local/review.json) + case "$issue_validation_source" in + "linked_issue"|"pr_body"|"both") + ;; + *) + echo "Invalid issue validation source in .local/review.json: $issue_validation_source" + exit 1 + ;; + esac + + local issue_validation_status + issue_validation_status=$(jq -r '.issueValidation.status // ""' .local/review.json) + case "$issue_validation_status" in + "valid"|"unclear"|"invalid"|"already_fixed_on_main") + ;; + *) + echo "Invalid issue validation status in .local/review.json: $issue_validation_status" + exit 1 + ;; + esac + + local invalid_issue_summary_count + invalid_issue_summary_count=$(jq '[.issueValidation.summary | select((type != "string") or (gsub("^\\s+|\\s+$";"") | length == 0))] | length' .local/review.json) + if [ "$invalid_issue_summary_count" -gt 0 ]; then + echo "Invalid issue validation summary in .local/review.json: issueValidation.summary must be a non-empty string" + exit 1 + fi + + if [ "$recommendation" = "READY FOR /prepare-pr" ] && [ "$issue_validation_status" != "valid" ]; then + echo "Invalid recommendation in .local/review.json: READY FOR /prepare-pr requires issueValidation.status=valid" + exit 1 + fi + local docs_status docs_status=$(jq -r '.docs // ""' .local/review.json) case "$docs_status" in