v3 : inertie à cinq crans — moteur, données, serveur (L10)
Moteur (ld-engine/inertia.rs) : cinq crans, M_k = 50, 50, 55, 60, 66 % ; s_k = 60, 67, 75, 83, 90 % de « pour » au-delà de C à la participation habituelle p̃ ; G_k = ln(1 − (s_k − M_k)/(1 − M_k)) / ln(p̃). p̃ = médiane des votants des propositions du groupe (au moins 5, votées dans l'année), sinon la référence 2C/W ; bornée à [1 %, 50 %]. Le changement d'inertie hérite du cran de l'article (remplace « inertie + »). Un seuil qui tombe sur un entier n'y gagne plus une voix par arrondi. Données : migration 0005 (les quatre mots deviennent 2 à 5, gardés tels quels dans *_legacy ; adoptions intactes ; journaux inertia_changes et inertia_amendments). Seed : 3 partout, 4 pour E1 et E2. Amendement d'inertie gardé (E1, E2 : 3 → 4, seulement si aucun vote n'a changé leur inertie ; une proposition d'inertie ouverte reste ouverte, votée au nouveau cran), journalisé, une seule fois, republié. Serveur : participation mesurée une fois par jour (settings), échelle dans les seuils, le balayage et l'adoption ; crans, M, G, s_k, p̃ et sa source servis au client. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -112,13 +112,15 @@ async fn the_seed_a_minima_and_the_open_proposals() {
|
||||
assert_eq!(e1["tally"]["for"], 0);
|
||||
assert_eq!(doc["doc"]["voteFloor"], 50.0);
|
||||
assert_eq!(doc["doc"]["electorate"], 5745);
|
||||
// Every other article is an open proposal at zero votes, standard inertia.
|
||||
// Every other article is an open proposal at zero votes, at the middle level of inertia.
|
||||
let e3 = unit(&doc, "E3");
|
||||
assert!(e3["inForce"].is_null());
|
||||
// In the order of the seed, whatever their random identifiers.
|
||||
let labels: Vec<&str> = e3["proposals"].as_array().expect("p").iter().filter_map(|p| p["label"].as_str()).collect();
|
||||
assert_eq!(labels, ["1.0.0", "0.4.0-draft"], "E3 and its 0.4.0 variant");
|
||||
assert_eq!(e3["inertia"], "standard");
|
||||
assert_eq!(e3["inertia"], 3);
|
||||
// The two structural commitments start one level up (Yvv, 2026-10-30).
|
||||
assert_eq!((unit(&doc, "E1")["inertia"].as_u64(), unit(&doc, "E2")["inertia"].as_u64()), (Some(4), Some(4)));
|
||||
// Translations seeded.
|
||||
assert!(e1["translations"]["en"]["body"].as_str().expect("en").contains("commit"));
|
||||
}
|
||||
@@ -375,20 +377,23 @@ async fn a_contradiction_signal_blocks_entering_into_force() {
|
||||
assert_eq!(v["entered"][0]["code"], "K1");
|
||||
}
|
||||
|
||||
/// Replaces « inertia change is voted one level up » (2026-10-21): since
|
||||
/// 2026-10-30 a change of inertia inherits the level of its article (ADR 0007).
|
||||
#[tokio::test]
|
||||
async fn inertia_change_is_voted_one_level_up() {
|
||||
async fn inertia_change_is_voted_at_the_level_of_the_article() {
|
||||
let (mut a, _) = Client::new().await;
|
||||
a.login("Yvv", false).await;
|
||||
let id = doc_id(&mut a, "monnaie-libre").await;
|
||||
let (_, doc) = a.call("GET", &format!("/api/docs/{id}"), None).await;
|
||||
let uid = unit(&doc, "E1")["id"].as_str().expect("u").to_owned();
|
||||
let (s, v) = a.call("POST", &format!("/api/units/{uid}/inertia"), Some(json!({ "target": "high" }))).await;
|
||||
let (s, v) = a.call("POST", &format!("/api/units/{uid}/inertia"), Some(json!({ "target": 5 }))).await;
|
||||
assert_eq!(s, StatusCode::OK, "{v}");
|
||||
let p = v["id"].as_str().expect("id").to_owned();
|
||||
let (_, again) = a.call("POST", &format!("/api/units/{uid}/inertia"), Some(json!({ "target": "high" }))).await;
|
||||
// The word of before reads as its level: the same proposal, not a second one.
|
||||
let (_, again) = a.call("POST", &format!("/api/units/{uid}/inertia"), Some(json!({ "target": "max" }))).await;
|
||||
assert_eq!(again["id"], p.as_str());
|
||||
let (_, d) = a.call("GET", &format!("/api/proposals/{p}"), None).await;
|
||||
assert_eq!(d["proposal"]["votedAtInertia"], "high");
|
||||
assert_eq!((d["proposal"]["inertiaTarget"].as_u64(), d["proposal"]["votedAtInertia"].as_u64()), (Some(5), Some(4)));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -769,6 +774,10 @@ async fn publication_writes_the_texts_in_force_to_the_repository() {
|
||||
serde_json::from_str(&show("monnaie-libre/acte-engagement-certification/document.json")).expect("json");
|
||||
assert_eq!(json["units"].as_array().expect("units").len(), 3);
|
||||
assert_eq!(json["units"][0]["status"], "seed-minimal");
|
||||
// Levels of inertia are published as numbers, 1 to 5.
|
||||
let levels: Vec<Option<u64>> =
|
||||
json["units"].as_array().expect("units").iter().map(|u| u["inertia"].as_u64()).collect();
|
||||
assert_eq!(levels, [Some(3), Some(4), Some(4)]);
|
||||
assert!(show("README.md").contains("libreDecision"));
|
||||
let done: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM outbox WHERE done_at IS NULL")
|
||||
.fetch_one(&state.db)
|
||||
|
||||
Reference in New Issue
Block a user