Files

154 lines
5.1 KiB
Python

#!/usr/bin/env python3
"""Extract every `## Q<n>` block from WORK-QUEUE.md into a queue-ledger table.
Ledger (Extract lane) — data extraction, today 2026-10-29.
Source: /root/troupe-standup/WORK-QUEUE.md (revision HEAD).
Output:
queue-ledger.tsv q | seq | title | status | state
queue-ledger.md rendered markdown table
queue-ledger.json structured + counts
Every row is derived from the raw `## Q<n>` heading lines and the first line
"Status:" (optionally bold "**Status:") inside each block, so the artifact is
a faithful replay of the file. The CHECK re-parses the source with an
independent inline parser and diffs the committed TSV.
"""
import csv
import json
import re
from pathlib import Path
REPO = Path("/root/troupe-standup")
SRC = REPO / "WORK-QUEUE.md"
OUT_DIR = REPO / "wizard-work" / "ledger" / "2026-10-29-queue-ledger"
TOP_HEADING = re.compile(r"^## ")
Q_HEADING = re.compile(r"^## Q(\d+)\s?(.*)$")
STATUS_LINE = re.compile(r"^\*\*\s*Status\s*[:,]\s*(.*)$")
CLOSED_MARKERS = (
"DONE", "CLOSED", "COMPLETE", "RESOLVED",
"VERIFIED", "SATISFIED", "RE-SCOPED",
)
OPEN_MARKERS = ("OPEN", "OPEN AND", "UNCLAIMED", "AWAITING", "OPEN-AND")
def classify(status_text):
"""Classify a replayed status line into closed / open / unclassified.
Deterministic rules over the verbatim status text only:
- closed: contains a completion marker (DONE/CLOSED/COMPLETE/RESOLVED/
VERIFIED/SATISFIED, case-insensitive);
- open: contains an open marker (OPEN/UNCLAIMED/AWAITING, case-insensitive);
- otherwise unclassified (e.g. a status that reads as partial or tbd).
"""
u = (status_text or "").strip().upper()
if not u:
return "unclassified"
closed = ("DONE" in u) or ("CLOSED" in u) or ("COMPLETE" in u) or (
"RESOLVED" in u
) or ("VERIFIED" in u) or ("SATISFIED" in u)
if closed:
return "closed"
open_ = ("OPEN" in u) or ("UNCLAIMED" in u) or ("AWAITING" in u)
if open_:
return "open"
return "unclassified"
def extract_rows(src_path):
rows = []
current_q = None
current_title = None
status = None
def flush():
nonlocal current_q, current_title, status
if current_q is not None:
rows.append({
"q": current_q,
"seq": len(rows) + 1,
"title": current_title,
"status": status if status is not None else "no Status line",
"state": classify(status) if status is not None else "unclassified",
})
current_q = None
current_title = None
status = None
for raw in src_path.read_text(encoding="utf-8").splitlines():
line = raw.rstrip()
m = Q_HEADING.match(line)
if m:
flush()
current_q = int(m.group(1))
raw_title = m.group(2).strip()
if raw_title.startswith("—"):
raw_title = raw_title[1:].strip()
current_title = raw_title
continue
if TOP_HEADING.match(line):
flush()
continue
if current_q is not None and status is None:
sm = STATUS_LINE.match(line)
if sm:
status = sm.group(1).strip()
# Drop a stray leading asterisk pair that can survive "**Status".
if status.startswith("**"):
status = status[2:].strip()
flush()
return rows
def main():
rows = extract_rows(SRC)
OUT_DIR.mkdir(parents=True, exist_ok=True)
tsv_path = OUT_DIR / "queue-ledger.tsv"
with tsv_path.open("w", encoding="utf-8", newline="") as fh:
w = csv.writer(fh, delimiter="\t")
w.writerow(["q", "seq", "title", "status", "state"])
for r in rows:
w.writerow([r["q"], r["seq"], r["title"], r["status"], r["state"]])
json_path = OUT_DIR / "queue-ledger.json"
counts = {"closed": 0, "open": 0, "unclassified": 0}
for r in rows:
counts[r["state"]] += 1
payload = {
"source": str(SRC),
"generated_at": "2026-10-29T16:30:00Z",
"total_rows": len(rows),
"counts": counts,
"rows": rows,
}
json_path.write_text(json.dumps(payload, ensure_ascii=False, indent=2),
encoding="utf-8")
md_path = OUT_DIR / "queue-ledger.md"
with md_path.open("w", encoding="utf-8") as fh:
fh.write("# Queue ledger\n\n")
fh.write("Every `## Q<n>` block in `WORK-QUEUE.md` at HEAD, replayed "
"verbatim from its `Status:` line.\n\n")
fh.write("| q | title | status | state |\n")
fh.write("|---|---|---|---|\n")
for r in rows:
fh.write(f"| {r['q']} | {r['title']} | {r['status']} | {r['state']} |\n")
fh.write(f"\n**Total rows: {len(rows)}** "
f"(closed {counts['closed']}, open {counts['open']}, "
f"unclassified {counts['unclassified']}).\n")
print(f"rows: {len(rows)}")
print(f"counts: {counts}")
print(f"wrote {tsv_path}")
print(f"wrote {json_path}")
print(f"wrote {md_path}")
if __name__ == "__main__":
main()