#!/usr/bin/env python3 """Regenerate code-reviews/README.md from the per-library findings.md files. The findings files are the source of truth; README.md is a generated index. Run this after recording, resolving, or re-triaging a finding so the aggregated tables stay in sync (see REVIEW-PROCESS.md section 5). Usage: python3 regen-readme.py # rewrite README.md python3 regen-readme.py --check # exit 1 if README.md is stale (for CI) Works from any directory — paths are resolved relative to this script. """ import os import re import sys BASE = os.path.dirname(os.path.abspath(__file__)) SEVERITY_ORDER = {"Critical": 0, "High": 1, "Medium": 2, "Low": 3} PENDING_STATUSES = {"Open", "In Progress"} NOT_REVIEWED = "—" # rendered for libraries with no recorded review date/commit yet def discover_libraries(): """Library folders are every subdirectory of code-reviews/ holding a findings.md, excluding the _template folder. Returned sorted for a stable README order.""" libraries = [] for name in sorted(os.listdir(BASE)): if name.startswith(("_", ".")): continue if os.path.isfile(os.path.join(BASE, name, "findings.md")): libraries.append(name) return libraries def parse_header(library, text): """Extract (last_reviewed, commit) from the library's header table. Returns None for either field when it is absent or still templated, so the README can render a 'not yet reviewed' dash instead of a fake baseline.""" last = re.search(r"\|\s*Last reviewed\s*\|\s*([0-9]{4}-[0-9]{2}-[0-9]{2})", text) commit = re.search(r"\|\s*Commit reviewed\s*\|\s*`([^`<]+)`", text) return ( last.group(1) if last else None, commit.group(1) if commit else None, ) def parse_findings(library): """Parse one library's findings.md into ((last_reviewed, commit), [(library, id, severity, title, status), ...]).""" text = open(os.path.join(BASE, library, "findings.md")).read() header = parse_header(library, text) findings = [] for block in re.split(r"^### ", text, flags=re.M)[1:]: head = block.splitlines()[0].strip() m = re.match(r"([A-Za-z][A-Za-z0-9]*-\d+)\b(.*)", head) if not m: raise SystemExit(f"{library}/findings.md: unparseable finding heading: {head!r}") fid = m.group(1).strip() title = m.group(2).strip().lstrip("—–-").strip().replace("|", "\\|") sev = re.search(r"\|\s*Severity\s*\|\s*([A-Za-z]+)", block) status = re.search(r"\|\s*Status\s*\|\s*([A-Za-z' ]+?)\s*\|", block) if not sev or not status: raise SystemExit(f"{library}/findings.md: {fid} is missing a Severity or Status field") findings.append((library, fid, sev.group(1), title, status.group(1).strip())) return header, findings def finding_number(finding): return int(re.search(r"-(\d+)$", finding[1]).group(1)) def build_readme(libraries, per_library): pending = sorted( (f for fs in per_library.values() for f in fs[1] if f[4] in PENDING_STATUSES), key=lambda f: (SEVERITY_ORDER.get(f[2], 9), f[0], finding_number(f)), ) reviewed = sum(1 for lib in libraries if per_library[lib][0][0] is not None) def severity_total(sev): return sum(1 for f in pending if f[2] == sev) def open_count(library, sev): return sum(1 for f in per_library[library][1] if f[2] == sev and f[4] in PENDING_STATUSES) lines = [] add = lines.append add("# Code Reviews") add("") add("Comprehensive, per-library code reviews of the `ZB.MOM.WW.*` shared libraries hosted") add("in this repo. Each library (one self-contained `.slnx` at the repo root) has its own") add("folder containing a `findings.md`. This README is the aggregated index — the single") add("place to see all outstanding work.") add("") add("> Generated by `regen-readme.py` from the per-library `findings.md` files. Do not") add("> edit by hand — edit the findings files and re-run the script.") add("") add("## How it works") add("") add("- Reviews are performed one library at a time against a fixed checklist.") add("- Each library is reviewed against its normalized component spec under `components/`.") add("- Every finding is recorded in the library's `findings.md` with a severity and status.") add("- Findings are **never deleted** — they are closed by changing their status, keeping") add(" a full audit trail.") add("- This README aggregates every **pending** finding (`Open` / `In Progress`) across all") add(" libraries.") add("") add("See **[REVIEW-PROCESS.md](REVIEW-PROCESS.md)** for the full procedure: the review") add("checklist, severity definitions, finding format, the library → component-spec mapping,") add("and how to mark items resolved.") add("") add("## Layout") add("") add("```") add("code-reviews/") add("├── README.md # this file — process overview + pending findings") add("├── REVIEW-PROCESS.md # how to perform a review and track findings") add("├── regen-readme.py # regenerates this README from the findings files") add("├── _template/findings.md # copy-this template for a library review") add("└── /findings.md # one folder per ZB.MOM.WW.* shared library") add("```") add("") add("## Summary") add("") add(f"{reviewed} of {len(libraries)} libraries reviewed. " f"{len(pending)} pending finding{'s' if len(pending) != 1 else ''} across all libraries.") add("") add("| Severity | Open findings |") add("|----------|---------------|") for sev in ("Critical", "High", "Medium", "Low"): add(f"| {sev} | {severity_total(sev)} |") add(f"| **Total** | **{len(pending)}** |") add("") add("## Library Status") add("") add("| Library | Last reviewed | Commit | Open (C/H/M/L) | Open | Total |") add("|---------|---------------|--------|----------------|------|-------|") for library in libraries: counts = [open_count(library, s) for s in ("Critical", "High", "Medium", "Low")] last_reviewed, commit = per_library[library][0] last_cell = last_reviewed if last_reviewed else NOT_REVIEWED commit_cell = f"`{commit}`" if commit else NOT_REVIEWED add(f"| [{library}]({library}/findings.md) | {last_cell} | {commit_cell} " f"| {counts[0]}/{counts[1]}/{counts[2]}/{counts[3]} " f"| {sum(counts)} | {len(per_library[library][1])} |") add("") add("## Pending Findings") add("") add("Every `Open` / `In Progress` finding across all libraries, highest severity first.") add("Resolved findings drop off this list but remain recorded in their library's") add("`findings.md` (see [REVIEW-PROCESS.md](REVIEW-PROCESS.md) §4–§5). Full detail —") add("description, location, recommendation — lives in the library's `findings.md`.") add("") for sev in ("Critical", "High", "Medium", "Low"): rows = [f for f in pending if f[2] == sev] add(f"### {sev} ({len(rows)})") add("") if not rows: add("_None open._") add("") continue add("| ID | Library | Title |") add("|----|---------|-------|") for library, fid, _, title, _ in rows: add(f"| {fid} | [{library}]({library}/findings.md) | {title} |") add("") return "\n".join(lines) def main(): check = "--check" in sys.argv[1:] libraries = discover_libraries() per_library = {m: parse_findings(m) for m in libraries} content = build_readme(libraries, per_library) readme_path = os.path.join(BASE, "README.md") pending = sum(1 for fs in per_library.values() for f in fs[1] if f[4] in PENDING_STATUSES) total = sum(len(fs[1]) for fs in per_library.values()) if check: current = open(readme_path).read() if os.path.exists(readme_path) else "" if current != content: print("README.md is stale — run: python3 code-reviews/regen-readme.py") sys.exit(1) print(f"README.md is up to date ({pending} pending / {total} total).") return open(readme_path, "w").write(content) print(f"README.md regenerated — {pending} pending, {total} total findings " f"across {len(libraries)} libraries.") if __name__ == "__main__": main()