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

14 KiB
Raw Blame History

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 : 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)

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 :

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

  • Santé vue de l'extérieur → "build":"94ddb175".
  • 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.
  • Redémarrage à froid (docker compose restart dans /opt/libredecision-app), santé vue de l'extérieur, journaux : aucun amendement rejoué.
  • 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.
  • 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.

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

(à remplir par orch)