each row is a normalized event joined to the run it triggered:
- run present ⇒ verdict chip (blocked/passed/sent to review) + leading fail
reason, row links to /runs/$runId
- in flight ⇒ 'evaluating…' that resolves in place when the run completes
- no run ⇒ dimmed row with the reason (push/comment/installation/exempt)
- eventServices.listActivity joins events→runs + first failing rule one-liner
- live: worker NOTIFYs a 'runs' channel on process-event completion + resume;
api SSE forwards a 'run' event; web resolves the row in cache (no polling,
no second row)
- client-side filter chips: all/blocked/sent to review/passed/no run
- route + nav renamed; listActivity integration-tested
checks green: biome, typecheck, boundaries, 196 tests.