import json d = json.load(open('/tmp/mofin_health.json')) print("generated_at:", d.get('generated_at')) print() # 1. Pipelines with error/warn status print("=== PIPELINES (error/warn) ===") for p in d.get('pipelines', []): if p.get('status') in ('error', 'fail', 'warn'): print(f"[{p['status']}] {p.get('name') or p.get('script')} | profile={p.get('profile')} | type={p.get('type')} | schedule={p.get('schedule')} | last_run={p.get('last_run')}") print() print("=== FEATURE TREE (non-ok nodes) ===") def walk(n, path=''): label = n.get('label', '?') p = f"{path}/{label}" if n.get('status') not in ('ok', None): print(f"[{n.get('status')}] {p}") for pipe in n.get('pipes', []): if pipe.get('status') != 'ok': print(f" pipe: [{pipe.get('status')}] {pipe.get('name') or pipe.get('script')} | last_run={pipe.get('last_run')}") for c in n.get('children', []): walk(c, p) walk(d.get('feature_tree', {})) print() print("=== DATA ENTITIES (orphan/write_only) ===") for e in d.get('entities', []): if e.get('flow_status') in ('orphan', 'write_only'): print(f"[{e['flow_status']}] {e['name']} | rows={e.get('rows')} | writers={e.get('writers')} | readers={e.get('readers')} | {e.get('desc','')[:60]}") print() print("=== ARCHITECTURE violations ===") arch = d.get('architecture', {}) print("violation_count:", arch.get('violation_count')) for v in (arch.get('price_api_violations') or [])[:10]: print(f" {v.get('script')} L{v.get('line')}") print() print("=== JSON files with warn ===") for j in d.get('json_files', []): if j.get('warn'): print(f"[warn] {j['name']} | {j.get('desc','')[:60]} | readers={j.get('readers')}")