# PRD Validation Checks

## Overview

POST-CHECK PRD validation rules (BLOCKING). All checks must pass before proceeding to development.

## Check 1: Version

PRD $version must be 3.0.0 or 4.0.0.

```javascript
if (prd.$version !== "3.0.0" && prd.$version !== "4.0.0") {
  BLOCKING_ERROR("PRD version must be 3.0.0 or 4.0.0, got: " + prd.$version);
}
```

## Check 2: File Manifest Location

PRD must contain file manifest in correct location:
- v3: `implementation.filesToCreate`
- v4: `expectedFiles`

```javascript
const ftc = prd.$version === "4.0.0" ? prd.expectedFiles : prd.implementation?.filesToCreate;
if (!ftc) {
  BLOCKING_ERROR("prd.json missing file manifest (v3: implementation.filesToCreate, v4: expectedFiles)");
  STOP;
}
```

## Check 3: All 8 Categories Present

File manifest must contain all 8 categories:
- domain
- application
- infrastructure
- api
- frontend
- seedData
- tests
- documentation

```javascript
const categories = ['domain', 'application', 'infrastructure', 'api', 'frontend', 'seedData', 'tests', 'documentation'];
const missingCategories = categories.filter(cat => !ftc[cat]);
if (missingCategories.length > 0) {
  BLOCKING_ERROR("Missing categories: " + missingCategories.join(', '));
}
```

## Check 4: File Counts Match

File count for each category must match between PRD and feature handoff.

```javascript
for (const cat of categories) {
  const prdCount = ftc[cat]?.length ?? 0;
  const featureCount = featureHandoff[cat]?.length ?? 0;
  if (prdCount !== featureCount) {
    BLOCKING_ERROR(`${cat}: prd=${prdCount} but feature=${featureCount}`);
  }
}
```

## Check 5: Specification Files (Companion Files)

PRD must contain all 5 companion file definitions:
- entities
- rules
- usecases
- screens
- permissions

Each companion file must exist and be non-empty (>10 bytes).

```javascript
const specFiles = prd.specificationFiles;
if (!specFiles) {
  BLOCKING_ERROR("specificationFiles missing from PRD");
}
const specKeys = ['entities', 'rules', 'usecases', 'screens', 'permissions'];
for (const key of specKeys) {
  if (!specFiles[key]) {
    BLOCKING_ERROR(`specificationFiles.${key} path missing`);
  }
  const companionPath = `.ralph/${specFiles[key]}`;
  if (!fileExists(companionPath)) {
    BLOCKING_ERROR(`Companion file not found: ${companionPath}`);
  }
  const companionSize = fileSize(companionPath);
  if (companionSize < 10) {
    BLOCKING_ERROR(`Companion file empty or too small: ${companionPath} (${companionSize} bytes)`);
  }
}
```

## Check 6: C# Identifier Validity

File paths must be valid C# identifiers (no spaces, apostrophes, accents).

Error message pattern:
```
File path contains illegal characters for C# identifier: "{filePath}"
— entity name must be canonicalized (see references/entity-canonicalization.md)
```

Implementation:

```javascript
for (const [cat, files] of Object.entries(ftc)) {
  for (const file of (files || [])) {
    const filePath = file.path || file;
    // Extract filename without extension
    const fileName = filePath.split('/').pop().replace(/\.(cs|tsx|ts|json)$/, '');
    // Check for illegal characters in C# file names
    if (/[\s'àâäéèêëïîôùûüçÀÂÄÉÈÊËÏÎÔÙÛÜÇ]/.test(fileName)) {
      BLOCKING_ERROR(`${cat}: File path contains illegal characters for C# identifier: "${filePath}" — entity name must be canonicalized (see references/entity-canonicalization.md)`);
    }
  }
}
```

## Display Output

Display verification table showing all 8 categories match between module JSON files and prd.json.
