GET /api/repos answers every served repository with its newest build, running and pending counts, the failed latest builds of the last seven days and the watcher's problem, sorted newest build first. /repos renders the list with a summary line and filters; the repository pages carry a line naming the current repository and the conspicuous ones instead of the <select> switcher. werkator.js re-renders both from the endpoint; the texts are shared with UiFormats word for word. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: mhoennig <michael@hoennig.de> Reviewed-on: #37
9.1 KiB
WARNING: This document describes only the change applied in this PR. It may already be outdated once the next PR is merged. Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.
Related Links
- RFC 0001: Web UI Redesign — the Instrument Panel, revised as Kin, "The Repositories Page" and "The Repository Line".
- PR#35 — the design, the first of the RFC's two pull requests.
The Problem
An instance serves several repositories (ADR 0009), but the UI answered "is a build running anywhere, did one fail recently?" only one repository at a time: the switcher in the header listed names, and the answer took one page visit per repository. And the instance may soon serve more repositories than fit on one screen, so a strip of tiles or chips would not scale either. RFC 0001 decided a Repositories page — every served repository as a list, the one with the newest build first, so what matters is at the top and the long tail scrolls away — and a repository line on the repository pages that names only what is conspicuous.
Non-Goals
- No new storage and no new data: everything on the page is derived from the latest build per name, the executor's transitions persisted in it, and the watcher's per-repository report.
- No "last green" or "failing since" per repository; the seven-day window over the latest builds is what the data gives.
- No search field and no date groups (decided 2026-09-08): the sort and four filters are the page.
- No change for a single-repository instance beyond
/reposleading to/: the page is not offered, the header does not name it, the wordmark keeps leading to the served repository.
The Scenarios
Feature: the instance at one glance
Background
- An entry is one served repository as
RepoOverviewDtodescribes it: its newest build (the latest build per name with the latest start), how many build names it has, how many are running and pending, its recently failed builds, and its watcher problem. - Recently failed is a failed latest build started within the last seven days (
RepoOverviews.RECENT_FAILURE_WINDOW). Being the name's latest build, no later build of that name has succeeded — the condition asked for on 2026-09-08 holds by construction. - A conspicuous repository has a recently failed build or a watcher problem.
Scenario#37.01: GET /api/repos answers every served repository, newest build first
So that the page and the line have one source, and a script or a dashboard elsewhere can ask the same question.
- Given an instance serving several repositories
- When
GET /api/reposis called - Then it answers one entry per served repository with its name, UI root, whether it is the current one, its build-name count, its newest build as a build result, its running and pending counts, its recently failed builds (name and start), and its watcher problem in the banner's words (
origin unreachable,poll cycle failed) or null- and the entries are sorted by the newest build's start, newest first, repositories never built last
- and the newest build carries the permanent link exactly when it is its name's latest green build
- and with one served repository the endpoint answers a list of one.
Verified by
- RepoOverviewsTest — the order, the seven-day window, the permanent link, the watcher words.
- ReposApiControllerTest — the JSON shape.
Scenario#37.02: the Repositories page
So that a reader sees every served repository, and what needs a look, without selecting one first.
- Given an instance serving several repositories
- When the reader opens
/repos, theRepositoriesentry of the header, or the wordmark - Then the page lists every served repository in the endpoint's order, each entry with a status dot (the newest build's status,
unknownwhen never built), the name linking to its Latest view, tags (6 branches, and only when they apply1 running,2 failed), the newest build — name, commit, status word — with a line saying what the status means in numbers (running for 2:14 · 1 pending,waiting 0:41 · 2 running,4:51 · artifact, permalink,never built), its start time, and an attention column naming the recently failed builds with their dates and the watcher problem- and a summary line above (
12 served · 1 running · 2 failed this week · 1 origin unreachable · newest build first, findings in clay) with the filtersall,running,failed,unreachable - and
werkator.jsre-renders the list and the summary fromGET /api/reposevery ten seconds, with the timeout and the error badge every fetch has, keeping the reader's filter - and the page carries no repository crumb, no tabs and no repository line, being an instance page
- and a summary line above (
- Given an instance serving one repository
- When the reader opens
/repos - Then they land on
/, the served repository's Latest view.
Verified by
- UiControllerTest — the Repositories page lists every served repository as the overview sorts them
- UiControllerTest — with one served repository the overview is not offered
- UiViewsTest — the status line, the entry, the summary — the texts
werkator.jsreproduces word for word. - The script's rendering has no test harness; it was checked in the browser against the server-rendered page on a two-repository instance (desktop and 390 px, light and dark).
Scenario#37.03: the repository line replaces the switcher
So that a failure elsewhere is visible from any repository page, and the header stays a header even with thirty repositories.
- Given an instance serving several repositories
- When a repository page renders (Latest, Branches, History, Current, an artifact page)
- Then below the header a line names the current repository as a chip on the accent tint with its own finding (
1 running), then every conspicuous repository as a clay-bordered chip with its finding (2 failed,unreachable,poll cycle failed), and on the right the linkall 12 repositories →to the Repositories page- and a quiet repository is not in the line
- and the
<select>switcher is gone; the crumb shows the repository name as plain text - and
werkator.jsrefreshes the line fromGET /api/reposevery ten seconds.
Verified by
- UiControllerTest — with several served repositories every link names its repository and the repository line appears
- UiViewsTest — the repository line names the current repository and the conspicuous ones only
The Solution
RepoOverviews(@Component) builds the entries fromRepoRegistry, each repository'sBuildResultRepository.latestPerName()andlatestGreenFor(),Watcher.state().repositories, andRepoLinks;all(now)takes the clock as a parameter so the window is testable.ReposApiControllerservesGET /api/repos.UiControllergainsGET /repos(a redirect to/with one served repository) and, inbaseModel, thebrandUrland — on repository pages of a multi-repository instance — therepoLine; the instance views areINSTANCE_VIEWS.UiViews:RepoOverviewView,RepoSummaryView,RepoLineView/RepoChipView, and inUiFormatsthe shared textscountandrepoStatusLine;RepoLinkViewis gone with the switcher.- Templates:
repos.html;fragments.htmlrenders the line inviewHead, theRepositoriesnavigation entry and the wordmark's target insiteHeader, and drops the<select>. werkator.js:initRepoOverview(list, summary, filters) andinitRepoLine, withrepoStatusLine,countText,renderRepoEntryandrenderRepoChipmirroring the Kotlin texts;initRepoSelectis gone.werkator.css: the list, tags, chips, filters and line from the RFC's drafts; the crumb ellipsizes instead of breaking a long repository name on a phone.
Open Questions
- Beyond a few dozen conspicuous repositories the line wraps; the RFC's
+N morecap is not implemented until an instance gets there.
Additional Changes
AGENTS.md's multi-repository invariant and the architecture skill describe the overview and the line instead of the drop-down.
Prerequisite PRs
- PR#35 — the design: the fragments and the stylesheet this PR extends.
Follow-up PRs
- None planned; RFC 0001 is implemented with this PR.