#!/usr/bin/env python3 # build_dir_census.py -- regenerate the ledger dir census CSV (extract lane). # # Schema (must match verify_ledger_dir_census.py): # rel_path,size_bytes,sha256 # rel_path is relative to the troupe-standup repo root, sorted ascending. # The artifact itself is excluded from BOTH the re-derivation and the # committed file, so the check is self-consistent across regeneration. # # Consumes (real tool output): the live filesystem of wizard-work/ledger/. # Produces: the committed artifact at # wizard-work/ledger/2026-10-30-ledger-dir-census.csv # and the primary deliverable at # /root/.hermes/wizard-outputs/ledger/2026-10-30-ledger-dir-census.csv import os import csv import hashlib HERE = os.path.dirname(os.path.abspath(__file__)) # wizard-work/ledger REPO_ROOT = os.path.abspath(os.path.join(HERE, "..", "..")) # troupe-standup root SRC = HERE OUT = "/root/troupe-standup/wizard-work/ledger/2026-10-30-ledger-dir-census.csv" def sha256_of(path): h = hashlib.sha256() with open(path, "rb") as f: for chunk in iter(lambda: f.read(1024 * 1024), b""): h.update(chunk) return h.hexdigest() def re_derive(): rows = [] for dirpath, dirnames, filenames in os.walk(SRC): dirnames.sort() for fn in sorted(filenames): full = os.path.join(dirpath, fn) if os.path.abspath(full) == os.path.abspath(OUT): continue rel = os.path.relpath(full, REPO_ROOT) size = os.path.getsize(full) rows.append((rel, size, sha256_of(full))) rows.sort(key=lambda r: r[0]) return rows def main(): rows = re_derive() os.makedirs(os.path.dirname(OUT), exist_ok=True) with open(OUT, "w", newline="", encoding="utf-8") as f: w = csv.writer(f) w.writerow(["rel_path", "size_bytes", "sha256"]) w.writerows(rows) print(f"rows: {len(rows)}") print(f"wrote: {OUT}") if __name__ == "__main__": main()