| ADR-0001 |
Record architecture decisions |
Accepted |
| ADR-0002 |
Use freezed + json_serializable, with extensions for behavior |
Accepted |
| ADR-0003 |
Use a pure-Dart SimpleTimeOfDay for serializable time values |
Accepted |
| ADR-0004 |
Do not adopt a third-party state-management library |
Accepted |
| ADR-0005 |
The Dart CLI must remain free of Flutter imports |
Accepted |
| ADR-0006 |
Sentry telemetry is gated behind opt-in analytics consent |
Accepted |
| ADR-0007 |
.drill files are versioned ZIP archives of JSON parts |
Accepted |
| ADR-0008 |
Persistent program library with active plan and shared catalog |
Accepted |
| ADR-0009 |
Short polling with CDN-cached session status as live transport |
Accepted |
| ADR-0010 |
Live catalog updates via HEAD polling with CDN cache |
Accepted |
| ADR-0011 |
Synchronized exercise control with coordinator-driven state |
Accepted |
| ADR-0012 |
Position sharing |
Accepted |
| ADR-0013 |
Local end-to-end catalog testing via netlify dev, CLI seeding and a build-time base URL |
Accepted |
| ADR-0014 |
Server-controlled drill upload contract |
Accepted |
| ADR-0015 |
Shareable install links open the plan in the app via ringdrill.app/i/<slug> |
Accepted |
| ADR-0016 |
PWA update strategy: no-cache entry points, resilient SW detection, and an in-app last resort |
Accepted |
| ADR-0017 |
Decouple number of stations from number of rounds in exercise setup |
Accepted |
| ADR-0018 |
Introduce RolePlay and Actor entities, persist schema 1.1 in metadata |
Accepted |
| ADR-0019 |
Roleplayer as a third session participant role |
Accepted |
| ADR-0020 |
Reduce map label and marker clutter via clustering, a unified marker spec, zoom-gated labels and per-layer visibility toggles |
Accepted |
| ADR-0021 |
Use app.ringdrill as the iOS and macOS bundle identifier and keep org.discoos.ringdrill on Android |
Accepted |
| ADR-0022 |
Store long-form markdown content as .md files in the drill archive |
Accepted |
| ADR-0023 |
Render the Brief view with a dedicated BriefTheme token set inspired by docs-site typography, independent of Material ColorScheme |
Accepted |
| ADR-0024 |
Introduce Account, User and Identity as separate entities |
Accepted |
| ADR-0025 |
Authorise catalog writes against Account, with per-plan access policy |
Accepted |
| ADR-0026 |
Sheet-based context navigation with replace-semantics for detail surfaces |
Accepted |
| ADR-0027 |
Unify all bottom sheets behind two showRingdrillSheet variants |
Accepted |
| ADR-0028 |
Group lib/views/ by feature and distribute shared domain widgets |
Accepted |
| ADR-0029 |
Surface a live mini player via ActivityKit on iOS and a foreground service notification on Android |
Accepted |
| ADR-0030 |
Adopt a Material 3 master/detail layout on medium and expanded viewports, promote forms to modal dialogs and anchor the drill mini-player to the master column |
Accepted |
| ADR-0031 |
Row edit affordances use swipe and long-press; pencil reserved for AppBar |
Accepted |
| ADR-0032 |
Prefix every program-scoped path with /program/:uuid/ and drive activation from the URL |
Accepted |
| ADR-0033 |
Adopt a selective platform-adaptive UI layer on iOS, keeping Material as the base |
Accepted |
| ADR-0034 |
Centralise numbering in one module and make number formats configurable per plan |
Accepted |
| ADR-0035 |
Give exercises an explicit order field and user-driven reordering |
Accepted |
| ADR-0036 |
Extract a shared reorder section and let stations be reordered in the Stations segment and coordinator |
Accepted |
| ADR-0037 |
Size text for legibility on iOS: tighten the baseline type scale and clamp scaling at 1.3 |
Accepted |
| ADR-0038 |
Gate first-launch consent and rationale behind a four-stage onboarding |
Accepted |
| ADR-0039 |
Split the site, PWA and API across separate origins |
Accepted |
| ADR-0040 |
Extend the catalog feed schema with description, exercise count, author and access policy |
Accepted |
| ADR-0041 |
Brief pre-rendering port from Dart to Node (reserved, referenced by ADR-0039) |
Reserved |
| ADR-0042 |
Centralise build-time feature flags with sunset telemetry |
Accepted |
| ADR-0043 |
Tags live in the .drill format and publish is last-write-wins |
Accepted |
| ADR-0044 |
Render the shareable preview on the site and expose plan meta as JSON |
Accepted |
| ADR-0045 |
Drill library bundle format for multi-program export and import |
Accepted |
| ADR-0046 |
Plan-scoped variables with cascading value overrides |
Accepted |
| ADR-0047 |
Station-scoped scenario locations and persons, and RolePlay portrays a Person |
Accepted |
| ADR-0048 |
Extract a Flutter-free field resolver from BriefRenderer |
Accepted |
| ADR-0049 |
Selectors adapt to window size behind one picker primitive — bottom sheet on compact, dialog on medium/expanded |
Accepted |
| ADR-0050 |
Per-output-format chip formatting via a ChipFormatter strategy |
Accepted |
| ADR-0051 |
Single MapConfig.fitFor camera-fit helper for every map surface |
Accepted |
| ADR-0052 |
Map and brief viewer overlays adapt to window size like ADR-0049's selectors |
Accepted |
| ADR-0053 |
MapView owns its default camera fit, centring and marker construction |
Accepted |
| ADR-0054 |
Consistent map interactivity on medium/expanded windows, via a built-in MapView.withFullscreen command |
Proposed |
| ADR-0055 |
Dual-accept programId/planId at the Netlify API boundary, with Sentry-tracked deprecation |
Accepted |
| ADR-0056 |
One drill player with peer modes — exercise, station, roleplay, team |
Accepted |
| ADR-0057 |
Editing is gated on the device's role, and frozen on a running exercise |
Accepted |
| ADR-0058 |
Introduce a source format compiled to .drill by a Flutter-free CLI |
Accepted |
| ADR-0059 |
Normalize legacy .drill archives through an ordered migration ladder |
Accepted |
| ADR-0060 |
Serve the MCP server remotely as a Netlify function, with the compiler cross-compiled to JavaScript |
Accepted |
| ADR-0061 |
Accept a UTM string wherever the source format takes a position |
Accepted |
| ADR-0062 |
Express a non-uniform exercise as a mode plus station durations |
Accepted |
| ADR-0063 |
Give every staff role its own brief audience, and declare each field's audiences on the field |
Accepted |
| ADR-0064 |
Cut the document out of the authoring loop, and stop over-answering |
Accepted |
| ADR-0065 |
Ship the authoring conventions over MCP, not only as a local skill |
Accepted |
| ADR-0066 |
A team scope for cross-reference tokens |
Rejected |
| ADR-0067 |
Give tokens a searchable browser sheet, and leave the caret menu as the fast path |
Accepted |
| ADR-0068 |
Decide whether a cascaded field resolves in the borrowing scope |
Accepted |
| ADR-0069 |
Render the brief through a lazy viewport, and navigate it without relying on mounted headings |
Accepted |
| ADR-0070 |
Deliver a built archive by handle, not through the transcript |
Accepted |
| ADR-0071 |
Report a modelling shortcut, instead of only advising against it |
Accepted |
| ADR-0072 |
Let a roster reach the account that owns the plan, and keep the catalog stripped |
Accepted |
| ADR-0073 |
Select the auth backend by mode, and ship a mock adapter for dev and test |
Accepted |
| ADR-0074 |
A catalog entry is a distinct object, identified by (namespace, slug) and defined by an allowlist |
Accepted |
| ADR-0075 |
Send mail through a provider adapter, and keep templates and events on our side |
Accepted |
| ADR-0076 |
Protect local plan storage at rest, without an async read path |
Accepted |
| ADR-0077 |
Reverse indexes for per-user lookups in the blob store |
Proposed |
| ADR-0078 |
Put the expiry in the key, and let the sweep catch itself up |
Proposed |