evals: wire the verifier into third-party harnesses for evidence collection - #2610
Conversation
|
62a6ccd to
6e57d3a
Compare
There was a problem hiding this comment.
All reported issues were addressed
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 16 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
d6f34cd to
8146652
Compare
There was a problem hiding this comment.
All reported issues were addressed across 16 files
Architecture diagram
sequenceDiagram
participant CLI as TUI Run
participant Runner as External Harness Runner
participant Adapter as Tool Adapter
participant Recorder as ObservationRecorder
participant Exposure as LLMExposure
participant Browser as Browser/CDP
participant Harness as Harness Adapter
participant Gate as Verifier Gate
Note over CLI,Gate: Evidence Collection Flow for External Harnesses
CLI->>Runner: runCommand(options)
Runner->>Adapter: prepareToolAdapter(exposure)
alt Observations enabled (EVAL_HARNESS_OBSERVATIONS != none)
Adapter->>Recorder: new ObservationRecorder(exposure.captureObservation)
Note over Recorder: Buffers probes by run index
end
Note over Runner,Harness: Per-Step Observation Collection
loop Each agent tool execution
Runner->>Exposure: runTool(code)
Exposure->>Browser: Execute code
Exposure-->>Runner: Return result
alt Recorder exists
Runner->>Recorder: record()
Recorder->>Exposure: captureObservation()
Exposure->>Browser: Capture screenshot + URL
alt Capture success
Browser-->>Exposure: TerminalArtifact
Exposure-->>Recorder: Artifact data
Recorder->>Recorder: Buffer at current runIndex
else Capture failure/timeout
Exposure-->>Recorder: Error/empty
Note over Recorder: Leave gap (no shift)
end
end
end
Note over Runner,Harness: Final State & Trajectory Assembly
Runner->>Exposure: captureFinalState()
Exposure->>Browser: Capture final screenshot + URL
Browser-->>Exposure: TerminalArtifact
Exposure-->>Runner: terminalArtifact
Runner->>Adapter: drainStepObservations()
Adapter->>Recorder: drain()
Recorder-->>Adapter: StepObservation[]
Adapter-->>Runner: stepObservations
Runner->>Harness: fromHarnessResult({terminalArtifact, stepObservations})
alt claude_code adapter
Harness->>Harness: Map observations to LLM_RUN_TOOL_NAME steps
Note over Harness: Attach probeEvidence per step
alt Has screenshot artifact
Harness->>Harness: finalObservation = terminalArtifact
else Fallback
Harness->>Harness: finalObservation = last agent screenshot
end
else codex adapter
Harness->>Harness: Filter bridge runs (browser_run.mjs)
alt Bridge runs >= recorded observations
Harness->>Harness: Map by ordinal, attach probeEvidence
else Mismatch detected
Note over Harness: Skip attachment (misattribution risk)
end
end
Note over Harness,Gate: Verifiability Aggregation & Gating
CLI->>CLI: Collect all results
CLI->>Gate: summarizeArmVerifiability(results, harness)
Gate->>Gate: Group by (harness × surface × model)
Gate-->>CLI: ArmVerifiability[]
CLI->>CLI: Print per-arm summary
alt EVAL_MAX_UNVERIFIABLE_CRITERIA set
CLI->>Gate: resolveUnverifiableCriteriaLimit()
CLI->>Gate: armsOverLimit(arms, limit)
Gate-->>CLI: Arms exceeding limit
alt Arms over limit
CLI->>CLI: Log violations, set exitCode=1
else No graded arms with gate set
CLI->>CLI: Log warning, set exitCode=1
end
end
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
8146652 to
e06877e
Compare
…ection Per-step probe observations (url + screenshot through the exposure's own surface) attach to run-tool steps for claude_code and bridge runs for codex, and the harness-observed terminal artifact anchors the final observation — parity with the Stagehand-driven TrajectoryRecorder path. Unverifiable criteria are aggregated per (harness x surface x model) arm after each batch; EVAL_MAX_UNVERIFIABLE_CRITERIA turns the report into a gate. EVAL_HARNESS_OBSERVATIONS=none excludes a run from evidence collection.
Strict integer parsing for EVAL_MAX_UNVERIFIABLE_CRITERIA (malformed values stay report-only); bridge probe callbacks can no longer hang a request or flip a successful run to an error; a configured gate now fails loudly when verifier-backed runs produced no graded arms instead of being silently bypassed; codex observation attachment refuses to guess when recorded bridge runs outnumber filter-matched steps — a gap grades safer than misattributed evidence.
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
83c982d to
88d32fd
Compare
Summary
STG-2752: external-harness runs now carry per-step observations and a final observation grounded in harness-captured evidence, and unverifiable-criteria counts are reported per arm and can gate the batch.
ToolStartResult.captureEvidence(optional hook): each code surface captures current page state (url + screenshot + aria tree) through its own handles — one shared capture per surface, resolved throughsession.activePage()at capture timeobservationRecorder.ts(new): run-indexed probe buffer; a failed capture leaves a gap instead of shifting later observations onto the wrong step;EVAL_HARNESS_OBSERVATIONS=noneexcludes a run from evidence collectionclaude_codeand each bridge run incodex; the trajectory adapters attach them to code steps only, and refuse attachment when counts mismatch (misattribution is worse than a gap)tui runprints per-arm verifiability and enforces theEVAL_MAX_UNVERIFIABLE_CRITERIAgateVerified live: in webvoyager runs the verifier now rejects agent claims that the collected step evidence does not support (e.g. asserted ingredients absent from the extracted list).
Stacked follow-ups: #2649 extends the gate to count verifier-failed (ungraded, self-reported) rows per arm and fail gated batches containing any; #2650 extends per-step observation to the MCP tool surfaces via the runner event streams.
Summary by cubic
Wires verifier-backed evidence capture into
claude_codeandcodexso runs include per-step URL/screenshot probes and a harness-observed final artifact. Adds per-arm verifiability reporting and an optional gate for STG-2752.New Features
ObservationRecorderfor per-step probes; opt out withEVAL_HARNESS_OBSERVATIONS=none, timeout viaEVAL_OBSERVATION_TIMEOUT_MS.run_toolinclaude_codeand each bridge run incodex; adapters attach only to code steps (LLM_RUN_TOOL_NAME,browser_run.mjs) asprobeEvidence. Final observation prefers the harness-captured artifact, else the last agent screenshot.tui runprints per-arm verifiability and enforces theEVAL_MAX_UNVERIFIABLE_CRITERIAgate.Bug Fixes
codexonly attaches observations when recorded bridge runs match filtered steps;claude_codecaptures a terminal artifact before cleanup; final observation requires a screenshot.EVAL_MAX_UNVERIFIABLE_CRITERIA; the gate fails loudly when set but no arms were graded.Written for commit 88d32fd. Summary will update on new commits.