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

REQUESTED#442 congruency

Forge FAMILY TREE / evolution tool: cluster 264 repos into 109 lineages, classify fork pattern (identical/linear/diverged/split-store), name the canonical tip, emit stage-by-stage tree + reconciliation plan

goal

Build the FORGE FAMILY TREE / EVOLUTION tool: cluster every forge repo into lineages, classify how each family forked, name the CANONICAL tip, and produce a stage-by-stage evolution tree plus a reconciliation plan for the few families that truly diverged. WHY (measured, not theoretical — a prototype was run on 2026-07-15 over config/forge/remotes/*.git): * 264 bare repos collapse to 109 DISTINCT LINEAGES (grouped by root-commit set). * Of those 109: 68 IDENTICAL (pure duplicates, same tip ingested from several paths) 36 LINEAR (one tip supersets the rest; the others are STALE copies) 3 DIVERGED (true forks: jazz.git, notes_db.git, z3_mcp.git) 2 SPLIT-STORE (objects not shared; need a fetch before they can be compared: big-jazz.git, code__code.git) So only ~5 families carry real reconciliation work. The other ~104 need NO merge — just pick the superset tip and drop the aliases. The 264 is largely an ingestion-path illusion (code__X, code__rebuild__X, gitlab__<group>__X, gitlab__<group>__jazz-forge__X, and bare X are the SAME project ingested repeatedly). * PROVEN CONSEQUENCE FOR THE LIVE REBUILD: jail.git (47 commits) SUPERSETS agent_tools_suite.git (46) — shared root 379ac05319, ats's tip is a direct ancestor of jail's. jail adds 6 files (crankws-mcp/server.py +138, start-crank.py, claude-gui.py, registry.crankws.json, crank_job_backlog.json, crank_job_congruency.json). The in-flight agent_tools_suite rebuild (#412-436) is therefore ticketed from a NON-CANONICAL tip, and jail's unique modules will be rebuilt into a SEPARATE forge2/jail/ package — one lineage split across two packages, because nothing in the pipeline models a family. DELIVERABLE: checkouts/current/congruency/tools/forge_family_tree.py — standalone, no deps beyond git + stdlib + sqlite3. It MUST: 1. DISCOVER + CLUSTER. Walk config/forge/remotes/*.git. Group by root-commit SET (`git rev-list --max-parents=0 --all`). Repos sharing a root are one lineage. 2. RESOLVE TIPS CORRECTLY — the prototype's key gotcha: MOST of these bare repos have an UNRESOLVABLE HEAD (`git rev-parse HEAD` returns the literal string "HEAD"; `--verify` fails and silently drops the repo, which produced a wrong "0 diverged" answer on the first run). Resolve tips via `git for-each-ref refs/heads`, preferring main/master, else the ref with most commits. 3 repos have NO refs at all — report them, never skip silently. 3. CLASSIFY each family: IDENTICAL — all members share one tip. LINEAR — the max-commit tip is an ancestor of every other tip (superset). Name the CANONICAL tip; list the stale aliases. DIVERGED — some tip is NOT reachable from the candidate: compute `merge-base`, and report each side's unique commits and file-level diff. 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) and then re-classify. 4. EVOLUTION IN STAGES. For each family emit the tree: root -> shared spine -> fork points -> tips, annotated with commit dates (stage boundaries), which repo/alias sits at each node, and what each fork ADDED vs the spine. Additive-only divergence must be distinguished from conflicting divergence (both sides modified the same file) — that distinction IS the reconciliation cost. 5. RECONCILIATION PLAN per family: IDENTICAL -> keep canonical, drop N aliases (zero work). LINEAR -> fast-forward: canonical already contains everything; drop stale aliases. ADDITIVE -> union: the merge is mechanical (no conflicting hunks). CONFLICTING-> flag for synthesis: list the conflicting files; this is the ONLY case needing a human/competitive-synthesis decision (see #206). 6. OUTPUT: (a) machine-readable — a sqlite db or JSON: families, members, tips, classification, canonical tip, fork edges, reconciliation verdict; (b) human-readable ASCII family tree. 7. --selftest on THROWAWAY git repos built in a temp dir that synthesize 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: omni.git is MISSING agent_tools_suite's tip 888d3447c6 (it holds the common line but not the fork's feature commits). config/forge/remotes/*.git is authoritative. Optionally REPORT omni coverage gaps as a side output. DOWNSTREAM VALUE (state it in the tool's own docstring, do not implement here): the canonical-tip map is what should drive forge2 rebuild scope — ticket modules ONLY from canonical tips, skip stale variants (a stale fork's older foo.py hashes to a DIFFERENT module-sha than the tip's foo.py, so today it mints a second ticket and we rebuild an obsolete module), and rebuild one lineage into ONE forge2 package. ACCEPTANCE: --selftest green; a real run over config/forge/remotes reproduces the prototype's headline numbers (264 repos -> 109 lineages; 68 IDENTICAL / 36 LINEAR / 3 DIVERGED / 2 SPLIT-STORE, with the 2 split-store families RESOLVED after fetch rather than left unknown); correctly names jail.git as the canonical tip over agent_tools_suite.git; prints a readable family tree. RUN THIS ON CLAUDE (multi-file git reasoning; not a GLM task).

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

not yet recorded — lands with the ticket-class build