Files
Nomarchy/agent/CONVENTIONS.md
Bernardo Magri 6d70bba8e6 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>
2026-07-04 08:51:11 +01:00

3.6 KiB
Raw Blame History

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 writeShellScriptBins 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 (V0V3) 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.