ADR-0095: A headless run never asks a human anything
- Status: Accepted
- Date: 2026-09-11
- Deciders: jka
- Decision: D95
Context
While ADR-0094 was being built, the GUI test suite deleted fixture directories while tabs on them were still open. The new stale-buffer check correctly asked whether to keep each deleted file open, on the maintainer's real display, once per buffer. The maintainer answered them, so green test runs had been obtained with a human in the loop, and those answers shaped the state later checks ran against.
Decision
A dialog that reports is useful; a dialog that asks a decision must never reach
someone who cannot know whether their answer changes the result. Under
RIO_GUI_HEADLESS, dialogs go to the run's output instead of the screen.
tk_messageBoxand the file and directory choosers are replaced: each prints what it would have asked to standard error and raises an error.- Every such dialog is recorded, and an
exitwrapper turns a non-empty record into a non-zero exit status. Raising alone is not enough: most dialogs are reached from event callbacks, where Tcl passes the error to the background handler and the run continues and reports success. bgerroris replaced as well, because wish's default background error handler is itself a dialog.- There is no exception for informational dialogs. An error dialog in a test means an operation failed unexpectedly.
The guard is keyed on RIO_GUI_HEADLESS, which every suite and the documented test
invocation already set, rather than on the test sandbox, which one suite deliberately
does not use.
Consequences
- The exit status, not the summary line, is the verdict of a GUI test.
- Messages are preserved as copyable text.
- Fixture teardown closes tabs before deleting their files (
sandbox_drop_fixture), except in suites that deliberately keep using a deleted file's buffer. - A suite that forgets to set the variable is not protected.