[ADD] interface: application shell — banner, sections, theme, about
The window showed only a banner; it now holds the application. App mounts
the session, the facade and the generation, settles the working folder
and lists its events before it reports ready, re-reading the list once a
question is answered or a refused determination succeeds. The banner
carries version, mode and the event list command; an open event shows its
sections in their first form; the theme follows the system at each start
and the operator's choice lasts the session; À propos names the build.
Errors are collected for a report, and Electron removes the session's
locks at exit.
Checked: 2189 node, 193 browser, 60 node-long; the Electron start check.
--- FR ---
[ADD] interface : coquille — bandeau, sections, thème, À propos
La fenêtre ne montrait qu'un bandeau ; elle tient désormais l'application.
App monte la séance, la façade et la génération, règle le dossier de
travail et liste ses événements avant de se dire prête, et relit la liste
une fois une question répondue ou une détermination refusée réussie. Le
bandeau porte version, mode et la commande de la liste ; un événement
ouvert montre ses sections dans leur première forme ; le thème suit le
système à chaque démarrage et le choix de l'opérateur vaut pour la séance ;
À propos nomme la construction. Les erreurs se collectent pour un
signalement, et Electron efface à la sortie les verrous de la séance.
Vérifié : 2189 node, 193 navigateur, 60 node-long ; démarrage d'Electron.
Assisted-by: Claude Opus 5.5
2026-10-07 07:22:05 -04:00
// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
// Le bloc « À propos » (§ 18.6) : une ligne que l'opérateur copie dans un
// courriel — nom, version affichée, version Windows, plateforme, provenance,
// version de format —, et ce qui tient lieu de version à l'écran, la marque
// de provenance dans une construction de documentation (§ 19.4).
import assert from 'node:assert/strict' ;
[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
import { readFileSync } from 'node:fs' ;
[ADD] interface: application shell — banner, sections, theme, about
The window showed only a banner; it now holds the application. App mounts
the session, the facade and the generation, settles the working folder
and lists its events before it reports ready, re-reading the list once a
question is answered or a refused determination succeeds. The banner
carries version, mode and the event list command; an open event shows its
sections in their first form; the theme follows the system at each start
and the operator's choice lasts the session; À propos names the build.
Errors are collected for a report, and Electron removes the session's
locks at exit.
Checked: 2189 node, 193 browser, 60 node-long; the Electron start check.
--- FR ---
[ADD] interface : coquille — bandeau, sections, thème, À propos
La fenêtre ne montrait qu'un bandeau ; elle tient désormais l'application.
App monte la séance, la façade et la génération, règle le dossier de
travail et liste ses événements avant de se dire prête, et relit la liste
une fois une question répondue ou une détermination refusée réussie. Le
bandeau porte version, mode et la commande de la liste ; un événement
ouvert montre ses sections dans leur première forme ; le thème suit le
système à chaque démarrage et le choix de l'opérateur vaut pour la séance ;
À propos nomme la construction. Les erreurs se collectent pour un
signalement, et Electron efface à la sortie les verrous de la séance.
Vérifié : 2189 node, 193 navigateur, 60 node-long ; démarrage d'Electron.
Assisted-by: Claude Opus 5.5
2026-10-07 07:22:05 -04:00
import { describe , test } from '../../test/lanceur.js' ;
import { TABLES _APPLICATION } from '../application/libelles.js' ;
import { MARQUE _TEMOIN , creerTraduction } from '../application/traduction.js' ;
import { FORMAT } from '../stockage/document.js' ;
import { VERSION } from '../version.genere.js' ;
import { blocAPropos , provenanceVisible , versionVisible } from './apropos.js' ;
import { TABLES _INTERFACE , libelleProvenance } from './libelles.js' ;
const { t } = creerTraduction ( [ ... TABLES _APPLICATION , ... TABLES _INTERFACE ] ) ;
const temoin = creerTraduction ( [ ... TABLES _APPLICATION , ... TABLES _INTERFACE ] , { langue : 'temoin' } ) . t ;
describe ( 'blocAPropos (§ 18.6)' , ( ) => {
test ( 'une ligne : nom, version affichée, version Windows, plateforme, provenance, format, séparés par « · »' , ( ) => {
assert . match ( VERSION . windows ? ? '' , /^\d+\.\d+\.\d+\.0$/ , 'VERSION.windows engendré' ) ;
const bloc = blocAPropos ( { version : VERSION , plateforme : 'electron' , provenance : 'livraison' , format : FORMAT } , t ) ;
assert . equal ( typeof bloc , 'string' ) ;
assert . doesNotMatch ( bloc , /[\n\r\u{2028}\u{2029}]/u ) ;
assert . deepEqual ( bloc . split ( ' \u{00B7} ' ) , [
t ( 'coquille.nom' ) ,
VERSION . affichee ,
VERSION . windows ,
'electron' ,
libelleProvenance ( 'livraison' ) ,
t ( 'coquille.apropos.format' , { format : FORMAT } ) ,
] ) ;
assert . ok ( bloc . includes ( String ( FORMAT ) ) ) ;
} ) ;
test ( 'chaque plateforme et chaque provenance s’ y lisent ; un mode sans libellé sous son propre nom' , ( ) => {
const cas = [
[ 'web' , 'developpement' , libelleProvenance ( 'developpement' ) ] ,
[ 'epreuve' , 'test' , libelleProvenance ( 'test' ) ] ,
[ 'electron' , 'documentation' , libelleProvenance ( 'documentation' ) ] ,
[ 'web' , 'production' , 'production' ] ,
] ;
assert . ok ( cas . length > 0 ) ;
for ( const [ plateforme , provenance , libelle ] of cas ) {
const champs = blocAPropos ( { version : VERSION , plateforme , provenance , format : FORMAT } , t ) . split ( ' \u{00B7} ' ) ;
assert . equal ( champs [ 3 ] , plateforme , provenance ) ;
assert . equal ( champs [ 4 ] , libelle , provenance ) ;
}
} ) ;
[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
test ( 'une forme de la version absente, vide ou qui n’ est pas une chaîne lève RangeError en la nommant : jamais un bloc copiable faux' , ( ) => {
const fautes = [ undefined , null , '' , 7 ] ;
assert . equal ( fautes . length , 4 ) ;
for ( const faute of fautes ) {
for ( const [ forme , version ] of [
[ 'windows' , { affichee : VERSION . affichee , windows : faute } ] ,
[ 'affichee' , { affichee : faute , windows : VERSION . windows } ] ,
] ) {
assert . throws (
( ) => blocAPropos ( { version , plateforme : 'web' , provenance : 'test' , format : FORMAT } , t ) ,
( erreur ) => erreur instanceof RangeError && erreur . message . includes ( forme ) ,
` ${ forme } ${ String ( faute ) } ` ,
) ;
}
}
} ) ;
[ADD] interface: application shell — banner, sections, theme, about
The window showed only a banner; it now holds the application. App mounts
the session, the facade and the generation, settles the working folder
and lists its events before it reports ready, re-reading the list once a
question is answered or a refused determination succeeds. The banner
carries version, mode and the event list command; an open event shows its
sections in their first form; the theme follows the system at each start
and the operator's choice lasts the session; À propos names the build.
Errors are collected for a report, and Electron removes the session's
locks at exit.
Checked: 2189 node, 193 browser, 60 node-long; the Electron start check.
--- FR ---
[ADD] interface : coquille — bandeau, sections, thème, À propos
La fenêtre ne montrait qu'un bandeau ; elle tient désormais l'application.
App monte la séance, la façade et la génération, règle le dossier de
travail et liste ses événements avant de se dire prête, et relit la liste
une fois une question répondue ou une détermination refusée réussie. Le
bandeau porte version, mode et la commande de la liste ; un événement
ouvert montre ses sections dans leur première forme ; le thème suit le
système à chaque démarrage et le choix de l'opérateur vaut pour la séance ;
À propos nomme la construction. Les erreurs se collectent pour un
signalement, et Electron efface à la sortie les verrous de la séance.
Vérifié : 2189 node, 193 navigateur, 60 node-long ; démarrage d'Electron.
Assisted-by: Claude Opus 5.5
2026-10-07 07:22:05 -04:00
test ( 'en langue témoin, le bloc entier est encadré une fois' , ( ) => {
const bloc = blocAPropos ( { version : VERSION , plateforme : 'web' , provenance : 'test' , format : FORMAT } , temoin ) ;
const { ouverture , fermeture } = MARQUE _TEMOIN ;
assert . ok ( bloc . startsWith ( ouverture ) && bloc . endsWith ( fermeture ) , bloc ) ;
assert . equal ( bloc . split ( ouverture ) . length , 2 , bloc ) ;
assert . equal ( bloc . split ( fermeture ) . length , 2 , bloc ) ;
} ) ;
} ) ;
describe ( 'versionVisible (§ 18.6, § 19.4)' , ( ) => {
test ( 'la version affichée, hors d’ une construction de documentation' , ( ) => {
for ( const provenance of [ 'developpement' , 'livraison' , 'test' ] ) {
assert . equal ( versionVisible ( provenance , VERSION . affichee , t ) , VERSION . affichee , provenance ) ;
}
} ) ;
test ( 'la marque de provenance, sans le numéro, dans une construction de documentation' , ( ) => {
const marque = versionVisible ( 'documentation' , VERSION . affichee , t ) ;
assert . equal ( marque , t ( 'coquille.version.documentation' ) ) ;
assert . ok ( ! marque . includes ( VERSION . affichee ) , marque ) ;
} ) ;
} ) ;
describe ( 'provenanceVisible (§ 18.6)' , ( ) => {
test ( 'le libellé du mode par la traduction reçue ; un mode sans libellé sous son propre nom' , ( ) => {
for ( const mode of [ 'developpement' , 'livraison' , 'documentation' , 'test' ] ) {
assert . equal ( provenanceVisible ( mode , t ) , libelleProvenance ( mode ) , mode ) ;
}
assert . equal ( provenanceVisible ( 'production' , t ) , 'production' ) ;
assert . equal ( provenanceVisible ( 'constructor' , t ) , 'constructor' ) ;
} ) ;
test ( 'en langue témoin, le libellé est encadré, le mode sans libellé non : il est une donnée' , ( ) => {
const { ouverture , fermeture } = MARQUE _TEMOIN ;
assert . equal ( provenanceVisible ( 'test' , temoin ) , ` ${ ouverture } ${ libelleProvenance ( 'test' ) } ${ fermeture } ` ) ;
assert . equal ( provenanceVisible ( 'production' , temoin ) , 'production' ) ;
} ) ;
} ) ;
[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
describe ( 'la version de l’ interface vient des dépendances (§ 13.4, § 18.6)' , ( ) => {
test ( 'App.svelte ne lit pas la version engendrée : la version affichée et la forme Windows arrivent par ses propriétés, produitVersion et versionWindows' , ( ) => {
const source = readFileSync ( new URL ( './App.svelte' , import . meta . url ) , 'utf8' ) ;
const imports = [ ... source . matchAll ( /^\s*import\s[^;]*?from\s+'([^']+)'/gmu ) ] . map ( ( [ , chemin ] ) => chemin ) ;
assert . ok ( imports . length > 0 , 'des imports relevés' ) ;
assert . deepEqual (
imports . filter ( ( chemin ) => chemin . includes ( 'version.genere' ) ) ,
[ ] ,
) ;
assert . match ( source , /\bversionWindows\b/u ) ;
assert . match ( source , /blocAPropos\(\s*\{\s*version:\s*\{\s*affichee:\s*produitVersion,\s*windows:\s*versionWindows\s*\}/u ) ;
} ) ;
} ) ;