---
name: step-02-export
description: Generate PRD files, verify integrity, output progress tracker and manifest
---

> **Context files:** `references/prd-generation.md` | `templates/tpl-progress.md`

# Step 02: Export (PRD + Verification)

## MANDATORY EXECUTION RULES

- **ALWAYS** generate PRD via `ss business-analyse-handoff` CLI command (deterministic, never LLM)
- **ALWAYS** verify PRD structure: $version=3.0.0 or 4.0.0, implementation.filesToCreate (v3) or expectedFiles (v4), 8 categories
- **ALWAYS** verify file counts match between PRD and handoff
- **ALWAYS** generate progress.txt from template
- **ALWAYS** update BA manifest (docs/index.json)
- **NEVER** skip POST-CHECK validation

## YOUR TASK

For each module, generate PRD files via CLI, verify integrity, create progress tracker, update manifest, and display completion summary.

---

## EXECUTION SEQUENCE

### 1. Generate PRD Files

For EACH module:

**Option A — Flat-file BA (recommended):**

```bash
# Single module:
ss business-analyse-handoff --ba-dir {moduleBaDir} --output .ralph/prd-{moduleCode}.json

# All modules from app-level index.json:
ss business-analyse-handoff --ba-app {appIndexPath}
```

**Option B — Legacy feature.json:**

```bash
ss business-analyse-handoff --feature {moduleFeaturePath} --output .ralph/prd-{moduleCode}.json
```

**Option C — v4 spec-oriented PRD (1M context + compaction):**

```bash
ss business-analyse-handoff --ba-app {appIndexPath} --v4
```

Generates `prd-{moduleCode}.json` with `$version: "4.0.0"` containing:
- `objectives[]` with acceptance criteria (instead of pre-computed tasks)
- `expectedFiles` (same 8 categories, for file reconciliation)
- `gates` (declarative quality gate definitions)
- Architecture, business rules, BR mapping, seed data (same as v3)

### 2. POST-CHECK PRD (BLOCKING)

> **Reference:** See loaded context `prd-generation.md` for complete validation rules.

```javascript
const prd = readJSON(`.ralph/prd-${moduleCode}.json`);
const featureHandoff = moduleFeature.handoff.filesToCreate;

// Check 1: Version
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: filesToCreate location (v3: implementation.filesToCreate, v4: expectedFiles)
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
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
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)
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: File paths must be valid C# identifiers (no spaces, apostrophes, accents)
// Reference: references/entity-canonicalization.md
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 verification table showing all 8 categories match between module JSON files and prd.json.

### 3. Generate modules-queue.json (if 2+ modules)

```json
{
  "modules": [
    { "code": "{code}", "prdFile": ".ralph/prd-{code}.json", "status": "pending", "order": 1, "dependencies": [], "complexity": "simple" },
    { "code": "{code}", "prdFile": ".ralph/prd-{code}.json", "status": "pending", "order": 2, "dependencies": ["{dep}"], "complexity": "medium" }
  ],
  "currentIndex": 0,
  "totalModules": "{count}",
  "completedModules": 0,
  "strategy": "topological"
}
```

Write to: `.ralph/modules-queue.json`

### 4. Generate progress.txt

> **Template:** See loaded context `tpl-progress.md` for complete structure.
> **Data source:** Populate with module-specific data from index.json.

- One section per module in topological order
- CORE SeedData: 5 entries (mandatory)
- Business SeedData: per module (varies)
- Hierarchical task structure (module -> layer -> tasks)
- Each task: checkbox, description, effort, dependencies
- Summary with totals across all modules
- Cross-module tasks IF multi-module

Before writing:
```
IF .ralph/progress.txt exists AND contains "Iteration" entries:
  WARN: "progress.txt contains development progress — appending handoff section instead of overwriting"
  APPEND instead of WRITE
```

Write to: `.ralph/progress.txt`

### 5. Update BA Manifest (docs/index.json)

**Schema:**

```json
{
  "version": "1.0",
  "updatedAt": "{ISO timestamp}",
  "analyses": [
    {
      "appCode": "{app_code}",
      "appName": "{application_name}",
      "moduleCode": null | "{module_code}",
      "moduleName": "{module_name}",
      "version": "{version}",
      "status": "handed-off",
      "featureDescription": "{description}",
      "path": "{app_code}/business-analyse/v{version}/index.json",
      "updatedAt": "{ISO timestamp}"
    }
  ]
}
```

**Update logic:**

1. Read existing manifest (or create empty)
2. **PROJECT MODE:** Add/update project entry + all app entries + all module entries per app
3. **SINGLE-APP MODE:** Update app entry + module entries for this app
4. Write manifest back with updated timestamp
5. Display: "BA manifest updated: docs/index.json ({total} entries)"

### 6. Display Completion Summary

```
══════════════════════════════════════════════════════════════
  DERIVE-PRD COMPLETE — {application_name}
══════════════════════════════════════════════════════════════

Modules: {count} ({names})
Complexity: {simple|medium|complex}
Files: {total across all modules}
Tasks: {total}

Readiness Scores:
┌──────────────┬────────────┬──────────────┐
│ Module       │ Blocking   │ Files        │
├──────────────┼────────────┼──────────────┤
│ {module1}    │ 100%       │ {count}      │
│ {module2}    │ 100%       │ {count}      │
└──────────────┴────────────┴──────────────┘

Artifacts generated:
  .ralph/prd-{module}.json                — Task breakdown per module
  .ralph/prd-{module}.entities.json       — Entity specifications (companion)
  .ralph/prd-{module}.rules.json          — Business rules (companion)
  .ralph/prd-{module}.usecases.json       — Use cases (companion)
  .ralph/prd-{module}.screens.json        — Screen specifications (companion)
  .ralph/prd-{module}.permissions.json    — Permissions (companion)
  .ralph/progress.txt                     — Progression tracker
  .ralph/modules-queue.json               — Module execution order (if multi-module)
  docs/index.json                         — BA manifest (status: handed-off)

[NEXT] Development:
  1. Run /business-analyse-develop to begin implementation
  2. Modules will be processed in topological order
  3. Each module PRD contains {total_files} files across 8 categories

══════════════════════════════════════════════════════════════
```

---

## SELF-VERIFICATION (BEFORE COMPLETION)

1. `.ralph/prd-{module}.json` exists for ALL modules (>100 bytes each)
2. `.ralph/progress.txt` exists (>500 bytes)
3. `.ralph/modules-queue.json` exists (if 2+ modules)
4. `docs/index.json` updated with correct entry count and status "handed-off"
5. All PRD files have $version=3.0.0 or 4.0.0, file manifest present, 8 categories
6. File counts match between PRD and handoff for all categories
7. For EACH module: 5 companion files exist in `.ralph/` (entities, rules, usecases, screens, permissions)
8. Each PRD contains `specificationFiles` with all 5 paths
9. Each companion file is non-empty (>10 bytes)

**IF any check fails -> fix before completing.**
