Packages

development-driven-specs — the dds toolchain (protocol 2) as a Mix task. A thin shim over the bundled instruments (Python, stdlib); never a port.

Current section

Files

Jump to
dds priv toolchain canon principles.md
Raw

priv/toolchain/canon/principles.md

# Documentation Principles
This document is the meta-rule that governs every other non-executable
artifact in the repository. Audience: contributors and LLM agents.
Vocabulary established here is assumed by [`conventions.md`](conventions.md).
## 1. The Directive
> **Non-executable content takes one of three forms: conditional,
> snapshot, or co-maintained current-state. Anything else makes a
> present-tense claim the artifact cannot defend, and will rot.**
| Form | Example | Why it's durable |
|---|---|---|
| **Conditional** | *"When X, do Y."* | Asserts what follows from what; makes no worldly claim. Truth-value independent of the world's state. |
| **Snapshot** | *"On date T, the team decided X because Y."* | A claim about a past moment. The moment is over; the claim is permanent regardless of present state. |
| **Co-maintained current-state** | *"This module routes events to handlers."* (in a module-level docstring) | Present-tense assertion *proximate enough to the code* that contributors update both together. Durable through maintenance gradient, not logical immunity. |
The **forbidden form** is the uncoupled present-tense assertion: prose
description of how the system, world, or business currently is, written
in a location no contributor reliably maintains alongside the relevant
code. README architecture descriptions, freestanding design docs in
present tense, and inline comments of the form *"this function assumes
X"* (where the hedge "assumes" smuggles a worldly claim about X) are
the canonical failure cases.
### Code is the source of truth; docs are the *why*
The directive's positive form, used as the working heuristic:
> **Code is the source of truth for what the system does. Non-executable
> artifacts exist for the *why*.**
When considering a sentence, ask *am I telling the reader something
the code cannot?* If the answer is recoverable by reading the code,
schema, test, or git history, the prose duplicates and will rot.
**Decay test:** for any sentence, ask "could this become false without
anybody noticing?" If yes, refactor to one of the three permitted
forms or delete.
### If it's a list, it's not a doc
The same heuristic applied one level up, to whole artifacts rather than
sentences. **Enumeration is structured data, not prose.** An inventory —
a row per datum, per action, per dependency, with its fields (stores,
stakes, classification, flows) — belongs in the code, the schema, or the
structured compliance feed, each of which can hold and reconcile it. A
prose document that re-lists those rows is the uncoupled present-tense
failure (§1) committed at the document scale: the structured source
moves and the prose silently lies, and no contributor reliably
maintains both.
What survives in prose is the *argument the enumeration supports* — the
claim about the **shape** of the holding that no schema row carries:
"confidentiality is the only axis that matters here," "this action's
harm is a cost, not a read," "this key extends the at-rest concern to
the credential, not just the content." A claim names the datum that
*proves* it; the datum is evidence cited, not an entry maintained. The
test for a document is therefore the decay test's sibling: *strip every
row recoverable from a structured source — is there an argument left?*
If yes, that argument is the document. If no, the document was a copy of
the register and should be deleted, its rows left to the source that
owns them.
This is why the data / capability / identity concerns here are
arguments, not rosters: each holds the few load-bearing claims about
what the app holds, can do, and mints — and cedes the enumeration to the
code and the feed.
### What these artifacts are about
The directive above is *how* you write; this is *what about*. Everything
non-executable here documents one subject — **the product** — through
three lenses:
- **What it is** — the product's purpose and the concepts it models.
Described as current-state, best-effort, carrying no source because it
appeals to no authority; it is what runs, not a claim someone signed
off (the root is [`domain/what-the-product-is.md`](domain/what-the-product-is.md)).
- **How it is realized** — what the running system holds, can do, mints,
and depends on. The enumeration is structured data (code + the
compliance feed); the prose is the argument about its *shape* (the
data / capability / identity concerns).
- **How it is guaranteed** — the decisions and obligations that make the
realization trustworthy: ADRs (cross-cutting rules, with their
reasoning) and goals (externally sourced obligations, with their
source). These keep full evidentiary weight — a decision can be wrong
and must be traceable.
The product is the subject; the three are lenses on it, not a filing
scheme — an artifact may be looked at through more than one (the session
content is both *what the product is about* and *the thing guaranteed*),
which is why this is stated as an axis of meaning, not a directory
layout. The physical layers (`domain/`, `goals/`, `adr/`) are the
*forms* these are written in, governed by the directive; they do not
have to mirror the three lenses one-to-one.
**Composition is the reader's, not the author's.** Each artifact is a
defensible atom plus its cross-references; the *posture* — the coverage
view, the lifecycle walk, the per-subject picture an auditor or an
engineer wants — is **composed by the consumer** (a person following the
links, or the compliance interface that reads the feed and the
rationale pointers), not authored here as standing prose. A hand-written
"security overview" or "current posture" document is the uncoupled
present-tense form (§1) at document scale: it restates atoms it cannot
co-maintain and rots. The repository's job is to make every atom true
and reachable; assembling them into a view is a query, not a file.
## 2. The maintenance gradient
A current-state assertion's durability is determined by **proximity to
the code it describes**, not by language or hedging. The litmus test:
*if the surrounding code changed in a way that made the assertion false,
would a contributor opening the change notice the assertion needed
updating?*
- Proximate enough: module-level docstrings, inline comments, glossary
entries near related code, current-state sections of a goal document.
- Not proximate enough: README at repo root describing module-level
architecture, separate wiki pages, design docs maintained in a
different directory or by a different team.
If proximity is weak, choose a conditional or a snapshot instead.
## 3. Three decay modes (only the first is artifact-detectable)
| Mode | What changes | Detected by |
|---|---|---|
| **Premise rot** | A worldly fact the artifact named is no longer true | Explicit `Premises:` sections; reader checks each premise against the world |
| **Logic rot** | The reasoning was flawed even at the time | Re-derivation only; no artifact catches this |
| **Priority rot** | What the team optimized for has changed | Recording priorities at the moment (`Optimized-for:` trailers) makes the shift visible when read later |
A directive-compliant artifact does not pretend to prevent any of
these. It makes the first detectable, gives readers leverage to suspect
the second, and makes the third visible by recording the priorities
that drove the decision.
## 4. The three layers
Three artifact directories, each a distinct epistemic layer:
| Layer | Path | Captures (why) | Not for (lives in code) | Authority |
|---|---|---|---|---|
| **Domain** | `docs/domain/` | Definitions, business policy, vocabulary | Schema, lifecycle, relationships | Product + domain experts |
| **Goals** | `docs/goals/` | Verbatim source quote + sourced clarifications | Paraphrased requirements lists | Product (+ external sign-off) |
| **ADRs** | `docs/adr/` | Cross-cutting rules with premises and reasoning | Application transcripts | Architecture |
Code realizes all three. Tests verify goals against the domain. Commit
messages carry per-change snapshots (original asks, rejected
alternatives) that none of the three layers absorbs directly.
**Goal layer specifics.** A goal is the *system-mediated contract*
between user intent and current realization — neither a feature
("the orders dashboard") nor a pure intent ("operators want their
books to balance"). Above the goal level, content becomes a value-level
principle (write an ADR). Below the goal level, content becomes
realization (write code).
**Not every change has a goal.** Goals exist for work derived from
external authority (product, customer, regulator, domain expert).
Internal refactors, dev tooling, dependency bumps, and engineering-
initiated technical decisions do not produce goal entries. If the
answer to *"who outside engineering authorized this?"* is "nobody,"
the work routes elsewhere — likely an ADR (if cross-cutting) or just
a code change.
**Multiple goals per file.** Goal files are grouped by area
(`docs/goals/<area>.md`); each goal is a `## Goal:` block within. The
file is the unit of grouping; each goal block is the unit of identity.
**Layer interactions.** Goals reference domain entries (vocabulary they
lean on) and conform to ADRs (constraints they must satisfy). ADR
premises often cite domain facts. The cross-references are explicit
file paths.
## 5. Sources, authority, and the requirement-as-premise
A requirement is a premise — a load-bearing current-state claim — with
one property technical premises lack: it has been **signed off** by an
authority. The world cannot falsify a requirement; only the source can
retract it.
Every requirement-bearing document carries three elements:
- **Statement and source quote** in the file. The file must be
self-readable; a goal whose source is only in `git blame` is
indistinguishable from a fabricated goal until someone runs the
blame.
- **Per-modification attribution** in the commit log via trailers
(`Original-ask:`, `Source:`, etc.). Answers "who modified this
file when, from what request."
- **Enforcement** in tests.
CODEOWNERS makes source authority structural at the modification
layer; the PR approval log is the durable proof.
### 5.1 Sourcing under uncertainty
When a requirement's source cannot be determined with confidence,
**ask** — do not infer. A fabricated source signs off authority on
behalf of someone who has not signed off, and CODEOWNERS amplifies the
fabrication because subsequent reviewers trust it. For LLM agents
specifically: if the source is not in the conversation or in linked
artifacts, stop and ask the user. Producing plausible-looking
attribution is a directive violation analogous to forecasting a future
migration — both create content the artifact cannot defend.
### 5.2 Deriving artifacts from code, and the is→ought line
Artifacts are routinely *derived from the code* — a reviewer (human or
agent) reads the codebase and writes the arguments and rules it
warrants. Two rules keep derivation honest, and both are normative, not
merely procedural:
- **Derive from source, never from plausibility.** A premise that was
not checked against the code it describes — read the *mechanism*, not
its name — is fabrication wearing a convention, the same violation as
a fabricated source (§5.1). Verify that every cited path exists; assert
what the code *does*, with the file as evidence.
- **The is→ought line.** "The code does X" is a **premise, never the
reasoning.** A rule whose only justification is its own current
implementation is circular. Normative force comes from exactly two
places: **ratification** (the CODEOWNERS merge that accepts the rule)
for rules drawn from observed practice, and an **external source** for
obligations (§5). Until one occurs, a code-derived rule is a
*proposal* — recorded as such, never as already-binding.
The operational procedure for a derivation pass — what to survey, how to
fact-check, how to draft — is application, not principle; an agent
performing it follows the carried `deriving-from-code.md`.
## 6. Negative space, conjecture, and supersession
**Negative space** — rejected alternatives, deliberate omissions,
original asks — cannot live in code (code shows what is, not what was
considered and dismissed) and is lost without explicit capture. It
belongs in **commit-message trailers** (`Considered-alternatives:`,
`Out-of-scope:`, `Original-ask:`) and, for cross-cutting decisions,
in ADR Reasoning sections. Goals and domain documents do not carry
internal history sections; their commit logs serve that role.
Rejections and out-of-scope items are **premise-dependent decisions**,
not pure historical facts. They carry the same structure as positive
decisions:
- *Decision*: at moment T, given premise P, we did X.
- *Rejection*: at moment T, given premise P, we did **not** do Y.
Both depend on P; both invite re-evaluation when P changes. A rejection
captured without its premise is an opinion future readers can't audit.
Capture takes the form `<alternative>: rejected because <premise>`
where "because" introduces a current-state claim about the world or
the system, not a feeling. The same applies to out-of-scope items.
**Conjecture is forbidden** in non-executable artifacts: an artifact may
not pre-decide what a future maintainer should do once a premise
changes. Existence-predicate comments name the **Premise** and
**Consequence**; they do not specify the replacement, the migration, or
the timeline. Those decisions belong to the moment of change, not the
moment of authorship. If a planned migration exists separately (an RFC,
an issue, a separate ADR), reference it as a pointer.
**Supersession** is git-tracked uniformly across artifact types.
Documents are freely edited; git is the substrate that preserves every
prior state via `git log -p`, `git blame`, and `git log --follow`
(across renames). Snapshots inside a document need not be physically
append-only — the discipline is that *the moment a snapshot describes
be accurately captured at the time of writing* and not retroactively
rewritten to misrepresent it.
A substantive identity change to an artifact (its rule, contract, or
definition) is handled by **rename**, since filenames are content-named
(see [`conventions.md` §8](conventions.md#8-naming-and-cross-referencing));
git's rename tracking carries the history, and any pointer in code or
other artifacts is updated as part of the same change. A refinement
that does not change identity is an **edit** at the same path — and
this is the common case. *"Always do X"* becoming *"do X except when Y"*
is an edit; the prior form is recorded in the new text's Reasoning
section, with the premise that drove the exception named explicitly
(symmetric with how rejected alternatives are recorded — see §6). Full
retraction without replacement is a deletion, with rationale in the
deletion commit; this is rare, because a position worth codifying is
usually worth refining rather than abandoning.
ADRs receive no special supersession ceremony. The reasoning that makes
git sufficient for goals and domain documents applies equally to ADRs:
readers identify the rule currently in force by reading the file at
its content-named path; history is recoverable via git when needed.
## 7. External registers
"Code is the source of truth" is not limited to code. A
machine-authoritative system outside the repository that holds
structured claims about it — a compliance register, an API catalogue,
an SLO inventory — stands in the same relation to prose that code
does: the register holds the structured claim (the *what*); artifacts
here hold the *why*, in the same three forms; nothing new is invented
for it. Because the join between them is a pointer, its health is
computable — a missing, orphaned, or stale *why* surfaces as a
detectable finding rather than rotting silently, which is the
directive's standard for every coupling. Conventions in
[`registers.md`](registers.md).
## 8. Recursion and limits
This document and `conventions.md` follow their own rules: the rules
above are conditionals, the layer descriptions are co-maintained
current-state (this file is updated atomically when the structure
changes), and each commit's history is the snapshot record of how the
discipline was established. If practice and principles diverge, raise
the discrepancy explicitly — silent drift is itself a directive
violation.
Three failure modes the directive does not solve:
- **Logic rot** is undetectable by any artifact.
- **Implicit assumptions** that nobody named at authoring time cannot
later be invalidated as premises because they were never recorded.
- **Cumulative reading cost.** Long histories grow expensive to
synthesize; periodic synthesis entries (themselves dated, not
rewrites of history) mitigate without eliminating this.
The directive's claim is not that these are impossible — only that
they fail *visibly* (premise rot detectable, fabricated source caught
at PR review, missing test makes lack of enforcement obvious) rather
than silently.