Add /swarm:review --pr: review a PR diff and post the result#29
Merged
Conversation
Opt-in flag to run the local swarm ensemble against a GitHub PR's diff and publish the output-gated result as a PR comment, with no CI setup, repo secrets, or API-token cost. - --pr [<number>]: resolve the PR (explicit number or the current branch via `gh pr view`), take `gh pr diff` as the review input - Reuse the pipeline unchanged; only the diff source (step 1) and a new publish step (step 5) differ — the workflow is untouched - Confirm once before posting; post via `gh pr comment` under the user's own identity with a `## 🐝 Swarm review` marker header - Only output-gated findings are ever posted - Read-only; mutually exclusive with --fix/--loop (documented) - pr-flow compatible: posted as non-`claude` author, so claude-review.sh polling ignores it - Graceful failure on missing/unauth gh, no PR, or post failure - Bump swarm 0.3.0 -> 0.4.0; update READMEs Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHHArYXzAy4DVYyFu15bpU
Document the PR-review-and-post feature in swarm-review-pipeline.md: the workflow-untouched design (diff still arrives via a temp-file path, --pr only swaps how it is filled), the pr-flow compatibility design point (posted under the user's own gh identity, so claude-review.sh's claude-author poll ignores it), output-gated-only posting with a single confirm, and the --fix/--loop mutual exclusion. Update the index line. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHHArYXzAy4DVYyFu15bpU
Fold the swarm ensemble's confirmed findings on the --pr diff: - Restructure step 1 into ONE block with an `if REVIEW_PR` branch instead of a second self-contained `set -euo pipefail` script that read $TMPD/$DIFF from the first (would abort under set -u if run as its own Bash call). This also: routes --pr through the shared empty-diff guard, makes INCLUDE_UNTRACKED=0 actually consumed, cleans up $TMPD on every SWARM_PR_ERR exit, and replaces the literal PR_ARG placeholder with a default-safe empty string. - Sync plugins/swarm/.claude-plugin/plugin.json description with marketplace.json (both advertise --pr, previously byte-identical). - Defer step-3 $TMPD cleanup to step 5 for --pr (step 5 needs the temp dir for the comment body) and correct the "reuse $TMPD" wording. - Mark the PR title as untrusted display data; harden the step-5 confirm gate to scan the body for injected/echoed diff content before posting. - Fold the PR-specific report header into the step-3 render spec. - Standardize the --pr placeholder to `[<number>]` in the top README. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHHArYXzAy4DVYyFu15bpU
Deeper findings from the deepest-effort ensemble pass, several of them
consequences of the first review's own fixes:
- Fix REVIEW_PR/PR_ARG clobber: the block's hardcoded defaults overwrote
the caller-set --pr mode, silently reverting to a local review. Read
via ${REVIEW_PR:-0}/${PR_ARG:-} so a same-call prefix survives; reword
the instruction to prefix, not edit-in-place.
- Deterministically sanitize finding text before it enters the posted
Markdown (escape pipes/newlines/backticks, neutralize @-mentions and
raw HTML, inert links) — the human confirm scan alone is not enough for
content leaving the sandbox to a public comment under the user's identity.
- Pin the reviewed revision: capture headRefOid, show `reviewed at <sha>`
in the report header + comment body, optionally re-check the head at
post time so a mid-window push can't make a stale comment look current.
- Warn (SWARM_PR_WARN) when the local checkout isn't the PR head, since
the in-session verifier reads file:line from local disk, not the PR head.
- Validate PR_ARG as a bare number so gh can't be pointed at another repo.
- Clean up $TMPD on every step-5 exit (decline / post-failure), not just
the success path — the deferred cleanup otherwise leaks the PR diff.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GHHArYXzAy4DVYyFu15bpU
Two external-only review rounds (codex/grok/composer, no opus finders); applied the confirmed correctness/security fixes, several of which were regressions introduced by the earlier fix rounds: R0: - Hard-stop (not soft-warn) when the local checkout isn't the PR head — the in-session verifier reads file:line from disk, so a divergent tree silently mis-judges solo findings and gates the posted output on that. - Capture gh stderr into SWARM_PR_ERR instead of discarding it. - Undo the cross-turn $TMPD defer (step 3 cleans it; step 5 uses its own temp) so a decline/error can't strand the fetched PR diff on disk. - Deterministic guard rejecting --pr combined with --fix/--loop. - Tighten finding-text sanitization (neutralize @ anywhere, not just leading). R1 (fixing R0-introduced regressions): - Make the stale-head check a real gate that stops before posting, not an advisory echo followed by an unconditional gh pr comment. - Validate the --pr value to ^[0-9]+$ in the model layer before building the shell prefix, closing a PR_ARG assignment-time injection. - Extract headRefOid via gh --jq (no python3 dep) and treat an empty OID as a hard error instead of silently skipping the head guard. - Also require a clean working tree at the PR head (not just HEAD==oid). - Write the comment body with the Write tool, never a fixed-delimiter heredoc a steered finding line could forge. - Restore composer in the skill description. Loop stopped by judgment: it diverged (8 -> 13 findings), and the recurring class (whole publish path is model-interpreted prose) is a named residual — extract it into a testable scripts/ helper as a follow-up rather than bolting on more inline shell. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHHArYXzAy4DVYyFu15bpU
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
--pr [<number>]flag on/swarm:review: run the local mixture-of-agents ensemble against a GitHub PR's diff and post the surviving findings as a PR comment — the codex/grok/Claude review voice on GitHub with no CI setup, repo secrets, or API-token cost.Changes
plugins/swarm/skills/review/SKILL.md—--prflag parsing (read-only, mutually exclusive with--fix/--loop); agh-backed diff-source block in step 1 (resolve PR viagh pr view, diff viagh pr diff, gracefulSWARM_PR_ERRstops); step-3 routing + PR header; new step 5 (build body from output-gated findings only,## 🐝 Swarm reviewmarker header, confirm once, post viagh pr comment, graceful failure, pr-flow compatibility note).0.3.1→0.4.0(minor);plugin.json+marketplace.jsonin sync.swarm-review-pipeline.md+ index capture the design.Readiness
check-structure.pygreen (0 errors)Test plan
/swarm:review --pr <n>against a real PR resolves the diff and runs the ensemble## 🐝 Swarm reviewheader and is not picked up by pr-flow'sclaude-author polling--pr --fix/--loopis refused with a clear messageghmissing/unauthenticated, no PR, or post failure each report clearly without losing the review🤖 Generated with Claude Code