Skip to content

Entity identifier shape — AA-NNNN-<slug>

Status: open/accepted

  • Every entity filename is AA-NNNN-<optional-slug>.md — an uppercase type abbreviation, a 4-character id, and an optional, immutable slug.
  • The id is identity: immutable, globally unique within its prefix, and the stable anchor for wikilinks and git history.
  • Two numbering styles: incrementing for curated, low-volume catalogs (Standards, Principles); base-36 for high-volume, machine-minted, or branch-parallel records (Decisions, Milestones, Tasks, Backlog).
  • Filenames are immutable; the slug is authoring convenience and never tracks title changes.
  • Order lives outside the id — in a manifest, or the Milestone version.

What filename, frontmatter id, and wikilink form every entity in SDLC uses, and how the three pieces fit together so renames don’t shatter inbound references.

Adopt one identifier rule across every entity type.

AA-NNNN-<optional-slug>.md
  • AA — the entity type’s uppercase abbreviation. Favor a single letter; expand to more letters only on collision.
  • NNNN — a 4-character id, either incrementing or base-36 per the type (see Numbering styles).
  • <slug> — optional, chosen at create time, immutable thereafter.

The dash between AA and NNNN disambiguates multi-letter abbreviations from the id (CO-7F2M, not the ambiguous CO7F2M). The wikilink and frontmatter id: follow the same shape.

ComponentFormExample
Abbreviation AA1–3 uppercase lettersD, CO, PR
Id NNNN — incrementingzero-padded decimal, 4 digits0008
Id NNNN — base-364 chars [0-9A-Z], deterministically minted (.N sub-id allowed for Milestones under either style)3F2K, ML68, 0001.1
Sluglowercase, dash-separated words; optional, immutabledeterministic-op-substrate
FilenameAA-NNNN.md or AA-NNNN-<slug>.mdD-0008-aggressive-upgrade.md
WikilinkAA-NNNN or AA-NNNN-<slug>[D-0008-markdown-standard](/planning/decisions/markdown-standard/)
Frontmatter id:AA-NNNND-0008

Incrementing — the next unused number in the type’s own sequence, zero-padded to four digits. Suits low-volume, curated catalogs that humans cite and read in order. Two branches can mint the same number for different entities; that is a flagged consistency error, and the duplicate is renumbered before merge. Decisions and Milestones started here but proved branch-parallel in practice and moved to base-36 (2026-07-05).

Base-36 — four characters from [0-9A-Z], minted deterministically from a seed with collision-retry (~1.68M ids per prefix; see mintBase36 in apps/sdlc/lib/model/identifier.ts). Suits high-volume, fast-capture, or machine-created records authored on divergent branches, where a shared counter would collide. Carries no order.

Abbreviations follow the favor-one-letter rule; each expands only when a shorter form is already taken. Decision and Milestone moved to base-36 on 2026-07-05: both kept being minted on parallel branches and colliding (a milestone renumber and a decision-id clash in the same week, during D-3PDM-cross-project-data-model-adoption’s enactment). Existing incrementing ids are grandfathered. The shipped types (D, S, P, M, TM, RF, C, DR, PR, T, B) are locked in the PREFIXES registry (apps/sdlc/lib/model/identifier.ts), which mirrors this table; the remaining rows are proposals that lock when each type ships.

AAEntityNumberingNotes
DDecisionBase-36Moved from incrementing 2026-07-05 (branch-parallel minting kept colliding); legacy D-0001… grandfathered.
SStandardIncrementing
PPrincipleIncrementing
MMilestoneBase-36Moved from incrementing 2026-07-05; .N sub-id allowed (M-0001.1); order is the version field; legacy M-0000… grandfathered.
GGoalIncrementing
PRProductIncrementingP taken by Principle.
DRDriverIncrementingD taken by Decision.
CCapabilityIncrementing
COConstraintIncrementingC taken by Capability.
CTContractIncrementingC/CO taken.
RRequirementIncrementing
TMTermIncrementingGlossary vocabulary (D-B4CA-term-entity-and-generated-glossary); T taken by Task, G reserved for Goal.
RFReferenceIncrementingCurated external source (D-0009-reference-entity-and-docs-appendix); R reserved for Requirement.
TTaskBase-36High volume; created on parallel branches.
BBacklogBase-36Fast capture, pre-triage.
RLRelationBase-36Capability edge; edges proliferate (D-3PDM-cross-project-data-model-adoption). R reserved for Requirement, RF taken by Reference.
ACAcceptanceCriterionBase-36Many per task; machine-generated.
AGAgentBase-36A is free; AG reads clearer for Agent.
EVEvidenceBase-36High volume; E retired with Epic.
WWorkSessionBase-36Runtime records.
  • Filename is immutable. Once created, a file never renames — not on a title change, not on slug drift. Inbound wikilinks and git log --follow stay intact.
  • Id is identity. The AA-NNNN id is globally unique within its prefix space (D-0001, M-0001, T-0001 coexist) and never changes. Frontmatter id: matches the filename; a duplicate id is a defect the consistency check hard-fails.
  • Slug is optional and immutable. Chosen at create time for readability; the frontmatter title is the source of truth for display and may drift from the slug.
  • Order lives outside the id. Ids carry no position. Milestones order by version (ascending semver is the roadmap); any other ordered type orders by a manifest.
  • Existing ids are preserved. The corpus keeps its ids as-is regardless of the style rule (base-36 Decisions like D-ORMG, sequential Tasks like T-0001); the style governs newly minted ids only.

The pre-existing corpus was reshaped to AA-NNNN-<slug> by inserting the abbreviation dash (D0007-…D-0007-…, MML68M-ML68); ids were preserved, slugs unchanged, and inbound wikilinks swept in lockstep. The break from historical filenames is accepted (no git --follow bridging). New entity types ship conformant on day one. Implemented by T-87GH-new-scripts-derive-schema-bound-values under M-ML68; the per-type prefix registry is mirrored in D-ORMG-data-model.


← Back to Decisions