Morphism Docs Contract Enforcement Spec

assetactive

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:

  • about
  • architecture
  • governance
  • operations
  • reference

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.md
    • AGENTS.md
    • SSOT.md
    • docs/DOCTRINE.md
  • no duplicate canonical claim exists for the same domain
  • deprecated docs do not retain authority: canonical in frontmatter

Mechanisms:

  • parse frontmatter
  • inspect authority field
  • inspect optional tags and sources fields
  • 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:

  • status
  • authority
  • owner
  • last_verified
  • style

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_verified older 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 at docs/ 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 status is one of: proposed, accepted, deprecated, superseded
  • if status: superseded, then superseded_by field is present and references a valid ADR number
  • required sections exist: Context, Decision, Consequences

Output Model

The validator emits:

  • ERROR for doctrine violations that block merge
  • WARN for migration-phase issues and advisory notices
  • INFO for 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:

  1. Required canonical files present
  2. Lane validation (allowed and forbidden lanes)
  3. Frontmatter validation for canonical docs
  4. Filename validation (kebab-case)
  5. Depth validation
  6. 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 |