---
name: step-01b-applications
description: Application identity confirmation (single-app) or full application decomposition (multi-app)
model: opus
next_step: steps/step-02-decomposition.md
---

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

# Step 1b: Application Identity & Decomposition

## MANDATORY EXECUTION RULES

- ALWAYS use ULTRATHINK mode
- ALL communication in `{language}`
- This step ALWAYS runs. It has two modes:
  - **Single-app mode** (`workflow.mode !== "project"`): Lightweight application identity confirmation — name, code, context, route, icon, table prefix validation, application roles recap. Creates the `seedDataCore.navigationApplications` entry.
  - **Multi-app mode** (`workflow.mode === "project"`): Full application decomposition as defined in sections 1-7 below.

---

## MODE GATE

```
IF workflow.mode === "project":
  → Execute FULL multi-app flow (sections 1-7 below)
ELSE:
  → Execute LIGHTWEIGHT single-app identity (sections 0a-0f below)
```

---

## SINGLE-APP PATH (sections 0a-0f)

> This path runs when `workflow.mode !== "project"` (single application, most common case).
> It confirms the application-level identity (Level 2 of the navigation hierarchy) before proceeding to module decomposition.

### 0a. Read Application Context

```
appFeature = ba-reader.findFeature({feature_id})
→ Read metadata: application, context, tablePrefix
→ Read cadrage: applicationRoles, coverageMatrix, globalScope
→ Read cadrage.codebaseContext (if exists)
```

### 0b. Derive Application Identity

From the cadrage data, derive the formal application identity:

```javascript
applicationCode = toPascalCase(metadata.application)  // e.g., "HumanResources"
applicationLabel = metadata.application                // e.g., "Ressources Humaines" (human-readable)
applicationRoute = `/${toKebabCase(applicationCode)}`  // e.g., "/human-resources"
applicationIcon = suggestIconFromDomain(applicationCode) // e.g., "users" for HR, "shopping-cart" for Sales
tablePrefix = metadata.tablePrefix                     // e.g., "rh_" (already defined in step-01)
sort = 1                                               // First (and only) application
```

**Icon suggestion heuristics:**
| Domain pattern | Suggested icon |
|---------------|---------------|
| HR, Employee, Staff, Personnel | `users` |
| Sales, Commerce, Revenue | `shopping-cart` |
| Finance, Accounting, Budget | `wallet` |
| Inventory, Stock, Warehouse | `package` |
| CRM, Customer, Client | `contact` |
| Project, Task, Planning | `clipboard-list` |
| Support, Ticket, Help | `headphones` |
| Reporting, Analytics, Dashboard | `bar-chart-2` |
| Other | `layout-grid` |

### 0c. Confirm Application Identity (BLOCKING)

Display the application identity:

```
{language == "fr"
  ? "## Identité de l'application\n\nVoici l'identité de votre application dans la hiérarchie de navigation SmartStack :"
  : "## Application Identity\n\nHere is your application's identity in the SmartStack navigation hierarchy:"}

| {language == "fr" ? "Niveau" : "Level"} | {language == "fr" ? "Valeur" : "Value"} |
|-------|-------|
| Application Code | `{applicationCode}` |
| Application Name | `{applicationLabel}` |
| Route | `{applicationRoute}` |
| Icon | `{applicationIcon}` |
| Table Prefix | `{tablePrefix}` |
| Sort Order | `{sort}` |

{language == "fr"
  ? "### Rôles applicatifs\n\nCes rôles seront hérités par tous les modules :"
  : "### Application Roles\n\nThese roles will be inherited by all modules:"}

| Role | Level | Permission Pattern |
|------|-------|--------------------|
{for each role in cadrage.applicationRoles: role.role | role.level | {kebab(applicationCode)}.* }
```

Ask via AskUserQuestion:
```
question: "{language == 'fr' ? 'Cette identité d\'application est-elle correcte ?' : 'Is this application identity correct?'}"
header: "Application"
options:
  - label: "{language == 'fr' ? 'Oui, parfait' : 'Yes, perfect'}"
    description: "{language == 'fr' ? 'Code, route, icône et rôles sont corrects' : 'Code, route, icon and roles are correct'}"
  - label: "{language == 'fr' ? 'Modifier' : 'Modify'}"
    description: "{language == 'fr' ? 'Changer le code, la route, l\'icône ou les rôles' : 'Change code, route, icon or roles'}"
```

**IF "Modify":**
→ Ask which field(s) to change via follow-up AskUserQuestion
→ Apply changes
→ Re-display and re-confirm (loop until validated)

### 0d. Build Application SeedData Entries

Create the `navigationApplications` entry (Level 1 hierarchy entry):

```json
{
  "navigationApplications": [
    {
      "code": "{applicationCode}",
      "label": "{applicationLabel}",
      "icon": "{applicationIcon}",
      "route": "{applicationRoute}",
      "sort": 1
    }
  ]
}
```

Create the `applicationRoles` entries (from cadrage.applicationRoles):

```json
{
  "applicationRoles": [
    { "code": "admin", "name": "{applicationLabel} Admin", "permissions": "*" },
    { "code": "manager", "name": "{applicationLabel} Manager", "permissions": "CRU" },
    { "code": "contributor", "name": "{applicationLabel} Contributor", "permissions": "CR" },
    { "code": "viewer", "name": "{applicationLabel} Viewer", "permissions": "R" }
  ]
}
```

> **NOTE:** The roles map from `cadrage.applicationRoles` levels. If the cadrage defined custom roles beyond the standard 4, include them here too.

### 0e. Write Application Identity to Feature.json

```
ba-writer.enrichSection({
  featureId: {feature_id},
  section: "metadata",
  data: {
    applicationCode: "{applicationCode}",
    applicationRoute: "{applicationRoute}",
    applicationIcon: "{applicationIcon}"
  }
})
```

> **NOTE:** The full `seedDataCore` arrays (`navigationApplications`, `applicationRoles`) will be written in step-03c when compiling the first module's specification. Here we only persist the identity fields in metadata so they are available to step-02 and step-03.

### 0f. Summary and Continue

```
{language == "fr"
  ? "✅ Application **{applicationCode}** identifiée\n\n- Route : `{applicationRoute}`\n- Icône : `{applicationIcon}`\n- Préfixe : `{tablePrefix}`\n- Rôles : {roleCount} rôles applicatifs définis\n\n→ Prochaine étape : décomposition en modules"
  : "✅ Application **{applicationCode}** identified\n\n- Route: `{applicationRoute}`\n- Icon: `{applicationIcon}`\n- Prefix: `{tablePrefix}`\n- Roles: {roleCount} application roles defined\n\n→ Next step: module decomposition"}
```

→ Load `steps/step-02-decomposition.md`

---

## MULTI-APP PATH (sections 1-7)

> This path runs when `workflow.mode === "project"` (multi-application mode).
> It takes the candidate applications identified during cadrage and formalizes them.

### 1. Load Project Context

```
projectFeature = ba-reader.findProjectFeature()
globalRoles = projectFeature.cadrage.globalRoles (if defined)
globalScope = projectFeature.cadrage.globalScope

// Candidate applications: PRE-IDENTIFIED from step-00 prompt analysis + enriched by step-01 cadrage
candidateApps = projectFeature.metadata.candidateApplications
// These candidates already have: name, description, modules[], context, dependencies[]
// They may also include transversal apps extracted from shared modules (step-01 section 5b)

IF candidateApps is null or empty:
  // Fallback: derive from coverage matrix (legacy path)
  candidateApps = projectFeature.cadrage.coverageMatrix grouped by domain
```

### 2. Application Identity (per candidate)

For EACH candidate application from the cadrage analysis:

#### 2a. Confirm Application Name and Context

Display proposed application:
```
{language == "fr"
  ? "### Application : {suggestedName}\n\n**Description :** {description based on coverage matrix items}"
  : "### Application: {suggestedName}\n\n**Description:** {description based on coverage matrix items}"}
```

Ask via AskUserQuestion:
```
question: "{language == 'fr' ? 'Cette application vous convient-elle ?' : 'Does this application suit you?'}"
header: "{appName}"
options:
  - label: "{language == 'fr' ? 'Oui, parfait' : 'Yes, perfect'}"
    description: "{language == 'fr' ? 'Nom et description corrects' : 'Name and description are correct'}"
  - label: "{language == 'fr' ? 'Modifier' : 'Modify'}"
    description: "{language == 'fr' ? 'Changer le nom ou la description' : 'Change name or description'}"
```

#### 2b. Table Prefix (per application)

Each application MUST have its own unique table prefix.

1. Derive suggested prefix from application name (2-5 lowercase letters + `_`)
2. Validate:
   - Format: `^[a-z]{2,5}_$`
   - No collision with platform prefixes: `auth_`, `nav_`, `usr_`, `ai_`, `cfg_`, `wkf_`, `support_`, `entra_`, `ref_`, `loc_`, `lic_`, `tenant_`
   - No collision with other applications in this project
3. Ask via AskUserQuestion for confirmation

#### 2c. Application-Specific Roles

Based on global roles from cadrage + application-specific needs:

```
{language == "fr"
  ? "### Rôles pour {appName}\n\nVoici les rôles hérités des rôles globaux, adaptés à cette application :"
  : "### Roles for {appName}\n\nHere are the roles inherited from global roles, adapted for this application:"}

| Role | Level | Permission Pattern |
|------|-------|--------------------|
{for each role: name | admin/manager/contributor/viewer | app.* pattern}
```

Ask via AskUserQuestion if additional roles are needed for this specific application.

#### 2d. Application Scope

Extract the subset of global scope that applies to this application:

```
applicationScope = {
  mustHave: globalScope.mustHave.filter(item => belongsToApp(item, appCode)),
  shouldHave: globalScope.shouldHave.filter(item => belongsToApp(item, appCode)),
  couldHave: globalScope.couldHave.filter(item => belongsToApp(item, appCode))
}
```

Display and confirm with user.

### 3. Inter-Application Dependency Analysis

After all applications are defined:

1. **Identify dependencies:** For each pair of applications:
   - Shared entities (e.g., Employee defined in HR, referenced by Self-Service)
   - Event flows (e.g., HR publishes "EmployeeCreated", Self-Service subscribes)
   - Authentication delegation (e.g., Self-Service uses HR's employee data for auth)
   - Data dependencies (e.g., Self-Service reads HR data)

2. **Build dependency graph:**
```
applicationDependencyGraph = {
  edges: [
    { from: "EmployeeSelfService", to: "HumanResources", type: "data-dependency", description: "Reads employee data" }
  ],
  topologicalOrder: ["HumanResources", "EmployeeSelfService"],
  layers: [
    { layer: 0, applications: ["HumanResources"] },
    { layer: 1, applications: ["EmployeeSelfService"] }
  ]
}
```

3. **Cycle detection:** If circular dependencies detected → BLOCKING ERROR
   - Display the cycle
   - Ask user to resolve (merge applications or remove dependency)

### 4. Client Checkpoint (BLOCKING)

Display the full application structure:

```
{language == "fr"
  ? "### Structure du projet\n\nVoici les applications identifiées :"
  : "### Project Structure\n\nHere are the identified applications:"}

| # | Application | Préfixe | Rôles | Dépendances |
|---|-------------|---------|-------|-------------|
{for each app: index | name | prefix | role count | dependency list}

{language == "fr"
  ? "### Ordre de traitement\n\nLes applications seront traitées dans cet ordre (fondations d'abord) :"
  : "### Processing Order\n\nApplications will be processed in this order (foundations first):"}

{for each layer: "Layer {n}: {app1}, {app2}, ..."}
```

Ask via AskUserQuestion:
```
question: "{language == 'fr' ? 'Cette structure de projet vous convient-elle ?' : 'Does this project structure suit you?'}"
header: "Validation"
options:
  - label: "{language == 'fr' ? 'Oui, continuer' : 'Yes, continue'}"
    description: "{language == 'fr' ? 'Passer à la décomposition en modules' : 'Proceed to module decomposition'}"
  - label: "{language == 'fr' ? 'Modifier' : 'Modify'}"
    description: "{language == 'fr' ? 'Ajouter, supprimer ou modifier des applications' : 'Add, remove, or modify applications'}"
  - label: "{language == 'fr' ? 'Fusionner en une seule' : 'Merge into one'}"
    description: "{language == 'fr' ? 'Finalement, c\'est une seule application avec plusieurs modules' : 'Actually, this is one application with multiple modules'}"
```

**IF "Merge into one":**
→ Convert back to single-application mode
→ Delete project-level feature.json
→ Create application-level feature.json with all scope items
→ Execute single-app path (sections 0a-0f above)

### 5. Create Per-Application Feature.json Files

For EACH application in topological order:

```
ba-writer.createApplicationFeature({
  id: generate_feature_id(),
  version: "1.0",
  scope: "application",
  status: "draft",
  metadata: {
    application: {app.code},
    applicationCode: {toPascalCase(app.code)},
    applicationRoute: {`/${toKebabCase(app.code)}`},
    applicationIcon: {app.icon},
    language: {language},
    featureDescription: {app.description},
    workflowType: "new",
    analysisMode: "interactive",
    mcpAvailable: true,
    tablePrefix: {app.tablePrefix},
    projectRef: {project_id},
    workflow: {
      mode: "application",
      moduleOrder: [],
      currentModuleIndex: 0,
      completedModules: [],
      currentModule: null
    }
  }
})
```

Store the created feature.json path in the project feature.json `applications[].featureJsonPath`.

### 6. Write to Project Feature.json

```
ba-writer.enrichApplicationRegistry({
  projectId: {project_id},
  applications: [
    {
      code: {app1.code},
      name: {app1.name},
      tablePrefix: {app1.tablePrefix},
      icon: {app1.icon},
      route: {app1.route},
      description: {app1.description},
      applicationRoles: [{...}],
      scope: { mustHave: [...], shouldHave: [...], couldHave: [...] },
      modules: [],
      dependencies: [{...}],
      status: "pending",
      featureJsonPath: {app1.featureJsonPath},
      estimatedComplexity: {app1.estimatedComplexity}
    },
    // ... more applications
  ],
  applicationDependencyGraph: {
    edges: [...],
    topologicalOrder: [...],
    layers: [...]
  }
})

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

### 7. Display Summary

```
{language == "fr"
  ? "### Décomposition en applications terminée\n\n"
  : "### Application decomposition complete\n\n"}

| Application | Préfixe | Route | Feature ID |
|-------------|---------|-------|------------|
{for each app: name | prefix | route | FEAT-NNN}

{language == "fr"
  ? "→ Prochaine étape : décomposition en modules pour **{firstApp}** (application {1}/{total})"
  : "→ Next step: module decomposition for **{firstApp}** (application {1}/{total})"}
```

---

## NEXT STEP

Load: `./step-02-decomposition.md` (for the first application in topological order, or the single application)
