#!/usr/bin/env python3 """Trace collector for the cold run «door to file». It reads the three places a run leaves a trace and prints them as facts an outsider can check: the platform's Postgres, the engine's own disk (project DB + sidecars + the frame stream), and the HTTP surface plus the downloaded bytes. Two rules it follows everywhere, because both were paid for: * every zero is printed next to a CONTROL number, so «nothing happened» and «nothing was read» are told apart on the page rather than in the reader's head; * the three traces are NOT independent — the platform's rows are materialised from the engine's event stream and its text comes from the same `tmctl` verbs — so the report says so rather than presenting agreement between them as corroboration. Usage: collect.py --stand DIR --dsn DSN [--book ID] [--run ID] [--label NAME] [--json OUT] """ import argparse import json import os import re import sqlite3 import subprocess import sys from collections import Counter MICRO = 1_000_000 def psql(dsn, sql): """One query, rows as lists of strings. Separator is a tab; psql -A -t gives raw fields.""" out = subprocess.run( [os.path.expanduser("~/.local/pgsql/bin/psql"), dsn, "-At", "-F", "\t", "-c", sql], capture_output=True, text=True) if out.returncode != 0: raise RuntimeError(f"psql failed: {out.stderr.strip()}\nSQL: {sql}") return [line.split("\t") for line in out.stdout.strip().splitlines() if line != ""] def one(dsn, sql, default="0"): rows = psql(dsn, sql) return rows[0][0] if rows and rows[0] and rows[0][0] != "" else default def section(title): print() print("=" * 78) print(title) print("=" * 78) def stamp_of(binary): """The VCS stamp of a Go binary, as three answers: revision, modified, and how many vcs.* lines were there at all. The third is the one that matters: a binary built in a linked worktree carries NONE, and a gate that only refuses `vcs.modified=true` passes it every time.""" out = subprocess.run(["go", "version", "-m", binary], capture_output=True, text=True).stdout lines = [l.strip() for l in out.splitlines()] vcs = [l for l in lines if "\tvcs." in l or l.startswith("build\tvcs.")] rev = mod = "" for l in vcs: if "vcs.revision=" in l: rev = l.split("vcs.revision=")[1].strip() if "vcs.modified=" in l: mod = l.split("vcs.modified=")[1].strip() return {"binary": binary, "revision": rev, "modified": mod, "vcs_lines": len(vcs), "build_lines": len(lines)} def freeze_gate(stand, sha): section("A. FREEZE GATE — every binary, three conditions, not one") ok = True for name in ("tmctl", "tmplatformd", "tmplatformctl"): path = os.path.join(stand, "bin", name) if not os.path.exists(path): print(f" {name}: ABSENT at {path}") ok = False continue s = stamp_of(path) verdict = [] if s["vcs_lines"] == 0: verdict.append("NO vcs.* LINES AT ALL — the gate would be vacuous") if s["revision"] != sha: verdict.append(f"revision is not the frozen one ({sha[:12]})") if s["modified"] != "false": verdict.append(f"vcs.modified={s['modified']!r}") print(f" {name}: revision={s['revision'][:12] or '(none)'} modified={s['modified'] or '(none)'} " f"vcs_lines={s['vcs_lines']} (control: build lines {s['build_lines']}) " f"→ {'ok' if not verdict else '⛔ ' + '; '.join(verdict)}") ok = ok and not verdict print(f" VERDICT: {'all three binaries are from the freeze' if ok else '⛔ NOT ALL BINARIES ARE FROM THE FREEZE'}") return ok def platform_trace(dsn, book, run): section("B. PLATFORM (Postgres) — the rows, each zero beside its control") tables = ["users", "books", "chapters", "units", "runs", "run_attempts", "reservations", "credit_ledger", "book_events", "exports", "bank_terms"] for t in tables: n = one(dsn, f"select count(*) from {t}") print(f" {t}: {n}") if book: print(f"\n -- this book ({book}) --") print(" books row:", psql(dsn, f""" select status, chapter_count, source_chars, expected_micro_usd, book_once_micro_usd, step_max_micro_usd, ordered_at is not null from books where id = '{book}'""")) units = psql(dsn, f""" select u.state, count(*) from units u join chapters c on c.id = u.chapter_id where c.book_id = '{book}' group by 1 order by 1""") total = one(dsn, f"select count(*) from units u join chapters c on c.id=u.chapter_id where c.book_id='{book}'") print(f" units by state: {units} (control: units of this book = {total})") ev = psql(dsn, f"select event, count(*) from book_events where book_id='{book}' group by 1 order by 2 desc") evtotal = one(dsn, f"select count(*) from book_events where book_id='{book}'") print(f" book_events by event: {ev} (control: events of this book = {evtotal})") bank_all = one(dsn, f"select count(*) from bank_terms where book_id='{book}'") bank_ok = one(dsn, f"select count(*) from bank_terms where book_id='{book}' and status='approved'") allbooks = one(dsn, "select count(*) from bank_terms") print(f" bank_terms: {bank_all} rows, {bank_ok} approved (control: bank_terms of ALL books = {allbooks})") ex = psql(dsn, f"""select id, format, state, complete, size_bytes, path from exports where book_id='{book}' order by requested_at""") print(f" exports: {ex or 'none'} (control: exports of ALL books = {one(dsn, 'select count(*) from exports')})") if run: print(f"\n -- this run ({run}) --") print(" runs row:", psql(dsn, f""" select status, verify_bank, bond_funded, coalesce(paused_reason,''), coalesce(failure_reason,''), ceiling_chapters, finished_at is not null from runs where id='{run}'""")) att = psql(dsn, f""" select attempt_no, exit_code, exit_result, last_seq, spend_micro_usd, ceiling_arg_micro_usd, engine_binary from run_attempts where run_id='{run}' order by attempt_no""") print(f" run_attempts ({len(att)}): ") for a in att: print(" ", a) print(" ⚠ attempts, not runs: a resume after a bank stop is a SECOND attempt under the same run id") def money(dsn, book, run, projectdb): section("C. MONEY — micro-USD, as a CHECK between paths and never as an identity") led = psql(dsn, "select kind, count(*), coalesce(sum(amount_micro_usd),0) from credit_ledger group by 1 order by 1") print(f" credit_ledger by kind: {led}") grants = int(one(dsn, "select coalesce(sum(amount_micro_usd),0) from credit_ledger where kind='grant'")) settle = int(one(dsn, "select coalesce(sum(amount_micro_usd),0) from credit_ledger where kind='settlement'")) balance = int(one(dsn, "select coalesce(sum(amount_micro_usd),0) from credit_ledger")) openres = one(dsn, "select count(*) from reservations where state='open'") allres = one(dsn, "select count(*) from reservations") print(f" grants: {grants:>12} µUSD (${grants/MICRO:.6f})") print(f" settlements: {settle:>12} µUSD (${settle/MICRO:.6f})") print(f" balance: {balance:>12} µUSD (${balance/MICRO:.6f}) = sum of ALL ledger rows") print(f" open reservations: {openres} (control: reservations of every state = {allres})") spend_att = one(dsn, f"select coalesce(sum(spend_micro_usd),0) from run_attempts where run_id='{run}'") if run else "0" print(f" Σ run_attempts.spend_micro_usd for this run: {spend_att}") if projectdb and os.path.exists(projectdb): rows, total, hits, models, bad = request_log(projectdb) print(f" engine request_log: {rows} rows, Σ cost_usd = ${total:.6f} → {round(total*MICRO)} µUSD") print(f" tm_hit=1 (answer taken from a checkpoint, bought nothing): {hits} (control: rows = {rows})") print(f" distinct model_actual: {models}") print(f" rows with err or finish_reason != stop: {len(bad)} (control: rows = {rows})") for b in bad: print(" ", b) print(f" ⚠ request_log is TELEMETRY, not the source of money (the engine's money lives in spend/checkpoints);") print(f" a redrive deletes checkpoints, so a difference here is a named class, not an error to hide.") sp = engine_spend(projectdb) print(f" engine spend table: {sp}") else: print(f" engine request_log: NOT READ — no project db at {projectdb}") def request_log(db): c = sqlite3.connect(f"file:{db}?mode=ro", uri=True) rows = c.execute("select count(*) from request_log").fetchone()[0] total = c.execute("select coalesce(sum(cost_usd),0) from request_log").fetchone()[0] hits = c.execute("select count(*) from request_log where tm_hit=1").fetchone()[0] models = [r[0] for r in c.execute("select distinct model_actual from request_log order by 1")] bad = c.execute("""select id, stage, role, model_actual, finish_reason, err from request_log where coalesce(err,'') != '' or coalesce(finish_reason,'') not in ('stop','')""").fetchall() return rows, total, hits, models, bad def engine_spend(db): c = sqlite3.connect(f"file:{db}?mode=ro", uri=True) return c.execute("select book_id, date, committed_usd, reserved_usd from spend").fetchall() def engine_disk(bookdir): section("D. ENGINE DISK — frames, sidecars, checkpoints") if not os.path.isdir(bookdir): print(f" no book directory at {bookdir}") return files = sorted(os.listdir(bookdir)) print(f" book directory holds {len(files)} entries: {files}") ev = os.path.join(bookdir, "events.jsonl") if os.path.exists(ev): kinds = Counter() n = 0 with open(ev, encoding="utf-8") as f: for line in f: n += 1 try: kinds[json.loads(line).get("type", "?")] += 1 except json.JSONDecodeError: kinds[""] += 1 print(f" events.jsonl: {n} frames, by type: {dict(kinds)}") else: print(f" events.jsonl: ABSENT (control: {len(files)} files were listed in this directory)") for name in sorted(f for f in files if ".bank" in f or "signature" in f or "mined" in f): p = os.path.join(bookdir, name) print(f" sidecar {name}: {os.path.getsize(p)} bytes sha256={sha256(p)}") db = os.path.join(bookdir, "project.db") if os.path.exists(db): c = sqlite3.connect(f"file:{db}?mode=ro", uri=True) for t in ("checkpoints", "chunk_status", "glossary", "bank_stop_presented", "snapshots"): try: print(f" {t}: {c.execute(f'select count(*) from {t}').fetchone()[0]} rows") except sqlite3.Error as e: print(f" {t}: unreadable ({e})") def sha256(path): import hashlib h = hashlib.sha256() with open(path, "rb") as f: for chunk in iter(lambda: f.read(1 << 20), b""): h.update(chunk) return h.hexdigest() def build_report(stand, bookdir, out): section("E. BUILD REPORT — the seven counters the API does NOT carry") cfg = os.path.join(bookdir, "book.yaml") if not os.path.exists(cfg): print(f" no book.yaml at {cfg}") return # --out names the FILE, not a directory, and an explicit path is never replaced — so each call # writes its own copy rather than asking the engine to overwrite one. os.makedirs(os.path.dirname(out), exist_ok=True) # The verb first, its flags after, and no --json: the report is JSON regardless (the flag is # refused by name). Order and flags are the platform's own BuildArgs (internal/runner/build.go). cmd = [os.path.join(stand, "bin", "tmctl"), "build", "--config", cfg, "--format", "txt", "--out", out, "--partial"] res = subprocess.run(cmd, capture_output=True, text=True) print(f" $ {' '.join(cmd)}") print(f" exit {res.returncode}") # The report is the WHOLE of stdout, pretty-printed over many lines: a per-line scan finds # nothing and reports "no document", which looks exactly like a build that said nothing. doc = None try: doc = json.loads(res.stdout) except json.JSONDecodeError: start = res.stdout.find("{") if start >= 0: try: doc = json.loads(res.stdout[start:]) except json.JSONDecodeError: doc = None if doc is None: print(" stdout carried no report document:") print(" ", res.stdout.strip()[:600]) print(" stderr:", res.stderr.strip()[:600]) return keys = ["build_version", "total_units", "pending_units", "withheld_units", "incomplete_units", "stale_units", "stale_unknown", "ghost_rows", "config_drift", "complete"] for k in keys: print(f" {k}: {doc.get(k)}") print(f" removed_files: {doc.get('removed_files')} stale_copies: {doc.get('stale_copies')}") clean = (doc.get("complete") is True and doc.get("stale_unknown") is False and all(doc.get(k, 0) == 0 for k in ("pending_units", "withheld_units", "incomplete_units", "stale_units", "ghost_rows"))) print(f" VERDICT: {'a WHOLE book — all five counters zero, stale_unknown false, complete true' if clean else '⛔ NOT whole by this report'}") print(" ⚠ stale_units == 0 proves nothing on its own: under config drift it is mechanically zero,") print(" which is why stale_unknown is printed beside it rather than folded into the same count.") return doc def main(): ap = argparse.ArgumentParser() ap.add_argument("--stand", required=True) ap.add_argument("--dsn", required=True) ap.add_argument("--book", default="") ap.add_argument("--run", default="") ap.add_argument("--sha", default=os.environ.get("FREEZE_SHA", "")) ap.add_argument("--label", default="collect") ap.add_argument("--skip-build", action="store_true") a = ap.parse_args() print(f"COLD RUN «DOOR TO FILE» — trace bundle «{a.label}»") print(f"stand={a.stand} book={a.book or '(none)'} run={a.run or '(none)'}") if a.sha: freeze_gate(a.stand, a.sha) bookdir = os.path.join(a.stand, "stand", "books", a.book) if a.book else "" platform_trace(a.dsn, a.book, a.run) money(a.dsn, a.book, a.run, os.path.join(bookdir, "project.db") if bookdir else "") if bookdir: engine_disk(bookdir) if not a.skip_build: import time as _t build_report(a.stand, bookdir, os.path.join( a.stand, "evidence", "builds", f"{a.label}-{_t.strftime('%Y%m%dT%H%M%S')}.txt")) section("F. WHAT THIS BUNDLE DOES NOT PROVE") print(" The platform's rows are MATERIALISED from the engine's event stream, and its text, its") print(" manifest and its file come from the same `tmctl` verbs. So B, D and E agreeing is ONE") print(" database agreeing with itself, not three witnesses. Independent of them are only the") print(" bytes downloaded over HTTP and their sha256. There is no provider-side billing here.") if __name__ == "__main__": main()