70 lines
2.0 KiB
Python
70 lines
2.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Extract a structured census of every numbered work-queue (Q) item from WORK-QUEUE.md.
|
|
|
|
Output: TSV with columns Q | Title | Status | Target
|
|
"""
|
|
import re
|
|
import sys
|
|
|
|
SRC = "/root/troupe-standup/WORK-QUEUE.md"
|
|
|
|
HEADING_RE = re.compile(r"^## (Q([0-9]+)) — (.*)$")
|
|
STATUS_RE = re.compile(r"^\*\*Status:(.*)$")
|
|
TARGET_RE = re.compile(r"`(recoveries/[A-Za-z0-9._-]+\.md|docs/[A-Za-z0-9._-]+\.md|checkins/[A-Za-z0-9._-]+\.md)`")
|
|
|
|
|
|
def strip_note(title: str) -> str:
|
|
# "Title *(notes)*" -> "Title"
|
|
return re.sub(r"\s*\*.*$", "", title).strip()
|
|
|
|
|
|
def extract(path: str):
|
|
with open(path, encoding="utf-8") as fh:
|
|
lines = fh.read().splitlines()
|
|
|
|
rows = []
|
|
i = 0
|
|
n = len(lines)
|
|
while i < n:
|
|
m = HEADING_RE.match(lines[i])
|
|
if m:
|
|
q = m.group(2)
|
|
title = strip_note(m.group(3))
|
|
# scan up to 60 following lines for the status line
|
|
status = ""
|
|
target = ""
|
|
j = i + 1
|
|
while j < n:
|
|
line = lines[j]
|
|
sm = STATUS_RE.match(line)
|
|
if sm and not status:
|
|
status = sm.group(1).strip()
|
|
tm = TARGET_RE.search(line)
|
|
if tm and not target:
|
|
target = tm.group(1)
|
|
if status and target:
|
|
break
|
|
j += 1
|
|
if j < n and lines[j].startswith("## "):
|
|
break
|
|
rows.append((q, title, status, target))
|
|
i = j
|
|
continue
|
|
i += 1
|
|
return rows
|
|
|
|
|
|
def main():
|
|
rows = extract(SRC)
|
|
out = "/root/troupe-standup/wizard-work/ledger/2026-10-25-workqueue-census.tsv"
|
|
with open(out, "w", encoding="utf-8") as fh:
|
|
fh.write("Q\tTitle\tStatus\tTarget\n")
|
|
for q, title, status, target in rows:
|
|
fh.write(f"{q}\t{title}\t{status}\t{target}\n")
|
|
print(f"rows: {len(rows)}")
|
|
print(f"written: {out}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|