doloop on dispatch
The conventions your codebase already holds — and what your AI keeps breaking.
✓ ran locally · your source never left this machine · same result every run
1 · Your codebase's wall — 62 conventions no linter could know
Each: when this codebase calls the first, it calls the second — at the rate shown, far more than code at large (lift). These are your invented pairings, inferred from your own code.
every description_input() → also MarkdownText()
89% of the time · 48× more than the world · 18 sites
every description_input() → also Context()
89% of the time · 46× more than the world · 18 sites
every description_input() → also Modal()
100% of the time · 31× more than the world · 18 sites
every description_input() → also build()
100% of the time · 24× more than the world · 18 sites
every description_input() → also ack()
100% of the time · 22× more than the world · 18 sites
every filter_by() → also first()
94% of the time · 24× more than the world · 17 sites
every filter_by() → also create()
88% of the time · 17× more than the world · 17 sites
every title_input() → also description_input()
100% of the time · 122× more than the world · 14 sites
every title_input() → also MarkdownText()
93% of the time · 50× more than the world · 14 sites
every title_input() → also Context()
93% of the time · 48× more than the world · 14 sites
… and 52 more.
2 · Proof these are real, not noise
We split your functions in half, learned the conventions from one half, and checked the other. A function in code doloop never looked at still follows the rule 84% of the time (29× chance). Real regularities, not overfit.
3 · The spine — where a change ripples widest
Betweenness over your import graph: the load-bearing files a merge should weigh more.
| src/dispatch/database/core.py | bridge 100 · imported by 149 |
| src/dispatch/database/service.py | bridge 96 · imported by 51 |
| src/dispatch/incident/models.py | bridge 84 · imported by 37 |
| src/dispatch/plugins/dispatch_slack/middleware.py | bridge 82 · imported by 6 |
| src/dispatch/case/models.py | bridge 61 · imported by 36 |
| src/dispatch/signal/models.py | bridge 34 · imported by 19 |
4 · What this means for merge confidence
Your AI writes the most average version of any change — it has never seen your codebase's wall. When it rewrites a real function, it drops the codebase convention 37–72% of the time (measured), and that break is invisible to your compiler, linter, type checker, and tests — it's valid code, just not your code.
doloop's gate catches exactly that, deterministically, and triages every change:
| ● GREEN | fits your patterns, leaf file — merge, move fast (most changes) |
| ● YELLOW | a codebase-drift, a load-bearing file, or a shared-state write — glance |
| ● RED | a break in a load-bearing file, or a security sink — read this one |
5 · Run it yourself
doloop conventions dispatch
doloop read --open dispatch
doloop gate --staged # in your pre-commit / CI