Morphism Docs Contract Enforcement Spec
status: active authority: derived owner: morphism last_verified: 2026-03-25 style: D sources:
- docs/DOCTRINE.md
docs_contract.py — Enforcement Specification
Purpose
docs_contract.py validates that the repository conforms to Morphism Doctrine.
It is the primary enforcement seed for:
- topology validation
- authority uniqueness
- frontmatter validity
- depth rules
- naming rules
- generated-region rules
- canonical freshness hooks
- changed-surface awareness
Validation Classes
1. Topology validation
Checks:
- all human-authored docs under
docs/belong to an allowed lane - no forbidden top-level lane exists
docs/doctrine/does not exist as a directory- deprecated legacy lanes are flagged
Allowed lanes:
aboutarchitecturegovernanceoperationsreference
Error examples:
ERROR docs/shared/foo.md: invalid lane "shared"
ERROR docs/doctrine/why-morphism.md: forbidden lane "doctrine"
ERROR docs/guides/setup.md: invalid lane "guides" — migrate to "operations" or "reference"
2. Authority validation
Checks:
- required canonical files exist:
README.mdAGENTS.mdSSOT.mddocs/DOCTRINE.md
- no duplicate canonical claim exists for the same domain
- deprecated docs do not retain
authority: canonicalin frontmatter
Mechanisms:
- parse frontmatter
- inspect
authorityfield - inspect optional
tagsandsourcesfields - optionally inspect explicit domain identifiers if added later
Error examples:
ERROR docs/DOCTRINE.md: missing (required canonical file)
ERROR docs/governance/MORPHISM.md: retains "authority: canonical" — must be demoted to "reference"
WARN docs/governance/workflow.md and docs/governance/enforcement.md: possible authority overlap on domain "enforcement"
3. Frontmatter validation
Checks on all files with authority: canonical:
Required fields:
statusauthorityownerlast_verifiedstyle
Allowed values:
status ∈ {draft, active, deprecated}authority ∈ {canonical, derived, generated}style ∈ {D, E, C, B}
Errors:
- missing required field
- invalid enum value
- malformed date (must be valid YYYY-MM-DD)
last_verifiedolder than 180 days → warning
Error examples:
ERROR docs/architecture/system.md: missing required field "style"
ERROR docs/governance/invariants.md: invalid status "WIP" — must be draft|active|deprecated
WARN docs/reference/commands.md: last_verified is 194 days old
4. Naming validation
Checks:
- markdown filenames under
docs/are lowercase kebab-case - exception:
DOCTRINE.md(uppercase by convention atdocs/root) - directory names under
docs/are from the approved semantic noun list - forbidden directory names are rejected
Kebab-case pattern: ^[a-z0-9]+(-[a-z0-9]+)*\.md$
Forbidden directory names: misc, general, shared, temp, stuff, other, guides, docs, notes, doctrine
Error examples:
ERROR docs/reference/Commands.md: filename must be kebab-case
ERROR docs/Shared/utils.md: forbidden directory name "Shared"
5. Depth validation
Checks:
- under
docs/, canonical and human-authored paths do not exceed allowed depth - explicit exemptions may be read from a Doctrine-maintained allowlist
Default allowed shapes:
docs/<lane>/<file>.md (depth 3 from root)
docs/<lane>/<subtopic>/<file>.md (depth 4 from root)
Anything deeper is an error unless exempted.
Error examples:
ERROR docs/governance/decisions/archive/old/0001-foo.md: exceeds max depth (5 > 4)
6. Generated-region validation
Checks:
- hybrid docs use stable generated markers
- generated markers are balanced (every BEGIN has a matching END)
- marker names are consistent within a file
- protected regions are not manually edited if regeneration fingerprints are available
Markers:
<!-- GENERATED:BEGIN <name> -->
<!-- GENERATED:END <name> -->
Error examples:
ERROR docs/reference/commands.md: unmatched GENERATED:BEGIN "commands" without corresponding END
ERROR docs/architecture/repo-map.md: GENERATED:BEGIN "tree" name does not match GENERATED:END "map"
7. Generated freshness validation
Checks where declared:
- generated docs are newer than declared inputs
- or regeneration stamp matches current source hash
- or generation manifest confirms freshness
Inputs may come from:
- scripts (modification time)
- schemas (content hash)
- CLI help outputs (content hash)
- inventories (content hash)
This validation is optional until generation paths are formally declared (Phase 4 of consolidation).
8. Link validation
Checks:
- internal markdown links resolve to existing files
- anchor references to canonical docs resolve
- moved docs do not leave broken internal references
Implementation note: link validation may use a lightweight resolver (regex-based path extraction) initially, with full AST-based checking added later.
9. Changed-surface awareness
When a PR diff includes changes to:
- commands (CLI source files)
- schemas (JSON Schema definitions, Zod schemas)
- repo structure (directory additions, moves, or deletions under
docs/) - canonical behavior surfaces (
.morphism/config.json, policy files)
the validator checks whether corresponding canonical docs changed in the same diff.
Initial implementation: path heuristics mapping source directories to canonical doc files.
Later implementation: explicit source mappings declared in frontmatter sources field.
10. ADR validation
Checks on files in docs/governance/decisions/:
- filename matches pattern
NNNN-kebab-case.md - required frontmatter fields present:
status,authority,owner,last_verified,style - ADR
statusis one of:proposed,accepted,deprecated,superseded - if
status: superseded, thensuperseded_byfield is present and references a valid ADR number - required sections exist: Context, Decision, Consequences
Output Model
The validator emits:
ERRORfor doctrine violations that block mergeWARNfor migration-phase issues and advisory noticesINFOfor informational notices
Machine-readable mode:
{
"errors": [],
"warnings": [],
"info": [],
"summary": {
"total_checks": 0,
"passed": 0,
"failed": 0,
"warnings": 0
}
}
Human mode:
ERROR docs/reference/Commands.md: filename must be kebab-case
ERROR docs/doctrine/why-morphism.md: forbidden top-level lane "doctrine"
WARN docs/runbooks/: legacy lane — should migrate to docs/operations/
INFO docs/governance/decisions/: 3 ADRs found, all valid
Exit Semantics
- exit code
0→ no errors - exit code
1→ one or more errors - warnings do not fail unless promoted by CI policy
Migration Policy
During migration, legacy lanes and deprecated files may emit warnings instead of errors. After migration cutoff (when Doctrine exits Migration Phase), they become errors.
Phases:
- Phase A (current): warn on legacy topology, warn on deprecated authority claims
- Phase B (after lane collapse): error on new violations, warn on pre-existing violations
- Phase C (after Doctrine reaches v1.0 Enforcement Phase): error on all violations
Minimum Initial Implementation
The first enforceable version should implement only:
- Required canonical files present
- Lane validation (allowed and forbidden lanes)
- Frontmatter validation for canonical docs
- Filename validation (kebab-case)
- Depth validation
- Basic changed-surface awareness (path heuristics)
Everything else follows incrementally.
Recommended Implementation Order
| Priority | Check | Complexity | Blocks merge | |---|---|---|---| | 1 | Required canonical files exist | Low | Yes | | 2 | Lane validation | Low | Yes (after Phase B) | | 3 | Forbidden lane detection | Low | Yes | | 4 | Filename kebab-case | Low | Yes | | 5 | Frontmatter presence and validity | Medium | Yes | | 6 | Depth validation | Low | Yes | | 7 | Authority uniqueness | Medium | Yes | | 8 | Link validation | Medium | Warn only initially | | 9 | Generated region balance | Low | Yes | | 10 | Changed-surface awareness | High | Warn only | | 11 | Generated freshness | High | Warn only | | 12 | ADR format validation | Low | Yes |