Files
decision/docs/adr/0013-quorum.md
T

142 lines
8.8 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.
# 0013 — Le quorum : les votants qui manquent comptent comme « non »
> Remplace, dans [0002](0002-vote-permanent.md) et [0007](0007-inertie-cinq-crans.md), le
> plancher C de voix pour placé devant la formule. Décisions d'Yvv du 2026-11-02 et du
> 2026-11-03. La migration est la `0011` : la `0010` reste au lot V.
**Contexte.** Depuis le 2026-10-21, `R = C + B^W + (M + (1 − M)(1 − (T/W)^G)) · max(0, T − C)` :
C voix pour d'abord (50 dans Monnaie libre, 1 dans le groupe d'essai), puis la part de l'inertie
sur les votes au-delà. Yvv, 2026-11-02 : « C suit le cran, mais c'est une proposition par
défaut, variable modifiable par l'auteur initial du texte » ; « ce n'est pas un nombre de vote
pour a priori, c'est plutôt un quorum, à partir de ce nombre, alors il faut la bonne proportion
attendue par l'indice. Si c'est 60 % et c = 10, alors il faut 6 voix pour et ça passe. » Au
formulaire : « La courbe d'aujourd'hui, après le quorum » ; les quorums par défaut
« 12 · 12 · 50 · 50 · 50 », le groupe d'essai à 1 partout ; « L'auteur, avant le 1er vote ».
Le 2026-11-03, à « Sous le quorum, les votants qui manquent comptent-ils comme des « non » ? » :
« Ils comptent comme non ».
## Décision
**La formule, jugée sur un quorum Q** (`crates/ld-engine/src/threshold.rs`) :
```
T' = max(T, Q)
R = B^W + (M + (1 − M)·(1 − (T'/W)^G)) · T'
```
Une version passe si au moins une voix est exprimée et si « pour » ≥ ⌈R⌉. Sous le quorum, les
votants qui manquent comptent comme « non » : la part de l'inertie est demandée à Q votants.
La règle tient dans **une seule fonction nommée**, `threshold::judged_voters`, qui porte la
phrase d'Yvv. M, G et les cinq crans ne changent pas (ADR 0007) : la courbe est celle
d'aujourd'hui, après le quorum. L'exemple d'Yvv (60 %, Q = 10) donne 6 « pour » ; 6 « pour »
contre 5 « contre » ne passent pas, 7 contre 4 passent.
**Monotone.** Un « pour » de plus ne nuit jamais, un « contre » de plus n'aide jamais : à
« pour » fixé, un « contre » de plus laisse T' à Q ou l'augmente, et ratio(T')·T' ne décroît pas
avec T' (sa dérivée reste entre 0,06 et 1 pour les cinq crans, p̃ dans ses bornes). Les tests
le vérifient sur une grille (`an_against_never_helps`, l'équivalence de `passes` avec
`yes_needed` et `no_needed`).
**Ce que l'écran peut dire** (`Evaluation`) : `quorum` ; `yesNeeded`, le total de « pour » qui
passe avec les « contre » d'aujourd'hui ; `noNeeded`, le total de « contre » qui tient les
« pour » d'aujourd'hui en échec (0 : le quorum les tient déjà) ; `missing = yesNeeded − pour` ;
`wellRated`, la part de l'inertie tenue sur les T votants venus, le quorum mis de côté
(l'aperçu « si les bien cotées passent »).
**Un quorum par cran**, le défaut d'un article à ce cran (`documents.quorums`) : Monnaie libre
**12 · 12 · 50 · 50 · 50**, le groupe d'essai **1 partout**. Une proposition d'inertie se juge
sur le quorum de son article (elle hérite de son cran, ADR 0007) ; un module, sur celui de son
cran.
**Le quorum d'un article** (`units.quorum`, NULL : celui du cran) est fixé par l'auteur de sa
première version — pour un texte du seed, sans auteur, par un administrateur —, et seulement
**avant le premier vote** : `trustin_access::sets_quorum`, la route `PUT /units/{id}/quorum`
(`{ "quorum": n | null }`, en-tête CSRF), dans `crates/ld-server/src/quorum.rs`. Bornes : de 2
à W (une voix seule ne fait jamais passer un texte), de 1 à W dans le groupe d'essai
(`ld_engine::inertia::quorum_bounds`, `trustin_access::TEST_GROUP`). Chaque changement est
consigné (`quorum_changes` : qui, de quoi, à quoi, quand). Refus : 403 à qui n'est pas
l'auteur, 400 `quorum` hors des bornes, 409 `voted` dès qu'un vote existe.
**« Un vote existe »** : une seule fonction, `quorum::voted_units` (et `quorum::a_vote_exists`
pour une unité), que le lot V étendra là et nulle part ailleurs. Sur l'une des versions de
l'article (textes, retrait, changement d'inertie ; toute révision) : un vote du serveur
(`votes`) ; une ligne de bulletin de la chaîne en attente ou confirmé (un bulletin refusé ou
expiré n'est pas un vote) ; une adoption (une version entrée en vigueur par le vote en garde la
trace, même ses votes retirés). **Limite connue** : un vote du serveur retiré avant toute
adoption ne laisse pas de ligne (`votes` ne garde que le dernier choix) ; après lui, l'auteur
peut de nouveau fixer le quorum.
**La participation de référence** reste p0 = 2Q₀/W, Q₀ le quorum de référence du document
(`documents.vote_floor` : 50 dans Monnaie libre, 1 dans le groupe d'essai), **jamais le quorum
d'un article** : un auteur qui baisserait le sien déplacerait l'échelle de tout le groupe.
## Une base existante
Un document seedé n'est jamais réinstancié. Tant que `documents.quorums` est NULL, chaque cran
lit `vote_floor` (le C d'avant : 50 et 1). L'**amendement de quorums**
`2026-11-03-quorums-par-cran` (`crates/ld-server/src/quorum_amend.rs`) décide une fois par
document, seulement si le seed d'aujourd'hui donne ces quorums à l'instance : NULL → écrit
(`applied`) ; les mêmes → `present` ; d'autres → refusé (`quorums_set`), gardés tels quels.
Chaque décision est consignée (`quorum_amendments` : ce qui était là, ce que dit le seed,
l'issue, la raison) et dans les journaux ; là où le document publie (Monnaie libre), une ligne
s'ajoute à la file (« quorums par cran : 12 · 12 · 50 · 50 · 50 (ADR 0013) »), qui attend le
premier texte (ADR 0011). Rien d'autre n'est touché : ni le quorum propre d'un article, ni un
vote, ni un texte.
## Les nombres
Monnaie libre, W = 5 745 (repli des tests), participation de référence (100 votants) :
| | cran 1 | cran 2 | cran 3 | cran 4 | cran 5 |
|---|---|---|---|---|---|
| quorum | 12 | 12 | 50 | 50 | 50 |
| « pour » à 0 vote (C d'avant : 50) | 8 | 9 | 39 | 43 | 46 |
| « pour » à 100 votants (C d'avant : 80 · 84 · 88 · 92 · 95) | 60 | 67 | 75 | 83 | 90 |
Au cran 2, quorum 12 : 9 « pour » passent avec 3 « contre » au plus ; 9 contre 4 demandent 11
(`yesNeeded`), il en manque 2 ; 8 « pour » ne passent pas même sans « contre » (`noNeeded` 0).
W = 7 224 (tests `ld-engine/src/inertia.rs`), « pour » exigés :
| Médiane | T | cran 1 | cran 2 | cran 3 | cran 4 | cran 5 |
|---|---|---|---|---|---|---|
| 120 votants | 120 | 72 | 81 | 90 | 100 | 108 |
| 120 votants | 500 | 284 | 310 | 347 | 386 | 424 |
| 120 votants | 2 000 | 1 068 | 1 123 | 1 252 | 1 389 | 1 537 |
| 360 votants | 120 | 76 | 86 | 96 | 106 | 113 |
| 360 votants | 360 | 216 | 242 | 270 | 299 | 324 |
| 360 votants | 500 | 296 | 328 | 367 | 407 | 443 |
| 360 votants | 2 000 | 1 092 | 1 164 | 1 301 | 1 446 | 1 598 |
Le cas de référence de la formule (vote forgeron v2.0.0 : W 7 224, 120 votants, M 50 %, G 0,2,
Q 0 → 94 voix) reste le test de la formule elle-même.
## Les données
Migration `0011` (additive) : `documents.quorums` (JSON des cinq quorums), `units.quorum`, les
tables `quorum_changes` et `quorum_amendments`. Le seed : `"quorums"` sur chaque instance.
`vote_floor` reste, lu pour p0. Les adoptions nouvelles gardent `quorum` dans leurs `params`
(celles d'avant gardent `constant`, lu tel quel). L'API : `doc.quorums`, `levels[].quorum`,
l'unité `quorum` (le sien ou `null`), `quorumDefault`, `canSetQuorum` ; le `document.json`
publié : `quorums`.
## Coût
- Les seuils de Monnaie libre baissent à faible participation : 9 « pour » au lieu de 50 pour
I1, E1 et E2 au cran 2 ; 39 au lieu de 50 au cran 3. À la participation habituelle, la part
s_k s'applique à tous les votants, plus seulement au-delà de C.
- **Dans le groupe d'essai, une voix seule passe**, à tout cran et quel que soit le nombre de
membres (avant : deux voix sous 16 membres). Les tests qui demandent deux voix y posent le
quorum 2 de l'article, comme son auteur le ferait.
- En production, si les propositions d'inertie I1 → 5 et E1 → 5 restent ouvertes (ADR 0011),
I1 et E1 restent aux crans 3 et 4 : leur quorum est 50, pas 12. *(Yvv les a retirées le
03/11 avant M6 : I1 et E1 sont au cran 2, quorum 12.)*
- Le texte F1.1 du seed (« Seuil = C + B^W + … ») et N1.1 (« le groupe demande d'abord C voix
pour ») décrivent encore C : orch les réécrira au prochain tour de textes, avec la relecture
d'Yvv (ce lot ne touche pas aux textes du seed). *(Fait par le lot T : F1.1, F1.2 et N1.1 disent
le quorum par cran, en ligne depuis M6b, le 03/11, `bb4bdf5` ; relecture d'Yvv :
`docs/chantiers/acte-certification/textes-quorum-seed.md`. Trois de leurs phrases reprises par
le lot T2, amendement `2026-11-03-…-phrases` qui suit celui de M6b : la part du cran, la plus
haute au quorum, baisse quand la participation monte ; le quorum se fixe tant que l'article ne
garde la trace d'aucun vote ; il n'est pas un nombre minimal de votants.)*