@@ -394,3 +394,58 @@ def test_full_run_empty_results(self, aggregator):
394394 verdict = aggregator .run ([])
395395 assert verdict .status == VerdictStatus .PASS
396396 assert verdict .confidence == 0.0
397+
398+ def test_verdict_json_serialization_never_none (self , aggregator ):
399+ """Regression test: verdict.json must always have a valid status string,
400+ never None. See: fix/verdict-json-none."""
401+ import json
402+
403+ # Test all verdict paths
404+ test_cases = [
405+ ([], VerdictStatus .PASS ), # empty → PASS
406+ ([make_critic_result ("c" , [make_finding (severity = Severity .INFO )])],
407+ VerdictStatus .PASS_WITH_NOTES ),
408+ ([make_critic_result ("c" , [make_finding (severity = Severity .HIGH )])],
409+ VerdictStatus .REVISE ),
410+ ([make_critic_result ("c" , [make_finding (severity = Severity .CRITICAL )])],
411+ VerdictStatus .REJECT ),
412+ ]
413+
414+ valid_statuses = {s .value for s in VerdictStatus }
415+
416+ for critic_results , expected_status in test_cases :
417+ verdict = aggregator .run (critic_results )
418+
419+ # Verify the object
420+ assert verdict .status == expected_status
421+ assert verdict .status is not None
422+
423+ # Verify serialization (what gets written to verdict.json)
424+ dumped = verdict .model_dump ()
425+ assert dumped ["status" ] is not None , f"verdict.json status is None for { expected_status } "
426+ assert dumped ["status" ] in valid_statuses , f"verdict.json status '{ dumped ['status' ]} ' not in { valid_statuses } "
427+
428+ # Verify round-trip through JSON (what gets read back)
429+ json_str = json .dumps (dumped )
430+ loaded = json .loads (json_str )
431+ assert loaded ["status" ] is not None
432+ assert loaded ["status" ] in valid_statuses
433+
434+ def test_verdict_fallback_serialization (self , aggregator ):
435+ """Regression test: even the aggregator-crash fallback path must serialize
436+ a valid status, never None."""
437+ import json
438+
439+ fallback = Verdict (
440+ status = VerdictStatus .REJECT ,
441+ reasoning = "Aggregator failed: test" ,
442+ confidence = 0.0 ,
443+ report = None ,
444+ )
445+ dumped = fallback .model_dump ()
446+ assert dumped ["status" ] == "REJECT"
447+ assert dumped ["status" ] is not None
448+
449+ json_str = json .dumps (dumped )
450+ loaded = json .loads (json_str )
451+ assert loaded ["status" ] == "REJECT"
0 commit comments