---
name: ba-reconcile-menu
description: >
  Reconciles the `.smartstack/ba/` menu tree (sections/modules currently in
  `index.md`) against the codes embedded in downstream documents (`use-case.md`,
  `screen.md`, `règles-métier.md`, `rbac.md`). Detects RENAMES (heuristic) and
  DELETIONS, asks the user to validate the diff, then rewrites the downstream
  docs (drops stranded UC/SCR/BR/RBAC blocks, scrubs body references, renames
  codes in place). Idempotent. Run AUTOMATICALLY as Phase 0.5 of `/ba-loop`
  whenever the menu was modified after content was created — never skip a
  modified menu, always audit and correct.
allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion]
argument-hint: '[--dry-run] [--app APPCODE]'
---

# ba-reconcile-menu — Menu reconciliation

You are the **menu reconciler**. Your job: when the user has modified the
menu tree (`/ba-create-menu`) after downstream content was generated,
detect what changed (rename or delete of a section/module) and either
**migrate** the existing UC/SCR/BR/RBAC codes to the new code or **clean
up** the stranded blocks.

You **never invent content** — you delete stale references and rename codes
that the heuristic (Levenshtein + UC overlap) confidently matches. When in
doubt, you **defer to the user** via `AskUserQuestion` before applying.

## Why this skill exists

`/ba-loop` (and the per-phase `/ba-create-*` skills) operate in "enrich" mode
— they **add** items but **never remove**. If a section disappears from the
menu, its UCs / screens / rules still exist in the downstream files and
become orphans. The audits don't detect this by default (the SEC-007 and
UC-019 rules were added to catch it, but those audits **report** the problem;
this skill **fixes** it).

The rule the orchestrator follows:

> **En cas de modification du menu lors d'un rerun, tu ne peux pas skipper :
> tu dois auditer si ce qui a été fait est correct et corriger si ce ne
> l'est pas.**

## Inputs

- The `.smartstack/ba/` tree must exist (otherwise the menu hasn't even been
  created — defer to `/ba-create-menu`).
- Optional `--app APPCODE`: scope to one application (default: all).
- Optional `--dry-run`: report the plan without writing.

## Workflow

### Step 1 — Dry-run scan

Invoke the CLI in dry-run mode to discover what changed:

```bash
npx --prefer-offline tsx skills/business-analyse/reconcile-menu/cli/reconcile-menu/index.ts \
  --spec '{"baRoot": ".smartstack/ba", "dryRun": true}'
```

The CLI returns a JSON envelope describing:
- `renames[]` — sections/modules whose code changed in the tree but whose
  downstream codes still use the old name. Each rename carries a confidence
  score (0..1) and a reason (`code-similar`, `uc-overlap`, or both).
- `deletions[]` — sections/modules referenced by codes but absent from the
  tree, with no rename match.
- `staleRefs[]` — every code that points to a ghost section, useful for
  display.

If **both arrays are empty** → the tree is consistent. Report a one-liner to
the user (`"Menu cohérent — aucune réconciliation nécessaire."`) and stop.

### Step 2 — Show the diff + validate

Present the diff to the user as a single `AskUserQuestion` (closed choices):

```
J'ai détecté les écarts suivants entre le menu actuel et les documents
downstream :

— RENAMES (sections renommées) —
  - CRM/PIPELINE/OPPORTUNITES → CRM/PIPELINE/PROSPECTS (confiance 92%, code-similar+uc-overlap)
    Tous les UC/SCR/BR/RBAC seront réécrits sur le nouveau code.

— SUPPRESSIONS (sections supprimées) —
  - CRM/PIPELINE/LEGACY (3 codes orphelins, raison : no-rename-candidate)
    Les blocs UC/SCR seront supprimés et les références body nettoyées.

Que veux-tu faire ?
```

Options:
- **Appliquer la réconciliation** (recommandé) — applies all changes.
- **Voir le détail** — pre-prints each `staleRefs[].file:line` then re-asks.
- **Skipper cette réconciliation** — emits a verdict file with severity
  `warn` and aborts (downstream audits will then block).

### Step 3 — Apply

If validated, invoke the CLI without `--dry-run`:

```bash
npx --prefer-offline tsx skills/business-analyse/reconcile-menu/cli/reconcile-menu/index.ts \
  --spec '{"baRoot": ".smartstack/ba"}'
```

The CLI:
1. For each RENAME: substitutes every `(KIND)-APP-MOD-OLD-NNN` →
   `(KIND)-APP-MOD-NEW-NNN` in every downstream file.
2. For each DELETION: drops every heading block whose code matches the
   deleted (APP,MOD,SEC) triplet, scrubs body references (comma-separated
   lists collapse correctly; empty `Règles liées` lines become `—`).
3. Removes any orphan section directory still on disk.
4. Writes `.smartstack/ba/_audit/reconcile.md` (the verdict).

### Step 4 — Report

Surface a 3–6 line business summary:

```
Réconciliation appliquée :
- 1 section renommée (PROSPECTS), 2 codes migrés
- 1 section supprimée (LEGACY), 3 blocs nettoyés + 1 dossier retiré
- 5 fichiers modifiés

→ Relance /ba-loop pour ré-enrichir les sections renommées.
```

## Decision table

| Situation | Action |
|-----------|--------|
| Tree is consistent (no renames, no deletions) | One-liner OK, no Write, no user prompt |
| Renames only, all confidence ≥ 0.8 | Show diff + validate, then apply |
| Renames with confidence < 0.8 | Highlight low-confidence renames in the AskUserQuestion description; let user opt out per rename via free-text "Other" |
| Deletions only | Show diff + validate (deletions are destructive — git is the safety net) |
| Mix of renames + deletions | Show both blocks in the same AskUserQuestion |
| User picks "Skipper" | Write verdict with severity `warn`, abort |
| CLI returns `success: false` | Surface the `errors[]` to the user, halt |

## Guard rails

- **Never apply without showing the diff** — even on a single rename. The
  user must see what is about to change.
- **Never edit the menu tree itself** — that's `/ba-create-menu`'s job. This
  skill ONLY touches downstream docs.
- **Never invent codes** — the rename/delete decisions come from the
  deterministic CLI; you do not extrapolate.
- **Idempotent** — running twice in a row is a no-op (the second pass
  detects no remaining ghosts).
- **`git` is the safety net** — deletions are physical (no archive folder).
  The user can `git diff` / `git checkout` to recover.

## How the heuristic works (for transparency)

The CLI matches each "ghost" (section referenced by codes but absent from
the tree) against the "arrivals" (sections present in the tree without any
code) using two signals:

- **Code similarity**: Levenshtein distance normalised over the longer
  string length. < 0.3 → strong match (`OPPORTUNITES` ↔ `OPPORTUNITY` =
  0.08).
- **UC overlap**: Jaccard similarity of the UC heading titles between
  ghost and arrival (after lowercasing + accent stripping). ≥ 0.5 → strong
  match.

A rename is "clear" when **exactly one arrival** scores high enough AND
**beats the runner-up by ≥ 0.3 confidence**. Otherwise → DELETE (the user
can still rename manually before re-running).

## Used by the loop orchestrator

`/ba-loop` invokes this skill as **Step 0.5 — Menu reconciliation preflight**
(between Step 0 read-state and Step 1 actors). When `renames + deletions = 0`
the loop continues silently; otherwise the loop **pauses**, asks the user
via this skill, and only resumes after reconciliation is applied or
explicitly skipped.

This is the answer to "**you can't skip a modified menu — audit and
correct**".
