Files
decision/actes/2026-11-03-m6-propositions-seed-quorum-tampon.md
T

250 lines
17 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 M6 (Propositions seed, quorum par cran, tampon des votes et vote simulé, accueil sous la voûte)
Classe : déploie
Projet : libreDecision Date : 2026-11-03
**État : EXÉCUTÉ (03/11, 06h45-07h04, par orch dev-63 sous mandat ; pipeline 37)** — figé le 03/11/2026 à 06 h 22 sur `94ddb17` (`94ddb175643c8d523a083bbfee3882f22b82f628`) — 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). Relecture indépendante : « 94ddb17 : ok », inscrite le 03/11 à 06 h 42 (prémisse 4).
## Intention
Mettre en ligne la revue d'Yvv du 02/11 et ses décisions du 02/11 et du 03/11 (registre) :
- **H** : l'accueil sous la voûte, les trois points sous l'arche, le titre centré en deux lignes
(`a3c0a76`) ;
- **S** : les Propositions seed (I1, E1, E2 ouvertes, au cran 2, ADR 0011), la publication suspendue sans
texte en vigueur, le quorum par cran (ADR 0013, `PUT /units/{id}/quorum`), la licence
`AGPL-3.0-or-later` (`349c8ed`) ;
- **V** : le tampon des votes (ADR 0012), le vote simulé partout tant que la chaîne est fermée, marqué
« simulé », qui compte puis s'efface par l'acte « supprime » ; la publication « pas avant des votes
prouvés » (`94ddb17`).
Hors de M6 : T (les articles du seed qui décrivent encore l'ancien plancher C : F1.1, F1.2, N1.1), puis U
(le lecteur) en M7. Yvv, à 06 h 07 : « J'ai retiré les propositions. tu peux livrer Decision. »
## Décisions d'Yvv que l'acte applique
- Propositions seed au cran 2 ; aucun article en vigueur au départ (02/11).
- Quorum par cran 12 · 12 · 50 · 50 · 50 dans Monnaie libre, 1 à l'essai ; l'auteur le change avant le
premier vote (02/11) ; sous le quorum, les votants manquants comptent comme « non » (03/11).
- Un vote simulé compte, puis s'efface à l'ouverture de la chaîne par un acte « supprime » (02/11).
- Q11 (03/11, « Pas avant des votes prouvés ») : un texte entré en vigueur par des votes simulés est en
vigueur sur le site, mais ne se publie pas. Règle stricte, confirmée par orch le 03/11 à 06 h 11 : rien
ne part tant qu'une entrée simulée ne tient pas sur les seuls votes prouvés.
- Q12 (03/11, « Oui, retire-les ») : les propositions d'inertie I1 → 5 et E1 → 5 retirées avant le
démarrage du nouveau serveur. **Fait par Yvv à l'écran, annoncé à 06 h 07** ; vu sur la copie de
06 h 11 (prémisse 2).
## Ce qui part
Version `94ddb17`, qui contient la version en ligne `3f10a0e` : 51 commits, 84 fichiers. Hors du code
(vérifié le 03/11 à 06 h 22) : rien dans `docker/`, `.woodpecker/`, `.env` ou `data/`, aucun fichier
sensible. Le seed JSON change (bases neuves seulement : un document seedé n'est jamais réinstancié).
## Ce que l'acte écrit dans la base de production (donnée runtime)
- **Migrations additives** `0009` (Propositions seed : `proposals.seed_featured`, la table
`seed_proposal_amendments`), `0010` (tampon : `ballots.mode` défaut `'chain'`, `ballot_lines.outcome`,
l'index `ballots_doc` ; aucune ligne réécrite), `0011` (quorums : `documents.quorums`, `units.quorum`,
la table `quorum_amendments`).
- **Amendement Propositions seed** (`2026-11-02-i1/e1/e2-proposition-seed`), par document et par article,
seulement si personne n'y a touché : la version passe d'en vigueur à ouverte et marquée ;
`units.in_force_id` à NULL ; une ligne `revisions` de type `seed_proposal` ; le cran à 2 avec une ligne
`inertia_changes`, si personne n'a touché au cran ; une ligne `seed_proposal_amendments` ; dans Monnaie
libre, une ligne `outbox`, qui attend.
- **Amendement quorums** (`2026-11-03-quorums-par-cran`), une fois par document : `documents.quorums`
là où il est NULL ; une ligne `quorum_amendments` ; une ligne `outbox` dans Monnaie libre.
- **Le tampon** : la première mise en route n'en écrit rien.
- **La publication** : suspendue (aucun article en vigueur, puis « pas avant des votes prouvés »). Le
dépôt des textes garde son dernier état.
- **Aucun vote, aucune identité, aucune autre proposition n'est touché.**
**Répétition faite le 03/11 de 06 h 21 à 06 h 22**, avec le serveur de `94ddb17` (binaire de la boucle),
sur une copie de la copie de production de 06 h 11 min 12 (santé `3f10a0e8`), publication vers un dépôt nu
local (`m6/repetition.sh`, scratchpad de l'intégrateur ; journal `m6/repetition.log`).
| | Avant | Après |
|---|---|---|
| Migrations | 1–8 | 1–11 |
| Propositions | inertie retirées 3 · ordres en vigueur 16 · textes en vigueur 6 · textes ouverts 64 · titres en vigueur 2 | inertie retirées 3 · ordres en vigueur 16 · textes ouverts 70 · titres en vigueur 2 |
| Unités en vigueur | essai 12 · Monnaie libre 12 | essai 9 · Monnaie libre 9 |
| I1, E1, E2 (deux groupes) | en vigueur, crans 3, 4, 4 | ouvertes, Propositions seed, cran 2, 2, 2 |
| Révisions | 101 | 107 |
| Traductions | 144 | 144 |
| `inertia_changes` | 4 | 10 |
| `seed_proposal_amendments` | absente | 6 lignes, statut et cran « applied » |
| `quorum_amendments` / `documents.quorums` | absentes | 2 lignes « applied » ; Monnaie libre `[12,12,50,50,50]`, essai `[1,1,1,1,1]` |
| File de publication (Monnaie libre) | 0 en attente, 13 faites | 4 en attente, 13 faites |
| Commits poussés vers le dépôt des textes (local) | — | 0 (« publication suspended … waiting=4 ») |
| Votes, bulletins, signalements, identités | 0, 0, 0, 1 | 0, 0, 0, 1 |
`integrity_check` ok, `foreign_key_check` vide, avant et après. Journal : six « seed proposal amendment …
status=applied level=applied to_level=2 », deux « quorums written », « publication suspended », aucune
ligne ERROR ni WARN. **Un second démarrage ne rejoue rien** (mêmes comptes, la file reste à 4, 0 commit).
## Effet attendu
- Les deux groupes : I1, E1 et E2 sont des « Propositions seed », ouvertes, au cran 2 ; aucun article n'est
en vigueur ; les modules (titre du document au cran 4, ordre de chaque section au cran 2) restent en
vigueur.
- Le seuil se lit en quorum : au cran 2, 9 « pour » passent avec 3 « contre » au plus.
- **Le vote simulé s'ouvre dans Monnaie libre dès la mise en ligne** (pas de `LD_VOTE_ACCOUNT`) : toute
personne qui ouvre le groupe y vote, une personne invitée comprise ; le vote compte aussitôt, marqué
« simulé » sous l'article ; 9 « pour » simulés font entrer I1, E1 ou E2 **sur le site**, sans
publication. Effet de « simule le vote à tout endroit » et « il compte, puis s'efface » ; orch le porte à
son rapport (03/11, 06 h 11). À l'ouverture de la chaîne, l'acte « supprime » (`ld-server
discard-simulation`, à blanc, puis `--apply`) écartera ces votes et réexaminera ce qu'ils ont fait entrer.
**Cet acte se jouera serveur arrêté** (relecture : `give_back` écrit sans garde, à côté du serveur).
- **Un lien d'équipe multiplie les voix simulées** (relecture, vu : un lien vers Monnaie libre ouvert
9 fois sous 9 noms donne 9 « pour », et I1 entre sur le site). En production le 03/11 à 06 h 11 :
aucun lien d'équipe ; 2 invitations vers Monnaie libre, dont 1 pas encore ouverte (expire le 05/11).
**À dire à Yvv** : ne pas créer de lien d'équipe vers Monnaie libre pendant la simulation, ou le
borner à quelques ouvertures.
- Après un vote simulé, le message bref dit encore « Vote enregistré. » et le panier « N votes
enregistrés. » ; sous l'article, c'est bien « simulé ». Repris par U (M7).
- L'accueil sous la voûte.
Irréversibilité : **partielle**. Le code se remet en arrière ; les données changées restent.
## Avant — prémisses vivantes
1. La production sert `3f10a0e` : `curl -s https://decision.librodrome.org/api/health` →
`"build":"3f10a0e8"` ; `git fetch prod && git rev-parse --short prod/main` → `3f10a0e`.
2. Sur une copie fraîche de la base (commande ci-dessous) : aucune proposition d'inertie `open` ; 0 vote,
0 bulletin ; I1, E1, E2 en vigueur, aux crans 3, 4, 4, dans les deux groupes. **Lu sur la copie de
06 h 11 min 12** : 3 propositions d'inertie, toutes `withdrawn` (I1 → 5, E1 → 5, et une ancienne sur
l'ordre de l'introduction) ; 0 vote, 0 bulletin, 0 signalement, 1 identité ; I1, E1, E2 en vigueur,
crans 3, 4, 4, dans les deux groupes. À relire sur la seconde copie, juste avant la poussée. Si un de
ces articles a bougé, l'amendement le refuse avec sa raison au journal, et l'acte reste valable.
3. Sur la même copie : 0 vote, donc aucune proposition n'entre au premier balayage.
4. La relecture indépendante de `94ddb17`, inscrite « ok » dans `~/harness/etat/relectures.json` ; aucune
autre relecture de ce code en cours. **Faite** : « 94ddb17 : ok », sous-agent neuf, rendue et inscrite le
03/11 à 06 h 42 (transcript `~/.claude/projects/-home-yvv-Documents-PROD-DEV-libreDecision/d0a7108b-7f2f-484a-bcb0-de339238199d/subagents/agent-ab9f269c254b56f31.jsonl`).
Aucun bloquant. Elle a rejoué la mise en route sur une base faite par `3f10a0e` (écritures exactement
celles annoncées, second démarrage sans rejeu, publication suspendue), sondé la formule sur 25 millions
de cas (une voix seule ne passe jamais, un « contre » n'aide jamais, `yesNeeded` / `noNeeded` exacts),
la route du quorum (bornes, CSRF, auteur, 409 après un vote), les routes de développement (404 sans
`LD_DEV_LOGIN`), la simulation et l'acte « supprime » (à blanc : la base inchangée). Ses constats « à
reprendre » sont traités dans ce dossier (le retour, le lien d'équipe, l'acte « supprime ») ou
renvoyés à U (« Vote enregistré. »).
5. `git diff 3f10a0e 94ddb17 -- docker/ .woodpecker/ .env data/` → vide (vérifié à 06 h 22).
6. Boucle verte sur `94ddb17` le 03/11 de 06 h 16 à 06 h 21 : fmt, clippy `-D warnings`, 286 tests Rust,
svelte-check 0 erreur 0 avertissement, 56 vitest, build, e2e 36 / 36. Image de production construite
le 03/11 à 06 h 25 (`docker build -f docker/app.Dockerfile --target production`, sortie 0, les tests
rejoués dedans : 56 vitest, tests Rust tous « ok ») ; image de contrôle retirée à 06 h 26.
## Copie de la base (prise par orch, lecture seule, aucune écriture côté production)
```sh
set -euo pipefail
d=/tmp/ld-m6-copie; mkdir -m 700 -p "$d"
for f in libredecision.db libredecision.db-wal libredecision.db-shm; do
ssh sonic "docker exec lpk-libredecision-app sh -c 'test -f /data/$f && cat /data/$f'" > "$d/$f" </dev/null || rm -f "$d/$f"
done
chmod 600 "$d"/*
date '+%H:%M:%S'; curl -s https://decision.librodrome.org/api/health; echo
sqlite3 -readonly "$d/libredecision.db" 'PRAGMA integrity_check; PRAGMA foreign_key_check;'
```
Pas un instantané atomique (la base, puis son journal WAL) : `integrity_check` le dirait, et l'on reprend
la copie. Lecture : `m6/counts.sh <db>` (scratchpad de l'intégrateur), en `sqlite3 -readonly`.
## Commande exacte
Selon la règle du canon du 02/11, un dossier « déploie » ne liste que la poussée qui met en ligne :
```sh
cd /home/yvv/Documents/PROD/DEV/libreDecision
git push prod 94ddb175643c8d523a083bbfee3882f22b82f628:main
```
(remote `prod` = `gitea@git.open.us.org:EHV/decision.git` ; Woodpecker `.woodpecker/app.yml`, puis
`maquette.yml`.)
## Vérifications après
- [x] Santé vue de l'extérieur → `"build":"94ddb175"`.
- [x] Journaux : `ssh sonic 'docker logs lpk-libredecision-app 2>&1 | grep -E "amendment|quorums written|publication|ERROR|WARN"'`
→ six « seed proposal amendment … status=applied level=applied », deux « quorums written »,
« publication suspended », aucune erreur.
- [x] Redémarrage à froid (`docker compose restart` dans `/opt/libredecision-app`), santé vue de
l'extérieur, journaux : aucun amendement rejoué.
- [x] Sur une copie fraîche : les comptes « Après » de la répétition, à la ligne près ; `integrity_check`
ok, `foreign_key_check` vide ; copie retirée ensuite.
- [x] Le dépôt des textes n'a reçu aucun commit : `git ls-remote gitea@git.open.us.org:yvv/decision-depot-textes-reference.git main`
→ le même sha qu'avant la poussée (le relever avant).
- [ ] À l'écran (Yvv, à son retour) : l'accueil sous la voûte ; l'Acte d'engagement : les Propositions
seed, aucun article en vigueur ; voter dans Monnaie libre affiche « simulé ».
## Retour
**Avant tout retour vers `3f10a0e`, couper la publication.** `94ddb17` met 4 lignes en file au premier
démarrage (`seed_proposal_amend.rs:419`, `quorum_amend.rs:140`) ; `3f10a0e` ne connaît pas l'attente du
premier texte et publierait aussitôt un document **sans aucun article** (vu par la relecture : commit de
`fr.md`, `en.md`, `es.md` et `document.json` vides, 118 lignes retirées). Le compose prend
`${LD_PUBLISH_REMOTE:-…}` : une valeur vide reprend le défaut, il faut donc retirer la ligne.
```sh
ssh sonic
cd /opt/libredecision-app
cp docker-compose.yml docker-compose.yml.m6-avant-retour
sed -i '/LD_PUBLISH_REMOTE/d' docker-compose.yml
docker tag libredecision-app:previous libredecision-app:latest
docker compose up -d --force-recreate
```
- **Répété le 03/11 à 06 h 45** : le serveur de `3f10a0e`, sans `LD_PUBLISH_REMOTE`, sur la base issue de
la répétition M6 : démarrage sans erreur, aucune publication (dépôt nu local : 0 commit), la file reste
à 4 en attente. Le serveur tolère les migrations qu'il ne connaît pas (`set_ignore_missing(true)`,
`lib.rs:100`). La prochaine mise en ligne réécrit `docker-compose.yml` depuis le dépôt (`app.yml`).
- **Les données** : pas de retour automatique. `3f10a0e` montrerait I1, E1, E2 comme propositions
ouvertes sans la marque, et aucun article en vigueur ; les votes simulés éventuels y compteraient comme
des votes du serveur. Un retour du code au-delà de quelques minutes demande un acte de données à part.
- **Risque connu, le retour automatique du pipeline** : si le nouveau conteneur échoue après avoir
démarré, `.woodpecker/app.yml` relance `previous` (`3f10a0e`) **avec** la publication, qui partirait
vide. La répétition et l'image ne montrent aucun échec de démarrage ; si le pipeline échoue quand même,
regarder aussitôt le dépôt des textes (`git ls-remote … main`) et, s'il a reçu le document vide, couper
la publication comme ci-dessus, puis republier le dernier état par-dessus (acte à part).
- **La publication** : en marche avant, rien ne part (suspendue).
## Exécution
Acte exécuté le 03/11/2026, 06h45-07h04, par orch (session dev-63, e66db8ca), sous mandat
« déploie » (inscrit du 03/11 au 08/11) ; consignes d'Yvv du 03/11 à 06h00 (« livre et déploie tout
ce que tu peux ») et à 06h07 (« tu peux livrer Decision »).
- Dossier relu en entier à 06h45 ; relecture « 94ddb17 : ok » vue inscrite ; aucune autre relecture
de ce code en cours (libredecision-d4, PRÊT M6).
- Prémisse 1, 06h45:51 : santé `{"build":"3f10a0e8","ok":true}`, `prod/main` = `3f10a0e`.
- Seconde copie, 06h46:32 (`/tmp/ld-m6-copie2`, 700/600), santé `3f10a0e8` : `integrity_check` ok,
`foreign_key_check` vide. Prémisses 2 et 3 : la colonne « Avant » à la ligne près ; 3 propositions
d'inertie, toutes `withdrawn` ; 0 vote, 0 bulletin, 0 signalement, 1 identité ; I1, E1, E2 en vigueur,
crans 3, 4, 4, dans les deux groupes ; file 0 en attente, 13 faites.
- Dépôt des textes avant : `main` = `9e0f45a9e8d4af356a0c42daa5f4fb9eb9e6dfb3`. Pipelines : 36
`success` en tête, rien en cours.
- Poussée `git push prod 94ddb175643c8d523a083bbfee3882f22b82f628:main` à 06h46:5x, passée du premier
coup (`3f10a0e..94ddb17`).
- Pipeline n° 37 : `running` à 06h47:06 ; `app` vert (healthcheck `success`, `retablir` sauté) ;
`maquette` verte ; `success` à 07h02:59. L'étape `sbom-publish` échoue dans les deux workflows, comme
au pipeline 36 : écart ancien, sans effet sur le déploiement.
- Après :
- santé `{"build":"94ddb175","ok":true}` ;
- journaux : six « seed proposal amendment … status="applied" level="applied" to_level=2 », deux
« quorums written » (essai `[1, 1, 1, 1, 1]`, Monnaie libre `[12, 12, 50, 50, 50]`),
« publication suspended … waiting=4 », aucune ligne ERROR ni WARN ;
- redémarrage à froid (`docker compose restart` dans `/opt/libredecision-app`) à 07h03:07 :
« listening … build=94ddb175 », « publication suspended … waiting=4 », aucun amendement rejoué ;
santé `94ddb175` ;
- copie fraîche, 07h03:31 (`/tmp/ld-m6-apres`) : la colonne « Après » de la répétition à la ligne
près. Migrations 1–11 ; inertie retirées 3, ordres en vigueur 16, textes ouverts 70, titres en
vigueur 2 ; unités en vigueur 9 et 9 ; I1, E1, E2 ouvertes au cran 2 dans les deux groupes ;
révisions 107 ; traductions 144 ; `inertia_changes` 10 ; 6 `seed_proposal_amendments` « applied » ;
2 `quorum_amendments` « applied » ; file 4 en attente, 13 faites ; 0, 0, 0, 1 ; `integrity_check`
ok, `foreign_key_check` vide ;
- dépôt des textes : `main` = `9e0f45a9e8d4af356a0c42daa5f4fb9eb9e6dfb3`, inchangé : aucun commit.
- `main` local avancé sur `94ddb17` (`git fetch . 94ddb17…:main`, depuis `fa8e8dc`).
- Les trois copies de la base (`/tmp/ld-m6-copie` de 06h11, `/tmp/ld-m6-copie2`, `/tmp/ld-m6-apres`)
retirées à 07h03:43. Les copies de répétition de l'intégrateur sont à retirer par lui.
- Reste à l'écran, pour Yvv à son retour : l'accueil sous la voûte ; l'Acte d'engagement (les
Propositions seed, aucun article en vigueur) ; un vote dans Monnaie libre affiche « simulé ».
- Image de retour : `libredecision-app:previous` (`3f10a0e`), avec la coupure de la publication
d'abord (§ Retour).