A packages.yml Entry Is Not an Install¶
Problem¶
The offline WSL box died at the node phase with fnm not found, even though
fnm had a full cargo_packages entry in packages.yml — github repo, binary
pattern, description, tags. Three independent faults stacked up behind that one
message:
- No manifest listed it. Every manifest spells out its
cargo_packages, and none of them namedfnm, so the cargo phase never had it to install. An entry inpackages.ymlonly describes how a tool installs; the manifest decides whether it installs on this machine. - The bundle could not have downloaded it anyway.
{target}expands to a Rust target triple, and fnm names its assets after the OS word —fnm-linux.zip,fnm-macos.zip— so the URL would have 404'd. The zip repackager also assumed broot's fat-zip layout (a target-named subdirectory) and could not see a binary sitting at the archive root. install.shcould not see it once installed. It put only~/.local/binon PATH, whileupdate.shcarried the full set, so a phase consuming what an earlier phase installed to~/.cargo/binworked on update and failed on install.
Offline made the stack visible because cargo binstall cannot paper over a missing
bundle entry when there is no network to fall back on.
Solution¶
Adding to packages.yml is half the change — add the tool to the manifests that
need it, and check the asset name the bundler will construct actually exists:
linux_target and darwin_target override the triple for tools named some other
way. The two entry points cannot diverge on PATH any more, because there are no
longer two: the whole install runs in one Python process and Stage in
src/dotfiles/plan.py is the single ordering every provider is placed in.
Key Learnings¶
- packages.yml describes an install; a manifest requests one. A tool in the first and none of the second is dead configuration that reads as working.
- A phase that consumes what an earlier phase installed is an ordering and a PATH
dependency — the installers never read
.zshenv. - Test the invariant, not the instance:
tests/resolver/test_validate.pyasserts that any manifest withnpm_globalsalso installs fnm, read off disk rather than from a list of names, so a new manifest is covered the day it is written. - Anything the bundler only exercises for one tool (a zip layout, a naming scheme) should be a function with unit tests, not an inline block that has never met a second shape.