Commit d2c8d27
authored
fix(orb): webhook redelivery, reputation cadence, DB retention, and gate severity fidelity (#9237)
* fix(db): index retention columns and add delete paths for four never-pruned caches (#9083)
No RETENTION_POLICY table had a leading index on its retention timestamp, so
pruneExpiredRecords's ctid-keyed batched delete forced a full sequential scan of
the whole table on Postgres per batch -- large tables blew the prune job's
30-minute timeout and retention fell permanently behind (signal_snapshots alone
reached 787MB at ~44KB/row). Rewrite the delete to range over a real,
indexable primary key ordered by the retention column instead of rowid/ctid,
and add the matching leading index for every policy table via migration 0191.
Also close the "no delete path at all" gap for four read-side caches
(grounding_file_content_cache, ai_review_cache, ai_slop_cache,
linked_issue_satisfaction_cache) that only enforced their TTL at the read
site, and add retention for three previously-untracked append-only logs
(review_audit, decision_records, orb_webhook_events).
Deliberately deferred: pull_request_files, check_summaries, gate_outcomes,
agent_runs, and advisories are current-state tables (upserted per natural
key, read as live state for open PRs/checks) rather than append-only logs,
so they are excluded from this pass per RETENTION_POLICY's own documented
scope -- pruning them needs a read-pattern review this PR doesn't do.
* fix(webhook): stop treating stuck queued/superseded deliveries as permanent duplicates (#9054)
The dedup guard in enqueueWebhookByEnv only ever exempted 'error' rows from
suppression. A row left at 'queued' (the insert happened but WEBHOOKS.send()
was lost) or 'superseded' (overwritten by a later coalesced delivery) could
never be redelivered: every GitHub retry and every operator "Redeliver"
click carries the same delivery_id + payload hash, hits the guard, and is
silently discarded as a no-op duplicate forever -- including
check_suite.completed, the maybeReReviewOnCiCompletion auto-merge trigger.
getWebhookEvent now also returns receivedAt, and a 'queued'/'superseded' row
past a 10-minute staleness window is treated the same as an 'error' row:
never suppressed. A migration purges the historical backlog of rows this
bug already stuck permanently (dead by definition once a full day old),
since replaying them is not useful and the code fix means no future
delivery can get stuck this way again.
Deferred: an active cron sweep that proactively re-triggers GitHub's own
redelivery API for still-stuck rows was not implemented -- webhook_events
does not persist the raw payload (by design, to avoid growing the exact
blob-retention problem #9083 addresses), and this fix already ensures any
future stuck delivery is redeliverable well inside GitHub's redelivery
window without needing an active poke.
* fix(governor): consume cadenceFactor to scale rate-limit cadence instead of hard-denying (#9062)
selfReputationThrottle's own doc comment promises a soft cadence throttle
that "a recovering ratio restores it -- never a hard permanent ban", but
the chokepoint ignored cadenceFactor entirely and hard-denied on ANY
throttled verdict. Since submissions are the only source of new decided
outcomes, and governor_reputation_history never decayed, a miner that hit
the throttle band could never submit again to dilute its ratio back down
-- an absorbing, permanent self-ban.
evaluateGovernorChokepoint now consumes a non-floored cadenceFactor by
scaling the per-repo write-rate-limit window instead of denying; the hard
deny is reserved for the extreme "floored" ratio only. The miner-lib
wrapper advances its rate-limit bucket against the SAME scaled policy the
decision was evaluated with, so state stays consistent with the verdict
it recorded.
governor_reputation_history also gains a 14-day half-life decay (applied
at both read and increment time), so even a floored ratio ages back below
the sample-size floor over calendar time with zero new submissions,
delivering the "recovering ratio" contract the module already documented.
* fix(review): make finding severity load-bearing in check-run display, tighten confidence default, resolve near-miss code names (#9085)
Finding severity was purely decorative: a warning-labeled finding
(missing_linked_issue, slop_risk_above_threshold) can be the exact reason
the gate one-shot-closes a PR, while a critical-labeled one
(ai_consensus_defect, under the advisory-only default aiReviewGateMode)
can have no gate effect at all. A contributor reading a plain warning
icon on the finding that is about to close their PR was being actively
misinformed.
formatCheckRunOutput/buildCheckRunAnnotations now accept the real blocker
codes from the SAME advisory's GateCheckEvaluation (when the caller has
one) and use them to correct the displayed severity: an actual blocker
always renders at the most alarming level regardless of its authored
severity, and a non-blocking finding is capped at warning even if authored
critical, so it never cries wolf louder than a genuine one. The parameter
is optional and purely additive -- every existing caller that omits it
keeps today's exact rendering. Wired the one caller with the evaluation
already in scope (processors.ts's check-run publish).
Also:
- An absent AdvisoryFinding.confidence degraded to 1.0 (maximum
certainty) at three gate-side consumption sites, the same "silence is
not certainty" anti-pattern CONFIDENCE_WHEN_UNSTATED already fixed at
the model-parsing layer. These sites read confidence off a finding
object via a path the parser doesn't cover (a producer that omitted
it, or the unvalidated cached-advisory JSON parse), so they now share
the same 0.5 fallback instead of a second, wrong hardcoded default.
- Renamed the near-miss repo_not_registered -> repo_not_cached (mirrors
pr_not_cached/issue_not_cached's naming for the identical "not yet
synced" shape) to stop it being confused with repo_unregistered, one
character away and with the opposite gate consequence (repo_not_cached
holds the gate for a human; repo_unregistered is a non-blocking
advisory warning).
The engine's gate-advisory.ts twin gets the matching confidence-default
and rename fixes to stay in lock-step with the host copy.1 parent 2206537 commit d2c8d27
26 files changed
Lines changed: 999 additions & 124 deletions
File tree
- migrations
- packages
- loopover-engine
- src
- advisory
- governor
- test
- loopover-miner/lib
- src
- db
- github
- queue
- review
- rules
- test/unit
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
42 | 47 | | |
43 | 48 | | |
44 | 49 | | |
| |||
196 | 201 | | |
197 | 202 | | |
198 | 203 | | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
199 | 207 | | |
200 | | - | |
| 208 | + | |
201 | 209 | | |
202 | | - | |
203 | | - | |
204 | | - | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
205 | 213 | | |
206 | 214 | | |
207 | 215 | | |
| |||
634 | 642 | | |
635 | 643 | | |
636 | 644 | | |
637 | | - | |
| 645 | + | |
| 646 | + | |
638 | 647 | | |
639 | 648 | | |
640 | 649 | | |
| |||
678 | 687 | | |
679 | 688 | | |
680 | 689 | | |
681 | | - | |
| 690 | + | |
682 | 691 | | |
683 | 692 | | |
684 | 693 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
38 | | - | |
| 38 | + | |
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
| |||
97 | 97 | | |
98 | 98 | | |
99 | 99 | | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
100 | 107 | | |
101 | 108 | | |
102 | 109 | | |
| |||
110 | 117 | | |
111 | 118 | | |
112 | 119 | | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
113 | 144 | | |
114 | 145 | | |
115 | 146 | | |
| |||
184 | 215 | | |
185 | 216 | | |
186 | 217 | | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
187 | 247 | | |
188 | 248 | | |
189 | 249 | | |
| |||
192 | 252 | | |
193 | 253 | | |
194 | 254 | | |
195 | | - | |
| 255 | + | |
196 | 256 | | |
197 | 257 | | |
198 | 258 | | |
| |||
206 | 266 | | |
207 | 267 | | |
208 | 268 | | |
209 | | - | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
210 | 274 | | |
211 | 275 | | |
212 | 276 | | |
| |||
216 | 280 | | |
217 | 281 | | |
218 | 282 | | |
219 | | - | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
220 | 290 | | |
221 | 291 | | |
222 | 292 | | |
| |||
275 | 345 | | |
276 | 346 | | |
277 | 347 | | |
278 | | - | |
279 | | - | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
280 | 355 | | |
281 | | - | |
282 | | - | |
283 | | - | |
284 | | - | |
285 | | - | |
286 | | - | |
287 | | - | |
288 | | - | |
289 | | - | |
290 | | - | |
291 | | - | |
292 | | - | |
293 | | - | |
294 | | - | |
295 | | - | |
296 | | - | |
297 | | - | |
298 | | - | |
| 356 | + | |
299 | 357 | | |
300 | | - | |
| 358 | + | |
301 | 359 | | |
302 | 360 | | |
303 | 361 | | |
| |||
0 commit comments