Files
Gitea-Tools/skills/llm-project-workflow/workflows/review-merge-pr.md
T

49 KiB
Raw Blame History

task_mode, canonical, final_report_schema
task_mode canonical final_report_schema
review-merge-pr true ../schemas/review-merge-final-report.md

Review and merge PR workflow (canonical)

Task mode: review-merge-pr

This file is the canonical PR review/merge workflow for Gitea-Tools. Load it before any PR mutation. Final report schema: schemas/review-merge-final-report.md.

Default task prompt:

Review the next eligible open PR in this project. Merge it only if every identity, capability, author-safety, inventory, queue-ordering, worktree, validation, already-landed, prior-review, final-report, mutation-ledger, proof-wording, and merge gate passes.

Do not improvise around the gates. Follow project skills, MCP gates, and workflow rules exactly.


0. Load the canonical workflow first

Before starting PR work, check whether the project provides a canonical PR review/merge workflow through a project skill, runbook, or MCP helper.

If available, load it first and report:

  • workflow source
  • workflow version, commit, or hash
  • whether this prompt conflicts with the loaded workflow

If the canonical workflow cannot be loaded and the project requires it, stop and produce a recovery handoff only.

0A. Workflow-load and session boundary anchor (#403)

The MCP gate is the authority — not local file viewing.

Before any reviewer mutation:

  1. Record pre-review commands with gitea_record_pre_review_command when they are not automatically classified (inventory/diagnostic commands may be recorded explicitly for proof).
  2. Call gitea_load_review_workflow to establish workflow hash proof and session boundary state in the same in-process session proof.
  3. Do not claim the workflow was loaded by reading skills/llm-project-workflow/workflows/review-merge-pr.md as a local file; that narrative does not satisfy the validator.

Allowed before workflow load (classify as read_only_inventory or diagnostic):

  • gitea_whoami, gitea_resolve_task_capability, gitea_list_prs, gitea_view_pr, gitea_get_runtime_context
  • git fetch / git remote update for inventory
  • git status, git worktree list (read-only)

Boundary violations (block downstream reviewer mutations even after load):

  • validation commands (pytest, python -m unittest) in the main checkout
  • local profile/credential/config inspection (profiles.json, gitea-mcp.json, .env, keychain dumps)
  • MCP repair (pkill, MCP config edits)
  • git mutations before workflow load

Final reports must include a structured Workflow-load helper result block copied from gitea_load_review_workflow, including at minimum:

  • workflow_hash
  • final_report_schema_hash
  • boundary_status (clean or violation)

1. Start with live identity, profile, runtime, and capability checks

Prove:

  • authenticated identity
  • active reviewer profile
  • repo/project
  • runtime context
  • exact capabilities needed for inventory, review, request-changes, approve, comment, and merge

A nearby capability does not count.

Examples:

  • create_issue does not authorize issue_comment
  • review_pr does not authorize merge_pr
  • issue_comment does not authorize create_issue
  • review_pr does not authorize request_changes unless the capability explicitly covers that operation
  • review_pr does not authorize approve unless the capability explicitly covers that operation

If capability cannot be proven, stop and produce a recovery handoff only.

2. Stop immediately on blocked infrastructure

If any of the following appears, stop immediately:

  • infra_stop
  • MCP reconnect failure
  • stale capability state
  • dirty control checkout
  • dirty review worktree
  • missing capability
  • workspace mismatch
  • stale target branch state
  • broken canonical workflow loading
  • failed required preflight
  • capability resolver warning that says the current state may be unsafe
  • stale or inconsistent runtime context

Do not continue PR selection, validation, review, approval, merge, cleanup, or reconciliation.

Produce an executable recovery handoff only.

Blocked recovery handoffs must not include direct approve or merge replay commands.

Blocked handoffs must say to rerun the full workflow after the blocker clears.

Do not preserve stale ready to merge, approved, or all gates passed state across MCP failures, reconnects, or capability re-resolution.

3. Author safety

If you are the PR author, stop immediately.

Do not approve, request changes, comment as reviewer, merge, close, or mutate the PR.

Produce a recovery handoff only.

If author identity cannot be proven, stop and produce a recovery handoff only.

If authenticated identity changes during the run, restart identity/profile/capability checks before any further mutation.

4. Main checkout rule

The main project checkout must stay on master, main, or dev.

Do not review, test, fix, merge, resolve conflicts, or cleanup from the main checkout.

Do not run tests in the main checkout.

Do not run baseline validation in the main checkout.

All PR validation and baseline comparison work must happen under the projects branches/ directory.

No exceptions for small fixes, docs, tests, cleanup, conflict resolution, emergencies, or “just one file.”

Updating the main checkout is allowed only after a successful merge and only if the project workflow explicitly allows stable-branch update.

Do not update the main checkout if merge failed, was blocked, or produced reconciliation-only status.

If the main checkout is dirty before selection, stop and produce a recovery handoff.

If the main checkout becomes dirty during the run, stop and produce a recovery handoff unless the only change is the explicitly allowed post-merge stable-branch fast-forward.

5. No raw MCP repair during normal review

Do not run pkill, kill MCP processes, edit MCP config, restart servers, or perform control-checkout repair during normal PR review.

If MCP repair is required, stop PR review and produce a separate CONTROL-CHECKOUT REPAIR MODE handoff.

Do not mix MCP repair mode with PR review/merge mode.

Do not use successful repair as permission to resume the same review flow. After repair, rerun the full workflow from the beginning.

6. No background task tools

Do not use schedule, manage_task, background jobs, async waits, or delayed task tools during PR review/merge.

Use direct commands and MCP tools only.

If a required action cannot complete synchronously, stop and produce a recovery handoff.

Long synchronous commands, such as a test suite, are allowed only if they are run directly and reported with exact command, working directory, and result.

Do not say “I will check later,” “I will monitor,” or “I will continue in the background.”

7. No local Gitea fallback during normal review

During normal reviewer workflows, do not read Gitea profile secret files.

Do not inspect or open files such as:

  • profiles.json
  • local token stores
  • credential files
  • local Gitea auth/profile config files
  • .env files containing Gitea credentials
  • keychain dumps
  • token helper outputs

Do not run local Gitea helper scripts when MCP tools are available.

Use MCP tools for Gitea operations.

Local fallback is allowed only in explicit recovery mode when MCP is unavailable and identity/profile/capability can be independently proven.

If local fallback is used, report:

  • why MCP was unavailable
  • exact identity proof
  • exact profile proof
  • exact repo proof
  • exact capability proof
  • exact local command used

Do not use local fallback to bypass MCP gates.

8. Build a complete live PR inventory

List all open PRs.

Follow pagination until the tool proves there are no more pages.

Do not assume inventory is complete.

Do not claim oldest eligible PR, next eligible PR, or complete queue inventory unless pagination is proven.

Pagination proof must not rely on assumed default API page size.

Inventory is complete only if one of the following is proven:

  • the MCP response explicitly says there is no next page / has_more=false / final page
  • the workflow traversed pages until an empty page or explicit final page was returned
  • the tool response includes total-count or pagination metadata proving all open PRs were returned
  • the request explicitly set page / limit / per_page, and the response explicitly proves the server honored that page size and did not truncate results

Do not say “inventory complete” merely because the result count is less than an assumed default page size.

If the tool returns exactly the requested page size, assume there may be more pages unless the tool proves otherwise.

If pagination metadata is absent and the tool cannot page, report INVENTORY_PAGINATION_UNPROVEN and stop unless the canonical workflow explicitly permits continuing with an incomplete inventory.

For each open PR, identify:

  • PR number
  • title
  • author
  • base branch
  • head branch
  • draft/WIP state
  • mergeability
  • linked issue
  • current head SHA
  • whether the PR appears already landed

Final report must include pagination/final-page proof.

9. Queue ordering proof rule

State the queue ordering policy before selecting a PR.

If the project uses oldest-first review, explicitly sort or reason by PR number or created date.

Do not rely on the API response order unless the tool proves that order matches the project policy.

If newer PRs appear before the selected PR in the API response, explain that they are newer and not earlier in the queue.

Final report must include:

  • queue ordering policy used
  • whether API order matched that policy
  • selected PRs position under that policy
  • earlier PRs considered
  • earlier PRs skipped and why

If queue ordering cannot be proven, stop and produce a recovery handoff.

10. Select the next actionable PR using project rules

If the open PR queue is empty:

  • First, look at approvals next to see if there are pending approvals or approved PRs that need attention/merge.
  • Next, look at issues next to see if there are open issues requiring action/fixes.

Do not review your own PR.

Do not review stale, draft, blocked, duplicate, already-owned, dependency-blocked, already-landed, already-requested-changes work unless the rules explicitly allow it.

Do not skip an earlier actionable PR without documenting why.

Use these terms precisely:

  • Oldest open PR requiring action
  • Eligibility class
  • Next review/merge eligible PR

Do not call an already-landed PR eligible for review or eligible for merge.

If the oldest open PR is already landed, classify it as:

ALREADY_LANDED_RECONCILE_REQUIRED

If the oldest open PR is ALREADY_LANDED_RECONCILE_REQUIRED, stop normal review immediately unless project policy explicitly allows skipping reconciliation blockers.

Report:

Queue blocked by already-landed PR requiring reconciliation

Do not keep rerunning normal review on the same already-landed PR.

If the selected PR is not the oldest open PR requiring action, report why every earlier PR was not actionable.

11. Skip-prior-PR rule

Do not skip an earlier open PR without live proof or explicitly labeled prior proof from current-session review feedback.

If skipping because of prior REQUEST_CHANGES, fetch current review feedback and verify the head SHA has not changed since the blocking review.

If skipping because of non-mergeable status, fetch live PR state and provide conflict proof.

Report for every skipped earlier PR:

  • skipped PR number
  • current head SHA
  • blocking category
  • blocking review decision, if applicable
  • blocking review head SHA, if applicable
  • mergeability result, if applicable
  • conflict proof command/tool, if applicable
  • conflicting files, if available
  • whether the head changed after the blocker
  • reason it remains blocked

If blocker proof cannot be fetched, classify the PR as:

BLOCKER_STATUS_UNVERIFIED

Then stop or produce a recovery handoff according to project policy.

Do not skip an earlier PR based only on memory from a previous session.

11A. Skipped PRs are read-only

Skipping an earlier PR must be a read-only classification step.

Do not submit REQUEST_CHANGES, approve, comment, merge, close, or otherwise mutate a skipped PR.

If an earlier PR already has unresolved REQUEST_CHANGES at the same head SHA, do not duplicate the review. Fetch the review feedback, verify the head SHA is unchanged, classify the PR as blocked, and move on only if project policy allows skipping blocked PRs.

If the head SHA changed after the blocking review, the PR is not safely skippable based on the old blocker. Re-evaluate it according to queue policy.

The final report must distinguish:

  • prior blocker reused
  • blocker revalidated live in this session
  • blocker status unverified

Do not claim live proof unless the proof command or MCP tool ran in the current session.

If you mutate a skipped PR, stop immediately and report a workflow violation.

12. Non-mergeable skip proof rule

Do not skip a non-mergeable earlier PR without live proof.

For every skipped non-mergeable PR, report:

  • PR number
  • current head SHA
  • mergeability result
  • command/tool used to prove conflict
  • conflicting files, if available
  • whether head changed since any prior blocker

If conflict proof cannot be retrieved, classify the PR as:

MERGEABILITY_UNVERIFIED

Then stop or produce a recovery handoff according to project policy.

Conflict proof must be obtained in a session-owned diagnostic worktree under branches/, unless the MCP tool itself provides exact conflict files and proof.

Do not perform conflict proof in the main checkout.

13. Prior request-changes override rule

Before approving a PR, fetch current PR review feedback.

If the PR has a prior REQUEST_CHANGES review, report:

  • blocking reviewer
  • blocking review timestamp
  • blocking review head SHA
  • current head SHA
  • blocker text
  • whether the head changed since the blocker

If the head changed after the request-changes review, verify the new head addresses the blocker before approving.

If the head did not change after the request-changes review, do not approve unless you prove one of:

  • the earlier blocker was incorrect
  • the validation environment was wrong
  • the issue was resolved externally in a way that does not require PR head changes
  • project policy explicitly permits overriding that blocker with proof

If this proof is missing, do not approve.

If the selected PR still has unresolved REQUEST_CHANGES at the same head SHA and no override proof exists, submit REQUEST_CHANGES only if no equivalent unresolved request-changes review already exists at that same head SHA. Otherwise stop with a recovery handoff or classify it blocked according to project policy.

Final report must include the prior blocker, current head, whether head changed, and why approval is safe.

14. Pin the PR head SHA before validation

Re-fetch the selected PR.

Record the current head SHA.

Call this the candidate head SHA.

Do not call it the reviewed head SHA until validation and diff review have actually passed.

If the head SHA changes before review submission or merge, restart review or stop.

If the head SHA changes after approval but before merge, do not merge. Restart review or stop.

Final report must include:

  • candidate head SHA
  • reviewed head SHA, only if validation and diff review passed
  • whether head changed during the run

15. Refresh target branch before ancestry checks

Fetch the PR target branch from the remote before checking whether the PR head is already landed.

Do not rely on stale local master, main, or dev.

Record the fetched target branch SHA used for ancestry checks.

If the target branch cannot be fetched or verified, stop and produce a recovery handoff.

git fetch, git remote update, and any command that updates refs must be reported under Git ref mutations, not read-only diagnostics.

16. Already-landed PR gate

After pinning the PR head SHA and refreshing the target branch, check whether the PR head SHA is already an ancestor of the target branch.

If the PR head SHA is already landed on the target branch, stop normal review/merge flow.

Do not approve the PR.

Do not request changes unless there is a real code/review blocker.

Do not call the merge API.

Produce an ALREADY_LANDED_RECONCILE_REQUIRED handoff instead.

The handoff must include:

  • PR number/title
  • eligibility class
  • candidate head SHA
  • reviewed head SHA: none
  • target branch
  • target branch SHA
  • ancestor proof
  • linked issue status, if verified
  • recommended reconciliation action
  • required capabilities for reconciliation

Any close/comment/issue mutation requires separate exact capability proof.

Do not tell the user or another agent to manually close a PR or issue unless the handoff clearly says capability must be proven first or an authorized human must do it.

17. Linked issue verification

If the PR claims to close or link an issue, fetch the linked issue live before reporting its status.

If the linked issue was not fetched live in the current session, report:

Linked issue status: not verified in this session

Do not claim issue open, issue closed, or issue resolved without live proof.

Any PR close, issue close, or comment recommendation must say exact capability must be proven first, unless an authorized human performs it.

The linked issue number in diagnostics, final report, and controller handoff must match the selected PR.

Do not include stale issue numbers from prior PRs.

If linked issue status changes after merge, fetch the issue again before reporting post-merge status.

18. Review worktree ownership rule

Prefer a fresh session-owned review worktree under branches/, named like:

branches/review-pr<PR_NUMBER>-<branch-name>

Do not reuse a branch-named or existing worktree unless safe-reuse proof passes.

Safe-reuse proof must include:

  • exact worktree path
  • worktree is inside branches/
  • worktree is not the main checkout
  • worktree is not owned by another active task/session
  • clean tracked state
  • clean untracked state
  • current branch/head before reset
  • reset target SHA
  • explicit project policy allowing reuse/reset

Do not run git reset --hard, git clean, checkout, or other destructive worktree commands unless the worktree is session-owned or safe-reuse proof passes.

If safe-reuse proof cannot be produced, create a fresh session-owned review worktree.

19. Reviewer worktree no-edit rule

The PR validation worktree is for validating the submitted PR head only.

Do not edit files in the PR validation worktree.

Do not apply local fixes in the PR validation worktree.

Do not run official validation after modifying the PR validation worktree.

If you need to test a possible fix, create a separate diagnostic scratch worktree and label it clearly:

Diagnostic local experiment — not PR-head validation

Any diagnostic edits must be reported under File edits by reviewer.

Diagnostic test results must not be reported as official PR validation results.

Do not say File edits by reviewer: none if any file was edited in any review, diagnostic, baseline, or artifact worktree.

20. Validate in a session-owned worktree under branches/

Prove:

  • exact review worktree path
  • worktree is inside branches/
  • worktree is clean before validation
  • PR head is checked out in that worktree
  • review worktree HEAD matches candidate head SHA

Run required validation:

  • tests
  • compile checks
  • lint checks
  • diff checks
  • secret/provenance checks
  • dangerous artifact checks
  • project-specific validation

If validation fails, request changes with exact blockers, unless an equivalent unresolved request-changes review already exists at the same head SHA.

If an equivalent unresolved request-changes review already exists at the same head SHA, do not duplicate it. Stop with a final report or recovery handoff according to project policy.

If validation cannot run, do not approve or merge.

21. Official validation integrity rule

Record the PR head SHA before validation.

Prove the validation worktree is clean before validation.

Run validation against the unmodified PR head.

After validation, prove the validation worktree is still clean.

If validation fails, submit REQUEST_CHANGES using the unmodified PR-head failure, unless an equivalent unresolved request-changes review already exists at the same head SHA.

If the worktree was edited after validation for diagnosis, report it separately and do not use post-edit test results as official validation.

If official validation was contaminated by a local edit, stop and produce a recovery handoff.

Official validation integrity status must be one of:

  • passed
  • failed
  • not run
  • contaminated — recovery required

Do not invent a softer status.

21A. Validation failure history rule

Every validation failure observed during the review session must appear in the final report, even if a later rerun passes.

Before claiming Validation: passed, list every failed validation command from the session under Validation failure history.

For each failure, report:

  • command
  • failing test or error
  • suspected cause
  • whether it reproduced
  • whether it exists on baseline master
  • evidence for whether it is or is not PR-caused

If a later rerun passes, also report:

  • what changed between runs
  • whether environmental state was cleaned (for example /tmp lock files)
  • why the pass is trustworthy

If the cause is unknown, do not erase the earlier failure with plain Validation: passed. Use a status such as passed after transient failure investigation.

gitea_validate_review_final_report rejects reports that omit known earlier validation failures when validation_session.observed_failures is supplied.

21B. Validation status taxonomy (#406)

When the final report summarizes how validation concluded, use one of these validation status labels (distinct from per-command pass/fail entries):

  • passed — raw PR-head validation passed on the unmodified head.
  • failed — raw PR-head validation failed and no allowed resolution path was proven.
  • baseline-equivalent failure accepted — only when a clean baseline worktree under branches/ proves matching failure signatures on the target branch (baseline path, target SHA, exact commands, failure lists, and failure signatures match: true).
  • raw-head failure resolved by merge simulation — raw PR-head validation failed, but merge simulation into the current target passed cleanly; report merge simulation under Worktree/index mutations with full #317 proof.
  • passed after transient failure investigation — a later run passed after an earlier failure in the same session; document the failure history (#396).

Do not use baseline-equivalent failure accepted when only merge simulation resolved the failure. Do not use bare passed when raw PR-head validation failed unless one of the resolution statuses above applies.

22. Baseline validation rule

Do not run tests in the main checkout.

If the PR full suite fails and you need to compare failures against master, create a clean baseline worktree under branches/, such as:

branches/baseline-master-pr<PR_NUMBER>

Baseline comparison must include:

  • baseline worktree path
  • baseline target SHA
  • PR head SHA
  • exact command run on both worktrees
  • baseline failures
  • PR failures
  • proof the failure signatures match
  • proof the baseline worktree was clean before and after validation
  • proof the PR worktree was clean before and after validation

Do not approve a PR with full-suite failures unless:

  • project policy allows baseline comparison
  • baseline proof is complete
  • failure signatures match
  • new/changed tests pass
  • failures are proven unrelated to the PR

If full-suite failures differ or proof is incomplete, submit REQUEST_CHANGES, unless an equivalent unresolved request-changes review already exists at the same head SHA.

Do not claim “same as master” unless the clean baseline worktree proof is included.

Do not claim “full-suite failures are pre-existing” unless baseline proof is complete and the failure signatures match.

23. Validation command proof rule

Before any diff, test, or compile validation, record in the same command transcript or final report:

  • pwd or explicit working directory
  • git rev-parse HEAD
  • git status --short --branch
  • expected PR head SHA (candidate head SHA)

Validation commands must use one of:

  • git -C <review_worktree> ...
  • cd <review_worktree> && ... in the same command
  • tool-provided explicit working-directory metadata

Do not rely on inferred shell cwd from a prior command in a different block.

gitea_validate_review_final_report rejects validation claims without cwd/HEAD proof when validation_session is supplied.

Baseline validation must document baseline worktree path, baseline target SHA, cwd proof, exact baseline command, and baseline result using the same rules.

Report the exact validation command as executed.

Report the working directory where validation ran.

If using bare pytest, also report:

  • which pytest
  • pytest --version
  • whether it resolves to the project venv

Prefer the project venv executable when available, for example:

/Users/jasonwalker/Development/Gitea-Tools/venv/bin/pytest tests/

Do not summarize validation as just pytest passed unless the exact command, working directory, and result are included.

For every validation command, report:

  • command
  • working directory
  • exit code or pass/fail result
  • summary count if available
  • whether it was official PR-head validation, baseline validation, or diagnostic-only validation

24. Local merge simulation rule

A local merge simulation is not read-only.

Commands such as the following must be reported as worktree/index mutations:

  • git merge --no-commit
  • git merge --abort
  • git reset
  • git checkout
  • git clean
  • git worktree add
  • git worktree remove

If merge simulation is needed, prefer a separate session-owned diagnostic worktree.

If merge simulation is run in the review worktree, prove:

  • worktree clean before simulation
  • exact merge command
  • result/conflict status
  • abort/reset command
  • worktree clean after abort

Do not list merge simulation under read-only diagnostics.

Do not call the worktree clean after simulation unless clean status was actually checked after abort/reset.

If conflicting files are reported, they must come from current-session proof.

25. Review the actual diff

Check:

  • correctness
  • tests
  • scope
  • security boundaries
  • workflow rule compliance
  • whether the PR really closes or satisfies the linked issue
  • unrelated changes
  • dangerous generated artifacts
  • secrets
  • provenance markers
  • temporary agent files
  • whether the PR is redundant because the diff is already present on the target branch
  • whether the PR modifies reviewer workflow, MCP gates, profiles, routing, or authorization boundaries
  • whether documentation and tests match behavior

Do not approve based only on test pass/fail status. Review the diff.

Report files reviewed.

26. Review decision

If blockers exist, submit REQUEST_CHANGES, unless an equivalent unresolved request-changes review already exists at the same head SHA.

If non-blocking notes exist, comment clearly only if exact comment capability is proven.

If everything passes, approve only if exact approve/review capability is proven.

Do not approve and merge unless both actions are separately authorized.

Submit review only after dry-run review passes if the tool supports dry run.

Do not approve already-landed, redundant, stale, or reconciliation-only PRs.

Do not approve a PR with unresolved prior REQUEST_CHANGES unless the prior-request-changes override rule is satisfied.

Do not submit review mutations on skipped PRs.

26A. Terminal review mutation hard-stop

A live review mutation is terminal for the current reviewer run except for same-PR merge continuation after approval.

Terminal review mutations include:

  • REQUEST_CHANGES
  • APPROVED
  • review comment submission
  • PR comment submission used as review feedback
  • any tool that records final review decision state
  • any tool that changes PR review state
  • any tool that consumes a session review-mutation budget

After REQUEST_CHANGES or blocking feedback, stop immediately and produce the final report.

After APPROVED, continue only to merge preflight and merge for the same selected PR, if merge is authorized and all merge gates pass.

Do not mutate one PR and then continue reviewing, approving, requesting changes, commenting on, or merging another PR in the same run.

Do not consume a live review mutation on an earlier skipped PR.

If a live mutation happens on a non-selected or skipped PR, stop immediately and report the workflow violation.

If a tool blocks further review mutation because a live mutation already occurred, stop immediately. Do not continue validation of another PR.

The final report must identify:

  • the terminal mutation
  • PR number affected by the terminal mutation
  • whether same-PR merge continuation was allowed
  • whether the run stopped as required

26B. Per-PR reviewer lease (#407)

Parallel reviewer sessions are allowed only when each session holds a distinct, live PR lease.

Before validation or review mutation on a selected PR:

  1. Call gitea_acquire_reviewer_pr_lease with worktree path, candidate head SHA, and target branch SHA.
  2. Post heartbeats via gitea_heartbeat_reviewer_pr_lease before validation, after validation, before review mutation, and before merge.
  3. Do not approve, request changes, or merge unless the in-session lease matches the selected PR.

If PR head or target branch advances during the lease, stop and refresh inventory before continuing.

Final reports must include lease session id, acquisition proof, heartbeat status, and release/blocked status.

26B-1. Merger lease adoption (#536)

When review and merge are different sessions, the merger must adopt the reviewer's lease — never manually seed reviewer_pr_lease._SESSION_LEASE.

Before merge in a merger-only session:

  1. Confirm approval_at_current_head via gitea_get_pr_review_feedback.
  2. Call gitea_adopt_merger_pr_lease from a clean merger worktree under branches/, passing expected_head_sha pinned to the approved head.
  3. Quote the adoption comment id and adopted_from_session_id in the handoff.
  4. Proceed to gitea_merge_pr only after adoption succeeds.

Manual in-process lease seeding is rejected by mutation gates (fail closed).

26C. Conflict-fix lease and stale-head protection (#399)

Before validating, approving, or merging a PR:

  1. Check for an active conflict-fix lease on the PR; stop if one is active.
  2. Pin expected_head_sha before validation and pass it to gitea_mark_final_review_decision, gitea_submit_pr_review, and gitea_merge_pr.
  3. Re-fetch live PR head immediately before approval and merge; refuse when live head differs from the reviewed SHA.

Final reports must state:

  • reviewed head SHA
  • final live head SHA before approval
  • final live head SHA before merge
  • whether any push occurred during validation

27. Merge rules

Before merge, rerun fresh live checks:

  • whoami
  • active profile/runtime
  • exact merge capability
  • author safety
  • PR re-fetch
  • reviewed head SHA unchanged
  • visible APPROVED review applies to the current live PR head SHA (approval_at_current_head); if the head moved after approval, re-review at the new head before merge (#471)
  • target branch freshly fetched
  • PR still open
  • PR still mergeable
  • PR head is not already landed
  • required checks still pass
  • linked issue handling is correct
  • review worktree is clean

Merge only after all gates pass.

Do not merge if:

  • MCP reconnect failed
  • capability state is stale
  • worktree is dirty
  • PR head changed
  • approval is stale (approved SHA ≠ current live head SHA)
  • validation failed
  • inventory was incomplete
  • PR is already landed
  • target branch is stale
  • you are the PR author
  • prior request-changes override proof is missing
  • terminal review mutation occurred on a different PR earlier in the run
  • final decision was not marked for the selected PR, if the workflow requires final-decision marking

If the merge tool requires an explicit confirmation string, report:

  • first gated/no-op call, if any
  • confirmation string used
  • which call actually performed the merge

Rejected, dry-run, or confirmation-gated merge calls must not be reported as performed merge mutations.

28. After merge

Confirm:

  • merge result
  • target branch updated
  • merged commit/SHA, if available
  • selected PR head SHA is now ancestor of target branch
  • linked issue status if the PR claims to close an issue

Clean only the session-owned branches/ review worktree if the project workflow explicitly allows cleanup.

Review, baseline, and merge-simulation worktrees created during this run are transient and are removed automatically at successful completion once they are clean, carry no open PR, and hold no active lease (#401). Use gitea_audit_worktree_cleanup (read-only) to classify branches/ entries; only clean_stale_removable and detached_review_leftover may be removed, one-by-one, after git worktree list proof plus per-worktree proof of path, branch/HEAD, clean/dirty status, no active PR/lease, and the removal result. Dirty, active-PR, active-issue, and leased worktrees are never deleted automatically; a failed removal must be reported with the leftover path and reason.

Do not delete or mutate unrelated branches/worktrees.

Do not touch the main checkout except to update the stable branch after merge if explicitly allowed by the workflow.

Any stable-branch update after merge is a git mutation and must be reported.

Do not update the main checkout if merge failed, was blocked, or produced reconciliation-only status.

If any local artifact is created after final cleanup, run and report a new final status check.

28A. Post-merge cleanup proof checklist (#402)

Successful tool execution is not proof that cleanup was authorized. Before claiming remote branch deletion or local worktree removal, the final report must carry the full safety checklist below. If any gate is missing, report CLEANUP_SKIPPED with the exact blocker — never perform cleanup and never claim it was performed.

Remote branch deletion checklist

When gitea_delete_branch (or equivalent) deletes the merged PR head branch, report:

  • Delete-branch capability resolved: name the task (delete_branch / cleanup_branch / reconcile_merged_cleanups) and permission (gitea.branch.delete) with resolver proof before the delete call
  • Merge result: merged
  • Merge commit SHA: full 40-character SHA
  • Merged PR head branch / deleted branch: exact branch name (must match)
  • Branch protection: none / branch is not protected
  • Open PR inventory proof: no other open PR references the branch
  • Active heartbeat/claim/lease: none

Local worktree removal checklist

When removing session-owned review/simulation worktrees under branches/, report:

  • Session-owned worktree path: exact path under branches/
  • Pre-removal tracked state: clean
  • Pre-removal untracked state: clean
  • Git worktree list after removal: command output or equivalent proof

Skipped cleanup

If any gate fails, report:

  • Cleanup outcome: CLEANUP_SKIPPED
  • Cleanup blocker: exact missing gate (for example gitea.branch.delete capability not resolved)

Skipped cleanup with an exact blocker passes validation. Performed-cleanup claims without the checklist fail validation.

28B. MCP-native cleanup only (#517)

Post-merge cleanup of leases, comments, branches, and worktrees must go through explicit MCP tools — never raw git, curl/API scripts, or ad hoc helper scripts.

Merger and reviewer sessions must not perform cleanup inline. Record:

  • Merge mutations — only gitea_merge_pr (or review mutations for review-only runs)
  • Cleanup mutations — only authorized reconciler MCP tools, cited by exact tool name

Authorized cleanup tools include gitea_reconcile_merged_cleanups, gitea_cleanup_post_merge_moot_lease, gitea_delete_branch, and gitea_cleanup_merged_pr_branch (when available). Lease cleanup uses append-only release comments — never delete another session's lease comment.

Hand cleanup to a prgs-reconciler session with gitea.branch.delete capability proof. Raw git branch -d, git push --delete, and comment-deletion API calls are blocked in final-report validation.

Template: templates/post-merge-cleanup-handoff.md.

29. Recovery handoff rules

If blocked, produce a recovery handoff with:

  • exact blocker
  • failed tool/function, if any
  • repo/project
  • selected PR, if one was safely selected
  • eligibility class
  • candidate head SHA, if known
  • reviewed head SHA, only if validation and diff review passed
  • target branch and target branch SHA, if known
  • linked issue status, or not verified in this session
  • worktree path, if created
  • exact state reached before stopping
  • safe next action
  • statement that no unsafe mutation was attempted

Blocked handoffs must not include direct approve or merge replay commands.

Blocked handoffs must say to rerun the full workflow after the blocker clears.

If the blocker is a terminal review mutation already consumed in the current run, the handoff must say that the next run must start from the beginning and must not reuse stale ready/approved state.

30. Final report must be precise

Include:

  • canonical workflow source/version/hash, if available
  • authenticated identity/profile
  • repo/project
  • complete PR inventory proof, including pagination/final-page proof
  • queue ordering policy used
  • selected PR number/title/author
  • eligibility class
  • author-safety result
  • skipped earlier PRs and live blocker proof or prior blocker proof, if any
  • prior request-changes proof, if any
  • candidate head SHA
  • target branch and target branch SHA used for ancestry checks
  • reviewed head SHA, only if validation and diff review passed
  • already-landed gate result
  • linked issue proof/status, if applicable
  • main checkout branch
  • main checkout dirty state
  • review worktree used: true/false
  • review worktree path
  • review worktree inside branches/: true/false
  • review worktree HEAD state: detached/branch/none
  • review worktree dirty before validation: true/false/not applicable
  • review worktree dirty after validation: true/false/not applicable
  • baseline validation worktree, if used
  • baseline validation result, if used
  • files reviewed
  • validation commands and results
  • official validation integrity status
  • diagnostic scratch experiments, if any
  • local merge simulation result, if any
  • review decision
  • terminal review mutation, if any
  • merge preflight results, if merge was attempted
  • merge result, if merged
  • cleanup result
  • blockers, if stopped
  • confirmation that the main checkout was not used for task work
  • final proof that no unsupported proof wording is used

If the report and actual tool/command log disagree, fix the report before final output.

31. Final report must distinguish mutation types

Do not use the legacy field Workspace mutations.

Use only precise categories:

  • File edits by reviewer:
  • Worktree/index mutations:
  • Git ref mutations:
  • MCP/Gitea mutations:
  • Review mutations:
  • Merge mutations:
  • Cleanup mutations:
  • External-state mutations:
  • Read-only diagnostics:

git fetch, git remote update, and any command that updates refs must be listed under Git ref mutations, not read-only diagnostics.

If git reset --hard, checkout, clean, worktree add/remove, merge simulation, merge abort, or similar commands occurred, report them under Worktree/index mutations.

Use precise wording:

  • File edits by reviewer: none
  • Worktree/index mutations: ...
  • Git ref mutations: ...
  • MCP/Gitea mutations: ...

Do not collapse review, merge, cleanup, or external-state mutations into vague wording.

31B. Mutation-capability table (#405)

Every performed mutation requires exact capability proof resolved before that mutation executes. Nearby capabilities never authorize a different operation — review_pr does not authorize merge_pr, and merge_pr does not authorize delete_branch / gitea.branch.delete.

When any mutation beyond a bare review occurs (merge, branch delete, issue close/comment, etc.), the final report must include a mutation-capability table with one row per performed mutation:

  • mutation (tool/action name)
  • exact task/capability resolved (for example merge_pr / gitea.pr.merge)
  • result
  • order/timestamp proof that capability was resolved before the mutation

If exact capability proof is missing, skip the mutation or stop the workflow — never claim a performed mutation without its row. Post-hoc capability proof after the mutation fails validation.

31A. Local artifact and report consistency rule

Do not create local walkthrough, notes, markdown, JSON, or report artifacts during reviewer runs unless the canonical workflow or operator explicitly requires it.

If any file is edited, created, generated, or written, report it under File edits by reviewer.

For each file write, report:

  • exact path
  • whether it was inside the repo
  • whether it was tracked or untracked
  • why it was created
  • whether final git status was run after the write

Do not say File edits by reviewer: none if any file write occurred.

Do not write files after the final clean-status check unless you rerun and report a new final clean-status check.

If the action log says Edited, Created, Wrote, or equivalent, the mutation ledger must include that file.

If the file was created outside the repo, still report it under File edits by reviewer and label it outside repo.

If the file was created inside the repo, report whether it is tracked or untracked.

If an artifact was created only for operator handoff, state that explicitly.

Default behavior: do not create walkthrough.md or similar artifacts unless the workflow explicitly requires it.

32. Controller handoff consistency rule

The controller handoff must use the same canonical schema and facts as the final report.

If the already-landed gate fires, the controller handoff must include:

  • Eligibility class: ALREADY_LANDED_RECONCILE_REQUIRED
  • Candidate head SHA:
  • Reviewed head SHA: none
  • Review worktree used: false
  • Review worktree path: none
  • Git ref mutations:
  • Review decision: none
  • Merge result: none

Do not use these legacy fields:

  • Pinned reviewed head
  • Scratch worktree used
  • Workspace mutations
  • Mutations: None when any git ref, MCP, Gitea, review, merge, cleanup, or external-state mutation occurred

The narrative report and controller handoff must agree on:

  • eligibility class
  • candidate head SHA
  • reviewed head SHA
  • mutation state
  • worktree usage
  • review decision
  • terminal review mutation
  • merge result
  • linked issue status

If they disagree, fix the report before final output.

33. Forbidden final-report claims unless proven

Do not claim:

  • oldest eligible PR
  • next eligible PR
  • reviewed head SHA
  • ready to merge
  • workspace mutations none
  • scratch worktree false
  • all gates passed
  • inventory complete
  • already landed
  • merged
  • issue closed
  • manual close required
  • target branch up to date
  • read-only merge simulation
  • no file edits by reviewer
  • same as master
  • full-suite failures are pre-existing
  • prior request-changes resolved
  • local fallback was safe
  • live proof
  • live blocker proof
  • skipped PR
  • terminal mutation none
  • no unsafe mutation

unless the corresponding proof is included.

If anything blocks safe review or merge, stop immediately and produce an executable recovery handoff.

Do not improvise around the gates.

Do not preserve stale ready to merge state across MCP failures or reconnects.

Do not include approve or merge replay commands in a blocked handoff. Say to restart the full workflow after the blocker clears.

34. Proof wording enforcement

The following phrases are forbidden unless directly supported by current-session evidence:

  • live proof
  • live blocker proof
  • inventory complete
  • same as master
  • no file edits
  • full-suite failures are pre-existing
  • issue closed
  • merged
  • target branch up to date
  • all gates passed
  • next eligible PR
  • oldest eligible PR
  • no unsafe mutation
  • worktree clean
  • linked issue verified
  • PR still mergeable
  • head unchanged
  • final page
  • no next page

If the proof comes from prior review feedback rather than a command/tool run in the current session, label it as prior proof, not live proof.

If relying on prior review feedback at unchanged head SHA, say:

Prior blocker reused; head SHA unchanged since blocking review.

Do not say:

Live blocker proof

unless the blocker was actually revalidated in the current session.

If a tool call was rejected, confirmation-gated, dry-run-only, or no-op, report it separately from performed mutations.

A dry run is not a mutation.

A confirmation-gated rejected call is not a performed mutation.

A successful merge call is a merge mutation.

A successful review submission is a review mutation.

A final-decision marking call is a review mutation if it records durable review state or consumes review-mutation budget.

35. Duplicate request-changes prevention

Before submitting REQUEST_CHANGES, fetch current review feedback.

If an unresolved REQUEST_CHANGES review already exists at the same head SHA with the same blocker, do not submit another REQUEST_CHANGES.

Report:

  • prior blocking reviewer
  • prior blocking timestamp
  • prior blocking head SHA
  • current head SHA
  • blocker text
  • why the blocker still applies
  • that no duplicate review mutation was submitted

If the head SHA changed or the old blocker is not equivalent, evaluate normally.

Do not consume the sessions review mutation budget just to duplicate an existing blocker.

36. Final self-check before output

Before final output, check the report for contradictions.

Verify:

  • if any file was edited, File edits by reviewer is not none
  • if any worktree was added/removed, Worktree/index mutations lists it
  • if any fetch happened, Git ref mutations lists it
  • if any review was submitted, Review mutations lists it
  • if any merge was performed, Merge mutations lists it
  • if any cleanup happened, Cleanup mutations lists it
  • if any issue/PR external state changed, External-state mutations lists it
  • if pagination is claimed complete, final-page proof is present
  • if live proof is claimed, the proof ran in the current session
  • if same-as-master is claimed, baseline proof is complete
  • if issue closed is claimed, linked issue was fetched after merge
  • if merged is claimed, merge result and target ancestry proof are present
  • if selected PR is claimed next eligible, every earlier PR has proof-backed skip reasoning
  • if a terminal mutation happened, no other PR was reviewed or mutated afterward

If any contradiction exists, fix the final report before output.

37. Controller handoff schema

End every run with a controller handoff using this schema.

Do not omit fields. Use none or not verified in this session where appropriate.

Controller Handoff:

  • Task:
  • Repo:
  • Role:
  • Identity:
  • Active profile:
  • Runtime context:
  • Selected PR:
  • Linked issue:
  • Eligibility class:
  • Queue ordering policy:
  • Inventory pagination proof:
  • Earlier PRs skipped:
  • Candidate head SHA:
  • Reviewed head SHA:
  • Target branch:
  • Target branch SHA:
  • Already-landed gate:
  • Author-safety result:
  • Prior request-changes state:
  • Review worktree used:
  • Review worktree path:
  • Review worktree inside branches:
  • Review worktree HEAD state:
  • Review worktree dirty before validation:
  • Review worktree dirty after validation:
  • Baseline worktree used:
  • Baseline worktree path:
  • Files reviewed:
  • Validation:
  • Validation failure history:
  • Validation cwd/HEAD proof:
  • Official validation integrity status:
  • Terminal review mutation:
  • Review decision:
  • Merge preflight:
  • Merge result:
  • Linked issue status:
  • Main checkout branch:
  • Main checkout dirty state:
  • Main checkout updated:
  • File edits by reviewer:
  • Worktree/index mutations:
  • Git ref mutations:
  • MCP/Gitea mutations:
  • Review mutations:
  • Merge mutations:
  • Cleanup mutations:
  • External-state mutations:
  • Read-only diagnostics:
  • Blockers:
  • Current status:
  • Safe next action:
  • Safety statement:

38. Stop conditions summary

Stop immediately and produce a recovery handoff if:

  • canonical workflow is required but cannot be loaded
  • identity/profile/capability cannot be proven
  • authenticated identity is the PR author
  • runtime context is blocked
  • infra stop appears
  • MCP reconnect fails
  • capability state is stale
  • inventory pagination cannot be proven
  • queue ordering cannot be proven
  • earlier PR blocker status cannot be verified
  • selected PR is already landed
  • target branch cannot be fetched
  • linked issue cannot be verified when required for decision
  • review worktree is dirty
  • validation cannot run
  • validation fails and request-changes cannot be safely submitted
  • baseline comparison is required but incomplete
  • prior request-changes override proof is missing
  • PR head changes before review or merge
  • merge preflight fails
  • terminal review mutation occurs on a different PR
  • any report contradiction cannot be resolved

Blocked handoffs must not include direct approve or merge replay commands.

Blocked handoffs must say to rerun the full workflow after the blocker clears.

Do not improvise around the gates.