feat(agent): autonomous-loop infrastructure + roadmap rework
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 <noreply@anthropic.com>
This commit is contained in:
25
CLAUDE.md
Normal file
25
CLAUDE.md
Normal file
@@ -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/`.
|
||||||
13
README.md
13
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
|
├── templates/downstream/ # `nix flake init -t` starter for users
|
||||||
├── docs/TESTING.md # how to verify changes (incl. AI-agent rules)
|
├── docs/TESTING.md # how to verify changes (incl. AI-agent rules)
|
||||||
├── docs/OVERRIDES.md # how downstream users override defaults
|
├── 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
|
└── tools/ # maintainer-only
|
||||||
├── import-palettes.py # converts old-distro themes → JSON + assets
|
├── import-palettes.py # converts old-distro themes → JSON + assets
|
||||||
├── test-live-iso.sh # build the ISO + boot it in QEMU
|
├── test-live-iso.sh # build the ISO + boot it in QEMU
|
||||||
@@ -395,6 +397,9 @@ reload # exec zsh (reload the shell)
|
|||||||
|
|
||||||
## Roadmap & known issues
|
## Roadmap & known issues
|
||||||
|
|
||||||
See **[docs/ROADMAP.md](docs/ROADMAP.md)** — forward-looking plans plus the
|
The prioritized queue of what's next lives in
|
||||||
log of shipped fixes. Kept out of the README so this stays a focused entry
|
**[agent/BACKLOG.md](agent/BACKLOG.md)**; the detailed design/decision
|
||||||
point.
|
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.
|
||||||
|
|||||||
142
agent/BACKLOG.md
Normal file
142
agent/BACKLOG.md
Normal file
@@ -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 § <item>"); 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".
|
||||||
70
agent/CONVENTIONS.md
Normal file
70
agent/CONVENTIONS.md
Normal file
@@ -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+<mnemonic>` 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.
|
||||||
58
agent/GOALS.md
Normal file
58
agent/GOALS.md
Normal file
@@ -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+<mnemonic>` 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.
|
||||||
63
agent/HARDWARE-QUEUE.md
Normal file
63
agent/HARDWARE-QUEUE.md
Normal file
@@ -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.
|
||||||
33
agent/JOURNAL.md
Normal file
33
agent/JOURNAL.md
Normal file
@@ -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 title> (<commit sha, or "no commit">)
|
||||||
|
- **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).
|
||||||
118
agent/LOOP.md
Normal file
118
agent/LOOP.md
Normal file
@@ -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.
|
||||||
60
agent/MEMORY.md
Normal file
60
agent/MEMORY.md
Normal file
@@ -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[<name>]: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).
|
||||||
@@ -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
|
stays a focused entry point — what Nomarchy is, how to install it, and
|
||||||
how to override it. Items marked ✓ are shipped.
|
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 § <item>". When a backlog item ships, its
|
||||||
|
> lasting design notes get a ✓ entry here.
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
- **Menu system** (apps launcher + theme switching + system actions), built
|
- **Menu system** (apps launcher + theme switching + system actions), built
|
||||||
on rofi 2.0 (native Wayland on 26.05) — its `.rasi` theme is baked from
|
on rofi 2.0 (native Wayland on 26.05) — its `.rasi` theme is baked from
|
||||||
|
|||||||
Reference in New Issue
Block a user