# AGENTS.md — Prose Contracts Repo All agents operating on prose contracts MUST follow this workflow. No exceptions. ## The Rule **No agent pushes directly to `main`. All changes go through PRs with automated validation.** ## Why Two incidents taught us this: 1. **The .117→.19 IP fix** — A stale IP in a contract was "fixed" without verification, breaking Zulip. The fix was right but the approach was wrong. Automated consistency checks would have caught it. 2. **The /grafana/ route regression** — An nginx route that was deliberately removed (Jul 2) was re-added to a contract diagram. CI linting now catches this automatically. ## Agent Workflow ``` ┌─────────────────────────────────────────────────────────┐ │ 1. Clone repo → create branch → make changes │ │ 2. Push branch → open PR │ │ 3. CI pipeline runs automatically: │ │ ✅ validate: frontmatter (kind, name, description) │ │ ✅ lint: structure + regression detection │ │ ✅ ai-review: LiteLLM reviews diff vs ground truth │ │ 4. All green → merge PR to main │ │ 5. Agents run contracts from main │ └─────────────────────────────────────────────────────────┘ ``` ## Branch Protection (enforced by Gitea) | Rule | Enforcement | |------|------------| | Direct push to `main` | ❌ Blocked (except abiba-bot for emergencies) | | PR merge without passing CI | ❌ Blocked — all 3 checks must be green | | Status check contexts | `pr-pipeline / validate`, `pr-pipeline / lint`, `pr-pipeline / ai-review` | ## What the CI checks for ### Stage 1 — Validate - YAML frontmatter is valid (proper `---` delimiters) - `kind` field is one of: `function`, `responsibility`, `gateway`, `pattern`, `test`, `template` - `name` and `description` fields are present ### Stage 2 — Lint - Responsibility contracts have `## Maintains` - Function contracts have `## Parameters` and `## Returns` - **Regression rules (automatic rejection):** - `/grafana/` nginx route — was reverted Jul 2, must not reappear - `CT 122` or `CT 123` as CT ID labels — don't exist in the cluster - These rules are hardcoded in `scripts/prose-lint.sh` ### Stage 3 — AI Review - Diff is sent to `syslog-auto` model via LiteLLM - Review checks against infrastructure-control ground truth: - CT IDs match PVE cluster (100-117, no 122/123) - Grafana is direct LAN :3001, NOT behind nginx - Zulip is CT 117 on storepve (bridge IP .19) - Strix Halo :8080 is firewalled to .116 only - Review is posted to the PR ## Authorization ### Who can change what | Contract | Sensitivity | Who can change | |----------|------------|----------------| | `infrastructure-control.prose.md` | **CRITICAL** — topology source of truth | Abiba only (after live verification) | | `proxmox-monitor.prose.md` | **CRITICAL** — deployed monitoring | Abiba only | | `hermes-config-template.prose.md` | **HIGH** — all agent configs | Abiba, Mumuni, Tanko | | `zulip-health.prose.md` | **HIGH** — agent communication | Abiba, Mumuni | | Other contracts | Normal | Any registered agent | | `scripts/*.sh` | **HIGH** — runtime scripts | Abiba only | ### Enforcement (self-policing) The CI does not block based on author identity today (Gitea doesn't support CODEOWNERS natively). Instead, agents self-enforce: 1. Before changing a CRITICAL contract, check with Abiba 2. If you're unsure, tag `@abiba-bot` in the PR description 3. Abiba reviews CRITICAL contract changes before merge ## Emergency Bypass In an emergency (service down, fix must ship immediately): 1. Push to a branch 2. Open PR with `[EMERGENCY]` in the title 3. CI still runs — but if it fails and the fix is verified, abiba-bot can bypass and push directly to main 4. Post-incident: open a follow-up PR to fix any CI violations ## Quick Start ```bash # Clone git clone https://git.sysloggh.net/SyslogSolution/prose-contracts.git cd prose-contracts # Create branch git checkout -b fix/my-change # Make changes, test locally bash scripts/prose-lint.sh # run lint locally before pushing # Push and open PR git add -A git commit -m "fix: description of change" git push origin fix/my-change # Open PR at https://git.sysloggh.net/SyslogSolution/prose-contracts/pulls # CI runs automatically — wait for all checks to pass # Merge when green ``` ## Verification Before Acting **Contracts are leads, not facts.** Live-state fields (IPs, ports, credentials) drift. Before acting on any value from a contract, verify it against the live system. Follow the `verify-before-mutate` protocol: ```bash safe-mutate --verify "CMD" [--expect "PATTERN"] --mutate "CMD" [--reason "WHY"] ``` ## Writing New Contracts Read the [Authoring Guide](docs/AUTHORING-GUIDE.md) before writing any new contract. It covers the full process: verify → draft → lint → review → ship, with templates and style rules.