| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- #!/usr/bin/env python3
- """
- audit_review.py — List and group audit feedback by target file.
- Usage:
- python3 audit_review.py <wiki-root> [--open|--resolved|--all]
- Examples:
- python3 audit_review.py ~/wikis/ai-research --open
- python3 audit_review.py ~/wikis/ai-research --resolved
- python3 audit_review.py ~/wikis/ai-research --all
- Reads every file under `<wiki-root>/audit/` (open) and `<wiki-root>/audit/resolved/`
- (resolved), parses the YAML frontmatter, and prints a report grouped by target
- file. Use this at the start of an `audit` operation to decide processing order.
- Exit codes:
- 0 — done (always, regardless of audit count)
- """
- import os
- import re
- import sys
- from collections import defaultdict
- from pathlib import Path
- FRONTMATTER_RE = re.compile(r"^---\n(.*?)\n---\n", re.DOTALL)
- def parse_frontmatter(text: str) -> dict | None:
- m = FRONTMATTER_RE.match(text)
- if not m:
- return None
- body = m.group(1)
- result: dict = {}
- for line in body.split("\n"):
- if not line.strip() or line.lstrip().startswith("#"):
- continue
- if ":" not in line:
- continue
- key, _, rest = line.partition(":")
- key = key.strip()
- val = rest.strip()
- if val.startswith("[") and val.endswith("]"):
- inner = val[1:-1].strip()
- result[key] = [p.strip().strip('"').strip("'") for p in inner.split(",") if p.strip()]
- elif val.startswith('"') and val.endswith('"'):
- result[key] = val[1:-1].replace("\\n", "\n").replace('\\"', '"')
- elif val.startswith("'") and val.endswith("'"):
- result[key] = val[1:-1]
- else:
- result[key] = val
- return result
- def extract_comment_one_line(text: str) -> str:
- """Pull the first non-empty line of the # Comment section."""
- in_comment = False
- for line in text.splitlines():
- stripped = line.strip()
- if stripped.lower().startswith("# comment"):
- in_comment = True
- continue
- if not in_comment:
- continue
- if not stripped:
- continue
- if stripped.startswith("#"):
- break
- return stripped[:100]
- return "(no comment body)"
- SEVERITY_ORDER = {"error": 0, "warn": 1, "suggest": 2, "info": 3}
- def main(root: str, mode: str) -> int:
- root_path = Path(root)
- audit_dir = root_path / "audit"
- if not audit_dir.exists():
- print(f"ERROR: audit/ not found at {audit_dir}", file=sys.stderr)
- return 1
- files: list[Path] = []
- if mode in ("open", "all"):
- files.extend(sorted(p for p in audit_dir.glob("*.md") if p.name != ".gitkeep"))
- if mode in ("resolved", "all"):
- resolved = audit_dir / "resolved"
- if resolved.exists():
- files.extend(sorted(p for p in resolved.glob("*.md") if p.name != ".gitkeep"))
- if not files:
- print(f"No {mode} audit files found.")
- return 0
- grouped: dict[str, list[dict]] = defaultdict(list)
- for p in files:
- text = p.read_text(encoding="utf-8")
- fm = parse_frontmatter(text)
- if fm is None:
- print(f"⚠️ {p.relative_to(root_path)} — missing frontmatter", file=sys.stderr)
- continue
- fm["_path"] = str(p.relative_to(root_path))
- fm["_one_liner"] = extract_comment_one_line(text)
- grouped[fm.get("target", "(no-target)")].append(fm)
- total = sum(len(v) for v in grouped.values())
- print(f"{mode.upper()} audits: {total} across {len(grouped)} target files\n")
- for target in sorted(grouped.keys()):
- entries = grouped[target]
- entries.sort(key=lambda e: (
- SEVERITY_ORDER.get(e.get("severity", "info"), 99),
- e.get("created", ""),
- ))
- print(f"{target} ({len(entries)} {mode})")
- for e in entries:
- sev = e.get("severity", "?")
- aid = e.get("id", "?")
- author = e.get("author", "?")
- created = e.get("created", "?")[:10] # date only
- line = e.get("_one_liner", "")
- print(f" [{aid}] {sev}: {line} — {author}, {created}")
- print()
- return 0
- if __name__ == "__main__":
- if len(sys.argv) < 2:
- print(__doc__)
- sys.exit(1)
- root = sys.argv[1]
- mode = "open"
- for arg in sys.argv[2:]:
- if arg == "--open":
- mode = "open"
- elif arg == "--resolved":
- mode = "resolved"
- elif arg == "--all":
- mode = "all"
- else:
- print(f"Unknown flag: {arg}", file=sys.stderr)
- sys.exit(1)
- sys.exit(main(root, mode))
|