---
name: step-01-transform
description: Build handoff data per module - 8 categories with all gap fixes
model: sonnet
next_step: steps/step-02-export.md
---

> **Context files:** `references/handoff-file-templates.md` | `references/handoff-mappings.md` | `references/handoff-seeddata-generation.md` | `references/entity-domain-mapping.md`

# Step 01: Transform (Handoff Data Generation)

## MANDATORY EXECUTION RULES

- **ALWAYS** process modules in topological order (dependencies first)
- **ALWAYS** map to 8 categories (including "documentation")
- **ALWAYS** propagate personRoleConfig verbatim from analysis.entities[]
- **ALWAYS** separate seedData into core/business categories
- **ALWAYS** map entity to domain file path (1:1)
- **ALWAYS** include dependencies[] per file entry
- **NEVER** invent entities/FRs/BRs not in module JSON files
- **ALL** API routes from specification.apiEndpoints (exact copy)

## YOUR TASK

For each module in topological order, build the complete handoff data with 8 file categories, BR-to-code mapping, API endpoint summary, and write to feature.json via ba-writer.

---

## EXECUTION SEQUENCE

For **EACH module** in topological order:

### 1. Calculate Complexity

```json
{
  "complexity": "simple|medium|complex",
  "complexityDetails": {
    "entities": {count},
    "useCases": {count},
    "businessRules": {count},
    "calculated": "{level} (entities<=X, UCs<=Y, BRs<=Z)"
  }
}
```

| Criteria | Simple | Medium | Complex |
|----------|--------|--------|---------|
| Entities | <=3 | <=6 | >6 |
| Use Cases | <=5 | <=12 | >12 |
| Business Rules | <=10 | <=20 | >20 |

**Global complexity** = highest across all modules.

### 2. Map Specification to Files (8 Categories)

> **Reference:** Read `references/handoff-file-templates.md` for complete JSON templates.
> All backend paths MUST include `{ApplicationName}/` hierarchy.

| Category | Source | Key rules |
|----------|--------|-----------|
| **Domain** | `analysis.entities[]` | Entities, ValueObjects, Enums |
| **Application** | `analysis.useCases[]` | Services, DTOs, Validators |
| **Infrastructure** | `analysis.entities[]` | EF Configurations, DbSet |
| **API** | `specification.apiEndpoints[]` | Controllers (exact copy) |
| **Frontend** | `specification.uiWireframes[]` | Pages, Components, Hooks; split by file (NOT monolithic) |
| **SeedData** | `specification.seedDataCore` | CORE (2 app-level + per-module) + business |
| **Tests** | All layers | Unit, Integration, Security tests |
| **Documentation** | All layers | Technical docs, user guides, API specs (can be empty `[]`) |

**Frontend Task Splitting (MANDATORY):**
- Each page as separate entry (not bundled mega-task)
- Include `linkedWireframes[]` + `wireframeAcceptanceCriteria`
- FK fields: `"fkFields": ["EmployeeId->Employee", "DepartmentId->Department"]`
- ALL pages use `/ui-components` skill
- Route wiring: separate entry in `filesToCreate.frontend`

**Route Convention (CRITICAL):**
- Transform PascalCase module codes to kebab-case in NavigationModule/Section routes
- Example: `"HumanResources"` -> `"/human-resources"` (NEVER include `/business/` prefix)

**Documentation Category:**
- Include `doc-data.ts` for documentation data export
- Include API specification files if applicable
- Can be empty `[]` if no documentation is planned at this stage
- Will be populated later by `/documentation` skill after `/ralph-loop`

### 3. Map Business Rules to Code

> **Reference:** Read `references/handoff-mappings.md` — Section "Business Rules to Code Mapping"

For each BR in `analysis.businessRules[]` of EACH module:
- ruleId, title, module, severity (critical/high/medium/low)
- implementationPoints: Array of {layer, component, method, implementation} across all layers

### 4. Propagate personRoleConfig (GAP #2 Fix)

For each entity in `analysis.entities[]`:
- IF entity has `personRoleConfig` property:
  - Copy verbatim into handoff entity data
  - Ensures `/apex` and `/ralph-loop` receive person extension configuration
  - See `references/handoff-mappings.md` — Section "Person Extension Mapping"

### 5. Separate SeedData Core/Business (GAP #3 Fix)

Each seedData entry MUST include a `category` field:

```json
{
  "path": "src/Infrastructure/Persistence/Seeding/Data/NavigationApplicationSeedData.cs",
  "type": "SeedData",
  "category": "core",
  "module": "shared"
}
```

- `category: "core"` — Navigation, Permissions, Roles (mandatory infrastructure)
- `category: "business"` — Domain-specific reference/lookup data

> **Reference:** Read `references/handoff-seeddata-generation.md` for complete core seed generation.

### 6. Map Entity to Domain File (GAP #4 Fix)

> **Reference:** Read `references/entity-domain-mapping.md` for complete mapping rules.

1:1 mapping from BA entity to Domain file:

| BA Element | Domain File Path |
|------------|-----------------|
| Entity | `src/Domain/Entities/{App}/{Module}/{EntityName}.cs` |
| ValueObject | `src/Domain/{Module}/ValueObjects/{VOName}.cs` |
| Enum | `src/Domain/{Module}/Enums/{EnumName}.cs` |

### 7. Add Dependencies per File Entry (GAP #7 Fix)

Each file entry includes `dependencies[]` ordered by layer:

| Layer | Dependencies |
|-------|-------------|
| domain | `[]` (no dependencies) |
| infrastructure | `["domain"]` |
| application | `["domain"]` |
| api | `["application"]` |
| seedData | `["domain", "infrastructure"]` |
| frontend | `["api"]` |
| tests | `["domain", "application", "infrastructure", "api"]` |
| documentation | `[]` |

### 8. API Endpoint Summary

> **ABSOLUTE RULE:** Copy **EXACTLY** from `specification.apiEndpoints[]`. **NEVER** reinvent routes.

For each endpoint: operation, method, route, linkedUC, linkedFR, permissions, requestSchema, responseSchema, errorCodes, module.

### 9. Write Handoff to Feature.json

```
FOR i = 0 to modules.length-1:
  1. moduleCode = modules[i].code
  2. moduleFeature = ba-reader.findFeature(modules[i].featureJsonPath)
  3. Build handoff payload:
     - complexity (from step 1)
     - filesToCreate (full 8-category structure, filtered for this module)
     - brToCodeMapping (from step 3)
     - apiEndpointSummary (from step 8)
     - prdFile: ".ralph/prd-{moduleCode}.json"
     - totalFiles: count from filesToCreate
     - totalTasks: estimated from complexity
     - handedOffAt: ISO timestamp
  4. Write via ba-writer.enrichModuleHandoff({ moduleFeatureId, handoffData })
  5. Display: "handoff {i+1}/{N}: {moduleCode} ({fileCount} files)"
```

### 10. POST-CHECK Per Module (BLOCKING)

For each module, verify:

```javascript
const handoff = moduleFeature.handoff;

// 1. Handoff not empty
if (!handoff || Object.keys(handoff).length === 0) {
  BLOCKING_ERROR("Module {moduleCode}: handoff is empty");
}

// 2. All 8 categories present
const categories = ['domain', 'application', 'infrastructure', 'api', 'frontend', 'seedData', 'tests', 'documentation'];
const missing = categories.filter(cat => !handoff.filesToCreate[cat]);
if (missing.length > 0) {
  BLOCKING_ERROR("Module {moduleCode}: missing categories: " + missing.join(', '));
}

// 3. BR-to-code mapping non-empty
if (!handoff.brToCodeMapping || handoff.brToCodeMapping.length === 0) {
  BLOCKING_ERROR("Module {moduleCode}: brToCodeMapping is empty");
}

// 4. Display pass
console.log("POST-CHECK PASS: {moduleCode} — 8 categories, {brCount} BRs mapped");
```

---

## NEXT STEP

Load: `steps/step-02-export.md`
