Skip to content

Architecture decision records

An ADR records one decision that is expensive to reverse or invisible from the code: why there is no join table for tags, why sync pushes rows back to the server that just sent them. The code tells you what; an ADR tells you why not the obvious alternative.

ADR Decision Status Date
0001 Kotlin Multiplatform, SQLDelight, UUIDv7 ids and a desktop app built from shared :core and :ui modules Accepted; phases 1–5 done, the synced-folder half superseded by 0002 2026-08-07
0002 Sync through a server, hub and spoke, last writer wins, tombstones; the protocol still in use Accepted; client and realtime superseded by 0005 2026-08-09
0003 The desktop is pointer- and keyboard-first: sidebar, two panes, drag and drop, command palette Accepted 2026-08-21
0004 A tag is identity only; which tasks wear it is a packed column on the task Accepted 2026-08-22
0005 The sync backend moves from Supabase to Neon (Data API + Neon Auth), realtime becomes a poll Accepted 2026-08-25
flowchart LR
  A1["0001<br/>KMP + desktop"] --> A2["0002<br/>server sync protocol"]
  A1 --> A3["0003<br/>desktop interaction"]
  A2 --> A4["0004<br/>tags"]
  A2 --> A5["0005<br/>Neon backend"]
  A1 -. "decision 6 superseded" .-> A2
  A2 -. "decisions 6, 12 superseded" .-> A5

Planning notes and issues refer to ADRs that are not written yet. Since 0005 went to the Neon move, these take the next free numbers when the work starts, in the order it starts — the number is not reserved by the plan:

  • the adaptive shell, one navigator on every platform (#48);
  • the TaskQuery grammar and where saved views are stored (#149);
  • how recurrence is drawn on a calendar (#148);
  • end-to-end encrypted sync (#152);
  • one desktop process, and launcher actions from the dock, the app menu and the jump list (plan).

Copy the template below into docs/adr/NNNN-short-slug.md with the next free number, and open it in the same pull request as the first code that depends on it.

  • An accepted ADR is not rewritten. To change a decision, write a new ADR that supersedes it, and add one line to the old one’s status pointing forward. The status line is the only part of an old ADR that changes.
  • An amendment is for a narrow exception that leaves the decision standing — see ADR 0002’s amendment 1.
  • Number the decisions inside it (### 1. …), so code comments and other ADRs can cite “ADR 0004, decision 3”.
  • Write the rejected alternatives down with the reason. That section is what stops the same question being reopened in a year.
---
title: "ADR NNNN — The decision, as a sentence"
sidebar:
label: "NNNN · Short label"
order: NNNN
---
**Status:** proposed | accepted | superseded by [ADR MMMM](MMMM-slug.md)
**Date:** YYYY-MM-DD
**Supersedes:** nothing | ADR MMMM decision N
## Context
What forces the decision now, and what it must not break.
## Decisions
### 1. The first decision
What we do, and why this and not the obvious alternative.
## Consequences
What gets easier, what gets harder, what we now have to keep true.
## Alternatives rejected
- **The alternative.** Why not.