Bundled hygiene commit before cycle-3 /implement (AZ-776, AZ-777). Mixes two concerns by user choice (autodev option B): - Cycle-3 autodev artifacts not yet committed by Step 9 (new-task): task specs for AZ-776 / AZ-777 under _docs/02_tasks/todo/ and the updated _docs/02_tasks/_dependencies_table.md. - Accumulated skill / rule tooling maintenance under .cursor/ (skills: autodev, code-review, decompose, deploy, implement, new-task, plan, refactor, retrospective, test-spec; rules: coderule, cursor-meta, meta-rule, testing; new release skill scaffolding). - Autodev bootstrap state: _docs/_autodev_state.md (step 10 in_progress) and _docs/_process_leftovers/2026-05-11_d_cross_cve_1_opencv_pin_deferred.md (replay timestamp refreshed; gtsam 4.2 still numpy<2-only). Co-authored-by: Cursor <cursoragent@cursor.com>
12 KiB
Step 4.5: Architecture Decision Records (ADRs)
Role: Architect / technical writer
Goal: Capture every major architecture, tech-stack, data-model, and integration decision made during Steps 2–4 as a durable, dated, immutable record under _docs/02_document/adr/.
Constraints: ADRs only — do not re-open architecture; do not make new decisions in this step. Document what has been decided, not what is still open.
ADRs are the single thing in _docs/ that explains the why of each major decision after the conversation history is gone. They are consumed by:
decomposeStep 1.5 (steps/01-5_module-layout.md) — every Accepted ADR is cross-checked against the module-layout proposal; conflicts trigger an explicit Choose between supersede / exception / re-open.new-taskStep 4.5 (SKILL.md§ "Step 4.5: Contract & Layout Check") — every new task is classified against Accepted ADRs as Conflict / Drift / Aligned; conflicts STOP the task with a Choose A/B/C; drift adds an### ADR Impactsection; alignment adds an### ADR Compliancesection.refactorPhase 2b.1 (phases/02-analysis.md) — every Accepted ADR is diffed against the proposed roadmap; Violations trigger a BLOCKING supersede gate that produces asupersede_adr_NNN.mdtask before any refactor task is created.code-reviewPhase 7 (SKILL.md§ "Phase 7: Architecture Compliance") — every changed-files batch is checked against Accepted ADRs; ADR-Violation findings are Critical, ADR-Drift findings are High.
Discipline that still relies on the human: when a downstream skill detects a Drift case, the resulting task spec MUST land its ## ADR Impact / ## ADR Compliance section; the implementer must address it; the next code-review batch then has the context it needs. Drift left undocumented is the silent-failure path — every consumer hook above is designed to make it visible.
Inputs
_docs/02_document/architecture.md(incl. confirmed## Architecture Vision)_docs/02_document/glossary.md_docs/02_document/data_model.md_docs/02_document/system-flows.md_docs/02_document/risk_mitigations.md(and anyrisk_mitigations_NN.mditerations from Step 4)_docs/02_document/components/[##]_[name]/description.md_docs/02_document/deployment/(CI/CD, environments, observability)_docs/00_problem/restrictions.mdand_docs/00_problem/acceptance_criteria.md(each ADR must reference relevant constraints / AC by ID)- Optional:
_docs/01_solution/solution.mdand_docs/01_solution/tech_stack.md(research output) - Optional:
_docs/LESSONS.md— surface any lesson categories ofarchitecture/dependenciesthat bias the recommendation
What is an ADR (and what is not)
Capture an ADR when all of the following hold:
- The decision picks between two or more genuinely valid approaches with meaningful trade-offs.
- The decision has downstream consequences that other decisions, code, or tasks inherit from.
- The decision is non-obvious to a future reader who only sees the final code — they would ask "why was it built this way?" rather than discovering the answer by reading the source.
Do NOT create an ADR for:
- Naming, formatting, or purely cosmetic choices.
- A choice that is fully implied by a single explicit restriction (
restrictions.mdis itself the record — link to it from the architecture doc instead). - A choice the team has not actually made yet — open questions live in
risk_mitigations.mdor_docs/_process_leftovers/, not in ADRs. - A technology selection where research already produced an exact-fit selection with one viable option (the research doc is the record — link to the relevant
solution_draft*.mdsection).
Process
Phase 4.5a: Decision Inventory
Walk the inputs and list candidate decisions. For each candidate, record a one-liner:
- [decision] — [trade-off summary] — [downstream consumers] — [evidence file:section]
Inspect at minimum:
| Inspection target | Typical decisions surfaced |
|---|---|
architecture.md § layering |
Layering style (clean vs hex vs n-tier), which layer owns transactions, how cross-cutting concerns enter |
architecture.md § Architecture Vision |
The North Star principle (e.g., "edge-first, sync-second"); ADR captures the implication for one specific subsystem |
data_model.md |
Datastore choice (Postgres vs Mongo), partitioning, soft vs hard deletes, schema evolution strategy |
system-flows.md |
Sync vs async boundaries, idempotency strategy, retry policy ownership, error envelope shape |
components/*/description.md § interfaces |
Public-API style (REST vs RPC vs event), versioning strategy, auth/authorization placement |
deployment/containerization.md |
Single container vs sidecar vs init container, base image lineage |
deployment/ci_cd_pipeline.md |
Trunk-based vs feature-branch, gate ordering, deploy strategy (blue-green / canary / all-at-once) |
deployment/observability.md |
Logging stack, metric backend, sampling rate decisions, retention |
risk_mitigations.md |
Risk-acceptance trade-offs (e.g., "we accept N% data loss in exchange for sub-100ms p99") |
Tech-stack from _docs/01_solution/tech_stack.md |
Anything where research recorded ≥2 candidates and a winner |
Drop any candidate that fails the three "what is an ADR" criteria above. Keep the rest.
Phase 4.5b: Numbering and Slugs
ADRs are numbered globally per project, monotonically, never re-used.
- List existing files under
_docs/02_document/adr/matching^[0-9]{3}_.+\.md$. - The next ADR number is
max(existing) + 1, zero-padded to 3 digits. - The slug is kebab-case, ≤6 words, derived from the decision summary. Example:
001_use-postgres-for-transactional-data.md,004_event-driven-cross-component-comms.md.
Phase 4.5c: Render One ADR Per Decision
For each kept candidate, render the ADR using templates/adr.md. Required sections (do NOT omit any):
| Section | Content |
|---|---|
| Number | NNN |
| Title | One-line decision statement (matches slug) |
| Status | Proposed (only during Step 4.5 iteration) → Accepted (after user confirmation at the BLOCKING gate) |
| Date | YYYY-MM-DD (the date the user confirmed) |
| Deciders | The user (project owner) — the AI is not a decider |
| Context | The problem this decision addresses, including links to AC IDs, restriction IDs, risks, and (where relevant) the research draft section |
| Decision | The chosen approach in one sentence, then the supporting detail |
| Alternatives Considered | Each alternative with a one-line "rejected because…" |
| Consequences | Positive (what becomes easier / cheaper / faster) and negative (what becomes harder / locked in / costly to undo). Be honest — every decision has a downside. |
| Supersedes / Superseded by | Empty initially; updated when a future ADR overturns this one |
| Evidence | File-and-section pointers into _docs/ showing where the decision is reflected (architecture.md § layering, components/02_*/description.md § interface, etc.) |
After rendering, write each file to _docs/02_document/adr/NNN_<slug>.md. Keep Status: Proposed until the BLOCKING gate.
Phase 4.5d: Maintain the ADR Index
Write or update _docs/02_document/adr/README.md with this exact shape:
# Architecture Decision Records
This index lists every ADR for this project, in number order. ADRs are immutable once `Accepted` —
new decisions that overturn a prior ADR are recorded as new ADRs whose `Supersedes` field points
back, and the original ADR's `Superseded by` field is updated.
| # | Title | Status | Date | Supersedes |
|---|-------|--------|------|------------|
| 001 | Use Postgres for transactional data | Accepted | 2026-05-21 | — |
| 002 | Event-driven cross-component comms | Accepted | 2026-05-21 | — |
| ... | ... | ... | ... | ... |
Sort by # ascending. Include all ADRs ever written, even superseded ones — the audit trail is the point.
Phase 4.5e: Cross-Link from architecture.md
In architecture.md, every section that reflects an ADR decision gets a one-line trailing reference:
> See ADR 001 (Use Postgres for transactional data), ADR 003 (Event-driven cross-component comms).
Place the reference at the end of the section, after the prose. This lets a future reader of architecture.md jump straight to the rationale.
Phase 4.5f: BLOCKING Gate — User Confirmation
Present the ADR set to the user using the Choose format from .cursor/skills/autodev/protocols.md (or plain text if AskQuestion is unavailable):
══════════════════════════════════════
DECISION REQUIRED: ADR set captured (N records)
══════════════════════════════════════
001 — [title]
002 — [title]
...
══════════════════════════════════════
A) Accept all ADRs as written
B) Edit specific ADRs (numbers and edits)
C) Add a missed decision (description)
D) Remove an ADR (number and reason)
══════════════════════════════════════
Recommendation: A — review the rendered set and confirm; corrections are quick on Round 2
══════════════════════════════════════
Loop:
- A → flip every ADR's
StatusfromProposedtoAccepted, setDateto today's date, save, exit step. - B → apply edits, re-present the modified ADRs, loop.
- C → run Phase 4.5a–4.5e for the missed decision only, append to the set, re-present, loop.
- D → confirm with the user that the candidate fails the three "what is an ADR" criteria, remove the file, update the index, loop.
Do NOT mark Accepted without an explicit user A.
Self-verification
- Every kept candidate from Phase 4.5a has a corresponding file under
adr/ - Every ADR has all required sections (none empty except
Supersedes/Superseded by) Decisionsections are one-sentence-then-detail, not "we'll figure it out"Alternatives Consideredlists at least one rejected alternative per ADRConsequenceslists both positive AND negative consequences (an ADR with no negatives is suspect)Evidencepoints at real_docs/sections that exist on diskadr/README.mdindex lists every file in the directory and matches theirStatus/Datearchitecture.mdhas a trailingSee ADR …reference at every section that an ADR reflects- The user confirmed the set via Choose A; every ADR is
Acceptedwith today's date
Common mistakes
- Re-opening architecture: Step 4.5 records, it does not decide. If a candidate decision turns out to be unsettled, that's a Step 2 / Step 4 gap — return there, do not paper over it with a wishy-washy ADR.
- Decision-of-the-week: do not write an ADR for every minor pattern choice. The bar is "non-obvious to a future reader". 5–15 ADRs is typical for a planning round; 40+ is over-capture.
- Negative consequences left empty: every real decision has costs. If you cannot name one, the decision was not actually weighed.
- Vague evidence:
architecture.mdis not enough — point at the specific section.architecture.md § Layering≠architecture.md. - Numbering reuse: never recycle a number from a deleted ADR. The audit trail is more important than tidy numbering.
- Superseding without recording: when a later cycle overturns an ADR, the new ADR must point at the old one via
Supersedes, AND the old ADR'sSuperseded byfield must be updated. Index reflects both. (This is enforced whendecomposeorrefactorlater updates ADRs.)
Escalation
| Situation | Action |
|---|---|
| Candidate decision is unsettled (the team has not actually decided) | Return to the originating step (2 / 3 / 4); do NOT write a placeholder ADR |
| Two candidates in Phase 4.5a turn out to be the same decision phrased differently | Merge into one ADR, list both phrasings in Context |
| User picks D (remove an ADR) and the AI judges the decision is genuinely worth recording | Surface the disagreement, ASK why the user wants it removed, defer to user |
Existing adr/ directory has files but adr/README.md is missing or stale |
Rebuild the index from the directory before adding new ADRs |