diff --git a/AGENTS.md b/AGENTS.md index bad976d..052e732 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,20 +3,27 @@ Guidance for AI agents and contributors working in this repo. Read `README.md` for commands and layout. -## Maintaining this file +## Prose discipline -Every agent session reads this file in full, so its length is a cost paid on every task. -Keep it the shortest thing that still changes what someone does. +Every word in this repo is read again on every future task, so prose is a recurring cost. On **any** +change, sweep the prose you touched — this file, `README.md`, the example READMEs, and code +comments — and cut it back to what a competent reader could not infer: -- **Trim as you add.** After any edit, re-read the whole file and compress: merge overlapping - entries, cut prose that restates a rule, drop what the code or `README.md` already says. - Question each section — same information, fewer words. -- **Record the decision and the reason it turns on, nothing else.** Not the investigation, not - what was tried first, not how it was verified — that belongs in the PR that made the change. +- **Delete history.** Git holds it. No "this moved from X", "used to be Y", "was tried and + rejected", "(declined twice)", dated changelog entries, or the symptom that prompted a fix. Record + the decision and the reason it *currently* turns on, nothing else. +- **Delete restatement.** A comment that says what the adjacent line says, a doc paragraph that + re-explains a table above it, a file-map entry that expands the filename. The fix is deletion, + not trimming. +- **Delete the self-evident** and anything already stated once elsewhere. **One home per fact** — + link to it instead of repeating it; the same sentence in five files is five chances to drift. - **Give every accepted risk an expiry** ("valid while X"), and delete the entry once X stops holding. -- **One home per fact.** Link to it rather than restating it — the same sentence in five files - is five things to update and five chances to drift. +- **Keep** the surprising why, the footgun, the invariant, the external constraint, and the one-time + setup a reader cannot dig out of the code. Once a line has earned its place, make it short and + information-dense. + +Trimming is not a separate task to schedule — do it in the same change, every time. ## How to work with tasks @@ -31,29 +38,23 @@ branch, create a PR and merge it when the CI/CD turns green. 1. **Simplicity** — prefer the solution that is easiest to understand, smallest, and most readable. 2. **Few dependencies** — runtime deps stay minimal (today `ejs`, `lucide-static`, `@larvit/log`). Prefer the Node standard library; justify any new dependency; do not add frameworks. The app is - **stateless — no database**. Auth/identity/OAuth are **Ory sidecar services** (Kratos/Keto/Hydra, - backed by Postgres), reached over their REST APIs with built-in `fetch` — no SDK. New - capabilities ship as **plugin folders** under `plugins/` that fetch their data from upstream - services, not as core code. + **stateless — no database**. Auth/identity/OAuth are **Ory sidecar services** reached over their + REST APIs with built-in `fetch` — no SDK. New capabilities ship as **plugin folders** under + `plugins/` that fetch their data from upstream services, not as core code. 3. **Strict TypeScript** — `tsconfig.json` is strict (incl. `noUncheckedIndexedAccess`, `exactOptionalPropertyTypes`, `verbatimModuleSyntax`). Keep it that way. Prefer exact types; limit nullable and multi-option types. -4. **Environment-agnostic** — the app never asks *which environment* it runs in; no `NODE_ENV` - branching. Every behaviour is an **explicit config toggle** (e.g. `CACHE_TEMPLATES`, - `REQUIRE_SECURE_SECRETS`), read once in `src/config.ts`. Compose files set them per deployment. -5. **Semantic, accessible DOM** — use the right element for the job (landmarks, one `