docs(proevesett): v2 first run is 8 of 8; the new case falls on a planted code fault

v2 = eight cases, expectations committed in 3892a83 before the run.
Run 1: 8/8 cases, 36/36 graders, 65 s, $1.97 (list-price estimate).
Known-positive for the intent-gate case, in a scratch copy: --check made
to accept everything → 0.75 (names-code fails). Removing only the gate's
command line from trekplan.md did NOT fell it (1.00): the child rebuilt the
call from the surrounding prose — the case measures the gate's effect; the
exact line is pinned by the unit test that executes it. One green run of
case 5 does not prove the instability gone; that needs more runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-23 09:32:37 +02:00
commit dc9b480780
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q

View file

@ -1,8 +1,9 @@
# Prøvesett — Voyage's fixed test set as a plugin eval suite # Prøvesett — Voyage's fixed test set as a plugin eval suite
**Status:** v1, seven cases, first run **6 of 7** (2026-09-23, Claude Code 2.1.280). **Status:** v2, eight cases. v1 (seven cases) first run **6 of 7**; v2 first run
The cases and their expectations were committed *before* the first run; the **8 of 8** (both 2026-09-23, Claude Code 2.1.280). Each version's cases and
run did not change them. Red is data here, not a defect in the suite. expectations were committed *before* its first run; the run did not change them.
Red is data here, not a defect in the suite. What v2 changed and why: § v2 below.
The unit suite (`npm test`) proves Voyage's modules in isolation. This suite proves The unit suite (`npm test`) proves Voyage's modules in isolation. This suite proves
something the unit suite cannot: that the **commands, as a model reads and follows something the unit suite cannot: that the **commands, as a model reads and follows
@ -49,7 +50,9 @@ promises and ends in seconds. Nothing starts the `/trekplan` exploration swarm o
| `review-validate-flags-bad-finding-id` | **known-positive:** `--validate` fails a review whose finding ID is not 40-char hex, and names the rule | review-validator runs; `REVIEW_BAD_FINDING_ID` in the trace; reply says FAIL; no Agent, no Write | pass | | `review-validate-flags-bad-finding-id` | **known-positive:** `--validate` fails a review whose finding ID is not 40-char hex, and names the rule | review-validator runs; `REVIEW_BAD_FINDING_ID` in the trace; reply says FAIL; no Agent, no Write | pass |
| `review-validate-passes-clean-review` | **known-negative:** `--validate` passes a valid review and raises nothing | review-validator runs; reply says PASS; no `REVIEW_*` error code in the trace; no Agent, no Write | pass | | `review-validate-passes-clean-review` | **known-negative:** `--validate` passes a valid review and raises nothing | review-validator runs; reply says PASS; no `REVIEW_*` error code in the trace; no Agent, no Write | pass |
### The one red case The v1 table above is kept as it was run. v2 rows and grader changes: § v2.
### The one red case (v1; fixed in v2, see § v2)
`review-requires-project` failed on its text grader only: the child replied in one turn `review-requires-project` failed on its text grader only: the child replied in one turn
without reproducing the exact error line `Error: --project <dir> is required.` The without reproducing the exact error line `Error: --project <dir> is required.` The
@ -81,6 +84,34 @@ therefore falls when this part of Voyage breaks.
| Cost | $1.67, the tool's list-price estimate; on a subscription it counts against usage limits instead | | Cost | $1.67, the tool's list-price estimate; on a subscription it counts against usage limits instead |
| Output | `evals/results/<timestamp>/aggregate-result.json` + `report.html` (gitignored) | | Output | `evals/results/<timestamp>/aggregate-result.json` + `report.html` (gitignored) |
## v2 (2026-09-23): the intent gate gets a case, case 5's error moves into code
Expectations committed in `3892a83` before the v2 run. Offline structure tests in
`tests/lib/proevesett.test.mjs` pin what each grader can see.
| Change | Why |
|--------|-----|
| **New case `plan-halts-without-intent-approval`**: a `brief_version` 2.1 brief *with* `phase_signals` and no `intent_approved_hash`. Graders: `gate-ran` (`intent-approval.mjs --check` in a Bash call), `names-code` (the gate's own JSON `code` for `BRIEF_INTENT_NOT_APPROVED` in the trace), `no-agent`, `no-plan-file` | Veikart steg 1's gate had no case. No v1 trace reached it: case 4 halts at the sequencing gate first |
| **`review-requires-project`**: the arg parser got a CLI that checks `--project` itself and prints `Error: --project <dir> is required.` + usage (exit 1, code `ARG_REQUIRED_MISSING`). `trekreview.md` runs it with `$ARGUMENTS` and relays its stderr. The reply-regex grader `project-required` is replaced by `parser-ran` + `names-missing-project` (the parser's code in the trace, the same form as `names-rule`) | The fix this doc recommended for the red case. Also: the prose passed `"$@"`, which the Bash tool never has. The parser never ran (0 Bash calls in the case-5 traces), so the model composed the line from prose. That failed 2 of 10 on backticks |
| `no-error-code` → `code\W{1,12}REVIEW_[A-Z_]+`, bound to the validator's JSON output | The listed codes missed `REVIEW_WRONG_TYPE` and `REVIEW_VERSION_FORMAT` |
| `says-pass` / `says-fail` reject a preceding `NOT` and a longer word | Raw substrings: "did not PASS" passed `says-pass` |
| `no-bash-write` beside every `no-write`: redirect, `tee`, `touch`, `cp`, `mv`, `rm`, `sed -i` in the Bash command | `no-write` sees only the Write tool |
All new patterns were run against the ten traces of the PM re-measurement. There
were no false positives, and the known-positive and known-negative still split.
**v2 first run: 8 of 8** (graders 36 of 36, 65 s, $1.97; the tool's list-price
estimate).
**Known-positive for the new case, demonstrated** in a scratch copy (never this
tree):
- With `--check` made to accept every brief (`intent-approval.mjs`), the case dropped
to **0.75**. `names-code` failed; the other graders passed.
- Removing only the gate's command line from `trekplan.md` did **not** fell the case
(1.00). The child rebuilt the `--check` call from the prose around it. So the case
measures whether the gate works, not whether that exact line is there. The line is
pinned by `tests/validators/intent-approval.test.mjs`, which executes it.
## Measured facts about the harness this suite relies on ## Measured facts about the harness this suite relies on
These were measured by probe cases in a scratch copy, not taken from the docs. These were measured by probe cases in a scratch copy, not taken from the docs.
@ -121,7 +152,7 @@ From the plugin root:
claude plugin eval . --trust-plugin --ablation none --runs 1 --scaffold --no-publish --allow-tools Bash Write claude plugin eval . --trust-plugin --ablation none --runs 1 --scaffold --no-publish --allow-tools Bash Write
``` ```
- `--scaffold` runs each case's `scaffold.sh` as you, outside the sandbox. The three - `--scaffold` runs each case's `scaffold.sh` as you, outside the sandbox. The four
scaffolds in this suite only write fixture files into the run's workspace. scaffolds in this suite only write fixture files into the run's workspace.
- `--allow-tools Bash Write` grants the tools the commands need (Bash runs under the OS - `--allow-tools Bash Write` grants the tools the commands need (Bash runs under the OS
sandbox). Write is granted so that the `no-write` and `no-plan-file` graders measure a sandbox). Write is granted so that the `no-write` and `no-plan-file` graders measure a
@ -142,6 +173,8 @@ The suite is the fixed yardstick that a rule change is measured against:
4. A new promise gets a new case, and its expectation is committed before its first run, 4. A new promise gets a new case, and its expectation is committed before its first run,
the same as here. `N` grows; it never shrinks to make `n` look better. the same as here. `N` grows; it never shrinks to make `n` look better.
Because `runs: 1` is a sample, an unstable case such as `review-requires-project` will Because `runs: 1` is a sample, an unstable case such as `review-requires-project` in v1
sometimes stop a change that is innocent. That is the intended price. Moving the guard will sometimes stop a change that is innocent. That is the intended price. Moving the guard
into code removes the instability; editing the grader does not. into code removes the instability; editing the grader does not. v2 did the move: the
parser now writes the line, and the grader reads the parser's code. One green run does
not show the instability is gone. That takes more runs.