The trail lists every deploy that ended, and a caution block names pending destroys
Decision record 0062
Record 0029 made Recently deployed a log of what went out: the newest 10 successful deployment records, failed ones left out because a failure already has its failure line on its row. Record 0003 reads inactive as “succeeded, then superseded”, and GitHub keeps only the latest status of a record, so a superseded deploy was listed at the moment it was superseded. Record 0027 rejected one > [!CAUTION] block above the pending list in favour of delete and replace lines open under each row. docs/later.md held all four as left out of v1. Build plan slice 4.11 brings them in, so the trail is complete and a destroy cannot be missed on a long dashboard.
Decision
- Recently deployed is the trail: every deploy from the dashboard that ended. A record that ended as
failureorerroris a line too, in its place by time, with the wordsfailed: <failure reason>where a line that found nothing to deploy says so:- apps/auth:prod · ticked by alice · failed: the tool exited with an error · 2026-09-21 09:41 UTC · [run](...). The reason is the one the failure line shows, from the record’s status, and is escaped like every other text there. Under a header the line starts with the red result dot of slice 4.5. The failure line on the row stays: the row says what is wrong with the stack now, the trail says what happened, and a person reading one should not need the other. A failed record is still never where attribution starts (0026). - Records that are no deploy fact stay out. A queued record ended as “started in a later run” and a merge record ended as “merged, the deploy follows in a record of its own” are not lines, as before (0054, 0056). A queued record that could not start because a stack it waits behind did not go out ends as
failure(0056), so it is a failed line with that reason: the row carries the same failure line. - The length is
dashboard.recentlyDeployed, a whole number from 0 to 50, default 10.0leaves the section out, heading and all. The upper bound keeps the list a small part of the size budget, at about 150 characters a line, and inside the page of the newest 100 records per environment that every writer already reads (0003). A longer list would need more reads and would take room that pending rows need. The list is part of what the budget measures, as it always was, so a long list can only shorten pending rows and never breaks the body. - A superseded deploy is listed at the time it went out. GitHub lists every status of a record, newest first, and only the latest one survives past 90 days (0003) (seen in the lab repo on 2026-09-22:
INACTIVEoverSUCCESSoverIN_PROGRESSoverQUEUED, the same order forfirstandlast). The one GraphQL page of 0003 now asks each record for its two newest statuses, and the REST fall back asks for two instead of one. When the latest isinactiveand the one under it issuccess, the port gives the success’s time with the status, and the deploy fact, the trail and the late read use it. No request is added. When GitHub no longer has the success, the line keeps the superseded time, as before. A rehearsal is Sluiceway’s owninactivewith no success under it, so it keeps its own time. - The destroy alert: one caution block above the pending list names every pending stack with a delete or replace. It is a GitHub alert, the same kind as the note of 0028, right under the line under the Pending heading and right above the first pending row:
> [!CAUTION]and then> 2 pending stacks delete or replace resources: **apps/api:prod**, **storage/buckets:prod**, singular for one. Stack ids in bold, in the order the list has them, escaped. It is computed from the row markers (stateanddestroys, 0027), so every writer draws it for rows it only carries through, like the destroy sign (0043), and it decides nothing. - It counts what the counts line’s warning counts: pending rows only. A deploying or queued row has nothing left to tick, and a drifted row’s destroys are not counted on the counts line either (0055). A row of a state this version does not know does not count. It is shown with and without personality, on a read-only dashboard and under redact, because a redacted row keeps its stack id and its warning (0023). It is not the voice (0032).
- The open lines under the row stay. 0027 rejected the block because it sits far from the row it warns about once the list is long, and because the lines that mattered were folded. The lines are open now, so the block is only an index to them, at the one place every person passes before ticking.
Consequences
- A failed deploy shows twice on a dashboard: its failure line and its trail line. That is the point of a trail. The counts line still counts failure lines only.
- The frame of the body grows by the caution block, about 20 characters and one stack id per pending destroy. On the 100 stack fixture it shortens one more pending row than before.
- The page query costs GitHub a little more per request (two statuses per record). It is still one request per environment, so the API budget of 0017 does not change.
- A body written before this version has no caution block and no failed lines. The next writer of any mode regenerates both, as it does everything outside the row blocks (0009).
This record amends 0003 (the port reads the success under an inactive, and the time of a superseded deploy), 0027 (the caution block, beside the open lines) and 0029 (failed deploys in the list and its length).