docs: expand #594 stale decision-lock cleanup guidance

Add allowed/forbidden workflow steps to the review-merge skill and
document the #594 cleanup gate on the Safety-and-Gates wiki page.
This commit is contained in:
2026-07-09 15:21:21 -04:00
parent 3f3f880147
commit 86651a3d05
2 changed files with 73 additions and 2 deletions
@@ -826,6 +826,75 @@ The final report must identify:
* whether same-PR merge continuation was allowed
* whether the run stopped as required
## 26A-1. Stale durable review-decision lock cleanup (#594)
After #559, the review-decision lock is durable under
`~/.cache/gitea-tools/session-state/` (for example
`review_decision_lock-prgs-reviewer.json`). That durability can outlive the work
it protects: a terminal `approve` / `request_changes` on a PR that is already
**merged or closed** still hard-stops later unrelated reviews under #332.
**Do not** delete session-state files by hand. Use the canonical MCP path.
### When cleanup is allowed
Use `gitea_cleanup_stale_review_decision_lock` when:
1. `gitea_mark_final_review_decision` / live review is blocked by
`terminal review mutation already consumed ... (#332)`.
2. Live Gitea state for the **last terminal mutation's PR** is **merged** or
**closed** (no same-PR merge sequence remains).
3. Active profile identity matches the durable lock (reviewer profile with
`gitea.pr.review` for `apply=true`).
4. Optional pin: pass `expected_terminal_pr` to the prior terminal PR number
(for example `586` when resuming after a merged #586 lock).
Recommended sequence:
```text
gitea_whoami
gitea_resolve_task_capability(task="cleanup_stale_review_decision_lock")
gitea_cleanup_stale_review_decision_lock(apply=false, remote=..., org=..., repo=...)
# inspect is_moot / cleanup_allowed / last_terminal_pr
gitea_cleanup_stale_review_decision_lock(
apply=true,
expected_terminal_pr=<last_terminal_pr>,
remote=..., org=..., repo=...,
)
gitea_resolve_task_capability(task="review_pr")
gitea_load_review_workflow()
# continue formal mark + submit for the *new* PR
```
Successful `apply=true` clears memory + durable store and returns an audit
record (and posts a durable PR comment on the terminal PR when
`post_audit_comment` is true and comment permission allows).
Same-profile auto-expire: after `gitea_merge_pr` succeeds for the PR that this
profile just approved, the decision lock for that profile is cleared
automatically. Cross-profile locks (for example reviewer approve, merger merge)
still require `gitea_cleanup_stale_review_decision_lock`.
### When cleanup is forbidden
Refuse / fail-closed — keep #332 hard-stop — when:
* the last terminal PR is still **open** (active review or merge sequence may
still apply)
* live PR state cannot be fetched (ambiguous)
* no lock or no terminal live mutation exists
* profile identity does not match the lock
* apply requested without authenticated identity or `gitea.pr.review`
* `expected_terminal_pr` does not match the last terminal PR
Do **not** use cleanup to:
* bypass #332 on an open PR
* replace `gitea_authorize_review_correction` for a mistaken review on a still
active PR (#211)
* auto-approve or auto-merge any PR
* justify `rm` of session-state files
## 26B. Per-PR reviewer lease (#407)
Parallel reviewer sessions are allowed only when each session holds a distinct,