Files
Nomarchy/agent/LOOP.md
Bernardo Magri 02d7baeb7c
All checks were successful
Check / eval (push) Successful in 3m7s
docs: VISION for v1.0 + clarify docs/ vs agent/ vs .claude
Add docs/VISION.md (product themes, v1.0 bar, agent slice hints) and
README maps under docs/ and agent/. Point ROADMAP, BACKLOG, LOOP,
CLAUDE, HARDWARE, and the root README at the split: VISION = intent,
BACKLOG = executable queue, ROADMAP = design history, .claude = harness
only. Mark v1.0 track in BACKLOG PROPOSED for human triage.
2026-07-09 09:33:51 +01:00

7.8 KiB
Raw Blame History

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)

Model & token economy

Spend expensive tokens on judgment, not mechanics.

  • Plan and reason on the strong model. Orientation, task selection, design, debugging, Nix eval semantics, verification judgment, and anything that would land in a commit unreviewed stay with the top-tier model running the loop (Fable 5).
  • Delegate mechanical subtasks to cheaper models. When a subtask is fully specified and needs no design judgment — grep/audit sweeps, README-option-table reconciliation, a repeated edit applied across files, summarizing long logs or check output — hand it to a subagent with a model override: haiku for search/summarize/audit, sonnet for routine well-specified edits. The strong model writes the spec, reviews the result, and owns the commit. Only delegate when writing the spec is cheaper than doing the work — a spawned agent starts cold and must re-derive context.
  • Read narrowly. Step 0's list is the whole orientation read (the last 35 entries of the journal, never the full file). Read large files by section, don't re-read what's already in context, and tail build/check logs instead of dumping them.
  • Write tersely. Journal entries follow the template and no more; commit bodies state what/why/tier, not a narrative.
  • Headless runners may run whole low-stakes iterations (QA sweeps, docs-drift passes) on a cheaper --model; iterations touching modules/ or pkgs/ behavior keep the strong model.

One iteration, step by step

0. Orient

  1. Read GOALS.md, CONVENTIONS.md, MEMORY.md, the last 35 entries of JOURNAL.md, and BACKLOG.md. If the top task is product-shaped (UX, release bar, day-2 confidence), also read the matching section of docs/VISION.md — do not invent work from VISION; only execute BACKLOG items. Map of docs vs agent state: docs/README.md, agent/README.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.
  • Mechanical, fully-specified sub-steps go to a cheaper model (see Model & token economy above); design and review stay here.
  • 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.