[ADD] application: clock, translation, formatting, displayed name
The screens need one clock, one translation mechanism and one way to
format and name, or each component grows its own. horloge.js is the only
code that reads time and arms timers, injected so tests drive it.
traduction.js keys texts by domain, in two families of tables, raises on a
missing key and never shows a raw key; libelles/ splits the label table by
domain. format.js formats numbers and dates in French, and personnes.js
composes the displayed name the frozen labels use. Nothing persists
between sessions.
Checked: 1773 node and 43 browser tests.
--- FR ---
[ADD] application : horloge, traduction, mise en forme, nom affiché
Les écrans exigent une horloge, un mécanisme de traduction et une façon de
mettre en forme et de nommer, sans quoi chaque composant ferait les siens.
horloge.js est le seul code qui lit l'heure et arme des minuteries, injecté
pour que les épreuves le pilotent. traduction.js range les textes par
domaine, en deux familles de tables, lève sur une clé absente et ne montre
jamais une clé brute ; libelles/ découpe la table des libellés par domaine.
format.js met en forme nombres et dates en français, et personnes.js
compose le nom affiché qu'emploient les libellés figés. Rien ne persiste
d'une séance à l'autre.
Vérifié : 1773 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:39 -04:00
|
|
|
// © 2026 TechnoLibre (http://www.technolibre.ca)
|
|
|
|
|
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
|
|
|
|
|
|
|
|
|
|
// Les textes des codes de la séance (§ 8.3 à § 8.8, § 14.6), et les libellés
|
|
|
|
|
// figés que la séance écrit au journal : jalons, reprise, retours. Un libellé
|
|
|
|
|
// d'entrée se compose une fois, à l'écriture du geste, et le journal en garde
|
|
|
|
|
// le texte, jamais le code (§ 8.2).
|
[ADD] application: observable session, events facade, places and seats
The screens of iteration 3 need state they can subscribe to and commands
that keep the plan sound. The session follows the Svelte store contract,
unblocks a plan, cancels a gesture, keeps the framing, and orders the
warnings of a gesture. The facade lists events, settles the working folder
and runs copy, rename, import and delete. Places cover reservations, titles,
designation and the retained plan: each gesture reads seats as the display
shows them, reserved people keep their table, and a person removed frees
her chair while every other seat stays.
Checked: 1973 node, 127 browser, 60 node-long tests; coverage floors kept.
--- FR ---
[ADD] application : séance observable, façade des événements, places
Les écrans de l'itération 3 exigent un état auquel s'abonner et des
commandes qui gardent le plan sain. La séance suit le contrat des magasins
de Svelte, débloque un plan, annule un geste, garde le cadrage et ordonne
les avertissements d'un geste. La façade liste les événements, règle le
dossier de travail et mène copie, renommage, import et suppression. Les
places couvrent réservations, titres, désignation et plan retenu : chaque
geste lit les sièges comme l'écran les montre, une personne réservée garde
sa table, et une personne retirée libère sa chaise sans déplacer les autres.
Vérifié : 1973 node, 127 navigateur, 60 node-long ; seuils de couverture.
Assisted-by: Claude Opus 5.5
2026-10-07 04:14:24 -04:00
|
|
|
import {
|
|
|
|
|
capitale,
|
|
|
|
|
causeEntreParentheses,
|
|
|
|
|
cite,
|
|
|
|
|
compte,
|
|
|
|
|
depuisQuand,
|
|
|
|
|
enumeration,
|
|
|
|
|
nomEtat,
|
|
|
|
|
ouEcrire,
|
|
|
|
|
phraseDeRaison,
|
|
|
|
|
} from './aides.js';
|
|
|
|
|
|
|
|
|
|
// Le placement qu'une dérive touche : le retenu, ou une proposition par son
|
|
|
|
|
// numéro.
|
|
|
|
|
const nomDuPlacement = (id) => (id === 'retenu' ? 'le placement retenu' : `la proposition n° ${id}`);
|
|
|
|
|
|
|
|
|
|
// Les raisons d'un placement, chacune par son texte.
|
|
|
|
|
const phrasesDe = (raisons, texte) => raisons.map((raison) => phraseDeRaison(raison.code, raison, texte)).join(' ');
|
|
|
|
|
|
|
|
|
|
// Une violation du retenu : la réservation qu'il ne tient pas par le texte
|
|
|
|
|
// de RESERVATION_NON_HONOREE, toute autre par le texte de son code.
|
|
|
|
|
const phraseDeViolation = (violation, texte) =>
|
|
|
|
|
violation.code === 'RESERVATION'
|
|
|
|
|
? texte('RESERVATION_NON_HONOREE', violation)
|
|
|
|
|
: phraseDeRaison(violation.code, violation, texte);
|
[ADD] application: clock, translation, formatting, displayed name
The screens need one clock, one translation mechanism and one way to
format and name, or each component grows its own. horloge.js is the only
code that reads time and arms timers, injected so tests drive it.
traduction.js keys texts by domain, in two families of tables, raises on a
missing key and never shows a raw key; libelles/ splits the label table by
domain. format.js formats numbers and dates in French, and personnes.js
composes the displayed name the frozen labels use. Nothing persists
between sessions.
Checked: 1773 node and 43 browser tests.
--- FR ---
[ADD] application : horloge, traduction, mise en forme, nom affiché
Les écrans exigent une horloge, un mécanisme de traduction et une façon de
mettre en forme et de nommer, sans quoi chaque composant ferait les siens.
horloge.js est le seul code qui lit l'heure et arme des minuteries, injecté
pour que les épreuves le pilotent. traduction.js range les textes par
domaine, en deux familles de tables, lève sur une clé absente et ne montre
jamais une clé brute ; libelles/ découpe la table des libellés par domaine.
format.js met en forme nombres et dates en français, et personnes.js
compose le nom affiché qu'emploient les libellés figés. Rien ne persiste
d'une séance à l'autre.
Vérifié : 1773 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:39 -04:00
|
|
|
|
|
|
|
|
export const TABLE = new Map([
|
|
|
|
|
// --- La séance (§ 8.3, § 8.4, § 8.5, § 8.6, § 8.8) -------------------------
|
|
|
|
|
['AUCUN_EVENEMENT', () => "Aucun événement n'est ouvert."],
|
|
|
|
|
['MODE_LECTURE', () => "L'événement est ouvert en lecture : « Modifier » permet de le changer."],
|
|
|
|
|
['FORMAT', (details, texte) => texte('FORMAT_PLUS_RECENT', details)],
|
|
|
|
|
['BLOQUE', () => 'Le plan est bloqué.'],
|
|
|
|
|
// echec nomme ce que le support n'a pas reçu : la ligne d'un geste
|
|
|
|
|
// (ECRITURE), l'état d'un geste inscrit au journal (ETAT_NON_ECRIT), le
|
|
|
|
|
// jalon d'un geste enregistré (JALON_NON_ECRIT), ou le verrou d'un passage
|
|
|
|
|
// en écriture (VERROU_NON_ECRIT), qui ne perd rien.
|
|
|
|
|
[
|
|
|
|
|
'SUPPORT_ROMPU',
|
|
|
|
|
({ echec, ...details }, texte) => {
|
|
|
|
|
const refus = `Le support ne prend plus les écritures : ${ouEcrire(details, texte)} n'a pas pu s'écrire`;
|
|
|
|
|
const ailleurs = "« Écrire ailleurs » enregistre l'événement dans un autre dossier.";
|
|
|
|
|
if (echec === 'ECRITURE' || echec === 'ETAT_NON_ECRIT') {
|
|
|
|
|
const perte =
|
|
|
|
|
echec === 'ETAT_NON_ECRIT'
|
|
|
|
|
? "le dernier geste est inscrit à l'historique, mais pas dans l'état"
|
|
|
|
|
: "le dernier geste n'est pas enregistré";
|
|
|
|
|
return `${refus}, et ${perte}. Sur ce support, l'historique et l'état ne se correspondent plus ; ${ailleurs}`;
|
|
|
|
|
}
|
|
|
|
|
if (echec === 'JALON_NON_ECRIT') {
|
|
|
|
|
return (
|
|
|
|
|
`${refus}. Le dernier geste est enregistré, mais pas le jalon qui le nomme, ` +
|
|
|
|
|
`et aucun geste ne s'y enregistrerait plus ; ${ailleurs}`
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
if (echec === 'VERROU_NON_ECRIT') {
|
|
|
|
|
return (
|
|
|
|
|
`${refus}. L'événement y reste tel qu'il s'affiche, ` +
|
|
|
|
|
`mais aucun geste ne s'y enregistrerait ; ${ailleurs}`
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
throw new RangeError(`libelle : échec du support inconnu ${JSON.stringify(echec)}`);
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
['SUPPORT_INTACT', () => "Le support prend encore les écritures : l'événement reste où il est."],
|
|
|
|
|
// Quitter l'événement d'un support rompu : la séance tient la seule copie
|
|
|
|
|
// que l'écriture ailleurs peut encore sauver ; ETAT_NON_ECRIT dit que son
|
|
|
|
|
// dernier geste n'est qu'à l'historique de ce support.
|
|
|
|
|
[
|
|
|
|
|
'SUPPORT_ROMPU_NON_SAUVE',
|
|
|
|
|
({ echec, dossier }) => {
|
|
|
|
|
const geste =
|
|
|
|
|
echec === 'ETAT_NON_ECRIT' ? ", et son dernier geste n'y est inscrit qu'à l'historique" : '';
|
|
|
|
|
return (
|
|
|
|
|
`Le support ${cite(dossier)} ne prend plus les écritures${geste} : ` +
|
|
|
|
|
"l'événement ouvert n'est sauvé dans aucun autre dossier. " +
|
|
|
|
|
"« Écrire ailleurs » l'enregistre d'abord ; le quitter maintenant l'abandonne à ce support."
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'EVENEMENT_CHANGE',
|
|
|
|
|
({ revision }) =>
|
|
|
|
|
`Une autre séance a modifié cet événement depuis son ouverture : il s'affiche tel qu'elle l'a laissé, ` +
|
|
|
|
|
`à la révision ${revision}, et les gestes suivants s'y ajoutent.`,
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'VERROU_REPRIS',
|
[ADD] interface: event list, open event, participants, import, plan
The working screens of an evening. The home screen lists the events of
the working folder, asks its question, loads demos, copies, renames,
imports and deletes, and shows what the trash holds. An open event frames
its mode, offers Modifier, Débloquer and a confirmed lock takeover, and
shows its warnings. Participants get a grid, a form and a file; an import
goes through a preview and a report; tables, the default and tours have
their screens; the plan draws tables, chairs, empty seats and names.
Checked: 2342 node, 356 browser, 60 node-long; the Electron start check.
--- FR ---
[ADD] interface : liste, événement, participants, import, tables, plan
Les écrans de travail d'une soirée. L'accueil liste les événements du
dossier de travail, pose sa question, charge les démonstrations, copie,
renomme, importe et supprime, et montre ce que tient la corbeille. Un
événement ouvert encadre son mode, offre Modifier, Débloquer et une
reprise de verrou confirmée, et montre ses avertissements. Les
participants ont une grille, un formulaire et une fiche ; un import passe
par un aperçu et un rapport ; tables, défaut et tours ont leurs écrans ;
le plan dessine tables, chaises, sièges vides et noms.
Vérifié : 2342 node, 356 navigateur, 60 node-long ; démarrage d'Electron.
Assisted-by: Claude Opus 5.5
2026-10-07 08:12:27 -04:00
|
|
|
({ depuis }, texte) => `Le verrou qu'une autre séance tenait${depuisQuand(depuis, texte)} est repris.`,
|
[ADD] application: clock, translation, formatting, displayed name
The screens need one clock, one translation mechanism and one way to
format and name, or each component grows its own. horloge.js is the only
code that reads time and arms timers, injected so tests drive it.
traduction.js keys texts by domain, in two families of tables, raises on a
missing key and never shows a raw key; libelles/ splits the label table by
domain. format.js formats numbers and dates in French, and personnes.js
composes the displayed name the frozen labels use. Nothing persists
between sessions.
Checked: 1773 node and 43 browser tests.
--- FR ---
[ADD] application : horloge, traduction, mise en forme, nom affiché
Les écrans exigent une horloge, un mécanisme de traduction et une façon de
mettre en forme et de nommer, sans quoi chaque composant ferait les siens.
horloge.js est le seul code qui lit l'heure et arme des minuteries, injecté
pour que les épreuves le pilotent. traduction.js range les textes par
domaine, en deux familles de tables, lève sur une clé absente et ne montre
jamais une clé brute ; libelles/ découpe la table des libellés par domaine.
format.js met en forme nombres et dates en français, et personnes.js
compose le nom affiché qu'emploient les libellés figés. Rien ne persiste
d'une séance à l'autre.
Vérifié : 1773 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:39 -04:00
|
|
|
],
|
[ADD] application: observable session, events facade, places and seats
The screens of iteration 3 need state they can subscribe to and commands
that keep the plan sound. The session follows the Svelte store contract,
unblocks a plan, cancels a gesture, keeps the framing, and orders the
warnings of a gesture. The facade lists events, settles the working folder
and runs copy, rename, import and delete. Places cover reservations, titles,
designation and the retained plan: each gesture reads seats as the display
shows them, reserved people keep their table, and a person removed frees
her chair while every other seat stays.
Checked: 1973 node, 127 browser, 60 node-long tests; coverage floors kept.
--- FR ---
[ADD] application : séance observable, façade des événements, places
Les écrans de l'itération 3 exigent un état auquel s'abonner et des
commandes qui gardent le plan sain. La séance suit le contrat des magasins
de Svelte, débloque un plan, annule un geste, garde le cadrage et ordonne
les avertissements d'un geste. La façade liste les événements, règle le
dossier de travail et mène copie, renommage, import et suppression. Les
places couvrent réservations, titres, désignation et plan retenu : chaque
geste lit les sièges comme l'écran les montre, une personne réservée garde
sa table, et une personne retirée libère sa chaise sans déplacer les autres.
Vérifié : 1973 node, 127 navigateur, 60 node-long ; seuils de couverture.
Assisted-by: Claude Opus 5.5
2026-10-07 04:14:24 -04:00
|
|
|
[
|
|
|
|
|
'RETOUR_AUTOMATIQUE',
|
|
|
|
|
() =>
|
|
|
|
|
"Faute d'activité, l'événement est revenu seul en lecture ; chaque geste achevé était déjà enregistré. " +
|
|
|
|
|
'« Modifier » permet de reprendre.',
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// --- Ce qu'un geste fait naître (§ 5.9, § 9, § 14.12) ----------------------
|
|
|
|
|
[
|
|
|
|
|
'DERIVE_NOUVELLE',
|
|
|
|
|
({ touchees }, texte) => {
|
|
|
|
|
const noms = touchees.map(({ id }) => nomDuPlacement(id));
|
|
|
|
|
const accord = touchees.length > 1 ? 'ne décrivent plus' : 'ne décrit plus';
|
|
|
|
|
const parPlacement = touchees.map(({ id, raisons }) => `${capitale(nomDuPlacement(id))} : ${phrasesDe(raisons, texte)}`);
|
|
|
|
|
return (
|
|
|
|
|
`Après ce geste, ${enumeration(noms)} ${accord} la liste ou les tables actuelles, et rien n'est effacé. ` +
|
|
|
|
|
parPlacement.join(' ')
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
],
|
[FIX] plan: named warning, one places state, highlight, table spacing
The unheld-reservation warning names the person and the table number
instead of their identifiers. The places state is computed once per change
and handed to the side panels, not once per panel. A person can be
highlighted from their menu or from the grid, and the view bar names them.
A created table takes a cell a full pitch away from every table, its own
capacity included, so no name list runs over a neighbour's chairs. The
rendering guards fail on an empty walk and also check focus and selection.
Checked: 2692 node, 496 browser, 60 long tests, from the index alone.
--- FR ---
[FIX] plan : avertissement nommé, état des places unique, évidence, pas
L'avertissement de réservation non honorée nomme la personne et le numéro
de la table plutôt que leurs identifiants. L'état des places se calcule une
fois par changement et passe aux panneaux, non une fois par panneau. Une
personne se met en évidence par son menu ou depuis la grille, et la barre
de vue la nomme. Une table créée prend une case à un pas plein de chaque
table, sa capacité comprise : aucune liste ne court sur les chaises
voisines. Les gardes du rendu échouent sur un parcours vide et éprouvent
aussi le focus et la sélection. Vérifié : 2692 node, 496 navigateur, 60.
Assisted-by: Claude Opus 5.5
2026-10-07 15:05:01 -04:00
|
|
|
// La personne se nomme par personne, et la table par numero, quand les
|
|
|
|
|
// détails les portent (avertissementsApres les lit sur la charge) ; une
|
|
|
|
|
// violation d'INVARIANT_VIOLE, qui ne les porte pas, garde les identifiants.
|
[FIX] iteration 3 review: seat targets, gestures, warnings, settings
The wheel no longer zooms during a gesture, so a drop lands under the
ghost. A seat is a target the size of its pitch. A floor drop refuses to
remove an every-tour reservation. A seat reservation the retained plan
does not hold is flagged at the seat, with its swap as remedy. DERIVE names
the person; capacities have an upper bound; Generate waits for a pending
setting; a worker that fails to load shows a refusal; § 5.3 constraints
get their switches. Commands are not re-entrant and a double click does not
confirm. Checked: 2755 node, 550 browser tests, from the index alone.
--- FR ---
[FIX] revue de l'itération 3 : cibles, gestes, avertissements, réglages
La molette ne zoome plus pendant un geste : le dépôt tombe sous le fantôme.
Un siège est une cible de la taille de son pas. Un dépôt sur le sol refuse
de retirer une réservation de tous les tours. Une réservation à un siège
que le retenu ne tient pas est relevée au siège, l'échange en remède. La
dérive nomme la personne ; les capacités ont une borne ; Générer attend un
réglage en cours ; un travailleur qui ne se charge pas donne un refus ; le
§ 5.3 a ses bascules. Les commandes ne sont pas ré-entrantes et un double
clic ne confirme pas. Vérifié : 2755 node, 550 navigateur, index seul.
Assisted-by: Claude Opus 5.5
2026-10-07 17:50:35 -04:00
|
|
|
// Au siège, siege et occupant disent la chaise réservée et ce qu'elle
|
|
|
|
|
// porte : la personne est assise à la même table, à un autre siège.
|
[ADD] application: observable session, events facade, places and seats
The screens of iteration 3 need state they can subscribe to and commands
that keep the plan sound. The session follows the Svelte store contract,
unblocks a plan, cancels a gesture, keeps the framing, and orders the
warnings of a gesture. The facade lists events, settles the working folder
and runs copy, rename, import and delete. Places cover reservations, titles,
designation and the retained plan: each gesture reads seats as the display
shows them, reserved people keep their table, and a person removed frees
her chair while every other seat stays.
Checked: 1973 node, 127 browser, 60 node-long tests; coverage floors kept.
--- FR ---
[ADD] application : séance observable, façade des événements, places
Les écrans de l'itération 3 exigent un état auquel s'abonner et des
commandes qui gardent le plan sain. La séance suit le contrat des magasins
de Svelte, débloque un plan, annule un geste, garde le cadrage et ordonne
les avertissements d'un geste. La façade liste les événements, règle le
dossier de travail et mène copie, renommage, import et suppression. Les
places couvrent réservations, titres, désignation et plan retenu : chaque
geste lit les sièges comme l'écran les montre, une personne réservée garde
sa table, et une personne retirée libère sa chaise sans déplacer les autres.
Vérifié : 1973 node, 127 navigateur, 60 node-long ; seuils de couverture.
Assisted-by: Claude Opus 5.5
2026-10-07 04:14:24 -04:00
|
|
|
[
|
|
|
|
|
'RESERVATION_NON_HONOREE',
|
[FIX] iteration 3 review: seat targets, gestures, warnings, settings
The wheel no longer zooms during a gesture, so a drop lands under the
ghost. A seat is a target the size of its pitch. A floor drop refuses to
remove an every-tour reservation. A seat reservation the retained plan
does not hold is flagged at the seat, with its swap as remedy. DERIVE names
the person; capacities have an upper bound; Generate waits for a pending
setting; a worker that fails to load shows a refusal; § 5.3 constraints
get their switches. Commands are not re-entrant and a double click does not
confirm. Checked: 2755 node, 550 browser tests, from the index alone.
--- FR ---
[FIX] revue de l'itération 3 : cibles, gestes, avertissements, réglages
La molette ne zoome plus pendant un geste : le dépôt tombe sous le fantôme.
Un siège est une cible de la taille de son pas. Un dépôt sur le sol refuse
de retirer une réservation de tous les tours. Une réservation à un siège
que le retenu ne tient pas est relevée au siège, l'échange en remède. La
dérive nomme la personne ; les capacités ont une borne ; Générer attend un
réglage en cours ; un travailleur qui ne se charge pas donne un refus ; le
§ 5.3 a ses bascules. Les commandes ne sont pas ré-entrantes et un double
clic ne confirme pas. Vérifié : 2755 node, 550 navigateur, index seul.
Assisted-by: Claude Opus 5.5
2026-10-07 17:50:35 -04:00
|
|
|
({ participant, table, tour, personne = null, numero = null, siege, occupant = null }) => {
|
|
|
|
|
const qui = personne ?? `la personne n° ${participant}`;
|
|
|
|
|
const ou = numero === null ? `table d'identifiant ${table}` : `table ${numero}`;
|
|
|
|
|
if (siege === undefined) {
|
|
|
|
|
return `Le placement retenu n'honore pas la réservation de ${qui} à la ${ou} au tour ${tour} : il la place ailleurs.`;
|
|
|
|
|
}
|
|
|
|
|
const chaise = occupant === null ? `laisse le siège ${siege} vide` : `donne le siège ${siege} à une autre personne`;
|
|
|
|
|
return (
|
|
|
|
|
`Le placement retenu n'honore pas la réservation de ${qui} au siège ${siege} de la ${ou} au tour ${tour} : ` +
|
|
|
|
|
`il l'assied à un autre siège de cette table, et ${chaise}.`
|
|
|
|
|
);
|
|
|
|
|
},
|
[ADD] application: observable session, events facade, places and seats
The screens of iteration 3 need state they can subscribe to and commands
that keep the plan sound. The session follows the Svelte store contract,
unblocks a plan, cancels a gesture, keeps the framing, and orders the
warnings of a gesture. The facade lists events, settles the working folder
and runs copy, rename, import and delete. Places cover reservations, titles,
designation and the retained plan: each gesture reads seats as the display
shows them, reserved people keep their table, and a person removed frees
her chair while every other seat stays.
Checked: 1973 node, 127 browser, 60 node-long tests; coverage floors kept.
--- FR ---
[ADD] application : séance observable, façade des événements, places
Les écrans de l'itération 3 exigent un état auquel s'abonner et des
commandes qui gardent le plan sain. La séance suit le contrat des magasins
de Svelte, débloque un plan, annule un geste, garde le cadrage et ordonne
les avertissements d'un geste. La façade liste les événements, règle le
dossier de travail et mène copie, renommage, import et suppression. Les
places couvrent réservations, titres, désignation et plan retenu : chaque
geste lit les sièges comme l'écran les montre, une personne réservée garde
sa table, et une personne retirée libère sa chaise sans déplacer les autres.
Vérifié : 1973 node, 127 navigateur, 60 node-long ; seuils de couverture.
Assisted-by: Claude Opus 5.5
2026-10-07 04:14:24 -04:00
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'INVARIANT_VIOLE',
|
|
|
|
|
({ proposition, violations }, texte) =>
|
|
|
|
|
`Le placement retenu, issu de la proposition n° ${proposition}, enfreint ` +
|
|
|
|
|
`${compte(violations.length, 'règle', 'règles')} que la dérive ne dit pas. ` +
|
|
|
|
|
violations.map((violation) => phraseDeViolation(violation, texte)).join(' '),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'CONFIGURATION_INCOHERENTE',
|
|
|
|
|
({ code, details }, texte) =>
|
|
|
|
|
`Après ce geste, la configuration ne se tient plus : ${phraseDeRaison(code, details, texte)} ` +
|
|
|
|
|
'Le diagnostic et la génération la refusent tant que rien ne la corrige.',
|
|
|
|
|
],
|
[ADD] application: clock, translation, formatting, displayed name
The screens need one clock, one translation mechanism and one way to
format and name, or each component grows its own. horloge.js is the only
code that reads time and arms timers, injected so tests drive it.
traduction.js keys texts by domain, in two families of tables, raises on a
missing key and never shows a raw key; libelles/ splits the label table by
domain. format.js formats numbers and dates in French, and personnes.js
composes the displayed name the frozen labels use. Nothing persists
between sessions.
Checked: 1773 node and 43 browser tests.
--- FR ---
[ADD] application : horloge, traduction, mise en forme, nom affiché
Les écrans exigent une horloge, un mécanisme de traduction et une façon de
mettre en forme et de nommer, sans quoi chaque composant ferait les siens.
horloge.js est le seul code qui lit l'heure et arme des minuteries, injecté
pour que les épreuves le pilotent. traduction.js range les textes par
domaine, en deux familles de tables, lève sur une clé absente et ne montre
jamais une clé brute ; libelles/ découpe la table des libellés par domaine.
format.js met en forme nombres et dates en français, et personnes.js
compose le nom affiché qu'emploient les libellés figés. Rien ne persiste
d'une séance à l'autre.
Vérifié : 1773 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:39 -04:00
|
|
|
[
|
|
|
|
|
'VERROU_NON_RENDU',
|
|
|
|
|
({ cause }, texte) =>
|
|
|
|
|
`Le verrou de l'événement n'a pas pu être rendu${causeEntreParentheses(cause, texte)} : ` +
|
|
|
|
|
'une autre séance de ce poste le reprendra une fois ce logiciel fermé.',
|
|
|
|
|
],
|
[FIX] local settings: an unreadable or unwritable file no longer blocks
An unreadable reglages_locaux.json, or a folder that refused to write it,
refused the paper choice, so no badge sheet or preview could be produced
on that machine. The chosen paper now holds for the session on that
working folder, in memory, and the file is never overwritten. On that
folder it wins over a stale paper still in the file; the first settings
write that succeeds there retains it and withdraws the warning. The
warning names the file and no longer promises defaults never written.
Checked: node 3918, browser 773; each fix red under the previous code.
--- FR ---
[FIX] réglages locaux : un fichier illisible ou non écrit ne bloque plus
Un reglages_locaux.json illisible, ou un dossier qui refusait de l'écrire,
refusait le choix du papier : ni planche ni aperçu sur cette machine. Le
papier choisi vaut désormais pour la séance sur ce dossier de travail, en
mémoire, et le fichier n'est jamais écrasé. Sur ce dossier, il l'emporte
sur un papier périmé du fichier ; la première écriture des réglages qui y
réussit le retient et retire l'avertissement. L'avertissement nomme le
fichier et ne promet plus de valeurs par défaut jamais écrites.
Vérifié : node 3918, navigateur 773 ; chaque correction rouge avant elle.
Assisted-by: Claude Opus 5.5
2026-10-10 20:20:04 -04:00
|
|
|
// Le papier choisi que le dossier de travail refuse d'écrire dans les
|
|
|
|
|
// réglages locaux : il vaut pour la séance, en mémoire.
|
|
|
|
|
[
|
|
|
|
|
'REGLAGES_NON_ECRITS',
|
|
|
|
|
(details, texte) =>
|
|
|
|
|
`Les réglages locaux ${ouEcrire(details, texte)} n'ont pas pu s'écrire : ` +
|
|
|
|
|
'le papier choisi vaut pour cette séance, sans être retenu sur cette machine.',
|
|
|
|
|
],
|
[ADD] application: clock, translation, formatting, displayed name
The screens need one clock, one translation mechanism and one way to
format and name, or each component grows its own. horloge.js is the only
code that reads time and arms timers, injected so tests drive it.
traduction.js keys texts by domain, in two families of tables, raises on a
missing key and never shows a raw key; libelles/ splits the label table by
domain. format.js formats numbers and dates in French, and personnes.js
composes the displayed name the frozen labels use. Nothing persists
between sessions.
Checked: 1773 node and 43 browser tests.
--- FR ---
[ADD] application : horloge, traduction, mise en forme, nom affiché
Les écrans exigent une horloge, un mécanisme de traduction et une façon de
mettre en forme et de nommer, sans quoi chaque composant ferait les siens.
horloge.js est le seul code qui lit l'heure et arme des minuteries, injecté
pour que les épreuves le pilotent. traduction.js range les textes par
domaine, en deux familles de tables, lève sur une clé absente et ne montre
jamais une clé brute ; libelles/ découpe la table des libellés par domaine.
format.js met en forme nombres et dates en français, et personnes.js
compose le nom affiché qu'emploient les libellés figés. Rien ne persiste
d'une séance à l'autre.
Vérifié : 1773 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:39 -04:00
|
|
|
['RIEN_A_DEFAIRE', () => "Rien à défaire : l'historique commence à cet instant."],
|
|
|
|
|
['RIEN_A_REFAIRE', () => 'Rien à refaire : seul un retour se refait, tant que nul geste ne le suit.'],
|
|
|
|
|
['INSTANT_NON_RESTITUABLE', ({ revision }) => `L'historique ne restitue plus l'instant ${revision}.`],
|
|
|
|
|
[
|
|
|
|
|
'JALON_NON_ECRIT',
|
|
|
|
|
({ dossier, cause }, texte) =>
|
|
|
|
|
`Le geste est enregistré, mais le jalon qui le nomme n'a pas pu s'écrire ` +
|
|
|
|
|
`dans le dossier ${cite(dossier)}${causeEntreParentheses(cause, texte)}.`,
|
|
|
|
|
],
|
|
|
|
|
['SANS_EFFET', () => "Ce geste ne change rien : rien n'est enregistré."],
|
|
|
|
|
|
|
|
|
|
// --- Les libellés figés du journal (§ 8.2, § 8.3) --------------------------
|
|
|
|
|
['JALON_CREATION', () => 'Création'],
|
|
|
|
|
['JALON_ETAT', ({ etat }) => `État ${cite(nomEtat(etat))}`],
|
|
|
|
|
['JALON_AVANT_GENERATION', () => 'Avant la génération'],
|
|
|
|
|
['ENTREE_REPRISE', () => "Reprise de l'état trouvé sur le disque"],
|
|
|
|
|
['ENTREE_DEFAIRE', ({ libelle: instant }) => `Défait : ${cite(instant)}`],
|
|
|
|
|
['ENTREE_REFAIRE', ({ libelle: instant }) => `Refait : ${cite(instant)}`],
|
|
|
|
|
['ENTREE_REVENIR', ({ libelle: instant }) => `Retour à ${cite(instant)}`],
|
|
|
|
|
]);
|