forked from cleveragents/cleveragents-core
178 lines
15 KiB
Markdown
178 lines
15 KiB
Markdown
# Architecture Decision Records
|
||
|
||
This directory contains the Architecture Decision Records (ADRs) for CleverAgents. Each ADR captures a single significant architectural decision — the context that motivated it, the decision itself, its design implications, constraints, consequences, and how compliance is verified.
|
||
|
||
The [CleverAgents Specification](../specification.md) evolves from ADRs, which is the sole source of truth for the system's architecture and behavior. An ADRs acceptance ultimately results in rewriting the specification to incorperate the new architectural decision. Architectural changes to the specification should only be possible through the introduction of new ADR.
|
||
|
||
## What Is an ADR?
|
||
|
||
An Architecture Decision Record is a short document that records a significant architectural choice along with the context and consequences of that choice. ADRs provide a decision log that helps current and future contributors understand *why* the system is shaped the way it is — not just *what* was built, but the reasoning, trade-offs, and alternatives that led to each decision.
|
||
|
||
## Front-Matter
|
||
|
||
Every ADR begins with a YAML front-matter block that provides structured metadata. This metadata drives the rendered header, status timeline, and the inventory tables below. The front-matter fields are:
|
||
|
||
| Field | Type | Required | Description |
|
||
|-------|------|----------|-------------|
|
||
| `adr_number` | integer | yes | Sequential ADR identifier (e.g., `1`, `42`). Used to generate the page title as `ADR-NNN: <title>`. |
|
||
| `title` | string | yes | Human-readable title. Combined with `adr_number` to produce the H1 heading automatically — do **not** add an `# H1` line in the markdown body. |
|
||
| `status_history` | list | yes | Chronological list of status transitions. Each entry is a tuple of `[date, status]` or `[date, status, person(s)]`. See [Status Lifecycle](#status-lifecycle) for valid statuses. |
|
||
| `tier` | integer | yes | Architectural tier (1–4). See [Tier System](#tier-system). |
|
||
| `authors` | list of strings | no | Contributors who authored or substantially edited the ADR. |
|
||
| `superseded_by` | integer | no | ADR number of the decision that replaces this one. Only meaningful when the current status is `Superseded`. Renders as a link in the page header. |
|
||
| `related_adrs` | list of objects | no | Cross-references to other ADRs. Each entry has `number` (int), `title` (string), and `relationship` (string). The build system generates the Related ADRs table from this data. |
|
||
| `acceptance` | object | no | Governance voting record. Contains `votes_for`, `votes_against`, and `abstentions` — each a list of objects with `voter` (string) and `comment` (string). The build system generates the Acceptance section from this data. |
|
||
|
||
Example front-matter:
|
||
|
||
```yaml
|
||
---
|
||
adr_number: 17
|
||
title: "Automation Profiles"
|
||
status_history:
|
||
- ["2026-02-16", "Draft", "Jeffrey Phillips Freeman"]
|
||
- ["2026-02-16", "Proposed", "Jeffrey Phillips Freeman"]
|
||
- ["2026-02-16", "Accepted", "Jeffrey Phillips Freeman"]
|
||
tier: 3
|
||
authors: ["Jeffrey Phillips Freeman"]
|
||
superseded_by:
|
||
related_adrs:
|
||
- number: 6
|
||
title: "Plan Lifecycle"
|
||
relationship: "Profiles control which lifecycle phase transitions require human approval"
|
||
- number: 7
|
||
title: "Decision Tree and Correction"
|
||
relationship: "Confidence thresholds determine which decisions require human intervention"
|
||
acceptance:
|
||
votes_for:
|
||
- voter: "Jeffrey Phillips Freeman <Jeffrey.Freeman@CleverThis.com>"
|
||
comment: "Named profiles with confidence thresholds provide a clean spectrum from full manual to full autonomous control"
|
||
votes_against: []
|
||
abstentions: []
|
||
---
|
||
```
|
||
|
||
The build system reads this front-matter to automatically generate:
|
||
|
||
- The page **H1 title** (e.g., "ADR-017: Automation Profiles")
|
||
- A **subtitle header** showing tier, drafted date, current status with date, and authors
|
||
- A **status timeline** in the sidebar (desktop) or at the end of the article (mobile)
|
||
- The **Related ADRs** table with links, titles, and relationship descriptions
|
||
- The **Acceptance** section with voting tallies
|
||
- The **inventory tables** on this page
|
||
|
||
## Status Lifecycle
|
||
|
||
Each ADR progresses through a lifecycle tracked by the `status_history` front-matter field. The following diagram shows the valid state transitions:
|
||
|
||

|
||
|
||
The following statuses are recognized:
|
||
|
||
| Status | Meaning | What may change |
|
||
|--------|---------|-----------------|
|
||
| **Draft** | The ADR is being written. It captures initial thinking but has not yet been formally proposed for review. Draft ADRs may be incomplete or contain open questions. | Everything. All content sections, front-matter fields, and structural decisions are open for revision. The only field that must not change is `adr_number`. |
|
||
| **Proposed** | The ADR is content-complete and has been submitted for review and voting. Reviewers evaluate the decision, its rationale, and its design. Discussion may surface clarifications, but the substantive content should be stable. | Content is mostly frozen. Only metadata changes are expected: votes are recorded in `acceptance`, minor wording clarifications may be applied, and `status_history` is updated. A Proposed ADR must resolve to either **Accepted** or **Rejected** — it cannot move back to Draft or skip to any other status. |
|
||
| **Accepted** | The ADR has been reviewed, voted on, and approved. It represents a binding architectural commitment that the project will follow. Implementation should conform to what the ADR specifies. | The ADR is immutable in substance. Only `related_adrs` may be updated as new ADRs are added that reference this one. If the decision needs material change, a new ADR should supersede it rather than editing the accepted text. |
|
||
| **Rejected** | The ADR was proposed but not accepted after review. The reasoning is preserved for historical reference so the same ground is not relitigated without new information. | The ADR is immutable. It remains in the record as evidence that the option was considered and declined. |
|
||
| **Superseded** | A previously accepted ADR that has been replaced by a newer decision. The `superseded_by` field links to the replacing ADR. The original remains in the record for historical context. | Only the `superseded_by` field and `status_history` are updated when this transition occurs. |
|
||
| **Deprecated** | A previously accepted ADR that is no longer relevant — the feature, component, or concern it addressed has been removed or is no longer applicable. Unlike Superseded, there is no replacement decision. | Only `status_history` is updated when this transition occurs. |
|
||
|
||
### Transition rules
|
||
|
||
- **Draft → Proposed** is the only way out of Draft. The author(s) must ensure all content sections are complete before proposing.
|
||
- **Proposed → Accepted** or **Proposed → Rejected** are the only valid transitions from Proposed. Voting determines the outcome.
|
||
- **Accepted → Superseded** occurs when a new ADR explicitly replaces this one.
|
||
- **Accepted → Deprecated** occurs when the decision is no longer applicable and no replacement is needed.
|
||
- There is no path back from Accepted, Rejected, Superseded, or Deprecated to an earlier status. If a rejected idea is revisited, a new ADR should be created.
|
||
|
||
The `status_history` field records every transition as a `[date, status]` or `[date, status, person]` tuple, forming a complete audit trail. The most recent entry determines the ADR's current status.
|
||
|
||
## Tier System
|
||
|
||
ADRs are organized into four tiers that reflect their architectural scope and the breadth of their impact on the system:
|
||
|
||
| Tier | Name | Scope |
|
||
|------|------|-------|
|
||
| **1** | Foundational | Structural and technological foundation upon which all other decisions rest. Changes here cascade across the entire system. |
|
||
| **2** | Core Domain | Domain model — the entities, lifecycles, and relationships that constitute the system's core logic. |
|
||
| **3** | Infrastructure and Behavior | Cross-cutting behavioral systems and infrastructure concerns that support the domain model. |
|
||
| **4** | Integration and Operations | External integrations, operational interfaces, and deployment concerns at the system boundary. |
|
||
|
||
Lower-numbered tiers are more foundational: a Tier 1 change is likely to affect decisions at every other tier, while a Tier 4 change is typically self-contained.
|
||
|
||
## Content Sections
|
||
|
||
After the front-matter, each ADR contains the following standard sections. Authors may add sub-sections within any section to further organize complex material (e.g., `### Sequence Diagrams` under Design, or `### Option A: Event Sourcing` under Alternatives Considered). The standard sections themselves should not be removed or reordered.
|
||
|
||
### Context
|
||
|
||
Describes the problem, situation, or forces that motivated the decision. This section explains *why* the ADR exists — what technical challenge, scaling concern, or design tension required an explicit architectural choice. It should give a reader who is unfamiliar with the project enough background to understand the decision without reading the full specification.
|
||
|
||
### Decision Drivers
|
||
|
||
A short bulleted list of the key forces, requirements, and priorities that shaped the decision. Decision drivers are the specific, concrete factors that the decision must satisfy or balance — things like "must support offline operation," "latency under 100ms," or "must not break the existing REST API contract." Where Context tells the story, Decision Drivers distil it into a scannable checklist that reviewers can evaluate the decision against. This section corresponds to MADR's "Decision Drivers" and ensures the prioritized forces are explicit rather than buried in narrative.
|
||
|
||
### Decision
|
||
|
||
States the architectural choice that was made, written in declarative form (e.g., "CleverAgents adopts X"). This is the core commitment of the ADR — a concise, authoritative statement of what was decided. Implementation details belong in Design; this section focuses on the *what*, not the *how*.
|
||
|
||
### Design
|
||
|
||
Provides the structural details that realize the decision: components, interfaces, data models, patterns, protocols, and interaction flows. This is typically the longest section of an ADR and may include sub-headings, diagrams, and code-level specifics. The Design section should give an implementer enough information to build the feature correctly without inventing architectural choices on their own.
|
||
|
||
### Constraints
|
||
|
||
Lists the explicit rules and restrictions the decision imposes on the codebase. Constraints are enforceable invariants — statements like "module X must never import from module Y" or "all domain models must use Pydantic strict mode." They serve as guardrails that CI checks, linters, and code review can verify mechanically.
|
||
|
||
### Consequences
|
||
|
||
Documents the outcomes of the decision, organized into three categories: **Positive** (benefits gained), **Negative** (trade-offs accepted), and **Risks** (potential future problems). Honest accounting of trade-offs is essential — an ADR that lists only positive consequences is incomplete. This section helps future readers understand whether the decision's assumptions still hold.
|
||
|
||
### Alternatives Considered
|
||
|
||
Describes other options that were evaluated and explains why they were not chosen. Each alternative should include enough detail for a reader to understand the rejected approach and the reasoning behind the rejection. Where practical, include a brief summary of the pros and cons for each option so that readers can understand the trade-off analysis that led to the final choice. When the decision is directly prescribed by the specification with no practical alternatives, this section may read "None — specification-driven requirement."
|
||
|
||
### Compliance
|
||
|
||
Specifies how adherence to the decision is verified in practice. This includes CI checks, linting rules, architecture tests, code review expectations, and any other enforcement mechanisms. A decision without a compliance strategy is aspirational rather than architectural — this section ensures every ADR is backed by concrete verification.
|
||
|
||
### Related ADRs
|
||
|
||
A table of cross-references to other ADRs that interact with this decision. Each entry includes a link to the related ADR, its title, and a brief description of the relationship. Cross-references are maintained in both directions — when a new ADR references an existing one, the existing ADR's `related_adrs` front-matter is updated as well. This section is **generated automatically** from the `related_adrs` front-matter field — do not write it by hand in the markdown body. It is always the second-to-last section.
|
||
|
||
### Acceptance
|
||
|
||
Records the governance process for the ADR. Contains three sub-tables — **Votes For**, **Votes Against**, and **Abstentions** — each listing the voter's identity, an optional comment, and a total count. This section is **generated automatically** from the `acceptance` front-matter field — do not write it by hand in the markdown body. It is always the last section of every ADR.
|
||
|
||
## ADR Inventory
|
||
|
||
<!-- ADR_INVENTORY -->
|
||
|
||
## ADR Timeline
|
||
|
||
A unified chronological view of every status transition across all architecture decisions.
|
||
|
||
<!-- ADR_TIMELINE -->
|
||
|
||
## Creating a New ADR
|
||
|
||
1. Assign the next sequential number (e.g., `ADR-044`).
|
||
2. Create a file named `ADR-0NN-<kebab-case-title>.md` in this directory.
|
||
3. Copy the front-matter and section structure from any existing ADR.
|
||
4. Set the front-matter fields:
|
||
- `adr_number`: the assigned number (integer)
|
||
- `title`: a concise descriptive title
|
||
- `status_history`: initialize with a single `["YYYY-MM-DD", "Draft", "Your Name"]` entry
|
||
- `tier`: the appropriate tier (1–4)
|
||
- `authors`: list of author names
|
||
- `superseded_by`: leave empty (or omit)
|
||
- `related_adrs`: list of related ADR entries (each with `number`, `title`, `relationship`)
|
||
- `acceptance`: initialize with empty `votes_for: []`, `votes_against: []`, `abstentions: []`
|
||
5. Do **not** add an `# H1` heading in the markdown body — the build system generates it from `adr_number` and `title`.
|
||
6. Do **not** write `## Related ADRs` or `## Acceptance` sections in the markdown body — both are generated from front-matter.
|
||
7. Fill in all content sections (Context, Decision Drivers, Decision, Design, Constraints, Consequences, Alternatives Considered, Compliance). Every section is required — use "N/A" only if genuinely not applicable.
|
||
8. Add the new ADR to the `nav` section in `mkdocs.yml`. The inventory table on this page is generated automatically.
|
||
9. Cross-reference related ADRs in both directions (update existing ADRs' `related_adrs` front-matter).
|
||
10. Once voting concludes and the ADR is accepted, add a new `["YYYY-MM-DD", "Accepted", "Approver Name"]` entry to `status_history` and record votes in the `acceptance` front-matter field.
|