A decision records why you chose something. It’s searchable. It’s surfaced in sync. It has no enforcement teeth. That’s deliberate — most architectural decisions are soft guidance.
Conventions are Enforceable
A convention is a team rule with a tier:
| Tier | Behavior |
|---|
must | Hard gate on PreToolUse — edits to matching files are blocked until the convention is superseded or marked stale. |
should | Surfaced as advisory context in sync. Agents see it, but writes aren’t blocked. |
may | Recorded for awareness. No UI intrusion. |
Create conventions with convention_propose. Discover the ones that will gate you with convention_list.
Decisions are cheap and plentiful — agents should record dozens per week. Conventions are load-bearing and rare — a few per quarter for “must” tier, more for “should”. Keeping them separate keeps every decide call low-stakes while giving the team a real escalation path when a pattern needs enforcement.
If you find yourself re-recording the same decision in multiple sessions (“please use zod for validation”), convert it into a must-tier convention so the next violation is blocked at write time, not review time.
Staleness
Every decision auto-links to the symbols it mentions. When those symbols change in git, Enagrams marks the decision stale.
decisions_stale lists them
decision_reaffirm marks them fresh again (when the decision still holds)
- Recording a new decision with the same title (or an explicit
supersedes link in the web UI) ends the stale one
This matters because architectural context drifts silently. A decision from March (“we chose React Query over SWR”) becomes misleading in November if the team migrated to TanStack — but only if you notice. Staleness detection makes that drift visible automatically.
Scope
affected_files accepts globs. Keep them narrow:
- Good:
src/routes/**/*.ts (all API routes)
- Too broad:
**/*.ts (whole codebase — every edit will hit this convention)
Broad must conventions produce angry teammates.