From 6d70bba8e66964b4dbb696fe8425db832d122f75 Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Sat, 4 Jul 2026 08:51:11 +0100 Subject: [PATCH] feat(agent): autonomous-loop infrastructure + roadmap rework MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A git-tracked agent/ directory so AI agents can iterate on the distro unattended (runner-agnostic: /loop, headless claude -p, or a fresh manual session — all state lives in the checkout, per the distro's own philosophy): - LOOP.md — the iteration protocol: orient → pick one BACKLOG task → verify up the V0–V3 ladder → commit+push main → record. Safety rails (v1 untouchable, no force-push, no surprise lock bumps) and stop-and-escalate conditions. - BACKLOG.md — the forward half of docs/ROADMAP.md reworked into a prioritized queue (5 NOW / 6 NEXT / LATER / PROPOSED / Decisions); ROADMAP.md stays the design/decision record + shipped log. - GOALS.md — the four pillars (stable > reproducible/zero-hidden-state > effortless config > beautiful), quality bars, non-goals. - CONVENTIONS.md — coding/design rules (in-flake state, menu placement, Waybar whole-swap parity, toggle-vs-package, no formatter). - MEMORY.md — curated hard-won lessons (VM recipes, btrfs-assistant segfault watch, rofi/WirePlumber/hyprlock gotchas). - HARDWARE-QUEUE.md — every pending V3 on-hardware check collected from the ROADMAP, with exact steps, split by machine. - JOURNAL.md — append-only iteration log, seeded with this bootstrap. Plus a root CLAUDE.md entry point and README/ROADMAP pointers. Verified: V0 — docs-only; nix flake check --no-build green. Co-Authored-By: Claude Fable 5 --- CLAUDE.md | 25 +++++++ README.md | 13 ++-- agent/BACKLOG.md | 142 ++++++++++++++++++++++++++++++++++++++++ agent/CONVENTIONS.md | 70 ++++++++++++++++++++ agent/GOALS.md | 58 ++++++++++++++++ agent/HARDWARE-QUEUE.md | 63 ++++++++++++++++++ agent/JOURNAL.md | 33 ++++++++++ agent/LOOP.md | 118 +++++++++++++++++++++++++++++++++ agent/MEMORY.md | 60 +++++++++++++++++ docs/ROADMAP.md | 6 ++ 10 files changed, 584 insertions(+), 4 deletions(-) create mode 100644 CLAUDE.md create mode 100644 agent/BACKLOG.md create mode 100644 agent/CONVENTIONS.md create mode 100644 agent/GOALS.md create mode 100644 agent/HARDWARE-QUEUE.md create mode 100644 agent/JOURNAL.md create mode 100644 agent/LOOP.md create mode 100644 agent/MEMORY.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..532653e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,25 @@ +# Nomarchy — agent entry point + +Nomarchy is a NixOS-based distro: rock-stable, fully reproducible, themed +from one JSON, configured through a menu that writes into the user's own +flake checkout. Read the README for the architecture. + +## If you're here to work autonomously (the loop) +Follow **`agent/LOOP.md`** — it defines one iteration: orient +(GOALS/BACKLOG/JOURNAL/MEMORY), take the top actionable BACKLOG item, +verify up the V0–V3 ladder, commit+push on `main`, record. All loop state +is git-tracked in `agent/`. + +## Rules that apply to every session, loop or not +- **Honesty rule** (docs/TESTING.md): for visual/interactive changes, + evaluation is not rendering — state exactly what you verified and at + which tier. Cheap check first, always: `nix flake check --no-build`. +- **Conventions** (`agent/CONVENTIONS.md`): in-flake state, menu + placement, Waybar parity with the summer whole-swaps, toggle-vs-package + discipline, commented template examples for opt-ins. +- **Git:** direct commits on `main`, pushed; `v1` is the human-only + release pointer — never touch it. Never run `nix flake update` unless + the task is a lock bump. No formatter — match the aligned + hand-formatting. +- Machine-specifics live in `hosts/`, the distro in `modules/`, data in + `themes/`, code in `pkgs/`, maintainer tools in `tools/`. diff --git a/README.md b/README.md index 7d6a072..64fa067 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,9 @@ Flat on purpose. Two module trees, one options file each, no hidden layers. ├── templates/downstream/ # `nix flake init -t` starter for users ├── docs/TESTING.md # how to verify changes (incl. AI-agent rules) ├── docs/OVERRIDES.md # how downstream users override defaults -├── docs/ROADMAP.md # forward-looking plans + shipped-fixes log +├── docs/ROADMAP.md # design/decision records + shipped-fixes log +├── agent/ # autonomous-agent loop: protocol (LOOP.md), +│ # prioritized BACKLOG, journal, memory └── tools/ # maintainer-only ├── import-palettes.py # converts old-distro themes → JSON + assets ├── test-live-iso.sh # build the ISO + boot it in QEMU @@ -395,6 +397,9 @@ reload # exec zsh (reload the shell) ## Roadmap & known issues -See **[docs/ROADMAP.md](docs/ROADMAP.md)** — forward-looking plans plus the -log of shipped fixes. Kept out of the README so this stays a focused entry -point. +The prioritized queue of what's next lives in +**[agent/BACKLOG.md](agent/BACKLOG.md)**; the detailed design/decision +records and the log of shipped fixes stay in +**[docs/ROADMAP.md](docs/ROADMAP.md)**. Development runs on an +agent-driven loop — see **[agent/LOOP.md](agent/LOOP.md)**. Kept out of +the README so this stays a focused entry point. diff --git a/agent/BACKLOG.md b/agent/BACKLOG.md new file mode 100644 index 0000000..8e942a8 --- /dev/null +++ b/agent/BACKLOG.md @@ -0,0 +1,142 @@ +# Backlog — the prioritized task queue + +The forward-looking half of the old docs/ROADMAP.md, reworked as a queue +agents can execute. Detailed design notes and decision records stay in +`docs/ROADMAP.md` (referenced as "ROADMAP § "); this file is *what's +next, in what order*. + +**Rules:** +- Agents take the topmost actionable item (see LOOP.md). Finished items + are **deleted** here — the journal + git log are the record; durable + design notes get a ✓-entry in docs/ROADMAP.md if worth keeping. +- Tags: `[blocked:hw]` needs real hardware (see HARDWARE-QUEUE.md) · + `[human]` needs Bernardo · `[stuck]` two failed attempts, needs help · + `[big]` must be split before starting. +- Agents may append to **PROPOSED** and **Decisions** freely; only + Bernardo moves items *out* of PROPOSED into the tiers. + +--- + +## NOW + +### 1. Opt-in auto-commit of the flake on state mutations +Phase 4 of the in-flake-state principle (phases 1–3: night-light, +keyboard memory, display resolution — shipped). Every menu write +(`nomarchy-theme-sync set/apply`) already does `git add -N`; add an +opt-in (a `settings.autoCommit` flag, itself menu-toggled) that commits +**owned files only** (theme-state.json) with a generated message after +each mutation. **Why:** closes the loop on "your checkout is your +machine" — settings changes become history. **Done when:** off by +default; toggleable from the System menu; commits fire on apply/set; +never commits unrelated dirty files; graceful when the repo has no user +git identity. **Verify:** V1 + a round-trip on the theme-sync CLI in a +sandbox repo; V2 if wired into a check. + +### 2. btrfs-assistant segfault — attempt the nixpkgs override fix +ROADMAP § Snapshot browse/restore. btrfs-assistant 2.2 crashes in +`libbtrfsutil.so.1.4.0` (ABI mismatch, confirmed not a VM artifact); the +`nomarchy-snapshots` fzf fallback ships. Try an override aligning its +libbtrfsutil (or a version bump/pin); if upstream nixpkgs has since +fixed it, just verify and re-point the menu. **Done when:** the GUI +launches in the VM test, or the attempt is written up as infeasible +(then re-check on each lock bump). **Verify:** V2 — extend the snapper +VM check to launch the binary. + +### 3. Keyboard layouts — cycle bind + summer-bar parity +ROADMAP § Keyboard layouts, remaining bullets: (a) a multi-layout cycle +bind (`hyprctl switchxkblayout` current-device, or xkb `grp:` option) +when >1 session layout, in the cheatsheet; (b) add `hyprland/language` +to the summer-day/night `waybar.jsonc` whole-swaps (parity rule — the +generated bar has it, the static ones don't; gating doesn't translate, +decide the static behavior and note it). **Verify:** V1 + `jq` the +rendered configs; V3 queue the on-hardware cycle check. + +### 4. Full docs review & restructure +ROADMAP § Full docs review. The roadmap/backlog split is done (this +file); remaining: reconcile every README option table against the live +`nomarchy.*` surface; drift pass over docs/OVERRIDES.md, docs/TESTING.md, +templates/downstream/README.md; read the install/first-run story end to +end. Site-vs-markdown is a Decision (below). **Verify:** V0 + a +mechanical option-surface diff (eval the options, compare to the +tables — consider making that a permanent check). + +### 5. Webcam follow-ups (small) +ROADMAP § Webcam: ship `v4l-utils` + `cameractrls` (commented app-suite +entries or alongside the camera toggle — respect the option-surface +rule) for genuine-tuning cases; write up the portal/Flatpak +libcamera-path gap (internal IR still listed there) as a PROPOSED item +with options. **Verify:** V1. + +## NEXT + +### 6. Automated upstream lock bumps (maintainer CI) `[big]` +ROADMAP § Automated upstream lock bumps — design decided: weekly +scheduled job (Forgejo Actions) runs `nix flake update` (within pinned +release branches) → `nix flake check` + the `checks.*` suite + toplevel +build → lands on `main` on green; `v1` promotion stays human. Repo has +no CI today, so slice: (a) a workflow that just runs checks on push, +(b) the scheduled bump job, (c) the fast-lane note for security bumps. + +### 7. Display profiles — docked/undocked switching +ROADMAP § Display / monitor management, remaining: true profile +switching of the *same* outputs (multi-layout toggles, beyond +per-output hotplug rules), optionally workspace-to-monitor binding. +Design first (state-file shape, menu surface) — write the plan into +this entry before coding. + +### 8. Greeter theming from the JSON +ROADMAP § Greeter. tuigreet themed from theme-state.json at system +rebuild (same model as Plymouth's tint). Scope: tuigreet only (no SDDM). + +### 9. Launch-or-focus UX scripts +ROADMAP § launch-or-focus. Hyprland dispatch scripts: a bind launches an +app or focuses its existing window. Curate which apps get binds; +cheatsheet entries via keybinds.nix. + +### 10. "nomarchy" control center + first-boot welcome `[big]` +ROADMAP § control center. A single front-end over the common toggles on +the same `nomarchy-theme-sync` surface, + a first-boot guided +"pick your theme / essentials" flow. Needs a design pass (TUI vs GUI) +→ write options into Decisions before implementing. + +### 11. Look & Feel menu category +ROADMAP § Menu system, remaining: group Theme + night-light (+ wallpaper +cycle, future appearance toggles) under a Look & Feel submenu once it +earns ≥3 entries — keep the root at six. + +## LATER + +- **Wallpapers artifact split** (ROADMAP § Faster switches — decided, + deferred): pinned `Nomarchy-wallpapers` input so a state write stops + re-copying 86 MB. Follow-on: pre-built theme variants if switches are + still slow after. +- **Installer round 2** (ROADMAP § Installer): multi-disk BTRFS RAID, + impermanence, BIOS/legacy boot. +- **Boot-from-snapshot**: a systemd-boot equivalent of grub-btrfs. +- **Night-light geo mode**: lat/long auto sunset/sunrise (means wlsunset). +- **Per-theme icon overrides** / more icon packs (ROADMAP § Icon themes). +- **MIPI/IPU software-ISP camera** support (no-UVC machines). +- **Auto-timezone Waybar tooltip** showing the detected zone (optional). +- **VPN exit-node richer display** (country/city) (optional). +- **NixOS release bump → v2** `[human]`: deliberate, hand-edited, never + automated; the previous attempt was discarded (2026-06-22) over a + Hyprland OOM blocker — see MEMORY.md before retrying. + +## PROPOSED (agent suggestions — await human triage) + +*Agents: append here with a one-paragraph pitch (what/why/cost). Do not +implement. Bernardo moves accepted items into a tier.* + +- *(empty)* + +## Decisions `[human]` + +Open calls only Bernardo can make; agents add options/evidence but never +decide. + +- **Formatter adoption:** repo deliberately has none; `nixfmt-rfc-style` + would flatten the aligned hand-formatting of ~33 files. Adopt or + declare never? +- **Docs site vs Markdown-in-repo** (from the docs-review item). +- **Control center form factor:** TUI (gum/ratatui-style) vs GUI vs + "the rofi menu *is* the control center, just add a first-boot flow". diff --git a/agent/CONVENTIONS.md b/agent/CONVENTIONS.md new file mode 100644 index 0000000..0250779 --- /dev/null +++ b/agent/CONVENTIONS.md @@ -0,0 +1,70 @@ +# Conventions — how Nomarchy code is written + +The standing rules an agent must follow while coding. GOALS.md says what +we're building; this says how. Details/rationale live in docs/ROADMAP.md's +decision records and the README. + +## Repo layout (the rule of thumb) +`modules/` is the distro (reusable, no machine specifics) · `hosts/` is a +machine · `themes/` is data · `pkgs/` is code · `tools/` is maintainer-only +· `agent/` is loop state. If a new file doesn't obviously belong to one of +those, it probably shouldn't exist. + +## Nix style +- **No formatter.** Files use deliberate aligned hand-formatting — match + the surrounding style exactly; never reflow a file you're only touching + a line of. +- Distro defaults use `lib.mkDefault` so a plain downstream assignment + wins; bind/exec lists concatenate. Behaviour options overridable, + appearance flows from the state JSON. +- Options live in the existing surfaces: `nomarchy.system.*` / + `nomarchy.hardware.*` / `nomarchy.services.*` (NixOS, `system.nix`), + everything else `nomarchy.*` (HM, `home.nix`). Update the README tables + when the surface changes. + +## Feature design +- **In-flake state:** any user-settable config gets a menu writer that + lands it in `theme-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 + values graduate via `mkDefault` reads of the settings key. +- **Toggle vs package:** a `nomarchy.*` toggle only when there's real + config behind it (units, groups, udev, firewall). A bare package goes + in the downstream template's `home.packages` — opt-out is deleting the + line. +- **Opt-in features** ship a commented example in + `templates/downstream/home.nix` or `system.nix`. +- **Menu:** new entries go in the right submenu (Tools › / System ›; root + stays six entries), end lists with the shared `↩ Back`, self-gate on + the feature's availability, and add the direct + `SUPER+CTRL+` bind in `keybinds.nix` (single source — it + feeds both Hyprland and the SUPER+? cheatsheet). +- **Waybar:** new indicators self-gate (hidden when irrelevant), use + named `writeShellScriptBin`s on PATH (so static configs can exec them + by bare name), and are added to **both** the generated `waybar.nix` + config **and** the summer-day/night `waybar.jsonc` whole-swaps (the + parity rule). +- **Theming:** every new visual surface consumes the palette from the + state JSON. There is no second renderer to keep in sync — add the key + to the JSON, consume it in the module. + +## Testing +- docs/TESTING.md is canonical; LOOP.md's ladder (V0–V3) sets the + required tier. Cheap first: `nix flake check --no-build`, `bash -n`, + `py_compile`. +- Prefer a permanent `checks.*` runNixOSTest over a one-off manual poke; + reusable recipes (headless Hyprland with software GL, QMP screenshots, + udev-event fakes) are indexed in MEMORY.md and demonstrated by the + existing checks (`distro-id`, `hardware-toggles`, + `battery-charge-limit`). +- The honesty rule: report exactly what you verified and at which tier. + +## Git +- `main` is development (direct commits, pushed); `v1` is the release + pointer — **human-only, fast-forward-only, never touched by agents**. +- Commit style: `feat|fix|test|docs|chore(scope): summary`, body with + what/why + verification tier + what remains. Bookkeeping (`agent/` + updates) rides in the same commit as the change. +- `flake.lock` moves only when the task *is* a lock bump, and only within + the pinned release branches. diff --git a/agent/GOALS.md b/agent/GOALS.md new file mode 100644 index 0000000..7c38226 --- /dev/null +++ b/agent/GOALS.md @@ -0,0 +1,58 @@ +# Goals — what "done" looks like for Nomarchy + +The north star every loop iteration serves. When two options conflict, +the earlier pillar wins. + +## The four pillars (in priority order) + +1. **Rock-stable.** A workstation you never fight. Everything is a NixOS/HM + generation — atomic, rollbackable, never partial. `nix flake check` is + green at every commit on `main`. Regressions are caught by the VM-test + suite (`checks.*`), not by users. `v1` only ever advances after human + 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 + `~/.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 + common knob is reachable from `nomarchy-menu` (SUPER+M); the menu is an + ergonomic writer for the flake. Where a toggle can take effect without a + rebuild, it must (`--no-switch` + flip the running service). +4. **Beautiful.** One JSON themes the entire desktop coherently — Hyprland, + Waybar, Ghostty, btop, rofi, GTK/Qt, boot splash, greeter. Every new + surface follows the palette. Informative, self-gating Waybar modules + (they hide when irrelevant). No unthemed corner survives contact with + the theme switcher. + +## Quality bars (non-negotiable) + +- **The honesty rule** (docs/TESTING.md): for anything visual, "the Nix + evaluates" is not "it renders". Verify at the highest tier you can reach + (see LOOP.md's verification ladder) and *state the tier you reached*. + Never claim a check you didn't run. +- **Parity rule:** any module added to the generated Waybar config must + also be added to the summer-day/night `waybar.jsonc` whole-swaps. +- **Menu placement:** new menu entries go in the right category submenu + (Tools › / System ›), with a direct `SUPER+CTRL+` bind and + self-gating where applicable. The root picker stays six entries. +- **Opt-in features** ship a commented example in + `templates/downstream/{home,system}.nix`. +- **Option surface discipline:** a toggle exists only when there is real + config behind it. Bare package installs go in the template's + `home.packages` (opt-out = delete the line), never a `nomarchy.apps.*`. + +## Non-goals (do not drift into these) + +- **No binary cache.** Compile-from-source is a deliberate values call; + automation targets the config/lock channel, not artifact distribution. +- **No second theming pipeline.** The dispatcher owns menu structure; the + renderer (rofi) stays swappable. No GTK4 launcher. +- **No nixpkgs major bump on `main`.** Lock updates stay within the pinned + release branch; a release jump is a deliberate `v2`, hand-edited by the + maintainer (the last attempt was discarded over a Hyprland OOM — see + agent/MEMORY.md). +- **No repo-wide reformat.** The `.nix` files use deliberate aligned + hand-formatting; adopting a formatter is an open maintainer decision + (BACKLOG.md § Decisions), not a cleanup. +- **No multi-DE.** Hyprland is the desktop. diff --git a/agent/HARDWARE-QUEUE.md b/agent/HARDWARE-QUEUE.md new file mode 100644 index 0000000..f17608d --- /dev/null +++ b/agent/HARDWARE-QUEUE.md @@ -0,0 +1,63 @@ +# Hardware queue — V3 checks only a human can run + +Everything shipped at V1/V2 whose final verification needs real hardware. +Agents **append** (newest at the bottom of a section) with exact steps; +Bernardo runs them and either checks off (`[x]` + date + verdict) or files +the failure as a NOW bug in BACKLOG.md. Machines: the **AMD dev box** +(Ryzen AI laptop: AMD + fingerprint + NPU), the **Latitude 5410** (Intel +QA machine), the **T14s** (webcam case). + +## Any machine (dev box is fine) +- [ ] **Battery charge limit re-apply on unplug** — `sudo nixos-rebuild + switch` with `power.batteryChargeLimit = 80`, physically unplug/replug + AC, confirm `charge_control_end_threshold` re-reads 80. (udev trigger + already VM-verified.) +- [ ] **SSH_AUTH_SOCK for GUI clients** — after relogin, launch a GUI git + client (or `rofi`-launched terminal-less app) and confirm it reaches + gpg-agent's SSH socket without an interactive shell parent. +- [ ] **Night-light full cycle** — first menu enable rebuilds + hyprsunset + starts; later toggles are instant (no rebuild); an *off* survives + reboot (ExecCondition); stopping hyprsunset restores gamma. +- [ ] **Auto-timezone** — enable from the menu; confirm geoclue finds the + zone, `/etc/localtime` updates, and the Waybar clock refreshes + (SIGUSR2 watcher) — also after a manual `timedatectl set-timezone`. +- [ ] **Keyboard hotplug picker (re-verify after in-flake graduation)** — + plug an external keyboard post-login, pick a layout in rofi, confirm + it applies per-device only, persists in `settings.keyboard.devices`, + and graduates into a `device{}` block on the next rebuild. +- [ ] **Snapshots restore/rollback** — `nomarchy-menu snapshot` → + `nomarchy-snapshots`: browse/diff, restore a file (`undochange`), + and a root-config rollback, each behind the typed-`yes` gate. +- [ ] **Update awareness** — with `nomarchy.updates.enable`, let the timer + fire (or start the unit): indicator appears only when inputs are + behind, notification only on count growth, click opens the upgrade + flow. +- [ ] **VPN menu live paths** — import a real WireGuard `.conf` and an + `.ovpn` via System → VPN, toggle up/down (● / ○ state), and the + Tailscale block: up/down + exit-node without sudo (operator grant). +- [ ] **Printer menu** — with `nomarchy.services.printing`, System → + Printers opens system-config-printer; add a printer, test page. +- [ ] **GRUB UEFI ISO theme render** — boot the ISO on UEFI hardware: + composed splash background, palette menu in the lower third, accent + timeout bar. +- [ ] **Visual theme pass** — live ISO: all six identity themes (bars) + + the four authored rofi `.rasi` (nord/retro-82/lumon/kanagawa) look + right, not just parse. + +## AMD dev box only +- [ ] **AMD runtime bits** — VA-API (`vainfo` → radeonsi), amd-pstate EPP + active and PPD switching governors; opt-ins: ROCm (`rocminfo`, a GPU + PyTorch/Ollama smoke) and the XDNA NPU driver loading. +- [ ] **Fingerprint** — `fprintd-enroll` + (opt-in PAM) login/sudo. + +## Latitude 5410 only +- [ ] **Media keys + gestures** (from dccceb4) — volume/brightness keys + drive the OSD; touchpad gestures work. +- [ ] **v1 QA batch on-hardware pass** (583708d batch was QEMU-verified) — + general smoke before the next `main → v1` promotion. + +## T14s only +- [ ] **Webcam IR-hide end-to-end on Nomarchy** — installer detects the + RGB+IR pair, bakes `hardware.camera.hideIrSensor`; `wpctl status` + shows one colour source; an app picker lists one camera; Howdy-style + direct `/dev/video2` reads still work. diff --git a/agent/JOURNAL.md b/agent/JOURNAL.md new file mode 100644 index 0000000..2f1ce07 --- /dev/null +++ b/agent/JOURNAL.md @@ -0,0 +1,33 @@ +# 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 3–5 entries to orient. Keep an +entry under ~15 lines; durable lessons go to MEMORY.md, not here. + +Template: + +```markdown +## YYYY-MM-DD — () +- **Task:** which BACKLOG item (or QA sweep / bootstrap / escalation) +- **Did:** what changed, in 2–4 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-04 — Bootstrap the loop infrastructure (this commit) +- **Task:** create `agent/` (human-requested): LOOP/GOALS/BACKLOG/ + CONVENTIONS/MEMORY/HARDWARE-QUEUE/JOURNAL, root CLAUDE.md, README + + ROADMAP pointers. +- **Did:** reworked the forward half of docs/ROADMAP.md into the tiered + BACKLOG (5 NOW / 6 NEXT / LATER / Decisions); collected every pending + on-hardware check into HARDWARE-QUEUE.md; seeded MEMORY.md from the + ROADMAP's decision records. +- **Verified:** V0 (docs-only change; `nix flake check --no-build` run to + confirm the tree still evaluates). +- **Pending:** Bernardo to sanity-read GOALS.md pillars + BACKLOG tiering + — reorder freely, the order *is* the instruction. +- **Next suggestion:** BACKLOG NOW#1 (opt-in auto-commit — Phase 4 of + in-flake state, already the agreed next step). diff --git a/agent/LOOP.md b/agent/LOOP.md new file mode 100644 index 0000000..62af04b --- /dev/null +++ b/agent/LOOP.md @@ -0,0 +1,118 @@ +# The loop — autonomous iteration protocol + +How an AI agent works on Nomarchy unattended. One **iteration** = pick one +task, do it, verify it, commit it, record it. The protocol is +runner-agnostic; the same iteration works under any of: + +- **Interactive `/loop`** in a Claude Code session in this repo — the agent + self-paces iterations until stopped. +- **Headless** (`claude -p`, cron/systemd-timer) — one invocation runs one + iteration (or a small fixed number) and exits. +- **A fresh manual session** — a human says "do a loop iteration"; the + files below carry all the state, so any session can pick up where the + last left off. + +All loop state lives in this directory, git-tracked. There is no state +outside the checkout (the distro's own philosophy, applied to its agents). + +## The files + +| File | Role | Who writes it | +|---|---|---| +| `GOALS.md` | North star + quality bars + non-goals | Human (agents propose edits) | +| `BACKLOG.md` | Prioritized task queue (NOW/NEXT/LATER/PROPOSED/DECISIONS) | Both — see its header rules | +| `JOURNAL.md` | Append-only iteration log | Agents | +| `MEMORY.md` | Curated durable lessons/gotchas | Agents (curated, not append-only) | +| `HARDWARE-QUEUE.md` | Pending on-hardware checks only Bernardo can run | Agents append, human checks off | +| `CONVENTIONS.md` | Repo/design conventions to follow while coding | Human (agents propose edits) | + +## One iteration, step by step + +### 0. Orient +1. Read `GOALS.md`, `CONVENTIONS.md`, `MEMORY.md`, the **last 3–5 entries** + of `JOURNAL.md`, and `BACKLOG.md`. +2. `git pull --ff-only` (skip silently if offline). Confirm you are on + `main` with a clean tree. **A dirty tree you didn't create → stop and + report; never stash or discard someone else's work.** +3. Sanity baseline: if the last journal entry reports a red + `nix flake check`, or you have any reason to suspect breakage, run + `nix flake check --no-build` first. **A red baseline preempts the + backlog — fixing it *is* this iteration's task.** + +### 1. Pick exactly one task +- Take the **topmost actionable** item: NOW before NEXT; never LATER + unless NOW and NEXT are empty or all blocked. +- *Actionable* means: not `[blocked:hw]` (those wait in + `HARDWARE-QUEUE.md`), not `[human]` (decisions), and small enough to + finish + verify in one iteration. If the top item is too big, **split + it in BACKLOG.md** (that edit is part of the iteration) and take the + first slice. +- Never implement anything from **PROPOSED** — those await human triage. +- If nothing is actionable, do a **QA sweep** instead: run the full check + suite, hunt drift (README option tables vs the live `nomarchy.*` + surface, template drift, dead code), deepen a VM test, or research and + write up a PROPOSED item. An iteration that only improves the backlog + is a valid iteration. If even that yields nothing, journal it and stop + — do not manufacture churn. + +### 2. Work +- Keep the diff focused on the task. Unrelated fixes you trip over become + PROPOSED/NOW entries, not scope creep. +- Follow `CONVENTIONS.md`. Match the surrounding hand-formatting; never + run a formatter. +- New gotcha discovered the hard way → one line in `MEMORY.md` now, while + it's fresh. + +### 3. Verify — the ladder +Climb as high as the change warrants and your environment allows; **record +the tier reached** in the commit body and journal entry. + +| Tier | What | When required | +|---|---|---| +| **V0** | `nix flake check --no-build` (+ `bash -n` / `py_compile` for scripts) | Every change, no exceptions | +| **V1** | Build the touched output: `system.build.toplevel`, the HM generation, the ISO, or the package | Anything beyond docs/comments | +| **V2** | VM: a `checks.*` runNixOSTest (add one if the change is guardable), or boot `tools/test-live-iso.sh` / `tools/test-install.sh` | Behavioral changes — services, boot, installer, session | +| **V3** | Real hardware | Cannot be done by the agent → append to `HARDWARE-QUEUE.md` with exact test steps | + +The honesty rule governs: a visual/interactive change verified only to V1 +is **not done** — it ships as "V1-verified, V2/V3 pending" with the pending +check queued. Prefer *adding a permanent `checks.*` test* over a one-off +manual VM poke when the behavior is testable headlessly (see MEMORY.md for +the reusable recipes). + +### 4. Commit + push +- Style: match the log — `feat(scope): …`, `fix(scope): …`, + `test(scope): …`, `docs(scope): …`. Body explains what/why + the + verification tier reached and what remains. +- Include the `agent/` bookkeeping updates (backlog/journal/memory/queue) + **in the same commit** as the change they describe. +- Commit directly on `main` and `git push` (Bernardo's standing workflow). +- **Never:** force-push; touch the `v1` branch or any branch/tag you + didn't create; commit secrets or binaries; run `nix flake update` + unless the task is explicitly a lock bump; delete themes, wallpapers, + or user-facing assets without the backlog saying so. + +### 5. Record +1. Mark the task in `BACKLOG.md` (move to its ✓ line or delete, per that + file's rules). +2. Append a `JOURNAL.md` entry (template in that file). +3. Queue any V3 checks in `HARDWARE-QUEUE.md`. + +### 6. Pace (self-paced runners only) +Under `/loop`, continue to the next iteration while tasks remain +actionable and checks stay green. Stop the loop when: nothing is +actionable, the same task has failed twice (journal the failure analysis +and mark the item `[stuck]`), or a `[human]` decision blocks everything +remaining. + +## Stop-and-escalate conditions (any runner) + +Write a journal entry + a BACKLOG note, then stop, when: +- A fix would require touching `v1`, force-pushing, or a nixpkgs release + jump. +- The working tree contains uncommitted work you didn't create. +- A task turns out to need a design decision Bernardo hasn't made → move + it to **Decisions** in BACKLOG.md with the options laid out. +- Two consecutive iterations failed on the same task (`[stuck]`). +- Anything would delete or rewrite user data, git history, or the state + file schema in a non-backward-compatible way. diff --git a/agent/MEMORY.md b/agent/MEMORY.md new file mode 100644 index 0000000..3eea308 --- /dev/null +++ b/agent/MEMORY.md @@ -0,0 +1,60 @@ +# Memory — durable lessons, learned the hard way + +Curated, not append-only: one line per fact, newest at the top of its +section; delete entries that stop being true. Details usually live in a +docs/ROADMAP.md decision record — pointer given as (§ item). Add a fact +here the moment a debugging session teaches you something a future +iteration would otherwise rediscover. + +## Testing & VM recipes +- Reusable headless VM harness: `checks.*` via runNixOSTest — existing + examples to crib from: `distro-id` (boots + `switch-to-configuration + dry-activate`), `hardware-toggles` (kernel cmdline/PAM assertions), + `battery-charge-limit` (fake Mains adapter via `test_power`, real udev + uevent, `InvocationID` change proves the restart). +- Themed-desktop screenshots work headlessly: software-GL Hyprland + (`LIBGL_ALWAYS_SOFTWARE` on virtio-gpu) + `machine.screenshot()` QMP + dump — prototyped 2026-06-19, kept as the fallback for theme previews + (§ Visual theme picker). +- Hyprland/Ghostty need guest GL (`virtio-vga-gl`, `gl=on`) in + interactive QEMU or the session won't start; black screen ≈ missing GL + (docs/TESTING.md § gotchas). +- No KVM = slow, not broken; don't read slowness as failure. + +## Known-broken / watchlist +- **btrfs-assistant 2.2 segfaults on launch** (nixpkgs 26.05, + `libbtrfsutil.so.1.4.0` ABI mismatch; crashes on hardware too, not a VM + artifact). `nomarchy-snapshots` fzf flow is the shipped fallback; + re-check on every lock bump (§ Snapshot browse/restore; BACKLOG NOW#2). +- **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 write re-copies the source before eval — the wallpapers-artifact + split (BACKLOG LATER) is the decided fix (§ Faster switches). + +## Gotchas (cost a debugging session once) +- Never kill a Wayland session-lock client (hyprlock): its crash + failsafe drops to a tty instead of unlocking (§ Hibernate + double-unlock). +- rofi `element-icon size` is one value = a square cell; `WxH` silently + collapses and non-square icons letterbox — pre-crop images square at + build (§ Visual theme picker). +- WirePlumber 0.5 monitor rules can only early-match `device.api`; + `device.product.name` etc. bind *after* the rule runs — surgical + libcamera scoping is impossible (§ Webcam). +- `hyprctl switchxkblayout` is a *global* layout flip; per-device isolation + needs `device[]:kb_layout` keywords (§ Keyboard layouts). +- Waybar's clock captures the timezone at construction — a zone change + needs SIGUSR2 (watcher in `timezone.nix`) (§ Automatic timezone). +- Waybar `persistent_workspaces` (underscore) is dead syntax silently + ignored; the hyphen form is honoured and renders phantom workspaces + (§ Waybar shows non-existent workspaces). +- GTK4/libadwaita/Qt6 read light/dark from the portal's + `org.freedesktop.appearance color-scheme` (dconf), not Stylix polarity + (§ GTK/Qt ignore the theme's mode). +- Update order matters downstream: `sys-update` (lock) before + `home-update`, or desktop changes are silently skipped against the old + lock (README § 3). +- grub `loadfont`s every `.pf2` in a theme dir — reuse a bundled DejaVu + rather than shipping fonts (§ Distro branding). diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index e8ed14b..e3b55d1 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -5,6 +5,12 @@ Forward-looking plans, plus a running log of shipped fixes (the stays a focused entry point — what Nomarchy is, how to install it, and how to override it. Items marked ✓ are shipped. +> **The live, prioritized queue now lives in [`agent/BACKLOG.md`](../agent/BACKLOG.md)** +> (part of the autonomous-agent loop, `agent/LOOP.md`). This file remains +> the detailed design/decision record and the shipped log — backlog items +> reference it as "ROADMAP § ". When a backlog item ships, its +> lasting design notes get a ✓ entry here. + ## Roadmap - **Menu system** (apps launcher + theme switching + system actions), built on rofi 2.0 (native Wayland on 26.05) — its `.rasi` theme is baked from