Architecture Decision Records as the Backbone of Vibe Engineering


When I started building Sol, I made a decision early that paid off more than almost any technical choice: every significant architectural decision would get a written record before implementation began.
37 ADRs later, those records aren't just documentation. They're the reason Sol works. They're the context layer that allows 30 AI coding agents to make consistent architectural decisions without a human reviewing every line. And they've fundamentally changed how I think about building software with AI.
What is an ADR?
An Architecture Decision Record captures a single architectural decision: the context that prompted it, the options you considered, the choice you made, and the consequences you expect. The format I use is lightweight MADR (Markdown Any Decision Records):
# ADR-0001: Sentinel as Go Process with Targeted AI Call-outs
Status: accepted
Date: 2026-01-15
## Context
Sol needs 24/7 health monitoring for agent sessions, but only
about 5% of monitoring decisions require actual judgment. Running
a full AI session for monitoring would burn API costs on routine
patrols that are 95% deterministic.
## Options Considered
1. Full Claude session as sentinel (always-on AI)
2. Pure Go process (no AI, heuristics only)
3. Go process with targeted AI call-outs (hybrid)
## Decision
Option 3. The sentinel runs as a Go process handling routine
patrols (heartbeat checks, output hashing, idle reaping). When
a heuristic triggers (unchanged output hash across two patrol
cycles), it fires a targeted AI assessment via `claude -p` to
determine if the agent is genuinely stuck.
## Consequences
**Benefits:**
- Patrol cost is near-zero for normal operation
- AI costs proportional to actual problems (~few calls per hour)
- Go process is deterministic, testable, restartable
**Tradeoffs:**
- Two-patrol-cycle detection latency (~6 minutes minimum)
- AI assessment quality depends on prompt engineeringThat's it. No formal governance process. No committee approval. Just a markdown file in docs/decisions/ with a sequential number, committed to the repo alongside the code it describes.
Why ADRs matter for AI-assisted development
Here's where it gets interesting. When you're writing code yourself, architectural decisions live in your head. You know why the forge is a Go process instead of a Claude session because you made that call last Tuesday. The context is implicit.
When AI agents are writing your code, that implicit context doesn't exist. Each agent session starts fresh. It can read the codebase, but it can't read your mind. Without ADRs, you get agents that:
- Reintroduce patterns you already rejected
- Build components that duplicate existing functionality
- Make local optimizations that violate global constraints
- Solve the same problem three different ways across different sessions
With ADRs, every agent session can read docs/decisions/ and understand not just what the architecture is, but why. That "why" is what prevents an agent from "improving" the forge by turning it into a long-running Claude session, when you already tried that approach, learned it drifts and wastes API costs on polling, and deliberately moved away from it.
The supersession chain: teaching through evolution
The most valuable thing about Sol's ADRs isn't any single record. It's the supersession chains that show how decisions evolved.
The forge component went through five architectures:
- ADR-0002: Pure Go process. Cheap and deterministic, but couldn't handle merge conflicts that required judgment.
- ADR-0005: Full Claude session with Go toolbox. Could resolve conflicts, but the session drifted, compacted context, and burned API tokens polling for work.
- ADR-0017: Workflow-constrained Claude session. More structured, but still too rigid for the variety of merge scenarios.
- ADR-0027: Back to deterministic Go. Gave up on AI judgment in the merge loop. Cheap, but conflicts had to be dispatched to outpost agents, adding minutes of wall time per conflict.
- ADR-0028: Go orchestration shell with ephemeral Claude sessions. Go handles the queue, claims MRs, and owns all state transitions. For each claimed MR, it starts a fresh Claude session that handles the full merge execution: syncing, merging, resolving conflicts inline, running quality gates, and pushing. The session reports its result via a
.forge-result.jsonfile, then Go reads the file and records the outcome. No session survives between merges. No drift, no context rot, no idle polling.
An AI agent reading this chain learns the core pattern: separate orchestration (mechanical, always-on) from judgment (expensive, ephemeral). It didn't take 5 tries because the team was indecisive. Each architecture revealed something about the problem that the previous one couldn't.
When I point a new agent at a Sol component and it can read this history, it doesn't just know what to build. It knows what not to build, and why.
ADRs as agent context
In Sol's CLAUDE.md (the file that configures AI agent behavior), there's a simple instruction:
Architectural decisions get an ADR in
docs/decisions/. ADR format: lightweight MADR. Context, Options Considered (when warranted), Decision, Consequences.
This does two things. First, it tells agents where to find architectural context before making implementation decisions. Second, it tells them to write new ADRs when they make architectural choices of their own. The ADR corpus grows as the codebase grows, and future agents benefit from the accumulated context.
A concrete example: ADR-0023 (Unified Agent Startup) was written after a bug where a respawned agent inherited the wrong Claude configuration directory. The ADR doesn't just document the fix. It documents the 9-step startup sequence, which roles register where, and the Go registry pattern used. Any agent working on startup code reads this ADR and knows exactly how the system fits together, because a previous session wrote it down.
Practical patterns I've found
After 37 ADRs, some patterns have emerged:
Lead with the problem, not the solution. The Context section should make the reader feel the pain. "We need a merge queue" is weak. "Agents push to isolated branches but nothing lands on main without quality gates, and manual merging of 30 branches per day is not sustainable" is strong. When an AI agent reads this, it understands the constraint, not just the requirement.
Include what you rejected and why. The Options Considered section is where the real value lives. An agent that sees "we considered a database-backed tether but rejected it because it violates the CRASH principle (tether must survive database failure)" won't propose database-backed tethers in the future.
Name your patterns. Sol's ADRs coined several internal patterns: "deterministic Go + targeted AI" for processes that are mostly mechanical with occasional judgment, "CRASH principle" for crash recovery as a first-class requirement, "GLASS principle" for everything inspectable with unix tools. Once a pattern has a name, agents can reference it. "This follows the deterministic-plus-targeted-AI pattern from ADR-0001" is a sentence that collapses paragraphs of context into a shared concept.
Keep them small. Each ADR covers one decision. If you're writing an ADR that covers three decisions, write three ADRs. Cross-reference them. Small ADRs are easier to read, easier to reference, and easier for AI agents to process without hitting context limits.
Track supersession explicitly. When a decision is revised, don't edit the old ADR. Write a new one that references it. The old record is valuable history. ADR-0005 being superseded by ADR-0027 tells a story about what was learned. Editing ADR-0005 to say something different would erase that learning.
The vibe engineering connection
"Vibe engineering" is a term that gets thrown around loosely, but at its core it means using AI agents to build software at a pace and scale that wasn't previously possible. The challenge is that speed without coherence produces chaos.
ADRs are the coherence layer. They're lightweight enough that they don't slow you down (a good ADR takes 10 minutes to write), persistent enough that they survive across sessions and agents, and structured enough that AI can parse and apply them reliably.
When I commission 30 agents to work on Sol, each one reads the same docs/decisions/ directory. They all share the same architectural context. They all know why the forge uses ephemeral sessions instead of a persistent one. They all know the CRASH principle means state must survive process death. They all know that "deterministic Go + targeted AI" is the default pattern for background processes.
That shared context is what turns 30 independent AI sessions into a coordinated team. The ADRs are, in a very real sense, the management layer. They encode the architectural decisions that a human tech lead would normally communicate through code reviews, design discussions, and institutional knowledge. Except they scale to 30 agents without the tech lead becoming a bottleneck.
Getting started
You don't need 37 ADRs to benefit. Start with one. The next time you make an architectural choice that has meaningful tradeoffs, write it down in the MADR format. Put it in docs/decisions/0001-your-decision.md. Reference it in your CLAUDE.md or README.
The first few feel like overhead. By the tenth, you'll notice that you're making better decisions because the act of writing forces clarity. By the twentieth, you'll notice that your AI agents are making better decisions because they have context you never had to repeat.
That's the real payoff. Not documentation for its own sake, but a growing body of architectural knowledge that compounds over time, whether the reader is human or AI.