Files
decision/CLAUDE.md
T
YvvandClaude Fable 5 7cfc7ea352 v2 : nettoyage des orphelins v1 + documentation livrable
- 43 fichiers v1 supprimés (composants documents/protocols/sanctuary/toolbox,
  stores auth/documents/groups/mandates/organizations/protocols/votes,
  composables api/notifications/formula/websocket, utils doublons du moteur)
- nuxt.config épuré (polkadot retiré, KaTeX et apiBase gardés), meta v2
- README.md, CONTRIBUTING.md, CLAUDE.md réécrits pour la v2
- Build zéro erreur, 342/342 tests verts

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 14:09:05 +02:00

5.5 KiB
Raw Blame History

libreDecision

Boîte à outils de la première démocratie — décider ensemble, du trio à la population. v2 local-first : 6 routes de décision, 5 modalités, documents sous vote permanent, mandats, observatoire. Marque blanche par construction (seeds Ğ1 + Atelier du Canal). Référence produit : docs/dev/BLUEPRINT-V2.md — toute décision de comportement s'y adosse.

Protocole de début de session

  1. git pull --rebase origin main
  2. Si l'objectif de la session n'est pas précisé, le demander

Stack

  • Frontend : Nuxt 4 (Vue 3, TypeScript, SPA — SSR off) + Nuxt UI v3 + Pinia + UnoCSS ; package manager : npm ; port 3002 strict
  • Local-first : IndexedDB (idb-keyval) via app/data/persistence.ts — une clé ld2:<collectiveId> par collectif, export/import de bundles JSON, seeds par le même chemin
  • Backend v1 (FastAPI + SQLAlchemy async, port 8002) : conservé pour la future synchro — non requis pour le dev frontend ; runtimeConfig.public.apiBase gardé dans nuxt.config en prévision
  • Déploiement : Docker multi-stage + Traefik ; CI Woodpecker

Structure

frontend/
  app/
    engine/            # moteurs PURS (zéro dépendance Nuxt) : threshold (+electionResult),
                       # nuanced, modeParams, parametric (+crystallize), settings, state (canTransition),
                       # triage, impact — import UNIQUEMENT via le barrel ~/engine
    data/
      persistence.ts   # IndexedDB local-first
      templates.ts     # 7 gabarits de collectif (invariant : protocole Consentement partout)
      seeds/           # duniter-g1.bundle.json (324 Ko) + atelier-du-canal.bundle.json
    stores/
      collective.ts    # le tenant : collectif actif, état complet, cycle de vie des bundles
      decisions.ts     # façade d'actions sans état propre (LWW updatedAt, persist debounced)
    composables/       # useMood (useLibreMood), useFeed (le Fil = sélecteur pur), useSearch
    components/        # par domaine : chemin/ decisions/ votes/ texts/ mandates/ feed/
                       #               onboarding/ common/ (primitives Ld*)
    pages/             # 14 routes : / · decider · decisions (+[id], vote, observatoire) ·
                       #             textes (+[slug], formules) · mandats (+[id], nouveau) ·
                       #             creer (layout bare) · donnees
    lexicon.ts         # SOURCE UNIQUE des libellés FR + FORBIDDEN_UI_TERMS
    types/domain.ts    # le noyau du modèle
  tests/               # 342 tests vitest : engine/, stores/, seeds/ (non-perte), lexicon.spec.ts
backend/               # v1 FastAPI conservé pour la synchro future — ne pas développer dessus
  scripts/export_seed_bundle.py   # extrait seed.py → duniter-g1.bundle.json (source vivante = bundle)
docker/                # compose + Dockerfiles
docs/dev/BLUEPRINT-V2.md          # la référence produit v2
public/hexagram-tsing*.svg        # sceau 井 (#48 Tsing)

Données runtime

  • postgres-data / ipfs-data : volumes Docker du backend v1 — jamais écrasés
  • .env racine : secrets backend — jamais commité

Commandes

# Frontend (tout le dev v2)
cd frontend && npm run dev        # :3002
npm test                          # vitest — 342 tests, référence à maintenir
npm run build                     # zéro erreur exigé avant commit

# Seeds : le bundle est la source vivante ; seed.py (backend) est remplacé par
cd backend && .venv/bin/python scripts/export_seed_bundle.py   # régénère duniter-g1.bundle.json
# → test de non-perte bloquant : tests/seeds/duniter-g1.spec.ts

# Docker
docker compose -f docker/docker-compose.yml up

Conventions / pièges

  • UI français, code anglais (variables, commentaires, docstrings)
  • lexicon.ts d'abord : aucun libellé UI en dur si le lexicon peut le porter ; ton = tutoyer la personne, sujet grammatical = la personne ou le collectif, jamais la formule ni le système
  • Anti-lexique (tests/lexicon.spec.ts) : FORBIDDEN_UI_TERMS scanné sur lexicon + templates .vue (insensible casse/accents) — « triage », « verdict », « déléguer »… restent des identifiants de code, jamais des textes affichés
  • Invariants doctrinaux : jamais de score sur une personne (attributs jamais affichés à autrui, re-votes visibles du seul auteur) ; jamais de contenu adopté sans geste humain (cristallisation, clôture de dossier, départage = gestes datés) ; repli universel → consent ; dérogation asymétrique (alourdir libre, alléger motivé)
  • Budget 400 lignes max par page (app/pages/)
  • Moteurs purs : engine/ sans Nuxt/Pinia/DOM, import via ~/engine seulement ; stores en imports explicites (testables sous vitest nu) ; toute mutation d'état passe par canTransition(decision, to, ctx)
  • Formule inertie : R = C + B^W + (M + (1M)(1(T/W)^G))·max(0, TC)frontend/app/engine/threshold.ts ; l'Atelier (/textes/formules) est la seule maison des lettres W/T/M/B/G/C et de KaTeX
  • Mood system : useLibreMood() (composables/useMood.ts) — jamais de :global() dans <style scoped> pour les styles mood-dépendants (causa le bug dark mode veil)
  • Sceau (#48 Tsing) : LdSeal dans les layouts ; SVGs dans public/
  • CSS drop-shadow() safe pour l'emboss ; <filter> SVG inline cause des artefacts
  • Composants : pathPrefix: false — noms de fichiers uniques, auto-import
  • Domaine : decision.librodrome.org (Woodpecker CI ; ancien dossier : Glibredecision)