Fusion du lot G : sur une version retenue par une objection, « contre » et retrait oui, « pour » non (Yvv, 01/11)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-11-02 01:29:35 +01:00
co-authored by Claude Opus 5.5
23 changed files with 478 additions and 116 deletions
+26
View File
@@ -17,6 +17,10 @@
//! is changed by a proposal. The target is fixed when the objection is raised;
//! - the votes already cast on it stay, but it cannot enter into force
//! (`votable` and the adoption: a non-votable version is blocked);
//! - while it is held, one may still **vote against it or take one's vote
//! back**, never add a *for* (`may_cast`, Yvv 2026-11-01: « Retirer ou
//! "contre" »): it can only lose votes, and once lifted it enters with the
//! votes still there;
//! - its author **answers**: a substantive revision of it, or a proposal linked
//! to the objection (on the article it repeats, for a « redit »; a reworded
//! version, for a version without author). A substantive revision of **the
@@ -31,6 +35,7 @@
//! lift too (never reiterate: the objection is not theirs); withdrawing either
//! version ends it.
use crate::ballot::Choice;
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
@@ -296,6 +301,16 @@ pub fn votable(id: &str, in_force: bool, held: &[&str]) -> bool {
in_force || !held.contains(&id)
}
/// May this choice be cast on a version? `held` = a standing objection holds it
/// back now (never a version in force, `votable`). Yvv, 2026-11-01, to « pendant
/// qu'une objection retient une version, que permet-on ? »: « Retirer ou
/// "contre" ». On a held version one may take one's vote back or vote against,
/// never add a *for*: it can only lose votes while it is held, and once lifted it
/// enters with the votes still there. A version not held takes any choice.
pub fn may_cast(held: bool, choice: Choice) -> bool {
!held || choice != Choice::For
}
#[cfg(test)]
mod tests {
use super::*;
@@ -357,6 +372,17 @@ mod tests {
assert!(votable("x", true, &["x"]), "a version in force is never made non-votable");
}
#[test]
fn a_held_version_takes_against_and_withdrawal_never_for() {
// Yvv, 2026-11-01: « Retirer ou "contre" » — it can only lose votes while held.
assert!(!may_cast(true, Choice::For), "never a new *for* while held");
assert!(may_cast(true, Choice::Against), "against, yes");
assert!(may_cast(true, Choice::None), "taking one's vote back, yes");
for c in [Choice::For, Choice::Against, Choice::None] {
assert!(may_cast(false, c), "a version not held takes any choice: {c:?}");
}
}
#[test]
fn the_full_cycle_answer_reiterate_answer_lift() {
let start = Phase::Author { cycle: 1 };