# Acte — Mise en ligne M8 (aucun chiffre daté dans les textes votés, lots T3, T3b et T3c) Classe : déploie Projet : libreDecision Date : 2026-11-03 **État : PRÉPARÉ, non figé** (en attente de la relecture indépendante de `de1b7eb`) — sur `de1b7eb` (`de1b7eb5d7e982aee7c70a41c9f5799fb171493e`) ; préparé par l'intégrateur libredecision-d4 ; exécuté par orch (dev-63) sous son mandat (« déploie » et « pousse », du 03/11 au 08/11). ## Pour Yvv : ce que tu liras de changé Deux textes votés de départ changent, dans les deux groupes : N1.1 « Niveaux d'inertie » et F1.2 « Paramètres par défaut ». F1.1 « Formule du seuil WoT » n'est pas touché. Chaque phrase finale, avant (le texte en ligne aujourd'hui) et après, en français, qui fait foi. **N1.1 « Niveaux d'inertie »** 1. Le quorum : - avant : « Chaque cran a aussi son quorum, qui n'est pas un nombre minimal de votants : sous le quorum, les votants qui manquent comptent comme « non ». » - après : « Chaque cran a aussi son quorum : sous le quorum de l'article, les votants qui manquent comptent comme « non », et il faut autant de « pour » que si ce quorum avait voté. » 2. La part : - avant : « La part dépend du cran et du nombre de votants, comparé à la participation habituelle du groupe : au-delà du quorum, plus il y a de votants, plus elle baisse, jusqu'à la majorité M quand tout le monde vote. » - après : « La part exigée dépend du cran et du nombre de votants, comparé à la participation habituelle du groupe : au-delà de ce quorum, plus il y a de votants, plus elle baisse, jusqu'à la majorité M quand tout le monde vote. » 3. La formule : - avant : « `Part exigée = M + (1 − M) × (1 − (T'/W)^G)`, où T' est le nombre de votants, ou le quorum s'il en manque. » - après : « `Part exigée = M + (1 − M) × (1 − (T'/W)^G)`, où T' est le nombre de votants, ou le quorum de l'article s'il en manque. » 4. L'introduction des cinq crans : - avant : « **Les cinq crans** : le quorum dans Monnaie libre, la part exigée quand le groupe vote comme d'habitude, puis quand tout le monde vote, et ce qui est à ce cran au départ. » - après : « **Les cinq crans** : le quorum dans Monnaie libre, la part exigée au-delà du quorum de l'article, à la participation habituelle, puis quand tout le monde vote, et ce qui est à ce cran au départ. » 5. Les cinq lignes des crans, la même retouche dans chacune : - avant : « … quorum 12 ; 60 % comme d'habitude, 50 % quand tout le monde vote. … » (de même 67, 75, 83 et 90 %) ; - après : « … quorum 12 ; 60 % à la participation habituelle, 50 % quand tout le monde vote. … ». Le reste de chaque ligne ne change pas. 6. La référence : - avant : « Tant que le groupe n'a pas voté sur 5 propositions, elle vaut deux fois le quorum de référence du document : 100 votants dans Monnaie libre. » - après : « Tant qu'elle repose sur moins de 5 propositions, elle vaut deux fois le quorum de référence du document : 100 votants dans Monnaie libre. » 7. Les bornes : - avant : « Elle reste entre 1 % et 50 % de l'électorat, et se mesure une fois par jour. » - après : « Elle est ramenée entre 1 % et 50 % de l'électorat, et se mesure une fois par jour. » 8. G : - avant : « **G** se calcule pour que la part exigée, à la participation habituelle, soit exactement celle du cran : `G = ln(1 − (s − M)/(1 − M)) / ln(p̃)`, où s est la part exigée comme d'habitude et p̃ la participation habituelle divisée par W. » - après : « **G** se calcule pour que la part exigée, au-delà du quorum de l'article, soit exactement celle du cran à la participation habituelle : `G = ln(1 − (s − M)/(1 − M)) / ln(p̃)`, où s est cette part du cran (60, 67, 75, 83 ou 90 %) et p̃ la participation habituelle divisée par W. » 9. L'exemple, retiré (rien ne le remplace) : « Exemple : avec 7 224 membres et une participation habituelle de 120 votants, quand 120 personnes votent, il faut 72, 81, 90, 100 ou 108 voix pour, du cran 1 au cran 5 ; au cran 3, 75 % des 120 votants, soit 90. Sous le quorum, les absents comptent comme « non » : au cran 2 (quorum 12), 9 voix pour passent avec 3 « contre » au plus ; au cran 3 (quorum 50), il faut 39 voix pour, avec 11 « contre » au plus. » **F1.2 « Paramètres par défaut »** 10. Le cran par défaut : - avant : « Le cran par défaut est le 3 (moyenne) : M = 55 %, un quorum de 50 dans Monnaie libre, et le groupe demande 75 % de « pour » quand il vote comme d'habitude. Tout nouvel article commence à ce cran. » - après : « Le cran par défaut est le 3 (moyenne) : M = 55 %, un quorum de 50 dans Monnaie libre, et, au-delà du quorum, le groupe demande 75 % de « pour » à sa participation habituelle. Tout nouvel article commence à ce cran. » **Pourquoi.** - **L'exemple (9)** : ta décision du 03/11, aucun chiffre daté dans un texte voté. 7 224 membres et 120 votants sont un état de la toile et une participation d'une date ; ce qui en était calculé sort avec eux. - **Le quorum (1)** : « pas un nombre minimal de votants » est faux pour un quorum bas fixé par l'auteur. Au quorum 2 (le plus bas dans Monnaie libre), il faut 2 « pour », à tout cran et sur toute toile : le quorum y est bien un minimum. La phrase nouvelle est vraie pour tout quorum : sous le quorum de l'article, le moteur demande exactement le seuil de ce quorum. « Autant de « pour » » plutôt que « autant de voix pour », qui se lisait d'abord « pour que » ; « de l'article », parce qu'un article peut avoir le quorum que son auteur a fixé, pas celui du cran. - **« À la participation habituelle » (4, 5, 8, 10)** : les textes disaient la part du cran « comme d'habitude », ce qui se lit comme le nombre de votants que le groupe a vraiment d'habitude. Le moteur, lui, prend la participation habituelle telle que N1.1 la définit : la médiane, **ramenée entre 1 % et 50 % de l'électorat**. Dès que la médiane sort de ces bornes, ou reste sous le quorum de l'article, la part n'est plus celle du cran. Deux exemples, calculés par le moteur : - 7 224 membres, médiane de 40 votants (sous 1 %, ramenée à 72,24), cran 2, quorum 12 : à 40 votants, il faut 28 « pour » (68,7 %), pas 27 (67 %) ; - 3 000 membres, médiane de 40 (dans les bornes), cran 3, quorum 50 : la part se calcule sur le quorum, il faut 38 « pour » de ces 40 votants (95 %), pas 75 %. Le terme défini, « à la participation habituelle », et « au-delà du quorum de l'article » rendent ces phrases vraies dans tous les cas. - **La part exigée, le quorum de l'article (2, 3)** : le terme défini, au lieu de « la part » et « le quorum » nus. La part exigée baisse au-delà du quorum ; le nombre de « pour », arrondi à l'entier, peut remonter d'une voix (9 sur 12, puis 10 sur 13). - **La référence (6)** : la médiane ne compte que l'année écoulée. Avec moins de 5 propositions dans l'année, la référence de 100 votants revient, même si le groupe en a voté plus avant ; « tant que le groupe n'a pas voté sur 5 propositions » était faux. - **Les bornes (7)** : « est ramenée » dit ce que fait le moteur (une médiane hors des bornes est remplacée par la borne) ; « reste » se lisait comme un constat. Trois tours de relecture indépendante y ont mené : T3 (le retrait et les phrases 1, 4, 10), puis T3b (G, et « autant de « pour » ») après « 2ce2028 : à reprendre », puis T3c (le terme défini partout, 2, 3, 5, 6, 7) après « e7ab82f : à reprendre ». Orch a donné son accord sur chaque tour : à 17 h 46, après 18 h 13 et après 19 h 18, avec ces mots : « c'est une correction de vérité, qui reste dans ce qu'il a validé ». Le détail et les textes entiers en fr, en, es : `docs/chantiers/acte-certification/textes-quorum-seed.md` (section « Lot T3 »). Chaque phrase de F1.2 et de N1.1, avec le test qui la vérifie : `docs/chantiers/acte-certification/t3c-liste-fermee.md`. ## Intention Mettre en ligne les lots T3, T3b et T3c. Yvv, le 03/11 avant 16 h 56, mot pour mot : « Je valide textes-quorum-seed (dont le point 3, pas de chiffre datés dans un texte voté). Tu peux lancer la livraison de decision. » (registre `~/harness/etat/reponses-yvv.md`, commit `9b701da`). Ordre T3 d'orch (dev-63, 03/11 vers 16 h 57) : retirer des textes votés F1.1, F1.2, N1.1 (fr, en, es ; deux groupes) tout chiffre qui dépend de l'état de la toile ou d'une participation à une date ; le texte reste vrai pour tout W ; la phrase de N1.1 « pas un nombre minimal de votants », fausse pour un quorum d'auteur bas, écrite vraie. Points 1, 2, 4 et 8 de `textes-quorum-seed.md` : le défaut reste. **Les preuves** (`crates/ld-server/tests/seed_quorum_texts.rs`, `crates/ld-server/tests/quorum.rs`) : la liste fermée (`t3c-liste-fermee.md`) nomme, pour chaque phrase qui affirme un nombre, une part ou un sens de variation, le test qui la vérifie contre le moteur sur une grille commune de 85 100 cas. Cette grille couvre W de 100 à 10 000 000, des médianes sous 1 % et au-dessus de 50 % de W ramenées par le moteur, chaque quorum d'auteur de 2 à W jusqu'à W = 1 000, et les cinq crans. Huit tests sont vus rouges sur le texte de `e7ab82f`, et quatre mutations du code sont vues rouges. Aucun chiffre daté : le test des nombres n'admet que des paramètres. ## Ce qui part Version `de1b7eb` (lots T3, T3b et T3c), qui contient la version en ligne `6f6197c`. Code touché : `crates/ld-server/src/seed_amend.rs` (les deux amendements), `crates/ld-server/src/wot.rs` (une constante rendue publique pour les tests, valeur inchangée), `seeds/acte-engagement-certification.json` (bases neuves), des tests (`tests/seed_quorum_texts.rs`, `tests/quorum.rs`) et une fixture (`tests/fixtures/seed-quorum-t2.json`, les textes de T2) ; le reste est documentation. `web/` et `crates/ld-engine` : rien. Configuration (`docker/`, `.woodpecker/`, `.env`, `data/`) et migrations : rien (prémisse 4). ## Ce que l'acte écrit dans la base de production (donnée runtime) - **Aucune migration.** - **Amendement de seed gardé** `2026-11-03-f1-2-chiffres` et `2026-11-03-n1-1-chiffres`, qui suivent (`follows`) ceux de T2 (`2026-11-03-f1-2-phrases`, `-n1-1-phrases`), décidé une fois par document, dans une transaction, seulement si personne n'a touché l'article : 0 vote (simulé compris), 0 ligne de bulletin, aucune coquille, traduction de membre ni objection, texte d'avant identique à l'empreinte posée par T2 (F1.2 `96caf353…`, N1.1 `7fbedcb8…`) ; textes d'après : F1.2 `0c3b800b…`, N1.1 `8107c5fc…` ; F1.2 et N1.1 admis à la révision 4 seulement si ce sont les amendements suivis (M5, M6b, M6c), et eux seuls, qui l'ont écrite. - `proposals` : texte fr, révision + 1 (F1.2 et N1.1 → 5) ; - `revisions` : une ligne `amendment` ; - `translations` : en et es remplacés ; - `seed_amendments` : la décision ; - `outbox` : une ligne par article dans Monnaie libre, qui attend (publication suspendue) ; rien pour l'essai. Refus possibles, le texte d'avant reste : `not_a_seed`, `no_open_version`, `voted_into_force`, `confirmed`, `votes`, `ballots`, `corrected`, `translation_edited`, `signalled`, `revised`, `text_differs`, `changed`. - Les amendements de T2 sur F1.2 et N1.1 sont marqués dépassés : ils ne décident plus rien. - **F1.1 n'est pas touché. Aucun vote, aucune autre proposition, aucun autre article n'est touché ; la publication reste suspendue.** ## Répétition **Faite le 03/11 de 20 h 03 min 37 à 20 h 04 min 20, réseau coupé** (`unshare -rn`, boucle locale seule : `m8/repetition-isolee.sh`), avec le serveur de `de1b7eb` (binaire de la boucle, construit à 20 h 03, copié en `m8/ld-server-de1b7eb` ; il porte l'empreinte `8107c5fc…`), sur une copie (18 h 47 min 52, empreintes inchangées depuis) de la copie de production prise par orch de 17 h 46 min 22 à 17 h 46 min 30 (production sur `6f6197cc`), publication vers un dépôt nu local (journal `m8/repetition-m8c.log`, scratchpad de l'intégrateur). Deux démarrages. Orch comparera les comptes de la production à ceux de cette copie avant de pousser. | | Avant | Après | |---|---|---| | F1.1 (deux groupes) | ouverte, seed, révision 3, 0 vote, 0 bulletin | inchangée | | F1.2, N1.1 (deux groupes) | ouvertes, seed, révision 4, 0 vote, 0 bulletin | révision 5 | | Révisions | 119 | 123 | | Traductions | 144 | 144 (en, es des deux articles remplacés) | | `seed_amendments` | 22 | 26 | | File de publication (Monnaie libre) | 10 en attente, 13 faites | 12 en attente, 13 faites | | Commits vers le dépôt des textes (local) | — | 0 (« publication suspended … waiting=12 ») | | Tout le reste (`m8/counts.sh` : migrations 1–11, propositions, unités en vigueur, I1/E1/E2, `inertia_changes`, votes, bulletins, signalements, identités, quorums) | | identique | **La base entière comparée** (`.dump`, et colonne par colonne) : changent exactement les 4 propositions de F1.2 et N1.1 (`body`, `revision`, `updated_at` : `ff53cbdc`, `13ee215f` dans Monnaie libre, `e7ae6bcb`, `d75f7e90` dans l'essai), leurs 8 traductions en et es (`body`, `source_hash`, `updated_at`), 4 révisions et 4 décisions ajoutées, 2 lignes de file ajoutées et les 10 lignes en attente reportées (`next_at`), les deux compteurs (`sqlite_sequence` : révisions 123, file 25). Rien d'autre (`settings` inchangé : W n'a pas pu être relu, réseau coupé). `integrity_check` ok, `foreign_key_check` vide. Les textes écrits sont ceux du seed de `de1b7eb`, en fr, en et es, dans les deux groupes (comparés). Journal : quatre « seed amendment applied » (`2026-11-03-f1-2-chiffres`, `-n1-1-chiffres` × essai, Monnaie libre), « publication suspended … waiting=12 », aucune ligne ERROR ; un seul WARN, attendu réseau coupé : « web of trust size: no node nor indexer answered, keeping the last value ». **Un second démarrage ne rejoue rien** (comptes identiques, aucun « applied »). Deux répétitions précédentes, sur `2ce2028` (17 h 54, réseau non coupé : W relu sur `rpc.duniter.org`, `settings.wot_size` 5 709 → 5 711) et sur `e7ab82f` (18 h 54, réseau coupé), avaient donné les mêmes comptes ; seuls les textes écrits diffèrent. ## Effet attendu - Dans les deux groupes, N1.1 n'a plus d'exemple chiffré et dit la phrase du quorum vraie ; N1.1 et F1.2 disent « au-delà du quorum » ; en fr, en et es. F1.1 inchangé. - Rien d'autre ne change ; le dépôt des textes reste à `9e0f45a`. Irréversibilité : **partielle**. Le code se remet en arrière ; les nouveaux textes restent (l'ancien est dans l'historique de chaque proposition). ## Avant — prémisses vivantes 1. La production sert `6f6197c` : santé `"build":"6f6197cc"` ; `prod/main` → `6f6197c`. 2. Sur une copie fraîche, `m8/premisse.sh ` (scratchpad de l'intégrateur, lecture seule) : 6 lignes, toutes `open`, origine `seed`, révision 3 pour F1.1 et 4 pour F1.2 et N1.1, votes, bulletins, coquilles et objections à 0 ; migration 11. Un article touché est refusé par l'amendement avec sa raison, et l'acte reste valable pour l'autre. **Lu par l'intégrateur le 03/11 à 17 h 47, puis à 18 h 54**, sur ses copies de la copie d'orch de 17 h 46 : l'attendu exact ; 0 vote et 0 ligne de bulletin en tout ; une identité. À relire sur la copie fraîche juste avant la poussée, et comparer `counts.sh` à la colonne « Avant » de la répétition. 3. La relecture indépendante de `de1b7eb`, inscrite « ok » dans `~/harness/etat/relectures.json`. - Première relecture, **`2ce2028` : à reprendre** (sous-agent neuf, sans le contexte de l'intégrateur, lancé à 17 h 55, inscrit à 18 h 12 ; transcript `~/.claude/projects/-home-yvv-Documents-PROD-DEV-libreDecision/d0a7108b-7f2f-484a-bcb0-de339238199d/subagents/agent-a3341da520d4c5530.jsonl`) : la phrase de G de N1.1 fausse sous le quorum ; mineurs : « autant de voix pour que si » ambigu, le test de « 100 votants » qui ne pouvait pas échouer, la répétition qui avait lu W sur la chaîne. Tout repris par le lot T3b (`e7ab82f`). - Deuxième relecture, **`e7ab82f` : à reprendre** (sous-agent neuf, sans le contexte de l'intégrateur, lancé à 18 h 56, inscrit à 19 h 16 ; transcript `~/.claude/projects/-home-yvv-Documents-PROD-DEV-libreDecision/d0a7108b-7f2f-484a-bcb0-de339238199d/subagents/agent-a92ddff6f85c88f90.jsonl`) : « quand le groupe vote comme d'habitude » se lit comme la médiane réelle, alors que le moteur cale G sur la participation habituelle bornée (W 7 224, médiane 40, cran 2 : 28 « pour » sur 40, pas 27) ; la grille des tests sautait ces cas. Repris par le lot T3c (lancé à 19 h 18, fusionné à 19 h 57 : `de1b7eb`), avec la liste fermée des phrases demandée par orch (`t3c-liste-fermee.md`). - **Relecture de `de1b7eb` : en cours** (sous-agent neuf, sans le contexte de l'intégrateur, lancé le 03/11 à 20 h 05, sur la liste fermée ; consigne `m8/relis-m8c.md` du scratchpad de l'intégrateur). 4. `git diff 6f6197c de1b7eb -- docker/ .woodpecker/ .env data/ crates/ld-server/migrations/ web/ crates/ld-engine/` → vide (vu par l'intégrateur le 03/11 à 20 h 04). 5. Boucle verte sur `de1b7eb`, le 03/11 de 19 h 57 à 20 h 03 (journal `m8/loop-c.log`), du premier coup : fmt, clippy `-D warnings`, 316 tests Rust, svelte-check 0 / 0 (648 fichiers), 78 vitest, build, e2e 42 / 42 (19 h 59 à 20 h 03). Image de production : en cours. 6. Sur sonic, aucun témoin `/opt/libredecision-app/deploying`. ## Commande exacte ```sh cd /home/yvv/Documents/PROD/DEV/libreDecision git push prod de1b7eb5d7e982aee7c70a41c9f5799fb171493e:main ``` ## Vérifications après - [ ] Santé vue de l'extérieur → `"build":"de1b7eb5"`. - [ ] Journaux : quatre « seed amendment applied » (`2026-11-03-f1-2-chiffres`, `-n1-1-chiffres` × essai, Monnaie libre), « publication suspended … waiting=12 », aucune ligne ERROR ni WARN. - [ ] Redémarrage à froid : aucun amendement rejoué. - [ ] Sur une copie fraîche : F1.2 et N1.1 en révision 5, F1.1 en révision 3, dans les deux groupes ; le reste identique à la ligne près à la copie d'avant (comptes de `counts.sh`) ; `integrity_check` ok. - [ ] Le dépôt des textes reste à `9e0f45a`. ## Retour - **Le code** : `docker tag libredecision-app:previous libredecision-app:latest`, puis `cd /opt/libredecision-app && docker compose up -d --force-recreate`. `previous` sera `6f6197c`, qui attend aussi le premier texte pour publier : pas de coupure de la publication à faire. `6f6197c` sert les nouveaux textes tels quels (ce sont des données). - **Les textes** : pas de retour automatique ; l'ancien texte reste dans l'historique de chaque proposition, un nouvel amendement gardé pourrait le remettre.