Ticket graphs

Every ticket as the root of its provenance graph — goal, patch, approval, runs and (as the ticket-class build lands) mandate, manifestations, guarantees, journey, artifacts and children. Rendered through the <<<TicketGraphList>>> tag.

← all ticket-graphs

DONE#445 congruency

Forge family tree PART 1 of 2 (supersedes #443): discover + cluster 264 repos -> 109 lineages, classify (IDENTICAL/LINEAR/FORK-CAME-HOME/DIVERGED/SPLIT-STORE), emit tree. Containment gate is PART 2.

goal

PART 1 OF 2 (supersedes #443, which timed out at 2400s having written NOTHING — its spec was too large for one worker pass: 8.3KB, 7 requirements, plus reasoning over 264 repos. Its two siblings with identical engine/timeout succeeded — #440 wrote 1723 lines, #438 completed two rounds — so the ticket size was the variable, not the worker. THIS TICKET IS DELIBERATELY HALF THE SCOPE.) SCOPE: DISCOVER + CLASSIFY ONLY. Emit the family tree. The containment retirement gate and the merge-home planning are PART 2 and are explicitly OUT OF SCOPE here — do not build them. DELIVERABLE: checkouts/current/congruency/tools/forge_family_tree.py — standalone, stdlib + git only. 1. CLUSTER. Walk config/forge/remotes/*.git (264 bare repos). Group by root-commit SET (`git rev-list --max-parents=0 --all`). Repos sharing a root set are ONE LINEAGE. 2. RESOLVE TIPS — THE GOTCHA THAT ALREADY PRODUCED A WRONG ANSWER ONCE. Most of these bare repos have an UNRESOLVABLE HEAD: `git rev-parse HEAD` returns the literal string "HEAD", and `rev-parse --verify HEAD` FAILS. A first prototype used --verify, silently dropped 42 of 109 families, and confidently reported "0 diverged" — which was false. Resolve tips via `git for-each-ref refs/heads`, preferring main/master, else the ref with the most commits. 3 repos have NO refs at all: REPORT them explicitly, never skip silently. 3. CLASSIFY each lineage: IDENTICAL — every member shares one tip (pure ingestion duplicates). LINEAR — the max-commit tip is an ancestor of every other tip (superset); the rest are stale. Report the superset tip + the stale aliases. FORK-CAME-HOME — *** THE SAME GIT SHAPE AS LINEAR. *** A fork whose additions belong merged BACK into its parent/home, after which the fork retires. Topology CANNOT distinguish this from LINEAR — they differ only in INTENT, which is not in the DAG. So NEVER auto-decide direction: REPORT the topology, PROPOSE a direction, and accept an operator-supplied override. Mark the jail.git / agent_tools_suite.git family as FORK-CAME-HOME (see below). DIVERGED — a tip is NOT reachable from the candidate: report `merge-base`, each side's unique commits, and the file-level diff. Distinguish ADDITIVE divergence (no conflicting hunks — mechanical union) from CONFLICTING (both sides changed the same file) — that distinction IS the reconciliation cost. SPLIT-STORE — a member's tip object is ABSENT from the candidate's store. Do not guess: fetch into a scratch object store (or use --alternates), then re-classify. 4. THE JAIL CASE (operator-defined, do not re-derive): jail.git (47 commits) is topologically a linear superset of agent_tools_suite.git (46) — shared root 379ac05319, ats tip 888d3447c6 is an ancestor of jail tip 38e95ad16d, jail adds 6 files. BUT JAIL IS **NOT** CANONICAL AND NOT A DESTINATION. jail was an expedient: a name wrapped around some packages in a folder, with a mess of tests cleaned up in a hurry. It is a GRAB-BAG whose packages belong to SEVERAL DIFFERENT home repos. Direction is REVERSED from what topology suggests: jail merges HOME and is then omitted. agent_tools_suite IS a home repo. Do NOT name jail canonical. 5. OUTPUT: (a) machine-readable — sqlite or JSON: lineages, members, tips, classification, proposed direction, fork edges; (b) a human-readable ASCII family tree. 6. --selftest on THROWAWAY git repos in a temp dir synthesizing each class (identical / linear / additive-diverged / conflicting-diverged / split-store / no-refs / unresolvable-HEAD), proving each is classified correctly. No network, no live db, no writes outside the temp dir. DO NOT USE omni.git AS THE SOURCE OF TRUTH — it is INCOMPLETE (measured: it is MISSING agent_tools_suite's tip 888d3447c6). config/forge/remotes/*.git is authoritative. ACCEPTANCE: --selftest green; a real run reproduces the measured headline — 264 repos -> 109 LINEAGES, of which 68 IDENTICAL / 36 LINEAR / 3 DIVERGED (jazz.git, notes_db.git, z3_mcp.git) / 2 SPLIT-STORE (big-jazz.git, code__code.git), with the split-store pair RESOLVED after fetch rather than left unknown; the jail/agent_tools_suite family classified FORK-CAME-HOME and jail NOT named canonical; prints a readable tree. RUN ON CLAUDE.

patch

none

approval

unapproved

runs

no runs recorded

mandate (clauses)

not yet recorded — lands with the ticket-class build

manifestations

not yet recorded — lands with the ticket-class build

guarantees

not yet recorded — lands with the ticket-class build

journey (blunders & successes)

not yet recorded — lands with the ticket-class build

artifacts (forge)

not yet recorded — lands with the ticket-class build

source (forge tree)

browse congruency source (forge-parked tree)

children

#452 Forge evolution PART 2 (v2, supersedes #449): EVOLUTION TIMELINE from git dates + containment retirement gate + 118-blob orphan worklist. OMNI IS BLACK-BOXED — it is not a git (every git cmd fails) and covers 11% of forge; config/forge/remotes is the only authority. (spawned · DONE)
#449 Forge evolution PART 2 of 2: EVOLUTION TIMELINE (root -> fork-point -> tip dates + fork width, plus omni ingest stamps as a second clock) + mechanical CONTAINMENT retirement gate + the 118-blob orphan/merge-home worklist. Read-only; consumes #445's JSON. (spawned · ACTIVE)