sctm2-r5-code-20260611 / tests /test_step4_plugin_handoff.py
agoniii97's picture
Normalize datetime precision for HF P1 tensor build
ae6d94c verified
Raw
History Blame Contribute Delete
2.64 kB
"""Step 3 -> Step 4 architecture-plugin handoff safety.
Step 4 must instantiate the SAME architecture that produced the checkpoint. The
trained plugin id is recorded in the Step 3 manifest; Step 4 inherits it (or
verifies an explicit override). These tests pin that contract so a forgotten
``--model-plugin`` on a new-SCTM run cannot silently/loudly load IO weights into
the canonical skeleton.
"""
from __future__ import annotations
import json
import pytest
from sctm_next_round.checkpoint_manifest import load_step3_checkpoint_context, reconcile_model_plugin_id
def test_reconcile_inherits_trained_plugin_when_cli_default() -> None:
assert reconcile_model_plugin_id("canonical", "SCTM-IO-OU") == "SCTM-IO-OU"
assert reconcile_model_plugin_id(None, "SCTM-IO-OU") == "SCTM-IO-OU"
def test_reconcile_keeps_canonical_and_trusts_cli_on_legacy_manifest() -> None:
assert reconcile_model_plugin_id("canonical", "canonical") == "canonical"
assert reconcile_model_plugin_id("canonical", None) == "canonical"
assert reconcile_model_plugin_id("SCTM-IO", None) == "SCTM-IO" # legacy manifest w/o plugin -> trust CLI
def test_reconcile_accepts_alias_and_case_variants_of_same_architecture() -> None:
# same class via alias/case must NOT be treated as a conflict
assert reconcile_model_plugin_id("sctm-io-ou", "SCTM-IO-OU") == "sctm-io-ou"
assert reconcile_model_plugin_id("informative-observation-ou", "SCTM-IO-OU") == "informative-observation-ou"
def test_reconcile_raises_on_genuine_architecture_conflict() -> None:
with pytest.raises(ValueError):
reconcile_model_plugin_id("SCTM-IO", "SCTM-IO-OU") # different classes
with pytest.raises(ValueError):
reconcile_model_plugin_id("canonical-with-explicit", "SCTM-IO-OU") if False else None
reconcile_model_plugin_id("sctm", "SCTM-IO-OU") # canonical explicitly named vs IO checkpoint
def test_step3_manifest_plugin_id_round_trips_into_context(tmp_path) -> None:
step3 = tmp_path / "step3"
step3.mkdir()
(step3 / "selected.pt").write_bytes(b"\x00") # checkpoint file must exist for resolver
(step3 / "selected_checkpoint_manifest.json").write_text(
json.dumps({"selected_step": 8500, "selected_checkpoint_sha256": "deadbeef", "model_plugin_id": "SCTM-IO-OU"}),
encoding="utf-8",
)
ctx = load_step3_checkpoint_context(step3)
assert ctx.model_plugin_id == "SCTM-IO-OU"
assert ctx.selected_step == 8500
# the full Step-4 handoff: a default CLI inherits the trained plugin
assert reconcile_model_plugin_id("canonical", ctx.model_plugin_id) == "SCTM-IO-OU"