Files
gps-denied-onboard/.cursor/skills/plan/steps/04-5_adr-capture.md
T
Oleksandr Bezdieniezhnykh 6044a33197 chore: WIP pre-implement
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>
2026-05-21 13:14:11 +03:00

12 KiB
Raw Blame History

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 24 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:

  • decompose Step 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-task Step 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 Impact section; alignment adds an ### ADR Compliance section.
  • refactor Phase 2b.1 (phases/02-analysis.md) — every Accepted ADR is diffed against the proposed roadmap; Violations trigger a BLOCKING supersede gate that produces a supersede_adr_NNN.md task before any refactor task is created.
  • code-review Phase 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 any risk_mitigations_NN.md iterations from Step 4)
  • _docs/02_document/components/[##]_[name]/description.md
  • _docs/02_document/deployment/ (CI/CD, environments, observability)
  • _docs/00_problem/restrictions.md and _docs/00_problem/acceptance_criteria.md (each ADR must reference relevant constraints / AC by ID)
  • Optional: _docs/01_solution/solution.md and _docs/01_solution/tech_stack.md (research output)
  • Optional: _docs/LESSONS.md — surface any lesson categories of architecture / dependencies that bias the recommendation

What is an ADR (and what is not)

Capture an ADR when all of the following hold:

  1. The decision picks between two or more genuinely valid approaches with meaningful trade-offs.
  2. The decision has downstream consequences that other decisions, code, or tasks inherit from.
  3. 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.md is 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.md or _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*.md section).

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.

  1. List existing files under _docs/02_document/adr/ matching ^[0-9]{3}_.+\.md$.
  2. The next ADR number is max(existing) + 1, zero-padded to 3 digits.
  3. 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.

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 Status from Proposed to Accepted, set Date to today's date, save, exit step.
  • B → apply edits, re-present the modified ADRs, loop.
  • C → run Phase 4.5a4.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)
  • Decision sections are one-sentence-then-detail, not "we'll figure it out"
  • Alternatives Considered lists at least one rejected alternative per ADR
  • Consequences lists both positive AND negative consequences (an ADR with no negatives is suspect)
  • Evidence points at real _docs/ sections that exist on disk
  • adr/README.md index lists every file in the directory and matches their Status / Date
  • architecture.md has a trailing See ADR … reference at every section that an ADR reflects
  • The user confirmed the set via Choose A; every ADR is Accepted with 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". 515 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.md is not enough — point at the specific section. architecture.md § Layeringarchitecture.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's Superseded by field must be updated. Index reflects both. (This is enforced when decompose or refactor later 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