81 lines
3.1 KiB
Python
81 lines
3.1 KiB
Python
from __future__ import annotations
|
|
|
|
import pathlib
|
|
import re
|
|
import shlex
|
|
import subprocess
|
|
|
|
ROOT = pathlib.Path(__file__).resolve().parents[5]
|
|
LANES = ROOT / "docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/lanes"
|
|
FINDING = re.compile(r"^###\s+(L[1-4]-F\d{2})\b")
|
|
commands: dict[str, list[tuple[pathlib.Path, int, str]]] = {}
|
|
inventory: list[tuple[str, str]] = []
|
|
|
|
for lane in sorted(LANES.glob("lane-0[1-4]-*.md")):
|
|
current = None
|
|
for line_number, raw in enumerate(lane.read_text(encoding="utf-8").splitlines(), 1):
|
|
match = FINDING.match(raw)
|
|
if match:
|
|
current = match.group(1)
|
|
commands.setdefault(current, [])
|
|
continue
|
|
row = re.match(r"^\| (?:\x60)?(raw/branch-notes/[^\x60|]+\.md)(?:\x60)? \| (READ_FULL|NOT_READ|BLOCKED) \|", raw)
|
|
if row:
|
|
inventory.append((row.group(1), row.group(2)))
|
|
candidate = raw.strip()
|
|
if candidate.startswith("$ "):
|
|
candidate = candidate[2:]
|
|
if current and candidate.startswith(("grep ", "sed ")):
|
|
commands[current].append((lane, line_number, candidate))
|
|
|
|
expected = (
|
|
[f"L1-F{i:02d}" for i in range(1, 15)]
|
|
+ [f"L2-F{i:02d}" for i in range(1, 10)]
|
|
+ [f"L3-F{i:02d}" for i in range(1, 17)]
|
|
+ [f"L4-F{i:02d}" for i in range(1, 22)]
|
|
)
|
|
passed = 0
|
|
verified_output_lines = 0
|
|
failures = []
|
|
no_commands = []
|
|
|
|
for finding_id in expected:
|
|
if not commands.get(finding_id):
|
|
no_commands.append(finding_id)
|
|
continue
|
|
for lane, line_number, command in commands[finding_id]:
|
|
try:
|
|
argv = shlex.split(command)
|
|
except ValueError as exc:
|
|
failures.append(f"{finding_id}:{lane.name}:{line_number}:parse:{exc}")
|
|
continue
|
|
if not argv or argv[0] not in {"grep", "sed"}:
|
|
failures.append(f"{finding_id}:{lane.name}:{line_number}:unsafe")
|
|
continue
|
|
paths = []
|
|
for token in argv[1:]:
|
|
if token.endswith(".md"):
|
|
path = pathlib.Path(token)
|
|
paths.append((path if path.is_absolute() else ROOT / path).resolve())
|
|
if not paths or any(ROOT not in path.parents for path in paths):
|
|
failures.append(f"{finding_id}:{lane.name}:{line_number}:path")
|
|
continue
|
|
result = subprocess.run(argv, cwd=ROOT, text=True, capture_output=True)
|
|
if result.returncode != 0 or not result.stdout.strip():
|
|
failures.append(f"{finding_id}:{lane.name}:{line_number}:exit={result.returncode}")
|
|
continue
|
|
passed += 1
|
|
verified_output_lines += len([line for line in result.stdout.splitlines() if line.strip()])
|
|
|
|
print(f"inventory_rows={len(inventory)}")
|
|
print(f"inventory_unique={len(set(path for path, _ in inventory))}")
|
|
print(f"read_full={sum(status == 'READ_FULL' for _, status in inventory)}")
|
|
print(f"finding_ids={len(commands)}")
|
|
print(f"expected_finding_ids={len(expected)}")
|
|
print(f"commands_passed={passed}")
|
|
print(f"commands_failed={len(failures)}")
|
|
print(f"verified_output_lines={verified_output_lines}")
|
|
print(f"findings_without_commands={len(no_commands)}")
|
|
if failures:
|
|
print("failures=" + " || ".join(failures))
|