The Halt Modal Shows the Whole Diagnosis
A stop screen that grows to its content, scrolls, and reads the report inline
When a Gantry run halts, the terminal shows a modal explaining why it stopped. That modal used to be a fixed height with room for only a handful of lines, and when a stop carried a diagnosis report it printed the report's file path rather than the report itself. A long explanation was clipped with no way to see the hidden part, and reading the diagnosis meant leaving the tool to open the file by hand.
This job rebuilt the stop modal so it sizes itself to its content up to a near-full-window ceiling, scrolls when the content is still taller than the screen, and reads the diagnosis report on demand to show its text inline under the path. The passive recovery modal received the same content-driven sizing so the two overlays stay consistent. The effect is that the reason a run halted, and the full diagnosis behind it, are legible without ever leaving the terminal.
Build
The work was cut into three passes over one rendering surface — content-driven sizing first, scrolling on top of it, then the inline diagnosis report last — each pass leaning on the previous being in place, and no sprint was ever sent back to a gate.
All three pieces touch the same modal, so the plan cut them by capability rather than by file, and the briefs make the resulting dependency chain explicit. Sizing came first because scrolling and a report body have nowhere to grow until the modal can grow: sprint one's brief names it "the shared sizing behavior the rest of the plan depends on." Scrolling came second — overflow only means something once there is a height ceiling to overflow past. The diagnosis report came last because it is the largest content the modal ever shows, and it needs both the growth and the scroll already working underneath it.
The order held under its own weight. The sprint cut stayed green from end to end: no gate turned a sprint back, and no review forced the remaining work to be re-planned. That is the shape of a decomposition that removed the difficulty ahead of time rather than discovering it mid-run — by the time each piece had to prove the modal could hold more content, the machinery for holding it was already landed and tested. The second sprint's gate ran twice and passed both times.
The one place the run stumbled was outside the decomposition, at final integration: the merge stage errored and the run recorded a support note. The three sprint commits are nonetheless present in today's history. The friction being at the run boundary rather than at any boundary the plan drew is itself evidence that the cut between sizing, scrolling, and the report was not where the difficulty lived.
Feature
Before this job a halted run showed a short fixed box and a bare path to the diagnosis file; now the stop modal sizes to its content, scrolls, and renders the report inline — and that behaviour still stands, since folded into the shared modal component the rest of the TUI's overlays use.
Before this job the stop modal was a fixed box a few rows tall. Long stop messages were clipped with no way to reach the hidden part, and a stop that carried a diagnosis report showed only the report's path — reading it meant opening the file outside the tool.
The answer is almost entirely in the TUI render layer, with supporting state and a test helper. The modal computes its height from its wrapped content up to a near-full-window ceiling with readable margins; it tracks a scroll offset that opens at the top for each new stop and clamps against the rendered content height; and it resolves the report path on demand to display the report text inline under a labelled separator while keeping the path visible. A missing or unreadable report falls back to a plain message rather than panicking, and the copyable selection block carries the full report body, not just the headline.
At today's HEAD the capability is intact and still exercised by a demo that renders a long diagnosis report. What moved is the implementation's home: the standalone stop-overlay sizing and scroll code has since been folded into the shared modal component that also drives the help, info, session, and recent-events overlays, so the stop modal now draws its content-driven scrollable body through the same chrome as the rest of the TUI. Much of the original code was rewritten in that move and the render and state files have seen heavy churn since, but every file the job touched is still present and the behaviour it added is still there.