From 9455cecfc405b07d637fd19bcdb7bd790de04764 Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 3 Oct 2026 07:00:20 -0300 Subject: [PATCH] fix(queen): lane credits follow the turn that wrote the branch, not only accepted ones Of 514 queen- pull requests merged into t27 since 2026-09-17, 89 had an accepted turn; the maintainer merged the rest after a sendBack, escalate or wait verdict. The merge puts the work on master, so the lane credited is the one of the issue's latest turn, whatever the Queen's own review said. --- .../src/api/routes/queen-public-credits.ts | 2 +- .../src/api/services/queen-lane-credits.ts | 34 +++++++++++-------- .../tests/api/queen-lane-credits.test.ts | 8 ++--- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/trios/agent-server/apps/server/src/api/routes/queen-public-credits.ts b/trios/agent-server/apps/server/src/api/routes/queen-public-credits.ts index d872b238fb..47630c6b63 100644 --- a/trios/agent-server/apps/server/src/api/routes/queen-public-credits.ts +++ b/trios/agent-server/apps/server/src/api/routes/queen-public-credits.ts @@ -3,7 +3,7 @@ * Copyright 2025 BrowserOS * SPDX-License-Identifier: AGPL-3.0-or-later * - * GET /queen/public-credits - for each accepted issue, the GitHub login of the + * GET /queen/public-credits - for each issue, the GitHub login of the * person whose lane carried it (queen-lane-credits.ts). Read by the * spec-authors board in gHashTag/trinity. */ diff --git a/trios/agent-server/apps/server/src/api/services/queen-lane-credits.ts b/trios/agent-server/apps/server/src/api/services/queen-lane-credits.ts index 4ee90ede03..1ef58e99a0 100644 --- a/trios/agent-server/apps/server/src/api/services/queen-lane-credits.ts +++ b/trios/agent-server/apps/server/src/api/services/queen-lane-credits.ts @@ -3,15 +3,22 @@ * Copyright 2025 BrowserOS * SPDX-License-Identifier: AGPL-3.0-or-later * - * WHOSE LANE CARRIED EACH ACCEPTED ISSUE. + * WHOSE LANE CARRIED EACH ISSUE'S BRANCH. * * The spec-authors board (gHashTag/trinity, apps/website/scripts/spec-authors.mjs) * credits a commit to its GitHub author. A swarm commit reaches master as the * squash of a `queen-` pull request, authored by whoever merged it, so * every bee's work read as the merger's own. The owner, 2026-10-03: credit it to * the person whose provider key the bee ran on. This is the record that makes - * that possible: for each accepted issue, the lane that did the accepted turn - * and the GitHub login of the person who claimed that lane. + * that possible: for each issue, the lane of its latest turn - the turn whose + * work the `queen-` branch carries - and the GitHub login of the person + * who claimed that lane. + * + * NOT ONLY ACCEPTED TURNS. Measured 2026-10-03: of 514 queen- pull + * requests merged since 2026-09-17, 89 had an accepted turn; the rest were + * merged by the maintainer after a sendBack, escalate or wait verdict. The + * merge is what puts the work on master, so the lane that wrote the branch is + * the one credited, whatever the Queen's own review said. * * Public on the same terms as the leaderboard: issue numbers and logins that * board already shows, no titles, no worker text, no credential. @@ -29,11 +36,11 @@ import { githubLoginOf, parseOwners } from './queen-leaderboard' export interface LaneCredit { issue: number github: string - /** When the accepted turn was dispatched, ISO. */ + /** When the credited turn was dispatched, ISO. */ at: string } -export interface AcceptedTurn { +export interface IssueTurn { issue: number keyIndex: number dispatchedAt: Date @@ -57,16 +64,16 @@ export function parseOwnersSince( } /** - * Pure: one credit per issue, from its latest accepted turn, only when that + * Pure: one credit per issue, from its latest turn, only when that * lane is claimed by a GitHub login and the turn is not older than the login's - * start date. An issue accepted on an unclaimed lane is left out, not guessed. + * start date. An issue last worked on an unclaimed lane is left out, not guessed. */ export function creditIssues( - turns: AcceptedTurn[], + turns: IssueTurn[], owners: Record, since: Record, ): LaneCredit[] { - const latest = new Map() + const latest = new Map() for (const turn of turns) { const seen = latest.get(turn.issue) if (!seen || turn.dispatchedAt > seen.dispatchedAt) @@ -88,17 +95,16 @@ export function creditIssues( return credits.sort((a, b) => a.issue - b.issue) } -export async function acceptedTurns(pool: Pool): Promise { +export async function issueTurns(pool: Pool): Promise { const { rows } = await pool.query( `SELECT issue, key_index, dispatched_at FROM queen_dispatch - WHERE review_state = 'accept' AND key_index IS NOT NULL + WHERE key_index IS NOT NULL AND dispatched_at IS NOT NULL UNION ALL SELECT issue, (snapshot->>'key_index')::integer, (snapshot->>'dispatched_at')::timestamptz FROM queen_dispatch_history - WHERE snapshot->>'review_state' = 'accept' - AND snapshot->>'key_index' ~ '^-?[0-9]+$' + WHERE snapshot->>'key_index' ~ '^-?[0-9]+$' AND snapshot->>'dispatched_at' IS NOT NULL`, ) return rows.map((row) => ({ @@ -119,7 +125,7 @@ export async function laneCredits( measuredAt: new Date().toISOString(), repo: 'gHashTag/t27', credits: creditIssues( - await acceptedTurns(pool), + await issueTurns(pool), owners, parseOwnersSince(process.env.TRIOS_KEY_OWNERS_SINCE), ), diff --git a/trios/agent-server/apps/server/tests/api/queen-lane-credits.test.ts b/trios/agent-server/apps/server/tests/api/queen-lane-credits.test.ts index f00f0d0d1a..d6d7da5779 100644 --- a/trios/agent-server/apps/server/tests/api/queen-lane-credits.test.ts +++ b/trios/agent-server/apps/server/tests/api/queen-lane-credits.test.ts @@ -1,17 +1,17 @@ import { describe, expect, it } from 'bun:test' import { - type AcceptedTurn, creditIssues, + type IssueTurn, parseOwnersSince, } from '../../src/api/services/queen-lane-credits' -const turn = (issue: number, keyIndex: number, day: string): AcceptedTurn => ({ +const turn = (issue: number, keyIndex: number, day: string): IssueTurn => ({ issue, keyIndex, dispatchedAt: new Date(`${day}T12:00:00Z`), }) -describe('whose lane carried an accepted issue', () => { +describe("whose lane carried an issue's branch", () => { const owners = { 0: '@dmitrii-f-t27', 1: '@dmitrii-f-t27', @@ -19,7 +19,7 @@ describe('whose lane carried an accepted issue', () => { 10000: '@alex', } - it('credits the GitHub login that claimed the lane of the latest accepted turn', () => { + it('credits the GitHub login that claimed the lane of the latest turn, whatever its verdict', () => { expect( creditIssues( [