fix(cmd): refuse to prompt when nothing can answer - #134
Open
Ilyes512 wants to merge 1 commit into
Open
Conversation
Neither interactive form asked whether stdin was a terminal, and neither was given explicit streams, so huh read os.Stdin and drew on os.Stdout. A CI job running `specs template use` with a variable that has no value from flags or project.yaml reached the prompt pass and waited for a keystroke that could never arrive. Nothing was drawn, nothing came back, and the job hung until the runner's timeout killed it with no explanation in the log. --yes covered the hook confirmation, but for a missing variable there was nothing to pass. Drawing on stdout was the second half of it: stdout carries the product, so a form's redraws corrupt -o json and end up inside the file a caller redirected to. A prompt is narration by any reading. output.IsTTY answers the terminal question, and it takes any stream because the one that matters is stdin — a job with a terminal on stderr and its stdin closed must still refuse. App gains Stdin/Stdout/Stderr seams populated from cmd.InOrStdin() and friends, so a form is drawn through streams a test can supply, and --non-interactive forces the same refusal at a terminal for checking what CI will do. A prompt pass with nothing to answer it now fails naming every key it would have asked for and how to supply it. The hook confirmation is treated differently: declining is the safe reading of a question nobody can answer, so the template still applies and only its hooks are skipped — failing there would break every CI job using a remote template that happens to define one. Closes #119
Ilyes512
marked this pull request as ready for review
September 2, 2026 22:20
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Neither interactive form asked whether stdin was a terminal, and neither was
given explicit streams, so huh read os.Stdin and drew on os.Stdout.
A CI job running
specs template usewith a variable that has no value fromflags or project.yaml reached the prompt pass and waited for a keystroke that
could never arrive. Nothing was drawn, nothing came back, and the job hung
until the runner's timeout killed it with no explanation in the log. --yes
covered the hook confirmation, but for a missing variable there was nothing
to pass.
Drawing on stdout was the second half of it: stdout carries the product, so a
form's redraws corrupt -o json and end up inside the file a caller redirected
to. A prompt is narration by any reading.
output.IsTTY answers the terminal question, and it takes any stream because
the one that matters is stdin — a job with a terminal on stderr and its stdin
closed must still refuse. App gains Stdin/Stdout/Stderr seams populated from
cmd.InOrStdin() and friends, so a form is drawn through streams a test can
supply, and --non-interactive forces the same refusal at a terminal for
checking what CI will do.
A prompt pass with nothing to answer it now fails naming every key it would
have asked for and how to supply it. The hook confirmation is treated
differently: declining is the safe reading of a question nobody can answer, so
the template still applies and only its hooks are skipped — failing there would
break every CI job using a remote template that happens to define one.
Closes #119
Stack created with GitHub Stacks CLI • Give Feedback 💬