Agent workflow: branch off main, rehearse on PRE, never act on PROD, tear PRE down #52
Labels
No labels
needs-info
needs-triage
ready-for-agent
ready-for-human
wontfix
needs-info
needs-triage
ready-for-agent
ready-for-human
review/merge-ready
review/needs-fix
review/needs-human
review/needs-review
wayfinder:grilling
wayfinder:map
wayfinder:prototype
wayfinder:research
wayfinder:task
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
olympus/infra-forge#52
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem Statement
The Operator works this repo with Agents.
AGENTS.mdanddocs/agents/say how an Agent reads the issue tracker and the domain docs, but nothing says how an Agent works: which branch to start from, where to work, what it may run, and what must not outlive the work. Four rules live in the Operator's head and in the git history:main;The rule that matters most — rehearse on PRE — is not reachable from the place an Agent works. A fresh worktree carries no gitignored secrets (
tofu/.env,tofu/npm/.env,ansible/.env,ansible/vault-pass) and no OpenTofu state, somake prerefuses at its first gate; and PRE's identity is fixed (vmid 142,10.12.0.142), so two Agents rehearsing at once would collide on the Node and on the shared base image. The convention cannot be followed even by an Agent that wants to follow it.Solution
Write the workflow down where Agents already look, and make the rules reachable.
docs/agents/workflow.md("How an Agent works in this repo"), states the four rules as prose and points at the runbook's PRE rehearsal for the procedure.make worktreeTarget makes rule 1 real: it creates a fresh worktree on a new branch offorigin/main, links the host-level secrets into it, gives it its own OpenTofu state copy, and gives its PRE its own identity — so a rehearsal from the worktree works, and two Agents can rehearse at once without colliding.PRODandPRE, andRehearsaljoins the glossary.User Stories
main, so that my change never rides on a stale base..env.PROD,PRE), so that no document, issue or commit drifts to "live" or "staging".Implementation Decisions
docs/agents/workflow.md, repo-only.AGENTS.mdgains a### Workflowpointer under## Agent skills;docs/wiki-pages.ymllists the new page underexclude(an unpublished doc that is neither published nor excluded is a coverage gap in that manifest).PROD,PRE, Guest, Stack, Service, Target, rehearsal, Operator, Agent).git fetch origin && git switch -c hermes/<issue>-<slug> origin/main, one branch per issue, in a worktree.prod,guest,edge,service,snapshot,state-backup) andssh; explicitly allow the read-only ones (guest-plan,edge-plan,service-check) andverify(which reads PROD from the WAN and writes only to a temp dir); a mutation on PROD needs the Operator's approval. The deploy model is stated plainly: merge is not deploy — after merge the Operator runsmake prodby hand, for now.inventories/prod|pre/hosts,group_vars/forgejo/*for PROD,host_vars/forgejo-pre.ymlfor PRE); no role or template may branch on environment (verified: none does today). A rehearsal covers the roles, the playbook, the templated config, the units and the package installs; it cannot cover the Edge, TLS, the WAN-published URL, the SSH stream or per-repo Actions (forgejo_actions_repos: []on PRE).make pre-down, then the PR. Evidence is one line per acceptance criterion / user story, not full logs.make worktreecreates the worktree (git worktree addunder.worktrees/), links the four gitignored secrets from the primary checkout (they are host-level, not per-branch), seeds the worktree's OpenTofu state copy, and records the worktree's PRE identity. A clean worktree missing those secrets cannot runmake pre; the Target creates the links.ip_config { ipv4 { address = "dhcp" } }with the gateway omitted, and novm_id(the provider assigns one;random_vm_ids = truein the provider block makes concurrent assignment collision-safe). PROD keepsvmid = 141and10.12.0.141pinned.ipv4map (per network device). The rehearsal reads it from the apply's state/output and writes a generated PRE inventory andhost_varsfor the worktree — PRE's host variables stop being a committed static file for rehearsal purposes.proxmox_download_file.debian_13_base, a node-level template pinned by checksum) is imported into each worktree's state, or resolved by aproxmox_filesdata-source lookup, so no worktree re-downloads it and none collides on it.make prodTarget,PROD_WORD := prod(the typed apply-gate word),PROD_INVENTORY,inventories/prod, the ADR 0004 slug, and lowercaseprodin commands all stay as they are. The glossary's PROD entry states this so nobody "fixes" them.GLOSSARY.mdgainsRehearsal(definition only, no procedure) and the PROD/PRE entries carry thePROD/PREspelling..forgejo/workflowsdoes not exist; issue #2 covers the first workflow). The eventual gate: an Agent writes tests that verify each acceptance criterion / user story, and CI runs them automatically.Testing Decisions
make pre), used at the highest point; no new seam is introduced.make worktreeTarget is verified bymake -n worktree(the composed commands) and one real run; the DHCP/vmid change is verified by the first PRE apply showing a distinct address and vmid from PROD's.make pre/make pre-downTargets and the runbook's PRE rehearsal section.Out of Scope
Further Notes
lesson-5-end-with-preprecedent survives only in an old PR title; the rule is written fresh here rather than cited.