@@ -147,19 +147,44 @@ def configure_cpu_reexec_test_mode(settings: Any) -> Path:
147147
148148
149149def normalize_manifest_for_replication (manifest : dict [str , Any ]) -> dict [str , Any ]:
150- """Return a deep copy with volatile ``compute`` timing/memory fields fixed to a constant.
150+ """Return a deep copy with volatile host- timing fields fixed to a constant.
151151
152- Two honest CPU re-execs of the SAME submission differ ONLY in these host-timing fields; fixing
153- them makes the canonical manifest bytes (and thus :func:`compute_manifest_sha256`) identical,
154- which is what lets two independent worker replicas agree and be accepted (rather than disputed).
152+ Two honest CPU re-execs of the SAME submission differ in host timing: the
153+ classical ``compute`` wall/RSS fields plus (after telemetry-rt) per-step
154+ ``metrics.train_series.points[*].wall_s`` and the linked
155+ ``train_series_sha256`` digests. Fix timing so canonical manifest bytes
156+ (and thus :func:`compute_manifest_sha256`) match across replicas.
155157 """
156158
159+ from .train_series import train_series_sha256
160+
157161 normalized = copy .deepcopy (manifest )
158162 compute = normalized .get ("compute" )
159163 if isinstance (compute , dict ):
160164 for field in VOLATILE_COMPUTE_FIELDS :
161165 if field in compute :
162166 compute [field ] = 0
167+
168+ metrics = normalized .get ("metrics" )
169+ series_digest : str | None = None
170+ if isinstance (metrics , dict ):
171+ raw_series = metrics .get ("train_series" )
172+ if isinstance (raw_series , dict ):
173+ points = raw_series .get ("points" )
174+ if isinstance (points , list ):
175+ for point in points :
176+ if isinstance (point , dict ) and "wall_s" in point :
177+ point ["wall_s" ] = 0.0
178+ series_digest = train_series_sha256 (raw_series )
179+ if "train_series_sha256" in metrics :
180+ metrics ["train_series_sha256" ] = series_digest
181+ if "sha256" in raw_series :
182+ raw_series ["sha256" ] = series_digest
183+
184+ artifacts = normalized .get ("artifacts" )
185+ if isinstance (artifacts , dict ) and "train_series_sha256" in artifacts :
186+ artifacts ["train_series_sha256" ] = series_digest or ("0" * 64 )
187+
163188 return normalized
164189
165190
0 commit comments