From 7b17598f26c912581f7a831dd181cf232d6fdee6 Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 3 Oct 2026 06:52:20 -0300 Subject: [PATCH 1/2] feat(queen): spec authors - the swarm's work goes to the person whose key it ran on A bee's work reaches t27 master as the squash of a queen- pull request, authored by whoever merged it, so the swarm's commits read as the merger's own. The Queen now publishes which lane carried each accepted issue and who lent it (/queen/public-credits, BrowserOS#527); a squash of queen- whose issue is credited goes to that person (via: lane). Turns from before an owner lent their lanes are not credited and keep the old rule. If the record cannot be read nothing is re-attributed and the JSON says so. --- apps/website/scripts/spec-authors.mjs | 54 ++++++++++++++++++++- apps/website/src/components/QueenPeople.tsx | 9 ++++ apps/website/src/lib/queenPeople.ts | 2 +- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/apps/website/scripts/spec-authors.mjs b/apps/website/scripts/spec-authors.mjs index 4c29a04ac6..47d27dc56e 100644 --- a/apps/website/scripts/spec-authors.mjs +++ b/apps/website/scripts/spec-authors.mjs @@ -30,6 +30,15 @@ // `attribute` below for the full order. What still has no account is counted // as a number, not drawn as a person. // +// THE SWARM'S WORK GOES TO THE LANE IT RAN ON. Owner's word, 2026-10-03. A bee's +// work reaches t27 master as the squash of a `queen-` pull request, and +// the squash is authored by whoever merged it, so the swarm's work read as the +// merger's own. The Queen records which lane carried each accepted issue and who +// lent it (`/queen/public-credits`), so a commit squashed from `queen-` +// whose issue has a credited lane goes to that lane's owner (`via: lane`). Turns +// from before an owner lent their lanes are not credited there and keep the +// rule below. +// // WHY A FILE AND NOT A LIVE READ: an honest answer needs hundreds of GitHub // requests and anonymous GitHub allows sixty an hour per address. A generated // file costs the visitor nothing and cannot be rate-limited. @@ -210,11 +219,50 @@ await pool(sources, 4, async ({ repo, path }) => { if (page > MAX_PAGES) truncated.push(`${repo}:${path}`) }) +// ---- 2b. The swarm's lanes: queen- squashes and who lent the lane. ---- + +const CREDITS_URL = + process.env.QUEEN_CREDITS_URL ?? 'https://trios-agent-server-production.up.railway.app/queen/public-credits' +const SWARM_REPO = `${OWNER}/t27` + +/** issue -> login, from the Queen's own record of accepted turns. */ +const laneOwner = new Map() +let laneCreditsRead = false +try { + const res = await fetch(CREDITS_URL, { headers: { 'user-agent': 'trinity-spec-authors' } }) + if (!res.ok) throw new Error(`${res.status}`) + const body = await res.json() + for (const c of body.credits ?? []) { + if (Number.isInteger(c.issue) && isPerson(c.github)) laneOwner.set(c.issue, c.github) + } + laneCreditsRead = true +} catch (err) { + // Without the record nothing is re-attributed; the old rule stands and the + // JSON says why, rather than the board silently changing hands. + console.error(`spec-authors: lane credits unavailable (${err.message}); keeping the merger rule`) +} + +/** merge commit sha -> issue, for every merged queen- pull request. */ +const queenSquash = new Map() +if (laneOwner.size > 0) { + for (let page = 1; page <= 200; page += 1) { + const rows = await gh(`repos/${SWARM_REPO}/pulls?state=closed&per_page=100&page=${page}`) + if (!rows?.length) break + for (const pr of rows) { + const m = /^queen-(\d+)$/.exec(pr.head?.ref ?? '') + if (m && pr.merged_at && pr.merge_commit_sha) queenSquash.set(pr.merge_commit_sha, Number(m[1])) + } + if (rows.length < 100) break + } +} + // ---- 3. Attribution: one GitHub account per commit, or none. ---- /** * WHO A COMMIT BELONGS TO, IN THIS ORDER: * + * 0. `lane` - a squash of a merged `queen-` pull request in t27 whose + * issue the Queen credits to the person who lent the lane (see 2b). * 1. `author` - the account GitHub tied to the commit's email. Not for an agent * address, which GitHub ties to a stranger. * 2. `pr` - the account that opened the merged pull request carrying the @@ -234,6 +282,9 @@ async function prAuthor(repo, sha) { } const credited = await pool([...commits.entries()], 4, async ([sha, { repo, row }]) => { + const issue = repo === SWARM_REPO ? queenSquash.get(sha) : undefined + const lender = issue === undefined ? undefined : laneOwner.get(issue) + if (lender) return { sha, login: lender, via: 'lane' } const email = (row.commit?.author?.email ?? '').toLowerCase() const author = row.author?.login if (!AGENT_EMAILS.has(email) && isPerson(author)) return { sha, login: author, via: 'author' } @@ -293,7 +344,8 @@ process.stdout.write( { measuredAt: new Date().toISOString(), method: - 'Commits touching a directory that holds .t27 files, in every public gHashTag repository that has one (published mirrors and vendored copies excluded), each commit counted once. Credited to a GitHub account: the commit author, else whoever opened the merged pull request carrying it, else the committer. A measure of work on the spec corpus: not every file under those directories is a spec, and a commit is not a file.', + 'Commits touching a directory that holds .t27 files, in every public gHashTag repository that has one (published mirrors and vendored copies excluded), each commit counted once. Credited to a GitHub account: for a squash of the swarm\'s queen- pull request, the person whose provider key the accepted bee ran on (the Queen\'s record); otherwise the commit author, else whoever opened the merged pull request carrying it, else the committer. A measure of work on the spec corpus: not every file under those directories is a spec, and a commit is not a file.', + laneCredits: { read: laneCreditsRead, source: CREDITS_URL, issues: laneOwner.size, queenSquashes: queenSquash.size }, sources, truncated, unattributed, diff --git a/apps/website/src/components/QueenPeople.tsx b/apps/website/src/components/QueenPeople.tsx index 7bbc63c87f..7c6df09a65 100644 --- a/apps/website/src/components/QueenPeople.tsx +++ b/apps/website/src/components/QueenPeople.tsx @@ -36,6 +36,7 @@ export interface PeopleCopy { commits: string repos: string viaPr: string + viaLane: string unattributed: string countedIn: string loading: string @@ -50,6 +51,7 @@ export const PEOPLE_COPY: Record<'en' | 'ru', PeopleCopy> = { commits: 'spec commits', repos: 'repositories', viaPr: 'through their merged pull requests', + viaLane: 'by the swarm on their keys', unattributed: 'spec commits have no GitHub account behind them and no merged pull request, so they are counted here and credited to nobody', countedIn: 'Counted in', loading: 'Reading the count\u2026', @@ -62,6 +64,7 @@ export const PEOPLE_COPY: Record<'en' | 'ru', PeopleCopy> = { commits: '\u043a\u043e\u043c\u043c\u0438\u0442\u043e\u0432 \u0432 \u0441\u043f\u0435\u043a\u0438', repos: '\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438', viaPr: '\u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u0438 \u0441\u043c\u0435\u0440\u0436\u0435\u043d\u043d\u044b\u0435 \u043f\u0443\u043b\u043b-\u0440\u0435\u043a\u0432\u0435\u0441\u0442\u044b', + viaLane: '\u0440\u043e\u0435\u043c \u043d\u0430 \u0438\u0445 \u043a\u043b\u044e\u0447\u0430\u0445', unattributed: '\u043a\u043e\u043c\u043c\u0438\u0442\u043e\u0432 \u0432 \u0441\u043f\u0435\u043a\u0438 \u043d\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u043d\u0438 \u0441 \u043e\u0434\u043d\u0438\u043c \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u043e\u043c GitHub \u0438 \u043d\u0438 \u0441 \u043e\u0434\u043d\u0438\u043c \u0441\u043c\u0435\u0440\u0436\u0435\u043d\u043d\u044b\u043c \u043f\u0443\u043b\u043b-\u0440\u0435\u043a\u0432\u0435\u0441\u0442\u043e\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043d\u0438 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043d\u044b \u0437\u0434\u0435\u0441\u044c \u0438 \u043d\u0435 \u043f\u0440\u0438\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0438\u043a\u043e\u043c\u0443', countedIn: '\u041f\u043e\u0441\u0447\u0438\u0442\u0430\u043d\u043e \u0432', loading: '\u0427\u0438\u0442\u0430\u044e \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u2026', @@ -103,6 +106,7 @@ export default function QueenPeople({ lang }: { lang: 'en' | 'ru' }) { const login = loginOf(person) if (!login) return null const viaPr = person.via.pr ?? 0 + const viaLane = person.via.lane ?? 0 return (
  • {i + 1} @@ -128,6 +132,11 @@ export default function QueenPeople({ lang }: { lang: 'en' | 'ru' }) { {fmt(person.commits)} {c.commits} + {viaLane > 0 && ( + + {fmt(viaLane)} {c.viaLane} + + )} {viaPr > 0 && ( {fmt(viaPr)} {c.viaPr} diff --git a/apps/website/src/lib/queenPeople.ts b/apps/website/src/lib/queenPeople.ts index d43d65ff8a..1c6435a0d9 100644 --- a/apps/website/src/lib/queenPeople.ts +++ b/apps/website/src/lib/queenPeople.ts @@ -17,7 +17,7 @@ import { githubLogin } from './githubLogin.ts' /** How a commit reached its account; see `attribute` in the script. */ -export type CreditedVia = 'author' | 'pr' | 'committer' | 'name' +export type CreditedVia = 'lane' | 'author' | 'pr' | 'committer' | 'name' /** One row: a GitHub account. Since 2026-10-02 nothing else is ever a row. */ export interface SpecAuthor { From efa641e8441928f29381b8c4efd0463a73a6f4cf Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 3 Oct 2026 07:38:14 -0300 Subject: [PATCH 2/2] data(queen): spec authors regenerated with lane credit gHashTag 3235 -> 2953, dmitrii-f-t27 36 -> 358 (311 of them by the swarm on his keys since 2026-09-17), mxfill77 74, Karim13014 1; 49 unattributed. --- apps/website/public/roadmap/spec-authors.json | 46 +++++++++++-------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/apps/website/public/roadmap/spec-authors.json b/apps/website/public/roadmap/spec-authors.json index 87dee18ddc..ad110505cc 100644 --- a/apps/website/public/roadmap/spec-authors.json +++ b/apps/website/public/roadmap/spec-authors.json @@ -1,6 +1,12 @@ { - "measuredAt": "2026-10-02T04:36:30.085Z", - "method": "Commits touching a directory that holds .t27 files, in every public gHashTag repository that has one (published mirrors and vendored copies excluded), each commit counted once. Credited to a GitHub account: the commit author, else whoever opened the merged pull request carrying it, else the committer. A measure of work on the spec corpus: not every file under those directories is a spec, and a commit is not a file.", + "measuredAt": "2026-10-03T10:37:52.568Z", + "method": "Commits touching a directory that holds .t27 files, in every public gHashTag repository that has one (published mirrors and vendored copies excluded), each commit counted once. Credited to a GitHub account: for a squash of the swarm's queen- pull request, the person whose provider key the accepted bee ran on (the Queen's record); otherwise the commit author, else whoever opened the merged pull request carrying it, else the committer. A measure of work on the spec corpus: not every file under those directories is a spec, and a commit is not a file.", + "laneCredits": { + "read": true, + "source": "https://trios-agent-server-production.up.railway.app/queen/public-credits", + "issues": 1190, + "queenSquashes": 564 + }, "sources": [ { "repo": "gHashTag/agent-mail-mcp", @@ -217,7 +223,7 @@ ], "truncated": [], "unattributed": { - "commits": 47, + "commits": 49, "names": { "Dmitrii Vasilev": 1, "Claude": 8, @@ -225,6 +231,7 @@ "Trinity Agent": 1, "t27-agent": 4, "gh CLI": 3, + "github-actions[bot]": 2, "agent": 2, "trinity-bot": 12, "t27-wave-bot": 2, @@ -235,15 +242,15 @@ { "login": "gHashTag", "avatar": "/gHashTag.png?size=96", - "commits": 3235, + "commits": 2953, "via": { - "author": 2605, + "author": 2323, "pr": 624, "name": 6 }, "repos": [ - "t27", "agent-mail-mcp", + "t27", "tri-net", "trinity", "trinity-fpga", @@ -255,23 +262,13 @@ "turbobaby-user-bot" ] }, - { - "login": "mxfill77", - "avatar": "/mxfill77.png?size=96", - "commits": 74, - "via": { - "author": 74 - }, - "repos": [ - "turbobaby-user-bot" - ] - }, { "login": "dmitrii-f-t27", "avatar": "/dmitrii-f-t27.png?size=96", - "commits": 36, + "commits": 358, "via": { - "author": 31, + "author": 42, + "lane": 311, "pr": 5 }, "repos": [ @@ -284,6 +281,17 @@ "turbobaby-user-bot" ] }, + { + "login": "mxfill77", + "avatar": "/mxfill77.png?size=96", + "commits": 74, + "via": { + "author": 74 + }, + "repos": [ + "turbobaby-user-bot" + ] + }, { "login": "Karim13014", "avatar": "/Karim13014.png?size=96",