v3 : modules d'ordre et de titre — moteur, données, serveur (L11)

L'ordre des articles de chaque section (cran 2) et le titre du document
(cran 4) deviennent des modules : des unités à part, dont les versions
sont des propositions votées comme les articles (dépliées, panier, chaîne).

- moteur : ld-engine/src/order.rs (qui est dans l'ordre, ordre proposé,
  complété à la fin quand un article entre ou sort, places redistribuées,
  nouvel article en fin de section) ; pending : un ordre de moins de deux
  articles n'est jamais à voter ;
- données : migration 0007 (units.kind, module_amendments) ; le seed
  déclare ses modules ; module_amend.rs les ajoute une fois, gardé et
  journalisé, aux documents nés sans eux, sans toucher articles ni votes ;
- serveur : modules.rs, order.rs, doc_title.rs (portes pour proposer,
  entrée en vigueur : les articles changent de place, le document change
  de titre, en et es passent « à revoir ») ; publication des modules ;
- reste mineur : la médiane compte les statuts open, in_force, applied,
  et eux seuls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-10-31 02:08:44 +01:00
co-authored by Claude Opus 5.5
parent 1a35d0f521
commit 3831ddb1bf
21 changed files with 2249 additions and 115 deletions
+27 -3
View File
@@ -7,10 +7,14 @@
//! existing document is a seed amendment (`seed_amend`): listed, decided once,
//! and applied only to an article nobody has touched; a newer starting level of
//! inertia, an inertia amendment (`inertia_amend`), on an article whose inertia
//! no vote changed.
//! no vote changed; modules the seed declares (the title, the order of each
//! section, ADR 0009), a module amendment (`module_amend`), built from what the
//! document holds.
use crate::AppState;
use crate::inertia_amend;
use crate::module_amend;
use crate::modules;
use crate::seed_amend;
use crate::util::{self, LangMap};
use ld_engine::inertia::InertiaLevel;
@@ -25,9 +29,24 @@ pub struct SeedDoc {
pub summary: LangMap,
pub source_lang: String,
pub instances: Vec<SeedInstance>,
/// The modules of the document (ADR 0009): its title, the order of each section.
#[serde(default)]
pub modules: Option<SeedModules>,
pub units: Vec<SeedUnit>,
}
#[derive(Deserialize)]
pub struct SeedModules {
pub title: Option<SeedModule>,
pub order: Option<SeedModule>,
}
#[derive(Deserialize)]
pub struct SeedModule {
/// The level it starts at, 1 to 5.
pub inertia: InertiaLevel,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SeedInstance {
@@ -72,12 +91,13 @@ pub async fn ensure_groups(state: &AppState) -> anyhow::Result<()> {
Ok(())
}
/// On start: the groups, the documents missing from them, then the seed and
/// inertia amendments (each decided once per document).
/// On start: the groups, the documents missing from them, then the seed,
/// inertia and module amendments (each decided once per document).
pub async fn ensure(state: &AppState) -> anyhow::Result<()> {
let seeds = documents(state).await?;
seed_amend::apply(state, &seeds, seed_amend::AMENDMENTS).await?;
inertia_amend::apply(state, &seeds, inertia_amend::AMENDMENTS).await?;
module_amend::apply(state, &seeds, module_amend::AMENDMENTS).await?;
Ok(())
}
@@ -223,6 +243,10 @@ async fn instantiate(state: &AppState, seed: &SeedDoc, inst: &SeedInstance) -> a
}
}
}
// The modules, from the document just written: its title, the order of each section.
if let Some(m) = &seed.modules {
modules::create(&mut tx, &doc_id, m.into(), &now).await?;
}
if inst.publish_path.is_some() {
sqlx::query(
"INSERT INTO outbox (doc_id, reason, created_at, next_at) VALUES (?, 'publication initiale', ?, ?)",