fix(migration): operator-window SC2 must be regression-relative, not strict

The operator window's step [a] called 40-validate-standalone.sh directly (strict
exit-code), so it STOPped on the first target carrying pre-existing in-repo test
red — voyage (2 doc-consistency drifts re phase_models/phase_signals, content moved
to docs/operations.md) and ai-psychosis (1). But the migration's ratified contract,
the one the Step-11 dry-run validated as PASS 11/11, is 'introduce no regression':
pre-existing in-repo red is the plugin's own concern, not a migration regression.
The window enforced a STRICTER gate than the contract the dry-run signed off.

Fix: new 41-validate-or-regression.sh — the single per-target gate the window calls
in [a]. It runs 40 strict, then on failure passes iff the standalone failing-test
NAME set is a SUBSET of the live in-repo set (the exact decision 99-dryrun.sh makes),
reusing sc2-regression.sh. A genuine extraction-introduced regression still STOPs the
window; a structure-validator fail and the config-audit gate stay strict.

Single-source the failing-name capture: extract capture_fails into capture-fails.sh
(mirrors the sc2-regression.sh extraction) so the live gate and the dry-run agree on
what 'failing' means; 99-dryrun.sh now delegates to it (behaviour identical).

Verified end-to-end on the real extracts: 40 strict fails voyage+ai-psychosis while
41 passes them 'N pre-existing, regression-relative'; clean targets (llm-security,
graceful-handoff) still pass via the strict path. New hermetic tests: capture-fails
3/3, 41 6/6 (strict-pass, regression-relative-pass, genuine-regression-fail,
structure-not-eligible, gate pass/fail). RUNBOOK per-repo step updated to 41.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-06-18 06:25:55 +02:00
commit 3403648c6c
7 changed files with 336 additions and 12 deletions

View file

@ -99,11 +99,15 @@ Order (lower risk last so problems surface while the blast radius is small):
```bash
KEY=<target> # e.g. voyage
# a. extract + validate standalone (config-audit uses its dedicated SC2 gate)
# a. extract + validate standalone (config-audit uses its dedicated SC2 gate).
# SC2 is REGRESSION-RELATIVE (the contract the Step-11 dry-run validated): 41 runs 40 strict, then on
# failure passes iff the standalone failing-test set is a SUBSET of the live in-repo set — so pre-existing
# in-repo red (e.g. voyage's 2 doc-consistency drifts, ai-psychosis's 1) does NOT STOP the rollout, while
# a genuine extraction-introduced regression still does. (Strict 40 alone would STOP on that blessed red.)
if [ "$KEY" = "config-audit" ]; then
WORK=$WORK bash MIG/50-config-audit-sc2.sh # config-audit: SC2 PASS (...)
else
WORK=$WORK bash MIG/40-validate-standalone.sh "$KEY" # <KEY>: PASS (...)
WORK=$WORK bash MIG/41-validate-or-regression.sh "$KEY" # <KEY>: PASS (standalone strict | N pre-existing)
fi
# b. create the Forgejo repo (auto_init:false, public)