Skip to content

[feat] Show scorer results in the dashboard #1182

Closed

Description

@SaulMoro

Parent: #1137

Goal

Labels on teamai-reports are only worth their cost if someone reads them. Add a scorer view to the existing teamai dashboard that answers two questions: is a scorer's pass rate moving, and does it differ by tool, model, team revision or definition.

What it shows

  • One measurement at a time. Before any grouping, the view fixes the scorer, the rubric version (rubric.sourceHash, with teamRevision shown when there is one), the source (workflow or session), the run mode (runMode, [feat] Run mode: tell attended runs from unattended ones #1384) and the judge (judge.kind, and for a model judge its recorded tool and model). Labels that differ in any of these are never summed: a changed rubric, another kind of subject, another run mode or another judge is a different measurement. The view opens on the newest rubric whose labels carry rubric.teamRevision, so a member's uncommitted draft does not become the team's view. When no label of the scorer has one, it opens on the rubric with the latest scoredAt. Labels without judge data form their own judge not recorded cohort.
  • Pass rate over a window, 30 days by default, as a headline and as a weekly trend. The window is about when labels were scored, not when the work happened, and the view says so. A week with no labels is a gap, not 0%. The headline shows n, passed and failed next to the rate.
  • Group by one recorded configuration dimension: tool, model, team revision, definition, the role, project or tag selection the assets were delivered for (team.selection, [feat] Score a finished session on demand #1178), or fingerprint ([feat] Record the agent each workflow step ran as #1176). Session labels can also be grouped by a team skill the session loaded (used.skills, [feat] Score a finished session on demand #1178), with a label counted under each skill it lists. Model groups keep whether the model was reported or only requested. Labels without that part form a not recorded group, never a guessed one.
  • Before and after a team commit. Given a commit of the team repo, the view splits the labels in two: those whose agent.team.revision contains it, checked with git merge-base --is-ancestor in this machine's team clone, and those that do not. A label without team, or whose revision this clone does not have, is not recorded. It combines with grouping by skill, so a team sees the sessions that loaded a skill before and after the commit that changed it.
  • Failing labels. Under a cohort, the view lists its failing labels: author, scoredAt, platform and used.skills, newest first. When the team repo holds a pushed session whose origin is the label's subject, the row shows that session's name, so a teammate can open it with teamai session resume or score it with teamai score --team-session. It shows no native session id, prompt or reasoning.
  • Pass/fail as stored. passed is read from the label, never recomputed against the scorer's current passingScore.
  • A line under the view: Labels from sessions and workflow runs show how the tools did on the work that came along. To compare tools, models or team assets on the same tasks, run a benchmark.

Data

Scope

  • Read API and page in the existing dashboard structure, next to the Workflow Runs page ([feat] Add a Workflow Runs page to the dashboard #1088) if it has merged.
  • English and Chinese strings.
  • docs/guide/dashboard.md and docs/guide/zh-CN/dashboard.md: a section on the scorer view and what it can and cannot show.

Acceptance criteria

  1. With fixture labels from two versions of a scorer, the view opens on the newest one whose labels carry rubric.teamRevision, with its own n, and the other shows only its labels. A version whose labels carry no teamRevision does not open by default while another does.
  2. Workflow and session labels of the same scorer are never in the same count. Neither are labels from two judge models with the same rubric.
  3. Grouping by model puts labels with no model under not recorded, and keeps reported and requested-only models apart.
  4. A workflow label is grouped by the agent of the pass it judges. A label on a pre-[feat] Record the agent each workflow step ran as #1176 record has only the definition.
  5. A label scored in January and rescored in February counts once, in February.
  6. Raising passingScore in the scorer file does not change any past pass rate.
  7. A week without labels shows a gap in the trend.
  8. No API response contains a key or value from a judge's reasoning file or a session transcript (test with fixture text).
  9. Grouping by role puts labels from members with different primaryRole on the same team revision in different groups. Grouping by skill counts a label whose used.skills names two skills under both.
  10. A fixture benchmark run with diff-quality labels leaves the view's n for diff-quality unchanged.
  11. With labels on revisions A, B (child of A) and C (child of B), splitting at B puts A before and B and C after. A label with no team is not recorded.
  12. A failing label whose subject is a pushed session is listed with that session's name and no native session id.

Test plan

  • Unit tests for the aggregation: dedup before the window, cohorts, the join to passes, grouping, gaps.
  • API tests for criterion 8.
  • One real run of teamai dashboard against a fixture reports branch, with a screenshot in the PR.

Out of scope

Benchmark comparisons in the dashboard, per-asset health (#408), judge reasoning in the browser, and alerts.

Dependencies

Update: run modes and session labels

The original scope already covers session labels. This update adds the runMode split (#1384) and a reminder table. Run mode is fixed like source and judge: labels of different modes are never summed, and labels without runMode form their own not recorded cohort.

scorer           runMode       source    labels   passed
review-quality   attended      session   14       71%
review-quality   unattended    workflow  52       88%
review-quality   not recorded  session    9       67%

A member's own dashboard also compares the sessions the friction reminder fired on with those it did not, so the threshold can be tuned with data. "Reminder fired" is hinted in the member's local per-session contribute state (getSessionPath, src/contribute-check.ts:120-128), the learning offer. That state is only on the member's machine, so this table covers only sessions run on that machine, says so, and is not part of the team view.

Column What it counts
sessions this machine's dashboard session_start events without launchedBy (#1384), in the window
labelled those sessions with a label of this cohort, from the local label store and teamai-reports, deduplicated by #1178's key
passed labelled sessions whose label passed; the rate is over labelled sessions only

It compares within one scorer, rubric, source, judge and run mode. A session with no reminder state is not recorded; no reminder state is inferred from a label.

review-quality · rubric 3a9e1c · session · claude / <recorded-model> · attended · sessions run on this machine
reminder fired   sessions   labelled   passed
yes              18         11         64%
no               96         40         85%
not recorded     12          3         —

The state file is swept 24 hours after its session's last write (cleanupStaleSessions, STALE_SESSION_MS, src/contribute-check.ts:183-208), which is shorter than the 30 days window. So the reminder decision must outlive it: when cleanup sweeps a state file, it keeps a record of only hinted, true or false, for every swept file (and the facts #1388 adds to it), removed after 30 days. #1388 needs the same record for its once-per-session offers; whichever of the two issues lands first adds it, and the other reuses it. The table stays local to this machine.

Added criteria:

  1. Labels of the same scorer with different runMode are never in the same count; labels without runMode are counted under not recorded.
  2. The reminder table reads only this machine's contribute state, and a label whose session has no state there is not recorded.
  3. A session whose reminder fired 10 days ago, whose state file was swept since, still counts under yes in a 30 days window.
  4. A session whose reminder did not fire, whose state file was swept 10 days ago, still counts under no in a 30 days window.

Activity

  1. SaulMoro commented on Oct 20, 2026

    @SaulMoro
    CollaboratorAuthor

    Benchmark trials are scored through #1085 at sampling 100 (#1180), so their labels land in run records as workflow labels, and nothing keeps them out of this view. Arms deliberately use other models and other asset sets (#1181), so they would distort each scorer's trend and groupings. Leave out labels from a run whose end record has benchmark. #1180 adds that field; if it lands later, it adds this exclusion. Criterion: a fixture benchmark run with diff-quality labels leaves the view's n for diff-quality unchanged.

    #1249 reads this view's aggregation through teamai digest --json, so the aggregation lives where both can use it.

  2. SaulMoro commented on Oct 23, 2026

    @SaulMoro
    CollaboratorAuthor

    Notes from building #1085 (#1297) and #1178 (#1298), for the data this view reads:

    • Workflow labels are not in run records. Both kinds of label live in one store on teamai-reports, scores/<member>/<YYYY-MM>.jsonl, told apart by source. A workflow label names its pass in subject: {runId, step, pass}, so the join to that pass's agent goes through the run record, but the label itself is read from scores/.

    • The judge is recorded the way a pass records its agent:

      "judge": {"kind": "model", "tool": "claude",
                "model": {"requested": "haiku", "reported": "claude-haiku-5-5", "alias": "fast"},
                "isolation": "verified", "access": "read"}

      So a judge cohort can keep reported and requested-only models apart, like criterion 3 asks for the agent, and show the team alias the scorer asked for.

    • used.skills is stable across rescoring. It is checked against what the session-start capture recorded as delivered, so a member's own skill with a team skill's name is not listed, and a pull that later removes a skill does not change a rescore.

    • Workflow labels carry no used.skills yet. A pass does not record the skills its launch loaded; that needs a field on the stored pass, one in the driver report and one on the label. Until then, grouping by skill applies to session labels only.

    • teamai score --team-session does not exist. [feat] Score a finished session on demand #1178 scores sessions on this machine only. For the failing-labels list, teamai session resume <name> works today; scoring a pushed session needs its own change (it can read the archive through SyncManager.loadSession and feed the same session scorer).

    • Linking a label to a pushed session: an archived session keeps origin (src/session-flow/sync.ts), which holds the source platform and session id the label's subject names.

  3. SaulMoro commented on Oct 25, 2026

    @SaulMoro
    CollaboratorAuthor

    Added a section at the end of the body: this issue now also shows session labels, which are published today but never read, and splits every view by run mode (#1384). It also asks for a friction-reminder vs label view to tune the reminder threshold. Now blocked by #1384. Part of #1383.

  4. SaulMoro commented on Oct 25, 2026

    @SaulMoro
    CollaboratorAuthor

    Rewrote the appended section. Labels are grouped by runMode (#1384), and records without it form a not recorded cohort.
    The friction-reminder comparison is now local to the member's dashboard, because reminder state is only in ~/.teamai/sessions/<id>.json on that machine (src/contribute-check.ts:120-128). It also shows the labelled count, so its pass rate covers labelled sessions only.
    Added two criteria for these. The rest of the body is unchanged.

  5. SaulMoro commented on Oct 25, 2026

    @SaulMoro
    CollaboratorAuthor
  6. SaulMoro commented on Oct 25, 2026

    @SaulMoro
    CollaboratorAuthor

    The record kept after the 24 hours cleanup now holds hinted for every swept session, false included. Without that, the reminder table's no row would lose every older session.
    Added criterion 16 for that case.

  7. added a commit that references this issue on Oct 27, 2026
    3d253e4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions