Flow
Checks the approval labels still need
1Brackets around mixed rules
Any rule that mixes AND with OR gets explicit brackets.
2One row per spelling
A small test table with each verdict and each source spelling, including capitals.
3Expected label per row
Each row must land in the label you meant, and no row in a generic bucket by surprise.
4Count after a rebuild
The summary total should match a raw count of events for the same hours.
Human approvals never showed up in the approval chart. Every plain accept and every plain reject was filed as automatic. The bars were the right height, but the colors were wrong.
The chart is part of a dashboard I'm building to watch coding agents. Each time an agent wants to use a tool, it logs a verdict and a source, either a config rule or a person. A query sorts those into automatic or manual, accept or reject, and that split is the whole point of the chart.
The line that read like English
The query's first rule meant "an accept or an approval, from a rule." But in SQL, AND is grouped before OR, so it really meant this (made-up names):
verdict = 'allow' OR (verdict = 'granted' AND origin = 'rule')
Any plain accept matched, no matter who made it. The query takes the first rule that matches, so the manual rule below never got a turn. Rejects broke the same way. If you write a rule that mixes AND with OR, put the brackets in yourself.
The totals were still right, since every row landed somewhere, and "almost everything is automatic" sounds believable for agents with a loose config. So the chart looked fine to anyone reading it.
Two copies, two different bugs
A second copy of the same sorting lived in an hourly summary table. That copy grouped things right but only knew one exact spelling for a person, and my agents spell it a few ways. So many human choices ended up in a bucket with no source.
The query reads the view now
The repair did three things: the query stopped sorting and now just reads the summary table, so the rules live in one place. The table ignores capitals and treats anything starting with the person word as a person. And the table was rebuilt from scratch, because it stores labels when rows arrive. Editing it alone would not have fixed the old rows.
Still no test for the labels
A rebuild like this can miss rows that arrive while it runs. Time ranges snap to whole hours, and the rarer approval words no longer say who decided. The gap that bugs me most is the missing test. A tiny table with one row for each verdict and each spelling, checked against the label you expect, would have flagged this the first time it ran.