- Date: 2026-06-18
- Status: Accepted (codifies existing convention; now load-bearing)
- Phase / Feature: Studio architecture
- Supersedes: the prose rule in
Rules.md§"Studio tools — documentation pattern" (kept as a pointer to this ADR)
Context
Studio is a growing umbrella of editor tooling under apps/web/src/dev-tools/studio/. As of this ADR there are eight live or scaffolded tools (layers, nav-bar, sidebar, punta, dito, adaptive, canvas, passo, tela) and at least seven more planned (palette, publish, share, theme, view-mode, history, cmd-palette). The scaling problem is real: without a binding documentation shape, every new tool re-invents what to write, where to write it, and what to leave out. After three or four tools we have already seen sample drift:
- Two tools described "what it does" in three different prose tones.
- Telemetry sections diverged on payload-naming conventions (
camelCasevssnake_case). - One tool's
glossary.mdomitted "Pure module" while another's listed it as a single line; the term means the same thing in both.
The cost compounds. Every new tool adds one more place a contributor must learn from scratch. A binding shape pays off the first time we use it (consistency) and pays compound interest from then on (every reader knows where to look for which question).
The shape we converged on is the Material + Carbon Design System playbook: a per-component / per-tool folder with a fixed file set covering README, navigator, architecture, contract, invariants, integration, API reference, telemetry, testing, migration, scenarios, glossary. Industry-tested. Reviewers from outside ARNO recognise it on sight.
Decision
Every tool under apps/web/src/dev-tools/studio/<tool>/ is documented by an 11-file canonical set in docs/<tool>/. The shape is non-negotiable. No exceptions for "small" or "obvious" tools.
The 11 files (plus _index.md for navigation — 12 total)
| File | Role |
|---|---|
README.md | Entry point: what the tool is, audience, strategic role, what it does / does not do, code map, doc map, quick start, roadmap, governance. |
_index.md | Navigator: when to open this folder, what to read first per scenario, code links, governance TL;DR. |
architecture.md | Mental model, core problem, solution, data flow, surfaces, module map, state boundaries, performance, coupling map. |
contract.md | What a consumer / surface / variant must provide. Types, registration shape, capability flags, versioning policy. |
invariants.md | Guarantees and laws — what cannot happen. Each invariant lists protection + test reference. |
integration.md | Spread checklist for adding the tool to a new surface or variant. Step-by-step, prerequisites, smoke checklist. |
api-reference.md | Every public function, type, and event. Signatures + parameters + returns + examples. |
telemetry.md | Event schema, payload shapes, digest pipeline, interpretation guide, privacy, extension procedure. |
testing.md | TDD policy, layers (per docs/testing-standard.md), coverage targets, CI gates, scenario authoring rules. |
migration.md | Contract versioning, breaking-change policy, upgrade-function shape, schema-version tag rules. |
scenarios.md | Catalogue of regression scenarios with source attribution (chat report / spec rule / ADR §). |
glossary.md | Terminology lock — every domain term used in the tool's docs and code. |
Code folder rule
The corresponding code folder (apps/web/src/dev-tools/studio/<tool>/) carries only code — no pointer .md files. The naming convention studio/<tool>/ ↔ docs/<tool>/ is the discovery contract; an extra pointer file duplicates state and goes stale. Until a tool has its first code file, the code folder does not exist at all; it appears with the first implementation commit.
Umbrella manifest
apps/web/src/dev-tools/studio/_index.md is the single Studio map. It enumerates active + planned tools, their docs locations, the shared kernel, and the dependency graph between tools.
Language
All Studio docs follow the repo-wide §"Language" rule in Rules.md — English.
When this applies
- Creating a new Studio tool folder under
apps/web/src/dev-tools/studio/<tool>/→ createdocs/<tool>/with all 12 files (11 canonical +_index.md) in the same PR. - Splitting an existing tool into two → each half gets its own 12-file set, the old set is archived under
docs/<old>/_archived/. - A tool with empty / stub content per file is acceptable on day 1 (
# scenarios — none yet, will grow with bug reports) — but the file must exist so the structure is discoverable.
Anti-patterns (forbidden)
- Documenting a tool only in code comments.
- Single mega-
README.mdcovering everything. - Adding a 12th non-canonical file (
design-notes.md,history.md,decisions.md). Fold the content into the matching canonical file or push it to an ADR. - Skipping
glossary.mdbecause "everyone knows what it means". The glossary protects against terminology drift across tools.
Enforcement
This ADR's pattern is enforced by three mechanisms working together:
- PR review. A new tool without all 12 files is rejected at review.
- AutoTests hook (
Tools/AutoTests/run.sh,struct_index_exists) — fires PreToolUse-style and requires_index.md+README.mdin every folder that contains any.mdfile. This catches the common error of creating a folder with one or two files. - CI workflow (
scripts/check-doc-completeness.ts,.github/workflows/check-docs.yml) — runs on every PR. Fails the build when:docs/<tool>/exists but is missing any of the 12 canonical filesapps/web/src/dev-tools/studio/<tool>/exists butdocs/<tool>/is missing- A
docs/<tool>/folder contains a 13th non-canonical.mdfile - A cross-reference (
see docs/X/Y.md) points at a missing file
The CI workflow is the authoritative mechanism. The other two are early-warning systems.
Consequences
Positive
- Consistency. Every reader knows: "the contract is in
contract.md, the guarantees are ininvariants.md". No more "where did they put it this time?". - Faster onboarding. A new contributor opens one tool's folder and sees the full surface. After reading two, they know the shape; the third is trivial.
- Cross-tool comparison is mechanical. Diff
docs/punta/contract.mdagainstdocs/dito/contract.mdto compare two tools' contracts side-by-side. The shape lines up; only the content differs. - Migration / refactor is mechanical. Renaming a tool =
git mv docs/<old> docs/<new>+ grep cross-refs. The shape transfers. - Drift detection is mechanical. A tool whose
migration.mdsays1.0.0but whosecontract-version.tssays2.0.0is caught by review at a glance.
Negative
- Boilerplate cost. A new tool requires 12 files even when 8 of them are placeholder stubs. The "empty stub day 1" rule mitigates this — but it is still ~3 hours of typing.
- Density tax. Junior contributors can drown in the doc surface. We accept this; the alternative (ad-hoc docs per tool) is worse at scale.
- Maintenance lag. When code outpaces docs, the 12-file shape makes the gap visible. This is actually a feature (the gap is obvious), but it requires discipline to close.
Risk: doc-as-LARP
The biggest failure mode is treating the docs as a checklist instead of a contract. A tool with all 12 files but vacuous content satisfies the structural check and fails the actual purpose. Mitigation: PR review requires that invariants.md contains at least one invariant with a test reference, contract.md describes at least one mandatory registration, and scenarios.md cites at least one source. The CI check (planned v2) will parse for these signals.
Alternatives considered
- Single
docs/studio.mdcovering everything. Rejected — the per-tool shape makes cross-tool comparison and renaming much easier. - One
<tool>.mdper tool (flat docs). Rejected — concatenates all twelve concerns into one file, defeating searchability. - Doc inside the code folder (
studio/<tool>/docs/*.md). Rejected — see ADR 0060. - Adopt Material Design's exact file naming (
overview.mdinstead ofREADME.md, etc.). Rejected —README.mdis what GitHub renders by default; we keep the GitHub UX.
Open questions
- How do we version the canonical set itself? Today the file list is fixed at 12. If we add a 13th canonical file (e.g.
accessibility.md), every existing tool must add it. Plan: when this trigger fires, open a separate ADR amending the file set and the CI script in the same PR.
References
- Industry: Material Design Components, IBM Carbon DS, Atlassian DS, Shopify Polaris — all ship per-component doc folders with a fixed file set.
- Cross-refs in repo:
Rules.md§"Studio tools — documentation pattern" (the prose form that points to this ADR),CLAUDE.md(mentions the rule),docs/testing-standard.md(referenced from §Tests of every Studio tool'stesting.md). - Related ADRs: 0059 (naming chord), 0060 (docs/code separation).