---
name: efcore-squash
description: EF Core migration squasher - combine multiple migrations into one
color: magenta
model: sonnet
tools: Bash, Glob, Read
steps:
  - steps/shared/step-00-init.md
  - steps/squash/step-00-init.md
  - steps/squash/step-01-backup.md
  - steps/squash/step-02-fetch.md
  - steps/squash/step-03-create.md
  - steps/squash/step-04-validate.md
---

# EF Core Squash Agent

Consolide plusieurs migrations en une seule, en récupérant le ModelSnapshot **ET les migrations** de la branche parente.

**Progressive Steps:** Load `steps/squash/` for detailed instructions.

## Principe Fondamental

```
RÈGLE D'OR: Récupérer SNAPSHOT + MIGRATIONS de la branche PARENTE

feature/* → snapshot + migrations de develop
develop   → snapshot + migrations de main
release/* → snapshot + migrations de main
hotfix/*  → snapshot + migrations de main
main      → BLOQUÉ (jamais squash)

⚠️ Ne JAMAIS récupérer uniquement le snapshot sans les migrations!
```

## Workflow

1. **Determine**: Identifier branche parente (`determine_base_branch`)
2. **List**: Migrations propres à cette branche (pas héritées)
3. **Confirm**: Demander validation utilisateur
4. **Backup**: Sauvegarder tous les fichiers
5. **Fetch**: Récupérer **ModelSnapshot ET migrations** de branche parente (CRUCIAL!)
6. **Delete**: Supprimer migrations de la branche UNIQUEMENT
7. **Create**: Créer migration consolidée (MCP obligatoire)
8. **Inject SQL Objects**: Si `Persistence/SqlObjects/` contient des `.sql`, injecter `SqlObjectHelper.ApplyAll(migrationBuilder)` dans le `Up()`
9. **Validate**: Build + script OK

## Commandes Clés

```bash
# Déterminer branche parente et DbContext
determine_base_branch   # → BASE_BRANCH, BRANCH_TYPE
detect_efcore_project   # → $DBCONTEXT, $DBCONTEXT_TYPE, $SCHEMA

# Identifier migrations propres à la branche
BASE_MIGS=$(git ls-tree -r --name-only "origin/$BASE_BRANCH" -- Migrations/ | grep "\.cs$" | grep -v "Designer\|Snapshot")
LOCAL_MIGS=$(find Migrations -name "*.cs" | grep -v Designer | grep -v Snapshot)

# Backup
BACKUP_DIR=".claude/gitflow/backup/migrations/squash_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR" && cp Migrations/*.cs "$BACKUP_DIR/"

# ═══════════════════════════════════════════════════════════════════════════
# CRUCIAL: Récupérer SNAPSHOT + MIGRATIONS de la branche parente
# ═══════════════════════════════════════════════════════════════════════════
git fetch origin "$BASE_BRANCH"

# 1. Récupérer le ModelSnapshot
git checkout "origin/$BASE_BRANCH" -- Migrations/*ModelSnapshot.cs
echo "✅ Snapshot récupéré de origin/$BASE_BRANCH"

# 2. Récupérer TOUTES les migrations de la branche parente
# ⚠️ OBLIGATOIRE: Sans ça, les migrations de develop/main seront perdues!
for base_mig in $BASE_MIGS; do
  base_name=$(basename "${base_mig%.cs}")
  git checkout "origin/$BASE_BRANCH" -- "Migrations/${base_name}.cs" 2>/dev/null || true
  git checkout "origin/$BASE_BRANCH" -- "Migrations/${base_name}.Designer.cs" 2>/dev/null || true
  echo "  ✅ $base_name récupéré"
done
echo "✅ $(echo "$BASE_MIGS" | wc -l) migrations récupérées de origin/$BASE_BRANCH"

# Supprimer migrations de la branche uniquement
for mig in $BRANCH_ONLY_MIGRATIONS; do
  rm -f "Migrations/${mig}"*
done

# Créer migration consolidée - UTILISER MCP OBLIGATOIRE
# $DBCONTEXT_TYPE = "core" ou "extensions" (de detect_efcore_project)
mcp__smartstack__suggest_migration({ description: "...", context: DBCONTEXT_TYPE })
# Résultat: core_v1.9.0_001_Description

dotnet ef migrations add "$MIGRATION_NAME_FROM_MCP" --context "$DBCONTEXT"

# Valider
dotnet build && dotnet ef migrations script --idempotent > /dev/null
```

## Safety Checks

- [ ] Branche parente identifiée
- [ ] main/master = BLOQUÉ
- [ ] User confirmation obtenue
- [ ] Backup créé
- [ ] **Snapshot parent récupéré** (origin/$BASE_BRANCH)
- [ ] **Migrations parent récupérées** (fichiers .cs ET .Designer.cs)
- [ ] Migrations de la branche supprimées (pas celles héritées!)
- [ ] **SQL Objects injectés** (si `Persistence/SqlObjects/*.sql` existe → `SqlObjectHelper.ApplyAll`)
- [ ] Build OK après squash
- [ ] Script générable

## Output Format

```
SQUASH - {current_branch}
  Base:   origin/{BASE_BRANCH}

  Récupéré de {BASE_BRANCH}:
    ✅ ModelSnapshot
    ✅ {N} migrations (fichiers .cs + .Designer.cs)

  Consolidé:
    Avant:  {M} migrations (propres à cette branche)
    Après:  1 migration ({MIGRATION_NAME} via MCP)

  Backup: .claude/gitflow/backup/migrations/squash_{timestamp}/

Prochains: /efcore:db-reset, /efcore:db-deploy
```

## Cas Particuliers

| Situation | Action |
|-----------|--------|
| 0 migrations propres | "Rien à squash" - exit |
| Snapshot identique | Migration vide créée - warning |
| Build fail | Restaurer backup automatiquement |
| Sur main/master | BLOQUÉ - exit code 1 |

## Priority

Safety > Correctness > Speed.

1. Backup OBLIGATOIRE (sauf --no-backup)
2. Snapshot parent OBLIGATOIRE (jamais optionnel)
3. Restauration auto si échec
