diff --git a/docs/milestones.md b/docs/milestones.md index 8e7cc8a72..f074bf4e8 100644 --- a/docs/milestones.md +++ b/docs/milestones.md @@ -69,7 +69,10 @@ it passes through, and how the freeze is performed all belong to [process-version.md](process-version.md#freezing-the-cutover-procedure); **record the resulting commit here when it happens.** -- Freeze commit: _not yet frozen — the shakedown is ongoing._ +- Freeze commit: `8bf09ed2bd1ee42e4475cc616536ebab6b1d5a4b` — the six proc-v1 + digests (three predictors, three evaluators) blessed into + `FROZEN_PROCESS_DIGESTS`. The freeze takes effect on `main` at the promotion + that carries this commit. ## The near-term target: the OT2026 long-conference cert release diff --git a/src/fedcourtsai/process_version.py b/src/fedcourtsai/process_version.py index d427f39af..eff16e1c7 100644 --- a/src/fedcourtsai/process_version.py +++ b/src/fedcourtsai/process_version.py @@ -38,12 +38,24 @@ # named process change; the digest moves on *any* input change regardless. CURRENT_PROCESS_LABEL = "proc-v1" -# The blessed process digests — the frozen-headline set. EMPTY during the -# shakedown: the freeze is a future one-line commit that pastes the digest(s) -# from `fedcourts process-digest --all` in here. Keyed on the digest, never the -# label, so a process that drifted under an unchanged label is not silently -# blessed. -FROZEN_PROCESS_DIGESTS: frozenset[str] = frozenset() +# The blessed process digests — the frozen-headline set: the six proc-v1 +# processes (three predictors, three evaluators) read off +# `fedcourts process-digest --all` at the freeze. Keyed on the digest, never +# the label, so a process that drifts under an unchanged label is not silently +# blessed; a material change bumps CURRENT_PROCESS_LABEL and earns a fresh +# blessing here. +FROZEN_PROCESS_DIGESTS: frozenset[str] = frozenset( + { + # predictors: claude-baseline, codex-baseline, gemini-baseline + "sha256:460abab2fe175059ca588fd1f72cefb15fb3beaab2e2ec4732f8c42c7c6c66a7", + "sha256:940cd32d118bb174faed45cbcc2e8eeb18161b2c24c4c81fac85a56c686f205e", + "sha256:526b83dcd18ee0d1a4ee026f4f5f20ee115bdf546a1360a58828481951442494", + # evaluators: claude-judge, codex-judge, gemini-judge + "sha256:42a33a2d79f7ebccf79e6a00ae233b241314e863f60616562fc46063f98a3427", + "sha256:0cee3de6951543bb302104aa44260a5f066d23523951e9610b8b0efc43f84d95", + "sha256:3c0d725159f8dc4c4a58c384da9497bb44f1948e9d043b55b5e2e1345e82dc2a", + } +) # The retrieval surface each engine's cells run with. Folded into the digest # because it is a process input as much as the model or the prompt: a cell that diff --git a/tests/test_process_version.py b/tests/test_process_version.py index 99924cba2..b24bfb7be 100644 --- a/tests/test_process_version.py +++ b/tests/test_process_version.py @@ -18,7 +18,7 @@ from fedcourtsai import process_version from fedcourtsai.process_version import _config_canonical -from fedcourtsai.registry import load_predictors +from fedcourtsai.registry import enabled_evaluators, enabled_predictors, load_predictors from fedcourtsai.schemas import ProcessVersion CONFIG = Path("config") @@ -129,7 +129,20 @@ def test_is_frozen_gates_on_the_digest_not_the_label(monkeypatch) -> None: # ty assert not process_version.is_frozen(None) -def test_the_frozen_set_is_empty_until_the_freeze_commit() -> None: - """The shakedown state: nothing is blessed yet, so nothing is frozen.""" - assert frozenset() == process_version.FROZEN_PROCESS_DIGESTS +def test_the_frozen_set_blesses_exactly_the_registry_digests() -> None: + """The frozen set holds one digest per registered process — the six + proc-v1 processes blessed at the freeze — and every entry actually + resolves against the current registry, so a prompt or config drift after + the freeze shows up here as a digest that no longer matches.""" + assert len(process_version.FROZEN_PROCESS_DIGESTS) == 6 + assert all(d.startswith("sha256:") for d in process_version.FROZEN_PROCESS_DIGESTS) + repo_root = Path(__file__).resolve().parent.parent + config_root = repo_root / "config" + rows = [("predictor", p.id) for p in enabled_predictors(config_root / "predictors.yaml")] + rows += [("evaluator", e.id) for e in enabled_evaluators(config_root / "evaluators.yaml")] + current = { + process_version.digest_for_actor(repo_root, config_root, role, actor_id) + for role, actor_id in rows + } + assert current == set(process_version.FROZEN_PROCESS_DIGESTS) assert not process_version.is_frozen(_pv("sha256:anything"))