# Contribuer à libreDecision

La référence produit est `docs/dev/BLUEPRINT-V2.md` — toute contribution qui touche au
comportement doit s'y conformer (ou proposer un amendement du blueprint, argumenté).

## Environnement

```bash
# Frontend — suffit pour tout le développement v2 (local-first, aucun serveur requis)
cd frontend
npm install
npm run dev        # http://localhost:3002 — port strict, jamais de fallback
npm test           # vitest — 342 tests
npm run build      # doit passer sans erreur avant tout commit

# Backend v1 (optionnel — conservé pour la future synchro)
cd backend
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
```

## Conventions

- **UI en français, code en anglais** (variables, commentaires, docstrings).
- **`app/lexicon.ts` est la source unique des libellés français.** Aucun libellé UI en dur
  dans un composant s'il existe (ou devrait exister) dans le lexicon. Ton : tutoyer la
  personne dans ses gestes ; actes collectifs à l'infinitif ; le sujet grammatical est
  toujours la personne ou le collectif — jamais la formule ni le système.
- **Test anti-lexique** (`tests/lexicon.spec.ts`) : la liste `FORBIDDEN_UI_TERMS` interdit
  certains mots dans toute chaîne visible (lexicon + templates `.vue`), insensible à la casse
  et aux accents. « Triage », « verdict », « déléguer »… peuvent exister comme identifiants de
  code, jamais à l'écran.
- **CSS** : borderless (profondeur via background + box-shadow), palettes par classes
  `.mood-*` sur `<html>`, composants natifs (`<input>`, `<select>`, `<button>` custom).
- **Composants** : `pathPrefix: false` — noms de fichiers uniques et parlants, auto-import.

## Invariants doctrinaux (non négociables)

- **Jamais de score sur une personne.** Pas de note, pas de réputation, pas d'agrégat
  individuel. `Person.attributes` ne sont jamais affichés à autrui ni agrégés ; l'historique
  de re-vote n'est visible que de son auteur.
- **Jamais de contenu adopté sans geste humain.** Le moteur constate des seuils sur des
  contenus formulés par des humains ; la cristallisation paramétrique, la clôture d'un
  dossier découpé, le départage d'une égalité sont des gestes datés — jamais des automatismes.
- **Le repli universel est le consentement** : tout collectif a un protocole Consentement
  (`protocolByRange.consent`), tout repli de résolution y mène.
- **Dérogation asymétrique** : alourdir libre (1 tap journalisé) ; alléger = note obligatoire
  + fenêtre d'objection.
- **Budget 400 lignes maximum par page** (`app/pages/`). Au-delà, extraire des composants.
- **Moteurs purs** : `app/engine/` ne dépend de rien (ni Nuxt, ni Pinia, ni DOM), s'importe
  uniquement via le barrel `~/engine`, et chaque module a ses tests vitest. Les stores
  s'écrivent avec des imports explicites (pas d'auto-import Nuxt) pour rester testables sous
  vitest pur.

## Ajouter une modalité de vote

1. `app/types/domain.ts` — étendre `VoteMethod` et les types de session/vote nécessaires.
2. `app/engine/` — le calcul dans un module pur + ses tests (`tests/engine/`). Exporter via
   `engine/index.ts`.
3. `app/engine/state.ts` — la règle de clôture (automatique à `closesAt`, ou geste humain).
4. `app/lexicon.ts` — les libellés (et vérifier l'anti-lexique).
5. `app/components/votes/VoteX.vue` — l'écran de la modalité, branché dans
   `pages/decisions/[id]/vote.vue`.
6. Seeds et gabarits — un protocole nommé qui la référence (le modifier = amender le Pacte).

## Ajouter un gabarit de collectif

Dans `app/data/templates.ts` : une entrée `TEMPLATE_CARDS` + le montage dans
`buildTemplateBundle()`. Invariants : protocole Consentement au minimum, clause A1
(« Notre finalité »), préambule Autonomie–Équilibre–Liaison proposé et modifiable, cercles
typés `kind`. Un bundle seed passe par le même `importBundle()` que l'import utilisateur.

## Tests

```bash
cd frontend && npm test
```

- `tests/engine/` — les moteurs purs (seuils, triage, états, médiane, impact…).
- `tests/stores/` — la façade decisions sous Pinia nu.
- `tests/seeds/` — tests de non-perte : le bundle Ğ1 doit conserver 33+59 clauses, décomptes
  et provenance exacts ; l'Atelier du Canal doit couvrir tous les états.
- `tests/lexicon.spec.ts` — l'anti-lexique.

Le compteur de référence est **342 tests verts**. Toute PR qui en casse un est refusée ;
toute fonctionnalité de moteur arrive avec les siens.

## Build

`npm run build` doit rester vert (zéro erreur, zéro warning nouveau) avant chaque commit.
Vérifier mobile + desktop (zéro régression CSS).
