@@ -366,3 +366,34 @@ def test_augmentation_cache_cannot_change_across_attempts(benchmark, tmp_path):
366366 path .write_bytes (b"changed" )
367367 with pytest .raises (CheckpointError , match = "augmentation cache" ):
368368 b .run (Session (b .model_dir ), n_aug_per_dataset = 3 , aug_cache_dir = str (aug_dir ))
369+
370+
371+ @pytest .mark .parametrize ("change" , ["reader" , "unapproved-evaluator" , "model" ])
372+ def test_audited_reader_upgrade_preserves_resume_guards (benchmark , monkeypatch , tmp_path , change ):
373+ b = benchmark
374+ original_fingerprint = common .fingerprint_files
375+ evaluator_root = Path (common .__file__ ).resolve ().parents [1 ]
376+ identity = ["old" ]
377+
378+ def fingerprint (paths , root ):
379+ return identity [0 ] if root == evaluator_root else original_fingerprint (paths , root )
380+
381+ monkeypatch .setattr (common , "fingerprint_files" , fingerprint )
382+ (tmp_path / "checkpoint_compatibility.json" ).write_text (json .dumps ({"new" : ["old" ]}))
383+ compatible = common .compatible_evaluator_identity
384+ monkeypatch .setattr (common , "compatible_evaluator_identity" , lambda root , current , previous : compatible (tmp_path , current , previous ))
385+ with pytest .raises (Interrupted ):
386+ b .run (Session (b .model_dir , stop_after = 2 ))
387+ identity [0 ] = "unapproved" if change == "unapproved-evaluator" else "new"
388+ if change == "model" :
389+ (b .model_dir / "model.py" ).write_text ("changed inference implementation" )
390+ resumed = Session (b .model_dir )
391+ if change != "reader" :
392+ with pytest .raises (CheckpointError , match = "differs" ):
393+ b .run (resumed )
394+ assert not resumed .calls
395+ else :
396+ b .run (resumed )
397+ assert len (resumed .calls ) == 3
398+ assert RecorderCheckpoint .read_manifest (b .checkpoint )["benchmark" ]["evaluator_sha256" ] == "old"
399+ assert not compatible (tmp_path , "new" , "unrelated-old" )
0 commit comments