11from tests .unit .fixtures .calibration_package_stage_contract import (
2+ TARGET_CONFIG_SHA256 ,
23 TARGET_CONFIG_PATH ,
34 calibration_package_contract ,
45 calibration_package_parameters ,
@@ -60,7 +61,7 @@ def test_calibration_package_parameters_parse_runtime_args():
6061 workers = 8 ,
6162 n_clones = 430 ,
6263 target_config_path = TARGET_CONFIG_PATH ,
63- target_config_sha256 = "sha256:target-config" ,
64+ target_config_sha256 = TARGET_CONFIG_SHA256 ,
6465 target_config_mode = "explicit" ,
6566 skip_county = True ,
6667 skip_source_impute = True ,
@@ -82,7 +83,7 @@ def test_calibration_package_parameters_parse_runtime_args():
8283 "skip_takeup_rerandomize" : False ,
8384 "target_config" : TARGET_CONFIG_PATH ,
8485 "target_config_mode" : "explicit" ,
85- "target_config_sha256" : "sha256:target-config" ,
86+ "target_config_sha256" : TARGET_CONFIG_SHA256 ,
8687 "workers" : None ,
8788 }
8889
@@ -109,6 +110,28 @@ def test_calibration_package_parameters_require_identity_for_config_modes():
109110 raise AssertionError ("Explicit target config mode should require checksum" )
110111
111112
113+ def test_calibration_package_parameters_reject_malformed_target_config_checksum ():
114+ try :
115+ CalibrationPackageParameters .from_runtime_args (
116+ workers = 8 ,
117+ n_clones = 430 ,
118+ target_config_path = TARGET_CONFIG_PATH ,
119+ target_config_sha256 = "sha256:target-config" ,
120+ target_config_mode = "explicit" ,
121+ skip_county = True ,
122+ skip_source_impute = True ,
123+ skip_takeup_rerandomize = False ,
124+ chunked_matrix = False ,
125+ chunk_size = 25_000 ,
126+ parallel = False ,
127+ num_matrix_workers = 50 ,
128+ )
129+ except ValueError as exc :
130+ assert "SHA-256 digest" in str (exc )
131+ else :
132+ raise AssertionError ("Malformed target config checksum should fail" )
133+
134+
112135def test_calibration_package_parameters_accept_legacy_identity_fields_missing ():
113136 params = CalibrationPackageParameters .from_dict (
114137 {
@@ -130,6 +153,31 @@ def test_calibration_package_parameters_accept_legacy_identity_fields_missing():
130153 assert params .target_config_sha256 is None
131154
132155
156+ def test_calibration_package_contract_revalidates_backfilled_identity (tmp_path ):
157+ dataset_path , db_path , package_path = contract_input_paths (tmp_path )
158+ package = calibration_package_payload ()
159+ package ["metadata" ].pop ("target_config_sha256" )
160+ write_calibration_package_payload (package_path , package )
161+ parameters = calibration_package_parameters ()
162+ parameters .pop ("target_config_mode" )
163+ parameters .pop ("target_config_sha256" )
164+
165+ try :
166+ build_calibration_package_contract (
167+ package_path = package_path ,
168+ dataset_path = dataset_path ,
169+ db_path = db_path ,
170+ package = package ,
171+ parameters = parameters ,
172+ run_id = "run-a" ,
173+ completed_at = "2026-05-08T12:02:00Z" ,
174+ )
175+ except ValueError as exc :
176+ assert "target_config and target_config_sha256" in str (exc )
177+ else :
178+ raise AssertionError ("Backfilled target config identity should be revalidated" )
179+
180+
133181def test_calibration_package_parameters_reject_inconsistent_chunk_shape ():
134182 try :
135183 CalibrationPackageParameters (
@@ -252,7 +300,7 @@ def test_calibration_package_contract_records_matrix_summary(tmp_path):
252300 assert summary ["matrix_density" ] == 0.5
253301 assert summary ["n_targets" ] == 2
254302 assert summary ["target_name_count" ] == 2
255- assert summary ["target_config_sha256" ] == "sha256:target-config"
303+ assert summary ["target_config_sha256" ] == TARGET_CONFIG_SHA256
256304 assert summary ["n_clones" ] == 3
257305 assert summary ["seed" ] == 42
258306 assert summary ["matrix_builder" ] == "chunked"
0 commit comments