v3 : sixième relecture — une coquille touche les lettres et les espaces, rien d'autre

- La forme du texte (tout ce qui n'est ni lettre latine ni espace, dans
  l'ordre, avec les espaces qui touchent un chiffre) ne bouge plus : ponctuation,
  emphase, signes, parenthèses passent par une proposition (un signe moins devant
  un nombre en gras, deux conditions fusionnées, une parenthèse déplacée).
  Apostrophes et guillemets de tous styles comptent pour un même signe.
- Les espaces ne font que coller ou couper des mots, jamais déplacer une
  frontière (« les avoir » → « le savoir »).
- Identifiants qui contiennent un chiffre (clés, références) comparés à
  l'identique, casse comprise, comme les adresses.
- Correction écrite seulement sur le texte jugé (révision, statut, texte) :
  sinon conflit « changed » — plus de course avec une entrée en vigueur.
- Déploiement : « previous » n'est pas repris d'un pipeline annulé.
- Interface (fr/en/es) : la note de correction dit la règle telle qu'elle est.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-10-21 06:52:04 +02:00
co-authored by Claude Opus 5.5
parent 6c0754a5c3
commit fa8e8dc1f0
9 changed files with 218 additions and 130 deletions
+38 -15
View File
@@ -333,13 +333,25 @@ pub async fn edit(
if !(is_author || p.origin == "seed" || p.status == "in_force") {
return Err(AppError::Forbidden);
}
sqlx::query("UPDATE proposals SET title = ?, body = ?, updated_at = ? WHERE id = ?")
.bind(title)
.bind(body)
.bind(&now)
.bind(&id)
.execute(&state.db)
.await?;
// Written only over the text that was judged: an entry into force or another
// correction in between makes it a conflict, never a silent change.
let done = sqlx::query(
"UPDATE proposals SET title = ?, body = ?, updated_at = ?
WHERE id = ? AND revision = ? AND status = ? AND title = ? AND body = ?",
)
.bind(title)
.bind(body)
.bind(&now)
.bind(&id)
.bind(p.revision)
.bind(&p.status)
.bind(&p.title)
.bind(&p.body)
.execute(&state.db)
.await?;
if done.rows_affected() != 1 {
return Err(AppError::Conflict("changed"));
}
record_revision(&state, &id, p.revision, "typo", title, body, Some(&user.id)).await?;
// A typo fix does not change the meaning: up-to-date translations stay up to date.
sqlx::query("UPDATE translations SET source_hash = ? WHERE proposal_id = ? AND source_hash = ?")
@@ -361,14 +373,25 @@ pub async fn edit(
return Err(AppError::Conflict("substantive_not_author"));
}
let revision = p.revision + 1;
sqlx::query("UPDATE proposals SET title = ?, body = ?, revision = ?, updated_at = ? WHERE id = ?")
.bind(title)
.bind(body)
.bind(revision)
.bind(&now)
.bind(&id)
.execute(&state.db)
.await?;
// Only on the open proposal that was read: never on a text that entered into
// force in the meantime.
let done = sqlx::query(
"UPDATE proposals SET title = ?, body = ?, revision = ?, updated_at = ?
WHERE id = ? AND revision = ? AND status = 'open' AND title = ? AND body = ?",
)
.bind(title)
.bind(body)
.bind(revision)
.bind(&now)
.bind(&id)
.bind(p.revision)
.bind(&p.title)
.bind(&p.body)
.execute(&state.db)
.await?;
if done.rows_affected() != 1 {
return Err(AppError::Conflict("changed"));
}
record_revision(&state, &id, revision, "substantive", title, body, Some(&user.id)).await?;
// Signals were about the former text: they lapse, their authors may signal again.
sqlx::query(