Files
decision/actes/2026-11-03-m8-chiffres-dates.md
T

230 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Acte — Mise en ligne M8 (aucun chiffre daté dans les textes votés, lots T3 et T3b)
Classe : déploie
Projet : libreDecision Date : 2026-11-03
**État : PRÉPARÉ, non figé** (en attente de la relecture indépendante de `e7ab82f`) — sur `e7ab82f`
(`e7ab82f48f41f52b3f31e322553f7cf18bc21601`) ; 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é
Quatre phrases, avant / après (le français fait foi), et un exemple retiré. Toutes dans les textes votés
de départ, dans les deux groupes ; F1.1 n'est pas touché.
1. **N1.1, la phrase du quorum** (premier paragraphe) :
- 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, les votants qui manquent comptent comme
« non », et il faut autant de « pour » que si le quorum avait voté. »
2. **N1.1, 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, quand le
groupe vote comme d'habitude, puis quand tout le monde vote, et ce qui est à ce cran au départ. »
3. **N1.1, la phrase de G** (dernier paragraphe) :
- 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, soit exactement celle du cran
quand le groupe vote comme d'habitude : `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. »
4. **F1.2, « 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 » quand il vote comme d'habitude. Tout nouvel
article commence à ce cran. »
5. **N1.1, l'exemple retiré** (le paragraphe qui suivait la phrase de G ; 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. »
**Pourquoi.**
- L'exemple (5) : 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.
- La phrase du 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,
le moteur demande exactement le seuil du quorum. « autant de « pour » » plutôt que « autant de voix pour »,
qui se lisait d'abord « pour que ».
- Les phrases 2, 3 et 4 disaient la part du cran « comme d'habitude » sans condition. C'est faux quand la
participation habituelle reste sous le quorum : le groupe est alors jugé sur le quorum. Exemple : une
toile de 3 000 membres dont la participation habituelle est de 40 votants (dans les bornes : 1 % de
3 000, c'est 30), au cran 3, quorum 50 : la courbe donne 75 % à 40 votants, mais la part exigée se calcule
sur 50 (74,2 %), et il faut 38 « pour » de ces 40 votants, soit 95 %, pas 75 %. Cela arrive dès que la
toile passe sous 5 000 membres avec une participation habituelle sous 50, ou quand l'auteur d'un article
fixe un quorum au-dessus de la participation habituelle. Les phrases 2 et 4 ont été trouvées par le lot
T3 ; la phrase 3 par la relecture indépendante de T3 (« 2ce2028 : à reprendre »), reprise par le lot T3b.
Accord d'orch sur les trois (03/11, à 17 h 46, puis en réponse à mon message de 18 h 13).
Les preuves, phrase par phrase, et les textes entiers en fr, en, es :
`docs/chantiers/acte-certification/textes-quorum-seed.md`, section « Lot T3 » (avec « Après la relecture
de 2ce2028 »).
## Intention
Mettre en ligne les lots T3 et T3b. 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.
**en et es** (fidèles au français) :
- 1 : « Each level also has its quorum: below the quorum, the voters who are missing count as votes against,
and it takes as many votes in favour as if the quorum had voted. » ; « Cada nivel tiene además su quórum:
por debajo del quórum, los votantes que faltan cuentan como «no», y hacen falta tantos votos a favor como
si hubiera votado el quórum. »
- 2 : « the share asked beyond the quorum, when the group votes as usual » ; « la proporción exigida más allá
del quórum, cuando el grupo vota como de costumbre ».
- 3 : « **G** is computed so that the share asked, beyond the quorum, is exactly that of the level when the
group votes as usual: `G = …`, where s is that share of the level (60, 67, 75, 83 or 90%) and p̃ the usual
turnout divided by W. » ; « **G** se calcula para que la proporción exigida, más allá del quórum, sea
exactamente la del nivel cuando el grupo vota como de costumbre: `G = …`, donde s es esa proporción del
nivel (60, 67, 75, 83 o 90 %) y p̃ la participación habitual dividida por W. »
- 4 : « and, beyond the quorum, the group asks for 75% of votes in favour when it votes as usual » ; « y, más
allá del quórum, el grupo pide un 75 % de votos a favor cuando vota como de costumbre ».
**Les preuves** (tests de `crates/ld-server/tests/seed_quorum_texts.rs`) :
- aucun chiffre daté : `every_number_of_the_quorum_texts_is_the_engine_s` n'admet que des paramètres (vu
rouge sur les textes de T2) ; « 100 votants » y est dit pour ce qu'il est, deux fois le quorum de
référence, et `the_reference_turnout_is_a_parameter_the_bounds_bring_back` montre que les bornes le
ramènent hors de 200 à 10 000 membres ;
- 1 : `under_the_quorum_it_takes_as_many_for_as_if_the_quorum_had_voted`, plus de 500 000 cas (W de 100 à
10 000 000, chaque quorum de la borne basse à W, les cinq crans, quatre participations, le groupe d'essai) ;
- 2 et 4 : `the_share_of_a_level_as_usual_is_asked_beyond_the_quorum` ;
- 3 : `g_gives_the_share_of_the_level_beyond_the_quorum_when_the_group_votes_as_usual` (même grille ; G tel
qu'écrit égale celui du moteur ; s au-delà du quorum, plus bas en dessous ; le cas 3 000 / 40 en dur) ;
- F1.1 laissé : `b_to_the_power_w_never_counts_in_the_web_of_trust` (« B^W ne compte pas », de 100 à
10 000 000 membres).
## Ce qui part
Version `e7ab82f` (lots T3 et T3b), 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 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 `ddce5aa5…`, N1.1 `7f62fd42…` ; 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 18 h 54 min 44 à 18 h 55 min 28, réseau coupé** (`unshare -rn`, boucle locale seule :
`m8/repetition-isolee.sh`), avec le serveur de `e7ab82f` (binaire de la boucle, construit à 18 h 54, copié en
`m8/ld-server-e7ab82f`), sur une copie (18 h 47 min 52) 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-m8b.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
`e7ab82f`, 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 »).
Une première répétition, sur `2ce2028` (lot T3 seul), le 03/11 à 17 h 54, avait donné les mêmes comptes ; le
réseau n'y était pas coupé (W relu sur `rpc.duniter.org`, `settings.wot_size` 5 709 → 5 711), ce que la
relecture a relevé. Ses copies sont retirées (18 h 47).
## 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 <db>` (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 `e7ab82f`, 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`).
- **Relecture de `e7ab82f` : en cours** (sous-agent neuf, sans le contexte de l'intégrateur, lancé le
03/11 à 18 h 56).
4. `git diff 6f6197c e7ab82f -- docker/ .woodpecker/ .env data/ crates/ld-server/migrations/ web/ crates/ld-engine/`
→ vide (vu par l'intégrateur le 03/11 à 18 h 48).
5. Boucle verte sur `e7ab82f`, le 03/11 de 18 h 47 à 18 h 54 (journal `m8/loop-b.log`), du premier coup :
fmt, clippy `-D warnings`, 314 tests Rust, svelte-check 0 / 0 (648 fichiers), 78 vitest, build, e2e
42 / 42 (18 h 50 à 18 h 54). 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 e7ab82f48f41f52b3f31e322553f7cf18bc21601:main
```
## Vérifications après
- [ ] Santé vue de l'extérieur → `"build":"e7ab82f4"`.
- [ ] 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.