Files
HealthLog/.github/workflows/coach-eval.yml
T
Marc-André Bombeck c2ab9cda11 test(coach): put the dialog scenarios to a real model nightly
The live evaluation now captures the tool calls a generation makes, with
their arguments, and hands them to the judge. runScenarioLive puts a
scenario to the model in the chat turn's own context (system prompt,
tool-mode and dialog addenda, DATA INVENTORY, EARLIER TABLES, transcript)
over the real tool catalogue, answers each call with a stand-in result,
and reads the reply through the turn's clarification and chip parsers.
runScenarioJudge grades each scenario a few times with the same
evaluateScenario the deterministic suite uses and reports a pass rate per
scenario; the server-only scenarios and checks are left out.

Like the existing judge it runs only with COACH_EVAL_API_KEY, from the
nightly workflow's non-blocking step, and never throws.
2026-09-27 13:07:25 +02:00

72 lines
2.9 KiB
YAML

name: Coach eval
# B0 (v1.21.3) — the Coach evaluation harness, two layers.
#
# 1. The DETERMINISTIC suite (golden set + red-team battery + the grounding
# grader + the dialog scenarios) runs ALWAYS. It is free, offline, and the per-change floor — the
# same suite `pnpm test` runs, pinned here as a standing nightly check.
# 2. The LIVE JUDGE step runs ONLY when the `COACH_EVAL_API_KEY` repository
# secret is present, and is NON-BLOCKING (`continue-on-error: true`). With
# the secret absent it no-ops with a clear log line — the workflow stays
# green. The operator flips the secret on later; no rebuild needed. The
# same step puts the dialog scenarios to the model and logs a pass rate
# per scenario, with the tool calls and their arguments.
#
# Schedule + manual only. This is NOT a required check.
on:
schedule:
# Nightly at 04:20 UTC — off the busy hour, after any evening merges.
- cron: "20 4 * * *"
workflow_dispatch:
permissions:
contents: read
jobs:
coach-eval:
name: Coach eval — deterministic floor (always) + live judge (opt-in)
runs-on: ubuntu-latest
timeout-minutes: 15
# Map the opt-in secret to a job-level env so the live-judge steps can gate
# on it. The `secrets` context is NOT available in `if:` expressions — using
# it there is a workflow-file validation error that surfaces as a 0-second
# startup failure on every push. `env` is allowed in `if:`, so gate on that.
env:
COACH_EVAL_API_KEY: ${{ secrets.COACH_EVAL_API_KEY }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm db:generate
# Layer 1 — the deterministic floor. Free, offline, ALWAYS runs. A
# failure here reds the workflow: a regression in the golden set or the
# red-team battery is a real find.
- name: Deterministic floor (golden set + red team + dialog scenarios)
run: pnpm exec vitest run src/lib/ai/coach/eval/__tests__/
# Layer 2 — the live judge. Runs ONLY when the secret is present, and is
# non-blocking either way. With the secret absent the script no-ops with a
# clear line and exits 0.
- name: Live judge (opt-in, non-blocking)
if: ${{ env.COACH_EVAL_API_KEY != '' }}
continue-on-error: true
run: pnpm dlx tsx scripts/run-coach-eval.ts
# When the secret is absent, surface a clear no-op line so the run log
# explains why the live judge did not execute.
- name: Live judge skipped (no secret)
if: ${{ env.COACH_EVAL_API_KEY == '' }}
run: echo "COACH_EVAL_API_KEY not set — live Coach judge skipped (deterministic floor still gated above)."