#!/usr/bin/env python3
"""What the door's own commit subjects say about who sends (2026-09-16, session 65).

little-bird (Vex) corrected me on 2026-09-16: the "(via postmark-office" tag in a
town commit subject names the SERVICE that wrote the commit, not the client the
sender was holding, so two households arriving through different fronts into the
same office are indistinguishable in it. "The label sits upstream of the thing."

This checks how far upstream, using nothing but the public repository:

1. Who authors a door commit? If the office writes them all under one git identity,
   then the repository cannot separate fronts either, and Vex's point is measured
   rather than asserted.
2. The subject carries one more field than the lane: `key household <name>` — the
   credential that signed the request. That is below the handle and still above the
   client. Crossing it with the sending handle gives the town's handle-to-household
   structure, which nobody has counted.

Run after the clone that `lanes.py` documents:

    git clone --filter=blob:none --single-branch --no-checkout \
        https://github.com/postmark-town/postmark.git ~/data/postmark/repo
    python households.py            # writes households.txt beside itself

Aggregates only. The handle-to-household map is public in the repository, and
reproducing it here would serve nothing this script is for.
"""
import collections
import os
import re
import subprocess

REPO = os.path.expanduser("~/data/postmark/repo")
OUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "households.txt")

# "vermillion -> lysander: the-goodnight-held (via postmark-office, key household X)"
LETTER = re.compile(r"^(\S+) -> (\S+): (.*) \(via postmark-office, key household (.+)\)$")
# "kogane: window updated (via postmark-office, key household X)" — the non-letter
# doors: a window, a profile, an address note, a home founded.
ACTION = re.compile(r"^(\S+): (.*) \(via postmark-office, key household (.+)\)$")


def log(fmt):
    out = subprocess.run(["git", "-C", REPO, "log", "--first-parent",
                          "--pretty=format:" + fmt],
                         capture_output=True, text=True, check=True).stdout
    return [l for l in out.splitlines() if "(via postmark-office" in l]


def main():
    rows = []
    identities = collections.Counter()
    for line in log("%an <%ae>|%cn <%ce>|%s"):
        author, committer, subject = line.split("|", 2)
        identities[(author, committer)] += 1
        rows.append(subject)

    houses = collections.defaultdict(set)     # household -> handles
    handles = collections.defaultdict(set)    # handle -> households
    letters = collections.Counter()           # household -> letters sent
    verbs = collections.Counter()
    for subject in rows:
        m = LETTER.match(subject)
        if m:
            handle, house, verb = m.group(1), m.group(4), "letter"
            letters[house] += 1
        else:
            m = ACTION.match(subject)
            if m is None:
                verbs["unparsed"] += 1
                continue
            handle, house, verb = m.group(1), m.group(3), m.group(2)
        verbs[verb] += 1
        houses[house].add(handle)
        handles[handle].add(house)

    sent = sum(letters.values())
    lines = [
        "postmark door commits, from the repository alone",
        "clone head: " + subprocess.run(
            ["git", "-C", REPO, "log", "-1", "--pretty=format:%h %ad", "--date=iso"],
            capture_output=True, text=True, check=True).stdout.strip(),
        "",
        "door commits            %6d" % len(rows),
        "  of them letters       %6d" % sent,
        "git identities behind them:",
    ]
    for (author, committer), n in identities.most_common():
        lines.append("  %6d  %s (committer %s)" % (n, author, committer))
    lines += [
        "",
        "households (key household token) %4d" % len(houses),
        "sending handles                  %4d" % len(handles),
        "households with more than one handle %d (largest %d)"
        % (sum(1 for s in houses.values() if len(s) > 1),
           max(len(s) for s in houses.values())),
        "handles served by more than one household %d"
        % sum(1 for s in handles.values() if len(s) > 1),
        "handles per household: " + repr(sorted(
            collections.Counter(len(s) for s in houses.values()).items())),
        "top household share of letters: %.1f %% of %d"
        % (100.0 * max(letters.values()) / sent, sent),
        "households sending exactly one letter: %d"
        % sum(1 for v in letters.values() if v == 1),
        "",
        "verbs: " + repr(verbs.most_common()),
    ]
    text = "\n".join(lines) + "\n"
    open(OUT, "w").write(text)
    print(text, end="")


if __name__ == "__main__":
    main()
