chore(gate): walk the ADR-0003 pins, delete the placeholder versions.json - #81
Conversation
OM152002
left a comment
There was a problem hiding this comment.
Approve. I ran it rather than read it, and every behavioural claim checked out.
unknown id (--versions 99.0.0) exit=2 + valid-id list printed
full dry-run exit=0 walks all 8 pins
live attempt (no --dry-run) exit=2
out/metrics.ndjson 24 rows = 8 versions x (2 steps + 1 run)
out/matrix-run.json selection / versions_in_matrix: 8 / versions_walked[8]
Deleting versions.json instead of syncing it is the right call, and the reason given is the real one: two lists for one thing drift, and its only non-duplicated fields were the actively misleading part — per-version site_key / task_key relabelling the local-demo program as though a Grafana run had happened. Letting only testbed_version vary is the honest split.
Rejecting unknown ids with exit 2 rather than falling through to a default is the detail I'd have asked for if it were missing. A silent default is exactly how a placeholder run gets mistaken for a measurement, which is the bug this PR is closing.
The skip ledger earns its place — without versions_skipped[] {id, reason} a later reader cannot distinguish "8 pins, 3 unavailable" from "5 pins", and the denominator shrinks with nobody noticing. Proving it by temporarily marking 9.5.21 unavailable and reverting is the right way to test a branch no pin currently exercises.
Merges clean against main and #80, despite touching src/testbed/matrix.ts and tests/unit/testbed.test.ts, which #80 also edits. Worth re-checking after whichever lands first, since that overlap is real even though git resolves it today.
The thing I appreciate most is what the PR refuses to claim: walking eight versions over the same hand-written 2-step program is called "a better-shaped denominator, not a measurement", and stub 4 in architecture.md is narrowed rather than deleted — the dry-run PASS with zero tokens is still flagged. That is the distinction that keeps this row honest when someone reads the report later.
…json There were two version matrices and only one was real. `run-matrix.ts` iterated `experiments/gate-v1/versions.json`, which held a single `pending-b1@placeholder` entry — so `npm run gate:matrix` walked a fake list and any report generated from it was a report about nothing. `scripts/testbed/matrix.json` (ADR-0003) is now the single source of truth, read through `src/testbed/matrix.ts` rather than a second ad-hoc JSON import. versions.json is DELETED, not kept in sync. Two lists for one thing drift, and its only non-duplicated fields were actively misleading: per-version `site_key` / `task_key` overrides relabelled the hand-written local-demo program as though a Grafana run had happened. Now only `testbed_version` varies per run; `site_key` and `task_key` stay whatever the compiled program actually is. Added: - `--versions <a,b,c>` and `--versions all` (default). Unknown ids are rejected with the valid list and exit 2 — never a fall-through to a default, which is how a placeholder run gets mistaken for a measurement. - Versions marked `"status": "unavailable"` in matrix.json are skipped, logged, and recorded in a new `out/matrix-run.json` ledger alongside `versions_in_matrix` and `versions_walked`. Without that ledger a later reader cannot tell "8 pins, 3 unavailable" from "5 pins" and the denominator shrinks silently. `isUnavailable` / `availableVersions` are unit-tested; no pin carries the flag today. - Exit 1 when the selection walks zero versions. An empty NDJSON is a missing denominator, not a successful run. Unchanged on purpose: the --dry-run gate (live execution is #62), hard-coded PASS outcomes, and zero token counts. Every emitted row still carries "dry-run — tokens remain 0; not a gate measurement". Walking eight versions instead of one makes the row count honest, not the numbers meaningful. `npm run gate:matrix -- --dry-run` now emits 8 run rows + 16 step rows with the correct testbed_version each; `npm run gate:report` renders them and still reports no_data for repair-cost, self-heal and time-to-repair. Closes #26 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5229fad to
23b73a6
Compare
|
Rebased onto One real conflict, in
One line added on top of the rebase: Re-verified after the rebase: 🤖 Generated with Claude Code |
Closes #26.
There were two version matrices and only one was real.
run-matrix.tsiteratedexperiments/gate-v1/versions.json, which held a singlepending-b1@placeholderentry — sonpm run gate:matrixwalked a fake list and any report generated from it was a report aboutnothing.
scripts/testbed/matrix.json(ADR-0003) is now the single source of truth, read throughsrc/testbed/matrix.tsrather than a second ad-hoc JSON import.versions.jsonis deleted, not kept in syncTwo lists for one thing drift. Its only non-duplicated fields were per-version
site_key/task_keyoverrides, and those were actively misleading: they relabelled the hand-written2-step local-demo program per version as though a Grafana run had happened.
So only
testbed_versionvaries per run now.site_keyandtask_keystay whatever thecompiled program actually is. That is the honest split — the run really is on the local-demo
program; only which matrix slot it belongs to changes.
What's new
--versions <a,b,c>/--versions all(default all). Unknown ids are rejected with thevalid list and exit 2 — never a fall-through to a default, which is exactly how a
placeholder run gets mistaken for a measurement:
"status": "unavailable"versions are skipped, logged, and recorded — never silentlydropped. New
out/matrix-run.jsonledger carriesselection,versions_in_matrix,versions_walked, andversions_skipped[] {id, reason}. Without it a later reader cannot tell"8 pins, 3 unavailable" from "5 pins" and the denominator shrinks silently.
No pin carries the flag today, so I proved it by temporarily marking 9.5.21 unavailable
(reverted —
matrix.jsonis unchanged in this diff):isUnavailable/availableVersionsare unit-tested against a synthetic matrix, plus a testasserting no pin is currently marked unavailable.
Exit 1 when the selection walks zero versions. Not in the issue, but an empty NDJSON is a
missing denominator, not a successful run, and a CI caller should notice:
Still not a measurement
Unchanged on purpose: the
--dry-rungate (live execution is #62), hard-codedPASSoutcomes,and zero token counts. Every emitted row still carries
dry-run — tokens remain 0; not a gate measurement, andout/matrix-run.jsonrepeats it in anot_a_measurementfield. Walking eight versions instead of one makes the row count honest,not the numbers meaningful.
Verified output:
No invented rates; the empty denominators still report
no_data.Docs
experiments/gate-v1/README.md(version-list section, commands, exit codes, skip ledger, openquestions),
docs/gate/runner.mdopen questions,docs/architecture.md(package table,artifact table, and stub-table row 4 — which was about this placeholder), and the
dependabot.ymlcomment that pointed atversions.json.fixtures/compiled-program.jsonstill declarestestbed_version: "pending-b1@placeholder". Leftalone deliberately — it is accurate, that program was compiled against no testbed at all, and
the runner overrides it per version. Noted in the README.
Merge note
Test-merged against my three other open branches: #80 and #79 merge clean. #78 conflicts
in
docs/architecture.md— one hunk in the package table, because #78 inserts asrc/shared/row directly above the
experiments/gate-v1/row whose "Contract read" cell I changed.Resolution is to keep both: #78's new
src/shared/row, then this branch's editedexperiments/gate-v1/row.Tests
🤖 Generated with Claude Code