Commit Graph

721 Commits

Author SHA1 Message Date
4ac7122ac2 fix(gtk): bypass fragile SVG recoloring with static palette assets
Some checks failed
Check / eval (push) Failing after 1m41s
GTK's -gtk-recolor proved too fragile across different contexts, failing
to substitute the foreground color even when the SVG path used #000000.
Instead, we now generate two statically colored SVGs (normal + hover)
directly from the Nix palette hex codes, bypassing GTK's SVG recoloring
engine entirely.
2026-07-11 21:04:49 +01:00
ebfd344390 fix(gtk): add fill=#000000 to bundled submenu arrow SVG
Some checks failed
Check / eval (push) Failing after 1m33s
GTK's -gtk-recolor requires the explicit string #000000 inside the SVG
to correctly substitute the foreground color. Without it, the shape defaults
to a hard un-recolorable black, which remained invisible against the dark
popover menu backgrounds. Added viewBox for robustness.
2026-07-11 20:16:11 +01:00
3057a9e239 docs(journal): 2026-07-11 interactive T14s session entry
Some checks failed
Check / eval (push) Failing after 3m12s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:35:54 +01:00
6967d8973c fix(home): easyeffects waits for a live tray host, not waybar.service
Some checks failed
Check / eval (push) Failing after 4m10s
The tray-race guard (wwmm/easyeffects#4636) ordered the unit
After=waybar.service — inert here: Nomarchy's waybar runs from the
nomarchy-waybar supervisor (Hyprland exec-once), never as a systemd
unit, so the icon vanished whenever easyeffects won the boot race
(seen on TuringMachine 2026-07-11). Gate ExecStartPre on the SNI
watcher's IsStatusNotifierHostRegistered with a 30s timeout, non-fatal
so audio processing still starts on tray-less setups.

Also: #89 inventory narrowed by Bernardo's visual verdict — Telegram/
ZapZap fine; offenders are EasyEffects (slice 2) and Signal (slice 3).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:28:55 +01:00
dbc7741f58 docs(backlog): #89 slice-1 tray inventory done; #76 unblocked by migration
Some checks failed
Check / eval (push) Failing after 1m37s
Tray SNI inventory run live on the T14s: nm-applet, udiskie, Telegram
and EasyEffects are name-based (icon-lookup overridable); Signal and
ZapZap publish pixmaps only (slice 3). Method: watcher's
RegisteredStatusNotifierItems + busctl get-property.

#76: the dev box now runs Nomarchy (migrated 2026-07-11), so the
'not a Nomarchy machine' blocker is gone — retagged [human]; queue
step 1 (swapfile/zram/resume_offset wiring) verified live, only the
power-cycle test remains.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:21:50 +01:00
c608f58b5a fix(home): pin xdg.userDirs.setSessionVariables — HM 26.05 default flip
Some checks failed
Check / eval (push) Failing after 3m33s
home-manager 26.05 changes the default to false and warns on every
eval when home.stateVersion is older (every migrated machine). Pin the
legacy true: scripts and non-glib apps read the XDG_*_DIR session vars,
and an explicit value gives all downstreams identical behavior
regardless of stateVersion. mkDefault so a downstream can still opt out.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:13:19 +01:00
13ecfa92f0 fix(gtk): bundle the submenu arrow — Papirus has no pan-end-symbolic
Some checks failed
Check / eval (push) Failing after 1m33s
05bab55's menu fix pointed -gtk-icon-source at the icon theme, but
Papirus doesn't ship pan-end-symbolic and its inheritance chain
(breeze-dark → hicolor) has no provider installed, so GTK menu submenu
arrows rendered as nothing (nm-applet: no cue that 'VPN Connections'
opens a submenu). Bundle the triangle as a store-path SVG recolored
via -gtk-recolor(url(…)) — the same mechanism adw-gtk3 uses for its
own check-mark assets, immune to icon-pack coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:06:11 +01:00
61d591f5d2 feat(waybar): explain 'Not charging' hold state in the battery tooltip
With a charge cap, AC-plugged inside the hysteresis band (power.nix:
start = cap − 10) reports 'Not charging' — indistinguishable from a
broken charger without a hint. tooltip-format-plugged now says the cap
is holding the level and how charging resumes. No cap value baked: the
menu changes it live without a rebuild.

Whole-swap parity: the same tooltip added to all four theme
waybar.jsonc files (boreal/executive-slate/summer-day/summer-night) —
the generated config is bypassed under these themes.

Verified on hardware (TuringMachine, boreal theme, cap 80, battery 71%
in the hold band): all four jsonc validate with jq; home-manager switch
deploys the boreal config with the tooltip; battery currently in the
exact Plugged state the tooltip targets.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:06:11 +01:00
b39808d847 fix(waybar): VPN tooltip names the active VPN(s)
The shield's tooltip said only 'VPN active' — with both NM VPNs and
Tailscale feeding the same indicator, a forgotten tailscaled read as
'the icon is stuck after disconnecting'. List the active NM
VPN/WireGuard connection names and/or 'Tailscale' in the tooltip.

Verified on hardware (TuringMachine): script exercised with Tailscale
up → tooltip 'VPN: Tailscale'; tailscale down → empty output
(self-hide). NM name path is the same awk the nomarchy-vpn picker uses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:06:11 +01:00
Bernardo Magri
50a558615c feat(hyprland): SUPER+0 → workspace 10; migration doc gains autoLogin
Workspace binds were generated for 1-9 only, leaving SUPER+0 dead.
Generate 10, with the 0 key mapping to workspace 10 (and SHIFT+0 to
move); cheatsheet updated to match.

MIGRATION.md's example system.nix now includes
nomarchy.system.greeter.autoLogin — the migration path missed what
nomarchy-install sets on every LUKS machine, so migrated boxes stopped
at tuigreet asking for a password behind the LUKS prompt.

Verified: nix flake check --no-build passes; generated
homeConfigurations.nomarchy hyprland binds eval'd and contain
'$mod, 0, workspace, 10' + SHIFT variant. V3 next: rebuild on the
migrated T14s (TuringMachine) and press SUPER+0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:06:11 +01:00
14dd663d56 Update .gitea/workflows/check.yml
Some checks failed
Check / eval (push) Failing after 1m39s
2026-07-11 18:35:13 +01:00
Bernardo Magri
919dc4afc0 docs(backlog): promote tray icon parity → NEXT #89
Some checks failed
Check / eval (push) Failing after 1h16m53s
Bernardo accepted the EasyEffects tray-icon pitch and widened it: all
SNI apps (Signal/Telegram/ZapZap flatpaks too) should read monochrome
in the bar. Three slices: bus inventory (IconName vs IconPixmap),
HM shadow-icon override layer for name-based items, per-app knobs for
pixmap ones. PROPOSED pitch folded in.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 17:10:31 +01:00
Bernardo Magri
482cb87c70 fix(menu): release Left from kb-move-char-back before binding it to Back
Some checks failed
Check / eval (push) Failing after 8m34s
rofi hard-fails on a duplicate keybinding and reports it in a GUI error
dialog, not stderr — so 05bab55's Left=Back killed every menu entry
point on a real session while passing all stubbed tests. Rebind
kb-move-char-back to Control+b in both rofi_menu copies (menu + vpn).

V3 on the migrated T14s: error dialog reproduced with old flags, menu
renders with fixed flags. Journal + two PROPOSED pitches (EasyEffects 8
tray icon, parallel fingerprint/password PAM).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 16:58:04 +01:00
Bernardo Magri
2200379ea2 docs(migration): browser recovery — manual Web Store reinstall path
Some checks failed
Check / eval (push) Failing after 4m50s
Re-declaring is optional; ids are stable so restored data reattaches
on a plain Web Store reinstall too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 15:37:28 +01:00
Bernardo Magri
42542334e8 docs: backfill 05bab55 journal entry; real cause in MIGRATION browser note
Some checks failed
Check / eval (push) Has been cancelled
The migration session crashed before journaling. Follow-up diagnosis:
extensions vanished because programs.chromium.extensions wasn't carried
into the downstream flake — Chromium external-uninstall deletes the
extensions AND their Local Extension Settings. Rewrite the browser
migration note with the mechanism and the snapshot recovery path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 15:35:07 +01:00
Bernardo Magri
05bab5576e fix: migration first-boot, fingerprint PAM, menus, mic LED
Some checks failed
Check / eval (push) Failing after 9m12s
Post-migration annoyances from TuringMachine:

- Force fprintAuth from fingerprint.pam (NixOS defaults it on with fprintd)
- First-boot toast waits for swaync, retries, only marks after success
- Night light status/toggle handles masked units + hyprsunset/wlsunset
- VPN menu: define rofi_menu in nomarchy-vpn (was a silent no-op)
- Left arrow = ↩ Back in list menus; GTK menu contrast via Stylix
- Mic-mute LED udev + sync after wpctl; EasyEffects starts after tray
- Migration guide: HM before GUI login, fingerprint/browser/VPN notes

Verified: flake check --no-build; checks.first-boot; checks.hardware-toggles
(pam=false node). V3 session items pending after user rebuild.
2026-07-11 15:06:21 +01:00
Bernardo Magri
f2fb4adbce fix(theme): replace neon-glass wallpaper (drop center glass box)
All checks were successful
Check / eval (push) Successful in 11m1s
New 2560×1440 cyan/purple geometric void wallpaper without the mid-screen
GLASSMORPHISM panel; preview regenerated to match.

Verified: V0 — theme-wholeswap; center pixels near-black (no grey box).
2026-07-11 11:11:59 +01:00
Bernardo Magri
435f468079 docs(vision): renumber suggested slices after #88 ship
Some checks failed
Check / eval (push) Has been cancelled
2026-07-11 11:07:35 +01:00
Bernardo Magri
13f1b2b70e feat(theme): finish neon-glass polish (#88)
Some checks failed
Check / eval (push) Has been cancelled
Rewrite whole-swap rofi.rasi to rofi-native @colors (was invalid CSS
var()); cyan glass panel matching Boreal's hex-alpha pattern. btop
titles/selection in accent cyan; ui rounding/opacity tuned; preview.png
from theme-shot. Bar stays generated from JSON (no waybar.css).

Verified: V2 — contrast 24×7; theme-wholeswap; theme-shot neon-glass
desktop+menu viewed; boreal theme-shot regression green.
2026-07-11 11:07:02 +01:00
Bernardo Magri
2cd38e168d docs(backlog): complete #88 promotion bookkeeping
Some checks failed
Check / eval (push) Has been cancelled
Drop neon-glass from PROPOSED; point VISION slices at NEXT #88 finish
path. Companion to 78a3d60.

Verified: V0 (docs only).
2026-07-11 11:00:55 +01:00
Bernardo Magri
78a3d60b02 docs(backlog): promote neon-glass polish → NEXT #88
Some checks failed
Check / eval (push) Has been cancelled
Bernardo triage: finish path (not quarantine). Whole-swap assets stay;
do not reintroduce waybar.css without @define-color parity. V2 theme-shot
required on implement.

Verified: V0 (backlog/docs only).
2026-07-11 11:00:48 +01:00
Bernardo Magri
fc63feaa9d docs(vision): mark shipped Theme A/B/C; refresh PROPOSED
Some checks failed
Check / eval (push) Has been cancelled
VISION was still listing Firmware/Fingerprint/doctor/rebuild as open
work after they shipped. Sync ✓ rows + rewrite suggested agent slices.
PROPOSED: post-install hardware hints; neon-glass finish-or-quarantine.

Verified: V0 (docs/backlog only). Queue remains #76 [blocked:hw] only.
2026-07-11 10:59:11 +01:00
Bernardo Magri
9e8433e4d6 chore(agent): QA sweep + journal rotate (queue empty)
Some checks are pending
Check / eval (push) Waiting to run
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
Bernardo Magri
f47903a6a6 feat(audio): prefer dock/HDMI/USB sinks in WirePlumber (#87)
Some checks failed
Check / eval (push) Has been cancelled
Raise priority.session for HDMI/DisplayPort (1100) and USB (1050) ALSA
outputs so the default sink follows dock plug/unplug; built-in analog
wins again when externals disappear. Rules live in
modules/nixos/dock-audio-rules.nix; checks.dock-audio covers the contract.

Verified: V2 — flake check --no-build; checks.dock-audio green.
V3 pending: HARDWARE-QUEUE #87 real HDMI/USB-dock hotplug.
2026-07-11 10:36:07 +01:00
Bernardo Magri
27f18e4ccc feat(power): clamshell — ignore lid suspend when docked (#86)
Some checks failed
Check / eval (push) Has been cancelled
Explicit HandleLidSwitchDocked=ignore under services.logind so closing
the lid with an external display connected does not suspend. Undocked
lid path left to upstream defaults. checks.clamshell-logind asserts the
baked logind.conf and active logind; real multi-monitor lid V3 queued.

Verified: V2 — flake check --no-build; checks.clamshell-logind green.
V3 pending: HARDWARE-QUEUE #86 lid+external on a laptop.
2026-07-11 10:32:18 +01:00
Bernardo Magri
ce05eed754 docs(vision): fix HARDWARE.md section pointer after § renumber
Some checks failed
Check / eval (push) Has been cancelled
2026-07-11 10:28:56 +01:00
Bernardo Magri
523e44bbf8 docs(hardware): install-tested hall of fame (#85)
Some checks failed
Check / eval (push) Has been cancelled
HARDWARE.md §9 lists T14s Gen 4 + Latitude 5410/5310 with DMI/profile
notes and a "send your DMI line" PR invite. Split dock life #84 into
#86 clamshell + #87 dock audio (stable new IDs).

Verified: V0 (docs/backlog only).
2026-07-11 10:28:52 +01:00
Bernardo Magri
fe0b972171 feat(doctor): first-boot pre-activate fail flag (#83)
Some checks failed
Check / eval (push) Has been cancelled
If the installer left /var/log/nomarchy-hm-preactivate.log and no Home
Manager generation exists, doctor reports ✖ with the recovery one-liner
(home-manager switch --flake ~/.nomarchy -b bak). Clears once a
generation is present. checks.doctor covers both arms.

Verified: V2 — checks.doctor green; local smoke.
2026-07-11 10:28:14 +01:00
Bernardo Magri
639f553cb7 feat(lifecycle): plain-language generation diffs (#82)
Some checks failed
Check / eval (push) Has been cancelled
nomarchy-what-changed wraps nvd into "N added, M removed, K updated"
summaries. nomarchy-rebuild / nomarchy-home print full nvd and toast
the one-liner; System › What changed? offers toast + floating report.
checks.what-changed fixtures nvd via NOMARCHY_NVD.

Verified: V2 — flake check --no-build; checks.what-changed green;
local smoke on real HM generations.
2026-07-11 10:26:57 +01:00
Bernardo Magri
8f720b1078 feat(session): first-boot welcome toast (#81)
All checks were successful
Check / eval (push) Successful in 4m23s
One-shot user unit fires a dismissible "You're set" notification on the
first graphical session (SUPER+M / SUPER+T / SUPER+? + Network + Doctor),
then writes settings.firstBootShown into the flake checkout. Skips the
live ISO hostname (hosts/live.nix keeps its own toast). Toggle:
nomarchy.firstBootWelcome.enable. checks.first-boot covers the gate.

Verified: V2 — flake check --no-build; checks.first-boot green; local
shim smoke; downstream-template-home ships the unit.
2026-07-11 10:19:46 +01:00
Bernardo Magri
073adf743d test(doctor): V2 float harness for System › Doctor
Some checks failed
Check / eval (push) Has been cancelled
Headless softGL Hyprland harness (tools/doctor-float.nix): launches
nomarchy-menu doctor, asserts class/floating/center via hyprctl, dumps
before/after screenshots. Ran boreal + summer-night — both PASS
(floating centered sheet; Ghostty keeps ~800×600). MEMORY recipe.

Verified: V2 — THEME=boreal and THEME=summer-night doctor-float green;
screenshots viewed (desktop-before vs doctor-float under both themes).
2026-07-11 10:16:34 +01:00
Bernardo Magri
3d40a7e1ed feat(menu): open Doctor in a floating centered terminal
All checks were successful
Check / eval (push) Successful in 4m26s
Launch nomarchy-doctor via ghostty --class=com.nomarchy.doctor (same
pattern as the calendar popup) and match float/size/center windowrules
so System › Doctor and the Waybar doctor click no longer tile.

Verified: V1 — downstream-template-home builds; menu carries the class;
hyprland.conf has float/size/center for com.nomarchy.doctor;
windowrule-syntax green (19 rules). V2 live float confirm after
nomarchy-home (same class mechanism as calendar).
2026-07-11 10:08:50 +01:00
Bernardo Magri
71786bda6b feat(doctor): battery health readout (#80)
Some checks failed
Check / eval (push) Has been cancelled
Report-only cycle_count + retained capacity (charge_* or energy_*) as
% of design on system batteries; soft warn below 70% of design; skip
when attrs missing. NOMARCHY_POWER_SUPPLY_ROOT for the checks.doctor
fixture (test_power has no cycle/design attrs).

Verified: V2 — nix flake check --no-build; checks.doctor green (fake
BAT0 cycles/% + Device-scope ignore); local BAT0 smoke (energy_*).
2026-07-11 10:06:13 +01:00
Bernardo Magri
3132ba5ac8 docs(backlog): promote VISION-gap items → NEXT #80–#85 (human triage)
All checks were successful
Check / eval (push) Successful in 4m20s
Bernardo promoted: #80 battery health readout, #81 first-boot welcome
card, #82 generation readability, #83 doctor pre-activate fail flag,
#84 dock life polish [big — split before starting], #85 hardware hall
of fame. Wallpapers artifact split stays LATER. No implementation
started (explicit instruction).

Verification: V0 (backlog only).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 09:51:51 +01:00
Bernardo Magri
56793c1c27 docs(backlog): six VISION-gap PROPOSED pitches (B/C/A-residual/F)
All checks were successful
Check / eval (push) Successful in 4m18s
VISION cross-checked against the tree: firmware menu, fingerprint,
doctor GPU/hibernate, rebuild-error hints, post-install hints and the
install contracts are shipped; the genuinely open gaps are filed as
PROPOSED with one-paragraph pitches — first-boot welcome card,
generation readability, battery health readout, doctor pre-activate
fail flag, dock life polish [big], hardware hall of fame.

Verification: V0 (backlog only).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 09:44:56 +01:00
Bernardo Magri
53f75f6e1b polish(nightlight): geo-mode tooltip says it follows the location
Some checks failed
Check / eval (push) Has been cancelled
"Warm on schedule" was wrong in geo mode — the schedule is computed
from lat/long. Tooltip now reads "follows your location" when geo is
active.

Verification: V1 — rode the same flake check + template-home build as
the exit-node commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 09:41:34 +01:00
Bernardo Magri
656ebc9735 feat(menu): Tailscale exit-node rows show country/city
The Exit node picker listed bare hostnames; Mullvad-style nodes are
meaningless without their location. Rows are now
"hostname  — Country City", sliced from `tailscale exit-node list` by
the header's fixed-width column offsets (COUNTRY/CITY can be
multi-word, so field splitting is wrong by construction); nodes without
a location stay a bare hostname, and the pick strips back to the
hostname at the first space before `tailscale set --exit-node`.

Closes BACKLOG LATER "VPN exit-node richer display"; the VPN
HARDWARE-QUEUE entry now covers the location rows.

Verification: V1 — the awk was proven against a fabricated fixture
(one-word city, multi-word "United States / New York, NY", bare
self-hosted node), flake check exit 0, downstream-template-home builds
(writeShellScriptBin syntax-gates the script). Real `tailscale
exit-node list` output stays V3 (existing VPN menu live-paths entry).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 09:41:34 +01:00
Bernardo Magri
4ebd6770ec feat(nightlight): geo mode — lat/long-computed sunset via wlsunset
All checks were successful
Check / eval (push) Successful in 4m20s
Set BOTH nomarchy.nightlight.latitude/.longitude and the night light
switches backing unit: wlsunset computes sunrise/sunset from the
location daily (the fixed .sunrise/.sunset are ignored;
.temperature feeds the night temp). Everything user-facing is
unchanged — same nomarchy-nightlight toggle script, Waybar moon, and
live-state ExecCondition gate; the unit name is a single let-binding
so all three follow together. Declarative-only on purpose: coordinates
are machine config like the keyboard layout, so home.nix (commented
template example), not a menu writer.

checks.nightlight-geo guards the wiring at pure eval: rendered
wlsunset ExecStart carries the coords + night temperature, the
ExecCondition gate landed on the swapped unit, hyprsunset stays off in
geo mode.

Verification: V1 — nix flake check --no-build exit 0 (evals the new
asserts + option-docs sync); built downstream-template-home (default
hyprsunset path unregressed). V3 pending: visible warm shift at the
location's night + instant toggle/off-persistence on the swapped unit
(HARDWARE-QUEUE § Any machine).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 09:30:52 +01:00
Bernardo Magri
4c656b1e73 chore(agent): sync-sweep rule on task completion + apply it; zram user docs
All checks were successful
Check / eval (push) Successful in 4m45s
New standing rule (LOOP.md §5 step 4, echoed in AGENTS.md): when a task
ships, grep its number/feature name across agent/ and docs/ and update
or delete every cross-reference it made stale, in the same commit —
including pruning checked-off [x] HARDWARE-QUEUE entries whose outcome
is recorded (journal/ROADMAP; git history is the archive).

First application: BACKLOG PROPOSED groomed (the auto time-of-day theme
pitch was stale — shipped as #79; shipped/promoted placeholder lines
removed; v1.0 pointer rewritten; FUTURE promoted-stub dropped);
HARDWARE-QUEUE pruned of 29 checked entries (363→253 lines) with
dangling references reworded and the prune rule documented in its
header.

Also closes the zram user-doc gap: README §3 now documents the zram
default (zstd/50%/prio 100), hibernation working out of the box on new
installs, and the MIGRATION.md runbook for existing machines.

Verification: V0 (docs/meta only).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 09:20:54 +01:00
Bernardo Magri
5ef66c242e chore(agent): drop .claude/skills — AGENTS.md carries the routing
All checks were successful
Check / eval (push) Successful in 4m44s
The skill shims became redundant once the auto-loaded entry point
(CLAUDE.md → AGENTS.md) explicitly instructs reading VERIFICATION.md /
THEME-DESIGN.md; their only remaining value was explicit /nomarchy and
/theme invocation. The adapter is now permissions + subagent defs only.
References updated (AGENTS.md, agent/README.md, docs/README.md, README
tree, MEMORY.md hygiene note).

Verification: V0 (docs/meta only).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 09:06:32 +01:00
Bernardo Magri
dafa83e922 docs(agent): AGENTS.md explicitly requires reading VERIFICATION.md first
Some checks failed
Check / eval (push) Has been cancelled
The enforcement rules must not depend on any harness's skill/trigger
mechanism — the auto-loaded entry point itself now instructs every
agent to read agent/VERIFICATION.md before its first change (and
THEME-DESIGN.md / TESTING.md where relevant), instead of merely
pointing at them.

Verification: V0 (docs-only).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 09:04:14 +01:00
Bernardo Magri
c0fc16e25c docs(agent): vendor-neutral agent docs — AGENTS.md entry, agent/ SoT, .claude shims
All checks were successful
Check / eval (push) Successful in 4m28s
The repo is maintained by agents from multiple vendors, so agent
instructions move out of vendor-specific locations into shared,
git-tracked markdown:

- AGENTS.md is the new entry point for any harness; CLAUDE.md becomes a
  symlink to it (Claude Code keeps working unchanged).
- Skill bodies relocate to agent/: VERIFICATION.md (the enforcement
  rules, ex .claude/skills/nomarchy), DELEGATION.md (capability tiers
  light/standard/frontier, scout/runner role contracts, token economy,
  parallel fan-out — consolidates the CLAUDE.md model table, LOOP.md's
  economy section, and skill §6.5 into one place; vendor model names
  survive only in the per-harness mapping table), THEME-DESIGN.md
  (ex .claude/skills/theme, which previously lacked frontmatter).
- .claude/ shrinks to a thin Claude Code adapter: settings, subagent
  defs, and skill shims that route into agent/.
- Maps updated: agent/README.md (instructions vs state vs adapters),
  docs/README.md, README.md layout tree.

Cleanup: stale old_distro .gitignore entry dropped (dir long gone);
local result*/__pycache__ artifacts removed; JOURNAL.md rotated (29
recent entries kept, 120 older moved to agent/JOURNAL-ARCHIVE.md,
rotation rule documented in the header).

Verification: V0 (docs/meta only) — nix flake check --no-build exit 0
with the tracked symlink; grep sweep confirms no vendor model names
outside DELEGATION.md's mapping table.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 08:58:25 +01:00
Bernardo Magri
37615c85a4 test(hibernate): #76 checks.hibernate-swapfile — verify swapfile+offset in a VM
All checks were successful
Check / eval (push) Successful in 4m18s
Push #76's swapfile-resume residual into a VM as far as headlessly possible.
A full hibernate→resume from a RUNTIME swapfile turned out not to be
headless-reachable: systemd reports CanHibernate=no for a swap that isn't
declared in the boot config, and a runtime-computed resume_offset can't be
fed into the boot cmdline (the genuine chicken-and-egg). So the check now
verifies, bounded and deterministically, what the partition test
(checks.hibernate) can't and what a VM CAN prove: the installer's btrfs
@swap swapfile is built correctly and its offset is valid — NOCOW
mkswapfile, file-type swapon, a good `map-swapfile -r` offset the kernel
accepts (/sys/power/resume_offset), and zram (prio 100) above it.

The literal encrypted-swapfile power-cycle + LUKS-initrd unlock stays a V3
laptop check (the dev box runs exactly this layout, /proc/cmdline verified).

(First cut had an unbounded wait_for_shutdown that hung on the CanHibernate
refusal; rewritten with a thread-bounded wait + a CanHibernate pre-check,
which gave the clean verdict. Device is /dev/vdb without useNixStoreImage.)

Verification: V2 PASS (nix build .#checks.x86_64-linux.hibernate-swapfile,
fresh, exit 0); flake check --no-build green. #76 residual narrowed in
BACKLOG/ROADMAP.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 08:34:17 +01:00
Bernardo Magri
2fa5231215 fix(theme): #79 review fixes — wrap-around schedule + HH:MM guard
All checks were successful
Check / eval (push) Successful in 4m6s
Two low-severity edge bugs from a fresh-eyes review of the session batch:

- cmd_auto: an inverted schedule (sunrise > sunset, i.e. a day window that
  crosses midnight) stayed perpetually on the day theme — the old
  `not between` shortcut is an empty interval when sunrise > sunset.
  Replaced with a real wrap-around: daytime = mins >= sunrise or
  mins < sunset, so both directions switch. Normal sunrise < sunset path
  is unchanged (checks.auto-theme still holds).
- rofi autotheme HH:MM validator: `[0-2][0-9]` accepted 24:00–29:59.
  Tightened the case pattern to `[01][0-9]:[0-5][0-9]|2[0-3]:[0-5][0-9]`
  so out-of-range hours are rejected (they'd otherwise skew the boundary).

(Two other review findings dismissed: papirus DOES ship breeze/breeze-dark
so that iconPacks prefix is correct; the doctor RAM-unknown row is cosmetic
since /proc/meminfo is always readable.)

Verification: 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.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 08:19:05 +01:00
Bernardo Magri
808990592d docs(overrides): user guide for auto day/night theme (#79)
All checks were successful
Check / eval (push) Successful in 3m51s
Add an "Auto theme (day/night)" subsection to docs/OVERRIDES.md § 1
(Appearance), after the Icon pack section. Covers what it does (light/dark
switch on a schedule, same one engine), how to turn it on (Look & Feel ›
Auto theme, or the shell set/auto sequence), the settings.autoTheme
fields, and behavior (periodic ~15-min re-check, idempotent rebuilds,
instant disable). Names/fields/flags verified against rofi.nix,
nomarchy-theme-sync.py, and the icon section's style.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 22:31:21 +01:00
Bernardo Magri
49e0061dbb test(auto-theme): #79 V2 — simulate sunset in a VM (was mis-framed V3)
All checks were successful
Check / eval (push) Successful in 3m53s
Bernardo rightly pushed back on deferring #79 to a real session: a
simulated sunset IS VM-testable. Add checks.auto-theme, a runNixOSTest
that installs nomarchy-theme-sync, points NOMARCHY_DEFAULT_THEMES at the
presets, stubs the rebuild via NOMARCHY_REBUILD (a marker), configures
the day/night pair + schedule, then WALKS THE VM CLOCK across the
boundary: 19:55 -> 20:05 -> 20:06 -> next-day 07:30, asserting the active
theme goes summer-day -> night (1 rebuild) -> night (idempotent, still 1)
-> day (2 rebuilds).

This isolates the auto decision + apply + rebuild-trigger; the actual
home-manager switch is stubbed (that generic apply path is exercised by
every manual theme change). The only on-hardware residual is the user
timer firing on its OnCalendar schedule, which systemd-analyze validates.

#79 drops its [blocked:hw] tag — it's V2-verified. ROADMAP updated;
lesson recorded in MEMORY (don't default timer/session features to V3:
stub the generic step, simulate the clock).

Verification: V2 PASS (nix build .#checks.x86_64-linux.auto-theme, fresh,
exit 0); V0 flake check green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 22:04:38 +01:00
Bernardo Magri
860c70466f feat(menu): #79 slice 3 — Look & Feel › Auto theme (completes #79)
All checks were successful
Check / eval (push) Successful in 3m46s
Adds an "Auto theme (on/off)" row to Look & Feel and an `autotheme`
submenu: toggle the feature, pick the day/night themes (from
`nomarchy-theme-sync list`), and set the sunrise/sunset times (HH:MM,
validated). This is the menu surface over settings.autoTheme, completing
the auto time-of-day theme feature (slices: CLI / timer / menu).

Enabling writes the flag and defaults the summer-day/summer-night pair
--no-switch, then runs `auto --force`, so a single rebuild both installs
the timer and applies the correct theme for now. Disabling is instant
(--no-switch): the flag flips and `auto` self-gates, so the lingering
timer no-ops until the next rebuild. Day/night/time writes are live
--no-switch (read by `auto` at tick time).

Verification: V1 — HM generation builds (bash -n on nomarchy-menu at
build) + bash -n on the built menu. Logic test with stubbed
rofi/theme-sync/notify: selecting the toggle from off runs exactly `set
day/night/enable ... --no-switch` then `auto --force` — the intended
one-rebuild path. V0 flake check green. All three #79 slices shipped;
the live timer switch across sunset is a real-session (V3) check on a
Nomarchy machine.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 21:53:37 +01:00
Bernardo Magri
c44616aeb0 feat(autotheme): #79 slice 2 — systemd timer runs auto
All checks were successful
Check / eval (push) Successful in 3m53s
modules/home/autotheme.nix installs a user service + timer
(nomarchy-auto-theme) that periodically runs `nomarchy-theme-sync auto`,
so the day/night theme is applied on the current schedule through the
same one engine. Install gates on settings.autoTheme.enable (read from
state, the way updates.nix gates on its enable), so a machine not using
the feature carries no timer.

Timer: OnStartupSec=1min (settle after login) + OnCalendar=*:0/15 +
Persistent (catch a transition missed while off). Periodic rather than
exact sunrise/sunset timers — robust to suspend/DST, and `auto` is
idempotent (no rebuild unless the theme must change) so ticks are cheap.

Verification: V1 — real-config eval (state temporarily enabled, then
restored) confirms the units land when enabled (OnCalendar *:0/15,
ExecStart `... nomarchy-theme-sync auto`) and are absent when disabled;
systemd-analyze validates the schedule. V0 flake check green. The live
timer -> home-manager switch on a real Nomarchy session is pending a
Nomarchy machine (same blocker as #76).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 21:34:56 +01:00
Bernardo Magri
429de59b52 feat(theme-sync): #79 slice 1 — auto day/night theme primitive
All checks were successful
Check / eval (push) Successful in 3m58s
First slice of the auto time-of-day theme pair (VISION § D, split into
CLI / timer / menu). `nomarchy-theme-sync auto` reads
settings.autoTheme.{enable,day,night,sunrise,sunset}, picks day vs night
from the local clock, and applies the matching preset — but only if it
differs from the current one, so the slice-2 timer can fire freely
without triggering needless rebuilds. `--which` prints the decision
without switching; `--force` and `--no-switch` included.

cmd_apply's core is factored into apply_named() so `auto` drives the
exact same one engine (no second pipeline). apply behavior is unchanged.

Verification: V1 (package builds) + functional tests on the built binary
against scratch state — wide-day window → day slug, a 00:00–00:01 day
span → night, disabled → no-op, missing day/night → clear die, auto
--no-switch writes state, a re-run no-ops as "already on", and plain
apply still writes (refactor intact). V0 py_compile + flake check +
checks.theme-sync-validate green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 21:20:55 +01:00
Bernardo Magri
79d73cd623 docs(omarchy): #78 Omarchy → Nomarchy migrant one-pager
All checks were successful
Check / eval (push) Successful in 3m47s
Add docs/OMARCHY.md for users coming from Omarchy (VISION § F). Leads
with the one real difference — imperative dotfiles vs a declarative flake
built via the menu, with rollback through NixOS generations — then maps
the deltas: install (ISO/nomarchy-install or MIGRATION.md), a familiar
keybindings table, theming (SUPER+T / nomarchy-theme-sync), installing
software (home.packages / nix shell, no AUR), and update+rollback
(nomarchy-pull/-rebuild/-home, boot-menu generations, nomarchy-doctor).
Registered in docs/README.md; VISION § F marked shipped.

The Nomarchy side is grounded in the code: keybindings pulled from
keybinds.nix, and every cited command (7), the nsearch alias, and the
named theme slugs (gruvbox/rose-pine/nord) verified to exist. Omarchy-side
claims kept to known facts (Arch, dotfiles, pacman/AUR).

Verification: V0 (docs-only); commands/slugs/binds checked against the tree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 21:15:36 +01:00