@adia-ai/adia-ui-forge 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/.claude-plugin/plugin.json +2 -2
  2. package/CHANGELOG.md +8 -0
  3. package/agents/README.md +209 -0
  4. package/agents/a2ui-engineer.md +57 -0
  5. package/agents/author.md +56 -0
  6. package/agents/release-engineer.md +85 -0
  7. package/agents/repo-steward.md +56 -0
  8. package/agents/routing-corpus.json +89 -0
  9. package/agents/spec-architect.md +53 -0
  10. package/agents/tech-lead.md +57 -0
  11. package/agents/verifier.md +55 -0
  12. package/package.json +3 -2
  13. package/skills/adia-ui-authoring/SKILL.md +2 -2
  14. package/skills/adia-ui-authoring/assets/case-studies/theme-panel-promotion.md +1 -1
  15. package/skills/adia-ui-authoring/references/module-promotion.md +2 -2
  16. package/skills/adia-ui-gen-review/skill.json +1 -0
  17. package/skills/adia-ui-ops/CHANGELOG.md +291 -0
  18. package/skills/adia-ui-ops/SKILL.md +401 -0
  19. package/skills/adia-ui-ops/references/INDEX.md +158 -0
  20. package/skills/adia-ui-ops/references/audit-cadence.md +263 -0
  21. package/skills/adia-ui-ops/references/audit-patterns/archive-link-sweep.md +96 -0
  22. package/skills/adia-ui-ops/references/audit-patterns/audit-history-ledger.md +162 -0
  23. package/skills/adia-ui-ops/references/audit-patterns/browser-bundle-node-imports.md +154 -0
  24. package/skills/adia-ui-ops/references/audit-patterns/changelog-unreleased-bloat.md +75 -0
  25. package/skills/adia-ui-ops/references/audit-patterns/coverage-gaps.md +187 -0
  26. package/skills/adia-ui-ops/references/audit-patterns/entry-file-coverage.md +122 -0
  27. package/skills/adia-ui-ops/references/audit-patterns/format-hygiene.md +217 -0
  28. package/skills/adia-ui-ops/references/audit-patterns/lockstep-versioning.md +113 -0
  29. package/skills/adia-ui-ops/references/audit-patterns/memory-fragmentation.md +180 -0
  30. package/skills/adia-ui-ops/references/audit-patterns/orphan-detection.md +202 -0
  31. package/skills/adia-ui-ops/references/audit-patterns/pointer-validation.md +180 -0
  32. package/skills/adia-ui-ops/references/audit-patterns/redundancy-detection.md +210 -0
  33. package/skills/adia-ui-ops/references/audit-patterns/spec-dating-sweep.md +91 -0
  34. package/skills/adia-ui-ops/references/audit-patterns/stale-content.md +182 -0
  35. package/skills/adia-ui-ops/references/audit-patterns/staleness-tooling.md +156 -0
  36. package/skills/adia-ui-ops/references/audit-patterns/token-waste-detection.md +196 -0
  37. package/skills/adia-ui-ops/references/deploy-playbooks.md +259 -0
  38. package/skills/adia-ui-ops/references/doc-types/adr-pattern.md +210 -0
  39. package/skills/adia-ui-ops/references/doc-types/architecture-md.md +190 -0
  40. package/skills/adia-ui-ops/references/doc-types/changelog.md +183 -0
  41. package/skills/adia-ui-ops/references/doc-types/decisions-log.md +146 -0
  42. package/skills/adia-ui-ops/references/doc-types/plan-roadmap.md +182 -0
  43. package/skills/adia-ui-ops/references/doc-types/postmortem-pattern.md +206 -0
  44. package/skills/adia-ui-ops/references/genres/prose-and-writing.md +149 -0
  45. package/skills/adia-ui-ops/references/guidance/context-budget.md +137 -0
  46. package/skills/adia-ui-ops/references/guidance/llm-doc-writing.md +116 -0
  47. package/skills/adia-ui-ops/references/guidance/reliability-dial.md +186 -0
  48. package/skills/adia-ui-ops/references/recipes/adr-introduction.md +211 -0
  49. package/skills/adia-ui-ops/references/recipes/audit-existing-repo.md +234 -0
  50. package/skills/adia-ui-ops/references/recipes/cold-start-harvest.md +263 -0
  51. package/skills/adia-ui-ops/references/recipes/concurrent-learnings-merge.md +158 -0
  52. package/skills/adia-ui-ops/references/recipes/continuous-learning-loop.md +169 -0
  53. package/skills/adia-ui-ops/references/recipes/external-reference-verification.md +158 -0
  54. package/skills/adia-ui-ops/references/recipes/findings-index-readout.md +126 -0
  55. package/skills/adia-ui-ops/references/recipes/greenfield-setup.md +252 -0
  56. package/skills/adia-ui-ops/references/recipes/harvest-repo-brain.md +169 -0
  57. package/skills/adia-ui-ops/references/recipes/import-repo-brain-harvest.md +153 -0
  58. package/skills/adia-ui-ops/references/recipes/memory-organization.md +182 -0
  59. package/skills/adia-ui-ops/references/recipes/recommend-then-validate.md +199 -0
  60. package/skills/adia-ui-ops/references/recipes/self-healing-hooks.md +366 -0
  61. package/skills/adia-ui-ops/references/recipes/skill-stewardship-loop.md +113 -0
  62. package/skills/adia-ui-ops/references/standards/agents-md-spec.md +138 -0
  63. package/skills/adia-ui-ops/references/standards/claude-md-convention.md +123 -0
  64. package/skills/adia-ui-ops/references/standards/cross-tool-matrix.md +85 -0
  65. package/skills/adia-ui-ops/references/standards/readme-conventions.md +232 -0
  66. package/skills/adia-ui-ops/references/teach-protocol.md +215 -0
  67. package/skills/adia-ui-ops/scripts/audit-ops-roster.mjs +104 -0
  68. package/skills/adia-ui-ops/skill.json +65 -0
  69. package/skills/adia-ui-release/CHANGELOG.md +43 -0
  70. package/skills/adia-ui-release/SKILL.md +34 -6
  71. package/skills/adia-ui-release/references/independent-package-release.md +129 -0
  72. package/skills/adia-ui-release/references/recovery-paths.md +49 -2
  73. package/skills/adia-ui-release/scripts/dispatch-publish.mjs +68 -5
  74. package/skills/adia-ui-release/scripts/insert-stub.mjs +5 -3
  75. package/skills/adia-ui-release/scripts/make-ledger.mjs +22 -1
  76. package/skills/adia-ui-release/scripts/package-paths.mjs +44 -0
  77. package/skills/adia-ui-release/scripts/promote-unreleased.mjs +3 -2
  78. package/skills/adia-ui-release/scripts/release-pack.mjs +36 -7
  79. package/skills/adia-ui-release/scripts/tag-lockstep.mjs +10 -2
  80. package/skills/adia-ui-release/skill.json +9 -7
  81. package/skills/dogfood-sweep/CHANGELOG.md +37 -0
  82. package/skills/dogfood-sweep/README.md +105 -0
  83. package/skills/dogfood-sweep/SKILL.md +1000 -0
  84. package/skills/dogfood-sweep/analyze.mjs +600 -0
  85. package/skills/dogfood-sweep/skill.json +31 -0
@@ -0,0 +1,259 @@
1
+ # Deploy playbooks — exe.dev VM operations
2
+
3
+ > **Owner: `adia-ui-ops` modes 1-4** (cold-start triage entry).
4
+ > Absorbed verbatim from the retired standalone `exe-dev-ops` skill (v1.0.0,
5
+ > 2026-05-22). Authored content untouched; only the framing wrapper changed.
6
+
7
+ Operational playbook for services on **exe.dev** — shared Linux VMs reached via
8
+ `ssh <host>.exe.xyz`. This reference captures the platform contract (which
9
+ isn't obvious from docs), the standard layout we use across services, and the
10
+ two-three commands that solve 90% of day-to-day tasks.
11
+
12
+ ## When to use
13
+
14
+ - Deploying a new static site or API to a fresh exe.dev VM.
15
+ - Updating an existing deployed site (push new `dist/`).
16
+ - Rotating API keys or other secrets on the VM.
17
+ - Diagnosing a down service — seeing the **"Port 8000 unbound."** error page, 502s, or failed health checks.
18
+ - Adding a new systemd service / Caddy site to a VM already in service.
19
+
20
+ ## When NOT to use
21
+
22
+ - DNS config — exe.dev owns `<host>.exe.xyz` subdomains; nothing to do locally.
23
+ - TLS — the exe.dev front-door terminates HTTPS. Never bind :443 on the VM.
24
+ - Multi-VM orchestration / auto-scaling — out of scope, single VM per service.
25
+ - Anything requiring root on the host kernel — these are shared VMs, not full boxes.
26
+
27
+ ## Platform contract (the non-obvious bits)
28
+
29
+ These facts are easy to get wrong because the docs are thin — we learned them the hard way.
30
+
31
+ - **Your app must bind `:8000`** (plain HTTP). The exe.dev edge proxy terminates TLS on `<host>.exe.xyz` and forwards to VM `:8000`. If nothing is listening, exe.dev serves:
32
+
33
+ > **Port 8000 unbound.** `ssh <host>.exe.xyz sudo systemctl enable --now nginx`
34
+ >
35
+ > (The nginx suggestion is just their canonical example — Caddy, Node, anything that binds :8000 works.)
36
+
37
+ - **Default VM user: `exedev`** — uid 1000, member of `sudo` and `docker`. Use this for service processes; don't create a dedicated service user unless you have a real isolation requirement.
38
+ - **What's preinstalled:** `git`, `rsync`, `docker`. **Not preinstalled:** `caddy`, `node`, `npm`, `nginx`. Use apt + NodeSource for node.
39
+ - **`127.0.0.1:9999` runs `shelley`** — exe.dev's internal agent. Localhost-only. Don't kill it, don't bind anything to 9999.
40
+ - **Disk:** 25 GB on `/`; no separate `/srv` mount. Fits a typical static bundle + node modules comfortably.
41
+ - **Host SSH key:** currently RSA-2048 only on new VMs (as of 2026-04). Verify the fingerprint in the exe.dev console on first connect; then `ssh-keyscan >> ~/.ssh/known_hosts`.
42
+
43
+ ## Standard layout (convention we use)
44
+
45
+ | Path | Purpose | Owner |
46
+ | ----------------------------- | ----------------------------------------------- | ----------------- |
47
+ | `/srv/<app>/dist/` | Static bundle served by Caddy | `exedev:exedev` |
48
+ | `/srv/<app>/server.js` | Optional runtime (e.g. API proxy) | `exedev:exedev` |
49
+ | `/etc/caddy/Caddyfile` | Single-site; binds `:8000` | `root:root` |
50
+ | `/etc/systemd/system/<app>.service` | systemd unit for server.js | `root:root` |
51
+ | `/etc/<app>.env` | Secrets loaded via `EnvironmentFile=` | `root:root` 0600 |
52
+
53
+ **Never** put secrets in `/srv/<app>/` — that's the webroot.
54
+
55
+ ## Playbook: fresh provisioning
56
+
57
+ ```sh
58
+ # 1. SSH in; verify host key first via exe.dev console.
59
+ ssh <host>.exe.xyz
60
+
61
+ # 2. Install runtime.
62
+ sudo apt-get update -qq
63
+ sudo apt-get install -y caddy
64
+ curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
65
+ sudo apt-get install -y nodejs
66
+
67
+ # 3. Filesystem.
68
+ sudo mkdir -p /srv/<app>
69
+ sudo chown exedev:exedev /srv/<app>
70
+ ```
71
+
72
+ Then from your **local** machine:
73
+
74
+ ```sh
75
+ # 4. Push artifacts.
76
+ rsync -az --delete dist/ <host>.exe.xyz:/srv/<app>/dist/
77
+ rsync -a server.js <host>.exe.xyz:/srv/<app>/server.js # if applicable
78
+
79
+ # 5. Push Caddyfile + systemd unit.
80
+ scp deploy/Caddyfile <host>.exe.xyz:/tmp/
81
+ scp deploy/<app>.service <host>.exe.xyz:/tmp/
82
+ ```
83
+
84
+ Back on the VM:
85
+
86
+ ```sh
87
+ # 6. Activate Caddy.
88
+ sudo mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.default.bak
89
+ sudo mv /tmp/Caddyfile /etc/caddy/Caddyfile
90
+ sudo systemctl reload caddy
91
+
92
+ # 7. Activate service.
93
+ sudo mv /tmp/<app>.service /etc/systemd/system/<app>.service
94
+ sudo systemctl daemon-reload
95
+ sudo systemctl enable --now <app>
96
+
97
+ # 8. Seed secrets — do this by hand; never via agent transcript.
98
+ sudo install -m 0600 -o root -g root /dev/null /etc/<app>.env
99
+ sudo vim /etc/<app>.env
100
+ sudo systemctl restart <app>
101
+ ```
102
+
103
+ ## Playbook: deploy an update
104
+
105
+ Single command from the repo root once `npm run deploy:site` is wired:
106
+
107
+ ```sh
108
+ npm run deploy:site
109
+ ```
110
+
111
+ Under the hood: `npm run build:site && rsync -az --delete dist/ <host>.exe.xyz:/srv/<app>/dist/`. Caddy picks up static changes without a reload.
112
+
113
+ > ⚠️ **`deploy:site` is a `--delete` deploy — treat it as destructive.** `build:site`
114
+ > is **manual** (not wired into the npm release pipeline), so `dist/` silently drifts
115
+ > behind `main` until someone runs it, and the rsync **deletes** everything on the
116
+ > server that isn't in the fresh `dist/`. A real ui-kit run (2026-06-08) sent ~160 real
117
+ > content deltas and **deleted 3,572 files**. Never fire it blind — the sequence below
118
+ > is the contract for any `--delete` site deploy.
119
+
120
+ ### Hardened `--delete` deploy sequence
121
+
122
+ 1. **Build from a clean, fully-merged `main`** — never a feature branch. `dist/` ships
123
+ verbatim; whatever's missing on the server gets deleted.
124
+ - **In a FRESH worktree, build `@adia-ai/llm` FIRST:**
125
+ ```sh
126
+ npm run build -w @adia-ai/llm # BEFORE build:site
127
+ ```
128
+ The `llm` package **compiles its JS at publish time** and its outputs are
129
+ **gitignored** — so a fresh worktree (or any tree that hasn't published llm
130
+ locally) has no `packages/llm/index.js`, `build:site` copies nothing, and
131
+ **`/packages/llm/index.js` 404s on the deployed site → component registration
132
+ breaks on every `/site/components/*` page** (the docs components reference it). Found
133
+ **live 2026-06-09**; the **0-delete dry-run proved it had never been deployed** (the
134
+ file was absent on the server, so there was nothing to delete — not a regression, a
135
+ standing gap across every prior deploy). Build llm, then `build:site`, then the
136
+ dry-run.
137
+ 2. **Dry-run first, and adjudicate every delete:**
138
+ ```sh
139
+ rsync -azni --delete dist/ <host>.exe.xyz:/srv/<app>/dist/ # -n simulates · -i itemizes
140
+ ```
141
+ - `*deleting` lines = files removed from prod. Bucket **every one** into a known-safe
142
+ class; **abort if any served-content delete is unexplained.** Safe classes seen on
143
+ ui-kit: gallery review artifacts (`apps/genui/.../review/cycle-*/`), stale
144
+ `packages/a2ui/retrieval/` + eval reports, **content-hash-rotated** CodeMirror
145
+ chunks (`code/{chunk,dist}-<hash>.js` — old hash deleted, new hash sent = rotation,
146
+ not loss), restructured `packages/llm/*.js` dist copies, `node_modules/`
147
+ symlink-farm dirs, and refactor-orphaned app files. None are served HTML.
148
+ - **Don't panic at the send count.** A fresh local build never mtime-aligns with the
149
+ remote, so `rsync -a` flags ~every file as a send (`<f..t` = mtime-only touch). Only
150
+ `<f+++` (new) and `<f.s.` / `<fcst` (content) are real deltas — the 2026-06-08 run
151
+ itemized 12,540 "sends" of which only ~160 carried real content.
152
+ 3. **Snapshot prod FIRST — the only safety net for `--delete`:**
153
+ ```sh
154
+ ssh <host>.exe.xyz 'cp -al /srv/<app>/dist /srv/<app>/dist.bak-<date>' # hardlink: instant, reversible
155
+ ssh <host>.exe.xyz 'find /srv/<app>/dist.bak-<date> -type f | wc -l' # confirm it materialized
156
+ ```
157
+ `cp -al` is a hardlink farm — instant, ~0 extra disk, and a true point-in-time
158
+ snapshot because rsync replaces inodes (writes a temp file + renames) rather than
159
+ mutating in place. Restore with `rm -rf dist && mv dist.bak-<date> dist`.
160
+ 4. **Deploy** (the dry-run, minus `-n`):
161
+ ```sh
162
+ rsync -az --delete dist/ <host>.exe.xyz:/srv/<app>/dist/
163
+ ```
164
+ 5. **Verify the FILE, not the route.** A SPA returns `200` + the app shell for *any*
165
+ route even when stale — `curl https://<host>.exe.xyz/` proves nothing. Curl a
166
+ **fixture file** that only exists in the new build, then **render-check the real
167
+ screens**:
168
+ ```sh
169
+ curl -s https://<host>.exe.xyz/.../scenarios/manifest.json | grep -c <new-scenario> # >0
170
+ curl -s -o /dev/null -w '%{http_code}' https://<host>.exe.xyz/.../<scenario>/manifest.json # 200
171
+ ```
172
+ File-presence is necessary but not sufficient — SPAs render client-side from the
173
+ fixture, so only a headless-Chromium render proves the page composes (and didn't fall
174
+ back to a default scenario). Run Playwright with `env -u NODE_OPTIONS` (a cmux
175
+ `--require` in `NODE_OPTIONS` crashes node from the repo cwd).
176
+ 6. **Rollback if verify fails** — restore the snapshot to the exact pre-deploy state:
177
+ ```sh
178
+ ssh <host>.exe.xyz 'rm -rf /srv/<app>/dist && mv /srv/<app>/dist.bak-<date> /srv/<app>/dist'
179
+ ```
180
+ Keep the snapshot until the deploy is confirmed good, then prune it.
181
+
182
+ > **`build:site` DOES include the app's components** (a pre-deploy worry, disproven
183
+ > 2026-06-08). AdiaUI apps are Light-DOM / no-bundle — components live in
184
+ > `app/.../src/components/` (the **source** tree), which `build:site` copies wholesale,
185
+ > so the SPA is fully renderable in `dist/`. Presence ≠ render, though; step 5's
186
+ > render-check is still the proof.
187
+ >
188
+ > **The one exception — `@adia-ai/llm` (2026-06-09):** llm is NOT a source-tree
189
+ > component; it **builds its JS at publish** (gitignored outputs), so `build:site` copies
190
+ > nothing for it in a fresh worktree and `/packages/llm/index.js` 404s → component
191
+ > registration breaks site-wide. Run `npm run build -w @adia-ai/llm` **before** `build:site`
192
+ > (step 1 above). This is exactly why step 5 render-checks a **`/site/components/*`** page,
193
+ > not just a fixture file — the 404 is invisible to file-presence and to the SPA shell.
194
+
195
+ If `server.js` changed:
196
+
197
+ ```sh
198
+ rsync -a server.js <host>.exe.xyz:/srv/<app>/server.js
199
+ ssh <host>.exe.xyz 'sudo systemctl restart <app>'
200
+ ```
201
+
202
+ ## Playbook: rotate secrets
203
+
204
+ ```sh
205
+ ssh <host>.exe.xyz 'sudo vim /etc/<app>.env && sudo systemctl restart <app>'
206
+ ```
207
+
208
+ No rebuild, no redeploy. The static bundle never sees keys.
209
+
210
+ ## Playbook: diagnose
211
+
212
+ When the site is down or returning 502, start here — everything is read-only:
213
+
214
+ ```sh
215
+ ssh <host>.exe.xyz '
216
+ echo "=== caddy ==="
217
+ systemctl is-active caddy; systemctl status caddy --no-pager | head -10
218
+ echo "=== app service ==="
219
+ systemctl is-active <app>; journalctl -u <app> -n 30 --no-pager
220
+ echo "=== listening ports ==="
221
+ sudo ss -tlnp | grep -E ":(8000|3456|80|443)"
222
+ echo "=== caddy syntax check ==="
223
+ sudo caddy validate --config /etc/caddy/Caddyfile
224
+ echo "=== disk ==="
225
+ df -h /
226
+ '
227
+ ```
228
+
229
+ Common failures:
230
+
231
+ | Symptom | Likely cause | Fix |
232
+ | ------------------------------- | ---------------------------------------------- | ------------------------------------------------- |
233
+ | "Port 8000 unbound" page | Caddy not listening on `:8000` | Check Caddyfile header is `:8000` not `:80` |
234
+ | 502 on `/api/*` | `<app>` service down or wrong port | `systemctl status <app>`; tail journalctl |
235
+ | 500 from `/api/llm/*` | Missing/invalid API key | Check `/etc/<app>.env`, restart service |
236
+ | Static assets 404 | `rsync --delete` ran with wrong source | Rebuild local `dist/`, push again |
237
+ | Site serves a stale build (new fixtures 404, SPA shows a default scenario) | `deploy:site` never run after the merge — it's **manual**, not on the release pipeline | Run the hardened `--delete` sequence; verify the fixture **file**, not the route |
238
+ | Caddy won't reload | Syntax error in Caddyfile | `sudo caddy validate --config /etc/caddy/Caddyfile` |
239
+
240
+ ## Invariants
241
+
242
+ - **Secrets never flow through agent context.** The agent should `sudo vim` *or* pause and let the human seed `/etc/<app>.env`. Never `echo "sk-..." > /etc/<app>.env` in a Bash call.
243
+ - **Caddy binds `:8000`**, not `:80` or `:443`.
244
+ - **`--delete` on rsync is scoped to the webroot only** (`/srv/<app>/dist/`). Never rsync-delete against `/srv/<app>/` or the VM's home.
245
+ - **Snapshot the webroot before any `--delete` deploy.** `cp -al /srv/<app>/dist /srv/<app>/dist.bak-<date>` is the only rollback for the 3,500+ files a fresh `--delete` prunes. Dry-run and adjudicate every delete before you send.
246
+ - **Verify a fixture FILE, never the route.** `curl /` returns `200` even when the site is stale (the SPA serves its shell for any path); proof of a live deploy is a fixture file `200` plus a browser render-check.
247
+ - **Back up before overwriting system files.** `mv Caddyfile Caddyfile.default.bak` — not `rm`.
248
+
249
+ ## Current deployments
250
+
251
+ - `ui-kit.exe.xyz` → AdiaUI docs + demos (repo: `chat-ui`, artifacts: `deploy/`, webroot: `/srv/adia-ui/dist/`, secrets: `/etc/adia-ui.env`, service: `adia-ui.service`). Also serves the embedded-app HCC demo at `/apps/embedded-app/app`; updated only via the manual `npm run deploy:site` (`--delete` — use the hardened sequence above).
252
+
253
+ Add new hosts here as they come online.
254
+
255
+ ## Pairing with adia-ui-release
256
+
257
+ When `adia-ui-release` mode 8 (EXE deploy) hands off, this playbook owns the
258
+ deploy step. Release engineering builds artifacts; ops deploys them. See
259
+ `adia-ui-release/SKILL.md` §EXE-deploy mode for the upstream hand-off contract.
@@ -0,0 +1,210 @@
1
+ ---
2
+ date: 2026-04-27
3
+ coverage: canonical
4
+ peers:
5
+ - decisions-log.md
6
+ - architecture-md.md
7
+ - postmortem-pattern.md
8
+ primary_sources:
9
+ - Michael Nygard, "Documenting Architecture Decisions" (cognitect.com/blog/2011/11/15) — the original ADR essay
10
+ - https://adr.github.io — ADR organization (canonical hub)
11
+ - https://github.com/joelparkerhenderson/architecture-decision-record — Joel Parker Henderson's ADR catalog (most-cited examples library, actively maintained)
12
+ - https://adr.github.io/madr/ — MADR 4.0.0 (released 2024-09-17, "Markdown Any Decision Records")
13
+ - https://medium.com/olzzio/y-statements-10eb07b5a177 — Olaf Zimmermann, Y-statements (SATURN 2012)
14
+ - https://github.com/npryce/adr-tools — adr-tools CLI (lightly maintained)
15
+ - https://learn.microsoft.com/en-us/azure/well-architected/architect-role/architecture-decision-record — ADR / Decision Log canonical meaning
16
+ status: research-verified
17
+ ---
18
+
19
+ # Architecture Decision Records (ADRs)
20
+
21
+ > **One ADR captures one architectural decision and its context — *immutably*.** Decisions don't get edited; they get superseded. The newest ADR wins; older ADRs remain as history.
22
+
23
+ ## What an ADR is (and isn't)
24
+
25
+ An ADR is a **dated, numbered, status-bearing Markdown file** that captures:
26
+
27
+ - **Why** a decision was made (the problem and constraints)
28
+ - **What** was decided (the chosen path)
29
+ - **What was considered** (the alternatives and why they lost)
30
+ - **Consequences** (the trade-offs the team is signing up for)
31
+
32
+ An ADR is **not** a design doc, RFC, spec, or proposal. Those describe future work; an ADR records a *commitment that has been made*. Once accepted, it is rarely edited — instead, a new ADR supersedes it.
33
+
34
+ ## File layout
35
+
36
+ Standard:
37
+
38
+ ```
39
+ .brain/adrs/
40
+ ├── 0001-record-architecture-decisions.md
41
+ ├── 0002-use-postgres-not-mysql.md
42
+ ├── 0003-rest-not-graphql.md
43
+ ├── 0004-deprecate-redis-cache.md
44
+ └── README.md
45
+ ```
46
+
47
+ Numbering is strictly sequential. Filename pattern: `NNNN-kebab-case-title.md`.
48
+
49
+ ## The Nygard format (canonical, ~2011)
50
+
51
+ Michael Nygard's [original 2011 essay](https://www.cognitect.com/blog/2011/11/15/documenting-architecture-decisions) gave the field its first standard:
52
+
53
+ ```markdown
54
+ # 1. Record architecture decisions
55
+
56
+ Date: 2026-04-27
57
+
58
+ ## Status
59
+
60
+ Accepted
61
+
62
+ ## Context
63
+
64
+ What is the issue we're seeing that motivates this decision?
65
+
66
+ ## Decision
67
+
68
+ What is the change we're making?
69
+
70
+ ## Consequences
71
+
72
+ What becomes easier or harder because of this change?
73
+ ```
74
+
75
+ Five sections: Title, Date, Status, Context, Decision, Consequences. Short and disciplined.
76
+
77
+ ## Status values
78
+
79
+ The set is small and load-bearing:
80
+
81
+ | Status | Meaning |
82
+ |---|---|
83
+ | `Proposed` | Drafted, under discussion, not yet accepted |
84
+ | `Accepted` | Decided. The team is committed. |
85
+ | `Rejected` | Considered and not adopted. Recorded so it doesn't get re-proposed without context. |
86
+ | `Deprecated` | No longer active but not yet replaced |
87
+ | `Superseded by ADR-NNNN` | Replaced by a newer decision |
88
+
89
+ ## ADR vs Architecture Decision Log (ADL) — canonical meaning
90
+
91
+ The widely-cited industry view (Microsoft Azure Well-Architected Framework, AWS Prescriptive Guidance, adr.github.io):
92
+
93
+ > "An Architectural Decision Record (ADR) captures a single AD and its rationale; **the collection of ADRs constitutes the decision log.**"
94
+
95
+ So the canonical "decision log" is **the index of all ADRs** in `.brain/adrs/`, not a separate folder. Generate it from filenames + status fields, or maintain `.brain/adrs/README.md` as a hand-written index.
96
+
97
+ Some teams *additionally* maintain a lighter `.brain/decisions/` folder for non-architectural decisions (tooling picks, library swaps, day-to-day commitments). That's a **team convention, not industry standard** — but it's a useful split when ADRs feel too heavyweight for routine choices. The audit should detect both shapes and not flag either as wrong; just note which convention is in play.
98
+
99
+ ## MADR 4.0.0 (Markdown Any Decision Records)
100
+
101
+ MADR ([adr.github.io/madr](https://adr.github.io/madr/)) is the current canonical structured variant. Released **4.0.0 on 2024-09-17** with a notable rename: the *A* now stands for *Any* (was *Architectural*) — explicitly broadening scope to non-architectural decisions. Templates: `adr-template.md`, `adr-template-minimal.md`, `adr-template-bare.md`. **YADR** (YAML ADRs) added March 2026.
102
+
103
+ MADR adds:
104
+
105
+ - `Deciders:` (who decided)
106
+ - `Consulted:` / `Informed:` (who else was looped in)
107
+ - More explicit "Considered Options" with pros/cons per option
108
+
109
+ ```markdown
110
+ ---
111
+ status: accepted
112
+ date: 2026-04-27
113
+ deciders: alice, bob
114
+ consulted: data-team
115
+ informed: engineering-all
116
+ ---
117
+
118
+ # Use Postgres, not MySQL
119
+
120
+ ## Context and Problem Statement
121
+
122
+ We need a relational database for the user-account service.
123
+
124
+ ## Decision Drivers
125
+
126
+ - Mature JSONB support
127
+ - Strong concurrency story
128
+ - Existing team skills
129
+
130
+ ## Considered Options
131
+
132
+ - Postgres
133
+ - MySQL
134
+ - SQLite
135
+
136
+ ## Decision Outcome
137
+
138
+ Chosen: **Postgres**, because of JSONB + concurrency + team skills.
139
+
140
+ ### Consequences
141
+
142
+ - Good: rich query power, strong type system
143
+ - Bad: ops overhead vs SQLite
144
+
145
+ ## Pros and Cons of the Options
146
+
147
+ ### Postgres
148
+ - Good: ...
149
+ - Bad: ...
150
+
151
+ ### MySQL
152
+ - Good: ...
153
+ - Bad: ...
154
+ ```
155
+
156
+ MADR's structure scales better to larger teams and audit trails. Nygard's brevity is right for smaller teams. Pick one and stick with it.
157
+
158
+ ## Y-statements (Zimmermann)
159
+
160
+ A concise alternative format positioned by adr.github.io as current best practice. Single-sentence form:
161
+
162
+ > *"In the context of `<use case / user story>`, facing `<concern>` we decided for `<option>` and neglected `<other options>`, to achieve `<system qualities>` / `<desired consequences>`, accepting `<downside / undesired consequences>`."*
163
+
164
+ Origin: Olaf Zimmermann, SATURN 2012. Useful as a one-line summary line at the top of a longer ADR, or as the entire ADR for small reversible choices. Pairs well with MADR.
165
+
166
+ ## Tooling (April 2026)
167
+
168
+ - **`adr-tools`** by Nat Pryce: https://github.com/npryce/adr-tools — Bash CLI; **lightly maintained** as of April 2026 (no recent releases; MADR-support PR #43 was rejected for maintenance burden). Still functional for the ADR-creation workflow it was built for.
169
+ - **`adr-log`**: generates a Markdown index from a folder of ADRs.
170
+ - **`log4brains`**: web-based ADR browser; check current maintenance state before adopting.
171
+ - **`adr-manager`**: web-UI ADR editor.
172
+ - **For new projects, no tool is required.** `mkdir -p .brain/adrs && cp ~/.adr-templates/madr-minimal.md .brain/adrs/0001-record-architecture-decisions.md` is enough. Tooling adds friction; many teams now skip it.
173
+
174
+ ## How AGENTS.md should reference ADRs
175
+
176
+ In the `Where to find things` section:
177
+
178
+ ```markdown
179
+ - **Architecture Decision Records:** `.brain/adrs/` — newest-first; read before making architectural changes
180
+ ```
181
+
182
+ In the `Memory primitives` section:
183
+
184
+ ```markdown
185
+ - **Before making architectural decisions**, read `.brain/adrs/` newest-first. If your proposed change conflicts with an `Accepted` ADR, write a new ADR superseding it; don't silently override.
186
+ ```
187
+
188
+ ## Common anti-patterns
189
+
190
+ - **No `.brain/adrs/` folder at all** — decisions live in random PR descriptions, Slack, code comments. Memory fragmentation.
191
+ - **ADRs as RFCs** — files marked `Proposed` that never get marked `Accepted` or `Rejected`. Status drift.
192
+ - **Editing accepted ADRs** — defeats the audit trail. Edits should be supersessions instead.
193
+ - **No `Status:` field** — readers can't tell what's current.
194
+ - **Mixed numbering schemes** — `001-foo.md`, `2-bar.md`, `0003-baz.md`. Pick `NNNN-` four-digit and stick with it.
195
+ - **No ADR for the introduction of ADRs themselves** — the first ADR (`0001`) should be "Record architecture decisions" so the practice itself is decided.
196
+
197
+ ## Audit checks for ADRs
198
+
199
+ 1. **Folder exists** at `.brain/adrs/` (or close — `.brain/architecture/decisions/`, `adrs/`, etc.).
200
+ 2. **Numbering is consistent** (`NNNN-` four-digit, sequential).
201
+ 3. **Each ADR has a `Status:` field**.
202
+ 4. **No ADRs are in `Proposed` for >30 days** (probably abandoned — flag).
203
+ 5. **`.brain/adrs/` is referenced from AGENTS.md**.
204
+
205
+ ## Cross-references
206
+
207
+ - Decision log (looser): `decisions-log.md`
208
+ - Architecture overview: `architecture-md.md`
209
+ - Adding ADRs to existing repo: `../recipes/adr-introduction.md`
210
+ - Memory organization: `../recipes/memory-organization.md`
@@ -0,0 +1,190 @@
1
+ ---
2
+ date: 2026-04-27
3
+ coverage: canonical
4
+ peers:
5
+ - adr-pattern.md
6
+ - decisions-log.md
7
+ - changelog.md
8
+ primary_sources:
9
+ - https://matklad.github.io/2021/02/06/ARCHITECTURE.md.html — Aleksey Kladov (matklad), "ARCHITECTURE.md" (the canonical pattern essay, Feb 2021)
10
+ - https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/architecture.md — rust-analyzer's ARCHITECTURE.md (the canonical example)
11
+ - https://github.com/sourcegraph/sourcegraph/blob/main/doc/dev/background-information/architecture/index.md — Sourcegraph's adoption of the pattern
12
+ - https://learn.microsoft.com/en-us/azure/well-architected/architect-role/architecture-decision-record — Microsoft Azure WAF on architecture documentation
13
+ status: research-verified
14
+ ---
15
+
16
+ # ARCHITECTURE.md — current state, in 30 minutes
17
+
18
+ > **ARCHITECTURE.md answers: "I'm new here. Where do I look first?"** Not "what did we decide?" (that's ADRs) and not "what shipped?" (that's CHANGELOG). It is a *map of the codebase as it currently is*, optimized for someone landing in the repo cold.
19
+
20
+ This pattern delivers **Promise 2 (token-and-context-optimized)** by giving an LLM agent a single high-signal entry into the codebase's structure, and **Promise 1 (less-wasteful)** by replacing the scattered "tribal knowledge" that otherwise accumulates in PR comments, Slack threads, and 3-year-old wiki pages.
21
+
22
+ ## Origin and canonical source
23
+
24
+ The pattern was named and codified by **Aleksey Kladov** (handle: *matklad*, lead author of rust-analyzer) in the February 2021 blog post [**"ARCHITECTURE.md"**](https://matklad.github.io/2021/02/06/ARCHITECTURE.md.html). The canonical exemplar is rust-analyzer's own [`docs/dev/architecture.md`](https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/architecture.md).
25
+
26
+ Kladov's framing:
27
+
28
+ > "Looking at someone else's code is hard, but very useful sometimes. The best help for an outsider is a single document, a map, which describes the *bird's-eye view* of the project, and explains how to navigate the code."
29
+
30
+ The pattern has spread widely — Sourcegraph, Tantivy, hyperqueue, ripgrep, and many others use a doc by the same name (or `architecture/` folder with the same shape).
31
+
32
+ ## What ARCHITECTURE.md *is* (and what it's not)
33
+
34
+ | ARCHITECTURE.md | Not ARCHITECTURE.md |
35
+ |---|---|
36
+ | Current state of the system | History of how it got here (→ git log, ADRs) |
37
+ | Map of the codebase ("Module X lives at `src/x/`") | Decision rationale ("Why did we pick X?" → ADRs) |
38
+ | 30-minute onboarding | Comprehensive technical reference (→ separate docs) |
39
+ | Names directories and the responsibility of each | Lists every file (→ tooling) |
40
+ | Cross-cutting concerns (concurrency model, error handling, lifetime) | API documentation (→ generated docs) |
41
+ | Non-obvious intentional choices ("we deliberately don't use X") | Future plans (→ ROADMAP.md) |
42
+ | Updated when architecture changes | Updated weekly (→ PLAN.md) |
43
+
44
+ The discipline is: **document things that won't change much, that an experienced engineer would still want explained.** Module purpose, layering, where-data-flows-from-input-to-output, how-tests-are-organized, what-not-to-do.
45
+
46
+ ## The 30-minute onboarding shape
47
+
48
+ Kladov's recommended sections (with this skill's annotations):
49
+
50
+ ### 1. Bird's-eye view
51
+
52
+ One paragraph or one diagram. What does this project *do*? Who calls it, what does it call?
53
+
54
+ ```markdown
55
+ ## Bird's-eye view
56
+
57
+ `acme-cli` is a Rust binary that reads YAML config from `acme.yaml`,
58
+ queries an HTTPS API, and writes Markdown reports to stdout. It has
59
+ no persistent state. It is invoked from CI in the user's repo.
60
+ ```
61
+
62
+ If a diagram clarifies — use one. ASCII boxes are fine; Mermaid is fine; an image is fine. Don't gold-plate.
63
+
64
+ ### 2. Code map
65
+
66
+ The load-bearing section. **For each top-level directory, one paragraph: what's in it, what's the responsibility, where the boundaries are.**
67
+
68
+ ```markdown
69
+ ## Code map
70
+
71
+ ### `src/cli/`
72
+ Argument parsing (clap), command dispatch. No business logic — delegates to `src/core/`.
73
+
74
+ ### `src/core/`
75
+ The orchestrator. Reads config, fans out to API client, aggregates results. **The only module allowed to depend on both the config layer and the API layer.**
76
+
77
+ ### `src/api/`
78
+ HTTP client (reqwest). One module per endpoint group. Adding a new endpoint? Look here.
79
+
80
+ ### `tests/`
81
+ Integration tests. Use the `wiremock` fixture, not real HTTP.
82
+ ```
83
+
84
+ A reader (human or agent) can immediately answer: *"I want to add a new API endpoint. Where?"*
85
+
86
+ ### 3. Cross-cutting concerns
87
+
88
+ Things that span modules and aren't inferable from the code map.
89
+
90
+ ```markdown
91
+ ## Cross-cutting concerns
92
+
93
+ - **Error handling**: `anyhow::Error` everywhere except `src/api/` (typed errors). See ADR-0007.
94
+ - **Concurrency**: single-threaded by default; `--parallel N` spawns tokio. Only `src/core/parallel.rs` knows async.
95
+ - **Logging**: `tracing`, structured JSON. `RUST_LOG` configures.
96
+ ```
97
+
98
+ ### 4. Non-obvious intentional choices
99
+
100
+ The "we deliberately don't do X" section. Saves future contributors hours.
101
+
102
+ ```markdown
103
+ ## Things we deliberately don't do
104
+
105
+ - **No async by default.** Tokio startup dominated benchmarks. See ADR-0011.
106
+ - **No plugin system.** Rejected (ADR-0014).
107
+ - **No config format other than YAML.** TOML support was removed in v1.2.0.
108
+ ```
109
+
110
+ ARCHITECTURE.md *summarizes* the decision and points at the ADR for *why*.
111
+
112
+ ### 5. Where to look first
113
+
114
+ The newcomer's quick-start. Optional but high-value for LLM agents — it's a routing table for common tasks.
115
+
116
+ ```markdown
117
+ ## Where to look first
118
+
119
+ - **Adding a CLI flag?** `src/cli/args.rs`, then dispatch in `src/cli/mod.rs`.
120
+ - **Adding an API endpoint?** `src/api/`. Mirror an existing endpoint.
121
+ - **Investigating a CI failure?** `tests/integration/` first, then logs.
122
+ - **Performance regression?** `benches/` and `cargo bench`.
123
+ ```
124
+
125
+ ## Length and ergonomics
126
+
127
+ Kladov's own rust-analyzer ARCHITECTURE.md is ~600 lines. That's at the upper end. **For most repos, 200–400 lines is right.**
128
+
129
+ Under 100 lines → probably missing the code map.
130
+ Over 800 lines → split. Move detail into per-module READMEs (`src/api/README.md`) and keep ARCHITECTURE.md as the bird's-eye + index.
131
+
132
+ This skill's general guidance: **entry-level docs under ~200 lines, pushed-down detail in subdirectory READMEs.** See `../guidance/context-budget.md`.
133
+
134
+ ## Distinction from ADRs
135
+
136
+ The most-confused boundary: ARCHITECTURE.md is **present-tense, mutable, system-wide**; ADRs are **past-tense, immutable, per-decision**. ARCHITECTURE.md answers "Where does X live?"; ADRs answer "Why did we choose X?". ARCHITECTURE.md *links* to ADRs ("see ADR-0007"), never duplicates them.
137
+
138
+ ## Update discipline
139
+
140
+ ARCHITECTURE.md goes stale faster than ADRs and slower than PLAN.md. Recommended cadence:
141
+
142
+ 1. **PR-level**: any PR that adds, renames, or removes a top-level directory must update ARCHITECTURE.md in the same PR. Enforce with a CI check or a CODEOWNERS rule. See `../recipes/self-healing-hooks.md`.
143
+ 2. **Quarterly review**: a maintainer re-reads ARCHITECTURE.md against the current tree and patches drift.
144
+ 3. **LLM-on-diff**: when a large refactor lands, run an LLM-on-diff pass against ARCHITECTURE.md to flag suspect sections. See `../audit-patterns/staleness-tooling.md`.
145
+
146
+ ## How AGENTS.md links ARCHITECTURE.md
147
+
148
+ In the `Where to find things` section:
149
+
150
+ ```markdown
151
+ - **Architecture:** `ARCHITECTURE.md` — start here if you're new to the codebase
152
+ ```
153
+
154
+ In the `Memory primitives` section:
155
+
156
+ ```markdown
157
+ - **Before making changes that span multiple modules**, read `ARCHITECTURE.md` for the code map and cross-cutting concerns. Architecture-altering changes also require a new ADR.
158
+ ```
159
+
160
+ `ARCHITECTURE.md` at repo root is the recommended location (matklad's pattern). Avoid `.brain/architecture/index.md` unless you have a folder full of related docs.
161
+
162
+ ## Audit checks
163
+
164
+ 1. **File exists** at `/ARCHITECTURE.md` (repo root, per matklad).
165
+ 2. **Code map covers all top-level src directories.** Diff `ls src/` against the headings in the code map; missing entries = staleness.
166
+ 3. **No directory mentioned in the code map is missing from disk.** Renames or removals that didn't update the doc.
167
+ 4. **Length is in 100–800 range.** Both extremes are flagged.
168
+ 5. **AGENTS.md references ARCHITECTURE.md**, not just `.brain/`.
169
+ 6. **`Last reviewed:` line or YAML `date:` is within the last 180 days.** Older = quarterly review missed.
170
+
171
+ ## Common anti-patterns
172
+
173
+ - **No ARCHITECTURE.md** — newcomers and agents navigate by `ls` and pattern-match. Slow.
174
+ - **Feature list, not a code map** — describes what the product does, not how it's built.
175
+ - **History, not present-tense** — narrates evolution. That's a blog post.
176
+ - **Duplicates ADR content** — copy-pasted "why" rationale. Link to the ADR instead.
177
+ - **Alphabetical code map** — group by responsibility (core → adapters → entry-points).
178
+ - **Stale code map** — directories renamed in code, not in the doc. Catch with the audit.
179
+ - **Outsourced to a wiki** — agents can't read Confluence; drift is guaranteed. Keep it in the repo.
180
+
181
+ ## Cross-references
182
+
183
+ - ADR pattern (decisions, not state): `adr-pattern.md`
184
+ - Decision log (collection of ADRs): `decisions-log.md`
185
+ - Changelog (shipped, not state): `changelog.md`
186
+ - Plan / roadmap (planned, not state): `plan-roadmap.md`
187
+ - Self-healing PR-gate hooks: `../recipes/self-healing-hooks.md`
188
+ - LLM-on-diff staleness detection: `../audit-patterns/staleness-tooling.md`
189
+ - Context budget guidance (200-line target): `../guidance/context-budget.md`
190
+ - AGENTS.md "Where to find things" section: `../standards/agents-md-spec.md`