# Agent Transform Prompt for ba-writer (Module Handoff Generation)

## MANDATORY CONSTRAINTS

**INTERDICTION:** You must create EXACTLY 7 files and NOTHING ELSE. No README, SUMMARY, MANIFEST, INDEX, CHECKLIST.

## YOUR TASK

Transform module "{moduleCode}" for handoff.

## Output EXACT (7 files)

1. WRITE `{moduleDir}/handoff.json` (8 categories, brMapping, apiEndpoints, specificationFiles)
2. COPY VERBATIM `.ralph/prd-{moduleCode}.entities.json`
3. COPY VERBATIM `.ralph/prd-{moduleCode}.rules.json`
4. COPY VERBATIM `.ralph/prd-{moduleCode}.usecases.json`
5. COPY VERBATIM `.ralph/prd-{moduleCode}.screens.json`
6. COPY VERBATIM `.ralph/prd-{moduleCode}.permissions.json`
7. GENERATE `.ralph/prd-{moduleCode}.json` (PRD v3.0.0)

Return: `{ "moduleCode": "{moduleCode}", "filesCreated": 7, "errors": [], "complexity": "..." }`

## INPUT

- Module BA directory: `{moduleDir}` (ba-006: `docs/{projectSlug}/v{X.Y}/{appKebab}/{moduleKebab}/`)
- Application code: `{appCode}`
- Application name: `{appName}`
- Feature description: `{featureDescription}`
- Module index: `{moduleDir}/index.json`

## INSTRUCTIONS

### 1. Read Input Files

Read these 5 files from `{moduleDir}` (ba-006 location: `docs/{projectSlug}/v{X.Y}/{appKebab}/{moduleKebab}/`):

1. **entities.json** → `entities[]`
2. **usecases.json** → `useCases[]` (canonical key: `"useCases"`, fallback: `"usecases"`)
3. **rules.json** → `rules[]` (canonical key: `"rules"`, fallback: `"businessRules"`)
4. **permissions.json** → `roles[]`, `matrix[]`, `permissionPaths[]`
5. **screens.json** → `sections[]` (canonical key: `"sections"`, fallback: `"screens"`)

### 2. Normalization Safety Net (BACKWARD COMPAT)

When reading flat files, prefer canonical keys but fall back to alternatives:
- `useCases`: `data.useCases || data.usecases || []`
- `primaryActor`: `uc.primaryActor || uc.actor`
- `mainScenario`: `uc.mainScenario || uc.steps` (if `steps[]` contains objects, extract `.action`)
- `rules`: `data.rules || data.businessRules || []`
- `rules[].examples`: prefer `rule.examples[]` (`{input, expected}`); fallback: wrap `rule.example` string as `[{input: rule.example, expected: ""}]`
- `rules[].statement`: prefer `rule.statement`; fallback: `rule.description`
- `rules[].id`: prefer `rule.id`; fallback: `rule.code`
- `screens`: `data.sections || data.screens` (if `screens[]` exists, treat each screen as a section with 1 resource)

This safety net handles pre-4.52 BA outputs. It should become unnecessary once step-03-specify enforces canonical keys.

### 3. Determine Complexity

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

Classify the module based on these thresholds.

### 4. Generate API Endpoints

From use cases and entities, auto-generate REST endpoints:

- UC "Create X" → `POST /api/{app}/{module}`
- UC "List X" → `GET /api/{app}/{module}`
- UC "Update X" → `PUT /api/{app}/{module}/{id}`
- UC "Delete X" → `DELETE /api/{app}/{module}/{id}`
- UC "Get X" → `GET /api/{app}/{module}/{id}`

Use permission paths from `permissions.json` as-is.

### 5. Enrich Section UC/BR

Using `sectionCode` from `usecases.json` and `rules.json`, link each UC and BR to its section.

### 6. Entity Name Canonicalization (MANDATORY)

Before generating any file paths, canonicalize ALL entity names from `entities.json`:

1. Load `references/entity-canonicalization.md` for complete rules
2. For each entity in `entities.json > entities[]`:
   - If entity has `codeIdentifier` or `englishName` → use it directly
   - Otherwise → apply canonicalization: strip diacritics, remove apostrophes/spaces, remove French articles (d, de, du, l, la, le, les, un, une, des, a, au, aux, en), PascalCase
3. Use the CANONICALIZED name in ALL file path templates (`{EntityName}`, `{ServiceName}`, `{DtoName}`, etc.)
4. Store the mapping `{ originalName: "Type d'absence", canonicalName: "TypeAbsence" }` in handoff metadata for traceability

**Example:** Entity `"Type d'absence"` → canonicalized to `"TypeAbsence"` → path `src/Domain/Entities/App/Module/TypeAbsence.cs`

**BLOCKING:** If ANY entity name after canonicalization is not a valid C# identifier (`/^[A-Za-z_][A-Za-z0-9_]*$/`), STOP and report the error.

### 7. Build Handoff Data (8 Categories)

Load `references/handoff-file-templates.md` for complete JSON templates.

All backend paths MUST include `{ApplicationName}/` hierarchy.

| Category | Source | Key rules |
|----------|--------|-----------|
| **Domain** | `entities[]` | Entities, ValueObjects, Enums |
| **Application** | `useCases[]` | Services, DTOs, Validators |
| **Infrastructure** | `entities[]` | EF Configurations, DbSet |
| **API** | Generated from useCases + entities | Controllers |
| **Frontend** | `screens[]` | Pages, Components, Hooks; split by file (NOT monolithic) |
| **SeedData** | entities + permissions | CORE + business (include category field) |
| **Tests** | All layers | Unit, Integration, Security |
| **Documentation** | All layers | Technical docs (can be empty `[]`) |

**Frontend specifics:** Each page as separate entry, FK fields, ALL pages use `/ui-components`.

**Routes specifics:** PascalCase module codes → kebab-case (NEVER include `/business/` prefix).

### 8. Map Business Rules to Code

Load `references/handoff-mappings.md` for mapping rules.

For each rule: `ruleId`, `title`, `module`, `severity`, `implementationPoints[]`.

### 9. Handle personRoleConfig

If any entity has `personRoleConfig`, copy it verbatim into handoff.

### 10. Generate Seed Data

Load `references/handoff-seeddata-generation.md` for core seed generation.

- `category: "core"` → Navigation, Permissions, Roles
- `category: "business"` → Domain-specific data

### 11. Map Entity to Domain

Load `references/entity-domain-mapping.md` for mapping rules.

- Entity → `src/Domain/Entities/{App}/{Module}/{EntityName}.cs`
- ValueObject → `src/Domain/{Module}/ValueObjects/{VOName}.cs`
- Enum → `src/Domain/{Module}/Enums/{EnumName}.cs`

### 12. Declare Dependencies per File Entry

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

### 13. Write Result

Write via `ba-writer.enrichModuleHandoff` with the complete handoff payload:
- `complexity`, `filesToCreate` (8 categories), `brToCodeMapping`, `apiEndpointSummary`
- `prdFile`: `".ralph/prd-{moduleCode}.json"`
- `totalFiles`, `totalTasks`, `handedOffAt` (ISO timestamp)
- `featureDescription`: `{featureDescription}`

### 14. Write Specification Files (MANDATORY)

After writing the handoff data, ALSO write 5 companion files:

1. `.ralph/prd-{moduleCode}.entities.json` = VERBATIM copy of `{moduleDir}/entities.json`
2. `.ralph/prd-{moduleCode}.rules.json` = VERBATIM copy of `{moduleDir}/rules.json`
3. `.ralph/prd-{moduleCode}.usecases.json` = VERBATIM copy of `{moduleDir}/usecases.json`
4. `.ralph/prd-{moduleCode}.screens.json` = VERBATIM copy of `{moduleDir}/screens.json`
5. `.ralph/prd-{moduleCode}.permissions.json` = VERBATIM copy of `{moduleDir}/permissions.json`

Add `specificationFiles` to the PRD referencing these files (relative names, all in `.ralph/`):

```json
"specificationFiles": {
  "entities": "prd-{moduleCode}.entities.json",
  "rules": "prd-{moduleCode}.rules.json",
  "usecases": "prd-{moduleCode}.usecases.json",
  "screens": "prd-{moduleCode}.screens.json",
  "permissions": "prd-{moduleCode}.permissions.json"
}
```

### 15. POST-CHECK (BLOCKING)

After writing, verify:

1. Handoff not empty
2. All 8 categories present
3. `brToCodeMapping` non-empty
4. Section resources have `entity` field
5. `SeedData` contains CORE entries: NavigationModuleSeedData, NavigationSectionSeedData (if sections exist), PermissionsSeedData, RolesSeedData
6. For FIRST module only: `SeedData` contains APP-LEVEL CORE entries (NavigationApplicationSeedData, ApplicationRolesSeedData)
7. All 5 companion files exist in `.ralph/` and are non-empty
8. `specificationFiles` present in the PRD with all 5 paths
9. Entity count in companion matches source: `prd-{moduleCode}.entities.json` `entities[]` count = `{moduleDir}/entities.json` `entities[]` count
10. BR count in companion matches source: `prd-{moduleCode}.rules.json` `rules[]` count = `{moduleDir}/rules.json` `rules[]` count
11. Each `brToCodeMapping[].statement` is non-empty (not just a title paraphrase)

Display: `"POST-CHECK PASS: {moduleCode} -- 8 categories, {brCount} BRs mapped, {coreCount} core seeds, 5 companion files"`

## RETURN VALUE

Return a single JSON line:

```json
{ "moduleCode": "{moduleCode}", "filesCreated": 7, "errors": [], "complexity": "simple|medium|complex" }
```
