---
name: step-02-decomposition
description: Module decomposition - identify modules, dependency graph, topological sort, client checkpoint
model: opus
next_step: steps/step-03a1-setup.md
---

> **Context files:** `_shared.md`

# Step 2: Decomposition

## MANDATORY EXECUTION RULES

- ALWAYS present the module structure to the client for validation (BLOCKING checkpoint)
- NEVER proceed to specification without client approval of module structure
- ALWAYS sort modules by dependency (foundations first)
- ALWAYS detect dependency cycles (ERROR if found)
- This step runs for BOTH application mode and single-module mode (trivial for single)

## YOUR TASK

Decompose the application scope into ordered modules. Identify dependencies between modules and determine the processing order for iterative specification.

---

## EXECUTION SEQUENCE

### 1. Read Cadrage Results

```
// Determine context source based on workflow mode
IF workflow.mode === "project":
  projectFeature = ba-reader.findProjectFeature()
  currentAppCode = projectFeature.metadata.workflow.currentApplication
  currentApp = projectFeature.applications.find(a => a.code === currentAppCode)
  appFeature = ba-reader.findFeature(currentApp.featureJsonPath)

  // Scope decomposition to current application only
  → Read appFeature.cadrage.globalScope (application-specific scope from step-01b)
  → Read appFeature.cadrage.stakeholders (filtered to this application)
  → Read appFeature.cadrage.applicationRoles
  → Read appFeature.metadata.workflow.mode

  Display: "═══ Module decomposition for application: {currentApp.name} ({currentAppIndex + 1}/{total}) ═══"
ELSE:
  ba-reader.findFeature({feature_id})
  → Read cadrage.globalScope (mustHave, shouldHave, couldHave)
  → Read cadrage.stakeholders (roles, tasks, pain points)
  → Read cadrage.applicationRoles
  → Read cadrage.codebaseContext (existing modules found)
  → Read metadata.workflow.mode
```

IF status already "decomposed":
  Display: "Decomposition already completed. Loading next step."
  Load: steps/step-03a1-setup.md
  STOP

### 2. Module Identification

**From the scope items and stakeholder needs, identify distinct modules:**

For each mustHave/shouldHave scope item:
- Group related items into cohesive functional units
- Each module should be independently deployable
- Each module maps to a navigation entry at Level 3 (Module)

**ULTRATHINK Challenge:**
- "Is this one module or two? Could a user need only half of it?"
- "Are there hidden modules not mentioned in scope? (e.g., Notifications, Dashboard)"
- "Does the codebase already have modules that should be extended vs. created new?"

**For each module, determine:**

> **STRUCTURE CARD: modules[]** — Field names are EXACT. Include ALL fields below.
> ```json
> {
>   "code": "PascalCase",
>   "name": "Human-readable display name (e.g., 'Gestion du temps', 'Ressources Humaines')",
>   "description": "1-2 sentence description",
>   "featureType": "data-centric|integration|ui-centric|workflow|reporting|full-module",
>   "dependencies": ["OtherModule"],
>   "dependents": ["DependentModule"],
>   "status": "pending",
>   "featureJsonPath": null,
>   "priority": "must|should|could",
>   "sortOrder": 0,
>   "entities": ["Anticipated entity names"],
>   "estimatedComplexity": "simple|medium|complex",
>   "anticipatedSections": [
>     { "code": "list", "description": "Main page: grid, create button (navigates to /create page), click to detail", "resources": ["entity-grid", "entity-filters", "entity-create-page", "entity-edit-page"] },
>     { "code": "dashboard", "description": "Module KPIs and overview (if needed)", "resources": ["entity-kpi-cards", "entity-charts"] }
>   ],
>   "detailTabs": ["Informations", "RelatedEntity1", "Historique"]
> }
> ```
> **MANDATORY fields:** `code`, `name`, `description`, `featureType`, `dependencies`, `dependents`, `status`, `priority`, `sortOrder`, `entities`, `estimatedComplexity`
> **`name` vs `code`:** `code` is PascalCase for file paths/keys (e.g., "GestionTemps"). `name` is the human-readable label shown in navigation and HTML (e.g., "Gestion du temps"). They are ALWAYS both required.
> **OPTIONAL fields:** `anticipatedSections` (from cadrage coverageMatrix, enriched here with resources)
> **status:** Always `"pending"` at creation (updated to `"in-progress"` → `"specified"` → `"validated"` by step-03/04)
> **sortOrder:** Integer from topological sort (0 = foundation layer)
> **featureJsonPath:** Set to null at creation; updated to actual path when module feature.json is created in step-03
> **anticipatedSections:** Array of `{ code, description, resources[] }` objects. ONLY functional zones: `list` (always), `dashboard`, `approve`, `import`, `rapport`, `planning`. NEVER `create`, `edit`, or `detail` (those are actions/pages within `list`). Derived from `cadrage.coverageMatrix[].anticipatedSections` aggregated per module, then refined during decomposition.
> **detailTabs:** Array of tab names for the detail page (reached by clicking a row in `list`). Always includes "Informations". Add relationship tabs based on entity relations.

**Complexity estimation rules:**
| Criteria | Simple | Medium | Complex |
|----------|--------|--------|---------|
| Entities | ≤2 | 3-5 | >5 |
| Expected UCs | ≤4 | 5-10 | >10 |
| Integrations | 0 | 1-2 | >2 |
| Workflows | None | Simple | Multi-step with approvals |

### 3. Present Module List to Client

Display the identified modules as markdown:

```
## Modules identifiés pour {application_name}

{language == "fr"
  ? "**Préfixe de table :** `{metadata.tablePrefix}` — toutes les tables de cette application seront préfixées (ex: `{metadata.tablePrefix}Customers`, `{metadata.tablePrefix}Orders`)"
  : "**Table prefix:** `{metadata.tablePrefix}` — all tables in this application will be prefixed (e.g., `{metadata.tablePrefix}Customers`, `{metadata.tablePrefix}Orders`)"}

| # | Code | Nom | Type | Priorité | Complexité | Sections | Onglets détail | Entités |
|---|------|-----|------|----------|------------|----------|----------------|---------|
| 1 | Customers | Clients | data-centric | must | medium | list | Infos, Adresses, Contacts | Customer, Address, Contact |
| 2 | Products | Produits | data-centric | must | simple | list | Infos, Catégories | Product, Category |
| 3 | Orders | Commandes | workflow | must | complex | list, approve | Infos, Lignes, Historique | Order, OrderLine |
| 4 | Invoices | Facturation | workflow | should | medium | list, dashboard | Infos, Lignes, Paiements | Invoice, InvoiceLine, Payment |
```

> **Sections = functional zones only:** `list` (always), `dashboard`, `approve`, `import`, `rapport`, `planning`.
> **Onglets detail** = tabs in the detail page (reached by clicking a row in list).
> NEVER list `create`, `edit`, or `detail` as sections — they are actions/pages within `list`.

Ask via AskUserQuestion:
```
question: "Ces modules correspondent-ils à votre vision de l'application ?"
header: "Modules"
options:
  - label: "Validé"
    description: "La liste des modules est correcte, on peut continuer"
  - label: "Ajouter un module"
    description: "Il manque un module dans la liste"
  - label: "Retirer un module"
    description: "Un module est en trop ou hors périmètre"
  - label: "Modifier un module"
    description: "Renommer, fusionner ou découper un module"
```

IF modifications requested:
  Apply changes and re-present the list
  Loop until "Validé"

### 4. Dependency Analysis

For each pair of modules, determine dependencies:

**Dependency types:**
| Type | Signal | Example |
|------|--------|---------|
| FK | Module A references entity from module B | Order.CustomerId → Customer |
| Event | Module A produces event consumed by module B | Order.Created → Invoice.AutoGenerate |
| Shared-entity | Both modules operate on same entity | Both Orders and Invoices reference Customer |
| Lookup | Module A uses reference data from module B | Products.CategoryId → Categories (if separate module) |

**For each dependency found:**
```json
{
  "from": "Orders",
  "to": "Customers",
  "type": "FK",
  "description": "Order references Customer via CustomerId"
}
```

### 5. Topological Sort

Sort modules so dependencies are processed first:

**Algorithm:**
1. Build adjacency list from dependency edges
2. Compute in-degree for each module (number of dependencies)
3. Start with modules having in-degree 0 (no dependencies)
4. Process in BFS order: remove processed modules, reduce in-degrees
5. Group into layers (modules with same depth can be processed in parallel)

**Cycle detection:**
IF a cycle is detected:
  Display ERROR:
  ```
  ⚠ Dépendance circulaire détectée : {Module A} → {Module B} → {Module A}
  Les modules ne peuvent pas dépendre mutuellement.
  ```
  Ask user to resolve: remove one direction of the dependency

**Result:**
```json
{
  "topologicalOrder": ["Customers", "Products", "Orders", "Invoices"],
  "layers": [
    { "layer": 0, "modules": ["Customers", "Products"] },
    { "layer": 1, "modules": ["Orders"] },
    { "layer": 2, "modules": ["Invoices"] }
  ]
}
```

### 6. Client Checkpoint (BLOCKING)

Display the complete decomposition as markdown:

```
## Structure de l'application {application_name}

### Graphe de dépendances

```
Customers ──┐
            ├──→ Orders ──→ Invoices
Products ───┘
```

### Ordre de traitement

| Ordre | Module | Dépend de | Complexité | Sections | Onglets détail |
|-------|--------|-----------|------------|----------|----------------|
| 1 | Customers | (aucune) | medium | list | Infos, Adresses, Contacts |
| 2 | Products | (aucune) | simple | list | Infos, Catégories |
| 3 | Orders | Customers, Products | complex | list, approve | Infos, Lignes, Historique |
| 4 | Invoices | Orders, Customers | medium | list, dashboard | Infos, Lignes, Paiements |

### Détail des sections et resources par module

**Module : {module_name}**

| Section | Description | Resources |
|---------|-------------|-----------|
| list | Page principale : grille + création + navigation détail | {entity}-grid, {entity}-filters, {entity}-form |
| {section_2} | {functional zone description} | {resources} |

| Onglet détail | Contenu |
|---------------|---------|
| Informations | Fiche principale de l'entité |
| {relation_tab} | {sous-entités ou entités liées} |
| Historique | Journal des modifications |

(Repeat for each module)

> Les modules seront spécifiés dans cet ordre. Chaque module sera
> détaillé avec ses sections, entités, permissions et maquettes,
> puis validé avant de passer au suivant.
```

Ask via AskUserQuestion:
```
question: "Validez-vous cette structure et cet ordre de traitement ?"
header: "Validation"
options:
  - label: "Validé, on commence"
    description: "Commencer la spécification par {first_module}"
  - label: "Modifier l'ordre"
    description: "Changer la priorité de traitement des modules"
  - label: "Revenir aux modules"
    description: "Modifier la liste des modules"
```

IF "Revenir aux modules": Go back to step 3
IF "Modifier l'ordre": Re-sort and re-present

### 7. Write Module Registry

Use ba-writer to update master feature.json:

```
ba-writer.enrichModuleRegistry({
  featureId: {feature_id},
  modules: [{module objects with all fields}],
  dependencyGraph: {
    edges: [{dependency edges}],
    topologicalOrder: [{sorted module codes}],
    layers: [{layer groups}]
  }
})

// Initialize workflow loop state
ba-writer.enrichSection({
  featureId: {feature_id},
  section: "metadata.workflow",
  data: {
    moduleOrder: [{topological order}],
    currentModuleIndex: 0,
    completedModules: [],
    currentModule: {first module code}
  }
})

ba-writer.updateStatus({feature_id}, "decomposed")
```

### 8. Create Module Directories

For each module in moduleOrder:
```
Create: docs/business/{app}/{module_code}/business-analyse/v1.0/
```

> Module feature.json files will be created by step-03 when each module is processed.

### 9. Display Summary & AUTOCHAIN

```
═══════════════════════════════════════════════════════════
  DECOMPOSITION COMPLETE - {feature_id}
═══════════════════════════════════════════════════════════

| Aspect | Value |
|--------|-------|
| Modules identified | {count} |
| Dependencies | {edge count} |
| Dependency layers | {layer count} |
| First module | {first module name} |

### Processing Order
{numbered list of modules}

→ Starting iterative specification with {first_module}...
═══════════════════════════════════════════════════════════
```

### 9-bis. Team Mode Decision

After module registry is written and client has approved decomposition:

**IF moduleOrder.length >= 2 (TEAM MODE):**

```
Display:
═══════════════════════════════════════════════════════════
  Multi-module détecté ({N} modules) — Activation du Mode Team
═══════════════════════════════════════════════════════════

  Chaque module sera spécifié par un agent dédié avec un contexte frais.
  Vous validerez chaque proposition avant sa finalisation.

  Modules : {moduleOrder.join(" → ")}
═══════════════════════════════════════════════════════════
```

**Load: `references/team-orchestration.md`**
→ Follow the team orchestration protocol starting at §1 (Team Setup)
→ DO NOT load step-03a1-setup.md — agents will load it internally
→ **STOP HERE** — the team-orchestration.md takes over the workflow

**ELSE (single module — INLINE MODE):**

AUTOCHAIN — DO NOT STOP HERE:
- Do NOT ask "shall I continue?" or "voulez-vous que je continue?"
- Do NOT summarize what's coming next
- Do NOT wait for user input
- The user ALREADY validated at step 6 — that was the checkpoint
- IMMEDIATELY load step-03a1-setup.md

---

## SINGLE-MODULE MODE

When `workflow.mode = "module"` or only 1 scope item identified:

1. Create a single module entry with code = `{module_name}` from init
2. No dependency analysis needed
3. **Simplified checkpoint:** Quick confirmation instead of full validation
4. Set moduleOrder = [{single module code}]
5. Proceed to step-03 (inline, no team)

---

## NEXT STEP (conditional)

**If 2+ modules:** DO NOT load step-03a1. Load `references/team-orchestration.md` instead.
**If 1 module:** Load `./step-03a1-setup.md`

> **FORBIDDEN:** Asking any question between decomposition summary and step-03 load.
> The client checkpoint was at step 6. Do NOT add another one.

> **PROJECT MODE NOTE:** In project mode, this step runs once per application. After all modules for the current application are specified (via the module loop in step-03d), the application loop in `_module-loop.md` will advance to the next application and re-load this step for module decomposition of the next application. Module registries and dependency graphs are written to the APPLICATION-level feature.json (not the project level). The project-level feature.json tracks application status via `ba-writer.updateApplicationStatus()`.
