feat(lifecycle): auto-commit sweep of the machine flake before pull/rebuild/home
Some checks failed
Check / eval (push) Failing after 3m11s
Some checks failed
Check / eval (push) Failing after 3m11s
With settings.autoCommit on, only menu/theme mutations were committed (theme-sync pathspec-limits to theme-state.json by design), so hand edits to system.nix/home.nix and lock bumps stayed forever-dirty. New internal nomarchy-autocommit (nomarchy-lifecycle): live-reads the same flag, commits everything dirty as "nomarchy: auto-commit before <pull|rebuild|home switch>" with the swept file list in the body, fallback identity, never fatal (|| true at call sites). Called at the top of all three lifecycle commands; before the ff-only pull it also un-dirties the tree. Exposed via passthru.autocommit + package export; guarded by checks.lifecycle-autocommit (sandbox repos: sweep, no-op on clean/off/non-repo). Sync sweep: README, RECOVERY, ROADMAP, rofi toggle, control-center prompt, theme-sync docstring, JOURNAL. Verified: V1+ — flake check --no-build green; the new check builds; end-to-end run of the built nomarchy-rebuild (stubbed sudo/rebuild) against a copy of a real dirty ~/.nomarchy: 4 files → one commit, clean tree. No VM boot — no session-visible surface. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -194,7 +194,10 @@ nomarchy-what-changed # plain-language last rebuild (system + desktop; --summar
|
|||||||
`~/.nomarchy` is **your machine flake** (`system.nix` / `home.nix`). Newer
|
`~/.nomarchy` is **your machine flake** (`system.nix` / `home.nix`). Newer
|
||||||
Nomarchy code arrives when `flake.lock` updates the `nomarchy` input
|
Nomarchy code arrives when `flake.lock` updates the `nomarchy` input
|
||||||
(`nomarchy-pull`), not by `git pull` of that directory (many installs have
|
(`nomarchy-pull`), not by `git pull` of that directory (many installs have
|
||||||
no remote there — only local commits from auto-commit).
|
no remote there — only local commits from auto-commit). With auto-commit
|
||||||
|
on (menu: **System › Auto-commit**), all three commands above also sweep
|
||||||
|
any pending hand edits into a commit before they switch, so
|
||||||
|
`git -C ~/.nomarchy log` mirrors your generations.
|
||||||
|
|
||||||
| When | Run |
|
| When | Run |
|
||||||
|---|---|
|
|---|---|
|
||||||
|
|||||||
@@ -19,6 +19,28 @@ 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.
|
||||||
|
- **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.
|
||||||
|
- **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
|
||||||
|
~/.nomarchy via built nomarchy-rebuild with stubbed sudo/rebuild —
|
||||||
|
the 4 real dirty files landed in one commit, tree clean. No VM boot:
|
||||||
|
no session-visible surface. Real-machine confirmation lands after the
|
||||||
|
next nomarchy-pull picks up this rev.
|
||||||
|
- **Pending:** nothing queued; Bernardo's actual ~/.nomarchy still has
|
||||||
|
its 4 uncommitted files until his next pull/rebuild with the new rev.
|
||||||
|
- **Next suggestion:** back to BACKLOG (#89 slice 3, Signal pixmap).
|
||||||
|
|
||||||
## 2026-07-12 — #89 slice 2: EasyEffects tray icon themed monochrome (b98248f)
|
## 2026-07-12 — #89 slice 2: EasyEffects tray icon themed monochrome (b98248f)
|
||||||
- **Task:** BACKLOG #89 slice 2 — EasyEffects SNI shows Papirus' full-
|
- **Task:** BACKLOG #89 slice 2 — EasyEffects SNI shows Papirus' full-
|
||||||
colour blue equaliser, clashing with the monochrome tray.
|
colour blue equaliser, clashing with the monochrome tray.
|
||||||
|
|||||||
@@ -30,8 +30,10 @@ boreal` (or any preset). If a switch failed halfway, the state file is written
|
|||||||
`home-manager switch --flake ~/.nomarchy` (or `nomarchy-home`).
|
`home-manager switch --flake ~/.nomarchy` (or `nomarchy-home`).
|
||||||
|
|
||||||
Your flake checkout is a git repo, and with auto-commit enabled every
|
Your flake checkout is a git repo, and with auto-commit enabled every
|
||||||
apply is a commit: `git -C ~/.nomarchy log` to see what changed,
|
apply is a commit — and every `nomarchy-pull`/`-rebuild`/`-home` first
|
||||||
`git revert` the culprit, then `nomarchy-home`.
|
sweeps pending hand edits into one, so history mirrors your generations:
|
||||||
|
`git -C ~/.nomarchy log` to see what changed, `git revert` the culprit,
|
||||||
|
then `nomarchy-home`.
|
||||||
|
|
||||||
## 2. The desktop won't start at all
|
## 2. The desktop won't start at all
|
||||||
|
|
||||||
|
|||||||
@@ -960,6 +960,18 @@ Design/decision records and a running log of shipped work (items marked
|
|||||||
`get` now prints booleans JSON-style (`true`, not Python's `True`) —
|
`get` now prints booleans JSON-style (`true`, not Python's `True`) —
|
||||||
which also un-sticks the System menu's "Auto timezone (on/off)" label,
|
which also un-sticks the System menu's "Auto timezone (on/off)" label,
|
||||||
whose `= true` comparison could never match before.
|
whose `= true` comparison could never match before.
|
||||||
|
- ✓ **Auto-commit sweep before switch (2026-07-12):** the pathspec limit
|
||||||
|
above left hand edits (system.nix/home.nix, lock bumps) forever-dirty
|
||||||
|
even with `settings.autoCommit` on. Now `nomarchy-pull`/`-rebuild`/
|
||||||
|
`-home` run `nomarchy-autocommit` (internal, in nomarchy-lifecycle)
|
||||||
|
first: same live-read flag, commits *everything* dirty with an honest
|
||||||
|
`nomarchy: auto-commit before <pull|rebuild|home switch>` message whose
|
||||||
|
body lists the swept files — so `git log` mirrors the generation list
|
||||||
|
and hand edits still never ride a settings-named commit. Same fallback
|
||||||
|
identity; never fatal (`|| true` at the call sites — a git hiccup can't
|
||||||
|
block a rebuild); before the ff-only pull, it also un-dirties the tree.
|
||||||
|
Guarded by `checks.lifecycle-autocommit` (sandbox-repo round trip of
|
||||||
|
the real binary: sweep, no-op on clean/off/non-repo).
|
||||||
- **"nomarchy" control center:** a single TUI/GUI front-end over the common
|
- **"nomarchy" control center:** a single TUI/GUI front-end over the common
|
||||||
toggles — theme, power profile, opt-in services, display, DND — built on
|
toggles — theme, power profile, opt-in services, display, DND — built on
|
||||||
the same `nomarchy-theme-sync` / `nomarchy.*` surface the menu already
|
the same `nomarchy-theme-sync` / `nomarchy.*` surface the menu already
|
||||||
|
|||||||
50
flake.nix
50
flake.nix
@@ -125,6 +125,7 @@
|
|||||||
# Overlay tools exported for `nix build .#nomarchy-doctor` etc.
|
# Overlay tools exported for `nix build .#nomarchy-doctor` etc.
|
||||||
# (maintainer/CI convenience — modules install them via the overlay).
|
# (maintainer/CI convenience — modules install them via the overlay).
|
||||||
nomarchy-doctor = pkgs.nomarchy-doctor;
|
nomarchy-doctor = pkgs.nomarchy-doctor;
|
||||||
|
nomarchy-lifecycle = pkgs.nomarchy-lifecycle;
|
||||||
nomarchy-control-center = pkgs.nomarchy-control-center;
|
nomarchy-control-center = pkgs.nomarchy-control-center;
|
||||||
nomarchy-battery-notify = pkgs.nomarchy-battery-notify;
|
nomarchy-battery-notify = pkgs.nomarchy-battery-notify;
|
||||||
nomarchy-first-boot = pkgs.nomarchy-first-boot;
|
nomarchy-first-boot = pkgs.nomarchy-first-boot;
|
||||||
@@ -259,6 +260,55 @@
|
|||||||
touch $out
|
touch $out
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# The lifecycle "sweep before switch": with settings.autoCommit
|
||||||
|
# on, nomarchy-pull/-rebuild/-home first commit every dirty file
|
||||||
|
# in the machine flake (theme-sync's own auto_commit stays
|
||||||
|
# pathspec-limited to theme-state.json). Exercises the real
|
||||||
|
# helper binary against sandbox repos: flag on → one commit,
|
||||||
|
# clean tree, fallback identity, file list in the body; clean
|
||||||
|
# tree / flag off / no repo → untouched, never an error.
|
||||||
|
lifecycle-autocommit = pkgs.runCommand "nomarchy-lifecycle-autocommit"
|
||||||
|
{ nativeBuildInputs = [ pkgs.git ]; }
|
||||||
|
''
|
||||||
|
set -eu
|
||||||
|
tool=${pkgs.nomarchy-lifecycle.autocommit}/bin/nomarchy-autocommit
|
||||||
|
export HOME=$PWD # no global git config → fallback identity
|
||||||
|
|
||||||
|
mkdir flake && git -C flake init -q
|
||||||
|
printf '{ "settings": { "autoCommit": true } }' > flake/theme-state.json
|
||||||
|
echo base > flake/system.nix
|
||||||
|
git -C flake add -A
|
||||||
|
git -C flake -c user.name=T -c user.email=t@t commit -qm init
|
||||||
|
|
||||||
|
echo edit >> flake/system.nix
|
||||||
|
echo lock > flake/flake.lock
|
||||||
|
NOMARCHY_PATH=$PWD/flake $tool rebuild
|
||||||
|
[ -z "$(git -C flake status --porcelain)" ] \
|
||||||
|
|| { echo "FAIL: tree still dirty after sweep"; exit 1; }
|
||||||
|
git -C flake log -1 --format=%s \
|
||||||
|
| grep -qx 'nomarchy: auto-commit before rebuild'
|
||||||
|
git -C flake log -1 --format=%ae | grep -qx 'nomarchy@localhost'
|
||||||
|
git -C flake log -1 --format=%b | grep -q 'flake.lock'
|
||||||
|
|
||||||
|
# Clean tree → no new commit
|
||||||
|
NOMARCHY_PATH=$PWD/flake $tool rebuild
|
||||||
|
[ "$(git -C flake rev-list --count HEAD)" = 2 ]
|
||||||
|
|
||||||
|
# Flag off → dirty stays dirty, no commit
|
||||||
|
printf '{ "settings": { "autoCommit": false } }' > flake/theme-state.json
|
||||||
|
echo more >> flake/system.nix
|
||||||
|
NOMARCHY_PATH=$PWD/flake $tool rebuild
|
||||||
|
[ "$(git -C flake rev-list --count HEAD)" = 2 ]
|
||||||
|
[ -n "$(git -C flake status --porcelain)" ]
|
||||||
|
|
||||||
|
# Not a git repo → silent no-op, exit 0
|
||||||
|
mkdir plain
|
||||||
|
printf '{ "settings": { "autoCommit": true } }' > plain/theme-state.json
|
||||||
|
NOMARCHY_PATH=$PWD/plain $tool rebuild
|
||||||
|
|
||||||
|
touch $out
|
||||||
|
'';
|
||||||
|
|
||||||
# Installer hardware DB ↔ nixos-hardware (item 49): every module
|
# Installer hardware DB ↔ nixos-hardware (item 49): every module
|
||||||
# name the DB table and the CPU/GPU/chassis autodetect reference
|
# name the DB table and the CPU/GPU/chassis autodetect reference
|
||||||
# must exist in the PINNED nixos-hardware.nixosModules — a lock
|
# must exist in the PINNED nixos-hardware.nixosModules — a lock
|
||||||
|
|||||||
@@ -806,7 +806,9 @@ ${themeRows}
|
|||||||
autocommit)
|
autocommit)
|
||||||
# Toggle opt-in auto-commit: every menu/theme mutation also commits
|
# Toggle opt-in auto-commit: every menu/theme mutation also commits
|
||||||
# theme-state.json (that file only) in the downstream flake, so
|
# theme-state.json (that file only) in the downstream flake, so
|
||||||
# settings history is `git log`. Nothing in Nix consumes the flag —
|
# settings history is `git log`; nomarchy-pull/-rebuild/-home
|
||||||
|
# additionally sweep everything else dirty (hand edits, lock bumps)
|
||||||
|
# into a commit first. Nothing in Nix consumes the flag —
|
||||||
# the tool reads the live state on each write — so the toggle is
|
# the tool reads the live state on each write — so the toggle is
|
||||||
# instant, no rebuild. The off-write commits too (the tool fires
|
# instant, no rebuild. The off-write commits too (the tool fires
|
||||||
# when the flag was on before OR after), keeping history consistent.
|
# when the flag was on before OR after), keeping history consistent.
|
||||||
@@ -815,7 +817,7 @@ ${themeRows}
|
|||||||
notify-send "Auto-commit" "Off — menu changes stay uncommitted in your flake."
|
notify-send "Auto-commit" "Off — menu changes stay uncommitted in your flake."
|
||||||
else
|
else
|
||||||
nomarchy-theme-sync --quiet set settings.autoCommit true --no-switch
|
nomarchy-theme-sync --quiet set settings.autoCommit true --no-switch
|
||||||
notify-send "Auto-commit" "On — each change commits theme-state.json in your flake."
|
notify-send "Auto-commit" "On — menu changes commit; rebuilds sweep pending edits in too."
|
||||||
fi
|
fi
|
||||||
exit 0 ;;
|
exit 0 ;;
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function first_boot() {
|
|||||||
nomarchy-theme-sync apply "$chosen_theme"
|
nomarchy-theme-sync apply "$chosen_theme"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if gum confirm "Enable auto-commit for settings?"; then
|
if gum confirm "Enable auto-commit for your config? (settings changes + a sweep of pending edits before each rebuild)"; then
|
||||||
set_state "settings.autoCommit" "true"
|
set_state "settings.autoCommit" "true"
|
||||||
else
|
else
|
||||||
set_state "settings.autoCommit" "false"
|
set_state "settings.autoCommit" "false"
|
||||||
|
|||||||
@@ -15,6 +15,41 @@ let
|
|||||||
flake="''${NOMARCHY_PATH:-$HOME/.nomarchy}"
|
flake="''${NOMARCHY_PATH:-$HOME/.nomarchy}"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# Opt-in sweep (settings.autoCommit — the same flag theme-sync honours):
|
||||||
|
# commit EVERYTHING dirty in the machine flake before a pull/rebuild/
|
||||||
|
# home switch, so hand edits to system.nix/home.nix and lock bumps land
|
||||||
|
# in history at the moment they become live — `git log` mirrors the
|
||||||
|
# generation list. Complements nomarchy-theme-sync's auto_commit, which
|
||||||
|
# is pathspec-limited to theme-state.json on menu writes precisely so
|
||||||
|
# half-finished hand edits never ride a settings-named commit; here the
|
||||||
|
# sweep is the point, and the commit body lists what was swept. Never
|
||||||
|
# fatal — callers `|| true` so a git hiccup can't block a rebuild. Not
|
||||||
|
# in the symlinkJoin paths (internal; callers use the store path) but
|
||||||
|
# exposed as passthru.autocommit for checks.lifecycle-autocommit.
|
||||||
|
nomarchy-autocommit = writeShellScriptBin "nomarchy-autocommit" ''
|
||||||
|
${preamble "nomarchy-autocommit"}
|
||||||
|
label="''${1:-rebuild}"
|
||||||
|
[ -d "$flake/.git" ] || exit 0
|
||||||
|
command -v git >/dev/null 2>&1 || exit 0
|
||||||
|
flag=$(${jq}/bin/jq -r '.settings.autoCommit // false' \
|
||||||
|
"$flake/theme-state.json" 2>/dev/null || true)
|
||||||
|
[ "$flag" = "true" ] || exit 0
|
||||||
|
dirty=$(git -C "$flake" status --porcelain || true)
|
||||||
|
[ -n "$dirty" ] || exit 0
|
||||||
|
g=(git -C "$flake")
|
||||||
|
if [ -z "$("''${g[@]}" config user.email 2>/dev/null || true)" ]; then
|
||||||
|
g+=(-c user.name=Nomarchy -c user.email=nomarchy@localhost)
|
||||||
|
fi
|
||||||
|
"''${g[@]}" add -A
|
||||||
|
if "''${g[@]}" commit --quiet -m "nomarchy: auto-commit before $label" \
|
||||||
|
-m "$dirty"; then
|
||||||
|
echo "nomarchy-autocommit: committed pending flake changes before $label:"
|
||||||
|
echo "$dirty" | sed 's/^/ /'
|
||||||
|
else
|
||||||
|
echo "nomarchy-autocommit: commit failed — continuing without it" >&2
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
nomarchy-pull = writeShellScriptBin "nomarchy-pull" ''
|
nomarchy-pull = writeShellScriptBin "nomarchy-pull" ''
|
||||||
${preamble "nomarchy-pull"}
|
${preamble "nomarchy-pull"}
|
||||||
if [ ! -e "$flake/flake.nix" ]; then
|
if [ ! -e "$flake/flake.nix" ]; then
|
||||||
@@ -22,6 +57,9 @@ let
|
|||||||
echo " Set NOMARCHY_PATH or put your machine flake in ~/.nomarchy." >&2
|
echo " Set NOMARCHY_PATH or put your machine flake in ~/.nomarchy." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
# With settings.autoCommit on, sweep pending hand edits into a commit
|
||||||
|
# first — also keeps the ff-only pull below safe on a dirty tree.
|
||||||
|
${nomarchy-autocommit}/bin/nomarchy-autocommit pull || true
|
||||||
# Optional: pull *your* machine config only if this checkout tracks a
|
# Optional: pull *your* machine config only if this checkout tracks a
|
||||||
# remote. Distro updates come from the nomarchy flake *input* below —
|
# remote. Distro updates come from the nomarchy flake *input* below —
|
||||||
# many installs have no upstream on ~/.nomarchy (local auto-commits).
|
# many installs have no upstream on ~/.nomarchy (local auto-commits).
|
||||||
@@ -52,6 +90,9 @@ let
|
|||||||
echo "nomarchy-rebuild: no flake.nix at $flake" >&2
|
echo "nomarchy-rebuild: no flake.nix at $flake" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
# With settings.autoCommit on, sweep pending hand edits (system.nix,
|
||||||
|
# lock bumps, …) into a commit so `git log` mirrors the generations.
|
||||||
|
${nomarchy-autocommit}/bin/nomarchy-autocommit rebuild || true
|
||||||
before=$(readlink -f /run/current-system)
|
before=$(readlink -f /run/current-system)
|
||||||
log=$(mktemp)
|
log=$(mktemp)
|
||||||
trap 'rm -f "$log"' EXIT
|
trap 'rm -f "$log"' EXIT
|
||||||
@@ -94,6 +135,9 @@ let
|
|||||||
echo "nomarchy-home: no flake.nix at $flake" >&2
|
echo "nomarchy-home: no flake.nix at $flake" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
# With settings.autoCommit on, sweep pending hand edits (home.nix, …)
|
||||||
|
# into a commit so `git log` mirrors the generations.
|
||||||
|
${nomarchy-autocommit}/bin/nomarchy-autocommit "home switch" || true
|
||||||
# Snapshot the active HM generation before the switch so we can nvd it.
|
# Snapshot the active HM generation before the switch so we can nvd it.
|
||||||
hm_before=""
|
hm_before=""
|
||||||
for d in \
|
for d in \
|
||||||
@@ -164,6 +208,7 @@ symlinkJoin {
|
|||||||
home-update
|
home-update
|
||||||
nomarchy-what-changed
|
nomarchy-what-changed
|
||||||
];
|
];
|
||||||
|
passthru.autocommit = nomarchy-autocommit;
|
||||||
meta = {
|
meta = {
|
||||||
description = "Nomarchy machine-flake lifecycle: pull, rebuild, home";
|
description = "Nomarchy machine-flake lifecycle: pull, rebuild, home";
|
||||||
mainProgram = "nomarchy-pull";
|
mainProgram = "nomarchy-pull";
|
||||||
|
|||||||
@@ -143,7 +143,10 @@ def auto_commit(message: str) -> None:
|
|||||||
fire this when the flag is on before OR after the write, so the
|
fire this when the flag is on before OR after the write, so the
|
||||||
disable-toggle itself lands in history instead of staying dirty.
|
disable-toggle itself lands in history instead of staying dirty.
|
||||||
`bg` is deliberately excluded (runtime wallpaper churn); the wallpaper
|
`bg` is deliberately excluded (runtime wallpaper churn); the wallpaper
|
||||||
path rides along with the next apply/set commit."""
|
path rides along with the next apply/set commit. The rest of a dirty
|
||||||
|
tree (hand edits, lock bumps) is swept by nomarchy-lifecycle's
|
||||||
|
nomarchy-autocommit right before a pull/rebuild/home switch — same
|
||||||
|
flag, honest message — so it never rides a settings-named commit."""
|
||||||
if not (FLAKE_DIR / ".git").exists() or shutil.which("git") is None:
|
if not (FLAKE_DIR / ".git").exists() or shutil.which("git") is None:
|
||||||
return
|
return
|
||||||
git = ["git", "-C", str(FLAKE_DIR)]
|
git = ["git", "-C", str(FLAKE_DIR)]
|
||||||
|
|||||||
Reference in New Issue
Block a user