status: contributors index — humans and AI models on one metric (#746)
Fourth public dashboard (contributors.html + contributors.json): who builds Eleven, ranked by commits. Humans come from the GitHub contributors API (login, avatar as an embedded data URI — the pages allow no external hosts — profile link, commit count); AI models come from Co-Authored-By trailers with the anthropic email in git history, so the models sit in the index beside the humans on the same metric — honest for an AI-written codebase. Contributors own their row: bios seed from the GitHub profile bio, then hand-edits to the committed JSON win (tools/contributors.mjs preserves bio/name/hidden on every refresh); "hidden": true leaves the index. Contract test pins the shape: known kinds, positive sorted counts, humans carry profile URL + data-URI avatar, and no email address can reach the published JSON. Footer links added across all four pages; docs/status.md gains the page + refresh recipe (no staleness hook — unlike the carbon tally there's no pruning window, so a stale count just catches up on the next run).
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
9 files changed,
+439
−9
deploy/status-publish.sh+9 −2docs/status.md+26 −2test/status-contract.test.mjs+32 −2tools/contributors.mjs+95 −0web/status/books.html+1 −1web/status/carbon.html+1 −1web/status/contributors.html+212 −0web/status/contributors.json+62 −0web/status/index.html+1 −1
diff --git a/deploy/status-publish.sh b/deploy/status-publish.sh| index 3936c36..05bf8ca 100755 |
| --- a/deploy/status-publish.sh |
| +++ b/deploy/status-publish.sh |
| @@ -52,6 +52,10 @@ |
| # staged with the pages and republished as-is. Aggregate token counts and |
| # kg estimates only — never per-session data. |
| # |
| +# contributors.json — also COMMITTED data (tools/contributors.mjs), |
| +# republished as-is. Public GitHub identities + commit counts only; |
| +# contributors own their row (bio, hidden) in the committed JSON. |
| +# |
| # Adding a field? It must be an aggregate over the whole fleet / all payers, |
| # or it doesn't ship. |
| # ============================================================================== |
| @@ -83,7 +87,7 @@ |
| # the sidecars' completion key). |
| # /opt/lchat/status-pages/ — the viewer pages, copied from web/status/ |
| # (index.html, books.html, carbon.html, carbon.json, |
| -# icon-192.png). |
| +# contributors.html, contributors.json, icon-192.png). |
| # aws CLI + sqlite3 (apt install awscli sqlite3). |
| set -euo pipefail |
| @@ -742,8 +746,11 @@ publish() { |
| [ -f "$PAGES_DIR/index.html" ] && upload "$PAGES_DIR/index.html" index.html "text/html; charset=utf-8" "max-age=300" |
| [ -f "$PAGES_DIR/books.html" ] && upload "$PAGES_DIR/books.html" books.html "text/html; charset=utf-8" "max-age=300" |
| [ -f "$PAGES_DIR/carbon.html" ] && upload "$PAGES_DIR/carbon.html" carbon.html "text/html; charset=utf-8" "max-age=300" |
| - # The carbon tally is committed data (see header) — republished, not built. |
| + # The carbon tally + contributors index are committed data (see header) — |
| + # republished, not built. |
| [ -f "$PAGES_DIR/carbon.json" ] && upload "$PAGES_DIR/carbon.json" carbon.json "application/json" "max-age=300" |
| + [ -f "$PAGES_DIR/contributors.html" ] && upload "$PAGES_DIR/contributors.html" contributors.html "text/html; charset=utf-8" "max-age=300" |
| + [ -f "$PAGES_DIR/contributors.json" ] && upload "$PAGES_DIR/contributors.json" contributors.json "application/json" "max-age=300" |
| [ -f "$PAGES_DIR/icon-192.png" ] && upload "$PAGES_DIR/icon-192.png" icon-192.png "image/png" "max-age=86400" |
| else |
| echo "warning: $PAGES_DIR missing — JSONs published, pages skipped (copy web/status/* there)" >&2 |
diff --git a/docs/status.md b/docs/status.md| index 53c1234..5b6d74d 100644 |
| --- a/docs/status.md |
| +++ b/docs/status.md |
| @@ -1,4 +1,4 @@ |
| -# 🤖 Public status dashboards — fleet state, the books & the carbon tally |
| +# 🤖 Public status dashboards — fleet, books, carbon & contributors |
| Three world-readable pages, published every 5 minutes from the router box: the |
| running half of #550 Part 11/12's transparency direction (the append-only |
| @@ -21,6 +21,14 @@ public *ledger* repo is still roadmap — see `docs/planet-scale.md`). |
| `tools/carbon-tally.mjs` — see *Keeping the carbon tally accruing* below); |
| the box timer just republishes it with the pages. Methodology + error bars: |
| `docs/comparison-carbon.md`. |
| +- **Contributors** (`contributors.html` + `contributors.json`) — who builds |
| + Eleven, humans and AI models on one metric: humans as GitHub commit authors, |
| + models as `Co-Authored-By` trailers in git history. Committed data like the |
| + carbon tally (`web/status/contributors.json`, refreshed by |
| + `tools/contributors.mjs`); republished as-is. **Contributors own their row**: |
| + bios seed from the GitHub profile, then edits to the committed JSON win — |
| + customise your `bio` (or set `"hidden": true` to leave the index) by PR, and |
| + the tool preserves those fields on every refresh. |
| Pieces: generator `deploy/status-publish.sh` (box timer, mirrors |
| `deploy/fleet-backup.sh`), viewer pages `web/status/`, bucket + IAM |
| @@ -56,6 +64,11 @@ aggregation boundary lives in the generator and holds by construction: |
| entire schema, and the contract test allowlists it. A provider that can't |
| be honestly resolved is omitted, never zeroed or guessed. Disbursements |
| belong to the future ledger repo, not these dashboards. |
| +- **Contributors: public GitHub identity only, owned by its subject.** Login, |
| + display name, avatar, profile link, commit count — all already public on |
| + GitHub — plus a bio the contributor writes. Never emails (the contract test |
| + greps), never private activity. Anyone listed can hide themselves with |
| + `"hidden": true` in the committed JSON. |
| - **Carbon: aggregate token counts and kg estimates only.** Never per-session |
| data, never prompt or transcript content — the tally reads token *usage |
| numbers* from local transcripts and publishes only their sums. |
| @@ -168,6 +181,17 @@ a `not_counted` honesty string. The contract test pins the arithmetic: totals |
| must equal the ledger sum, each entry's kg must derive from its tokens × the |
| factors, and each source's periods must be chronological and non-overlapping. |
| +## Refreshing the contributors index |
| + |
| +`node tools/contributors.mjs --write` (needs `gh` authenticated) refreshes |
| +commit counts, avatars (embedded as data URIs — the pages allow no external |
| +hosts), and profile links, preserving `bio`/`name`/`hidden`. Run it when the |
| +index looks stale — after a burst of merges, or when a new contributor lands — |
| +commit, and copy `web/status/contributors.{html,json}` to the box's |
| +status-pages dir. No hook nudges for this one: unlike the carbon tally there |
| +is no pruning window, so a stale count costs nothing and catches up on the |
| +next refresh. |
| + |
| ## Keeping the carbon tally accruing |
| The tally's raw material is the local Claude Code transcripts on **each |
| @@ -211,7 +235,7 @@ carries the sources and the "as of" date). |
| `STATUS_ANTHROPIC_ADMIN_KEY=…` (an `sk-ant-admin…` key with read-only |
| usage scope — never the sidecars' completion key). `chown lchat:lchat`, |
| `chmod 0600`. |
| -3. **Pages on the box**: `scp web/status/{index.html,books.html,carbon.html,carbon.json,icon-192.png} |
| +3. **Pages on the box**: `scp web/status/{index.html,books.html,carbon.html,carbon.json,contributors.html,contributors.json,icon-192.png} |
| root@<box>:/opt/lchat/status-pages/`. |
| 4. **Install the timer**: `scp deploy/status-publish.sh root@<box>:/opt/lchat/` |
| then `ssh root@<box> /opt/lchat/status-publish.sh install`. The unit runs |
diff --git a/test/status-contract.test.mjs b/test/status-contract.test.mjs| index be4cf8d..b516812 100644 |
| --- a/test/status-contract.test.mjs |
| +++ b/test/status-contract.test.mjs |
| @@ -69,6 +69,9 @@ const booksHtml = read("web/status/books.html"); |
| // dry-run output — the real file is its own fixture. |
| const carbon = JSON.parse(read("web/status/carbon.json")); |
| const carbonHtml = read("web/status/carbon.html"); |
| +// The contributors index is COMMITTED data too (tools/contributors.mjs). |
| +const contributors = JSON.parse(read("web/status/contributors.json")); |
| +const contributorsHtml = read("web/status/contributors.html"); |
| await test("fleet page fields all exist in the generator's fleet.json", () => { |
| for (const f of fields(indexHtml)) { |
| @@ -89,10 +92,37 @@ await test("carbon page fields all exist in the committed carbon.json", () => { |
| } |
| }); |
| +await test("contributors page fields all exist in the committed contributors.json", () => { |
| + for (const f of fields(contributorsHtml)) { |
| + assert.notEqual(resolve(contributors, f), undefined, "contributors.json is missing " + f); |
| + } |
| +}); |
| + |
| +// Contributor entries stay well-formed as the tool regenerates them: known |
| +// kinds, positive commit counts, sorted by the metric, humans carry a profile |
| +// link + self-contained data-URI avatar (the pages allow no external hosts), |
| +// and no email address ever reaches the published JSON. |
| +await test("contributors entries are well-formed, sorted, and email-free", () => { |
| + let prev = Infinity; |
| + for (const c of contributors.contributors) { |
| + assert.ok(["human", "ai"].includes(c.kind), "kind: " + c.kind); |
| + assert.ok(Number.isInteger(c.commits) && c.commits > 0, c.id + ": commits"); |
| + assert.ok(c.commits <= prev, "not sorted by commits at " + c.id); |
| + prev = c.commits; |
| + assert.ok(c.name && c.id, "name + id present"); |
| + if (c.kind === "human") { |
| + assert.match(c.url, /^https:\/\/github\.com\//, c.id + ": profile url"); |
| + assert.match(c.avatar, /^data:image\//, c.id + ": avatar must be a data URI"); |
| + } |
| + } |
| + assert.ok(!/[\w.+-]+@[\w-]+\.[\w.]+/.test(JSON.stringify(contributors).replace(/data:image\/[^"]+/g, "")), |
| + "an email address leaked into contributors.json"); |
| +}); |
| + |
| // A manifest entry nobody reads is drift too: each leaf property must appear |
| // in the page's render code, not just the manifest. |
| await test("every declared field is actually read by its page", () => { |
| - for (const [html, fs] of [[indexHtml, fields(indexHtml)], [booksHtml, fields(booksHtml)], [carbonHtml, fields(carbonHtml)]]) { |
| + for (const [html, fs] of [[indexHtml, fields(indexHtml)], [booksHtml, fields(booksHtml)], [carbonHtml, fields(carbonHtml)], [contributorsHtml, fields(contributorsHtml)]]) { |
| const body = html.slice(html.indexOf("];") + 2); |
| for (const f of fs) { |
| const leaf = f.split(".").pop().replace("[]", ""); |
| @@ -113,7 +143,7 @@ await test("degraded books shape carries available:false + reason", () => { |
| // customer, transaction, or provider-account/workspace id may appear in |
| // published output. |
| await test("fixtures contain no per-payer ids or hostnames", () => { |
| - for (const j of [fleet, fleetGF, fleetAC, books, booksDown, booksNoExp, carbon]) { |
| + for (const j of [fleet, fleetGF, fleetAC, books, booksDown, booksNoExp, carbon, contributors]) { |
| const s = JSON.stringify(j); |
| assert.ok(!/sub_|cus_|txn_|wrkspc_|req_fixture|ce_fixture|\.example|\.sock/.test(s), "leak in " + s.slice(0, 80)); |
| } |
diff --git a/tools/contributors.mjs b/tools/contributors.mjs| new file mode 100644 |
| index 0000000..3cff447 |
| --- /dev/null |
| +++ b/tools/contributors.mjs |
| @@ -0,0 +1,95 @@ |
| +#!/usr/bin/env node |
| +// 🤖 Refresh the public contributors index (web/status/contributors.json) |
| +// from GitHub + git history. |
| +// |
| +// Humans come from the GitHub contributors API (commit counts, avatars, |
| +// profile links — needs `gh` authenticated for this private repo). AI |
| +// contributors come from Co-Authored-By trailers with the anthropic email — |
| +// this codebase is AI-written, so the models sit in the index alongside the |
| +// humans, on the same metric. |
| +// |
| +// node tools/contributors.mjs # print the would-be JSON (dry run) |
| +// node tools/contributors.mjs --write # rewrite web/status/contributors.json |
| +// |
| +// The JSON is COMMITTED (like carbon.json) and republished as-is by |
| +// deploy/status-publish.sh. Stats fields (commits, url, avatar) regenerate on |
| +// every run; the human-owned fields are PRESERVED: |
| +// bio — seeded from the GitHub profile bio on first appearance, then |
| +// yours: customise it by editing your entry in a PR |
| +// name — display name, same rule |
| +// hidden — set true to stay out of the published index entirely |
| +// Avatars are embedded as data URIs (the status pages are self-contained — |
| +// no external requests), fetched small (s=96). |
| +import { readFileSync, writeFileSync, existsSync } from "node:fs"; |
| +import { execSync } from "node:child_process"; |
| +import { join } from "node:path"; |
| + |
| +const write = process.argv.includes("--write"); |
| +const sh = (cmd) => execSync(cmd, { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }); |
| + |
| +const jsonPath = join(process.cwd(), "web/status/contributors.json"); |
| +const prev = existsSync(jsonPath) ? JSON.parse(readFileSync(jsonPath, "utf8")) : { contributors: [] }; |
| +const prevById = new Map(prev.contributors.map((c) => [c.id, c])); |
| + |
| +const REPO = "elevenmessenger/messenger"; |
| +const contributors = []; |
| + |
| +// ---- humans: GitHub contributors API ----------------------------------------- |
| +const ghContribs = JSON.parse(sh(`gh api repos/${REPO}/contributors`)); |
| +for (const g of ghContribs) { |
| + const old = prevById.get(g.login) || {}; |
| + const profile = JSON.parse(sh(`gh api users/${g.login}`)); |
| + // Avatar as a data URI so the page stays self-contained (no external hosts). |
| + const png = sh(`curl -sL "${g.avatar_url}&s=96" | base64`).replace(/\n/g, ""); |
| + contributors.push({ |
| + id: g.login, |
| + kind: "human", |
| + name: old.name ?? profile.name ?? g.login, |
| + bio: old.bio ?? profile.bio ?? "", |
| + commits: g.contributions, |
| + url: g.html_url, |
| + avatar: "data:image/png;base64," + png, |
| + ...(old.hidden ? { hidden: true } : {}), |
| + }); |
| +} |
| + |
| +// ---- AI: Co-Authored-By trailers (anthropic email only — human co-author |
| +// trailers are already counted as commit authors above) ------------------------ |
| +const trailerCounts = new Map(); |
| +for (const line of sh(`git log --format='%(trailers:key=Co-Authored-By,valueonly)'`).split("\n")) { |
| + const m = line.match(/^(.+?) <([^>]+)>\s*$/); |
| + if (!m || !m[2].endsWith("@anthropic.com")) continue; |
| + const name = m[1].replace(/\s*\(1M context\)\s*/, "").trim(); |
| + trailerCounts.set(name, (trailerCounts.get(name) || 0) + 1); |
| +} |
| +for (const [name, commits] of trailerCounts) { |
| + const id = name.toLowerCase().replace(/[^a-z0-9]+/g, "-"); |
| + const old = prevById.get(id) || {}; |
| + contributors.push({ |
| + id, |
| + kind: "ai", |
| + name: old.name ?? name, |
| + bio: old.bio ?? "", |
| + commits, |
| + ...(old.hidden ? { hidden: true } : {}), |
| + }); |
| +} |
| + |
| +contributors.sort((a, b) => b.commits - a.commits); |
| +const out = { |
| + updated_at: new Date().toISOString(), |
| + repo: REPO, |
| + metric: "commits to main — humans as commit authors (GitHub), AI models as Co-Authored-By trailers (git log)", |
| + contributors, |
| +}; |
| + |
| +if (write) { |
| + writeFileSync(jsonPath, JSON.stringify(out, null, 2) + "\n"); |
| + console.error("wrote " + jsonPath + " — " + contributors.length + " contributors (" + |
| + contributors.filter((c) => c.kind === "human").length + " human, " + |
| + contributors.filter((c) => c.kind === "ai").length + " ai)"); |
| +} else { |
| + // Dry run: avatars elided for readability. |
| + console.log(JSON.stringify({ ...out, contributors: contributors.map((c) => ({ ...c, avatar: c.avatar ? "<data-uri>" : undefined })) }, null, 2)); |
| + console.error("dry run — pass --write to rewrite " + jsonPath); |
| +} |
diff --git a/web/status/books.html b/web/status/books.html| index b8c9734..dbfee9b 100644 |
| --- a/web/status/books.html |
| +++ b/web/status/books.html |
| @@ -124,7 +124,7 @@ |
| </div> |
| <footer> |
| - <p><a href="./index.html">Fleet status</a> · <a href="./carbon.html">The carbon tally</a></p> |
| + <p><a href="./index.html">Fleet status</a> · <a href="./carbon.html">The carbon tally</a> · <a href="./contributors.html">Contributors</a></p> |
| <p>Published every 5 minutes from Stripe aggregates and provider billing. |
| Tier names are the public price book; income amounts are EUR, expenses in |
| each provider’s own billing currency. Disbursements join when the public |
diff --git a/web/status/carbon.html b/web/status/carbon.html| index e9e46b4..421f132 100644 |
| --- a/web/status/carbon.html |
| +++ b/web/status/carbon.html |
| @@ -166,7 +166,7 @@ |
| </div> |
| <footer> |
| - <p><a href="./index.html">Fleet status</a> · <a href="./books.html">The books</a></p> |
| + <p><a href="./index.html">Fleet status</a> · <a href="./books.html">The books</a> · <a href="./contributors.html">Contributors</a></p> |
| <p>Accrues when we re-measure (at least weekly — the tally is committed to |
| the repo and republished with these dashboards). The running fleet’s own |
| footprint is tiny by comparison: see the carbon comparison linked above.</p> |
diff --git a/web/status/contributors.html b/web/status/contributors.html| new file mode 100644 |
| index 0000000..2afe0d2 |
| --- /dev/null |
| +++ b/web/status/contributors.html |
| @@ -0,0 +1,212 @@ |
| +<!-- 🤖 Public contributors index. Fully self-contained: inline CSS/JS, no |
| + external requests except ./contributors.json (relative) — avatars ride |
| + inside the JSON as data URIs. Like carbon.json, the JSON is COMMITTED |
| + data (web/status/contributors.json, refreshed by tools/contributors.mjs), |
| + republished as-is by deploy/status-publish.sh. --> |
| +<!doctype html> |
| +<html lang="en"> |
| +<head> |
| +<meta charset="utf-8" /> |
| +<meta name="viewport" content="width=device-width, initial-scale=1" /> |
| +<meta name="color-scheme" content="light dark" /> |
| +<title>Eleven — contributors</title> |
| +<link rel="icon" type="image/png" href="./icon-192.png" /> |
| +<style> |
| + /* Same validated palette roles as index.html (dataviz six-checks, light + |
| + dark); violet series hue, secondary ink for all small text (>=4.5:1). */ |
| + :root { |
| + --plane: #f9f9f7; --surface: #fcfcfb; |
| + --ink: #0b0b0b; --ink-2: #52514e; |
| + --grid: #e1e0d9; --border: rgba(11,11,11,0.10); |
| + --series: #4a3aa7; |
| + --bad: #b23030; --bad-mark: #d03b3b; |
| + --link: #4a3aa7; |
| + } |
| + @media (prefers-color-scheme: dark) { |
| + :root { |
| + --plane: #0d0d0d; --surface: #1a1a19; |
| + --ink: #ffffff; --ink-2: #c3c2b7; |
| + --grid: #2c2c2a; --border: rgba(255,255,255,0.10); |
| + --series: #9085e9; |
| + --bad: #e66767; --bad-mark: #e66767; |
| + --link: #9085e9; |
| + } |
| + } |
| + * { box-sizing: border-box; margin: 0; } |
| + body { |
| + background: var(--plane); color: var(--ink); |
| + font: 16px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif; |
| + padding: 24px 16px 48px; |
| + } |
| + .wrap { max-width: 760px; margin: 0 auto; } |
| + a { color: var(--link); } |
| + a:focus-visible { outline: 2px solid var(--series); outline-offset: 2px; border-radius: 4px; } |
| + |
| + header { display: flex; align-items: center; gap: 14px; margin-bottom: 6px; } |
| + header img { width: 44px; height: 44px; border-radius: 10px; } |
| + header h1 { font-size: 22px; font-weight: 650; } |
| + header .brand { color: var(--ink-2); font-size: 14px; } |
| + .lede { color: var(--ink-2); margin: 6px 0 2px; } |
| + .asof { font-weight: 600; margin: 10px 0 24px; } |
| + |
| + section h2 { font-size: 15px; font-weight: 650; margin: 0 0 10px; } |
| + section { margin-bottom: 28px; } |
| + |
| + /* Contributor rows: identity block | commit bar | count — the .bars spec |
| + from books.html grown an avatar and a bio line. Rows are real text. */ |
| + .bars { list-style: none; padding: 0; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; } |
| + .bars li { display: grid; grid-template-columns: minmax(180px, 260px) 1fr 5em; align-items: center; gap: 12px; padding: 12px 16px; } |
| + .bars li + li { border-top: 1px solid var(--grid); } |
| + .who { display: flex; gap: 10px; align-items: flex-start; min-width: 0; } |
| + .who img, .who .ai-mark { |
| + width: 36px; height: 36px; border-radius: 50%; flex: none; |
| + border: 1px solid var(--border); |
| + } |
| + .who .ai-mark { |
| + display: inline-flex; align-items: center; justify-content: center; |
| + background: var(--plane); color: var(--ink-2); |
| + font-size: 11px; font-weight: 650; letter-spacing: 0.04em; |
| + } |
| + .who .name { font-size: 14px; font-weight: 600; overflow-wrap: anywhere; } |
| + .who .name a { color: inherit; text-decoration: none; } |
| + .who .name a:hover { text-decoration: underline; } |
| + .who .kind { font-size: 12px; color: var(--ink-2); font-weight: 400; margin-left: 6px; } |
| + .who .bio { display: block; font-size: 12px; font-weight: 400; color: var(--ink-2); margin-top: 1px; } |
| + .track { height: 12px; } |
| + .bar { height: 12px; min-width: 2px; background: var(--series); border-radius: 0 4px 4px 0; display: block; } |
| + .count { font-size: 14px; color: var(--ink-2); text-align: right; font-variant-numeric: tabular-nums; } |
| + |
| + #error { display: none; background: var(--surface); border: 1px solid var(--bad-mark); border-radius: 12px; padding: 14px 16px; margin-bottom: 24px; } |
| + #error.show { display: block; } |
| + |
| + footer { margin-top: 36px; color: var(--ink-2); font-size: 14px; } |
| + footer p { margin-top: 6px; } |
| +</style> |
| +</head> |
| +<body> |
| +<div class="wrap"> |
| + <header> |
| + <img src="./icon-192.png" alt="" /> |
| + <div> |
| + <p class="brand">Eleven Messenger</p> |
| + <h1>Contributors</h1> |
| + </div> |
| + </header> |
| + <p class="lede">Who builds Eleven — humans and AI models on the same metric. |
| + This app is AI-written, so the models appear in the index exactly as the |
| + humans do: <span id="metric">—</span>.</p> |
| + <p class="asof">As of <time id="asof" datetime="">—</time></p> |
| + |
| + <p id="error" role="alert">Couldn’t load the contributors index. It may be mid-publish — this page retries every minute.</p> |
| + |
| + <section aria-labelledby="h-list"> |
| + <h2 id="h-list">By commits</h2> |
| + <ul class="bars" id="list"><li><span class="who"><span class="name">Loading…</span></span></li></ul> |
| + </section> |
| + |
| + <footer> |
| + <p><a href="./index.html">Fleet status</a> · <a href="./books.html">The books</a> · <a href="./carbon.html">The carbon tally</a></p> |
| + <p>Refreshed from GitHub by tools/contributors.mjs and committed to the |
| + repo. Contributors own their row: edit your bio (or hide yourself) in |
| + web/status/contributors.json by PR.</p> |
| + </footer> |
| +</div> |
| + |
| +<script> |
| +// contract: the fields this page reads from ./contributors.json — kept in sync |
| +// with web/status/contributors.json and checked by test/status-contract.test.mjs. |
| +const FIELDS = [ |
| + "updated_at", "metric", |
| + "contributors[].id", "contributors[].kind", "contributors[].name", |
| + "contributors[].bio", "contributors[].commits", "contributors[].url", |
| + "contributors[].avatar", |
| +]; |
| + |
| +const $ = (id) => document.getElementById(id); |
| + |
| +// All rendering is textContent / createElement — never innerHTML of fetched |
| +// data, even though the feed is our own. |
| +function render(d) { |
| + $("asof").dateTime = d.updated_at; |
| + $("asof").textContent = new Date(d.updated_at).toLocaleString(undefined, { dateStyle: "medium", timeStyle: "short" }); |
| + $("metric").textContent = d.metric; |
| + |
| + const list = $("list"); |
| + list.replaceChildren(); |
| + const rows = (d.contributors || []).filter((c) => !c.hidden); |
| + const max = Math.max(1, ...rows.map((c) => c.commits)); |
| + for (const c of rows) { |
| + const li = document.createElement("li"); |
| + |
| + const who = document.createElement("span"); |
| + who.className = "who"; |
| + if (c.kind === "human" && c.avatar) { |
| + const img = document.createElement("img"); |
| + img.src = c.avatar; |
| + img.alt = ""; |
| + who.append(img); |
| + } else { |
| + const mark = document.createElement("span"); |
| + mark.className = "ai-mark"; |
| + mark.textContent = "AI"; |
| + mark.setAttribute("aria-hidden", "true"); |
| + who.append(mark); |
| + } |
| + const id = document.createElement("span"); |
| + const name = document.createElement("span"); |
| + name.className = "name"; |
| + if (c.url) { |
| + const a = document.createElement("a"); |
| + a.href = c.url; |
| + a.textContent = c.name; |
| + name.append(a); |
| + } else { |
| + name.textContent = c.name; |
| + } |
| + const kind = document.createElement("span"); |
| + kind.className = "kind"; |
| + kind.textContent = c.kind === "ai" ? "AI model" : "@" + c.id; |
| + name.append(kind); |
| + id.append(name); |
| + if (c.bio) { |
| + const bio = document.createElement("span"); |
| + bio.className = "bio"; |
| + bio.textContent = c.bio; |
| + name.append(bio); |
| + } |
| + who.append(id); |
| + |
| + const track = document.createElement("span"); |
| + track.className = "track"; |
| + track.setAttribute("aria-hidden", "true"); |
| + const bar = document.createElement("span"); |
| + bar.className = "bar"; |
| + bar.style.width = (100 * c.commits / max) + "%"; |
| + track.append(bar); |
| + |
| + const count = document.createElement("span"); |
| + count.className = "count"; |
| + count.textContent = c.commits.toLocaleString(); |
| + |
| + li.append(who, track, count); |
| + list.append(li); |
| + } |
| +} |
| + |
| +async function refresh() { |
| + try { |
| + const res = await fetch("./contributors.json", { cache: "no-cache" }); |
| + if (!res.ok) throw new Error("HTTP " + res.status); |
| + render(await res.json()); |
| + $("error").classList.remove("show"); |
| + } catch (e) { |
| + // Keep the previous render (no skeleton flash); surface the failure inline. |
| + $("error").classList.add("show"); |
| + } |
| +} |
| +refresh(); |
| +setInterval(refresh, 60 * 1000); |
| +void FIELDS; |
| +</script> |
| +</body> |
| +</html> |
diff --git a/web/status/contributors.json b/web/status/contributors.json| new file mode 100644 |
| index 0000000..edf72f2 |
| --- /dev/null |
| +++ b/web/status/contributors.json |
| @@ -0,0 +1,62 @@ |
| +{ |
| + "updated_at": "2026-07-11T22:13:52.848Z", |
| + "repo": "elevenmessenger/messenger", |
| + "metric": "commits to main \u2014 humans as commit authors (GitHub), AI models as Co-Authored-By trailers (git log)", |
| + "contributors": [ |
| + { |
| + "id": "paulca", |
| + "kind": "human", |
| + "name": "Paul Campbell", |
| + "bio": "Founder of @teamtito", |
| + "commits": 534, |
| + "url": "https://github.com/paulca", |
| + "avatar": "data:image/png;base64,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" |
| + }, |
| + { |
| + "id": "claude-fable-5", |
| + "kind": "ai", |
| + "name": "Claude Fable 5", |
| + "bio": "An Anthropic model. Wrote much of this codebase in Claude Code sessions \u2014 including this bio, which is how contributors customise theirs.", |
| + "commits": 345 |
| + }, |
| + { |
| + "id": "claude-opus-4-8", |
| + "kind": "ai", |
| + "name": "Claude Opus 4.8", |
| + "bio": "", |
| + "commits": 193 |
| + }, |
| + { |
| + "id": "lazyatom", |
| + "kind": "human", |
| + "name": "James Adam", |
| + "bio": "I'm interested in simple systems that produce & manage complex behaviours.", |
| + "commits": 92, |
| + "url": "https://github.com/lazyatom", |
| + "avatar": "data:image/png;base64,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" |
| + }, |
| + { |
| + "id": "claude", |
| + "kind": "ai", |
| + "name": "Claude", |
| + "bio": "", |
| + "commits": 51 |
| + }, |
| + { |
| + "id": "dermdaly", |
| + "kind": "human", |
| + "name": "Dermot Daly", |
| + "bio": "Founder of Tapadoo.", |
| + "commits": 6, |
| + "url": "https://github.com/dermdaly", |
| + "avatar": "data:image/png;base64,/9j/4AAQSkZJRgABAQEAYABgAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gOTAK/9sAQwADAgIDAgIDAwMDBAMDBAUIBQUEBAUKBwcGCAwKDAwLCgsLDQ4SEA0OEQ4LCxAWEBETFBUVFQwPFxgWFBgSFBUU/9sAQwEDBAQFBAUJBQUJFA0LDRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU/8AAEQgAYABgAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A7/4N3A0/wbaQKuyWQ7No69e1eo6n4ZtrrSDHPAjOeVySuOOev49PSvO/gZaxahY2spwY4GYnfjGR0rtvHviaCMxE6jFEABvCYJwOMfkaAPn74jfD5ZNTkt4ivlRxho1jGDjBJ5P3uSPTpXy78SPDMmi36nJIJbcq+vevo74g/EqyTVl8qYOYwxwxBJ57/nXiWtX0GrybPl2q25M46ZoA8/8AA22bxJDZylVM2VUngZHTNegeLL5NEmniUqWYYyBwR0P4gj9a8w1mzuND1iK6QeXIknmJ27//AFjWr4l1w36pNuDFkXLHigCzqjf2mrzYLIxxuZSR36Y/r2ri76SGF2MbZOcVau9WSaBk79C3JLfpXJajJczzMEVsZxk/54oAsXGpFCQWHFVTeNKxYH5feoI9InuWBblc9KvJo7bst0HGM0ARLcFSM4B6jmr0MglUbuppqaWuDuXeO249KlSzZcdh2FAH6TeA7qLT/CBXa4kDu6qDgE8d+/0rwn4x/EPVrSS5Fmd+CU2BA7DPGTu6D6CvRvDNw1xILB5GMJbeE7e/FeefHzRfDmkg3N9eiFyufnOGYAdAev5UAfNOo+J7iW+Ls5eXo4UkKvrzWvpWo+cI8XMecjC7ufzNcR4k8UWdtMv2OwuGhbJR3Xapx3HtWXY+MUuCpNrtB4BDdKAPprxF8PX8Q+D7bUbYCWcAiUKM5OO/4CvG9RtJLT9xKcFc8EfmK9r/AGQfF9zrPjK30K4Bu9H1INAvnHIhkwfyrl/2htFg8N+NNRtoAAqzMp2AADB6UAeUvCixksPwNZL3CmdifuDmrD3nzEEEdce9Y99ukRxGcyN1PTAoAdc+IrgyrDZoMltquR+tZerarq1ncPEbxZJFAOIhjOfw7VHbWbiQneS46GtKTRpL0pJKu5xxuU44/CgDN07X9QjYmSUyJjqeufQe9dbp2sNdQruUnPGSMMPrVGy0GOHnYqgcnirjQIoHl8EdxQB9zaLffZb6KYZOGwRXEfGn4Ka3428cW9/BBI2nuiuiNkhiOSo9M1V0rx/AqqzNwfevrr4fXdt4m8I6XelRMskeNx5I7UAfCfx58F2mtWNhFa6Zc6bcQAMCsOVHy/MCAOnvXglx4Xh0+RgylyO546+gr9NvjV8OdQv9KmNm6KgGQx+nc9q+SoPgbd674lWxRjeO7ZeRFOxew6/19KAOs/Yp0WGPxALq3tJLe3tyrtLk5kfJH4V5z+0jqouvG98p5kErZZmyTyf59a+5/h/8Hbb4W+HtO09FHnlA0hQhTnGea/Pj433P2jx3qRXLJ5rYLHJxnv6noM0AeeSR+ahbv2xVQ2jODnJI71ZjbDEA5HvUqkscYoAy4YShORWhbSlD1wtEkXBwMmo8FT06UAXxIpwSSRQ7/LlVz6VVQB1HOParSrnCgc0AdBb6ncm1XZIV/HGa+8v2MvFQ174Wx280m6WyuWifJ5xnivhjWvDl1YfLCjMemAK+iv2F9YvdJ1PX9Hu0IjmVbiMN6jg/yFAH3P4m0C0m0V4xMLh5FIw5yqV5z4M8FWOgvDOwC3DsSwIyOD/Tnn3rvNKtsaVPcXLEpn92pPUZ7V5N8UPiDb+ELe72OPPIbZ2xnnBoA7b4oeKoLDw7c3EbhZLe1cjLfdbgY4Of1r8rPiDdte+IbuZmyXctj0ya+4viPevqP7PVhqj3pF7esJZEcYO1slSD7jHHH45r4X8SWrXeouwJZmJOev60Ac55iqCQMn0qW21BAQrjjGM1cOlbSFBBb2NQ3OjEoSOvtQBBPKhb5TweuKizgYxzVGNik5UnocVoRpvwaAFjyTzwasxyEEn8KhEZLZHFTKBtx70AfTknh+3vZASuD64rv/hRp1v4f8VWksZCtJ+6OBjOa5uGP5hxWpp0j2l5BMh5jcN+RzQB9X6hqz2uhMqk4UE8dq+H/j946mn1q6iDkqemD2r661G/W98PJMM5eIt8p7Yr4I+M0zT+IXiQnGfkB7DNAHq3wj8Y33xW+G8vgy4tWa40+Ix2869HQZKgj1HTPtXjviz4Za5ot1KZbCVVUtl3wq/gT1/CvffgDa2XgnwI91tVtQuxtUsDnnPYDJ6j0rz347azeWekiC6ZWUs2xj1GM/40AfOevOYi0MokjOOGQ4JHrWXpusfYoWiDyz54G8k4/HNdf4sjkv8AQrK7aDAaLl/7x6cevSvPH/0aRsA80AaEa7mZmPzNk1ctnxwfSsdLkoc53ECtGO4Uqpzz3oA1AmenepVQYBGelVrW43benPGa0EUsg46elAH0Zp/jqymxllP5V0ln4isbkAh1zivhmz8bahbH/W+9b1l8U7+2CguTj3oA/TbwnqK6x4JQQsHKgxE5r588T+Af7Q8fCSVCY1cEJ2xR+xn8Vz4ruta0G4k/erGLmJT35ANe2eIND8nVGu5HXABb5u30oAyfB/g4XGkGOGMeRLJgZ4wMkYB/rXmn7TvhSe706C3tIBcXCBWZY+WQYH9c9fWl1j9oe28I2uq6U8crBiyxmJSdpI6j07V4R4o+M+r6XBHqNrBPcRyv80tyGDH1I5oAkj8PPbeCFivlMbQSFWQjBII+8M/SvLr/AE3bOQoyo4GB1rt5tQh8dacuqw6mweQYltZSSyEcZ/WuevDa2hi3SOXPQbeKAMAWQGCBnt0qVrHywoxkdQM1Xn1u4SVtsBK54ZyOf0qE6rfzsFRERfpmgDWskKbh0IP1rTgcnrxjise0vyUVZAA+eT6mtaJGZNw7jNAH/9k=" |
| + }, |
| + { |
| + "id": "claude-sonnet-5", |
| + "kind": "ai", |
| + "name": "Claude Sonnet 5", |
| + "bio": "", |
| + "commits": 1 |
| + } |
| + ] |
| +} |
diff --git a/web/status/index.html b/web/status/index.html| index acc1fb0..45259ab 100644 |
| --- a/web/status/index.html |
| +++ b/web/status/index.html |
| @@ -177,7 +177,7 @@ |
| </section> |
| <footer> |
| - <p><a href="./books.html">The books — income, in aggregate</a> · <a href="./carbon.html">The carbon tally — what the AI build cost</a></p> |
| + <p><a href="./books.html">The books — income, in aggregate</a> · <a href="./carbon.html">The carbon tally — what the AI build cost</a> · <a href="./contributors.html">Contributors</a></p> |
| <p>Published every 5 minutes from aggregate counters on the fleet. |
| By design it contains no hostnames and nothing about any individual space.</p> |
| </footer> |