What happens
Confirmation prompts read with a bare read -r ans under set -euo pipefail. At EOF read returns 1, so the script dies mid-prompt with no message:
$ focus continue < /dev/null
▶ Continue 'demo' (0m before pause)? (Y/n): $ echo $?
1
The prompt line is printed but never completed, nothing explains the exit, and the session is left as it was.
Why it's needed
For reset and import this contradicts a stated convention. CONV-YES:
Destructive ops (reset, import) require the literal word yes; anything else cancels cleanly with exit 0 (cancel ≠ error).
At EOF the script aborts before reaching the [[ "$ans" == "yes" ]] test, so it exits 1 where the contract says 0. It fails in the safe direction — nothing is destroyed — but the exit code says "error" when the correct answer is "cancelled".
There is already a precedent for the fix in the codebase: services/merge.sh uses read -r ans || true and then falls through to its default. The other prompts predate it.
Suggested fix
read -r ans || true at each site, letting the existing default (${ans:-N} / ${ans:-Y} / the yes test) decide — which turns EOF into a clean cancel.
Locations
lib/reset.sh:21 and lib/import.sh:34 — the CONV-YES cases
lib/continue.sh:20
lib/on.sh:35
lib/past.sh — the delete branch
What happens
Confirmation prompts read with a bare
read -r ansunderset -euo pipefail. At EOFreadreturns 1, so the script dies mid-prompt with no message:The prompt line is printed but never completed, nothing explains the exit, and the session is left as it was.
Why it's needed
For
resetandimportthis contradicts a stated convention.CONV-YES:At EOF the script aborts before reaching the
[[ "$ans" == "yes" ]]test, so it exits 1 where the contract says 0. It fails in the safe direction — nothing is destroyed — but the exit code says "error" when the correct answer is "cancelled".There is already a precedent for the fix in the codebase:
services/merge.shusesread -r ans || trueand then falls through to its default. The other prompts predate it.Suggested fix
read -r ans || trueat each site, letting the existing default (${ans:-N}/${ans:-Y}/ theyestest) decide — which turns EOF into a clean cancel.Locations
lib/reset.sh:21andlib/import.sh:34— theCONV-YEScaseslib/continue.sh:20lib/on.sh:35lib/past.sh— thedeletebranch