Files
Gitea-Tools/skills/llm-project-workflow/schemas/review-merge-final-report.md
sysadminandClaude Opus 4.8 ed0e8c82de fix(workflow): retire status:pr-open on every terminal PR transition (Closes #780)
status:pr-open was applied by gitea_create_pr and never removed again. Every
terminal path finished without touching it, so a repository audit found 40
closed issues still advertising an open PR.

Add terminal_pr_label_cleanup.py as the single authoritative rule and route
every sanctioned terminal path through it, so the paths cannot drift:

- merge (gitea_merge_pr)
- close without merge (gitea_edit_pr)
- supersession/abandonment (gitea_reconcile_superseded_by_merged_pr)
- already-landed reconciliation (gitea_reconcile_already_landed_pr)
- controller closure (gitea_close_issue)
- retry/recovery (new gitea_cleanup_terminal_pr_labels)

The rule removes only status:pr-open, preserves every other label, allows an
empty resulting set, is a no-op when the label is absent (so retries are
safe), and confirms the outcome by read-after-write rather than assumption.

Controller closure runs the cleanup before the state change and fails closed
if it cannot be completed and verified; closing first would bake in the stale
label with no later step to catch it. Post-merge cleanup never blocks the
merge, which already happened, and reports failures with a safe next action.

Also:
- gitea_assess_terminal_label_hygiene: read-only terminal validation that
  reports residual status:pr-open, exempting issues with a genuinely open PR.
- _put_issue_label_names now accepts Gitea's empty response body when the
  requested set is empty, so clearing the last label works.
- test_audit's close_issue fixture keys on the request instead of call order,
  since closing now also reads labels for the cleanup and its read-back.

Docs: label-taxonomy terminal-transition section, runbook pointer, and the
review-merge / reconcile-landed final-report terminal-label requirements.

Suite: 4045 passed, 11 failed, 6 skipped. The same 11 failures reproduce on
clean master df31674 (4010 passed, 11 failed) and are pre-existing.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-21 15:41:24 -04:00

139 lines
4.9 KiB
Markdown

# Review-merge controller handoff schema
**Task mode:** `review-merge-pr`
End every review/merge run with a section titled exactly `Controller Handoff`.
Use this canonical field set. Do not omit fields — use `none` or
`not verified in this session` where appropriate.
Do not use legacy fields: `Pinned reviewed head`, `Scratch worktree used`,
`Workspace mutations`, `Mutations: None` (when mutations occurred).
```md
## 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:
- 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:
- Workflow-load helper result:
```
The **Workflow-load helper result** field must carry structured output from
`gitea_load_review_workflow` (workflow_hash, final_report_schema_hash,
boundary_status). Narrative claims that workflow files were viewed locally are
not sufficient (#403).
### Already-landed handoff overrides
When eligibility class is `ALREADY_LANDED_RECONCILE_REQUIRED`:
- Reviewed head SHA: `none`
- Review worktree used: `false`
- Review worktree path: `none`
- Review decision: `none`
- Merge result: `none`
Identity format: `username / profile` (not personal email unless required — #305).
### Queue-status-only runs (no selected PR)
When the run inventories the queue but selects no PR for review:
- Selected PR: `none`
- Already-landed gate, Author-safety result, Merge preflight: `not applicable` or `not run` — never `passed`
- Review worktree detail fields: `not applicable` or `none` when Review worktree used is `false`
- Blockers must not be `none` if the narrative says all open PRs are conflicted, blocked, or unverified
- Inventory pagination proof must cite final-page metadata, not default page-size assumptions
Verifier: `review_proofs.assess_queue_status_report()`.
Narrative final report and controller handoff must agree on eligibility class,
candidate/reviewed head SHA, mutation state, worktree usage, review decision,
terminal review mutation, merge result, and linked issue status.
### Terminal label state (#780)
A run that takes a PR to a terminal state — merged, closed without merge,
superseded, or reconciled as already landed — must report what happened to the
linked issue's `status:pr-open` label, quoting the `pr_open_label_cleanup`
record the terminal tool returned:
- Terminal label cleanup: `clean` / `failed` / `not applicable (no linked issue)`
- Labels removed and preserved per issue, with the read-after-write read-back
Never claim the transition is complete while that record is not `clean`. A
failed cleanup does not undo the merge; the safe next action is
`gitea_cleanup_terminal_pr_labels` with `terminal_reason='retry_recovery'`,
confirmed by `gitea_assess_terminal_label_hygiene`.
### Proof-backed claims (#395)
Proof-sensitive claims must cite explicit command/tool evidence in the report
or structured MCP metadata — not narrative alone:
- **Inventory complete:** `has_more=false`, `is_final_page=true`,
`inventory_complete=true`, and/or `total_count` from `gitea_list_prs`.
- **Skipped earlier PRs:** merge-simulation command output, conflict file list,
or live `gitea_get_pr_review_feedback` / mergeability fields.
- **Baseline validation:** baseline worktree path, baseline target SHA,
dirty-before/after, exact command, exact result.
- **Master integration:** exact `git merge` / `git rebase` command and exit status.
- **Cleanup:** final `git worktree list` (or remove commands) proving session
worktrees were removed.
When a claim relies on prior-session blocker state or MCP metadata only, label
the proof source explicitly (`command`, `MCP metadata`, `prior blocker`,
`not checked`). Do not use `live proof` without that classification.
The report must also carry the canonical self-propagating handoff block
(`schemas/self-propagating-handoff.md`, #626) and that block must be posted to
the Gitea PR thread. A reviewer hands off to `merger`; a merger transitions to
`merged-awaiting-controller` rather than declaring the work accepted.