Status: accepted (2026-08-24).
Context
Charter Agreement Protocol artifacts carry protocol_revision as a
digest-covered member of every artifact, and consumers declare an explicit
revision set; compatibility is identity-exact or an error. Identifier-level
version tokens — module names like V2Decoder, paths like priv/v1/,
function names like decode_v2, test file names, config keys — would create a
second, uncoordinated versioning axis: the classic drift surface where two
names each claim to be current and neither is. The approved specification
states this posture as "ABP no-token" (spec, Implementation Decisions).
The Mix/Hex package, by contrast, must carry a semantic version — a released library without one cannot be depended on. Conflating "no version token in the protocol surface" with "no version anywhere" is the misreading this ADR closes.
Decision
No version token appears in any shipped protocol identifier: module segment,
function or macro name, atom, struct key, corpus path, config key, artifact
separator, or typ value.
The Hex package's semantic version and its exact mix.exs package-tag source
reference — source_ref: "v#{@version}" — are the sole permitted
version-bearing durable identities. Path, source kind, and spelling are part of
the allowlist; a version-token lookalike in any other identifier or location is
rejected.
ADR filenames are slug-only, with no numeric sequence prefixes, for the same reason — document sequence numbers are themselves a versioning axis.
Enforcement
Two layers, both landed:
- Landed now. The kimosabe durable-identifier sweep
(
durable-identifier-check.py) runs on the staged index and the tracked tree. This repository is configured[durable_identifiers].versioning = "allowed", which disables only the numbered-version checks so the permitted package-tag identity passes; transientphase/task/slice/sprint/step/work-ordertokens remain blocked regardless of that setting. - Landed with the first protocol identifiers. The
test/architecture/identifier-naming gate re-narrows the numbered-version allowance to exactly the package-tag identity — failing on every conventional token form (leadingv<N>, snake-boundary_v<N>, CamelCase humpV<N>) and on path segments, everywhere except the blessedmix.exssource reference. Its scanner covers owned paths plus module, function, macro, atom, struct-key, and test identifiers. A scratch mutation that planted a version-bearing module and path made the exact gate fail before the live tree was accepted.
Consequences
Evolution happens at the revision boundary inside the artifact, where it is
digest-covered and negotiation-gated; the code surface stays version-free and
rename-stable. No module, function, path, config key, test, separator, typ,
or internal compatibility branch may derive its name from a release, task, or
implementation sequence. Wire revisions remain digest-covered data. The
architecture gate makes any regression loud.