Skip to content

Commit 6dc1fc0

Browse files
committed
feat(verify): add score --format md (markdown table output)
Emit a GitHub-flavored markdown table (Category | Total | Green | Yellow | Red | Green %) mirroring the TechEngineBot validation-stats style, for readable PR comments instead of a code-block histogram. Refs #1
1 parent a78697e commit 6dc1fc0

1 file changed

Lines changed: 43 additions & 1 deletion

File tree

app/verify/cli.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,10 @@ def cmd_score(args: argparse.Namespace) -> int:
111111
if write_cache:
112112
ledger.replace_all(entries, SCORES_PATH)
113113

114-
_print_histogram(hist, scored, hard_flags, wrote_cache=write_cache)
114+
if getattr(args, "format", "text") == "md":
115+
_print_markdown(hist, scored, hard_flags)
116+
else:
117+
_print_histogram(hist, scored, hard_flags, wrote_cache=write_cache)
115118
return 0
116119

117120

@@ -146,6 +149,43 @@ def _print_histogram(hist, scored, hard_flags, wrote_cache) -> None:
146149
print("\ncache: wrote full Tier 0 scores to data/_verify/state/scores.jsonl")
147150

148151

152+
def _print_markdown(hist, scored, hard_flags) -> None:
153+
"""GitHub-flavored markdown table — readable in PR comments (mirrors the
154+
TechEngineBot validation-stats style)."""
155+
if scored == 0:
156+
print("_No records scored._")
157+
return
158+
totals = Counter()
159+
rows = []
160+
for cat in CATEGORIES:
161+
if cat not in hist:
162+
continue
163+
c = hist[cat]
164+
tot = sum(c.values())
165+
totals.update(c)
166+
gpct = 100 * c["green"] / tot if tot else 0.0
167+
rows.append(
168+
f"| {cat} | {tot} | {c['green']} | {c['yellow']} | {c['red']} | {gpct:.1f}% |"
169+
)
170+
gtot = sum(totals.values()) or 1
171+
print(f"**{scored} record(s) scored.**\n")
172+
print("| Category | Total | 🟢 Green | 🟡 Yellow | 🔴 Red | Green % |")
173+
print("| --- | ---: | ---: | ---: | ---: | ---: |")
174+
for r in rows:
175+
print(r)
176+
print(
177+
f"| **All** | **{sum(totals.values())}** | **{totals['green']}** | "
178+
f"**{totals['yellow']}** | **{totals['red']}** | "
179+
f"**{100*totals['green']/gtot:.1f}%** |"
180+
)
181+
if hard_flags:
182+
print("\n**Hard violations** (forced red):\n")
183+
print("| Count | Check |")
184+
print("| ---: | --- |")
185+
for name, n in hard_flags.most_common(10):
186+
print(f"| {n} | `{name}` |")
187+
188+
149189
def cmd_report(args: argparse.Namespace) -> int:
150190
if not SCORES_PATH.exists():
151191
print("no scores cache — run `python -m app.verify score` first")
@@ -371,6 +411,8 @@ def build_parser() -> argparse.ArgumentParser:
371411
sc.add_argument("--unverified-only", action="store_true", help="skip verified:true records")
372412
sc.add_argument("--changed", action="store_true", help="only records changed vs origin/main")
373413
sc.add_argument("--no-cache", action="store_true", help="do not write the scores cache")
414+
sc.add_argument("--format", choices=["text", "md"], default="text",
415+
help="output format: text histogram (default) or markdown table")
374416
sc.set_defaults(func=cmd_score)
375417

376418
rp = sub.add_parser("report", help="summarize latest ledger state")

0 commit comments

Comments
 (0)