feat(live-sync): path-activate heartbeat on dotfiles writes (Refs #11)

Timer-only heartbeat left GUI dotfiles edits uncommitted for up to 59
minutes; a trunk-sync session clearing the dirty tree on 2026-10-18
destroyed a month of uncommitted noctalia bar layout inside that gap.
live-sync.path (DirectoryNotEmpty on dotfiles/) fires the existing
flock-guarded oneshot within seconds of any repo-side dotfiles write,
shrinking the exposure window from ~1h to ~2s. Timer stays as the
hourly catch-all for the machine tiers.
This commit is contained in:
Frank
2026-10-18 17:20:17 -07:00
parent bde10f8948
commit c300f8b49c
2 changed files with 21 additions and 0 deletions
@@ -0,0 +1,13 @@
[Unit]
Description=Fire the live-sync heartbeat within seconds of a dotfiles-tier write
[Path]
# GUI writes (noctalia settings.toml, niri cfg) land in the repo via the
# dotfiles symlinks; this directory watch makes "GUI edit -> durable commit"
# sub-second instead of up to one heartbeat interval. DirectoryNotEmpty fires
# while the dir holds any file, so the unit re-triggers on every modification
# (the empty-dir edge case is irrelevant here — dotfiles is never empty).
DirectoryNotEmpty=%h/.omp/dotfiles
[Install]
WantedBy=paths.target
+8
View File
@@ -26,6 +26,13 @@ because the dirty tree collided with incoming work.
machine's own writes on a schedule. Tier law (which paths it may touch) lives machine's own writes on a schedule. Tier law (which paths it may touch) lives
in [AGENTS.md](../../AGENTS.md) § Live-sync tiers. in [AGENTS.md](../../AGENTS.md) § Live-sync tiers.
`live-sync.path` (`DirectoryNotEmpty` on `dotfiles/`) activates the same
service within seconds of any GUI dotfiles write; `live-sync.timer` remains
the hourly catch-all for the machine tiers the path unit does not watch.
The trigger gap between a GUI edit and its commit is what let a 2026-10-18
trunk-sync stash destroy a month of uncommitted bar layout — a timer-only
heartbeat leaves up to 59 minutes of exposure.
## Contract (black-box) ## Contract (black-box)
Run = one pass: flock → branch guard (`main` only) → stage allowlisted dirty Run = one pass: flock → branch guard (`main` only) → stage allowlisted dirty
@@ -61,6 +68,7 @@ with the usual dotfiles chain:
```bash ```bash
systemctl --user enable --now live-sync.timer # after the unit is linked systemctl --user enable --now live-sync.timer # after the unit is linked
systemctl --user enable --now live-sync.path # sub-second dotfiles trigger
systemctl --user start live-sync.service # one manual heartbeat systemctl --user start live-sync.service # one manual heartbeat
journalctl --user -u live-sync.service -n 20 # observe journalctl --user -u live-sync.service -n 20 # observe
``` ```