# Team Orchestration — Business-Analyse Propose & Review

> **Loaded by:** step-02 when multi-module detected (`moduleOrder.length >= 2`)
> **Purpose:** Delegate module specification to autonomous agents with user review.
> **Rule:** Single module = NO team. Only create team for 2+ modules.
> **Execution:** Parallel by dependency layer — all modules in the same layer run simultaneously.

---

## Multi-Application Team Structure (Project Mode)

> **Only applies when `workflow.mode === "project"`** (multiple applications in a single BA session).
> In single-application mode, skip this section entirely.

When the project contains multiple applications, the team structure adds an **application-level outer loop** around the existing module-level inner loop:

```
Team Lead (project level)
├── Application 1 (in topological order)
│   ├── mod-{app1-module1} (parallel per dependency layer)
│   ├── mod-{app1-module2}
│   └── consolidation-{app1}
├── Application 2
│   ├── mod-{app2-module1}
│   ├── mod-{app2-module2}
│   └── consolidation-{app2}
├── Cross-Application Consolidation Agent
└── Handoff Agent (all applications)
```

**Application Loop Protocol:**

```
FOR each application in projectFeature.applicationDependencyGraph.topologicalOrder:
  1. Load application feature.json
  2. Read module decomposition for this application
  3. Execute §1-§4 (team setup → module specification → review → layer completion)
     - Team name: "ba-{projectName}-{appCode}"
     - Agent names: "mod-{appCode}-{moduleCode}"
     - Context passed to agents includes application-specific: context, tablePrefix, applicationRoles
  4. After all modules in this application are specified:
     - Run per-application consolidation (§5 — scoped to this application's modules)
     - Mark application as "specified" in project feature.json
     - Clean up application team

AFTER all applications specified:
  5. Run cross-application consolidation (§5-bis)
  6. Run unified handoff (§6 — all applications at once)
  7. Cleanup (§7)
```

**Key differences from single-application mode:**
- Team names include application code to avoid collisions
- Agent prompts include application context (not just module context)
- Cross-application consolidation runs AFTER all per-application consolidations
- Handoff generates one PRD per module + one cross-application PRD
- The team lead tracks both `completedApplications[]` and `completedModules[]`

---

## 1. Team Setup

After step-02 decomposition is complete and client has approved the module structure:

### 1a. Clean Up Old Team Data (MANDATORY)

Before creating the team, clean up any leftover data from previous sessions to prevent stale task collisions:

```bash
# Remove leftover task files from previous runs
rm -f ~/.claude/tasks/ba-{appName}/*.json 2>/dev/null
# Remove leftover team directory (TeamDelete may leave remnants)
rm -rf ~/.claude/teams/ba-{appName} 2>/dev/null
```

> **Why:** If a previous session used the same team name and crashed or was interrupted,
> leftover task files will be picked up by new agents, causing them to receive stale
> task_assignment notifications for wrong modules.

### 1b. Create Team and Capture Actual Name

```javascript
const result = TeamCreate({ team_name: "ba-{appName}" });
// CRITICAL: TeamCreate may return a DIFFERENT name than requested!
// Always use the RETURNED team_name, not the requested one.
const actualTeamName = result.team_name;
```

Store team context for the session:
```javascript
const teamContext = {
  teamName: actualTeamName, // ← RETURNED name, NOT "ba-{appName}"
  moduleOrder: metadata.workflow.moduleOrder,
  dependencyLayers: dependencyGraph.layers, // ← from step-02 topological sort
  completedModules: [],
  completedLayers: [],
  mode: "propose-review"
};
```

> **WARNING:** NEVER hardcode `"ba-{appName}"` in subsequent calls.
> Always use `teamContext.teamName` (the actual name returned by TeamCreate).

---

## 2. Module Agent Spawn — Parallel by Dependency Layer

Process modules **layer by layer**. Within each layer, spawn ALL agents **simultaneously**.

```
FOR each layer in dependencyGraph.layers:
  Execute §2a → §2b → §2c → §2d → §2e → §3 → §4
```

### 2a. Pre-Spawn Cross-Module Analysis

**ALWAYS executed for layers with 2+ modules.** Analyze the module definitions within this layer to identify cross-module touchpoints BEFORE spawning agents.

```
IF layer.modules.length >= 2:

  ULTRATHINK: Analyze module definitions for same-layer interactions:

  1. Shared entity names
     → Do any modules reference the same entity? (e.g., both "Products" and "Inventory"
       might reference a "Category" entity)

  2. Potential FK overlaps
     → Do any modules anticipate creating entities that others might reference?
     → E.g., Products creates "Product" entity, Orders references "Product" via FK

  3. Naming conventions
     → Will both modules use similar attribute names? (e.g., "Code", "Name", "Status")
     → Agree on a consistent naming pattern

  4. Shared lookup data
     → Do any modules reference common reference tables?
     → E.g., both use a "Status" enum, a "Country" lookup, a "Currency" type

  5. Permission path consistency
     → Verify permission paths won't collide:
       {context}.{app}.{module1}.{entity}.{action}
       {context}.{app}.{module2}.{entity}.{action}

  Build coordinationNotes for EACH module in the layer:
```

**coordinationNotes template** (injected into each agent's prompt):

```
## Same-Layer Coordination Notes

You are running IN PARALLEL with: {otherModuleCodes.join(", ")}

### Known Touchpoints
- {otherModule} will define entity "{EntityName}" — if you need to reference it,
  use CROSS_MODULE_QUERY to get the exact attribute structure
- Naming convention: use {convention} for shared concepts (e.g., "Status" enum values)
- Shared lookups: {list any common reference data both modules might create}

### Your Responsibilities vs Theirs
- You own: {your entities — list}
- They own: {their entities — list}
- Contested/shared: {entities both might create — QUERY before defining}

### Cross-Module FK Convention
When referencing an entity owned by a same-layer module:
1. Send CROSS_MODULE_QUERY to team lead asking for the entity's attribute structure
2. WAIT for the answer before defining your FK field
3. Use the exact entity name and primary key type from the answer
```

> **IF layer has only 1 module:** Skip §2a entirely. No coordination notes needed.

### 2b. Prepare Agent Context (per module)

For EACH module in the layer, gather the context the agent needs:

```
1. ba-reader.readApplicationContext({feature_id})
   → Extract: appName, featureId, context, language

2. Read module decomposition data from master feature.json:
   → modules[moduleCode]: code, name, description, featureType, entities,
     anticipatedSections, dependencies, detailTabs, estimatedComplexity, priority

3. ba-reader.getCompletedModulesSummary({feature_id})
   → Compact summary of already-specified modules from COMPLETED LAYERS (max 100 lines)
   → Includes: entity names, FK relationships, permission paths, shared types
```

### 2c. Spawn ALL Layer Agents Simultaneously

**For layers with 1 module** — single spawn (same as standard):

```javascript
Task({
  subagent_type: "general-purpose",
  team_name: teamContext.teamName,
  name: "mod-{moduleCode}",
  model: "opus",
  mode: "bypassPermissions",
  prompt: BUILD_PROMPT(references/agent-module-prompt.md, {
    appName,
    featureId,
    moduleCode,
    moduleDescription: module.description,
    featureType: module.featureType,
    entities: module.entities,
    anticipatedSections: module.anticipatedSections,
    dependencies: module.dependencies,
    detailTabs: module.detailTabs,
    estimatedComplexity: module.estimatedComplexity,
    priority: module.priority,
    completedModulesSummary,
    coordinationNotes: "",  // empty for single-module layer
    language: metadata.language,
    docsDir: "docs/business/{appName}/{moduleCode}/business-analyse/v{version}/"
  }),
  description: "Specify {moduleCode}"
});
```

**For layers with 2+ modules** — spawn ALL in a **single message** (parallel):

```javascript
// CRITICAL: All Task() calls MUST be in ONE message for parallel execution.
// Do NOT await between them — they MUST be sent together.

// Agent 1:
Task({
  subagent_type: "general-purpose",
  team_name: teamContext.teamName,
  name: "mod-{moduleCode1}",
  model: "opus",
  mode: "bypassPermissions",
  prompt: BUILD_PROMPT(references/agent-module-prompt.md, {
    ...moduleContext1,
    coordinationNotes: coordinationNotesForModule1,  // ← NEW
  }),
  description: "Specify {moduleCode1}"
});

// Agent 2 (IN SAME MESSAGE):
Task({
  subagent_type: "general-purpose",
  team_name: teamContext.teamName,
  name: "mod-{moduleCode2}",
  model: "opus",
  mode: "bypassPermissions",
  prompt: BUILD_PROMPT(references/agent-module-prompt.md, {
    ...moduleContext2,
    coordinationNotes: coordinationNotesForModule2,  // ← NEW
  }),
  description: "Specify {moduleCode2}"
});

// ... repeat for all modules in this layer
```

**BUILD_PROMPT**: Read `references/agent-module-prompt.md`, replace all `{placeholders}` with actual values (including the new `{coordinationNotes}`), and pass as the `prompt` parameter.

### 2d. Track Layer State

After spawning, initialize layer tracking:

```javascript
const layerState = {
  layerIndex: L,
  modules: layer.modules,                        // ["Customers", "Products"]
  pendingProposals: [...layer.modules],           // agents not yet PROPOSAL_READY
  receivedProposals: {},                          // { moduleCode: proposalSummary }
  approvedModules: [],                            // modules approved by user
  crossModuleQueries: [],                         // log of queries handled
};
```

### 2e. Wait for Layer Completion — Message Handling Loop

After spawning all agents in the layer, the team lead enters a **message handling loop**.
Messages from teammates are delivered automatically — do NOT poll or re-spawn.

```
WHILE layerState.pendingProposals.length > 0:

  Wait for next message from any agent in this layer.

  CASE message matches "PROPOSAL_READY:{moduleCode}":
    → Remove moduleCode from pendingProposals
    → Store proposal in receivedProposals[moduleCode]
    → Display: "✓ Module {moduleCode} proposal received ({received}/{total})"
    → IF pendingProposals is now empty:
        → All agents in this layer have proposed
        → Proceed to §3 (Layer Review)

  CASE message matches "CROSS_MODULE_QUERY:{targetModule}":
    → Handle per §2-bis (Cross-Module Coordination Protocol)

  CASE message matches "CROSS_MODULE_ANSWER_RELAY:{requestingModule}":
    → Forward to requesting agent per §2-bis

  CASE message matches "ERROR:{moduleCode}:{description}":
    → Handle per §8 (Error Recovery)
    → Remove from pendingProposals if module is skipped
    → IF pendingProposals is now empty → proceed to §3
```

> **This loop may take several minutes** as agents work autonomously.
> The team lead does nothing except handle cross-module queries during this time.

---

## 2-bis. Cross-Module Coordination Protocol (Runtime Relay)

When an agent sends `CROSS_MODULE_QUERY:{targetModule}`, the team lead routes the query based on the target module's state:

### Case 1: Target is in a COMPLETED layer

The target module's specification is already written to feature.json.

```
→ Read target module's entities/attributes from completedModulesSummary
→ Send answer directly to requesting agent:

SendMessage({
  type: "message",
  recipient: "mod-{requestingModule}",
  content: "CROSS_MODULE_ANSWER:{requestingModule}\nAnswer: {entity structure from completed module data}",
  summary: "Answer from completed {targetModule}"
})
```

### Case 2: Target is in CURRENT layer AND has sent PROPOSAL_READY

The target agent has finished its proposal — we have its specification data.

```
→ Extract relevant entity/attribute info from receivedProposals[targetModule]
→ Send answer directly to requesting agent:

SendMessage({
  type: "message",
  recipient: "mod-{requestingModule}",
  content: "CROSS_MODULE_ANSWER:{requestingModule}\nAnswer: {entity structure from proposal data}",
  summary: "Answer from {targetModule} proposal"
})
```

### Case 3: Target is in CURRENT layer AND still working (no PROPOSAL_READY yet)

The target agent is still specifying — relay the question.

```
→ Forward question to target agent:

SendMessage({
  type: "message",
  recipient: "mod-{targetModule}",
  content: "CROSS_MODULE_QUERY_RELAY:{requestingModule}\nQuestion: {original question}",
  summary: "Relay query from {requestingModule}"
})

→ Wait for target agent to respond with CROSS_MODULE_ANSWER_RELAY
→ Forward answer to requesting agent:

SendMessage({
  type: "message",
  recipient: "mod-{requestingModule}",
  content: "CROSS_MODULE_ANSWER:{requestingModule}\nAnswer: {answer from target agent}",
  summary: "Answer from {targetModule}"
})
```

### Case 4: Circular query (A asks about B, B asks about A simultaneously)

Both agents are blocked waiting for each other. The team lead MUST resolve this autonomously.

```
→ ULTRATHINK: Based on SmartStack conventions and module descriptions,
  make a consistent design decision for BOTH modules.
→ Send CROSS_MODULE_ANSWER to BOTH agents with compatible entity structures.
→ Log resolution in layerState.crossModuleQueries[] for later review.
```

> **Every cross-module query is logged** in `layerState.crossModuleQueries[]` for display during §3 review.

---

## 3. Layer Review — Quality-First Protocol

When ALL agents in a layer have sent PROPOSAL_READY, the team lead presents the results to the user.

### 3a. Cross-Module Interaction Analysis (layers with 2+ modules)

**ALWAYS displayed FIRST** for multi-module layers. This gives the user a bird's-eye view of how modules in this layer interact.

```
═══════════════════════════════════════════════════════════
  Layer {L} — {N} modules terminés — Analyse croisée
═══════════════════════════════════════════════════════════

### Interactions cross-module détectées

| Module A | Module B | Type | Détail |
|----------|----------|------|--------|
| {mod1} | {mod2} | FK | {mod1}.{entity}.{field} → {mod2}.{entity} |
| {mod1} | {mod2} | Concept partagé | Les deux définissent "{concept}" |
| {mod1} | {mod2} | Lookup | {mod1} référence {mod2}.{entity} comme donnée de ref |

### Requêtes cross-module résolues pendant la spécification ({count})
{FOR each query in layerState.crossModuleQueries:}
  - {requestingModule} → {targetModule}: {question summary} → {answer summary}

### Points d'attention
- {naming inconsistencies detected between module proposals}
- {potential permission path conflicts}
- {shared entity definition differences}

─────────────────────────────────────────────────────────
```

> **For single-module layers:** Skip §3a entirely — no cross-module analysis needed.

### 3b. Individual Module Review (ALWAYS — for quality)

Review each module's proposal individually. For multi-module layers, the user has already seen the cross-module context from §3a.

```
FOR each module in layer (respecting topologicalOrder within layer):
```

**Step 1:** Format and display the proposal:

```
═══════════════════════════════════════════════════════════
  Proposition pour le module {moduleCode}
  (Layer {L} — module {idx+1}/{layerTotal} — global {globalIdx+1}/{totalModules})
═══════════════════════════════════════════════════════════

{structured summary from agent — displayed as-is}

─────────────────────────────────────────────────────────
```

**Step 2:** Ask the user via AskUserQuestion:

```
Validez-vous cette spécification ?
Options:
  1. "Valider" → approve as-is
  2. "Modifier" → provide feedback for revision
  3. "Voir détail" → team lead reads module feature.json and displays full content
```

**Step 3 — IMMEDIATELY after AskUserQuestion returns, handle the response:**

**IF user selected "Valider" (approve):**
```
SendMessage({
  type: "message",
  recipient: "mod-{moduleCode}",
  content: "APPROVED:{moduleCode}",
  summary: "{moduleCode} approved by user"
})
```
→ CRITICAL: You MUST send this message. Do NOT skip this step.
→ Then WAIT for the agent to send `MODULE_COMPLETE:{moduleCode}`.
→ Add moduleCode to `layerState.approvedModules`.
→ Continue to next module in this layer.

**IF user selected "Modifier" (revision):**
→ Ask user for specific feedback via AskUserQuestion
→ Then send:
```
SendMessage({
  type: "message",
  recipient: "mod-{moduleCode}",
  content: "REVISION:{moduleCode}\n{user_feedback}",
  summary: "{moduleCode} revision requested"
})
```
→ Then WAIT for the agent to send a new `PROPOSAL_READY` → re-display this module's proposal.
→ Other modules in the layer are NOT blocked — their proposals remain in receivedProposals.

**IF user selected "Voir détail":**
→ Read module feature.json via ba-reader.readSection({feature_id, section})
→ Display relevant sections in detail
→ Go back to Step 2 (re-ask the validation question)

### 3c. Revision Limits

- Max **3 revision cycles** per module
- After 3 rejections: team lead asks user if they want to switch to **inline interactive mode** for this module
  - If yes: shutdown agent, team lead loads step-03a1-setup.md and executes interactively
  - If no: mark module as "needs-review" and continue to next module

### 3d. Layer Consistency Check (layers with 2+ modules)

After ALL modules in a layer are approved, perform a final cross-module consistency verification:

```
IF layer.modules.length >= 2 AND all modules approved:

  ULTRATHINK: Verify cross-module consistency:

  1. FK references: Do FK field names match actual entity names across modules?
     → e.g., if Products.CategoryId references Categories.Category, names must match

  2. Permission paths: Are paths consistent and non-colliding?
     → business.{app}.{module1}.{entity}.read vs business.{app}.{module2}.{entity}.read

  3. i18n keys: Do keys follow consistent patterns? No collisions?
     → {module1}.labels.name vs {module2}.labels.name (OK — namespaced)

  4. Seed data IDs: Are deterministic GUIDs unique across modules?
     → Check DeterministicGuid inputs don't collide

  5. Entity attribute types: Are shared concepts typed consistently?
     → If both modules define "Status", is it the same enum type?

  IF inconsistency found:
    Display warning with specific issue:
    "⚠ Incohérence détectée entre {mod1} et {mod2}: {description}"

    AskUserQuestion:
      question: "Corriger automatiquement cette incohérence ?"
      options:
        1. "Corriger" → send REVISION to affected agent(s) with fix instructions
        2. "Ignorer" → proceed (will be caught in consolidation)

    IF "Corriger":
      → Send REVISION:{moduleCode}\n{auto-fix instructions} to affected agent
      → Wait for new PROPOSAL_READY
      → Re-approve (no full re-review needed — only the fix)

  IF no inconsistency found:
    Display: "✓ Cohérence cross-module vérifiée pour le layer {L}"
```

---

## 4. Layer Completion & Agent Shutdown

After ALL modules in a layer are approved AND consistency check passed:

### 4a. Shutdown ALL Layer Agents (MANDATORY — do NOT skip)

**IMMEDIATELY** after layer is fully approved, send shutdown_request to ALL agents in this layer:

```javascript
// Send shutdown to ALL layer agents
FOR each moduleCode in layer.modules:
  SendMessage({
    type: "shutdown_request",
    recipient: "mod-{moduleCode}",
    content: "Layer complete, shutting down"
  })
```

Wait for ALL agents to confirm shutdown (`shutdown_response approve: true`).

> **WARNING:** If you skip this step, agents will remain running indefinitely.
> Agents CANNOT self-terminate — they NEED shutdown_request from you.

### 4b. Update Layer Tracking

```javascript
FOR each moduleCode in layer.modules:
  teamContext.completedModules.push(moduleCode);
  ba-writer.updateModuleStatus({feature_id, moduleCode, status: "specified"});

teamContext.completedLayers.push(layerState.layerIndex);

Display:
"═══ Layer {L} complete — {layer.modules.length} modules specified ═══"
"═══ Progress: {completedModules.length}/{moduleOrder.length} modules ═══"
```

### 4c. Build Updated Context for Next Layer

Before spawning the next layer's agents, rebuild the `completedModulesSummary`:

```
ba-reader.getCompletedModulesSummary({feature_id})
→ Now includes ALL modules from completed layers
→ This summary is injected into next layer's agent prompts
→ Agents in the next layer will have full context of everything specified so far
```

### 4d. Next Layer or Consolidation

```
IF more layers remain in dependencyGraph.layers:
  → Go back to §2 for the next layer

IF all layers complete (all modules specified):
  → Proceed to §5 (Consolidation)
```

---

## 5. Consolidation Phase

After ALL modules are specified (all layers complete):

```
Display: "═══ All {moduleOrder.length} modules specified — Starting consolidation ═══"
```

### 5a. Spawn Consolidation Agent

```javascript
Task({
  subagent_type: "general-purpose",
  team_name: teamContext.teamName, // ← ACTUAL name from TeamCreate result
  name: "consolidation",
  model: "opus",
  mode: "bypassPermissions",
  prompt: `
You are a consolidation agent for business-analyse application "{appName}".

## Your Mission
Execute cross-module consolidation (steps 04a + 04b):
1. Load steps/step-04a-collect.md and execute
2. Load steps/step-04b-analyze.md and execute

## Context
- Feature ID: {featureId}
- Modules: {moduleOrder.join(", ")}
- Dependency layers: {JSON.stringify(dependencyGraph.layers)}
- All modules have status "specified"

## Output
Send CONSOLIDATION_READY with a structured report:
- Cross-module interactions (FK references, shared entities, event flows)
- Permission coherence (conflicts, overlaps, gaps)
- E2E user flows validated
- Global risks identified

## Communication
- CONSOLIDATION_READY:{appName}\n{report} → when analysis complete
- ERROR:{appName}:{description} → on blocking issue
  `,
  description: "Cross-module consolidation"
});
```

### 5b. Present Consolidation to User (04c Decision)

When CONSOLIDATION_READY received:

```
═══════════════════════════════════════════════════════════
  Consolidation cross-module — {appName}
═══════════════════════════════════════════════════════════

{consolidation report from agent}

─────────────────────────────────────────────────────────
```

AskUserQuestion: "Approuvez-vous la consolidation ?"
- "Approuver" → send APPROVED to agent → agent writes consolidation to master feature.json
- "Réviser" → send feedback → agent adjusts

After approval → shutdown consolidation agent.

**IF `workflow.mode === "project"`:** proceed to §5-bis (cross-application consolidation).
**ELSE:** proceed to §6 (handoff).

---

## 5-bis. Cross-Application Consolidation (Project Mode Only)

> **Only runs when `workflow.mode === "project"` AND all applications have been consolidated.**
> This step validates interactions BETWEEN applications, not just between modules within one application.

```javascript
Task({
  subagent_type: "general-purpose",
  team_name: teamContext.teamName,
  name: "cross-app-consolidation",
  model: "opus",
  mode: "bypassPermissions",
  prompt: `
You are a cross-application consolidation agent for project "{projectName}".

## Your Mission
Validate interactions between ALL applications in the project:

1. Cross-application shared entities
   → Entity defined in App A, referenced by App B via data dependency
2. Cross-application permission path consistency
   → Each app uses its own context prefix (e.g., business.hr.* vs business.selfservice.*)
3. Cross-application role consistency
   → Same role names have compatible permission levels across apps
4. Cross-application navigation coherence
   → Applications appear in correct contexts with non-colliding routes
5. Cross-application seed data ordering
   → Foundation applications must seed first (NavigationApplication order)

## Context
- Project ID: {projectId}
- Applications: ${JSON.stringify(projectFeature.applications.map(a => ({
    code: a.code, context: a.context, modules: a.modules.map(m => m.code)
  })))}
- Application dependency graph: ${JSON.stringify(projectFeature.applicationDependencyGraph)}

## Output
Send CROSS_APP_CONSOLIDATION_READY with:
- Cross-application interactions found
- Permission path conflicts (if any)
- Role inconsistencies (if any)
- Recommended seed data order
  `,
  description: "Cross-app consolidation"
});
```

When CROSS_APP_CONSOLIDATION_READY received:

```
═══════════════════════════════════════════════════════════
  Cross-Application Consolidation — {projectName}
═══════════════════════════════════════════════════════════

{cross-application consolidation report}

─────────────────────────────────────────────────────────
```

AskUserQuestion: "Approuvez-vous la consolidation inter-applications ?"
- "Approuver" → write cross-application interactions to project feature.json → proceed to §6
- "Réviser" → send feedback → agent adjusts

After approval → shutdown agent → proceed to §6.

---

## 6. Handoff Phase

```javascript
// Project mode: handoff agent processes ALL applications at once
// Single-app mode: handoff agent processes one application
const handoffContext = workflow.mode === "project"
  ? {
      scope: "project",
      projectId: projectId,
      applications: projectFeature.applications.map(a => ({
        code: a.code, context: a.context, featureId: a.featureJsonPath,
        modules: a.modules.map(m => m.code)
      })),
      totalModules: projectFeature.applications.reduce((sum, a) => sum + a.modules.length, 0)
    }
  : {
      scope: "application",
      featureId: featureId,
      modules: moduleOrder
    };

Task({
  subagent_type: "general-purpose",
  team_name: teamContext.teamName, // ← ACTUAL name from TeamCreate result
  name: "handoff",
  model: "sonnet",
  mode: "bypassPermissions",
  prompt: `
You are a handoff agent for business-analyse ${workflow.mode === "project" ? `project "${projectName}"` : `application "${appName}"`}.

## Your Mission
Execute the handoff sequence (steps 05a + 05b + 05c):
1. Load steps/step-05a-handoff.md and execute (file mapping, BR-to-code, API summary)
2. Load steps/step-05b-deploy.md and execute (prd.json, ba-interactive.html, manifest)
3. Load steps/step-05c-ralph-readiness.md and execute (quality gate)

## Context
${workflow.mode === "project" ? `
- Project ID: ${projectId}
- Applications: ${JSON.stringify(handoffContext.applications)}
- Total modules: ${handoffContext.totalModules}
- Workflow mode: project
- All applications and modules consolidated
` : `
- Feature ID: ${featureId}
- Modules: ${moduleOrder.join(", ")}
- All modules consolidated
`}

## Output
Send HANDOFF_READY with:
- PRD files generated (list)
- HTML deployed (path)
- Quality gate result (PASS/FAIL with details)

## Communication
- HANDOFF_READY:${workflow.mode === "project" ? projectName : appName}\n{report} → when all artifacts deployed
- ERROR:${workflow.mode === "project" ? projectName : appName}:{description} → on blocking issue
  `,
  description: "Handoff & deploy"
});
```

When HANDOFF_READY received:

```
═══════════════════════════════════════════════════════════
  Handoff complete — {appName}
═══════════════════════════════════════════════════════════

{handoff report}

─────────────────────────────────────────────────────────
```

Display final status to user. If quality gate PASS → ready for /ralph-loop.

---

## 7. Cleanup

After handoff complete:

```javascript
// Safety net: shutdown ALL remaining agents (module agents + consolidation + handoff)
// Module agents should already be shut down in §4a, but this catches any missed ones.
const allAgents = [
  ...teamContext.moduleOrder.map(m => `mod-${m}`),
  "consolidation",
  "handoff"
];

for (const agentName of allAgents) {
  SendMessage({
    type: "shutdown_request",
    recipient: agentName,
    content: "Workflow complete"
  });
  // Ignore errors for already-terminated agents
}

// Delete team
TeamDelete();

Display: "═══ Business-analyse complete — Team cleaned up ═══"
```

> **Note:** Sending shutdown_request to an already-terminated agent is harmless.
> This safety net ensures no orphan agents remain running.

---

## 8. Error Recovery

### Agent Crash in Parallel Layer

If an agent stops responding or sends ERROR while other agents in the same layer are still working:

```javascript
// 1. Do NOT disrupt other agents in the layer — they continue working
// 2. Check module status in feature.json
const moduleStatus = ba-reader.getModuleStatus({feature_id});

// 3. If module has partial data (status = "in-progress"):
//    → Spawn new agent for same module (joins existing layer)
//    → New agent detects partial state and continues
//    → Include in prompt: "Resume specification — partial data exists in feature.json"

// 4. Track retry count per module
if (retryCount[moduleCode] >= 3) {
  Display: "Agent failed 3 times for module {moduleCode}."
  AskUserQuestion: "Fallback to inline interactive mode for this module?"
  // If yes: remove from pendingProposals, will handle inline after layer completes
  // If no: skip module, mark as "needs-review"
}
```

> **Key difference from sequential mode:** Other agents in the layer keep running.
> The crashed module is retried independently without blocking the layer.

### Context Exhaustion on Team Lead

The team lead should stay under 30% context usage. If approaching limits:

1. **Minimize presentation**: Show only entity/section counts, not full details
2. **Auto-approve**: If user has approved 3+ modules without changes, suggest auto-approve mode
3. **Skip detail view**: Don't read full feature.json into team lead context

### Resume After Session Crash

If the entire session crashes:

1. User restarts `/business-analyse`
2. Step-00 detects existing feature.json with `status: "decomposed"` or partial modules
3. Reads `metadata.workflow.completedModules` to know which modules are done
4. Determines which layer to resume from:
   - Find the first layer where not all modules are in `completedModules`
   - Modules already completed in that layer are skipped
5. **Cleans up old team/task data** (§1a cleanup step) before creating new team
6. Creates new team (§1b — captures actual team name)
7. Spawns agents ONLY for incomplete modules in the current layer
8. Continues normally (parallel within layer, sequential between layers)

---

## Decision Matrix

| Condition | Action |
|-----------|--------|
| 1 module | NO team, classic inline execution |
| 2+ modules (single app) | Team mode (Propose & Review) |
| 2+ applications (project mode) | Application loop + per-app team mode |
| Modules in same dependency layer | Spawn ALL in parallel (single message) |
| Modules in different layers | Sequential — complete layer N before spawning layer N+1 |
| Layer with 1 module | Standard single-agent propose-review |
| Layer with 2+ modules | Pre-inject coordination notes + parallel spawn + batch review |
| Cross-module query (completed layer) | Answer from completedModulesSummary |
| Cross-module query (same layer, proposed) | Answer from receivedProposals |
| Cross-module query (same layer, working) | Relay to target agent |
| Circular cross-query (A↔B) | Team lead resolves autonomously |
| Agent error in parallel layer | Other agents continue; retry crashed module |
| User rejects 3 times | Offer fallback to inline interactive |
| Layer consistency check fails | Auto-fix via targeted REVISION |
| Context > 50% on team lead | Minimize presentation, suggest auto-approve |
| Session crash | Resume from feature.json + completedModules state |
| Project mode + all app modules done | Run per-app consolidation → advance to next app |
| Project mode + all apps done | Run cross-app consolidation (§5-bis) → unified handoff |
| Project mode + app has 1 module | Inline mode for that app (no team) |

---

## Message Protocol Summary

### Standard Messages (unchanged)

| Message | Direction | Purpose |
|---------|-----------|---------|
| `PROPOSAL_READY:{moduleCode}\n{summary}` | agent → lead | Specification complete |
| `APPROVED:{moduleCode}` | lead → agent | User approved |
| `REVISION:{moduleCode}\n{feedback}` | lead → agent | User wants changes |
| `MODULE_COMPLETE:{moduleCode}` | agent → lead | After approval confirmed |
| `CONSOLIDATION_READY:{appName}\n{report}` | agent → lead | Consolidation done |
| `HANDOFF_READY:{appName}\n{report}` | agent → lead | Handoff done |
| `ERROR:{moduleCode}:{description}` | agent → lead | Blocking error |
| `shutdown_request` / `shutdown_response` | lead ↔ agent | Termination |

### Cross-Module Messages (NEW — for parallel execution)

| Message | Direction | Purpose |
|---------|-----------|---------|
| `CROSS_MODULE_QUERY:{targetModule}\nQuestion:{q}\nContext:{ctx}` | agent → lead | Ask about same-layer module |
| `CROSS_MODULE_ANSWER:{requestingModule}\nAnswer:{a}` | lead → agent | Response to query |
| `CROSS_MODULE_QUERY_RELAY:{requestingModule}\nQuestion:{q}` | lead → target agent | Relay query to working agent |
| `CROSS_MODULE_ANSWER_RELAY:{requestingModule}\nAnswer:{a}` | target agent → lead | Response to relayed query |

---

## Token Budget Estimates

| Phase | Agent | Est. Context % | Notes |
|-------|-------|---------------|-------|
| Init + Cadrage + Decomposition | Team lead (inline) | 20-30% | Sequential, interactive |
| Pre-spawn analysis (per layer) | Team lead | +1-3% per layer | Cross-module touchpoint detection |
| Module specification (per module) | mod-{code} agent | 40-60% | Parallel within layer, fresh context |
| Cross-module relay (per query) | Team lead | +1-2% per query | Lightweight relay |
| Layer review (per layer) | Team lead | +3-5% per layer | Proposals + consistency check |
| Consolidation | consolidation agent | 30-40% | Cross-module validation |
| Handoff | handoff agent | 40-50% | Artifact generation |
| **Total team lead** | — | **30-50%** | Same budget, more throughput |
| **Total per module agent** | — | **40-60%** | Independent contexts |

**Key insight:** Team lead never exceeds 50% even with 10+ modules, because:
- Module specifications happen in separate parallel contexts
- Cross-module relay is lightweight (forward message, not re-analyze)
- Layer reviews are incremental (only current layer proposals)

**Wall-clock time improvement:**
- Layer with 3 independent modules: 1x (parallel) vs 3x (sequential) = **66% reduction**
- Typical 4-module app (2 layers of 2): ~50% wall-clock reduction
- Full benefit: apps with many independent foundation modules (layer 0)
