From 4b2b59b184ec837eda31e5c54eb2459e7a119784 Mon Sep 17 00:00:00 2001 From: m3taversal Date: Thu, 7 May 2026 18:31:07 -0400 Subject: [PATCH] fix(reaper): branch allowlist for disposable pipeline-managed branches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- lib/substantive_fixer.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/substantive_fixer.py b/lib/substantive_fixer.py index ebdf6a3..4772944 100644 --- a/lib/substantive_fixer.py +++ b/lib/substantive_fixer.py @@ -645,6 +645,10 @@ async def verdict_deadlock_reaper_cycle(conn) -> int: return 0 # 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( """SELECT number, branch, eval_issues, leo_verdict, domain_verdict, last_attempt, fix_attempts @@ -653,6 +657,7 @@ async def verdict_deadlock_reaper_cycle(conn) -> int: AND tier0_pass = 1 AND last_attempt IS NOT NULL AND last_attempt < datetime('now', ? || ' hours') + AND (branch LIKE 'extract/%' OR branch LIKE 'reweave/%' OR branch LIKE 'fix/%') AND ( (leo_verdict = 'request_changes' AND domain_verdict = 'approve') OR (leo_verdict = 'skipped' AND domain_verdict = 'request_changes')