Visual capture runs in-pass (src/queue/processors.ts ~11324-11400). On failure it yields beforeAfter=[] and never calls markPullRequestVisualCaptureSatisfied (~11374-11385). The same webhook's maintenance pass then reads botCaptureSatisfied as false (~3103-3123) and, with action: "close", issues a one-shot close.
There is no grace pass and no distinction between "capture concluded: this PR has no visual routes" and "the capture pipeline errored" (browserless down, timeout, transient network). A contributor's correct visual PR is closed because an internal service blipped — and under one-shot rules their recovery is to open a whole new PR.
Given missing before/after screenshot table was the single most common close reason in the 2026-07-26 ledger, any false-positive rate here is expensive.
Fix
On capture error (as opposed to a genuine no-visual-routes result) hold instead of close, or defer the gate one pass with a persisted attempt marker. Only close when the capture pipeline actually succeeded and found the table missing.
Visual capture runs in-pass (
src/queue/processors.ts~11324-11400). On failure it yieldsbeforeAfter=[]and never callsmarkPullRequestVisualCaptureSatisfied(~11374-11385). The same webhook's maintenance pass then readsbotCaptureSatisfiedas false (~3103-3123) and, withaction: "close", issues a one-shot close.There is no grace pass and no distinction between "capture concluded: this PR has no visual routes" and "the capture pipeline errored" (browserless down, timeout, transient network). A contributor's correct visual PR is closed because an internal service blipped — and under one-shot rules their recovery is to open a whole new PR.
Given
missing before/after screenshot tablewas the single most common close reason in the 2026-07-26 ledger, any false-positive rate here is expensive.Fix
On capture error (as opposed to a genuine no-visual-routes result) hold instead of close, or defer the gate one pass with a persisted attempt marker. Only close when the capture pipeline actually succeeded and found the table missing.