feat: PR filter — compare models on the same set of PRs
Build & push image / build-and-push (push) Successful in 13s
CI / test (push) Successful in 9m51s

UI: a repo#pr multi-select (labeled with how many models ran each PR)
scopes the whole table — runs, minutes, findings, points — to the chosen
PRs, so a model with 2 runs can be fairly compared against one with 60.
API: GET /scoreboard accepts ?repo= and ?pr= (repeatable or comma-list).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 22:55:43 -04:00
parent 2f003dd132
commit 1af115fdf1
6 changed files with 202 additions and 19 deletions
+22 -3
View File
@@ -5,6 +5,7 @@ import (
"errors"
"log"
"net/http"
"strconv"
"strings"
)
@@ -21,7 +22,9 @@ import (
// GET /healthz liveness (public)
// GET /runs list all runs (timing/tokens), oldest first
// GET /export flat report×finding×grade rows (the dashboard feed)
// GET /scoreboard points-free per-model rollup
// GET /scoreboard points-free per-model rollup; ?repo= and ?pr= (repeatable
// or comma-list) narrow it to specific PRs so models are
// compared on the same work
// POST /runs upsert one run (model review of a PR; timing/tokens)
// POST /reports record a batch of findings + this model's reports
// POST /findings/{id}/grade record a triage grade (is_real, severity, …)
@@ -79,8 +82,24 @@ func newServer(store *Store, token string) http.Handler {
writeJSON(w, http.StatusOK, rows)
})
mux.HandleFunc("GET /scoreboard", func(w http.ResponseWriter, _ *http.Request) {
stats, err := store.Scoreboard()
mux.HandleFunc("GET /scoreboard", func(w http.ResponseWriter, r *http.Request) {
f := ScoreboardFilter{Repo: r.URL.Query().Get("repo")}
// pr is repeatable and accepts comma lists: ?pr=1&pr=2 or ?pr=1,2
for _, v := range r.URL.Query()["pr"] {
for part := range strings.SplitSeq(v, ",") {
part = strings.TrimSpace(part)
if part == "" {
continue
}
n, err := strconv.Atoi(part)
if err != nil {
writeErr(w, http.StatusBadRequest, errors.New("invalid pr number: "+part))
return
}
f.PRs = append(f.PRs, n)
}
}
stats, err := store.Scoreboard(f)
if err != nil {
writeErr(w, http.StatusInternalServerError, err)
return