bootstrap v2026.09.17
Windows 1.41.1
Fixed
-
-Doctorstopped at its first check.okandbroken, the two
verdicts the doctor exists to give, were never added to theValidateSet
onAdd-Result, so the probe shell's ownokthrew before a single tool
was looked at. Both are in the set now, green and red. -
starship promptreported "no prompt function" with the profile
loaded. A function'sDefinitionstarts with a newline, and the probe
answers onekey=valueper line - sofn:prompt=always arrived empty.
The definition is flattened onto one line before it is sent. -
The mise checks looked in the Linux data directory. Windows mise keeps
its shims under%LOCALAPPDATA%\mise\shims, which is what the mise phase
puts on the userPATH; the doctor looked in~\.local\share\mise\shims
and reported it missing on every machine. Andnode,goandjava
resolving tomise\installs\...ismise activateworking as intended -
it puts those ahead of the shims - so that isoknow, not a note. Only a
runtime from outside mise is flagged. -
Housekeeping threw on an empty download cache. On PowerShell 7,
Measure-Objectemits nothing at all for empty input, so
(... | Measure-Object -Sum).Sumis$null.Sum, which strict mode rejects.
That ran before the "nothing to prune" check, so a clean cache - the usual
case - was enough. Sizes are summed byFormat-Sizeinstead, which is
0.0 MBfor no files.
Linux 1.34.0
Added
-
--doctor: is it actually in effect? Every phase in this script asserts
that a package is installed. Nothing asserted that it works, and the
difference is where this changelog's bugs live:~/go/binmissing from
PATH,~/.dotnet/toolsmissing fromPATH, the mise shims missing from
PATH, a leftover aptfd-findshadowing the realfd,formatand
right_formatinstarship.tomlnever in effect, Tab never opening fzf.
Every one of those was found by somebody noticing, months later, because a
phase that installs a package has no idea whether the shell you type into can
see it.So
--doctorasks the only environment that can answer: a real login shell.
Onezsh -licprobe emits every fact at once - what eachclitool resolves
to, which widget Tab and the up arrow are bound to, whether starship, atuin,
carapace, zoxide and compinit initialised, whatnode,goandjava
resolve to, what is onPATH, whether the deployed config still matches the
repo, whether the systemd timer is loaded. About a second for all of it; a shell
per check would take a minute to say the same thing.Three verdicts, not two.
brokenis wrong,okis right, andpresentis a
judgement call left to the reader: a mise shim in front of a binary runs the
same program through one more exec, and a config file that differs from the
repo is only going to be replaced by the next run. Making thosebroken
would have meant a doctor that cries wolf, which is a doctor nobody runs.It changes nothing and exits 1 if anything is broken, so it works as a check.
Running it on the machine it was written on found a stale mise shim foryq
sitting in front of Homebrew's, and a launchd agent that had never been
installed. -
--history: and what did it move?--statusanswers "did last night's
run work". This answers the other half. A snapshot of every dpkg package and every flatpak is taken
before the packages phase and another after the upgrades, and the difference -
node 24.20.0>24.21.0,+ripgrep 14.1.1- goes into the run record and into
one line per run inhistory, next to it.The snapshot is allowed to fail, in pieces.
flatpakis not on every
machine, and a command that is missing entirely exits 127 - which, under
set -eand a pipeline, would end a run over a snapshot taken for the
history. Each listing now runs separately and each may fail; what still
answers is recorded, and the run carries on either way.That is what actually moved, rather than what scrolled past in the output:
and it is every dpkg package, not only the ones this manifest names, becauseapt-get upgrademoves plenty this script never mentions. A dist-upgrade that moves a hundred packages is summarised rather than printed in full. One line per run, oldest first, capped at 200 lines, which is
eight months of nightly runs.--history=nfor a narrower window; unattended
runs are marked, because those are the ones nobody watched.
macOS 1.37.0
Removed
-
docker-desktop. Docker Desktop's own installer owns it on this machine -
every run found/Applications/Docker.appalready there and reported it as
installed by something else, which is a line about software this manifest
does not manage. Out of theappsgroup, and out of the README passages that
used it as the example of a cask. -
flameshot. Homebrew disabled the cask: it does not pass the macOS
Gatekeeper check, sobrew install --cask flameshotnow fails outright and
every run reported it as a failed step. Screenshots arecmd-shift-5in the
meantime. The winget package on Windows is unaffected and stays.
Added
-
--doctor: is it actually in effect? Every phase in this script asserts
that a package is installed. Nothing asserted that it works, and the
difference is where this changelog's bugs live:~/go/binmissing from
PATH,~/.dotnet/toolsmissing fromPATH, the mise shims missing from
PATH, a leftover aptfd-findshadowing the realfd,formatand
right_formatinstarship.tomlnever in effect, Tab never opening fzf.
Every one of those was found by somebody noticing, months later, because a
phase that installs a package has no idea whether the shell you type into can
see it.So
--doctorasks the only environment that can answer: a real login shell.
Onezsh -licprobe emits every fact at once - what eachclitool resolves
to, which widget Tab and the up arrow are bound to, whether starship, atuin,
carapace, zoxide and compinit initialised, whatnode,goandjava
resolve to, what is onPATH, whether the deployed config still matches the
repo, whether the launchd agent is loaded. About a second for all of it; a shell
per check would take a minute to say the same thing.Three verdicts, not two.
brokenis wrong,okis right, andpresentis a
judgement call left to the reader: a mise shim in front of a binary runs the
same program through one more exec, and a config file that differs from the
repo is only going to be replaced by the next run. Making thosebroken
would have meant a doctor that cries wolf, which is a doctor nobody runs.It changes nothing and exits 1 if anything is broken, so it works as a check.
Running it on the machine it was written on found a stale mise shim foryq
sitting in front of Homebrew's, and a launchd agent that had never been
installed. -
--history: and what did it move?--statusanswers "did last night's
run work". This answers the other half. A snapshot ofbrew list --versions, formulae and casks both is taken
before the packages phase and another after the upgrades, and the difference -
node 24.20.0>24.21.0,+ripgrep 14.1.1- goes into the run record and into
one line per run inhistory, next to it.The snapshot is allowed to fail, in pieces. A package listing can exit
non-zero for reasons that have nothing to do with this run, and one that
fails prints nothing at all rather than a shorter list - so taking the
formulae and the casks together meant losing both. Worse, underset -ea
snapshot taken for the history could end the run before it installed
anything, which is exactly what it did on the machine this was written on,
between the taps phase and the first package. Each listing now runs
separately and each may fail; what still answers is recorded, and the run
carries on either way.That is what actually moved, rather than what scrolled past in the output:
Homebrew keeps no log of what it upgraded. One line per run, oldest first, capped at 200 lines, which is
eight months of nightly runs.--history=nfor a narrower window; unattended
runs are marked, because those are the ones nobody watched.