2020sys .path .insert (0 , os .path .dirname (os .path .abspath (__file__ )))
2121from ledger_lib import load_modules_config # noqa: E402
2222
23- CLASS_ICON = {'clean' : '✅' , 'warning' : '⚠️' , 'failure' : '❌' , 'none' : 'N/A' , 'blocked' : '⛔' }
23+ # Reporting is pass/fail only. Warnings are deliberate green-keepers (tolerated
24+ # metadata gaps, etc.) and count as pass; we do not surface the warning level.
25+ def is_pass (status_class ):
26+ return status_class in ('clean' , 'warning' )
27+
28+
29+ def class_icon (status_class ):
30+ if status_class == 'failure' :
31+ return '❌'
32+ if is_pass (status_class ):
33+ return '✅'
34+ if status_class == 'blocked' :
35+ return '⛔'
36+ return '?'
2437
2538
2639def utc_now ():
@@ -46,29 +59,35 @@ def unit_icon(entry):
4659 unit = entry .get ('unit' )
4760 if not unit :
4861 return '—'
49- return CLASS_ICON . get (unit .get ('class' ), '?' )
62+ return class_icon (unit .get ('class' ))
5063
5164
5265def acceptance_cell (entry ):
5366 if not entry .get ('acceptance_configured' ):
5467 return 'N/A'
5568 acceptance = entry .get ('acceptance' )
56- if not acceptance :
57- return '⏳ pending'
58- targets = acceptance .get ('targets' , {})
59- if not targets :
69+ if not acceptance or not acceptance .get ('targets' ):
6070 return '⏳ pending'
61- return ' ' .join (f"{ name } :{ CLASS_ICON .get (cls , '?' )} " for name , cls in sorted (targets .items ()))
71+ targets = acceptance ['targets' ]
72+ return ' ' .join (f"{ name } :{ class_icon (cls )} " for name , cls in sorted (targets .items ()))
6273
6374
64- def is_fully_compatible (entry ):
75+ def unit_passed (entry ):
6576 unit = entry .get ('unit' )
66- if not unit or unit .get ('class' ) != 'clean' :
77+ return bool (unit ) and is_pass (unit .get ('class' ))
78+
79+
80+ def acceptance_passed (entry ):
81+ acceptance = entry .get ('acceptance' )
82+ return bool (acceptance ) and bool (acceptance .get ('targets' )) and is_pass (acceptance .get ('class' ))
83+
84+
85+ def is_fully_compatible (entry ):
86+ if not unit_passed (entry ):
6787 return False
6888 if not entry .get ('acceptance_configured' ):
6989 return True # unit-only; N/A acceptance is full coverage
70- acceptance = entry .get ('acceptance' ) or {}
71- return acceptance .get ('class' ) == 'clean'
90+ return acceptance_passed (entry )
7291
7392
7493def last_tested (entry ):
@@ -103,13 +122,13 @@ def main():
103122 anomalies = {mid : e for mid , e in modules .items () if e .get ('disposition' ) == 'removed-without-disposition' }
104123
105124 unit_tested = [e for e in active .values () if e .get ('unit' )]
106- unit_clean = [e for e in unit_tested if e ['unit' ].get ('class' ) == 'clean' ]
107- unit_warning = [e for e in unit_tested if e ['unit' ].get ('class' ) == 'warning' ]
108- unit_failure = [e for e in unit_tested if e ['unit' ].get ('class' ) == 'failure' ]
125+ unit_pass = [e for e in unit_tested if unit_passed (e )]
126+ unit_fail = [e for e in unit_tested if not unit_passed (e )]
109127
110128 acceptance_configured = [e for e in active .values () if e .get ('acceptance_configured' )]
111- acceptance_run = [e for e in acceptance_configured if e .get ('acceptance' )]
112- acceptance_clean = [e for e in acceptance_run if e ['acceptance' ].get ('class' ) == 'clean' ]
129+ acceptance_run = [e for e in acceptance_configured if e .get ('acceptance' , {}).get ('targets' )]
130+ acceptance_pass = [e for e in acceptance_run if acceptance_passed (e )]
131+ acceptance_fail = [e for e in acceptance_run if not acceptance_passed (e )]
113132
114133 fully_compatible = [e for e in active .values () if is_fully_compatible (e )]
115134 never_tested = [e for e in active .values () if not e .get ('unit' )]
@@ -138,13 +157,13 @@ def main():
138157 lines .append ('|---|---|' )
139158 lines .append (f"| Active modules | { len (active )} |" )
140159 lines .append (f"| Unit-tested | { len (unit_tested )} |" )
141- lines .append (f"| • unit clean | { len (unit_clean )} |" )
142- lines .append (f"| • unit warning | { len (unit_warning )} |" )
143- lines .append (f"| • unit failure | { len (unit_failure )} |" )
160+ lines .append (f"| • unit pass | { len (unit_pass )} |" )
161+ lines .append (f"| • unit fail | { len (unit_fail )} |" )
144162 lines .append (f"| Acceptance-configured | { len (acceptance_configured )} |" )
145163 lines .append (f"| • acceptance run | { len (acceptance_run )} |" )
146- lines .append (f"| • acceptance clean | { len (acceptance_clean )} |" )
147- lines .append (f"| **Fully compatible** (unit + acceptance/N/A all green) | **{ len (fully_compatible )} ** |" )
164+ lines .append (f"| • acceptance pass | { len (acceptance_pass )} |" )
165+ lines .append (f"| • acceptance fail | { len (acceptance_fail )} |" )
166+ lines .append (f"| **Fully compatible** (unit + acceptance/N/A all pass) | **{ len (fully_compatible )} ** |" )
148167 lines .append (f"| Never tested | { len (never_tested )} |" )
149168 lines .append (f"| Stale (> { stale_days } d) | { len (stale )} |" )
150169 lines .append (f"| Retired (incompatible / deprecated) | { len (retired )} |" )
0 commit comments