forked from yvv/decision
v3 : la Raison d'être remplace le Préambule (L7), amendement de seed gardé
- seed : I1 devient « Raison d'être », texte d'Yvv (fr), traduit en « Purpose » et « Razón de ser » ; apostrophes droites comme le reste du seed, insécables avant « ; » et dans les guillemets. - seed_amend.rs : un amendement de seed remplace un texte de départ dans une base existante, décidé une fois par document et seulement si personne n'a touché l'article (seed a minima d'origine, révision 1, aucun vote, aucune correction, aucune traduction de membre, aucun signalement, empreinte attendue). Décision consignée (migration 0004, table seed_amendments), ligne d'historique « texte de départ remplacé » avec son diff, republication mise en file là où le document publie. - Une coquille se mesure désormais aussi contre le texte posé par l'amendement. - Tests : règle pure (3), scénarios d'API (base neuve, amendement appliqué et republié une seule fois, cinq refus), e2e C13 ; C3, C6 et l'API suivent le nouveau texte (C6 : les apostrophes typographiques d'Unicité du compte, « latransmission » ayant disparu). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,10 +2,13 @@
|
||||
//!
|
||||
//! On start, missing groups are created and every `seeds/*.json` document is
|
||||
//! instantiated in each group it names, **only if that group does not hold it
|
||||
//! yet**. An existing document is never touched: from its first vote on, it
|
||||
//! is runtime data.
|
||||
//! yet**. An existing document is never instantiated again: from its first
|
||||
//! vote on, it is runtime data. The one way a newer seed text reaches an
|
||||
//! existing document is a seed amendment (`seed_amend`): listed, decided once,
|
||||
//! and applied only to an article nobody has touched.
|
||||
|
||||
use crate::AppState;
|
||||
use crate::seed_amend;
|
||||
use crate::util::{self, LangMap};
|
||||
use serde::Deserialize;
|
||||
use std::path::Path;
|
||||
@@ -64,14 +67,23 @@ pub async fn ensure_groups(state: &AppState) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// On start: the groups, the documents missing from them, then the seed
|
||||
/// 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?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The groups and every seed document missing from its groups; returns the seeds read.
|
||||
pub async fn documents(state: &AppState) -> anyhow::Result<Vec<SeedDoc>> {
|
||||
ensure_groups(state).await?;
|
||||
let dir = state.cfg.seed_dir.clone();
|
||||
let mut entries = match tokio::fs::read_dir(&dir).await {
|
||||
Ok(e) => e,
|
||||
Err(e) => {
|
||||
tracing::warn!(dir = %dir.display(), error = %e, "no seed directory");
|
||||
return Ok(());
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
};
|
||||
let mut files = Vec::new();
|
||||
@@ -82,13 +94,14 @@ pub async fn ensure(state: &AppState) -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
files.sort();
|
||||
let mut seeds = Vec::new();
|
||||
for path in files {
|
||||
load_file(state, &path).await?;
|
||||
seeds.push(load_file(state, &path).await?);
|
||||
}
|
||||
Ok(())
|
||||
Ok(seeds)
|
||||
}
|
||||
|
||||
async fn load_file(state: &AppState, path: &Path) -> anyhow::Result<()> {
|
||||
async fn load_file(state: &AppState, path: &Path) -> anyhow::Result<SeedDoc> {
|
||||
let raw = tokio::fs::read_to_string(path).await?;
|
||||
let seed: SeedDoc = serde_json::from_str(&raw).map_err(|e| anyhow::anyhow!("{}: {e}", path.display()))?;
|
||||
for inst in &seed.instances {
|
||||
@@ -111,7 +124,7 @@ async fn load_file(state: &AppState, path: &Path) -> anyhow::Result<()> {
|
||||
instantiate(state, &seed, inst).await?;
|
||||
tracing::info!(group = %inst.group, slug = %seed.slug, "seed instantiated");
|
||||
}
|
||||
Ok(())
|
||||
Ok(seed)
|
||||
}
|
||||
|
||||
async fn instantiate(state: &AppState, seed: &SeedDoc, inst: &SeedInstance) -> anyhow::Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user