Marketing eval framework: expert-calibrated judge library in evals/ (across copy, creative, tool-calling)
Vision
Build an expert-calibrated marketing eval framework — a shared judge harness plus a growing library of judges that grade the quality of what a marketing agent produces and does, across every major marketing task: copywriting, creative, positioning, and tool-calling. Lives as a top-level evals/ framework in this repo, mapped 1:1 onto the skills.
Reverse-engineered from runneth-tools/hook-grader (MIT) — an open-source eval that grades whether an ad hook stops the scroll, calibrated against a world-class creative strategist (Alysha, Runneth/Motion). We can seed the ad-hook judge directly, with credit.
What hook-grader taught us (the transferable primitive)
An eval is just judge + answer key, plus machinery to measure the judge against the key. hook-grader is a clean 6-part instance:
- Judge (
JUDGE.md) — a paste-able rubric (LLM system prompt) returning a structured JSON verdict (verdict,trigger,tactic,reasoning,improvement). - Answer key (
eval-set.json) — 116 examples hand-labeled by a named human expert, with a realistic distribution (73 FAIL / 43 PASS, not 50/50). - Harness (
eval-harness.mjs) — runs the judge over the key, reports agreement % + confusion breakdown (false-pass vs false-fail) + every disagreement. - Grader CLI (
grade.mjs) — grade new inputs at scale, BYO API key. - Lib (
lib.mjs) — provider-agnostic model calls (Anthropic/OpenAI auto-detect), batching, judge-loading. - Methodology (
METHODOLOGY.md) — calibration loop, blind two-judge consensus, what the score means.
Principles to carry over
- An eval = judge + answer key. A judge is only trustworthy insofar as it agrees with human labels.
- Rubric = failure taxonomy. The reliable signal in quality is negative — name the specific ways things fail; it's far easier and more reliable than predicting "great."
- Calibration loop: run judge → find disagreements → sharpen rubric → repeat; publish the agreement number.
- Match the real distribution in the answer key, or the judge learns the wrong prior.
- Err strict for a bad-X detector — optimize precision on the fails ("kill dead-on-arrival, then test the rest"), not "talent scout for great."
- Blind two-judge consensus (one model per lab, source hidden) for high-stakes grading.
- Structured verdict with an improvement suggestion — the eval doubles as a coach.
The three eval types (marketing tasks have different shapes)
- Type A — Artifact quality (hook-grader is this). Grade a produced artifact against an expert-calibrated rubric. One judge + answer key per artifact. Covers most copywriting/creative/positioning outputs.
- Type B — Tool-calling / trajectory. Input = a task + the agent's tool-call trace; judge grades whether it picked the right tool, right args, right sequence, and used the result. Answer key = tasks with known-good trajectories. This is what "tool calling" needs — it is not artifact quality.
- Type C — Skill behavioral. Already exists as each skill's
evals/evals.json(prompt +expected_output+assertions) — grades whether the agent behaves right (checksproduct-marketing.md, applies the framework, defers to the right sibling). The new framework is the quality/trajectory layer these don't cover; it complements, doesn't replace them.
Design note: keep the existing per-skill
evals/evals.json(behavioral) as-is. The new top-levelevals/framework is a distinct layer. The README must make the two-layer distinction explicit so contributors don't conflate them.
Proposed structure
evals/
├── README.md # the framework: eval = judge + answer key; the two layers; how to run & contribute
├── lib.mjs # shared: provider-agnostic model calls, batching, agreement, confusion, consensus mode
├── harness.mjs # generic: run ANY judge over ANY answer key → agreement % + confusion + disagreements
├── grade.mjs # generic CLI: grade new inputs with any named judge (BYO key)
├── judges/
│ ├── ad-hooks/ # Type A — SEEDED from hook-grader (credit Alysha/Runneth, MIT)
│ │ ├── JUDGE.md
│ │ ├── answer-key.json
│ │ └── README.md
│ ├── headlines/ # Type A
│ ├── value-props/ # Type A
│ ├── ctas/ # Type A
│ ├── subject-lines/ # Type A
│ ├── landing-hero/ # Type A
│ └── tool-calling/ # Type B (trajectory) — its own harness variant
└── METHODOLOGY.md # calibration loop, distribution, consensus, error-bias guidanceGeneralize hook-grader's single-topic files into a judge-agnostic harness (harness.mjs judges/<name>), so adding a category = adding a judges/<name>/ folder with JUDGE.md + answer-key.json. lib.mjs stays provider-agnostic (Anthropic + OpenAI, model override via env), and defaults to current models (Opus/Sonnet 4.x) rather than hook-grader's pinned ones.
Judge ↔ skill mapping (starter set)
| Skill | Judge(s) | Type |
|---|---|---|
| ad-creative | ad-hooks (seed), UGC-script, concept | A |
| copywriting | headlines, value-props, CTAs, landing-hero | A |
| emails / cold-email | subject-lines, cold-open, sequence-step | A |
| positioning / product-marketing | one-liner, category-frame | A |
| social | hook (short-form), thread-opener | A |
| ads / analytics / attribution | tool-calling (right tool, args, sequence) | B |
Answer-key & calibration methodology (per judge)
- 40–150 real, anonymized examples, hand-labeled by a credible human (name them, as hook-grader credits Alysha).
- Realistic distribution (most marketing artifacts fail the bar — reflect that).
- Calibration loop until agreement plateaus; publish the number + confusion split.
- Document the intended error bias (strict for bad-X detectors).
- Optional consensus mode for high-stakes categories.
Phased rollout
- Phase 0 — Harness. Generalize
lib.mjs+harness.mjs+grade.mjsto be judge-agnostic. Seedjudges/ad-hooks/from hook-grader (credit). Reproduce the agreement number as the framework's first passing check. Writeevals/README.md+METHODOLOGY.md. - Phase 1 — Copywriting judges. headlines, value-props, CTAs, subject-lines — each with a hand-labeled answer key and a calibration pass.
- Phase 2 — Tool-calling (Type B). Define the trajectory answer-key format + harness variant; one worked judge (e.g. "did the agent choose the right analytics/attribution tool + args").
- Phase 3 — Broaden + contribute. More categories, consensus mode, a
CONTRIBUTING-style guide so a new judge is a well-trodden path. Cross-link from each skill's README.
Strategic framing
This is an agent-native content play (see the pattern in memory): Runneth shipped an open eval as marketing. An open, expert-calibrated marketing eval framework is a category-defining asset for marketing-skills — more defensible than any single eval and the natural companion to the skills. MIT-friendly to seed (ad-hooks judge) with credit.
Open questions / decisions
- Human labelers: who calibrates each category's answer key? (For the seed, reuse hook-grader's labels with credit; net-new categories need a credible grader — us, or invited experts.)
- Runnable vs paste-only: ship the Node harness (BYO key) and the paste-the-
JUDGE.md-into-any-AI path (hook-grader does both — keep both). - CI: do we wire an agreement-threshold check into CI per judge, or keep it manual/opt-in (cost)?
- Naming:
evals/framework name and whether to also mirror it as a standalone public repo later for the marketing play. - Scoring granularity: PASS/FAIL (hook-grader) vs a 1–5 score per category — decide per judge.
Credit / license
hook-grader is MIT. Seed the ad-hooks judge and reuse its answer-key labels with clear credit to Alysha (@alyshaboehmm) and Runneth, mirroring how we credit other reused OSS (gooseworks, kappaemme). Net-new judges are ours.
Scoped from a reverse-engineering pass on hook-grader. Build not started — this is the plan of record.
Source: coreyhaines31/marketingskills