[FIX] session: undo never moves id counters back
Undoing back before a generation restored the whole charge, its prochainsIds included: the next generation numbered its propositions 1 to 3 again, and a label of the abandoned thread such as "retained proposition 2" named another proposition. § 8.9 forbids it: a counter never goes back. A retour now restores the content of the instant and keeps each counter at the larger of its restored and current value, so the next id is fresh. Checked: 1416 node tests; the retour test is red on the previous seance.js. --- FR --- [FIX] séance : un retour ne fait jamais reculer les compteurs Défaire jusqu'avant une génération restituait la charge entière, prochainsIds compris : la génération suivante renumérotait ses propositions de 1 à 3, et un libellé du fil abandonné, comme « retenu la proposition 2 », désignait une autre proposition. Le § 8.9 l'interdit : un compteur ne recule jamais. Un retour restitue désormais le contenu de l'instant et porte chaque compteur au plus grand de sa valeur restituée et de sa valeur courante. Vérifié : 1416 épreuves node ; l'épreuve du retour est rouge sur l'ancien code. Assisted-by: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
This commit is contained in:
parent
481f6a6bae
commit
a1cac443bb
2 changed files with 25 additions and 3 deletions
|
|
@ -416,6 +416,19 @@ export function creerSeance({
|
|||
}
|
||||
}
|
||||
|
||||
// La charge restituée, ses compteurs d'identifiants portés au plus grand
|
||||
// de leur valeur restituée et de leur valeur courante : un retour rend le
|
||||
// contenu d'un instant, jamais un identifiant déjà donné (§ 8.9) — une
|
||||
// génération après un défaire numérote au-delà des propositions défaites,
|
||||
// et le retenu d'un fil abandonné garde la proposition qu'il désignait.
|
||||
function avecCompteursCourants(charge, courante) {
|
||||
const prochainsIds = {};
|
||||
for (const cle of ['participant', 'table', 'proposition']) {
|
||||
prochainsIds[cle] = Math.max(charge.prochainsIds[cle], courante.prochainsIds[cle]);
|
||||
}
|
||||
return { ...charge, prochainsIds };
|
||||
}
|
||||
|
||||
// Un retour, sans son suivi : défaire vise le prédécesseur de l'instant
|
||||
// courant sur le fil, refaire le sommet de sa pile, revenir l'instant
|
||||
// donné ; l'entrée porte la charge restituée, son sens et sa cible.
|
||||
|
|
@ -431,7 +444,7 @@ export function creerSeance({
|
|||
if (cibleRefaire === null) throw new ErreurSeance('RIEN_A_REFAIRE');
|
||||
cible = cibleRefaire;
|
||||
}
|
||||
const charge = restituer(ouvert, cible);
|
||||
const charge = avecCompteursCourants(restituer(ouvert, cible), ouvert.charge);
|
||||
if (serialiserCharge(charge) === serialiserCharge(ouvert.charge)) throw new ErreurSeance('SANS_EFFET', { sens });
|
||||
const instant = sens === 'defaire' ? courant : libelleDeRevision(ouvert.journal, cible);
|
||||
const entree = { charge, libelle: libelleDuRetour(sens, instant), avertissements: [] };
|
||||
|
|
|
|||
|
|
@ -641,8 +641,17 @@ describe('séance : revenir, défaire, refaire (§ 8.3)', () => {
|
|||
[7, 'revenir', 2, 'Retour à « Ajouté Ancolie »'],
|
||||
],
|
||||
);
|
||||
assert.deepEqual(etatDe(fs).charge, reconstruire(journal, 2));
|
||||
assert.deepEqual(reconstruire(journal, 7), reconstruire(journal, 2));
|
||||
// L'instant 2 revient avec son contenu, et ses compteurs restent où trois
|
||||
// ajouts les ont portés : aucun identifiant donné ne se redonne (§ 8.9).
|
||||
const instant2 = reconstruire(journal, 2);
|
||||
const attendu = { ...instant2, prochainsIds: { ...instant2.prochainsIds, participant: 4 } };
|
||||
assert.deepEqual(etatDe(fs).charge, attendu);
|
||||
assert.deepEqual(reconstruire(journal, 7), attendu);
|
||||
await seance.executer('ajouterParticipant', { champs: { nom: 'Digitale' } });
|
||||
assert.deepEqual(
|
||||
seance.charge.participants.map(({ id, nom }) => [id, nom]),
|
||||
[[1, 'Ancolie'], [4, 'Digitale']],
|
||||
);
|
||||
});
|
||||
|
||||
test("refaire n'existe qu'après des retours, tant qu'aucun geste ne les suit", async () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue