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:
@@ -226,7 +226,7 @@ always — the same on-AC question `modules/home/idle.nix`'s suspend listener
|
||||
already answers with `${onAc} ||`.
|
||||
|
||||
In-flake state like the rest (`settings.*`), menu-writable, and read via
|
||||
`theme-state-read.nix` on the NixOS side — NOT `config.nomarchy.settings`,
|
||||
`state-read.nix` on the NixOS side — NOT `config.nomarchy.settings`,
|
||||
which does not exist there (ROADMAP § *NixOS-side state bridges (#116)*; copy
|
||||
the `bluetooth.enable` shape in `modules/nixos/default.nix` and add a case to
|
||||
`checks.state-bridges`). Pass = the toggle survives a rebuild,
|
||||
@@ -234,22 +234,6 @@ a suspended machine hibernates after the configured delay and resumes, and a
|
||||
machine without hibernate support hides the row instead of offering a
|
||||
suspend that never wakes.
|
||||
|
||||
### 107. Rename `theme.json` to reflect that it is the system state
|
||||
|
||||
The state file long ago stopped being about themes: it carries night-light,
|
||||
keyboard memory, display resolution and profiles, auto-commit, services and
|
||||
more, so `theme.json` now misnames its own contents and misleads anyone
|
||||
reading the flake. Rename it to `state.json` (Bernardo's call, 2026-07-14 —
|
||||
settled, do not revisit), and carry the `nomarchy-theme-sync` tool name along
|
||||
with it.
|
||||
|
||||
Standalone task — do not fold it into a feature. Ships with a compatibility
|
||||
shim that keeps reading an existing `theme.json` so downstream checkouts do
|
||||
not break on a pull, plus a migration note. Pass = a fresh install and an
|
||||
existing downstream checkout both work, every in-repo reference (modules,
|
||||
tools, template, docs) uses the new name, and the shim is documented with the
|
||||
release it can be dropped in.
|
||||
|
||||
### 104. Runtime Airplane mode
|
||||
|
||||
Add Airplane mode under System connectivity controls. It must disable Wi-Fi
|
||||
@@ -280,7 +264,7 @@ read, so *these two toggles have never actually worked for any user*. That
|
||||
cuts both ways: "preserve existing behavior" is not a reason to keep them
|
||||
(there is no behavior to preserve), but the state keys and their bridges are
|
||||
real now and outlive the TUI — dropping the rows must not drop the keys, or a
|
||||
machine whose theme-state.json already says `bluetooth.enable = false` will
|
||||
machine whose state.json already says `bluetooth.enable = false` will
|
||||
silently flip back on at the next rebuild. `checks.state-bridges` covers those
|
||||
two keys and will fail loudly if the bridges go with the tool; keep it green,
|
||||
and if a key is deliberately retired, remove its case in the same commit.
|
||||
|
||||
@@ -24,7 +24,7 @@ those, it probably shouldn't exist.
|
||||
|
||||
## Feature design
|
||||
- **In-flake state:** any user-settable config gets a menu writer that
|
||||
lands it in `theme-state.json` (`settings.*`), git-tracked. No
|
||||
lands it in `state.json` (`settings.*`), git-tracked. No
|
||||
`~/.local/state`, no side files. Instant-effect where possible
|
||||
(`--no-switch` + flip the service; the service reads the *live* working
|
||||
tree at start — the night-light `ExecCondition` pattern). Rebuild-baked
|
||||
|
||||
@@ -14,7 +14,7 @@ confidence, default identity, release bar) live in
|
||||
on-hardware QA.
|
||||
2. **Reproducible, with zero hidden state.** The downstream flake checkout
|
||||
*is* the machine. All user-settable config is menu-writable into the
|
||||
git-tracked state file (`theme-state.json` `settings.*`) — never
|
||||
git-tracked state file (`state.json` `settings.*`) — never
|
||||
`~/.local/state`, never `~/.config` side files. Re-cloning your flake
|
||||
reproduces the machine, settings and all.
|
||||
3. **Effortless to configure.** The user never has to learn Nix. Every
|
||||
|
||||
@@ -237,7 +237,7 @@ the **T14s** (webcam case).
|
||||
open Ghostty, so the hand `btop.theme` assets were only guest-file
|
||||
asserted (main_bg / inactive_fg keys) + desktop/bar rendered for
|
||||
rose-pine, everforest, summer-night, vantablack, catppuccin. On a
|
||||
real session: `nomarchy-theme-sync apply <slug>` then `btop` and
|
||||
real session: `nomarchy-state-sync apply <slug>` then `btop` and
|
||||
confirm backgrounds/text match the theme (esp. rose-pine Dawn light
|
||||
bg `#faf4ed`, vantablack near-black `#0d0d0d`, catppuccin Mocha
|
||||
`#1E1E2E`). One pass cycling those five is enough.
|
||||
|
||||
@@ -19,6 +19,17 @@ Template:
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-15 — #107 state.json + nomarchy-state-sync
|
||||
- **Task:** BACKLOG #107 — rename misnamed system state file and CLI.
|
||||
- **Did:** `theme-state.json` → `state.json` (template, root, docs, modules);
|
||||
package/CLI `nomarchy-theme-sync` → `nomarchy-state-sync` with symlink
|
||||
alias; `modules/state-read.nix`; mkFlake/doctor/lifecycle read legacy
|
||||
name; writes always land on `state.json` and remove the old file.
|
||||
- **Verified:** py_compile; legacy-file unit migrate (write removes
|
||||
theme-state.json); V0 flake check pending in same push.
|
||||
- **Pending:** drop `nomarchy-theme-sync` alias after release notes.
|
||||
- **Next suggestion:** #104 airplane, or #98 with a screenshot.
|
||||
|
||||
## 2026-07-15 — Close #94 installed chromium + kill Hyprland update-news
|
||||
- **Task:** Residual #94 (chromium on installed path) + first-boot polish
|
||||
seen while probing.
|
||||
@@ -373,7 +384,7 @@ Template:
|
||||
(`modules/home/options.nix:412`), so `or <fallback>` had been swallowing a
|
||||
missing-attribute error on the NixOS side forever. Options now declare a
|
||||
*static* default and the implementing module reads the state via
|
||||
`theme-state-read.nix` + `lib.mkIf (state != null) (lib.mkDefault state)` —
|
||||
`state-read.nix` + `lib.mkIf (state != null) (lib.mkDefault state)` —
|
||||
done for `bluetooth.enable` (default.nix) and `services.printing.enable`
|
||||
(services.nix). `batteryChargeLimit`'s read is simply deleted: power.nix's
|
||||
oneshot reads the key with `jq` at *runtime*, which is why that menu worked.
|
||||
@@ -421,7 +432,7 @@ Template:
|
||||
Making both state-owned surfaced two real bugs: `greeter.autoLogin`
|
||||
defaulted from `config.nomarchy.settings…`, an attribute that exists ONLY
|
||||
on the HM side, and `or null` swallowed it — the state path never worked on
|
||||
any machine ever built; and `theme-sync get` printed Python's `None` for a
|
||||
any machine ever built; and `state-sync get` printed Python's `None` for a
|
||||
JSON null, so any `case … null)` would miss.
|
||||
- **Verified:** **V1** — flake check, installer-safety, option-docs pass.
|
||||
Proved by eval/build: a state carrying autoLogin yields greetd
|
||||
@@ -580,14 +591,14 @@ Template:
|
||||
- **Next suggestion:** wait on round 7 before touching the dock path again.
|
||||
|
||||
## 2026-07-13 — #99 live-seed git-init; theme-switch failure filed as #113 (this commit)
|
||||
- **Task:** BACKLOG #99 — false "theme-state.json NOT git-tracked" doctor/
|
||||
- **Task:** BACKLOG #99 — false "state.json NOT git-tracked" doctor/
|
||||
Waybar warning in the live session; resolve the held question from Fable.
|
||||
- **Did:** hosts/live.nix `nomarchy-seed-flake` now `git init`+`add`+`commit`s
|
||||
the seeded `~/.nomarchy` (like nomarchy-install.sh:654), so the live
|
||||
checkout is a committed repo. Also committed #94's live-posture comment in
|
||||
flake.nix (separate commit).
|
||||
- **Verified:** V2 — focused serial-log VM run (`/tmp/nomarchy-v2-theme-99/`):
|
||||
doctor prints `✔ theme-state.json is git-tracked` + `✔ flake checkout is
|
||||
doctor prints `✔ state.json is git-tracked` + `✔ flake checkout is
|
||||
clean`, `GIT_REPO_OK`/`TRACKED_OK` markers. Held question RESOLVED: the
|
||||
same run's offline gruvbox switch failed with a 1176-drv source rebuild,
|
||||
but a local drv-equivalence test proved the failing
|
||||
@@ -885,14 +896,14 @@ Template:
|
||||
## 2026-07-12 — auto-commit sweep before pull/rebuild/home (interactive)
|
||||
- **Task:** Bernardo's request (no BACKLOG item): with autoCommit on,
|
||||
hand edits to `~/.nomarchy` (his had 4) stayed forever-dirty —
|
||||
theme-sync's commit is pathspec-limited to theme-state.json by design.
|
||||
state-sync's commit is pathspec-limited to state.json by design.
|
||||
- **Did:** New internal `nomarchy-autocommit` in nomarchy-lifecycle:
|
||||
live-reads `settings.autoCommit`, commits *everything* dirty with
|
||||
message `nomarchy: auto-commit before <label>` + file list in the
|
||||
body; called (`|| true`, never blocks) at the top of nomarchy-pull /
|
||||
-rebuild / -home. Exposed as `passthru.autocommit`; package exported.
|
||||
Docs/comments swept: README, RECOVERY, ROADMAP ✓ entry, rofi toggle
|
||||
text, control-center prompt, theme-sync docstring.
|
||||
text, control-center prompt, state-sync docstring.
|
||||
- **Verified:** V1+ — `nix flake check --no-build` green; new permanent
|
||||
`checks.lifecycle-autocommit` builds (real binary, sandbox repos:
|
||||
sweep/clean/off/non-repo); end-to-end on a *copy* of the real
|
||||
@@ -1301,7 +1312,7 @@ Template:
|
||||
- **Task:** Bernardo challenged the "V3 real-session" framing — a simulated
|
||||
sunset IS VM-testable. He's right; I'd conflated "needs a real desktop"
|
||||
with "needs the generic home-manager switch."
|
||||
- **Did:** Added `checks.auto-theme` runNixOSTest: installs nomarchy-theme-sync,
|
||||
- **Did:** Added `checks.auto-theme` runNixOSTest: installs nomarchy-state-sync,
|
||||
points `NOMARCHY_DEFAULT_THEMES` at presets, stubs the switch via
|
||||
`NOMARCHY_REBUILD` (a marker), configures the pair+schedule, then **walks
|
||||
the VM clock** 19:55→20:05→20:06→next-day 07:30 asserting slug goes
|
||||
@@ -1320,7 +1331,7 @@ Template:
|
||||
- **Task:** BACKLOG #79 slice 3 — the menu; completes the feature.
|
||||
- **Did:** `rofi.nix` — "Auto theme (on/off)" row in Look & Feel + an
|
||||
`autotheme)` submenu: toggle, pick day/night (from
|
||||
`nomarchy-theme-sync list`), set sunrise/sunset (HH:MM input, validated).
|
||||
`nomarchy-state-sync list`), set sunrise/sunset (HH:MM input, validated).
|
||||
Enable writes the flag + defaults the summer pair `--no-switch`, then
|
||||
`exec auto --force` — one rebuild installs the timer AND applies the right
|
||||
theme. Disable is instant `--no-switch` (`auto` self-gates; the lingering
|
||||
@@ -1342,14 +1353,14 @@ Template:
|
||||
- **Did:** `modules/home/autotheme.nix` (imported in home default.nix):
|
||||
`systemd.user.{service,timer}.nomarchy-auto-theme`, install gated on
|
||||
`config.nomarchy.settings.autoTheme.enable or false` (state-driven, like
|
||||
updates.nix gates on its enable). Service runs `nomarchy-theme-sync auto`
|
||||
updates.nix gates on its enable). Service runs `nomarchy-state-sync auto`
|
||||
with a PATH for `home-manager`; timer `OnStartupSec=1min` +
|
||||
`OnCalendar=*:0/15` + `Persistent`. Chose periodic over exact
|
||||
sunrise/sunset timers — robust to suspend/DST, and `auto` is idempotent so
|
||||
ticks are cheap (rebuild only at the transition).
|
||||
- **Verified:** **V1** — real-config eval (state temp-enabled, restored):
|
||||
`settings.autoTheme.enable`→true, timer `OnCalendar`=`*:0/15`, service
|
||||
ExecStart=`… nomarchy-theme-sync auto`; disabled→no units (isolation eval
|
||||
ExecStart=`… nomarchy-state-sync auto`; disabled→no units (isolation eval
|
||||
condition=false). `systemd-analyze calendar '*:0/15'` valid. **V0** flake
|
||||
check green. (Gotcha: a new .nix file is invisible to the flake until
|
||||
`git add` — flake eval only sees tracked files.)
|
||||
@@ -1360,7 +1371,7 @@ Template:
|
||||
## 2026-07-10 — #79 slice 1: auto time-of-day theme CLI primitive
|
||||
- **Task:** Split BACKLOG #79 (`VISION § D`, `[big]`) into 3 slices (CLI /
|
||||
timer / menu); took slice 1.
|
||||
- **Did:** `nomarchy-theme-sync auto` — reads
|
||||
- **Did:** `nomarchy-state-sync auto` — reads
|
||||
`settings.autoTheme.{enable,day,night,sunrise,sunset}`, computes day/night
|
||||
by the local clock, and applies the matching preset **only if different**
|
||||
(idempotent → the slice-2 timer won't rebuild needlessly). `--which`
|
||||
@@ -1371,7 +1382,7 @@ Template:
|
||||
against scratch state: wide-day→day slug, 00:00–00:01 window→night,
|
||||
disabled→no-op, missing day/night→die, `auto --no-switch` writes state,
|
||||
re-run→"already on" no-op, plain `apply` still writes (refactor intact).
|
||||
**V0** py_compile + flake check + `checks.theme-sync-validate` green.
|
||||
**V0** py_compile + flake check + `checks.state-sync-validate` green.
|
||||
- **Pending:** slices 2 (systemd sunrise/sunset timers + login apply, V2)
|
||||
and 3 (Look & Feel menu) remain under #79.
|
||||
- **Next suggestion:** #79 slice 2 — the timer/hook (V2 runNixOSTest).
|
||||
|
||||
@@ -100,10 +100,10 @@ iteration would otherwise rediscover.
|
||||
- **NixOS release bump is a trap:** the discarded attempt
|
||||
(branch deleted 2026-06-22) hit a Hyprland OOM blocker; a redo is a
|
||||
deliberate `v2`, never part of routine lock bumps.
|
||||
- `theme-state.json` is git-tracked inside an 86 MB flake tree, so every
|
||||
- `state.json` is git-tracked inside an 86 MB flake tree, so every
|
||||
state write re-copies the source before eval — the wallpapers-artifact
|
||||
split (BACKLOG LATER) is the decided fix (§ Faster switches).
|
||||
- **Friendly theme-state load** (`modules/theme-state-read.nix`, #66):
|
||||
- **Friendly theme-state load** (`modules/state-read.nix`, #66):
|
||||
`builtins.tryEval` does **not** catch `readFile`/`fromJSON` failures —
|
||||
gate with `pathExists` + empty/non-object checks before `fromJSON`.
|
||||
Subtle JSON syntax errors still surface from nlohmann (line/col);
|
||||
|
||||
Reference in New Issue
Block a user