Files
felhom-controller/.claude/rules/agent-coupling.md
T
admin 7db42c5fec
gates / gates (push) Successful in 12s
docs: CLAUDE.md becomes a core plus path-scoped rules (R-229)
215 lines -> 110 (92 effective; block-level HTML comments are stripped before
injection and never reach the model, verified empirically on Claude Code 2.1.222
with a control and a treatment run).

Four new .claude/rules/*.md, each with a paths: glob list so it loads only when a
matching file is read: gates, ui-hungarian, backup-paths, agent-coupling.

The ## Layout tree was deleted as derivable; REUSE.md already owns the per-package
seams its annotations stood in for. The host/access table was deleted in favour of
a pointer to documentation/operations/nodes.md -- it carried three defects at once:
demo-felhom given as the LAN fallback address as if it were the route, a pinned
"agent 0.93.0" against the project's own no-versions-in-docs rule, and the claim
that no drill VM was provisioned on demo-hp. Measured live: qm list shows VM 300
drill-r50. felhom-agent/CLAUDE.md was right; this file was wrong.

Kept verbatim: the seven session-critical invariants, the F9 live-validation fence,
the end-of-session checklist.

controller_gates.py registers the shared instructions gate (felhom.eu/scripts/,
never copied here; an absent sibling clone FAILS).

Docs only -- no Go, no version bump, no image, no deploy.
Ledger: felhom.eu/documentation/audits/LEDGER-instruction-trim-2026-08-06.md

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJc8sAGRWmavP3rMtdpkr2
2026-08-06 09:38:27 +02:00

44 lines
2.1 KiB
Markdown

---
paths: ["controller/internal/agentapi/**"]
---
# Coupling to the host agent — felhom-controller
`internal/agentapi` is **the disk seam**: the pinned-TLS client to the host agent's per-guest local
API. The controller holds no Proxmox credentials; everything disk/host/Proxmox goes through here.
## Declaring a coupled feature
Controller behaviour that depends on a specific agent version needs **all three**, or it ships broken
on an older box:
1. a `featureProbes` table row in `internal/agentapi/features.go`
2. a `Supports` gate call **at the feature's entry point** — not somewhere on the path to it
3. `MinAgent: X.Y.Z` in the CHANGELOG entry header
Rules: `felhom.eu/documentation/runbooks/publish-train-rules.md`.
## Never push a controller past the agent it depends on
The R-216 guard compared the box's agent against the **golden's** MinAgent while serving a **floor**
that could point elsewhere. Raise a floor above the vouched golden — which the day-0 runbook
recommends and a per-customer override makes trivial — and the guard checks a version it is not
serving. A box then landed on a controller needing a newer agent, and its customer was told a correct
recovery code was wrong.
**A floor above the vouched golden is HELD, with its own reason** (hub v0.97.0).
## Distinguish "could not reach" from "wrong answer"
A failed bundle FETCH must not be reported to a customer as a bad recovery code. Classify by **value**
(`ErrBundleFetch` → HTTP 502), never by error string — a string is not something a caller can branch
on. Unknown class → neutral message, never the typing message.
<!--
R-224, measured live 2026-08-05 (CAMPAIGN-11 F3/F4) with a correct current code: 0.0556 s with the
hub firewalled off and 0.0299 s with the agent stopped, against ~1.0 s for a genuine unseal — the
machine accused the customer of something it had not attempted. A green test named this exact
consequence since v0.125.0 and did not prevent it, because it asserted this package's error STRING
one layer below where the merge happened. Fixed agent v0.126.0 + controller v0.202.0.
-->