@@ -227,6 +227,100 @@ async def test_failure_report_redacts_environment_values_and_common_secret_forms
227227 assert "retryable=true" in report .error_message
228228
229229
230+ def test_failure_report_redacts_hyphenated_keys_and_bare_urls (tmp_path ):
231+ root = _copy_example (tmp_path )
232+ prepared = prepare_run (root / "pipeline.json" , run_id = "report_failure_hyphenated" )
233+ error = RuntimeError (
234+ "X-API-Key: hyphen-api-secret x-api-key=lower-hyphen-secret; "
235+ "endpoint https://private.example/v1?token=secret and http://10.0.0.8:8080/run"
236+ )
237+
238+ report = build_failure_report (
239+ prepared , progress = _progress (), error = error ,
240+ source_prompt_hashes = {}, existing_artifacts = [],
241+ generated_at = datetime (2026 , 7 , 18 , 0 , 1 , tzinfo = timezone .utc ),
242+ )
243+
244+ assert "hyphen-api-secret" not in report .error_message
245+ assert "lower-hyphen-secret" not in report .error_message
246+ assert "https://private.example/v1?token=secret" not in report .error_message
247+ assert "http://10.0.0.8:8080/run" not in report .error_message
248+ assert "endpoint [REDACTED]" in report .error_message
249+
250+
251+ @pytest .mark .asyncio
252+ @pytest .mark .parametrize (
253+ "token_usage" ,
254+ [
255+ {},
256+ {"prompt" : 1 , "completion" : 2 },
257+ {"prompt" : 1 , "completion" : "2" , "total" : 3 },
258+ {"prompt" : True , "completion" : 2 , "total" : 3 },
259+ {"prompt" : - 1 , "completion" : 2 , "total" : 1 },
260+ {"prompt" : 1 , "completion" : 2 , "total" : 4 },
261+ ["not" , "a" , "dict" ],
262+ ],
263+ )
264+ async def test_real_report_marks_malformed_token_usage_unavailable (tmp_path , token_usage ):
265+ root = _copy_example (tmp_path )
266+ prepared = prepare_run (root / "pipeline.json" , run_id = "report_real_bad_tokens" )
267+ fake_result = await run_fake_stage (prepared , scenario = "improve" )
268+ candidate = OptimizerCandidateProposal .model_validate ({
269+ ** fake_result .candidate .model_dump (exclude = {"scenario" , "seed" }), "provider" : "agent_optimizer" ,
270+ "optimizer_status" : "SUCCEEDED" , "finish_reason" : "completed" ,
271+ "baseline_pass_rate" : 1 / 3 , "best_pass_rate" : 1.0 ,
272+ "candidate_id" : f"optimizer-{ fake_result .candidate .candidate_id [- 12 :]} " ,
273+ })
274+ native = _optimize_result (
275+ await prepared .source_target .read_all (), candidate .prompts ,
276+ ).model_copy (update = {"total_token_usage" : token_usage })
277+ result = RealStageResult (
278+ ** fake_result .model_dump (exclude = {"scenario" , "candidate" }), candidate = candidate ,
279+ optimize_result = native ,
280+ )
281+
282+ report = build_optimization_report (
283+ prepared , result , progress = _progress (),
284+ finished_at = datetime (2026 , 7 , 18 , 0 , 1 , tzinfo = timezone .utc ),
285+ )
286+
287+ assert report .optimizer_resources .token_usage .status == "unavailable"
288+ assert report .optimizer_resources .token_usage .value is None
289+
290+
291+ @pytest .mark .asyncio
292+ async def test_real_report_allows_consistent_zero_token_usage_without_reflection_calls (tmp_path ):
293+ root = _copy_example (tmp_path )
294+ prepared = prepare_run (root / "pipeline.json" , run_id = "report_real_zero_tokens" )
295+ fake_result = await run_fake_stage (prepared , scenario = "improve" )
296+ candidate = OptimizerCandidateProposal .model_validate ({
297+ ** fake_result .candidate .model_dump (exclude = {"scenario" , "seed" }), "provider" : "agent_optimizer" ,
298+ "optimizer_status" : "SUCCEEDED" , "finish_reason" : "completed" ,
299+ "baseline_pass_rate" : 1 / 3 , "best_pass_rate" : 1.0 ,
300+ "candidate_id" : f"optimizer-{ fake_result .candidate .candidate_id [- 12 :]} " ,
301+ })
302+ native = _optimize_result (
303+ await prepared .source_target .read_all (), candidate .prompts ,
304+ ).model_copy (update = {
305+ "total_reflection_lm_calls" : 0 ,
306+ "total_token_usage" : {"prompt" : 0 , "completion" : 0 , "total" : 0 , "cached" : 7 },
307+ })
308+ result = RealStageResult (
309+ ** fake_result .model_dump (exclude = {"scenario" , "candidate" }), candidate = candidate ,
310+ optimize_result = native ,
311+ )
312+
313+ report = build_optimization_report (
314+ prepared , result , progress = _progress (),
315+ finished_at = datetime (2026 , 7 , 18 , 0 , 1 , tzinfo = timezone .utc ),
316+ )
317+
318+ assert report .optimizer_resources .token_usage .status == "available"
319+ assert report .optimizer_resources .token_usage .value == {
320+ "prompt" : 0 , "completion" : 0 , "total" : 0 , "cached" : 7 ,
321+ }
322+
323+
230324def test_report_dto_invariants_reject_inconsistent_artifact_states ():
231325 with pytest .raises (ValueError , match = "available artifacts require" ):
232326 ArtifactReference (
0 commit comments