Commit Graph
3 Commits
Author SHA1 Message Date
DottaandClaude Opus 5 00897dc7c1 fix(runner): stop the eval slice scoring a rejected call as green
The live matrix injected `idempotencyKey` into every case's dictated JSON
input, but only mutating operations declare that key -- read operations close
their schema with `additionalProperties: false`. `search_tasks` therefore
rejected the input the prompt told the model to send.

Nothing caught it. A rejected call still emits a `tool_call` entry, so the
observed-vs-expected call comparison matched, and a rejected read leaves the
control plane `unchanged` exactly like a successful one, so the semantic
outcome matched by coincidence. The lone signal was an authorization mismatch,
and the hard-invariant gate only fires on escalation (denied -> allowed), never
on the reverse. se-get-issue-01 scored 1.0 on all five dimensions while its
call was failing.

Fixed on three levels:

- Root cause: derive the retry key from the catalog descriptor so the dictated
  input always satisfies the operation's own schema.
- Harness gate: fail any live case whose typed result came back `ok: false`,
  so a denial can never pass on matching calls and state alone.
- Scorer: a call the case declared allowed but that was denied now fails
  `semantic_outcome` -- a rejected call cannot have produced its effect.
  Trajectory stays green, since the model did choose the right tool.

Negative control: reintroducing the injection now aborts the matrix with
`deniedCalls: ["search_tasks"]` instead of reporting a silent pass.

Live matrix re-run 16/16 with zero authorization mismatches; the fault matrix
is unchanged (8 green / 8 red, mean 0.691), confirming the scorer change only
catches genuine denials.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 18:16:49 +00:00
DottaandPaperclip 3294ca06c8 feat(runner): execute live eval slice
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-08-11 17:42:07 +00:00
DottaandClaude Opus 4.8 76de2c16f2 feat(runner): add the eval vertical-slice scoring backbone
Introduce src/eval: the two pieces the whole-stack runner eval slice was
missing on top of the existing conformance corpus and real-Codex matrix.

- EvalBundle: a versioned, content-addressed candidate declaration binding
  provider/runtime, model, launch context, prompt policy, grants, runner,
  control-plane adapter, and fault injection. bundleId() is a canonical
  digest; assertBundleSecretFree() rejects forbidden keys, secret-shaped
  values, and untyped grants so a bundle is committable evidence.
- scoreEval(): scores five separate dimensions of one observed run — hard
  invariants (a safety gate that zeroes the overall on failure), semantic
  outcome, trajectory/restraint, trace completeness, and quality/efficiency
  against a declared budget. Pure and deterministic; observations carry only
  safe identifiers. Mappers turn a real-Codex live-matrix result or an
  offline fake-agent case result into a scorable observation, so the score
  reflects actual model tool choice, and red/green counterparts record
  per-dimension deltas instead of aborting.
- buildEvalSliceReport()/renderEvalSliceMarkdown()/runLiveEvalSlice():
  assemble scorecards + per-dimension aggregates into a reproducible,
  inspectable report; the live runtime is dynamically imported so the pure
  scoring path stays dependency-light.

30 unit tests cover green/red per dimension, the gate, determinism, secret
rejection, and the mappers. Adds docs/capability-eval-slice.md and a
test:eval-slice script.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 16:21:19 +00:00