Fusion de la tête du chantier (924a40d : lots B2 et F) dans le lot D

Les deux côtés gardés partout. Aux coutures :
- une objection (redit / contredit) porte sur deux articles, jamais sur un module ;
  un ordre ne se corrige pas, ni par son auteur ni par un autre ; une coquille du
  titre suit le chemin de F (l'auteur du titre, un administrateur pour le titre
  de départ, ou 3 jours), et documents.title suit à l'application ;
- votable() couvre les modules ; leurs totaux passent par shown_tally, à l'écran
  et dans document.json ;
- « Modules à voter » ne compte plus une version retenue par une objection (test
  vu rouge) ; la liste du groupe la compte toujours parmi les propositions en cours ;
- le panier : une fonction pour les articles et les modules, avec les versions
  retenues de F ; un nouvel article se propose dans une section, à sa fin, et peut
  répondre à une objection ;
- migrations 0007 (modules) puis 0008 (objections) ;
- C25 et C26 supportent un groupe d'essai où une voix suffit (dès 16 membres).

Boucle : fmt, clippy -D warnings, cargo test (227), svelte-check 0, vitest 55,
build, e2e 35 / 35 (C1–C33 et M1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-10-31 09:41:30 +01:00
co-authored by Claude Opus 5.5
82 changed files with 8285 additions and 677 deletions
+6 -1
View File
@@ -206,7 +206,8 @@ fn kept_params(st: &DocState, unit: &docs::UnitRow, p: &docs::ProposalRow) -> se
/// The electorate changes (the web of trust grows or shrinks): every few
/// minutes, every document is passed through the engine again — after the
/// usual participation of each group is measured again, once a day.
/// usual participation of each group is measured again, once a day, and after
/// the deadlines of three days are passed (`deadlines`).
pub async fn sweeper(state: AppState) {
let mut tick = tokio::time::interval(Duration::from_secs(300));
loop {
@@ -214,6 +215,10 @@ pub async fn sweeper(state: AppState) {
if let Err(e) = crate::participation::refresh(&state, false).await {
tracing::warn!(error = %e, "usual participation");
}
// Objections lifted and typo fixes applied at their deadline (three days).
if let Err(e) = crate::deadlines::sweep(&state).await {
tracing::warn!(error = %e, "deadlines");
}
let ids: Vec<String> = match sqlx::query_scalar("SELECT id FROM documents").fetch_all(&state.db).await {
Ok(ids) => ids,
Err(e) => {