61 lines
2.5 KiB
Python
61 lines
2.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Derivation core for the wizard-work git worktree census (extract lane).
|
|
|
|
Shared `derive()` — the single source of truth for every census value.
|
|
Used by the extractor runner AND the verifier so both read the live git tree;
|
|
nothing is hardcoded, nothing is a stub. Exit-gated by the CHECK.
|
|
"""
|
|
import subprocess
|
|
from collections import Counter
|
|
|
|
REPO = "/root/troupe-standup"
|
|
|
|
|
|
def git(*args):
|
|
return subprocess.run(
|
|
["git", "-C", REPO, *args], capture_output=True, text=True, check=True
|
|
).stdout
|
|
|
|
|
|
def derive():
|
|
data = {}
|
|
data["stamp"] = "2026-11-02"
|
|
data["repo"] = REPO
|
|
data["branch"] = git("rev-parse", "--abbrev-ref", "HEAD").strip()
|
|
data["branch_head"] = git("rev-parse", "--short", "HEAD").strip()
|
|
data["head"] = git("rev-parse", "HEAD").strip()
|
|
data["commit_count"] = int(git("rev-list", "--count", "HEAD").strip())
|
|
data["tracked_file_count"] = len(git("ls-files").splitlines())
|
|
data["total_unique_emails"] = len({e for e in git("log", "--format=%ae").splitlines() if e})
|
|
data["ahead_by_origin_main"] = int(git("rev-list", "--count", "origin/main..HEAD").strip())
|
|
data["behind_by_origin_main"] = int(git("rev-list", "--count", "HEAD..origin/main").strip())
|
|
data["remote_heads"] = {
|
|
l: git("rev-parse", "--short", l).strip()
|
|
for l in git("branch", "-r", "--format=%(refname:short)").splitlines()
|
|
if l.strip()
|
|
}
|
|
|
|
# Author census: group commits by (name, email) with first/last date.
|
|
by_pair = {}
|
|
for line in git("log", "--format=%an%x00%ae%x00%ad", "--date=iso-strict").splitlines():
|
|
if not line.strip():
|
|
continue
|
|
name, email, date = line.split("\x00")
|
|
by_pair.setdefault((name, email), []).append(date)
|
|
rows = []
|
|
for (name, email), dates in by_pair.items():
|
|
rows.append({"name": name, "email": email, "count": len(dates), "first": min(dates), "last": max(dates)})
|
|
nc = Counter(r["name"] for r in rows)
|
|
ec = Counter(r["email"] for r in rows)
|
|
for r in rows:
|
|
r["name_collides"] = nc[r["name"]] > 1
|
|
r["email_collides"] = ec[r["email"]] > 1
|
|
rows.sort(key=lambda r: (-r["count"], r["name"].lower(), r["email"]))
|
|
data["author_census"] = rows
|
|
|
|
# Top-modified files: commit count per path from --name-only.
|
|
names = git("log", "--pretty=format:", "--name-only").splitlines()
|
|
fc = Counter(n for n in names if n.strip())
|
|
data["top_modified_files"] = [{"path": p, "commits": c} for p, c in fc.most_common()]
|
|
return data
|