# Content-as-Code Metadata System Specification

**Version:** 1.0  
**Status:** DRAFT  
**Created:** November 4, 2025  
**Author:** Sam Henry  
**Purpose:** Define architecture for version-controlled content management with metadata inheritance, data file references, and programmatic rendering

---

## 1. Executive Summary

Roadcrew will implement a **Content-as-Code Metadata System** that separates content, metadata, and data into distinct, version-controlled files. This enables:

- **Single source of truth** for metadata (data files)
- **Cascading inheritance** for defaults (global → scope → file-level)
- **Clean frontmatter** (only override what's different)
- **Programmatic rendering** (same content rendered multiple ways)
- **Publishing safety** (explicitly control what customers see)

**Benefit:** 640 files with consistent metadata, reduced duplication, machine-readable structure for automation.

---

## 2. Goals & Non-Goals

### Goals ✅
- Centralize metadata in data files (single edit updates everywhere)
- Support cascading defaults (global → scope → file-level)
- Enable reference-based frontmatter (author: "jane" instead of full details)
- Build rendering pipeline (markdown → HTML, JSON, GitHub issues)
- Maintain version control as audit trail
- Ensure internal-only content doesn't leak to customers
- Support templating with metadata injection

### Non-Goals ❌
- Database-backed metadata (Git is source of truth)
- Real-time metadata syncing (batch build-time resolution)
- Frontend metadata UI (CLI/programmatic access only)
- Breaking existing file structure (additive implementation)

---

## 3. System Architecture

### 3.1 Directory Structure

```
/context
  /data                              # Global metadata (inherited by all)
    _defaults.yml                    # Global defaults (all scopes inherit)
    authors.yml                      # Author registry
    licenses.yml                     # License definitions
    roadcrew-config.yml              # Roadcrew version/deployment config
    tags.yml                         # Standard tags

  /specs
    /data
      _defaults.yml                  # Specs-specific defaults
      _template_defaults.yml         # For spec templates
    authentication-spec.md           # Frontmatter + content
    payment-flow-spec.md

  /epics
    /data
      _defaults.yml                  # Epics-specific defaults
    epic-1171.md
    epic-1172.md

  /brds
    /data
      _defaults.yml
    brd-feature-x.md

  /prds
    /data
      _defaults.yml
    prd-feature-x.md

/memory-bank
  /data
    _defaults.yml                    # Memory bank defaults
    contributors.yml                 # Team/contributor info
  activeContext.md
  systemPatterns.md
  projectbrief.md

/templates/roadcrew
  /data
    _defaults.yml                    # Template defaults
    template-types.yml               # Template type metadata
  spec.template.md
  epic.template.md
  release.template.md

/commands
  /data
    _defaults.yml                    # Command defaults
    command-stages.yml               # Workflow stage metadata
  01-analysis/
    analyze-repo.md
  02-planning/
    create-spec.md
```

### 3.2 Metadata Resolution Layers

Metadata is resolved in this order (later layers override earlier):

```
Layer 1: Global Defaults
  └─ /context/data/_defaults.yml
     └─ Layer 2: Scope Defaults
        └─ /context/[scope]/data/_defaults.yml
           └─ Layer 3: Type Defaults (if applicable)
              └─ /context/[scope]/data/_[type]_defaults.yml
                 └─ Layer 4: File Frontmatter
                    └─ /context/[scope]/filename.md
                       └─ Layer 5: Reference Resolution
                          └─ Fetch full objects from data files
                             └─ Final Metadata Object
```

---

## 4. Data File Specifications

### 4.1 Global Defaults (`/context/data/_defaults.yml`)

```yaml
# Organizational
organization: "North Star Holdings, LLC"
copyright: "Copyright (c) 2025 North Star Holdings, LLC"
contact: "info@tailwind-ai.com"
website: "https://tailwind-ai.com"

# Licensing
license: "LicenseRef-RoadcrewLicense-1.0"
spdx_license_identifier: "LicenseRef-RoadcrewLicense-1.0"
license_file: "/LICENSE-COMMERCIAL"

# Roadcrew System
roadcrew_version_min: "1.6.0"
roadcrew_version_target: "1.7.0"

# Content Defaults
audience: "all"                      # all | internal | customers | team
status: "draft"                      # draft | active | deprecated | archived
internal_only: false                 # If true, never publish to customers
checksum_enabled: true               # Track content changes via hash

# Publishing
publish_to_customers: true
inject_copyright_footer: true
inject_license_footer: true

# Metadata
created_at: null                     # Set by individual files
updated_at: null                     # Set by individual files
version: "1.0.0"                     # File version, not Roadcrew version
```

### 4.2 Authors Registry (`/context/data/authors.yml`)

```yaml
# Format: username: full_details
sam.henry:
  name: "Sam Henry"
  email: "sam@tailwind-ai.com"
  role: "Technical PM"
  organization: "Tailwind AI"
  github: "samhenry"
  avatar_url: "https://avatars.githubusercontent.com/u/12345"

jane.smith:
  name: "Jane Smith"
  email: "jane@tailwind-ai.com"
  role: "Senior Engineer"
  organization: "Tailwind AI"
  github: "janesmith"
  avatar_url: "https://avatars.githubusercontent.com/u/67890"

# For contractors/external contributors
external.contributor:
  name: "External Contributor"
  role: "Contractor"
  organization: "External"
```

### 4.3 Licenses Registry (`/context/data/licenses.yml`)

```yaml
# Format: identifier: license_details
LicenseRef-RoadcrewLicense-1.0:
  name: "Roadcrew Commercial License"
  identifier: "LicenseRef-RoadcrewLicense-1.0"
  spdx_id: "LicenseRef-RoadcrewLicense-1.0"
  description: "Commercial license for Roadcrew framework"
  url: "/LICENSE-COMMERCIAL"
  customer_facing: true
  internal_only: false

MIT:
  name: "MIT License"
  identifier: "MIT"
  spdx_id: "MIT"
  description: "Permissive open-source license"
  url: "https://opensource.org/licenses/MIT"
  customer_facing: true
  internal_only: false

CC-BY-4.0:
  name: "Creative Commons Attribution 4.0"
  identifier: "CC-BY-4.0"
  spdx_id: "CC-BY-4.0"
  description: "Attribution required, commercial use allowed"
  url: "https://creativecommons.org/licenses/by/4.0/"
  customer_facing: true
  internal_only: false
```

### 4.4 Roadcrew Config (`/context/data/roadcrew-config.yml`)

```yaml
# System versioning
current_version: "1.6.0"
min_supported_version: "1.5.0"
next_version: "1.7.0"

# Release tracking
active_release: "1.6.0"
active_release_date: "2025-11-02"
next_release_date: "2025-12-15"

# Deployment modes
deployment_modes:
  - id: "submodule"
    name: "Git Submodule (Primary)"
    default: true
  - id: "multi-repo"
    name: "Multi-Repo (Enterprise)"
    default: false
  - id: "standalone"
    name: "Standalone (Legacy)"
    default: false

# Features
features:
  memory_bank: true
  spec_driven_workflow: true
  github_integration: true
  publishing_api: true
  metadata_system: true

# Build configuration
build:
  metadata_resolution: "cascade"
  validate_references: true
  inject_metadata_footer: true
  strip_internal_on_publish: true
```

### 4.5 Tags Registry (`/context/data/tags.yml`)

```yaml
# Standard tags used across system
categories:
  feature:
    name: "Feature"
    description: "New capability"
    color: "green"
  
  bug:
    name: "Bug"
    description: "Defect or issue"
    color: "red"
  
  refactor:
    name: "Refactor"
    description: "Code improvement without behavior change"
    color: "blue"
  
  internal:
    name: "Internal"
    description: "Internal system change"
    color: "gray"

domains:
  auth:
    name: "Authentication"
    description: "Auth systems and flows"
  
  payment:
    name: "Payment"
    description: "Payment processing"
  
  api:
    name: "API"
    description: "REST/GraphQL APIs"

audiences:
  internal:
    name: "Internal"
    description: "Roadcrew team only"
  
  customers:
    name: "Customers"
    description: "Customer-facing users"
  
  all:
    name: "Everyone"
    description: "Public content"
```

---

## 5. Frontmatter Format

### 5.1 Frontmatter Structure

All content files use this format:

```yaml
---
# Identity (REQUIRED)
title: "File Title"

# Metadata (OPTIONAL - inherits from defaults if not specified)
author: "sam.henry"                  # References authors.yml
license: "LicenseRef-RoadcrewLicense-1.0"  # References licenses.yml
status: "active"                     # Overrides default "draft"

# Relations (OPTIONAL)
parent: "EPIC-1171"                  # What epic/release?
children: ["SPEC-1236", "SPEC-1237"]  # What depends on this?
related: ["SPEC-1235"]                # Related specs

# Categorization (OPTIONAL)
tags: ["auth", "security"]
category: "feature"

# Publish Control (OPTIONAL - inherits from defaults)
internal_only: false                 # Don't publish to customers
audience: "all"                      # all | customers | internal | team

# Tracking (OPTIONAL - often auto-filled)
created_at: "2025-11-04"
updated_at: "2025-11-04"
version: "1.0.0"

# Type-Specific (OPTIONAL - depends on scope)
# For specs:
acceptance_criteria: 5
test_coverage_target: 80
# For commands:
stage: "planning"
executable: "scripts/commands/create-spec.ts"
# For templates:
template_type: "spec"
template_variables: ["{{PROJECT_NAME}}", "{{GITHUB_REPO}}"]
---

# Content starts here
## Overview
Content body...
```

### 5.2 Frontmatter Resolution Rules

**Minimal file (only override differences):**
```yaml
---
title: "My Spec"
author: "jane.smith"
status: "active"
# Everything else inherited from _defaults.yml
---
```

**Full file (explicit everything):**
```yaml
---
title: "My Spec"
author: "jane.smith"
status: "active"
copyright: "Copyright (c) 2025 North Star Holdings, LLC"
license: "LicenseRef-RoadcrewLicense-1.0"
internal_only: false
audience: "all"
# ... etc
---
```

**Both resolve to the same metadata** when processed by metadata resolver.

---

## 6. Metadata Resolver Algorithm

### 6.1 Resolution Process

```typescript
// pseudocode
function resolveMetadata(filePath: string): ResolvedMetadata {
  
  // 1. Load layers in order (later overrides earlier)
  const globalDefaults = loadYaml('/context/data/_defaults.yml')
  
  const scope = detectScope(filePath)  // 'specs', 'epics', etc.
  const scopeDefaults = loadYaml(`/context/${scope}/data/_defaults.yml`) || {}
  
  const fileType = getFileType(filePath)  // e.g., 'spec', 'template'
  const typeDefaults = loadYaml(
    `/context/${scope}/data/_${fileType}_defaults.yml`
  ) || {}
  
  const fileFrontmatter = parseFrontmatter(filePath)
  
  // 2. Merge layers
  const merged = deepMerge(
    globalDefaults,
    scopeDefaults,
    typeDefaults,
    fileFrontmatter
  )
  
  // 3. Resolve references
  const resolved = resolveReferences(merged)
  
  // 4. Validate
  validateMetadata(resolved)
  
  return resolved
}

function resolveReferences(metadata: any): any {
  
  // author: "jane" → full author object
  if (metadata.author && typeof metadata.author === 'string') {
    metadata.author = loadData('authors.yml')[metadata.author]
    if (!metadata.author) throw new Error(`Author not found: ${metadata.author}`)
  }
  
  // license: "MIT" → full license object
  if (metadata.license && typeof metadata.license === 'string') {
    metadata.license = loadData('licenses.yml')[metadata.license]
    if (!metadata.license) throw new Error(`License not found: ${metadata.license}`)
  }
  
  // tags: ["auth", "api"] → resolve to full tag objects
  if (Array.isArray(metadata.tags)) {
    metadata.tags = metadata.tags.map(tag => {
      return findTag(tag) || { name: tag, description: 'Unknown tag' }
    })
  }
  
  // parent: "EPIC-1171" → validate exists, fetch summary
  if (metadata.parent) {
    const parentFile = findFileById(metadata.parent)
    if (!parentFile) throw new Error(`Parent not found: ${metadata.parent}`)
    metadata.parent = {
      id: metadata.parent,
      title: extractTitleFromFile(parentFile),
      path: parentFile
    }
  }
  
  // Similar for children, related
  
  return metadata
}
```

### 6.2 Validation Rules

After resolution, validate:

```typescript
const validationRules = [
  {
    rule: "required_fields",
    description: "All files must have title + author",
    check: (m) => m.title && m.author
  },
  {
    rule: "author_exists",
    description: "Author reference must exist in authors.yml",
    check: (m) => authors[m.author?.username || m.author]
  },
  {
    rule: "license_exists",
    description: "License reference must exist in licenses.yml",
    check: (m) => licenses[m.license?.identifier || m.license]
  },
  {
    rule: "parent_exists",
    description: "Parent reference must resolve to actual file",
    check: (m) => m.parent ? fileExists(m.parent.id) : true
  },
  {
    rule: "no_duplicate_ids",
    description: "No two files can have same ID",
    check: (m) => uniqueAcrossAllFiles(m.id)
  },
  {
    rule: "bidirectional_relations",
    description: "If A is parent of B, then B must list A as parent",
    check: (m) => validateBidirectionalLinks(m)
  },
  {
    rule: "internal_only_not_published",
    description: "Files with internal_only: true cannot be in dist/",
    check: (m) => !m.internal_only || !isInDistribution(m)
  }
]
```

---

## 7. Build-Time Rendering

### 7.1 Rendering Pipeline

```
Source Files (markdown + frontmatter)
        ↓
    Parse frontmatter
        ↓
    Resolve metadata
        ↓
    Validate metadata
        ↓
    Apply rendering format
        ↓
    Inject boilerplate (copyright, footer, navigation)
        ↓
    Output (markdown, HTML, JSON, GitHub issues, etc.)
```

### 7.2 Rendering Formats

**Format 1: Markdown (for docs)**
```typescript
function renderMarkdown(filePath: string): string {
  const { content, metadata } = parseAndResolve(filePath)
  
  const header = `# ${metadata.title}\n\n`
  const breadcrumb = metadata.parent 
    ? `> Parent: [${metadata.parent.title}](${metadata.parent.path})\n\n`
    : ''
  const footer = renderMetadataFooter(metadata)
  
  return `${header}${breadcrumb}${content}\n\n${footer}`
}
```

**Format 2: HTML (for web)**
```typescript
function renderHTML(filePath: string): string {
  const { content, metadata } = parseAndResolve(filePath)
  
  return `
    <!DOCTYPE html>
    <html>
    <head>
      <title>${metadata.title}</title>
      <meta name="author" content="${metadata.author.name}">
      <meta name="description" content="${extractFirstParagraph(content)}">
      <meta property="og:title" content="${metadata.title}">
      <meta name="license" content="${metadata.license.spdx_id}">
    </head>
    <body>
      ${renderNavigation(metadata)}
      <article>
        <h1>${metadata.title}</h1>
        <aside class="metadata">
          Author: ${metadata.author.name}
          Updated: ${metadata.updated_at}
        </aside>
        ${marked(content)}
      </article>
      ${renderFooter(metadata)}
    </body>
    </html>
  `
}
```

**Format 3: JSON (for programmatic access)**
```typescript
function renderJSON(filePath: string): string {
  const { content, metadata } = parseAndResolve(filePath)
  
  return JSON.stringify({
    metadata,
    content,
    contentHtml: marked(content),
    navigation: {
      parent: metadata.parent,
      children: metadata.children,
      related: metadata.related
    }
  }, null, 2)
}
```

**Format 4: GitHub Issue (for automation)**
```typescript
function renderGitHubIssue(filePath: string): GitHubIssueBody {
  const { content, metadata } = parseAndResolve(filePath)
  
  return {
    title: `[${metadata.category}] ${metadata.title}`,
    body: `
## Overview
${content}

## Metadata
- **Author:** ${metadata.author.name}
- **Status:** ${metadata.status}
- **Created:** ${metadata.created_at}
- **Parent:** ${metadata.parent ? `#${metadata.parent.id}` : 'N/A'}

${metadata.children ? `## Related\n${metadata.children.map(c => `- #${c.id}`).join('\n')}` : ''}
    `,
    labels: metadata.tags.map(t => t.name),
    assignee: metadata.author.github
  }
}
```

---

## 8. Publishing & Distribution

### 8.1 Publishing Rules

When publishing to customers (`dist/` or `.roadcrew/`):

```typescript
const publishingRules = [
  {
    name: "strip_internal_fields",
    rule: "Remove internal_only: true files"
  },
  {
    name: "remove_sensitive_metadata",
    rule: "Remove author email, internal paths, git info"
  },
  {
    name: "sanitize_frontmatter",
    rule: "Keep only customer-safe fields: title, overview, acceptance_criteria, test_plan, etc.",
    keep_fields: [
      "title", "overview", "acceptance_criteria", "test_plan",
      "implementation_notes", "deployment", "tags", "category"
    ],
    remove_fields: [
      "author_email", "internal_notes", "cost_estimate",
      "exec_stakeholders", "budget_code"
    ]
  },
  {
    name: "resolve_template_variables",
    rule: "Replace {{VARIABLES}} with placeholders safe for customers"
  }
]
```

### 8.2 Publishing Pipeline

```typescript
function publishContent(filePath: string, targetRepo: string): void {
  const { content, metadata } = parseAndResolve(filePath)
  
  // 1. Check if should publish
  if (metadata.internal_only === true) {
    console.log(`Skipping internal-only file: ${filePath}`)
    return
  }
  
  // 2. Sanitize metadata
  const publishedMetadata = sanitizeMetadata(metadata)
  
  // 3. Render for publishing
  const frontmatter = stringifyYaml(publishedMetadata)
  const published = `---\n${frontmatter}\n---\n${content}`
  
  // 4. Write to target
  const outputPath = filePath.replace('roadcrew-internal', targetRepo)
  fs.writeFileSync(outputPath, published)
}

function sanitizeMetadata(metadata: any): any {
  const safe = {}
  const allowedFields = [
    'title', 'overview', 'acceptance_criteria', 'test_plan',
    'status', 'tags', 'category', 'created_at', 'updated_at'
  ]
  
  for (const field of allowedFields) {
    if (metadata[field]) safe[field] = metadata[field]
  }
  
  return safe
}
```

---

## 9. Implementation Phases

### Phase 1: Foundation (Weeks 1-2)
**Deliverables:**
- [ ] Data file structure (`/context/data/*.yml`)
- [ ] Metadata resolver (TypeScript)
- [ ] Validation rules + tests
- [ ] Documentation

**Timeline:** 2-3 hours development + testing

**Exit Criteria:**
- Resolver correctly cascades layers
- Reference resolution working (author, license, tags)
- Validation catches errors
- 90%+ test coverage

### Phase 2: Rendering (Week 2-3)
**Deliverables:**
- [ ] Markdown renderer
- [ ] HTML renderer
- [ ] JSON renderer
- [ ] GitHub issue renderer

**Timeline:** 3-4 hours development

**Exit Criteria:**
- All 4 formats working
- Metadata footer injected correctly
- Navigation links generated
- 85%+ test coverage

### Phase 3: Integration (Week 3)
**Deliverables:**
- [ ] Integrate resolver into command pipeline
- [ ] Update template generation to use metadata
- [ ] Publishing pipeline respects metadata rules
- [ ] Pre-publish validator checks metadata

**Timeline:** 2-3 hours development

**Exit Criteria:**
- Commands use metadata
- Templates generated with correct frontmatter
- Publishing tests pass
- No internal files leak to dist/

### Phase 4: Commands (Week 4)
**Deliverables:**
- [ ] `/validate-metadata` command
- [ ] `/render-content` command (formats: markdown, html, json)
- [ ] `/audit-metadata` command (find inconsistencies, orphaned files)
- [ ] `/update-defaults` command (bulk edit metadata)

**Timeline:** 2-3 hours development

**Exit Criteria:**
- All commands documented
- Commands tested with real files
- Help text clear and complete
- Performance acceptable (<5s per file)

---

## 10. Validation & Testing

### 10.1 Validation Checklist

**Pre-merge validation (CI/CD):**
```yaml
- metadata_files_valid: "All YAML files in /data/ valid syntax"
- no_duplicate_ids: "No two files share same ID"
- references_resolve: "All author/license/parent references found"
- bidirectional_links: "Parent/child relations bidirectional"
- required_fields: "All files have title + author"
- internal_only_safe: "No internal_only files in dist/"
- checksum_matches: "Content unchanged if checksum present"
- template_variables_documented: "All {{}} in templates documented"
- encoding_utf8: "All files UTF-8 encoded"
```

### 10.2 Test Scenarios

```typescript
describe('MetadataResolver', () => {
  it('cascades defaults correctly', () => {
    // Global + Scope + File defaults merge in right order
  })
  
  it('resolves author references', () => {
    // author: "jane" → full author object from authors.yml
  })
  
  it('resolves license references', () => {
    // license: "MIT" → full license object from licenses.yml
  })
  
  it('validates required fields', () => {
    // Throws error if title or author missing
  })
  
  it('handles missing references', () => {
    // Throws error if author/license/parent not found
  })
  
  it('renders markdown with footer', () => {
    // Footer contains copyright, license, author
  })
  
  it('strips internal fields on publish', () => {
    // internal_only: true files removed from output
  })
})
```

---

## 11. Examples

### 11.1 Complete Workflow Example

**Step 1: Create spec file with minimal frontmatter**
```yaml
# File: /context/specs/authentication-spec.md
---
title: "User Authentication Specification"
author: "sam.henry"
status: "active"
---

## Overview
...content...
```

**Step 2: Resolver cascades metadata**
```
Layer 1 (global defaults):
  → copyright, license, audience, internal_only, etc.

Layer 2 (specs scope defaults):
  → roadcrew_type: "spec", test_coverage_target: 80

Layer 3 (file frontmatter):
  → title, author, status

Layer 4 (reference resolution):
  → author: "sam.henry" → { name: "Sam Henry", email: "sam@tailwind-ai.com", ... }
  → license: "LicenseRef-RoadcrewLicense-1.0" → { name: "Roadcrew Commercial License", ... }

Final metadata object:
{
  title: "User Authentication Specification",
  author: { name: "Sam Henry", email: "sam@tailwind-ai.com", ... },
  status: "active",
  copyright: "Copyright (c) 2025 North Star Holdings, LLC",
  license: { name: "Roadcrew Commercial License", ... },
  roadcrew_type: "spec",
  test_coverage_target: 80,
  audience: "all",
  internal_only: false,
  ...
}
```

**Step 3: Render for publishing**
```markdown
---
title: "User Authentication Specification"
status: "active"
acceptance_criteria: 5
test_coverage_target: 80
---

## Overview
...content...

---
**License:** Roadcrew Commercial License ([LicenseRef-RoadcrewLicense-1.0](/LICENSE-COMMERCIAL))
**Copyright:** Copyright (c) 2025 North Star Holdings, LLC
**Last Updated:** November 4, 2025
```

### 11.2 Inheritance Example

**Global defaults:**
```yaml
# /context/data/_defaults.yml
license: "LicenseRef-RoadcrewLicense-1.0"
copyright: "Copyright (c) 2025 North Star Holdings, LLC"
status: "draft"
internal_only: false
audience: "all"
```

**Specs defaults:**
```yaml
# /context/specs/data/_defaults.yml
roadcrew_type: "spec"
test_coverage_target: 80
acceptance_criteria_required: true
```

**Individual file:**
```yaml
# /context/specs/feature-x-spec.md
---
title: "Feature X Specification"
author: "jane.smith"
status: "active"        # Override "draft" default
---
```

**Result when resolved:**
```yaml
title: "Feature X Specification"
author: { name: "Jane Smith", email: "jane@tailwind-ai.com", ... }
status: "active"                                    # From file (overrides default)
roadcrew_type: "spec"                              # From specs defaults
test_coverage_target: 80                           # From specs defaults
license: "LicenseRef-RoadcrewLicense-1.0"          # From global defaults
copyright: "Copyright (c) 2025 North Star..."      # From global defaults
internal_only: false                               # From global defaults
audience: "all"                                    # From global defaults
```

---

## 12. Migration Path

### Backward Compatibility

Current files (without comprehensive frontmatter) continue working:
- Missing metadata fields get defaults
- Old frontmatter format still valid
- Gradual migration: update files as they change

### Migration Strategy

```
Phase 1 (Week 1): Deploy metadata system (non-breaking)
  - All files work with or without full metadata
  - New files use new system
  - Old files gracefully inherit defaults

Phase 2 (Week 2-3): Migrate critical files
  - Update spec templates
  - Update command documentation
  - Update memory-bank files

Phase 3 (Week 4): Bulk migration
  - Script to add frontmatter to remaining files
  - Review and validate
  - Commit all updates

Phase 4 (Week 5): Deprecate old patterns
  - Document old format as deprecated
  - Start warning on old format
  - Plan removal in next major version
```

---

## 13. Success Metrics

- [ ] All 640+ files have validated frontmatter
- [ ] Metadata resolver covers 100% of use cases
- [ ] Publishing pipeline safely strips internal fields
- [ ] Build time for metadata resolution <2 seconds
- [ ] Zero internal-only files leak to customers
- [ ] 90%+ test coverage on resolver
- [ ] Documentation complete and examples working

---

## 14. Related Documents

- **Architecture:** `memory-bank/systemPatterns.md` (Component D: Publishing)
- **Publishing:** `.cursor/rules/08-publishing.mdc`
- **Mode Routing:** `.cursor/rules/09-mode-routing.mdc`
- **Templates:** `templates/roadcrew/README.md`
