ADRs
ADR 0058 — Studio tools documentation pattern (11-file canonical set)
  • 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 (camelCase vs snake_case).
  • One tool's glossary.md omitted "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)

FileRole
README.mdEntry point: what the tool is, audience, strategic role, what it does / does not do, code map, doc map, quick start, roadmap, governance.
_index.mdNavigator: when to open this folder, what to read first per scenario, code links, governance TL;DR.
architecture.mdMental model, core problem, solution, data flow, surfaces, module map, state boundaries, performance, coupling map.
contract.mdWhat a consumer / surface / variant must provide. Types, registration shape, capability flags, versioning policy.
invariants.mdGuarantees and laws — what cannot happen. Each invariant lists protection + test reference.
integration.mdSpread checklist for adding the tool to a new surface or variant. Step-by-step, prerequisites, smoke checklist.
api-reference.mdEvery public function, type, and event. Signatures + parameters + returns + examples.
telemetry.mdEvent schema, payload shapes, digest pipeline, interpretation guide, privacy, extension procedure.
testing.mdTDD policy, layers (per docs/testing-standard.md), coverage targets, CI gates, scenario authoring rules.
migration.mdContract versioning, breaking-change policy, upgrade-function shape, schema-version tag rules.
scenarios.mdCatalogue of regression scenarios with source attribution (chat report / spec rule / ADR §).
glossary.mdTerminology 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>/ → create docs/<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.md covering 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.md because "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:

  1. PR review. A new tool without all 12 files is rejected at review.
  2. AutoTests hook (Tools/AutoTests/run.sh, struct_index_exists) — fires PreToolUse-style and requires _index.md + README.md in every folder that contains any .md file. This catches the common error of creating a folder with one or two files.
  3. 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 files
    • apps/web/src/dev-tools/studio/<tool>/ exists but docs/<tool>/ is missing
    • A docs/<tool>/ folder contains a 13th non-canonical .md file
    • 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 in invariants.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.md against docs/dito/contract.md to 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.md says 1.0.0 but whose contract-version.ts says 2.0.0 is 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.md covering everything. Rejected — the per-tool shape makes cross-tool comparison and renaming much easier.
  • One <tool>.md per 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.md instead of README.md, etc.). Rejected — README.md is 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's testing.md).
  • Related ADRs: 0059 (naming chord), 0060 (docs/code separation).