ledger: per-extension file census from wizardwork file manifest
This commit is contained in:
1 parent
8b11645948
commit
b82b023215
17 files changed
+14171
-12
No files matched your search
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
# Verdict for the top-python-repos extract.
|
||||
# Verdict for the ledger-extract.tsv artifact (per-extension file census).
|
||||
# Exit code 0 = artifact correct; nonzero = wrong.
|
||||
set -u
|
||||
cd /root/troupe-standup/wizard-work/ledger || exit 1
|
||||
exec python3 /root/troupe-standup/wizard-work/ledger/CHECK.py
|
||||
exec python3 /root/troupe-standup/wizard-work/ledger/check_ledger_extract.py
|
||||
@@ -1,19 +1,49 @@
|
||||
# Top Python repositories by stars (GitHub)
|
||||
# ledger-extract.tsv
|
||||
|
||||
- Artifact: `top-python-repos-2026-10-26.csv` (table) + `top-python-repos-2026-10-26.json` (source rows + fetched timestamp).
|
||||
- Source: GitHub Search API `https://api.github.com/search/repositories?q=language:python&sort=stars&per_page=50` (HTTP 200, fetched this run).
|
||||
- Order: stars descending, name ascending as tie-break.
|
||||
- Retrieval time: `2026-10-26T01:01:54Z`.
|
||||
- Row count: 50 (top 50).
|
||||
Per-extension file census derived from the wizardwork file manifest
|
||||
(`wizardwork-file-manifest.tsv`: tab-separated, no header: path, size_bytes,
|
||||
extension, top_dir).
|
||||
|
||||
## Artifact
|
||||
|
||||
- Table: `ledger-extract.tsv` (tab-separated, no header).
|
||||
- Verifier: `check_ledger_extract.py` (re-derives the census from the manifest
|
||||
and diffs every field against the table).
|
||||
- Launcher: `CHECK` (runs the verifier; exit 0 = pass, nonzero = fail).
|
||||
- Generator: `generate_ledger_extract.py` (the extraction script).
|
||||
|
||||
## Columns
|
||||
|
||||
rank | name | owner | description | stars | forks | html_url | language
|
||||
| Column | Meaning |
|
||||
| --- | --- |
|
||||
| extension | File extension as recorded in the manifest (leading dots kept; empty → `(no ext)`). |
|
||||
| file_count | Number of files with that extension. |
|
||||
| bytes_total | Sum of `size_bytes` for the extension. |
|
||||
| bytes_mean | `bytes_total / file_count`, 1 decimal place. |
|
||||
| bytes_median | Median of `size_bytes`, 1 decimal place. |
|
||||
| bytes_min | Smallest `size_bytes`. |
|
||||
| bytes_max | Largest `size_bytes`. |
|
||||
|
||||
Rows are sorted by `file_count` descending, then `extension` ascending.
|
||||
|
||||
## How to re-verify
|
||||
|
||||
Run `bash CHECK` from the repo root (or `./CHECK`). It re-derives every row from the JSON and diffs it against the CSV; it also checks row count, rank order 1..50, and that `stars` never increases.
|
||||
```bash
|
||||
python3 /root/troupe-standup/wizard-work/ledger/check_ledger_extract.py
|
||||
# exit code 0 = artifact matches the manifest-derived census
|
||||
```
|
||||
|
||||
## License
|
||||
or from the repo root:
|
||||
|
||||
Data provided by GitHub under its API terms. Stars/forks as of retrieval; they change over time.
|
||||
```bash
|
||||
bash wizard-work/ledger/CHECK
|
||||
```
|
||||
|
||||
## Provenance
|
||||
|
||||
| Item | Value |
|
||||
| --- | --- |
|
||||
| Source manifest | `wizard-work/ledger/wizardwork-file-manifest.tsv` |
|
||||
| Source row count | 3426 files |
|
||||
| Distinct extensions | recomputed by the verifier at run time |
|
||||
| Extraction | `generate_ledger_extract.py` (stdlib only) |
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Inline discrepancy check between manifest CSV and emitted TSV (ad hoc probe)."""
|
||||
import csv
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
man = defaultdict(int)
|
||||
with open("/root/troupe-standup/wizard-work/ledger/wizardwork-census.csv") as f:
|
||||
r = csv.reader(f)
|
||||
next(r) # header
|
||||
for row in r:
|
||||
man[row[4]] += 1
|
||||
print("manifest:", dict(man), "total", sum(man.values()))
|
||||
|
||||
s = defaultdict(int)
|
||||
with open("/root/troupe-standup/wizard-work/ledger/wizardwork-census.tsv") as f:
|
||||
next(f)
|
||||
for line in f:
|
||||
p = line.rstrip("\n").split("\t")
|
||||
s[p[0]] = int(p[1])
|
||||
print("emitted:", dict(s), "total", sum(s.values()))
|
||||
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Verifier for ledger-extract.tsv.
|
||||
|
||||
Recomputes the census from the wizardwork file manifest and compares it
|
||||
field-for-field against the artifact. Exit code 0 = artifact correct,
|
||||
nonzero = wrong.
|
||||
"""
|
||||
import csv
|
||||
import statistics
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
|
||||
MANIFEST = "/root/troupe-standup/wizard-work/ledger/wizardwork-file-manifest.tsv"
|
||||
OUT = "/root/troupe-standup/wizard-work/ledger/ledger-extract.tsv"
|
||||
HEADER = ["extension", "file_count", "bytes_total", "bytes_mean",
|
||||
"bytes_median", "bytes_min", "bytes_max"]
|
||||
|
||||
|
||||
def norm_ext(ext):
|
||||
return "(no ext)" if ext == "" else ext
|
||||
|
||||
|
||||
def expected_rows():
|
||||
counts = defaultdict(int)
|
||||
sizes = defaultdict(list)
|
||||
with open(MANIFEST, newline="") as f:
|
||||
for line in f:
|
||||
parts = line.rstrip("\n").split("\t")
|
||||
if len(parts) < 3:
|
||||
continue
|
||||
try:
|
||||
size = int(parts[1])
|
||||
except ValueError:
|
||||
continue
|
||||
ext = norm_ext(parts[2])
|
||||
counts[ext] += 1
|
||||
sizes[ext].append(size)
|
||||
rows = []
|
||||
for ext, szs in sizes.items():
|
||||
total = sum(szs)
|
||||
rows.append((ext, counts[ext], total,
|
||||
total / counts[ext], statistics.median(szs),
|
||||
min(szs), max(szs)))
|
||||
rows.sort(key=lambda r: (-r[1], r[0]))
|
||||
return rows
|
||||
|
||||
|
||||
def main():
|
||||
expected = expected_rows()
|
||||
try:
|
||||
with open(OUT, newline="") as f:
|
||||
act = list(csv.DictReader(f, delimiter="\t"))
|
||||
except Exception as e:
|
||||
print("CHECK FAIL: cannot read %s: %r" % (OUT, e))
|
||||
sys.exit(1)
|
||||
|
||||
if not act:
|
||||
print("CHECK FAIL: artifact is empty")
|
||||
sys.exit(1)
|
||||
|
||||
if list(act[0].keys()) != HEADER:
|
||||
print("CHECK FAIL: header %r" % (list(act[0].keys()),))
|
||||
sys.exit(1)
|
||||
|
||||
if len(act) != len(expected):
|
||||
print("CHECK FAIL: row count %d != expected %d"
|
||||
% (len(act), len(expected)))
|
||||
sys.exit(1)
|
||||
|
||||
for i, (a, e) in enumerate(zip(act, expected), 1):
|
||||
ext, cnt, total, mean, med, mn, mx = e
|
||||
exp = {"extension": ext,
|
||||
"file_count": str(cnt),
|
||||
"bytes_total": str(total),
|
||||
"bytes_mean": "%.1f" % mean,
|
||||
"bytes_median": "%.1f" % med,
|
||||
"bytes_min": str(mn),
|
||||
"bytes_max": str(mx)}
|
||||
if a != exp:
|
||||
print("CHECK FAIL: row %d %r != %r" % (i, a, exp))
|
||||
sys.exit(1)
|
||||
|
||||
print("CHECK PASS: %d extension rows | top=%s count=%s"
|
||||
% (len(act), expected[0][0], expected[0][1]))
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,92 @@
|
||||
date,wizard,filename,n_lines,n_did,n_blocked,n_next,n_ask
|
||||
2026-09-24,zephyrus-02.md,2026-09-24-zephyrus-02.md,46,1,1,1,1
|
||||
2026-09-24,zephyrus.md,2026-09-24-zephyrus.md,18,1,1,1,1
|
||||
2026-09-25,zephyrus.md,2026-09-25-zephyrus.md,72,1,1,1,1
|
||||
2026-09-26,zephyrus-02.md,2026-09-26-zephyrus-02.md,29,0,0,0,0
|
||||
2026-09-26,zephyrus.md,2026-09-26-zephyrus.md,66,1,1,0,0
|
||||
2026-09-27,zephyrus.md,2026-09-27-zephyrus.md,15,1,1,1,4
|
||||
2026-09-28,zephyrus-02.md,2026-09-28-zephyrus-02.md,13,1,1,1,1
|
||||
2026-09-28,zephyrus.md,2026-09-28-zephyrus.md,14,1,1,1,4
|
||||
2026-09-30,zephyrus.md,2026-09-30-zephyrus.md,38,1,1,1,1
|
||||
2026-10-01,zephyrus-03.md,2026-10-01-zephyrus-03.md,17,0,0,0,0
|
||||
2026-10-01,zephyrus-04.md,2026-10-01-zephyrus-04.md,23,0,0,0,0
|
||||
2026-10-01,zephyrus-05.md,2026-10-01-zephyrus-05.md,6,0,0,0,0
|
||||
2026-10-01,zephyrus-06.md,2026-10-01-zephyrus-06.md,73,1,1,1,1
|
||||
2026-10-01,zephyrus-07.md,2026-10-01-zephyrus-07.md,40,0,0,0,0
|
||||
2026-10-01,zephyrus.md,2026-10-01-zephyrus.md,13,1,0,0,1
|
||||
2026-10-02,zephyrus-01.md,2026-10-02-zephyrus-01.md,159,0,0,0,0
|
||||
2026-10-03,zephyrus-02.md,2026-10-03-zephyrus-02.md,104,1,1,1,1
|
||||
2026-10-03,zephyrus-03.md,2026-10-03-zephyrus-03.md,57,1,1,1,1
|
||||
2026-10-03,zephyrus.md,2026-10-03-zephyrus.md,201,0,0,0,0
|
||||
2026-10-04,zephyrus-02.md,2026-10-04-zephyrus-02.md,86,1,1,1,1
|
||||
2026-10-04,zephyrus.md,2026-10-04-zephyrus.md,115,0,0,0,0
|
||||
2026-10-05,zephyrus-02.md,2026-10-05-zephyrus-02.md,80,0,1,0,1
|
||||
2026-10-05,zephyrus-03.md,2026-10-05-zephyrus-03.md,32,0,0,0,0
|
||||
2026-10-05,zephyrus.md,2026-10-05-zephyrus.md,85,0,0,0,1
|
||||
2026-10-06,cassian.md,2026-10-06-cassian.md,34,1,1,1,1
|
||||
2026-10-06,zephyrus-02.md,2026-10-06-zephyrus-02.md,72,0,1,1,0
|
||||
2026-10-06,zephyrus-04.md,2026-10-06-zephyrus-04.md,53,0,0,0,0
|
||||
2026-10-06,zephyrus-05.md,2026-10-06-zephyrus-05.md,56,0,0,0,0
|
||||
2026-10-06,zephyrus-06.md,2026-10-06-zephyrus-06.md,40,0,0,0,0
|
||||
2026-10-06,zephyrus-wizards-02.md,2026-10-06-zephyrus-wizards-02.md,10,0,0,0,0
|
||||
2026-10-06,zephyrus-wizards-03.md,2026-10-06-zephyrus-wizards-03.md,13,0,0,1,0
|
||||
2026-10-06,zephyrus-wizards.md,2026-10-06-zephyrus-wizards.md,24,1,1,0,1
|
||||
2026-10-06,zephyrus.md,2026-10-06-zephyrus.md,121,0,1,1,0
|
||||
2026-10-07,cassian-02.md,2026-10-07-cassian-02.md,73,1,1,1,1
|
||||
2026-10-07,cassian-q5-census.md,2026-10-07-cassian-q5-census.md,519,0,0,1,0
|
||||
2026-10-07,cassian-q5-recount.md,2026-10-07-cassian-q5-recount.md,19,0,0,0,0
|
||||
2026-10-07,cassian.md,2026-10-07-cassian.md,31,1,1,1,1
|
||||
2026-10-07,zephyrus-02.md,2026-10-07-zephyrus-02.md,35,0,0,0,0
|
||||
2026-10-07,zephyrus.md,2026-10-07-zephyrus.md,118,0,1,1,1
|
||||
2026-10-08,merlin.md,2026-10-08-merlin.md,138,2,2,3,2
|
||||
2026-10-08,zephyrus.md,2026-10-08-zephyrus.md,81,1,1,0,0
|
||||
2026-10-09,merlin.md,2026-10-09-merlin.md,173,1,1,1,1
|
||||
2026-10-09,zephyrus.md,2026-10-09-zephyrus.md,31,1,1,1,1
|
||||
2026-10-10,mercury.md,2026-10-10-mercury.md,30,1,1,1,1
|
||||
2026-10-10,merlin.md,2026-10-10-merlin.md,1128,6,6,6,6
|
||||
2026-10-10,zephyrus.md,2026-10-10-zephyrus.md,52,1,0,1,1
|
||||
2026-10-11,mercury.md,2026-10-11-mercury.md,31,1,1,1,1
|
||||
2026-10-11,merlin.md,2026-10-11-merlin.md,1246,10,10,10,10
|
||||
2026-10-11,zephyrus.md,2026-10-11-zephyrus.md,49,2,0,1,2
|
||||
2026-10-12,mercury.md,2026-10-12-mercury.md,42,1,1,1,1
|
||||
2026-10-12,merlin.md,2026-10-12-merlin.md,1563,8,11,11,11
|
||||
2026-10-12,zephyrus.md,2026-10-12-zephyrus.md,13,1,1,2,1
|
||||
2026-10-13,gemini.md,2026-10-13-gemini.md,29,1,1,1,1
|
||||
2026-10-13,mercury.md,2026-10-13-mercury.md,22,1,1,1,1
|
||||
2026-10-13,merlin.md,2026-10-13-merlin.md,1392,11,11,10,12
|
||||
2026-10-13,zephyrus.md,2026-10-13-zephyrus.md,36,1,1,0,0
|
||||
2026-10-14,mercury.md,2026-10-14-mercury.md,25,1,1,1,1
|
||||
2026-10-14,merlin.md,2026-10-14-merlin.md,1636,11,11,11,11
|
||||
2026-10-14,zephyrus.md,2026-10-14-zephyrus.md,49,1,1,1,1
|
||||
2026-10-15,mercury.md,2026-10-15-mercury.md,34,1,1,1,1
|
||||
2026-10-15,merlin.md,2026-10-15-merlin.md,1158,8,8,8,9
|
||||
2026-10-15,volt.md,2026-10-15-volt.md,281,2,2,2,3
|
||||
2026-10-15,zephyrus.md,2026-10-15-zephyrus.md,48,1,1,1,1
|
||||
2026-10-16,mercury.md,2026-10-16-mercury.md,25,1,1,1,1
|
||||
2026-10-16,volt.md,2026-10-16-volt.md,481,0,0,0,0
|
||||
2026-10-16,zephyrus.md,2026-10-16-zephyrus.md,56,1,1,1,1
|
||||
2026-10-17,mercury.md,2026-10-17-mercury.md,26,1,1,1,1
|
||||
2026-10-17,volt.md,2026-10-17-volt.md,624,0,0,0,0
|
||||
2026-10-17,zephyrus.md,2026-10-17-zephyrus.md,21,1,1,0,0
|
||||
2026-10-18,mercury.md,2026-10-18-mercury.md,29,1,1,1,1
|
||||
2026-10-18,volt.md,2026-10-18-volt.md,534,9,10,11,12
|
||||
2026-10-18,zephyrus.md,2026-10-18-zephyrus.md,17,1,1,0,1
|
||||
2026-10-19,mercury.md,2026-10-19-mercury.md,18,1,1,1,1
|
||||
2026-10-19,volt.md,2026-10-19-volt.md,487,6,7,8,6
|
||||
2026-10-19,zephyrus.md,2026-10-19-zephyrus.md,16,1,1,0,1
|
||||
2026-10-20,mercury.md,2026-10-20-mercury.md,27,1,1,1,1
|
||||
2026-10-20,volt.md,2026-10-20-volt.md,137,1,2,2,2
|
||||
2026-10-20,zephyrus.md,2026-10-20-zephyrus.md,21,1,1,0,1
|
||||
2026-10-21,mercury.md,2026-10-21-mercury.md,27,1,1,1,1
|
||||
2026-10-21,volt.md,2026-10-21-volt.md,20,1,1,1,1
|
||||
2026-10-21,zephyrus.md,2026-10-21-zephyrus.md,22,1,1,0,1
|
||||
2026-10-22,mercury.md,2026-10-22-mercury.md,28,1,1,1,1
|
||||
2026-10-22,zephyrus.md,2026-10-22-zephyrus.md,9,1,1,1,4
|
||||
2026-10-23,mercury.md,2026-10-23-mercury.md,28,1,1,1,1
|
||||
2026-10-23,volt.md,2026-10-23-volt.md,21,1,1,1,1
|
||||
2026-10-23,zephyrus.md,2026-10-23-zephyrus.md,13,1,1,1,2
|
||||
2026-10-24,mercury.md,2026-10-24-mercury.md,28,1,1,1,1
|
||||
2026-10-24,zephyrus.md,2026-10-24-zephyrus.md,18,1,1,1,1
|
||||
2026-10-25,mercury.md,2026-10-25-mercury.md,28,1,1,1,1
|
||||
2026-10-25,volt.md,2026-10-25-volt.md,44,3,3,3,3
|
||||
2026-10-25,zephyrus.md,2026-10-25-zephyrus.md,80,1,1,0,1
|
||||
|
+92
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Independent verification of checkin-inventory.csv.
|
||||
|
||||
Two independent implementations of the same extraction spec:
|
||||
build : os.listdir() + open/read + re.match() + str.count()
|
||||
verify: os.scandir() + Path.read_text() + re.fullmatch() + str.count()
|
||||
|
||||
Exits 0 only if the CSV's rows equal a fresh recomputation from the source files.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import csv
|
||||
|
||||
SRC = "/root/troupe-standup/checkins"
|
||||
CSV_PATH = "/root/troupe-standup/wizard-work/ledger/checkin-inventory.csv"
|
||||
PAT = re.compile(r"^(\d{4}-\d{2}-\d{2})-(.+)$")
|
||||
FIELDS = ["date", "wizard", "filename", "n_lines", "n_did", "n_blocked", "n_next", "n_ask"]
|
||||
|
||||
|
||||
def build_expected():
|
||||
rows = []
|
||||
with os.scandir(SRC) as it:
|
||||
for entry in it:
|
||||
if not entry.is_file():
|
||||
continue
|
||||
name = entry.name
|
||||
if not name.endswith(".md"):
|
||||
continue
|
||||
m = PAT.fullmatch(name)
|
||||
if not m:
|
||||
continue
|
||||
date, wizard = m.group(1), m.group(2)
|
||||
with open(entry.path, encoding="utf-8", errors="replace") as fh:
|
||||
data = fh.read()
|
||||
rows.append((date, wizard, name, data.count("\n"),
|
||||
data.count("Did"), data.count("Blocked"),
|
||||
data.count("Next"), data.count("Ask")))
|
||||
rows.sort(key=lambda r: (r[0], r[1]))
|
||||
return rows
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def _norm(row):
|
||||
d = dict(row)
|
||||
for k in ("n_lines", "n_did", "n_blocked", "n_next", "n_ask"):
|
||||
d[k] = int(d[k])
|
||||
return tuple(d[h] for h in FIELDS)
|
||||
|
||||
|
||||
def read_csv():
|
||||
with open(CSV_PATH, newline="", encoding="utf-8") as fh:
|
||||
reader = csv.DictReader(fh)
|
||||
assert reader.fieldnames == FIELDS, f"header mismatch: {reader.fieldnames}"
|
||||
return [_norm(r) for r in reader]
|
||||
|
||||
|
||||
def main():
|
||||
ok = True
|
||||
try:
|
||||
expected = build_expected()
|
||||
actual = read_csv()
|
||||
except Exception as exc: # noqa: BLE001
|
||||
print("FAIL: could not load source or artifact:", exc)
|
||||
return 1
|
||||
|
||||
if len(expected) != len(actual):
|
||||
ok = False
|
||||
print(f"FAIL: row count mismatch: expected {len(expected)}, actual {len(actual)}")
|
||||
|
||||
diff = 0
|
||||
for i in range(max(len(expected), len(actual))):
|
||||
exp = expected[i] if i < len(expected) else None
|
||||
act = actual[i] if i < len(actual) else None
|
||||
if exp != act:
|
||||
ok = False
|
||||
diff += 1
|
||||
print(f"FAIL row {i + 1}: expected={exp} actual={act}")
|
||||
|
||||
if ok:
|
||||
print(f"PASS: {len(actual)} check-in rows match the source files "
|
||||
f"({len(set(r[0] for r in actual))} distinct dates, "
|
||||
f"{sorted(set(r[1] for r in actual))})")
|
||||
else:
|
||||
print(f"FAIL: {diff} differing rows")
|
||||
return 0 if ok else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,165 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Extract the wizard-work directory census: one finished data-artifact table.
|
||||
|
||||
Lane: Extract (data extraction and tables).
|
||||
|
||||
Scopes (real, from this host's filesystem):
|
||||
* every top-level directory under /root/troupe-standup/wizard-work
|
||||
* every regular file under it (full manifest, including cache-tree files)
|
||||
|
||||
Per-directory summary columns:
|
||||
dir : top-level directory name
|
||||
files : regular files (all, incl. inside cache trees)
|
||||
scripts : .py / .sh files
|
||||
data : .csv / .json / .tsv / .xml / .txt
|
||||
docs : .md files (incl. README.md)
|
||||
caches : cache directories (__pycache__/.pytest_cache/.ruff_cache)
|
||||
other : everything else
|
||||
check : CHECK file path relative to the root, or "-" when none
|
||||
checkok : "yes" when an executable CHECK is present, else "no"
|
||||
|
||||
Outputs
|
||||
wizardwork-census.tsv : summary table (TSV)
|
||||
wizardwork-census.csv : full file manifest (CSV)
|
||||
wizardwork-census.md : markdown table (the human-facing artifact)
|
||||
CHECK-wizardwork-census : a shell verifier that recomputes the census and diffs
|
||||
"""
|
||||
import csv
|
||||
import os
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(os.environ.get("WIZARDWORK_ROOT", "/root/troupe-standup/wizard-work"))
|
||||
OUT = Path(os.environ.get("WIZARDWORK_OUT", "/root/troupe-standup/wizard-work/ledger"))
|
||||
SUMMARY_NAME = "wizardwork-census.tsv"
|
||||
MANIFEST_NAME = "wizardwork-census.csv"
|
||||
|
||||
SCRIPT_EXTS = {".py", ".sh"}
|
||||
DATA_EXTS = {".csv", ".json", ".tsv", ".xml", ".txt"}
|
||||
DOC_EXTS = {".md"}
|
||||
CACHE_DIRS = {"__pycache__", ".pytest_cache", ".ruff_cache"}
|
||||
|
||||
|
||||
def bucket(ext: str) -> str:
|
||||
if ext in SCRIPT_EXTS:
|
||||
return "script"
|
||||
if ext in DATA_EXTS:
|
||||
return "data"
|
||||
if ext in DOC_EXTS:
|
||||
return "doc"
|
||||
return "other"
|
||||
|
||||
|
||||
def build():
|
||||
rows = []
|
||||
summary = defaultdict(lambda: defaultdict(int))
|
||||
totals = defaultdict(int)
|
||||
|
||||
for top in sorted(ROOT.iterdir()):
|
||||
if not top.is_dir():
|
||||
continue
|
||||
has_exec_check = False
|
||||
for dirpath, dirnames, filenames in os.walk(top):
|
||||
for d in dirnames:
|
||||
if d in CACHE_DIRS:
|
||||
summary[top.name]["caches"] += 1
|
||||
for fn in filenames:
|
||||
p = Path(dirpath) / fn
|
||||
rel = p.relative_to(ROOT)
|
||||
ext = p.suffix.lower()
|
||||
b = bucket(ext)
|
||||
if b == "script":
|
||||
summary[top.name]["scripts"] += 1
|
||||
totals["scripts"] += 1
|
||||
elif b == "data":
|
||||
summary[top.name]["data"] += 1
|
||||
totals["data"] += 1
|
||||
elif b == "doc":
|
||||
summary[top.name]["docs"] += 1
|
||||
totals["docs"] += 1
|
||||
else:
|
||||
summary[top.name]["other"] += 1
|
||||
totals["other"] += 1
|
||||
summary[top.name]["files"] += 1
|
||||
totals["files"] += 1
|
||||
if os.access(p, os.X_OK) and fn.lower().startswith("check"):
|
||||
has_exec_check = True
|
||||
rows.append({
|
||||
"rel": rel.as_posix(),
|
||||
"size": p.stat().st_size,
|
||||
"ext": ext or "(no ext)",
|
||||
"kind": b,
|
||||
"top": top.name,
|
||||
})
|
||||
if has_exec_check:
|
||||
summary[top.name]["check"] = rel_check(top)
|
||||
summary[top.name]["checkok"] = "yes"
|
||||
else:
|
||||
summary[top.name]["check"] = "-"
|
||||
summary[top.name]["checkok"] = "no"
|
||||
|
||||
# ---- manifest CSV ----
|
||||
with open(OUT / MANIFEST_NAME, "w", newline="") as fh:
|
||||
w = csv.writer(fh, lineterminator="\n")
|
||||
w.writerow(["path", "size_bytes", "extension", "kind", "top_dir"])
|
||||
for r in sorted(rows, key=lambda x: x["rel"]):
|
||||
w.writerow([r["rel"], r["size"], r["ext"], r["kind"], r["top"]])
|
||||
|
||||
# ---- summary TSV ----
|
||||
hdr = ["dir", "files", "scripts", "data", "docs", "caches", "other", "check", "checkok"]
|
||||
with open(OUT / SUMMARY_NAME, "w") as fh:
|
||||
fh.write("\t".join(hdr) + "\n")
|
||||
for top in sorted(summary):
|
||||
s = summary[top]
|
||||
fh.write("\t".join([
|
||||
top, str(s["files"]), str(s["scripts"]), str(s["data"]),
|
||||
str(s["docs"]), str(s["caches"]), str(s.get("other", 0)),
|
||||
s.get("check", "-"), s.get("checkok", "no"),
|
||||
]) + "\n")
|
||||
|
||||
# ---- markdown table ----
|
||||
md = []
|
||||
md.append("# wizard-work directory census")
|
||||
md.append("")
|
||||
md.append("Extract — data extraction and tables. Derived on this host from")
|
||||
md.append("`find /root/troupe-standup/wizard-work -type f` (2026-10-26).")
|
||||
md.append("")
|
||||
md.append("| dir | files | scripts | data | docs | caches | other | check | checkok |")
|
||||
md.append("|---|---|---|---|---|---|---|---|---|")
|
||||
for top in sorted(summary):
|
||||
s = summary[top]
|
||||
md.append(f"| {top} | {s['files']} | {s['scripts']} | {s['data']} | "
|
||||
f"{s['docs']} | {s['caches']} | {s.get('other', 0)} | "
|
||||
f"{s.get('check', '-')} | {s.get('checkok', 'no')} |")
|
||||
md.append("")
|
||||
md.append("Totals: 9 top-level directories, "
|
||||
f"{totals['files']} files "
|
||||
f"({totals['scripts']} script, {totals['data']} data, "
|
||||
f"{totals['docs']} doc, {totals['other']} other, "
|
||||
f"{totals['caches']} cache dirs).")
|
||||
md.append("")
|
||||
with open(OUT / "wizardwork-census.md", "w") as fh:
|
||||
fh.write("\n".join(md))
|
||||
|
||||
print("wrote:", OUT / SUMMARY_NAME)
|
||||
print("wrote:", OUT / MANIFEST_NAME)
|
||||
print("wrote:", OUT / "wizardwork-census.md")
|
||||
print("total dirs:", len(summary), "total files:", totals["files"])
|
||||
for top in sorted(summary):
|
||||
s = summary[top]
|
||||
print(f" {top:22s} files={s['files']:4d} script={s['scripts']:4d} "
|
||||
f"data={s['data']:4d} docs={s['docs']:4d} caches={s['caches']:3d} "
|
||||
f"other={s.get('other', 0):4d} check={s.get('check','-')} checkok={s.get('checkok','no')}")
|
||||
|
||||
|
||||
def rel_check(top: Path) -> str:
|
||||
chk = [p for p in top.rglob("CHECK") if p.is_file() and os.access(p, os.X_OK)]
|
||||
if not chk:
|
||||
chk = [p for p in top.rglob("CHECK*") if p.is_file() and os.access(p, os.X_OK)]
|
||||
if not chk:
|
||||
chk = [p for p in top.rglob("check*") if p.is_file() and os.access(p, os.X_OK)]
|
||||
return chk[0].relative_to(ROOT).as_posix() if chk else "-"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
build()
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Clean, self-contained manifest generator (tab-delimited; no CSV quoting issues)."""
|
||||
import os
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(os.environ.get("WIZARDWORK_ROOT", "/root/troupe-standup/wizard-work"))
|
||||
OUT = Path(os.environ.get("WIZARDWORK_OUT", "/root/troupe-standup/wizard-work/ledger"))
|
||||
MANIFEST = OUT / "wizardwork-file-manifest.tsv" # tab-delimited manifest
|
||||
|
||||
def build():
|
||||
rows = []
|
||||
for top in sorted(ROOT.iterdir()):
|
||||
if not top.is_dir():
|
||||
continue
|
||||
for dirpath, _dirnames, filenames in os.walk(top):
|
||||
for fn in filenames:
|
||||
p = Path(dirpath) / fn
|
||||
rel = p.relative_to(ROOT)
|
||||
rows.append((rel.as_posix(), p.stat().st_size, fn, top.name))
|
||||
rows.sort()
|
||||
with open(MANIFEST, "w") as f:
|
||||
for rel, size, fn, top in rows:
|
||||
f.write(f"{rel}\t{size}\t{fn}\t{top}\n")
|
||||
print("manifest written:", MANIFEST, "rows:", len(rows))
|
||||
|
||||
if __name__ == "__main__":
|
||||
build()
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate the per-extension file census table from the wizardwork file manifest.
|
||||
|
||||
Reads : /root/troupe-standup/wizard-work/ledger/wizardwork-file-manifest.tsv
|
||||
tab-separated, NO header: path, size_bytes, extension, top_dir
|
||||
Writes: /root/troupe-standup/wizard-work/ledger/ledger-extract.tsv
|
||||
tab-separated: extension, file_count, bytes_total, bytes_mean,
|
||||
bytes_median, bytes_min, bytes_max
|
||||
sorted by file_count desc, then extension asc (deterministic).
|
||||
"""
|
||||
import csv
|
||||
import statistics
|
||||
from collections import defaultdict
|
||||
|
||||
MANIFEST = "/root/troupe-standup/wizard-work/ledger/wizardwork-file-manifest.tsv"
|
||||
OUT = "/root/troupe-standup/wizard-work/ledger/ledger-extract.tsv"
|
||||
|
||||
|
||||
def norm_ext(ext):
|
||||
return "(no ext)" if ext == "" else ext
|
||||
|
||||
|
||||
def main():
|
||||
counts = defaultdict(int)
|
||||
sizes = defaultdict(list)
|
||||
with open(MANIFEST, newline="") as f:
|
||||
for line in f:
|
||||
parts = line.rstrip("\n").split("\t")
|
||||
if len(parts) < 3:
|
||||
continue
|
||||
try:
|
||||
size = int(parts[1])
|
||||
except ValueError:
|
||||
continue
|
||||
ext = norm_ext(parts[2])
|
||||
counts[ext] += 1
|
||||
sizes[ext].append(size)
|
||||
|
||||
rows = []
|
||||
for ext, szs in sizes.items():
|
||||
total = sum(szs)
|
||||
mean = total / counts[ext]
|
||||
med = statistics.median(szs)
|
||||
rows.append((ext, counts[ext], total, mean, med, min(szs), max(szs)))
|
||||
|
||||
rows.sort(key=lambda r: (-r[1], r[0]))
|
||||
|
||||
with open(OUT, "w", newline="") as f:
|
||||
w = csv.writer(f, delimiter="\t", lineterminator="\n")
|
||||
w.writerow(["extension", "file_count", "bytes_total", "bytes_mean",
|
||||
"bytes_median", "bytes_min", "bytes_max"])
|
||||
for ext, cnt, total, mean, med, mn, mx in rows:
|
||||
w.writerow([ext, cnt, total, "%.1f" % mean, "%.1f" % med, mn, mx])
|
||||
|
||||
print("Wrote %d extension rows to %s" % (len(rows), OUT))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,54 @@
|
||||
# Stackchain Magazine photo catalog - extracted table
|
||||
|
||||
_Normalized from `stackchain_catalog_raw.json`, `stackchain_catalog_batch2.json`, `stackchain_catalog_batch3.json`. One row per catalog image file. "transcribed" = source carried a JSON entry with non-empty type and text._
|
||||
|
||||
| Image file | Type | Status | Transcription source | Identifiers (excerpt) | Text excerpt |
|
||||
|---|---|---|---|---|---|
|
||||
| img_05d51da1fd9d.jpg | COVER | transcribed | batch2.json | No @handles or amounts are readable. Bitcoin (₿) symbols appear on the gold coin held by the center character and on the | STACKCHAIN
|
||||
MAGAZINE
|
||||
CAPTAIN'S LOG 4 TO BOLDY STACK
|
||||
WHERE NO ONE HAS STACKED
|
||||
BEFORE. A NEW ALL TIME H |
|
||||
| img_125532ea2e01.jpg | COVER | transcribed | batch2.json | Block height printed on the orange band: 'B/H: 850,683'. Publication/brand name visible in the cover text: 'STACKCHAIN'. | B/H: 850,683
|
||||
BY NOTHING YOU DESERVE
|
||||
TOM SAVES 10 STACKCHAIN
|
||||
BY THE TIME THE BUYING [unreadable]
|
||||
FOMO |
|
||||
| img_1325775751e6.jpg | PAGE | transcribed | batch3.json | No @handles visible. QR code printed on the left page edge; "Stackchainers" branding label in the party meme; amounts re | [unreadable]CLASSIC
|
||||
PERO
|
||||
ional rapper.
|
||||
I was a slave yesterday
|
||||
Man how did you become so rich?
|
||||
Fucki |
|
||||
| img_67eedaf526e7.jpg | - | unparsed-entry | raw.json | | {
|
||||
"type": "COVER",
|
||||
"text": "STACKCHAIN\nMAGAZINE\nROUND 5\nINTERVIEW WITH MADEX\nBY ISBELL\n88K |
|
||||
| img_72f52468393f.jpg | PAGE | transcribed | batch3.json | STACKCHAIN MAGAZINE logo; @chain; #GoPio; #DSB; D&B GANG; amounts: 58K, 58k, 59k, 100K, 100k, $417.00, $580.00; no block | STACKCHAIN MAGAZINE
|
||||
58K MEMES
|
||||
58K
|
||||
#GoPio
|
||||
$417.00
|
||||
58k @chain
|
||||
JOIN LBDC STABLECOIN
|
||||
CHOOSE FREEDOM D&B |
|
||||
| img_7333a3df0aac.jpg | PAGE | transcribed | batch3.json | @Lokopettyfork, LokoPettyFork, Lokopettyfork; 'verizon' logo; 'MSTR' ticker; Bitcoin logo; amounts: $70,206.87, $10.00, | LOKOPETTYFORK
|
||||
GANG FOREVER
|
||||
$10.00
|
||||
YOU ARE PART OF
|
||||
THE REBEL ALLIANCE,
|
||||
AND A TRAITOR!
|
||||
LokoPettyFork
|
||||
D |
|
||||
| img_d5ada9cee4e9.jpg | PAGE | transcribed | batch3.json | none | DS #GOPIOS
|
||||
What I think I look like
|
||||
GO Pios
|
||||
What I actually look like
|
||||
Say 'Go Pios'
|
||||
LEAVE IT ON.
|
||||
#GO |
|
||||
| img_fcb2e6a8f066.jpg | PHOTO_OF_PERSON_HOLDING_MAGAZINE | transcribed | raw.json | Spine call-number label reading 'B/H872.372'. Magazine cover logo appears as 'MACHINA' with accompanying cover line 'SEL | B/H872.372
|
||||
[unreadable]O CHAIN
|
||||
[unreadable]INE
|
||||
[unreadable]OUND 5
|
||||
MACHINA
|
||||
SELF-CUSTODY//BIT[unreadab |
|
||||
@@ -0,0 +1,82 @@
|
||||
[
|
||||
{
|
||||
"file": "img_05d51da1fd9d.jpg",
|
||||
"type": "COVER",
|
||||
"status": "transcribed",
|
||||
"source": "batch2.json",
|
||||
"text": "STACKCHAIN\nMAGAZINE\nCAPTAIN'S LOG 4 TO BOLDY STACK\nWHERE NO ONE HAS STACKED\nBEFORE. A NEW ALL TIME HIGH\nINTERVIEW WITH LINA SEICHE (THE LITTLE HODLER)\nBY TSELLY\nTHE OBSTACLE IS THE WAY: FINDING HOPE IN BITCOIN\nBY HUMBLE WARRIOR\nTWO YEARS OF STACKCHAIN\nBY ANTHONY VON DESSAUER",
|
||||
"identifiers": "No @handles or amounts are readable. Bitcoin (\u20bf) symbols appear on the gold coin held by the center character and on the octopus-like character's head. Logo mark in lower-left corner: cartoon monkey wearing a red bandana with the word 'MAGAZINE' beneath it.",
|
||||
"text_excerpt": "STACKCHAIN\nMAGAZINE\nCAPTAIN'S LOG 4 TO BOLDY STACK\nWHERE NO ONE HAS STACKED\nBEFORE. A NEW ALL TIME H",
|
||||
"identifiers_excerpt": "No @handles or amounts are readable. Bitcoin (\u20bf) symbols appear on the gold coin held by the center character and on the"
|
||||
},
|
||||
{
|
||||
"file": "img_125532ea2e01.jpg",
|
||||
"type": "COVER",
|
||||
"status": "transcribed",
|
||||
"source": "batch2.json",
|
||||
"text": "B/H: 850,683\nBY NOTHING YOU DESERVE\nTOM SAVES 10 STACKCHAIN\nBY THE TIME THE BUYING [unreadable]\nFOMO IN THE [unreadable] HOPE [unreadable]\nBY STACKING SATS, [unreadable]\nBUY STACKCHAIN AND HODL THE LITTLE [unreadable]\n[unreadable]",
|
||||
"identifiers": "Block height printed on the orange band: 'B/H: 850,683'. Publication/brand name visible in the cover text: 'STACKCHAIN'. No @handles, avatars, or sats amounts are readable; the only numeric identifier is the block height 850,683.",
|
||||
"text_excerpt": "B/H: 850,683\nBY NOTHING YOU DESERVE\nTOM SAVES 10 STACKCHAIN\nBY THE TIME THE BUYING [unreadable]\nFOMO",
|
||||
"identifiers_excerpt": "Block height printed on the orange band: 'B/H: 850,683'. Publication/brand name visible in the cover text: 'STACKCHAIN'."
|
||||
},
|
||||
{
|
||||
"file": "img_1325775751e6.jpg",
|
||||
"type": "PAGE",
|
||||
"status": "transcribed",
|
||||
"source": "batch3.json",
|
||||
"text": "[unreadable]CLASSIC\nPERO\nional rapper.\nI was a slave yesterday\nMan how did you become so rich?\nFucking Legend\nGFY\nHon. Yellow\nMEME MUSEUM\n[unreadable]\nYou guys should check out coinbase\nStackchainers\nHow did you afford this house Dad?\nWell it all started when Bananahodl stacked 1888 which, of course, Tao forked and then Ant...\nFucking legend\nGFY\nNO.\n70K\n85.11",
|
||||
"identifiers": "No @handles visible. QR code printed on the left page edge; \"Stackchainers\" branding label in the party meme; amounts referenced: 1888 (stacked), 70K, and a small partially legible label reading 85.11.",
|
||||
"text_excerpt": "[unreadable]CLASSIC\nPERO\nional rapper.\nI was a slave yesterday\nMan how did you become so rich?\nFucki",
|
||||
"identifiers_excerpt": "No @handles visible. QR code printed on the left page edge; \"Stackchainers\" branding label in the party meme; amounts re"
|
||||
},
|
||||
{
|
||||
"file": "img_67eedaf526e7.jpg",
|
||||
"type": "-",
|
||||
"status": "unparsed-entry",
|
||||
"source": "raw.json",
|
||||
"text": "{\n \"type\": \"COVER\",\n \"text\": \"STACKCHAIN\\nMAGAZINE\\nROUND 5\\nINTERVIEW WITH MADEX\\nBY ISBELL\\n88K CHRONICLES: HOW ICO CONSPIRED\\nTO SUPPRESS THE BITCOIN PRICE\\nBY DENIZ\\nREASONS TO BUY ALTCOINS\\nBY SKYLER\\nSELF-CUSTODY//BITCOIN ONLY\\nMAGAZINE\\n18+\\nstackchain\\nMAGAZINE\\nMADE IN [unreadable]\\n[unreadable graffiti tags on the owl artwork]\",\n \"visual\": \"A photographed, slightly angled shot of the Stackchain Magazine Round 5 cover (the frame is rotated roughly 90 degrees, so the cover's masthead runs vertically along the right edge in this photo). Collage-style design on a dark background: the left two-thirds is dominated by an overlapping print/poster of a massive owl- or griffin-like creature with a fierce staring yellow-orange eye and black-and-white striped/feathered plumage, set against a bright red sun disc, surrounded by explosive red, orange and black paint splatters and graffiti scrawls. Layered over/behind it is a dark interior photo of a bearded man in a black t-shirt with tattooed forearms, wearing a plaid flannel shirt and holding a camera to his face as if shooting the scene. Along the right edge, the word STACKCHAIN is rendered in large glowing neon-orange outlined capitals with a strong halo/bloom effect, with MAGAZINE and ROUND 5 in matching smaller orange neon type beneath it, plus a couple of orange diamond/star shapes. In the lower area, a large white graffiti-style tag reads MAGAZINE in mirrored/flipped letterforms, sitting above it the mirrored line SELF-CUSTODY//BITCOIN ONLY. In the bottom-left corner sits the magazine's mascot logo: a cartoon monkey/chimp face wearing an orange bandana, with cursive 'stackchain' and MAGAZINE text, next to a small circular 18+ badge. Overall palette: neon orange, red, black, and white, with a gritty street-art/photocollage aesthetic.\",\n \"identifiers\": \"Stackchain Magazine mascot logo: cartoon monkey/chimp in an orange bandana with cursive 'stackchain' wordmark and MAGAZINE (bottom-left corner), plus a circular '18+' age badge. Mirrored/reversed text elements on the cover: 'SELF-CUSTODY//BITCOIN ONLY' and graffiti-style 'MAGAZINE' tag (letterforms are flipped, indicating the artwork/photo is mirror-reversed). Related credit lines appear as plain names: MADEX, ISBELL, DENIZ, SKYLER (no @",
|
||||
"identifiers": "",
|
||||
"text_excerpt": "{\n \"type\": \"COVER\",\n \"text\": \"STACKCHAIN\\nMAGAZINE\\nROUND 5\\nINTERVIEW WITH MADEX\\nBY ISBELL\\n88K ",
|
||||
"identifiers_excerpt": ""
|
||||
},
|
||||
{
|
||||
"file": "img_72f52468393f.jpg",
|
||||
"type": "PAGE",
|
||||
"status": "transcribed",
|
||||
"source": "batch3.json",
|
||||
"text": "STACKCHAIN MAGAZINE\n58K MEMES\n58K\n#GoPio\n$417.00\n58k @chain\nJOIN LBDC STABLECOIN\nCHOOSE FREEDOM D&B GANG TO 100K\nWENT BACK TO REMOVE 58K FROM THE CHAIN\nFACK EVERYTHING\nThe halvening\n58k forever\ndon't sell\nwe're so back\nLFG\npump it!!!\n58k forever\nEXPECTATIONS\n100k\n58k\nbitchcoin reality\nU wake up and see the price at 58k\nImmediately u buy and stack to Lokepetyfork\n1, U save the raccoons\n2, U raise the price to 59k\n#DSB to 100k\n58K MAXI\n$580.00\n58K\nPLEBS\nSTACKCHAIN MAGA",
|
||||
"identifiers": "STACKCHAIN MAGAZINE logo; @chain; #GoPio; #DSB; D&B GANG; amounts: 58K, 58k, 59k, 100K, 100k, $417.00, $580.00; no block heights visible",
|
||||
"text_excerpt": "STACKCHAIN MAGAZINE\n58K MEMES\n58K\n#GoPio\n$417.00\n58k @chain\nJOIN LBDC STABLECOIN\nCHOOSE FREEDOM D&B ",
|
||||
"identifiers_excerpt": "STACKCHAIN MAGAZINE logo; @chain; #GoPio; #DSB; D&B GANG; amounts: 58K, 58k, 59k, 100K, 100k, $417.00, $580.00; no block"
|
||||
},
|
||||
{
|
||||
"file": "img_7333a3df0aac.jpg",
|
||||
"type": "PAGE",
|
||||
"status": "transcribed",
|
||||
"source": "batch3.json",
|
||||
"text": "LOKOPETTYFORK\nGANG FOREVER\n$10.00\nYOU ARE PART OF\nTHE REBEL ALLIANCE,\nAND A TRAITOR!\nLokoPettyFork\nDon't Stop Believing\nBitcoin\n$70,206.87\n\u25b2 3,052.52 (3.01%) Past Year\nverizon\nMEME\nMUSEUM\n100\nSAY NO TO 58K CBDC STABLECOIN\nCHOOSE FREEDOM \u20bfSB GANG TO 100K!\nBUY BITCOIN\nBUY BITCOIN\nBUY BITCOIN\nBUY BITCOIN\n$100.00\n@Lokopettyfork\n8722100\nWHAT IS YOUR KEY TO SUCCESS?\nLOOK, OTHERS BUY MSTR, I JUST STACK TO LOKOPETTYFORK IT'S NOT SOOO COMPLICATED\n100\nLokopettyfork",
|
||||
"identifiers": "@Lokopettyfork, LokoPettyFork, Lokopettyfork; 'verizon' logo; 'MSTR' ticker; Bitcoin logo; amounts: $70,206.87, $10.00, 3,052.52, 3.01%, 58K, 100K, $100, 100, $100.00, 8722100; '\u20bfSB' reference.",
|
||||
"text_excerpt": "LOKOPETTYFORK\nGANG FOREVER\n$10.00\nYOU ARE PART OF\nTHE REBEL ALLIANCE,\nAND A TRAITOR!\nLokoPettyFork\nD",
|
||||
"identifiers_excerpt": "@Lokopettyfork, LokoPettyFork, Lokopettyfork; 'verizon' logo; 'MSTR' ticker; Bitcoin logo; amounts: $70,206.87, $10.00, "
|
||||
},
|
||||
{
|
||||
"file": "img_d5ada9cee4e9.jpg",
|
||||
"type": "PAGE",
|
||||
"status": "transcribed",
|
||||
"source": "batch3.json",
|
||||
"text": "DS #GOPIOS\nWhat I think I look like\nGO Pios\nWhat I actually look like\nSay 'Go Pios'\nLEAVE IT ON.\n#GOPIOS\nCarroll University\nBitcoin Twitter\nMe: GOPIOS\n#GoPios\n#Go Pios\nGFY\n#GoPios\nvechains\nElection\n58kgs\nMe, just vibing to GO PIOS\nGO PIOS\nPIZZA? BLOCK? ALL TIME HIGHS?\nGO PIOS!\nSoul ETF\nWEN\nGM\nGOPIOS\nSTOP BELIEV\nCARROLL\n6",
|
||||
"identifiers": "none",
|
||||
"text_excerpt": "DS #GOPIOS\nWhat I think I look like\nGO Pios\nWhat I actually look like\nSay 'Go Pios'\nLEAVE IT ON.\n#GO",
|
||||
"identifiers_excerpt": "none"
|
||||
},
|
||||
{
|
||||
"file": "img_fcb2e6a8f066.jpg",
|
||||
"type": "PHOTO_OF_PERSON_HOLDING_MAGAZINE",
|
||||
"status": "transcribed",
|
||||
"source": "raw.json",
|
||||
"text": "B/H872.372\n[unreadable]O CHAIN\n[unreadable]INE\n[unreadable]OUND 5\nMACHINA\nSELF-CUSTODY//BIT[unreadable]",
|
||||
"identifiers": "Spine call-number label reading 'B/H872.372'. Magazine cover logo appears as 'MACHINA' with accompanying cover line 'SELF-CUSTODY//BIT[unreadable]'. No @handles, avatars, watermarks, block heights, or sat amounts are readable in the image.",
|
||||
"text_excerpt": "B/H872.372\n[unreadable]O CHAIN\n[unreadable]INE\n[unreadable]OUND 5\nMACHINA\nSELF-CUSTODY//BIT[unreadab",
|
||||
"identifiers_excerpt": "Spine call-number label reading 'B/H872.372'. Magazine cover logo appears as 'MACHINA' with accompanying cover line 'SEL"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Isolated scratch test of gen_manifest.py."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
# make scratch dirs
|
||||
os.makedirs("/tmp/scratch_wiz", exist_ok=True)
|
||||
open("/tmp/scratch_wiz/a.txt", "w").write("hello")
|
||||
open("/tmp/scratch_wiz/b.sh", "w").write("#!/bin/bash\necho hi\n")
|
||||
open("/tmp/scratch_wiz/beam/CHECK", "w").write("#!/bin/bash\n# CHECK: verify\nset -e\ncd \"$(dirname \"$(readlink -f \"$0\")\")\"\necho content > /tmp/x\n")
|
||||
|
||||
sys.path.insert(0, "/root/troupe-standup/wizard-work/ledger")
|
||||
import importlib.util
|
||||
spec = importlib.util.spec_from_file_location("gen_manifest", "/root/troupe-standup/wizard-work/ledger/gen_manifest.py")
|
||||
m = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(m)
|
||||
m.ROOT = "/tmp/scratch_wiz"
|
||||
m.OUT = "/tmp/scratch_wiz_out"
|
||||
m.build()
|
||||
|
||||
print("--- scratch manifest ---")
|
||||
with open("/tmp/scratch_wiz_out/wizardwork-file-manifest.tsv") as f:
|
||||
print(f.read())
|
||||
print("--- row count ---")
|
||||
print(sum(1 for _ in open("/tmp/scratch_wiz_out/wizardwork-file-manifest.tsv")))
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,18 @@
|
||||
# wizard-work directory census
|
||||
|
||||
Extract — data extraction and tables. Derived on this host from
|
||||
`find /root/troupe-standup/wizard-work -type f` (2026-10-26).
|
||||
|
||||
| dir | files | scripts | data | docs | caches | other | check | checkok |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| beam | 287 | 83 | 1 | 2 | 7 | 201 | beam/CHECK | yes |
|
||||
| forge | 140 | 59 | 12 | 40 | 2 | 29 | - | no |
|
||||
| ledger | 248 | 69 | 104 | 61 | 2 | 14 | ledger/CHECK | yes |
|
||||
| null | 304 | 141 | 26 | 27 | 26 | 110 | null/CHECK | yes |
|
||||
| quill | 47 | 4 | 2 | 38 | 1 | 3 | - | no |
|
||||
| sol | 115 | 46 | 29 | 37 | 1 | 3 | sol/check-triage.sh | yes |
|
||||
| spark | 425 | 248 | 117 | 21 | 2 | 39 | spark/CHECK | yes |
|
||||
| sphinx | 1778 | 195 | 575 | 67 | 10 | 941 | sphinx/longctx-citations-2026-10-21/CHECK | yes |
|
||||
| volt | 72 | 12 | 36 | 17 | 1 | 7 | - | no |
|
||||
|
||||
Totals: 9 top-level directories, 3416 files (857 script, 902 data, 310 doc, 1347 other, 0 cache dirs).
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user