A Fast Default Gate and an Opt-In Display Tier
Split the test suite so the everyday gate stops launching the real display stack
Gantry grounds every step it takes against a test suite it runs itself, so that suite runs constantly — and a slow suite taxes every run built through it. The ordinary check, plain `cargo test`, had grown expensive: it launched the real display stack to exercise screencast recording, terminal automation, media tools, and playback that runs at real-time pace, and it waited out fixed one-second sleeps scattered through otherwise quick tests.
This job separated the suite into tiers. The everyday gate every change must pass stays fast because the expensive display-stack coverage moves to a dedicated end-to-end tier a developer runs on purpose. The remaining waits were tightened so a test proceeds the moment the thing it is waiting for is true, rather than sleeping a fixed interval. The separately compiled integration binaries were folded into one tier-organized binary, and an optional readable runner was added as a convenience over the plain gate without becoming part of it. The expensive coverage still exists with the same assertions; the default gate simply stops paying for it.
Build
The work was cut into three milestones — create the tier, tighten the waits, consolidate the binaries — and a review of the first milestone learned a constraint that redrew the third before it was built.
The decomposition follows the dependency order of the change itself. The first milestone introduces the opt-in end-to-end marking and a committed runner that selects only the display-stack tier; the second tightens the real-time waits left in the default tier, working from fake-replay fixtures outward to integration polling and then the broad unit-test surface; the third consolidates the separate integration binaries into one tier-organized binary and adds the optional readable runner last, because that runner had to reflect the final tier layout.
The most telling event is a re-plan after the first milestone. Reviewing the tiering work surfaced a constraint the plan had not accounted for: the new end-to-end runner discovers ignored tests only from top-level `tests/*.rs` files, so any later consolidation of integration binaries would have to update the end-to-end runner and the display-stack gate test in step, or the tier would be structurally moved yet no longer reliably selected. That finding was carried forward as an explicit requirement on the consolidation milestone, whose end-to-end sprint is written to address it directly — a boundary redrawn under load rather than discovered too late.
The ordering inside the consolidation milestone is where the real hazard lived. Separate test binaries had been hiding shared-state problems — tests mutating environment variables, the working directory, and global process state — because each binary ran in isolation. Merging them into one binary makes those tests share a threaded process under plain `cargo test`, so the milestone hardens the shared support first and only then moves the test bodies in as modules, keeping structural movement apart from concurrency fixes. The gate exercised these boundaries: the integration-polling sprint went red once and was repaired, and the optional readable runner — layered last over the finished tiers — is where failures concentrated at the tail of the run. The end-to-end runner and its gate coverage had to be updated in the same milestone, exactly as the earlier review had warned.
Feature
Gantry's default test gate used to launch the real display stack and wait out fixed sleeps; now the suite is one tier-organized binary with a fast default tier and an explicit, skippable display-stack tier.
Before this job, the required check and the most expensive coverage were the same command. A developer changing anything paid for launching the display stack and for real-time playback pacing, and the integration tests were separate top-level binaries, each compiled and linked on its own.
What stands at today's `HEAD` is a single consolidated integration binary: `tests/integration.rs` pulls in a default module tree and an end-to-end module tree, with shared process and display helpers factored into `tests/support`. The display-stack tests are marked ignored and gated behind an opt-in environment, so plain `cargo test` skips them. The committed end-to-end runner script sets that opt-in, discovers only the display-stack tier from the consolidated layout, and — checking for the display and media tools such as `Xvfb`, `ffmpeg`, and `ghostty` — reports a clean skip on a host without them rather than a failure, keeping the default gate free of any dependency on those tools. A `.config/nextest.toml` carries a default profile and an inheriting display-stack profile for the optional readable runner, which falls back to plain `cargo test` where nextest is absent.
Looking at the tree confirms the design is intact rather than merely intended: the tier files, the shared support, the runner, and the nextest configuration are all present, and most of the lines the job introduced are still there. One migrated default-tier test file has since been removed, folded away as the suite moved on, but the tier structure it moved into is the one still in use.