zingo-adrs holds the architecture decision records for every zingolabs code repository. "Architecture" reads broadly: any decision that shapes how a repository is built, tested, or released belongs here, whether it concerns system structure, process, or infrastructure.
A record's path says which repositories it binds.
- An org-scoped record binds every code repository. It lives at the top
level, numbered
NNN. - A repo-scoped record binds exactly one code repository. It lives in
that repository's subdirectory (
zaino/for zaino), numberedNNNN.
Each scope numbers its records in its own sequence. Take the next free number when proposing; concurrent proposals may collide, so renumber at merge, not before. A gap in a sequence means a proposal was abandoned or renumbered, nothing more.
Inside zingo-adrs, a bare ADR-NNNN cites a record in the citing record's own
scope. A citation into another scope carries the path: zaino/0016 names the
zaino record, and 003 names the org-scoped one.
A code repository chooses the form by medium. A source comment names the
repository and the scope, as in zingo-adrs zingolib/0011, because its reader
may see it outside a checkout. Rendered Markdown links the record's file on the
dev branch of zingo-adrs, as in
https://github.com/zingolabs/zingo-adrs/blob/dev/zaino/0016-changeset-derived-release-pipeline.md,
but only for a merged record, whose number no longer changes.
Markdown cites a record whose pull request is still open in the
source-comment form, without a link.
Neither medium cites a checkout path such as docs/adr/zingolib/0011-…, which
resolves only after the submodule is initialised and which GitHub cannot follow.
Records are append-only. Supersede, never delete or rewrite: a reversed decision gets a new record, and the old record's status names its successor. A record documents the decision as made and does not track the code, so "the code changed" is never a reason to remove one.
A record is a Markdown file named NNN-kebab-title.md (or NNNN- in a
repository scope) whose first line is a # title. The first line under its
## Status heading is exactly one of:
accepted, from the pull request that proposes the record onward. The merge is the acceptance, so the line is written once and not edited afterwards to say so;proposed, for a record merged to put an idea on the record before it is final. It binds nothing. A later pull request moves it toacceptedor supersedes it;superseded by [<citation>](<relative path to the successor>).
Prose after that line may narrow a partial supersession, but the line itself is the whole record's standing. A record states one decision: context, decision, consequences. Keep it short; full governed behaviour belongs in a specification in the code repository, referenced from the record.
Open a pull request against dev in this repository. Records are never
proposed in a code repository: zingo-adrs is the sole write side, and code
repositories carry read-only copies.
docs/howto-code-repositories.md explains,
for a reader arriving from a code repository, how its docs/adr/ relates to
this repository.
A code repository holds zingo-adrs as a git submodule at docs/adr/. Only
the pointer, one commit hash, is checked in there; the records never enter
that repository's history. A code repository's scope directory here, such as
zingolib/, therefore appears at docs/adr/zingolib/ in its checkout, and
the org-scoped records sit directly under docs/adr/. To add the submodule:
git submodule add git@github.com:zingolabs/zingo-adrs.git docs/adrTo materialise the records after cloning:
git submodule update --init docs/adrTo advance the pointer to the current dev of zingo-adrs, then commit the change:
git submodule update --remote docs/adrA stale pointer is not a defect, and no code repository gates on it. The records are read-only from the code repository's side: propose changes here.
tools/workbench holds check-records, which CI runs on every pull request.
It verifies file names, the status vocabulary, that every superseded by
link resolves, that numbers are unique within a scope, and that the index
below matches the records. Regenerate the index with:
cargo run --manifest-path tools/workbench/Cargo.toml -- --write .| Number | Record | Status |
|---|---|---|
| 001 | No upstream types in public APIs | accepted |
| 002 | client_rpc_test_fixtures moves to its own repository |
accepted |
| 003 | ADR: Branching, Versioning, Documentation, Public Interfaces, and Release Strategy | superseded by zaino/0016 |
| 004 | Decision records live in zingo-adrs and are mirrored into code repositories by subtree | superseded by 005 |
| 005 | Code repositories point at zingo-adrs by submodule, and hold none of its content | accepted |