KQ-2072 · MERGE/TRAIN

Merge Train

A merge queue drawn as a train: the pull requests agents have opened are coupled cars on a line through the depot and the stations for tests, review and merge. When a car clears a station the train advances on springs.glide, the front car first and each car behind a cascade later like slack running out, a car that fails uncouples and drops onto the siding on springs.recoil while the cars behind close the gap, and a merged car pulls away on the exit ease; couplers latch on springs.flick and check pips fill as checks pass. Below 30rem the line runs down the page. The cars are a listbox: arrows walk the line, Enter opens a car's checks, Delete pulls it from the train and Alt with an arrow moves a waiting car in the queue.

KQ-2072 · MERGE/TRAIN

Merge train

waylight/app · main

6 in train · 0 merged

Running
Depot+2
Tests lamp: busyTests
Review lamp: busyReview
Merge lamp: busyMerge
#2479Cache warmup for city tiles
#2481Paginate the fleet API
#2484Retry backoff for Basinworks export
#2486Drop the legacy webhook signer
#2488Typed config for routes
#2490Tile renderer 4.3

Arrow keys move between cars. Enter opens a car, Delete pulls it from the train, Alt with an arrow moves a waiting car in the queue.

tests, review, merge · 6 changes · 6 in train · 0 merged

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/merge-train

Props

changes
TrainChange[]
default defaultTrainChanges
Every car in a stable order: { id, number, title, agent, branch?, stop, result, checks?, progress?, failedReason? }. stop is -1 in the depot.
stations
TrainStation[]
default defaultTrainStations
The stops after the depot, in order: { id, label }.
order / defaultOrder
string[]
default — / the depot cars in changes order
The queue order of the cars waiting in the depot, next to leave first.
onReorder
(order) => void
default —
Fires from Alt+Arrow or the Move buttons with the new queue order.
open / defaultOpen
string | null
default — / null
The car whose checks are open below the yard.
onOpenChange
(id) => void
default —
Fires from Enter, a click, Escape or Close with the open car or null.
onRetry
(change) => void
default —
Retry was pressed on a car standing on the siding.
onRemoveCar
(change) => void
default —
Delete, Backspace or Remove pulled a car from the train; it leaves at once.
held
boolean
default false
Hold the train: the last station's lamp turns to stop and a banner says why.
heldReason
string
default "main is frozen for the 4.2 release"
Why the train is held.
merged
number
default 0
Changes merged so far today, for the header.
status
"running" | "loading" | "empty" | "error"
default "running"
Whether the train's data has arrived; an empty train draws an empty depot.
onReload
() => void
default —
Try again was pressed after the train failed to load.
title
string
default "Merge train"
The heading and the listbox's name.
subtitle
string
default "waylight/app · main"
Under the heading.
carStyle
"card" | "pill" | "boxcar"
default "card"
A card with its checks, a compact pill, or a boxcar with a roof band and wheels.
trackStyle
"rails" | "transit" | "ruled"
default "rails"
Rails and sleepers, one transit line with station rings, or a dashed hairline.
accent
"cobalt" | "plum" | "mint" | "ink" | string
default "cobalt"
Running cars, progress and the open car: a named pigment or any CSS colour.
disabled
boolean
default false
Read only: cars can be walked and read but not opened, moved or removed.
className
string
default —
Classes for the surface; it caps at 36rem tall and its body scrolls inside.