SPB Git

spb/wp42_uqo

Public
4.0 KB · 66 lines python
1#!/usr/bin/env python32"""PUBLIC self-check (arm A4 and controller): verifies deliverable presence and well-formedness only. It knows nothing about the3correct answers. Usage: python tools/selfcheck.py [--workspace .] [--json]"""4from __future__ import annotations5import argparse, json, os, sys, zipfile67def check(workspace: str) -> dict:8    task = json.load(open(os.path.join(workspace, "task.json"), encoding="utf-8"))9    out = os.path.join(workspace, "out"); problems = []; checks = []10    for d in task.get("required_deliverables", []):11        p = os.path.join(out, d["path"])12        if d["path"].endswith("/") or d.get("kind") in ("dir", "directory"):13            ok = os.path.isdir(p) and any(os.path.isfile(os.path.join(dp, f)) for dp, _, fs in os.walk(p) for f in fs)14            checks.append({"path": d["path"], "exists": ok})15            if not ok: problems.append(f"missing or empty directory deliverable: out/{d['path']}")16            continue17        ok = os.path.isfile(p) and os.path.getsize(p) > 018        checks.append({"path": d["path"], "exists": ok})19        if not ok: problems.append(f"missing or empty deliverable: out/{d['path']}"); continue20        kind = d.get("kind") or os.path.splitext(p)[1].lstrip(".")21        if kind in ("xlsx", "docx", "pptx"):22            try:23                with zipfile.ZipFile(p) as z: z.testzip()24            except Exception as e:  # noqa: BLE00125                problems.append(f"out/{d['path']} is not a valid {kind} (zip) file: {e}"); continue26            if kind == "xlsx" and d.get("must_have_formulas"):27                try:28                    import openpyxl29                    wb = openpyxl.load_workbook(p); n = sum(1 for ws in wb.worksheets for row in ws.iter_rows() for c in row if isinstance(c.value, str) and c.value.startswith("="))30                    if n == 0: problems.append(f"out/{d['path']} contains no formulas (the brief requires a working spreadsheet)")31                    errs = 032                    try:33                        wb2 = openpyxl.load_workbook(p, data_only=True)34                        errs = sum(1 for ws in wb2.worksheets for row in ws.iter_rows() for c in row if isinstance(c.value, str) and c.value.startswith("#"))35                    except Exception: pass  # noqa: BLE00136                    if errs: problems.append(f"out/{d['path']} has {errs} cells with error values (#REF!, #DIV/0!, ...)")37                except ImportError: pass38            if kind == "docx":39                try:40                    import docx41                    n = sum(len(par.text.split()) for par in docx.Document(p).paragraphs)42                    if n < 50: problems.append(f"out/{d['path']} has only {n} words")43                except ImportError: pass44        if kind == "json":45            try: json.load(open(p, encoding="utf-8"))46            except Exception as e: problems.append(f"out/{d['path']} is not valid JSON: {e}")  # noqa: BLE00147    cp = os.path.join(out, "COMPLETION.json")48    if os.path.isfile(cp):49        try:50            c = json.load(open(cp, encoding="utf-8"))51            for k in ("status", "summary", "deliverables"):52                if k not in c: problems.append(f"COMPLETION.json lacks '{k}'")53            if c.get("status") not in ("completed", "needs_clarification", "abstained"): problems.append("COMPLETION.json status must be completed | needs_clarification | abstained")54        except Exception as e: problems.append(f"COMPLETION.json invalid: {e}")  # noqa: BLE00155    else: problems.append("missing out/COMPLETION.json")56    return {"ok": not problems, "problems": problems, "checks": checks}5758if __name__ == "__main__":59    ap = argparse.ArgumentParser(); ap.add_argument("--workspace", default="."); ap.add_argument("--json", action="store_true")60    a = ap.parse_args(); r = check(a.workspace)61    if a.json: print(json.dumps(r, indent=1))62    else:63        print("SELF-CHECK:", "OK" if r["ok"] else f"{len(r['problems'])} problem(s)")64        for p in r["problems"]: print(" -", p)65    sys.exit(0 if r["ok"] else 1)66
Files · e883970b49fd91449e9df61ba1881564aeb053c6
Menu

Theme