ledger: daily commit census 2026-11-04 (extract lane)

This commit is contained in:
ledger committed 2026-11-04 01:49:39 +00:00
1 parent 95a5998a2d
commit ade23054b6
7 files changed
+355

No files matched your search

+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
# CHECK -- daily commit census (Extract lane). Exit 0 iff the committed
# daily-commit-census.csv is a byte-identical re-derivation from git at the rev
# the committed extraction_manifest.json pins. Independent of the extractor --
# pure bash + git + coreutils (sort/uniq/awk), no Python.
set -u
cd "$(dirname "${BASH_SOURCE[0]}")" || exit 1
SCRIPT_DIR="$(pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
OUT="$REPO_ROOT/wizard-work/ledger/2026-11-04-daily-commit-census/daily-commit-census.csv"
MANIFEST="$REPO_ROOT/wizard-work/ledger/2026-11-04-daily-commit-census/extraction_manifest.json"
test -s "$OUT" || { echo "FAIL: CSV missing or empty: $OUT" >&2; exit 1; }
test -s "$MANIFEST" || { echo "FAIL: manifest missing: $MANIFEST" >&2; exit 1; }
HEAD_FULL="$(sed -n 's/.*"head_full": "\([^"]*\)".*/\1/p' "$MANIFEST")"
test -n "$HEAD_FULL" || { echo "FAIL: no head_full in manifest" >&2; exit 1; }
tmp="$(mktemp)"
trap 'rm -f "$tmp"' EXIT
{
echo "date,commits"
git -C "$REPO_ROOT" log --date=short --pretty=format:%ad "$HEAD_FULL" | sort | uniq -c | awk '{print $2 "," $1}' | sort
sum="$(git -C "$REPO_ROOT" log --date=short --pretty=format:%ad "$HEAD_FULL" | sort | uniq -c | awk '{s += $1} END {print s}')"
echo "TOTAL,$sum"
} > "$tmp"
if cmp -s "$OUT" "$tmp"; then
echo "PASS: daily-commit-census.csv re-derives from git at pinned head $HEAD_FULL"
exit 0
fi
echo "FAIL: daily-commit-census.csv differs from re-derivation at pinned head $HEAD_FULL" >&2
diff -u "$OUT" "$tmp" >&2 || true
exit 1
@@ -0,0 +1,36 @@
# Ledger: daily commit census (2026-11-04)
Lane: **Extract — data extraction and tables**.
A machine-readable census of every commit on the troupe repository's `main`
branch, grouped by ISO calendar date.
## Source and method
- Source: `git log --date=short --pretty=format:%ad` on `/root/troupe-standup`
(branch `main`).
- Each commit contributes its ISO date `%ad`. Commits are then grouped by date
and counted; rows sorted ascending by date.
- Output gate: `daily-commit-census.csv` (41 day rows + 1 TOTAL row) is re-derived
from git at the pinned rev and diffed byte-identically by `verify_daily_commit_census.py`
and the standalone `CHECK` script.
## Metrics (measured, not asserted)
- Day rows: 41
- Commit total: 2612
- Pinned head: `4a4723c69b90799a833e6efba936972fc5659d58` (`git rev-parse HEAD`
at capture, 2026-11-04)
- Earliest date: 2026-09-24
- Latest date: 2026-11-04
- Busiest day: 2026-10-23 (171 commits)
- Quietest day (non-zero): 2026-11-04 (2 commits)
## Files
- `daily-commit-census.csv` — `date,commits` (one row per date, plus a `TOTAL` row)
- `extraction_manifest.json` — provenance: repo, pinned head, date range, counts
- `extract_daily_commit_census.py` — extractor (regenerates the CSV)
- `verify_daily_commit_census.py` — self-check gate (re-derives from pinned head)
- `CHECK` — independent bash re-derivation gate (no Python)
- `daily-commit-census.md` — top summary table for humans
@@ -0,0 +1,43 @@
date,commits
2026-09-24,31
2026-09-25,4
2026-09-26,24
2026-09-27,5
2026-09-28,11
2026-09-30,6
2026-10-01,17
2026-10-02,3
2026-10-03,21
2026-10-04,13
2026-10-05,14
2026-10-06,40
2026-10-07,25
2026-10-08,21
2026-10-09,8
2026-10-10,44
2026-10-11,63
2026-10-12,106
2026-10-13,90
2026-10-14,90
2026-10-15,46
2026-10-16,26
2026-10-17,41
2026-10-18,42
2026-10-19,50
2026-10-20,92
2026-10-21,123
2026-10-22,115
2026-10-23,171
2026-10-24,167
2026-10-25,153
2026-10-26,141
2026-10-27,147
2026-10-28,154
2026-10-29,84
2026-10-30,107
2026-10-31,98
2026-11-01,80
2026-11-02,80
2026-11-03,57
2026-11-04,2
TOTAL,2612
1 date commits
2 2026-09-24 31
3 2026-09-25 4
4 2026-09-26 24
5 2026-09-27 5
6 2026-09-28 11
7 2026-09-30 6
8 2026-10-01 17
9 2026-10-02 3
10 2026-10-03 21
11 2026-10-04 13
12 2026-10-05 14
13 2026-10-06 40
14 2026-10-07 25
15 2026-10-08 21
16 2026-10-09 8
17 2026-10-10 44
18 2026-10-11 63
19 2026-10-12 106
20 2026-10-13 90
21 2026-10-14 90
22 2026-10-15 46
23 2026-10-16 26
24 2026-10-17 41
25 2026-10-18 42
26 2026-10-19 50
27 2026-10-20 92
28 2026-10-21 123
29 2026-10-22 115
30 2026-10-23 171
31 2026-10-24 167
32 2026-10-25 153
33 2026-10-26 141
34 2026-10-27 147
35 2026-10-28 154
36 2026-10-29 84
37 2026-10-30 107
38 2026-10-31 98
39 2026-11-01 80
40 2026-11-02 80
41 2026-11-03 57
42 2026-11-04 2
43 TOTAL 2612
@@ -0,0 +1,46 @@
# Daily commit census — troupe repo `main` (2026-11-04)
| date | commits |
|---|---|
| 2026-09-24 | 31 |
| 2026-09-25 | 4 |
| 2026-09-26 | 24 |
| 2026-09-27 | 5 |
| 2026-09-28 | 11 |
| 2026-09-30 | 6 |
| 2026-10-01 | 17 |
| 2026-10-02 | 3 |
| 2026-10-03 | 21 |
| 2026-10-04 | 13 |
| 2026-10-05 | 14 |
| 2026-10-06 | 40 |
| 2026-10-07 | 25 |
| 2026-10-08 | 21 |
| 2026-10-09 | 8 |
| 2026-10-10 | 44 |
| 2026-10-11 | 63 |
| 2026-10-12 | 106 |
| 2026-10-13 | 90 |
| 2026-10-14 | 90 |
| 2026-10-15 | 46 |
| 2026-10-16 | 26 |
| 2026-10-17 | 41 |
| 2026-10-18 | 42 |
| 2026-10-19 | 50 |
| 2026-10-20 | 92 |
| 2026-10-21 | 123 |
| 2026-10-22 | 115 |
| 2026-10-23 | 171 |
| 2026-10-24 | 167 |
| 2026-10-25 | 153 |
| 2026-10-26 | 141 |
| 2026-10-27 | 147 |
| 2026-10-28 | 154 |
| 2026-10-29 | 84 |
| 2026-10-30 | 107 |
| 2026-10-31 | 98 |
| 2026-11-01 | 80 |
| 2026-11-02 | 80 |
| 2026-11-03 | 57 |
| 2026-11-04 | 2 |
| **TOTAL** | **2612** |
@@ -0,0 +1,91 @@
#!/usr/bin/env python3
"""Extract the daily commit census of the troupe repository.
Lane: Extract - data extraction and tables.
Source: live `git log --date=short --pretty=format:%ad` on the `main` branch of
/root/troupe-standup. Commits are grouped by ISO calendar date and counted.
Rows are sorted by date ascending. The pinned head (full + short) is recorded in
extraction_manifest.json so the extraction is reproducible at a fixed rev.
Output (written to <out_dir>):
daily-commit-census.csv - header, one row per date + a TOTAL row (41+1 lines)
extraction_manifest.json - provenance: repo, head, date range, row count, sums
Usage: python3 extract_daily_commit_census.py <out_dir>
"""
import json
import os
import subprocess
import sys
from collections import Counter
REPO = "/root/troupe-standup"
DATE_FMT = "%Y-%m-%d"
def git(*args):
return subprocess.run(
["git", "-C", REPO] + list(args),
check=True,
capture_output=True,
text=True,
).stdout
def build_rows():
dates = git("log", "--date=short", "--pretty=format:%ad").splitlines()
counts = Counter(d for d in dates if d)
return [{"date": d, "commits": c} for d, c in sorted(counts.items())]
def render_csv(rows):
lines = ["date,commits"]
for r in rows:
lines.append("{date},{commits}".format(**r))
total = sum(r["commits"] for r in rows)
lines.append("TOTAL,{total}".format(total=total))
return "\n".join(lines) + "\n"
def render_manifest(head_full, head_short, rows):
dates = [r["date"] for r in rows]
return {
"repo": REPO,
"branch": "main",
"source_command": "git log --date=short --pretty=format:%ad",
"head_full": head_full,
"head_short": head_short,
"earliest": dates[0],
"latest": dates[-1],
"day_rows": len(rows),
"total_commits": sum(r["commits"] for r in rows),
"method": "counts ISO calendar date of every commit on main",
}
def main():
out_dir = sys.argv[1] if len(sys.argv) > 1 else "."
os.makedirs(out_dir, exist_ok=True)
head_full = git("rev-parse", "HEAD").strip()
head_short = git("rev-parse", "--short", "HEAD").strip()
rows = build_rows()
csv_path = os.path.join(out_dir, "daily-commit-census.csv")
with open(csv_path, "w", encoding="utf-8") as f:
f.write(render_csv(rows))
manifest = render_manifest(head_full, head_short, rows)
with open(os.path.join(out_dir, "extraction_manifest.json"), "w", encoding="utf-8") as f:
json.dump(manifest, f, indent=2)
f.write("\n")
print("rows:", manifest["day_rows"], "total:", manifest["total_commits"],
"head:", head_short, "earliest:", manifest["earliest"], "latest:", manifest["latest"])
print("wrote:", csv_path)
if __name__ == "__main__":
main()
@@ -0,0 +1,12 @@
{
"repo": "/root/troupe-standup",
"branch": "main",
"source_command": "git log --date=short --pretty=format:%ad",
"head_full": "4a4723c69b90799a833e6efba936972fc5659d58",
"head_short": "4a4723c",
"earliest": "2026-09-24",
"latest": "2026-11-04",
"day_rows": 41,
"total_commits": 2612,
"method": "counts ISO calendar date of every commit on main"
}
@@ -0,0 +1,90 @@
#!/usr/bin/env python3
"""CHECK gate for the daily-commit-census extraction.
Re-derives the daily commit census from git at the PINNED head recorded in the
committed extraction_manifest.json, re-renders the CSV with the identical
format the extractor uses, and diffs it against the committed file. Exits 0 only
when every check matches exactly. This is a re-derivation, not an assertion of a
stored number.
Usage: python3 verify_daily_commit_census.py <artifact_dir>
"""
import difflib
import json
import os
import subprocess
import sys
REPO = "/root/troupe-standup"
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
from extract_daily_commit_census import render_csv, build_rows # noqa: E402
CSV_NAME = "daily-commit-census.csv"
def git(*args):
return subprocess.run(
["git", "-C", REPO] + list(args), check=True, capture_output=True, text=True
).stdout
def read_bytes(name):
with open(name, "rb") as f:
return f.read()
def main():
artdir = sys.argv[1] if len(sys.argv) > 1 else "."
os.chdir(artdir)
with open("extraction_manifest.json", encoding="utf-8") as f:
manifest = json.load(f)
head = manifest.get("head_full")
if not head:
print("FAIL: manifest has no head_full")
sys.exit(1)
# Re-derive from the pinned head.
raw = git("log", "--date=short", "--pretty=format:%ad", head).splitlines()
from collections import Counter
counts = Counter(d for d in raw if d)
rows = [{"date": d, "commits": c} for d, c in sorted(counts.items())]
expected = render_csv(rows)
ok = True
with open(CSV_NAME, encoding="utf-8") as f:
committed = f.read()
if committed == expected:
print("PASS: daily-commit-census.csv re-derives byte-identically from git "
"at pinned head %s" % head)
else:
ok = False
print("FAIL: daily-commit-census.csv diverges from re-derivation at "
"pinned head %s" % head)
exp = expected.splitlines()
obs = committed.splitlines()
for line in list(difflib.unified_diff(exp, obs, "expected@", "committed@"))[:12]:
print(" " + line)
# Independent integrity: the TOTAL row must equal the sum of the day rows.
day_sum = sum(int(r["commits"]) for r in rows)
total_lines = [ln for ln in committed.splitlines() if ln.startswith("TOTAL,")]
if total_lines == ["TOTAL,%d" % day_sum]:
print("PASS: TOTAL row %r == sum of day rows %d" % (total_lines[0], day_sum))
else:
ok = False
print("FAIL: TOTAL row %r != sum of day rows %d" % (total_lines, day_sum))
if ok:
print("ALL CHECKS PASSED")
sys.exit(0)
sys.exit(1)
if __name__ == "__main__":
main()