Closes #334 - Add workflows/review-merge-pr.md with reviewer-only gates and steps - Add schemas/review-merge-final-report.md with mutation ledger fields - Turn SKILL.md into task-mode router; replace inlined §F/§G with links - Point review/merge templates at extracted workflow - Add doc-contract tests for split structure Part of #333. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
7.8 KiB
Review and merge PR workflow
Task mode: review-merge-pr
Load this file before any PR review or merge mutation. Parent router:
../SKILL.md. Final report schema:
../schemas/review-merge-final-report.md.
Mode isolation (hard walls)
Review mode must not:
- create issues or edit issue bodies
- edit repository files, run formatting, or fix code
- claim issues, create branches, commit, push, or open PRs
- use author MCP namespace (
gitea-tools/prgs-author) for mutations - improvise raw MCP repair, shell fallbacks, or background task tools
Review mode must:
- use reviewer MCP namespace (
gitea-reviewer/prgs-reviewer) - prove identity, profile, runtime context, and exact capabilities before mutation
- validate only in a session-owned worktree under
branches/ - keep the main checkout on
master/main/devfor orchestration only
If the authenticated user equals the PR author → stop (no self-review, no self-merge).
Global worktree rule (reviewer)
The main project checkout is orchestration only. All review validation happens
under branches/ — typically a detached review worktree from
scripts/worktree-review <pr-head-branch>.
Before validation, prove:
- project root
- working directory (must be under
branches/) - worktree path
- worktree clean status
- pinned PR head SHA ==
git rev-parse HEAD
Never run git stash, git checkout --, git reset, or git clean on
another session's dirty files. If the shared worktree is dirty, create a scratch
review worktree instead.
Merge simulation (git merge --no-commit, git merge --abort) is a
worktree/index mutation, not read-only diagnostics (#317).
1. Pre-flight gates
Run before any PR mutation:
gitea_whoami— prove reviewer identity (not PR author)gitea_get_profile/gitea_get_runtime_contextgitea_resolve_task_capabilityforreview_pr,approve_pr,merge_prgitea_check_pr_eligibilityfor the intended action on the selected PR
Capability claims must cite exact resolver output (#179); bare "checks passed" is downgraded.
Stay in the reviewer namespace. Any author-namespace call requires explicit justification in the final report.
2. PR inventory and queue selection
Repo disambiguation
Gitea-Tools/gitea tool/MCP Gitea tool→Scaled-Tech-Consulting/Gitea-Toolsmcp-control-plane→Scaled-Tech-Consulting/mcp-control-plane- Ambiguous requests → inventory both configured repos
Report must state exactly which repo(s) were checked. A single-repo zero must not be reported as a global empty queue if the other repo was not inventoried.
Pagination proof (#330)
PR inventory completeness requires explicit final-page/no-next-page evidence, total-count evidence, or traversal until an empty/final page. Do not prove completeness by assuming the default Gitea API page size.
Trust gate (#196, #198)
Before reporting "no open PRs" or "queue empty":
- run
pr_inventory_trust_gate(orreview_proofs.assess_reviewer_queue_inventory) - only
trusted_emptyallows a clean empty-queue stop - a bare
[]fromgitea_list_prsis never sufficient
Empty-queue reports must include pr_inventory_trust_gate.status, reasons,
corroboration, remote/owner/repo/state filter, and inventory MCP profile.
Queue ordering (#321, #318)
Select the lowest eligible open PR unless a documented blocker requires skipping. Skipping requires live proof the blocker still applies — not stale handoff text.
Already-landed gate (#292, #294, #295)
If the PR head is already on the target branch, stop review/approve/merge. Redirect to reconciliation workflow; do not treat as review-eligible.
3. Review worktree and pinned head
scripts/worktree-review <pr-head-branch>→ detached underbranches/review-*- Prove checkout (#173):
- pinned PR head SHA from Gitea
- local
git rev-parse HEAD HEAD ==pinned head- diff base == PR base branch
- If head moved → re-pin and restart review
- Confirm worktree clean; inspect full diff; confirm scope matches linked issue
Linked issue consistency (#314): fetch/verify the linked issue live. Report the
same issue number in all sections. If not verified:
Linked issue status: not verified in this session.
Secret/provenance sweep (#179): state exact command/script/pattern and scope.
4. Validation
Run tests from the review worktree. Report must include (#311):
- exact command as executed
- working directory
- exact result (pass/fail counts)
- executable path proof for bare commands like
pytest(which,--version)
If full suite fails, default action is REQUEST_CHANGES (#323). Approval with
failures requires baseline worktree proof under branches/, not main checkout.
During validation, use gitea_dry_run_pr_review — never live APPROVE/REQUEST_CHANGES
to probe tool paths.
5. Review mutation (terminal)
After validation completes:
- Re-fetch PR; verify head SHA unchanged
gitea_mark_final_review_decisionwith pinned headgitea_submit_pr_review(..., final_review_decision_ready=True)— exactly one live reviewgitea_get_pr_review_feedback— confirm visible verdict (approval_visiblefor APPROVE; PENDING drafts do not count — #244)
Final reports must list exactly one review mutation
(review_proofs.assess_review_mutation_final_report).
Hard-stop after terminal review mutation (#332): do not perform additional review mutations in the same session unless operator-approved correction.
6. Merge preflight and execution
Merge only when:
- eligible non-author reviewer
- visible APPROVED review at pinned head
- no undismissed REQUEST_CHANGES
- PR open and mergeable
- live head == pinned reviewed head (re-fetch immediately before merge)
Use gitea_merge_pr with confirmation="MERGE PR <n>" and expected_head_sha.
Gated merge refuses moved heads and widened diffs when expected_changed_files is set.
7. Post-merge cleanup
After confirmed merge on remote master:
- Post-merge file-presence verification on
master - Close/release linked issue; remove
status:in-progress - Delete remote branch (when safe)
scripts/worktree-clean --delete-branch <branch>- Fetch/prune; confirm main checkout clean and
0 0vs remote
Never run cleanup before merge is confirmed on remote master.
See also ../templates/worktree-cleanup.md.
8. Fail-closed stops
Stop and report (no mutating action) when:
- identity/capability cannot be proven
- self-author detected
- worktree state unclear
- pinned head mismatch
- inventory incomplete or untrusted
- tests fail without baseline proof
- PR closed-not-merged (
merged=false) — run reconciliation instead - infra_stop or MCP transport failure — recovery handoff only
When blocked, emit recovery handoff per
../templates/recover-bad-state.md.
9. Role-boundary proof (#175)
A reviewer queue task must not silently become author implementation. If no eligible PR exists, stop with the queue report. Do not claim issues, branch, commit, push, or open PRs unless the operator explicitly retasks as author work.
Use review_proofs.assess_role_boundary; downgrade or stop if not clean.
10. A-bar proofs (#179)
All required before A-grade report or merge:
assess_capability_evidenceassess_sweep_evidenceassess_live_state_recheck(immediately before review submit and merge)assess_role_boundaryassess_review_mutation_final_reportbuild_final_report
Missing proof → downgrade or block merge.
Prompt templates
Short triggers still work via templates that reference this workflow: