This repository has no description
blogposts tangled-stats
2 folders · 26 files

README.md

Tangled stats #

Crawls every pull request on Tangled and renders the leaderboards as a self-contained HTML block for a Leaflet post.

Embedding #

embed.html is the whole panel as one fragment: a <style> block plus one <section class="tg-stats">. Paste it into the post.

blocks/ holds the same content cut into 14 fragments, each independently pasteable so you can place them one at a time between paragraphs:

File Block
01-headline.html hero figures + KPI strip
02-merged-alltime.html merged-PR leaderboard, all time
03-merged-august.html merged-PR leaderboard, August 2026
04-commits.html commit leaderboard, all time
05-commits-august.html commit leaderboard, August 2026
06-pies.html all four pies together
07-pie-merged-alltime.html one pie: merged PRs, all time
08-pie-merged-august.html one pie: merged PRs, August
09-pie-commits-alltime.html one pie: commits, all time
10-pie-commits-august.html one pie: commits, August
11-timeline.html merged PRs per month, network-wide
12-august-daily.html my August, day by day
13-comparison.html me versus everyone else
14-method.html method + the time-to-merge caveat

Each block carries its own copy of the stylesheet so it works alone. The rules are identical and scoped to .tg-stats, so repeated blocks in one post are harmless — but if you paste several, you can delete the <style> from all but the first.

blocks/index.html is a contact sheet showing every block rendered on black; open it locally to pick the ones you want. It carries no JavaScript, so it survives HTML sanitizing; hover tooltips come from SVG <title>, and every chart has a table view behind a <details>.

Colors are pinned to the permadeath.com Leaflet theme — --bg-page: 0,0,0 and --primary: 255,0,0 — and the type inherits Sometype Mono, which the blog already loads, so the block needs no extra network request. The panel commits to that one theme: no light mode, every color painted explicitly, nothing inherited from the host.

Re-running #

./run_all.sh          # waits for api.tangled.org, then runs everything

Stages, if you need them individually:

Script Does
crawl_pulls.py every PR for each repo DID in repo_dids.txt (resumable)
stage2_backfill.py maps repos to owners, finds repos on self-hosted knots
stage3_commits.py indexes merged PRs and resolves each author's PDS
stage3b_blobs.py fetches patch blobs, counts commits (resumable)
stage4_handles.py resolves DIDs to handles via plc.directory
analyze.py writes stats.json
build_html.py writes embed.html and preview.html

Seed repo_dids.txt from the knot before a fresh run:

curl -s "https://knot1.tangled.sh/xrpc/sh.tangled.sync.listRepos?limit=1000&cursor=N"

valpal.py checks a chart ramp against the black surface — ordinal monotonicity, adjacent lightness gaps, contrast. Run it before changing any chart color.

Caveats worth keeping in the post #

  • Commits are counted from PR patches, not from git history — Tangled publishes no global commit index (sh.tangled.git.refUpdate returns empty). Commits pushed straight to a branch are not counted.
  • Time to merge is not measurable. createdAt is asserted by the author's client; stateUpdatedAt derives from a different record's key, written by a different person on a different machine. 18% of other authors' merged PRs report merging before they were opened. Month bucketing survives this; durations do not.
  • Merge rate counts only decided PRs. Counting open PRs as failures compares one month of work against the network's two-year backlog.