Add deterministic check kinds (target_match, command, score_delta) to the rubric schema
## Problem/Motivation
The rubric schema (`schema/rubric.schema.json`) has deterministic check kinds for
inspecting text (`must_contain_any`, `must_not_contain`, `regex`, `json_schema`,
`php_lint`, `markdown_structure`, `format`, `tool_usage`, `fact_match`) and
`llm_judge` for subjective scoring. It has no kind for the deterministic-first
cases that come up when benchmarking coding agents on real Drupal work: compare
output to a reference, run a test in a sandbox, or measure a static-analysis score
delta.
This is the schema side of the ai_bench convergence discussed in #ai (Robert
Menetray, drupal.org/project/ai_bench): one shared schema, many consumers. The
four ai_bench benchmarks are Layer-5 domain bundles that need these kinds.
## Proposed resolution
Three additive deterministic check kinds, each following the existing `check_base`
pattern (`unevaluatedProperties: false`), plus executors in the reference
implementation:
- `target_match` — compare output to a reference string (`source` dot-path, e.g.
`expected.reference`), `mode: exact | normalized | chrf` (character n-gram
F-score, no LLM), `threshold` for chrf mode. For translation-style scoring where
exact match against a single reference is too brittle.
- `command` — run a command/test in a sandbox: `sandbox` (default `ddev`),
`setup: none | revert_fix | apply_patch`, `expect: exit_zero | test_transitions`.
The reverted-fix + regression-test oracle (`test_transitions`: the test fails in
the setup state and passes after the model's change).
- `score_delta` — run a deterministic scorer (`tool: audit | phpcs | phpstan`)
against a `baseline`, pass when the delta meets `min_delta`, with a
`guard_command` that must exit zero so the score can't be raised by breaking
code. Generalizes to any scorer (e.g. a readability score).
Additive and non-breaking: existing rubrics validate unchanged (`RubricValidator`
needs no PHP change; the new kinds render as raw-JSON rows in `RubricEditor`).
`command` and `score_delta` grade sandbox state, not the response text, so the
single-turn string response is not a constraint for them — their executors run
against the sandboxed execution environment designed in #3594701.
## Remaining tasks
- [x] Schema: three new `$defs` + `oneOf` entries, with valid and invalid examples.
- [ ] Reference implementation: a rubric-check evaluator + executors (`target_match`
string/chrf now; `command`/`score_delta` behind a sandbox harness interface).
- [ ] Socialize the field names with ai_bench before anyone depends on them
(additive kinds are cheap to rename now, expensive later).
## Related
- #3594676 roadmap to 1.0
- #3594701 sandboxed / stateful task evaluation (execution env for `command`/`score_delta`)
- #3594698 verify tool calls from the trace (the `tool_usage` path)
- #3594697 multi-turn execution (issue-resolution agent runtime)
issue