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