feat: reusable label-gated PR review loop (review / security / tests)#2
Merged
Conversation
Three Jules agents per round, each with a distinct lens and a strict JSON contract; designed around two constraints: no wasted agent turns and no PR noise. Loop mechanics: - The trigger label is a button: removed on pickup (re-arms), jules:reviewing while running, outcome labels per agent (review:approved|needs-changes, security:clear|flagged, tests:sufficient|needs-work) plus jules:approved / jules:error rollups. Label taxonomy bootstraps idempotently. - Same-SHA presses no-op unless the force label is used; the caller holds a per-PR job-level concurrency group with an exact-match label guard so our own label writes can never cancel an in-flight round. - New commits (synchronize) strip stale outcome labels and cancel the round. - Delta rounds: each agent's sticky comment carries a hidden marker (reviewed SHA, round, base64 open-findings state); the next round makes agents verify each previous finding (resolved/unresolved) and review only the diff since the last reviewed SHA. - Noise ceiling: exactly one sticky comment per agent, PATCHed in place. Resolved findings collapse into <details>. - Verdict -> labels is DERIVED from open findings (critical/high = fail, medium = warn); the model's own verdict can only make it stricter, so an agent cannot green-light its own open findings. - Human PR discussion (minus our stickies) is included in the prompt so agents see pushback and decisions. Context gathering reuses the pr-description include/exclude + per-file collapse strategy; per-agent guidelines files from the calling repo are appended to the prompts (e.g. RULES.md for review, CREDENTIALS.md for security).
- Rename the review-loop control labels jules:* -> muse:* (trigger muse:review, muse:force, state muse:reviewing, rollups muse:approved / muse:error) and brand user-visible strings (sticky headers, label descriptions) as Muse; Jules stays named where it is the engine (secrets, jules-ai action, session references). Sticky markers move to <!-- muse:<agent> ... --> — safe now, nothing is in production yet. - config/sources/repo.labels.json: canonical versioned label set (control + per-agent outcome labels). - scripts/sync-repo-labels.sh: idempotent sync of the manifest to given repos or every non-archived repo in an org (gh label create --force). GitHub's org 'default labels for new repos' has no API — mirror the manifest there once by hand, or re-run the script / rely on the workflow's self-bootstrap.
The three reusable workflows carried their operator documentation (usage snippets, loop mechanics, Linear/split-mode explanations) as YAML header comments. That prose now lives in docs/muse-workflows.md — one reference covering pr-description, changelog, and the review loop (label taxonomy, delta rounds, verdict derivation, failure modes, inputs) — and each YAML header is a one-breath summary + pointer. Deliberately NOT named AGENTS.md: that name is the convention for instructions addressed TO AI coding agents working on a repo, not documentation about CI automation.
The three lens prompts and the shared JSON contract were heredocs inside
reusable-pr-review.yml. They now live as plain markdown in
.github/actions/muse-prompts/prompts/ (contract.md, review.md,
security.md, tests.md) with {{AGENT}}/{{PREFIX}}/{{ROUND}}/{{MAX_FINDINGS}}
tokens substituted at runtime — editable and reviewable as prose, not
YAML string art.
Delivery mechanism: reusable workflows never check out their own repo,
so files next to the YAML don't exist on the runner. The tiny
muse-prompts composite action solves that — referencing a remote action
downloads the platform-tools tarball, and github.action_path exposes the
templates directory to the calling job.
WeekendSuperhero
enabled auto-merge (squash)
July 14, 2026 20:19
WeekendSuperhero
disabled auto-merge
July 14, 2026 20:20
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
A reusable three-agent PR review loop built on the same jules-ai plumbing as pr-description/changelog, designed around no wasted agent turns and no PR noise. Control labels use the
muse:*namespace.muse:reviewstarts a round and is removed on pickup (re-arms);muse:forcebypasses the same-SHA no-op. Outcome labels per agent +muse:approved/muse:errorrollups; taxonomy bootstraps itself idempotently and is versioned inconfig/sources/repo.labels.jsonwithscripts/sync-repo-labels.shto apply it org-wide.synchronizestrips stale outcome labels and cancels the round; comment/label writes usegithub.token(never triggers other workflows).Test plan
bash -non all run blocks + the sync scriptmuse:reviewon a real PR in the agent repo (caller: agent#298)No changes to existing workflows — new files only.