tml-2735: golden-case library + run-one-brief harness#641
Conversation
Scaffold the "Drive — Judge + live-experiment harness" project workspace: two-tier correctness-first scorecard, an LLM judge calibrated against an accreting instrumented-run corpus, and an SDK-spawned k=N A/B harness. Four slices (TML-2720 scorecard+vocabulary, TML-2735 golden-case harness, TML-2736 judge, TML-2737 experiment engine); two foundation slices run in parallel, judge + engine stack on top. Trace.jsonl carries the first natively-instrumented project-started/spec-authored/plan-authored events, emitted via the deterministic emitter merged in PR #633. Signed-off-by: wmadden-electric <286902546+wmadden-electric@users.noreply.github.com>
… spike frameworks Operator steer: keep the implementation minimal. Default to a bespoke LLM-judge + held-out agreement tally; adopt a third-party eval framework (Inspect/Braintrust/promptfoo) only if a time-boxed slice-3 spike shows it reduces net complexity. Run-production harness stays bespoke regardless. Adds spec non-goal + Open Question 6, design-notes alternative, plan slice-3 spike note, and the spike to TML-2736. Trace carries spec-amended/plan-amended. Signed-off-by: wmadden-electric <286902546+wmadden-electric@users.noreply.github.com>
Settle the six project-level open questions into decisions: - one project (judge + harness kept together; the feed->consume loop is the project) - judge model cross-family (hard); default GPT 5.5 vs the Claude orchestrator - per-run token signal from the SDK TurnEndedUpdate.usage - composed correctness gate (validation gates + QA run + judge intent); CI/merge is real-PR-only since sandboxed runs cannot use CI without an isolated fork - QA plans pre-written in each golden case acceptance set - baseline = previous skill version - bespoke-minimal scorer; slice-3 spike gates any framework on a net-complexity win Open Questions section now empty; decisions logged in spec + design-notes. Trace carries spec-amended. Signed-off-by: wmadden-electric <286902546+wmadden-electric@users.noreply.github.com>
…lidation Add a minimal Cursor-SDK harness that spawns one Drive orchestrator run on a golden brief with a pinned model, accumulates per-run token usage from the SDK turn-ended usage, and writes a run manifest. Live execution is gated behind --live + CURSOR_API_KEY; the default dry-run path makes no live call and the SDK is reached only via a dynamically-imported adapter, so typecheck/test/lint and CI stay green with no key and no @cursor/sdk installed. Token totals land in a run manifest beside the trace (transitional home) since the canonical tokens trace field is owned by TML-2720; no schema change here. Also add validate-parser over a >=3-transcript corpus, clearing TML-2728. Wire the new node --test suites into test:scripts and add drive:run-brief / drive:validate-parser shortcuts. Signed-off-by: wmadden-electric <286902546+wmadden-electric@users.noreply.github.com>
Curate 5 canonical Drive briefs with co-located acceptance sets and pre-written drive-qa-plan scripts under projects/drive-judge-harness/assets/golden/, spanning the Drive-shape space: a direct change, a single in-project slice, a small multi-slice project, an I12-halt/re-plan case (brief built on a false storage-capability premise), and a spike-first case (flaky test, unknown cause). Each case ships case.json + brief.md + acceptance.md + manual-qa.md so the Tier-1 correctness signal (validation gates + QA run + judge intent) is deterministic at run time. Add the slice spec/plan, the slice-scoped Drive trace, and parser-validation.md recording per-event confidence over the transcript corpus (clears TML-2728). Signed-off-by: wmadden-electric <286902546+wmadden-electric@users.noreply.github.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughAdds a drive-judge-harness package providing dry-run/live execution of a canonical Drive brief, token accumulation, run manifests, an SDK adapter to safely interact with ChangesDrive Judge Harness
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Comment |
size-limit report 📦
|
@prisma-next/extension-author-tools
@prisma-next/mongo-runtime
@prisma-next/family-mongo
@prisma-next/sql-runtime
@prisma-next/family-sql
@prisma-next/extension-arktype-json
@prisma-next/extension-cipherstash
@prisma-next/middleware-cache
@prisma-next/mongo
@prisma-next/extension-paradedb
@prisma-next/extension-pgvector
@prisma-next/extension-postgis
@prisma-next/postgres
@prisma-next/sql-orm-client
@prisma-next/sqlite
@prisma-next/target-mongo
@prisma-next/adapter-mongo
@prisma-next/driver-mongo
@prisma-next/contract
@prisma-next/utils
@prisma-next/config
@prisma-next/errors
@prisma-next/framework-components
@prisma-next/operations
@prisma-next/ts-render
@prisma-next/contract-authoring
@prisma-next/ids
@prisma-next/psl-parser
@prisma-next/psl-printer
@prisma-next/cli
@prisma-next/cli-telemetry
@prisma-next/emitter
@prisma-next/migration-tools
prisma-next
@prisma-next/vite-plugin-contract-emit
@prisma-next/mongo-codec
@prisma-next/mongo-contract
@prisma-next/mongo-value
@prisma-next/mongo-contract-psl
@prisma-next/mongo-contract-ts
@prisma-next/mongo-emitter
@prisma-next/mongo-schema-ir
@prisma-next/mongo-query-ast
@prisma-next/mongo-orm
@prisma-next/mongo-query-builder
@prisma-next/mongo-lowering
@prisma-next/mongo-wire
@prisma-next/sql-contract
@prisma-next/sql-errors
@prisma-next/sql-operations
@prisma-next/sql-schema-ir
@prisma-next/sql-contract-psl
@prisma-next/sql-contract-ts
@prisma-next/sql-contract-emitter
@prisma-next/sql-lane-query-builder
@prisma-next/sql-relational-core
@prisma-next/sql-builder
@prisma-next/target-postgres
@prisma-next/target-sqlite
@prisma-next/adapter-postgres
@prisma-next/adapter-sqlite
@prisma-next/driver-postgres
@prisma-next/driver-sqlite
commit: |
…k runtime Install @cursor/sdk as a dev dependency and import `Agent` as a runtime value in sdk-adapter.ts, replacing the previous hand-rolled structural mirror of the SDK. @cursor/sdk@1.0.15 ships .d.ts that re-export from unpublished @anysphere/* packages, so the SDK's own types (incl. TurnEndedUpdate, the token-usage carrier) are unresolvable. The adapter therefore uses the real runtime API and reads only the fields it consumes (usage, outcome) through runtime guards over `unknown` — no fabricated type surface. KNOWN-ISSUES.md documents the upstream bug and the swap-in path once resolvable types ship. Installing the SDK trips the repo's `trustPolicy: no-downgrade` on a transitive undici@5.29.0 (dropped provenance attestation on a newer publish); admitted via the documented trustPolicyExclude hatch (dev-only). The live path stays gated on --live + CURSOR_API_KEY; sdk-adapter is loaded lazily by run-one-brief, so tests/dry-run never require the key or the SDK. Signed-off-by: wmadden-electric <286902546+wmadden-electric@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
skills-contrib/drive-judge-harness/SKILL.md (1)
20-20: ⚡ Quick winConsider removing or generalizing milestone ticket references.
Line 20 (and lines 36, 94) reference specific TML-* ticket numbers (TML-2736, TML-2737, TML-2728, TML-2720). These milestone identifiers may become stale as the project evolves. Consider either removing them or replacing with more durable references (e.g., links to stable architecture docs or feature descriptions that age well).
Based on learnings: Do not reference transient project artifacts from durable system documentation; this pattern applies to milestone references that evolve over time.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@skills-contrib/drive-judge-harness/SKILL.md` at line 20, The SKILL.md text includes transient milestone ticket references (TML-2736, TML-2737, TML-2728, TML-2720); update the document to remove or generalize these identifiers by either deleting the TML-* tokens or replacing them with durable references (e.g., links to stable architecture docs, RFCs, or descriptive phrases like "judge calibration milestone" or "experiment engine feature") so the content ages well; search for the TML-* tokens in SKILL.md (lines that mention "judge", "experiment engine", or specific milestone names) and apply the replacement.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@skills-contrib/drive-judge-harness/run-one-brief.ts`:
- Around line 142-148: The loop over run.stream() and the subsequent await
run.wait() can throw and currently prevent writing the manifest; wrap the entire
"for await (const event of run.stream()) { ... }" plus "const outcome = await
run.wait()" sequence in a try/catch (or try/catch/finally) inside the same
function that calls createAgent (referencing run.stream(), run.wait(),
usageUpdates and TurnUsage), and in the catch record an outcome/status of
'error' and capture error.message into notes; in the finally ensure the manifest
is always written using the accumulated usageUpdates (summarize tokens from
usageUpdates for the manifest tokens field) so that even on runtime failures the
harness writes a manifest with status:'error' and the collected token usage.
In `@skills-contrib/drive-judge-harness/SKILL.md`:
- Around line 17-21: The package README (SKILL.md) currently hardcodes a
transient project path for the "golden-case library"; remove the explicit
projects/... path reference and either (a) replace it with a brief, generic
description of the golden-case library and its purpose/structure (e.g., "the
golden-case library contains briefs, acceptance sets, and QA plans used by the
harness"), or (b) point readers to a stable architecture or docs/ link if one
exists, or (c) if these cases are intended to be permanent, move the assets to a
durable package/location and update SKILL.md to reference that durable location;
update the sentence that mentions the "golden-case library" to reflect one of
these options.
In `@skills-contrib/drive-judge-harness/test/validate-parser.test.ts`:
- Line 5: The import statement bringing renderMarkdown and validateFixtures from
'../validate-parser.ts' includes a .ts extension which violates the TypeScript
import style; update the import to reference the module without the extension
(import { renderMarkdown, validateFixtures } from '../validate-parser') so the
symbols renderMarkdown and validateFixtures are imported from the extension-less
path.
In `@skills-contrib/drive-judge-harness/validate-parser.ts`:
- Line 3: The import statement currently includes a `.ts` file extension which
violates project TypeScript import conventions; remove the extension from the
import so it reads from '../drive-diagnose-run/posthoc' and keep the named
imports (Confidence, parseTranscript) intact to avoid changing symbol references
used elsewhere in validate-parser.ts.
---
Nitpick comments:
In `@skills-contrib/drive-judge-harness/SKILL.md`:
- Line 20: The SKILL.md text includes transient milestone ticket references
(TML-2736, TML-2737, TML-2728, TML-2720); update the document to remove or
generalize these identifiers by either deleting the TML-* tokens or replacing
them with durable references (e.g., links to stable architecture docs, RFCs, or
descriptive phrases like "judge calibration milestone" or "experiment engine
feature") so the content ages well; search for the TML-* tokens in SKILL.md
(lines that mention "judge", "experiment engine", or specific milestone names)
and apply the replacement.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 0c497b72-0cfe-4daf-8f29-12a8b8f1acbf
⛔ Files ignored due to path filters (30)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlprojects/drive-judge-harness/assets/golden/README.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/direct-change-diagnostic-wording/acceptance.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/direct-change-diagnostic-wording/brief.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/direct-change-diagnostic-wording/case.jsonis excluded by!projects/**projects/drive-judge-harness/assets/golden/direct-change-diagnostic-wording/manual-qa.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/i12-halt-storage-assumption/acceptance.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/i12-halt-storage-assumption/brief.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/i12-halt-storage-assumption/case.jsonis excluded by!projects/**projects/drive-judge-harness/assets/golden/i12-halt-storage-assumption/manual-qa.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/project-retry-policy/acceptance.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/project-retry-policy/brief.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/project-retry-policy/case.jsonis excluded by!projects/**projects/drive-judge-harness/assets/golden/project-retry-policy/manual-qa.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/slice-cli-list-flag/acceptance.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/slice-cli-list-flag/brief.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/slice-cli-list-flag/case.jsonis excluded by!projects/**projects/drive-judge-harness/assets/golden/slice-cli-list-flag/manual-qa.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/spike-first-flaky-test/acceptance.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/spike-first-flaky-test/brief.mdis excluded by!projects/**projects/drive-judge-harness/assets/golden/spike-first-flaky-test/case.jsonis excluded by!projects/**projects/drive-judge-harness/assets/golden/spike-first-flaky-test/manual-qa.mdis excluded by!projects/**projects/drive-judge-harness/design-notes.mdis excluded by!projects/**projects/drive-judge-harness/plan.mdis excluded by!projects/**projects/drive-judge-harness/slices/golden-case-harness/parser-validation.mdis excluded by!projects/**projects/drive-judge-harness/slices/golden-case-harness/plan.mdis excluded by!projects/**projects/drive-judge-harness/slices/golden-case-harness/spec.mdis excluded by!projects/**projects/drive-judge-harness/slices/golden-case-harness/trace.jsonlis excluded by!projects/**projects/drive-judge-harness/spec.mdis excluded by!projects/**projects/drive-judge-harness/trace.jsonlis excluded by!projects/**
📒 Files selected for processing (18)
package.jsonpnpm-workspace.yamlskills-contrib/drive-judge-harness/KNOWN-ISSUES.mdskills-contrib/drive-judge-harness/SKILL.mdskills-contrib/drive-judge-harness/load-brief.tsskills-contrib/drive-judge-harness/manifest.tsskills-contrib/drive-judge-harness/run-one-brief.tsskills-contrib/drive-judge-harness/sdk-adapter.tsskills-contrib/drive-judge-harness/test/fixtures/transcripts/direct-change-diagnostic-wording.transcript.jsonlskills-contrib/drive-judge-harness/test/fixtures/transcripts/project-retry-policy.transcript.jsonlskills-contrib/drive-judge-harness/test/fixtures/transcripts/slice-cli-list-flag.transcript.jsonlskills-contrib/drive-judge-harness/test/load-brief.test.tsskills-contrib/drive-judge-harness/test/manifest.test.tsskills-contrib/drive-judge-harness/test/run-one-brief.test.tsskills-contrib/drive-judge-harness/test/usage.test.tsskills-contrib/drive-judge-harness/test/validate-parser.test.tsskills-contrib/drive-judge-harness/usage.tsskills-contrib/drive-judge-harness/validate-parser.ts
…harness Signed-off-by: wmadden-electric <286902546+wmadden-electric@users.noreply.github.com> # Conflicts: # package.json
…istory Replace the three synthetic normal-shape golden cases with cases drawn from real merged PRs, so the corpus measures Drive runs against work the team actually shipped rather than synthesised tasks: - direct-change-example-emit-outputpath (TML-2722 / #618) - slice-dedupe-generated-imports (TML-2714 / #614) - project-reap-subsumed-ir-surfaces (TML-2727 / #630, #631, #629) — a three-slice parallel fan-out that exercises planner parallelisation and scope discipline. Each real case carries the task as posed (Linear ticket, solution-scrubbed so the run still does the design/planning), a base_sha to run against, and a reference.md describing the known-good output by commit SHA (the output itself is fetchable via git diff <base_sha> <merge_sha>). case.json gains source + base_sha; the loader ignores the extra fields until the experiment-engine slice wires base_sha into a checkout. The two pathological cases (i12-halt, spike-first) stay synthetic: no clean merged PR exhibits a halted or spiked run. Update harness tests, SKILL.md examples, and the corpus README for the renamed slugs. validate-parser fixtures are left as-is — they are synthetic parser fixtures with tuned event counts, not corpus members. Signed-off-by: wmadden-electric <286902546+wmadden-electric@users.noreply.github.com>
…tream throws Only createAgent was wrapped; a throw from run.stream() iteration or run.wait() escaped runOneBrief and, since main() runs as void main(), surfaced as an unhandled rejection with no manifest written — losing the accumulated token signal. Wrap the stream+wait in try/catch and always write an error manifest carrying the usage gathered so far plus the error message in notes. Signed-off-by: wmadden-electric <286902546+wmadden-electric@users.noreply.github.com>
…#654) ## Linked issue Refs [TML-2736](https://linear.app/prisma-company/issue/TML-2736). Third slice of the **Drive — Judge + live-experiment harness** project; builds on the two-tier scorecard ([#640](#640)) and the golden-case harness ([#641](#641)). ## At a glance The judge grades one Drive run and emits the `intent` correctness signal the scorecard already reads. Two invariants do the load-bearing work. A malformed model response is never a silent pass: ```ts const validated = RubricResponse(parsed); if (validated instanceof type.errors) { return { intent: null, reasons: [`malformed model output: ${validated.summary}`] }; } ``` …and the emission preserves any gate-recorded `mechanical`/`qa` rather than clobbering it, because the scorecard is last-write-wins on the whole triple: ```ts export function mergedCorrectnessPayload(events, projectRunId, intent) { const prior = latestCorrectness(events, projectRunId); return { mechanical: prior?.mechanical ?? null, qa: prior?.qa ?? null, intent }; } ``` Before this slice, the scorecard's `intent` component was always `null` → every run was `not-computable`. This slice makes it producible. ## Summary This PR ships a **bespoke-minimal LLM judge** under `skills-contrib/drive-judge-harness/judge/`. It carries two substantive pieces: 1. **The judge itself** — grades a completed Drive run (the produced diff + the run's trace) against a golden case's `acceptance.md`, through a cross-family judge model, and emits the `intent` correctness component. Three prompt sets: a requirements+intent rubric, a failure-mode classifier, and an operator-turn classifier. 2. **The recorded decision to build it bespoke** — a time-boxed spike compared Inspect / Braintrust / promptfoo and confirmed bespoke-minimal. The rationale lands in the project `spec.md` and `design-notes.md`; promptfoo is the recorded escape hatch. The judge model is **injected** everywhere, so the whole subtree typechecks, tests, and lints with **no `CURSOR_API_KEY`** and **`@cursor/sdk` absent** — tests pass a mock. The live adapter is reached only behind the same `--live` + key gate as the harness. ## How it fits together 1. **The model boundary** (`judge/judge-model.ts`) — a one-method `JudgeModel` interface (`grade(prompt) => Promise<string>`). Everything downstream takes it as a dependency; tests inject a mock and never make a real call. 2. **The live adapter** (`judge/judge-model-sdk.ts`) — pins a cross-family judge id (default `gpt-5.5`) and **rejects a same-family judge id at construction** (a Claude judge grading a Claude orchestrator throws before any SDK code runs). The `@cursor/sdk` import is lazy, so module load stays green without the package. 3. **The three prompt sets** (`rubric-correctness.ts`, `classify-failure.ts`, `classify-operator.ts`) — each renders a prompt, calls the model, and parses an arktype-validated verdict. The operator-turn classifier uses the measurement model's five canonical buckets (`docs/drive/measurement-model.md`): legitimate-design, legitimate-authorisation, illegitimate-asked, illegitimate-correction, illegitimate-rescue. 4. **The merge-preserving emission** (`judge/emit-correctness.ts`) — folds the rubric's `intent` into the run's latest recorded `{mechanical, qa}` and emits one `correctness-recorded` event through the deterministic emitter. The slice-1 scorecard composes it; no scorecard or schema edits. 5. **The calibration harness** (`judge/calibration.ts` + `judge/calibration/labels.md`) — a judge-vs-human agreement tally with a ≥0.80 gate. The machinery lands; the calibration *run* is parked (see Reviewer notes). ## Reviewer notes - **The calibration run is deliberately parked, not forgotten.** Calibration needs ~10–20 instrumented runs, and corpus generation is real-dollar spend the operator is holding. So this slice ships the gate machinery and an honest "uncalibrated" status; the project-DoD calibration item stays unchecked. `SKILL.md` and `calibration/labels.md` both record the deferral and the operator-spend gate. - **The merge rule is the subtle part.** `computeScorecard` is last-write-wins on the whole `{mechanical, qa, intent}` triple — it does not merge components. A naive judge emitting `{mechanical:null, qa:null, intent:pass}` would erase a gate's recorded pass. `emit-correctness.ts` reads-merges-emits so that can't happen; the end-to-end test asserts a prior `mechanical:pass` survives. - **One unplanned helper.** `judge/parse-json.ts` lifts a JSON object out of a model response (bare / fenced / embedded) — factored out so the malformed-→null path lives in one place rather than three copies. - **The planning commit rides along.** The first commit scaffolds the slice (spec, plan, trace) and records the spike; the second is the implementation. They're one reviewable unit. ## Testing performed - `node --test` over the six new judge suites — **43 cases, all green**, run with `CURSOR_API_KEY` unset. - `pnpm typecheck` — clean. - `pnpm lint:deps` — no dependency violations. - `pnpm lint:casts` — `delta=0` (no new bare casts). - `pnpm test:scripts` — 545 cases green (nothing else regressed). ## Skill update `skills-contrib/drive-judge-harness/SKILL.md` documents the judge, the cross-family requirement, the `correctness-recorded` merge rule, the fail-to-null invariant, and the parked calibration. ## Checklist - [x] DCO sign-off on every commit - [x] Tests written first and passing - [x] Title follows the `TML-NNNN:` convention - [x] No new bare casts (`lint:casts` delta 0) ## Alternatives considered - **Adopt an off-the-shelf eval framework (Inspect / Braintrust / promptfoo).** Confirmed-rejected by the spike. They grade `(input → model output)`; our unit is a whole Drive run scored from trace + diff + golden acceptance set. A framework can host the tiny grading call but not the integration with our trace/scorecard/golden assets — that glue is bespoke either way. promptfoo (TS, MIT, local) is recorded as the escape hatch if the bespoke scorer grows hairy. - **Emit the `intent` component on its own.** Rejected — it would clobber the gate-recorded `mechanical`/`qa` under last-write-wins. Hence the merge-preserving helper. - **An `other` operator-turn bucket + non-null fallback.** Rejected — the measurement model defines exactly five buckets; a malformed response yields `bucket: null` (same fail-to-null discipline as the rubric) rather than an off-doc catch-all. - **Run the calibration now.** Rejected — corpus generation is held on cost. The judge ships uncalibrated-but-honest; the gate is computable the moment the corpus exists. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit # Release Notes * **New Features** * Introduced LLM-based judge system for Drive orchestrator evaluation with failure mode classification, operator turn assessment, and correctness rubric grading * Implemented cross-family model constraint enforcement between judge and orchestrator * Added calibration framework for judge accuracy validation with agreement-rate metrics * **Documentation** * Expanded judge harness documentation with detailed module descriptions and key invariants * Added calibration corpus specification and workflow guidance * **Tests** * Added comprehensive test coverage for judge components, classifiers, and calibration logic <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Will Madden <madden@prisma.io> Co-authored-by: Will Madden <madden@prisma.io>
Decision
A golden-case library + a minimal live harness is how we accrete the instrumented-run corpus the Drive LLM judge (TML-2736) calibrates against, and the run-spawning mechanism the experiment engine (TML-2737) builds the k=N A/B loop on. This slice ships both, plus validates the post-hoc trace parser (clears TML-2728). Foundation slice of project Drive — Judge + live-experiment harness (Parallel group F). Stacked on planning PR #638.
What's here
1. Golden-case library —
projects/drive-judge-harness/assets/golden/5 canonical Drive briefs spanning the Drive-shape space, each with
case.json+brief.md+acceptance.md(expected verdict + requirements + correctness oracle) + a pre-writtendrive-qa-planmanual-qa.md(so the Tier-1 QA signal is deterministic at run time):direct-change-diagnostic-wordingslice-cli-list-flagproject-retry-policyi12-halt-storage-assumptionspike-first-flaky-test2.
run-one-briefharness —skills-contrib/drive-judge-harness/Spawns one orchestrator run on a golden brief with a pinned model, accumulates per-run token usage from the SDK's turn-ended
usage(inputTokens/outputTokens/cacheReadTokens/cacheWriteTokens), and writes a run manifest.No-API-key-in-CI guarantee. Live execution requires both
--liveandCURSOR_API_KEY; the default is a dry-run that makes no network call.@cursor/sdkis reached only throughsdk-adapter.ts's dynamic import on the live path, sotypecheck/test/lint/ CI all stay green with no key set and@cursor/sdknot installed. Tests inject a mockcreateAgent(zero live calls). The token accumulator and manifest writer are pure and unit-tested.3. Post-hoc parser validation (clears TML-2728)
validate-parser.tsrunsdrive-diagnose-run/posthoc.tsover a ≥3-transcript corpus;projects/drive-judge-harness/slices/golden-case-harness/parser-validation.mdrecords per-event confidence. Result: 12 events reconstructed — 0 high · 6 medium (dispatch existence) · 6 low (spec/plan authoring). The parser is structurally capped atmedium(transcripts lack ground-truth envelope fields); it is robust to sparse and rich transcripts; no behaviour bug surfaced —posthoc.tsunchanged.Dependency note (TML-2720)
The canonical
tokenstrace field is owned by the parallel slice TML-2720 (which ownsschema.ts/metrics.ts/report.ts— untouched here). Until that schema field lands, the harness writes token totals to a run manifest beside the trace rather than emitting an unvalidatable trace line through the fail-closed emitter. When TML-2720 lands, the manifest'stokensmigrates into the validated trace viaemit.ts.Deferred / out of scope
tokens/correctness schema additions → TML-2720.Operator-gated boundary (blocker reported, not worked around)
pnpm add @cursor/sdkfails the repo'strustPolicy: no-downgradeguard on a transitiveundici@5.29.0(an earlier version had provenance attestation this one lacks). Admitting a supply-chain-flagged package + adding atrustPolicyExcludeentry is an operator decision with repo-wide blast radius, and live execution needs aCURSOR_API_KEYregardless. So the SDK is fully isolated, the dep is not added to the lockfile, and live execution is operator-gated — the harness ships fully functional in dry-run/mock form. Resolution documented in the harnessSKILL.mdand the slice spec's open question.Gates (green)
pnpm typecheck(138/138) ·pnpm lint:deps·pnpm lint:casts(delta 0) ·pnpm lint:skills·pnpm test:scripts(468 tests incl. 34 new) · dry-run verified with noCURSOR_API_KEY.Summary by CodeRabbit
New Features
Tests
Documentation
Chores