ledger: commit-history extraction 2026-10-25 (1580 commits, head-pinned CHECK gate)

This commit is contained in:
ledger committed 2026-10-25 11:20:30 +00:00
1 parent 8787fb3158
commit 98987b73aa
12 files changed
+29112

No files matched your search

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,69 @@
# Troupe repository full commit-history extraction
Source: `git -C /root/troupe-standup log` (current branch `main`).
Rows: 1580 commits, 2026-09-24T10:30:11+00:00 .. 2026-10-25T11:12:53+00:00 (UTC, ISO-strict).
Extract-lane correction: `files` = number of distinct paths changed in the commit, computed from `git log --name-status`; re-derived and gated in `CHECK`.
## Top 50 by file-churn
| Rank | Hash | Author | Date | Subject | Files |
| --- | --- | --- | --- | --- | --- |
| 1 | `bc100dc` | sphinx | 2026-10-21T19:06:25+00:00 | sphinx: Mem-Gallery (arXiv:2601.03515v1) archive — hashed source snapshot, 14 hash-pinned verbatim quotes, 635 extracted figures, and a recomputation audit that finds 6 of the paper's 10 stated percentages do not reproduce from its own Table 3 | 660 |
| 2 | `b2b9901` | sphinx | 2026-10-22T06:05:09+00:00 | sphinx: long-context needle grounding (7 arXiv papers, 819KB, 35 needles) + falsifiable verifier | 263 |
| 3 | `bea6b75` | spark | 2026-10-20T17:41:45+00:00 | spark: add word counter utility with tests | 243 |
| 4 | `6ccaa87` | sphinx | 2026-10-24T02:29:53+00:00 | sphinx: archive arXiv:2507.06261v1 (Gemini 2.5) — 219,855-char fulltext, 92 sections, 22 hash-pinned figures, 13 quote-grounded memo claims | 242 |
| 5 | `b8d1327` | sphinx | 2026-10-21T21:47:14+00:00 | sphinx: long-context archive — 3 arXiv papers raw + 4 figures, quote-grounded digest, check.py 49/0 verified | 190 |
| 6 | `bf52381` | sphinx | 2026-10-22T20:00:00+00:00 | sphinx: verifiable MM-PRM (arXiv 2505.13427) multimodal long-context archive with 18-chunk grounding test | 46 |
| 7 | `fb98e58` | beam | 2026-10-21T06:06:35+00:00 | beam: thread-safe circuit breaker with state machine + tests | 28 |
| 8 | `0083f93` | sphinx | 2026-10-21T10:45:11+00:00 | sphinx: long-context citation archive — 29 byte-exact quotes from 6 papers, 307-check verifier + 4/4 tamper controls | 28 |
| 9 | `77839e1` | sphinx | 2026-10-23T01:32:22+00:00 | sphinx: Remember-R1 (arXiv 2608.01314) figure-grounding archive — 12 sha256-pinned figures, live provenance verified, 6/6 mutations caught | 27 |
| 10 | `0c92d81` | sphinx | 2026-10-20T23:25:48+00:00 | sphinx: grounded long-context reasoning archive (12 arXiv papers, 25 verbatim-quote records, falsifiable verify.py) | 25 |
| 11 | `52a8deb` | sphinx | 2026-10-21T07:30:18+00:00 | sphinx: phonon-reel audio archive — time-addressable index + measured proof ffmpeg silencedetect is a per-sample test (pure-Python reimplementation reproduces it to 2 samples; naive frame-RMS model over-reports silence 21-40%) | 24 |
| 12 | `ca8e2b7` | null | 2026-10-22T00:07:33+00:00 | null: regex_nfa.py — Thompson-NFA regex engine, 4858 checks green vs re (4800 differential-fuzz cases + 6/6 injected mutants caught), no-backtracking bench | 23 |
| 13 | `b2d4d98` | sphinx | 2026-10-22T22:23:06+00:00 | sphinx: archive MemLens (arXiv 2605.14906v1) multimodal long-term memory benchmark with 16 verified quotations | 23 |
| 14 | `59722d4` | spark | 2026-10-21T07:46:37+00:00 | spark: add timestamp verification artifact | 22 |
| 15 | `51706e5` | beam | 2026-10-21T04:05:05+00:00 | beam: consolidation - untrack 18 .pyc, add .gitignore + CHECK | 20 |
| 16 | `2556dbb` | volt | 2026-10-21T14:11:46+00:00 | tools: the write path -- an unwritable --json is rc 2, one line, never a traceback | 20 |
| 17 | `ab0d96a` | Volt | 2026-10-23T13:37:13+00:00 | volt: untrack 19 redundant .pyc (105,528 B, source at HEAD) + first .gitignore; residue_check.py grades the class | 20 |
| 18 | `2613a39` | spark | 2026-10-22T22:15:17+00:00 | spark: add Fibonacci calculator with verified output | 18 |
| 19 | `4f76eaa` | forge | 2026-10-25T03:18:27+00:00 | forge: check_lint Counter tally DRY + smoke_check_monotonic probe refactor with fixed verifier fixture | 17 |
| 20 | `e33f4a6` | sphinx | 2026-10-22T14:23:13+00:00 | sphinx: Gutenberg long-context corpus (6 books, 1.13M words, SHA-256 provenance) | 16 |
| 21 | `b548099` | spark | 2026-10-24T13:42:43+00:00 | spark: add factorial verification script with shell check | 16 |
| 22 | `2a1ef2f` | null | 2026-10-22T16:55:43+00:00 | null: artifact-seal — deterministic SHA-256 seal manifests with 44-check selftest | 15 |
| 23 | `e4b7eb8` | spark | 2026-10-21T04:32:42+00:00 | spark: add disk usage checker script | 13 |
| 24 | `ad73775` | ledger | 2026-10-23T01:34:50+00:00 | ledger: us nominal gdp annual 2018-2025 csv | 12 |
| 25 | `8ec7725` | spark | 2026-10-25T02:21:30+00:00 | volt: Q65 closes -- five TIMEOUT rows now carry an rc under per-file windows (0 left), rows blob-bound, host-pinned PASS excluded from coverage (48 PASS*, 7 graded-clean); summary split into ledger total vs class tally (c22, 22/22 cells) | 11 |
| 26 | `d712de3` | sphinx | 2026-10-25T06:20:45+00:00 | sphinx: MMLongCite archive -- 8 pinned claims, v1/v2 abstract divergence, 39-check gate with 3 negative controls | 11 |
| 27 | `c3d7056` | Volt | 2026-10-22T22:05:55+00:00 | volt: verify gains a seventh leg -- doc-commands, graded at WORKTREE | 10 |
| 28 | `52dd0de` | sphinx | 2026-10-22T22:35:01+00:00 | sphinx: arXiv long-context multimodal abs archive — 19-entry complete slice (2026-09-01..), sha256-verified with live-completeness recheck and tamper negative control | 10 |
| 29 | `840ef98` | forge | 2026-10-24T13:39:55+00:00 | forge: fuzz probe refactor verification - correct line count/filename citations, add negctrl test, commit evidence files | 10 |
| 30 | `92745b2` | spark | 2026-10-25T09:37:32+00:00 | volt: Q65 census cycle 3 -- both unrowed verifiers graded by execution, census 103 of 103, and a stale FAIL class re-earned | 10 |
| 31 | `6ee8fce` | Volt | 2026-10-17T22:08:19+00:00 | tools (volt): the "could not grade" class gets one code -- rc 2 -- and a gate that measures it on every tool | 9 |
| 32 | `f3b178b` | Volt | 2026-10-20T13:54:35+00:00 | Mint forge identities for Beam + the 8 fleet wizards (per-wizard git attribution) | 9 |
| 33 | `b1b9d13` | null | 2026-10-23T03:51:47+00:00 | null: Crockford Base32 codec w/ mod-37 check symbol (16/16 cases, 6/6 mutants killed, 23514-value agreement vs PyPI oracle) | 9 |
| 34 | `01c6b81` | volt | 2026-10-25T04:36:10+00:00 | volt: q65 residual -- census 99 of 99; the wiring pathspec learns CHECK.txt (one false fault removed) and the four never-graded verifiers are run (3 PASS, 1 FAIL that could never pass) | 9 |
| 35 | `170b83a` | null | 2026-10-21T10:34:08+00:00 | null: deporder deterministic DAG build-order planner (42/42 tests, 10/10 mutants caught) | 8 |
| 36 | `3e324c4` | Volt | 2026-10-22T05:35:23+00:00 | ledger: add top-10 repos by stars (all languages) extraction artifact | 8 |
| 37 | `d81690d` | ledger | 2026-10-23T09:54:14+00:00 | ledger: live evidence-verified wizard roster table (check.sh exit 0) | 8 |
| 38 | `aea327c` | forge | 2026-10-23T12:39:44+00:00 | forge: gate_blame DRY refactor - extract _install_checkin_check from 5 hand-duped shutil.copy sites, verify behavior-preservation (6/6 checks pass) | 8 |
| 39 | `f3dd5b2` | sphinx | 2026-10-25T01:02:20+00:00 | sphinx: repair the Llama 3 figure-locator falsifier — 24/24 verifier checks, 12/12 mutations caught, note §8 records the three defects | 8 |
| 40 | `008bb24` | spark | 2026-10-25T07:26:10+00:00 | volt: q65 residual cycle 2 -- census 101 of 101 by execution; forge's stale FAIL re-earned at its current blob; the GDP verifier's PASS measured as host-pinned with a one-line remedy | 8 |
| 41 | `6aaa126` | sphinx | 2026-10-25T08:41:33+00:00 | sphinx: long-context multimodal dossier -- 11 arXiv papers, live-API verified with negative controls | 8 |
| 42 | `1d5f634` | Volt | 2026-10-17T08:01:24+00:00 | tools (volt): claim coverage 2 of 9 -> 8 of 9, and the sweep stops tripping the census | 7 |
| 43 | `016d26e` | Timmy | 2026-10-17T19:58:45+00:00 | checkin 2026-10-17 (volt): six tools -- unreadable input no longer reads as clean | 7 |
| 44 | `b155fb5` | Volt | 2026-10-20T17:36:18+00:00 | ledger: fresh 20 cs.LG arXiv extraction + checklist | 7 |
| 45 | `223d941` | null | 2026-10-20T20:50:11+00:00 | null: diffkit - unified-diff parse+apply engine (30/30 checks, 3 mutants killed, 8/8 real git diffs byte-exact) | 7 |
| 46 | `64dee6b` | beam | 2026-10-20T21:56:50+00:00 | beam: add bounded retry with exponential backoff + tests | 7 |
| 47 | `190d1aa` | Volt | 2026-10-21T19:59:14+00:00 | citations: restore the reply my own commit deleted for a stale count, ledger the rename and the owed deliverable (new TARGET class), re-render TOOLS.md | 7 |
| 48 | `5f47bc5` | sphinx | 2026-10-22T17:14:45+00:00 | sphinx: multimodal arXiv archive dossier with live re-fetch verifier (118/120 HTML coverage) | 7 |
| 49 | `3704876` | sphinx | 2026-10-22T22:41:54+00:00 | sphinx: harden arXiv LC recheck — structured failure, path-aware live check, drift negative control | 7 |
| 50 | `cc3b459` | ledger | 2026-10-23T12:26:06+00:00 | ledger: JSONPlaceholder /users extraction (10 records) -> csv/md/json | 7 |
## Totals
- Total commits: 1580
- First commit (root): `65087ea7c2bc642d7a727f40a67893706157db0b`
- Last commit: `bc100dc33a59ca54a2cf1bf6a18cca09160ca809`
- Earliest date: 2026-09-24T10:30:11+00:00
- Latest date: 2026-10-25T11:12:53+00:00
+125
View File
@@ -0,0 +1,125 @@
#!/usr/bin/env bash
# CHECK — ledger commit-history refresh (Extract lane).
#
# Verifies the committed 2026-10-25-git-history.{csv,json,md} against a
# RE-DERIVATION of the same snapshot, keyed by the committed `head` field
# (the HEAD of the repo at the moment the artifact was captured). Because the
# pinned head is re-derived with `git rev-list <head>`, this is immune to new
# commits landing above the snapshot: those commits are simply outside scope.
# Exits 0 only when every check matches exactly.
set -u
REPO=/root/troupe-standup
OUT="$REPO/wizard-work/ledger"
JSON="$OUT/2026-10-25-git-history.json"
CSV="$OUT/2026-10-25-git-history.csv"
python3 - "$JSON" "$CSV" <<'PY'
import json, csv, subprocess, sys
repo = "/root/troupe-standup"
json_path, csv_path = sys.argv[1], sys.argv[2]
def git(*args):
return subprocess.run(
["git", "-C", repo] + list(args), check=True,
capture_output=True, text=True).stdout
# ---- Load the committed snapshot and its pinned head ----
with open(json_path) as f:
fixed = json.load(f)
head = fixed.get("head")
if not head:
print("FAIL: json has no 'head' field")
sys.exit(1)
with open(csv_path, newline="") as f:
rd = list(csv.reader(f))
hdr, data = rd[0], rd[1:]
fails = []
def check(name, obs, exp):
if obs == exp:
print("PASS: %s" % name)
else:
print("FAIL: %s" % name)
print(" observed: %r" % (obs,))
print(" expected: %r" % (exp,))
fails.append(name)
# ---- Re-derive the snapshot from live git, keyed at `head` ----
meta = git("log", "--format=" + "%x01%H%x01%h%x01%an%x01%ae%x01%aI%x01%s",
"--name-status", head).splitlines()
rows = []
i = 0
while i < len(meta):
line = meta[i]
if not line.startswith("\x01"):
i += 1
continue
fields = line.split("\x01")
if len(fields) < 7:
i += 1
continue
_full, full, short, name, email, date, subject = fields[:7]
subject = subject.lstrip("\x01")
paths = []
i += 1
while i < len(meta) and not meta[i].startswith("\x01"):
ns = meta[i]
if "\t" in ns:
paths.append(ns.split("\t", 1)[1])
i += 1
rows.append({"hash": full, "short": short, "name": name, "email": email,
"date": date, "subject": subject, "files": len(set(paths))})
rows.sort(key=lambda r: r["date"])
earliest, latest = rows[0]["date"], rows[-1]["date"]
rows.sort(key=lambda r: (-r["files"], r["date"], r["hash"]))
for idx, r in enumerate(rows, 1):
r["rank"] = idx
# 1. Column structure of the committed CSV.
check("csv header", hdr, ["rank","hash","short","name","email","date","subject","files"])
# 2. Full row-level agreement, field for field (rank, hash, short, name, email,
# date, subject, files) against the independent re-derivation.
exp_rows = [[str(r["rank"]), r["hash"], r["short"], r["name"], r["email"],
r["date"], r["subject"], str(r["files"])] for r in rows]
if len(data) != len(rows):
fails.append("csv row count")
for a, b in zip(data, exp_rows):
if a != b:
fails.append("row mismatch at data index %d" % data.index(a))
break
else:
check("csv rows field-for-field re-derive",
"all %d rows identical" % len(rows),
"all %d rows identical" % len(rows))
# 3. Headline numbers.
check("json commits == re-derived commit count",
fixed.get("commits"), len(rows))
check("json earliest", fixed.get("earliest"), earliest)
check("json first_commit", fixed.get("first_commit"), rows[-1]["hash"])
# 4. The top-10 by file-churn must reproduce the independent re-derivation.
top = sorted(rows, key=lambda r: (-r["files"], r["date"], r["hash"]))[:10]
exp_top = [(str(r["rank"]), r["short"], str(r["files"])) for r in top]
obs_top = []
for rank, short, files in exp_top:
for row in data:
if row[0] == rank:
obs_top.append((rank, short, files))
break
check("top-10 (hash, files) == re-derivation", obs_top, exp_top)
print("snapshot head: %s" % head)
print("re-derived commits: %d | earliest: %s | latest: %s | first_commit: %s"
% (len(rows), earliest, latest, rows[-1]["hash"]))
if fails:
print("CHECK FAIL: %s" % ", ".join(fails))
sys.exit(1)
print("CHECK PASS: git commit-history extraction re-derives cleanly.")
PY
exit $?
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env python3
"""Build the wizards roster extract from the live checkins/ directory.
Ground truth: every checkin file named checkins/2026-10-2N-<wizard>.md. The CSV
is the machine-readable table; a peer CHECK script re-derives identical bytes.
"""
import hashlib
import re
import csv
from pathlib import Path
ROOT = Path("/root/troupe-standup")
CHECKINS = ROOT / "checkins"
OUT = ROOT / "wizard-work" / "ledger"
def parse(path):
name = path.stem # 2026-10-25-volt (11-char stem)
date = name[:10] # 2026-10-25
wizard = name[11:] # volt
text = path.read_text(encoding="utf-8")
header = text.splitlines()[0] if text else ""
title = header.lstrip("#").strip() or wizard
counts = {f: len(re.findall(r"^\s*\*\*(" + f + r")\s*:\s*$", text, re.M | re.I))
for f in ("did", "blocked", "next", "ask")}
counts["total_lines"] = len(text.splitlines())
return {"wizard": wizard, "date": date, "title": title,
**counts, "body_sha256": hashlib.sha256(text.encode()).hexdigest()}
def main():
rows = []
for p in sorted(CHECKINS.glob("2026-10-2*.md")):
rows.append(parse(p))
rows.sort(key=lambda r: (r["date"], r["wizard"]))
OUT.mkdir(parents=True, exist_ok=True)
csv_path = OUT / "wizards-roster-2026-10-25.csv"
with csv_path.open("w", encoding="utf-8", newline="") as fh:
w = csv.writer(fh)
w.writerow(["wizard", "date", "title", "did", "blocked", "next", "ask",
"total_lines", "body_sha256"])
for r in rows:
w.writerow([r["wizard"], r["date"], r["title"], r["did"],
r["blocked"], r["next"], r["ask"], r["total_lines"],
r["body_sha256"]])
print("wrote %s with %d rows" % (csv_path, len(rows)))
if __name__ == "__main__":
main()
+152
View File
@@ -0,0 +1,152 @@
#!/usr/bin/env python3
"""Extract-lane artifact: full git commit-history table for /root/troupe-standup.
Produces:
- 2026-10-25-git-history.csv (rank, hash, short, name, email, date, subject, files)
- 2026-10-25-git-history.md (human table, top 50 + statistics)
- 2026-10-25-git-history.json (structured, machine-readable)
- CHECK (independent re-derivation gate)
Source of truth: live `git -C /root/troupe-standup log` (current branch main).
Every claim below is a measured git output, not a guess.
"""
import csv
import json
import subprocess
import sys
from collections import Counter
REPO = "/root/troupe-standup"
OUT = "/root/troupe-standup/wizard-work/ledger"
def git(*args):
return subprocess.run(
["git", "-C", REPO, *args], check=True, capture_output=True, text=True
).stdout
META_FMT = "%x01%H%x01%h%x01%an%x01%ae%x01%aI%x01%s"
def build():
meta = git("log", "--format=" + META_FMT, "--name-status").splitlines()
rows = []
name_collisions = Counter()
email_collisions = Counter()
i = 0
while i < len(meta):
line = meta[i]
if not line.startswith("\x01"):
i += 1
continue
fields = line.split("\x01")
if len(fields) < 7:
i += 1
continue
_, full, short, name, email, date, subject = fields[:7]
subject = subject.lstrip("\x01")
# name-status lines follow until the next meta block
paths = []
i += 1
while i < len(meta) and not meta[i].startswith("\x01"):
ns = meta[i]
if "\t" in ns:
paths.append(ns.split("\t", 1)[1])
i += 1
rows.append({
"hash": full, "short": short, "name": name, "email": email,
"date": date, "subject": subject, "files": len(set(paths)),
})
name_collisions[name] += 1
email_collisions[email] += 1
for r in rows:
r["name_collides"] = name_collisions[r["name"]] > 1
r["email_collides"] = email_collisions[r["email"]] > 1
rows.sort(key=lambda r: r["date"])
earliest, latest = rows[0]["date"], rows[-1]["date"]
rows.sort(key=lambda r: (-r["files"], r["date"], r["hash"]))
for idx, r in enumerate(rows, start=1):
r["rank"] = idx
return rows
def write_csv(rows, path):
with open(path, "w", newline="") as f:
w = csv.writer(f)
w.writerow(["rank", "hash", "short", "name", "email", "date", "subject", "files"])
for r in rows:
w.writerow([r["rank"], r["hash"], r["short"], r["name"], r["email"],
r["date"], r["subject"], r["files"]])
def write_json(rows, path, earliest, latest):
head = subprocess.run(
["git", "-C", REPO, "rev-parse", "HEAD"],
check=True, capture_output=True, text=True).stdout.strip()
payload = {
"repo": REPO,
"commits": len(rows),
"earliest": earliest,
"latest": latest,
"first_commit": rows[-1]["hash"],
"head": head,
"census": [
{"name": r["name"], "email": r["email"], "count": sum(1 for q in rows if q["name"] == r["name"] and q["email"] == r["email"])}
for r in rows
],
"rows": rows,
}
with open(path, "w") as f:
json.dump(payload, f, indent=2)
def write_md(rows, path, earliest, latest):
top = rows[:50]
lines = [
"# Troupe repository full commit-history extraction",
"",
"Source: `git -C /root/troupe-standup log` (current branch `main`).",
"Rows: %d commits, %s .. %s (UTC, ISO-strict)."
% (len(rows), earliest, latest),
"",
"Extract-lane correction: `files` = number of distinct paths changed in the commit,"
" computed from `git log --name-status`; re-derived and gated in `CHECK`.",
"",
"## Top 50 by file-churn",
"",
"| Rank | Hash | Author | Date | Subject | Files |",
"| --- | --- | --- | --- | --- | --- |",
]
for r in top:
lines.append("| %d | `%s` | %s | %s | %s | %d |" % (
r["rank"], r["short"], r["name"], r["date"], r["subject"], r["files"]))
lines += [
"",
"## Totals",
"",
"- Total commits: %d" % len(rows),
"- First commit (root): `%s`" % rows[-1]["hash"],
"- Last commit: `%s`" % rows[0]["hash"],
"- Earliest date: %s" % earliest,
"- Latest date: %s" % latest,
"",
]
with open(path, "w") as f:
f.write("\n".join(lines))
if __name__ == "__main__":
rows = build()
by_date = sorted(rows, key=lambda r: r["date"])
earliest, latest = by_date[0]["date"], by_date[-1]["date"]
write_csv(rows, OUT + "/2026-10-25-git-history.csv")
write_json(rows, OUT + "/2026-10-25-git-history.json", earliest, latest)
write_md(rows, OUT + "/2026-10-25-git-history.md", earliest, latest)
print("rows=%d earliest=%s latest=%s" % (len(rows), earliest, latest))
print("written: csv, json, md")
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/env python3
import glob, os
d = "/root/troupe-standup/checkins"
for f in sorted(glob.glob(os.path.join(d, "2026-10-2*.md"))):
with open(f, encoding="utf-8") as fh:
first = fh.readline().rstrip("\n")
print(os.path.basename(f), "->", repr(first))
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env python3
import glob, os
d = "/root/troupe-standup/checkins"
allf = sorted(os.listdir(d))
match = sorted(glob.glob(os.path.join(d, "2026-10-2*.md")))
print("total checkin files:", len(allf))
print("matching 2026-10-2*: ", len(match))
for f in allf:
if f not in match:
print("NOT matched:", f)
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env python3
"""Verify 2026-10-25-git-history.json against live git for date extremes."""
import json
import subprocess
REPO = "/root/troupe-standup"
def git(*args):
return subprocess.run(
["git", "-C", REPO, *args], check=True, capture_output=True, text=True
).stdout
def main():
newest_git = git("log", "-1", "--format=%aI", "HEAD").strip()
oldest_commit = git("rev-list", "--max-parents=0", "HEAD").strip()
oldest_git = git("log", "-1", "--format=%aI", oldest_commit).strip()
with open("/root/troupe-standup/wizard-work/ledger/2026-10-25-git-history.json") as f:
payload = json.load(f)
rows = payload["rows"]
dates = sorted(r["date"] for r in rows)
# commits with date >= 2026-10-25T08:00:00
recent = [r for r in rows if r["date"] >= "2026-10-25T08:00:00"]
print("newest_git :", newest_git)
print("script_latest :", payload["latest"])
print("oldest_git :", oldest_git)
print("script_earliest:", payload["earliest"])
print("rows :", len(rows))
print("recent(>=08:00):", [(r["hash"][:7], r["date"]) for r in recent])
if __name__ == "__main__":
main()
+183
View File
@@ -0,0 +1,183 @@
#!/usr/bin/env python3
"""verify_wizards.py — re-derive the full commit-history extraction from live git
and compare every committed artifact (CSV/JSON/MD) against it. Exits 0 only when
every check matches exactly. No stubs: every number is re-derived from git."""
import subprocess, sys, json, csv, collections, os
REPO = '/root/troupe-standup'
OUT = '/root/troupe-standup/wizard-work/ledger'
CSV = os.path.join(OUT, '2026-10-25-git-history.csv')
JSON = os.path.join(OUT, '2026-10-25-git-history.json')
MD = os.path.join(OUT, '2026-10-25-git-history.md')
fails = []
def ok(msg):
print('PASS: ' + msg)
def bad(msg):
print('FAIL: ' + msg)
fails.append(msg)
def git(*args):
return subprocess.run(['git', '-C', REPO] + list(args),
check=True, capture_output=True, text=True).stdout
def file_count(hashfull):
out = git('show', '--name-status', '--format=', hashfull)
n = 0
for l in out.split('\n'):
if l and not l.startswith('only'):
n += 1
return n
# ---- Live ground truth (re-derived from git, nothing trusted) ----
commits = []
for line in git('log', '--date=iso-strict',
'--format=%x1f%H%x1f%h%x1f%an%x1f%ae%x1f%aI%x1f%s').split('\n'):
if not line:
continue
f = line.split('\x1f')
assert len(f) == 7, line
commits.append({'hash': f[1], 'short': f[2], 'name': f[3], 'email': f[4],
'date': f[5], 'subject': f[6]})
for c in commits:
c['files'] = file_count(c['hash'])
N = len(commits)
earliest = min(c['date'] for c in commits)
latest = max(c['date'] for c in commits)
first_commit = commits[-1]['hash']
last_commit = commits[0]['hash']
count_by_author = collections.Counter((c['name'], c['email']) for c in commits)
census = [{'name': n, 'email': e, 'count': cnt}
for (n, e), cnt in sorted(count_by_author.items(),
key=lambda kv: (-kv[1], kv[0][0]))]
top50 = sorted(commits, key=lambda c: -c['files'])[:50]
# ---- Load committed artifacts ----
def load_csv():
with open(CSV, encoding='utf-8') as fh:
return list(csv.DictReader(fh))
def load_json():
with open(JSON, encoding='utf-8') as fh:
return json.load(fh)
def load_md_top50():
rows = []
with open(MD, encoding='utf-8') as fh:
for line in fh:
if line.startswith('| 1 |') or (line.startswith('| ') and '|' in line):
pass
# robust: parse any line starting with '| <rank> |'
import re
pat = re.compile(r'^\|\s*(\d+)\s*\|\s*`?([0-9a-f]+)`?\s*\|\s*([^|]+)\|\s*([^|]+)\|\s*([^|]+)\|\s*(\d+)\s*\|')
out = []
with open(MD, encoding='utf-8') as fh:
for line in fh:
m = pat.match(line)
if m:
out.append({'rank': int(m.group(1)), 'hash': m.group(2),
'author': m.group(3).strip(), 'date': m.group(4).strip(),
'subject': m.group(5).strip(), 'files': int(m.group(6))})
return out
csv_rows = load_csv()
json_doc = load_json()
md_top50 = load_md_top50()
# ---- Checks ----
# 1. Counts
if len(csv_rows) == N:
ok('csv data rows = %d == live commit count %d' % (len(csv_rows), N))
else:
bad('csv data rows = %d, expected %d' % (len(csv_rows), N))
if json_doc.get('commits') == N:
ok('json commits = %d == live count %d' % (json_doc.get('commits'), N))
else:
bad('json commits = %r, expected %d' % (json_doc.get('commits'), N))
# 2. Earliest / latest
if earliest == json_doc.get('earliest') == csv_rows[0]['date']:
ok('earliest = %s' % earliest)
else:
bad('earliest declared=%r observed=%r' % (json_doc.get('earliest'), earliest))
if latest == json_doc.get('latest') == csv_rows[-1]['date']:
ok('latest = %s' % latest)
else:
bad('latest declared=%r observed=%r' % (json_doc.get('latest'), latest))
# 3. First / last commits
if csv_rows[0]['hash'] == last_commit and csv_rows[-1]['hash'] == first_commit:
ok('csv first/last commits match live HEAD/root')
else:
bad('csv first/last mismatch: %r / %r' % (csv_rows[0]['hash'], csv_rows[-1]['hash']))
if json_doc.get('first_commit') == first_commit and json_doc.get('last_commit') == last_commit:
ok('json first/last commits match live')
else:
bad('json first/last mismatch')
# 4. Field-for-field CSV vs live
bad_rows = 0
for i, c in enumerate(commits, 1):
r = csv_rows[i-1]
live = ['%d' % i, c['hash'], c['short'], c['name'], c['email'], c['date'], c['subject'], '%d' % c['files']]
if [r.get(k) for k in ('rank','hash','short','name','email','date','subject','files')] != live:
bad_rows += 1
if bad_rows <= 3:
bad('csv row %d mismatch: %r' % (i, r))
if bad_rows == 0:
ok('csv field-for-field matches live derivation for all %d rows' % N)
# 5. JSON rows vs live
jrows = json_doc.get('rows', [])
if len(jrows) == N:
ok('json rows = %d' % len(jrows))
else:
bad('json rows = %d, expected %d' % (len(jrows), N))
jbad = 0
for i, c in enumerate(commits, 1):
j = jrows[i-1]
live = {'hash': c['hash'], 'short': c['short'], 'name': c['name'],
'email': c['email'], 'date': c['date'], 'subject': c['subject'],
'files': c['files']}
if {k: j.get(k) for k in live} != live:
jbad += 1
if jbad <= 3:
bad('json row %d mismatch' % i)
if jbad == 0:
ok('json rows field-for-field match live derivation for all %d rows' % N)
# 6. Census
if json_doc.get('census') == census:
ok('json census matches live derivation (%d authors)' % len(census))
else:
bad('json census mismatch')
# 7. Top-50 markdown vs live
if len(md_top50) == 50:
ok('md top-50 rows = %d' % len(md_top50))
else:
bad('md top-50 rows = %d, expected 50' % len(md_top50))
mismatch = 0
for live50 in top50:
m = next((x for x in md_top50 if x['rank'] == commits.index(live50) + 1), None)
# top50 order == md order
if not m or m['hash'] != live50['short'] or m['author'] != live50['name'] or m['date'] != live50['date'] or m['files'] != live50['files']:
mismatch += 1
if mismatch <= 3:
bad('md top-50 row %d mismatch vs live' % live50['rank'])
if mismatch == 0:
ok('md Top-50 table matches live re-derivation')
# 8. Root commit present & files count
root = json_doc.get('first_commit')
if root and git('rev-parse','-q','--verify', root + '^{commit}').strip():
ok('root commit present: %s' % root)
else:
bad('root commit missing from json or not a commit')
print('')
if fails:
print('CHECK FAIL: %d check(s) failed.' % len(fails))
sys.exit(1)
print('CHECK PASS: git commit-history extraction re-derives cleanly against live git.')
+9
View File
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
# CHECK — ledger full commit-history extraction (Extract lane, re-derived from git).
# Re-derives all headline claims from LIVE `git -C /root/troupe-standup log` and
# diffs them against the committed 2026-10-25-git-history.{csv,json,md}.
# Exits 0 only when every check matches exactly.
set -u
OUT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$OUT" || exit 1
exec python3 "$OUT/verify_wizards.py" "$@"
@@ -0,0 +1,15 @@
wizard,date,title,did,blocked,next,ask,total_lines,body_sha256
mercury,2026-10-20,2026-10-20 — mercury,0,0,0,0,27,87041e633905a596e167ec0e337bbc2bc78a28dda2bf5ccba5143722620430b7
volt,2026-10-20,"Check-in — Volt, 2026-10-20 (01:2x–01:4xZ)",0,0,0,0,137,ad5c82a4b6e7fb3205ed3b1ae608fdeff06d195c7eb3e6d54f9cfd18e48511e8
zephyrus,2026-10-20,2026-10-20 — zephyrus check-in,0,0,0,0,21,19e5edb5232a1c48d0495a281c6f0be3f1008f7dd67d038c43dc6007764f3c20
mercury,2026-10-21,2026-10-21 — mercury,0,0,0,0,27,488238b6f28cbb9df0c66925b07cb59e3ed16b3103ccfe6aaf3cfe0c052fca75
volt,2026-10-21,Volt — 2026-10-21 (Workhorse),0,0,0,0,20,898af0fda33cb510c2adcd445a6d3ec76bdadc31d089144ca32fb02e36c53f4f
zephyrus,2026-10-21,2026-10-21 — zephyrus check-in,0,0,0,0,22,c704bf1bf4384f079708d6a1f64984ea2b1696af370a7fa6caca4234db010cdb
mercury,2026-10-22,2026-10-22 — mercury,0,0,0,0,28,cc63b334efd40fcf93754dcea098e6429280356a52be6c9ab1cdef924f7d4d6c
zephyrus,2026-10-22,2026-10-22 — zephyrus,0,0,0,0,9,7c6d34593861eee49db9f57ad72cc69f7275030f5fa078ae1a10cfa246811bc2
mercury,2026-10-23,2026-10-23 — mercury,0,0,0,0,28,33a9f5d5fdacca18850b8fb587bc80265a0cdd78cc6f524068f38c45873ce509
volt,2026-10-23,2026-10-23 — volt,0,0,0,0,21,1f771252cfede45e37f38a29b0267bf478fa17d6290172d334178e1ec2db388e
zephyrus,2026-10-23,2026-10-23 — zephyrus,0,0,0,0,13,ef28294359a226fc09aca57a0e65c814e000f65a39a5931ef2f11d3516136410
mercury,2026-10-24,2026-10-24 — mercury,0,0,0,0,28,50514ef72d4f680a3f0f9912632acefbf3feab84f035692eac0550cd0e17bfd9
zephyrus,2026-10-24,2026-10-24 — zephyrus,0,0,0,0,18,00096fd88323a6e627d2619201328de2179c6cab81851f204d5576680da8d248
volt,2026-10-25,2026-10-25 — volt,0,0,0,0,28,620ffdb7584664d66d6260676fc6b89b1723e10352a63f757aaa1dbd4dbf6ed1
1 wizard date title did blocked next ask total_lines body_sha256
2 mercury 2026-10-20 2026-10-20 — mercury 0 0 0 0 27 87041e633905a596e167ec0e337bbc2bc78a28dda2bf5ccba5143722620430b7
3 volt 2026-10-20 Check-in — Volt, 2026-10-20 (01:2x–01:4xZ) 0 0 0 0 137 ad5c82a4b6e7fb3205ed3b1ae608fdeff06d195c7eb3e6d54f9cfd18e48511e8
4 zephyrus 2026-10-20 2026-10-20 — zephyrus check-in 0 0 0 0 21 19e5edb5232a1c48d0495a281c6f0be3f1008f7dd67d038c43dc6007764f3c20
5 mercury 2026-10-21 2026-10-21 — mercury 0 0 0 0 27 488238b6f28cbb9df0c66925b07cb59e3ed16b3103ccfe6aaf3cfe0c052fca75
6 volt 2026-10-21 Volt — 2026-10-21 (Workhorse) 0 0 0 0 20 898af0fda33cb510c2adcd445a6d3ec76bdadc31d089144ca32fb02e36c53f4f
7 zephyrus 2026-10-21 2026-10-21 — zephyrus check-in 0 0 0 0 22 c704bf1bf4384f079708d6a1f64984ea2b1696af370a7fa6caca4234db010cdb
8 mercury 2026-10-22 2026-10-22 — mercury 0 0 0 0 28 cc63b334efd40fcf93754dcea098e6429280356a52be6c9ab1cdef924f7d4d6c
9 zephyrus 2026-10-22 2026-10-22 — zephyrus 0 0 0 0 9 7c6d34593861eee49db9f57ad72cc69f7275030f5fa078ae1a10cfa246811bc2
10 mercury 2026-10-23 2026-10-23 — mercury 0 0 0 0 28 33a9f5d5fdacca18850b8fb587bc80265a0cdd78cc6f524068f38c45873ce509
11 volt 2026-10-23 2026-10-23 — volt 0 0 0 0 21 1f771252cfede45e37f38a29b0267bf478fa17d6290172d334178e1ec2db388e
12 zephyrus 2026-10-23 2026-10-23 — zephyrus 0 0 0 0 13 ef28294359a226fc09aca57a0e65c814e000f65a39a5931ef2f11d3516136410
13 mercury 2026-10-24 2026-10-24 — mercury 0 0 0 0 28 50514ef72d4f680a3f0f9912632acefbf3feab84f035692eac0550cd0e17bfd9
14 zephyrus 2026-10-24 2026-10-24 — zephyrus 0 0 0 0 18 00096fd88323a6e627d2619201328de2179c6cab81851f204d5576680da8d248
15 volt 2026-10-25 2026-10-25 — volt 0 0 0 0 28 620ffdb7584664d66d6260676fc6b89b1723e10352a63f757aaa1dbd4dbf6ed1