---
suivi: 1406
date: 2026-09-02
sujet: journal_doublons_regles_redaction
chantier: journal
type: fix
statut: poussé
hash: d6734f58
fichiers:
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - app/Services/JournalMiseAJourSyncService.php
  - app/Console/Commands/JournalSyncCommand.php
  - database/seeders/JournalMisesAJourSeeder.php
  - tests/Unit/JournalDoublons1406SourceTest.php
  - .cursor/rules/journal-mises-a-jour.mdc
  - docs/suivi/SUIVI_1406_journal_doublons_regles_redaction.md
---

## PROMPT ENVOYÉ

SUIVI #1406 — doublon journal sélecteur programme (#1403/#1405), cause fusion #364, nettoyage + règles rédaction + garde-fou warning.

## FICHES / ÉTAPE 0

- Catalogue : `database/data/journal_mises_a_jour_post_2026_06_12.php`
- Sync : `JournalSyncCommand` → `JournalMisesAJourSeeder` → `JournalMiseAJourSyncService`
- Table : `journal_mises_a_jour` ; idempotence sync = colonne `code` (update si existe, skip si soft-deleted)
- Fusion #364 : même `sujet` contigu → `fusion-{sujet}-{YYYYMMDD}`, titre = 1ʳᵉ, descriptions concaténées ; **ne retire pas** l’ancien `code` → doublon visible

## SYNTHÈSE

### A — Nettoyage
- Une seule entrée source `selecteur-programme-liste-format-1403-2026-09-02` (texte état final #1405).
- Soft-delete ciblé des orphelins `fusion-programme_selecteur-20260902` et `selecteur-programme-ordre-commune-1405-2026-09-02`.

### B — Récidive (minimal livré + arbitrage)
- Livré : warning `journal:sync` si doublon titre+date après fusion ; règles rédaction (fiche + règle Cursor).
- **Pas** de prune générique ni migration unique-sujet (arbitrage ci-dessous).

### C — Règles rédaction (lots suivants)
1. Une entrée = état actuel, pas l’historique des passes.
2. Affiner un sujet = mettre à jour le même `code`, pas une 2ᵉ entrée.
3. Relire tout le texte avant d’écrire (pas d’empilement contradictoire).
4. Pas d’entrée pour diagnostic / refactor / formatage interne.

## ARBITRAGE RESTANT (B profond)

| Option | Contenu | Coût |
|--------|---------|------|
| 1 (fait) | Règles + warning titre/date | Faible |
| 2 | Après fusion, soft-delete automatique de tous les codes absorbés | Touche sync en profondeur |
| 3 | Contrainte unique `(sujet)` ou `(titre, date_maj)` en base | Migration |

## DÉPLOIEMENT-TEST

```bash
git pull origin main
php artisan optimize:clear
php artisan view:clear
php artisan journal:sync
php artisan journal:sync   # 2ᵉ fois : pas de nouveau doublon
```

## LEÇON

`fuseContiguousEntries` + upsert par `code` sans prune = deux lignes pour un même annonce (code initial + `fusion-…`). Pour un ajustement même jour : **éditer l’entrée existante**.
