Add conflict-fix leases and stale-head protection for PR branch pushes #399

Closed
opened 2026-07-07 09:32:29 -05:00 by jcwalker3 · 2 comments
Owner

Problem:
Author conflict-fix sessions can push new commits to PR branches while reviewer sessions are validating or preparing to merge the same PR. This can cause a reviewer to approve one head SHA but merge a later unreviewed head SHA.

Observed risk:
A conflict-fix run pushed updates to multiple PR branches while sibling author/reviewer sessions were active. PR #376 appears especially risky because one session reports a reviewer working with head f595354, while the conflict-fix run reports pushing f595354..78777d4 before reviewer merge. Even if the merge was safe, the workflow needs hard protection against stale-head review/merge races.

Required behavior:
Before an author pushes to a PR branch, it must acquire a conflict-fix lease for that PR. Before a reviewer approves or merges, it must verify the PR head SHA still equals the reviewed SHA after all author pushes.

Acceptance criteria:

  1. Conflict-fix workflow checks for active reviewer lease before pushing to a PR branch.

  2. Reviewer workflow checks for active conflict-fix lease before validating, approving, or merging.

  3. Author push is blocked if a reviewer has an active lease on the PR.

  4. Reviewer approval/merge is blocked if PR head changed after validation.

  5. gitea_mark_final_review_decision, gitea_submit_pr_review, and gitea_merge_pr require final live head SHA equality with the reviewed SHA.

  6. Final report must include:

    • reviewed head SHA,
    • final live head SHA before approval,
    • final live head SHA before merge,
    • whether any push occurred during validation.
  7. Conflict-fix final report must include:

    • branch head before push,
    • branch head after push,
    • active reviewer lease status,
    • whether push was fast-forward,
    • whether any reviewer was active.
  8. Tests cover:

    • author push during active reviewer lease,
    • reviewer validating stale head,
    • PR head changes after approval-ready mark,
    • sibling conflict-fix push collision,
    • non-fast-forward rejection,
    • wrong-cwd push attempt.
  9. Documentation updates conflict-fix and review-merge workflows.

Non-goals:

  • Do not allow author profiles to approve, request changes, or merge.
  • Do not allow force-pushes as a conflict-fix shortcut.
  • Do not permit stale reviewer approval to authorize a newer head.
Problem: Author conflict-fix sessions can push new commits to PR branches while reviewer sessions are validating or preparing to merge the same PR. This can cause a reviewer to approve one head SHA but merge a later unreviewed head SHA. Observed risk: A conflict-fix run pushed updates to multiple PR branches while sibling author/reviewer sessions were active. PR #376 appears especially risky because one session reports a reviewer working with head `f595354`, while the conflict-fix run reports pushing `f595354..78777d4` before reviewer merge. Even if the merge was safe, the workflow needs hard protection against stale-head review/merge races. Required behavior: Before an author pushes to a PR branch, it must acquire a conflict-fix lease for that PR. Before a reviewer approves or merges, it must verify the PR head SHA still equals the reviewed SHA after all author pushes. Acceptance criteria: 1. Conflict-fix workflow checks for active reviewer lease before pushing to a PR branch. 2. Reviewer workflow checks for active conflict-fix lease before validating, approving, or merging. 3. Author push is blocked if a reviewer has an active lease on the PR. 4. Reviewer approval/merge is blocked if PR head changed after validation. 5. `gitea_mark_final_review_decision`, `gitea_submit_pr_review`, and `gitea_merge_pr` require final live head SHA equality with the reviewed SHA. 6. Final report must include: * reviewed head SHA, * final live head SHA before approval, * final live head SHA before merge, * whether any push occurred during validation. 7. Conflict-fix final report must include: * branch head before push, * branch head after push, * active reviewer lease status, * whether push was fast-forward, * whether any reviewer was active. 8. Tests cover: * author push during active reviewer lease, * reviewer validating stale head, * PR head changes after approval-ready mark, * sibling conflict-fix push collision, * non-fast-forward rejection, * wrong-cwd push attempt. 9. Documentation updates conflict-fix and review-merge workflows. Non-goals: * Do not allow author profiles to approve, request changes, or merge. * Do not allow force-pushes as a conflict-fix shortcut. * Do not permit stale reviewer approval to authorize a newer head.
jcwalker3 added the status:in-progress label 2026-07-07 10:42:14 -05:00
Author
Owner

Issue claim heartbeat

<!-- gitea-issue-claim-heartbeat:v1 --> **Issue claim heartbeat** - kind: claim - issue: #399 - branch: feat/issue-399-conflict-fix-leases - phase: claimed - profile: prgs-author - pr: none - blocker: none - next_action: create worktree and begin implementation
Author
Owner

Claiming #399 for implementation (author session, prgs-author / jcwalker3).

Branch: feat/issue-399-conflict-fix-leases

Planned slice (mirrors the assessor + final-report-validator pattern used by sibling PRs #397/#409/#411/#412):

  • conflict_fix_lease.py — lease model (PR number, branch, role, claimant, timestamps), assess_stale_head_gate() requiring reviewed-SHA == final-live-SHA before approve/merge, and assess_conflict_fix_push_gate() blocking author push while a reviewer lease is active.
  • Report verifiers: reviewer report must carry reviewed head SHA + final live head before approval + final live head before merge + push-during-validation flag; conflict-fix report must carry branch-head-before/after push, active-reviewer-lease status, fast-forward proof.
  • Wire into final_report_validator.py; docs in review-merge-pr.md + work-issue.md conflict-fix section; regression tests for the acceptance-criteria scenarios (author push during reviewer lease, reviewer validating stale head, head change after approval-ready, sibling push collision, non-FF rejection, wrong-cwd push).

This is the exact stale-head race audited on PR #376 this session (f595354..78777d4 push vs reviewer merge). Working in branches/issue-399-conflict-fix-leases.

Claiming #399 for implementation (author session, `prgs-author` / `jcwalker3`). **Branch:** `feat/issue-399-conflict-fix-leases` **Planned slice** (mirrors the assessor + final-report-validator pattern used by sibling PRs #397/#409/#411/#412): - `conflict_fix_lease.py` — lease model (PR number, branch, role, claimant, timestamps), `assess_stale_head_gate()` requiring reviewed-SHA == final-live-SHA before approve/merge, and `assess_conflict_fix_push_gate()` blocking author push while a reviewer lease is active. - Report verifiers: reviewer report must carry reviewed head SHA + final live head before approval + final live head before merge + push-during-validation flag; conflict-fix report must carry branch-head-before/after push, active-reviewer-lease status, fast-forward proof. - Wire into `final_report_validator.py`; docs in `review-merge-pr.md` + `work-issue.md` conflict-fix section; regression tests for the acceptance-criteria scenarios (author push during reviewer lease, reviewer validating stale head, head change after approval-ready, sibling push collision, non-FF rejection, wrong-cwd push). This is the exact stale-head race audited on PR #376 this session (`f595354..78777d4` push vs reviewer merge). Working in `branches/issue-399-conflict-fix-leases`.
sysadmin removed the status:in-progress label 2026-07-08 00:34:21 -05:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#399