# Reference: FEATURE_DATA Building Details

## moduleSpecs{} — ONE entry per module (CRITICAL)

### Architecture: Flat File Data Collection

**FLAT-FILE ARCHITECTURE:** Module data comes from separate JSON files collected in step-01,
NOT from index.json fields. Use `collected_data.modules[moduleCode].entities`, `.usecases`, etc.

For EACH module, use the flat file data from `collected_data.modules[moduleCode]`:

```javascript
const mod = collected_data.modules[moduleCode];

// NORMALIZE: usecases.json may use "useCases" (camelCase) or "usecases" (lowercase)
const rawUCs = mod.usecases?.useCases || mod.usecases?.usecases || [];
// NORMALIZE: rules.json may use "rules" or "businessRules"
const rawBRs = mod.rules?.rules || mod.rules?.businessRules || [];

moduleSpecs[moduleCode] = {
  useCases: rawUCs.map(uc => ({
    name: uc.name || uc.title || uc.id || "",
    sectionCode: uc.sectionCode || "",
    actor: uc.primaryActor || uc.actor || "",
    // SAFETY NET: steps may be strings[] (mainScenario) or objects[] ({step, action})
    steps: (uc.mainScenario || uc.steps || []).map(s =>
      typeof s === 'string' ? s : (s.action || s.description || "")
    ).join("\n"),
    alternative: (uc.alternativeScenarios || uc.alternativeFlows || []).map(a =>
      (a.name || a.trigger || "") + ": " + (a.steps || a.actions || []).map(s =>
        typeof s === 'string' ? s : (s.action || s.description || "")
      ).join(", ")
    ).join("\n")
  })),
  businessRules: rawBRs.map(br => ({
    name: br.name || br.id || "",
    sectionCode: br.sectionCode || "",
    category: br.category || "",
    severity: br.severity || "",
    statement: br.statement || br.description || "",
    example: (br.examples || (br.example ? [br.example] : [])).map(e =>
      typeof e === 'string' ? e : ((e.input || "") + " → " + (e.expected || ""))
    ).join("; "),
    domainSpecific: br.domainSpecific || false
  })),
  // ENTITY SAFETY NET: map fields[] → attributes[] if agent deviated
  entities: (mod.entities?.entities || []).map(ent => ({
    name: ent.name,
    description: ent.description || "",
    attributes: (ent.attributes || []).length > 0
      ? ent.attributes.map(a => ({ name: a.name, type: a.type || "string", required: a.required || false, description: a.description || "" }))
      : (ent.fields || []).map(f => ({ name: f.name, type: f.type || "string", required: f.required || false, description: f.description || "" })),
    relationships: (ent.relationships || []).map(r =>
      typeof r === 'string' ? r : r.target + " (" + r.type + ") - " + (r.description || ""))
  })),
  permissions: buildPermissionKeys(mod.permissions),
  apiEndpoints: mod.usecases?.apiEndpoints || []
}
```

### Building screens[] for HTML Interactive Mockups

```javascript
// BUILD screens[] for HTML interactive mockups — use helpers and format detection from references
const flatScr = mod.screens?.screens || [];
const sectionScr = mod.screens?.sections || [];
let screens = [];

// Apply normalization helpers from references/02-normalization-helpers.md
// Apply format detection from references/02-screen-format-detection.md

moduleSpecs[moduleCode].screens = screens;
```

### Enrich anticipatedSections with section-level UC/BR

**CRITICAL for HTML viewer to display UC/BR grouped by section.**

Execute AFTER moduleSpecs is built:

```javascript
// Post-processing: populate each section's useCases[] and businessRules[]
// using the sectionCode field from moduleSpecs
FEATURE_DATA.modules.forEach(m => {
  const spec = FEATURE_DATA.moduleSpecs[m.code];
  if (!spec) return;
  (m.anticipatedSections || []).forEach(section => {
    section.useCases = (spec.useCases || []).filter(uc => uc.sectionCode === section.code);
    section.businessRules = (spec.businessRules || []).filter(br => br.sectionCode === section.code);
  });
});
```

## Top-Level Fields: dependencies, consolidation, handoff

### dependencies[] (TOP-LEVEL — CRITICAL for HTML navigation)

```javascript
dependencies: (master.consolidation?.crossModuleInteractions || master.dependencyGraph?.edges || []).map(i => ({
  from: i.fromModule || i.from || "",
  to: i.toModule || i.to || "",
  description: i.description || ""
}))
```

**WARNING:** `data.dependencies` is used by the sidebar (navigation), module rendering, consolidation views,
handoff summary, and export. If this array is missing, the entire HTML page crashes with a TypeError.
ALWAYS include it, even if empty (`dependencies: []`).

### consolidation

```javascript
consolidation: {
  interactions: (master.consolidation?.crossModuleInteractions || []).map(i => ({
    from: i.fromModule,
    to: i.toModule,
    description: i.description || ""
  })),
  sharedEntities: master.consolidation?.sharedEntities || [],
  e2eFlows: (master.consolidation?.e2eFlows || []).map(f => ({
    name: f.name,
    steps: (f.steps || []).map(s => ({ module: s.module, action: s.action })),
    actors: (f.steps || []).map(s => s.permission).join(", ")
  }))
}
```

### handoff

```javascript
handoff: {
  complexity: master.handoff?.complexity,
  implementationStrategy: master.handoff?.implementationStrategy,
  moduleOrder: master.handoff?.moduleOrder,
  filesToCreate: master.handoff?.filesToCreate,
  brToCodeMapping: master.handoff?.brToCodeMapping,
  apiEndpointSummary: master.handoff?.apiEndpointSummary
}
```

## Helper Function: buildPermissionKeys()

See `references/data-mapping.md` for `buildPermissionKeys()` implementation.
