ADR-0009: One knowledge monorepo, folders per project, promote to core
- Status: Accepted
- Date: 2026-06-05
- Scope: core (the handbook itself)
Context
This repo began as expenses-knowledge, the shared brain for one product. A
second project is starting, and it should reuse every non-business decision
already made (git flow, architecture skeletons, i18n discipline, mobile-first,
…). Three storage shapes were considered:
- A knowledge repo per project — multiplies repos, scatters decisions, and
makes “have we solved this before, in any project?” unanswerable in one place. - A documentation platform (Notion, Docmost) — nice reading UI, but the
primary consumer of these docs is the AI assistant, which needs plain files
in a working tree (grep, no auth, no rate limits, offline in headless runs).
Moving the brain behind an API breaks the curator agent, hooks, and skills. - One git monorepo of knowledge, partitioned by folders — chosen.
Branch-per-project partitioning was explicitly rejected: branches are for
divergent versions that converge, not for permanently parallel content. They
prevent seeing the whole brain in one tree, break cross-project links and
search, and turn promotion into cherry-picks.
Decision
This repo — dev-handbook — is the single knowledge monorepo for all
projects:
docs/
├── core/<area>/ ← generic decisions (workflow, backend, frontend, infra)
├── <project>/<area>/ ← project-scoped decisions (e.g. expenses/)
kit/
├── core/ ← plugin "handbook" — generic skills/agents (handbook:*)
└── <project>/ ← per-project plugin (e.g. expenses:*)
- Decisions are born project-scoped and promoted to
core/when they
prove generic (or a second project wants them). Promotion =git mv+ a
generalization pass; the project’s specifics stay as illustrations. - ADR numbering: the handbook’s own sequence is global (0001…, this doc is
0009, next is 0010); ADR sets imported from code repos keep their original
numbers inside their folder (e.g.expenses/backend/0001-…). Full filenames
(number + slug) stay unique handbook-wide, and a doc keeps its number when
promoted between folders. - Wikilinks are filename-based (
[[0001-three-step-git-flow]], no folder
prefix) so links survive promotion moves. - Code repos keep no
docs/adr/of their own — their ADRs live here under
the project’s folder, and each code repo’sCLAUDE.mdpoints here. Trade-off
accepted: doc edits no longer ride in the same commit as the code they govern. - Generic kit skills are manifest-driven, not duplicated per project: a
handbook.jsonat each workspace root declares the project’s repos, version
files, and locale paths; skills read it instead of hardcoding repo names. - Reading UX is solved by rendering, not migrating: a static site (Quartz)
built fromdocs/, deployed like any other frontend. Git stays the single
source of truth.
Consequences
- One place to ask “how do we do X?” — for humans (rendered site / Obsidian
vault) and for the assistant (grep). - New projects start by installing the
handbookplugin and adding a
docs/<project>/folder +handbook.jsonmanifest — every core decision is
inherited for free. - The handbook repo becomes a dependency of every project’s workflow; it keeps
the same three-step git flow and approval gates as any code repo. - Cross-project content lives further from the code it governs; the
docs-curatoragent is the drift watchdog.
Related
- 0001-three-step-git-flow — the flow this repo itself follows
- 0003-collaboration-working-agreements — “one decision, one home” now means
this structure