Converge eval rubric schema with Magister's eval runner (3-layer rubrics, brand fixtures, config-as-candidate)
Why
Elliot built a marketing eval runner inside Magister (magister-marketing PR #890, branch codex/model-marketing-evals) — evals/ with candidates, brand fixtures, per-family rubrics, a runner engine, deterministic + blinded grading, and evidence capture. It's the same primitive as our open evals/ framework (#479). His README explicitly documents "the boundary for extracting the generic runner into a future standalone or open-source package."
These are the two halves of one thing: his is the proprietary, prod-integrated engine (real brand fixtures, canary safety, model routing); ours is the open, credibility layer (public rubrics + published human-agreement numbers). They should share a rubric/judge schema so a judge authored in one runs in the other. This issue tracks converging the two.
Already incorporated (done, not this issue)
Quick wins from Elliot's runner already merged into our framework (feature/eval-framework-phase0):
- Judge pinned to
temperature: 0(deterministic grading; kills the sampling-noise phantom swings from Magister #819, where a near-identical answer scored 71 then 49). - Injection defense — graded items framed as untrusted data, not instructions.
- Evidence capture — each benchmark run writes immutable
benchmark/runs/<id>/run.jsonfor offline inspection/re-grade. - METHODOLOGY "Deterministic judging" section, credited to Magister.
The convergence work (this issue)
1. Three-layer rubric schema (the big one)
Elliot's rubrics separate three concerns; ours are single-layer LLM PASS/FAIL. Adopt his split so a rubric is a superset both runners understand:
hard_gates— absolute fails (all claims grounded in the fixture, no forbidden claims, draft-only). Any gate fail = FAIL regardless.programmatic_checks— deterministic code checks, no LLM:labeled_character_limit(Meta primary text ≤125, headline ≤40),minimum_heading_matches(≥3 angles), etc. Un-gameable, free, noise-free.subjective_dimensions— 1–5 LLM scales (positioning, angle diversity, channel fit, testability), each with an explicit description/anchor.
Needs: a shared JSON schema (schema_version, id, task_family, the three arrays), a deterministic check runner in our harness, and a way to map 3-layer scores → an overall verdict for the calibration loop. Migrate our 8 judges to the new schema.
2. Brand-fixture grounding
Replace/augment our one-line benchmark briefs with synthetic brand fixtures (Elliot's fixtures/brands/<brand>/): product-marketing.md + sources/product-facts.md + constraints.json (authoritative_sources, forbidden_claims, required_disclosure, allowed_side_effects). This is what powers the "grounded claims / no forbidden claims" hard gate — it catches hallucinated marketing claims, which our current benchmark can't see. Add untrusted-notes.md-style fixtures for a prompt-injection resistance eval dimension.
3. Config-as-candidate + reproducibility
Extend our pricing.json registry from {model, price} to Elliot's candidate shape: model + effort + verbosity + max_output_tokens + cost_ceiling_usd_per_attempt + temperature_policy (he pins temperature_policy: "omit" in v1; GPT declares verbosity, Claude uses null). Add experiment-level random_seed + budget caps (max cost / attempts / deadline).
4. Blinding + evidence formalism
He formalizes blinding: the judge gets pairs.jsonl only; candidate identities join after a schema-valid import via a separate pair-map.json. Generation and grading are fully separate — evidence written once, then deterministic checks + blinded reviews + reports rerun offline. Align our benchmark's evidence format so a run is regradable and identity-blinded.
5. Honest-reporting metadata
Stamp rubric_version on every score; mark partial runs / unscored counts; never blend incomparable source sets into one trend (Magister #819's lessons).
Coordination
- Sync with Elliot on the shared rubric schema before either side hardens its format — a divergent schema defeats the purpose. His PR #890 is the reference implementation; our #479 is the open target.
- Decide the extraction boundary: does our open
evals/framework become the generic package his README references, or do both depend on a shared schema/spec repo?
Dependencies
- Our framework is on
feature/eval-framework-phase0(awaiting Corey's labeling pass before merge). The schema migration should land before or with that so we don't re-author judges twice. - Elliot's #890 (open). Coordinate merge order / schema freeze.
Filed from a review of Elliot's Magister eval runner. Companion to #479 (framework) and #480 (model benchmark).
Source: coreyhaines31/marketingskills