AGENTS.md: add 'minimize ongoing liability' as a first principle

The always-on rules are concretizations of a broader engineering posture
that wasn't stated explicitly. Add a short section that frames the spirit
behind those rules:

- One centralized detection point, not many heal hooks.
- One dispatcher, not branch-on-shape in every consumer.
- One canonical shape after migration, not forks on "old vs new".
- Three similar lines beats a premature abstraction.
- Delete dead paths when their last caller leaves.

Plus a forward-looking review prompt ("what do these paths look like after
5 more changes like this?") so the principle bites at design time, not
just at review time.

The internal-schema-version mechanism we just shipped is a concrete
application: one stamp + one dispatcher + one match arm per change, no
heal hooks scattered across the engine. Codify the pattern so future
work doesn't drift back to ad-hoc.
This commit is contained in:
Claude 2026-04-29 11:48:47 +00:00
parent 243c0c3464
commit b6a596670a
No known key found for this signature in database

View file

@ -96,6 +96,20 @@ Full diagram and concurrency model: [docs/architecture.md](docs/architecture.md)
---
## First principle: minimize ongoing liability
Every line of code, every conditional, every doc paragraph is a future maintenance cost. Pick patterns that contain the cost in *one* place, not scattered across many.
- **One centralized detection point**, not heal hooks in every code path.
- **One dispatcher / `match`-arm step**, not branch-on-shape in every consumer.
- **One canonical shape after migration**, not forks on "old vs new" forever.
- **Three similar lines** beats a premature abstraction. **A hypothetical future requirement** isn't a real one.
- **Delete dead paths** when their last caller leaves. Don't keep them around as a "just in case".
When evaluating a design, ask: *"what do these paths look like after 5 more changes like this?"* If the answer is "they fork everywhere", pick a shape that converges instead. The always-on rules below and the §IX deny-list in [docs/invariants.md](docs/invariants.md) are specific applications of this principle; when the rules are silent, fall back to it.
---
## Always-on rules (load these into your working memory)
These are architectural rules that need to be in scope on every change. They're framed at the level that survives renames and refactors — the deeper implementation specifics (function names, lock names, branch-prefix conventions, enforcement points) live in the per-area docs and may evolve. The full architectural invariants and deny-list are in [docs/invariants.md](docs/invariants.md); §IX (deny-list) is the fastest first-pass when reviewing any change.