fix(nixos): two toggles that reported success and did nothing — wire the state bridges
All checks were successful
Check / eval (push) Successful in 3m16s
All checks were successful
Check / eval (push) Successful in 3m16s
BACKLOG #116. `nomarchy.settings` is declared in exactly one place —
modules/home/options.nix:412, the Home Manager side. On NixOS the attribute
does not exist, and `or <fallback>` swallows the missing-attribute error, so
four options that "defaulted from the state" had silently been their fallback
on every machine ever built.
The item said three options, and called them benign. Both halves were wrong,
and re-grepping rather than trusting the account is what found it:
* There were four. The original enumeration read options.nix instead of
modules/nixos/ and missed services.nix's printing.enable — the same
mistake in miniature as the bug it was filing.
* Two were live user-facing bugs. Control Center is shipped
(default.nix:337) and reachable from the menu; its Bluetooth and Printing
toggles wrote settings.{bluetooth,printing}.enable and printed "requires
rebuild", and the rebuild changed nothing. They had never worked.
The fix is one shape, now uniform: the option declares a STATIC default, and
the implementing module reads the state via theme-state-read.nix (fails closed
on bad JSON, unlike greeter.nix's raw fromJSON — also moved onto the reader
here) and mkDefaults it behind `mkIf (state != null)`. An absent key leaves the
option default as the single source of the fallback; a hand-set system.nix
value still pins it. batteryChargeLimit gets no bridge and loses its dead read:
power.nix's oneshot already reads that key with jq at RUNTIME and prefers it
over the baked value, which is why that menu worked all along.
V2. The bug is proved real before/after on the same flipped state: BEFORE,
bluetooth stays true and printing stays false; AFTER, both flip, and a hand-set
value still outranks the state. Nothing in a build fails when a bridge dies, so
the guards are the point — checks.state-bridges asserts 11 eval cases, and
checks.printing-from-state boots a VM whose only input is the state file and
waits for a running cups.service. The guard was itself proved to fail:
re-breaking the bluetooth bridge makes it throw, naming both assertions. A
check that passes whether or not the property holds is worse than no check
(625b7e3). flake check, option-docs, template-sot, downstream-template-*,
installer-safety, hardware-toggles and battery-charge-limit all pass.
No V3: the mechanism is fully proved headlessly. Design record in ROADMAP §
NixOS-side state bridges (#116); new #117 (PROPOSED) for the control-center
toggles still leaving the rebuild to the user.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,44 @@ Template:
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-14 — #116: the state bridges that never were (this commit)
|
||||
- **Task:** BACKLOG #116 — NixOS options defaulting from
|
||||
`config.nomarchy.settings`, an attribute that exists only on the HM side.
|
||||
- **Did:** `nomarchy.settings` is declared in exactly ONE place
|
||||
(`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)` —
|
||||
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.
|
||||
greeter.nix moved off a raw `fromJSON` onto the fail-closed reader.
|
||||
- **The finding that mattered:** the item said "three options … benign today"
|
||||
and both halves were wrong. There were four (it grepped `options.nix`, not
|
||||
`modules/nixos/` — the same mistake in miniature as the bug it filed), and
|
||||
two were **live user-facing bugs**: Control Center's Bluetooth and Printing
|
||||
toggles wrote state nothing read and printed "requires rebuild", so they
|
||||
reported success and did nothing, for as long as they had existed.
|
||||
- **Verified:** **V2.** Before/after eval on the *same* flipped state proves
|
||||
the bug was real: BEFORE `hardware.bluetooth.enable=true` + `printing=false`
|
||||
(toggle inert); AFTER both flip, and a hand-set value still outranks the
|
||||
state. Permanent guards, since nothing in a build fails when a bridge dies:
|
||||
`checks.state-bridges` (11 eval assertions — absent key → default, state →
|
||||
config, hand-set → wins) and `checks.printing-from-state`, a runNixOSTest
|
||||
whose node's ONLY input is the state file and which waits for a running
|
||||
`cups.service` (+ avahi). **The guard was proved to fail**: re-breaking the
|
||||
bluetooth bridge made it throw, naming both broken assertions — a check that
|
||||
cannot fail is worse than none (625b7e3's lesson, applied). V0 flake check;
|
||||
option-docs, template-sot, downstream-template-{system,home},
|
||||
installer-safety, hardware-toggles, battery-charge-limit all green.
|
||||
- **Pending:** no V3 — the mechanism is fully proved headlessly. New **#117**
|
||||
(PROPOSED): the control-center toggles still leave the rebuild to the user,
|
||||
unlike every menu toggle since; a user can't tell "needs a rebuild" from
|
||||
"broken again", which is the symptom #116 just removed.
|
||||
- **Next suggestion:** #117 (needs Bernardo's call: rebuild per-toggle vs one
|
||||
apply-at-exit), or #115 suspend-then-hibernate — also `[human]`-gated, and
|
||||
its state read now has a worked shape to copy.
|
||||
|
||||
> The five entries below were reconstructed from the commits on 2026-07-14
|
||||
> after a session crash — the work was committed and pushed, and each commit
|
||||
> did its own sync sweep (BACKLOG #115/#116, HARDWARE-QUEUE, docs); only the
|
||||
|
||||
Reference in New Issue
Block a user