refactor(#107): theme-state.json → state.json, theme-sync → state-sync
Some checks failed
Check / eval (push) Has been cancelled
Some checks failed
Check / eval (push) Has been cancelled
The machine flake's git-tracked settings file is system state, not "theme" only — rename it to state.json. CLI becomes nomarchy-state-sync with a nomarchy-theme-sync symlink for scripts and muscle memory. Eval (mkFlake, doctor, lifecycle) still accepts theme-state.json; the next write migrates to state.json and removes the legacy file. Documented in MIGRATION.md; drop the CLI alias after release notes.
This commit is contained in:
@@ -19,7 +19,7 @@ Design/decision records and a running log of shipped work (items marked
|
||||
## Roadmap
|
||||
- **Menu system** (apps launcher + theme switching + system actions), built
|
||||
on rofi 2.0 (native Wayland on 26.05) — its `.rasi` theme is baked from
|
||||
theme-state.json like every other app, with rich per-element styling:
|
||||
state.json like every other app, with rich per-element styling:
|
||||
- ✓ shipped: `modules/home/rofi.nix` (per-element theme generated from
|
||||
the palette, `themes/<slug>/rofi.rasi` whole-swap) and the
|
||||
`nomarchy-menu` dispatcher: root picker (no args) · `power`
|
||||
@@ -197,18 +197,18 @@ Design/decision records and a running log of shipped work (items marked
|
||||
(confirmed): `themes/` is 86 MB and `backgrounds/` is **all** of it — the
|
||||
palette JSONs + per-theme overrides are only ~208 KB, and the wallpapers are
|
||||
**never read at Nix eval** (only the Python `swww` path uses them). But
|
||||
`theme-state.json` is git-tracked, so every `apply` rewrites it → the flake
|
||||
`state.json` is git-tracked, so every `apply` rewrites it → the flake
|
||||
tree changes → Nix re-copies the whole 86 MB source before `home-manager
|
||||
switch` can evaluate. You pay an 86 MB copy to change a 1 KB file.
|
||||
**Decided approach (deferred — don't want the extra moving part yet):**
|
||||
Option 1, a **separate pinned wallpapers artifact** — a `Nomarchy-wallpapers`
|
||||
repo or release tarball, pulled once via a flake input / `fetchurl` (pinned
|
||||
by hash → content-addressed, never re-copied on a state write), with
|
||||
`nomarchy-theme-sync` reading wallpapers from that stable store path (the
|
||||
`nomarchy-state-sync` reading wallpapers from that stable store path (the
|
||||
`NOMARCHY_DEFAULT_THEMES` env hook already anticipates external theme
|
||||
assets). Keeps eval **pure**; the live ISO still bakes them in (fetched at
|
||||
build). A state write then re-copies only ~208 KB. Rejected alternative:
|
||||
moving `theme-state.json` out to `~/.config` + `--impure` eval (one repo, no
|
||||
moving `state.json` out to `~/.config` + `--impure` eval (one repo, no
|
||||
second artifact, but trades away the in-tree-pinned-state reproducibility).
|
||||
Follow-on if `home-manager switch` itself is still the bottleneck after the
|
||||
copy is gone: **pre-built theme variants** (build each theme's generation
|
||||
@@ -302,7 +302,7 @@ Design/decision records and a running log of shipped work (items marked
|
||||
- ✓ **Auto time-of-day theme (#79, `VISION § D`):** an automatic light/dark
|
||||
theme switch through the **same** engine as a manual apply — no second
|
||||
pipeline. `settings.autoTheme = {enable, day, night, sunrise, sunset}`
|
||||
drives `nomarchy-theme-sync auto`, which picks day vs night by the local
|
||||
drives `nomarchy-state-sync auto`, which picks day vs night by the local
|
||||
clock and applies the preset **only if it differs** (idempotent).
|
||||
`modules/home/autotheme.nix` installs a user timer
|
||||
(`OnStartupSec` + `OnCalendar=*:0/15` + `Persistent`, gated on the state
|
||||
@@ -329,7 +329,7 @@ Design/decision records and a running log of shipped work (items marked
|
||||
`settings.{bluetooth,printing}.enable` and printed "requires rebuild", and
|
||||
the rebuild changed nothing, for as long as those toggles had existed.
|
||||
**The pattern, now uniform:** the option declares a *static* default and
|
||||
the implementing module reads the state via `modules/theme-state-read.nix`
|
||||
the implementing module reads the state via `modules/state-read.nix`
|
||||
(fails closed on bad JSON) and `mkDefault`s it —
|
||||
`lib.mkIf (stateX != null) (lib.mkDefault stateX)`, so an absent key leaves
|
||||
the option default as the single source of the fallback and a hand-set
|
||||
@@ -427,6 +427,11 @@ Design/decision records and a running log of shipped work (items marked
|
||||
default `$TERMINAL` / SUPER+Return, doctor + calendar + what-changed use
|
||||
`kitty --class=com.nomarchy.*`. Ghostty module and install-time GL probe
|
||||
removed. V3: Acer SUPER+Return + doctor float.
|
||||
- ✓ **State file rename (#107):** `theme-state.json` → `state.json`; CLI
|
||||
`nomarchy-theme-sync` → `nomarchy-state-sync` (old binary name kept as a
|
||||
symlink). Eval/read shims accept the legacy file name; the next write
|
||||
migrates. Documented in MIGRATION.md. Drop the CLI alias after the next
|
||||
stable release notes call it out.
|
||||
- ✓ **Installed default browser path (#94 residual):** live half closed by
|
||||
#103 + `checks.live-baseline-apps`. Installed path V2 (2026-07-15): re-boot
|
||||
of offline `test-install` disk — `chromium --version` on PATH (150.x),
|
||||
@@ -1112,7 +1117,7 @@ Design/decision records and a running log of shipped work (items marked
|
||||
`settings.nightlight.on` (runtime on/off). **Off by default.** The *first*
|
||||
enable from the menu writes `installed` and rebuilds to create the unit (the
|
||||
one accepted rebuild); **every toggle after is instant** —
|
||||
`nomarchy-theme-sync set settings.nightlight.on … --no-switch` (atomic +
|
||||
`nomarchy-state-sync set settings.nightlight.on … --no-switch` (atomic +
|
||||
`git add -N`, no rebuild) plus a `systemctl` start/stop. Splitting the sticky
|
||||
flag from the on/off is what avoids a **decay** bug: an instant-off writes
|
||||
only `on`, so an unrelated later rebuild (e.g. `sys-update`) never drops the
|
||||
@@ -1143,7 +1148,7 @@ Design/decision records and a running log of shipped work (items marked
|
||||
(opt-in, off by default) — geoclue + `services.automatic-timezoned` drive
|
||||
`/etc/localtime` from your location, so travelling to another zone updates the
|
||||
Waybar clock on its own. **Menu-driven, in-flake state** (the night-light /
|
||||
keyboard philosophy): the flag is `settings.autoTimezone` in theme-state.json,
|
||||
keyboard philosophy): the flag is `settings.autoTimezone` in state.json,
|
||||
git-tracked; the System-menu entry (`nomarchy-menu autotimezone` →
|
||||
`nomarchy-autotimezone`) writes it and rebuilds. **Not instant like
|
||||
night-light** — it's a *system* service (not a user unit you can start/stop),
|
||||
@@ -1318,10 +1323,10 @@ Design/decision records and a running log of shipped work (items marked
|
||||
- ✓ **Opt-in auto-commit of state mutations (in-flake state, Phase 4):**
|
||||
`settings.autoCommit` (menu: **System › Auto-commit**, self-gated on the
|
||||
flake being a git repo) makes every `apply`/`set` also `git commit`
|
||||
theme-state.json in the downstream flake. Design decisions: the flag is
|
||||
state.json in the downstream flake. Design decisions: the flag is
|
||||
**live-read by the tool** on each write — nothing in Nix consumes it, so
|
||||
the toggle is instant, no rebuild, no option-surface addition; the commit
|
||||
is **pathspec-limited** (`git commit -- theme-state.json`) so unrelated
|
||||
is **pathspec-limited** (`git commit -- state.json`) so unrelated
|
||||
dirty files are never swept up; it fires when the flag is on before *or*
|
||||
after the write, so the disable-toggle itself lands in history instead of
|
||||
staying forever-dirty; a same-value `set` no-ops (diff against HEAD); a
|
||||
@@ -1347,7 +1352,7 @@ Design/decision records and a running log of shipped work (items marked
|
||||
the real binary: sweep, no-op on clean/off/non-repo).
|
||||
- **"nomarchy" control center:** a single TUI/GUI front-end over the common
|
||||
toggles — theme, power profile, opt-in services, display, DND — built on
|
||||
the same `nomarchy-theme-sync` / `nomarchy.*` surface the menu already
|
||||
the same `nomarchy-state-sync` / `nomarchy.*` surface the menu already
|
||||
uses. Plus a first-boot welcome that lands new installs in a guided "pick
|
||||
your theme / essentials" flow (ties into the branding work).
|
||||
|
||||
@@ -1390,11 +1395,11 @@ Design/decision records and a running log of shipped work (items marked
|
||||
hardware QA, 2026-07-04): exec-once has no supervisor, so any crash
|
||||
orphaned the session until relogin — and the switch path itself was
|
||||
crash-prone: `reload_style_on_change` (inotify on style.css) and
|
||||
theme-sync's SIGUSR2 both fired while the HM symlinks flipped, a
|
||||
state-sync's SIGUSR2 both fired while the HM symlinks flipped, a
|
||||
double-reload race in waybar's in-place reload. Fix: (1) the bar runs
|
||||
under a `nomarchy-waybar` supervisor (waybar.nix) — ANY exit respawns
|
||||
it, with a crash-loop guard (5 fast exits → critical notification,
|
||||
stop); (2) theme-sync now prefers a clean `pkill -x waybar` when it
|
||||
stop); (2) state-sync now prefers a clean `pkill -x waybar` when it
|
||||
sees the supervisor (a restart with fresh config+style — no reload
|
||||
code path at all), keeping SIGUSR2 only as the fallback for
|
||||
unsupervised/custom bars; `reload_style_on_change` stays for manual
|
||||
|
||||
Reference in New Issue
Block a user