PR Roast Triage
Review every open PR, close what has no independent impact, roast the rest with fix recommendations. The human merges manually in the emitted order — never auto-merge, never merge from this skill.
Step 1 — Triage baseline (run first, before any opinion)
./scripts/pr-triage.sh # conflict status + CI status + suggested order
git status --short # scope out unrelated local changes first
git diff HEAD --stat
Step 2 — CI truth (annotations, not badges)
A red badge is not a verdict. Pull the failing step's annotation:
gh api repos/<owner>/<repo>/check-runs/<job_id>/annotations \
--jq '.[].message | .[0:200]'
Known infra flakes (re-run, do not "fix code"):
Unable to authenticate to FlakeHub→ Cargo Deny nix setup broken, pre-existing.hosted runner lost communication→ CodeQL/runner loss, pre-existing.- External-only red (Codacy/Sonar) with all GitHub checks green → code issue, real.
Step 3 — Duplicate detection (same base blob + same hunk)
Bot swarms file near-identical PRs. Compare, don't assume:
gh pr diff <a> --name-only
gh pr diff <b> 2>/dev/null | sed -n '1,80p' # same base hash? same function?
Same file + same base blob + same effect = duplicates. Keep exactly one:
- Green CI beats mergeable-but-red.
- Fewest unrelated files (no
export.jsontimestamp, no lockfile churn). - Backward-compat wrapper kept beats private-fn signature break.
- Newest branch (rebases cleanest onto latest main).
Close the losers with reason superseded by #<keeper>.
Step 4 — Roast rubric (every keeper PR)
- Atomicity: one logical change. Mega-PRs (>5 files across concerns) must split.
- Title honesty: title must describe the diff (
re-exporthiding a BFS cap = reject/retitle). - commitlint scope: must exist in
commitlint.config.cjsscope-enum(perf(hyperdim)fails; only listed scopes pass). - Rationale comments: never deleted to "shorten" (
Never delete rationale comments). Under 500 LOC gate pressure, bot PRs may attempt to strip docstrings/comments to make room for new code. Reject/roast this behavior; require extracting child submodules (e.g.hyperdim_binary_serde.rs) instead. - deny.toml: must only ADD ignores with advisory ID + reason. Deleting or
commenting out existing ignores re-breaks
cargo deny— reject. - Perf claims: no
criterionoutput or flamegraph = not review-ready. export.json/Cargo.locknoise: timestamp-only or resolver-churn hunks must be dropped before merge.- Bot comments (Jules hello, Sonar/Codacy pass notes) are noise, not reviews. Zero human comments = no hidden requirements, but also no approval.
- GitHub CLI GraphQL deprecation:
gh pr editandgh issue viewfail if querying deprecatedprojectCards. Query specific--jsonfields for reads, or usegh api -X PATCH repos/<owner>/<repo>/pulls/<id> -f title="..."for editing PR titles. - Multi-issue parent linkage: When a parent PR implements multiple child issues,
ensure all child issues (
Fixes #A,Fixes #B) are declared in the PR body so all issues close cleanly upon merge.
Step 5 — Manual merge order (emit, do not execute)
- Trivial green first (dependabot 1-liners).
- Security/clamp fixes (small, high value).
- Foundation before dependents (commitlint scope additions, owner/facade migrations before perf touches on the same files).
- One keeper per duplicate cluster; closes reference the keeper.
- Mega-PRs and SIMD/
unsafelast (need evidence + rebase after everything). - After each merge: rebase next, re-run CI, re-check
mergeable.
# per PR, in order:
git fetch origin main
gh pr checks <n> # all green?
git diff --stat origin/main...<branch> # no surprise reverts?
gh pr merge <n> --squash --delete-branch
Step 6 — Record in codebase
- Full roast →
plans/PR_ROAST_<YYYY_MM_DD>.md(per-PR verdict table + order + commands). - Pre-existing flakes/learnings → append
progress/LEARNINGS.md. plans/GOAP_STATE.md: update counters in place, setaction_last_completed(exactly once, last key) to the triage action.