Files
decision/CLAUDE.md
T
YvvandClaude Opus 5.5 3996f6f99d Lot T4 : l'ADR 0014, le fichier de relecture textes-amorce.md, les contrôles e2e au document de T4
ADR 0014 « Les informations de fonctionnement ne se votent pas » : ce qui sort
(F1, F1.1, F1.2, F1.3, N1, N1.1, O1 et l'ordre de leurs sections), comment (rien
d'effacé, units.retired_at), la garde et ses refus, aucun vote futur (404 / 400),
ce que dira l'interface (U3), la file de publication, le retour arrière (prouvé
avec l'image de de1b7eb), les limites. textes-amorce.md : chaque texte avant /
après en fr, en, es, E12, ce qui sort, les choix à confirmer par Yvv.

e2e (aucun changement de web/src) : C3, C9 (27 articles, cinq sections, quatre
Propositions seed), C17 (33 modules à voter), C18 et C31 (le texte d'I1 de
T4), C25 (cinq lignes d'ordre, E12 dans l'ordre de « fondamental »), C35 (E12
entre E1 et E2 ; le glisser d'une place), C38 (4 Propositions seed).
CONTROLES.md suit ; CLAUDE.md : article_amend.rs, retire.rs, amorce.rs,
fixtures/seed-m8, le seed de 27 articles, l'invariant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 21:45:27 +01:00

14 KiB
Raw Blame History

libreDecision

Rendre possible la décision collective — en fonction du contexte, processus et modalités, boîte à outils. v3 : Rust + Svelte, un chantier à la fois, chacun livré en production avant le suivant (docs/chantiers/README.md). Référence du chantier en cours : docs/chantiers/acte-certification/CHANTIER.md — toute décision de comportement s'y adosse ; les décisions durables dans docs/adr/. La maquette v2 (Nuxt + FastAPI) vit dans maquette/, intacte (Yvv la présente) — ne pas y développer.

Protocole de début de session

  1. git pull --rebase origin main (puis la branche du chantier : chantier/acte-certification)
  2. Lire HANDOFF.md (où on en est, ce qui attend Yvv)
  3. Si l'objectif de la session n'est pas précisé, le demander

Stack

  • Serveur : Rust edition 2024, toolchain 1.99 épinglée (rust-toolchain.toml) ; rustup installé sans PATH → export PATH=$HOME/.cargo/bin:$PATH. axum 0.8, sqlx 0.8 (SQLite, requêtes runtime + migrate!), tokio, reqwest rustls.
  • Interface : SvelteKit 2 / Svelte 5 (runes), adapter-static SPA, vite 7, vitest, Playwright ; npm. Polices Literata (textes) + Nunito (interface), fontsource.
  • Ports : dev interface 3002 (strict, proxy /api → 8002) · serveur 8002 · serveur jetable des e2e 8092 (sa chaîne Ğ1 simulée prend un port local éphémère).
  • Déploiement : une image (docker/app.Dockerfile), Woodpecker ci.open.us.org dépôt LPK/decision → sonic (fabio). .woodpecker/app.yml = le produit sur decision.librodrome.org ; .woodpecker/maquette.yml = la maquette sur maquette.decision.librodrome.org (le produit passe en premier et retire de la racine tout conteneur qui la revendique ; la maquette attend un déploiement réussi du produit). Push sur prod (gitea@git.open.us.org:EHV/decision.git) branche main = déploiement.

Structure

crates/
  ld-engine/        # PUR (zéro I/O) : threshold (formule inertielle sur un quorum, judged_voters,
                    # yes_needed / no_needed), inertia (cinq crans, leurs quorums, bornes, médiane,
                    # référence, échelle), edit (coquille vs fond, diff), assist (découpage, similarité,
                    # longueur), compose (adoption, aperçus), ballot (bulletin scellé ld1:, le dernier
                    # fait foi, jugement d'une transaction), address (SS58, préfixe g1), objection
                    # (redit / contredit : la dernière arrivée retenue, les tours, l'échéance), correction
                    # (la coquille d'un autre : attendre, valider, refuser, l'échéance), order (l'ordre
                    # d'une section : qui en est, complété à la fin, places), pending (modules à voter),
                    # buffer (le tampon des votes, ADR 0012 : réconciliation, poids des états,
                    # SIMULATED_ADOPTS)
  trustin-access/   # règles d'accès de trustinWallet : sees / opens / manages_access, vote_way (serveur ou
                    # chaîne), answers_typo, lifts_objection / reiterates_objection, reads_message,
                    # sets_quorum, casts_simulated (le vote simulé, chaîne fermée), groupes par défaut
                    # (TEST_GROUP)
  ld-server/
    migrations/     # schéma SQLite — additif seulement
    src/            # lib.rs (routes, csrf, run) · config.rs (LD_*) · auth.rs (connect OAuth2, invitations,
                    # dev, bootstrap) · team.rs (liens d'équipe) · docs.rs (lecture, aperçus) · proposals.rs (écrire, voter,
                    # traduire) · objections.rs (faire, lever, réitérer, la version retenue) · typos.rs
                    # (les coquilles des autres) · messages.rs (la boîte « Messages ») · deadlines.rs
                    # (les échéances de 3 jours) · clock.rs (horloge injectable) · adoption.rs
                    # (balayage, verrou) · participation.rs (p̃, une fois par
                    # jour) · publish.rs (file → git) · wot.rs (W sur la chaîne) · seed.rs ·
                    # seed_amend.rs / inertia_amend.rs / seed_proposal_amend.rs (amendements gardés ;
                    # le dernier fait des Propositions seed, ADR 0011) · ballots.rs (vote groupé,
                    # bulletins de la chaîne Ğ1, le tampon : intention, preuve, réconciliation ; le vote
                    # simulé, « ton vote ») · simulation.rs (l'acte « supprime » de la fin de la simulation :
                    # `ld-server discard-simulation [--apply]`, ADR 0012) · indexer.rs (txComments)
                    # · modules.rs / order.rs / doc_title.rs (les modules, ADR 0009 : l'ordre d'une
                    # section, le titre du document) · module_amend.rs (ajout gardé) · quorum.rs (le quorum
                    # d'un article, PUT /units/{id}/quorum ; « un vote existe » : voted_units, ADR 0013) ·
                    # quorum_amend.rs (les quorums par cran, amendement gardé) · article_amend.rs (un
                    # article du seed ajouté à un document existant, gardé : E12, lot T4) · retire.rs
                    # (formule, inertie, ordonnancement sortis du document sans rien effacer :
                    # units.retired_at, ADR 0014) · web.rs (sert web/build)
    tests/          # api.rs (scénarios bout en bout) · ballots.rs (vote par la chaîne, indexeur simulé) ·
                    # objections.rs · typos.rs (lot F, horloge avancée, migration 0008) · modules.rs (ordre,
                    # titre, ajout gardé) · seed_proposals.rs (Propositions seed, publication suspendue) ·
                    # quorum.rs (quorums par cran, la route, « un vote existe », l'amendement) ·
                    # fixtures/seed-production-2026-11-02/ (le seed que la production fait tourner :
                    # I1/E1/E2 en vigueur, pour rejouer les amendements sur une base comme elle) ·
                    # seed_quorum_texts.rs (lots T, T2 et T3 : F1.1, F1.2, N1.1 ; aucun chiffre daté, chaque
                    # phrase vraie pour tout W et tout quorum ; fixtures/seed-quorum-m6b.json et
                    # seed-quorum-t2.json, leurs textes depuis M6b et M6c, pour rejouer T2 et T3 sur une
                    # base comme la production ; depuis T4, sur le seed de M8) · amorce.rs (lot T4 : les
                    # textes d'Yvv, E12, le retrait ; après M6c et après M8, chaque ligne de chaque table
                    # gardée, le retour arrière) · fixtures/seed-m8/ (le seed de M8 : les derniers textes
                    # de formule, inertie, ordonnancement, référence du lot U3)
seeds/              # acte-engagement-certification.json (trilingue, 27 articles, 5 sections, aucun en
                    # vigueur ; I1/E1/E12/E2 Propositions seed au cran 2 (seed::SEED_PROPOSAL_LEVEL),
                    # inertie 3 ailleurs ; modules en vigueur sans vote : le titre à 4, l'ordre de chaque
                    # section à 2 ;
                    # quorums par cran : 12 · 12 · 50 · 50 · 50 Monnaie libre, 1 partout essai)
                    # upcoming/<groupe>.json : les « À venir » des outils d'un groupe (fr, en, es), lus au démarrage
web/src/
  lib/i18n/         # fr.ts SOURCE (types Key) · en.ts · es.ts — parité testée
  lib/components/   # Sidebar, DocPanel, VoteFold (le vote déplié sous l'article), BallotPanel (panier),
                    # ChainSign (signature, Ğecko), VersionDetails, ProposeView, UnitBlock, DeepList,
                    # OrderLine / Reorder (l'ordre d'une section : une ligne en fin de section, les poignées
                    # sur ses articles, sur place), QuorumSetting (le quorum de l'auteur), Crans (l'inertie dessinée),
                    # TitleBar / TitlePropose (le titre du document), Seal…
  lib/wallet/       # injected.ts (portefeuille injectedWeb3, polkadot-api chargé à la signature) · gecko.ts
  lib/basket.ts     # PUR : sections, tout pour / tout contre, versions en concurrence, versions retenues, modules
  lib/objections.ts # où l'auteur répond à une objection · lib/diff.ts : le diff resserré d'une coquille
  lib/order.ts      # PUR : placer, monter / descendre, ce qui a bougé
  routes/           # / (accueil + choix du groupe) · connexion · invitation · equipe · g/[group] (piliers, en cours) ·
                    # g/[group]/docs · g/[group]/docs/[doc] (lecteur,
                    # vote déplié ?vote=, panneau sans onglets ?onglet=panier|proposer|details|reglages ;
                    # l'ancien onglet=propositions déplie le vote ; note : docs/chantiers/acte-certification/UX-lecteur.md)
                    # · g/[group]/decisions · g/[group]/mandats ·
                    # g/[group]/protocoles (à venir) · acces (trustinWallet) · messages (la boîte) ;
                    # /groupes, /decisions… redirigent
web/e2e/            # Playwright C1–C38 + M1, M2 ; serve.sh = serveur jetable /tmp/ld-e2e sur :8092 et
                    # chain-mock.mjs (nœud et indexeur Ğ1 simulés) ; faux portefeuille dans helpers.ts
docker/             # app.Dockerfile · app-compose.yml (sonic)
.woodpecker/        # app.yml · maquette.yml
docs/               # chantiers/ · adr/ · dev/BLUEPRINT-V2.md (doctrine de la maquette) · recherche/
maquette/           # v2 intacte (frontend Nuxt, backend FastAPI, docker, docs-v1)

Données runtime — jamais écrasées

  • Production : volume lpk-libredecision-app_data (/data : libredecision.db, textes/ = clone du dépôt publié, keys/ = clé de publication, bootstrap-admin.txt). Jamais down -v, jamais recréé.
  • Maquette : volumes lpk-decision-main_postgres-data / _ipfs-data (inchangés).
  • Local : data/ (gitignoré) — le supprimer repart du seed. Les e2e utilisent /tmp/ld-e2e.
  • Un document seedé n'est jamais réinstancié : dès qu'il existe en base, c'est de la donnée.

Commandes — la boucle (tout vert = fait)

export PATH=$HOME/.cargo/bin:$PATH
cargo fmt --all --check && cargo clippy --workspace --all-targets -- -D warnings && cargo test --workspace
cd web && npm run check && npm test && npm run build && npm run e2e     # e2e : 40 contrôles (42 tests, C25 et C35 en deux)

LD_DEV_LOGIN=1 cargo run -p ld-server     # :8002, sert web/build
cd web && npm run dev                     # :3002 à chaud
docker build -f docker/app.Dockerfile --target production .   # rejoue toute la boucle

Conventions / pièges

  • UI français, code anglais ; trilingue : aucune chaîne affichée en dur, tout passe par web/src/lib/i18n/fr.ts puis en/es (test de parité + FORBIDDEN_UI_TERMS). Tutoyer ; le sujet est la personne ou le groupe, jamais le système. Le français du texte voté fait foi.
  • Moteur pur : une règle de vote / édition / composition s'écrit et se teste dans ld-engine avant d'être câblée. Le serveur ne décide jamais l'accès seul : trustin-access.
  • Invariants : les informations de fonctionnement (formule, inertie, ordonnancement) ne se votent pas : hors du document, une unité retirée (units.retired_at) n'est ni lue, ni votée, ni comptée, ni publiée, et rien n'est effacé (ADR 0014) ; au départ, aucun article n'est en vigueur : I1, E1, E12 et E2 sont des Propositions seed (ouvertes, mises en avant, au cran 2 ; seuls les modules sont des seeds a minima), et la publication d'un document attend son premier texte en vigueur (ADR 0011) ; un quorum par cran (12 · 12 · 50 · 50 · 50 dans Monnaie libre), que l'auteur d'un article change avant le premier vote : sous le quorum, les votants qui manquent comptent comme « non », et une seule voix ne fait jamais passer un texte (quorum ≥ 2), sauf dans le groupe d'essai (quorum 1 ; ADR 0013) ; une coquille ne demande pas de vote, un changement de fond si ; la coquille d'un autre attend son auteur (un administrateur pour le seed) ou 3 jours, et en vigueur seule une coquille validée change le texte ; une objection retient la dernière arrivée jusqu'à sa levée (jamais un texte en vigueur ; ADR 0010) : elle n'entre pas en vigueur, et on peut y retirer son vote ou passer à « contre », jamais ajouter un « pour » (Yvv, 01/11/2026 : « Retirer ou "contre" ») ; l'inertie de l'inertie hérite du cran de l'article (cinq crans, ADR 0007) ; le groupe d'essai ne publie jamais ; dans Monnaie libre, un vote est une transaction Ğ1 et le dernier fait foi dans l'ordre de la chaîne (ADR 0008) — jamais de transaction réelle en test (chaîne simulée ; un essai réel est un acte « paye » d'Yvv).
  • Écritures : en-tête x-requested-with: libredecision obligatoire (CSRF) ; cookie ld_session. Les tests d'API passent par Client (tests/api.rs).
  • Pièges vus : pkill -f target/debug/ld-server tue son propre shell → pkill -x ld-server ; un from_secret absent fait refuser tout le pipeline Woodpecker ; la route hôte /* de fabio masque le webroot ACME → arrêter le service avant acme.sh --issue ; Playwright en locale fr-FR (sinon l'interface part en anglais).
  • Design : sans bordures, arrondis 16/12/20/14, quatre ambiances pierre, calcaire (claires), nuit, ardoise (sombres) (data-mood, posé avant le premier rendu, clé ld:mood), logo « Clé de voûte » (Logo, jamais incliné, --cle par ambiance), sceau hexagramme 井 #48 en SVG (Seal — jamais le glyphe, qui s'affiche mal). Mouvement réduit respecté.
  • Domaine : decision.librodrome.org ; dépôt des textes git.open.us.org/yvv/decision-depot-textes-reference (provisoire : puis un dépôt pour l'ouverture, puis le dépôt officiel pour les textes en vigueur).