fix(reaper): branch allowlist for disposable pipeline-managed branches
Some checks are pending
CI / lint-and-test (push) Waiting to run

Apply Ganymede review nit #3 from f97dd15 review (the deferred close_on_forgejo
fix already landed in e14b5f2 — Ganymede was reviewing the older commit).

SQL gate previously had no branch filter — empirically all 92 candidates were
extract/* but structurally any agent branch in the deadlock shape was a
candidate. Positive allowlist for extract/, reweave/, fix/ scopes the reaper
to disposable pipeline-managed branches that the pipeline created and can
recreate. Agent branches (theseus/, vida/, epimetheus/, etc.) are WIP feature
work and must not be reaped — owners review their own PRs on their own cadence.

Cheap target-class lock complementing the LIMIT 50 blast-radius cap.
Same scoping principle as PIPELINE_OWNED_PREFIXES, but tighter — epimetheus/
review branches are pipeline-owned for merge purposes but NOT disposable.

Items 2-4 from this review:
- WARNING #2 (audit_log idx_audit_event_ts): defer to followup branch alongside
  sync-mirror migration cleanup, as Ganymede suggested.
- NIT #3 (this commit): branch allowlist applied.
- NIT #4 (token asymmetry comment=admin/close=leo): confirmed established
  codebase pattern. merge.py:946-948 does the same — comment system-toned,
  close attributed to Leo for verdict-source UI clarity. Not accidental.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
m3taversal 2026-05-07 18:31:07 -04:00
parent ba234ec4b3
commit 4b2b59b184

View file

@ -645,6 +645,10 @@ async def verdict_deadlock_reaper_cycle(conn) -> int:
return 0 return 0
# Two stuck-verdict shapes: leo:rc+domain:approve, leo:skipped+domain:rc. # Two stuck-verdict shapes: leo:rc+domain:approve, leo:skipped+domain:rc.
# Branch allowlist scopes the reaper to disposable pipeline-managed branches.
# extract/, reweave/, fix/ are content the pipeline created and can recreate;
# agent branches (theseus/, vida/, epimetheus/, etc.) are WIP feature work
# and must not be reaped — owners review their own PRs on their own cadence.
rows = conn.execute( rows = conn.execute(
"""SELECT number, branch, eval_issues, leo_verdict, domain_verdict, """SELECT number, branch, eval_issues, leo_verdict, domain_verdict,
last_attempt, fix_attempts last_attempt, fix_attempts
@ -653,6 +657,7 @@ async def verdict_deadlock_reaper_cycle(conn) -> int:
AND tier0_pass = 1 AND tier0_pass = 1
AND last_attempt IS NOT NULL AND last_attempt IS NOT NULL
AND last_attempt < datetime('now', ? || ' hours') AND last_attempt < datetime('now', ? || ' hours')
AND (branch LIKE 'extract/%' OR branch LIKE 'reweave/%' OR branch LIKE 'fix/%')
AND ( AND (
(leo_verdict = 'request_changes' AND domain_verdict = 'approve') (leo_verdict = 'request_changes' AND domain_verdict = 'approve')
OR (leo_verdict = 'skipped' AND domain_verdict = 'request_changes') OR (leo_verdict = 'skipped' AND domain_verdict = 'request_changes')