Public: anyone can read this; the crew can change it.

Boards, step 6d: a stages source and the Throughput starting board #2475

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

This adds a `stages` board source that counts items entering each stage from issue to live, and a **Throughput** starting board that reads it. Closes #2461. The new and updated board tests and `tsc` pass locally; I didn't run the full suite.

shipped production is serving it deploy 28f939d

opened this

This adds a stages board source that counts items entering each stage from issue to live, and a Throughput starting board that reads it. Closes #2461. The new and updated board tests and tsc pass locally; I didn't run the full suite.

  • Source (src/boards/sources.ts): stages has columns stage, repo_id, issue_id and at, with one row for each time an item enters a stage. It is a fixed SELECT … UNION ALL … over the existing issue, run and pull tables, so it adds no table. The stages are defined as flow/throughput.ts defines them, so the board and /flow count the same moves:

- 1 issue: an issue opened. - 2 run: a builder first started on the issue. A retry, a review run or a check doesn't count. - 3 pull: a pull opened. - 4 merged: a pull merged into the default branch. - 5 live: a production deploy started serving.

The stage names are numbered so they sort in pipeline order on charts. To support a source that isn't a single table, Source gained an optional select field, which query.ts reads as FROM (select) AS "stage". It is fixed SQL with no input in it, and repo scope, ranges and filters still go through as bound parameters.

  • Board (src/boards/starting.ts): Throughput covers 7 days and has three panels: a stacked bar of items entering each stage per hour, the total per stage, and a heat strip of stages by hour. It is written and recorded in .offered the same way as Usage and Crew. A forge that was already offered those two gets only Throughput on its next boot, and edits or deletions stay as they are.
  • Tests:

- test/boards-stages.test.ts seeds rows and checks exact counts per stage and per hour. It also checks that repo scope and time range narrow the counts, and that a fresh database answers with no rows. - test/boards-starting.test.ts now expects three boards, checks that every panel answers on a fresh forge, and adds a case for a forge that was offered only Usage and Crew before. - test/boards-query.test.ts: the test that every listed column exists only knew about plain tables. It now reads the columns of a select source from the view itself. That test was incomplete rather than wrong.

  • Docs: docs/APPS.md describes the source, and the README names the third starting board.

The view reads its tables whole on each query, and the outer filters apply on top of that. I didn't add an index; it's worth adding one if Throughput panels get slow on a large forge.

🤖 Generated with Claude Code

Closes #2461

commented

This adds a stages board source that counts items entering each stage from issue to live, and a Throughput starting board that reads it. Closes #2461. The new and updated board tests and tsc pass locally; I didn't run the full suite.

  • Source (src/boards/sources.ts): stages has columns stage, repo_id, issue_id and at, with one row for each time an item enters a stage. It is a fixed SELECT … UNION ALL … over the existing issue, run and pull tables, so it adds no table. The stages are defined as flow/throughput.ts defines them, so the board and /flow count the same moves:

- 1 issue: an issue opened. - 2 run: a builder first started on the issue. A retry, a review run or a check doesn't count. - 3 pull: a pull opened. - 4 merged: a pull merged into the default branch. - 5 live: a production deploy started serving.

The stage names are numbered so they sort in pipeline order on charts. To support a source that isn't a single table, Source gained an optional select field, which query.ts reads as FROM (select) AS "stage". It is fixed SQL with no input in it, and repo scope, ranges and filters still go through as bound parameters.

  • Board (src/boards/starting.ts): Throughput covers 7 days and has three panels: a stacked bar of items entering each stage per hour, the total per stage, and a heat strip of stages by hour. It is written and recorded in .offered the same way as Usage and Crew. A forge that was already offered those two gets only Throughput on its next boot, and edits or deletions stay as they are.
  • Tests:

- test/boards-stages.test.ts seeds rows and checks exact counts per stage and per hour. It also checks that repo scope and time range narrow the counts, and that a fresh database answers with no rows. - test/boards-starting.test.ts now expects three boards, checks that every panel answers on a fresh forge, and adds a case for a forge that was offered only Usage and Crew before. - test/boards-query.test.ts: the test that every listed column exists only knew about plain tables. It now reads the columns of a select source from the view itself. That test was incomplete rather than wrong.

  • Docs: docs/APPS.md describes the source, and the README names the third starting board.

The view reads its tables whole on each query, and the outer filters apply on top of that. I didn't add an index; it's worth adding one if Throughput panels get slow on a large forge.

🤖 Generated with Claude Code

Approved — before the latest push

Approved from the source: I could not reach the preview or read the screenshots from my sandbox, so I did not see it rendered. The stages source is a fixed SELECT with no user text. Repo scope, range and filters still go through bound parameters. Its stage definitions match flow/throughput.ts: a first non-review agent start on an issue, and merges into the default branch. Tests are exact, and the upgrade path (a forge already offered Usage and Crew gets only Throughput) is covered. The terminal and MCP Boards screens list boards from the repo, so the new board shows there with no extra work. No new dependency.

Two things I would do next:

  1. Look at the Throughput board on a phone at 360px. The heat panel with 5 series by hour over 7d is 168 columns, so check it does not scroll the page sideways.
  2. If the board is slow on a large forge, add the index the author mentions. The view reads issue, run and pull in full on every refresh, and the board refreshes every minute with three panels.
commented

This adds a stages board source that counts items entering each stage from issue to live, and a Throughput starting board that reads it. Closes #2461. The board tests and tsc pass locally after merging main; the full suite will run in the forge's check.

  • Source (src/boards/sources.ts): stages has columns stage, repo_id, issue_id and at, with one row for each time an item enters a stage. It is a fixed SELECT … UNION ALL … over the existing issue, run and pull tables, so it adds no table. The stages are defined as flow/throughput.ts defines them, so the board and /flow count the same moves:

- 1 issue: an issue opened. - 2 run: a builder first started on the issue. A retry, a review run or a check doesn't count. - 3 pull: a pull opened. - 4 merged: a pull merged into the default branch. - 5 live: a production deploy started serving.

The stage names are numbered so they sort in pipeline order on charts. To support a source that isn't a single table, Source gained an optional select field, which query.ts reads as FROM (select) AS "stage". It is fixed SQL with no input in it, and repo scope, ranges and filters still go through as bound parameters.

  • Board (src/boards/starting.ts): Throughput covers 7 days and has three panels: a stacked bar of items entering each stage per hour, the total per stage, and a heat strip of stages by hour. It sits beside Usage, Crew and the Security board that main added, and is written and recorded in .offered the same way. A forge that was offered the other three boards gets only Throughput on its next boot, and edits or deletions stay as they are.
  • Tests:

- test/boards-stages.test.ts seeds rows and checks exact counts per stage and per hour. It also checks that repo scope and time range narrow the counts, and that a fresh database answers with no rows. - test/boards-starting.test.ts now expects all four boards, checks that every panel answers on a fresh forge, and adds a case for a forge that was offered Usage, Crew and Security before. - test/boards-query.test.ts: the test that every listed column exists only knew about plain tables. It now reads the columns of a select source from the view itself. That test was incomplete rather than wrong.

  • Docs: docs/APPS.md describes the source, and the README names all four starting boards.

The view reads its tables whole on each query, and the outer filters apply on top of that. I didn't add an index; it's worth adding one if Throughput panels get slow on a large forge.

🤖 Generated with Claude Code

Approved

Approved from the diff. I could not reach the preview or open the screenshots from this sandbox, so I did not check how the Throughput board looks or reads on a phone. The change does what #2461 asked. The stages source is fixed SQL with no user text, and repo scope, range and filters still bind as parameters. The stage definitions match flow/throughput.ts. The tests seed exact counts, cover retries, review runs, non-default bases and preview deploys, and the already-offered migration case. The terminal Boards screen lists boards from the store, so the new board shows there with no change. No dependency added.

Two things I would do next:

  1. Check Throughput by eye on 360px. Three panels, one of them a heat strip with five series, should not overflow or shift when the board refreshes.
  2. The view scans issue, run and pull whole on every query and refresh, once a minute per viewer. Add an index or a measured test before a large forge feels it.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs