tests/test_v2_selectors.py
"""Nested protocol, fold isolation, reward baseline and conservative gate tests."""
import copy
import inspect
import numpy as np
import pytest
from mcss.vision_probe.v2_selectors import (
TRAJECTORIES,
_choice,
_fit,
_winner,
fit_v2,
predict_v2,
select_v2,
)
def rows(zero=False):
result = []
for seq in range(3):
for slot in range(1 + (seq == 2)):
for i, t in enumerate(TRAJECTORIES):
reward = 0.0 if zero else (0.02 if i == 5 else -0.01 if i else 0.0)
result.append(
{
"split": "discovery",
"sequence": str(seq),
"target_slot": slot,
"trajectory": list(t),
"J": 0.4 + reward,
"visible": {
"quality": reward,
"sequence_signal": float(seq),
"f_cycle": reward / 2,
},
}
)
return result
def test_nested_isolation_weighted_scaler_and_final_model():
data = rows()
fitted = fit_v2(data, ["quality", "sequence_signal"], {})
for name, cv in fitted["nested_cv_results"].items():
assert cv["outer_oof_score_before_fallback"]["net_delta_J"] > 0
assert cv["final_policy"] == "RIDGE_GATE"
for outer in cv["outer_folds"]:
held = set(outer["held_out_sequences"])
assert held.isdisjoint(outer["training_sequences"])
for fold in outer["inner_cv"]["folds"]:
model = fold["model"]
train = set(model["training_sequences"])
assert train.isdisjoint(held | set(fold["held_out_sequences"]))
index = model["feature_names"].index("sequence_signal")
assert model["mean"][index] == pytest.approx(np.mean([float(s) for s in train]))
totals = list(model["scaler_provenance"]["sequence_total_weights"].values())
assert max(totals) == pytest.approx(min(totals))
assert model["scaler_provenance"]["weight_sum"] == pytest.approx(
model["scaler_provenance"]["row_count"]
)
for decision in outer["oof_decisions"]:
assert held.isdisjoint(decision["fitted_sequences"])
artifact = fitted["selectors"][name]
group = data[:16]
assert (
select_v2([r["visible"] for r in group], [r["trajectory"] for r in group], artifact)
== 5
)
def test_zero_reward_forces_always_off_and_no_final_tuning():
data = rows(zero=True)
fitted = fit_v2(data, ["quality", "sequence_signal"], {})
for name, artifact in fitted["selectors"].items():
assert artifact["policy"] == "ALWAYS_OFF"
assert artifact["outer_nonpositive_forced_off"] is True
assert fitted["nested_cv_results"][name]["final_tuning"] is None
group = data[:16][::-1]
features = [r["visible"] for r in group]
assert select_v2(features, [r["trajectory"] for r in group], artifact) == 15
assert predict_v2(features, artifact) == [0.0] * 16
def test_no_validation_rows_and_no_inference_label_injection():
data = rows(zero=True)
bad = copy.deepcopy(data)
bad[0]["split"] = "validation"
with pytest.raises(ValueError, match="discovery"):
fit_v2(bad, ["quality", "sequence_signal"], {})
artifact = fit_v2(data, ["quality", "sequence_signal"], {})["selectors"]["CycleGate"]
features = [{**r["visible"], "target_J": r["J"]} for r in data[:16]]
with pytest.raises(ValueError, match="visible"):
predict_v2(features, artifact)
assert set(inspect.signature(select_v2).parameters) == {"features", "trajectories", "artifact"}
def test_off_never_competes_and_strict_threshold_and_ties():
prediction = [-1.0] * 16
prediction[0] = 100.0
prediction[2] = 0.001
prediction[1] = 0.001
assert _choice(prediction, TRAJECTORIES, 0.001) == 0
assert _choice(prediction, TRAJECTORIES, 0.0005) == 1
prediction[1] = 0.0009999999999
assert _choice(prediction, TRAJECTORIES, 0.0005) == 1
def test_weighted_reward_fit_pair_baseline_invariance():
data = rows()
changed = copy.deepcopy(data)
for row in changed:
row["J"] += 7 * float(row["sequence"]) + float(row["target_slot"])
first = _fit(data, ["quality", "sequence_signal"], 1.0)
second = _fit(changed, ["quality", "sequence_signal"], 1.0)
assert first["coefficients"] == pytest.approx(second["coefficients"], abs=1e-12)
assert first["mean"][1] == pytest.approx(1.0)
def test_tuning_tie_break_low_writes_then_threshold_then_regularization():
def c(reward, write, threshold, alpha):
return {
"score": {"net_delta_J": reward, "write_rate": write},
"threshold": threshold,
"alpha": alpha,
}
candidates = [
c(0.001, 0.5, 0.005, 100),
c(0.001 + 1e-13, 0.1, 0.0, 0.1),
c(0.001, 0.1, 0.002, 1),
c(0.001, 0.1, 0.002, 100),
]
assert _winner(candidates) is candidates[-1]
def test_nested_results_are_deterministic_and_json_serializable():
import json
data = rows()
first = fit_v2(data, ["quality", "sequence_signal"], {"seed": 20260926})
second = fit_v2(data, ["quality", "sequence_signal"], {"seed": 20260926})
assert json.dumps(first, sort_keys=True, allow_nan=False) == json.dumps(
second, sort_keys=True, allow_nan=False
)
assert first["selectors"]["GateOnly"]["feature_names"] == ["quality", "sequence_signal"]
assert first["selectors"]["CycleGate"]["feature_names"] == [
"quality",
"sequence_signal",
"f_cycle",
]