Three things were in history that should not have been, all invisible to the tool that deploys them: - `home/dank/.omp/dotfiles/**` — 3 files re-hosting `niri/cfg/autostart.kdl`, `niri/cfg/keybinds.kdl` and `systemd-user/…/swayidle-lock.service` under a prefix `scripts/deploy.sh` never reads (it walks `dotfiles/<pkg>/`). The live package is deployed and symlinked, so the copy asserted nothing; it only misled. Moved to `.AGENTTRASH/20261020-tracked-debt/`. - `.pre-pull-backup/**` — 2 managed-skill files, a local backup in history, which `.gitignore` itself declares must stay on disk only. Same destination. - `dotfiles/noctalia/.local/share/noctalia/wallpapers/` — 23 images, 80.4 MiB. Untracked, files left in place: `~/.local/share/noctalia/wallpapers` symlinks into this directory and the theme reads it, so deleting them would have gone black. Every filename carries its wallhaven ID, so a fresh box restores the set with one `curl` per file plus `deploy.sh`; losing the set is an acceptable outcome, 80 MiB per clone forever is not. New page `omp-docs/tools/dotfiles-deploy.md` owns the deploy contract (the `--check`/sync/`--adopt` modes, `zz-$(hostname)` override semantics, the dconf and systemd-user special cases) because nothing documented it, plus two laws: media the pipeline consumes is content not config, and `systemctl --user enable` snapshots an absolute path — so enabling from a worktree means the seven-day reap silently kills the unit while `is-enabled` keeps answering `enabled`. That second law is not theoretical: `default.target.wants/blankpad-desk-autoswitch.service` pointed into the reaped `wt/de-redesign-20261009` and desk auto-switching had been off since. It is relinked to `dotfiles/zz-blankpad/` and left inactive rather than started mid- session; starting it applies a desk profile. Refs #40
3.7 KiB
type, title, description, tags, timestamp, verified
| type | title | description | tags | timestamp | verified | ||||
|---|---|---|---|---|---|---|---|---|---|
| reference | Dotfiles deployment tier | How dotfiles/ packages become live configuration — stow-equivalent symlinks, host override packages, and the two laws about theme media and systemd enable symlinks. |
|
2026-10-20 | 2026-10-20 |
Dotfiles deployment tier
dotfiles/ holds home-relative trees and scripts/deploy.sh is a stow-equivalent: the
repo checkout is the deployment, and deploying replaces live files with symlinks into
the repo, so git pull + deploy.sh is the whole propagation story. One directory per
tool (niri, ghostty, gtk-3.0, systemd-user, …); a package named zz-$(hostname)
is stowed last and its files replace symlinks coming from base packages.
| Mode | Effect |
|---|---|
deploy.sh --check |
dry run — adopts identicals, reports what would be linked, lists divergents, writes nothing. Run this first, always |
deploy.sh (sync) |
adopt identicals, link new, quarantine divergents into .quarantine/ and replace them |
deploy.sh --adopt |
like sync, but divergents are reported and skipped rather than quarantined |
Two package shapes are not symlinks: dconf/dump.txt is loaded with dconf load /, and
systemd-user units get daemon-reload plus enable --now only when their ExecStart
binary resolves on the current machine, so a unit belonging to another box stays inert
instead of crash-looping.
The tracked unit is the file, not the directory. A live directory can be a real
directory and still be fully tracked, because every file inside it is a symlink into the
repo (niri is 12 tracked / 1 box-only; gtk-3.0 is 3/0). Any audit that classifies by
directory mislabels the tree — classify per file with readlink -f. The live census and
its classifier command are in home-config-census.
Law: media the theme pipeline consumes is content, not config
Wallpapers live at dotfiles/noctalia/.local/share/noctalia/wallpapers/ and are
gitignored. They were tracked until 2026-10-20 — 23 files, 80 MiB — which meant every
clone of a configuration repo carried a media library no diff can review, and the
payload only ever grows because deleting a tracked blob from the tree does not delete it
from history. Noctalia reads
~/.local/share/noctalia/wallpapers/, which is a set of symlinks into that directory, so
the files stay on disk and untracking them broke nothing on this box.
Restore on a fresh box: every filename is wallhaven_<id>.<ext> and the ID is the whole
address — curl -L -o <name> "https://wallhaven.cc/w/<id>" puts the library back, then
deploy.sh relinks it. Losing the set is an acceptable outcome; 80 MB per clone forever
is not.
Law: never systemctl --user enable a unit from a worktree
enable writes ~/.config/systemd/user/default.target.wants/<unit> as a symlink to the
unit path it was handed, and that path is absolute. The heartbeat reaps wt/* worktrees
older than seven days (live-sync), so a unit enabled from a worktree turns
into a dangling symlink while systemctl --user is-enabled still answers enabled — the
unit is dead and the status lies about it. Found on 2026-10-20:
blankpad-desk-autoswitch.service pointed into the reaped wt/de-redesign-20261009, so
desk auto-switching had been silently off since the reap.
Check the link target before the unit file:
ls -l ~/.config/systemd/user/default.target.wants/
# every target must resolve; a dangling one is a reaped worktree, not a config bug
Fix is to relink into the deployment checkout (~/.omp/dotfiles/…), systemctl --user daemon-reload, then confirm with is-active — is-enabled proves nothing.