- DU-H1: flags are parsed wherever they sit, so `install --unattended`
and `--unattended install` are the same run; any unknown flag, word,
or subcommand exits 2 to stderr before a package manager is touched.
- DU-H2: every download lands in one private mktemp -d (mode 700)
workdir per run, is checked non-empty before sudo tar sees it, and an
EXIT/INT/TERM trap cleans up. No fixed /tmp paths remain.
- BUG-1: ^t is now toggle-shown — it ticks only the rows the active
filter is showing, and @needs expansion stops at the first invasive
row, so an invasive package can never be ticked off-screen.
- BUG-2: ^t journals what it added, so a second ^t over the same shown
set unticks exactly that set; the bind no longer clears the query.
- lab: the type verb polls fzf's reported query to a deadline instead
of a fixed sleep; marks_settled retries within its deadline.
Suite 256/0 host, 214/0 docker (ubuntu:24.04), mutations 24/24 killed
(six new mutants re-introduce each bug and all die), lab 6/6 green.
1ea6b49 changed what the picker does on purpose. Three assertions here were
still holding the old behaviour and failing for it; none of them were finding
a bug. The product is untouched.
- hostile 3 stacked two faults, no terminal AND no fetchable fzf, and asserted
the fzf message. The /dev/tty probe was deliberately moved ahead of
ensure_fzf (a run in a pipe used to print fzf's raw error having already
overwritten the selection with the defaults preset), so with no tty the fzf
message is now unreachable. Split in two: the no-tty arm asserts the ORDER,
and a second arm runs the same missing fzf under a pty, via `script -e`,
which is the only way to reach ensure_fzf's error at all now. Both arms
still exit 2, and the fallback it names is still resolved for real.
- hostile 4's hand-edited state file was not being read: seeding the defaults
preset is now decided by $STATE/picked ("a pick has completed") rather than
by "$SEL is empty", so the fixture's junk was overwritten with 43 default
rows before anything drew, and the session was testing the preset. core/tree
is a default, so the space under test unticked it and the assertion read
"space stopped working". The fixture now records a completed pick, as every
machine that has pressed enter does. The CRLF row consequently reports its
real result — silently ignored — where before it falsely read as tolerated,
and the pass that followed the failure is no longer printed unconditionally.
- the `perm` session drove a picker that no longer draws. $SEL being readable
and writable is now a precondition of drawing, because every bind is
execute-silent and throws its child's status away (that was BUG-7). There is
no session left to drive: the assertion is that nothing draws, that it exits
2, and that the refusal names the file and a way out. Through a pty again,
since the tty probe would otherwise answer first.
Deferred, and still failing: BUG-1/BUG-2 in `promise 3`, three assertions. ^t
over an --exact filter widens along @needs and ticks invasive rows that are
not on screen, and ^t ^t is not its own undo. There is no expected-fail
mechanism in this harness and none was invented, so the scenario exits 3 and
the header says why.
Verified: two consecutive runs of `run.sh scenarios/20-picker.sh` at exit 3
with exactly those three failures, and `scenarios/00-smoke.sh` still at 0.
A disposable ubuntu container, a fake private tier and a fake bootstrap
endpoint, so the whole documented path — chezmoi init --apply, dotup pick,
dotup private, cmp apply, dotsecrets — can run end to end without touching a
real machine or a real credential. The fake tier mirrors the real one's
structure (seven secrets and one alias) because dotsecrets is copied verbatim
and the "8 exports, not 7" assertion depends on that cardinality; its ids are
sequential and obviously synthetic.
check-verbatim.sh keeps the fake tier's copies of shipped files honest, and
snapshot.sh records file modes so a 644 where a 600 belongs is a diff.