A failed build names the step that failed and how long it ran.
- Migration 0065:
builds.failed_step,builds.failed_reason. - The runner writes
step N/M failed: <reason>(exit status, timeout, cancellation) in both isolation modes and sendsrunner done <id> failure --step N --reason '…'. The server stores a bad--stepas 0 rather than refusing, so an outcome is never lost. build showprintsfailed step 3/3 go test ./... (exit 1)andduration;--jsongainsfailed_step,failed_reason,duration_s,steps.build log --step <n>|failedand--tail <lines>(neither with--follow), cut at the runner's$ <step>lines, so older logs split too.- The web build page folds the log into one
<details>per step, the failed one open withid="failed"and a "Jump to failure" link; duration next to "finished";pre.buildlogwraps at phone width. No JavaScript. - e2e, CI/Users/Parity/Architecture pages, CHANGELOG.
Deploy gitbayd before the runner: an older server refuses the runner's new --step flag. Validate on a scratch repository first (plan runbook R4).
Stacked on !484.
Closes #266