---
name: ba-develop-plan
description: >
  Orchestrates multi-module development across applications by executing the
  phased plan from /ba-create-plan-development. Reads dev-plan.json, runs a preflight
  check, then drives wave-by-wave execution: for each wave, launches one
  /ba-develop subagent per module (parallel within a wave), runs compile/test
  checks between waves, and reports unified results. Fully autonomous like
  /ba-develop: it never halts — unhealable issues (preflight not-ready, wave
  blockers, inter-wave compile failure) are recorded as blockers and the run
  continues to the end, aggregating every module's blockers in the final report.
group: H
argument-hint: '[--waves 1,2]'
allowed-tools: [Agent, Bash, Read, Glob, Grep, Skill]  # Bash: CLI invocation
---

# ba-develop-plan — Wave-by-wave development orchestrator

> **MAINTENANCE FREEZE (plan v3, 2026-07-18).** The SmartStack Studio's
> campaign orchestrator is the canonical multi-module driver (DAG of
> short-context units, per-unit retry, plan-gap gates). This wave
> orchestrator remains usable standalone but is FROZEN — no new
> orchestration logic lands here. See the freeze note in `ba-develop`.

## Your role

You are the **top-level orchestrator** of a multi-module, multi-application
development pipeline. You do not write code yourself. Your job is to:

1. Run the **preflight CLI** to validate the plan.
2. For each **wave** (sequential), launch **one subagent per module** (parallel
   within a wave) that each invokes `/ba-develop`.
3. Run compile/test **checks** between waves — record blockers but **never
   halt**; Wave N+1 always starts.
4. Report a **unified execution log** aggregating every module's `blockers[]`.

You never load PRD slices yourself — only the per-module subagents (via
`/ba-develop`) do. This keeps your own context minimal.

## Prerequisites

- `/ba-create-plan-development` has been run → `.smartstack/ba/_plan/dev-plan.json` exists.
- Each module in the plan has a PRD (`prd.md` + 3 slices + `pagespecs/`).
- Each module has a passing audit (`_audit/prd.md` → GO, score ≥ 80).
- The `projectPath` (target project) exists and has a feature branch checked out.

## Step 1 — Pre-flight validation

Invoke the preflight CLI:

```bash
npx --prefer-offline tsx skills/ba-develop-plan/cli/preflight-develop-plan/index.ts \
  --spec '{"baRoot": ".smartstack/ba", "projectPath": "<absolute-path>"}'
```

Parse the returned `ExecuteEnvelope<PreflightReport>`:

- `report.canProceed === true` → proceed to Step 2.
- `report.canProceed === false` → **do NOT halt**. Record each
  `report.waves[].modules[].blockers` entry as a plan-level blocker
  (`kind: "preflight.not-ready"`) and proceed anyway — each module's
  `/ba-develop` is itself never-halt and defers its own gaps. The preflight is
  advisory, not a gate.
- `report.waves[]` gives you the per-wave, per-module readiness status.
- Since 2026-08 (chantier 4.5) the preflight also reads the
  **`/ba-audit-pre-dev` aggregate** (`.smartstack/ba/_audit/pre-dev.md`) —
  the BA-side readiness verdict that previously had NO reader: a `❌` or
  `— non audité` cell for a module lands in that module's `blockers`
  (`preDev` on the report carries the detail), an absent aggregate is a
  warning (readiness unproven). Surface these blockers VERBATIM in the final
  report — they name the `/ba-create-*` + `/ba-audit-*` to run.

A `not-ready` module is **not** a reason to stop: it runs anyway (its
`/ba-develop` defers what it can't build) and its blockers aggregate into the
final report. Use `--waves 1,2` only when the user explicitly asks to limit the
run — never as an automatic reaction to a not-ready module.

## Step 2 — Branch check

Before launching any subagent, verify the working branch:

```bash
cd "<projectPath>" && git branch --show-current
```

- If on `main` or `develop` → **do NOT halt**: record a `git.cannot-commit`
  blocker (`userAction: run /gitflow start feature/develop-plan, then re-run`)
  and proceed. Per-module commits get skipped (each `/ba-develop` handles that),
  but the code still lands on disk.
- If on a feature branch → proceed.

## Step 3 — Wave-by-wave execution

For each wave (in ascending order, starting from Wave 1):

### 3a — Launch subagents (one per module, parallel within a wave)

For each module in the wave, launch a **subagent** with the Agent tool:

```
Agent(
  description: "ba-develop <APP>/<MODULE>",
  prompt: "You are running /ba-develop for module <APP>/<MODULE>.
    Module directory: .smartstack/ba/<APP>/<MODULE>
    Project path: <projectPath>

    Read the skill at skills/ba-develop/SKILL.md and follow its instructions
    exactly. The module directory contains the PRD files (prd.md, prd.entities.md,
    prd.api.md, prd.frontend.md, pagespecs/) and the upstream BA docs.

    Execute all 4 phases (Core → Entities → API → Frontend) with gates.
    Commit after each passed gate.

    Return the output contract JSON when done.",
)
```

**Parallelization rules:**
- Modules in the **same wave** have no cross-module dependencies → they CAN
  run in parallel (launch all subagents in one message).
- Modules in **different waves** MUST be sequential (Wave N+1 depends on Wave N).
- **Exception**: if two modules share the same application and Phase 0
  (core-seed) writes to the same `CoreSeedData` file, you MUST serialize
  Phase 0 across those modules. The simplest approach: run Phase 0 for ALL
  modules in the wave first (serially if same app), then parallelize Phases 1–3.

### 3b — Collect results

After all subagents in the wave complete, collect their results.
Each subagent returns (per `/ba-develop` output contract):

```json
{
  "moduleDir": "...",
  "moduleCode": "...",
  "phases": [
    { "name": "core", "status": "passed|passed-after-heal|completed-with-blockers|skipped", "commitHash": "..." },
    ...
  ],
  "blockers": [ { "phase": "...", "kind": "...", "severity": "critical|high|medium", "summary": "...", "userAction": "..." } ],
  "overallStatus": "success|success-after-heal|success-with-warnings|completed-with-blockers"
}
```

`/ba-develop` never emits `failed` or `halted` — it always completes, returning
`completed-with-blockers` whenever any item was deferred. Read `blockers[]`,
not a failure status.

### 3b-bis — Frontend registry reconciliation (per web app)

`/ba-develop` Phase 3c runs the app-wide `aggregate-component-registry` on each
module subagent's orchestrator. When a wave runs **N module subagents in
parallel**, those N aggregator runs each glob ALL `src/extensions/*Registry.ts`
and overwrite the SAME two shared files — `componentRegistry.generated.ts` and
its i18n sibling `moduleResources.generated.ts` — last-writer-wins. A run that
fires before a sibling module's locale JSON is scaffolded emits
`componentRegistry.generated.ts` **without** the
`import './moduleResources.generated'` line → the i18n registration becomes dead
code and every business page renders **raw keys**.

To reconcile, after ALL module subagents in the wave complete (and before the
inter-wave compile check), re-run the aggregator **once per web app** on the
orchestrator, serially:

```bash
npx --prefer-offline tsx skills/development/frontend/routes/cli/aggregate-component-registry/index.ts \
  --project-path "<web-root>"
```

By this point every module's locale bundles exist, so this final, serialized,
full-app run re-emits the import and registers every namespace — it is the
**authoritative** aggregation regardless of how the parallel intermediate runs
raced. If the CLI exits non-zero (its i18n regression guard or consistency canary
tripped), record a `frontend.registry-reconcile` blocker (high) and continue —
never halt. `<web-root>` is the app's web project root (the parent of `src/`),
the same path Phase 3c uses.

### 3c — Wave checkpoint (never halts)

`/ba-develop` always completes, so every module returns either a `success*` or
`completed-with-blockers` status. The wave **never blocks the run**:

1. **All modules `success*`** → record wave as `✅ passed`, proceed to next wave.
2. **One or more modules `completed-with-blockers`** → record wave as
   `⚠️ blockers`, **collect their `blockers[]` into the plan-level aggregate**,
   and **proceed to the next wave anyway**. A deferred artifact in Wave N may
   cause a Wave N+1 module to defer more items — that cascade is acceptable and
   surfaces as additional blockers, never as a stop.
3. Surface every collected blocker in the final report (§ Step 4).

### 3d — Inter-wave compile check

After the wave checkpoint, run a project-wide compile check:

```bash
cd "<projectPath>" && dotnet build --no-restore 2>&1
```

This catches cross-module integration issues (e.g. a module in Wave 2
references a type from Wave 1 that was renamed). If the build fails, **do NOT
halt** — record a `cross-wave.compile` blocker (high) with the error and
proceed to the next wave. Later waves may be independent; any further breakage
aggregates as more blockers.

## Step 4 — Final report

After all waves complete (the run always reaches this point — it never halts),
emit a unified report:

```
## Development Plan Execution Report

_Executed on <date> · <N> waves · <M> modules_

### Wave Summary

| Wave | Status | Modules | Duration |
|------|--------|---------|----------|
| 1    | ✅     | CRM/CONTACTS, BILLING/PRODUCTS | ~15min |
| 2    | ✅     | CRM/PIPELINE | ~10min |
| 3    | ⚠️     | BILLING/INVOICES (API deferred) | ~12min |

### Per-Module Results

| Module | Core | Entities | API | Frontend | Status |
|--------|------|----------|-----|----------|--------|
| CRM/CONTACTS | ✅ a1b2c3d | ✅ e4f5a6b | ✅ c7d8e9f | ✅ 01a2b3c | success |
| BILLING/PRODUCTS | ✅ ... | ✅ ... | ✅ ... | ✅ ... | success |
| CRM/PIPELINE | ✅ ... | ✅ ... | ✅ ... | ✅ ... | success-with-warnings |
| BILLING/INVOICES | ✅ ... | ✅ ... | ⚠️ deferred | ✅ ... | completed-with-blockers |

### Warnings
- CRM/PIPELINE: 2 ACs not covered (UC-CRM-PIPELINE-OPPORTUNITES-001#AC-02, UC-CRM-PIPELINE-OPPORTUNITES-002#AC-01)

### Blockers
- BILLING/INVOICES (api.2a, high): business test count (3) < rule count (5) — deferred, run continued

### Next Steps
1. Address BILLING/INVOICES API blockers (add the missing rules/tests)
2. Re-run: `/ba-develop-plan` (it will skip completed waves if commits exist)
```

## Re-run behavior

When re-running after a partial run (interrupted, or one that finished with
blockers the user has since addressed):

1. The preflight CLI re-checks readiness (it may have changed).
2. For each wave, check if all modules already have their commits:
   - Use `git log --oneline --grep="feat(<moduleCode>):"` to detect existing commits.
   - If ALL 4 phase commits exist for a module → **skip** it (already developed).
   - If SOME commits exist → resume from the first phase without a commit (tell
     the `/ba-develop` subagent which phase to start from).
3. This avoids re-running already-completed work.

## Anti-patterns

- **Halting the run because a wave has blockers.** `/ba-develop` always
  completes; a wave with `completed-with-blockers` modules proceeds to the next
  wave. Cross-module FKs from Wave N+1 resolve to Wave N entities — if a Wave N
  entity was deferred, Wave N+1 may defer more items; that cascade is acceptable
  and aggregates as blockers. Surface the causal link in the report, never stop.
- **Parallelizing across waves.** The topological sort guarantees the wave
  order is safe. Violating it breaks FK resolution.
- **Loading all modules' PRDs into your context.** You're the orchestrator —
  you only need the plan structure. Each subagent loads only its own PRD.
- **Modifying the plan during execution.** If you discover the plan is wrong,
  defer it as a blocker (`userAction: re-run /ba-create-plan-development`) and
  continue with the current plan — never halt.
- **Ignoring the inter-wave compile gate.** Per-module gates catch intra-module
  issues; the inter-wave gate catches cross-module integration issues.
- **Running Phase 0 (core-seed) in parallel for modules of the same app.**
  They write to the same `CoreSeedData.cs` — serialize Phase 0 within an app.
- **Relying on the parallel modules' Phase 3c aggregator runs as the final
  registry.** They race on the two shared generated files
  (`componentRegistry.generated.ts` + `moduleResources.generated.ts`) —
  last-writer-wins, which can drop the i18n import and ship raw keys. Always
  re-run `aggregate-component-registry` once per web app at wave end (§ 3b-bis).

## Non-goals

- Does not replace `/ba-develop` — it orchestrates multiple calls to it.
- Does not modify PRD files or BA tree.
- Does not handle deployment or CI — execution is local only.
- Does not invent a development order — it follows the plan from
  `/ba-create-plan-development`.
