Files
Nomarchy/agent/JOURNAL.md
Bernardo Magri 9e8433e4d6
Some checks are pending
Check / eval (push) Waiting to run
chore(agent): QA sweep + journal rotate (queue empty)
NEXT only has #76 [blocked:hw]. Re-ran option-docs, template-sot, and a
V2 suite (doctor, first-boot, what-changed, clamshell-logind, dock-audio,
windowrule-syntax, battery-notify, zram-swap, nightlight-geo) — all green.
Rotated JOURNAL.md 41→18 entries into JOURNAL-ARCHIVE.

Verified: V2 — listed checks green; flake check --no-build green.
2026-07-11 10:40:57 +01:00

315 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Journal — append-only iteration log
One entry per iteration, **newest first**. This is the loop's short-term
memory: the next session reads the last 35 entries to orient. Keep an
entry under ~15 lines; durable lessons go to MEMORY.md, not here. When
this file grows past ~25 entries, rotate the tail to
[JOURNAL-ARCHIVE.md](JOURNAL-ARCHIVE.md) (history, never edited).
Template:
```markdown
## YYYY-MM-DD — <task title> (<commit sha, or "no commit">)
- **Task:** which BACKLOG item (or QA sweep / bootstrap / escalation)
- **Did:** what changed, in 24 lines
- **Verified:** tier reached (V0/V1/V2) + the actual commands/checks run
- **Pending:** V3 queued? follow-ups filed? anything [stuck]?
- **Next suggestion:** what the following iteration should probably take
```
---
## 2026-07-11 — QA sweep (queue empty but #76)
- **Task:** QA sweep — NEXT only has #76 `[blocked:hw]`; no other
actionable items.
- **Did:** option-docs (88 opts) + template-sot green; HM generation has
What changed? / doctor float / first-boot unit; rotated JOURNAL.md
41→18 entries (tail → JOURNAL-ARCHIVE). No product code change.
- **Verified:** **V2**`nix flake check --no-build`; rebuilt green:
doctor, first-boot, what-changed, clamshell-logind, dock-audio,
windowrule-syntax, battery-notify, zram-swap, nightlight-geo.
- **Pending:** #76 V3 hibernate on Nomarchy hardware; #86/#87 V3 dock QA.
- **Next suggestion:** HARDWARE-QUEUE pass by human, or promote LATER
wallpapers split / triage PROPOSED.
## 2026-07-11 — #87 dock audio sink priority
- **Task:** NEXT #87 — default audio follows dock plug/unplug.
- **Did:** WirePlumber `90-nomarchy-dock-audio` (HDMI/DP session prio
1100, USB 1050) via `modules/nixos/dock-audio-rules.nix` + default.nix
pipewire. `checks.dock-audio` pure rule asserts + conf-file VM. V3
hotplug steps in HARDWARE-QUEUE. Closed #87.
- **Verified:** **V2**`nix flake check --no-build`; `checks.dock-audio`
green (pure rule asserts + conf installed under wireplumber.conf.d).
- **Pending:** V3 real HDMI/USB-dock hotplug (HARDWARE-QUEUE).
- **Next suggestion:** QA sweep or LATER wallpapers split if promoted.
## 2026-07-11 — #86 clamshell HandleLidSwitchDocked
- **Task:** NEXT #86 — lid closed + external monitor must not suspend.
- **Did:** Explicit `HandleLidSwitchDocked=ignore` in
`modules/nixos/power.nix` (logind settings.Login). Undocked lid
behaviour unchanged. idle.nix comment corrected. `checks.clamshell-logind`
asserts conf + active logind. V3 steps in HARDWARE-QUEUE. Closed #86.
- **Verified:** **V2**`nix flake check --no-build`;
`checks.clamshell-logind` green (`HandleLidSwitchDocked=ignore` +
logind active).
- **Pending:** V3 real lid+external on laptop (HARDWARE-QUEUE).
- **Next suggestion:** #87 dock audio sink follow.
## 2026-07-11 — #85 hardware hall of fame + split #84
- **Task:** NEXT #85 docs hall of fame; #84 was `[big]` → split.
- **Did:** HARDWARE.md §9 install-tested table (T14s Gen 4 AMD, Latitude
5410/5310) + DMI PR invite; renumbered following sections. #84#86
clamshell + #87 dock audio. VISION/ROADMAP; closed #85.
- **Verified:** V0 (docs only).
- **Pending:** —
- **Next suggestion:** #86 clamshell or #87 dock audio (both product).
## 2026-07-11 — #83 doctor first-boot pre-activate flag
- **Task:** NEXT #83 — doctor points at failed installer HM pre-activate.
- **Did:** doctor row: if `/var/log/nomarchy-hm-preactivate.log` is present
and no Home Manager generation exists → ✖ +
`home-manager switch --flake ~/.nomarchy -b bak`. Skip/ok otherwise.
Extended `checks.doctor` (fail arm + recovered gen). Closed #83.
- **Verified:** **V2** — checks.doctor green (fail arm + recovered gen);
local smoke with NOMARCHY_HM_PREACTIVATE_LOG / empty HOME.
- **Pending:** —
- **Next suggestion:** #85 docs hall of fame (cheap) or split #84 dock.
## 2026-07-11 — #82 generation readability
- **Task:** NEXT #82 — plain-language “what changed last rebuild”.
- **Did:** `pkgs/nomarchy-what-changed` (nvd → “N added, M removed, K
updated”); wired into lifecycle post-`nomarchy-rebuild` / `nomarchy-home`
(full nvd + notify toast); System What changed? (toast + floating
full report). `checks.what-changed` with NOMARCHY_NVD fixture. Closed #82.
- **Verified:** **V2** — checks.what-changed green; local smoke on real
HM gens (“Desktop: 1 added, 1 removed”) + fixture counts.
- **Pending:** —
- **Next suggestion:** #83 doctor pre-activate fail flag or #85 docs.
## 2026-07-11 — #81 first-boot welcome toast
- **Task:** NEXT #81 — dismissible “you're set” card (`VISION § B`).
- **Did:** `pkgs/nomarchy-first-boot` + user oneshot
(`modules/home/first-boot.nix`): notify once with SUPER+M/T/? + Network
+ Doctor pointers; marker `settings.firstBootShown` via theme-sync
`--no-switch` (in-checkout state). Skip live hostname. Option
`nomarchy.firstBootWelcome.enable` (default on). `checks.first-boot`.
ROADMAP/VISION/README; closed #81.
- **Verified:** **V2**`nix flake check --no-build`; `checks.first-boot`
green (toast + marker + silent re-run + live skip); local shim smoke;
downstream-template-home carries the user unit.
- **Pending:** V3 — real swaync rendering on first installed login
(toast body is pure text; not queued unless it misbehaves).
- **Next suggestion:** #82 generation readability or #85 docs hall of fame.
## 2026-07-11 — #80 doctor battery health readout
- **Task:** NEXT #80 — battery health in `nomarchy-doctor` (`VISION § C`).
- **Did:** Doctor row: `cycle_count` + retained capacity
(`charge_full`/`design` or `energy_*`) as `% of design`; system
batteries only; soft warn &lt;70% design; skip when attrs absent.
`NOMARCHY_POWER_SUPPLY_ROOT` for the VM fixture. Extended
`checks.doctor` (fake BAT0 + Device-scope MOUSE0 ignore). HARDWARE §10,
ROADMAP ✓, VISION ✓; closed #80.
- **Verified:** **V2**`nix flake check --no-build`; `checks.doctor`
green; local smoke on real BAT0 (342 cycles, 81% via energy_*) + fixture.
- **Pending:** Power-menu surface left optional/out of scope (doctor is
the product surface for report-only health).
- **Next suggestion:** #81 first-boot welcome card (highest product ROI)
or #85 docs-only hall of fame.
## 2026-07-11 — Triage: VISION-gap PROPOSED → NEXT #80#85 (Bernardo)
- **Task:** Bernardo promoted five of the six fresh VISION-gap pitches
(all but the wallpapers split, which stays LATER).
- **Did:** NEXT gains #80 battery health readout, #81 first-boot welcome
card, #82 generation readability, #83 doctor pre-activate fail flag,
#84 dock life polish `[big]`, #85 hardware hall of fame. PROPOSED
placeholder left. **No implementation started** (explicit instruction).
- **Verified:** V0 (backlog only).
- **Pending:** —
- **Next suggestion:** #80 (smallest) or #81 (highest product ROI); #84
must be split first.
## 2026-07-11 — Quick wins: exit-node locations + geo tooltip
- **Task:** BACKLOG LATER "VPN exit-node richer display" + a geo-mode
tooltip nit from the previous iteration (human asked for quick wins).
- **Did:** Tailscale Exit node picker rows now "hostname — Country City",
sliced by the header's fixed-width column offsets (COUNTRY/CITY are
multi-word; never field-split), locationless nodes stay bare, pick strips
back to hostname at the first space. Nightlight Waybar tooltip says
"follows your location" in geo mode. Queue's VPN entry updated.
- **Verified:** V1 — awk proven against a fabricated 3-case fixture
(Mullvad 1-word + multi-word city + bare node); flake check exit 0;
downstream-template-home builds (writeShellScriptBin syntax-gates both
scripts). Real tailscale output is V3 (existing VPN queue entry).
- **Pending:** V3 VPN menu live paths (extended, not new).
- **Next suggestion:** wallpapers artifact split (LATER, decided).
## 2026-07-11 — Night-light geo mode (lat/long → wlsunset)
- **Task:** BACKLOG LATER "Night-light geo mode" (human-picked).
- **Did:** `nomarchy.nightlight.latitude`/`.longitude` (both set = geo mode):
`services.wlsunset` (location-computed sunrise/sunset, `.temperature`
night temp) replaces hyprsunset; the toggle script's `unit=` and the
live-state ExecCondition follow via one `unit` let-binding. Template
example lines, README row, ROADMAP ✓. New `checks.nightlight-geo`:
pure-eval asserts on the rendered units (coords + temp in ExecStart,
ExecCondition present, hyprsunset off). Declarative-only (no menu writer —
coords are machine config like keyboard layout).
- **Verified:** V1 — `nix flake check --no-build` exit 0 (evals the new
asserts + option-docs); built `downstream-template-home` (default
hyprsunset path unregressed) + the check drv. Caught en route: HM renders
`ExecStart` as a list (`toString` needed in eval asserts).
- **Pending:** V3 queued (HARDWARE-QUEUE § Any machine): visible warm shift
at location night + toggle/persistence on the swapped unit.
- **Next suggestion:** wallpapers artifact split (LATER, decided).
## 2026-07-11 — Sync-sweep rule + grooming + zram user docs (human-requested)
- **Task:** Bernardo: groom stale items and codify the check so they don't
recur; close the zram user-doc gap.
- **Did:** LOOP.md §5 gains step 4 **Sync sweep** (grep item/feature across
agent/+docs/ on ship; prune recorded `[x]` queue entries) + an AGENTS.md
rule line. Applied it: BACKLOG PROPOSED pruned (auto-theme pitch was
stale — shipped as #79; shipped/promoted placeholders removed; v1.0
pointer rewritten; FUTURE promoted-stub dropped). HARDWARE-QUEUE pruned
29 checked `[x]` entries (363→~250 lines), dangling refs reworded,
prune rule in header. README §3 now documents the zram default +
hibernation out-of-the-box + MIGRATION pointer.
- **Verified:** V0 (docs/meta only) — grep sweep for dangling refs clean.
- **Pending:** night-light geo mode next (same session).
- **Next suggestion:** wallpapers artifact split (LATER, decided).
## 2026-07-11 — Vendor-neutral agent docs restructure (human-requested)
- **Task:** Bernardo: de-vendor the agent instructions (multi-model repo),
clean stale files, better docs/agent/.claude structure.
- **Did:** New root `AGENTS.md` entry (CLAUDE.md → symlink). Skill bodies
moved to `agent/`: VERIFICATION.md (enforcement, ex-nomarchy skill),
DELEGATION.md (tiers light/standard/frontier + scout/runner contracts +
fan-out; consolidates CLAUDE.md table + LOOP §economy + skill §6.5),
THEME-DESIGN.md (ex-theme skill, now with frontmatterd shim). `.claude/`
is a thin adapter (shims route into `agent/`). Maps updated (agent/,
docs/, README tree). Stale: `.gitignore` old_distro entry dropped; local
result*/__pycache__ removed. JOURNAL rotated (29 kept, 120 →
JOURNAL-ARCHIVE.md).
- **Verified:** V0 — `nix flake check --no-build` exit 0 with the symlink
tracked; vendor-name grep clean outside DELEGATION's mapping table.
- **Pending:** nothing; other harnesses add their own adapter row when used.
- **Next suggestion:** #76/#79 remain [blocked:hw]; otherwise groom PROPOSED.
## 2026-07-11 — #76 checks.hibernate-swapfile (VM-verify the swapfile+offset)
- **Task:** Bernardo — push #76's swapfile-resume residual into a VM (like
the auto-theme sunset trick).
- **Did:** Tried a full runtime-swapfile hibernate→resume test; it hit a
bounded, definitive **`CanHibernate=no`** — systemd won't hibernate to a
swap that isn't declared in the boot config, and a runtime-computed
`resume_offset` can't reach the boot cmdline (the genuine chicken-and-egg).
First cut also had an **unbounded `wait_for_shutdown`** that hung → killed
it, bounded the wait in a thread (180s) + a `CanHibernate` pre-check, which
is what surfaced the clean verdict. Pivoted `checks.hibernate-swapfile` to
what a VM *can* prove deterministically and the partition test can't: the
installer swapfile **build + offset** — NOCOW `mkswapfile`, file-type
swapon, valid `map-swapfile -r` offset accepted by `/sys/power/resume_offset`,
zram above it. (Device fix: `/dev/vdb` once `useNixStoreImage` was dropped.)
- **Verified:** **V2 PASS** (fresh build, exit 0). BACKLOG/ROADMAP updated;
#76 residual narrowed to the literal encrypted power-cycle (dev box runs it).
- **Lesson:** the sunset-trick spirit applies but not always the full cycle —
when systemd/kernel gates the behaviour (CanHibernate), verify the
*construction* deterministically and leave only the physical cycle to HW.
Always bound `wait_for_shutdown` (no timeout param → thread + join).
- **Next suggestion:** #76/#79 both `[blocked:hw]`; QA / PROPOSED otherwise.
## 2026-07-11 — Code-review fixes (parallel review of the session batch)
- **Task:** Bernardo asked for parallel work; spawned a fresh-eyes opus
review of `2055842..HEAD` (static). It found the batch sound — 2 real LOW
edge bugs, 1 false positive, 1 cosmetic.
- **Did:** (1) `cmd_auto` — inverted sunrise/sunset (sunrise > sunset) went
perpetually day; replaced the `not between` shortcut with a real
wrap-around `mins >= sunrise or mins < sunset`, so a cross-midnight day
window switches both ways. (2) `rofi.nix` autotheme HH:MM guard tightened
`[0-2][0-9]``[01][0-9]|2[0-3]` so 2429 are rejected. Dismissed the
`breeze` finding (papirus DOES ship breeze/breeze-dark — verified) and the
cosmetic doctor-RAM one.
- **Verified:** py_compile; boundary truth-table (normal + wrap-around);
HH:MM case table (23:00/19:59/20:00 accept, 24/25/30:00 reject); `auto
--which` normal-case unchanged; menu bash -n; flake check green. Normal
case unchanged so `checks.auto-theme` still holds.
- **Pending:** hibernate-swapfile VM test still running (uncommitted flake.nix).
- **Next suggestion:** land hibernate-swapfile once its VM test returns.
## 2026-07-10 — #79 V2: checks.auto-theme (simulated sunset) — was mis-framed V3
- **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,
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
summer-day → night (1 rebuild) → night (idempotent, still 1) → day (2). The
self-gating I relied on: presets via env, wallpaper/notify no-op headless,
run_switch honors NOMARCHY_REBUILD + waybar nudge is check=False.
- **Verified:** **V2 PASS**`nix build .#checks…auto-theme` fresh, exit 0.
Dropped #79's `[blocked:hw]`; it's done (V2). Updated ROADMAP.
- **Lesson:** don't default "timer/session feature" to V3 — stub only the
generic step (the real HM switch, covered elsewhere) and simulate the rest
(clock) headlessly. Only the literal timer-fires-on-OnCalendar is on-HW,
and its schedule is systemd-analyze-validated.
- **Next suggestion:** NEXT head #76 `[blocked:hw]`; else QA / PROPOSED.
## 2026-07-10 — #79 slice 3: Look & Feel Auto theme menu (#79 complete)
- **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).
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
timer no-ops). Day/night/times are live `--no-switch`.
- **Verified:** **V1** — HM generation builds (`writeShellScriptBin` bash -n
on nomarchy-menu passes) + bash -n on the built menu. **Logic test**
(stubbed rofi/theme-sync/notify): selecting "Auto theme (off)" runs exactly
`set day summer-day`, `set night summer-night`, `set enable true`
(all `--no-switch`), then `auto --force` — the intended one-rebuild path.
Disable path is static-clear (set false `--no-switch`, no `auto`); a
stateful-stub dynamic test would loop (stub doesn't reflect the flip). V0
flake check green. **#79 collapsed to `[blocked:hw]`** (all 3 slices done;
only live-session switch remains, needs a Nomarchy machine).
- **Pending:** V3 real-session (timer switches day↔night across sunset).
- **Next suggestion:** NEXT head #76/#79 both `[blocked:hw]`; QA/PROPOSED.
## 2026-07-10 — #79 slice 2: auto-theme systemd timer
- **Task:** BACKLOG #79 slice 2 — the timer/hook.
- **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`
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
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.)
- **Pending:** live timer→`home-manager switch` on a real Nomarchy session
(needs a Nomarchy machine, like #76). Slice 3 (menu) next.
- **Next suggestion:** #79 slice 3 — Look & Feel Auto theme menu.
## 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
`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`
prints the decision without switching; `--force`/`--no-switch` too.
Factored `cmd_apply`'s core into `apply_named` so `auto` reuses the exact
same one engine (GOALS: no second pipeline).
- **Verified:** **V1** package builds; functional tests on the built bin
against scratch state: wide-day→day slug, 00:0000: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.
- **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).