Files
HealthLog/.github/workflows/coach-eval.yml
T

70 lines
2.8 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) 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.
#
# 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@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
- 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)
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)."