From bde10f8948d13455d0f23bf0fe1b8c7beb14f358 Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 18 Oct 2026 17:16:49 -0700 Subject: [PATCH 1/3] docs: work-log entry for noctalia bar clobber + dangling-stash recovery Documents the 16:46 layout loss (uncommitted GUI state stashed, stash entry destroyed during trunk sync) and the git-fsck recovery landed in c87b378. Lesson codified in managed skills. --- omp-docs/log.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/omp-docs/log.md b/omp-docs/log.md index db60c72..982e6f3 100644 --- a/omp-docs/log.md +++ b/omp-docs/log.md @@ -11,6 +11,10 @@ timestamp: 2026-08-28 # Bundle Change Log +## 2026-10-18 — Noctalia bar layout clobbered by trunk-sync stash, recovered from dangling objects + +Frank's months of GUI-built bar customizations (cat/clock/clock-utc/weather start, taskbar center, capsule groups g1–g4, control-cheat-sheet, thickness/font-scale/opacity styling) vanished from the live bar at 16:46. Root cause: the layout existed **only in the working tree** — the repo copy of `settings.toml` carried a stale plain layout because GUI edits hadn't been committed inside the hourly heartbeat window — and a trunk-sync session clearing the dirty tree for `origin/main` stashed it; the stash entry was subsequently destroyed (three `WIP on main` stashes within 60 s, all later dropped). Recovery: `git fsck --lost-found` surfaced the destroyed stash as dangling commit `7fe3ed8` (16:46:09); candidate validated in a sandboxed `XDG_*_HOME` before restore, clobbered file preserved to `.AGENTTRASH/`, layout restored through the symlink target and proven by screenshot, committed as `c87b378` — the durable copy the layout never had. Lessons codified into managed skills: trunk-sync must preservation-**commit** every dirty deployment path (never stash, never `stash clear`), and GUI layout edits get committed the same session they're made. + ## 2026-10-18 — Fleet law: issue/PR attribution footers Every agent-opened issue and PR body now ends with a `cwd:` + `session:` footer (session id from `/status`), in AGENTS.md of both `dank/command-center` and `dank/serverAppConfigs` (mirrored PRs). Born from the live-sync review: once the machine starts filing and committing on its own, its artifacts must trace back to the box and session that produced them. From c300f8b49cd6c3ba8aef6dd210dc0e58908e04b6 Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 18 Oct 2026 17:20:17 -0700 Subject: [PATCH 2/3] 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. --- .../.config/systemd/user/live-sync.path | 13 +++++++++++++ omp-docs/tools/live-sync.md | 8 ++++++++ 2 files changed, 21 insertions(+) create mode 100644 dotfiles/systemd-user/.config/systemd/user/live-sync.path diff --git a/dotfiles/systemd-user/.config/systemd/user/live-sync.path b/dotfiles/systemd-user/.config/systemd/user/live-sync.path new file mode 100644 index 0000000..e1172bd --- /dev/null +++ b/dotfiles/systemd-user/.config/systemd/user/live-sync.path @@ -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 diff --git a/omp-docs/tools/live-sync.md b/omp-docs/tools/live-sync.md index 5d66bb3..c3129ab 100644 --- a/omp-docs/tools/live-sync.md +++ b/omp-docs/tools/live-sync.md @@ -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 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) Run = one pass: flock → branch guard (`main` only) → stage allowlisted dirty @@ -61,6 +68,7 @@ with the usual dotfiles chain: ```bash 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 journalctl --user -u live-sync.service -n 20 # observe ``` From b353fa90753044b79bd6cf7b8c8abc3fbb6d9a35 Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 18 Oct 2026 17:23:58 -0700 Subject: [PATCH 3/3] revert(live-sync): drop path-activation unit Frank veto: DirectoryNotEmpty re-fires on every file event (GUI writes, wallpaper shuffle) un-debounced -> hundreds of heartbeat spawns/day. The sweep is cheap (57 ms CPU) but the trigger design was event spam. Exposure-window fix is an open design question; timer unchanged. --- .../.config/systemd/user/live-sync.path | 13 ------------- omp-docs/tools/live-sync.md | 8 -------- 2 files changed, 21 deletions(-) delete mode 100644 dotfiles/systemd-user/.config/systemd/user/live-sync.path diff --git a/dotfiles/systemd-user/.config/systemd/user/live-sync.path b/dotfiles/systemd-user/.config/systemd/user/live-sync.path deleted file mode 100644 index e1172bd..0000000 --- a/dotfiles/systemd-user/.config/systemd/user/live-sync.path +++ /dev/null @@ -1,13 +0,0 @@ -[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 diff --git a/omp-docs/tools/live-sync.md b/omp-docs/tools/live-sync.md index c3129ab..5d66bb3 100644 --- a/omp-docs/tools/live-sync.md +++ b/omp-docs/tools/live-sync.md @@ -26,13 +26,6 @@ because the dirty tree collided with incoming work. machine's own writes on a schedule. Tier law (which paths it may touch) lives 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) Run = one pass: flock → branch guard (`main` only) → stage allowlisted dirty @@ -68,7 +61,6 @@ with the usual dotfiles chain: ```bash 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 journalctl --user -u live-sync.service -n 20 # observe ```