Files
Gitea-Tools/skills/llm-project-workflow/workflows/review-merge-pr.md
T
sysadminandClaude Opus 4.8 3976f886e4 feat(skill): extract review-merge-pr workflow from monolithic SKILL.md
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]>
2026-07-07 03:32:59 -04:00

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/dev for 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:

  1. project root
  2. working directory (must be under branches/)
  3. worktree path
  4. worktree clean status
  5. 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:

  1. gitea_whoami — prove reviewer identity (not PR author)
  2. gitea_get_profile / gitea_get_runtime_context
  3. gitea_resolve_task_capability for review_pr, approve_pr, merge_pr
  4. gitea_check_pr_eligibility for 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 toolScaled-Tech-Consulting/Gitea-Tools
  • mcp-control-planeScaled-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 (or review_proofs.assess_reviewer_queue_inventory)
  • only trusted_empty allows a clean empty-queue stop
  • a bare [] from gitea_list_prs is 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

  1. scripts/worktree-review <pr-head-branch> → detached under branches/review-*
  2. Prove checkout (#173):
    • pinned PR head SHA from Gitea
    • local git rev-parse HEAD
    • HEAD == pinned head
    • diff base == PR base branch
  3. If head moved → re-pin and restart review
  4. 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:

  1. Re-fetch PR; verify head SHA unchanged
  2. gitea_mark_final_review_decision with pinned head
  3. gitea_submit_pr_review(..., final_review_decision_ready=True) — exactly one live review
  4. gitea_get_pr_review_feedback — confirm visible verdict (approval_visible for 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:

  1. Post-merge file-presence verification on master
  2. Close/release linked issue; remove status:in-progress
  3. Delete remote branch (when safe)
  4. scripts/worktree-clean --delete-branch <branch>
  5. Fetch/prune; confirm main checkout clean and 0 0 vs 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_evidence
  • assess_sweep_evidence
  • assess_live_state_recheck (immediately before review submit and merge)
  • assess_role_boundary
  • assess_review_mutation_final_report
  • build_final_report

Missing proof → downgrade or block merge.


Prompt templates

Short triggers still work via templates that reference this workflow: